aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/pull_request_template.md7
-rw-r--r--.github/workflows/build_cmake.yml41
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt22
-rw-r--r--README.md18
-rw-r--r--cmake/FindClang.cmake13
-rw-r--r--cmake/FindQt5.cmake8
-rw-r--r--cmake/Findyaml-cpp.cmake8
-rw-r--r--cmake/QtCreatorAPI.cmake128
-rw-r--r--cmake/QtCreatorAPIInternal.cmake63
-rw-r--r--cmake/QtCreatorIDEBranding.cmake6
-rw-r--r--cmake/QtCreatorTranslations.cmake1
-rw-r--r--cmake/Utils.cmake7
-rw-r--r--coin/instructions/build.yaml11
-rw-r--r--coin/instructions/common_environment.yaml4
-rw-r--r--coin/instructions/provision.yaml13
-rw-r--r--coin/instructions/test.yaml15
-rw-r--r--coin/module_config.yaml9
-rw-r--r--coin/product_dependencies.yaml4
-rw-r--r--dist/changes-8.0.0.md270
-rw-r--r--dist/changes-8.0.1.md81
-rw-r--r--dist/clangformat/README.md4
-rw-r--r--doc/qtcreator/examples/textfinder/CMakeLists.txt71
-rw-r--r--doc/qtcreator/examples/textfinder/TextFinder_de_DE.ts22
-rw-r--r--doc/qtcreator/examples/textfinder/main.cpp16
-rw-r--r--doc/qtcreator/examples/textfinder/textfinder.cpp8
-rw-r--r--doc/qtcreator/examples/textfinder/textfinder.h18
-rw-r--r--doc/qtcreator/examples/textfinder/textfinder.pro13
-rw-r--r--doc/qtcreator/examples/textfinder/textfinder.qrc10
-rw-r--r--doc/qtcreator/examples/textfinder/textfinder.ui61
-rw-r--r--doc/qtcreator/images/coco-coveragebrowser-load-execution-report.pngbin0 -> 10187 bytes
-rw-r--r--doc/qtcreator/images/qml-toolbar-image.pngbin3561 -> 3699 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-add-resource-wizard2.pngbin7249 -> 8385 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-add-resource-wizard3.pngbin9889 -> 10958 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-add-resource-wizard4.pngbin0 -> 5671 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-add-resource.pngbin17473 -> 12941 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-create-template.pngbin0 -> 9869 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-baremetal-kit.pngbin20849 -> 26372 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-boot2qt-deployment-steps.pngbin13002 -> 16143 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-build-settings-ios.pngbin34314 -> 6248 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-clang-code-model-build-settings.pngbin4320 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-clang-code-model-options.pngbin7306 -> 4144 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-clang-tidy.pngbin7683 -> 16971 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-clang-tools-options-customized.pngbin9647 -> 9922 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-clazy.pngbin16782 -> 22558 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-coco.pngbin0 -> 5550 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-code-pasting-options.pngbin3858 -> 3876 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-code-style-clang-format.pngbin23281 -> 27364 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.pngbin16780 -> 14629 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-custom-parser.pngbin3857 -> 4276 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-debugger-attach-to-running-debug-server.pngbin21017 -> 20955 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-debugging-helper-options.pngbin12681 -> 13283 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-diagnostics-configuration.pngbin10890 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-docker-image-selection.pngbin0 -> 23142 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-docker-preferences.pngbin0 -> 57498 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-editor-settings.pngbin25503 -> 27030 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-embedded-linux-deployment-details.pngbin14384 -> 17305 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-external-tools.pngbin18298 -> 18861 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-formedit.pngbin50650 -> 47774 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-gitlab-clone-repository.pngbin0 -> 7551 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-gitlab-preferences-add-server.pngbin0 -> 4901 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-gitlab-preferences-project.pngbin0 -> 7631 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-gitlab-preferences.pngbin0 -> 9334 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-gitlab-project-list.pngbin0 -> 18577 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-image-viewer.pngbin19781 -> 6395 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-intro-and-location-qt-gui.pngbin11480 -> 11404 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-ios-add-kit.pngbin92748 -> 79505 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-ios-device-configurations.pngbin18559 -> 23381 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-ios-preferences.pngbin66515 -> 51597 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-ios-simulator-deploy.pngbin41536 -> 34387 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-kits-add.pngbin31584 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-kits.pngbin32416 -> 34560 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-language-client-inspector-memory-usage.pngbin0 -> 8506 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-language-client-options-java.pngbin7749 -> 6835 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-language-client-options.pngbin10533 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-language-server-generic-stdio.pngbin0 -> 10203 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-link-with-qt.pngbin5515 -> 6311 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-mcu-kit.pngbin26402 -> 32077 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-mcu-options.pngbin9520 -> 11640 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-new-project-build-system-qt-gui.pngbin7691 -> 8412 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-new-project-qt-versions-qt-gui.pngbin12862 -> 17152 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-new-project-summary-qt-gui.pngbin11708 -> 13342 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-open-documents-view.pngbin3173 -> 1319 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-options-android-main.pngbin18155 -> 28235 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-options-android-sdk-tools.pngbin22305 -> 28238 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-options-clangd.pngbin6133 -> 12308 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-options-text-editor-display.pngbin14533 -> 10742 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-options-texteditor-completion.pngbin7114 -> 14439 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-python-advanced.pngbin0 -> 11773 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-python-interpreters.pngbin0 -> 4987 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-python-plugins.pngbin0 -> 5699 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-qml-js-editing.pngbin0 -> 5888 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-qnx-deployment.pngbin12013 -> 12050 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-qt-versions.pngbin14539 -> 22916 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-refactoring-options-locations.pngbin5681 -> 5570 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-semanticerror-clang.pngbin33662 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-semanticerror.pngbin9491 -> 22255 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-sidebar.pngbin19045 -> 18628 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-syntaxerror-clang.pngbin31551 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-syntaxerror.pngbin9802 -> 22392 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-textfinder-contents.pngbin12662 -> 11972 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-todo-excluded-files.pngbin0 -> 4048 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-typo-clang.pngbin52930 -> 19902 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-valgrind-remote-settings.pngbin6520 -> 5425 bytes
-rw-r--r--doc/qtcreator/images/qtdesigner-add-profile.pngbin0 -> 7553 bytes
-rw-r--r--doc/qtcreator/images/qtdesigner-embedded-design.pngbin0 -> 5238 bytes
-rw-r--r--doc/qtcreator/src/analyze/cpu-usage-analyzer.qdoc38
-rw-r--r--doc/qtcreator/src/analyze/creator-analyze.qdoc22
-rw-r--r--doc/qtcreator/src/analyze/creator-clang-static-analyzer.qdoc16
-rw-r--r--doc/qtcreator/src/analyze/creator-coco.qdoc120
-rw-r--r--doc/qtcreator/src/analyze/creator-cppcheck.qdoc2
-rw-r--r--doc/qtcreator/src/analyze/creator-heob.qdoc2
-rw-r--r--doc/qtcreator/src/analyze/creator-valgrind-overview.qdoc6
-rw-r--r--doc/qtcreator/src/analyze/creator-valgrind.qdoc10
-rw-r--r--doc/qtcreator/src/android/androiddev.qdoc36
-rw-r--r--doc/qtcreator/src/android/deploying-android.qdoc16
-rw-r--r--doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc24
-rw-r--r--doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc9
-rw-r--r--doc/qtcreator/src/cmake/creator-projects-cmake.qdoc4
-rw-r--r--doc/qtcreator/src/debugger/creator-debugger-common.qdocinc4
-rw-r--r--doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc32
-rw-r--r--doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc6
-rw-r--r--doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc74
-rw-r--r--doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc2
-rw-r--r--doc/qtcreator/src/debugger/qtquick-debugging.qdoc6
-rw-r--r--doc/qtcreator/src/docker/creator-docker.qdoc133
-rw-r--r--doc/qtcreator/src/editors/creator-clangformat.qdocinc50
-rw-r--r--doc/qtcreator/src/editors/creator-code-completion.qdoc14
-rw-r--r--doc/qtcreator/src/editors/creator-code-indentation.qdoc61
-rw-r--r--doc/qtcreator/src/editors/creator-code-refactoring.qdoc38
-rw-r--r--doc/qtcreator/src/editors/creator-code-syntax.qdoc54
-rw-r--r--doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc51
-rw-r--r--doc/qtcreator/src/editors/creator-diff-editor.qdoc4
-rw-r--r--doc/qtcreator/src/editors/creator-editors-options-text.qdoc36
-rw-r--r--doc/qtcreator/src/editors/creator-editors-options.qdoc4
-rw-r--r--doc/qtcreator/src/editors/creator-locator.qdoc12
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-beautifier.qdoc12
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc49
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-code-pasting.qdoc13
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc28
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc86
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc4
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc2
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-text-editing-macros.qdoc6
-rw-r--r--doc/qtcreator/src/editors/creator-quick-fixes.qdoc9
-rw-r--r--doc/qtcreator/src/editors/creator-search.qdoc8
-rw-r--r--doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc26
-rw-r--r--doc/qtcreator/src/howto/creator-external-tools.qdoc8
-rw-r--r--doc/qtcreator/src/howto/creator-help.qdoc28
-rw-r--r--doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc39
-rw-r--r--doc/qtcreator/src/howto/creator-only/creator-autotest.qdoc50
-rw-r--r--doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc83
-rw-r--r--doc/qtcreator/src/howto/creator-only/creator-task-lists.qdoc10
-rw-r--r--doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc18
-rw-r--r--doc/qtcreator/src/howto/creator-telemetry.qdoc2
-rw-r--r--doc/qtcreator/src/incredibuild/creator-projects-incredibuild-building.qdoc10
-rw-r--r--doc/qtcreator/src/ios/creator-ios-dev.qdoc2
-rw-r--r--doc/qtcreator/src/linux-mobile/b2qtdev.qdoc12
-rw-r--r--doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc29
-rw-r--r--doc/qtcreator/src/linux-mobile/linuxdev-keys.qdocinc8
-rw-r--r--doc/qtcreator/src/linux-mobile/linuxdev-processes.qdocinc2
-rw-r--r--doc/qtcreator/src/linux-mobile/linuxdev.qdoc12
-rw-r--r--doc/qtcreator/src/mcu/creator-mcu-dev.qdoc20
-rw-r--r--doc/qtcreator/src/meson/creator-projects-meson-building.qdoc3
-rw-r--r--doc/qtcreator/src/meson/creator-projects-meson.qdoc6
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-advanced.qdoc7
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc26
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-glossary.qdoc19
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-issues.qdoc7
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc14
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc11
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-supported-platforms.qdoc10
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc14
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-custom-output-parser.qdoc19
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc4
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-build-run-tutorial.qdoc4
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-build-systems.qdocinc10
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc11
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc4
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc18
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc20
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc32
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards.qdoc4
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-debuggers.qdoc6
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-nimble.qdoc2
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc6
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-qbs.qdoc10
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc8
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc4
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc6
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-editor.qdoc8
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc4
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc10
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc4
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc8
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc2
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc194
-rw-r--r--doc/qtcreator/src/projects/creator-projects-running.qdoc8
-rw-r--r--doc/qtcreator/src/python/creator-python-project.qdocinc75
-rw-r--r--doc/qtcreator/src/qnx/creator-deployment-qnx.qdoc5
-rw-r--r--doc/qtcreator/src/qnx/creator-developing-qnx.qdoc2
-rw-r--r--doc/qtcreator/src/qtcreator-toc.qdoc6
-rw-r--r--doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc2
-rw-r--r--doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc16
-rw-r--r--doc/qtcreator/src/qtquick/creator-only/qtquick-tutorial-create-empty-project.qdocinc6
-rw-r--r--doc/qtcreator/src/qtquick/qtquick-live-preview-devices.qdoc2
-rw-r--r--doc/qtcreator/src/qtquick/qtquick-profiler.qdoc10
-rw-r--r--doc/qtcreator/src/qtquick/qtquick-toolbars.qdoc6
-rw-r--r--doc/qtcreator/src/user-interface/creator-file-system-view.qdoc6
-rw-r--r--doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc4
-rw-r--r--doc/qtcreator/src/user-interface/creator-projects-view.qdoc8
-rw-r--r--doc/qtcreator/src/user-interface/creator-ui.qdoc157
-rw-r--r--doc/qtcreator/src/vcs/creator-only/creator-vcs-clearcase.qdoc16
-rw-r--r--doc/qtcreator/src/vcs/creator-only/creator-vcs-cvs.qdoc4
-rw-r--r--doc/qtcreator/src/vcs/creator-only/creator-vcs-gitlab.qdoc146
-rw-r--r--doc/qtcreator/src/vcs/creator-only/creator-vcs-mercurial.qdoc2
-rw-r--r--doc/qtcreator/src/vcs/creator-only/creator-vcs-options.qdocinc9
-rw-r--r--doc/qtcreator/src/vcs/creator-only/creator-vcs-perforce.qdoc8
-rw-r--r--doc/qtcreator/src/vcs/creator-only/creator-vcs-subversion.qdoc2
-rw-r--r--doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc11
-rw-r--r--doc/qtcreator/src/vcs/creator-vcs-git.qdoc20
-rw-r--r--doc/qtcreator/src/webassembly/creator-webassembly.qdoc8
-rw-r--r--doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc37
-rw-r--r--doc/qtcreator/src/widgets/qtdesigner-overview.qdoc44
-rw-r--r--doc/qtcreatordev/src/actionmanager.qdoc2
-rw-r--r--doc/qtcreatordev/src/common-extension-tasks.qdoc4
-rw-r--r--doc/qtcreatordev/src/qtcreator-dev.qdoc6
-rw-r--r--doc/qtcreatordev/src/qtcreator-documentation.qdoc6
-rw-r--r--doc/qtcreatordev/src/qtcreator-ui-text.qdoc12
-rw-r--r--doc/qtdesignstudio/config/qtdesignstudio.qdocconf1
-rw-r--r--doc/qtdesignstudio/examples/doc/coffeemachine.qdoc2
-rw-r--r--doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc4
-rw-r--r--doc/qtdesignstudio/images/loader3d-navigator.pngbin0 -> 6100 bytes
-rw-r--r--doc/qtdesignstudio/images/loader3d-select-source-component.pngbin0 -> 12138 bytes
-rw-r--r--doc/qtdesignstudio/images/loader3d-select-source.pngbin0 -> 25687 bytes
-rw-r--r--doc/qtdesignstudio/images/loader3d-visibility.pngbin0 -> 13189 bytes
-rw-r--r--doc/qtdesignstudio/images/navigator-show-all-loader.pngbin0 -> 9079 bytes
-rw-r--r--doc/qtdesignstudio/images/qt-sketch-bridge-settings.pngbin40905 -> 25614 bytes
-rw-r--r--doc/qtdesignstudio/src/components/qtquick-buttons.qdoc2
-rw-r--r--doc/qtdesignstudio/src/components/qtquick-controls.qdoc4
-rw-r--r--doc/qtdesignstudio/src/components/qtquick-images.qdoc2
-rw-r--r--doc/qtdesignstudio/src/components/qtquick-text.qdoc2
-rw-r--r--doc/qtdesignstudio/src/overviews/qtquick-placeholder-data.qdoc2
-rw-r--r--doc/qtdesignstudio/src/overviews/studio-crashpad.qdoc4
-rw-r--r--doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc4
-rw-r--r--doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc8
-rw-r--r--doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc6
-rw-r--r--doc/qtdesignstudio/src/qtbridge/qtbridge-ps-setup.qdoc8
-rw-r--r--doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-setup.qdoc8
-rw-r--r--doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc22
-rw-r--r--doc/qtdesignstudio/src/qtbridge/qtbridge-xd-setup.qdoc8
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-javascript.qdoc4
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-loader-3d.qdoc67
-rw-r--r--doc/qtdesignstudio/src/qtquickdesigner-components/qtdesignstudio-visual-effects.qdoc2
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc10
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-properties.qdoc2
-rw-r--r--qbs/modules/qtc/qtc.qbs19
-rw-r--r--qbs/modules/sqlite_sources/sqlite-sources.qbs4
-rw-r--r--qtcreator_ide_branding.pri6
-rwxr-xr-xscripts/deployqt.py18
-rwxr-xr-xscripts/deployqtHelper_mac.sh16
-rw-r--r--share/qtcreator/CMakeLists.txt39
-rw-r--r--share/qtcreator/android/sdk_definitions.json19
-rw-r--r--share/qtcreator/debugger/dumper.py21
-rw-r--r--share/qtcreator/debugger/lldbbridge.py10
-rw-r--r--share/qtcreator/debugger/qttypes.py32
-rw-r--r--share/qtcreator/debugger/stdtypes.py58
-rw-r--r--share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h1
-rw-r--r--share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h4
-rw-r--r--share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp3
-rw-r--r--share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc2
-rw-r--r--share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc2
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_landscape.hdrbin0 -> 100900 bytes
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_studio.hdrbin0 -> 108923 bytes
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml31
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml51
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml15
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml13
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml73
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml19
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp10
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h5
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp113
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h9
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp3
-rw-r--r--share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml4
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/App.qml42
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/CustomCheckBox.ui.qml135
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/InstallQdsStatusBlock.ui.qml80
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/PageText.ui.qml49
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/ProjectInfoStatusBlock.ui.qml112
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/PushButton.ui.qml120
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/Screen01.ui.qml222
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/logo.pngbin0 -> 3449 bytes
-rw-r--r--share/qtcreator/qmldesigner/landingpage/content/logo@2x.pngbin0 -> 7320 bytes
-rw-r--r--share/qtcreator/qmldesigner/landingpage/imports/LandingPage/+QDS_theming/Colors.qml39
-rw-r--r--share/qtcreator/qmldesigner/landingpage/imports/LandingPage/Colors.qml40
-rw-r--r--share/qtcreator/qmldesigner/landingpage/imports/LandingPage/Values.qml56
-rw-r--r--share/qtcreator/qmldesigner/landingpage/imports/LandingPage/qmldir2
-rw-r--r--share/qtcreator/qmldesigner/landingpage/landingpage.qmlproject86
-rw-r--r--share/qtcreator/qmldesigner/landingpage/main.qml9
-rw-r--r--share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageApi/LandingPageApi.qml44
-rw-r--r--share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageApi/qmldir1
-rw-r--r--share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageTheme/Dummy.qml32
-rw-r--r--share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageTheme/qmldir1
-rw-r--r--share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml106
-rw-r--r--share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml6
-rw-r--r--share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml35
-rw-r--r--share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml16
-rw-r--r--share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml159
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml92
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckBoxSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckDelegateSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ComboBoxSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ContainerSection.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSection.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml41
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml40
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialogSpecifics.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DrawerSpecifics.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/IconSection.qml145
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/InsetSection.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/LabelSpecifics.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSection.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSection.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSpecifics.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioButtonSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeDelegateSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchDelegateSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabButtonSpecifics.qml35
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextAreaSpecifics.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolButtonSpecifics.qml37
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml1205
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml1175
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml46
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SearchBox.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/FilterComboBox.qml6
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml134
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttfbin23512 -> 23736 bytes
-rw-r--r--share/qtcreator/qmldesigner/qt4mcu/qul-22.qml2
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json3
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl5
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk49
-rw-r--r--share/qtcreator/styles/creator-dark.xml2
-rw-r--r--share/qtcreator/styles/dark.xml2
-rw-r--r--share/qtcreator/styles/default_classic.xml1
-rw-r--r--share/qtcreator/styles/grayscale.xml1
-rw-r--r--share/qtcreator/styles/inkpot.xml2
-rw-r--r--share/qtcreator/styles/intellij.xml1
-rw-r--r--share/qtcreator/styles/modnokai_night_shift_v2.xml2
-rw-r--r--share/qtcreator/styles/solarized-dark.xml2
-rw-r--r--share/qtcreator/styles/solarized-light.xml2
-rw-r--r--share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl2
-rw-r--r--share/qtcreator/templates/wizards/classes/python/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl2
-rw-r--r--share/qtcreator/templates/wizards/files/qtquick2/wizard.json7
-rw-r--r--share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt3
-rw-r--r--share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt3
-rw-r--r--share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt3
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json8
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_empty.py6
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py13
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_qtquick.py14
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget.py16
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget_gen.py39
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json8
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/qtquickapplication/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget/wizard.json10
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget_gen/main.pyproject3
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget_gen/wizard.json114
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquick2-extension/CMakeLists.6.x.txt44
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.cpp23
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.qml.tpl29
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquick2-extension/object.cpp14
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquick2-extension/object.h7
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquick2-extension/object.qml.tpl10
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json142
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt6
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt6
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt4
-rw-r--r--share/qtcreator/translations/qtcreator_de.ts2
-rw-r--r--share/qtcreator/translations/qtcreator_ja.ts18214
-rw-r--r--share/qtcreator/translations/qtcreator_ru.ts2
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/app/CMakeLists.txt37
-rw-r--r--src/app/main.cpp6
-rw-r--r--src/libs/3rdparty/cplusplus/Bind.cpp14
-rw-r--r--src/libs/3rdparty/cplusplus/CMakeLists.txt7
-rw-r--r--src/libs/3rdparty/cplusplus/CoreTypes.cpp7
-rw-r--r--src/libs/3rdparty/cplusplus/CoreTypes.h6
-rw-r--r--src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp24
-rw-r--r--src/libs/3rdparty/cplusplus/FullySpecifiedType.h15
-rw-r--r--src/libs/3rdparty/cplusplus/Literals.h5
-rw-r--r--src/libs/3rdparty/cplusplus/Name.cpp24
-rw-r--r--src/libs/3rdparty/cplusplus/Name.h9
-rw-r--r--src/libs/3rdparty/cplusplus/Names.cpp10
-rw-r--r--src/libs/3rdparty/cplusplus/Names.h22
-rw-r--r--src/libs/3rdparty/cplusplus/Scope.cpp2
-rw-r--r--src/libs/3rdparty/cplusplus/Symbol.cpp157
-rw-r--r--src/libs/3rdparty/cplusplus/Symbol.h168
-rw-r--r--src/libs/3rdparty/cplusplus/Symbols.cpp349
-rw-r--r--src/libs/3rdparty/cplusplus/Symbols.h533
-rw-r--r--src/libs/3rdparty/cplusplus/Type.cpp2
-rw-r--r--src/libs/3rdparty/sqlite/carray.c1
-rw-r--r--src/libs/3rdparty/sqlite/config.h281
-rw-r--r--src/libs/3rdparty/syntax-highlighting/.git-blame-ignore-revs1
-rw-r--r--src/libs/3rdparty/syntax-highlighting/.gitlab-ci.yml5
-rw-r--r--src/libs/3rdparty/syntax-highlighting/.kde-ci.yml5
-rw-r--r--src/libs/3rdparty/syntax-highlighting/CMakeLists.txt13
-rw-r--r--src/libs/3rdparty/syntax-highlighting/KF5SyntaxHighlightingConfig.cmake.in4
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/AbstractHighlighter (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/AbstractHighlighter)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Definition (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Definition)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/DefinitionDownloader (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/DefinitionDownloader)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/FoldingRegion (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/FoldingRegion)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Format (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Format)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Repository (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Repository)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/State (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/State)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/SyntaxHighlighter (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/SyntaxHighlighter)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Theme (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Theme)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/WildcardMatcher (renamed from src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/WildcardMatcher)0
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h6
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h8
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp4
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/generators/.gitignore1
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/generators/Pipfile11
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml82
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml50
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml57
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/css.xml75
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/python.xml10
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/themes/homunculus.theme177
-rw-r--r--src/libs/3rdparty/syntax-highlighting/patches/0003-Add-qmake-Qbs-files-and-files-generated-by-CMake.patch117
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt1
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt40
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/repository.h2
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt17
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp112
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h66
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp47
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.h22
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/qmldir2
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/qmldir.license2
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp65
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h45
-rw-r--r--src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs2
-rw-r--r--src/libs/CMakeLists.txt10
-rw-r--r--src/libs/advanceddockingsystem/ads_globals.cpp2
-rw-r--r--src/libs/advanceddockingsystem/ads_globals.h12
-rw-r--r--src/libs/advanceddockingsystem/dockmanager.cpp1
-rw-r--r--src/libs/advanceddockingsystem/dockoverlay.cpp6
-rw-r--r--src/libs/advanceddockingsystem/floatingdockcontainer.cpp3
-rw-r--r--src/libs/advanceddockingsystem/floatingdragpreview.cpp2
-rw-r--r--src/libs/advanceddockingsystem/workspacemodel.cpp4
-rw-r--r--src/libs/aggregation/aggregation_global.h2
-rw-r--r--src/libs/clangsupport/CMakeLists.txt73
-rw-r--r--src/libs/clangsupport/alivemessage.cpp37
-rw-r--r--src/libs/clangsupport/alivemessage.h56
-rw-r--r--src/libs/clangsupport/annotationsmessage.cpp46
-rw-r--r--src/libs/clangsupport/annotationsmessage.h112
-rw-r--r--src/libs/clangsupport/baseserverproxy.cpp74
-rw-r--r--src/libs/clangsupport/baseserverproxy.h58
-rw-r--r--src/libs/clangsupport/clangcodemodelclientinterface.cpp65
-rw-r--r--src/libs/clangsupport/clangcodemodelclientinterface.h66
-rw-r--r--src/libs/clangsupport/clangcodemodelclientmessages.h34
-rw-r--r--src/libs/clangsupport/clangcodemodelclientproxy.cpp130
-rw-r--r--src/libs/clangsupport/clangcodemodelclientproxy.h76
-rw-r--r--src/libs/clangsupport/clangcodemodelconnectionclient.cpp91
-rw-r--r--src/libs/clangsupport/clangcodemodelconnectionclient.h50
-rw-r--r--src/libs/clangsupport/clangcodemodelserverinterface.cpp80
-rw-r--r--src/libs/clangsupport/clangcodemodelserverinterface.h60
-rw-r--r--src/libs/clangsupport/clangcodemodelservermessages.h43
-rw-r--r--src/libs/clangsupport/clangcodemodelserverproxy.cpp107
-rw-r--r--src/libs/clangsupport/clangcodemodelserverproxy.h68
-rw-r--r--src/libs/clangsupport/clangsupport.qbs27
-rw-r--r--src/libs/clangsupport/clangsupport_global.h228
-rw-r--r--src/libs/clangsupport/clangsupportdebugutils.cpp108
-rw-r--r--src/libs/clangsupport/clangsupportdebugutils.h53
-rw-r--r--src/libs/clangsupport/codecompletion.cpp101
-rw-r--r--src/libs/clangsupport/codecompletion.h147
-rw-r--r--src/libs/clangsupport/codecompletionchunk.cpp84
-rw-r--r--src/libs/clangsupport/codecompletionchunk.h117
-rw-r--r--src/libs/clangsupport/completionsmessage.cpp45
-rw-r--r--src/libs/clangsupport/completionsmessage.h77
-rw-r--r--src/libs/clangsupport/connectionclient.cpp400
-rw-r--r--src/libs/clangsupport/connectionclient.h146
-rw-r--r--src/libs/clangsupport/connectionserver.cpp31
-rw-r--r--src/libs/clangsupport/connectionserver.h149
-rw-r--r--src/libs/clangsupport/diagnosticcontainer.cpp63
-rw-r--r--src/libs/clangsupport/diagnosticcontainer.h130
-rw-r--r--src/libs/clangsupport/documentschangedmessage.cpp45
-rw-r--r--src/libs/clangsupport/documentschangedmessage.h70
-rw-r--r--src/libs/clangsupport/documentsclosedmessage.cpp45
-rw-r--r--src/libs/clangsupport/documentsclosedmessage.h71
-rw-r--r--src/libs/clangsupport/documentsopenedmessage.cpp50
-rw-r--r--src/libs/clangsupport/documentsopenedmessage.h81
-rw-r--r--src/libs/clangsupport/documentvisibilitychangedmessage.cpp46
-rw-r--r--src/libs/clangsupport/documentvisibilitychangedmessage.h78
-rw-r--r--src/libs/clangsupport/echomessage.cpp38
-rw-r--r--src/libs/clangsupport/echomessage.h69
-rw-r--r--src/libs/clangsupport/endmessage.cpp37
-rw-r--r--src/libs/clangsupport/endmessage.h56
-rw-r--r--src/libs/clangsupport/filecontainer.cpp57
-rw-r--r--src/libs/clangsupport/filecontainer.h124
-rw-r--r--src/libs/clangsupport/fixitcontainer.cpp55
-rw-r--r--src/libs/clangsupport/fixitcontainer.h74
-rw-r--r--src/libs/clangsupport/followsymbolmessage.cpp55
-rw-r--r--src/libs/clangsupport/followsymbolmessage.h121
-rw-r--r--src/libs/clangsupport/ipcclientinterface.h35
-rw-r--r--src/libs/clangsupport/ipcclientprovider.h53
-rw-r--r--src/libs/clangsupport/ipcinterface.h49
-rw-r--r--src/libs/clangsupport/ipcserverinterface.h35
-rw-r--r--src/libs/clangsupport/lineprefixer.cpp60
-rw-r--r--src/libs/clangsupport/lineprefixer.h49
-rw-r--r--src/libs/clangsupport/messageenvelop.cpp98
-rw-r--r--src/libs/clangsupport/messageenvelop.h118
-rw-r--r--src/libs/clangsupport/processcreator.cpp190
-rw-r--r--src/libs/clangsupport/processcreator.h85
-rw-r--r--src/libs/clangsupport/processexception.cpp40
-rw-r--r--src/libs/clangsupport/processexception.h48
-rw-r--r--src/libs/clangsupport/processhandle.h47
-rw-r--r--src/libs/clangsupport/processstartedevent.cpp34
-rw-r--r--src/libs/clangsupport/processstartedevent.h44
-rw-r--r--src/libs/clangsupport/readmessageblock.cpp122
-rw-r--r--src/libs/clangsupport/readmessageblock.h65
-rw-r--r--src/libs/clangsupport/referencesmessage.cpp45
-rw-r--r--src/libs/clangsupport/referencesmessage.h89
-rw-r--r--src/libs/clangsupport/requestannotationsmessage.cpp41
-rw-r--r--src/libs/clangsupport/requestannotationsmessage.h68
-rw-r--r--src/libs/clangsupport/requestcompletionsmessage.cpp51
-rw-r--r--src/libs/clangsupport/requestcompletionsmessage.h102
-rw-r--r--src/libs/clangsupport/requestfollowsymbolmessage.cpp48
-rw-r--r--src/libs/clangsupport/requestfollowsymbolmessage.h90
-rw-r--r--src/libs/clangsupport/requestreferencesmessage.cpp49
-rw-r--r--src/libs/clangsupport/requestreferencesmessage.h96
-rw-r--r--src/libs/clangsupport/requesttooltipmessage.cpp48
-rw-r--r--src/libs/clangsupport/requesttooltipmessage.h89
-rw-r--r--src/libs/clangsupport/sourcelocationcontainer.cpp74
-rw-r--r--src/libs/clangsupport/sourcelocationcontainer.h60
-rw-r--r--src/libs/clangsupport/sourcelocationscontainer.cpp47
-rw-r--r--src/libs/clangsupport/sourcelocationscontainer.h92
-rw-r--r--src/libs/clangsupport/sourcerangecontainer.cpp54
-rw-r--r--src/libs/clangsupport/sourcerangecontainer.h90
-rw-r--r--src/libs/clangsupport/tokeninfocontainer.cpp114
-rw-r--r--src/libs/clangsupport/tokeninfocontainer.h344
-rw-r--r--src/libs/clangsupport/tooltipinfo.cpp65
-rw-r--r--src/libs/clangsupport/tooltipinfo.h113
-rw-r--r--src/libs/clangsupport/tooltipmessage.cpp44
-rw-r--r--src/libs/clangsupport/tooltipmessage.h82
-rw-r--r--src/libs/clangsupport/unsavedfilesremovedmessage.cpp45
-rw-r--r--src/libs/clangsupport/unsavedfilesremovedmessage.h70
-rw-r--r--src/libs/clangsupport/unsavedfilesupdatedmessage.cpp45
-rw-r--r--src/libs/clangsupport/unsavedfilesupdatedmessage.h70
-rw-r--r--src/libs/clangsupport/utf8string.cpp58
-rw-r--r--src/libs/clangsupport/utf8string.h323
-rw-r--r--src/libs/clangsupport/utf8stringvector.cpp113
-rw-r--r--src/libs/clangsupport/utf8stringvector.h105
-rw-r--r--src/libs/clangsupport/writemessageblock.cpp106
-rw-r--r--src/libs/clangsupport/writemessageblock.h68
-rw-r--r--src/libs/cplusplus/AlreadyConsideredClassContainer.h2
-rw-r--r--src/libs/cplusplus/CMakeLists.txt9
-rw-r--r--src/libs/cplusplus/CppDocument.cpp22
-rw-r--r--src/libs/cplusplus/CppDocument.h2
-rw-r--r--src/libs/cplusplus/CppRewriter.cpp4
-rw-r--r--src/libs/cplusplus/DependencyTable.cpp5
-rw-r--r--src/libs/cplusplus/FastPreprocessor.cpp6
-rw-r--r--src/libs/cplusplus/FindUsages.cpp48
-rw-r--r--src/libs/cplusplus/FindUsages.h8
-rw-r--r--src/libs/cplusplus/Icons.cpp26
-rw-r--r--src/libs/cplusplus/LookupContext.cpp112
-rw-r--r--src/libs/cplusplus/LookupContext.h4
-rw-r--r--src/libs/cplusplus/Macro.cpp2
-rw-r--r--src/libs/cplusplus/MatchingText.cpp2
-rw-r--r--src/libs/cplusplus/PreprocessorEnvironment.cpp2
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp43
-rw-r--r--src/libs/cplusplus/SnapshotSymbolVisitor.cpp3
-rw-r--r--src/libs/cplusplus/SymbolNameVisitor.cpp2
-rw-r--r--src/libs/cplusplus/TypeOfExpression.cpp6
-rw-r--r--src/libs/cplusplus/pp-engine.cpp3
-rw-r--r--src/libs/extensionsystem/extensionsystem_global.h2
-rw-r--r--src/libs/extensionsystem/pluginmanager.cpp28
-rw-r--r--src/libs/extensionsystem/pluginspec.cpp85
-rw-r--r--src/libs/extensionsystem/pluginspec.h4
-rw-r--r--src/libs/extensionsystem/pluginspec_p.h7
-rw-r--r--src/libs/glsl/glsl.h2
-rw-r--r--src/libs/languageserverprotocol/CMakeLists.txt1
-rw-r--r--src/libs/languageserverprotocol/basemessage.cpp20
-rw-r--r--src/libs/languageserverprotocol/basemessage.h5
-rw-r--r--src/libs/languageserverprotocol/clientcapabilities.cpp12
-rw-r--r--src/libs/languageserverprotocol/clientcapabilities.h2
-rw-r--r--src/libs/languageserverprotocol/completion.cpp18
-rw-r--r--src/libs/languageserverprotocol/completion.h21
-rw-r--r--src/libs/languageserverprotocol/icontent.h131
-rw-r--r--src/libs/languageserverprotocol/initializemessages.cpp12
-rw-r--r--src/libs/languageserverprotocol/initializemessages.h17
-rw-r--r--src/libs/languageserverprotocol/jsonkeys.h420
-rw-r--r--src/libs/languageserverprotocol/jsonobject.cpp4
-rw-r--r--src/libs/languageserverprotocol/jsonobject.h67
-rw-r--r--src/libs/languageserverprotocol/jsonrpcmessages.cpp103
-rw-r--r--src/libs/languageserverprotocol/jsonrpcmessages.h138
-rw-r--r--src/libs/languageserverprotocol/languagefeatures.cpp22
-rw-r--r--src/libs/languageserverprotocol/languagefeatures.h11
-rw-r--r--src/libs/languageserverprotocol/languageserverprotocol.qbs1
-rw-r--r--src/libs/languageserverprotocol/languageserverprotocol_global.h2
-rw-r--r--src/libs/languageserverprotocol/lsptypes.cpp7
-rw-r--r--src/libs/languageserverprotocol/lsptypes.h3
-rw-r--r--src/libs/languageserverprotocol/lsputils.cpp2
-rw-r--r--src/libs/languageserverprotocol/lsputils.h1
-rw-r--r--src/libs/languageserverprotocol/messages.cpp2
-rw-r--r--src/libs/languageserverprotocol/servercapabilities.cpp9
-rw-r--r--src/libs/languageserverprotocol/workspace.cpp2
-rw-r--r--src/libs/languageserverprotocol/workspace.h2
-rw-r--r--src/libs/languageutils/languageutils_global.h2
-rw-r--r--src/libs/libs.qbs2
-rw-r--r--src/libs/modelinglib/CMakeLists.txt3
-rw-r--r--src/libs/modelinglib/modelinglib.qbs2
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp8
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/qmt_global.h2
-rw-r--r--src/libs/modelinglib/qmt/resources/resources_modelinglib.qrc (renamed from src/libs/modelinglib/qmt/resources/resources.qrc)0
m---------src/libs/qlitehtml0
-rw-r--r--src/libs/qmldebug/qmldebug_global.h2
-rw-r--r--src/libs/qmldebug/qmldebugconnection.cpp13
-rw-r--r--src/libs/qmleditorwidgets/CMakeLists.txt2
-rw-r--r--src/libs/qmleditorwidgets/qmleditorwidgets.qbs2
-rw-r--r--src/libs/qmleditorwidgets/qmleditorwidgets_global.h2
-rw-r--r--src/libs/qmleditorwidgets/resources_qmleditorwidgets.qrc (renamed from src/libs/qmleditorwidgets/resources.qrc)0
-rw-r--r--src/libs/qmljs/parser/qmljsglobal_p.h2
-rw-r--r--src/libs/qmljs/qmljs_global.h2
-rw-r--r--src/libs/qmljs/qmljscheck.cpp40
-rw-r--r--src/libs/qmljs/qmljsevaluate.cpp1
-rw-r--r--src/libs/qmljs/qmljsfindexportedcpptypes.cpp2
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp8
-rw-r--r--src/libs/qmljs/qmljslink.cpp3
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp104
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h3
-rw-r--r--src/libs/qmljs/qmljsplugindumper.cpp35
-rw-r--r--src/libs/qmljs/qmljsplugindumper.h8
-rw-r--r--src/libs/qmljs/qmljsreformatter.cpp33
-rw-r--r--src/libs/qmljs/qmljsreformatter.h4
-rw-r--r--src/libs/qmljs/qmljsscanner.cpp20
-rw-r--r--src/libs/qmljs/qmljsstaticanalysismessage.cpp4
-rw-r--r--src/libs/qmljs/qmljsstaticanalysismessage.h4
-rw-r--r--src/libs/qtcreatorcdbext/CMakeLists.txt10
-rw-r--r--src/libs/sqlite/CMakeLists.txt25
-rw-r--r--src/libs/sqlite/sqlitebasestatement.h4
-rw-r--r--src/libs/sqlite/sqlitedatabasebackend.h4
-rw-r--r--src/libs/sqlite/sqliteglobal.h4
-rw-r--r--src/libs/sqlite/sqlitesessionchangeset.h4
-rw-r--r--src/libs/sqlite/sqlitesessions.h4
-rw-r--r--src/libs/ssh/CMakeLists.txt22
-rw-r--r--src/libs/ssh/sftpdefs.cpp28
-rw-r--r--src/libs/ssh/sftpdefs.h75
-rw-r--r--src/libs/ssh/sftpfilesystemmodel.cpp384
-rw-r--r--src/libs/ssh/sftpfilesystemmodel.h100
-rw-r--r--src/libs/ssh/sftpsession.cpp340
-rw-r--r--src/libs/ssh/sftpsession.h73
-rw-r--r--src/libs/ssh/sftptransfer.cpp192
-rw-r--r--src/libs/ssh/sftptransfer.h62
-rw-r--r--src/libs/ssh/ssh.qbs50
-rw-r--r--src/libs/ssh/ssh.qrc5
-rw-r--r--src/libs/ssh/ssh_global.h40
-rw-r--r--src/libs/ssh/sshconnection.cpp498
-rw-r--r--src/libs/ssh/sshconnection.h160
-rw-r--r--src/libs/ssh/sshconnectionmanager.cpp226
-rw-r--r--src/libs/ssh/sshconnectionmanager.h58
-rw-r--r--src/libs/ssh/sshkeycreationdialog.cpp140
-rw-r--r--src/libs/ssh/sshkeycreationdialog.h59
-rw-r--r--src/libs/ssh/sshkeycreationdialog.ui250
-rw-r--r--src/libs/ssh/sshlogging.cpp32
-rw-r--r--src/libs/ssh/sshlogging_p.h34
-rw-r--r--src/libs/ssh/sshprocess.cpp51
-rw-r--r--src/libs/ssh/sshprocess.h40
-rw-r--r--src/libs/ssh/sshremoteprocess.cpp108
-rw-r--r--src/libs/ssh/sshremoteprocess.h57
-rw-r--r--src/libs/ssh/sshremoteprocessrunner.cpp233
-rw-r--r--src/libs/ssh/sshremoteprocessrunner.h75
-rw-r--r--src/libs/ssh/sshsettings.cpp171
-rw-r--r--src/libs/ssh/sshsettings.h68
-rw-r--r--src/libs/tracing/qml/MainView.qml18
-rw-r--r--src/libs/tracing/tracing_global.h2
-rw-r--r--src/libs/utils/CMakeLists.txt46
-rw-r--r--src/libs/utils/algorithm.h16
-rw-r--r--src/libs/utils/ansiescapecodehandler.cpp3
-rw-r--r--src/libs/utils/appmainwindow.cpp2
-rw-r--r--src/libs/utils/appmainwindow.h1
-rw-r--r--src/libs/utils/archive.cpp123
-rw-r--r--src/libs/utils/archive.h19
-rw-r--r--src/libs/utils/aspects.cpp115
-rw-r--r--src/libs/utils/aspects.h125
-rw-r--r--src/libs/utils/basetreeview.cpp7
-rw-r--r--src/libs/utils/buildablehelperlibrary.cpp8
-rw-r--r--src/libs/utils/buildablehelperlibrary.h7
-rw-r--r--src/libs/utils/changeset.h4
-rw-r--r--src/libs/utils/checkablemessagebox.cpp1
-rw-r--r--src/libs/utils/classnamevalidatinglineedit.cpp3
-rw-r--r--src/libs/utils/classnamevalidatinglineedit.h2
-rw-r--r--src/libs/utils/codegeneration.cpp20
-rw-r--r--src/libs/utils/commandline.cpp34
-rw-r--r--src/libs/utils/commandline.h10
-rw-r--r--src/libs/utils/completinglineedit.h1
-rw-r--r--src/libs/utils/crumblepath.cpp4
-rw-r--r--src/libs/utils/declarationmacros.h32
-rw-r--r--src/libs/utils/delegates.cpp1
-rw-r--r--src/libs/utils/delegates.h1
-rw-r--r--src/libs/utils/detailsbutton.cpp2
-rw-r--r--src/libs/utils/detailsbutton.h4
-rw-r--r--src/libs/utils/detailswidget.cpp1
-rw-r--r--src/libs/utils/deviceshell.cpp527
-rw-r--r--src/libs/utils/deviceshell.h109
-rw-r--r--src/libs/utils/differ.cpp14
-rw-r--r--src/libs/utils/differ.h1
-rw-r--r--src/libs/utils/dropsupport.cpp6
-rw-r--r--src/libs/utils/dropsupport.h2
-rw-r--r--src/libs/utils/elfreader.cpp2
-rw-r--r--src/libs/utils/elfreader.h10
-rw-r--r--src/libs/utils/elidinglabel.cpp43
-rw-r--r--src/libs/utils/elidinglabel.h12
-rw-r--r--src/libs/utils/environment.cpp107
-rw-r--r--src/libs/utils/environment.h97
-rw-r--r--src/libs/utils/environmentdialog.cpp8
-rw-r--r--src/libs/utils/environmentdialog.h4
-rw-r--r--src/libs/utils/environmentmodel.cpp16
-rw-r--r--src/libs/utils/environmentmodel.h4
-rw-r--r--src/libs/utils/execmenu.cpp1
-rw-r--r--src/libs/utils/fadingindicator.h6
-rw-r--r--src/libs/utils/fancylineedit.cpp8
-rw-r--r--src/libs/utils/fancylineedit.h3
-rw-r--r--src/libs/utils/fancymainwindow.cpp5
-rw-r--r--src/libs/utils/filecrumblabel.cpp3
-rw-r--r--src/libs/utils/filecrumblabel.h3
-rw-r--r--src/libs/utils/fileinprojectfinder.cpp3
-rw-r--r--src/libs/utils/fileinprojectfinder.h9
-rw-r--r--src/libs/utils/filenamevalidatinglineedit.cpp1
-rw-r--r--src/libs/utils/filepath.cpp181
-rw-r--r--src/libs/utils/filepath.h10
-rw-r--r--src/libs/utils/filesearch.cpp28
-rw-r--r--src/libs/utils/filesearch.h8
-rw-r--r--src/libs/utils/filesystemmodel.cpp6
-rw-r--r--src/libs/utils/filesystemmodel.h1
-rw-r--r--src/libs/utils/fileutils.cpp48
-rw-r--r--src/libs/utils/fileutils.h15
-rw-r--r--src/libs/utils/filewizardpage.cpp2
-rw-r--r--src/libs/utils/filewizardpage.h3
-rw-r--r--src/libs/utils/fixedsizeclicklabel.h1
-rw-r--r--src/libs/utils/futuresynchronizer.h2
-rw-r--r--src/libs/utils/guard.h1
-rw-r--r--src/libs/utils/headerviewstretcher.cpp1
-rw-r--r--src/libs/utils/headerviewstretcher.h1
-rw-r--r--src/libs/utils/historycompleter.cpp4
-rw-r--r--src/libs/utils/hostosinfo.cpp30
-rw-r--r--src/libs/utils/hostosinfo.h9
-rw-r--r--src/libs/utils/htmldocextractor.cpp1
-rw-r--r--src/libs/utils/htmldocextractor.h4
-rw-r--r--src/libs/utils/icon.cpp51
-rw-r--r--src/libs/utils/icon.h18
-rw-r--r--src/libs/utils/id.cpp16
-rw-r--r--src/libs/utils/id.h7
-rw-r--r--src/libs/utils/images/help.png (renamed from src/libs/ssh/images/help.png)bin430 -> 430 bytes
-rw-r--r--src/libs/utils/infobar.cpp77
-rw-r--r--src/libs/utils/infobar.h35
-rw-r--r--src/libs/utils/infolabel.cpp7
-rw-r--r--src/libs/utils/itemviews.h6
-rw-r--r--src/libs/utils/json.cpp5
-rw-r--r--src/libs/utils/json.h8
-rw-r--r--src/libs/utils/jsontreeitem.cpp30
-rw-r--r--src/libs/utils/jsontreeitem.h2
-rw-r--r--src/libs/utils/launcherinterface.cpp14
-rw-r--r--src/libs/utils/launcherinterface.h11
-rw-r--r--src/libs/utils/launcherpackets.cpp100
-rw-r--r--src/libs/utils/launcherpackets.h41
-rw-r--r--src/libs/utils/launchersocket.cpp542
-rw-r--r--src/libs/utils/launchersocket.h121
-rw-r--r--src/libs/utils/layoutbuilder.cpp6
-rw-r--r--src/libs/utils/link.h15
-rw-r--r--src/libs/utils/listmodel.h1
-rw-r--r--src/libs/utils/macroexpander.cpp3
-rw-r--r--src/libs/utils/macroexpander.h6
-rw-r--r--src/libs/utils/mapreduce.h1
-rw-r--r--src/libs/utils/mimetypes/mimedatabase.cpp140
-rw-r--r--src/libs/utils/mimetypes/mimedatabase.h74
-rw-r--r--src/libs/utils/mimetypes/mimedatabase_p.h47
-rw-r--r--src/libs/utils/mimetypes/mimemagicrule_p.h7
-rw-r--r--src/libs/utils/mimetypes/mimeutils.cpp140
-rw-r--r--src/libs/utils/mimetypes2/mimedatabase.cpp960
-rw-r--r--src/libs/utils/mimetypes2/mimedatabase.h97
-rw-r--r--src/libs/utils/mimetypes2/mimedatabase_p.h136
-rw-r--r--src/libs/utils/mimetypes2/mimeglobpattern.cpp312
-rw-r--r--src/libs/utils/mimetypes2/mimeglobpattern_p.h176
-rw-r--r--src/libs/utils/mimetypes2/mimemagicrule.cpp412
-rw-r--r--src/libs/utils/mimetypes2/mimemagicrule_p.h146
-rw-r--r--src/libs/utils/mimetypes2/mimemagicrulematcher.cpp104
-rw-r--r--src/libs/utils/mimetypes2/mimemagicrulematcher_p.h95
-rw-r--r--src/libs/utils/mimetypes2/mimeprovider.cpp1011
-rw-r--r--src/libs/utils/mimetypes2/mimeprovider_p.h226
-rw-r--r--src/libs/utils/mimetypes2/mimetype.cpp570
-rw-r--r--src/libs/utils/mimetypes2/mimetype.h142
-rw-r--r--src/libs/utils/mimetypes2/mimetype_p.h102
-rw-r--r--src/libs/utils/mimetypes2/mimetypeparser.cpp348
-rw-r--r--src/libs/utils/mimetypes2/mimetypeparser_p.h129
-rw-r--r--src/libs/utils/mimetypes2/mimeutils.cpp135
-rw-r--r--src/libs/utils/mimeutils.h83
-rw-r--r--src/libs/utils/minimizableinfobars.cpp157
-rw-r--r--src/libs/utils/minimizableinfobars.h80
-rw-r--r--src/libs/utils/multitextcursor.cpp6
-rw-r--r--src/libs/utils/multitextcursor.h1
-rw-r--r--src/libs/utils/namevaluedictionary.cpp3
-rw-r--r--src/libs/utils/namevaluedictionary.h4
-rw-r--r--src/libs/utils/namevalueitem.h2
-rw-r--r--src/libs/utils/namevaluemodel.cpp10
-rw-r--r--src/libs/utils/namevaluemodel.h3
-rw-r--r--src/libs/utils/namevaluesdialog.cpp4
-rw-r--r--src/libs/utils/namevaluesdialog.h4
-rw-r--r--src/libs/utils/namevaluevalidator.cpp10
-rw-r--r--src/libs/utils/namevaluevalidator.h14
-rw-r--r--src/libs/utils/networkaccessmanager.h4
-rw-r--r--src/libs/utils/outputformatter.cpp10
-rw-r--r--src/libs/utils/outputformatter.h4
-rw-r--r--src/libs/utils/pathchooser.cpp29
-rw-r--r--src/libs/utils/pathchooser.h10
-rw-r--r--src/libs/utils/pathlisteditor.cpp11
-rw-r--r--src/libs/utils/pathlisteditor.h1
-rw-r--r--src/libs/utils/persistentsettings.cpp15
-rw-r--r--src/libs/utils/persistentsettings.h3
-rw-r--r--src/libs/utils/port.cpp38
-rw-r--r--src/libs/utils/port.h5
-rw-r--r--src/libs/utils/porting.h13
-rw-r--r--src/libs/utils/portlist.cpp1
-rw-r--r--src/libs/utils/portlist.h5
-rw-r--r--src/libs/utils/process_ctrlc_stub.cpp9
-rw-r--r--src/libs/utils/processenums.h81
-rw-r--r--src/libs/utils/processhandle.h10
-rw-r--r--src/libs/utils/processinfo.cpp205
-rw-r--r--src/libs/utils/processinfo.h47
-rw-r--r--src/libs/utils/processinterface.cpp48
-rw-r--r--src/libs/utils/processinterface.h139
-rw-r--r--src/libs/utils/processreaper.cpp313
-rw-r--r--src/libs/utils/processreaper.h8
-rw-r--r--src/libs/utils/processutils.cpp69
-rw-r--r--src/libs/utils/processutils.h20
-rw-r--r--src/libs/utils/progressindicator.cpp3
-rw-r--r--src/libs/utils/progressindicator.h4
-rw-r--r--src/libs/utils/projectintropage.cpp1
-rw-r--r--src/libs/utils/projectintropage.h4
-rw-r--r--src/libs/utils/proxyaction.cpp3
-rw-r--r--src/libs/utils/proxycredentialsdialog.cpp1
-rw-r--r--src/libs/utils/proxycredentialsdialog.h5
-rw-r--r--src/libs/utils/qrcparser.cpp51
-rw-r--r--src/libs/utils/qrcparser.h19
-rw-r--r--src/libs/utils/qtcprocess.cpp1730
-rw-r--r--src/libs/utils/qtcprocess.h253
-rw-r--r--src/libs/utils/reloadpromptutils.cpp12
-rw-r--r--src/libs/utils/removefiledialog.cpp2
-rw-r--r--src/libs/utils/runextensions.h7
-rw-r--r--src/libs/utils/savefile.cpp6
-rw-r--r--src/libs/utils/savefile.h6
-rw-r--r--src/libs/utils/settingsaccessor.cpp8
-rw-r--r--src/libs/utils/settingsaccessor.h6
-rw-r--r--src/libs/utils/shellcommand.cpp31
-rw-r--r--src/libs/utils/shellcommand.h11
-rw-r--r--src/libs/utils/singleton.cpp4
-rw-r--r--src/libs/utils/statuslabel.h4
-rw-r--r--src/libs/utils/stringutils.cpp29
-rw-r--r--src/libs/utils/stringutils.h10
-rw-r--r--src/libs/utils/stylehelper.cpp12
-rw-r--r--src/libs/utils/templateengine.cpp1
-rw-r--r--src/libs/utils/templateengine.h11
-rw-r--r--src/libs/utils/temporarydirectory.cpp7
-rw-r--r--src/libs/utils/temporaryfile.cpp2
-rw-r--r--src/libs/utils/temporaryfile.h1
-rw-r--r--src/libs/utils/terminalcommand.cpp14
-rw-r--r--src/libs/utils/terminalprocess.cpp377
-rw-r--r--src/libs/utils/terminalprocess_p.h54
-rw-r--r--src/libs/utils/textfieldcheckbox.h4
-rw-r--r--src/libs/utils/textfieldcombobox.h4
-rw-r--r--src/libs/utils/textfileformat.cpp4
-rw-r--r--src/libs/utils/textutils.cpp4
-rw-r--r--src/libs/utils/textutils.h9
-rw-r--r--src/libs/utils/theme/theme.h6
-rw-r--r--src/libs/utils/theme/theme_p.h3
-rw-r--r--src/libs/utils/tooltip/tips.cpp6
-rw-r--r--src/libs/utils/tooltip/tips.h6
-rw-r--r--src/libs/utils/tooltip/tooltip.cpp6
-rw-r--r--src/libs/utils/tooltip/tooltip.h1
-rw-r--r--src/libs/utils/touchbar/touchbar.cpp5
-rw-r--r--src/libs/utils/touchbar/touchbar.h12
-rw-r--r--src/libs/utils/treemodel.cpp1
-rw-r--r--src/libs/utils/treemodel.h1
-rw-r--r--src/libs/utils/uncommentselection.cpp5
-rw-r--r--src/libs/utils/uncommentselection.h2
-rw-r--r--src/libs/utils/unixutils.cpp6
-rw-r--r--src/libs/utils/unixutils.h1
-rw-r--r--src/libs/utils/url.cpp2
-rw-r--r--src/libs/utils/url.h6
-rw-r--r--src/libs/utils/utils.qbs20
-rw-r--r--src/libs/utils/utils.qrc1
-rw-r--r--src/libs/utils/utils_global.h2
-rw-r--r--src/libs/utils/utilsicons.cpp6
-rw-r--r--src/libs/utils/utilsicons.h6
-rw-r--r--src/libs/utils/variablechooser.cpp40
-rw-r--r--src/libs/utils/variablechooser.h7
-rw-r--r--src/libs/utils/winutils.cpp8
-rw-r--r--src/libs/utils/wizard.cpp7
-rw-r--r--src/plugins/CMakeLists.txt3
-rw-r--r--src/plugins/android/CMakeLists.txt2
-rw-r--r--src/plugins/android/android_global.h2
-rw-r--r--src/plugins/android/androidavdmanager.cpp102
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp16
-rw-r--r--src/plugins/android/androidbuildapkstep.h2
-rw-r--r--src/plugins/android/androidconfigurations.cpp155
-rw-r--r--src/plugins/android/androidconfigurations.h14
-rw-r--r--src/plugins/android/androidconstants.h8
-rw-r--r--src/plugins/android/androidcreatekeystorecertificate.cpp4
-rw-r--r--src/plugins/android/androiddebugsupport.cpp9
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp54
-rw-r--r--src/plugins/android/androiddeployqtstep.h5
-rw-r--r--src/plugins/android/androiddevice.cpp327
-rw-r--r--src/plugins/android/androiddevice.h30
-rw-r--r--src/plugins/android/androiddeviceinfo.cpp16
-rw-r--r--src/plugins/android/androiddeviceinfo.h9
-rw-r--r--src/plugins/android/androidmanager.cpp98
-rw-r--r--src/plugins/android/androidmanifesteditor.cpp3
-rw-r--r--src/plugins/android/androidmanifesteditorwidget.cpp6
-rw-r--r--src/plugins/android/androidpackageinstallationstep.cpp2
-rw-r--r--src/plugins/android/androidplugin.cpp9
-rw-r--r--src/plugins/android/androidplugin.h1
-rw-r--r--src/plugins/android/androidpotentialkit.cpp10
-rw-r--r--src/plugins/android/androidqmlpreviewworker.cpp17
-rw-r--r--src/plugins/android/androidqmlpreviewworker.h4
-rw-r--r--src/plugins/android/androidqtversion.cpp40
-rw-r--r--src/plugins/android/androidrunconfiguration.cpp7
-rw-r--r--src/plugins/android/androidrunner.cpp6
-rw-r--r--src/plugins/android/androidrunnerworker.cpp29
-rw-r--r--src/plugins/android/androidsdkdownloader.cpp27
-rw-r--r--src/plugins/android/androidsdkdownloader.h11
-rw-r--r--src/plugins/android/androidsdkmanager.cpp53
-rw-r--r--src/plugins/android/androidsdkmanagerwidget.cpp18
-rw-r--r--src/plugins/android/androidsdkmanagerwidget.h2
-rw-r--r--src/plugins/android/androidsdkmanagerwidget.ui15
-rw-r--r--src/plugins/android/androidsettingswidget.cpp104
-rw-r--r--src/plugins/android/androidsettingswidget.ui15
-rw-r--r--src/plugins/android/androidsignaloperation.cpp77
-rw-r--r--src/plugins/android/androidsignaloperation.h21
-rw-r--r--src/plugins/android/avddialog.cpp10
-rw-r--r--src/plugins/android/avdmanageroutputparser.cpp17
-rw-r--r--src/plugins/android/javalanguageserver.cpp3
-rw-r--r--src/plugins/android/javalanguageserver.h3
-rw-r--r--src/plugins/android/splashscreencontainerwidget.cpp2
-rw-r--r--src/plugins/autotest/CMakeLists.txt1
-rw-r--r--src/plugins/autotest/autotest_global.h2
-rw-r--r--src/plugins/autotest/autotestconstants.h1
-rw-r--r--src/plugins/autotest/autotestplugin.cpp2
-rw-r--r--src/plugins/autotest/boost/boosttestconfiguration.cpp3
-rw-r--r--src/plugins/autotest/boost/boosttestconfiguration.h2
-rw-r--r--src/plugins/autotest/boost/boosttestframework.cpp9
-rw-r--r--src/plugins/autotest/boost/boosttestframework.h1
-rw-r--r--src/plugins/autotest/boost/boosttestoutputreader.cpp12
-rw-r--r--src/plugins/autotest/boost/boosttestoutputreader.h4
-rw-r--r--src/plugins/autotest/catch/catchcodeparser.cpp24
-rw-r--r--src/plugins/autotest/catch/catchconfiguration.cpp5
-rw-r--r--src/plugins/autotest/catch/catchconfiguration.h2
-rw-r--r--src/plugins/autotest/catch/catchframework.cpp7
-rw-r--r--src/plugins/autotest/catch/catchframework.h1
-rw-r--r--src/plugins/autotest/catch/catchoutputreader.cpp3
-rw-r--r--src/plugins/autotest/catch/catchoutputreader.h2
-rw-r--r--src/plugins/autotest/catch/catchtestparser.cpp6
-rw-r--r--src/plugins/autotest/catch/catchtreeitem.cpp4
-rw-r--r--src/plugins/autotest/ctest/ctestconfiguration.cpp2
-rw-r--r--src/plugins/autotest/ctest/ctestconfiguration.h2
-rw-r--r--src/plugins/autotest/ctest/ctestoutputreader.cpp2
-rw-r--r--src/plugins/autotest/ctest/ctestoutputreader.h4
-rw-r--r--src/plugins/autotest/ctest/ctesttool.cpp7
-rw-r--r--src/plugins/autotest/ctest/ctesttool.h1
-rw-r--r--src/plugins/autotest/ctest/ctesttreeitem.cpp1
-rw-r--r--src/plugins/autotest/gtest/gtestconfiguration.cpp2
-rw-r--r--src/plugins/autotest/gtest/gtestconfiguration.h2
-rw-r--r--src/plugins/autotest/gtest/gtestframework.cpp9
-rw-r--r--src/plugins/autotest/gtest/gtestframework.h1
-rw-r--r--src/plugins/autotest/gtest/gtestoutputreader.cpp9
-rw-r--r--src/plugins/autotest/gtest/gtestoutputreader.h2
-rw-r--r--src/plugins/autotest/itestframework.h1
-rw-r--r--src/plugins/autotest/loadprojectscenario.cpp2
-rw-r--r--src/plugins/autotest/projectsettingswidget.cpp30
-rw-r--r--src/plugins/autotest/projectsettingswidget.h5
-rw-r--r--src/plugins/autotest/qtest/qttestconfiguration.cpp2
-rw-r--r--src/plugins/autotest/qtest/qttestconfiguration.h2
-rw-r--r--src/plugins/autotest/qtest/qttestframework.cpp9
-rw-r--r--src/plugins/autotest/qtest/qttestframework.h1
-rw-r--r--src/plugins/autotest/qtest/qttestoutputreader.cpp2
-rw-r--r--src/plugins/autotest/qtest/qttestoutputreader.h2
-rw-r--r--src/plugins/autotest/qtest/qttestresult.cpp8
-rw-r--r--src/plugins/autotest/qtest/qttestsettings.cpp1
-rw-r--r--src/plugins/autotest/quick/quicktest_utils.cpp5
-rw-r--r--src/plugins/autotest/quick/quicktestconfiguration.cpp2
-rw-r--r--src/plugins/autotest/quick/quicktestconfiguration.h2
-rw-r--r--src/plugins/autotest/quick/quicktestframework.cpp7
-rw-r--r--src/plugins/autotest/quick/quicktestframework.h1
-rw-r--r--src/plugins/autotest/quick/quicktestparser.cpp4
-rw-r--r--src/plugins/autotest/testconfiguration.cpp4
-rw-r--r--src/plugins/autotest/testconfiguration.h6
-rw-r--r--src/plugins/autotest/testframeworkmanager.cpp1
-rw-r--r--src/plugins/autotest/testoutputreader.cpp20
-rw-r--r--src/plugins/autotest/testoutputreader.h7
-rw-r--r--src/plugins/autotest/testrunconfiguration.h2
-rw-r--r--src/plugins/autotest/testrunner.cpp56
-rw-r--r--src/plugins/autotest/testrunner.h8
-rw-r--r--src/plugins/autotest/testsettingspage.cpp6
-rw-r--r--src/plugins/autotest/testsettingspage.ui10
-rw-r--r--src/plugins/autotoolsprojectmanager/CMakeLists.txt1
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp6
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp2
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwidget.h2
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwizard.h4
-rw-r--r--src/plugins/baremetal/baremetalplugin.cpp1
-rw-r--r--src/plugins/baremetal/baremetalrunconfiguration.cpp16
-rw-r--r--src/plugins/baremetal/debugservers/gdb/gdbserverprovider.cpp20
-rw-r--r--src/plugins/baremetal/debugservers/gdb/gdbserverprovider.h2
-rw-r--r--src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp5
-rw-r--r--src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp37
-rw-r--r--src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.h2
-rw-r--r--src/plugins/baremetal/iarewtoolchain.cpp6
-rw-r--r--src/plugins/baremetal/keiltoolchain.cpp6
-rw-r--r--src/plugins/baremetal/sdcctoolchain.cpp6
-rw-r--r--src/plugins/bazaar/bazaarclient.cpp11
-rw-r--r--src/plugins/bazaar/bazaarplugin.cpp2
-rw-r--r--src/plugins/beautifier/abstractsettings.cpp89
-rw-r--r--src/plugins/beautifier/abstractsettings.h18
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyle.cpp7
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp60
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstylesettings.h15
-rw-r--r--src/plugins/beautifier/beautifierplugin.cpp2
-rw-r--r--src/plugins/beautifier/generalsettings.cpp2
-rw-r--r--src/plugins/beautifier/generalsettings.h2
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustify.cpp3
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifysettings.cpp52
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifysettings.h9
-rw-r--r--src/plugins/bineditor/bineditorplugin.cpp2
-rw-r--r--src/plugins/bineditor/bineditorwidget.cpp4
-rw-r--r--src/plugins/boot2qt/CMakeLists.txt5
-rw-r--r--src/plugins/boot2qt/boot2qt.qbs4
-rw-r--r--src/plugins/boot2qt/device-detection/qdbwatcher.cpp9
-rw-r--r--src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp1
-rw-r--r--src/plugins/boot2qt/qdbdevice.cpp89
-rw-r--r--src/plugins/boot2qt/qdbdevice.h2
-rw-r--r--src/plugins/boot2qt/qdbdevicedebugsupport.cpp55
-rw-r--r--src/plugins/boot2qt/qdbmakedefaultappservice.cpp127
-rw-r--r--src/plugins/boot2qt/qdbmakedefaultappservice.h58
-rw-r--r--src/plugins/boot2qt/qdbmakedefaultappstep.cpp99
-rw-r--r--src/plugins/boot2qt/qdbplugin.cpp15
-rw-r--r--src/plugins/boot2qt/qdbrunconfiguration.cpp25
-rw-r--r--src/plugins/boot2qt/qdbstopapplicationservice.cpp119
-rw-r--r--src/plugins/boot2qt/qdbstopapplicationservice.h60
-rw-r--r--src/plugins/boot2qt/qdbstopapplicationstep.cpp109
-rw-r--r--src/plugins/clangcodemodel/CMakeLists.txt39
-rw-r--r--src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp7
-rw-r--r--src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.h3
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalitem.cpp536
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalitem.h80
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalmodel.cpp68
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalmodel.h49
-rw-r--r--src/plugins/clangcodemodel/clangbackendcommunicator.cpp517
-rw-r--r--src/plugins/clangcodemodel/clangbackendcommunicator.h146
-rw-r--r--src/plugins/clangcodemodel/clangbackendlogging.cpp34
-rw-r--r--src/plugins/clangcodemodel/clangbackendlogging.h35
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.cpp374
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.h100
-rw-r--r--src/plugins/clangcodemodel/clangbackendsender.cpp131
-rw-r--r--src/plugins/clangcodemodel/clangbackendsender.h61
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.qbs72
-rw-r--r--src/plugins/clangcodemodel/clangcodemodelplugin.cpp38
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistinterface.cpp81
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistinterface.h69
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp718
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprocessor.h117
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprovider.cpp87
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprovider.h61
-rw-r--r--src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp366
-rw-r--r--src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h114
-rw-r--r--src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp10
-rw-r--r--src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h5
-rw-r--r--src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp177
-rw-r--r--src/plugins/clangcodemodel/clangcurrentdocumentfilter.h60
-rw-r--r--src/plugins/clangcodemodel/clangdast.cpp416
-rw-r--r--src/plugins/clangcodemodel/clangdast.h124
-rw-r--r--src/plugins/clangcodemodel/clangdclient.cpp2843
-rw-r--r--src/plugins/clangcodemodel/clangdclient.h53
-rw-r--r--src/plugins/clangcodemodel/clangdfollowsymbol.cpp527
-rw-r--r--src/plugins/clangcodemodel/clangdfollowsymbol.h66
-rw-r--r--src/plugins/clangcodemodel/clangdiagnosticfilter.cpp188
-rw-r--r--src/plugins/clangcodemodel/clangdiagnosticfilter.h60
-rw-r--r--src/plugins/clangcodemodel/clangdiagnosticmanager.cpp505
-rw-r--r--src/plugins/clangcodemodel/clangdiagnosticmanager.h98
-rw-r--r--src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp106
-rw-r--r--src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h8
-rw-r--r--src/plugins/clangcodemodel/clangdlocatorfilters.cpp28
-rw-r--r--src/plugins/clangcodemodel/clangdlocatorfilters.h2
-rw-r--r--src/plugins/clangcodemodel/clangdsemantichighlighting.cpp925
-rw-r--r--src/plugins/clangcodemodel/clangdsemantichighlighting.h57
-rw-r--r--src/plugins/clangcodemodel/clangdswitchdecldef.cpp198
-rw-r--r--src/plugins/clangcodemodel/clangdswitchdecldef.h60
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentparser.cpp51
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentparser.h46
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp460
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.h97
-rw-r--r--src/plugins/clangcodemodel/clangfixitoperation.cpp38
-rw-r--r--src/plugins/clangcodemodel/clangfixitoperation.h18
-rw-r--r--src/plugins/clangcodemodel/clangfixitoperationsextractor.cpp119
-rw-r--r--src/plugins/clangcodemodel/clangfixitoperationsextractor.h55
-rw-r--r--src/plugins/clangcodemodel/clangfollowsymbol.cpp274
-rw-r--r--src/plugins/clangcodemodel/clangfollowsymbol.h60
-rw-r--r--src/plugins/clangcodemodel/clangfunctionhintmodel.cpp125
-rw-r--r--src/plugins/clangcodemodel/clangfunctionhintmodel.h52
-rw-r--r--src/plugins/clangcodemodel/clanghighlightingresultreporter.cpp224
-rw-r--r--src/plugins/clangcodemodel/clanghighlightingresultreporter.h42
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.cpp227
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.h57
-rw-r--r--src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h78
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.cpp514
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.h65
-rw-r--r--src/plugins/clangcodemodel/clangoverviewmodel.cpp251
-rw-r--r--src/plugins/clangcodemodel/clangoverviewmodel.h70
-rw-r--r--src/plugins/clangcodemodel/clangprojectsettings.cpp147
-rw-r--r--src/plugins/clangcodemodel/clangprojectsettings.h75
-rw-r--r--src/plugins/clangcodemodel/clangprojectsettingswidget.cpp22
-rw-r--r--src/plugins/clangcodemodel/clangprojectsettingswidget.h6
-rw-r--r--src/plugins/clangcodemodel/clangprojectsettingswidget.ui31
-rw-r--r--src/plugins/clangcodemodel/clangrefactoringengine.cpp148
-rw-r--r--src/plugins/clangcodemodel/clangrefactoringengine.h64
-rw-r--r--src/plugins/clangcodemodel/clangtextmark.cpp291
-rw-r--r--src/plugins/clangcodemodel/clangtextmark.h32
-rw-r--r--src/plugins/clangcodemodel/clanguiheaderondiskmanager.cpp75
-rw-r--r--src/plugins/clangcodemodel/clanguiheaderondiskmanager.h50
-rw-r--r--src/plugins/clangcodemodel/clangutils.cpp456
-rw-r--r--src/plugins/clangcodemodel/clangutils.h105
-rw-r--r--src/plugins/clangcodemodel/tasktimers.cpp108
-rw-r--r--src/plugins/clangcodemodel/tasktimers.h90
-rw-r--r--src/plugins/clangcodemodel/test/activationsequenceprocessortest.cpp180
-rw-r--r--src/plugins/clangcodemodel/test/activationsequenceprocessortest.h59
-rw-r--r--src/plugins/clangcodemodel/test/clangautomationutils.cpp140
-rw-r--r--src/plugins/clangcodemodel/test/clangautomationutils.h46
-rw-r--r--src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp45
-rw-r--r--src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp846
-rw-r--r--src/plugins/clangcodemodel/test/clangcodecompletion_test.h70
-rw-r--r--src/plugins/clangcodemodel/test/clangdtests.cpp113
-rw-r--r--src/plugins/clangcodemodel/test/clangfixittest.cpp112
-rw-r--r--src/plugins/clangcodemodel/test/clangfixittest.h64
-rw-r--r--src/plugins/clangcodemodel/test/data/clangtestdata.qrc5
-rw-r--r--src/plugins/clangcodemodel/test/data/completion/completion.pro2
-rw-r--r--src/plugins/clangcodemodel/test/data/find-usages/find-usages.pro2
-rw-r--r--src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit.cpp (renamed from tests/unit/unittest/data/diagnostic_comparison_fixit.cpp)0
-rw-r--r--src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit_expected1.cpp (renamed from tests/unit/unittest/data/diagnostic_comparison_fixit_expected1.cpp)0
-rw-r--r--src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit_expected2.cpp (renamed from tests/unit/unittest/data/diagnostic_comparison_fixit_expected2.cpp)0
-rw-r--r--src/plugins/clangcodemodel/test/data/fixits/diagnostic_semicolon_fixit.cpp (renamed from tests/unit/unittest/data/diagnostic_semicolon_fixit.cpp)0
-rw-r--r--src/plugins/clangcodemodel/test/data/fixits/diagnostic_semicolon_fixit_expected.cpp (renamed from tests/unit/unittest/data/diagnostic_semicolon_fixit_expected.cpp)0
-rw-r--r--src/plugins/clangcodemodel/test/data/follow-symbol/follow-symbol.pro2
-rw-r--r--src/plugins/clangcodemodel/test/data/highlighting/highlighting.pro2
-rw-r--r--src/plugins/clangcodemodel/test/data/local-references/local-references.pro2
-rw-r--r--src/plugins/clangformat/CMakeLists.txt8
-rw-r--r--src/plugins/clangformat/clangformatbaseindenter.cpp51
-rw-r--r--src/plugins/clangformat/clangformatbaseindenter.h3
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.cpp211
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.h11
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.ui71
-rw-r--r--src/plugins/clangformat/clangformatconstants.h6
-rw-r--r--src/plugins/clangformat/clangformatfile.cpp45
-rw-r--r--src/plugins/clangformat/clangformatfile.h6
-rw-r--r--src/plugins/clangformat/clangformatindenter.cpp50
-rw-r--r--src/plugins/clangformat/clangformatindenter.h1
-rw-r--r--src/plugins/clangformat/clangformatplugin.cpp10
-rw-r--r--src/plugins/clangformat/clangformatsettings.cpp43
-rw-r--r--src/plugins/clangformat/clangformatsettings.h19
-rw-r--r--src/plugins/clangformat/clangformatutils.cpp23
-rw-r--r--src/plugins/clangformat/clangformatutils.h5
-rw-r--r--src/plugins/clangformat/tests/clangformat-test.cpp1
-rw-r--r--src/plugins/clangtools/CMakeLists.txt9
-rw-r--r--src/plugins/clangtools/clangtool.cpp7
-rw-r--r--src/plugins/clangtools/clangtoolruncontrol.cpp9
-rw-r--r--src/plugins/clangtools/clangtoolrunner.cpp55
-rw-r--r--src/plugins/clangtools/clangtoolrunner.h7
-rw-r--r--src/plugins/clangtools/clangtools.qbs3
-rw-r--r--src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp6
-rw-r--r--src/plugins/clangtools/clangtoolsplugin.cpp8
-rw-r--r--src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp6
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettings.cpp2
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp61
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettingswidget.h8
-rw-r--r--src/plugins/clangtools/clangtoolssettings.cpp9
-rw-r--r--src/plugins/clangtools/clangtoolsunittests.cpp4
-rw-r--r--src/plugins/clangtools/clangtoolsunittests.qrc12
-rw-r--r--src/plugins/clangtools/diagnosticmark.cpp44
-rw-r--r--src/plugins/clangtools/documentclangtoolrunner.cpp15
-rw-r--r--src/plugins/clangtools/executableinfo.cpp6
-rw-r--r--src/plugins/clangtools/readexporteddiagnosticstest.cpp314
-rw-r--r--src/plugins/clangtools/readexporteddiagnosticstest.h76
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/CMakeLists.txt (renamed from tests/unit/unittest/data/clangtools/CMakeLists.txt)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.cpp (renamed from tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.cpp)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.yaml (renamed from tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.yaml)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero_win.yaml (renamed from tests/unit/unittest/data/clangtools/clang-analyzer.dividezero_win.yaml)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.cpp (renamed from tests/unit/unittest/data/clangtools/clazy.qgetenv.cpp)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.yaml (renamed from tests/unit/unittest/data/clangtools/clazy.qgetenv.yaml)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv_win.yaml (renamed from tests/unit/unittest/data/clangtools/clazy.qgetenv_win.yaml)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/empty.yaml (renamed from tests/unit/unittest/data/clangtools/empty.yaml)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/main.cpp (renamed from tests/unit/unittest/data/clangtools/main.cpp)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.cpp (renamed from tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.cpp)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.yaml (renamed from tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.yaml)0
-rw-r--r--src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr_win.yaml (renamed from tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr_win.yaml)0
-rw-r--r--src/plugins/classview/classviewparsertreeitem.cpp12
-rw-r--r--src/plugins/classview/classviewutils.cpp2
-rw-r--r--src/plugins/clearcase/activityselector.cpp4
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp10
-rw-r--r--src/plugins/clearcase/clearcasesettings.cpp3
-rw-r--r--src/plugins/cmakeprojectmanager/CMakeLists.txt1
-rw-r--r--src/plugins/cmakeprojectmanager/builddirparameters.cpp25
-rw-r--r--src/plugins/cmakeprojectmanager/builddirparameters.h18
-rw-r--r--src/plugins/cmakeprojectmanager/cmake_global.h2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp449
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h59
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.cpp37
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp252
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildsystem.h54
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeeditor.cpp4
-rw-r--r--src/plugins/cmakeprojectmanager/cmakekitinformation.cpp19
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeparser.cpp7
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprocess.cpp163
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprocess.h34
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.cpp35
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.h9
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectconstants.h5
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp41
-rw-r--r--src/plugins/cmakeprojectmanager/cmakesettingspage.cpp7
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketool.cpp33
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp18
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketoolmanager.h6
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp7
-rw-r--r--src/plugins/cmakeprojectmanager/configmodel.cpp4
-rw-r--r--src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp1
-rw-r--r--src/plugins/cmakeprojectmanager/fileapidataextractor.cpp26
-rw-r--r--src/plugins/cmakeprojectmanager/fileapireader.cpp3
-rw-r--r--src/plugins/cmakeprojectmanager/fileapireader.h3
-rw-r--r--src/plugins/coco/CMakeLists.txt7
-rw-r--r--src/plugins/coco/Coco.json.in19
-rw-r--r--src/plugins/coco/coco.qbs21
-rw-r--r--src/plugins/coco/cocolanguageclient.cpp297
-rw-r--r--src/plugins/coco/cocolanguageclient.h52
-rw-r--r--src/plugins/coco/cocoplugin.cpp127
-rw-r--r--src/plugins/coco/cocoplugin.h48
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp39
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp27
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h6
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp15
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h1
-rw-r--r--src/plugins/coreplugin/actionmanager/actioncontainer.cpp6
-rw-r--r--src/plugins/coreplugin/actionmanager/actionmanager.cpp79
-rw-r--r--src/plugins/coreplugin/actionmanager/actionmanager_p.h13
-rw-r--r--src/plugins/coreplugin/actionmanager/command.cpp177
-rw-r--r--src/plugins/coreplugin/actionmanager/command.h61
-rw-r--r--src/plugins/coreplugin/actionmanager/command_p.h40
-rw-r--r--src/plugins/coreplugin/actionmanager/commandsfile.cpp4
-rw-r--r--src/plugins/coreplugin/basefilewizardfactory.cpp18
-rw-r--r--src/plugins/coreplugin/coreconstants.h2
-rw-r--r--src/plugins/coreplugin/corejsextensions.cpp33
-rw-r--r--src/plugins/coreplugin/corejsextensions.h3
-rw-r--r--src/plugins/coreplugin/coreplugin.cpp5
-rw-r--r--src/plugins/coreplugin/designmode.cpp10
-rw-r--r--src/plugins/coreplugin/dialogs/codecselector.cpp9
-rw-r--r--src/plugins/coreplugin/dialogs/externaltoolconfig.cpp8
-rw-r--r--src/plugins/coreplugin/dialogs/externaltoolconfig.ui8
-rw-r--r--src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp4
-rw-r--r--src/plugins/coreplugin/dialogs/ioptionspage.cpp10
-rw-r--r--src/plugins/coreplugin/dialogs/newdialogwidget.cpp3
-rw-r--r--src/plugins/coreplugin/dialogs/openwithdialog.cpp2
-rw-r--r--src/plugins/coreplugin/dialogs/promptoverwritedialog.cpp2
-rw-r--r--src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp10
-rw-r--r--src/plugins/coreplugin/dialogs/saveitemsdialog.cpp12
-rw-r--r--src/plugins/coreplugin/dialogs/saveitemsdialog.h2
-rw-r--r--src/plugins/coreplugin/dialogs/settingsdialog.cpp21
-rw-r--r--src/plugins/coreplugin/dialogs/shortcutsettings.cpp15
-rw-r--r--src/plugins/coreplugin/documentmanager.cpp69
-rw-r--r--src/plugins/coreplugin/documentmanager.h3
-rw-r--r--src/plugins/coreplugin/editormanager/documentmodel.cpp23
-rw-r--r--src/plugins/coreplugin/editormanager/documentmodel.h2
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp110
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.h2
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager_p.h3
-rw-r--r--src/plugins/coreplugin/editormanager/editorview.cpp29
-rw-r--r--src/plugins/coreplugin/editormanager/editorview.h4
-rw-r--r--src/plugins/coreplugin/editormanager/ieditorfactory.cpp2
-rw-r--r--src/plugins/coreplugin/editormanager/ieditorfactory.h6
-rw-r--r--src/plugins/coreplugin/editormanager/ieditorfactory_p.h12
-rw-r--r--src/plugins/coreplugin/editormanager/iexternaleditor.h6
-rw-r--r--src/plugins/coreplugin/editormanager/openeditorswindow.cpp5
-rw-r--r--src/plugins/coreplugin/externaltool.cpp31
-rw-r--r--src/plugins/coreplugin/externaltool.h13
-rw-r--r--src/plugins/coreplugin/externaltoolmanager.cpp26
-rw-r--r--src/plugins/coreplugin/externaltoolmanager.h15
-rw-r--r--src/plugins/coreplugin/fancytabwidget.h5
-rw-r--r--src/plugins/coreplugin/fileiconprovider.cpp5
-rw-r--r--src/plugins/coreplugin/find/basetextfind.cpp2
-rw-r--r--src/plugins/coreplugin/find/finddialog.ui20
-rw-r--r--src/plugins/coreplugin/find/findplugin.cpp2
-rw-r--r--src/plugins/coreplugin/find/findtoolwindow.cpp6
-rw-r--r--src/plugins/coreplugin/find/searchresultcolor.h13
-rw-r--r--src/plugins/coreplugin/find/searchresultitem.h9
-rw-r--r--src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp62
-rw-r--r--src/plugins/coreplugin/find/searchresulttreeitemroles.h6
-rw-r--r--src/plugins/coreplugin/find/searchresulttreemodel.cpp19
-rw-r--r--src/plugins/coreplugin/find/searchresulttreeview.cpp4
-rw-r--r--src/plugins/coreplugin/find/searchresultwindow.cpp6
-rw-r--r--src/plugins/coreplugin/foldernavigationwidget.cpp10
-rw-r--r--src/plugins/coreplugin/icore.cpp6
-rw-r--r--src/plugins/coreplugin/idocument.cpp11
-rw-r--r--src/plugins/coreplugin/idocument.h2
-rw-r--r--src/plugins/coreplugin/iwelcomepage.h1
-rw-r--r--src/plugins/coreplugin/iwizardfactory.cpp20
-rw-r--r--src/plugins/coreplugin/locator/executefilter.cpp24
-rw-r--r--src/plugins/coreplugin/locator/executefilter.h6
-rw-r--r--src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp10
-rw-r--r--src/plugins/coreplugin/mainwindow.cpp30
-rw-r--r--src/plugins/coreplugin/mimetypemagicdialog.cpp22
-rw-r--r--src/plugins/coreplugin/mimetypemagicdialog.h12
-rw-r--r--src/plugins/coreplugin/mimetypesettings.cpp20
-rw-r--r--src/plugins/coreplugin/modemanager.cpp2
-rw-r--r--src/plugins/coreplugin/navigationsubwidget.cpp5
-rw-r--r--src/plugins/coreplugin/navigationwidget.cpp8
-rw-r--r--src/plugins/coreplugin/outputpane.cpp2
-rw-r--r--src/plugins/coreplugin/outputpanemanager.cpp11
-rw-r--r--src/plugins/coreplugin/patchtool.cpp3
-rw-r--r--src/plugins/coreplugin/plugininstallwizard.cpp100
-rw-r--r--src/plugins/coreplugin/progressmanager/progressmanager.cpp46
-rw-r--r--src/plugins/coreplugin/progressmanager/progressmanager_p.h1
-rw-r--r--src/plugins/coreplugin/settingsdatabase.cpp3
-rw-r--r--src/plugins/coreplugin/sidebar.cpp20
-rw-r--r--src/plugins/coreplugin/sidebarwidget.cpp7
-rw-r--r--src/plugins/coreplugin/statusbarmanager.cpp3
-rw-r--r--src/plugins/coreplugin/themechooser.cpp2
-rw-r--r--src/plugins/coreplugin/vcsmanager.cpp15
-rw-r--r--src/plugins/coreplugin/welcomepagehelper.cpp9
-rw-r--r--src/plugins/cpaster/cpasterplugin.cpp2
-rw-r--r--src/plugins/cpaster/frontend/argumentscollector.cpp2
-rw-r--r--src/plugins/cpaster/protocol.cpp8
-rw-r--r--src/plugins/cpaster/settings.cpp2
-rw-r--r--src/plugins/cppcheck/cppcheckplugin.cpp7
-rw-r--r--src/plugins/cppcheck/cppcheckrunner.cpp68
-rw-r--r--src/plugins/cppcheck/cppcheckrunner.h9
-rw-r--r--src/plugins/cppcheck/cppchecktextmark.cpp17
-rw-r--r--src/plugins/cppcheck/cppchecktextmarkmanager.h2
-rw-r--r--src/plugins/cppcheck/cppchecktool.cpp2
-rw-r--r--src/plugins/cppeditor/CMakeLists.txt8
-rw-r--r--src/plugins/cppeditor/abstractoverviewmodel.h2
-rw-r--r--src/plugins/cppeditor/baseeditordocumentprocessor.cpp11
-rw-r--r--src/plugins/cppeditor/baseeditordocumentprocessor.h9
-rw-r--r--src/plugins/cppeditor/builtincursorinfo.cpp5
-rw-r--r--src/plugins/cppeditor/builtineditordocumentparser.cpp6
-rw-r--r--src/plugins/cppeditor/builtineditordocumentprocessor.cpp63
-rw-r--r--src/plugins/cppeditor/builtineditordocumentprocessor.h11
-rw-r--r--src/plugins/cppeditor/builtinindexingsupport.cpp7
-rw-r--r--src/plugins/cppeditor/clangdiagnosticconfig.cpp2
-rw-r--r--src/plugins/cppeditor/clangdiagnosticconfig.h2
-rw-r--r--src/plugins/cppeditor/clangdiagnosticconfigsmodel.cpp17
-rw-r--r--src/plugins/cppeditor/clangdiagnosticconfigsmodel.h2
-rw-r--r--src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp39
-rw-r--r--src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.h6
-rw-r--r--src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp2
-rw-r--r--src/plugins/cppeditor/compileroptionsbuilder.cpp29
-rw-r--r--src/plugins/cppeditor/compileroptionsbuilder.h12
-rw-r--r--src/plugins/cppeditor/compileroptionsbuilder_test.cpp56
-rw-r--r--src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp104
-rw-r--r--src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h21
-rw-r--r--src/plugins/cppeditor/cppchecksymbols.cpp63
-rw-r--r--src/plugins/cppeditor/cppcodeformatter.cpp4
-rw-r--r--src/plugins/cppeditor/cppcodemodelinspectordialog.cpp9
-rw-r--r--src/plugins/cppeditor/cppcodemodelinspectordumper.cpp38
-rw-r--r--src/plugins/cppeditor/cppcodemodelsettings.cpp302
-rw-r--r--src/plugins/cppeditor/cppcodemodelsettings.h43
-rw-r--r--src/plugins/cppeditor/cppcodemodelsettingspage.cpp156
-rw-r--r--src/plugins/cppeditor/cppcodemodelsettingspage.h3
-rw-r--r--src/plugins/cppeditor/cppcodemodelsettingspage.ui50
-rw-r--r--src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp15
-rw-r--r--src/plugins/cppeditor/cppcodestylepreferencesfactory.h12
-rw-r--r--src/plugins/cppeditor/cppcodestylesettingspage.cpp20
-rw-r--r--src/plugins/cppeditor/cppcodestylesettingspage.h4
-rw-r--r--src/plugins/cppeditor/cppcodestylesnippets.h6
-rw-r--r--src/plugins/cppeditor/cppcompletion_test.cpp9
-rw-r--r--src/plugins/cppeditor/cppcompletionassist.cpp111
-rw-r--r--src/plugins/cppeditor/cppcompletionassist.h10
-rw-r--r--src/plugins/cppeditor/cppcompletionassistprovider.h1
-rw-r--r--src/plugins/cppeditor/cppcurrentdocumentfilter.cpp9
-rw-r--r--src/plugins/cppeditor/cppcurrentdocumentfilter.h2
-rw-r--r--src/plugins/cppeditor/cppdoxygen_test.cpp2
-rw-r--r--src/plugins/cppeditor/cppeditor.qbs8
-rw-r--r--src/plugins/cppeditor/cppeditorconstants.h4
-rw-r--r--src/plugins/cppeditor/cppeditordocument.cpp142
-rw-r--r--src/plugins/cppeditor/cppeditordocument.h8
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.cpp20
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.h2
-rw-r--r--src/plugins/cppeditor/cppeditorwidget.cpp237
-rw-r--r--src/plugins/cppeditor/cppeditorwidget.h8
-rw-r--r--src/plugins/cppeditor/cppelementevaluator.cpp48
-rw-r--r--src/plugins/cppeditor/cppfilesettingspage.cpp10
-rw-r--r--src/plugins/cppeditor/cppfindreferences.cpp22
-rw-r--r--src/plugins/cppeditor/cppfollowsymbolundercursor.cpp34
-rw-r--r--src/plugins/cppeditor/cppfollowsymbolundercursor.h19
-rw-r--r--src/plugins/cppeditor/cppfunctiondecldeflink.cpp2
-rw-r--r--src/plugins/cppeditor/cppinsertvirtualmethods.cpp21
-rw-r--r--src/plugins/cppeditor/cpplocalsymbols.cpp8
-rw-r--r--src/plugins/cppeditor/cpplocalsymbols_test.cpp2
-rw-r--r--src/plugins/cppeditor/cpplocatordata.cpp4
-rw-r--r--src/plugins/cppeditor/cppminimizableinfobars.cpp175
-rw-r--r--src/plugins/cppeditor/cppminimizableinfobars.h80
-rw-r--r--src/plugins/cppeditor/cppmodelmanager.cpp297
-rw-r--r--src/plugins/cppeditor/cppmodelmanager.h87
-rw-r--r--src/plugins/cppeditor/cppmodelmanager_test.cpp26
-rw-r--r--src/plugins/cppeditor/cppmodelmanagersupport.h23
-rw-r--r--src/plugins/cppeditor/cppoutline.cpp2
-rw-r--r--src/plugins/cppeditor/cppoverviewmodel.cpp12
-rw-r--r--src/plugins/cppeditor/cppparsecontext.cpp2
-rw-r--r--src/plugins/cppeditor/cpppointerdeclarationformatter.cpp6
-rw-r--r--src/plugins/cppeditor/cppprojectfile.cpp2
-rw-r--r--src/plugins/cppeditor/cppprojectfilecategorizer.cpp2
-rw-r--r--src/plugins/cppeditor/cppprojectinfogenerator.cpp3
-rw-r--r--src/plugins/cppeditor/cppqtstyleindenter.cpp2
-rw-r--r--src/plugins/cppeditor/cppquickfix_test.cpp42
-rw-r--r--src/plugins/cppeditor/cppquickfixassistant.cpp26
-rw-r--r--src/plugins/cppeditor/cppquickfixassistant.h4
-rw-r--r--src/plugins/cppeditor/cppquickfixes.cpp301
-rw-r--r--src/plugins/cppeditor/cppquickfixprojectsettingswidget.cpp43
-rw-r--r--src/plugins/cppeditor/cppquickfixprojectsettingswidget.h7
-rw-r--r--src/plugins/cppeditor/cppquickfixprojectsettingswidget.ui25
-rw-r--r--src/plugins/cppeditor/cpprefactoringchanges.cpp103
-rw-r--r--src/plugins/cppeditor/cpprefactoringchanges.h23
-rw-r--r--src/plugins/cppeditor/cpprefactoringengine.cpp119
-rw-r--r--src/plugins/cppeditor/cpprefactoringengine.h49
-rw-r--r--src/plugins/cppeditor/cppsourceprocessor.cpp10
-rw-r--r--src/plugins/cppeditor/cppsourceprocessor_test.cpp3
-rw-r--r--src/plugins/cppeditor/cpptoolsreuse.cpp34
-rw-r--r--src/plugins/cppeditor/cpptoolsreuse.h9
-rw-r--r--src/plugins/cppeditor/cpptoolssettings.cpp44
-rw-r--r--src/plugins/cppeditor/cpptoolssettings.h8
-rw-r--r--src/plugins/cppeditor/cpptoolstestcase.cpp2
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.cpp6
-rw-r--r--src/plugins/cppeditor/cppuseselections_test.cpp2
-rw-r--r--src/plugins/cppeditor/cppuseselectionsupdater.cpp2
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp2
-rw-r--r--src/plugins/cppeditor/cursorineditor.h6
-rw-r--r--src/plugins/cppeditor/doxygengenerator.cpp4
-rw-r--r--src/plugins/cppeditor/fileandtokenactions_test.cpp18
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp15
-rw-r--r--src/plugins/cppeditor/followsymbolinterface.h59
-rw-r--r--src/plugins/cppeditor/functionutils.cpp10
-rw-r--r--src/plugins/cppeditor/generatedcodemodelsupport.cpp2
-rw-r--r--src/plugins/cppeditor/headerpathfilter.cpp18
-rw-r--r--src/plugins/cppeditor/headerpathfilter.h7
-rw-r--r--src/plugins/cppeditor/includeutils.cpp28
-rw-r--r--src/plugins/cppeditor/indexitem.h2
-rw-r--r--src/plugins/cppeditor/insertionpointlocator.cpp4
-rw-r--r--src/plugins/cppeditor/projectinfo_test.cpp16
-rw-r--r--src/plugins/cppeditor/refactoringengineinterface.h79
-rw-r--r--src/plugins/cppeditor/resourcepreviewhoverhandler.cpp3
-rw-r--r--src/plugins/cppeditor/searchsymbols.cpp4
-rw-r--r--src/plugins/cppeditor/semantichighlighter.cpp2
-rw-r--r--src/plugins/cppeditor/symbolfinder.cpp25
-rw-r--r--src/plugins/cppeditor/typehierarchybuilder.cpp2
-rw-r--r--src/plugins/cppeditor/typehierarchybuilder_test.cpp2
-rw-r--r--src/plugins/cppeditor/usages.h69
-rw-r--r--src/plugins/cvs/CMakeLists.txt1
-rw-r--r--src/plugins/cvs/cvsplugin.cpp36
-rw-r--r--src/plugins/cvs/cvssettings.cpp1
-rw-r--r--src/plugins/debugger/CMakeLists.txt2
-rw-r--r--src/plugins/debugger/analyzer/detailederrorview.cpp8
-rw-r--r--src/plugins/debugger/analyzer/startremotedialog.cpp20
-rw-r--r--src/plugins/debugger/analyzer/startremotedialog.h8
-rw-r--r--src/plugins/debugger/breakhandler.cpp1
-rw-r--r--src/plugins/debugger/breakpoint.h2
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp128
-rw-r--r--src/plugins/debugger/cdb/cdbengine.h12
-rw-r--r--src/plugins/debugger/console/consoleview.cpp6
-rw-r--r--src/plugins/debugger/debugger.qbs2
-rw-r--r--src/plugins/debugger/debuggeractions.cpp1
-rw-r--r--src/plugins/debugger/debuggerconstants.h8
-rw-r--r--src/plugins/debugger/debuggerdialogs.cpp11
-rw-r--r--src/plugins/debugger/debuggerengine.cpp47
-rw-r--r--src/plugins/debugger/debuggerengine.h24
-rw-r--r--src/plugins/debugger/debuggeritem.cpp6
-rw-r--r--src/plugins/debugger/debuggeritemmanager.cpp23
-rw-r--r--src/plugins/debugger/debuggerkitinformation.cpp3
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp37
-rw-r--r--src/plugins/debugger/debuggerrunconfigurationaspect.cpp5
-rw-r--r--src/plugins/debugger/debuggerrunconfigurationaspect.h8
-rw-r--r--src/plugins/debugger/debuggerruncontrol.cpp93
-rw-r--r--src/plugins/debugger/debuggerruncontrol.h3
-rw-r--r--src/plugins/debugger/debuggersourcepathmappingwidget.cpp2
-rw-r--r--src/plugins/debugger/debuggertooltipmanager.cpp13
-rw-r--r--src/plugins/debugger/disassembleragent.cpp5
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp131
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h4
-rw-r--r--src/plugins/debugger/lldb/lldbengine.cpp104
-rw-r--r--src/plugins/debugger/lldb/lldbengine.h7
-rw-r--r--src/plugins/debugger/loadcoredialog.cpp92
-rw-r--r--src/plugins/debugger/loadcoredialog.h5
-rw-r--r--src/plugins/debugger/moduleshandler.cpp1
-rw-r--r--src/plugins/debugger/pdb/pdbengine.cpp79
-rw-r--r--src/plugins/debugger/pdb/pdbengine.h6
-rw-r--r--src/plugins/debugger/peripheralregisterhandler.cpp8
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp106
-rw-r--r--src/plugins/debugger/qml/qmlengine.h5
-rw-r--r--src/plugins/debugger/qml/qmlengineutils.cpp3
-rw-r--r--src/plugins/debugger/qml/qmlinspectoragent.cpp6
-rw-r--r--src/plugins/debugger/sourcefileshandler.cpp13
-rw-r--r--src/plugins/debugger/sourceutils.cpp30
-rw-r--r--src/plugins/debugger/stackhandler.cpp15
-rw-r--r--src/plugins/debugger/terminal.cpp32
-rw-r--r--src/plugins/debugger/terminal.h4
-rw-r--r--src/plugins/debugger/threadshandler.cpp2
-rw-r--r--src/plugins/debugger/unstartedappwatcherdialog.cpp40
-rw-r--r--src/plugins/debugger/unstartedappwatcherdialog.h8
-rw-r--r--src/plugins/debugger/uvsc/uvscengine.cpp11
-rw-r--r--src/plugins/debugger/watchhandler.cpp42
-rw-r--r--src/plugins/designer/CMakeLists.txt10
-rw-r--r--src/plugins/designer/cpp/formclasswizardpage.cpp76
-rw-r--r--src/plugins/designer/cpp/formclasswizardpage.h14
-rw-r--r--src/plugins/designer/cpp/formclasswizardpage.ui33
-rw-r--r--src/plugins/designer/designer.qbs2
-rw-r--r--src/plugins/designer/designer_export.h2
-rw-r--r--src/plugins/designer/formeditorplugin.cpp39
-rw-r--r--src/plugins/designer/gotoslot_test.cpp2
-rw-r--r--src/plugins/designer/qtcreatorintegration.cpp2
-rw-r--r--src/plugins/designer/resourcehandler.cpp4
-rw-r--r--src/plugins/diffeditor/CMakeLists.txt1
-rw-r--r--src/plugins/diffeditor/diffeditor_global.h2
-rw-r--r--src/plugins/diffeditor/diffeditordocument.cpp4
-rw-r--r--src/plugins/diffeditor/diffeditorfactory.cpp2
-rw-r--r--src/plugins/diffeditor/diffeditorplugin.cpp49
-rw-r--r--src/plugins/diffeditor/diffeditorwidgetcontroller.cpp8
-rw-r--r--src/plugins/docker/CMakeLists.txt5
-rw-r--r--src/plugins/docker/docker.qbs14
-rw-r--r--src/plugins/docker/dockerapi.cpp132
-rw-r--r--src/plugins/docker/dockerapi.h68
-rw-r--r--src/plugins/docker/dockerbuildstep.cpp178
-rw-r--r--src/plugins/docker/dockerbuildstep.h40
-rw-r--r--src/plugins/docker/dockerconstants.h5
-rw-r--r--src/plugins/docker/dockerdevice.cpp1299
-rw-r--r--src/plugins/docker/dockerdevice.h36
-rw-r--r--src/plugins/docker/dockerdevicewidget.cpp231
-rw-r--r--src/plugins/docker/dockerdevicewidget.h63
-rw-r--r--src/plugins/docker/dockerplugin.cpp24
-rw-r--r--src/plugins/docker/dockerplugin.h6
-rw-r--r--src/plugins/docker/dockersettings.cpp7
-rw-r--r--src/plugins/docker/kitdetector.cpp372
-rw-r--r--src/plugins/docker/kitdetector.h56
-rw-r--r--src/plugins/fakevim/fakevimactions.cpp1
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp74
-rw-r--r--src/plugins/fakevim/fakevimplugin.cpp12
-rw-r--r--src/plugins/genericprojectmanager/CMakeLists.txt1
-rw-r--r--src/plugins/genericprojectmanager/genericprojectwizard.cpp2
-rw-r--r--src/plugins/git/CMakeLists.txt1
-rw-r--r--src/plugins/git/changeselectiondialog.cpp40
-rw-r--r--src/plugins/git/changeselectiondialog.h3
-rw-r--r--src/plugins/git/gerrit/gerritdialog.ui12
-rw-r--r--src/plugins/git/gerrit/gerritmodel.cpp43
-rw-r--r--src/plugins/git/gerrit/gerritplugin.cpp55
-rw-r--r--src/plugins/git/gerrit/gerritserver.cpp32
-rw-r--r--src/plugins/git/gerrit/gerritserver.h2
-rw-r--r--src/plugins/git/git.qbs1
-rw-r--r--src/plugins/git/git_global.h36
-rw-r--r--src/plugins/git/gitclient.cpp470
-rw-r--r--src/plugins/git/gitclient.h26
-rw-r--r--src/plugins/git/giteditor.cpp7
-rw-r--r--src/plugins/git/gitgrep.cpp23
-rw-r--r--src/plugins/git/gitplugin.cpp28
-rw-r--r--src/plugins/git/gitplugin.h3
-rw-r--r--src/plugins/git/gitsettings.cpp8
-rw-r--r--src/plugins/git/mergetool.cpp77
-rw-r--r--src/plugins/git/mergetool.h16
-rw-r--r--src/plugins/gitlab/CMakeLists.txt14
-rw-r--r--src/plugins/gitlab/GitLab.json.in19
-rw-r--r--src/plugins/gitlab/gitlab.qbs31
-rw-r--r--src/plugins/gitlab/gitlabclonedialog.cpp263
-rw-r--r--src/plugins/gitlab/gitlabclonedialog.h74
-rw-r--r--src/plugins/gitlab/gitlabdialog.cpp302
-rw-r--r--src/plugins/gitlab/gitlabdialog.h81
-rw-r--r--src/plugins/gitlab/gitlabdialog.ui268
-rw-r--r--src/plugins/gitlab/gitlaboptionspage.cpp313
-rw-r--r--src/plugins/gitlab/gitlaboptionspage.h112
-rw-r--r--src/plugins/gitlab/gitlabparameters.cpp215
-rw-r--r--src/plugins/gitlab/gitlabparameters.h93
-rw-r--r--src/plugins/gitlab/gitlabplugin.cpp358
-rw-r--r--src/plugins/gitlab/gitlabplugin.h64
-rw-r--r--src/plugins/gitlab/gitlabprojectsettings.cpp329
-rw-r--r--src/plugins/gitlab/gitlabprojectsettings.h109
-rw-r--r--src/plugins/gitlab/queryrunner.cpp148
-rw-r--r--src/plugins/gitlab/queryrunner.h75
-rw-r--r--src/plugins/gitlab/resultparser.cpp288
-rw-r--r--src/plugins/gitlab/resultparser.h119
-rw-r--r--src/plugins/glsleditor/CMakeLists.txt1
-rw-r--r--src/plugins/glsleditor/glslcompletionassist.cpp5
-rw-r--r--src/plugins/glsleditor/glslcompletionassist.h4
-rw-r--r--src/plugins/glsleditor/glsleditor.cpp3
-rw-r--r--src/plugins/help/docsettingspage.cpp1
-rw-r--r--src/plugins/help/helpmanager.cpp3
-rw-r--r--src/plugins/help/helpplugin.cpp1
-rw-r--r--src/plugins/help/litehtmlhelpviewer.cpp24
-rw-r--r--src/plugins/imageviewer/imageview.cpp13
-rw-r--r--src/plugins/imageviewer/imageview.h1
-rw-r--r--src/plugins/imageviewer/imageviewer.cpp9
-rw-r--r--src/plugins/imageviewer/imageviewer.h1
-rw-r--r--src/plugins/imageviewer/imageviewerconstants.h1
-rw-r--r--src/plugins/imageviewer/imageviewerfile.cpp2
-rw-r--r--src/plugins/imageviewer/imageviewerplugin.cpp6
-rw-r--r--src/plugins/imageviewer/imageviewertoolbar.ui7
-rw-r--r--src/plugins/incredibuild/commandbuilderaspect.cpp2
-rw-r--r--src/plugins/ios/iosbuildstep.cpp6
-rw-r--r--src/plugins/ios/iosconfigurations.cpp53
-rw-r--r--src/plugins/ios/iosdevice.cpp35
-rw-r--r--src/plugins/ios/iosdsymbuildstep.h2
-rw-r--r--src/plugins/ios/iosprobe.cpp4
-rw-r--r--src/plugins/ios/iosrunconfiguration.cpp51
-rw-r--r--src/plugins/ios/iosrunconfiguration.h46
-rw-r--r--src/plugins/ios/iosrunner.cpp23
-rw-r--r--src/plugins/ios/iosrunner.h4
-rw-r--r--src/plugins/ios/iossimulator.h2
-rw-r--r--src/plugins/ios/iostoolhandler.cpp7
-rw-r--r--src/plugins/ios/simulatorcontrol.cpp4
-rw-r--r--src/plugins/languageclient/CMakeLists.txt2
-rw-r--r--src/plugins/languageclient/client.cpp1334
-rw-r--r--src/plugins/languageclient/client.h184
-rw-r--r--src/plugins/languageclient/diagnosticmanager.cpp141
-rw-r--r--src/plugins/languageclient/diagnosticmanager.h63
-rw-r--r--src/plugins/languageclient/documentsymbolcache.cpp24
-rw-r--r--src/plugins/languageclient/documentsymbolcache.h1
-rw-r--r--src/plugins/languageclient/languageclient.qbs2
-rw-r--r--src/plugins/languageclient/languageclient_global.h2
-rw-r--r--src/plugins/languageclient/languageclientcompletionassist.cpp41
-rw-r--r--src/plugins/languageclient/languageclientcompletionassist.h1
-rw-r--r--src/plugins/languageclient/languageclientformatter.cpp7
-rw-r--r--src/plugins/languageclient/languageclientformatter.h1
-rw-r--r--src/plugins/languageclient/languageclientfunctionhint.cpp6
-rw-r--r--src/plugins/languageclient/languageclienthoverhandler.cpp73
-rw-r--r--src/plugins/languageclient/languageclienthoverhandler.h12
-rw-r--r--src/plugins/languageclient/languageclientinterface.cpp83
-rw-r--r--src/plugins/languageclient/languageclientinterface.h23
-rw-r--r--src/plugins/languageclient/languageclientmanager.cpp60
-rw-r--r--src/plugins/languageclient/languageclientmanager.h21
-rw-r--r--src/plugins/languageclient/languageclientoutline.cpp143
-rw-r--r--src/plugins/languageclient/languageclientoutline.h9
-rw-r--r--src/plugins/languageclient/languageclientplugin.cpp3
-rw-r--r--src/plugins/languageclient/languageclientquickfix.cpp87
-rw-r--r--src/plugins/languageclient/languageclientquickfix.h44
-rw-r--r--src/plugins/languageclient/languageclientsettings.cpp91
-rw-r--r--src/plugins/languageclient/languageclientsettings.h23
-rw-r--r--src/plugins/languageclient/languageclientsymbolsupport.cpp28
-rw-r--r--src/plugins/languageclient/languageclientsymbolsupport.h2
-rw-r--r--src/plugins/languageclient/languageclientutils.cpp112
-rw-r--r--src/plugins/languageclient/languageclientutils.h5
-rw-r--r--src/plugins/languageclient/locatorfilter.cpp11
-rw-r--r--src/plugins/languageclient/locatorfilter.h5
-rw-r--r--src/plugins/languageclient/lspinspector.cpp77
-rw-r--r--src/plugins/languageclient/lspinspector.h8
-rw-r--r--src/plugins/languageclient/semantichighlightsupport.cpp76
-rw-r--r--src/plugins/languageclient/semantichighlightsupport.h5
-rw-r--r--src/plugins/macros/actionmacrohandler.cpp4
-rw-r--r--src/plugins/macros/macro.cpp2
-rw-r--r--src/plugins/macros/macromanager.cpp17
-rw-r--r--src/plugins/macros/macrooptionswidget.cpp2
-rw-r--r--src/plugins/mcusupport/CMakeLists.txt5
-rw-r--r--src/plugins/mcusupport/mcuabstractpackage.h6
-rw-r--r--src/plugins/mcusupport/mcuabstracttargetfactory.h58
-rw-r--r--src/plugins/mcusupport/mcuhelpers.cpp51
-rw-r--r--src/plugins/mcusupport/mcuhelpers.h41
-rw-r--r--src/plugins/mcusupport/mcukitinformation.cpp78
-rw-r--r--src/plugins/mcusupport/mcukitinformation.h13
-rw-r--r--src/plugins/mcusupport/mcukitmanager.cpp683
-rw-r--r--src/plugins/mcusupport/mcukitmanager.h86
-rw-r--r--src/plugins/mcusupport/mculegacyconstants.h33
-rw-r--r--src/plugins/mcusupport/mcupackage.cpp91
-rw-r--r--src/plugins/mcusupport/mcupackage.h26
-rw-r--r--src/plugins/mcusupport/mcusupport.qbs13
-rw-r--r--src/plugins/mcusupport/mcusupport_global.h21
-rw-r--r--src/plugins/mcusupport/mcusupportcmakemapper.cpp79
-rw-r--r--src/plugins/mcusupport/mcusupportcmakemapper.h35
-rw-r--r--src/plugins/mcusupport/mcusupportconstants.h34
-rw-r--r--src/plugins/mcusupport/mcusupportdevice.cpp1
-rw-r--r--src/plugins/mcusupport/mcusupportoptions.cpp190
-rw-r--r--src/plugins/mcusupport/mcusupportoptions.h43
-rw-r--r--src/plugins/mcusupport/mcusupportoptionspage.cpp88
-rw-r--r--src/plugins/mcusupport/mcusupportoptionspage.h6
-rw-r--r--src/plugins/mcusupport/mcusupportplugin.cpp53
-rw-r--r--src/plugins/mcusupport/mcusupportplugin.h5
-rw-r--r--src/plugins/mcusupport/mcusupportrunconfiguration.cpp16
-rw-r--r--src/plugins/mcusupport/mcusupportsdk.cpp863
-rw-r--r--src/plugins/mcusupport/mcusupportsdk.h48
-rw-r--r--src/plugins/mcusupport/mcusupportversiondetection.cpp26
-rw-r--r--src/plugins/mcusupport/mcusupportversiondetection.h21
-rw-r--r--src/plugins/mcusupport/mcutarget.cpp27
-rw-r--r--src/plugins/mcusupport/mcutarget.h30
-rw-r--r--src/plugins/mcusupport/mcutargetdescription.h33
-rw-r--r--src/plugins/mcusupport/mcutargetfactory.cpp156
-rw-r--r--src/plugins/mcusupport/mcutargetfactory.h52
-rw-r--r--src/plugins/mcusupport/mcutargetfactorylegacy.cpp140
-rw-r--r--src/plugins/mcusupport/mcutargetfactorylegacy.h66
-rw-r--r--src/plugins/mcusupport/settingshandler.cpp90
-rw-r--r--src/plugins/mcusupport/settingshandler.h53
-rw-r--r--src/plugins/mcusupport/test/CMakeLists.txt2
-rw-r--r--src/plugins/mcusupport/test/armgcc_nxp_1050_json.h113
-rw-r--r--src/plugins/mcusupport/test/armgcc_nxp_mimxrt1170_evk_freertos_json.h114
-rw-r--r--src/plugins/mcusupport/test/armgcc_stm32f769i_freertos_json.h113
-rw-r--r--src/plugins/mcusupport/test/armgcc_stm32h750b_metal_json.h99
-rw-r--r--src/plugins/mcusupport/test/gcc_desktop_json.h55
-rw-r--r--src/plugins/mcusupport/test/ghs_rh850_d1m1a_baremetal_json.h87
-rw-r--r--src/plugins/mcusupport/test/iar_nxp_1064_json.h105
-rw-r--r--src/plugins/mcusupport/test/iar_stm32f469i_metal_json.h99
-rw-r--r--src/plugins/mcusupport/test/nxp_1064_json.h93
-rw-r--r--src/plugins/mcusupport/test/packagemock.h4
-rw-r--r--src/plugins/mcusupport/test/settingshandlermock.h48
-rw-r--r--src/plugins/mcusupport/test/unittest.cpp740
-rw-r--r--src/plugins/mcusupport/test/unittest.h87
-rw-r--r--src/plugins/mercurial/commiteditor.cpp6
-rw-r--r--src/plugins/mercurial/mercurialclient.cpp31
-rw-r--r--src/plugins/mercurial/mercurialplugin.cpp20
-rw-r--r--src/plugins/mesonprojectmanager/CMakeLists.txt5
-rw-r--r--src/plugins/mesonprojectmanager/exewrappers/toolwrapper.cpp2
-rw-r--r--src/plugins/mesonprojectmanager/mesonactionsmanager/mesonactionsmanager.cpp2
-rw-r--r--src/plugins/mesonprojectmanager/mesonprojectmanager.qbs2
-rw-r--r--src/plugins/mesonprojectmanager/mesonprojectplugin.cpp6
-rw-r--r--src/plugins/mesonprojectmanager/project/mesonbuildconfiguration.cpp5
-rw-r--r--src/plugins/mesonprojectmanager/project/mesonprocess.cpp82
-rw-r--r--src/plugins/mesonprojectmanager/project/mesonprocess.h10
-rw-r--r--src/plugins/mesonprojectmanager/project/mesonproject.cpp11
-rw-r--r--src/plugins/mesonprojectmanager/project/mesonproject.h5
-rw-r--r--src/plugins/mesonprojectmanager/project/mesonrunconfiguration.cpp53
-rw-r--r--src/plugins/mesonprojectmanager/project/mesonrunconfiguration.h2
-rw-r--r--src/plugins/mesonprojectmanager/project/ninjabuildstep.cpp5
-rw-r--r--src/plugins/mesonprojectmanager/project/ninjabuildstep.h3
-rw-r--r--src/plugins/mesonprojectmanager/resources_meson.qrc (renamed from src/plugins/mesonprojectmanager/resources.qrc)0
-rw-r--r--src/plugins/mesonprojectmanager/settings/general/settings.cpp5
-rw-r--r--src/plugins/modeleditor/CMakeLists.txt1
-rw-r--r--src/plugins/modeleditor/classviewcontroller.cpp4
-rw-r--r--src/plugins/modeleditor/componentviewcontroller.cpp16
-rw-r--r--src/plugins/modeleditor/elementtasks.cpp11
-rw-r--r--src/plugins/modeleditor/modeleditor.cpp24
-rw-r--r--src/plugins/modeleditor/modeleditor_global.h2
-rw-r--r--src/plugins/modeleditor/modelindexer.cpp17
-rw-r--r--src/plugins/modeleditor/modelsmanager.cpp8
-rw-r--r--src/plugins/modeleditor/modelutilities.cpp2
-rw-r--r--src/plugins/modeleditor/pxnodecontroller.cpp5
-rw-r--r--src/plugins/nim/editor/nimtexteditorwidget.cpp4
-rw-r--r--src/plugins/nim/editor/nimtexteditorwidget.h4
-rw-r--r--src/plugins/nim/nimplugin.cpp6
-rw-r--r--src/plugins/nim/project/nimblebuildstep.cpp5
-rw-r--r--src/plugins/nim/project/nimblebuildsystem.cpp4
-rw-r--r--src/plugins/nim/project/nimblerunconfiguration.cpp20
-rw-r--r--src/plugins/nim/project/nimbuildconfiguration.cpp3
-rw-r--r--src/plugins/nim/project/nimrunconfiguration.cpp8
-rw-r--r--src/plugins/nim/settings/nimcodestylepreferencesfactory.cpp7
-rw-r--r--src/plugins/nim/settings/nimcodestylepreferencesfactory.h6
-rw-r--r--src/plugins/nim/settings/nimcodestylepreferenceswidget.cpp2
-rw-r--r--src/plugins/nim/settings/nimcodestylepreferenceswidget.h3
-rw-r--r--src/plugins/nim/suggest/nimsuggest.cpp15
-rw-r--r--src/plugins/nim/suggest/nimsuggest.h3
-rw-r--r--src/plugins/nim/suggest/server.cpp34
-rw-r--r--src/plugins/nim/suggest/server.h10
-rw-r--r--src/plugins/perforce/perforcechecker.cpp31
-rw-r--r--src/plugins/perforce/perforcechecker.h3
-rw-r--r--src/plugins/perforce/perforceplugin.cpp27
-rw-r--r--src/plugins/perforce/perforcesettings.cpp2
-rw-r--r--src/plugins/perforce/perforcesubmiteditor.cpp2
-rw-r--r--src/plugins/perfprofiler/perfconfigwidget.cpp44
-rw-r--r--src/plugins/perfprofiler/perfconfigwidget.h16
-rw-r--r--src/plugins/perfprofiler/perfprofiler_global.h2
-rw-r--r--src/plugins/perfprofiler/perfprofilerplugin.cpp4
-rw-r--r--src/plugins/perfprofiler/perfprofilerruncontrol.cpp59
-rw-r--r--src/plugins/perfprofiler/perfprofilertool.cpp7
-rw-r--r--src/plugins/perfprofiler/perftracepointdialog.cpp67
-rw-r--r--src/plugins/perfprofiler/perftracepointdialog.h18
-rw-r--r--src/plugins/perfprofiler/tracepoints.sh16
-rw-r--r--src/plugins/plugins.qbs5
-rw-r--r--src/plugins/projectexplorer/CMakeLists.txt21
-rw-r--r--src/plugins/projectexplorer/abi.cpp11
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.cpp23
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.cpp2
-rw-r--r--src/plugins/projectexplorer/applicationlauncher.cpp481
-rw-r--r--src/plugins/projectexplorer/applicationlauncher.h80
-rw-r--r--src/plugins/projectexplorer/appoutputpane.cpp71
-rw-r--r--src/plugins/projectexplorer/buildaspects.cpp1
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.cpp32
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.h5
-rw-r--r--src/plugins/projectexplorer/buildmanager.cpp23
-rw-r--r--src/plugins/projectexplorer/buildstep.cpp4
-rw-r--r--src/plugins/projectexplorer/buildsteplist.cpp11
-rw-r--r--src/plugins/projectexplorer/buildsteplist.h4
-rw-r--r--src/plugins/projectexplorer/buildsystem.cpp20
-rw-r--r--src/plugins/projectexplorer/buildsystem.h5
-rw-r--r--src/plugins/projectexplorer/buildtargetinfo.h3
-rw-r--r--src/plugins/projectexplorer/codestylesettingspropertiespage.cpp4
-rw-r--r--src/plugins/projectexplorer/codestylesettingspropertiespage.h3
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.cpp4
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.cpp11
-rw-r--r--src/plugins/projectexplorer/customparser.cpp9
-rw-r--r--src/plugins/projectexplorer/customparser.h8
-rw-r--r--src/plugins/projectexplorer/customtoolchain.cpp44
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizard.cpp6
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizardpage.cpp6
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizardparameters.cpp14
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp15
-rw-r--r--src/plugins/projectexplorer/dependenciespanel.cpp4
-rw-r--r--src/plugins/projectexplorer/dependenciespanel.h5
-rw-r--r--src/plugins/projectexplorer/deployconfiguration.cpp14
-rw-r--r--src/plugins/projectexplorer/deploymentdata.h4
-rw-r--r--src/plugins/projectexplorer/deploymentdataview.cpp3
-rw-r--r--src/plugins/projectexplorer/desktoprunconfiguration.cpp8
-rw-r--r--src/plugins/projectexplorer/desktoprunconfiguration.h3
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdevice.cpp70
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdevice.h5
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp62
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.h47
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp33
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicefilesystemmodel.cpp321
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicefilesystemmodel.h72
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicemanager.cpp20
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicemanagermodel.h10
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocess.cpp49
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocess.h62
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp25
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.h9
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp34
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocesslist.h27
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicesettingswidget.h5
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp82
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h10
-rw-r--r--src/plugins/projectexplorer/devicesupport/filetransfer.cpp227
-rw-r--r--src/plugins/projectexplorer/devicesupport/filetransfer.h66
-rw-r--r--src/plugins/projectexplorer/devicesupport/filetransferinterface.h93
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.cpp86
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.h36
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevicefactory.cpp1
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevicefactory.h19
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevicefwd.h42
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevicewidget.h8
-rw-r--r--src/plugins/projectexplorer/devicesupport/localprocesslist.cpp187
-rw-r--r--src/plugins/projectexplorer/devicesupport/localprocesslist.h6
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp359
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h75
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp79
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h13
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshparameters.cpp219
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshparameters.h92
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshsettings.cpp206
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshsettings.h68
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp3
-rw-r--r--src/plugins/projectexplorer/editorconfiguration.cpp9
-rw-r--r--src/plugins/projectexplorer/editorconfiguration.h6
-rw-r--r--src/plugins/projectexplorer/editorsettingspropertiespage.cpp15
-rw-r--r--src/plugins/projectexplorer/editorsettingspropertiespage.h5
-rw-r--r--src/plugins/projectexplorer/editorsettingspropertiespage.ui60
-rw-r--r--src/plugins/projectexplorer/environmentaspect.cpp2
-rw-r--r--src/plugins/projectexplorer/environmentaspect.h5
-rw-r--r--src/plugins/projectexplorer/environmentaspectwidget.cpp26
-rw-r--r--src/plugins/projectexplorer/environmentaspectwidget.h12
-rw-r--r--src/plugins/projectexplorer/environmentwidget.cpp2
-rw-r--r--src/plugins/projectexplorer/extracompiler.cpp5
-rw-r--r--src/plugins/projectexplorer/gccparser.cpp37
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.cpp115
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.h12
-rw-r--r--src/plugins/projectexplorer/gnumakeparser.cpp6
-rw-r--r--src/plugins/projectexplorer/journaldwatcher.cpp2
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp23
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonfieldpage.h7
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonfieldpage_p.h1
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp13
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp9
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp20
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp8
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp14
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp4
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp24
-rw-r--r--src/plugins/projectexplorer/kit.cpp29
-rw-r--r--src/plugins/projectexplorer/kitchooser.cpp4
-rw-r--r--src/plugins/projectexplorer/kitinformation.cpp54
-rw-r--r--src/plugins/projectexplorer/kitinformation.h13
-rw-r--r--src/plugins/projectexplorer/kitmanager.cpp16
-rw-r--r--src/plugins/projectexplorer/kitmanagerconfigwidget.cpp14
-rw-r--r--src/plugins/projectexplorer/kitmodel.cpp8
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp51
-rw-r--r--src/plugins/projectexplorer/msvcparser.cpp32
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp113
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.h3
-rw-r--r--src/plugins/projectexplorer/namedwidget.cpp2
-rw-r--r--src/plugins/projectexplorer/namedwidget.h3
-rw-r--r--src/plugins/projectexplorer/outputparser_test.cpp2
-rw-r--r--src/plugins/projectexplorer/panelswidget.cpp71
-rw-r--r--src/plugins/projectexplorer/panelswidget.h6
-rw-r--r--src/plugins/projectexplorer/project.cpp19
-rw-r--r--src/plugins/projectexplorer/project.h4
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.cpp19
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.h6
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp216
-rw-r--r--src/plugins/projectexplorer/projectexplorer.h8
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qbs16
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h1
-rw-r--r--src/plugins/projectexplorer/projectfilewizardextension.cpp31
-rw-r--r--src/plugins/projectexplorer/projectimporter.cpp22
-rw-r--r--src/plugins/projectexplorer/projectmacro.cpp10
-rw-r--r--src/plugins/projectexplorer/projectmacro.h1
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp32
-rw-r--r--src/plugins/projectexplorer/projectnodes.h14
-rw-r--r--src/plugins/projectexplorer/projectnodeshelper.h5
-rw-r--r--src/plugins/projectexplorer/projectpanelfactory.cpp4
-rw-r--r--src/plugins/projectexplorer/projectpanelfactory.h7
-rw-r--r--src/plugins/projectexplorer/projectsettingswidget.cpp90
-rw-r--r--src/plugins/projectexplorer/projectsettingswidget.h69
-rw-r--r--src/plugins/projectexplorer/projecttree.cpp44
-rw-r--r--src/plugins/projectexplorer/projecttree.h2
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.cpp24
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.h5
-rw-r--r--src/plugins/projectexplorer/projectwelcomepage.cpp8
-rw-r--r--src/plugins/projectexplorer/projectwelcomepage.h5
-rw-r--r--src/plugins/projectexplorer/projectwindow.cpp84
-rw-r--r--src/plugins/projectexplorer/projectwizardpage.cpp14
-rw-r--r--src/plugins/projectexplorer/rawprojectpart.cpp5
-rw-r--r--src/plugins/projectexplorer/rawprojectpart.h6
-rw-r--r--src/plugins/projectexplorer/runconfiguration.cpp39
-rw-r--r--src/plugins/projectexplorer/runconfiguration.h12
-rw-r--r--src/plugins/projectexplorer/runconfigurationaspects.cpp196
-rw-r--r--src/plugins/projectexplorer/runconfigurationaspects.h96
-rw-r--r--src/plugins/projectexplorer/runcontrol.cpp574
-rw-r--r--src/plugins/projectexplorer/runcontrol.h81
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.cpp6
-rw-r--r--src/plugins/projectexplorer/sanitizerparser.cpp258
-rw-r--r--src/plugins/projectexplorer/sanitizerparser.h61
-rw-r--r--src/plugins/projectexplorer/session.cpp55
-rw-r--r--src/plugins/projectexplorer/simpleprojectwizard.cpp6
-rw-r--r--src/plugins/projectexplorer/target.cpp29
-rw-r--r--src/plugins/projectexplorer/target.h7
-rw-r--r--src/plugins/projectexplorer/targetsettingspanel.cpp6
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.cpp10
-rw-r--r--src/plugins/projectexplorer/targetsetupwidget.cpp2
-rw-r--r--src/plugins/projectexplorer/taskhub.cpp9
-rw-r--r--src/plugins/projectexplorer/taskmodel.cpp2
-rw-r--r--src/plugins/projectexplorer/taskwindow.cpp3
-rw-r--r--src/plugins/projectexplorer/toolchain.cpp6
-rw-r--r--src/plugins/projectexplorer/toolchain.h11
-rw-r--r--src/plugins/projectexplorer/toolchainmanager.cpp2
-rw-r--r--src/plugins/projectexplorer/toolchainoptionspage.cpp57
-rw-r--r--src/plugins/projectexplorer/toolchainsettingsaccessor.cpp18
-rw-r--r--src/plugins/projectexplorer/toolchainsettingsaccessor.h2
-rw-r--r--src/plugins/projectexplorer/treescanner.h4
-rw-r--r--src/plugins/projectexplorer/userfileaccessor.cpp6
-rw-r--r--src/plugins/projectexplorer/waitforstopdialog.cpp6
-rw-r--r--src/plugins/projectexplorer/waitforstopdialog.h2
-rw-r--r--src/plugins/projectexplorer/windebuginterface.cpp14
-rw-r--r--src/plugins/projectexplorer/windebuginterface.h3
-rw-r--r--src/plugins/projectexplorer/xcodebuildparser.h1
-rw-r--r--src/plugins/python/CMakeLists.txt4
-rw-r--r--src/plugins/python/pipsupport.cpp191
-rw-r--r--src/plugins/python/pipsupport.h100
-rw-r--r--src/plugins/python/pyside.cpp199
-rw-r--r--src/plugins/python/pyside.h74
-rw-r--r--src/plugins/python/pysidebuildconfiguration.cpp122
-rw-r--r--src/plugins/python/pysidebuildconfiguration.h70
-rw-r--r--src/plugins/python/pysideuicextracompiler.cpp72
-rw-r--r--src/plugins/python/pysideuicextracompiler.h53
-rw-r--r--src/plugins/python/python.qbs8
-rw-r--r--src/plugins/python/pythonconstants.h4
-rw-r--r--src/plugins/python/pythoneditor.cpp35
-rw-r--r--src/plugins/python/pythonlanguageclient.cpp488
-rw-r--r--src/plugins/python/pythonlanguageclient.h50
-rw-r--r--src/plugins/python/pythonplugin.cpp13
-rw-r--r--src/plugins/python/pythonproject.cpp9
-rw-r--r--src/plugins/python/pythonrunconfiguration.cpp262
-rw-r--r--src/plugins/python/pythonrunconfiguration.h20
-rw-r--r--src/plugins/python/pythonsettings.cpp537
-rw-r--r--src/plugins/python/pythonsettings.h32
-rw-r--r--src/plugins/python/pythonutils.cpp110
-rw-r--r--src/plugins/python/pythonutils.h6
-rw-r--r--src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp3
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp9
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstep.cpp1
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectimporter.cpp5
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager_global.h2
-rw-r--r--src/plugins/qbsprojectmanager/qbssession.cpp64
-rw-r--r--src/plugins/qbsprojectmanager/qbssession.h4
-rw-r--r--src/plugins/qmakeprojectmanager/externaleditors.cpp14
-rw-r--r--src/plugins/qmakeprojectmanager/profileeditor.cpp4
-rw-r--r--src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp12
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.cpp1
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.h3
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp3
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp6
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.cpp2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanager_global.h2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h5
-rw-r--r--src/plugins/qmakeprojectmanager/qmakesettings.cpp3
-rw-r--r--src/plugins/qmakeprojectmanager/qmakestep.cpp7
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt25
-rw-r--r--src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp2
-rw-r--r--src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs3
-rw-r--r--src/plugins/qmldesigner/checkablefiletreeitem.cpp67
-rw-r--r--src/plugins/qmldesigner/checkablefiletreeitem.h53
-rw-r--r--src/plugins/qmldesigner/cmakegeneratordialog.cpp189
-rw-r--r--src/plugins/qmldesigner/cmakegeneratordialog.h70
-rw-r--r--src/plugins/qmldesigner/cmakegeneratordialogtreemodel.cpp201
-rw-r--r--src/plugins/qmldesigner/cmakegeneratordialogtreemodel.h73
-rw-r--r--src/plugins/qmldesigner/cmakeprojectconverter.cpp440
-rw-r--r--src/plugins/qmldesigner/cmakeprojectconverter.h99
-rw-r--r--src/plugins/qmldesigner/cmakeprojectconverterdialog.cpp227
-rw-r--r--src/plugins/qmldesigner/cmakeprojectconverterdialog.h69
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp7
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/addsignalhandlerdialog.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp3
-rw-r--r--src/plugins/qmldesigner/components/componentcore/findimplementation.cpp4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp33
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu.cpp19
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp26
-rw-r--r--src/plugins/qmldesigner/components/componentcore/theme.h2
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp6
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp9
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp32
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.h5
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp8
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp65
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp22
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/animationcurve.h14
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp23
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditor.h4
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp36
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h8
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp59
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp65
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h8
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp9
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp57
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h12
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp1
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/keyframe.h1
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/treeitem.cpp6
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/treeitem.h9
-rw-r--r--src/plugins/qmldesigner/components/debugview/debugview.cpp36
-rw-r--r--src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp2
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.cpp35
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.h6
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp18
-rw-r--r--src/plugins/qmldesigner/components/eventlist/eventlist.h4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp18
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/contentnoteditableindicator.cpp24
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp19
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.cpp17
-rw-r--r--src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/layeritem.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp26
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movetool.cpp8
-rw-r--r--src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/rotationmanipulator.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/seekerslider.cpp1
-rw-r--r--src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp12
-rw-r--r--src/plugins/qmldesigner/components/formeditor/snapper.cpp8
-rw-r--r--src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp3
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentview.cpp22
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp10
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp7
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp2
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp142
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h31
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp54
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp21
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h19
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp84
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h33
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp14
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h1
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp277
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorview.h18
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp1
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathitem.cpp37
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp15
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathtool.cpp2
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathtoolview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp3
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp11
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp15
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h1
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp14
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp4
-rw-r--r--src/plugins/qmldesigner/components/resources/resources_qmldesigner_components.qrc (renamed from src/plugins/qmldesigner/components/resources/resources.qrc)0
-rw-r--r--src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp2
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp6
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp52
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.h7
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorview.cpp25
-rw-r--r--src/plugins/qmldesigner/components/texttool/texttool.cpp2
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp142
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h13
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui84
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp2
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp9
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp10
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp1
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp1
-rw-r--r--src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp3
-rw-r--r--src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs3
-rw-r--r--src/plugins/qmldesigner/componentsplugin/entertabdesigneraction.cpp3
-rw-r--r--src/plugins/qmldesigner/componentsplugin/tabviewindexmodel.cpp7
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/addpropertyvisitor.cpp10
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/changepropertyvisitor.cpp9
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractproperty.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractview.h42
-rw-r--r--src/plugins/qmldesigner/designercore/include/forwardview.h44
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelnode.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceview.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h4
-rw-r--r--src/plugins/qmldesigner/designercore/include/rewriterview.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/signalhandlerproperty.h19
-rw-r--r--src/plugins/qmldesigner/designercore/include/viewmanager.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp5
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp123
-rw-r--r--src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp5
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h5
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp6
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp98
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp23
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractproperty.cpp25
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp45
-rw-r--r--src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp7
-rw-r--r--src/plugins/qmldesigner/designercore/model/bindingproperty.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode.cpp34
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode_p.h8
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalproperty.cpp11
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalproperty.h3
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp37
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h21
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp67
-rw-r--r--src/plugins/qmldesigner/designercore/model/model_p.h6
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelmerger.cpp26
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelnode.cpp39
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelnodepositionrecalculator.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp10
-rw-r--r--src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp5
-rw-r--r--src/plugins/qmldesigner/designercore/model/propertyparser.cpp13
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlanchors.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp17
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlstate.cpp31
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp16
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriteaction.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp16
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriterview.cpp39
-rw-r--r--src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp53
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp159
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.h15
-rw-r--r--src/plugins/qmldesigner/designercore/model/viewmanager.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp2
-rw-r--r--src/plugins/qmldesigner/designmodecontext.cpp13
-rw-r--r--src/plugins/qmldesigner/designmodecontext.h9
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp61
-rw-r--r--src/plugins/qmldesigner/documentmanager.cpp10
-rw-r--r--src/plugins/qmldesigner/dynamiclicensecheck.h7
-rw-r--r--src/plugins/qmldesigner/generatecmakelists.cpp626
-rw-r--r--src/plugins/qmldesigner/generatecmakelists.h98
-rw-r--r--src/plugins/qmldesigner/generatecmakelistsconstants.h64
-rw-r--r--src/plugins/qmldesigner/generateresource.cpp13
-rw-r--r--src/plugins/qmldesigner/generateresource.h2
-rw-r--r--src/plugins/qmldesigner/openuiqmlfiledialog.cpp2
-rw-r--r--src/plugins/qmldesigner/qmldesignerconstants.h14
-rw-r--r--src/plugins/qmldesigner/qmldesignercore.cmake27
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.cpp15
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.qbs25
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp16
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp20
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h8
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs3
-rw-r--r--src/plugins/qmldesigner/shortcutmanager.cpp20
-rw-r--r--src/plugins/qmldesigner/shortcutmanager.h5
-rw-r--r--src/plugins/qmldesigner/studioplugin/CMakeLists.txt1
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.cpp26
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.h3
-rw-r--r--src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp9
-rw-r--r--src/plugins/qmljseditor/qmljseditingsettingspage.cpp29
-rw-r--r--src/plugins/qmljseditor/qmljseditingsettingspage.h6
-rw-r--r--src/plugins/qmljseditor/qmljseditingsettingspage.ui26
-rw-r--r--src/plugins/qmljseditor/qmljseditor.cpp36
-rw-r--r--src/plugins/qmljseditor/qmljseditor.h2
-rw-r--r--src/plugins/qmljseditor/qmljseditor_global.h2
-rw-r--r--src/plugins/qmljseditor/qmljseditorplugin.cpp9
-rw-r--r--src/plugins/qmljseditor/qmljsfindreferences.cpp49
-rw-r--r--src/plugins/qmljseditor/qmljshoverhandler.cpp13
-rw-r--r--src/plugins/qmljseditor/qmljsquickfixassist.cpp3
-rw-r--r--src/plugins/qmljseditor/qmljsquickfixassist.h1
-rw-r--r--src/plugins/qmljseditor/qmljsquickfixes.cpp2
-rw-r--r--src/plugins/qmljseditor/qmljssemantichighlighter.cpp6
-rw-r--r--src/plugins/qmljseditor/qmloutlinemodel.cpp4
-rw-r--r--src/plugins/qmljseditor/qmltaskmanager.cpp25
-rw-r--r--src/plugins/qmljseditor/qmltaskmanager.h2
-rw-r--r--src/plugins/qmljseditor/quicktoolbar.cpp12
-rw-r--r--src/plugins/qmljstools/CMakeLists.txt4
-rw-r--r--src/plugins/qmljstools/qmljscodestylepreferences.cpp110
-rw-r--r--src/plugins/qmljstools/qmljscodestylepreferences.h66
-rw-r--r--src/plugins/qmljstools/qmljscodestylepreferencesfactory.cpp14
-rw-r--r--src/plugins/qmljstools/qmljscodestylepreferencesfactory.h6
-rw-r--r--src/plugins/qmljstools/qmljscodestylepreferenceswidget.cpp95
-rw-r--r--src/plugins/qmljstools/qmljscodestylepreferenceswidget.h58
-rw-r--r--src/plugins/qmljstools/qmljscodestylesettings.cpp83
-rw-r--r--src/plugins/qmljstools/qmljscodestylesettings.h58
-rw-r--r--src/plugins/qmljstools/qmljscodestylesettingspage.cpp61
-rw-r--r--src/plugins/qmljstools/qmljscodestylesettingspage.h15
-rw-r--r--src/plugins/qmljstools/qmljscodestylesettingspage.ui33
-rw-r--r--src/plugins/qmljstools/qmljscodestylesettingswidget.cpp71
-rw-r--r--src/plugins/qmljstools/qmljscodestylesettingswidget.h66
-rw-r--r--src/plugins/qmljstools/qmljscodestylesettingswidget.ui76
-rw-r--r--src/plugins/qmljstools/qmljsindenter.cpp2
-rw-r--r--src/plugins/qmljstools/qmljslocatordata.cpp2
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp28
-rw-r--r--src/plugins/qmljstools/qmljsrefactoringchanges.cpp4
-rw-r--r--src/plugins/qmljstools/qmljssemanticinfo.cpp2
-rw-r--r--src/plugins/qmljstools/qmljstools.qbs9
-rw-r--r--src/plugins/qmljstools/qmljstools_global.h2
-rw-r--r--src/plugins/qmljstools/qmljstoolssettings.cpp13
-rw-r--r--src/plugins/qmljstools/qmljstoolssettings.h5
-rw-r--r--src/plugins/qmlpreview/CMakeLists.txt1
-rw-r--r--src/plugins/qmlpreview/qmlpreview_global.h2
-rw-r--r--src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp2
-rw-r--r--src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp4
-rw-r--r--src/plugins/qmlpreview/qmlpreviewplugin.cpp5
-rw-r--r--src/plugins/qmlpreview/qmlpreviewruncontrol.cpp30
-rw-r--r--src/plugins/qmlprofiler/flamegraphmodel.cpp3
-rw-r--r--src/plugins/qmlprofiler/pixmapcachemodel.cpp2
-rw-r--r--src/plugins/qmlprofiler/qmlprofiler_global.h2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp3
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerplugin.cpp2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp15
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp14
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp4
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertextmark.cpp37
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertextmark.h1
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertool.cpp57
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertool.h2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp9
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerviewmanager.h4
-rw-r--r--src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp42
-rw-r--r--src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h3
-rw-r--r--src/plugins/qmlprojectmanager/CMakeLists.txt18
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc (renamed from src/plugins/qmldesigner/boilerplate.qrc)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp67
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h53
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp189
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h70
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp201
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h73
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp440
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h99
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp227
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h69
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp629
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h98
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h64
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl (renamed from src/plugins/qmldesigner/qmlprojectappmainqml.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl (renamed from src/plugins/qmldesigner/qmlprojectenvheader.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl (renamed from src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl (renamed from src/plugins/qmldesigner/qmlprojectmaincpp.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl (renamed from src/plugins/qmldesigner/qmlprojectmaincppheader.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl (renamed from src/plugins/qmldesigner/qmlprojectmainqml.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl (renamed from src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl (renamed from src/plugins/qmldesigner/qmlprojectmodules.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp3
-rw-r--r--src/plugins/qmlprojectmanager/projectfilecontenttools.cpp142
-rw-r--r--src/plugins/qmlprojectmanager/projectfilecontenttools.h53
-rw-r--r--src/plugins/qmlprojectmanager/qdslandingpage.cpp233
-rw-r--r--src/plugins/qmlprojectmanager/qdslandingpage.h114
-rw-r--r--src/plugins/qmlprojectmanager/qdslandingpagetheme.cpp56
-rw-r--r--src/plugins/qmlprojectmanager/qdslandingpagetheme.h46
-rw-r--r--src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp24
-rw-r--r--src/plugins/qmlprojectmanager/qmlmainfileaspect.h8
-rw-r--r--src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp11
-rw-r--r--src/plugins/qmlprojectmanager/qmlmultilanguageaspect.h7
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp35
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.h1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectconstants.h4
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectgen/qmlproject.tpl72
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp265
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.h61
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectgen/templates.qrc5
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.qbs31
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager_global.h2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectplugin.cpp233
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectplugin.h18
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp13
-rw-r--r--src/plugins/qnx/CMakeLists.txt3
-rw-r--r--src/plugins/qnx/qnx.qbs3
-rw-r--r--src/plugins/qnx/qnxanalyzesupport.cpp9
-rw-r--r--src/plugins/qnx/qnxconfiguration.cpp1
-rw-r--r--src/plugins/qnx/qnxdebugsupport.cpp31
-rw-r--r--src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp146
-rw-r--r--src/plugins/qnx/qnxdeployqtlibrariesdialog.h42
-rw-r--r--src/plugins/qnx/qnxdevice.cpp127
-rw-r--r--src/plugins/qnx/qnxdevice.h4
-rw-r--r--src/plugins/qnx/qnxdeviceprocess.cpp83
-rw-r--r--src/plugins/qnx/qnxdeviceprocess.h51
-rw-r--r--src/plugins/qnx/qnxdeviceprocesslist.cpp16
-rw-r--r--src/plugins/qnx/qnxdeviceprocesslist.h6
-rw-r--r--src/plugins/qnx/qnxdeviceprocesssignaloperation.cpp7
-rw-r--r--src/plugins/qnx/qnxdeviceprocesssignaloperation.h2
-rw-r--r--src/plugins/qnx/qnxdevicetester.cpp129
-rw-r--r--src/plugins/qnx/qnxdevicetester.h27
-rw-r--r--src/plugins/qnx/qnxdevicewizard.cpp4
-rw-r--r--src/plugins/qnx/qnxplugin.cpp3
-rw-r--r--src/plugins/qnx/qnxqtversion.h4
-rw-r--r--src/plugins/qnx/qnxrunconfiguration.cpp12
-rw-r--r--src/plugins/qnx/qnxtoolchain.cpp4
-rw-r--r--src/plugins/qnx/qnxutils.cpp8
-rw-r--r--src/plugins/qnx/slog2inforunner.cpp44
-rw-r--r--src/plugins/qnx/slog2inforunner.h11
-rw-r--r--src/plugins/qtsupport/CMakeLists.txt1
-rw-r--r--src/plugins/qtsupport/baseqtversion.cpp49
-rw-r--r--src/plugins/qtsupport/exampleslistmodel.cpp11
-rw-r--r--src/plugins/qtsupport/gettingstartedwelcomepage.cpp15
-rw-r--r--src/plugins/qtsupport/images/icons/playoverlay.pngbin0 -> 2472 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/playoverlay@2x.pngbin0 -> 5841 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/qteventicon.pngbin3403 -> 0 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/qteventicon@2x.pngbin7047 -> 0 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/videotutorialicon.pngbin4131 -> 0 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/videotutorialicon@2x.pngbin8810 -> 0 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtube-xhiVA0P4yk.webpbin0 -> 3670 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtube1tSpq5OLkYI.webpbin0 -> 5150 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtube1w0ak9RNNWY.webpbin0 -> 6074 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtube2RvhhEAZQxM.webpbin0 -> 2934 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtube3o2Wo4YzlII.webpbin0 -> 5884 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtube9BcAYDlpuT8.webpbin0 -> 3540 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtube9xqhq9nDiOg.webpbin0 -> 5790 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeB0X5FOev9Lw.webpbin0 -> 4646 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeBkgjJfxYN20.webpbin0 -> 3434 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeDP0lMoLVneY.webpbin0 -> 2916 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeDRFz0Tll4G8.webpbin0 -> 5790 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeECA8_oLT0ZE.webpbin0 -> 4600 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeG0AbgVHGdXI.webpbin0 -> 6662 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeKo3DuCgFamo.webpbin0 -> 4438 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubePzV2MYRAUYQ.webpbin0 -> 4792 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeR6zWLfHIYJw.webpbin0 -> 4464 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeT_13aX5NTPk.webpbin0 -> 1900 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeTiJiF0MOOFc.webpbin0 -> 4218 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeW3WC-VpKdGQ.webpbin0 -> 4164 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeWIRRoPxIerc.webpbin0 -> 3880 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeX0kEkB0ewyw.webpbin0 -> 6976 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeY-MM-9FigTc.webpbin0 -> 5102 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeYJfFwDBOvqk.webpbin0 -> 2436 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeau3brB7lNms.webpbin0 -> 9842 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubehrKz63Q_Rf0.webpbin0 -> 3466 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubejbx3Oq1Q4gY.webpbin0 -> 5602 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubemAhwHsGdJuI.webpbin0 -> 4762 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubemn-JmXIMCqk.webpbin0 -> 3856 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubenmvurCcsWos.webpbin0 -> 6926 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubepN0pRBUqrrc.webpbin0 -> 6856 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeqclquZ99ZVQ.webpbin0 -> 6190 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubesRihJdZFuCg.webpbin0 -> 4464 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubetnZo9umrPtg.webpbin0 -> 6782 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubeuuhmSZxK1mk.webpbin0 -> 3968 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubev4glCQt2jE0.webpbin0 -> 4494 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubev_ynSET9FHU.webpbin0 -> 4122 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubexNIz78IPBu0.webpbin0 -> 1726 bytes
-rw-r--r--src/plugins/qtsupport/images/icons/youtubezAqSiIGdj8M.webpbin0 -> 7862 bytes
-rw-r--r--src/plugins/qtsupport/images_areaofinterest.xml380
-rw-r--r--src/plugins/qtsupport/qtbuildaspects.cpp34
-rw-r--r--src/plugins/qtsupport/qtbuildaspects.h17
-rw-r--r--src/plugins/qtsupport/qtcreator_tutorials.xml76
-rw-r--r--src/plugins/qtsupport/qtoptionspage.cpp7
-rw-r--r--src/plugins/qtsupport/qtsupport.qbs2
-rw-r--r--src/plugins/qtsupport/qtsupport.qrc45
-rw-r--r--src/plugins/qtsupport/qtsupport_global.h2
-rw-r--r--src/plugins/qtsupport/qtsupportplugin.cpp2
-rw-r--r--src/plugins/qtsupport/screenshotcropper.cpp181
-rw-r--r--src/plugins/qtsupport/screenshotcropper.h48
-rw-r--r--src/plugins/remotelinux/CMakeLists.txt23
-rw-r--r--src/plugins/remotelinux/abstractpackagingstep.cpp148
-rw-r--r--src/plugins/remotelinux/abstractpackagingstep.h71
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp110
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeployservice.h22
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp1
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeploystep.h5
-rw-r--r--src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp176
-rw-r--r--src/plugins/remotelinux/abstractuploadandinstallpackageservice.h65
-rw-r--r--src/plugins/remotelinux/customcommanddeploystep.cpp150
-rw-r--r--src/plugins/remotelinux/customcommanddeploystep.h40
-rw-r--r--src/plugins/remotelinux/deploymenttimeinfo.cpp6
-rw-r--r--src/plugins/remotelinux/deploymenttimeinfo.h5
-rw-r--r--src/plugins/remotelinux/filesystemaccess_test.cpp124
-rw-r--r--src/plugins/remotelinux/filesystemaccess_test.h6
-rw-r--r--src/plugins/remotelinux/genericdirectuploadservice.cpp124
-rw-r--r--src/plugins/remotelinux/genericdirectuploadservice.h17
-rw-r--r--src/plugins/remotelinux/genericdirectuploadstep.h3
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp36
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h6
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp7
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h4
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp20
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.h3
-rw-r--r--src/plugins/remotelinux/killappstep.cpp154
-rw-r--r--src/plugins/remotelinux/killappstep.h45
-rw-r--r--src/plugins/remotelinux/linuxdevice.cpp1431
-rw-r--r--src/plugins/remotelinux/linuxdevice.h12
-rw-r--r--src/plugins/remotelinux/linuxdeviceprocess.cpp115
-rw-r--r--src/plugins/remotelinux/linuxdeviceprocess.h54
-rw-r--r--src/plugins/remotelinux/linuxdevicetester.cpp344
-rw-r--r--src/plugins/remotelinux/linuxdevicetester.h31
-rw-r--r--src/plugins/remotelinux/linuxprocessinterface.h58
-rw-r--r--src/plugins/remotelinux/makeinstallstep.cpp90
-rw-r--r--src/plugins/remotelinux/makeinstallstep.h5
-rw-r--r--src/plugins/remotelinux/packageuploader.cpp109
-rw-r--r--src/plugins/remotelinux/packageuploader.h70
-rw-r--r--src/plugins/remotelinux/publickeydeploymentdialog.cpp121
-rw-r--r--src/plugins/remotelinux/publickeydeploymentdialog.h13
-rw-r--r--src/plugins/remotelinux/remotelinux.qbs43
-rw-r--r--src/plugins/remotelinux/remotelinux_constants.h5
-rw-r--r--src/plugins/remotelinux/remotelinux_export.h2
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp102
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h58
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp78
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h44
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp70
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h45
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp134
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h58
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp16
-rw-r--r--src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp25
-rw-r--r--src/plugins/remotelinux/remotelinuxdeployconfiguration.h6
-rw-r--r--src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp52
-rw-r--r--src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.h14
-rw-r--r--src/plugins/remotelinux/remotelinuxenvironmentreader.cpp51
-rw-r--r--src/plugins/remotelinux/remotelinuxenvironmentreader.h16
-rw-r--r--src/plugins/remotelinux/remotelinuxkillappservice.cpp102
-rw-r--r--src/plugins/remotelinux/remotelinuxkillappservice.h58
-rw-r--r--src/plugins/remotelinux/remotelinuxkillappstep.cpp66
-rw-r--r--src/plugins/remotelinux/remotelinuxkillappstep.h43
-rw-r--r--src/plugins/remotelinux/remotelinuxpackageinstaller.cpp149
-rw-r--r--src/plugins/remotelinux/remotelinuxpackageinstaller.h85
-rw-r--r--src/plugins/remotelinux/remotelinuxplugin.cpp26
-rw-r--r--src/plugins/remotelinux/remotelinuxqmltoolingsupport.cpp9
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfiguration.cpp16
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfiguration.h2
-rw-r--r--src/plugins/remotelinux/remotelinuxsignaloperation.cpp61
-rw-r--r--src/plugins/remotelinux/remotelinuxsignaloperation.h15
-rw-r--r--src/plugins/remotelinux/remotelinuxx11forwardingaspect.cpp54
-rw-r--r--src/plugins/remotelinux/remotelinuxx11forwardingaspect.h46
-rw-r--r--src/plugins/remotelinux/rsyncdeploystep.cpp183
-rw-r--r--src/plugins/remotelinux/rsyncdeploystep.h15
-rw-r--r--src/plugins/remotelinux/sshkeycreationdialog.cpp141
-rw-r--r--src/plugins/remotelinux/sshkeycreationdialog.h57
-rw-r--r--src/plugins/remotelinux/sshkeycreationdialog.ui250
-rw-r--r--src/plugins/remotelinux/sshkeydeployer.cpp108
-rw-r--r--src/plugins/remotelinux/sshkeydeployer.h62
-rw-r--r--src/plugins/remotelinux/sshprocessinterface.h67
-rw-r--r--src/plugins/remotelinux/tarpackagecreationstep.cpp359
-rw-r--r--src/plugins/remotelinux/tarpackagecreationstep.h46
-rw-r--r--src/plugins/remotelinux/tarpackagedeploystep.cpp281
-rw-r--r--src/plugins/remotelinux/tarpackagedeploystep.h40
-rw-r--r--src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp98
-rw-r--r--src/plugins/remotelinux/uploadandinstalltarpackagestep.h62
-rw-r--r--src/plugins/remotelinux/x11forwardingaspect.cpp57
-rw-r--r--src/plugins/remotelinux/x11forwardingaspect.h54
-rw-r--r--src/plugins/resourceeditor/CMakeLists.txt1
-rw-r--r--src/plugins/resourceeditor/resource_global.h4
-rw-r--r--src/plugins/resourceeditor/resourceeditor.qbs2
-rw-r--r--src/plugins/resourceeditor/resourcenode.cpp26
-rw-r--r--src/plugins/resourceeditor/resourcenode.h14
-rw-r--r--src/plugins/scxmleditor/common/colorsettings.cpp11
-rw-r--r--src/plugins/scxmleditor/common/structure.cpp2
-rw-r--r--src/plugins/scxmleditor/outputpane/warningmodel.cpp2
-rw-r--r--src/plugins/scxmleditor/plugin_interface/actionhandler.cpp1
-rw-r--r--src/plugins/scxmleditor/plugin_interface/connectableitem.cpp49
-rw-r--r--src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp84
-rw-r--r--src/plugins/scxmleditor/plugin_interface/parallelitem.cpp10
-rw-r--r--src/plugins/scxmleditor/plugin_interface/scattributeitemdelegate.cpp4
-rw-r--r--src/plugins/scxmleditor/plugin_interface/sceneutils.cpp16
-rw-r--r--src/plugins/scxmleditor/plugin_interface/sceneutils.h10
-rw-r--r--src/plugins/silversearcher/findinfilessilversearcher.cpp4
-rw-r--r--src/plugins/studiowelcome/examplecheckout.cpp47
-rw-r--r--src/plugins/studiowelcome/examplecheckout.h3
-rw-r--r--src/plugins/studiowelcome/presetmodel.cpp4
-rw-r--r--src/plugins/studiowelcome/studiowelcome.qbs3
-rw-r--r--src/plugins/studiowelcome/studiowelcomeplugin.cpp200
-rw-r--r--src/plugins/studiowelcome/userpresets.h2
-rw-r--r--src/plugins/subversion/subversionclient.cpp7
-rw-r--r--src/plugins/subversion/subversionplugin.cpp7
-rw-r--r--src/plugins/texteditor/CMakeLists.txt2
-rw-r--r--src/plugins/texteditor/behaviorsettingspage.cpp60
-rw-r--r--src/plugins/texteditor/behaviorsettingspage.ui45
-rw-r--r--src/plugins/texteditor/behaviorsettingswidget.cpp8
-rw-r--r--src/plugins/texteditor/codeassist/assistinterface.cpp16
-rw-r--r--src/plugins/texteditor/codeassist/assistinterface.h14
-rw-r--r--src/plugins/texteditor/codeassist/assistproposaliteminterface.h4
-rw-r--r--src/plugins/texteditor/codeassist/codeassistant.cpp25
-rw-r--r--src/plugins/texteditor/codeassist/documentcontentcompletion.cpp2
-rw-r--r--src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp2
-rw-r--r--src/plugins/texteditor/codeassist/genericproposal.cpp2
-rw-r--r--src/plugins/texteditor/codeassist/iassistproposal.h4
-rw-r--r--src/plugins/texteditor/codestyleselectorwidget.cpp4
-rw-r--r--src/plugins/texteditor/codestyleselectorwidget.ui2
-rw-r--r--src/plugins/texteditor/colorschemeedit.cpp9
-rw-r--r--src/plugins/texteditor/displaysettings.cpp4
-rw-r--r--src/plugins/texteditor/displaysettings.h1
-rw-r--r--src/plugins/texteditor/displaysettingspage.cpp2
-rw-r--r--src/plugins/texteditor/displaysettingspage.ui9
-rw-r--r--src/plugins/texteditor/findinfiles.cpp5
-rw-r--r--src/plugins/texteditor/findinopenfiles.cpp4
-rw-r--r--src/plugins/texteditor/fontsettings.cpp6
-rw-r--r--src/plugins/texteditor/fontsettingspage.cpp9
-rw-r--r--src/plugins/texteditor/fontsettingspage.h1
-rw-r--r--src/plugins/texteditor/formattexteditor.cpp5
-rw-r--r--src/plugins/texteditor/highlighter.cpp12
-rw-r--r--src/plugins/texteditor/highlighter.h4
-rw-r--r--src/plugins/texteditor/highlightersettings.cpp4
-rw-r--r--src/plugins/texteditor/highlightersettingspage.cpp1
-rw-r--r--src/plugins/texteditor/icodestylepreferencesfactory.h6
-rw-r--r--src/plugins/texteditor/outlinefactory.cpp9
-rw-r--r--src/plugins/texteditor/refactoringchanges.cpp8
-rw-r--r--src/plugins/texteditor/refactoringchanges.h4
-rw-r--r--src/plugins/texteditor/snippets/snippet.cpp1
-rw-r--r--src/plugins/texteditor/tabsettings.cpp2
-rw-r--r--src/plugins/texteditor/textdocument.cpp31
-rw-r--r--src/plugins/texteditor/textdocument.h3
-rw-r--r--src/plugins/texteditor/textdocumentlayout.cpp14
-rw-r--r--src/plugins/texteditor/textdocumentlayout.h7
-rw-r--r--src/plugins/texteditor/texteditor.cpp264
-rw-r--r--src/plugins/texteditor/texteditor.h9
-rw-r--r--src/plugins/texteditor/texteditor.qbs1
-rw-r--r--src/plugins/texteditor/texteditor_global.h2
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.cpp6
-rw-r--r--src/plugins/texteditor/texteditorconstants.cpp14
-rw-r--r--src/plugins/texteditor/texteditorconstants.h15
-rw-r--r--src/plugins/texteditor/texteditoroverlay.cpp18
-rw-r--r--src/plugins/texteditor/texteditoroverlay.h4
-rw-r--r--src/plugins/texteditor/texteditorplugin.cpp13
-rw-r--r--src/plugins/texteditor/texteditorsettings.cpp59
-rw-r--r--src/plugins/texteditor/textmark.cpp95
-rw-r--r--src/plugins/texteditor/textmark.h17
-rw-r--r--src/plugins/todo/constants.h2
-rw-r--r--src/plugins/todo/optionsdialog.cpp2
-rw-r--r--src/plugins/todo/todoicons.cpp5
-rw-r--r--src/plugins/todo/todoitem.h2
-rw-r--r--src/plugins/todo/todoprojectsettingswidget.cpp1
-rw-r--r--src/plugins/todo/todoprojectsettingswidget.h4
-rw-r--r--src/plugins/updateinfo/updateinfoplugin.cpp152
-rw-r--r--src/plugins/updateinfo/updateinfoplugin.h1
-rw-r--r--src/plugins/updateinfo/updateinfotools.h35
-rw-r--r--src/plugins/valgrind/CMakeLists.txt3
-rw-r--r--src/plugins/valgrind/callgrind/callgrindcontroller.cpp242
-rw-r--r--src/plugins/valgrind/callgrind/callgrindcontroller.h96
-rw-r--r--src/plugins/valgrind/callgrind/callgrindcycledetection.cpp7
-rw-r--r--src/plugins/valgrind/callgrind/callgrindfunction.cpp13
-rw-r--r--src/plugins/valgrind/callgrind/callgrindfunctioncycle.cpp8
-rw-r--r--src/plugins/valgrind/callgrind/callgrindparsedata.cpp2
-rw-r--r--src/plugins/valgrind/callgrind/callgrindparser.cpp15
-rw-r--r--src/plugins/valgrind/callgrind/callgrindproxymodel.cpp3
-rw-r--r--src/plugins/valgrind/callgrindengine.cpp214
-rw-r--r--src/plugins/valgrind/callgrindengine.h51
-rw-r--r--src/plugins/valgrind/callgrindtool.cpp15
-rw-r--r--src/plugins/valgrind/callgrindvisualisation.cpp6
-rw-r--r--src/plugins/valgrind/memcheckerrorview.cpp2
-rw-r--r--src/plugins/valgrind/memchecktool.cpp97
-rw-r--r--src/plugins/valgrind/memchecktool.h2
-rw-r--r--src/plugins/valgrind/valgrind.qbs2
-rw-r--r--src/plugins/valgrind/valgrindengine.cpp52
-rw-r--r--src/plugins/valgrind/valgrindengine.h3
-rw-r--r--src/plugins/valgrind/valgrindmemcheckparsertest.cpp7
-rw-r--r--src/plugins/valgrind/valgrindrunner.cpp311
-rw-r--r--src/plugins/valgrind/valgrindrunner.h17
-rw-r--r--src/plugins/valgrind/valgrindsettings.cpp2
-rw-r--r--src/plugins/valgrind/valgrindtestrunnertest.cpp2
-rw-r--r--src/plugins/valgrind/xmlprotocol/error.cpp5
-rw-r--r--src/plugins/valgrind/xmlprotocol/errorlistmodel.cpp15
-rw-r--r--src/plugins/valgrind/xmlprotocol/modelhelpers.cpp2
-rw-r--r--src/plugins/valgrind/xmlprotocol/suppression.cpp2
-rw-r--r--src/plugins/vcsbase/CMakeLists.txt1
-rw-r--r--src/plugins/vcsbase/baseannotationhighlighter.cpp29
-rw-r--r--src/plugins/vcsbase/basevcseditorfactory.cpp2
-rw-r--r--src/plugins/vcsbase/basevcseditorfactory.h2
-rw-r--r--src/plugins/vcsbase/basevcssubmiteditorfactory.cpp2
-rw-r--r--src/plugins/vcsbase/basevcssubmiteditorfactory.h2
-rw-r--r--src/plugins/vcsbase/cleandialog.cpp9
-rw-r--r--src/plugins/vcsbase/submiteditorwidget.cpp6
-rw-r--r--src/plugins/vcsbase/submitfieldwidget.cpp6
-rw-r--r--src/plugins/vcsbase/vcsbase_global.h2
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.cpp45
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.h11
-rw-r--r--src/plugins/vcsbase/vcsbaseclientsettings.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbaseclientsettings.h1
-rw-r--r--src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp1
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp10
-rw-r--r--src/plugins/vcsbase/vcsbaseeditorconfig.cpp4
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.cpp6
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.cpp3
-rw-r--r--src/plugins/vcsbase/vcscommand.cpp1
-rw-r--r--src/plugins/vcsbase/vcsoutputwindow.cpp13
-rw-r--r--src/plugins/vcsbase/wizard/vcscommandpage.cpp11
-rw-r--r--src/plugins/webassembly/webassemblydevice.cpp1
-rw-r--r--src/plugins/webassembly/webassemblyemsdk.cpp2
-rw-r--r--src/plugins/webassembly/webassemblyplugin.cpp2
-rw-r--r--src/plugins/webassembly/webassemblyrunconfiguration.cpp30
-rw-r--r--src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp3
-rw-r--r--src/plugins/webassembly/webassemblyrunconfigurationaspects.h5
-rw-r--r--src/plugins/webassembly/webassemblytoolchain.cpp80
-rw-r--r--src/plugins/webassembly/webassemblytoolchain.h7
-rw-r--r--src/plugins/welcome/introductionwidget.cpp4
-rw-r--r--src/plugins/winrt/CMakeLists.txt16
-rw-r--r--src/plugins/winrt/WinRt.json.in20
-rw-r--r--src/plugins/winrt/images/winrtdevice.pngbin164 -> 0 bytes
-rw-r--r--src/plugins/winrt/images/winrtdevice@2x.pngbin239 -> 0 bytes
-rw-r--r--src/plugins/winrt/images/winrtdevicesmall.pngbin122 -> 0 bytes
-rw-r--r--src/plugins/winrt/images/winrtdevicesmall@2x.pngbin160 -> 0 bytes
-rw-r--r--src/plugins/winrt/winrt.qbs38
-rw-r--r--src/plugins/winrt/winrt.qrc8
-rw-r--r--src/plugins/winrt/winrtconstants.h44
-rw-r--r--src/plugins/winrt/winrtdebugsupport.cpp132
-rw-r--r--src/plugins/winrt/winrtdebugsupport.h49
-rw-r--r--src/plugins/winrt/winrtdeployconfiguration.cpp70
-rw-r--r--src/plugins/winrt/winrtdeployconfiguration.h53
-rw-r--r--src/plugins/winrt/winrtdevice.cpp365
-rw-r--r--src/plugins/winrt/winrtdevice.h83
-rw-r--r--src/plugins/winrt/winrtpackagedeploymentstep.cpp408
-rw-r--r--src/plugins/winrt/winrtpackagedeploymentstep.h40
-rw-r--r--src/plugins/winrt/winrtphoneqtversion.cpp70
-rw-r--r--src/plugins/winrt/winrtphoneqtversion.h52
-rw-r--r--src/plugins/winrt/winrtplugin.cpp92
-rw-r--r--src/plugins/winrt/winrtplugin.h48
-rw-r--r--src/plugins/winrt/winrtqtversion.cpp68
-rw-r--r--src/plugins/winrt/winrtqtversion.h53
-rw-r--r--src/plugins/winrt/winrtrunconfiguration.cpp94
-rw-r--r--src/plugins/winrt/winrtrunconfiguration.h72
-rw-r--r--src/plugins/winrt/winrtruncontrol.cpp110
-rw-r--r--src/plugins/winrt/winrtruncontrol.h60
-rw-r--r--src/plugins/winrt/winrtrunnerhelper.cpp225
-rw-r--r--src/plugins/winrt/winrtrunnerhelper.h86
-rw-r--r--src/share/3rdparty/fonts/SourceCodePro-Bold.ttfbin211716 -> 138268 bytes
-rw-r--r--src/share/3rdparty/fonts/SourceCodePro-BoldIt.ttfbin0 -> 116112 bytes
-rw-r--r--src/share/3rdparty/fonts/SourceCodePro-It.ttfbin180472 -> 116740 bytes
-rw-r--r--src/share/3rdparty/fonts/SourceCodePro-Regular.ttfbin212880 -> 138680 bytes
-rw-r--r--src/share/3rdparty/package-manager/conan.cmake469
-rw-r--r--src/shared/designerintegrationv2/CMakeLists.txt7
-rw-r--r--src/shared/help/CMakeLists.txt2
-rw-r--r--src/shared/proparser/CMakeLists.txt2
m---------src/shared/qbs0
-rw-r--r--src/tools/CMakeLists.txt7
-rw-r--r--src/tools/clangbackend/CMakeLists.txt8
-rw-r--r--src/tools/clangbackend/clangbackend.qbs38
-rw-r--r--src/tools/clangbackend/clangbackendmain.cpp103
-rw-r--r--src/tools/clangbackend/source/CMakeLists.txt73
-rw-r--r--src/tools/clangbackend/source/clangasyncjob.h79
-rw-r--r--src/tools/clangbackend/source/clangbackend_global.h39
-rw-r--r--src/tools/clangbackend/source/clangclock.h36
-rw-r--r--src/tools/clangbackend/source/clangcodecompleteresults.cpp83
-rw-r--r--src/tools/clangbackend/source/clangcodecompleteresults.h61
-rw-r--r--src/tools/clangbackend/source/clangcodemodelserver.cpp520
-rw-r--r--src/tools/clangbackend/source/clangcodemodelserver.h109
-rw-r--r--src/tools/clangbackend/source/clangcompletecodejob.cpp73
-rw-r--r--src/tools/clangbackend/source/clangcompletecodejob.h43
-rw-r--r--src/tools/clangbackend/source/clangdocument.cpp453
-rw-r--r--src/tools/clangbackend/source/clangdocument.h142
-rw-r--r--src/tools/clangbackend/source/clangdocumentjob.h67
-rw-r--r--src/tools/clangbackend/source/clangdocumentprocessor.cpp149
-rw-r--r--src/tools/clangbackend/source/clangdocumentprocessor.h79
-rw-r--r--src/tools/clangbackend/source/clangdocumentprocessors.cpp127
-rw-r--r--src/tools/clangbackend/source/clangdocumentprocessors.h67
-rw-r--r--src/tools/clangbackend/source/clangdocuments.cpp291
-rw-r--r--src/tools/clangbackend/source/clangdocuments.h90
-rw-r--r--src/tools/clangbackend/source/clangdocumentsuspenderresumer.cpp134
-rw-r--r--src/tools/clangbackend/source/clangdocumentsuspenderresumer.h62
-rw-r--r--src/tools/clangbackend/source/clangexceptions.cpp83
-rw-r--r--src/tools/clangbackend/source/clangexceptions.h87
-rw-r--r--src/tools/clangbackend/source/clangfilepath.cpp89
-rw-r--r--src/tools/clangbackend/source/clangfilepath.h38
-rw-r--r--src/tools/clangbackend/source/clangfilesystemwatcher.cpp91
-rw-r--r--src/tools/clangbackend/source/clangfilesystemwatcher.h57
-rw-r--r--src/tools/clangbackend/source/clangfollowsymbol.cpp163
-rw-r--r--src/tools/clangbackend/source/clangfollowsymbol.h50
-rw-r--r--src/tools/clangbackend/source/clangfollowsymboljob.cpp68
-rw-r--r--src/tools/clangbackend/source/clangfollowsymboljob.h43
-rw-r--r--src/tools/clangbackend/source/clangiasyncjob.cpp71
-rw-r--r--src/tools/clangbackend/source/clangiasyncjob.h75
-rw-r--r--src/tools/clangbackend/source/clangjobcontext.cpp73
-rw-r--r--src/tools/clangbackend/source/clangjobcontext.h59
-rw-r--r--src/tools/clangbackend/source/clangjobqueue.cpp313
-rw-r--r--src/tools/clangbackend/source/clangjobqueue.h83
-rw-r--r--src/tools/clangbackend/source/clangjobrequest.cpp299
-rw-r--r--src/tools/clangbackend/source/clangjobrequest.h128
-rw-r--r--src/tools/clangbackend/source/clangjobs.cpp226
-rw-r--r--src/tools/clangbackend/source/clangjobs.h102
-rw-r--r--src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.cpp63
-rw-r--r--src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.h42
-rw-r--r--src/tools/clangbackend/source/clangreferencescollector.cpp226
-rw-r--r--src/tools/clangbackend/source/clangreferencescollector.h61
-rw-r--r--src/tools/clangbackend/source/clangrequestannotationsjob.cpp70
-rw-r--r--src/tools/clangbackend/source/clangrequestannotationsjob.h53
-rw-r--r--src/tools/clangbackend/source/clangrequestreferencesjob.cpp68
-rw-r--r--src/tools/clangbackend/source/clangrequestreferencesjob.h42
-rw-r--r--src/tools/clangbackend/source/clangrequesttooltipjob.cpp67
-rw-r--r--src/tools/clangbackend/source/clangrequesttooltipjob.h43
-rw-r--r--src/tools/clangbackend/source/clangresumedocumentjob.cpp54
-rw-r--r--src/tools/clangbackend/source/clangresumedocumentjob.h44
-rw-r--r--src/tools/clangbackend/source/clangstring.h174
-rw-r--r--src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.cpp124
-rw-r--r--src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.h72
-rw-r--r--src/tools/clangbackend/source/clangsuspenddocumentjob.cpp59
-rw-r--r--src/tools/clangbackend/source/clangsuspenddocumentjob.h39
-rw-r--r--src/tools/clangbackend/source/clangtooltipinfocollector.cpp574
-rw-r--r--src/tools/clangbackend/source/clangtooltipinfocollector.h48
-rw-r--r--src/tools/clangbackend/source/clangtranslationunit.cpp262
-rw-r--r--src/tools/clangbackend/source/clangtranslationunit.h115
-rw-r--r--src/tools/clangbackend/source/clangtranslationunits.cpp162
-rw-r--r--src/tools/clangbackend/source/clangtranslationunits.h84
-rw-r--r--src/tools/clangbackend/source/clangtranslationunitupdater.cpp227
-rw-r--r--src/tools/clangbackend/source/clangtranslationunitupdater.h119
-rw-r--r--src/tools/clangbackend/source/clangtype.cpp282
-rw-r--r--src/tools/clangbackend/source/clangtype.h86
-rw-r--r--src/tools/clangbackend/source/clangunsavedfilesshallowarguments.cpp57
-rw-r--r--src/tools/clangbackend/source/clangunsavedfilesshallowarguments.h49
-rw-r--r--src/tools/clangbackend/source/clangupdateannotationsjob.cpp116
-rw-r--r--src/tools/clangbackend/source/clangupdateannotationsjob.h63
-rw-r--r--src/tools/clangbackend/source/clangupdateextraannotationsjob.cpp59
-rw-r--r--src/tools/clangbackend/source/clangupdateextraannotationsjob.h43
-rw-r--r--src/tools/clangbackend/source/codecompleter.cpp219
-rw-r--r--src/tools/clangbackend/source/codecompleter.h64
-rw-r--r--src/tools/clangbackend/source/codecompletionchunkconverter.cpp83
-rw-r--r--src/tools/clangbackend/source/codecompletionchunkconverter.h52
-rw-r--r--src/tools/clangbackend/source/codecompletionsextractor.cpp530
-rw-r--r--src/tools/clangbackend/source/codecompletionsextractor.h91
-rw-r--r--src/tools/clangbackend/source/commandlinearguments.cpp128
-rw-r--r--src/tools/clangbackend/source/commandlinearguments.h54
-rw-r--r--src/tools/clangbackend/source/cursor.cpp544
-rw-r--r--src/tools/clangbackend/source/cursor.h151
-rw-r--r--src/tools/clangbackend/source/diagnostic.cpp181
-rw-r--r--src/tools/clangbackend/source/diagnostic.h92
-rw-r--r--src/tools/clangbackend/source/diagnosticset.cpp124
-rw-r--r--src/tools/clangbackend/source/diagnosticset.h82
-rw-r--r--src/tools/clangbackend/source/diagnosticsetiterator.h95
-rw-r--r--src/tools/clangbackend/source/fixit.cpp58
-rw-r--r--src/tools/clangbackend/source/fixit.h57
-rw-r--r--src/tools/clangbackend/source/fulltokeninfo.cpp264
-rw-r--r--src/tools/clangbackend/source/fulltokeninfo.h59
-rw-r--r--src/tools/clangbackend/source/skippedsourceranges.cpp134
-rw-r--r--src/tools/clangbackend/source/skippedsourceranges.h59
-rw-r--r--src/tools/clangbackend/source/sourcelocation.cpp148
-rw-r--r--src/tools/clangbackend/source/sourcelocation.h83
-rw-r--r--src/tools/clangbackend/source/sourcerange.cpp118
-rw-r--r--src/tools/clangbackend/source/sourcerange.h67
-rw-r--r--src/tools/clangbackend/source/token.cpp227
-rw-r--r--src/tools/clangbackend/source/token.h94
-rw-r--r--src/tools/clangbackend/source/tokeninfo.cpp799
-rw-r--r--src/tools/clangbackend/source/tokeninfo.h145
-rw-r--r--src/tools/clangbackend/source/tokenprocessor.h165
-rw-r--r--src/tools/clangbackend/source/tokenprocessoriterator.h96
-rw-r--r--src/tools/clangbackend/source/unsavedfile.cpp132
-rw-r--r--src/tools/clangbackend/source/unsavedfile.h61
-rw-r--r--src/tools/clangbackend/source/unsavedfiles.cpp160
-rw-r--r--src/tools/clangbackend/source/unsavedfiles.h74
-rw-r--r--src/tools/clangbackend/source/utf8positionfromlinecolumn.cpp91
-rw-r--r--src/tools/clangbackend/source/utf8positionfromlinecolumn.h54
-rw-r--r--src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp14
-rw-r--r--src/tools/cplusplus-frontend/cplusplus-frontend.cpp2
-rw-r--r--src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp45
-rw-r--r--src/tools/cplusplus-update-frontend/cplusplus-update-frontend.cpp4
-rw-r--r--src/tools/icons/downloadytthumbnails.py144
-rw-r--r--src/tools/icons/export.py3
-rw-r--r--src/tools/icons/qtcreatoricons.svg184
-rw-r--r--src/tools/iostool/CMakeLists.txt1
-rw-r--r--src/tools/iostool/cfutils.h55
-rw-r--r--src/tools/iostool/iosdevicemanager.cpp237
-rw-r--r--src/tools/iostool/iosdevicemanager.h2
-rw-r--r--src/tools/iostool/iostool.cpp8
-rw-r--r--src/tools/iostool/iostool.h1
-rw-r--r--src/tools/iostool/iostool.qbs1
-rw-r--r--src/tools/iostool/mobiledevicelib.cpp28
-rw-r--r--src/tools/iostool/mobiledevicelib.h9
-rw-r--r--src/tools/iostool/relayserver.cpp3
-rw-r--r--src/tools/processlauncher/CMakeLists.txt3
-rw-r--r--src/tools/processlauncher/launchersockethandler.cpp173
-rw-r--r--src/tools/processlauncher/launchersockethandler.h12
-rw-r--r--src/tools/processlauncher/processlauncher.qbs3
-rw-r--r--src/tools/qml2puppet/CMakeLists.txt4
-rw-r--r--src/tools/qtcreatorcrashhandler/CMakeLists.txt21
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandler.cpp6
-rw-r--r--src/tools/qtpromaker/main.cpp11
-rw-r--r--src/tools/screenshotcropper/CMakeLists.txt9
-rw-r--r--src/tools/screenshotcropper/cropimageview.cpp89
-rw-r--r--src/tools/screenshotcropper/cropimageview.h53
-rw-r--r--src/tools/screenshotcropper/main.cpp62
-rw-r--r--src/tools/screenshotcropper/screenshotcropperwindow.cpp96
-rw-r--r--src/tools/screenshotcropper/screenshotcropperwindow.h55
-rw-r--r--src/tools/screenshotcropper/screenshotcropperwindow.ui103
-rw-r--r--src/tools/sdktool/CMakeLists.txt49
-rw-r--r--src/tools/sdktool/addabiflavor.cpp57
-rw-r--r--src/tools/sdktool/addabiflavor.h2
-rw-r--r--src/tools/sdktool/addcmakeoperation.cpp119
-rw-r--r--src/tools/sdktool/addcmakeoperation.h2
-rw-r--r--src/tools/sdktool/adddebuggeroperation.cpp77
-rw-r--r--src/tools/sdktool/adddebuggeroperation.h2
-rw-r--r--src/tools/sdktool/adddeviceoperation.cpp86
-rw-r--r--src/tools/sdktool/adddeviceoperation.h2
-rw-r--r--src/tools/sdktool/addkeysoperation.cpp144
-rw-r--r--src/tools/sdktool/addkeysoperation.h3
-rw-r--r--src/tools/sdktool/addkitoperation.cpp511
-rw-r--r--src/tools/sdktool/addkitoperation.h3
-rw-r--r--src/tools/sdktool/addqtoperation.cpp186
-rw-r--r--src/tools/sdktool/addqtoperation.h4
-rw-r--r--src/tools/sdktool/addtoolchainoperation.cpp168
-rw-r--r--src/tools/sdktool/addtoolchainoperation.h3
-rw-r--r--src/tools/sdktool/addvalueoperation.cpp59
-rw-r--r--src/tools/sdktool/addvalueoperation.h2
-rw-r--r--src/tools/sdktool/findkeyoperation.cpp42
-rw-r--r--src/tools/sdktool/findkeyoperation.h4
-rw-r--r--src/tools/sdktool/findvalueoperation.cpp43
-rw-r--r--src/tools/sdktool/findvalueoperation.h2
-rw-r--r--src/tools/sdktool/getoperation.cpp34
-rw-r--r--src/tools/sdktool/getoperation.h3
-rw-r--r--src/tools/sdktool/main.cpp15
-rw-r--r--src/tools/sdktool/operation.cpp2
-rw-r--r--src/tools/sdktool/operation.h4
-rw-r--r--src/tools/sdktool/rmcmakeoperation.cpp87
-rw-r--r--src/tools/sdktool/rmcmakeoperation.h2
-rw-r--r--src/tools/sdktool/rmdebuggeroperation.cpp93
-rw-r--r--src/tools/sdktool/rmdebuggeroperation.h3
-rw-r--r--src/tools/sdktool/rmdeviceoperation.cpp21
-rw-r--r--src/tools/sdktool/rmdeviceoperation.h2
-rw-r--r--src/tools/sdktool/rmkeysoperation.cpp98
-rw-r--r--src/tools/sdktool/rmkeysoperation.h2
-rw-r--r--src/tools/sdktool/rmkitoperation.cpp105
-rw-r--r--src/tools/sdktool/rmkitoperation.h2
-rw-r--r--src/tools/sdktool/rmqtoperation.cpp59
-rw-r--r--src/tools/sdktool/rmqtoperation.h2
-rw-r--r--src/tools/sdktool/rmtoolchainoperation.cpp77
-rw-r--r--src/tools/sdktool/rmtoolchainoperation.h3
-rw-r--r--src/tools/sdktool/sdktool.qbs69
-rw-r--r--src/tools/sdktool/sdktoollib.qbs109
-rw-r--r--src/tools/tools.qbs3
-rw-r--r--src/tools/winrtdebughelper/CMakeLists.txt8
-rw-r--r--src/tools/winrtdebughelper/winrtdebughelper.cpp74
-rw-r--r--src/tools/winrtdebughelper/winrtdebughelper.qbs12
-rw-r--r--tests/auto/CMakeLists.txt1
-rw-r--r--tests/auto/aggregation/tst_aggregate.cpp2
-rw-r--r--tests/auto/algorithm/tst_algorithm.cpp2
-rw-r--r--tests/auto/android/tst_avdmanageroutputparser.cpp24
-rw-r--r--tests/auto/auto.qbs1
-rw-r--r--tests/auto/changeset/tst_changeset.cpp2
-rw-r--r--tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp2
-rw-r--r--tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp2
-rw-r--r--tests/auto/cplusplus/fileiterationorder/tst_fileiterationorder.cpp2
-rw-r--r--tests/auto/cplusplus/misc/tst_misc.cpp2
-rw-r--r--tests/auto/cplusplus/semantic/tst_semantic.cpp8
-rw-r--r--tests/auto/debugger/CMakeLists.txt1
-rw-r--r--tests/auto/debugger/tst_dumpers.cpp66
-rw-r--r--tests/auto/debugger/tst_gdb.cpp4
-rw-r--r--tests/auto/diff/differ/tst_differ.cpp3
-rw-r--r--tests/auto/environment/tst_environment.cpp2
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.h2
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.h2
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.h2
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.h2
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.h2
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.h2
-rw-r--r--tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp2
-rw-r--r--tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt2
-rw-r--r--tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp2
-rw-r--r--tests/auto/externaltool/CMakeLists.txt2
-rw-r--r--tests/auto/externaltool/externaltool.qbs9
-rw-r--r--tests/auto/externaltool/tst_externaltooltest.cpp2
-rw-r--r--tests/auto/filesearch/tst_filesearch.cpp2
-rw-r--r--tests/auto/json/tst_json.cpp5
-rw-r--r--tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp29
-rw-r--r--tests/auto/mapreduce/tst_mapreduce.cpp2
-rw-r--r--tests/auto/pointeralgorithm/tst_pointeralgorithm.cpp2
-rw-r--r--tests/auto/profilewriter/tst_profilewriter.cpp3
-rw-r--r--tests/auto/qml/codemodel/check/CMakeLists.txt1
-rw-r--r--tests/auto/qml/codemodel/check/tst_check.cpp2
-rw-r--r--tests/auto/qml/codemodel/dependencies/CMakeLists.txt1
-rw-r--r--tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp2
-rw-r--r--tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp2
-rw-r--r--tests/auto/qml/codemodel/importscheck/CMakeLists.txt1
-rw-r--r--tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp2
-rw-r--r--tests/auto/qml/persistenttrie/tst_testtrie.cpp2
-rw-r--r--tests/auto/qml/qmldesigner/coretests/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp245
-rw-r--r--tests/auto/qml/qmldesigner/coretests/tst_testcore.h3
-rw-r--r--tests/auto/qml/qmldesigner/data/fx/states.qml6
-rw-r--r--tests/auto/qml/qmldesigner/wizard/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp2
-rw-r--r--tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp2
-rw-r--r--tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp2
-rw-r--r--tests/auto/qml/reformatter/nullishCoalescing.qml9
-rw-r--r--tests/auto/qml/reformatter/tst_reformatter.cpp2
-rw-r--r--tests/auto/runextensions/tst_runextensions.cpp2
-rw-r--r--tests/auto/sdktool/CMakeLists.txt2
-rw-r--r--tests/auto/sdktool/sdktool.qbs2
-rw-r--r--tests/auto/sdktool/tst_sdktool.cpp59
-rw-r--r--tests/auto/ssh/CMakeLists.txt9
-rw-r--r--tests/auto/ssh/ssh.qbs17
-rw-r--r--tests/auto/ssh/tst_ssh.cpp594
-rw-r--r--tests/auto/toolchaincache/tst_toolchaincache.cpp2
-rw-r--r--tests/auto/tracing/flamegraphview/CMakeLists.txt2
-rw-r--r--tests/auto/tracing/flamegraphview/tst_flamegraphview.cpp10
-rw-r--r--tests/auto/tracing/timelineabstractrenderer/tst_timelineabstractrenderer.cpp2
-rw-r--r--tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp2
-rw-r--r--tests/auto/tracing/timelinemodelaggregator/tst_timelinemodelaggregator.cpp2
-rw-r--r--tests/auto/tracing/timelinenotesmodel/tst_timelinenotesmodel.cpp2
-rw-r--r--tests/auto/tracing/timelineoverviewrenderer/tst_timelineoverviewrenderer.cpp2
-rw-r--r--tests/auto/tracing/timelinerenderer/CMakeLists.txt1
-rw-r--r--tests/auto/tracing/timelinerenderpass/tst_timelinerenderpass.cpp2
-rw-r--r--tests/auto/tracing/timelinerenderstate/tst_timelinerenderstate.cpp2
-rw-r--r--tests/auto/tracing/timelinezoomcontrol/tst_timelinezoomcontrol.cpp2
-rw-r--r--tests/auto/updateinfo/tst_updateinfo.cpp17
-rw-r--r--tests/auto/utils/CMakeLists.txt1
-rw-r--r--tests/auto/utils/deviceshell/CMakeLists.txt8
-rw-r--r--tests/auto/utils/deviceshell/deviceshell.qbs12
-rw-r--r--tests/auto/utils/deviceshell/tst_deviceshell.cpp369
-rw-r--r--tests/auto/utils/fileutils/tst_fileutils.cpp3
-rw-r--r--tests/auto/utils/indexedcontainerproxyconstiterator/tst_indexedcontainerproxyconstiterator.cpp2
-rw-r--r--tests/auto/utils/persistentsettings/tst_persistentsettings.cpp2
-rw-r--r--tests/auto/utils/qtcprocess/CMakeLists.txt9
-rw-r--r--tests/auto/utils/qtcprocess/processtestapp/CMakeLists.txt17
-rw-r--r--tests/auto/utils/qtcprocess/processtestapp/main.cpp64
-rw-r--r--tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp293
-rw-r--r--tests/auto/utils/qtcprocess/processtestapp/processtestapp.h131
-rw-r--r--tests/auto/utils/qtcprocess/processtestapp/processtestapp.qbs30
-rw-r--r--tests/auto/utils/qtcprocess/qtcprocess.qbs38
-rw-r--r--tests/auto/utils/qtcprocess/tst_qtcprocess.cpp694
-rw-r--r--tests/auto/utils/settings/tst_settings.cpp2
-rw-r--r--tests/auto/utils/stringutils/tst_stringutils.cpp2
-rw-r--r--tests/auto/utils/templateengine/tst_templateengine.cpp4
-rw-r--r--tests/auto/utils/treemodel/tst_treemodel.cpp2
-rw-r--r--tests/auto/utils/utils.qbs1
-rw-r--r--tests/auto/valgrind/CMakeLists.txt4
-rw-r--r--tests/auto/valgrind/callgrind/CMakeLists.txt34
-rw-r--r--tests/auto/valgrind/memcheck/CMakeLists.txt27
-rw-r--r--tests/auto/valgrind/memcheck/modeldemo.cpp10
-rw-r--r--tests/auto/valgrind/memcheck/modeldemo.qbs15
-rw-r--r--tests/auto/valgrind/memcheck/testapps/CMakeLists.txt12
-rw-r--r--tests/auto/valgrind/memcheck/testapps/free1/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/free2/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/invalidjump/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/leak1/CMakeLists.txt5
-rw-r--r--tests/auto/valgrind/memcheck/testapps/leak2/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/leak3/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/leak4/CMakeLists.txt4
-rw-r--r--tests/auto/valgrind/memcheck/testapps/overlap/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/syscall/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/testapp.cmake4
-rw-r--r--tests/auto/valgrind/memcheck/testapps/uninit1/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/uninit2/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/memcheck/testapps/uninit3/CMakeLists.txt3
-rw-r--r--tests/auto/valgrind/valgrind.cmake30
-rw-r--r--tests/auto/valgrind/valgrindautotest.qbs1
-rw-r--r--tests/manual/CMakeLists.txt2
-rw-r--r--tests/manual/coco/README.md36
-rw-r--r--tests/manual/debugger/gui/CMakeLists.txt7
-rw-r--r--tests/manual/debugger/gui/gui.qbs1
-rw-r--r--tests/manual/debugger/simple/simple_test_app.cpp6
-rw-r--r--tests/manual/debugger/simple/simple_test_app.qbs1
-rw-r--r--tests/manual/debugger/simple/simple_test_plugin.qbs1
-rw-r--r--tests/manual/deviceshell/CMakeLists.txt10
-rw-r--r--tests/manual/deviceshell/deviceshell.qbs22
-rw-r--r--tests/manual/deviceshell/tst_deviceshell.cpp228
-rw-r--r--tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-build1
-rw-r--r--tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-clang-llbd-build1
-rw-r--r--tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-run6
-rw-r--r--tests/manual/docker/README.md2
-rw-r--r--tests/manual/manual.qbs3
-rw-r--r--tests/manual/ssh/CMakeLists.txt2
-rw-r--r--tests/manual/ssh/sftpfsmodel/CMakeLists.txt18
-rw-r--r--tests/manual/ssh/sftpfsmodel/main.cpp46
-rw-r--r--tests/manual/ssh/sftpfsmodel/sftpfsmodel.pro9
-rw-r--r--tests/manual/ssh/sftpfsmodel/sftpfsmodel.qbs38
-rw-r--r--tests/manual/ssh/sftpfsmodel/window.cpp117
-rw-r--r--tests/manual/ssh/sftpfsmodel/window.h52
-rw-r--r--tests/manual/ssh/sftpfsmodel/window.ui201
-rw-r--r--tests/manual/ssh/shell/CMakeLists.txt13
-rw-r--r--tests/manual/ssh/shell/argumentscollector.cpp135
-rw-r--r--tests/manual/ssh/shell/argumentscollector.h50
-rw-r--r--tests/manual/ssh/shell/main.cpp56
-rw-r--r--tests/manual/ssh/shell/shell.cpp108
-rw-r--r--tests/manual/ssh/shell/shell.h60
-rw-r--r--tests/manual/ssh/shell/shell.pro6
-rw-r--r--tests/manual/ssh/shell/shell.qbs27
-rw-r--r--tests/manual/ssh/ssh.pri17
-rw-r--r--tests/manual/ssh/ssh.pro8
-rw-r--r--tests/manual/widgets/crumblepath/crumblepath.qbs1
-rw-r--r--tests/manual/widgets/infolabel/infolabel.qbs1
-rw-r--r--tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp34
-rw-r--r--tests/manual/widgets/manhattanstyle/manhattanstyle.qbs1
-rw-r--r--tests/manual/widgets/tracing/tracing.qbs1
-rw-r--r--tests/system/objects.map2
-rw-r--r--tests/system/shared/clang.py2
-rw-r--r--tests/system/shared/suites_qtta.py2
-rw-r--r--tests/system/shared/utils.py18
-rw-r--r--tests/system/suite_HELP/tst_HELP02/test.py2
-rw-r--r--tests/system/suite_QMLS/tst_QMLS02/test.py2
-rw-r--r--tests/system/suite_debugger/tst_qml_js_console/test.py2
-rw-r--r--tests/system/suite_editors/tst_clean_whitespaces/test.py2
-rw-r--r--tests/system/suite_editors/tst_edit_externally/test.py2
-rw-r--r--tests/system/suite_editors/tst_generic_highlighter/test.py4
-rw-r--r--tests/system/suite_general/tst_create_proj_wizard/test.py9
-rw-r--r--tests/system/suite_general/tst_default_settings/test.py42
-rw-r--r--tests/system/suite_general/tst_installed_languages/test.py2
-rw-r--r--tests/system/suite_general/tst_save_before_build/test.py2
-rw-r--r--tests/system/suite_qtquick/tst_qtquick_creation4/test.py4
-rw-r--r--tests/unit/CMakeLists.txt3
-rw-r--r--tests/unit/echoserver/CMakeLists.txt9
-rw-r--r--tests/unit/echoserver/echoclangcodemodelserver.cpp107
-rw-r--r--tests/unit/echoserver/echoclangcodemodelserver.h58
-rw-r--r--tests/unit/echoserver/echoserver.qbs30
-rw-r--r--tests/unit/echoserver/echoserverprocessmain.cpp57
-rw-r--r--tests/unit/unit.qbs1
-rw-r--r--tests/unit/unittest/CMakeLists.txt146
-rw-r--r--tests/unit/unittest/activationsequencecontextprocessor-test.cpp221
-rw-r--r--tests/unit/unittest/activationsequenceprocessor-test.cpp195
-rw-r--r--tests/unit/unittest/chunksreportedmonitor.cpp59
-rw-r--r--tests/unit/unittest/chunksreportedmonitor.h55
-rw-r--r--tests/unit/unittest/clangasyncjob-base.cpp64
-rw-r--r--tests/unit/unittest/clangasyncjob-base.h64
-rw-r--r--tests/unit/unittest/clangcodecompleteresults-test.cpp108
-rw-r--r--tests/unit/unittest/clangcodemodelserver-test.cpp753
-rw-r--r--tests/unit/unittest/clangcompareoperators.h40
-rw-r--r--tests/unit/unittest/clangcompletecodejob-test.cpp103
-rw-r--r--tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp589
-rw-r--r--tests/unit/unittest/clangdiagnosticfilter-test.cpp238
-rw-r--r--tests/unit/unittest/clangdocument-test.cpp361
-rw-r--r--tests/unit/unittest/clangdocumentprocessor-test.cpp103
-rw-r--r--tests/unit/unittest/clangdocumentprocessors-test.cpp183
-rw-r--r--tests/unit/unittest/clangdocuments-test.cpp377
-rw-r--r--tests/unit/unittest/clangdocumentsuspenderresumer-test.cpp311
-rw-r--r--tests/unit/unittest/clangfixitoperation-test.cpp130
-rw-r--r--tests/unit/unittest/clangfollowsymbol-test.cpp367
-rw-r--r--tests/unit/unittest/clangisdiagnosticrelatedtolocation-test.cpp146
-rw-r--r--tests/unit/unittest/clangjobqueue-test.cpp512
-rw-r--r--tests/unit/unittest/clangjobs-test.cpp140
-rw-r--r--tests/unit/unittest/clangparsesupportivetranslationunitjob-test.cpp69
-rw-r--r--tests/unit/unittest/clangreferencescollector-test.cpp506
-rw-r--r--tests/unit/unittest/clangrequestannotationsjob-test.cpp85
-rw-r--r--tests/unit/unittest/clangrequestreferencesjob-test.cpp114
-rw-r--r--tests/unit/unittest/clangresumedocumentjob-test.cpp92
-rw-r--r--tests/unit/unittest/clangstring-test.cpp216
-rw-r--r--tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp200
-rw-r--r--tests/unit/unittest/clangsuspenddocumentjob-test.cpp73
-rw-r--r--tests/unit/unittest/clangtooltipinfo-test.cpp696
-rw-r--r--tests/unit/unittest/clangtranslationunit-test.cpp196
-rw-r--r--tests/unit/unittest/clangtranslationunits-test.cpp150
-rw-r--r--tests/unit/unittest/clangupdateannotationsjob-test.cpp124
-rw-r--r--tests/unit/unittest/clientserverinprocess-test.cpp258
-rw-r--r--tests/unit/unittest/clientserveroutsideprocess-test.cpp156
-rw-r--r--tests/unit/unittest/codecompleter-test.cpp680
-rw-r--r--tests/unit/unittest/codecompletionsextractor-test.cpp865
-rw-r--r--tests/unit/unittest/completionchunkstotextconverter-test.cpp379
-rw-r--r--tests/unit/unittest/cursor-test.cpp941
-rw-r--r--tests/unit/unittest/data/complete_arrow.cpp6
-rw-r--r--tests/unit/unittest/data/complete_completer_main.cpp28
-rw-r--r--tests/unit/unittest/data/complete_completer_main_unsaved.cpp28
-rw-r--r--tests/unit/unittest/data/complete_extractor_brief_comment.cpp11
-rw-r--r--tests/unit/unittest/data/complete_extractor_class.cpp21
-rw-r--r--tests/unit/unittest/data/complete_extractor_constructor.cpp22
-rw-r--r--tests/unit/unittest/data/complete_extractor_constructorMemberInitialization.cpp5
-rw-r--r--tests/unit/unittest/data/complete_extractor_enumeration.cpp22
-rw-r--r--tests/unit/unittest/data/complete_extractor_function.cpp22
-rw-r--r--tests/unit/unittest/data/complete_extractor_function_unsaved.cpp22
-rw-r--r--tests/unit/unittest/data/complete_extractor_function_unsaved_2.cpp22
-rw-r--r--tests/unit/unittest/data/complete_extractor_functionoverload.cpp9
-rw-r--r--tests/unit/unittest/data/complete_extractor_namespace.cpp22
-rw-r--r--tests/unit/unittest/data/complete_extractor_private_function_definition.cpp5
-rw-r--r--tests/unit/unittest/data/complete_extractor_variable.cpp36
-rw-r--r--tests/unit/unittest/data/complete_forwarding_header_1.h3
-rw-r--r--tests/unit/unittest/data/complete_forwarding_header_2.h3
-rw-r--r--tests/unit/unittest/data/complete_smartpointer.cpp63
-rw-r--r--tests/unit/unittest/data/complete_target_header.h3
-rw-r--r--tests/unit/unittest/data/complete_target_header_changed.h4
-rw-r--r--tests/unit/unittest/data/complete_target_header_unsaved.h4
-rw-r--r--tests/unit/unittest/data/complete_testfile_1.cpp45
-rw-r--r--tests/unit/unittest/data/complete_translationunit_parse_error.cpp2
-rw-r--r--tests/unit/unittest/data/complete_withDotArrowCorrectionForForwardDeclaredClassPointer.cpp6
-rw-r--r--tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer.cpp6
-rw-r--r--tests/unit/unittest/data/complete_withDotArrowCorrectionForPointerInitial.cpp6
-rw-r--r--tests/unit/unittest/data/complete_withDotArrowCorrectionForPointerUpdated.cpp6
-rw-r--r--tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer_afterTyping.cpp6
-rw-r--r--tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer_beforeTyping.cpp6
-rw-r--r--tests/unit/unittest/data/complete_withGlobalCompletionAfterForwardDeclaredClassPointer.cpp7
-rw-r--r--tests/unit/unittest/data/complete_withNoDotArrowCorrectionForArrowDot.cpp7
-rw-r--r--tests/unit/unittest/data/complete_withNoDotArrowCorrectionForColonColon.cpp1
-rw-r--r--tests/unit/unittest/data/complete_withNoDotArrowCorrectionForDotDot.cpp7
-rw-r--r--tests/unit/unittest/data/complete_withNoDotArrowCorrectionForFloat.cpp4
-rw-r--r--tests/unit/unittest/data/complete_withNoDotArrowCorrectionForObject.cpp6
-rw-r--r--tests/unit/unittest/data/complete_withNoDotArrowCorrectionForObjectWithArrowOperator.cpp9
-rw-r--r--tests/unit/unittest/data/complete_withNoDotArrowCorrectionForOnlyDot.cpp7
-rw-r--r--tests/unit/unittest/data/completions_order.cpp41
-rw-r--r--tests/unit/unittest/data/cursor.cpp147
-rw-r--r--tests/unit/unittest/data/cursor.h44
-rw-r--r--tests/unit/unittest/data/diagnostic_diagnostic.cpp8
-rw-r--r--tests/unit/unittest/data/diagnostic_diagnosticset.cpp5
-rw-r--r--tests/unit/unittest/data/diagnostic_diagnosticset_header.cpp2
-rw-r--r--tests/unit/unittest/data/diagnostic_diagnosticset_mainfile.cpp4
-rw-r--r--tests/unit/unittest/data/diagnostic_erroneous_header.h11
-rw-r--r--tests/unit/unittest/data/diagnostic_erroneous_source.cpp24
-rw-r--r--tests/unit/unittest/data/diagnostic_source_location.cpp9
-rw-r--r--tests/unit/unittest/data/diagnostic_source_range.cpp13
-rw-r--r--tests/unit/unittest/data/empty1.cpp0
-rw-r--r--tests/unit/unittest/data/empty2.cpp0
-rw-r--r--tests/unit/unittest/data/empty3.cpp0
-rw-r--r--tests/unit/unittest/data/followsymbol_header.h59
-rw-r--r--tests/unit/unittest/data/followsymbol_main.cpp95
-rw-r--r--tests/unit/unittest/data/highlightingmarks.cpp811
-rw-r--r--tests/unit/unittest/data/highlightingmarks.h0
-rw-r--r--tests/unit/unittest/data/include_testfile.cpp27
-rw-r--r--tests/unit/unittest/data/references.cpp174
-rw-r--r--tests/unit/unittest/data/skippedsourceranges.cpp19
-rw-r--r--tests/unit/unittest/data/token.cpp3
-rw-r--r--tests/unit/unittest/data/tooltipinfo.cpp212
-rw-r--r--tests/unit/unittest/data/tooltipinfo.h3
-rw-r--r--tests/unit/unittest/data/translationunits.cpp8
-rw-r--r--tests/unit/unittest/data/translationunits.h3
-rw-r--r--tests/unit/unittest/data/uicmain.cpp3
-rw-r--r--tests/unit/unittest/diagnostic-test.cpp206
-rw-r--r--tests/unit/unittest/diagnosticcontainer-matcher.h55
-rw-r--r--tests/unit/unittest/diagnosticset-test.cpp199
-rw-r--r--tests/unit/unittest/dummyclangipcclient.h42
-rw-r--r--tests/unit/unittest/filesystem-utilities.h62
-rw-r--r--tests/unit/unittest/fixit-test.cpp134
-rw-r--r--tests/unit/unittest/googletest.h3
-rw-r--r--tests/unit/unittest/gtest-clang-printing.cpp87
-rw-r--r--tests/unit/unittest/gtest-clang-printing.h45
-rw-r--r--tests/unit/unittest/gtest-creator-printing.cpp496
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h92
-rw-r--r--tests/unit/unittest/highlightingresultreporter-test.cpp164
-rw-r--r--tests/unit/unittest/lineprefixer-test.cpp135
-rw-r--r--tests/unit/unittest/mockclangcodemodelclient.h50
-rw-r--r--tests/unit/unittest/mockclangcodemodelserver.h62
-rw-r--r--tests/unit/unittest/mockqueue.h37
-rw-r--r--tests/unit/unittest/readandwritemessageblock-test.cpp337
-rw-r--r--tests/unit/unittest/readexporteddiagnostics-test.cpp350
-rw-r--r--tests/unit/unittest/rundocumentparse-utility.h40
-rw-r--r--tests/unit/unittest/skippedsourceranges-test.cpp174
-rw-r--r--tests/unit/unittest/sourcelocation-test.cpp143
-rw-r--r--tests/unit/unittest/sourcerange-test.cpp170
-rw-r--r--tests/unit/unittest/sourcerangecontainer-matcher.h67
-rw-r--r--tests/unit/unittest/sqlitedatabase-test.cpp1
-rw-r--r--tests/unit/unittest/token-test.cpp143
-rw-r--r--tests/unit/unittest/tokenprocessor-test.cpp1871
-rw-r--r--tests/unit/unittest/translationunitupdater-test.cpp148
-rw-r--r--tests/unit/unittest/unittest-utility-functions.h9
-rw-r--r--tests/unit/unittest/unittest.qbs329
-rw-r--r--tests/unit/unittest/unsavedfile-test.cpp234
-rw-r--r--tests/unit/unittest/unsavedfiles-test.cpp192
-rw-r--r--tests/unit/unittest/utf8-test.cpp282
-rw-r--r--tests/unit/unittest/utf8positionfromlinecolumn-test.cpp163
3197 files changed, 83703 insertions, 98860 deletions
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000000..277028cbb2d
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,7 @@
+Thank you for contributing to Qt Creator! Unfortunately the GitHub Qt Creator
+presence is only a git mirror.
+
+Please submit your patch via gerrit:
+https://wiki.qt.io/Qt_Creator#Setting_up_Gerrit_to_contribute_back_to_Qt_Creator
+
+We are sorry for the inconvenience.
diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml
index ab0cbacd8b1..e65a45b87a6 100644
--- a/.github/workflows/build_cmake.yml
+++ b/.github/workflows/build_cmake.yml
@@ -7,7 +7,7 @@ on:
- 'doc/**'
env:
- QT_VERSION: 6.2.3
+ QT_VERSION: 6.3.1
CLANG_VERSION: 14.0.3
ELFUTILS_VERSION: 0.175
CMAKE_VERSION: 3.21.1
@@ -25,10 +25,10 @@ jobs:
matrix:
config:
- {
- name: "Windows MSVC 2019", artifact: "Windows-MSVC",
- os: windows-2019,
+ name: "Windows Latest MSVC", artifact: "Windows-MSVC",
+ os: windows-latest,
cc: "cl", cxx: "cl",
- environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
+ environment_script: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
is_msvc: true
}
- {
@@ -121,7 +121,10 @@ jobs:
COMMAND sudo apt update
)
execute_process(
- COMMAND sudo apt install libgl1-mesa-dev libvulkan-dev libxcb-xinput-dev libxcb-xinerama0-dev libxkbcommon-dev libxkbcommon-x11-dev
+ COMMAND
+ sudo apt install libgl1-mesa-dev libvulkan-dev libxcb-xinput-dev libxcb-xinerama0-dev libxkbcommon-dev libxkbcommon-x11-dev
+ libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xkb1 libxcb-randr0 libxcb-icccm4
+ xvfb
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
@@ -129,6 +132,18 @@ jobs:
endif()
endif()
+ if ("${{ runner.os }}" STREQUAL "Windows")
+ file(MAKE_DIRECTORY build/build/bin)
+ foreach(retry RANGE 10)
+ file(DOWNLOAD "https://download.qt.io/development_releases/prebuilt/llvmpipe/windows/opengl32sw-64.7z" ./opengl32sw-64.7z SHOW_PROGRESS)
+ file(SIZE ./opengl32sw-64.7z fileSize)
+ if (fileSize GREATER 0)
+ break()
+ endif()
+ endforeach()
+ execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ../../../opengl32sw-64.7z WORKING_DIRECTORY build/build/bin)
+ endif()
+
if (NOT "x${{ matrix.config.toolchain }}" STREQUAL "x")
foreach(retry RANGE 10)
file(DOWNLOAD "${{ matrix.config.toolchain }}" ./toolchain.7z SHOW_PROGRESS)
@@ -140,6 +155,12 @@ jobs:
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./toolchain.7z)
endif()
+ # For tests update the docker image
+ find_program(docker_executable docker)
+ if (docker_executable)
+ execute_process(COMMAND ${docker_executable} pull alpine:latest COMMAND_ECHO STDOUT)
+ endif()
+
- name: Download Qt
id: qt
shell: cmake -P {0}
@@ -585,7 +606,6 @@ jobs:
execute_process(COMMAND ccache -s)
- name: Run tests
- if: matrix.config.artifact == 'running-of-tests-is-disabled'
shell: cmake -P {0}
run: |
include(ProcessorCount)
@@ -594,11 +614,16 @@ jobs:
set(ENV{CTEST_OUTPUT_ON_FAILURE} "ON")
if ("${{ runner.os }}" STREQUAL "Linux")
- set(ENV{QT_QPA_PLATFORM} "offscreen")
+ set(ENV{DISPLAY} ":1")
+ set(ENV{LIBGL_ALWAYS_SOFTWARE} "1")
+ set(ctest_launcher xvfb-run --auto-servernum --server-num=1)
+ elseif ("${{ runner.os }}" STREQUAL "Windows")
+ set(ENV{QT_OPENGL} "software")
+ set(ENV{QT_ASSUME_STDERR_HAS_CONSOLE} "1")
endif()
execute_process(
- COMMAND ctest -j ${N} --timeout 5
+ COMMAND ${ctest_launcher} ctest -j ${N} --timeout 300 --label-exclude exclude_from_precheck --exclude-regex tst_perfdata
WORKING_DIRECTORY build/build
RESULT_VARIABLE result
OUTPUT_VARIABLE output
diff --git a/.gitignore b/.gitignore
index 0bfdb066a7e..de76458a885 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@ tags
ui_*.h
wrapper.bat
wrapper.sh
+debug_toolchain.cmake
# qtcreator generated files
*.creator.user*
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aec846721de..0b9672c0a81 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,8 +2,12 @@ cmake_minimum_required(VERSION 3.16)
## Add paths to check for cmake modules:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+include(Utils)
-option(BUILD_WITH_PCH "Build with precompiled headers" ON)
+env_with_default("QTC_BUILD_WITH_PCH" ENV_QTC_BUILD_WITH_PCH ON)
+env_with_default("QTC_WITH_TESTS" ENV_QTC_WITH_TESTS OFF)
+
+option(BUILD_WITH_PCH "Build with precompiled headers" "${ENV_QTC_BUILD_WITH_PCH}")
include(FeatureSummary)
include(QtCreatorIDEBranding RESULT_VARIABLE IDE_BRANDING_FILE)
@@ -24,12 +28,12 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
-qtc_handle_sccache_support()
+qtc_handle_compiler_cache_support()
option(BUILD_LINK_WITH_QT "Link with Qt from the parent Qt Creator" OFF)
qtc_link_with_qt()
-option(WITH_TESTS "Build Tests" OFF)
+option(WITH_TESTS "Build Tests" ${ENV_QTC_WITH_TESTS})
add_feature_info("Build tests" ${WITH_TESTS} "")
option(WITH_DEBUG_CMAKE "Enabled CMake project debugging functionality" OFF)
option(SHOW_BUILD_DATE "Show build date in about dialog" OFF)
@@ -53,6 +57,14 @@ if (WITH_TESTS)
set(IMPLICIT_DEPENDS Qt5::Test)
endif()
+# suppress bogus warning
+# warning C4573 requires the compiler to capture 'this' but the current default capture mode does not allow it
+# when using QObject::connect in lambda without capturing 'this' - which would lead to warnings
+# with other compilers
+if(MSVC)
+ add_compile_options(/wd4573)
+endif()
+
find_package(Qt5
${IDE_QT_VERSION_MIN}
COMPONENTS Concurrent Core Gui Network PrintSupport Qml Sql Widgets Xml Core5Compat ${QT_TEST_COMPONENT}
@@ -76,6 +88,10 @@ else()
# This includes the code that will enable higher compiler warnings level (/W3 for MSVC, -Wall -Wextra for GCC)
# This is controlled by QT_COMPILE_OPTIONS_DISABLE_WARNINGS target property.
include(QtCompilerFlags)
+
+ if (MSVC AND QT_FEATURE_static_runtime)
+ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
+ endif()
endif()
find_package(Qt5 COMPONENTS LinguistTools QUIET)
find_package(Qt5 COMPONENTS Quick QuickWidgets Designer DesignerComponents Help SerialPort Svg Tools QUIET)
diff --git a/README.md b/README.md
index 55ce5919e68..86d4c43f65f 100644
--- a/README.md
+++ b/README.md
@@ -43,10 +43,10 @@ Prerequisites:
* Debugging Tools for Windows (optional, for MSVC debugging support with CDB)
* On Mac OS X: latest Xcode
* On Linux: GCC 7 or later
-* LLVM/Clang 10 or later (optional, LLVM/Clang 13 is recommended.
+* LLVM/Clang 10 or later (optional, LLVM/Clang 14 is recommended.
See [instructions](#getting-llvmclang-for-the-clang-code-model) on how to
get LLVM.
- The ClangFormat, ClangPchManager and ClangRefactoring use the LLVM C++ API.
+ The ClangFormat plugin uses the LLVM C++ API.
Since the LLVM C++ API provides no compatibility guarantee,
if later versions don't compile we don't support that version.)
* CMake
@@ -147,10 +147,20 @@ like Qt and LLVM, additionally run
cmake --install . --prefix /path/to/qtcreator_install --component Dependencies
+### Performance Analyzer
+
+If you have not installed Qt with the Maintenance Tool, you must
+either set the path to the `perfparser` executable as a value of
+the `PERFPROFILER_PARSER_FILEPATH` environment variable or copy
+the executable to from the Qt Creator installation directory to
+the build directory. That is, copy it from
+`/path/to/qtcreator_install/Tools/QtCreator/libexec/qtcreator/` to
+/path/to/qtcreator_buid/libexec/qtcreator/`.
+
## Getting LLVM/Clang for the Clang Code Model
-The Clang Code Model depends on the LLVM/Clang libraries. The currently
-recommended LLVM/Clang version is 13.0.
+The Clang code model uses `Clangd` and the ClangFormat plugin depends on the
+LLVM/Clang libraries. The currently recommended LLVM/Clang version is 14.0.
### Prebuilt LLVM/Clang packages
diff --git a/cmake/FindClang.cmake b/cmake/FindClang.cmake
index 1133558dc76..a62ebb5ba4b 100644
--- a/cmake/FindClang.cmake
+++ b/cmake/FindClang.cmake
@@ -1,21 +1,12 @@
find_package(Clang CONFIG)
-# silence a lot of warnings from building against llvm
-if(MSVC AND TARGET libclang)
- target_compile_options(libclang INTERFACE /wd4267)
-endif()
-
option(CLANGTOOLING_LINK_CLANG_DYLIB "Force linking of Clang tooling against clang-cpp" NO)
-if (TARGET clangTooling AND NOT CLANGTOOLING_LINK_CLANG_DYLIB)
- set(CLANG_TOOLING_LIBS libclang clangTooling clangQuery clangIndex)
- set(CLANG_FORMAT_LIB clangFormat)
-elseif (TARGET clang-cpp)
- set(CLANG_TOOLING_LIBS libclang clang-cpp)
+set(CLANG_FORMAT_LIB clangFormat)
+if (TARGET clang-cpp AND CLANGTOOLING_LINK_CLANG_DYLIB)
set(CLANG_FORMAT_LIB clang-cpp)
endif()
-
if (WIN32 AND TARGET clangTooling)
# check that we can compile against clangTooling
# which requires the build modes to be compatible
diff --git a/cmake/FindQt5.cmake b/cmake/FindQt5.cmake
index a48e293e416..fc16ec17237 100644
--- a/cmake/FindQt5.cmake
+++ b/cmake/FindQt5.cmake
@@ -61,11 +61,15 @@ set(__additional_imported_components ATSPI2_nolink) # Work around QTBUG-97023
foreach(comp IN LISTS Qt5_FIND_COMPONENTS __additional_imported_components)
if(TARGET Qt6::${comp})
if (NOT TARGET Qt5::${comp})
- set_property(TARGET Qt6::${comp} PROPERTY IMPORTED_GLOBAL TRUE)
+ if (NOT QT_FEATURE_static)
+ set_property(TARGET Qt6::${comp} PROPERTY IMPORTED_GLOBAL TRUE)
+ endif()
add_library(Qt5::${comp} ALIAS Qt6::${comp})
endif()
if (TARGET Qt6::${comp}Private AND NOT TARGET Qt5::${comp}Private)
- set_property(TARGET Qt6::${comp}Private PROPERTY IMPORTED_GLOBAL TRUE)
+ if (NOT QT_FEATURE_static)
+ set_property(TARGET Qt6::${comp}Private PROPERTY IMPORTED_GLOBAL TRUE)
+ endif()
add_library(Qt5::${comp}Private ALIAS Qt6::${comp}Private)
endif()
endif()
diff --git a/cmake/Findyaml-cpp.cmake b/cmake/Findyaml-cpp.cmake
index 9325e891b70..e6b65053bfe 100644
--- a/cmake/Findyaml-cpp.cmake
+++ b/cmake/Findyaml-cpp.cmake
@@ -22,9 +22,7 @@ else()
endif()
set(YAML_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../src/libs/3rdparty/yaml-cpp)
add_qtc_library(yaml-cpp
- DEFINES YAML_CPP_DLL yaml_cpp_EXPORTS
INCLUDES ${YAML_SOURCE_DIR}/include
- PUBLIC_DEFINES YAML_CPP_DLL
PUBLIC_INCLUDES ${YAML_SOURCE_DIR}/include
PROPERTIES AUTOMOC OFF AUTOUIC OFF
SOURCES
@@ -116,6 +114,12 @@ else()
${YAML_SOURCE_DIR}/src/tag.h
${YAML_SOURCE_DIR}/src/token.h
)
+ if (NOT QTC_STATIC_BUILD)
+ extend_qtc_target(yaml-cpp
+ DEFINES yaml_cpp_EXPORTS
+ PUBLIC_DEFINES YAML_CPP_DLL)
+ endif()
+
if(TARGET yaml-cpp)
set(yaml-cpp_FOUND 1)
set_package_properties(yaml-cpp PROPERTIES DESCRIPTION "using internal src/libs/3rdparty/yaml-cpp")
diff --git a/cmake/QtCreatorAPI.cmake b/cmake/QtCreatorAPI.cmake
index 9e26402b6b0..257d351426b 100644
--- a/cmake/QtCreatorAPI.cmake
+++ b/cmake/QtCreatorAPI.cmake
@@ -43,6 +43,8 @@ option(BUILD_LIBRARIES_BY_DEFAULT "Build libraries by default. This can be used
option(BUILD_TESTS_BY_DEFAULT "Build tests by default. This can be used to build all tests by default, or none." ON)
option(QTC_SEPARATE_DEBUG_INFO "Extract debug information from binary files." OFF)
option(WITH_SCCACHE_SUPPORT "Enables support for building with SCCACHE and separate debug info with MSVC, which SCCACHE normally doesn't support." OFF)
+option(WITH_CCACHE_SUPPORT "Enables support for building with CCACHE and separate debug info with MSVC, which CCACHE normally doesn't support." OFF)
+option(QTC_STATIC_BUILD "Builds libraries and plugins as static libraries" OFF)
# If we provide a list of plugins, executables, libraries, then the BUILD_<type>_BY_DEFAULT will be set to OFF
# and for every element we set BUILD_<type>_<elment> to ON
@@ -110,7 +112,7 @@ function(qtc_source_dir varName)
endfunction()
function(add_qtc_library name)
- cmake_parse_arguments(_arg "STATIC;OBJECT;SKIP_TRANSLATION;ALLOW_ASCII_CASTS;FEATURE_INFO;SKIP_PCH"
+ cmake_parse_arguments(_arg "STATIC;OBJECT;SHARED;SKIP_TRANSLATION;ALLOW_ASCII_CASTS;FEATURE_INFO;SKIP_PCH"
"DESTINATION;COMPONENT;SOURCES_PREFIX;BUILD_DEFAULT"
"CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PROPERTIES" ${ARGN}
)
@@ -156,7 +158,7 @@ function(add_qtc_library name)
endif()
set(library_type SHARED)
- if (_arg_STATIC)
+ if (_arg_STATIC OR (QTC_STATIC_BUILD AND NOT _arg_SHARED))
set(library_type STATIC)
endif()
if (_arg_OBJECT)
@@ -167,7 +169,12 @@ function(add_qtc_library name)
add_library(QtCreator::${name} ALIAS ${name})
if (${name} MATCHES "^[^0-9-]+$")
- string(TOUPPER "${name}_LIBRARY" EXPORT_SYMBOL)
+ if (QTC_STATIC_BUILD)
+ set(export_symbol_suffix "STATIC_LIBRARY")
+ else()
+ set(export_symbol_suffix "LIBRARY")
+ endif()
+ string(TOUPPER "${name}_${export_symbol_suffix}" EXPORT_SYMBOL)
endif()
if (WITH_TESTS)
@@ -184,7 +191,7 @@ function(add_qtc_library name)
SOURCES ${_arg_SOURCES}
INCLUDES ${_arg_INCLUDES}
PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES}
- DEFINES ${EXPORT_SYMBOL} ${default_defines_copy} ${_arg_DEFINES} ${TEST_DEFINES}
+ DEFINES ${default_defines_copy} ${_arg_DEFINES} ${TEST_DEFINES}
PUBLIC_DEFINES ${_arg_PUBLIC_DEFINES}
DEPENDS ${_arg_DEPENDS} ${IMPLICIT_DEPENDS}
PUBLIC_DEPENDS ${_arg_PUBLIC_DEPENDS}
@@ -193,6 +200,12 @@ function(add_qtc_library name)
EXTRA_TRANSLATIONS ${_arg_EXTRA_TRANSLATIONS}
)
+ if (QTC_STATIC_BUILD)
+ extend_qtc_target(${name} PUBLIC_DEFINES ${EXPORT_SYMBOL})
+ else()
+ extend_qtc_target(${name} DEFINES ${EXPORT_SYMBOL})
+ endif()
+
# everything is different with SOURCES_PREFIX
if (NOT _arg_SOURCES_PREFIX)
get_filename_component(public_build_interface_dir "${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE)
@@ -244,6 +257,7 @@ function(add_qtc_library name)
unset(NAMELINK_OPTION)
if (library_type STREQUAL "SHARED")
set(NAMELINK_OPTION NAMELINK_SKIP)
+ qtc_add_link_flags_no_undefined(${name})
endif()
unset(COMPONENT_OPTION)
@@ -251,25 +265,27 @@ function(add_qtc_library name)
set(COMPONENT_OPTION "COMPONENT" "${_arg_COMPONENT}")
endif()
- install(TARGETS ${name}
- EXPORT QtCreator
- RUNTIME
- DESTINATION "${_DESTINATION}"
- ${COMPONENT_OPTION}
- OPTIONAL
- LIBRARY
- DESTINATION "${IDE_LIBRARY_PATH}"
- ${NAMELINK_OPTION}
- ${COMPONENT_OPTION}
- OPTIONAL
- OBJECTS
- DESTINATION "${IDE_LIBRARY_PATH}"
- COMPONENT Devel EXCLUDE_FROM_ALL
- ARCHIVE
- DESTINATION "${IDE_LIBRARY_ARCHIVE_PATH}"
- COMPONENT Devel EXCLUDE_FROM_ALL
- OPTIONAL
- )
+ if (NOT QTC_STATIC_BUILD OR _arg_SHARED)
+ install(TARGETS ${name}
+ EXPORT QtCreator
+ RUNTIME
+ DESTINATION "${_DESTINATION}"
+ ${COMPONENT_OPTION}
+ OPTIONAL
+ LIBRARY
+ DESTINATION "${IDE_LIBRARY_PATH}"
+ ${NAMELINK_OPTION}
+ ${COMPONENT_OPTION}
+ OPTIONAL
+ OBJECTS
+ DESTINATION "${IDE_LIBRARY_PATH}"
+ COMPONENT Devel EXCLUDE_FROM_ALL
+ ARCHIVE
+ DESTINATION "${IDE_LIBRARY_ARCHIVE_PATH}"
+ COMPONENT Devel EXCLUDE_FROM_ALL
+ OPTIONAL
+ )
+ endif()
qtc_enable_separate_debug_info(${name} "${IDE_LIBRARY_PATH}")
@@ -277,7 +293,7 @@ function(add_qtc_library name)
qtc_enable_sanitize(${SANITIZE_FLAGS})
endif()
- if (NAMELINK_OPTION)
+ if (NAMELINK_OPTION AND NOT QTC_STATIC_BUILD)
install(TARGETS ${name}
LIBRARY
DESTINATION "${IDE_LIBRARY_PATH}"
@@ -296,7 +312,7 @@ endfunction(add_qtc_library)
function(add_qtc_plugin target_name)
cmake_parse_arguments(_arg
"SKIP_INSTALL;INTERNAL_ONLY;SKIP_TRANSLATION;EXPORT;SKIP_PCH"
- "VERSION;COMPAT_VERSION;PLUGIN_JSON_IN;PLUGIN_PATH;PLUGIN_NAME;OUTPUT_NAME;BUILD_DEFAULT"
+ "VERSION;COMPAT_VERSION;PLUGIN_JSON_IN;PLUGIN_PATH;PLUGIN_NAME;OUTPUT_NAME;BUILD_DEFAULT;PLUGIN_CLASS"
"CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PLUGIN_DEPENDS;PLUGIN_RECOMMENDS;PLUGIN_TEST_DEPENDS;PROPERTIES"
${ARGN}
)
@@ -419,13 +435,25 @@ function(add_qtc_plugin target_name)
CONTENT "${plugin_json}")
endif()
- add_library(${target_name} SHARED ${_arg_SOURCES})
+ if (QTC_STATIC_BUILD)
+ set(library_type STATIC)
+ else()
+ set(library_type SHARED)
+ endif()
+
+ add_library(${target_name} ${library_type} ${_arg_SOURCES})
add_library(QtCreator::${target_name} ALIAS ${target_name})
set_public_headers(${target_name} "${_arg_SOURCES}")
+ update_resource_files_list("${_arg_SOURCES}")
### Generate EXPORT_SYMBOL
- string(TOUPPER "${name}_LIBRARY" EXPORT_SYMBOL)
+ if (QTC_STATIC_BUILD)
+ set(export_symbol_suffix "STATIC_LIBRARY")
+ else()
+ set(export_symbol_suffix "LIBRARY")
+ endif()
+ string(TOUPPER "${name}_${export_symbol_suffix}" EXPORT_SYMBOL)
if (WITH_TESTS)
set(TEST_DEFINES WITH_TESTS SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
@@ -438,7 +466,7 @@ function(add_qtc_plugin target_name)
extend_qtc_target(${target_name}
INCLUDES ${_arg_INCLUDES}
PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES}
- DEFINES ${EXPORT_SYMBOL} ${DEFAULT_DEFINES} ${_arg_DEFINES} ${TEST_DEFINES}
+ DEFINES ${DEFAULT_DEFINES} ${_arg_DEFINES} ${TEST_DEFINES}
PUBLIC_DEFINES ${_arg_PUBLIC_DEFINES}
DEPENDS ${_arg_DEPENDS} ${_DEP_PLUGINS} ${IMPLICIT_DEPENDS}
PUBLIC_DEPENDS ${_arg_PUBLIC_DEPENDS}
@@ -447,6 +475,13 @@ function(add_qtc_plugin target_name)
EXTRA_TRANSLATIONS ${_arg_EXTRA_TRANSLATIONS}
)
+ if (QTC_STATIC_BUILD)
+ extend_qtc_target(${target_name} PUBLIC_DEFINES ${EXPORT_SYMBOL}
+ DEFINES QT_STATICPLUGIN)
+ else()
+ extend_qtc_target(${target_name} DEFINES ${EXPORT_SYMBOL})
+ endif()
+
get_filename_component(public_build_interface_dir "${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE)
file(RELATIVE_PATH include_dir_relative_path ${PROJECT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(${target_name}
@@ -469,6 +504,10 @@ function(add_qtc_plugin target_name)
set(skip_translation ON)
endif()
+ if(NOT _arg_PLUGIN_CLASS)
+ set(_arg_PLUGIN_CLASS ${target_name}Plugin)
+ endif()
+
qtc_output_binary_dir(_output_binary_dir)
set_target_properties(${target_name} PROPERTIES
LINK_DEPENDS_NO_SHARED ON
@@ -488,6 +527,7 @@ function(add_qtc_plugin target_name)
OUTPUT_NAME "${name}"
QT_SKIP_TRANSLATION "${skip_translation}"
QT_COMPILE_OPTIONS_DISABLE_WARNINGS OFF
+ QTC_PLUGIN_CLASS_NAME ${_arg_PLUGIN_CLASS}
${_arg_PROPERTIES}
)
@@ -495,7 +535,7 @@ function(add_qtc_plugin target_name)
enable_pch(${target_name})
endif()
- if (NOT _arg_SKIP_INSTALL)
+ if (NOT _arg_SKIP_INSTALL AND NOT QTC_STATIC_BUILD)
if (_arg_EXPORT)
set(export QtCreator${target_name})
else()
@@ -767,10 +807,10 @@ function(extend_qtc_executable name)
endfunction()
function(add_qtc_test name)
- cmake_parse_arguments(_arg "GTEST;MANUALTEST" "TIMEOUT"
+ cmake_parse_arguments(_arg "GTEST;MANUALTEST;EXCLUDE_FROM_PRECHECK" "TIMEOUT"
"DEFINES;DEPENDS;INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;SKIP_PCH;CONDITION" ${ARGN})
- if ($_arg_UNPARSED_ARGUMENTS)
+ if (${_arg_UNPARSED_ARGUMENTS})
message(FATAL_ERROR "add_qtc_test had unparsed arguments!")
endif()
@@ -792,7 +832,7 @@ function(add_qtc_test name)
endif()
foreach(dependency ${_arg_DEPENDS})
- if (NOT TARGET ${dependency} AND NOT _arg_GTEST)
+ if (NOT TARGET ${dependency})
if (WITH_DEBUG_CMAKE)
message(STATUS "'${dependency}' is not a target")
endif()
@@ -831,6 +871,9 @@ function(add_qtc_test name)
if (NOT _arg_GTEST AND NOT _arg_MANUALTEST)
add_test(NAME ${name} COMMAND ${name})
+ if (_arg_EXCLUDE_FROM_PRECHECK)
+ set_tests_properties(${name} PROPERTIES LABELS exclude_from_precheck)
+ endif()
if (DEFINED _arg_TIMEOUT)
set(timeout_option TIMEOUT ${_arg_TIMEOUT})
else()
@@ -840,17 +883,32 @@ function(add_qtc_test name)
endif()
endfunction()
-function(finalize_qtc_gtest test_name exclude_sources_regex)
+function(finalize_qtc_gtest test_name)
if (NOT TARGET ${test_name})
return()
endif()
+
+ cmake_parse_arguments(_arg "EXCLUDE_ALL_FROM_PRECHECK" "EXCLUDE_SOURCES_REGEX"
+ "EXCLUDE_FROM_PRECHECK" ${ARGN})
+
+ if (${_arg_UNPARSED_ARGUMENTS})
+ message(FATAL_ERROR "finalize_qtc_gtest had unparsed arguments!")
+ endif()
+
get_target_property(test_sources ${test_name} SOURCES)
- if (exclude_sources_regex)
- list(FILTER test_sources EXCLUDE REGEX "${exclude_sources_regex}")
+ if (_arg_EXCLUDE_SOURCES_REGEX)
+ list(FILTER test_sources EXCLUDE REGEX "${_arg_EXCLUDE_SOURCES_REGEX}")
endif()
include(GoogleTest)
gtest_add_tests(TARGET ${test_name} SOURCES ${test_sources} TEST_LIST test_list SKIP_DEPENDENCY)
+ if(_arg_EXCLUDE_ALL_FROM_PRECHECK)
+ set_tests_properties(${test_list}
+ PROPERTIES LABELS exclude_from_precheck)
+ elseif(_arg_EXCLUDE_FROM_PRECHECK)
+ set_tests_properties(${_arg_EXCLUDE_FROM_PRECHECK}
+ PROPERTIES LABELS exclude_from_precheck)
+ endif()
foreach(test IN LISTS test_list)
finalize_test_setup(${test})
endforeach()
diff --git a/cmake/QtCreatorAPIInternal.cmake b/cmake/QtCreatorAPIInternal.cmake
index 53522ee5f70..359fed79398 100644
--- a/cmake/QtCreatorAPIInternal.cmake
+++ b/cmake/QtCreatorAPIInternal.cmake
@@ -4,6 +4,10 @@ if (CMAKE_VERSION VERSION_LESS 3.18)
endif()
endif()
+if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
+ include(CheckLinkerFlag)
+endif()
+
include(FeatureSummary)
#
@@ -105,6 +109,7 @@ set(__QTC_PLUGINS "" CACHE INTERNAL "*** Internal ***")
set(__QTC_LIBRARIES "" CACHE INTERNAL "*** Internal ***")
set(__QTC_EXECUTABLES "" CACHE INTERNAL "*** Internal ***")
set(__QTC_TESTS "" CACHE INTERNAL "*** Internal ***")
+set(__QTC_RESOURCE_FILES "" CACHE INTERNAL "*** Internal ***")
# handle SCCACHE hack
# SCCACHE does not work with the /Zi option, which makes each compilation write debug info
@@ -113,15 +118,24 @@ set(__QTC_TESTS "" CACHE INTERNAL "*** Internal ***")
# This increases memory usage, disk space usage and linking time, so should only be
# enabled if necessary.
# Must be called after project(...).
-function(qtc_handle_sccache_support)
- if (MSVC AND WITH_SCCACHE_SUPPORT)
- foreach(config DEBUG RELWITHDEBINFO)
- foreach(lang C CXX)
- set(flags_var "CMAKE_${lang}_FLAGS_${config}")
- string(REPLACE "/Zi" "/Z7" ${flags_var} "${${flags_var}}")
- set(${flags_var} "${${flags_var}}" PARENT_SCOPE)
+function(qtc_handle_compiler_cache_support)
+ if (WITH_SCCACHE_SUPPORT OR WITH_CCACHE_SUPPORT)
+ if (MSVC)
+ foreach(config DEBUG RELWITHDEBINFO)
+ foreach(lang C CXX)
+ set(flags_var "CMAKE_${lang}_FLAGS_${config}")
+ string(REPLACE "/Zi" "/Z7" ${flags_var} "${${flags_var}}")
+ set(${flags_var} "${${flags_var}}" PARENT_SCOPE)
+ endforeach()
endforeach()
- endforeach()
+ endif()
+ endif()
+ if (WITH_CCACHE_SUPPORT)
+ find_program(CCACHE_PROGRAM ccache)
+ if(CCACHE_PROGRAM)
+ set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" CACHE STRING "CXX compiler launcher" FORCE)
+ set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" CACHE STRING "C compiler launcher" FORCE)
+ endif()
endif()
endfunction()
@@ -161,6 +175,22 @@ function(qtc_enable_sanitize _sanitize_flags)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" PARENT_SCOPE)
endfunction()
+function(qtc_add_link_flags_no_undefined target)
+ # needs CheckLinkerFlags
+ if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
+ set(no_undefined_flag "-Wl,--no-undefined")
+ check_linker_flag(CXX ${no_undefined_flag} QTC_LINKER_SUPPORTS_NO_UNDEFINED)
+ if (NOT QTC_LINKER_SUPPORTS_NO_UNDEFINED)
+ set(no_undefined_flag "-Wl,-undefined,error")
+ check_linker_flag(CXX ${no_undefined_flag} QTC_LINKER_SUPPORTS_UNDEFINED_ERROR)
+ if (NOT QTC_LINKER_SUPPORTS_UNDEFINED_ERROR)
+ return()
+ endif()
+ endif()
+ target_link_options("${target}" PRIVATE "${no_undefined_flag}")
+ endif()
+endfunction()
+
function(append_extra_translations target_name)
if(NOT ARGN)
return()
@@ -201,6 +231,16 @@ function(set_public_headers target sources)
endforeach()
endfunction()
+function(update_resource_files_list sources)
+ foreach(source IN LISTS sources)
+ if (source MATCHES "\.qrc$")
+ get_filename_component(resource_name ${source} NAME_WE)
+ string(REPLACE "-" "_" resource_name ${resource_name})
+ update_cached_list(__QTC_RESOURCE_FILES "${resource_name}")
+ endif()
+ endforeach()
+endfunction()
+
function(set_public_includes target includes)
foreach(inc_dir IN LISTS includes)
if (NOT IS_ABSOLUTE ${inc_dir})
@@ -217,15 +257,15 @@ endfunction()
function(finalize_test_setup test_name)
cmake_parse_arguments(_arg "" "TIMEOUT" "" ${ARGN})
if (DEFINED _arg_TIMEOUT)
- set(timeout ${_arg_TIMEOUT})
+ set(timeout_arg TIMEOUT ${_arg_TIMEOUT})
else()
- set(timeout 5)
+ set(timeout_arg)
endif()
# Never translate tests:
set_tests_properties(${name}
PROPERTIES
QT_SKIP_TRANSLATION ON
- TIMEOUT ${timeout}
+ ${timeout_arg}
)
if (WIN32)
@@ -485,6 +525,7 @@ function(extend_qtc_target target_name)
endif()
set_public_headers(${target_name} "${_arg_SOURCES}")
+ update_resource_files_list("${_arg_SOURCES}")
foreach(file IN LISTS _arg_EXPLICIT_MOC)
set_explicit_moc(${target_name} "${file}")
diff --git a/cmake/QtCreatorIDEBranding.cmake b/cmake/QtCreatorIDEBranding.cmake
index 660159e7a7a..5f423dda8d0 100644
--- a/cmake/QtCreatorIDEBranding.cmake
+++ b/cmake/QtCreatorIDEBranding.cmake
@@ -1,6 +1,6 @@
-set(IDE_VERSION "7.0.3") # The IDE version.
-set(IDE_VERSION_COMPAT "7.0.0") # The IDE Compatibility version.
-set(IDE_VERSION_DISPLAY "7.0.3") # The IDE display version.
+set(IDE_VERSION "8.0.2") # The IDE version.
+set(IDE_VERSION_COMPAT "8.0.0") # The IDE Compatibility version.
+set(IDE_VERSION_DISPLAY "8.0.2") # The IDE display version.
set(IDE_COPYRIGHT_YEAR "2022") # The IDE current copyright year.
set(IDE_SETTINGSVARIANT "QtProject") # The IDE settings variation.
diff --git a/cmake/QtCreatorTranslations.cmake b/cmake/QtCreatorTranslations.cmake
index a9da1e52476..2e9c564b8ff 100644
--- a/cmake/QtCreatorTranslations.cmake
+++ b/cmake/QtCreatorTranslations.cmake
@@ -27,6 +27,7 @@ function(_extract_ts_data_from_targets outprefix)
set(_target_sources "")
if(_source_files)
+ list(FILTER _source_files EXCLUDE REGEX ".*[.]json[.]in|.*[.]svg")
list(APPEND _target_sources ${_source_files})
endif()
if(_extra_translations)
diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake
new file mode 100644
index 00000000000..0b0670b267f
--- /dev/null
+++ b/cmake/Utils.cmake
@@ -0,0 +1,7 @@
+function (env_with_default envName varToSet default)
+ if(DEFINED ENV{${envName}})
+ set(${varToSet} $ENV{${envName}} PARENT_SCOPE)
+ else()
+ set(${varToSet} ${default} PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/coin/instructions/build.yaml b/coin/instructions/build.yaml
index 5f7c305ea44..de935a697c9 100644
--- a/coin/instructions/build.yaml
+++ b/coin/instructions/build.yaml
@@ -138,17 +138,8 @@ instructions:
property: target.arch
equals_value: X86
- - type: SignPackage
- directory: "{{.AgentWorkingDir}}/qt-creator/qt-creator_build/install/"
- maxTimeInSeconds: 1200
- maxTimeBetweenOutput: 1200
- enable_if:
- condition: property
- property: host.os
- equals_value: Windows
-
- type: UploadArtifact
- archiveDirectory: "{{.AgentWorkingDir}}/qt-creator/qt-creator_build/install/"
+ archiveDirectory: "{{.AgentWorkingDir}}/qt-creator/qt-creator_build/build"
transferType: UploadModuleBuildArtifact
maxTimeInSeconds: 1800
maxTimeBetweenOutput: 1800
diff --git a/coin/instructions/common_environment.yaml b/coin/instructions/common_environment.yaml
index bca60728d6e..8a3df309955 100644
--- a/coin/instructions/common_environment.yaml
+++ b/coin/instructions/common_environment.yaml
@@ -13,10 +13,10 @@ instructions:
instructions:
- type: EnvironmentVariable
variableName: QTC_QT_BASE_URL
- variableValue: "http://ci-files02-hki.intra.qt.io/packages/jenkins/archive/qt/6.2/6.2.4-final-released/Qt6.2.4"
+ variableValue: "http://ci-files02-hki.intra.qt.io/packages/jenkins/archive/qt/6.3/6.3.1-final-released/Qt6.3.1"
- type: EnvironmentVariable
variableName: QTC_QT_MODULES
- variableValue: "qt5compat qtbase qtdeclarative qtimageformats qtquick3d qtquickcontrols2 qtquicktimeline qtserialport qtshadertools qtsvg qttools qttranslations"
+ variableValue: "qt5compat qtbase qtdeclarative qtimageformats qtquick3d qtquickcontrols2 qtquicktimeline qtserialport qtshadertools qtsvg qttools qttranslations qtwebengine"
- type: EnvironmentVariable
variableName: MACOSX_DEPLOYMENT_TARGET
variableValue: 10.14
diff --git a/coin/instructions/provision.yaml b/coin/instructions/provision.yaml
index 5d0431a273b..302103ec3f6 100644
--- a/coin/instructions/provision.yaml
+++ b/coin/instructions/provision.yaml
@@ -32,6 +32,15 @@ instructions:
property: host.os
in_values: [MacOS, Linux, Windows]
- type: ExecuteCommand
+ command: "pip3 install wget colorlog"
+ maxTimeInSeconds: 1200
+ maxTimeBetweenOutput: 120
+ userMessageOnFailure: "Failed to install Python packages, check logs."
+ enable_if:
+ condition: property
+ property: host.os
+ in_values: [MacOS, Linux]
+ - type: ExecuteCommand
command: "python3 -u {{.AgentWorkingDir}}/build/qtsdk/packaging-tools/install_qt.py --qt-path {{.AgentWorkingDir}}/build/qt_install_dir --temp-path {{.AgentWorkingDir}}/build/qt_temp --base-url {{.Env.QTC_QT_BASE_URL}} --base-url-postfix={{.Env.QTC_QT_POSTFIX}} --icu7z http://master.qt.io/development_releases/prebuilt/icu/prebuilt/56.1/icu-linux-g++-Rhel7.2-x64.7z {{.Env.QTC_QT_MODULES}}"
executeCommandArgumentSplitingBehavior: SplitAfterVariableSubstitution
maxTimeInSeconds: 3600
@@ -52,10 +61,10 @@ instructions:
property: host.os
equals_value: MacOS
- type: ExecuteCommand
- command: "pip.exe install pywin32"
+ command: "pip.exe install pywin32 wget colorlog"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 120
- userMessageOnFailure: "Failed to install win32api, check logs."
+ userMessageOnFailure: "Failed to install Python packages, check logs."
enable_if:
condition: property
property: host.os
diff --git a/coin/instructions/test.yaml b/coin/instructions/test.yaml
new file mode 100644
index 00000000000..c66442585e4
--- /dev/null
+++ b/coin/instructions/test.yaml
@@ -0,0 +1,15 @@
+type: Group
+instructions:
+ - type: InstallBinaryArchive
+ relativeStoragePath: "{{.Env.MODULE_ARTIFACTS_RELATIVE_STORAGE_PATH}}/artifacts.tar.gz"
+ directory: "qt-creator/qt-creator_build/build"
+ maxTimeInSeconds: 1800
+ maxTimeBetweenOutput: 1800
+ userMessageOnFailure: "Failed to unarchive build artifacts, check logs"
+ - type: ChangeDirectory
+ directory: "{{.AgentWorkingDir}}/qt-creator/qt-creator_build/build"
+ - type: ExecuteCommand
+ command: "ctest -j 4 --timeout 60 --output-on-failure --label-exclude exclude_from_precheck --exclude-regex tst_perfdata"
+ maxTimeInSeconds: 600
+ maxTimeBetweenOutput: 600
+ userMessageOnFailure: "Failed to run tests, check logs"
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
index 163721ea254..96428853f26 100644
--- a/coin/module_config.yaml
+++ b/coin/module_config.yaml
@@ -63,13 +63,20 @@ make_instructions: &make_instructions
- !include "{{qt-creator/qt-creator}}/provision.yaml"
- !include "{{qt-creator/qt-creator}}/build.yaml"
+test_instructions: &test_instructions
+ type: Group
+ instructions:
+ - !include "{{qt-creator/qt-creator}}/provision.yaml"
+ - !include "{{qt-creator/qt-creator}}/test.yaml"
instructions:
Build:
- *common_environment
- *make_instructions
- Test: []
+ Test:
+ - *common_environment
+ - *test_instructions
LicenseCheck:
- *run_license_check
diff --git a/coin/product_dependencies.yaml b/coin/product_dependencies.yaml
index 08569b97254..cbcc2bbf7e1 100644
--- a/coin/product_dependencies.yaml
+++ b/coin/product_dependencies.yaml
@@ -1,4 +1,4 @@
dependencies:
- ../../qt/qt5.git:
- ref: "6.2"
+ ../../qt/tqtc-qt5.git:
+ ref: "tqtc/lts-6.2"
diff --git a/dist/changes-8.0.0.md b/dist/changes-8.0.0.md
new file mode 100644
index 00000000000..35675b2281f
--- /dev/null
+++ b/dist/changes-8.0.0.md
@@ -0,0 +1,270 @@
+Qt Creator 8
+============
+
+Qt Creator version 8 contains bug fixes and new features.
+
+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/7.0..v8.0.0
+
+General
+-------
+
+* Moved `Tools > Options` to `Edit > Preferences`
+
+Help
+----
+
+* Added support for mouse forward and backward buttons (QTCREATORBUG-25168)
+
+Editing
+-------
+
+* Added shortcut for adding next search match to multi-selection
+* Added warning when editing generated file (QTCREATORBUG-27173)
+* Added option for hiding line ending information `Text Editor > Display >
+ Display file line ending`
+* Fixed updating of annotations (QTCREATORBUG-26812)
+* Fixed that whitespace was not selected on double-click (QTCREATORBUG-24607)
+* Fixed `Rewrap Paragraph` when indenting with tabs (QTCREATORBUG-27602)
+* Fixed code folding marker visibility after `Open in New Window`
+ (QTCREATORBUG-27748)
+
+### C++
+
+* Removed `libclang` based code model
+* Fixed that `Generate Setter and Getter` generated non-static methods for
+ static pointer types (QTCREATORBUG-27547)
+* Fixed `Add Local Declaration` for class templates (QTCREATORBUG-26004)
+* Fixed that `Follow Symbol Under Cursor` could jump to new location even after
+ the user started doing other things (QTCREATORBUG-20878)
+* Fixed that macros were highlighted as preprocessor statements
+ (QTCREATORBUG-23548)
+* Fixed initialization of pointer variables when generating member for
+ `Q_PROPERTY` (QTCREATORBUG-27770)
+* Clangd
+ * Increased minimum `Clangd` version to 14
+ * Added warning and disabling of `Clangd` by default on machines with low
+ memory (QTCREATORBUG-19297)
+ * Improved performance of `compile_commands.json` creation
+ * Replaced some refactoring actions by the ones from `Clangd`
+ * Added desugaring of types and warning about unused includes
+ * Added option for ignoring big files
+ * Added information on parent function to `Find References With Access Type`
+ (QTCREATORBUG-27550)
+ * Added warning icon and deprecation tag to completion items for deprecated
+ API (QTCREATORBUG-2325)
+ * Worked around `Clangd` highlighting issue (QTCREATORBUG-27601)
+ * Fixed `Follow Symbol Under Cursor` for template types (QTCREATORBUG-27524)
+ * Fixed that issues from other files could be shown in `Issues`
+ (QTCREATORBUG-27260)
+ * Fixed position of diagnostics lightbulb
+ * Fixed function return types in `Outline` (QTCREATORBUG-27587)
+ * Fixed that UI files with same name could confuse code model
+ (QTCREATORBUG-27584)
+* clang-format
+ * Fixed cursor position when undoing formatting (QTCREATORBUG-27608)
+
+### QML
+
+* Added option for maximum line length to code style options
+ (QTCREATORBUG-23411)
+* Fixed handling of JavaScript string templates (QTCREATORBUG-21869)
+* Fixed formatting issue with nullish coalescing operator (QTCREATORBUG-27344)
+* Fixed that `Follow Symbol Under Cursor` could open file from build directory
+ instead of source directory (QTCREATORBUG-27173)
+* Fixed member lookup for items with same name in different modules
+ (QTCREATORBUG-26714)
+
+### Python
+
+* Switched to `python-lsp-server` by default (QTCREATORBUG-26230)
+* Added configuration options for `python-lsp-server`
+* Added check and installation help for `PySide` (PYSIDE-1742)
+* Added clean up of outdated interpreters
+* Added UIC based project wizard
+* Improved code style in wizard generated files
+* Fixed that unsaved and uncompiled UI files where outdated in code model
+* Fixed performance issues (QTCREATORBUG-24140, QTCREATORBUG-24704)
+
+### Language Server Protocol
+
+* Improved performance for large server responses
+* Added support for dragging in `Outline` (QTCREATORBUG-27502)
+* Fixed order of outline items (QTCREATORBUG-4346)
+* Fixed semantic highlighting after server reset
+* Fixed that semantic update was delayed by `Document update threshold` even
+ after saving
+* Fixed that tooltips could appear while Qt Creator is not in the foreground
+* Fixed synchronization of outline view (QTCREATORBUG-27595)
+
+### Image Viewer
+
+* Added button for copying image as data URL
+
+### FakeVim
+
+* Partially implemented multi repeat command `:g, :v`
+
+Projects
+--------
+
+* Added locator filter for starting run configurations
+* Added `BuildSystem:Name` variable for default build directory
+ (QTCREATORBUG-26147)
+
+### CMake
+
+* Added `Profile` build configuration type that is `RelWithDebInfo` with `QML
+ debugging and profiling`
+* Added `install` command to wizard generated projects
+* Turned `QML debugging and profiling` option on by default for `Debug`
+ configurations
+* Removed hardcoded `QT_QML_DEBUG` from wizard created project files
+* Fixed issue when reconfiguring with `QML debugging and profiling` option
+ enabled
+* Fixed missing path to `ninja` for `ExternalProject_Add` (QTCREATORBUG-27495)
+* Fixed that headers were wrongly classified as `C` code if `qt_add_qml_module`
+ is used (QTCREATORBUG-27117)
+
+### Compilation Database
+
+* Fixed wrong removal of command line options (QTCREATORBUG-22949)
+
+Debugging
+---------
+
+* Switched fallback Qt version for debug information to Qt 6.2
+* Added pretty printer for `QAnyStringView`
+* Added workaround for LLDB on Ubuntu 22.04
+
+Analyzer
+--------
+
+### Coco
+
+* Added experimental `Coco` integration
+* Added visualization of code coverage in code editor
+
+### CppCheck
+
+* Added `Copy to Clipboard` to text marks (QTCREATORBUG-27092)
+* Fixed quoting of command line arguments (QTCREATORBUG-27284)
+
+Version Control Systems
+-----------------------
+
+* Changed output pane to use text editor font (QTCREATORBUG-27164)
+
+### Git
+
+* Fixed that fetching tags when showing changes blocked UI
+
+### Gerrit
+
+* Fixed that non-Gerrit remote could be selected in `Push to Gerrit`
+
+### GitLab
+
+* Added experimental `GitLab` integration
+* Added support for browsing and cloning projects
+
+Platforms
+---------
+
+### Windows
+
+* Removed support for Universal Windows Platform (UWP)
+* Added auto-detection for MSVC ARM toolchain and debugger
+* Fixed ABI detection on ARM Windows
+* Fixed ABI detection of static Qt (QTCREATORBUG-27735)
+* Fixed interrupting remote CDB processes (QTCREATORBUG-21657)
+
+### macOS
+
+* Fixed import of existing builds of CMake projects that were done on the
+ command line (QTCREATORBUG-27591)
+
+### Android
+
+* Added option to connect physical device over WiFi
+* Moved SDK manager to separate dialog
+* Aligned platform names with Android Studio (QTCREATORBUG-27161)
+* Fixed issues with newer SDK tools (QTCREATORBUG-27174)
+
+### iOS
+
+* Improved consecutive deployment speed (QTCREATORBUG-24371)
+
+### Remote Linux
+
+* Switched to `echo` for testing connection
+* Fixed deployment of multiple directories with `rsync`
+
+### Docker
+
+* Added default mount point set to projects directory
+* Fixed state detection of docker daemon
+* Fixed issues with kit initialization
+
+### MCU
+
+* Added support for QUL 2.0 and removed support for earlier versions
+
+### QNX
+
+* Fixed debugger detection
+
+Credits for these changes go to:
+--------------------------------
+Aaron Barany
+Adam Treat
+Aleksei German
+Alesandro Portale
+Alessandro Portale
+Alexander Akulich
+Alexander Drozdov
+Alexandru Croitor
+Andre Hartmann
+André Pönitz
+Artem Sokolovskii
+Assam Boudjelthia
+Bartlomiej Moskal
+BogDan Vatra
+Christiaan Janssen
+Christian Kandeler
+Christian Stenger
+Christian Strømme
+Cristian Adam
+Cristián Maureira-Fredes
+David Schulz
+Dmitry Shachnev
+Eike Ziller
+Erik Verbruggen
+Evgeny Shtanov
+Fawzi Mohamed
+Henning Gruendl
+Ihor Ivlev
+Ippei Sugita
+Jaroslaw Kobus
+Knud Dollereder
+Leena Miettinen
+Mahmoud Badri
+Marcus Tillmanns
+Mats Honkamaa
+Maximilian Goldstein
+Miikka Heikkinen
+Orgad Shaneh
+Piotr Mućko
+Rafael Roquetto
+Robert Löhning
+Samuel Ghinet
+Sergey Morozov
+Tapani Mattila
+Tasuku Suzuki
+Thiago Macieira
+Thomas Hartmann
+Xavier Besson
diff --git a/dist/changes-8.0.1.md b/dist/changes-8.0.1.md
new file mode 100644
index 00000000000..37247687c2f
--- /dev/null
+++ b/dist/changes-8.0.1.md
@@ -0,0 +1,81 @@
+Qt Creator 8.0.1
+================
+
+Qt Creator version 8.0.1 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/v8.0.0..v8.0.1
+
+Editing
+-------
+
+* Delayed context menu tooltip action creation
+* Cached the last QIcon created from a Utils::Icon
+
+### C++
+
+* Prevent opening unneeded generated ui header files in clangd
+* Fixed documents getting opened in wrong clangd
+
+Projects
+--------
+
+### Compilation Database
+
+* Fixed project state when compilation database changes timestamp without
+ changing contents
+
+Platforms
+---------
+
+### macOS
+
+* Fixed crash of user applications that access protected resources
+ (QTCREATORBUG-27962)
+
+### Boot2Qt
+
+* Fixed crash when manually rebooting (QTCREATORBUG-27879)
+
+### QNX
+
+* Fixed debugger startup (QTCREATORBUG-27915)
+
+### Baremetal
+
+* Fixed running and debugging applications (QTCREATORBUG-27972)
+* Fixed bug when cloning jLink gdb server provider
+
+Debugging
+---------
+
+* Fixed bitfield display with Python 3
+
+
+Credits for these changes go to:
+--------------------------------
+Alexander Akulich
+Alibek Omarov
+André Pönitz
+Christian Kandeler
+Christian Stenger
+Cristian Adam
+David Schulz
+Dmitry Kovalev
+Eike Ziller
+Ivan Komissarov
+Jaroslaw Kobus
+Knud Dollereder
+Mahmoud Badri
+Marcus Tillmanns
+Mats Honkamaa
+Miikka Heikkinen
+Orgad Shaneh
+Oswald Buddenhagen
+Samuel Ghinet
+Thomas Hartmann
+Vikas Pachdha
diff --git a/dist/clangformat/README.md b/dist/clangformat/README.md
index 26982360aea..e333fcc7fb6 100644
--- a/dist/clangformat/README.md
+++ b/dist/clangformat/README.md
@@ -35,13 +35,13 @@ For more information about clang-format, see
1. Enable the Beautifier plugin and restart to load it.
2. Configure the plugin:
- In Menu: Tools > Options > Beautifier > Tab: Clang Format
+ In Menu: Edit > Preferences > Beautifier > Tab: Clang Format
* Select a valid clang-format executable
* Use predefined style: File
* Fallback style: None
3. Set shortcuts for convenience:
- In Menu: Tools > Options > Environment > Keyboard
+ In Menu: Edit > Preferences > Environment > Keyboard
* ClangFormat / FormatFile - e.g. Alt+C, F
* ClangFormat / FormatAtCursor - e.g. Alt+C, C
* ClangFormat / DisableFormattingSelectedText - e.g. Alt+C, D
diff --git a/doc/qtcreator/examples/textfinder/CMakeLists.txt b/doc/qtcreator/examples/textfinder/CMakeLists.txt
new file mode 100644
index 00000000000..39f9d4cd471
--- /dev/null
+++ b/doc/qtcreator/examples/textfinder/CMakeLists.txt
@@ -0,0 +1,71 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(TextFinder VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
+find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets LinguistTools)
+
+set(TS_FILES TextFinder_de_DE.ts)
+
+set(PROJECT_SOURCES
+ main.cpp
+ textfinder.cpp
+ textfinder.h
+ textfinder.ui
+ ${TS_FILES}
+ textfinder.qrc
+)
+
+if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
+ qt_add_executable(TextFinder
+ MANUAL_FINALIZATION
+ ${PROJECT_SOURCES}
+ )
+# Define target properties for Android with Qt 6 as:
+# set_property(TARGET TextFinder APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
+# ${CMAKE_CURRENT_SOURCE_DIR}/android)
+# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
+
+ qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
+else()
+ if(ANDROID)
+ add_library(TextFinder SHARED
+ ${PROJECT_SOURCES}
+ )
+# Define properties for Android with Qt 5 after find_package() calls as:
+# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
+ else()
+ add_executable(TextFinder
+ ${PROJECT_SOURCES}
+ )
+ endif()
+
+ qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
+endif()
+
+target_link_libraries(TextFinder PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
+
+set_target_properties(TextFinder PROPERTIES
+ MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
+ MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
+ MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
+ MACOSX_BUNDLE TRUE
+ WIN32_EXECUTABLE TRUE
+)
+
+install(TARGETS TextFinder
+ BUNDLE DESTINATION .
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+if(QT_VERSION_MAJOR EQUAL 6)
+ qt_finalize_executable(TextFinder)
+endif()
diff --git a/doc/qtcreator/examples/textfinder/TextFinder_de_DE.ts b/doc/qtcreator/examples/textfinder/TextFinder_de_DE.ts
new file mode 100644
index 00000000000..ae942c6f1c6
--- /dev/null
+++ b/doc/qtcreator/examples/textfinder/TextFinder_de_DE.ts
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="de_DE">
+<context>
+ <name>TextFinder</name>
+ <message>
+ <location filename="textfinder.ui" line="14"/>
+ <source>TextFinder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="textfinder.ui" line="22"/>
+ <source>Keyword</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="textfinder.ui" line="32"/>
+ <source>Find</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/doc/qtcreator/examples/textfinder/main.cpp b/doc/qtcreator/examples/textfinder/main.cpp
index 37cc1de814f..d9799019643 100644
--- a/doc/qtcreator/examples/textfinder/main.cpp
+++ b/doc/qtcreator/examples/textfinder/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator
@@ -47,15 +47,25 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
#include "textfinder.h"
#include <QApplication>
+#include <QLocale>
+#include <QTranslator>
int main(int argc, char *argv[])
{
- Q_INIT_RESOURCE(textfinder);
QApplication a(argc, argv);
+
+ QTranslator translator;
+ const QStringList uiLanguages = QLocale::system().uiLanguages();
+ for (const QString &locale : uiLanguages) {
+ const QString baseName = "TextFinder_" + QLocale(locale).name();
+ if (translator.load(":/i18n/" + baseName)) {
+ a.installTranslator(&translator);
+ break;
+ }
+ }
TextFinder w;
w.show();
return a.exec();
diff --git a/doc/qtcreator/examples/textfinder/textfinder.cpp b/doc/qtcreator/examples/textfinder/textfinder.cpp
index f402e0f31de..06d43a4cb69 100644
--- a/doc/qtcreator/examples/textfinder/textfinder.cpp
+++ b/doc/qtcreator/examples/textfinder/textfinder.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator
@@ -47,18 +47,18 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
#include "textfinder.h"
//! [1]
+#include "./ui_textfinder.h"
#include <QFile>
#include <QTextStream>
//! [1]
-#include <QMessageBox>
//! [3]
TextFinder::TextFinder(QWidget *parent)
- : QWidget(parent), ui(new Ui::TextFinder)
+ : QWidget(parent)
+ , ui(new Ui::TextFinder)
{
ui->setupUi(this);
loadTextFile();
diff --git a/doc/qtcreator/examples/textfinder/textfinder.h b/doc/qtcreator/examples/textfinder/textfinder.h
index 8351a473777..2366a55aa30 100644
--- a/doc/qtcreator/examples/textfinder/textfinder.h
+++ b/doc/qtcreator/examples/textfinder/textfinder.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator
@@ -47,24 +47,21 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
-#pragma once
-
-#include "ui_textfinder.h"
+#ifndef TEXTFINDER_H
+#define TEXTFINDER_H
#include <QWidget>
-namespace Ui
-{
- class TextFinder;
-}
+QT_BEGIN_NAMESPACE
+namespace Ui { class TextFinder; }
+QT_END_NAMESPACE
class TextFinder : public QWidget
{
Q_OBJECT
public:
- TextFinder(QWidget *parent = 0);
+ TextFinder(QWidget *parent = nullptr);
~TextFinder();
//! [0]
@@ -76,3 +73,4 @@ private:
void loadTextFile();
//! [0]
};
+#endif // TEXTFINDER_H
diff --git a/doc/qtcreator/examples/textfinder/textfinder.pro b/doc/qtcreator/examples/textfinder/textfinder.pro
deleted file mode 100644
index f8f547aef7c..00000000000
--- a/doc/qtcreator/examples/textfinder/textfinder.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-TARGET = TextFinder
-TEMPLATE = app
-
-QT += widgets
-
-SOURCES += main.cpp\
- textfinder.cpp
-
-HEADERS += textfinder.h
-
-FORMS += textfinder.ui
-
-RESOURCES += textfinder.qrc
diff --git a/doc/qtcreator/examples/textfinder/textfinder.qrc b/doc/qtcreator/examples/textfinder/textfinder.qrc
index 03cc512f4d6..fb804b5eca1 100644
--- a/doc/qtcreator/examples/textfinder/textfinder.qrc
+++ b/doc/qtcreator/examples/textfinder/textfinder.qrc
@@ -1,5 +1,5 @@
- <!DOCTYPE RCC><RCC version="1.0">
- <qresource>
- <file>input.txt</file>
- </qresource>
- </RCC> \ No newline at end of file
+<RCC>
+ <qresource prefix="/">
+ <file>input.txt</file>
+ </qresource>
+</RCC>
diff --git a/doc/qtcreator/examples/textfinder/textfinder.ui b/doc/qtcreator/examples/textfinder/textfinder.ui
index ba8018742a5..33f9d9c9729 100644
--- a/doc/qtcreator/examples/textfinder/textfinder.ui
+++ b/doc/qtcreator/examples/textfinder/textfinder.ui
@@ -6,33 +6,30 @@
<rect>
<x>0</x>
<y>0</y>
- <width>378</width>
- <height>158</height>
+ <width>800</width>
+ <height>600</height>
</rect>
</property>
<property name="windowTitle">
- <string>Find Text</string>
+ <string>TextFinder</string>
</property>
- <layout class="QVBoxLayout">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <layout class="QGridLayout">
- <item row="0" column="1">
- <widget class="QLineEdit" name="lineEdit"/>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="searchLabel">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
<property name="text">
- <string>&amp;Keyword:</string>
- </property>
- <property name="buddy">
- <cstring>lineEdit</cstring>
+ <string>Keyword</string>
</property>
</widget>
</item>
- <item row="0" column="2">
+ <item>
+ <widget class="QLineEdit" name="lineEdit"/>
+ </item>
+ <item>
<widget class="QPushButton" name="findButton">
<property name="text">
- <string>&amp;Find</string>
+ <string>Find</string>
</property>
</widget>
</item>
@@ -41,38 +38,8 @@
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
- <item>
- <spacer>
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>16</height>
- </size>
- </property>
- </spacer>
- </item>
</layout>
</widget>
<resources/>
- <connections>
- <connection>
- <sender>lineEdit</sender>
- <signal>returnPressed()</signal>
- <receiver>findButton</receiver>
- <slot>animateClick()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>261</x>
- <y>17</y>
- </hint>
- <hint type="destinationlabel">
- <x>320</x>
- <y>17</y>
- </hint>
- </hints>
- </connection>
- </connections>
+ <connections/>
</ui>
diff --git a/doc/qtcreator/images/coco-coveragebrowser-load-execution-report.png b/doc/qtcreator/images/coco-coveragebrowser-load-execution-report.png
new file mode 100644
index 00000000000..b99df7773d0
--- /dev/null
+++ b/doc/qtcreator/images/coco-coveragebrowser-load-execution-report.png
Binary files differ
diff --git a/doc/qtcreator/images/qml-toolbar-image.png b/doc/qtcreator/images/qml-toolbar-image.png
index 75cb2b4417a..21fafda65bf 100644
--- a/doc/qtcreator/images/qml-toolbar-image.png
+++ b/doc/qtcreator/images/qml-toolbar-image.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-add-resource-wizard2.png b/doc/qtcreator/images/qtcreator-add-resource-wizard2.png
index 8efcf7c4a7a..13246171a3b 100644
--- a/doc/qtcreator/images/qtcreator-add-resource-wizard2.png
+++ b/doc/qtcreator/images/qtcreator-add-resource-wizard2.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-add-resource-wizard3.png b/doc/qtcreator/images/qtcreator-add-resource-wizard3.png
index 9b4188e718d..1ca3c01636e 100644
--- a/doc/qtcreator/images/qtcreator-add-resource-wizard3.png
+++ b/doc/qtcreator/images/qtcreator-add-resource-wizard3.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-add-resource-wizard4.png b/doc/qtcreator/images/qtcreator-add-resource-wizard4.png
new file mode 100644
index 00000000000..ea985fc5ea0
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-add-resource-wizard4.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-add-resource.png b/doc/qtcreator/images/qtcreator-add-resource.png
index 42da7b0173c..dd7a2c59cdd 100644
--- a/doc/qtcreator/images/qtcreator-add-resource.png
+++ b/doc/qtcreator/images/qtcreator-add-resource.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-create-template.png b/doc/qtcreator/images/qtcreator-android-create-template.png
new file mode 100644
index 00000000000..75436a093fa
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-android-create-template.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-baremetal-kit.png b/doc/qtcreator/images/qtcreator-baremetal-kit.png
index 7f83bf6691f..b723dc54c56 100644
--- a/doc/qtcreator/images/qtcreator-baremetal-kit.png
+++ b/doc/qtcreator/images/qtcreator-baremetal-kit.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-boot2qt-deployment-steps.png b/doc/qtcreator/images/qtcreator-boot2qt-deployment-steps.png
index a1e6741a68e..1e8a355c5b8 100644
--- a/doc/qtcreator/images/qtcreator-boot2qt-deployment-steps.png
+++ b/doc/qtcreator/images/qtcreator-boot2qt-deployment-steps.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-build-settings-ios.png b/doc/qtcreator/images/qtcreator-build-settings-ios.png
index eb14112004b..145731d1dd3 100644
--- a/doc/qtcreator/images/qtcreator-build-settings-ios.png
+++ b/doc/qtcreator/images/qtcreator-build-settings-ios.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-clang-code-model-build-settings.png b/doc/qtcreator/images/qtcreator-clang-code-model-build-settings.png
deleted file mode 100644
index c3a0c6b6306..00000000000
--- a/doc/qtcreator/images/qtcreator-clang-code-model-build-settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-clang-code-model-options.png b/doc/qtcreator/images/qtcreator-clang-code-model-options.png
index db3d99af6ad..126f393c5d2 100644
--- a/doc/qtcreator/images/qtcreator-clang-code-model-options.png
+++ b/doc/qtcreator/images/qtcreator-clang-code-model-options.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-clang-tidy.png b/doc/qtcreator/images/qtcreator-clang-tidy.png
index 4e1f234380e..4f7baf1549a 100644
--- a/doc/qtcreator/images/qtcreator-clang-tidy.png
+++ b/doc/qtcreator/images/qtcreator-clang-tidy.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-clang-tools-options-customized.png b/doc/qtcreator/images/qtcreator-clang-tools-options-customized.png
index 7484117db5f..5e4a397853d 100644
--- a/doc/qtcreator/images/qtcreator-clang-tools-options-customized.png
+++ b/doc/qtcreator/images/qtcreator-clang-tools-options-customized.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-clazy.png b/doc/qtcreator/images/qtcreator-clazy.png
index 258bcb6ae62..15dfb0aeb6b 100644
--- a/doc/qtcreator/images/qtcreator-clazy.png
+++ b/doc/qtcreator/images/qtcreator-clazy.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-coco.png b/doc/qtcreator/images/qtcreator-coco.png
new file mode 100644
index 00000000000..851897ef2b3
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-coco.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-code-pasting-options.png b/doc/qtcreator/images/qtcreator-code-pasting-options.png
index 38a1d4a3977..d9bb548098a 100644
--- a/doc/qtcreator/images/qtcreator-code-pasting-options.png
+++ b/doc/qtcreator/images/qtcreator-code-pasting-options.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-code-style-clang-format.png b/doc/qtcreator/images/qtcreator-code-style-clang-format.png
index 5eea378da21..27fac40e5fa 100644
--- a/doc/qtcreator/images/qtcreator-code-style-clang-format.png
+++ b/doc/qtcreator/images/qtcreator-code-style-clang-format.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.png b/doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.png
index 17dbf6bda25..e0f5e44e7c9 100644
--- a/doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.png
+++ b/doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-custom-parser.png b/doc/qtcreator/images/qtcreator-custom-parser.png
index 0b25f929728..2ef78136301 100644
--- a/doc/qtcreator/images/qtcreator-custom-parser.png
+++ b/doc/qtcreator/images/qtcreator-custom-parser.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-debugger-attach-to-running-debug-server.png b/doc/qtcreator/images/qtcreator-debugger-attach-to-running-debug-server.png
index 296d4e6e6f2..6d8292818be 100644
--- a/doc/qtcreator/images/qtcreator-debugger-attach-to-running-debug-server.png
+++ b/doc/qtcreator/images/qtcreator-debugger-attach-to-running-debug-server.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-debugging-helper-options.png b/doc/qtcreator/images/qtcreator-debugging-helper-options.png
index a73e6144bd4..43a106aed5c 100644
--- a/doc/qtcreator/images/qtcreator-debugging-helper-options.png
+++ b/doc/qtcreator/images/qtcreator-debugging-helper-options.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-diagnostics-configuration.png b/doc/qtcreator/images/qtcreator-diagnostics-configuration.png
deleted file mode 100644
index 0a1e5341e75..00000000000
--- a/doc/qtcreator/images/qtcreator-diagnostics-configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-docker-image-selection.png b/doc/qtcreator/images/qtcreator-docker-image-selection.png
new file mode 100644
index 00000000000..72401c2f320
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-docker-image-selection.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-docker-preferences.png b/doc/qtcreator/images/qtcreator-docker-preferences.png
new file mode 100644
index 00000000000..0b087201778
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-docker-preferences.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-editor-settings.png b/doc/qtcreator/images/qtcreator-editor-settings.png
index 2ad6d12e217..7b2c3ecb694 100644
--- a/doc/qtcreator/images/qtcreator-editor-settings.png
+++ b/doc/qtcreator/images/qtcreator-editor-settings.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-embedded-linux-deployment-details.png b/doc/qtcreator/images/qtcreator-embedded-linux-deployment-details.png
index 6f7886894d9..f667daf545a 100644
--- a/doc/qtcreator/images/qtcreator-embedded-linux-deployment-details.png
+++ b/doc/qtcreator/images/qtcreator-embedded-linux-deployment-details.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-external-tools.png b/doc/qtcreator/images/qtcreator-external-tools.png
index 31b325b1809..949eff9ae25 100644
--- a/doc/qtcreator/images/qtcreator-external-tools.png
+++ b/doc/qtcreator/images/qtcreator-external-tools.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-formedit.png b/doc/qtcreator/images/qtcreator-formedit.png
index 4ac5720b645..af25d8b5e87 100644
--- a/doc/qtcreator/images/qtcreator-formedit.png
+++ b/doc/qtcreator/images/qtcreator-formedit.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-gitlab-clone-repository.png b/doc/qtcreator/images/qtcreator-gitlab-clone-repository.png
new file mode 100644
index 00000000000..35194c4e4f2
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-gitlab-clone-repository.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-gitlab-preferences-add-server.png b/doc/qtcreator/images/qtcreator-gitlab-preferences-add-server.png
new file mode 100644
index 00000000000..f1963b3484d
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-gitlab-preferences-add-server.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-gitlab-preferences-project.png b/doc/qtcreator/images/qtcreator-gitlab-preferences-project.png
new file mode 100644
index 00000000000..835434f5c35
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-gitlab-preferences-project.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-gitlab-preferences.png b/doc/qtcreator/images/qtcreator-gitlab-preferences.png
new file mode 100644
index 00000000000..459d5d60ccb
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-gitlab-preferences.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-gitlab-project-list.png b/doc/qtcreator/images/qtcreator-gitlab-project-list.png
new file mode 100644
index 00000000000..039e294ef97
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-gitlab-project-list.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-image-viewer.png b/doc/qtcreator/images/qtcreator-image-viewer.png
index ea3ee88a83a..d953d15aa62 100644
--- a/doc/qtcreator/images/qtcreator-image-viewer.png
+++ b/doc/qtcreator/images/qtcreator-image-viewer.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-intro-and-location-qt-gui.png b/doc/qtcreator/images/qtcreator-intro-and-location-qt-gui.png
index 2afd5e6c149..9d4e7b2ca03 100644
--- a/doc/qtcreator/images/qtcreator-intro-and-location-qt-gui.png
+++ b/doc/qtcreator/images/qtcreator-intro-and-location-qt-gui.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-ios-add-kit.png b/doc/qtcreator/images/qtcreator-ios-add-kit.png
index bbf7742769e..b4312c6c3f0 100644
--- a/doc/qtcreator/images/qtcreator-ios-add-kit.png
+++ b/doc/qtcreator/images/qtcreator-ios-add-kit.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-ios-device-configurations.png b/doc/qtcreator/images/qtcreator-ios-device-configurations.png
index da6b6a4f01d..6612e68597a 100644
--- a/doc/qtcreator/images/qtcreator-ios-device-configurations.png
+++ b/doc/qtcreator/images/qtcreator-ios-device-configurations.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-ios-preferences.png b/doc/qtcreator/images/qtcreator-ios-preferences.png
index b6ad26f268b..935a528d6cb 100644
--- a/doc/qtcreator/images/qtcreator-ios-preferences.png
+++ b/doc/qtcreator/images/qtcreator-ios-preferences.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-ios-simulator-deploy.png b/doc/qtcreator/images/qtcreator-ios-simulator-deploy.png
index e2fc146a395..dbc720bdd33 100644
--- a/doc/qtcreator/images/qtcreator-ios-simulator-deploy.png
+++ b/doc/qtcreator/images/qtcreator-ios-simulator-deploy.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-kits-add.png b/doc/qtcreator/images/qtcreator-kits-add.png
deleted file mode 100644
index 396368b5039..00000000000
--- a/doc/qtcreator/images/qtcreator-kits-add.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-kits.png b/doc/qtcreator/images/qtcreator-kits.png
index efa38f4df6b..9cd08c36cc5 100644
--- a/doc/qtcreator/images/qtcreator-kits.png
+++ b/doc/qtcreator/images/qtcreator-kits.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-language-client-inspector-memory-usage.png b/doc/qtcreator/images/qtcreator-language-client-inspector-memory-usage.png
new file mode 100644
index 00000000000..862c88d17e3
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-language-client-inspector-memory-usage.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-language-client-options-java.png b/doc/qtcreator/images/qtcreator-language-client-options-java.png
index d70df4dd477..592d7d2f5a3 100644
--- a/doc/qtcreator/images/qtcreator-language-client-options-java.png
+++ b/doc/qtcreator/images/qtcreator-language-client-options-java.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-language-client-options.png b/doc/qtcreator/images/qtcreator-language-client-options.png
deleted file mode 100644
index 0ae18ec4e41..00000000000
--- a/doc/qtcreator/images/qtcreator-language-client-options.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-language-server-generic-stdio.png b/doc/qtcreator/images/qtcreator-language-server-generic-stdio.png
new file mode 100644
index 00000000000..4c0b26b8b68
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-language-server-generic-stdio.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-link-with-qt.png b/doc/qtcreator/images/qtcreator-link-with-qt.png
index 5173be111d6..f84311e7ee7 100644
--- a/doc/qtcreator/images/qtcreator-link-with-qt.png
+++ b/doc/qtcreator/images/qtcreator-link-with-qt.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-mcu-kit.png b/doc/qtcreator/images/qtcreator-mcu-kit.png
index 112707e22a1..c218ad647e8 100644
--- a/doc/qtcreator/images/qtcreator-mcu-kit.png
+++ b/doc/qtcreator/images/qtcreator-mcu-kit.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-mcu-options.png b/doc/qtcreator/images/qtcreator-mcu-options.png
index eafc35d51c9..a7234466e42 100644
--- a/doc/qtcreator/images/qtcreator-mcu-options.png
+++ b/doc/qtcreator/images/qtcreator-mcu-options.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-new-project-build-system-qt-gui.png b/doc/qtcreator/images/qtcreator-new-project-build-system-qt-gui.png
index 9bcb248e0f8..e0e5bcda818 100644
--- a/doc/qtcreator/images/qtcreator-new-project-build-system-qt-gui.png
+++ b/doc/qtcreator/images/qtcreator-new-project-build-system-qt-gui.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-new-project-qt-versions-qt-gui.png b/doc/qtcreator/images/qtcreator-new-project-qt-versions-qt-gui.png
index b829cee9512..292cac5e7ee 100644
--- a/doc/qtcreator/images/qtcreator-new-project-qt-versions-qt-gui.png
+++ b/doc/qtcreator/images/qtcreator-new-project-qt-versions-qt-gui.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-new-project-summary-qt-gui.png b/doc/qtcreator/images/qtcreator-new-project-summary-qt-gui.png
index e7b04b20542..81faa7e18e6 100644
--- a/doc/qtcreator/images/qtcreator-new-project-summary-qt-gui.png
+++ b/doc/qtcreator/images/qtcreator-new-project-summary-qt-gui.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-open-documents-view.png b/doc/qtcreator/images/qtcreator-open-documents-view.png
index ca8d619da62..a05eb4e84de 100644
--- a/doc/qtcreator/images/qtcreator-open-documents-view.png
+++ b/doc/qtcreator/images/qtcreator-open-documents-view.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-options-android-main.png b/doc/qtcreator/images/qtcreator-options-android-main.png
index 70d119b3206..5ecea57d998 100644
--- a/doc/qtcreator/images/qtcreator-options-android-main.png
+++ b/doc/qtcreator/images/qtcreator-options-android-main.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-options-android-sdk-tools.png b/doc/qtcreator/images/qtcreator-options-android-sdk-tools.png
index 19237d1b789..f3057ce0bca 100644
--- a/doc/qtcreator/images/qtcreator-options-android-sdk-tools.png
+++ b/doc/qtcreator/images/qtcreator-options-android-sdk-tools.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-options-clangd.png b/doc/qtcreator/images/qtcreator-options-clangd.png
index ef955f4563d..b03a9e4d70d 100644
--- a/doc/qtcreator/images/qtcreator-options-clangd.png
+++ b/doc/qtcreator/images/qtcreator-options-clangd.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-options-text-editor-display.png b/doc/qtcreator/images/qtcreator-options-text-editor-display.png
index d49884ae624..c00104e3b6f 100644
--- a/doc/qtcreator/images/qtcreator-options-text-editor-display.png
+++ b/doc/qtcreator/images/qtcreator-options-text-editor-display.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-options-texteditor-completion.png b/doc/qtcreator/images/qtcreator-options-texteditor-completion.png
index b501035e836..a891ed6365c 100644
--- a/doc/qtcreator/images/qtcreator-options-texteditor-completion.png
+++ b/doc/qtcreator/images/qtcreator-options-texteditor-completion.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-python-advanced.png b/doc/qtcreator/images/qtcreator-python-advanced.png
new file mode 100644
index 00000000000..eea49d610cf
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-python-advanced.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-python-interpreters.png b/doc/qtcreator/images/qtcreator-python-interpreters.png
new file mode 100644
index 00000000000..546adb1b2d3
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-python-interpreters.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-python-plugins.png b/doc/qtcreator/images/qtcreator-python-plugins.png
new file mode 100644
index 00000000000..c2ba0b05a17
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-python-plugins.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-qml-js-editing.png b/doc/qtcreator/images/qtcreator-qml-js-editing.png
new file mode 100644
index 00000000000..731c97f1c23
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-qml-js-editing.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-qnx-deployment.png b/doc/qtcreator/images/qtcreator-qnx-deployment.png
index 6608e121b67..e338e48f311 100644
--- a/doc/qtcreator/images/qtcreator-qnx-deployment.png
+++ b/doc/qtcreator/images/qtcreator-qnx-deployment.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-qt-versions.png b/doc/qtcreator/images/qtcreator-qt-versions.png
index 8d456039e30..4e33e55b996 100644
--- a/doc/qtcreator/images/qtcreator-qt-versions.png
+++ b/doc/qtcreator/images/qtcreator-qt-versions.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-refactoring-options-locations.png b/doc/qtcreator/images/qtcreator-refactoring-options-locations.png
index 9e0dc130662..0d3b2c54f40 100644
--- a/doc/qtcreator/images/qtcreator-refactoring-options-locations.png
+++ b/doc/qtcreator/images/qtcreator-refactoring-options-locations.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-semanticerror-clang.png b/doc/qtcreator/images/qtcreator-semanticerror-clang.png
deleted file mode 100644
index 9980485832b..00000000000
--- a/doc/qtcreator/images/qtcreator-semanticerror-clang.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-semanticerror.png b/doc/qtcreator/images/qtcreator-semanticerror.png
index e6920b98caf..72edb4744cd 100644
--- a/doc/qtcreator/images/qtcreator-semanticerror.png
+++ b/doc/qtcreator/images/qtcreator-semanticerror.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-sidebar.png b/doc/qtcreator/images/qtcreator-sidebar.png
index d7f6dea0f86..47d4e5e1f85 100644
--- a/doc/qtcreator/images/qtcreator-sidebar.png
+++ b/doc/qtcreator/images/qtcreator-sidebar.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-syntaxerror-clang.png b/doc/qtcreator/images/qtcreator-syntaxerror-clang.png
deleted file mode 100644
index 8beee1832fa..00000000000
--- a/doc/qtcreator/images/qtcreator-syntaxerror-clang.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-syntaxerror.png b/doc/qtcreator/images/qtcreator-syntaxerror.png
index 2f8916ce3b1..1561ef7ac20 100644
--- a/doc/qtcreator/images/qtcreator-syntaxerror.png
+++ b/doc/qtcreator/images/qtcreator-syntaxerror.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-textfinder-contents.png b/doc/qtcreator/images/qtcreator-textfinder-contents.png
index 213edc62b1e..f8362911e36 100644
--- a/doc/qtcreator/images/qtcreator-textfinder-contents.png
+++ b/doc/qtcreator/images/qtcreator-textfinder-contents.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-todo-excluded-files.png b/doc/qtcreator/images/qtcreator-todo-excluded-files.png
new file mode 100644
index 00000000000..faa347fdce8
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-todo-excluded-files.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-typo-clang.png b/doc/qtcreator/images/qtcreator-typo-clang.png
index 3e3ad7daeaf..76722d658ed 100644
--- a/doc/qtcreator/images/qtcreator-typo-clang.png
+++ b/doc/qtcreator/images/qtcreator-typo-clang.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-valgrind-remote-settings.png b/doc/qtcreator/images/qtcreator-valgrind-remote-settings.png
index 0b9e6146180..5ded5055e76 100644
--- a/doc/qtcreator/images/qtcreator-valgrind-remote-settings.png
+++ b/doc/qtcreator/images/qtcreator-valgrind-remote-settings.png
Binary files differ
diff --git a/doc/qtcreator/images/qtdesigner-add-profile.png b/doc/qtcreator/images/qtdesigner-add-profile.png
new file mode 100644
index 00000000000..7457872a191
--- /dev/null
+++ b/doc/qtcreator/images/qtdesigner-add-profile.png
Binary files differ
diff --git a/doc/qtcreator/images/qtdesigner-embedded-design.png b/doc/qtcreator/images/qtdesigner-embedded-design.png
new file mode 100644
index 00000000000..7dac5128d6c
--- /dev/null
+++ b/doc/qtcreator/images/qtdesigner-embedded-design.png
Binary files differ
diff --git a/doc/qtcreator/src/analyze/cpu-usage-analyzer.qdoc b/doc/qtcreator/src/analyze/cpu-usage-analyzer.qdoc
index fd05937df55..6244e3f5b24 100644
--- a/doc/qtcreator/src/analyze/cpu-usage-analyzer.qdoc
+++ b/doc/qtcreator/src/analyze/cpu-usage-analyzer.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -126,7 +126,7 @@
\section1 Specifying Performance Analyzer Settings
To specify global settings for the Performance Analyzer, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Analyzer >
\uicontrol {CPU Usage}. For each run configuration, you can also
use specialized settings. Select \uicontrol Projects > \uicontrol Run, and
then select \uicontrol Details next to
@@ -471,14 +471,23 @@
The Performance Analyzer might fail to record data for the following reasons:
- \list 1
- \li Perf events may be globally disabled on your system. The
- preconfigured \l Boot2Qt images come with perf events enabled. For
- a custom configuration you need to make sure that the file
+ \list
+ \li Perf events may be globally disabled on your system.
+ The preconfigured \l Boot2Qt images come with perf events enabled.
+ For a custom configuration you need to make sure that the file
\c {/proc/sys/kernel/perf_event_paranoid} contains a value smaller
than \c {2}. For maximum flexibility in recording traces you can
set the value to \c {-1}. This allows any user to record any kind
of trace, even using raw kernel trace points.
+
+ The way to enable Perf events depends on your Linux distribution.
+ On some distributions, you can run the following command with
+ root (or equivalent) privileges:
+
+ \badcode
+ echo -e "kernel.perf_event_paranoid=-1\nkernel.kptr_restrict=0" | sudo tee /etc/sysctl.d/10-perf.conf
+ \endcode
+
\li The connection between the target device and the host may not be
fast enough to transfer the data produced by Perf. Try modifying
the values of the \uicontrol {Stack snapshot size} or
@@ -501,8 +510,21 @@
drives the sampling from software. After the sampling has failed,
reboot the device. The kernel may have disabled important parts of
the performance counters system.
+ \li Perf might not be installed. The way to install it depends on your
+ Linux distribution. For example, you might try the following
+ commands:
+
+ \list
+ \li On Ubuntu 22.04:
+ \c {sudo apt install linux-tools-$(uname -r)}
+ \li On Debian:
+ \c {apt install linux-perf}
+ \endlist
\endlist
- Output from the helper program that processes the data is displayed in the
- \uicontrol {General Messages} output pane.
+ Output from the helper program that processes the data is displayed in
+ \l{Viewing Output}{General Messages}.
+
+ Some information is displayed in \l {Application Output} even if the
+ Performance Analyzer displays error messages.
*/
diff --git a/doc/qtcreator/src/analyze/creator-analyze.qdoc b/doc/qtcreator/src/analyze/creator-analyze.qdoc
index cff0f46cb30..77a7fd0aa22 100644
--- a/doc/qtcreator/src/analyze/creator-analyze.qdoc
+++ b/doc/qtcreator/src/analyze/creator-analyze.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -55,40 +55,46 @@
\li \l{Profiling QML Applications}{QML Profiler}
- You can inspect binding evaluations, signal handling, and
+ Inspect binding evaluations, signal handling, and
painting operations when running QML code. This is useful for
identifying potential bottlenecks, especially in the evaluation
of bindings.
+ \li \l{Checking Code Coverage}{Squish Coco}
+
+ Analyze the way an application runs as part of a test suite, for
+ example, and use the results to make the tests more efficient and
+ complete.
+
\li \l{Using Valgrind Code Analysis Tools}{Valgrind Code Analysis Tools}
- You can detect problems in memory management by using the Memcheck
+ Detect problems in memory management by using the Memcheck
tool and find cache misses in the code by using the Callgrind tool.
\li \l{Using Clang Tools}{Clang Tools}
- You can detect problems in C, C++, and Objective-C programs by
+ Detect problems in C, C++, and Objective-C programs by
using Clang-Tidy and Clazy.
\li \l{Detecting Memory Leaks with Heob}{Heob}
- You can use the Heob heap observer on Windows to detect buffer
+ Use the Heob heap observer on Windows to detect buffer
overruns and memory leaks.
\li \l{Analyzing CPU Usage}{Performance Analyzer}
- You can analyze the CPU usage of embedded applications and Linux
+ Analyze the CPU usage of embedded applications and Linux
desktop applications with the Performance Analyzer that integrates
the Linux Perf tool.
\li \l{Analyzing Code with Cppcheck}{Cppcheck}
- You can use the experimental Cppcheck plugin to detect undefined
+ Use the experimental Cppcheck plugin to detect undefined
behavior and dangerous coding constructs.
\li \l{Visualizing Chrome Trace Events}{Chrome Trace Format Visualizer}
- You can use the Chrome Trace Format (CTF) Visualizer to view
+ Use the Chrome Trace Format (CTF) Visualizer to view
Chrome trace events. This is especially useful when viewing
large trace files that are difficult to visualize using the
built-in trace-viewer (\c{chrome://tracing}).
diff --git a/doc/qtcreator/src/analyze/creator-clang-static-analyzer.qdoc b/doc/qtcreator/src/analyze/creator-clang-static-analyzer.qdoc
index c4d61e1c012..43459d767c5 100644
--- a/doc/qtcreator/src/analyze/creator-clang-static-analyzer.qdoc
+++ b/doc/qtcreator/src/analyze/creator-clang-static-analyzer.qdoc
@@ -122,8 +122,8 @@
\image qtcreator-clang-tools-options-customized.png "Clang Tools customized settings"
To restore the global settings, select \uicontrol {Restore Global Settings}.
- To view and modify the global settings, select
- \uicontrol {Open Global Settings}. To open the Clang static analyzer,
+ To view and modify the global settings, select the link in
+ \uicontrol {Use global settings}. To open the Clang static analyzer,
select \uicontrol {Go to Analyzer}.
\section1 Configuring Clang Tools
@@ -132,10 +132,10 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Analyzer >
\uicontrol {Clang Tools}.
- \image qtcreator-clang-tools-options.png "Clang Tools options tab"
+ \image qtcreator-clang-tools-options.png "Clang Tools preferences"
\li In the \uicontrol Clang-Tidy and \uicontrol Clazy-Standalone fields,
set the paths to the executables to use.
@@ -174,6 +174,8 @@
\li In the \uicontrol {Clang-Tidy Checks} tab, select
\uicontrol {Select Checks} to select the checks to perform.
+ To filter the checks, enter a string in the
+ \uicontrol {Filter by name} field.
\image qtcreator-clang-tidy.png "Clang-Tidy Checks tab"
@@ -189,8 +191,10 @@
\image qtcreator-clazy.png "Clazy Checks tab"
- \li In the \uicontrol {Topic Filter} field, select a topic to view
- only checks related to that area in the \uicontrol Checks field.
+ \li In the \uicontrol Filters field, select topics to view
+ only checks related to those areas in the \uicontrol Checks field.
+ To filter the checks in the selected areas, enter a string in the
+ \uicontrol {Filter by name} field.
\li To view all checks again, select \uicontrol {Reset Filter}.
diff --git a/doc/qtcreator/src/analyze/creator-coco.qdoc b/doc/qtcreator/src/analyze/creator-coco.qdoc
new file mode 100644
index 00000000000..4f74832e4b4
--- /dev/null
+++ b/doc/qtcreator/src/analyze/creator-coco.qdoc
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Creator documentation.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+**
+****************************************************************************/
+
+/*!
+ \previouspage creator-qml-performance-monitor.html
+ \page creator-coco.html
+ \nextpage creator-valgrind-overview.html
+
+ \title Checking Code Coverage
+
+ \l{https://doc.froglogic.com/squish-coco/latest/}{Squish Coco} is a complete
+ code coverage tool chain for Tcl, QML, C# and C/C++ programs that runs on
+ \macOS, Linux, and Windows.
+
+ Squish Coco analyzes the way an application runs, as part of a test suite,
+ for example. The results enable you to make the tests more efficient and
+ complete.
+
+ You can:
+
+ \list
+ \li Find untested code sections.
+ \li Find redundant tests which can then be eliminated. Squish Coco can
+ identify portions of the source code that are covered by a test. It
+ can detect whether a new test covers lines in the source code that
+ the existing tests do not cover.
+ \li Find dead code by displaying code that is never executed.
+ \li Calculate the optimum test execution order so as to maximize
+ test coverage for each run. This is particularly useful for manual
+ testing.
+ \li Analyze two separate versions of an application and compare the
+ differences. This makes it possible to see which tests are affected
+ by source code modifications and also to get some measure of the
+ test coverage of a patch or hot fix.
+ \li Measure the execution time of applications and tests.
+ \endlist
+
+ The experimental Coco plugin integrates Coco CoverageBrowser into \QC.
+ It enables you to analyze the test coverage by loading an instrumentation
+ database (a .csmes file) that was generated by Coco CoverageScanner.
+ It is currently supported only on Windows, with Squish Coco version 6.0,
+ or later.
+
+ To use the plugin, you must download and install Squish Coco.
+
+ \section1 Enabling the Coco Plugin
+
+ To enable the Coco plugin:
+
+ \list 1
+ \li Select \uicontrol Help > \uicontrol {About Plugins} >
+ \uicontrol Utilities > \uicontrol Coco to enable the plugin.
+ \li Select \uicontrol {Restart Now} to restart \QC and load the plugin.
+ \endlist
+
+ \section1 Configuring Coco
+
+ \list 1
+ \li Select \uicontrol Analyze > \uicontrol {Squish Coco}.
+ \image qtcreator-coco.png "Coco CoverageBrowser and CSMes file"
+ \li In \uicontrol {CoverageBrowser}, enter the path to the Coco
+ coverage browser to use for analyzing a .csmes file.
+ \li In \uicontrol CSMes, select the instrumentation database to load.
+ \li Select \uicontrol Open to start CoverageBrowser.
+ \li In CoverageBrowser, select \uicontrol File >
+ \uicontrol {Load Execution Report} and select the .csexe for the
+ coverage scan.
+ \image coco-coveragebrowser-load-execution-report.png "Load Execution Report dialog"
+ \li If you want to reuse the execution report, deselect the
+ \uicontrol {Delete execution report after loading} check box.
+ \endlist
+
+ Open the analyzed files in \QC. The results of the analysis are displayed
+ after the code in \uicontrol Edit mode. You can change the fonts and colors
+ used for different types of results.
+
+ \section1 Changing Fonts and Colors
+
+ To change the default fonts and colors, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol {Font & Colors}.
+ Create your own color scheme and select new fonts and colors for the
+ following results:
+
+ \list
+ \li Code Coverage Added Code
+ \li Partially Covered Code
+ \li Uncovered Code
+ \li Fully Covered Code
+ \li Manually Validated Code
+ \li Code Coverage Dead Code
+ \li Code Coverage Execution Count too Low
+ \li Implicitly Not Covered Code
+ \li Implicitly Covered Code
+ \li Implicit Manual Coverage Validation
+ \endlist
+
+ For more information, see \l{Specifying Text Editor Settings}.
+*/
diff --git a/doc/qtcreator/src/analyze/creator-cppcheck.qdoc b/doc/qtcreator/src/analyze/creator-cppcheck.qdoc
index a278f2db6d6..ab553c92687 100644
--- a/doc/qtcreator/src/analyze/creator-cppcheck.qdoc
+++ b/doc/qtcreator/src/analyze/creator-cppcheck.qdoc
@@ -94,6 +94,6 @@
marks or annotations.
To specify the settings above for the automatically run checks,
- select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol Analyzer
> \uicontrol Cppcheck.
*/
diff --git a/doc/qtcreator/src/analyze/creator-heob.qdoc b/doc/qtcreator/src/analyze/creator-heob.qdoc
index 1c484450c99..524804ca6e0 100644
--- a/doc/qtcreator/src/analyze/creator-heob.qdoc
+++ b/doc/qtcreator/src/analyze/creator-heob.qdoc
@@ -114,7 +114,7 @@
In the \uicontrol {Handle exceptions} list, select \uicontrol Off to use the
standard exception handler and have the debugger automatically attached if
the application crashes. This works only if you register \QC is as a
- post-mortem debugger by selecting \uicontrol Tools > \uicontrol Options >
+ post-mortem debugger by selecting \uicontrol Edit > \uicontrol Preferences >
\uicontrol Debugger > \uicontrol General >
\uicontrol {Use Qt Creator for post-mortem debugging}.
diff --git a/doc/qtcreator/src/analyze/creator-valgrind-overview.qdoc b/doc/qtcreator/src/analyze/creator-valgrind-overview.qdoc
index 919932e7a3d..1a5e72e5b85 100644
--- a/doc/qtcreator/src/analyze/creator-valgrind-overview.qdoc
+++ b/doc/qtcreator/src/analyze/creator-valgrind-overview.qdoc
@@ -30,7 +30,7 @@
// **********************************************************************
/*!
- \previouspage creator-qml-performance-monitor.html
+ \previouspage creator-coco.html
\page creator-valgrind-overview.html
\nextpage creator-analyzer.html
@@ -58,8 +58,8 @@
For more information about analyzing applications for which you do not have
a project, see \l{Running Valgrind Tools on External Applications}.
- To select options for the Valgrind tools, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Analyzer. You can override the general
+ To set preferences for the Valgrind tools, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Analyzer. You can override the general
settings for each project in the \uicontrol {Run Settings} for the project.
The following sections describe how to use the Valgrind tools:
diff --git a/doc/qtcreator/src/analyze/creator-valgrind.qdoc b/doc/qtcreator/src/analyze/creator-valgrind.qdoc
index 6baf3d5d799..0fc05d3ba72 100644
--- a/doc/qtcreator/src/analyze/creator-valgrind.qdoc
+++ b/doc/qtcreator/src/analyze/creator-valgrind.qdoc
@@ -103,8 +103,8 @@
separately for each project in the \l{Specifying Run Settings}{run settings}
of the project.
- To specify global settings for Valgrind, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Analyzer. The \uicontrol
+ To specify global settings for Valgrind, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Analyzer. The \uicontrol
{Memcheck Memory Analysis Options} group contains Memcheck options.
In \uicontrol {Extra Memcheck arguments}, specify additional arguments
@@ -112,7 +112,7 @@
Stack traces can get quite large and confusing, and therefore, reading them
from the bottom up can help. If the stack trace is not big enough or it is
- too big, select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer
+ too big, select \uicontrol Edit > \uicontrol Preferences > \uicontrol Analyzer
and define the length of the stack trace in the
\uicontrol {Backtrace frame count} field.
@@ -290,8 +290,8 @@
separately for each project in the \l{Specifying Run Settings}{run settings}
of the project.
- To specify global settings for Valgrind, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Analyzer. The \uicontrol
+ To specify global settings for Valgrind, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Analyzer. The \uicontrol
{Callgrind Profiling Options} group contains Callgrind options.
\image qtcreator-valgrind-callgrind-options.png "Valgrind options"
diff --git a/doc/qtcreator/src/android/androiddev.qdoc b/doc/qtcreator/src/android/androiddev.qdoc
index 7af57672040..06fb49c39b3 100644
--- a/doc/qtcreator/src/android/androiddev.qdoc
+++ b/doc/qtcreator/src/android/androiddev.qdoc
@@ -50,8 +50,8 @@
architectures (ABIs) installed as one.
To enable helpful code editing features for Java, such as code completion,
- highlighting, function tooltips, and navigating in code, specify settings
- for a \l{Specifying Java Language Server Settings}{Java language server}.
+ highlighting, function tooltips, and navigating in code, add a
+ \l{Java Language Server}{Java language server}.
The Android Debug Bridge (adb) command line tool is integrated to \QC to
enable you to deploy applications to connected Android devices, to run
@@ -80,11 +80,11 @@
To set up the development environment for Android:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices >
\uicontrol Android on Windows and Linux or \uicontrol {\QC} >
\uicontrol Preferences > \uicontrol Devices > \uicontrol Android on
\macos.
- \image qtcreator-options-android-main.png "Android options"
+ \image qtcreator-options-android-main.png "Android preferences"
\li In the \uicontrol {JDK location} field, set the path to the JDK.
\QC checks the JDK installation and reports errors.
@@ -94,7 +94,7 @@
\inlineimage icons/online.png
to open the JDK download web page in the default browser.
- \note We recommended using a 64-bit JDK, because the 32-bit one
+ \note We recommended using a 64-bit JDK because the 32-bit one
might cause issues with \c cmdline-tools, and some packages might
not be listed.
\li In the \uicontrol {Android SDK location} field, set the path to the
@@ -111,8 +111,8 @@
\li The installed NDK versions are listed in
\uicontrol {Android NDK list}.
The locked items were installed by the SDK Manager,
- and can only be modified from the \uicontrol {SDK Manager} tab.
- For more information, see \l{Managing Android NDK Packages}.
+ and can only be modified from the \uicontrol {Android SDK Manager}
+ dialog. For more information, see \l{Managing Android NDK Packages}.
\li Select the \uicontrol {Automatically create kits for Android tool chains}
check box to allow \QC to create the kits for you. \QC displays a
warning if it cannot find a suitable Qt version.
@@ -130,7 +130,7 @@
\section2 Manual Setup
\note We recommend that you use the latest Android SDK Command-Line Tools.
- Using Android SDK Tools version 25.2.5 or earlier is not supported, because
+ Using Android SDK Tools version 25.2.5 or earlier is not supported because
they cannot be fully integrated with \QC.
However, if the automatic setup does not meet your needs, you can download
@@ -171,16 +171,16 @@
\section2 Managing Android NDK Packages
- To view the installed \l{Android NDK} versions, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Devices > \uicontrol Android on Windows and
+ To view the installed \l{Android NDK} versions, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Devices > \uicontrol Android on Windows and
Linux or \uicontrol {\QC} > \uicontrol Preferences > \uicontrol Devices >
\uicontrol Android on \macos.
\image qtcreator-options-android-sdk-tools.png "Android NDK and SDK checks"
The locked versions were installed by the SDK Manager, and can only
- be modified from the SDK Manager tab. For more information, see
- \l{Managing Android SDK Packages}.
+ be modified from the \uicontrol {Android SDK Manager} dialog.
+ For more information, see \l{Managing Android SDK Packages}.
To manually download NDKs, select \inlineimage icons/online.png
.
@@ -201,8 +201,8 @@
installing, updating, and removing SDK packages. You can still use
sdkmanager for advanced SDK management.
- To view the installed Android SDK packages, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Devices > \uicontrol Android >
+ To view the installed Android SDK packages, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Devices > \uicontrol Android >
\uicontrol {SDK Manager} on Windows and Linux or \uicontrol {\QC} >
\uicontrol Preferences > \uicontrol Devices > \uicontrol Android >
\uicontrol {SDK Manager} on \macos.
@@ -229,7 +229,7 @@
\section1 Managing Android Virtual Devices (AVD)
- The available AVDs are listed in \uicontrol Tools > \uicontrol Options
+ The available AVDs are listed in \uicontrol Edit > \uicontrol Preferences
> \uicontrol Devices on Windows and Linux or \uicontrol {\QC} >
\uicontrol Preferences > \uicontrol Devices > on \macos. You can add more
AVDs.
@@ -268,7 +268,7 @@
To create new virtual devices:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices >
\uicontrol Add > \uicontrol {Android Device} on Windows and Linux
or \uicontrol {\QC} > \uicontrol Preferences > \uicontrol Devices >
\uicontrol Add > \uicontrol {Android Device} on \macos to open the
@@ -295,8 +295,8 @@
the application for debugging.
\note \QC cannot debug applications on Android devices if Android Studio is
- running. If the following message is displayed in the \uicontrol Output
- pane, close Android Studio and try again:
+ running. If the following message is displayed in \l {Application Output},
+ close Android Studio and try again:
\badcode
Ignoring second debugger -accepting and dropping.
diff --git a/doc/qtcreator/src/android/deploying-android.qdoc b/doc/qtcreator/src/android/deploying-android.qdoc
index 97c12b936d9..fc5e8d790f1 100644
--- a/doc/qtcreator/src/android/deploying-android.qdoc
+++ b/doc/qtcreator/src/android/deploying-android.qdoc
@@ -138,7 +138,7 @@
\l{androiddeployqt}.
You can view information about what the \c androiddeployqt tool is doing in
- the \uicontrol {Compile Output} pane. To view additional information, select the
+ \l {Compile Output}. To view additional information, select the
\uicontrol {Verbose output} check box.
Select \uicontrol {Add debug server} to include the debug server binary
@@ -161,7 +161,7 @@
\section3 Building AABs
- For testing the application locally, use the APK format, because
+ For testing the application locally, use the APK format because
the package can be uploaded directly to the device and run. For
distribution to the Google Play store, create an AAB by selecting
the \uicontrol {Build Android App Bundle (*.aab)} check box.
@@ -185,7 +185,7 @@
verify that the future versions of your application are actually created by
you.
- \warning Keep the key pair in a safe place and take back up copies, because
+ \warning Keep the key pair in a safe place and take back up copies because
you cannot update the application if you lose the key pair.
You can use \QC to generate a keystore and a \e {self-signed} certificate.
@@ -461,6 +461,16 @@
\li Select \uicontrol Projects > \uicontrol Build >
\uicontrol {Build Android APK} > \uicontrol {Create Templates}.
+ \li Check the path in \uicontrol {Android package source directory}.
+
+ \image qtcreator-android-create-template.png "Create Template dialog"
+
+ \li Select \uicontrol {Copy the Gradle files to Android directory} if you
+ plan to extend the Java part of your Qt application.
+
+ \li Select \uicontrol Finish to copy the template files to the \c android
+ directory and to open the manifest file for editing.
+
\li In the \uicontrol {Package name} field, enter a valid
\l{Package Names}{package name} for the application.
For example, \c {org.example.myapplication}.
diff --git a/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc b/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc
index f035845e3bb..bededd32d49 100644
--- a/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc
+++ b/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc
@@ -61,7 +61,7 @@
\endlist
The bare metal device type accepts custom GDB commands that you specify in
- the device options. You can specify the commands to execute when connecting
+ the device preferences. You can specify the commands to execute when connecting
using a particular debug server provider.
The following debug server providers are supported when using GDB:
@@ -92,7 +92,7 @@
\section1 Specifying Settings for Debug Server Providers
To create connections to bare metal devices using a debug server provider,
- select \uicontrol Tools > \uicontrol Options > \uicontrol Devices
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices
> \uicontrol {Bare Metal} > \uicontrol Add > \uicontrol Default.
The available settings depend on the debug server provider.
@@ -101,7 +101,7 @@
\l{https://github.com/EmBitz/EBlink}{EBlink} is an ARM Cortex-M debug tool
that supports squirrel scripting, live variables, and hot-plugging.
- \image qtcreator-baremetal-eblink.png "Bare metal device options for EBlink"
+ \image qtcreator-baremetal-eblink.png "Bare metal device preferences for EBlink"
To specify settings for \EBlink:
@@ -138,7 +138,7 @@
\l{https://www.segger.com/products/debug-probes/j-link/}{J-Link} is a line
of debug probes by Segger.
- \image qtcreator-baremetal-jlink.png "Bare metal device options for J-Link"
+ \image qtcreator-baremetal-jlink.png "Bare metal device preferences for J-Link"
To specify settings for J-Link debug probes:
@@ -170,7 +170,7 @@
(JTAG) facility. It enables source level debugging with the GDB compiled
for the ARM architecture.
- \image qtcreator-baremetal-openocd.png "Bare metal device options for OpenOCD"
+ \image qtcreator-baremetal-openocd.png "Bare metal device preferences for OpenOCD"
To specify settings for \OpenOCD:
@@ -196,7 +196,7 @@
\l{https://www.st.com/en/development-tools/stm32-programmers.html#products}
{ST-LINK Utility} is used for programming STM32 microcontrollers.
- \image qtcreator-baremetal-stlink.png "Bare metal device options for St-Link"
+ \image qtcreator-baremetal-stlink.png "Bare metal device preferences for St-Link"
To specify settings for St-Link:
@@ -234,7 +234,7 @@
\section3 uVision Simulator
- \image qtcreator-baremetal-uvision-simulator.png "Bare metal device options for uVision Simulator"
+ \image qtcreator-baremetal-uvision-simulator.png "Bare metal device preferences for uVision Simulator"
To specify settings for uVision Simulator or uVision St-Link Debugger:
@@ -251,7 +251,7 @@
\section3 uVision St-Link Debugger
- \image qtcreator-baremetal-uvision-st-link.png "Bare metal device options for uVision St-Link"
+ \image qtcreator-baremetal-uvision-st-link.png "Bare metal device preferences for uVision St-Link"
To specify settings for uVision St-Link Debugger:
@@ -268,13 +268,13 @@
\section1 Adding Bare Metal Devices
- \image qtcreator-baremetal-devices.png "Bare Metal device options"
+ \image qtcreator-baremetal-devices.png "Bare Metal device preferences"
To add a bare metal device:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices
> \uicontrol Add > \uicontrol {Bare Metal Device} >
\uicontrol {Start Wizard}.
@@ -288,10 +288,10 @@
\section1 Building for and Running on Bare Metal Devices
To add a kit for building applications and running them on bare metal
- devices, select \uicontrol Tools > \uicontrol Options > \uicontrol Kits
+ devices, select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits
> \uicontrol Add. For more information, see \l{Adding Kits}.
- \image qtcreator-baremetal-kit.png "Kit options for Bare Metal"
+ \image qtcreator-baremetal-kit.png "Kit preferences for Bare Metal"
You can build applications for and run them on bare metal devices
in the same way as for and on the desktop. For more information, see
diff --git a/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc b/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc
index 45e55f42987..789211b857b 100644
--- a/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc
+++ b/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc
@@ -147,8 +147,8 @@
stored in the CMakeLists.txt.user file, so deleting a build directory
does not delete the initial configuration.
- To be asked before \QC resets the changes, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Build & Run} > \uicontrol CMake >
+ To be asked before \QC resets the changes, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Build & Run} > \uicontrol CMake >
\uicontrol {Ask before re-configuring with initial parameters}.
\image qtcreator-build-run-options-cmake.png "CMake Build & Run options"
@@ -224,7 +224,7 @@
\QC can automatically set up the \l {Setting Up Conan}
{Conan package manager} for use with CMake.
- Select \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} >
+ Select \uicontrol Edit > \uicontrol Preferences > \uicontrol {Build & Run} >
\uicontrol CMake > \uicontrol {Package manager auto setup} to set the
value of the \c CMAKE_PROJECT_INCLUDE_BEFORE variable to the path to a
CMake script that installs dependencies from a \c conanfile.txt,
@@ -237,6 +237,5 @@
\image qtcreator-cmake-clean-steps.png
- The build errors and warnings are parsed and displayed in the
- \l Issues output pane.
+ The build errors and warnings are parsed and displayed in \l Issues.
*/
diff --git a/doc/qtcreator/src/cmake/creator-projects-cmake.qdoc b/doc/qtcreator/src/cmake/creator-projects-cmake.qdoc
index 5cac40c6372..0f0978aa509 100644
--- a/doc/qtcreator/src/cmake/creator-projects-cmake.qdoc
+++ b/doc/qtcreator/src/cmake/creator-projects-cmake.qdoc
@@ -96,7 +96,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol CMake.
\image qtcreator-cmakeexecutable.png
@@ -166,7 +166,7 @@
\endlist
- Warnings and errors are displayed in the \l {Issues} output pane.
+ Warnings and errors are displayed in \l {Issues}.
\section1 Adding External Libraries to CMake Projects
diff --git a/doc/qtcreator/src/debugger/creator-debugger-common.qdocinc b/doc/qtcreator/src/debugger/creator-debugger-common.qdocinc
index 95532c7698b..3daf0484e8e 100644
--- a/doc/qtcreator/src/debugger/creator-debugger-common.qdocinc
+++ b/doc/qtcreator/src/debugger/creator-debugger-common.qdocinc
@@ -148,8 +148,8 @@
\if defined(qtcreator)
\section2 Specifying Breakpoint Settings
- You can specify settings for breakpoints in \uicontrol Tools >
- \uicontrol Options > \uicontrol Debugger. For more information,
+ You can specify settings for breakpoints in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Debugger. For more information,
see \l{Specifying Debugger Settings}.
To use a full absolute path in breakpoints, select the
diff --git a/doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc b/doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc
index f1d74a9d8e9..faef2f96ff5 100644
--- a/doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc
+++ b/doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc
@@ -29,11 +29,11 @@
\section1 Specifying Debugger Settings
- To specify settings for managing debugger processes, select \uicontrol Tools
- > \uicontrol Options > \uicontrol Debugger. In the \uicontrol General tab,
+ To specify settings for managing debugger processes, select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol Debugger. In the \uicontrol General tab,
you can specify settings that are common to all debuggers.
- \image qtcreator-debugger-general-options.png
+ \image qtcreator-debugger-general-options.png "Debugger General preferences"
You can customize the appearance and behavior of the debug views,
\l{Specifying Breakpoint Settings}{specify settings for breakpoints},
@@ -71,10 +71,10 @@
\section2 Specifying GDB Settings
- To specify settings for managing the GDB process, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Debugger > \uicontrol GDB.
+ To specify settings for managing the GDB process, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Debugger > \uicontrol GDB.
- \image qtcreator-gdb-options.png "GDB options"
+ \image qtcreator-gdb-options.png "GDB preferences"
To specify a timeout for terminating non-responsive GDB processes, set the
number of seconds to wait in the \uicontrol {GDB timeout} field. The default
@@ -134,13 +134,13 @@
\section2 Specifying Extended GDB Settings
- To specify extended settings for GBD, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Debugger > \uicontrol {GDB Extended}.
+ To specify extended settings for GBD, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Debugger > \uicontrol {GDB Extended}.
The settings give access to advanced or experimental functions of GDB.
Enabling them may negatively impact your debugging experience, so use
them with care.
- \image qtcreator-gdb-extended-options.png "GDB Extended options"
+ \image qtcreator-gdb-extended-options.png "GDB Extended preferences"
To use asynchronous mode to control the inferior, select the
respective check box.
@@ -162,10 +162,10 @@
\section2 Specifying CDB Settings
- To specify settings for managing the CDB process, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Debugger > \uicontrol CDB.
+ To specify settings for managing the CDB process, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Debugger > \uicontrol CDB.
- \image qtcreator-cdb-options.png "CDB options"
+ \image qtcreator-cdb-options.png "CDB preferences"
You can specify additional arguments for starting CDB in the
\uicontrol {Additional arguments} field.
@@ -203,9 +203,9 @@
views, select the \uicontrol {Use Python dumper} check box.
For more information, see \l{Debugging Helper Implementation}.
- To add information about first-chance and second-chance exceptions
- to the \uicontrol Issues output pane, select the check boxes
- in the \uicontrol {Add Exceptions to the Issues View} group.
+ To display information about first-chance and second-chance exceptions
+ in \l Issues, select the check boxes
+ in the \uicontrol {Add Exceptions to Issues View} group.
\section2 Setting CDB Paths on Windows
@@ -214,7 +214,7 @@
to the symbol search path of the debugger:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Debugger >
\uicontrol {CDB Paths}.
\image qtcreator-debugger-cdb-paths.png
\li In the \uicontrol {Symbol Paths} group, select \uicontrol Insert.
diff --git a/doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc b/doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc
index 84f3132ea29..4f333dfd01a 100644
--- a/doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc
+++ b/doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc
@@ -40,9 +40,9 @@
The main debugger settings are associated with the
\l{glossary-buildandrun-kit}{kit} you build and run your project with. To
specify the debugger and compiler to use for each kit, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Kits.
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits.
- You need to set up the debugger only if the automatic setup fails, because
+ You need to set up the debugger only if the automatic setup fails because
the native debugger is missing (as is usually the case for the CDB debugger
on Windows, which you always must install yourself) or because the installed
version is not supported (for example, when your system contains no, or an
@@ -55,7 +55,7 @@
kit for your project.
If the debugger you want to use is not automatically detected, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Debuggers > \uicontrol Add to add it.
\note To use the debugging tools for Windows, you must install them and add
diff --git a/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc b/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc
index 28265fb9319..12495c11d25 100644
--- a/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc
+++ b/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc
@@ -110,8 +110,9 @@
\QC checks whether the compiled program is up-to-date, and rebuilds and
deploys it if the \uicontrol {Build before deploying} field is set to
build the whole project or the application to run and the
- \uicontrol {Always deploy before running} check box is selected in the
- \uicontrol {Build and Run} options. To debug the program without deploying
+ \uicontrol {Always deploy before running} check box is selected in
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Build & Run} >
+ \uicontrol General. To debug the program without deploying
it, select \uicontrol Debug > \uicontrol {Start Debugging} >
\uicontrol {Start Debugging Without Deployment}.
@@ -120,7 +121,7 @@
When using GDB or CDB as debug backend, you can specify additional commands
to execute before and after the backend and debugged program are started or
- attached in \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
+ attached in \uicontrol Edit > \uicontrol Preferences > \uicontrol Debugger >
\uicontrol GDB and \uicontrol CDB. For more information, see
\l{Specifying Debugger Settings}.
@@ -182,7 +183,7 @@
If a console application does not start up properly in the configured
console and the subsequent attach fails, you can diagnose the issue by
- using CDB's native console. Select \uicontrol Tools > \uicontrol Options >
+ using CDB's native console. Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Debugger > \uicontrol CDB > \uicontrol {Use CDB console} to
override the console set in the Windows system environment variables.
Note that the native console does not prompt on application exit.
@@ -336,7 +337,7 @@
The \QC installation program asks you whether you want to register \QC as a
post-mortem debugger. To change the setting, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Debugger >
\uicontrol General > \uicontrol {Use \QC for post-mortem debugging}.
You can launch the debugger in the post-mortem mode if an application
@@ -405,6 +406,15 @@
applications.
\li Select the \uicontrol {Break at "main"} check box to stop the
debugger at the main function.
+ \li Select the \uicontrol {Use target extended-remote to connect}
+ check box to create the connection in the
+ \c {target extended-remote mode}. In this mode, when the debugged
+ application exits or you detach from it, the debugger remains
+ connected to the target. You can rerun the application, attach
+ to a running application, or use monitor commands specific to the
+ target. For example, GDB does not exit unless it was invoked using
+ the \c {--once} option, but you can make it exit by using the
+ \c {monitor exit} command.
\li In the \uicontrol {Override SysRoot} field, specify the path to
the \c sysroot to use instead of the default \c sysroot.
\li In the \uicontrol {Init commands} field, enter the commands
@@ -424,11 +434,15 @@
By default, a non-responsive GDB process is terminated after 20 seconds.
To increase the timeout in the \uicontrol {GDB timeout} field, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Debugger >
\uicontrol GDB. For more information about settings that you can specify
to manage the GDB process, see \l{Specifying GDB Settings} and
\l{Specifying Extended GDB Settings}.
+ For more informaton about connecting with \c {target extended-remote} mode
+ in GDB, see \l{https://sourceware.org/gdb/onlinedocs/gdb/Connecting.html}
+ {Debugging with GDB: Connecting to a Remote Target}.
+
\section3 Using CDB
In remote mode, the local CDB process talks to a CDB process that runs on
@@ -494,8 +508,8 @@
\endlist
- To specify settings for managing the CDB process, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Debugger > \uicontrol CDB. For more
+ To specify settings for managing the CDB process, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Debugger > \uicontrol CDB. For more
information, see \l{Specifying CDB Settings}.
*/
@@ -643,7 +657,7 @@
\section2 Customizing Debug Views
You can change the appearance and behavior of the debug views by specifying
- settings in \uicontrol Options > \uicontrol Debugger. For example, you can:
+ settings in \uicontrol Preferences > \uicontrol Debugger. For example, you can:
\list
\li Use alternating row colors in debug views.
@@ -674,7 +688,7 @@
the bottom of the view. Output is displayed in the right pane of the
\uicontrol {Debugger Log} view.
- \note Usually, you do not need this feature, because \QC provides you
+ \note Usually, you do not need this feature because \QC provides you
with better ways to handle the task. For example, instead of using the GDB
\c print command from the command line, you can evaluate an expression in
the \uicontrol {Expressions} view.
@@ -754,7 +768,7 @@
When using CDB as debug backend, you can specify that the debugger should
break when application modules are loaded or unloaded. To enable breaking
- for the specified modules, select \uicontrol Tools > \uicontrol Options >
+ for the specified modules, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Debugger > \uicontrol CDB. For more information, see
\l{Specifying CDB Settings}.
@@ -791,7 +805,7 @@
(\uicontrol {Operate by Instruction}) tool button on the debugger tool bar.
By default, GDB shows AT&T style disassembly. To switch to the Intel style,
- select \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol Debugger >
\uicontrol GDB > \uicontrol {Use Intel style disassembly}.
\section2 Viewing and Editing Register State
@@ -861,9 +875,9 @@
To give the user simple access also to these items, \QC employs Python
scripts that are called \e {debugging helpers}.
Debugging helpers are always automatically used. To force a plain C-like
- display of structures, select \uicontrol Tools > \uicontrol Options >
+ display of structures, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Debugger > \uicontrol {Locals & Expressions}, and then deselect
- the \uicontrol {Use Debugging Helper} check box. This will still use the
+ the \uicontrol {Use Debugging Helpers} check box. This will still use the
Python scripts, but generate more basic output. To force the plain display
for a single object or for all objects of a given type, select the
corresponding option from the context menu.
@@ -888,19 +902,21 @@
least one of the three supported backends is available.
To use the default GDB pretty printers installed in your system or linked
- to the libraries your application uses, select \uicontrol Options >
+ to the libraries your application uses, select \uicontrol Preferences >
\uicontrol Debugger > \uicontrol GDB > \uicontrol {Load system GDB pretty
printers}. For more information, see \l{Specifying GDB Settings}.
+ \image qtcreator-gdb-options.png "GDB preferences"
+
\section2 Customizing Built-In Debugging Helpers
You can have commands executed after built-in debugging helpers have
been loaded and fully initialized. To load additional debugging helpers or
- modify existing ones, select \uicontrol Tools > \uicontrol Options >
+ modify existing ones, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Debugger > \uicontrol {Locals & Expressions}, and enter the
commands in the \uicontrol {Debugging Helper Customization} field.
- \image qtcreator-debugging-helper-options.png
+ \image qtcreator-debugging-helper-options.png "Locals & Expressions preferences"
If you receive error messages about receiving signals when using GDB, you
can specify \l{https://sourceware.org/gdb/onlinedocs/gdb/Signals.html}
@@ -918,7 +934,7 @@
\endcode
To display a message box as soon as your application receives a signal
- during debugging, select \uicontrol Tools > \uicontrol Options >
+ during debugging, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Debugger > \uicontrol GDB > \uicontrol {Show a message box
when receiving a signal}.
@@ -931,8 +947,8 @@
To add debugging helpers for custom types, add debugging helper
implementations to the startup file of the native debuggers (for example,
\c{~/.gdbinit} or \c{~/.lldbinit}) or specify them directly in the
- \uicontrol {Additional Startup Commands} in \uicontrol Tools >
- \uicontrol Options > \uicontrol Debugger > \uicontrol GDB.
+ \uicontrol {Additional Startup Commands} in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Debugger > \uicontrol GDB.
To get started with implementing debugging helpers for your own data types,
you can put their implementation into the file
@@ -965,9 +981,9 @@
update your \QC installation (when updating your Qt installation,
for example), copy it to a safe location outside the \QC
installation in your file system and specify the location in
- \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Debugger >
\uicontrol {Locals & Expressions} >
- \uicontrol {Extra Debugging Helpers}.
+ \uicontrol {Extra Debugging Helper}.
\endlist
The custom debugging helpers will be automatically picked up from
@@ -1108,9 +1124,11 @@
common situations.
When using CDB as debugger backend, you can enable the Python dumper by
- selecting \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
+ selecting \uicontrol Edit > \uicontrol Preferences > \uicontrol Debugger >
\uicontrol CDB > \uicontrol {Use Python dumper}.
+ \image qtcreator-cdb-options.png "CDB preferences"
+
\section3 Dumper Class
The \c Dumper class contains generic bookkeeping, low-level, and convenience
@@ -1497,7 +1515,7 @@
You might have created a release build that does not contain debug
information. A GNU Compiler Collection (GCC) debug build has the \c {-g}
option on the compiler command line. Check that this option is present in
- the \uicontrol {Compile Output} pane. If it is not, adjust your build
+ the \l {Compile Output}. If it is not, adjust your build
settings in the \uicontrol Projects mode.
\section1 Debugger Does Not Work
@@ -1544,10 +1562,12 @@
When using GDB as backend, you can automatically save a copy of
its symbol index in a cache on disk and retrieve it from there
- when loading the same binary in the future. Select \uicontrol Tools
- > \uicontrol Options > \uicontrol Debugger > \uicontrol GDB >
+ when loading the same binary in the future. Select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol Debugger > \uicontrol GDB >
\uicontrol {Use automatic symbol cache}.
+ \image qtcreator-gdb-options.png "GDB preferences"
+
Some slowness stems from maintaining breakpoints inside
the debugger (under some circumstances all breakpoints need to be inserted
and removed again for each step) and the evaluation of expressions after
@@ -1564,7 +1584,7 @@
\l{http://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace%20Protection}
{KernelHardening}.
- However, the usefulness of this security measure seems dubious, because this
+ However, the usefulness of this security measure seems dubious because this
feature can be easily disabled. With root permissions, you can disable the
feature temporarily by writing \c{0} into
\c{/proc/sys/kernel/yama/ptrace_scope} or permanently by changing the value
diff --git a/doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc b/doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc
index 51afd4ba68f..9375d05fb65 100644
--- a/doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc
+++ b/doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc
@@ -104,7 +104,7 @@
\image qtquick-example-setting-breakpoint3.png
\li To execute JavaScript commands in the current context, open the
- \uicontrol {QML Debugger Console} output pane.
+ \uicontrol {QML Debugger Console}.
\image qml-script-console.png
diff --git a/doc/qtcreator/src/debugger/qtquick-debugging.qdoc b/doc/qtcreator/src/debugger/qtquick-debugging.qdoc
index 02897e71a94..0934b94e3d7 100644
--- a/doc/qtcreator/src/debugger/qtquick-debugging.qdoc
+++ b/doc/qtcreator/src/debugger/qtquick-debugging.qdoc
@@ -162,6 +162,8 @@
the application from running until the debug client connects to the
server. This enables debugging from the start.
+ \note Setting breakpoints is only possible if the application is started with block mode.
+
\li Select \uicontrol Debug > \uicontrol {Start Debugging} >
\uicontrol {Attach to QML Port}.
@@ -253,8 +255,8 @@
When the application is interrupted by a breakpoint, you can use the
\uicontrol {QML Debugger Console} to execute JavaScript expressions in the
- current context. To open it, choose \uicontrol View >
- \uicontrol {Output Panes} > \uicontrol {QML Debugger Console}.
+ current context. To open it, choose \uicontrol View > \uicontrol Output >
+ \uicontrol {QML Debugger Console}.
\image qml-script-console.png "QML Debugger Console"
diff --git a/doc/qtcreator/src/docker/creator-docker.qdoc b/doc/qtcreator/src/docker/creator-docker.qdoc
new file mode 100644
index 00000000000..5f758065a4e
--- /dev/null
+++ b/doc/qtcreator/src/docker/creator-docker.qdoc
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Creator documentation.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+**
+****************************************************************************/
+
+ /*!
+ \page creator-adding-docker-devices.html
+ \previouspage creator-developing-b2qt.html
+ \nextpage creator-developing-generic-linux.html
+
+ \title Adding Docker Devices
+
+ You can add \l{ https://docs.docker.com/get-started/overview/}
+ {Docker images} as \e devices to run, debug, and analyze applications
+ built for the Docker container from \QC. A Docker device operates like
+ a virtual machine but uses less system resources at the cost of being
+ less flexible.
+
+ Docker support is experimental. While Linux, \macos, and Windows hosts are
+ supported in principle, Linux is the recommended platform.
+
+ Currently, only CMake is supported for building applications in the Docker
+ container.
+
+ You can run applications locally or in a compatible Docker container. To be
+ able to run and debug applications on Docker devices, you must install Docker
+ as well as add Docker devices and select them in the kit. \QC automatically
+ detects kits in the shared Docker directories, but you need to check that
+ they point to the correct kit items.
+
+ Use a wizard to search for Docker images available on your local Docker
+ installation and add them as devices. To access images from Docker hub or
+ other registries, you first need to pull the images using the
+ \l{https://docs.docker.com/engine/reference/commandline/pull/}{docker pull}
+ command. You can edit the Docker device preferences later in
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices.
+
+ To enable the experimental Docker plugin:
+
+ \list 1
+ \li In \QC, select \uicontrol Help > \uicontrol {About Plugins} >
+ \uicontrol Utilities > \uicontrol {Docker (experimental)}.
+ \li Select \uicontrol {Restart Now} to restart \QC and load the plugin.
+ \endlist
+
+ To add a Docker image as a device:
+
+ \list 1
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices
+ > \uicontrol Devices > \uicontrol Add > \uicontrol {Docker Device}
+ > \uicontrol {Start Wizard} to search for images in your local Docker
+ installation.
+ \image qtcreator-docker-image-selection.png "Docker Image Selection dialog"
+ \li Select the Docker image to use, and then select \uicontrol OK.
+ \note If the Docker process is not found, make sure that Docker is
+ running and the Docker CLI executable is set in PATH.
+ \li In \uicontrol Devices, check and modify Docker device preferences.
+ \image qtcreator-docker-preferences.png "Docker Device preferences"
+ \li Select \uicontrol {Run as outside user} to use the user ID and
+ group ID of the user running \QC in the Docker container.
+ \li In \uicontrol {Paths to mount}, specify host directories to mount
+ into the container, such as the project directory.
+ \li Select \uicontrol {Auto-detect Kit Items} to generate an initial
+ \l{Adding Kits}{build and run kit} for the Docker device.
+ \endlist
+
+ \section1 Specifying Paths to Mount
+
+ You can either copy your project files into the Docker container or specify
+ paths to them in \uicontrol {Paths to mount}. Shared mounts are restricted
+ to locations in the host system that can end up in the same absolute location
+ in the Docker container. On Windows, mounted drives cannot be used as shared
+ mounts.
+
+ The paths in \uicontrol {Paths to mount} are mapped one-to-one to the Docker
+ container. Select \uicontrol Insert to browse directories to add. Select
+ \uicontrol {Delete Line} to delete the selected path or \uicontrol Clear
+ to delete all paths.
+
+ \section1 Auto-detecting Kit Items
+
+ Select \uicontrol {Auto-detect Kit Items} to generate an initial
+ \l{Adding Kits}{build and run kit} for the Docker device. You can
+ either set the kit items, such \l{Adding Debuggers}{debuggers} and
+ \l{Adding Qt Versions}{Qt version}, in PATH or install them in the
+ Docker container.
+
+ Select \uicontrol {Search in PATH} to detect kit items that are set in PATH.
+
+ Select \uicontrol {Search in Selected Directories} to detect kit items in
+ the selected directories.
+
+ To view the automatically detected kit items, select
+ \uicontrol {List Auto-Detected Kit Items}. To remove
+ them, select \uicontrol {Remove Auto-Detected Kit Items}.
+
+ \section1 Editing Docker Device Kits
+
+ Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits to check
+ that the automatically generated kit points to the appropriate kit items.
+
+ To specify build settings:
+
+ \list 1
+ \li Open a project for an application you want to develop for the
+ device.
+ \li Select \uicontrol Projects > \uicontrol {Build & Run} to enable
+ the kit that you specified above.
+ \endlist
+
+ Select \uicontrol Run to specify run settings. Usually, you can use
+ the default settings.
+*/
diff --git a/doc/qtcreator/src/editors/creator-clangformat.qdocinc b/doc/qtcreator/src/editors/creator-clangformat.qdocinc
index c7e3e370af9..4267c17b074 100644
--- a/doc/qtcreator/src/editors/creator-clangformat.qdocinc
+++ b/doc/qtcreator/src/editors/creator-clangformat.qdocinc
@@ -36,8 +36,8 @@
\uicontrol {C++} > \uicontrol {ClangFormat}. Then select
\uicontrol {Restart Now} to restart \QC and load the plugin.
- \note If you enable the plugin, do not use the \l{Beautifying Source Code}
- {Beautifier}, because combining the two can provide unexpected results.
+ \note If you enable Clang Format, do not use the \l{Beautifying Source Code}
+ {Beautifier} because combining them can provide unexpected results.
You can use Clang Format to enforce a coding style for a project or the
whole organization. Create a \c {.clang-format} file that contains the
@@ -47,36 +47,28 @@
format file recursively from the directory that contains the source file
up to the file system root.
- To specify global settings for automatic formatting and indentation, you
- must copy the built-in settings and edit the copy:
+ To override the \c {.clang-format} file globally for all projects, select
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {C++} > \uicontrol Copy >
+ \uicontrol Edit > \uicontrol {ClangFormat} >
+ \uicontrol {Override Clang Format configuration file}.
+
+ \image qtcreator-code-style-clang-format.png "C++ Clang Format preferences"
+
+ In \uicontrol {Formatting mode}, select \uicontrol {Indenting Only} to only
+ indent code. Select \uicontrol {Full Formatting} to use the \key {Ctrl+I}
+ keyboard shortcut to format code instead of indenting. To apply the
+ formatting while you type, select \uicontrol {Format while typing}. To apply
+ the formatting to the edited code when you save the file, select
+ \uicontrol {Format edited code on file save}.
- \list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol {C++} >
- \uicontrol Edit > \uicontrol {Copy Built-in Code Style} >
- \uicontrol {ClangFormat}.
- \image qtcreator-code-style-clang-format.png "C++ Clang Format options"
- \li Select the \uicontrol {Format instead of indenting} check box to
- use the \key {Ctrl+I} keyboard shortcut to format code instead of
- indenting it.
- \li Select the \uicontrol {Format while typing} check box to apply the
- formatting while you type code.
- \li Select the \uicontrol {Format edited code on file save} check box
- to apply the formatting to the edited code when you save the file.
- \li Select the \uicontrol {Override Clang Format configuration file}
- check box to create a local configuration file that overrides the
- one stored in the file system.
- \note This is not recommended, because it defeats the purpose of
- a Clang format file.
- \li To modify the values in the file, select them in the left-side
- column and enter the new values.
- \li To view examples of the new values in the right-hand column, select
- \uicontrol Apply.
- \endlist
+ This creates a local configuration file that overrides the one stored in the
+ file system.
- To override the \c {.clang-format} file for a project, select
+ To override the \c {.clang-format} file for a particular project, create a
+ copy of the built-in style and edit its settings by selecting
\uicontrol Projects > \uicontrol {Project Settings} >
- \uicontrol {Code Style} > \uicontrol Edit >
- \uicontrol {Copy Built-in Code Style} > \uicontrol {ClangFormat} >
+ \uicontrol {Code Style} > \uicontrol Copy > \uicontrol Edit >
+ \uicontrol {ClangFormat} >
\uicontrol {Override Clang Format configuration file}.
You can create \c {.clang-format} files that contain the configuration
diff --git a/doc/qtcreator/src/editors/creator-code-completion.qdoc b/doc/qtcreator/src/editors/creator-code-completion.qdoc
index 67d0278b133..d979571998e 100644
--- a/doc/qtcreator/src/editors/creator-code-completion.qdoc
+++ b/doc/qtcreator/src/editors/creator-code-completion.qdoc
@@ -50,10 +50,10 @@
\section1 Specifying Completion Settings
- To specify settings for code completion, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Completion.
+ To specify settings for code completion, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Completion.
- \image qtcreator-options-texteditor-completion.png "Text Editor Completion options"
+ \image qtcreator-options-texteditor-completion.png "Text Editor Completion preferences"
By default, code completion does not consider case. To apply full or
first-letter case-sensitivity, select \uicontrol Full or
@@ -175,13 +175,13 @@
Code snippets specify code constructs. You can add, modify,
and remove snippets in the snippet editor. To open the editor, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Snippets.
\if defined(qtcreator)
The following image shows built-in C++ code snippets:
- \image qtcreator-edit-code-snippets.png "C++ snippet options"
+ \image qtcreator-edit-code-snippets.png "C++ snippet preferences"
\endif
The following image shows built-in QML code snippets:
@@ -257,7 +257,7 @@
project containing the file that is currently open in the editor:
\c {%{CurrentDocument:Project:Name}}.
- Use unique variable names within a snippet, because all instances of a
+ Use unique variable names within a snippet because all instances of a
variable are renamed when you specify a value for it.
To determine the case of values you enter in snippets, use the following
@@ -318,7 +318,7 @@
completion.
To use Nimsuggest, you must install it on the development PC. Then select
- \uicontrol Tools > \uicontrol Options > \uicontrol Nim > \uicontrol Tools,
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Nim > \uicontrol Tools,
and enter the path to the tool executable in the \uicontrol Path field.
\else
\include qtcreator-variables.qdocinc qtcreator variables
diff --git a/doc/qtcreator/src/editors/creator-code-indentation.qdoc b/doc/qtcreator/src/editors/creator-code-indentation.qdoc
index e9ef596caf7..55f82a416b4 100644
--- a/doc/qtcreator/src/editors/creator-code-indentation.qdoc
+++ b/doc/qtcreator/src/editors/creator-code-indentation.qdoc
@@ -31,7 +31,7 @@
\title Indenting Text or Code
When you type text or code, it is indented automatically according to the
- selected text editor or code style options. Select a block to indent it when
+ selected text editor or code style preferences. Select a block to indent it when
you press \key Tab. Press \key {Shift+Tab} to decrease the indentation. You
can disable automatic indentation.
@@ -76,19 +76,19 @@
In addition, you can import and export code style settings.
To automatically fix indentation according to the indentation settings
- when you save the file, select \uicontrol Tools > \uicontrol Options >
+ when you save the file, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Text Editor} > \uicontrol Behavior >
\uicontrol {Clean whitespace} > \uicontrol {Clean indentation}. Select
the \uicontrol {Skip clean whitespace for file types} check box to
exclude the specified file types.
- \image qtcreator-options-text-editor-behavior.png "Text Editor Behavior options"
+ \image qtcreator-options-text-editor-behavior.png "Text Editor Behavior preferences"
- To visualize whitespace in the editor, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Display >
+ To visualize whitespace in the editor, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Display >
\uicontrol {Visualize whitespace}.
- \image qtcreator-options-text-editor-display.png "Text Editor Display options"
+ \image qtcreator-options-text-editor-display.png "Text Editor Display preferences"
To help you keep line length at a particular number of characters, set the
number of characters in the \uicontrol {Display right margin at column}
@@ -103,13 +103,13 @@
To specify indentation settings for the C++ editor:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol {C++}.
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol {C++}.
\li In the \uicontrol {Current settings} field, select the settings to
modify and click \uicontrol Copy.
- \image qtcreator-options-code-style-cpp.png "C++ Code Style options"
+ \image qtcreator-options-code-style-cpp.png "C++ Code Style preferences"
\li Give a name to the settings and click \uicontrol OK.
\li Click \uicontrol Edit to specify code style settings for the project.
- \image qtcreator-code-style-settings-edit-cpp.png "Edit Code Style Settings dialog"
+ \image qtcreator-code-style-settings-edit-cpp.png "Edit Code Style dialog"
\endlist
You can specify how to:
@@ -126,10 +126,10 @@
\li Name getter functions.
\endlist
- You can use the live preview to see how the options change the indentation.
+ You can use the live preview to see how the preferences change the indentation.
To specify different settings for a particular project, select
- \uicontrol Projects > \uicontrol {Code Style Settings}.
+ \uicontrol Projects > \uicontrol {Code Style}.
\include creator-clangformat.qdocinc clang format
\endif
@@ -139,21 +139,24 @@
To specify settings for the Qt Quick editor:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Qt Quick}.
\li In the \uicontrol {Current settings} field, select the settings to
modify and click \uicontrol Copy.
- \image qtcreator-options-code-style-qml.png "QML Code Style options"
+ \image qtcreator-options-code-style-qml.png "QML Code Style preferences"
\li Give a name to the settings and click \uicontrol OK.
\li Click \uicontrol Edit to specify code style settings for the project.
- \image qtcreator-code-style-settings-edit-qtquick.png "Edit Code Style Settings dialog"
+ \image qtcreator-code-style-settings-edit-qtquick.png "Edit Code Style dialog"
\endlist
You can specify how to interpret the \key Tab key presses and how to align
continuation lines.
+ In \uicontrol {Line length}, you can adjust the maximum line length for
+ code lines.
+
To specify different settings for a particular project, select
- \uicontrol Projects > \uicontrol {Code Style Settings}.
+ \uicontrol Projects > \uicontrol {Code Style}.
\if defined(qtcreator)
\section1 Indenting Nim Files
@@ -161,13 +164,13 @@
To specify settings for the Nim editor (experimental):
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Nim.
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Nim.
\li In the \uicontrol {Current settings} field, select the settings to
modify and click \uicontrol Copy.
- \image qtcreator-options-code-style-nim.png "Nim Code Style options"
+ \image qtcreator-options-code-style-nim.png "Nim Code Style preferences"
\li Give a name to the settings and click \uicontrol OK.
\li Click \uicontrol Edit to specify code style settings for the project.
- \image qtcreator-code-style-settings-edit-nim.png "Edit Code Style Settings dialog"
+ \image qtcreator-code-style-settings-edit-nim.png "Edit Code Style dialog"
\endlist
You can specify how to interpret the \key Tab key presses and how to align
@@ -180,10 +183,10 @@
\section1 Indenting Other Text Files
To specify indentation settings for text files that do not contain C++ or
- QML code (such as Python code files), select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Behavior.
+ QML code (such as Python code files), select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Behavior.
- \image qtcreator-indentation.png "Text Editor Behavior options"
+ \image qtcreator-indentation.png "Text Editor Behavior preferences"
To specify different settings for a particular project, select
\uicontrol Projects > \uicontrol Editor.
@@ -226,11 +229,11 @@
select \uicontrol {With Spaces}. To follow the \uicontrol {Tab policy},
select \uicontrol {With Regular Indent}.
- \section1 Specifying Typing Options
+ \section1 Setting Typing Preferences
When you type text or code, it is indented automatically according to the
- selected text editor or code style options. To specify typing options,
- select \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ selected text editor or code style preferences. To set typing preferences,
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Behavior > \uicontrol Typing.
To disable automatic indentation, deselect the
@@ -263,21 +266,21 @@
You can also indent statements within functions and blocks and declarations
within namespaces.
- \image qtcreator-code-style-content.png "Content options"
+ \image qtcreator-code-style-content.png "Content preferences"
\section1 Specifying Settings for Braces
You can indent class, namespace, enum and function declarations and code
blocks.
- \image qtcreator-code-style-braces.png "Braces options"
+ \image qtcreator-code-style-braces.png "Braces preferences"
\section1 Specifying Settings for Switch Statements
You can indent case or default statements, or statements or blocks related
to them within switch statements.
- \image qtcreator-code-style-switch.png "Switch options"
+ \image qtcreator-code-style-switch.png "Switch preferences"
\section1 Specifying Alignment
@@ -290,7 +293,7 @@
aligned with the following line. Usually, this only affects \c if
statements.
- \image qtcreator-code-style-alignment.png "Alignment options"
+ \image qtcreator-code-style-alignment.png "Alignment preferences"
\section1 Binding Pointers and References
@@ -301,6 +304,6 @@
The \c * and \c & characters are automatically bound to identifiers of
pointers to functions and pointers to arrays.
- \image qtcreator-pointers-references.png "Pointers and References options"
+ \image qtcreator-pointers-references.png "Pointers and References preferences"
\endif
*/
diff --git a/doc/qtcreator/src/editors/creator-code-refactoring.qdoc b/doc/qtcreator/src/editors/creator-code-refactoring.qdoc
index 371aaeee16c..cadf6684a1f 100644
--- a/doc/qtcreator/src/editors/creator-code-refactoring.qdoc
+++ b/doc/qtcreator/src/editors/creator-code-refactoring.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -44,7 +44,7 @@
\l{Applying Refactoring Actions}.
By default, the refactored files are saved automatically. To disable
- this feature, deselect \uicontrol Tools > \uicontrol Options >
+ this feature, deselect \uicontrol Edit > \uicontrol Preferences >
\uicontrol System > \uicontrol {Auto-save files after refactoring}.
\if defined(qtcreator)
@@ -89,8 +89,8 @@
\endif
\endlist
- The \uicontrol {Search Results} pane shows the location
- and number of search hits in the current project.
+ \l{Search Results} shows the location and number of search hits in the
+ current project.
\if defined(qtcreator)
\image qtcreator-refactoring-find.png
@@ -101,12 +101,11 @@
You can browse the search results in the following ways:
\list
- \li To go directly to an instance, double-click the instance in the
- \uicontrol {Search Results} pane.
+ \li To go directly to an instance, double-click the instance in
+ \uicontrol {Search Results}.
\li To move between instances, click the \inlineimage icons/next.png
(\uicontrol {Next Item}) button and \inlineimage icons/prev.png
- (\uicontrol {Previous Item}) button in the
- \uicontrol {Search Results} pane.
+ (\uicontrol {Previous Item}) button in \uicontrol {Search Results}.
\li To expand and collapse the list of all instances, click the
\inlineimage icons/qtcreator-expand.png
(\uicontrol {Expand All}) button.
@@ -139,7 +138,7 @@
\uicontrol {QML/JS} > \uicontrol {Rename Symbol Under Cursor}
or press \key {Ctrl+Shift+R}.
- The \uicontrol {Search Results} pane shows the location
+ \uicontrol {Search Results} shows the location
and number of instances of the symbol in the current project.
\if defined(qtcreator)
@@ -153,30 +152,15 @@
To omit an instance, deselect the check box next to the instance.
\note This action replaces all selected instances of the symbol in
- all files listed in the \uicontrol {Search Results} pane. You cannot
+ all files listed in \uicontrol {Search Results}. You cannot
undo this action.
\if defined(qtcreator)
If the symbol is a class, select the \uicontrol {Rename files} check
box to also change the filenames that match the class name.
- \note Renaming local symbols does not open the \uicontrol {Search Results}
- pane. The instances of the symbol are highlighted in code and you can edit
+ \note Renaming local symbols does not open \uicontrol {Search Results}.
+ The instances of the symbol are highlighted in code and you can edit
the symbol. All instances of the local symbol are changed as you type.
\endif
-
- \section1 Multi-Cursor Editing
-
- To apply a change to several places simultaneously, press and hold \key Alt,
- and click to place cursors in several places. Any changes you make are
- applied simultaneously at all the cursor positions.
-
- Use the arrow keys to move all the cursors up and down. The \key Home and
- \key End key move all the cursors to the beginning or to the end of the
- line.
-
- Press and hold \key Alt and double-click strings to select several strings
- simultaneously.
-
- Press \key Esc to remove all the cursors and selections.
*/
diff --git a/doc/qtcreator/src/editors/creator-code-syntax.qdoc b/doc/qtcreator/src/editors/creator-code-syntax.qdoc
index 8da7ba560af..e646c74178c 100644
--- a/doc/qtcreator/src/editors/creator-code-syntax.qdoc
+++ b/doc/qtcreator/src/editors/creator-code-syntax.qdoc
@@ -31,35 +31,25 @@
\title Checking Code Syntax
As you write code, \QC checks code syntax. When \QC spots a syntax error in
- your code it underlines it and shows error details when you move the mouse
- pointer over the error. Similarly, when you are working on an instance of a
- JavaScript object notation (JSON) entity, \QC underlines errors in JSON data
- structure.
+ your code, it underlines it, displays an icon, and shows error details when
+ you move the mouse pointer over the error or the icon. If a fix is available,
+ you can apply it by clicking \inlineimage icons/refactormarker.png
+ .
+
+ Similarly, when you are working on an instance of a JavaScript object
+ notation (JSON) entity, \QC underlines errors in the JSON data structure.
\if defined(qtcreator)
- In the following screenshot, \QC points out an error, because a semicolon is
+ In the following screenshot, \QC annotates an error because a semicolon is
missing at the end of the line:
\image qtcreator-syntaxerror.png
- In the following screenshot, \QC issues a warning, because the variable is
+ In the following screenshot, \QC issues a warning because the variable is
not used:
\image qtcreator-semanticerror.png
- To modify the colors used for underlining errors and warnings, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
- \uicontrol {Font & Colors} > \uicontrol Copy, and select new colors for
- \uicontrol Error and \uicontrol Warning.
-
- \section1 Viewing Annotations
-
- When using the Clang code model, errors and warnings are additionally marked
- with icons and annotated. If a \l{http://clang.llvm.org/diagnostics.html}
- {Clang fix-it} is available, you can execute it by clicking the
- \inlineimage icons/refactormarker.png
- icon and pressing \key Enter.
-
In the following screenshot, a Qt class name contains a typo:
\image qtcreator-typo-clang.png
@@ -69,14 +59,10 @@
the \uicontrol {Annotation Settings} link to specify the position
of the line annotations.
- In the following screenshot, a semicolon is missing at the end of the
- line.
-
- \image qtcreator-syntaxerror-clang.png
-
- In the following screenshot, the variable is not used.
-
- \image qtcreator-semanticerror-clang.png
+ To modify the colors used for underlining errors and warnings, select
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
+ \uicontrol {Font & Colors} > \uicontrol Copy, and select new colors for
+ \uicontrol Error and \uicontrol Warning.
\else
In addition to underlining, errors and warnings are marked with icons and
@@ -87,17 +73,17 @@
\image qml-syntax-check.png
- \section2 Specifying Line Annotation Positions
+ \section1 Specifying Line Annotation Positions
To specify the position where the annotations are displayed, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Display > \uicontrol {Line annotations}, and then select
whether to display the annotations directly next to the code, aligned
to the right of the code, or in the right margin. Showing annotations
between lines can be useful if there is usually not enough space to
display annotations next to the text.
- \image qtcreator-options-text-editor-display.png "Text Editor Display options"
+ \image qtcreator-options-text-editor-display.png "Text Editor Display preferences"
If you hide the annotations by deselecting the check box, you can move the
mouse pointer over an icon to view them.
@@ -108,7 +94,7 @@
find common problems. To run the checks, select \uicontrol Tools >
\uicontrol {QML/JS} > \uicontrol {Run Checks} or press \key {Ctrl+Shift+C}.
The results are shown in the \uicontrol QML and \uicontrol {QML Analysis}
- filters of the \uicontrol Issues output pane.
+ filters in \l Issues.
Many of the error messages are similar to the ones in Douglas Crockford's
\l{http://www.jslint.com}{JSLint} tool. For more information about JSLint
@@ -747,7 +733,9 @@
\section1 Automatically Formatting QML/JS Files
- To automatically format QML/JS files upon saving, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Qt Quick} > \uicontrol {QML/JS Editing} >
+ To automatically format QML/JS files upon saving, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Qt Quick} > \uicontrol {QML/JS Editing} >
\uicontrol {Enable auto format on file save}.
+
+ \image qtcreator-qml-js-editing.png "QML/JS Editing preferences"
*/
diff --git a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc
index 60fafe368bb..c4b8d14873e 100644
--- a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc
+++ b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -109,7 +109,7 @@
\section2 Changing Text Encoding
To show the file encoding of the current file on the editor toolbar (5),
- select \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Display > \uicontrol {Display file encoding}.
To change the text encoding, click it on the toolbar and select new
@@ -125,10 +125,12 @@
\section2 Selecting Line Ending Style
To switch between Windows line endings (CRLF) and Unix line endings (LF),
- select the ending style on the editor toolbar (6).
+ select the ending style on the editor toolbar (6). To hide this field,
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor}
+ > \uicontrol Display, and deselect \uicontrol {Display file line ending}.
To set the line endings to use for all projects by default, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Behavior, and then select the ending style in the
\uicontrol {Default line endings} field.
@@ -138,6 +140,41 @@
For more information, see \l {Specifying Editor Settings}.
\endif
+ \section1 Editing Selected Lines
+
+ The \uicontrol Edit > \uicontrol Advanced menu contains options for editing
+ selected lines of text.
+
+ To duplicate the selected lines, select \uicontrol {Duplicate Selection}.
+ To format the duplicated lines as a comment, select
+ \uicontrol {Duplicate Selection and Comment}.
+
+ To turn selected text into lowercase, select \uicontrol {Lowercase Selection}
+ or press \key {Alt+U}. To turn it into uppercase, select
+ \uicontrol {Uppercase Selection} or press \key {Alt+Shift+U}.
+
+ To sort selected lines alphabetically, select \uicontrol {Sort Selected Lines}
+ or press \key {Alt+Shift+S}.
+
+ Select \uicontrol {Add Next Occurrence to Selection} or press \key {Ctrl+D}
+ to add a cursor at the next occurrence of selected text for multi-cursor
+ editing.
+
+ \section1 Multi-Cursor Editing
+
+ To apply a change to several places simultaneously, press and hold \key Alt,
+ and click to place cursors in several places. Any changes you make are
+ applied simultaneously at all the cursor positions.
+
+ Use the arrow keys to move all the cursors up and down. The \key Home and
+ \key End key move all the cursors to the beginning or to the end of the
+ line.
+
+ Press and hold \key Alt and double-click strings to select several strings
+ simultaneously.
+
+ Press \key Esc to remove all the cursors and selections.
+
\section1 Splitting the Editor View
Split the editor view or open the editor in a new window when you want to
@@ -250,8 +287,8 @@
splits opened, you can open the link in the next split by holding \key Ctrl
and \key Alt while clicking the symbol.
- To enable this moving function, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Behavior >
+ To enable this moving function, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Behavior >
\uicontrol {Enable mouse navigation}.
There are several additional ways of moving between symbol definitions and
@@ -278,7 +315,7 @@
split, prepend \key {Ctrl+E} to the shortcut. For example, press
\key {Ctrl+E,F2} to follow the symbol in the next split. If necessary, the
view is automatically split. To change the default behavior, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Display > \uicontrol {Always open links in another split}.
Additional symbols are
displayed and switching between definition and declaration is done in
diff --git a/doc/qtcreator/src/editors/creator-diff-editor.qdoc b/doc/qtcreator/src/editors/creator-diff-editor.qdoc
index a0a65b50ebc..bc8f79659b3 100644
--- a/doc/qtcreator/src/editors/creator-diff-editor.qdoc
+++ b/doc/qtcreator/src/editors/creator-diff-editor.qdoc
@@ -122,9 +122,9 @@
\section1 Changing the Colors
- To change the default colors, select \uicontrol Tools > \uicontrol Options >
+ To change the default colors, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Text Editor} > \uicontrol {Font & Colors}. Create your own color
- scheme and select new colors for the following options:
+ scheme and select new colors for the following items:
\list
diff --git a/doc/qtcreator/src/editors/creator-editors-options-text.qdoc b/doc/qtcreator/src/editors/creator-editors-options-text.qdoc
index d6448754483..5840f5defbe 100644
--- a/doc/qtcreator/src/editors/creator-editors-options-text.qdoc
+++ b/doc/qtcreator/src/editors/creator-editors-options-text.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -40,11 +40,12 @@
\title Specifying Text Editor Settings
- Set the font preferences and apply color schemes for syntax highlighting in
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ Set the font preferences and apply color schemes for syntax highlighting,
+ diff editor, and code analysis results in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol {Font & Colors}.
- \image qtcreator-font-colors.png "Text editor options"
+ \image qtcreator-font-colors.png "Text editor preferences"
\section2 Configuring Fonts
@@ -52,7 +53,7 @@
percentage for viewing the text. You can also zoom in or out by pressing
\key {Ctrl++} or \key {Ctrl+-}, or by pressing \key Ctrl and rolling
the mouse button up or down. To disable the mouse wheel function, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Behavior and deselect the
\uicontrol {Enable scroll wheel zooming} check box.
@@ -62,35 +63,34 @@
\section2 Defining Color Schemes
- You can select one of the predefined color schemes for syntax highlighting
- or create customized color schemes. The color schemes apply to highlighting
- both C++ and QML files and generic files.
+ You can select one of the predefined color schemes or create customized
+ color schemes.
To create a color scheme:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Text Editor} > \uicontrol {Fonts & Color} >
\uicontrol Copy.
\li Enter a name for the color scheme and click \uicontrol OK.
\li In the \uicontrol Foreground field, specify the color of the selected
- code element.
+ code element or message.
\li In the \uicontrol Background field, select the background
- color for the code element.
+ color for the code element or message.
The backgound of the \uicontrol Text element determines the background of the
code editor.
\li In \uicontrol Font, select \uicontrol Bold or \uicontrol Italic to
- format the text of the selected code element by making it bold or
- italic.
+ format the text of the selected code element or message by making it
+ bold or italic.
\li In \uicontrol Underline, select the color and style to use for
- underlining code elements.
+ underlining code elements or messages.
\endlist
@@ -101,7 +101,7 @@
\section2 Exporting and Importing Color Schemes
To share color schemes with others, export and import them as XML files.
- To export a color scheme, select \uicontrol Tools > \uicontrol Options >
+ To export a color scheme, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Text Editor} > \uicontrol {Fonts & Color} > \uicontrol Export,
and then select the filename and location for the XML file.
@@ -116,11 +116,11 @@
\section2 File Encoding
- To define the default file encoding, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Behavior, and
+ To define the default file encoding, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Behavior, and
then select a suitable option in \uicontrol {Default encoding}.
- \image qtcreator-options-texteditor-behavior-file-encodings.png "File encoding options"
+ \image qtcreator-options-texteditor-behavior-file-encodings.png "File encoding preferences"
Qt 5 and Qt 6 require UTF-8 encoded source files, and therefore the default
encoding is set to \uicontrol UTF-8.
diff --git a/doc/qtcreator/src/editors/creator-editors-options.qdoc b/doc/qtcreator/src/editors/creator-editors-options.qdoc
index a2e9d740b4a..6812e826ef7 100644
--- a/doc/qtcreator/src/editors/creator-editors-options.qdoc
+++ b/doc/qtcreator/src/editors/creator-editors-options.qdoc
@@ -41,9 +41,9 @@
\title Configuring the Editor
You can configure the text editor to suit your specific needs by selecting
- \uicontrol Tools > \uicontrol Options > \uicontrol{Text Editor}.
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol{Text Editor}.
- \image qtcreator-font-colors.png "Text Editor options"
+ \image qtcreator-font-colors.png "Text Editor preferences"
The settings you specify apply globally to all projects.
diff --git a/doc/qtcreator/src/editors/creator-locator.qdoc b/doc/qtcreator/src/editors/creator-locator.qdoc
index f3e82ea396c..67b82a7b5f3 100644
--- a/doc/qtcreator/src/editors/creator-locator.qdoc
+++ b/doc/qtcreator/src/editors/creator-locator.qdoc
@@ -247,7 +247,7 @@
\li In the locator, click \inlineimage icons/magnifier.png
(\uicontrol Options) and select \uicontrol Configure to open the
- \uicontrol Locator options.
+ \uicontrol Locator preferences.
\li Select a filter, and then select \uicontrol Edit.
@@ -256,7 +256,7 @@
\li To implicitly include the filter even when not typing a prefix as a
part of the search string, select \uicontrol {Include by default}.
- \li Specify other available options. For more information, see
+ \li Set other available preferences. For more information, see
\l{Adding Web Search Engines}.
\endlist
@@ -276,7 +276,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment > \uicontrol Locator >
\uicontrol {Web Search (prefix: r)} > \uicontrol Edit.
@@ -305,9 +305,9 @@
\list 1
\li In the locator, select \uicontrol Options >
- \uicontrol Configure to open the \uicontrol Locator options.
+ \uicontrol Configure to open the \uicontrol Locator preferences.
- \image qtcreator-locator-customize.png "Locator options tab"
+ \image qtcreator-locator-customize.png "Locator preferences"
\li Select \uicontrol Add > \uicontrol {Files in Directories} to add
a directory filter or \uicontrol {URL Template} to add a URL
@@ -352,7 +352,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment > \uicontrol Locator.
\li In \uicontrol {Refresh interval}, define new time in minutes.
diff --git a/doc/qtcreator/src/editors/creator-only/creator-beautifier.qdoc b/doc/qtcreator/src/editors/creator-only/creator-beautifier.qdoc
index dca905d6120..a391d54c8b0 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-beautifier.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-beautifier.qdoc
@@ -51,7 +51,7 @@
The Beautifier plugin parses the source code into component structures, such
as assignment statements, if blocks, loops, and so on, and formats them as
- specified in the Beautifier options. You can use a predefined style or
+ specified in the Beautifier preferences. You can use a predefined style or
define your own style.
To use the Beautifier plugin:
@@ -75,14 +75,14 @@
\li Select \uicontrol {Restart Now} to restart \QC and load the plugin.
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Beautifier to specify settings for beautifying files.
\li Select the \uicontrol {Enable auto format on file save} check box to
automatically beautify files when you save them using the tool you
select in the \uicontrol Tool field.
- \image qt-creator-beautifier-options-general.png "General Beautifier options"
+ \image qt-creator-beautifier-options-general.png "General Beautifier preferences"
\li In the \uicontrol {Restrict to MIME types} field, define the MIME
types of the files to beautify, separated by semicolons. Leave the
@@ -101,7 +101,7 @@
\uicontrol Uncrustify to specify settings for the tool you want to
use.
- \image beautifier_options.png "Uncrustify Beautifier options"
+ \image beautifier_options.png "Uncrustify Beautifier preferences"
\li In the \uicontrol Configuration group, specify the path to
the tool executable in the \uicontrol {Artistic Style command},
@@ -140,7 +140,7 @@
button, and then selecting the style to use from the list of
available styles.
- \image qtcreator-beautifier-options-clangformat.png "Clang Format Beautifier options"
+ \image qtcreator-beautifier-options-clangformat.png "Clang Format Beautifier preferences"
Select \uicontrol File to load the style configuration from
the \c .clang-format or \c _clang-format file located in the
@@ -164,7 +164,7 @@
\endlist
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Beautifier
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Beautifier
> \uicontrol {Artistic Style}, \uicontrol ClangFormat, or
\uicontrol Uncrustify > \uicontrol {Format Current File} to format
the currently open file.
diff --git a/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc b/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc
index d6f5709c372..dfaeb7c7b52 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc
@@ -65,7 +65,7 @@
\endlist
\QC comes with a plugin that provides some of these services
- for C++ on top of \l{http://clang.llvm.org/}{Clang}.
+ for C++ on top of \l{https://clangd.llvm.org/}{Clangd}.
\section1 About the Clang Code Model
@@ -75,6 +75,8 @@
set or a close approximation, as when using the built-in \QC code model.
Clang focuses on detailed information for diagnostics, which is really
useful if the code contains typos, for example.
+ We make use of these libraries via the clangd tool, which implements
+ an \l{https://microsoft.github.io/language-server-protocol/}{LSP} server.
Clang keeps up with the development of the C++ language. At the time of this
writing, it supports C++98/03, C++11, C++14, C++17, C89, C99, Objective-C,
@@ -98,14 +100,16 @@
\li \l{Using Clang Tools}{Diagnostics}
\li Outline of symbols
\li Tooltips
- \li Renaming of local symbols
+ \li Following symbols
+ \li Renaming symbols
+ \li Finding occurrences of symbols
\endlist
- To use the built-in code model instead, select \uicontrol Help >
- \uicontrol {About Plugins} > \uicontrol C++, and deselect the
- \uicontrol ClangCodeModel check box. Select \uicontrol {Restart Now}
- to restart \QC and have the changes take effect.
+ To use the built-in code model instead, select \uicontrol Edit > \uicontrol Preferences >
+ \uicontrol C++ > \uicontrol clangd, and deselect the \uicontrol {Use clangd} check box.
+ This setting also exists on the project level, so that you can have the clang-based
+ services generally enabled, but switch them off for for certain projects, or vice versa.
You can configure Clang diagnostics either globally or separately for:
@@ -120,10 +124,10 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol C++ >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol C++ >
\uicontrol {Code Model}.
- \image qtcreator-clang-code-model-options.png
+ \image qtcreator-clang-code-model-options.png "C++ Code Model preferences"
\li To instruct the code model to interpret ambiguous header files as C
language files if you develop mainly using C, select the
@@ -138,13 +142,6 @@
edit the value for the \uicontrol {Do not index files greater than}
check box. To index all files, deselect the check box.
- \li The \uicontrol {Diagnostic Configuration} field shows the Clang
- checks to perform. Click the value of the field to open the
- \uicontrol {Diagnostic Configurations} dialog, where you can
- select and edit the checks to perform.
-
- \image qtcreator-diagnostics-configuration.png
-
\endlist
\section1 Configuring clangd
@@ -164,9 +161,9 @@
To specify settings for clangd:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol C++ >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol C++ >
\uicontrol Clangd > \uicontrol {Use clangd}.
- \image qtcreator-options-clangd.png "clangd options"
+ \image qtcreator-options-clangd.png "clangd preferences"
\li In \uicontrol {Path to executable}, enter the path to clangd
version 13, or later.
\li For more accurate results during global symbol searches, select
@@ -179,6 +176,13 @@
\li In \uicontrol {Document update threshold}, specify the amount of
time \QC waits before sending document changes to the server.
If the document changes again while waiting, this timeout is reset.
+ \li Select \uicontrol {Ignore files greater than} to make parsing faster
+ by ignoring big files. Specify the maximum size of files to parse in
+ the field next to the check box.
+ \li The \uicontrol {Diagnostic Configuration} field shows the Clang
+ checks to perform. Click the value of the field to open the
+ \uicontrol {Diagnostic Configurations} dialog, where you can
+ select and edit the checks to perform.
\endlist
\section1 Clang Checks
@@ -203,16 +207,7 @@
\section1 Specifying Clang Code Model Settings at Project Level
You can specify Clang code model settings at project level by selecting
- \uicontrol Projects > \uicontrol {Clang Code Model}.
-
- In addition to configuring the diagnostics,
- you can select the \uicontrol {Enable MSVC-compliant template parsing} check
- box to parse templates in a MSVC-compliant way. This enables Clang to parse
- headers for example from Active Template Library (ATL) or Windows Runtime
- Library (WRL). However, using the relaxed and extended rules means that no
- highlighting or completion can be provided within template functions.
-
- \image qtcreator-clang-code-model-build-settings.png
+ \uicontrol Projects > \uicontrol {clangd}.
\include creator-compilation-database.qdocinc using compilation databases
diff --git a/doc/qtcreator/src/editors/creator-only/creator-code-pasting.qdoc b/doc/qtcreator/src/editors/creator-only/creator-code-pasting.qdoc
index 5fbc28c8323..952eee54b2e 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-code-pasting.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-code-pasting.qdoc
@@ -45,9 +45,9 @@
To specify settings for the code pasting service:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Code Pasting}.
- \image qtcreator-code-pasting-options.png "Code Pasting options"
+ \image qtcreator-code-pasting-options.png "Code Pasting preferences"
\li In the \uicontrol {Default protocol} field, select a code pasting
service to use by default.
\li In the \uicontrol Username field, enter your username.
@@ -56,9 +56,9 @@
\li Select the \uicontrol {Copy-paste URL to clipboard} check box to
copy the URL of the post on the code pasting service to the
clipboard when you paste a post.
- \li Select the \uicontrol {Display Output pane after sending a post}
- check box to display the URL in the \uicontrol {General Messages}
- output pane when you paste a post.
+ \li Select the \uicontrol {Display General Messages after sending a post}
+ check box to display the URL in \l{Viewing Output}{General Messages}
+ when you paste a post.
\endlist
Select \uicontrol Fileshare to specify the path to a shared network drive.
@@ -70,8 +70,7 @@
To paste a snippet of code onto the server, select \uicontrol Tools >
\uicontrol {Code Pasting} > \uicontrol {Paste Snippet} or press
\key {Alt+C,Alt+P}. By default, \QC copies the URL of the snippet to the
- clipboard and displays the URL in the \uicontrol {General Messages} output
- pane.
+ clipboard and displays the URL in \uicontrol {General Messages}.
To paste any content that you copied to the clipboard, select
\uicontrol Tools > \uicontrol {Code Pasting} > \uicontrol {Paste Snippet}.
diff --git a/doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc b/doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc
index 6d5217e657f..c95018f14ca 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc
@@ -115,10 +115,10 @@
\section2 Plugin Emulation
FakeVim also emulates some popular vim plugins. To enable plugin emulation
- for particular plugins, select \uicontrol Tools > \uicontrol Options >
+ for particular plugins, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol FakeVim > \uicontrol General > \uicontrol {Plugin Emulation}.
- \image qtcreator-fakevim-options-general-plugin-emulation.png "FakeVim Plugin Emulation options"
+ \image qtcreator-fakevim-options-general-plugin-emulation.png "FakeVim Plugin Emulation preferences"
Currently emulated plugins:
\list
@@ -291,12 +291,12 @@
\section1 Mapping FakeVim Commands
To map commands entered on the \uicontrol FakeVim command line to
- \QC functions, select \uicontrol Tools > \uicontrol Options >
+ \QC functions, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol FakeVim > \uicontrol {Ex Command Mapping}.
Enter a string in the \uicontrol Filter field to search for a specific
\QC function.
- \image qtcreator-fakevim-options-ex-command-mapping.png "FakeVim Ex Command Mapping options"
+ \image qtcreator-fakevim-options-ex-command-mapping.png "FakeVim Ex Command Mapping preferences"
Select a function in the list, and enter a string that will trigger the
function in the \uicontrol {Regular expression} field. You can view the
@@ -306,19 +306,19 @@
To reset the trigger expressions for all functions, select
\uicontrol {Reset All}.
- To map \e {user commands} to keyboard shortcuts, select \uicontrol Tools >
- \uicontrol Options > \uicontrol FakeVim >
+ To map \e {user commands} to keyboard shortcuts, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol FakeVim >
\uicontrol {User Command Mapping}. The user command mapped to the shortcut
is executed by FakeVim as if you were typing it (as when replaying a macro).
- \image qtcreator-fakevim-options-user-command-mapping.png "FakeVim User Command Mapping options"
+ \image qtcreator-fakevim-options-user-command-mapping.png "FakeVim User Command Mapping preferences"
- \section1 Specifying FakeVim Options
+ \section1 Setting FakeVim Preferences
- To make changes to the Vim-style settings, select \uicontrol Tools >
- \uicontrol Options > \uicontrol FakeVim > \uicontrol General.
+ To make changes to the Vim-style settings, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol FakeVim > \uicontrol General.
- \image qtcreator-fakevim-options.png "FakeVim options"
+ \image qtcreator-fakevim-options.png "FakeVim preferences"
To preselect the indentation settings specified for the text editor, select
\uicontrol {Copy Text Editor Settings}. To preselect the Qt coding style,
@@ -326,13 +326,13 @@
select \uicontrol {Set Plain Style}. You can then change any of the
preselected settings.
- To use a Vim-style color scheme, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol {Fonts & Color}.
+ To use a Vim-style color scheme, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol {Fonts & Color}.
In the \uicontrol {Color Scheme} list, select \uicontrol {Vim (dark)}.
\section1 Quitting FakeVim Mode
- To quit the FakeVim mode, unselect \uicontrol Tools > \uicontrol Options >
+ To quit the FakeVim mode, unselect \uicontrol Edit > \uicontrol Preferences >
\uicontrol FakeVim > \uicontrol {Use FakeVim} or press \key {Alt+V,Alt+V}.
You can temporarily escape FakeVim mode to access the normal \QC keyboard
diff --git a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc
index 001e85c1462..80ee71d960f 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc
@@ -40,7 +40,7 @@
\li \l{Completing Code}{Code completion}
\li Sending document formatting requests to the language server to
automatically format documents using the settings specified in
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor}
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor}
> \uicontrol Behavior
\li Highlighting the symbol under cursor
\li \l{Viewing Function Tooltips}{Viewing function tooltips}
@@ -79,33 +79,31 @@
\section1 Specifying Settings for Language Clients
- You can add a generic generic stdIO language server for Python, for example.
- For \l{Connecting Android Devices}{Android development}, you can add a Java
- language server.
+ \QC supports adding a Java language server for
+ \l{Connecting Android Devices}{Android development}. A Python language
+ server is added by default and you can edit its preferences.
+ For other languages, you can add generic stdIO language servers.
- \section2 Adding Language Servers
-
- To view a list of language servers, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Language Client} (or
- \uicontrol {Qt Creator} > \uicontrol Preferences >
- \uicontrol {Language Client} > on \macos).
-
- \image qtcreator-language-client-options.png "Language client options page"
+ To add language servers, select \uicontrol Edit > \uicontrol Preferences >
+ \uicontrol {Language Client} > \uicontrol Add (or \uicontrol {Qt Creator} >
+ \uicontrol Preferences > \uicontrol {Language Client} > \uicontrol Add
+ on \macos).
To enable a language server, select the check box next to the language
- server name and specify settings for the server.
+ server name and set server preferences.
To remove language servers from the list, select \uicontrol Delete.
- \section2 Specifying Generic Settings
+ \section2 Generic StdIO Language Server
To add a generic language server:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Language Client} > \uicontrol Add >
- \uicontrol {New Generic StdIO Language Server}
+ \uicontrol {Generic StdIO Language Server}
to add a generic language server.
+ \image qtcreator-language-server-generic-stdio.png
\li In the \uicontrol Name field, enter a name for the language server.
Select the \inlineimage icons/replace.png
(\uicontrol {Variables}) button to use a variable for the server
@@ -116,11 +114,12 @@
patterns to extend the MIME types, separated by semicolons.
\li In the \uicontrol {Startup behavior} field, select whether the
language server is started when \QC starts or when a project or file
- with a matching MIME type is opened. The
- \uicontrol {General Messages} \l{Viewing Output}{output pane}
- displays information about the connection to the language server.
- \li In the \uicontrol Initialization field, you can add language server
- specific JSON attributes to pass to an \c initialize request.
+ with a matching MIME type is opened. \l{Viewing Output}
+ {General Messages} displays information about the connection to the
+ language server.
+ \li In the \uicontrol {Initialization options} field, you can add
+ language server specific JSON attributes to pass to an \c initialize
+ request.
\li In the \uicontrol Executable field, enter the path to the language
server executable.
\li In the \uicontrol Arguments field, enter any required command line
@@ -128,15 +127,15 @@
arguments.
\endlist
- \section2 Specifying Java Language Server Settings
+ \section2 Java Language Server
To add a Java language server:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Language Client} > \uicontrol Add >
- \uicontrol {New Java Language Server} to add a Java language server.
- \image qtcreator-language-client-options-java.png "Java language server options"
+ \uicontrol {Java Language Server} to add a Java language server.
+ \image qtcreator-language-client-options-java.png "Java language server preferences"
\li In the \uicontrol Name field, enter a name for the language server.
Select the \inlineimage icons/replace.png
(\uicontrol {Variables}) button to use a variable for the server
@@ -146,6 +145,35 @@
the Java language server \c .jar file.
\endlist
+ \section2 Python Language Server
+
+ To set preferences for Python language servers:
+
+ \list 1
+ \li Select \uicontrol Edit > \uicontrol Preferences >
+ \uicontrol Python > \uicontrol {Language Server Configuration} to
+ select the Python language server plugins to use.
+ \image qtcreator-python-plugins.png "Python Language Server Configuration"
+ \li Select \uicontrol Advanced to configure the plugins.
+ \image qtcreator-python-advanced.png "Python language server plugin configuration"
+ \endlist
+
+ For a complete list of configuration options, see
+ \l{https://github.com/python-lsp/python-lsp-server/blob/develop/CONFIGURATION.md}
+ {Python Language Server Configuration}.
+
+ To disable the Python language server, deselect
+ \uicontrol {Use Python Language Server}.
+
+ \section2 Qml Language Server
+
+ Qt 6.4 ships with the qmlls language server that provides completions and warnings for QML.
+ It can be set up as a \l {Generic StdIO Language Server}, selecting \c {text/x-qml} and
+ \c {application/x-qt.ui+qml} as MIME Types, and \c {<Qt Installation>/bin/qmlls} as executable.
+
+ If the language server is used together with the QmlJSEditor plugin duplicate suggestions and
+ warnings might be shown. To avoid this you might want to disable it as described in
+ \l {Enabling and Disabling Plugins}.
\section1 Supported Locator Filters
@@ -166,12 +194,12 @@
responses that contain the requested information if the language server is
capable of handling the requests. To inspect the communication between \QC
and language servers and view server capabilities, select \uicontrol Tools
- > \uicontrol {Debug \QC} > \uicontrol {Inspect Language Client}.
+ > \uicontrol {Debug \QC} > \uicontrol {Inspect Language Clients}.
\image qtcreator-language-client-inspector-log.png "Language Client Inspector dialog"
The dialog shows a list of running language servers. The value of the
- \uicontrol {Startup behavior} field in the language server options
+ \uicontrol {Startup behavior} field in the language server preferences
determines when the server is started. The information displayed depends on
the language server.
@@ -201,11 +229,11 @@
For a clangd server, you can inspect the total amount of memory used by a
particular component in \uicontrol {Memory Usage}.
- \image qtcreator-language-client-inspector-capabilities.png "Language Client Inspector Capabilities tab"
+ \image qtcreator-language-client-inspector-memory-usage.png "Language Client Inspector Memory Usage tab"
\section1 Reporting Issues
- The language service client has been mostly tested with Python and Java.
+ The language server client has been mostly tested with Python and Java.
If problems arise when you try them or some other language, please select
\uicontrol Help > \uicontrol {Report Bug} to report them in the
\l{https://bugreports.qt.io/}{Qt Project Bug Tracker}. The reports
diff --git a/doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc b/doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc
index 5fefdd89317..ee916d9b140 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc
@@ -68,7 +68,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment > \uicontrol {MIME Types}.
\image qtcreator-mime-types.png "MIME Types"
@@ -99,7 +99,7 @@
numerical types, whereas masks for strings must be in base 16, and
start with 0x.
- \note You are recommended not to change the range and priority,
+ \note You are recommended not to change the range and priority
because it might cause problems when opening files in \QC.
\li Click \uicontrol OK to return to the \uicontrol {MIME Types} tab.
diff --git a/doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc b/doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc
index 19edbf37843..fadaa0853f9 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc
@@ -90,7 +90,7 @@
chart, select \inlineimage icons/statistics.png
(\uicontrol {View Statistics}).
- To search from the state chart, use the \uicontrol Search pane. The search
+ To search from the state chart, use \l {Search Results}. The search
checks the whole SCXML tree for attributes that match the search criteria.
To save the currently visible part of the state chart as an image, select
diff --git a/doc/qtcreator/src/editors/creator-only/creator-text-editing-macros.qdoc b/doc/qtcreator/src/editors/creator-only/creator-text-editing-macros.qdoc
index 17b15106276..d61f341c871 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-text-editing-macros.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-text-editing-macros.qdoc
@@ -46,13 +46,13 @@
\uicontrol {Text Editing Macros} > \uicontrol {Save Last Macro}.
To assign a keyboard shortcut to a text editing macro, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Environment >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment >
\uicontrol Keyboard. For more information, see
\l{Configuring Keyboard Shortcuts}.
You can also use the \c rm locator filter to run a macro. For more
information, see \l{Searching with the Locator}.
- To view and remove saved macros, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Macros.
+ To view and remove saved macros, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Macros.
*/
diff --git a/doc/qtcreator/src/editors/creator-quick-fixes.qdoc b/doc/qtcreator/src/editors/creator-quick-fixes.qdoc
index e3fd168cb06..5236950d402 100644
--- a/doc/qtcreator/src/editors/creator-quick-fixes.qdoc
+++ b/doc/qtcreator/src/editors/creator-quick-fixes.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -104,17 +104,18 @@
You can specify settings for the refactoring actions either globally for
all projects or separately for each project. To specify global options,
- select \uicontrol Tools > \uicontrol Options > \uicontrol C++ >
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol C++ >
\uicontrol {Quick Fixes}.
To specify custom settings for a particular project, select
\uicontrol Projects > \uicontrol {Project Settings} >
- \uicontrol {Quick Fixes} > \uicontrol {Custom Settings}.
+ \uicontrol {Quick Fixes}, and then deselect \uicontrol {Use global settings}.
\image qtcreator-refactoring-options-locations.png "Quick Fixes settings"
To revert to global settings, select \uicontrol {Reset to Global}. To
- delete the custom settings, select \uicontrol {Delete Custom Settings File}.
+ delete the custom settings, select \uicontrol {Use global settings}, and
+ then select \uicontrol {Delete Custom Settings File}.
\section2 Function Locations
diff --git a/doc/qtcreator/src/editors/creator-search.qdoc b/doc/qtcreator/src/editors/creator-search.qdoc
index 5d4315b8610..17b88f9824a 100644
--- a/doc/qtcreator/src/editors/creator-search.qdoc
+++ b/doc/qtcreator/src/editors/creator-search.qdoc
@@ -117,7 +117,7 @@
The locations of search hits, breakpoints, and bookmarks in your document
are highlighted on the editor scroll bar. To turn highlighting off, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Display > \uicontrol {Highlight search results on the scrollbar}.
To search using more advanced options, select \uicontrol Advanced.
@@ -200,8 +200,8 @@
\image qtcreator-searchresults.png
- A list of files containing the searched text is displayed in the
- \uicontrol {Search Results} pane.
+ A list of files containing the searched text is displayed in
+ \l {Search Results}.
\list
@@ -266,7 +266,7 @@
\li If Silver Searcher is not found, you might have installed it in a
location that is not found via the \c{PATH} environment variable.
- Select \uicontrol Tools > \uicontrol Options > \uicontrol Environment >
+ Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment >
\uicontrol System (or \uicontrol {\QC} > \uicontrol Preferences >
\uicontrol Environment > \uicontrol System on macOS), then select
\uicontrol Change in the \uicontrol Environment field and add an entry
diff --git a/doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc b/doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc
index 42983fe6325..3e255f3f37e 100644
--- a/doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc
+++ b/doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc
@@ -42,7 +42,7 @@
\endlist
To specify the color scheme to use for semantic highlighting, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol {Fonts & Color}.
\QC supports syntax highlighting also for other types of files than C++,
@@ -66,22 +66,22 @@
If more than one highlight definition is available for the file that you
open for editing, the editor asks you to select the one to use. To save
the selection, select \uicontrol {Remember My Choice}. To reset the
- remembered definitions, select \uicontrol Tools > \uicontrol Options >
+ remembered definitions, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Text Editor} > \uicontrol {Generic Highlighter} >
\uicontrol {Reset Remembered Definitions}.
If the editor cannot find the highlight definition for a file that you open
for editing, it prompts you to download additional highlight definition
files. Select \uicontrol {Download Definitions} to download the files.
- Information about the downloaded files is displayed in the
- \uicontrol {General Messages} \l{Viewing Output}{output pane}.
+ Information about the downloaded files is displayed in \l{Viewing Output}
+ {General Messages}.
To suppress the message for a particular file pattern, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor}
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor}
> \uicontrol {Generic Highlighter} and add the pattern to the
\uicontrol {Ignored file patterns} field.
- \image qtcreator-syntax-highlighter.png "Generic Highlighter options"
+ \image qtcreator-syntax-highlighter.png "Generic Highlighter preferences"
If you have written your own syntax definition files, you
can provide an additional definition search path in the
@@ -97,23 +97,23 @@
\image qtcreator-blockhighlighting.png
- To enable block highlighting, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Display >
+ To enable block highlighting, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Display >
\uicontrol {Highlight blocks}.
Use the folding markers to collapse and expand blocks of code within braces.
Click the folding marker to collapse or expand a block. In the figure above,
the folding markers are located between the line number and the text pane.
- To show the folding markers, select \uicontrol Tools > \uicontrol Options >
+ To show the folding markers, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Text Editor} > \uicontrol Display >
\uicontrol {Display folding markers}. This option is enabled by default.
- \image qtcreator-options-text-editor-display.png "Text Editor Display options"
+ \image qtcreator-options-text-editor-display.png "Text Editor Display preferences"
When the cursor is on a brace, the matching brace is animated by default. To
turn off the animation and just highlight the block and the braces, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Display and deselect \uicontrol {Animate matching parentheses}.
You can use keyboard shortcuts to move within and between blocks. To go to
@@ -125,8 +125,8 @@
To select the current block, press \key Ctrl+U. A second key press extends
the selection to the parent block. To undo the last selection, press
\key {Ctrl+Alt+Shift+U}. To enable smart block selection, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Behavior > \uicontrol {Enable smart selection changing}.
- \image qtcreator-options-text-editor-behavior.png "Text Editor Behavior options"
+ \image qtcreator-options-text-editor-behavior.png "Text Editor Behavior preferences"
*/
diff --git a/doc/qtcreator/src/howto/creator-external-tools.qdoc b/doc/qtcreator/src/howto/creator-external-tools.qdoc
index 35aae547c7e..6c2a576a1de 100644
--- a/doc/qtcreator/src/howto/creator-external-tools.qdoc
+++ b/doc/qtcreator/src/howto/creator-external-tools.qdoc
@@ -104,7 +104,7 @@
\section1 Configuring External Tools
You can change the configuration of preconfigured tools and configure
- additional tools in \QC \uicontrol Options.
+ additional tools in \QC \uicontrol Preferences.
\image qtcreator-external-tools.png
@@ -135,8 +135,8 @@
working directory.
\li In the \uicontrol Output field, select how to handle output from the
- tool. You can ignore the output, view it in the \uicontrol {General
- Messages} output pane, or replace the selected text with the
+ tool. You can ignore the output, view it in \l{Viewing Output}
+ {General Messages}, or replace the selected text with the
output in the code editor.
\li In the \uicontrol {Error output} field, select how to handle error
@@ -163,7 +163,7 @@
To globally change the system environment from the one in which
- \QC is started, select \uicontrol Tools > \uicontrol Options >
+ \QC is started, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment > \uicontrol System, and then select
\uicontrol Change in the \uicontrol Environment field.
\if defined(qtcreator)
diff --git a/doc/qtcreator/src/howto/creator-help.qdoc b/doc/qtcreator/src/howto/creator-help.qdoc
index 712f9abed3c..b41034b9920 100644
--- a/doc/qtcreator/src/howto/creator-help.qdoc
+++ b/doc/qtcreator/src/howto/creator-help.qdoc
@@ -57,7 +57,7 @@
space, in the fullscreen \uicontrol Help mode.
\li To select and configure how the documentation is displayed in the
- \uicontrol Help mode, select \uicontrol Tools > \uicontrol Options > \uicontrol Help.
+ \uicontrol Help mode, select \uicontrol Edit > \uicontrol Preferences > \uicontrol Help.
\endlist
The following image displays the context sensitive help in the \uicontrol Edit
@@ -66,10 +66,10 @@
\image qtcreator-context-sensitive-help.png
If the help HTML file does not use a style sheet, you can change the font
- family, style, and size in \uicontrol Tools > \uicontrol Options >
+ family, style, and size in \uicontrol Edit > \uicontrol Preferences >
\uicontrol Help > \uicontrol General.
- \image qtcreator-help-options.png
+ \image qtcreator-help-options.png "Help General preferences"
You can set the default zoom level in the \uicontrol Zoom field. When
viewing help pages, you can use the mouse scroll wheel to zoom them. To
@@ -87,8 +87,8 @@
\section1 Viewing Function Tooltips
- To hide function tooltips by default, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Behavior >
+ To hide function tooltips by default, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Behavior >
\uicontrol {Show help tooltips using the mouse} >
\uicontrol {On Shift+Mouseover}. You can still view the tooltips by pressing
and holding down the \key Shift key.
@@ -103,7 +103,7 @@
By default, \QC registers only the latest available version of the
documentation for each installed Qt module. To register all installed
- documentation, select \uicontrol Tools > \uicontrol Options >
+ documentation, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Kits > \uicontrol {Qt Versions} >
\uicontrol {Register documentation}.
@@ -148,7 +148,7 @@
\endlist
- To import and export bookmarks, select \uicontrol Tools > \uicontrol Options
+ To import and export bookmarks, select \uicontrol Edit > \uicontrol Preferences
> \uicontrol Help > \uicontrol General > \uicontrol {Import Bookmarks} or
\uicontrol {Export Bookmarks}.
@@ -207,7 +207,7 @@
For information on how to prepare your documentation and create a
.qch file, see \l{The Qt Help Framework}.
- \li To add the .qch file to \QC, select \uicontrol Tools > \uicontrol Options >
+ \li To add the .qch file to \QC, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Help > \uicontrol Documentation > \uicontrol Add.
\endlist
@@ -219,8 +219,8 @@
space, the help opens in the full-screen help mode.
You can specify that the help always opens in full-screen mode or
- is detached to an external window. Select \uicontrol Tools >
- \uicontrol Options > \uicontrol Help > \uicontrol General and specify
+ is detached to an external window. Select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Help > \uicontrol General and specify
settings for displaying context-sensitive help
in the \uicontrol {On context help} field. To detach the help window, select
\uicontrol {Always Show in External Window}.
@@ -231,11 +231,11 @@
\section1 Selecting the Start Page
You can select the page to display when you open the \uicontrol Help mode in the
- \uicontrol Tools > \uicontrol Options > \uicontrol Help > \uicontrol General
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Help > \uicontrol General
> \uicontrol {On help start} field.
To display the page and help views that were open when you exited the mode,
select the \uicontrol {Show My Tabs from Last Session} option. However, Web pages
- are not opened, because loading them would slow down opening the \uicontrol Help
+ are not opened because loading them would slow down opening the \uicontrol Help
mode.
To display a particular page, select \uicontrol {Show My Home Page}, and specify
@@ -261,10 +261,10 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Help >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Help >
\uicontrol Filters.
- \image qtcreator-help-filter-attributes.png "Filters tab in Help options"
+ \image qtcreator-help-filter-attributes.png "Filters tab in Help preferences"
\li Select \inlineimage icons/plus.png
to add a new filter in the \uicontrol {Add Filter} dialog.
diff --git a/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc b/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc
index a323726b775..e6b54c15f01 100644
--- a/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc
+++ b/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc
@@ -50,7 +50,7 @@
To view all functions available in \QC and the keyboard shortcuts defined
for them, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Environment >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment >
\uicontrol Keyboard. The shortcuts are listed by category. To find a keyboard
shortcut in the list, enter a function name or shortcut in the \uicontrol Filter
field.
@@ -75,12 +75,12 @@
To override the platform default value that determines whether
keyboard shortcuts are shown in the labels of context menu items,
- select \uicontrol Tools > \uicontrol Options > \uicontrol Environment >
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment >
\uicontrol Interface. The label of the \uicontrol {Show keyboard shortcuts
in context menus} check box indicates whether the platform default value
is \c on or \c off.
- \image qtcreator-options-environment-interface.png "Interface tab in the Environment options"
+ \image qtcreator-options-environment-interface.png "Interface tab in the Environment preferences"
\section1 Configuring Keyboard Shortcuts
@@ -88,7 +88,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Environment
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment
> \uicontrol Keyboard.
\li Select a command from the list.
@@ -227,22 +227,22 @@
\li Switch to \uicontrol Help mode
\li Ctrl+6
\row
- \li Toggle \uicontrol{Issues} pane
+ \li Toggle \uicontrol{Issues}
\li Alt+1 (Cmd+1 on \macos)
\row
- \li Toggle \uicontrol{Search Results} pane
+ \li Toggle \uicontrol{Search Results}
\li Alt+2 (Cmd+2 on \macos)
\row
- \li Toggle \uicontrol{Application Output} pane
+ \li Toggle \uicontrol{Application Output}
\li Alt+3 (Cmd+3 on \macos)
\row
- \li Toggle \uicontrol{Compile Output} pane
+ \li Toggle \uicontrol{Compile Output}
\li Alt+4 (Cmd+4 on \macos)
\row
- \li Toggle other output panes
+ \li Toggle other output views
\li Alt+number (Cmd+number on \macos)
- Where the number is the number of the output pane.
+ Where the number is the number of the view.
\if defined(qtcreator)
\row
\li Activate \uicontrol Bookmarks view
@@ -255,13 +255,13 @@
\li Activate \uicontrol{Open Documents} view
\li Alt+O
\row
- \li Maximize output panes
+ \li Maximize output views
\li Alt+9
\row
- \li Move to next item in output panes
+ \li Move to next item in output
\li F6
\row
- \li Move to previous item in output panes
+ \li Move to previous item in output
\li Shift+F6
\row
\li Activate \uicontrol Projects view
@@ -290,7 +290,7 @@
By default, \QC exits without asking for confirmation, unless
there are unsaved changes in open files. To always be asked,
select the \uicontrol {Ask for confirmation before exiting}
- check box in \uicontrol Tools > \uicontrol Options >
+ check box in \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment > \uicontrol System.
\li Ctrl+Q
\endtable
@@ -388,8 +388,8 @@
\li Select the current block
The second press extends the selection to the parent block. To
- enable this behavior, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} >
+ enable this behavior, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} >
\uicontrol Behavior >
\uicontrol {Enable smart selection changing}.
\li Ctrl+U
@@ -476,12 +476,19 @@
\li F4
\endif
\row
+ \li Add a cursor at the next occurrence of selected text for
+ multi-cursor editing
+ \li Ctrl+D
+ \row
\li Turn selected text into lowercase
\li Alt+U
\row
\li Turn selected text into uppercase
\li Alt+Shift+U
\row
+ \li Sort selected lines alphabetically
+ \li Alt+Shift+S
+ \row
\li Run static checks on JavaScript code to find common problems
\li Ctrl+Shift+C
\row
diff --git a/doc/qtcreator/src/howto/creator-only/creator-autotest.qdoc b/doc/qtcreator/src/howto/creator-only/creator-autotest.qdoc
index 89064fe4de2..0cea2e6451e 100644
--- a/doc/qtcreator/src/howto/creator-only/creator-autotest.qdoc
+++ b/doc/qtcreator/src/howto/creator-only/creator-autotest.qdoc
@@ -61,7 +61,7 @@
The handling of build system based tests is disabled by default to avoid
interference with code based parsers. To enable build system based tests,
- select the respective test tool in \uicontrol Options > \uicontrol Testing
+ select the respective test tool in \uicontrol Preferences > \uicontrol Testing
> \uicontrol General.
The detection of tests is usually much faster for build system based
@@ -332,7 +332,7 @@
\li In the \uicontrol Tests view, select the tests to run.
- \li In the \uicontrol {Test Results} output pane, select:
+ \li In the \uicontrol {Test Results}, select:
\list
\li \inlineimage icons/run_small.png
@@ -367,8 +367,8 @@
with the build system.
If a test takes more than a minute to execute, the default timeout might
- stop the test execution. To increase the timeout, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Testing} > \uicontrol General.
+ stop the test execution. To increase the timeout, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Testing} > \uicontrol General.
\section2 Selecting Tests to Run
@@ -415,10 +415,10 @@
\section1 Specifying Test Settings
To customize the handling of tests, test frameworks, and test tools, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Testing} >
\uicontrol General.
- \image qtcreator-autotests-options.png
+ \image qtcreator-autotests-options.png "Testing General preferences"
You can customize some settings at project level. To change settings
for the current project instead of globally, select \uicontrol Projects >
@@ -437,8 +437,8 @@
are omitted by default. To view them, deselect the \uicontrol {Omit internal
messages} and \uicontrol {Omit run configuration warnings} check boxes.
- By default, test result output is limited to 100,000 characters. The output
- pane is automatically scrolled down when new results are added. To display
+ By default, test result output is limited to 100,000 characters. The view
+ is automatically scrolled down when new results are added. To display
full results, deselect the \uicontrol {Limit result output} check box.
To disable automatic scrolling, deselect the
\uicontrol {Automatically scroll results} check box.
@@ -464,8 +464,8 @@
The code inside a benchmark test is measured, and possibly also repeated
several times in order to get an accurate measurement. This depends on the
measurement back-end that you can select in the
- \uicontrol {Benchmark Metrics} group in \uicontrol Tools >
- \uicontrol Options > \uicontrol {Testing} > \uicontrol {Qt Test}:
+ \uicontrol {Benchmark Metrics} group in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Testing} > \uicontrol {Qt Test}:
walltime, CPU tick counter, event counter, Valgrind Callgrind, and Linux
Perf. For more information, see \l{Creating a Benchmark}.
@@ -487,8 +487,8 @@
\section2 Specifying Settings for Running Google Tests
- To specify settings for running Google tests, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Testing} > \uicontrol {Google Test}.
+ To specify settings for running Google tests, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Testing} > \uicontrol {Google Test}.
\image qtcreator-autotests-options-google.png
@@ -515,8 +515,8 @@
\section2 Specifying Settings for Running Boost Tests
\list 1
- \li To specify settings for running Boost tests, select \uicontrol Tools
- > \uicontrol Options > \uicontrol {Testing} >
+ \li To specify settings for running Boost tests, select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol {Testing} >
\uicontrol {Boost Test}.
\image qtcreator-autotests-options-boost.png
\li In the \uicontrol {Log format} field, select the error report
@@ -539,9 +539,9 @@
\section2 Specifying Settings for Running Catch2 Tests
\list 1
\li To specify settings for running Catch2 tests, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Testing} >
\uicontrol {Catch Test}.
- \image qtcreator-autotests-options-catch2.png "Catch Test options"
+ \image qtcreator-autotests-options-catch2.png "Catch Test preferences"
\li Select the \uicontrol {Show success} check box to show succeeding
expressions as well. By default Catch2 will print only fails.
\li Select the \uicontrol {Break on failure while debugging} check box
@@ -571,9 +571,9 @@
\section2 Specifying Settings for Running CTest-Based Tests
\list 1
\li To specify settings for running CTest-based tests, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Testing} >
\uicontrol {CTest}.
- \image qtcreator-autotests-options-ctest.png "CTest options"
+ \image qtcreator-autotests-options-ctest.png "CTest preferences"
\li Select the \uicontrol {Output on failure} check box to show test
specific output if a test fails. Contrary to the CTest default
this is enabled by default.
@@ -598,21 +598,21 @@
\section1 Viewing Test Output
- The test results are displayed in the \uicontrol {Test Results} output pane
+ The test results are displayed in \l{Viewing Output}{Test Results}
in XML format. XML can be parsed more easily and reliably than plain text.
However, if a Qt test crashes, it might not produce complete XML code that
can be parsed, which might lead to information loss. The lost information
might be retrievable when viewing the results as plain text.
- To view the results of Qt tests as plain text, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Testing} > \uicontrol {Qt Test}, and
+ To view the results of Qt tests as plain text, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Testing} > \uicontrol {Qt Test}, and
then deselect the \uicontrol {Use XML output} check box. Then select the
\inlineimage icons/text.png
- (\uicontrol {Switch Between Visual and Text Display}) button in the
- \uicontrol {Test Results} output pane to switch to the text display.
+ (\uicontrol {Switch Between Visual and Text Display}) button in
+ \uicontrol {Test Results} to switch to the text display.
- The following table lists the messages that the \uicontrol {Test Results}
- output pane displays:
+ The following table lists the messages that \uicontrol {Test Results}
+ displays:
\table
\header
diff --git a/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc b/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc
index cbee052d365..b4f0c52fb78 100644
--- a/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc
+++ b/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc
@@ -43,7 +43,7 @@
\li \l {Move between open files}
\li \l {Switch to Edit mode}
\li \l {Find a specific setting}
- \li \l {Open output panes}
+ \li \l {View output}
\li \l {Find keyboard shortcuts}
\li \l {Run \QC from the command line}
\li \l {Show and hide sidebars}
@@ -111,16 +111,19 @@
\section1 Find a specific setting
- To find specific settings in \uicontrol Tools > \uicontrol Options,
- use the filter located at the top left of the \uicontrol Options dialog box.
+ To find specific settings in \uicontrol Edit > \uicontrol Preferences,
+ use the filter located at the top left of the \uicontrol Preferences dialog.
- \section1 Open output panes
+ \section1 View output
- The \l{Viewing Output}{output panes} provide a list of errors and warnings
- encountered during a build, detailed output from the compiler, status of a
- program when it is executed, debug output, and search results.
+ The \l{Viewing Output}{taskbar} provides different views to output from
+ several sources, such as a list of errors and warnings encountered during
+ a build, detailed output from the compiler, status of a program when it is
+ executed, debug output, or search results.
- To open output panes, use the following shortcuts:
+ \image qtcreator-output-panes-taskbar.png "Output on the taskbar"
+
+ To view different types of output, use the following shortcuts:
\list
@@ -134,7 +137,7 @@
\endlist
- For additional ways to open all output panes, see \l{Viewing Output}.
+ For additional ways to view other types of output, see \l{Viewing Output}.
\section1 Find keyboard shortcuts
@@ -142,8 +145,10 @@
You can see the keyboard shortcut for a menu command in the menu
or the tooltip for a button.
- To customize, import, or export keyboard shortcuts, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Environment > \uicontrol Keyboard.
+ To customize, import, or export keyboard shortcuts, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Environment > \uicontrol Keyboard.
+
+ \image qtcreator-keyboard-shortcuts.png "Keyboard preferences"
\section1 Run \QC from the command line
@@ -191,8 +196,9 @@
If an instance of a class is derived from QObject, and you would like to
find all other objects connected to one of your object's slots using
- Qt's signals and slots mechanism, select \uicontrol Tools > \uicontrol Options
- > \uicontrol{Debugger} > \uicontrol{Locals} > \uicontrol{Use Debugging Helper}.
+ Qt's signals and slots mechanism, select \uicontrol Edit > \uicontrol Preferences
+ > \uicontrol {Debugger} > \uicontrol {Locals & Expressions} >
+ \uicontrol {Use Debugging Helpers}.
In the \uicontrol{Locals} view, expand the object's entry and open
the slot in the \e slots subitem. The objects connected to this slot are
@@ -210,10 +216,10 @@
To switch off the debugging helpers:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
- \uicontrol{Locals}.
-
- \li Uncheck the \uicontrol{Use Debugging Helper} checkbox.
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Debugger >
+ \uicontrol {Locals & Expressions}.
+ \image qtcreator-debugging-helper-options.png "Locals & Expressions preferences"
+ \li Deselect \uicontrol {Use Debugging Helpers}.
\endlist
@@ -224,11 +230,10 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Debugger > \uicontrol General.
-
- \li Select the \uicontrol {Use tooltips in main editor while debugging} check
- box.
+ \image qtcreator-debugger-general-options.png "Debugger General preferences"
+ \li Select \uicontrol {Use tooltips in main editor when debugging}.
\endlist
@@ -250,8 +255,12 @@
create your own locator filters. That way you can locate files in a
directory structure you have defined.
- To create locator filters, select \uicontrol Tools > \uicontrol Options >
- \uicontrol Locator > \uicontrol Add.
+ \image qtcreator-locator.png "List of locator filters"
+
+ To create locator filters, select \uicontrol Edit > \uicontrol Preferences >
+ \uicontrol Environment > \uicontrol Locator > \uicontrol Add.
+
+ \image qtcreator-locator-customize.png "Locator preferences"
For more information, see \l{Creating Locator Filters}.
@@ -270,9 +279,13 @@
\section1 Add a license header template for C++ code
- A file containing a license header for C++ can be specified under
- \uicontrol Tools > \uicontrol Options > \uicontrol C++ >
- \uicontrol {License Template}. It may contain special placeholders enclosed
+ Specify a file containing a license header for C++ in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol C++ > \uicontrol {File Naming} >
+ \uicontrol {License template}.
+
+ \image qtcreator-options-cpp-files.png "File Naming preferences"
+
+ The license file may contain special placeholders enclosed
in \c{%%} that are replaced when generating a new file:
\list 1
@@ -303,7 +316,7 @@
\section1 Enclose selected code in curly braces, parentheses, or double quotes
When you have selected code and enter one of the following opening
- characters, the appropriate closing character is added automatically
+ characters, the matching closing character is added automatically
at the end of the selection:
\list
@@ -312,6 +325,12 @@
\li "
\endlist
+ To specify whether to automatically insert matching characters,
+ select \uicontrol Edit > \uicontrol Preferences >
+ \uicontrol {Text Editor} > \uicontrol Completion.
+
+ \image qtcreator-options-texteditor-completion.png "Completion preferences"
+
\section1 Select the enclosing block in C++
Press \key {Ctrl+U}.
@@ -319,9 +338,11 @@
\section1 Add my own code snippets to the auto-complete menu
You can add, modify, and remove snippets in the snippet editor.
- To open the editor, select \uicontrol Tools > \uicontrol Options
+ To open the editor, select \uicontrol Edit > \uicontrol Preferences
> \uicontrol {Text Editor} > \uicontrol Snippets.
+ \image qtcreator-snippet-modifiers.png "Snippets preferences"
+
For more information, see \l {Adding and Editing Snippets}.
\section1 Quickly write down notes somewhere
@@ -341,10 +362,12 @@
\section1 Configure the amount of recent files shown
- Select \uicontrol Tools > \uicontrol Options, and change the value of the
- list under \uicontrol Environment > \uicontrol System
+ Set the value of \uicontrol Edit > \uicontrol Preferences >
+ \uicontrol Environment > \uicontrol System
> \uicontrol {Maximum number of entries in "Recent Files"}.
+ \image qtcreator-options-environment-system.png "System preferences"
+
\section1 Search and replace across files using a regular expression
As an example, say you want to replace equality checks (\c {foo == bar})
diff --git a/doc/qtcreator/src/howto/creator-only/creator-task-lists.qdoc b/doc/qtcreator/src/howto/creator-only/creator-task-lists.qdoc
index e337a155739..0b7b830de1c 100644
--- a/doc/qtcreator/src/howto/creator-only/creator-task-lists.qdoc
+++ b/doc/qtcreator/src/howto/creator-only/creator-task-lists.qdoc
@@ -34,11 +34,11 @@
\page creator-task-lists.html
\nextpage creator-logging-viewer.html
- \title Showing Task List Files in Issues Pane
+ \title Showing Task List Files in Issues
You can use code scanning and analysis tools to examine source code. These
tools report issues for you to fix. \QC enables you to load lists of
- issues into the \uicontrol Issues pane for easier navigation.
+ issues into \l Issues for easier navigation.
\QC expects tasks to be defined in a simple line-based file format that is
easy to generate using scripts. The scripts can either convert reports from
@@ -49,13 +49,13 @@
\section1 Managing Task List Entries
- To open task list files in the \uicontrol Issues pane, choose \uicontrol File >
+ To open task list files in \uicontrol Issues, choose \uicontrol File >
\uicontrol Open. Right-click a task list entry to open a context menu that
contains commands for managing the entry. You can copy or remove task list
entries or navigate to the corresponding source code.
- \QC monitors the loaded files and displays the changes in the \uicontrol Issues
- pane. To keep the current entries in a task list, but stop checking for
+ \QC monitors the loaded files and displays the changes in \uicontrol Issues.
+ To keep the current entries in a task list, but stop checking for
changes, select \uicontrol {Stop Monitoring}.
\section1 Task List File Format
diff --git a/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc b/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc
index bcb5b6ee9e7..cf7639abea8 100644
--- a/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc
+++ b/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc
@@ -54,7 +54,7 @@
compiler. What should I do?}
Make sure that the application is in your system PATH when starting \QC.
- Also select \uicontrol Tools > \uicontrol Options to check the settings
+ Also select \uicontrol Edit > \uicontrol Preferences to check the settings
specified for the application. Many plugins specify either the path to the
tool they need or the environment they run in.
@@ -65,7 +65,7 @@
\QC has been localized into several languages. If the system
language is one of the supported languages, it is automatically selected.
- To change the language, select \uicontrol Tools > \uicontrol Options >
+ To change the language, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment and select a language in the \uicontrol Language
field. Select \uicontrol {Restart Now} to restart \QC and have the change
take effect.
@@ -173,7 +173,7 @@
\uicontrol Help mode.
To view the documentation that is available and to add documentation,
- select \uicontrol Tools > \uicontrol Options > \uicontrol Help >
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol Help >
\uicontrol Documentation. For more information, see
\l{Adding External Documentation}.
@@ -256,11 +256,11 @@
\b {On Unix (Linux and \macos):} \c qDebug() and related functions use
the standard output and error output. When you run or debug the
- application, you can view the output in the \uicontrol{Application Output} pane.
+ application, you can view the output in \l{Application Output}.
For console applications that require input, select \uicontrol Projects >
\uicontrol {Run Settings} > \uicontrol {Run in terminal}. To specify the
- terminal to use, select \uicontrol Tools > \uicontrol Options >
+ terminal to use, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment > \uicontrol System.
\b {On Windows:} Output is displayed differently for \e{console
@@ -287,9 +287,9 @@
\uicontrol {Run in terminal} for console applications.
For GUI applications, \c qDebug() and related functions use the Windows API
- function \c OutputDebugString(). The output is displayed in the
- \uicontrol{Application Output} pane. However, only one output pane tab may be
- open at a time or the output is not displayed correctly. You can use an
+ function \c OutputDebugString(). The output is displayed in
+ \uicontrol{Application Output}. However, \QC can show output from only one
+ source at the time for it to be displayed correctly. You can use an
external debug output viewer, such as the
\l{https://technet.microsoft.com/en-us/sysinternals/bb896647}
{DebugView for Windows} to display output from GUI applications.
@@ -319,7 +319,7 @@
\li The common solution is to give the user the ability to reorder
tabs. Now user has to manage tabs instead of writing code.
- \li Tabs force you to limit the amount of open editors, because
+ \li Tabs force you to limit the amount of open editors because
otherwise you get confused.
\endlist
diff --git a/doc/qtcreator/src/howto/creator-telemetry.qdoc b/doc/qtcreator/src/howto/creator-telemetry.qdoc
index 23e01ca7b8e..fe4ecb65ad1 100644
--- a/doc/qtcreator/src/howto/creator-telemetry.qdoc
+++ b/doc/qtcreator/src/howto/creator-telemetry.qdoc
@@ -106,7 +106,7 @@
To determine what data is transmitted to the backend storage:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Telemetry
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Telemetry
> \uicontrol {Usage Statistics}.
\image qtcreator-telemetry-settings.png "Telemetry settings"
\li In the \uicontrol {Telemetry mode} list, select the mode that
diff --git a/doc/qtcreator/src/incredibuild/creator-projects-incredibuild-building.qdoc b/doc/qtcreator/src/incredibuild/creator-projects-incredibuild-building.qdoc
index 84c754d23ab..8031e42508c 100644
--- a/doc/qtcreator/src/incredibuild/creator-projects-incredibuild-building.qdoc
+++ b/doc/qtcreator/src/incredibuild/creator-projects-incredibuild-building.qdoc
@@ -51,8 +51,7 @@
In the \uicontrol {Target and configuration} group, specify the command
helper and arguments that will be used to construct the build command.
- The build errors and warnings are parsed and displayed in the
- \uicontrol Issues output pane.
+ The build errors and warnings are parsed and displayed in \l Issues.
Select the \uicontrol {Keep original jobs number} check box to stop
IncrediBuild from overriding the \c {-j} command line switch, which
@@ -66,7 +65,7 @@
\image qtcreator-incredibuild-build-steps-linux.png
- You can specify the following options for Linux builds:
+ You can specify the following settings for Linux builds:
\list
\li \uicontrol {Nice value} is a numeric value between -20 and 19
@@ -79,7 +78,7 @@
\image qtcreator-incredibuild-build-steps-windows.png
- You can specify the following options for Windows builds:
+ You can specify the following settings for Windows builds:
\list
\li \uicontrol {Profile.xml} defines how Automatic Interception
@@ -142,6 +141,5 @@
For more information about the settings, see \l{IncrediBuild Build Steps}.
- The build errors and warnings are parsed and displayed in the
- \uicontrol Issues output pane.
+ The build errors and warnings are parsed and displayed in \l Issues.
*/
diff --git a/doc/qtcreator/src/ios/creator-ios-dev.qdoc b/doc/qtcreator/src/ios/creator-ios-dev.qdoc
index 3ebd8c93a01..fc9e4599004 100644
--- a/doc/qtcreator/src/ios/creator-ios-dev.qdoc
+++ b/doc/qtcreator/src/ios/creator-ios-dev.qdoc
@@ -113,7 +113,7 @@
\endlist
- \note If you cannot deploy applications, because a provisioning profile is
+ \note If you cannot deploy applications because a provisioning profile is
missing, check that provisioning profiles are listed in Xcode by selecting
\uicontrol Xcode > \uicontrol Preferences > \uicontrol Accounts. For more
information about how to acquire and install a provisioning profile, see
diff --git a/doc/qtcreator/src/linux-mobile/b2qtdev.qdoc b/doc/qtcreator/src/linux-mobile/b2qtdev.qdoc
index ba71b49ab2e..bb2b7214725 100644
--- a/doc/qtcreator/src/linux-mobile/b2qtdev.qdoc
+++ b/doc/qtcreator/src/linux-mobile/b2qtdev.qdoc
@@ -26,7 +26,7 @@
/*!
\page creator-developing-b2qt.html
\previouspage creator-developing-baremetal.html
- \nextpage creator-developing-generic-linux.html
+ \nextpage creator-adding-docker-devices.html
\title Connecting Boot2Qt Devices
@@ -66,7 +66,7 @@
\l{https://doc.qt.io/Boot2Qt/b2qt-requirements-x11.html#setting-up-usb-access-to-embedded-devices}
{Boot2Qt: Setting Up USB Access to Embedded Devices}.
- You can edit the settings later in \uicontrol Tools > \uicontrol Options >
+ You can edit the settings later in \uicontrol Edit > \uicontrol Preferences >
\uicontrol Devices > \uicontrol Devices.
\image qtcreator-boot2qt-device-configurations.png "Devices dialog"
@@ -107,10 +107,10 @@
\list 1
\li Make sure that your device can be reached via an IP address or
connect it with a USB connection.
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol {Qt Versions} > \uicontrol Add to add the Qt version
for Boot2Qt.
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Compilers > \uicontrol Add to add the compiler for
building the applications.
\li Select \uicontrol Tools > \uicontrol {Flash Boot to Qt Device}
@@ -119,7 +119,7 @@
parameters for connecting to the devices over the network (\QC
automatically detects devices connected with USB):
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Devices > \uicontrol Devices > \uicontrol Add >
\uicontrol Boot2Qt > \uicontrol {Finish}.
\image qtcreator-devices-boot2qt.png "Boot2Qt Network Device Setup wizard"
@@ -136,7 +136,7 @@
these is the SSH port number, which is available in
the variable \c %{Device:SshPort}.
\endlist
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Add to add a kit for building applications for the
device. Select the Qt version, compiler, and device that you
added above, and choose \uicontrol Boot2Qt as the device type.
diff --git a/doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc b/doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc
index d1880588a00..f26efa1e7bc 100644
--- a/doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc
+++ b/doc/qtcreator/src/linux-mobile/creator-deployment-embedded-linux.qdoc
@@ -47,12 +47,17 @@
\image qtcreator-embedded-linux-deployment-details.png "Deploy to embedded Linux"
The files to be installed are listed in the \uicontrol {Deployment} step,
- the \uicontrol {Files to deploy} field. The \uicontrol {Local File Path}
+ the \uicontrol {Files to deploy} field. The \uicontrol {Source File Path}
field displays the location of the file on the development PC. The
- \uicontrol {Remote Directory} field displays the directory where the file is
+ \uicontrol {Target Directory} field displays the directory where the file is
installed on the device. Text in red color indicates that the information is
missing.
+ If the build system did not automatically detect the source and target
+ directories, select \uicontrol {Override deployment data from build system},
+ and then select \uicontrol Add to enter them manually. To remove the
+ selected paths from \uicontrol {Files to deploy}, select \uicontrol Remove.
+
\section1 Adding Missing Files
The process to add files to deploy depends on the build system you use.
@@ -100,29 +105,17 @@
When you run the application on the device, \QC first uploads the
necessary files to it, as specified by the deploy steps.
- \section2 Finding Configured Devices
-
- The \uicontrol {Check for a configured device} step looks for a device that
- is ready for deployment.
-
- \section2 Checking for Free Disk Space
+ \section2 Uploading Files
- The \uicontrol {Check for free disk space} step is by default the first
- deploy step. Use it to find out whether the remote file system has enough
- space left to deploy your project. Errors due to lack of disk space can
- otherwise be hard to detect.
+ By default, \QC copies the application files to the device by
+ using the SSH file transfer protocol (SFTP), as specified by
+ the \uicontrol {Upload files via SFTP} step.
\note If the SFTP upload fails, make sure that the remote device has SFTP
enabled in its SSH daemon. Some versions of Dropbear that come without SFTP
support will crash when an SFTP upload is being attempted. This is not a bug
in \QC.
- \section2 Uploading Files
-
- By default, \QC copies the application files to the device by
- using the SSH file transfer protocol (SFTP), as specified by
- the \uicontrol {Upload files via SFTP} step.
-
If you have a lot of data to copy, select \uicontrol Details in the
\uicontrol {Upload Files via SFTP} step, and then select the
\uicontrol {Incremental deployment} check box. \QC takes note of the
diff --git a/doc/qtcreator/src/linux-mobile/linuxdev-keys.qdocinc b/doc/qtcreator/src/linux-mobile/linuxdev-keys.qdocinc
index 826611994cf..0218c306a75 100644
--- a/doc/qtcreator/src/linux-mobile/linuxdev-keys.qdocinc
+++ b/doc/qtcreator/src/linux-mobile/linuxdev-keys.qdocinc
@@ -41,10 +41,10 @@
development PC.
To tell \QC where it can find the tools, specify the paths to the
- directories where the tools are installed in \uicontrol Tools >
- \uicontrol Options > \uicontrol Devices > \uicontrol SSH:
+ directories where the tools are installed in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Devices > \uicontrol SSH:
- \image qtcreator-ssh-options.png
+ \image qtcreator-ssh-options.png "SSH preferences"
\list
\li Deselect the \uicontrol {Enable connection sharing} check box to
@@ -82,7 +82,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices
> \uicontrol Devices > \uicontrol {Create New}.
\image qtcreator-ssh-key-configuration.png "SSH Key Configuration dialog"
diff --git a/doc/qtcreator/src/linux-mobile/linuxdev-processes.qdocinc b/doc/qtcreator/src/linux-mobile/linuxdev-processes.qdocinc
index a8e2195e3ac..4c79c6f176e 100644
--- a/doc/qtcreator/src/linux-mobile/linuxdev-processes.qdocinc
+++ b/doc/qtcreator/src/linux-mobile/linuxdev-processes.qdocinc
@@ -29,7 +29,7 @@
\section2 Managing Device Processes
You can view processes running on devices and kill them. Select
- \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices >
\uicontrol Devices > \uicontrol {Show Running Processes}.
You can filter the processes by name or ID in the
diff --git a/doc/qtcreator/src/linux-mobile/linuxdev.qdoc b/doc/qtcreator/src/linux-mobile/linuxdev.qdoc
index 818b5fcad56..1af5707f830 100644
--- a/doc/qtcreator/src/linux-mobile/linuxdev.qdoc
+++ b/doc/qtcreator/src/linux-mobile/linuxdev.qdoc
@@ -29,7 +29,7 @@
\previouspage creator-developing-android.html
\nextpage studio-advanced.html
\else
- \previouspage creator-developing-b2qt.html
+ \previouspage creator-adding-docker-devices.html
\nextpage creator-developing-ios.html
\endif
@@ -49,7 +49,7 @@
{kit}.
You use a wizard to create the connections. You can edit the settings later
- in \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
+ in \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices >
\uicontrol Devices.
\image qtcreator-linux-device-configurations.png "Devices dialog"
@@ -76,11 +76,11 @@
\li Make sure that your device can be reached via an IP address.
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol {Qt Versions} > \uicontrol Add to add the Qt version
for embedded Linux.
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Compilers > \uicontrol Add to add the compiler for
building the applications.
@@ -89,7 +89,7 @@
\list a
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Devices > \uicontrol Devices > \uicontrol Add >
\uicontrol {Generic Linux Device}
> \uicontrol {Start Wizard}.
@@ -133,7 +133,7 @@
the SSH port number, which is available in the variable \c %{Device:SshPort}.
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Add to add a kit for building for the device. Select the
Qt version, compiler, and device that you added above, and choose
\uicontrol {Generic Linux Device} for the device type.
diff --git a/doc/qtcreator/src/mcu/creator-mcu-dev.qdoc b/doc/qtcreator/src/mcu/creator-mcu-dev.qdoc
index 25e6686750c..7db36a41210 100644
--- a/doc/qtcreator/src/mcu/creator-mcu-dev.qdoc
+++ b/doc/qtcreator/src/mcu/creator-mcu-dev.qdoc
@@ -82,10 +82,10 @@
\section2 Specifying MCU Settings
To configure a connection between \QC and your MCU board, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices >
\uicontrol MCU:
- \image qtcreator-mcu-options.png "MCU options"
+ \image qtcreator-mcu-options.png "MCU preferences"
\list 1
\li In the \uicontrol {Qt for MCUs SDK} field, specify the path
@@ -143,7 +143,7 @@
\image qtcreator-mcu-device.png "MCU devices"
- To add MCU devices, select \uicontrol Tools > \uicontrol Options >
+ To add MCU devices, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Devices > \uicontrol Add > \uicontrol {MCU Device} >
\uicontrol {Start Wizard}:
@@ -163,8 +163,8 @@
\image qtcreator-mcu-kit.png "MCU kits"
- You can edit and/or remove individual kits in \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits.
+ You can edit and/or remove individual kits in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits.
However, for adding new kits you should use the \uicontrol {Create Kit}
button in the {Qt for MCUs} settings tab. This method adds the paths to
@@ -197,16 +197,18 @@
\section1 Supported Qt for MCUs SDKs
- Since version 4.12.4, \QC supports versions 1.3 through 1.9 of the Qt for MCUs SDK.
- Since version 6.0.0, \QC adds support for versions 2.0 and later of the Qt for MCUs SDK.
- For older versions refer to the following table.
+ Since version 7.0.0, \QC supports version 2.0 and later of the Qt for MCUs SDK.
+ For older versions, refer to the following table.
\table
\header
\li \QC version
\li Qt for MCUs SDK version
\row
- \li 6.0.0 or later
+ \li 7.0.0 or later
+ \li 2.0 or later
+ \row
+ \li 6.0.x
\li 1.3 or later, including 2.0 or later
\row
\li 4.12.4 up to 5.0.3
diff --git a/doc/qtcreator/src/meson/creator-projects-meson-building.qdoc b/doc/qtcreator/src/meson/creator-projects-meson-building.qdoc
index b592c38d5f6..b0f5ef2c7da 100644
--- a/doc/qtcreator/src/meson/creator-projects-meson-building.qdoc
+++ b/doc/qtcreator/src/meson/creator-projects-meson-building.qdoc
@@ -68,7 +68,6 @@
\image qtcreator-meson-clean-steps.png "Meson clean steps"
- The build errors and warnings are parsed and displayed in the
- \uicontrol Issues output pane.
+ The build errors and warnings are parsed and displayed in \uicontrol Issues.
*/
diff --git a/doc/qtcreator/src/meson/creator-projects-meson.qdoc b/doc/qtcreator/src/meson/creator-projects-meson.qdoc
index 664c444aa35..fb1014124bc 100644
--- a/doc/qtcreator/src/meson/creator-projects-meson.qdoc
+++ b/doc/qtcreator/src/meson/creator-projects-meson.qdoc
@@ -55,7 +55,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Meson >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Meson >
\uicontrol Tools > \uicontrol Add.
\image qtcreator-mesonexecutable.png
@@ -70,10 +70,10 @@
\endlist
Select the
- \uicontrol Tools > \uicontrol Options > \uicontrol Kits > \uicontrol Kits
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits > \uicontrol Kits
tab to add the Meson and Ninja tools to a build and run kit:
- \image qtcreator-kits-meson.png "Setting Meson executable in Kit options"
+ \image qtcreator-kits-meson.png "Setting Meson executable in Kit preferences"
For more information, see \l {Adding Kits}.
diff --git a/doc/qtcreator/src/overview/creator-only/creator-advanced.qdoc b/doc/qtcreator/src/overview/creator-only/creator-advanced.qdoc
index b64bc842677..b3949a0d920 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-advanced.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-advanced.qdoc
@@ -88,12 +88,11 @@
\list
- \li \l{Showing Task List Files in Issues Pane}
+ \li \l{Showing Task List Files in Issues}
You can load report files created by code scanning and analysis
- tools to the \uicontrol Issues output pane. You can navigate to the
- corresponding source code by clicking the error message or by using
- keyboard shortcuts.
+ tools to \l Issues. You can navigate to the corresponding source
+ code by clicking the error message or by using keyboard shortcuts.
\li \l{Inspecting Internal Logs}
diff --git a/doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc b/doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc
index 041e8554053..f9f1f1a0103 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc
@@ -67,15 +67,15 @@
available in \QC. If it does not, you must add the kits yourself to tell
\QC where everything is.
- To add kits, select \uicontrol Tools > \uicontrol Options >
+ To add kits, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Kits > \uicontrol Add.
For more information, see \l{Adding Kits}.
Each kit consists of a set of values that define one environment, such as a
\l{glossary-device}{device}, compiler, and Qt version. If you know you have
- installed a Qt version, but it is not listed in \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits > \uicontrol {Qt Versions}, select
+ installed a Qt version, but it is not listed in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits > \uicontrol {Qt Versions}, select
\uicontrol {Link with Qt}.
If the Qt version is still not listed under \uicontrol Auto-detected, select
@@ -83,8 +83,8 @@
For more information, see \l{Adding Qt Versions}.
- Also check that your compiler is listed in \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits > \uicontrol {Compilers}.
+ Also check that your compiler is listed in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits > \uicontrol {Compilers}.
For more information, see \l{Adding Compilers}.
@@ -94,7 +94,7 @@
over a WLAN. You must also configure a connection between \QC and the
development PC and specify the device in a kit.
- To add devices, select \uicontrol Tools > \uicontrol Options >
+ To add devices, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Devices > \uicontrol Devices > \uicontrol Add.
For more information, see \l{Connecting Devices}.
@@ -104,7 +104,7 @@
You can use \QC with your favorite keyboard shortcuts.
To view and edit all keyboard shortcuts defined in \QC, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Environment >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment >
\uicontrol Keyboard. For more information, see \l{Keyboard Shortcuts}.
\section1 Changing Color Schemes
@@ -112,7 +112,7 @@
Themes enable you to customize the appearance of the \QC UI: widgets,
colors, and icons.
- To switch themes, select \uicontrol Tools > \uicontrol Options >
+ To switch themes, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment, and then select a theme
in the \uicontrol Theme field.
@@ -122,7 +122,7 @@
ones. The color schemes apply to highlighting C++ files, QML files, and
generic files.
- To change the color scheme, select \uicontrol Tools > \uicontrol Options >
+ To change the color scheme, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Text Editor} > \uicontrol {Fonts & Color}.
For more information, see \l{Defining Color Schemes}.
@@ -133,8 +133,8 @@
syntax definitions. \QC comes with most of the commonly used syntax files,
and you can download additional files.
- To download and use highlight definition files, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol {Generic Highlighter}.
+ To download and use highlight definition files, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol {Generic Highlighter}.
For more information, see \l{Generic Highlighting}.
@@ -145,7 +145,7 @@
the statement currently under your cursor. You can add, modify, and remove
snippets in the snippet editor.
- To open the snippet editor, select \uicontrol Tools > \uicontrol Options >
+ To open the snippet editor, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Text Editor} > \uicontrol Snippets.
For more information, see \l{Editing Code Snippets}.
@@ -157,7 +157,7 @@
\QC. Once it is set up correctly on the development PC, it should just work.
However, some configuration options are available and you can set them in
- \uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Version Control} >
\uicontrol General.
For more information about the supported functions, see
diff --git a/doc/qtcreator/src/overview/creator-only/creator-glossary.qdoc b/doc/qtcreator/src/overview/creator-only/creator-glossary.qdoc
index 03e862e2949..98fbb2f7a67 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-glossary.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-glossary.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -48,7 +48,7 @@
into binaries. Different build configurations allow you to
quickly build the project for different purposes.
By default, \QC creates \e {debug build} and \e {release build}
- configurations for each \l{glossary-buildandrun-kit}{kit} defined for your project.
+ configurations for each \e {kit} defined for your project.
A debug build contains
additional debug symbols that you need for debugging the
application but that you can leave out from the release version.
@@ -81,22 +81,22 @@
\li Handles the packaging and copying of the necessary files to a
location you want to run the executable at. The files can be
copied to a location in the file system of the development PC or
- a \l{glossary-device}{device}.
+ a \e {device}.
\row
\li Device
\target glossary-device
\li An embedded device or a mobile device. For more information, see
- \l{Target Platforms}.
+ \l{Embedded Platforms} and \l{Mobile Platforms}.
\row
\li Kit
\target glossary-buildandrun-kit
\li \QC groups build and run specific settings as kits to make
cross-platform development easier. Each kit consists of a set
- of values that define one environment, such as a \l{glossary-device}{device},
+ of values that define one environment, such as a \e {device},
tool chain, Qt version, and debugger command to use. Configure kits at
- \uicontrol Tools > \uicontrol Options > \uicontrol Kits.
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits.
\row
\li Mode
@@ -113,7 +113,7 @@
\target glossary-project
\li Groups together a set of source files, forms, and resource files
that you can build for, as well as deploy and run on different
- desktop and \l{glossary-device}{device} platforms, as
+ desktop and \e {device} platforms, as
specified by a \e {build configuration}, \e {deploy
configuration}, and \e {run configuration}.
@@ -129,9 +129,8 @@
\target glossary-run-config
\li Starts the application in the location where it was copied by
the \e {deploy configuration}. By default, when you run a
- project, \QC builds it, deploys it to the
- \l{glossary-device}{device} specified in the selected
- \l{glossary-buildandrun-kit}{kit},
+ project, \QC builds it, deploys it to the \e {device} specified
+ in the selected \e {kit},
and runs it there. However, if you have not made any changes to
the project since you last built and deployed it, \QC simply
runs it again.
diff --git a/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc b/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc
index bac658aef58..66e09433157 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc
@@ -104,7 +104,7 @@
items with names consisting of plain characters, numbers,
underscores, and hyphens.
- \li If error messages displayed in the \uicontrol {Compile Output} pane contain
+ \li If error messages displayed in \l {Compile Output} contain
paths where slashes are missing (for example, C:QtSDK),
check your PATH variable. For more information, see
\l{Troubleshooting MinGW Compilation Errors}.
@@ -117,7 +117,8 @@
\li When debugging executables created by the GNU Compiler version 4.5.0
(all platforms), some data types will not be displayed in the
- \uicontrol{Locals and Expressions} view due to missing debug information.
+ \uicontrol Locals and \uicontrol Expressions views due to missing
+ debug information.
\li GDB on Windows may not work if the 'Embassy \reg Security Center'
software by 'Wave \reg Systems' is installed and active (causing
@@ -131,7 +132,7 @@
\li Setting breakpoints in files that do not have unique absolute
paths may fail. For example, remounting parts of a file system
- using the --bind mount option.
+ using the \c {--bind mount} option.
\li Setting breakpoints in files will fail when using LLDB if the file path
contains symbolic links.
diff --git a/doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc b/doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc
index 6113855b829..00cbee95dba 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc
@@ -35,7 +35,6 @@
\list
\li \l Android
\li \l iOS
- \li \l {Universal Windows Platform (UWP)}
\endlist
You must install the tool chain for building applications for the targeted
@@ -83,17 +82,4 @@
\li \l{Qt for iOS}
\endlist
- \section1 Universal Windows Platform (UWP)
-
- Microsoft Windows 10 introduced the Universal Windows Platform (UWP),
- which provides a common application platform on every device that runs
- Windows 10, as a successor to Windows Runtime (WinRT) introduced by
- Windows 8. The UWP core APIs are the same on all Windows devices, and
- therefore applications that only use the core APIs will run on any
- Windows 10 device, such as a desktop PC, or Xbox One.
-
- For more information about developing applications for UWP using Qt 5, see
- \l{https://doc.qt.io/qt-5/winrt-support.html}{Qt for UWP}.
-
- \note Developing for UWP using Qt 6 is not supported.
*/
diff --git a/doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc b/doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc
index 70ff6464d68..ed7ff74f5aa 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -38,7 +38,7 @@
You can connect \l{glossary-device}{devices} to the development PC to run, debug,
and analyze applications built for them from \QC. When you install Qt for a
- target platform, such as Android, QNX, or Universal Windows Platform (UWP),
+ target platform, such as Android or QNX,
the build and run settings for the development targets might be set up
automatically in \QC.
@@ -74,6 +74,13 @@
You can connect \l{Boot2Qt} devices to the development PC to run,
debug, and analyze applications built for them from \QC.
+ \if defined(qtcreator)
+ \li \l {Adding Docker Devices}
+
+ You can add Docker images as \e devices to run, debug, and analyze
+ applications built for Docker containers from \QC.
+ \endif
+
\li \l{Connecting Generic Remote Linux Devices}
If you have a tool chain for building applications for embedded
diff --git a/doc/qtcreator/src/overview/creator-only/creator-supported-platforms.qdoc b/doc/qtcreator/src/overview/creator-only/creator-supported-platforms.qdoc
index f17cb98fbde..08ae76dd627 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-supported-platforms.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-supported-platforms.qdoc
@@ -81,19 +81,17 @@
\li \image ok
\li \inlineimage ok
\row
- \li \l{Universal Windows Platform (UWP)}{UWP}
- \li
- \li
- \li \image ok
- \row
\li \l{Building Applications for the Web}{WebAssembly}
\li \image ok
\li \image ok
\li \image ok
\endtable
+ \note UWP support was removed from \QC 8.0.
+ To develop for UWP using Qt 5, use \QC 7.0, or earlier.
+
\QC automatically runs scheduled checks for updates based on the settings
- specified in \uicontrol Tools > \uicontrol Options \uicontrol Environment >
+ specified in \uicontrol Edit > \uicontrol Preferences \uicontrol Environment >
\uicontrol Update.
For more information on the requirements for each platform, see:
diff --git a/doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc b/doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc
index f7bcd6765bb..08a38cf5de6 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc
@@ -41,7 +41,7 @@
\uicontrol {Build Directory} field.
To make in-source builds the default option for all projects, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Build & Run} >
\uicontrol {Default Build Properties}, and enter a period (.) in the
\uicontrol {Default build directory} field.
@@ -68,14 +68,14 @@
\section1 Global qmake Settings
- To specify settings for all qmake builds, select \uicontrol Tools
- > \uicontrol Options > \uicontrol {Build & Run} >
+ To specify settings for all qmake builds, select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol {Build & Run} >
\uicontrol Qmake.
\image qtcreator-build-settings-qmake.png "qmake build and run options"
- To set the default build properties, select \uicontrol Tools
- > \uicontrol Options > \uicontrol {Build & Run} >
+ To set the default build properties, select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol {Build & Run} >
\uicontrol {Default Build Properties}.
\image qtcreator-build-settings-default.png "default build options"
@@ -92,8 +92,8 @@
select \uicontrol Enable in the \uicontrol {Qt Quick Compiler} field. To
use default settings, select \uicontrol {Leave at Default}.
- You can specify default behavior for compiling QML code in \uicontrol Tools
- > \uicontrol Options > \uicontrol {Build & Run} > \uicontrol Qmake >
+ You can specify default behavior for compiling QML code in \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol {Build & Run} > \uicontrol Qmake >
\uicontrol {Use qmlcachegen}.
\section1 qmake Build Steps
diff --git a/doc/qtcreator/src/projects/creator-only/creator-custom-output-parser.qdoc b/doc/qtcreator/src/projects/creator-only/creator-custom-output-parser.qdoc
index fd49fe581b9..f15e71ab14e 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-custom-output-parser.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-custom-output-parser.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -32,10 +32,10 @@
Custom output parsers scan command line output for error
and warning patterns that you specify and create entries
- for found patterns in the \uicontrol Issues output pane.
+ for found patterns in \l Issues.
To view or add custom output parsers, select
- \uicontrol Tools > \uicontrol Options >
+ \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Build & Run} > \uicontrol {Custom Output Parsers}.
\image qtcreator-custom-parser-list.png
@@ -53,7 +53,7 @@
\section1 Specifying Settings for Custom Output Parsers
- \image qtcreator-custom-parser-options.png
+ \image qtcreator-custom-parser-options.png "Custom Output Parsers preferences"
A custom output parser enables you to capture errors and
warnings separately, according to the settings you specify
@@ -62,15 +62,15 @@
To create a custom output parser:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Build & Run} > \uicontrol {Custom Output Parsers}
> \uicontrol Add.
\li In the \uicontrol {Error message capture pattern} field, specify
a regular expression to define what is an error. The custom
parser matches the compile output line by line against the
- regular expression and displays errors in the \uicontrol Issues
- output pane. Create regular expression groups that contain
- the file name, line number and error message.
+ regular expression and displays errors in \l Issues. Create
+ regular expression groups that contain the file name, line number
+ and error message.
\li In the \uicontrol {Capture Positions} field, map the regular
expression groups to \uicontrol {File name}, \uicontrol {Line number},
and \uicontrol Message.
@@ -99,4 +99,7 @@
\li Select custom parsers to activate them for building or running
the project.
\endlist
+
+ Select \uicontrol {Parse standard output during build} to make output
+ parsers look for diagnostics on \c stdout in addition to \c stderr.
*/
diff --git a/doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc b/doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc
index 72b4ed80305..e566d482116 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc
@@ -159,10 +159,10 @@
\image qtcreator-cpp-class-wizard.png "Enter Class Name dialog"
The names of the header and source file are based on the class name. To
- change the default suffix of a file, select \uicontrol Tools > \uicontrol Options >
+ change the default suffix of a file, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {C++} > \uicontrol {File Naming}.
- \image qtcreator-options-cpp-files.png "File Naming tab in Options"
+ \image qtcreator-options-cpp-files.png "C++ File Naming preferences"
In the \uicontrol {License template} field, you can use
\l{Using Variables in Wizards}{predefined wizard variables} to specify the
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-build-run-tutorial.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-build-run-tutorial.qdoc
index d5c2be6bd57..e69d92ffa56 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-build-run-tutorial.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-build-run-tutorial.qdoc
@@ -83,8 +83,8 @@
\li Click \inlineimage icons/run_small.png
(\uicontrol Run) to build and run the application.
- \li To see the compilation progress, press \key{Alt+4} to open the
- \uicontrol {Compile Output} pane.
+ \li To see the compilation progress, press \key{Alt+4} to open
+ \l {Compile Output}.
If build errors occur, check that a Qt version and
\l{Adding Compilers}{compiler} are installed and
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-build-systems.qdocinc b/doc/qtcreator/src/projects/creator-only/creator-projects-build-systems.qdocinc
index 7ade105e82c..9c7c5ee301c 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-build-systems.qdocinc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-build-systems.qdocinc
@@ -62,12 +62,12 @@
information, see \l{Setting Up Qbs}.
To change the location of the project directory, and to specify settings
- for building and running projects, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Build & Run} > \uicontrol General. The
+ for building and running projects, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Build & Run} > \uicontrol General. The
\uicontrol CMake tab contains additional settings for CMake. You can find
- more settings for CMake in \uicontrol Tools > \uicontrol Options >
- \uicontrol Kits > \uicontrol CMake and for Qbs in \uicontrol Tools >
- \uicontrol Options > \uicontrol Qbs.
+ more settings for CMake in \uicontrol Edit > \uicontrol Preferences >
+ \uicontrol Kits > \uicontrol CMake and for Qbs in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Qbs.
To specify build and run settings for different target platforms,
select \uicontrol Projects. For more information on the options you have,
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc
index a16d5bc93de..c0a096e6150 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc
@@ -46,8 +46,7 @@
To check that the application code can be compiled and linked for a device,
you can build the project. The build errors and warnings are displayed in
- the \uicontrol {Issues} output pane. More detailed information is displayed
- in the \uicontrol {Compile Output} pane.
+ the \l Issues. More detailed information is displayed in \l {Compile Output}.
To build an application:
@@ -121,8 +120,8 @@
\section1 Building with CMake
\QC automatically runs CMake when you make changes to \c {CMakeLists.txt}
- files. To disable this feature, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits > \uicontrol CMake. Select the CMake
+ files. To disable this feature, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits > \uicontrol CMake. Select the CMake
executable to edit, and then deselect the \uicontrol {Autorun CMake} check
box.
@@ -132,7 +131,7 @@
To prevent failures on incremental builds, it might make sense
to always run qmake before building, even though it means that
- building will take more time. To enable this option, select \uicontrol Tools
- > \uicontrol Options > \uicontrol {Build & Run} > \uicontrol qmake >
+ building will take more time. To enable this option, select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol {Build & Run} > \uicontrol qmake >
\uicontrol {Run qmake on every build}.
*/
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc
index f018020f54a..8e35e74d258 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc
@@ -42,10 +42,10 @@
\title Customizing the Build Process
To configure how projects are built, deployed, and run, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run}
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Build & Run}
> \uicontrol General.
- \image qtcreator-project-options-deploy.png "Project General Options"
+ \image qtcreator-project-options-deploy.png "Project General preferences"
By default, the \uicontrol {Always deploy project before running it} (1) and
\uicontrol {Build the Whole Project} (2) options are enabled. Therefore,
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc
index 79280560dca..f8a78e6a1b7 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc
@@ -43,8 +43,8 @@
for and running it on a particular platform.
\QC automatically detects the compilers that are registered by your
- system or by the Qt Installer and lists them in \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits > \uicontrol Compilers:
+ system or by the Qt Installer and lists them in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits > \uicontrol Compilers:
\image qtcreator-toolchains.png
@@ -133,10 +133,10 @@
these compilers, you also specify the path to the script that sets up the
command prompt in the \uicontrol Initialization field.
- You specify the compiler to use for each kit in \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits.
+ You specify the compiler to use for each kit in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits.
- To add a C or C++ compiler, select \uicontrol Tools > \uicontrol Options >
+ To add a C or C++ compiler, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Kits > \uicontrol Compilers > \uicontrol Add. Select a compiler
in the list, and then select \uicontrol C or \uicontrol C++.
@@ -192,8 +192,8 @@
\section1 Adding Nim Compilers
- To build an application using the Nim Compiler, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits > \uicontrol Compilers >
+ To build an application using the Nim Compiler, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits > \uicontrol Compilers >
\uicontrol Add > \uicontrol Nim, and specify the path to the directory where
the compiler is located.
@@ -209,7 +209,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Compilers > \uicontrol Add > \uicontrol Custom >
\uicontrol C or \uicontrol C++.
@@ -245,7 +245,7 @@
\section1 Troubleshooting \MinGW Compilation Errors
- If error messages displayed in the \uicontrol {Compile Output} pane contain
+ If error messages displayed in \l {Compile Output} contain
paths where slashes are missing (for example, \c {C:QtSDK}),
check your PATH variable. At the command line, enter the following commands:
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc
index c89efd5a465..31fa0b883f5 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc
@@ -122,20 +122,26 @@
to desktop, embedded, and mobile target platforms.
\row
\li {1,4} Application (Qt for Python)
- \li Qt for Python - Empty
+ \li Empty Application
\li Creates a \l{https://doc.qt.io/qtforpython/index.html}
{Qt for Python} application that contains only the main
code for a QApplication.
\row
- \li Qt for Python - Window
+ \li Empty Window
\li Creates a Qt for Python application that contains an empty
window.
\row
- \li Qt for Python - Window (UI file)
+ \li Window UI
+ \li Creates a Qt for Python application that contains an empty
+ window with a widget-based UI. Preferred approach that requires
+ you to generate a Python file from the .ui file, to import
+ it directly into your application.
+ \row
+ \li Window UI - Dynamic load
\li Creates a Qt for Python application that contains an empty
window with a widget-based UI.
\row
- \li Qt for Python - Qt Quick Application
+ \li Qt Quick Application - Empty
\li Creates a Python project that contains an empty Qt Quick
Application.
\row
@@ -160,7 +166,7 @@
with a single QML file that contains the main view. You can
preview Qt Quick 2 UI projects in the
\l{Validating with Target Hardware}{QML Scene preview tool}.
- You do not need to build them, because they do not contain any
+ You do not need to build them because they do not contain any
C++ code.
Use this template only if you are prototyping. You cannot create
@@ -362,8 +368,8 @@
it. Triggering this keyboard shortcut will directly open the wizard without
the need to navigate to \uicontrol File > \uicontrol {New File} or \uicontrol {New Project}.
- Keyboard shortcuts for wizards can be set in \uicontrol Tools >
- \uicontrol Options > \uicontrol Environment > \uicontrol Keyboard >
+ Keyboard shortcuts for wizards can be set in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Environment > \uicontrol Keyboard >
\uicontrol Wizard. All wizard actions start with \uicontrol Impl there.
\section1 Related Topics
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc b/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc
index baa3e32c566..e1514887090 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc
@@ -34,7 +34,7 @@
actually copied from the \QC source directory into the \QC build directory
as part of the next \QC build.
- If you do not run CMake or qmake, your new wizard will not show up, because
+ If you do not run CMake or qmake, your new wizard will not show up because
it does not exist in the build directory you run your newly built \QC from.
It never got copied there because CMake or qmake did not inform the
build tool, such as make or ninja, about the new files in the source tree.
@@ -659,28 +659,22 @@
value of the widget, the user-provided value is stored and will
become the new default value the next time the wizard is run.
- \li \c data specifies settings for the widget:
+ \li \c visible is set to \c true if the widget is visible, otherwise
+ it is set to \c false. By default, it is set to \c true.
- \list
+ \li \c enabled is set to \c true if the widget is enabled, otherwise
+ it is set to \c false. By default, it is set to \c true.
- \li \c visible is set to \c true if the widget is visible, otherwise
- it is set to \c false. By default, it is set to \c true.
+ \li \c mandatory is set to \c true if this widget must have a value
+ for the \uicontrol Next button to become enabled. By default, it
+ is set to \c true.
- \li \c enabled is set to \c true if the widget is enabled, otherwise
- it is set to \c false. By default, it is set to \c true.
+ \li \c span is set to hide the label and to span the form. By
+ default, it is set to \c false. For more information, see
+ \l{Using Variables in Wizards}.
- \li \c mandatory is set to \c true if this widget must have a value
- for the \uicontrol Next button to become enabled. By default, it
- is set to \c true.
-
- \li \c span is set to hide the label and to span the form. By
- default, it is set to \c false. For more information, see
- \l{Using Variables in Wizards}.
-
- \endlist
-
- The additional settings available for a particular widget are described
- in the following sections.
+ \li \c data specifies additional settings for the particular widget type, as described
+ in the following sections.
\endlist
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards.qdoc
index c9f5cc6e5a4..1487f7ac4c5 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards.qdoc
@@ -103,8 +103,8 @@
\QC has some actions that can improve the wizard development process. These
are by default not bound to any keyboard shortcuts and can thus not be
- triggered. To enable them, assign keyboard shortcuts in \uicontrol Tools >
- \uicontrol Options > \uicontrol Environment > \uicontrol Keyboard >
+ triggered. To enable them, assign keyboard shortcuts in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Environment > \uicontrol Keyboard >
\uicontrol Wizard.
The following actions can help with wizard development:
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-debuggers.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-debuggers.qdoc
index 3ef847e4b87..2fbc3bd0890 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-debuggers.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-debuggers.qdoc
@@ -43,17 +43,17 @@
The debugger plugin automatically selects a suitable native debugger for
each \l{glossary-buildandrun-kit}{kit} from the ones found on your system.
- To override this choice, select \uicontrol Tools > \uicontrol Options >
+ To override this choice, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Kits.
To add debuggers:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Debuggers > \uicontrol Add.
- \image qtcreator-options-build-run-debuggers.png
+ \image qtcreator-options-build-run-debuggers.png "Adding debuggers"
\li In the \uicontrol Name field, give a descriptive name for the debugger.
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-nimble.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-nimble.qdoc
index f367625726c..d678bde79e6 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-nimble.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-nimble.qdoc
@@ -50,7 +50,7 @@
To configure \QC to build Nim executables:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits
\uicontrol Compilers > \uicontrol Add > \uicontrol Nim to specify
the path to the the Nim compiler.
\li Select \uicontrol Apply to add the compiler.
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc
index e6280066895..7055e473829 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc
@@ -47,15 +47,15 @@
The \uicontrol {Configure Project} tab displays a list of \l{glossary-buildandrun-kit}{kits}
for building and running projects, that are installed on the development PC and
- configured in \uicontrol Tools > \uicontrol Options > \uicontrol Kits.
+ configured in \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits.
Select the kits that you want to build and run the project with.
\image qtcreator-open-project-kits.png "Configure Project tab"
Even if you do not intend to build the project, the C++ and QML code models
need a Qt version and compiler to offer code completion. To specify them,
- select the \uicontrol Options link, or select \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits.
+ select the \uicontrol Preferences link, or select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits.
Qt for Python projects rely on the \l{Using Language Servers}
{language server client} for code completion, highlighting, and
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-qbs.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-qbs.qdoc
index 9c79a1c4936..f0fa1df7086 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-qbs.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-qbs.qdoc
@@ -39,8 +39,8 @@
with the build and run kit. \QC automatically creates a Qbs profile for each
kit. You can edit the build profiles by adding new keys and values.
- To check which Qbs version is being used, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Qbs > \uicontrol General.
+ To check which Qbs version is being used, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Qbs > \uicontrol General.
\section1 Building Qbs
@@ -66,8 +66,8 @@
To specify settings for Qbs:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Qbs.
- \image qtcreator-options-qbs.png
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Qbs.
+ \image qtcreator-options-qbs.png "Qbs preferences"
\li Deselect the \uicontrol {Use \QC settings directory for Qbs} check
box to store Qbs profiles in the Qbs settings directory.
\li In the \uicontrol {Path to qbs executable} field, you can view
@@ -81,7 +81,7 @@
\image creator-qbs-profiles.png "Qbs Profiles tab"
\li In the \uicontrol Kit field, select a build and run kit to view
the properties of the associated profile. To modify the properties,
- select \uicontrol Tools > \uicontrol Options > \uicontrol Kits.
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits.
For more information, see \l{Editing Qbs Profiles}.
\endlist
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc
index ff3bcbd36f5..9576a23c379 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc
@@ -48,7 +48,7 @@
version, select it in the list and select \uicontrol Details in the
\uicontrol {Qt version for} section.
- \image qtcreator-qt-versions.png "Qt Versions tab in Kit options"
+ \image qtcreator-qt-versions.png "Qt Versions tab in Kit preferences"
To remove invalid Qt versions, select \uicontrol {Clean Up}.
@@ -63,7 +63,7 @@
To link to a Qt installation:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
(or \uicontrol {Qt Creator} > \uicontrol Preferences on
\macos) > \uicontrol Kits > \uicontrol {Qt Versions} >
\uicontrol {Link with Qt}.
@@ -84,7 +84,7 @@
You specify the Qt version to use for each \l{glossary-buildandrun-kit}
{kit} for building and running your projects
- in \uicontrol Tools > \uicontrol Options > \uicontrol Kits, as described
+ in \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits, as described
in \l{Specifying Kit Settings}.
\section1 Setting Up New Qt Versions
@@ -93,7 +93,7 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol {Qt Versions} > \uicontrol Add.
\li Select the qmake executable for the Qt version that you want to
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc
index 329b69094bf..572317b43aa 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc
@@ -86,7 +86,7 @@
errors occur, if possible.
\li Select \uicontrol {Show command lines} to print actual
- command lines to the compile output pane instead of
+ command lines to \l{Compile Output} instead of
high-level descriptions.
\li Select \uicontrol {Force probes} to force re-execution of
@@ -104,7 +104,7 @@
default.
\note On Windows, the build will fail if the application
- is running, because the executable file cannot be
+ is running because the executable file cannot be
overwritten. To avoid this issue, you can deselect this
check box and add a \uicontrol {Qbs Install} deployment step
in the run settings that will be performed just before
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc
index 67d8859490e..69bd78a9c37 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc
@@ -58,10 +58,10 @@
\image qtcreator-code-style-clang-format.png "Clang Format Code Style settings in Projects mode"
To specify global code style settings sets for C++ files, select
- \uicontrol Tools > \uicontrol Options > \uicontrol C++.
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol C++.
- To specify global code style settings sets for QML files, select \uicontrol {Tools
- > Options > Qt Quick}.
+ To specify global code style settings sets for QML files, select
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Qt Quick}.
To configure the editor behavior for the current project:
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-editor.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-editor.qdoc
index 2f5ea21a01c..a22deebbcbc 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-editor.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-editor.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -42,8 +42,8 @@
You can configure the text editor according to your needs. You can specify
editor behavior either globally for all projects or separately for each
- project. To specify global editor behavior, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Behavior.
+ project. To specify global editor behavior, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Text Editor} > \uicontrol Behavior.
To configure the text editor behavior for the current project:
@@ -52,7 +52,7 @@
\li Select \uicontrol Projects > \uicontrol {Project Settings} >
\uicontrol Editor.
- \li In the \uicontrol {Editor settings} field, select \uicontrol {Custom}.
+ \li Deselect \uicontrol {Use global settings}.
\li Specify text editor settings for the project.
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc
index c47b9144e40..32a075169a3 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc
@@ -41,11 +41,11 @@
based on your project requirements.
To globally change the system environment from the one in which
- \QC is started, select \uicontrol Tools > \uicontrol Options >
+ \QC is started, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment > \uicontrol System, and then select
\uicontrol Change in the \uicontrol Environment field.
- \image qtcreator-options-environment-system.png "Environment options System tab"
+ \image qtcreator-options-environment-system.png "Environment preferences System tab"
In addition, you can specify custom environment variables in the
\uicontrol {Project Settings} > \uicontrol Environment settings.
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc
index 935c52d8947..217d31bedc8 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc
@@ -58,8 +58,8 @@
\image qtcreator-project-kits.png
- The list displays kits that are configured in \uicontrol Tools >
- \uicontrol Options > \uicontrol Kits. If the kit configuration is not
+ The list displays kits that are configured in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Kits. If the kit configuration is not
suitable for the project type, warning and error icons are displayed.
To view the warning and error messages, move the mouse pointer over
the kit name.
@@ -112,15 +112,15 @@
\li \l{Using Custom Output Parsers}{Custom Output Parsers}
- \li \l{Parsing C++ Files with the Clang Code Model}
- {Clang Code Model}
-
\li \l{Applying Refactoring Actions}{Quick Fixes}
\li \l{Using Clang Tools}{Clang Tools}
\li \l{To-Do Entries}{To-Do} (experimental)
+ \li \l{Parsing C++ Files with the Clang Code Model}
+ {Clangd}
+
\endlist
If you have multiple projects open in \QC, select the project to configure
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc
index 22cab734906..86d9cc3f7c9 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc
@@ -69,8 +69,8 @@
Click \uicontrol {Restore Global} to revert to the global settings.
- To specify global Valgrind settings, select \uicontrol {Tools > Options >
- Analyzer}.
+ To specify global Valgrind settings, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Analyzer.
//! [settings valgrind]
*/
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc
index aab400abda4..1d3ee1003dc 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc
@@ -33,8 +33,8 @@
the directory of the build result.
For console applications, check the \uicontrol{Run in terminal} check box.
- To specify the terminal to use on Linux and \macos, select \uicontrol Tools
- > \uicontrol Options > \uicontrol Environment > \uicontrol System.
+ To specify the terminal to use on Linux and \macos, select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol Environment > \uicontrol System.
To run with special environment variables set up, select them in the
\uicontrol {Run Environment} section. For more information, see
@@ -52,8 +52,8 @@
To disable library linking for the current project, deselect the
\uicontrol {Add build library search path to PATH} check box. To disable
- library linking for all projects, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Build & Run}, and then deselect the
+ library linking for all projects, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Build & Run}, and then deselect the
\uicontrol {Add linker library search paths to run environment} check box.
The \uicontrol {Use debug version of frameworks (DYLD_IMAGE_SUFFIX=_debug)} option
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc
index 3ad33409075..b56b3b8c0da 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run.qdoc
@@ -46,7 +46,7 @@
\image qtcreator-settings-run.png "Run Settings"
To prevent \QC from automatically creating run configurations, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run},
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Build & Run},
and then deselect the \uicontrol {Create suitable run configurations
automatically} check box.
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc
index ab74a044c58..49b332c528c 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc
@@ -58,16 +58,13 @@
\li \l{Connecting MCUs}{MCU Device} (commercial only)
\li \l{Connecting QNX Devices}{QNX Device}
\li \l{Building Applications for the Web}{WebAssembly Runtime}
- \li \l{https://doc.qt.io/qt-5/winrt-support.html}{Windows Phone} (Qt 5)
- \li Windows Phone Emulator (Qt 5)
- \li Windows Runtime (local, Qt 5)
\endlist
\section1 Filtering Kit Settings
Typically, only a subset of the kit settings is relevant for a particular
setup. Therefore, \QC plugins register sets of relevant settings that you
- can view and modify in \uicontrol Tools > \uicontrol Options >
+ can view and modify in \uicontrol Edit > \uicontrol Preferences >
\uicontrol Kits. For example, if you use CMake to build all your projects,
you can hide Qbs and qmake settings by default.
@@ -84,24 +81,45 @@
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Add.
- \image qtcreator-kits-add.png
-
To clone the selected kit, select \uicontrol Clone.
- \li In the \uicontrol Name column, enter a name for the kit.
+ \li Specify kit settings. The settings to specify depend on the build
+ system and device type.
- \li Select the \inlineimage icons/qtcreator-desktopdevice-button.png
- button to select an image to use as an icon for the kit.
+ \li Select \uicontrol OK to create the kit.
- \li In the \uicontrol {File system name} field, enter a name for the kit
- to use as a part of directory names. This value is used for the
- \e CurrentKit:FileSystemName variable, which determines the name of
- the shadow build directory, for example.
+ \endlist
- \li In the \uicontrol{Device type} field, select the type of the device.
+ \QC uses the \e {default kit} if it does not have enough information to
+ choose the kit to use. To set the selected kit as the default kit,
+ select \uicontrol {Make Default}.
+
+ \section2 Kit Settings
+
+ The following table summarizes the available kit settings.
+
+ \table
+ \header
+ \li Setting
+ \li Value
+ \row
+ \li \uicontrol Name
+ \li Name of the kit. You can use variables to generate the kit name
+ based on the values you set in the other fields.
+ \row
+ \li \inlineimage icons/qtcreator-desktopdevice-button.png
+ \li Image to use as an icon for the kit.
+ \row
+ \li \uicontrol {File system name}
+ \li Name for the kit to use as a part of directory names. This value is
+ used for the \c CurrentKit:FileSystemName variable, which determines
+ the name of the shadow build directory, for example.
+ \row
+ \li \uicontrol{Device type}
+ \li Type of the device.
Double-click the icon next to the field to select the image that is
displayed in the kit selector for this kit. You can use any
@@ -109,97 +127,101 @@
scaled to the size 64x64 pixels. For example, using the compiler
logo as an icon allows you to easily see, which compiler is used to
build the project for the selected kit.
+ \row
+ \li \uicontrol Device
+ \li The device to run applications on.
+ \row
+ \li \uicontrol {Build device}
+ \li The device to build applications on.
+
+ \row
+ \li \uicontrol Sysroot
+ \li Directory where the device image is located. If you are not
+ cross-compiling, leave this field empty.
+ \row
+ \li \uicontrol {Emulator skin}
+ \li Skin to use for the \l {Emulator}{Boot2Qt Emulator Device}.
+ \row
+ \li \uicontrol {Compiler}
+ \li C or C++ compiler that you use to build the project. You can add
+ compilers to the list if they are installed on the development PC,
+ but were not detected automatically. For more information, see
+ \l{Adding Compilers}.
- \li In the \uicontrol Device field, select a device.
-
- \li In the \uicontrol Sysroot field, specify the directory where the device
- image is located. If you are not cross-compiling, leave this field
- empty.
-
- \li In the \uicontrol {Emulator skin} field, select the skin to use for
- the \l {Emulator}{Boot2Qt Emulator Device}.
-
- \li In the \uicontrol {Compiler} field, select the C or C++ compiler
- that you use to build the project. You can add compilers to the list
- if they are installed on the development PC, but were not detected
- automatically. For more information, see \l{Adding Compilers}.
This setting is used to tell the code model which compiler is used.
If your project type and build tool support it, \QC also tells the
build tool to use this compiler for building the project.
-
- \li In the \uicontrol Environment field, select \uicontrol Change to modify
- environment variable values for build environments in
- the \uicontrol {Edit Environment Changes} dialog. For more information
- about how to add and remove variable values, see \l{Batch Editing}.
-
- \li Select the \uicontrol {Force UTF-8 MSVC compiler output} check box
- to either switch the language of MSVC to English or to keep the
- language setting and just force UTF-8 output, depending on the
+ \row
+ \li \uicontrol Environment
+ \li Select \uicontrol Change to modify environment variable values for
+ build environments in the \uicontrol {Edit Environment Changes}
+ dialog. For more information about how to add and remove variable
+ values, see \l{Batch Editing}.
+ \row
+ \li \uicontrol {Force UTF-8 MSVC compiler output}
+ \li Either switches the language of MSVC to English or keeps the
+ language setting and just forces UTF-8 output, depending on the
MSVC compiler used.
-
- \li In the \uicontrol Debugger field, select the debugger to debug the project
- on the target platform. \QC automatically detects available
- debuggers and displays a suitable debugger in the field. You can
- add debuggers to the list. For more information, see
- \l{Adding Debuggers}.
+ \row
+ \li \uicontrol Debugger
+ \li Debugger to debug the project on the target platform. \QC
+ automatically detects available debuggers and displays a
+ suitable debugger in the field. You can add debuggers to the list.
+ For more information, see \l{Adding Debuggers}.
For Android kits, the \uicontrol {Android GDB server} field will
display the path to GDB server executable.
-
- \li In the \uicontrol {Qt version} field, select the Qt version to use for
- building the project. You can add Qt versions to the list if they
- are installed on the development PC, but were not detected
- automatically. For more information, see \l{Adding Qt Versions}.
+ \row
+ \li \uicontrol {Qt version}
+ \li Qt version to use for building the project. You can add Qt versions
+ to the list if they are installed on the development PC, but were not
+ detected automatically. For more information, see \l{Adding Qt Versions}.
\QC checks the directories listed in the \c{PATH} environment
variable for the qmake executable. If a qmake executable is found,
it is referred to as \b{Qt in PATH} and selected as the Qt
version to use for the \uicontrol Desktop kit that is created by default.
-
- \li In the \uicontrol {Qt mkspec} field, specify the name of the mkspec
- configuration that should be used by qmake. If you leave this field
- empty, the default mkspec of the selected Qt version is used.
-
- \li In the \uicontrol {Additional Qbs profile settings} field, select
- \uicontrol Change to add settings to Qbs build profiles. For more
- information, see \l {Editing Qbs Profiles}.
-
- \li In the \uicontrol {CMake Tool} field, select the CMake executable
- to use for building the project. Select \uicontrol Manage to add
- installed CMake executables to the list. For more information, see
- \l{Adding CMake Tools}.
-
- \li In the \uicontrol {CMake generator} field, select \uicontrol Change
- to edit the CMake
- Generator to use for producing project files. Only the generators
+ \row
+ \li \uicontrol {Qt mkspec}
+ \li Name of the mkspec configuration that should be used by qmake. If
+ you leave this field empty, the default mkspec of the selected Qt
+ version is used.
+ \row
+ \li \uicontrol {Additional Qbs profile settings}
+ \li Select \uicontrol Change to add settings to Qbs build profiles.
+ For more information, see \l {Editing Qbs Profiles}.
+ \row
+ \li \uicontrol {CMake Tool}
+ \li CMake executable to use for building the project. Select
+ \uicontrol Manage to add installed CMake executables to
+ the list. For more information, see \l{Adding CMake Tools}.
+ \row
+ \li \uicontrol {CMake generator}
+ \li Select \uicontrol Change to edit the CMake Generator to use for
+ producing project files. Only the generators
with names beginning with the string \uicontrol CodeBlocks produce
all the necessary data for the \QC code model. \QC displays a
warning if you select a generator that is not supported.
For more information, see \l{Using Ninja as a CMake Generator}.
-
- \li In the \uicontrol {CMake configuration} field, select
- \uicontrol Change to edit the parameters of the CMake configuration
- for the kit.
-
- \li In the \uicontrol {Meson tool} field, select the Meson tool to use
- for building the project. Select \uicontrol Manage to add installed
- Meson tools to the list. For more information, see
+ \row
+ \li \uicontrol {CMake configuration}
+ \li Select \uicontrol Change to edit the parameters of the CMake
+ configuration for the kit.
+ \row
+ \li \uicontrol {Meson tool}
+ \li Meson tool to use for building the project. Select \uicontrol Manage
+ to add installed Meson tools to the list. For more information, see
\l{Adding Meson Tools}.
-
- \li In the \uicontrol {Ninja tool} field, select the Ninja tool to use
- for building the project with Meson. Select \uicontrol Manage to add installed
- Ninja tools to the list.
-
- \endlist
-
- \QC uses the \e {default kit} if it does not have enough information to
- choose the kit to use. To set the selected kit as the default kit,
- select \uicontrol {Make Default}.
+ \row
+ \li \uicontrol {Ninja tool}
+ \li Ninja tool to use for building the project with Meson. Select
+ \uicontrol Manage to add installed Ninja tools to the list.
+ \endtable
\section1 Editing Qbs Profiles
- To view the Qbs profile associated with the kit, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Qbs > \uicontrol Profiles.
+ To view the Qbs profile associated with the kit, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Qbs > \uicontrol Profiles.
\image creator-qbs-profiles.png "Qbs Profiles tab"
@@ -212,7 +234,7 @@
\list 1
- \li In \uicontrol Tools > \uicontrol Options > \uicontrol Kits, select
+ \li In \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits, select
the kit, and then select \uicontrol Change next to the
\uicontrol {Additional Qbs Profile Settings} field to open the
\uicontrol {Custom Properties} dialog.
diff --git a/doc/qtcreator/src/projects/creator-projects-running.qdoc b/doc/qtcreator/src/projects/creator-projects-running.qdoc
index 4d4bbbe4f34..cc756c8c048 100644
--- a/doc/qtcreator/src/projects/creator-projects-running.qdoc
+++ b/doc/qtcreator/src/projects/creator-projects-running.qdoc
@@ -47,7 +47,7 @@
To run executable files without deploying them first, select \uicontrol Build >
\uicontrol {Run Without Deployment}. To make this the default option, deselect the
- \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Build & Run} >
\uicontrol General > \uicontrol {Always deploy project before running it}
check box.
@@ -77,10 +77,10 @@
Select \uicontrol Manage to manage device settings. For example, you can add
AVDs or manually start disconnected AVDs.
- The \uicontrol {Application Output} pane displays the status of the
+ \l {Application Output} displays the status of the
application while it is running. You can select the \uicontrol Run button
- in the pane to re-run applications without building them first. This is
- useful when developing Qt Quick applications, because the QML files are
+ to re-run applications without building them first. This is
+ useful when developing Qt Quick applications because the QML files are
interpreted at runtime. Therefore, the application does not need to be
built again if you edited only QML files. This saves time especially if
the application contains large image files that would need to be bundled
diff --git a/doc/qtcreator/src/python/creator-python-project.qdocinc b/doc/qtcreator/src/python/creator-python-project.qdocinc
index 075d6b80962..4281694a5b6 100644
--- a/doc/qtcreator/src/python/creator-python-project.qdocinc
+++ b/doc/qtcreator/src/python/creator-python-project.qdocinc
@@ -33,6 +33,21 @@
to gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI},
and \l {Qt Widgets}.
+ If you have not installed PySide6, \QC prompts you to install it after
+ the project is created. Further, it prompts you to install the
+ \l {Python Language Server}{Python language server} that provides services
+ such as code completion and annotations. Select \uicontrol Install to install
+ PySide6 and the language server.
+
+ To view and manage the available Python interpreters, select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol Python > \uicontrol Interpreters.
+
+ \image qtcreator-python-interpreters.png "Python Interpreters in Preferences"
+
+ You can add and remove interpreters and clean up references to interpreters
+ that have been uninstalled, but still appear in the list. In addition, you
+ can set the interpreter to use by default.
+
The Qt for Python Application wizards generate a \c {.pyproject} file that
lists the files in the Python project and a \c {.py} file that contains
some boilerplate code. In addition, the widget based UI wizard creates a
@@ -44,7 +59,7 @@
use \c {.pyqtc} files, but we recommend that you choose \c{.pyproject} files
for new projects.
- The \uicontrol {Qt for Python - Window (UI file)} wizard enables you to
+ The \uicontrol {Window UI} wizard enables you to
create a Python project that contains the source file for a class. Specify
the PySide version, class name, base class, and and source file for the
class.
@@ -56,13 +71,22 @@
Widgets module, and Qt UI tools:
\badcode
- import os
- from pathlib import Path
import sys
from PySide6.QtWidgets import QApplication, QWidget
- from PySide6.QtCore import QFile
- from PySide6.QtUiTools import QUiLoader
+ \endcode
+
+ \note It is important that you first create the Python code
+ from your UI form. In PySide6, you can do this by executing
+ \c{pyside6-uic form.ui -o ui_form.py} on a terminal. This
+ enables you to import the class that represents your UI
+ from that Python file.
+
+ Once you generate the Python code from the UI file,
+ you can import the class:
+
+ \badcode
+ from ui_form import Ui_Widget
\endcode
The wizard also adds a main class with the specified name that
@@ -70,25 +94,22 @@
\badcode
class Widget(QWidget):
- def __init__(self):
- super(Widget, self).__init__()
- self.load_ui()
- ...
+ def __init__(self, parent=None):
+ super().__init__(parent)
\endcode
- The following lines in the main class load the generated Python class from
- the UI file:
+ The following lines in the main class instantiate the generated Python class from
+ your UI file, and set up the interface for the current class.
\badcode
- def load_ui(self):
- loader = QUiLoader()
- path = os.fspath(Path(__file__).resolve().parent / "form.ui")
- ui_file = QFile(path)
- ui_file.open(QFile.ReadOnly)
- loader.load(ui_file, self)
- ui_file.close()
+ self.ui = Ui_Widget()
+ self.ui.setupUi(self)
\endcode
+ \note UI elements of the new class can be accessed as member variables.
+ For example, if you have a button called \e{button1}, you
+ can interact with it using \c{self.ui.button1}.
+
Next, the wizard adds a main function, where it creates a
QApplication instance. As Qt can receive arguments from the command line,
you can pass any arguments to the QApplication object. Usually, you do not
@@ -96,7 +117,7 @@
\badcode
if __name__ == "__main__":
- app = QApplication([])
+ app = QApplication(sys.argv)
\endcode
Next, the wizard instantiates the \c MainWindow class and shows it:
@@ -107,11 +128,11 @@
...
\endcode
- Finally, the wizard calls the \c app.exec_() method to enter the Qt
+ Finally, the wizard calls the \c app.exec() method to enter the Qt
main loop and start executing the Qt code:
\badcode
- sys.exit(app.exec_())
+ sys.exit(app.exec())
\endcode
You can now modify the boilerplate code in the Edit mode to develop your
@@ -121,6 +142,8 @@
select \uicontrol {REPL Import File}. To also import all functions from
the file, select \uicontrol {REPL Import *}.
+ Always regenerate the Python code after modifying a UI file.
+
Open the .ui file in the \uicontrol Design mode to create a widget-based UI
in \QD.
@@ -155,9 +178,8 @@
to QGuiApplication and QQmlApplicationEngine:
\badcode
- import os
- from pathlib import Path
import sys
+ from pathlib import Path
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
@@ -177,18 +199,19 @@
\badcode
engine = QQmlApplicationEngine()
- engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
+ qml_file = Path(__file__).resolve().parent / "main.qml"
+ engine.load(qml_file)
\endcode
Finally, the wizard adds code that checks whether the file was successfully
loaded. If loading the file fails, the application exits with an error code.
- If loading succeeds, the wizard calls the \c app.exec_() method to enter the
+ If loading succeeds, the wizard calls the \c app.exec() method to enter the
Qt main loop and start executing the Qt code:
\badcode
if not engine.rootObjects():
sys.exit(-1)
- sys.exit(app.exec_())
+ sys.exit(app.exec())
\endcode
Open the .qml file in the \uicontrol Edit mode to design a Qt Quick UI, or
diff --git a/doc/qtcreator/src/qnx/creator-deployment-qnx.qdoc b/doc/qtcreator/src/qnx/creator-deployment-qnx.qdoc
index 5ec84643126..9580c4cfa0d 100644
--- a/doc/qtcreator/src/qnx/creator-deployment-qnx.qdoc
+++ b/doc/qtcreator/src/qnx/creator-deployment-qnx.qdoc
@@ -48,4 +48,9 @@
The deployment process is described in more detail in
\l{Deploying Applications to Generic Remote Linux Devices}.
+
+ \section1 Finding Configured Devices
+
+ The \uicontrol {Check for a configured device} deployment step looks for a
+ device that is ready for deployment.
*/
diff --git a/doc/qtcreator/src/qnx/creator-developing-qnx.qdoc b/doc/qtcreator/src/qnx/creator-developing-qnx.qdoc
index a5dbda8c779..9b4e453a317 100644
--- a/doc/qtcreator/src/qnx/creator-developing-qnx.qdoc
+++ b/doc/qtcreator/src/qnx/creator-developing-qnx.qdoc
@@ -51,7 +51,7 @@
\section1 Adding Kits for QNX Devices
- To view QNX device settings, select \uicontrol Tools > \uicontrol Options >
+ To view QNX device settings, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Devices > \uicontrol QNX. Select the \uicontrol {Generate kits}
check box to allow \QC to generate kits for QNX development. For more
information about how to create the kits manually, see \l {Adding Kits}.
diff --git a/doc/qtcreator/src/qtcreator-toc.qdoc b/doc/qtcreator/src/qtcreator-toc.qdoc
index 23bc02bec20..c904ac14892 100644
--- a/doc/qtcreator/src/qtcreator-toc.qdoc
+++ b/doc/qtcreator/src/qtcreator-toc.qdoc
@@ -69,6 +69,7 @@
\li \l{Using ClearCase}
\li \l{Using CVS}
\li \l{Using Git}
+ \li \l{Using GitLab}
\li \l{Using Mercurial}
\li \l{Using Perforce}
\li \l{Using Subversion}
@@ -168,6 +169,8 @@
\list
\li \l{Connecting Android Devices}
\li \l{Connecting Bare Metal Devices}
+ \li \l{Connecting Boot2Qt Devices}
+ \li \l{Adding Docker Devices}
\li \l{Connecting Generic Remote Linux Devices}
\li \l{Connecting iOS Devices}
\li \l{Connecting MCUs}
@@ -192,6 +195,7 @@
\li \l{Analyzing Code}
\list
\li \l{Profiling QML Applications}
+ \li \l{Checking Code Coverage}
\li \l{Using Valgrind Code Analysis Tools}
\list
\li \l{Detecting Memory Leaks with Memcheck}
@@ -228,7 +232,7 @@
\li \l{Using Command Line Options}
\li \l{Keyboard Shortcuts}
\li \l{Using External Tools}
- \li \l{Showing Task List Files in Issues Pane}
+ \li \l{Showing Task List Files in Issues}
\li \l{Inspecting Internal Logs}
\li \l{Managing Data Collection}
\list
diff --git a/doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc b/doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc
index 065ac60d262..0b09a9ddd04 100644
--- a/doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc
+++ b/doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc
@@ -43,7 +43,7 @@
asks you whether you would like to open the file in \QDS instead. Select
\uicontrol {Open in \QDS} to open the file in \QDS. To continue editing
the file in \QC, close the info bar. However, we do not recommend editing
- \l{UI Files}{UI files} in the \uicontrol Edit mode, because it is easy to
+ \l{UI Files}{UI files} in the \uicontrol Edit mode because it is easy to
add code that is not supported by \QDS. To hide the question, select
\uicontrol {Do Not Show Again}.
diff --git a/doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc b/doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc
index 7adfe570206..e7a737b8a1f 100644
--- a/doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc
+++ b/doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc
@@ -62,7 +62,7 @@
\li Qt Quick UI Prototype
\li Creates a Qt Quick UI project with a single QML file that
contains the main view. You can preview Qt Quick 2 UI projects
- in the QML Scene preview tool. You do not need to build them,
+ in the QML Scene preview tool. You do not need to build them
because they do not contain any C++ code.
This project type is compatible with \QDS. However, use this
@@ -114,7 +114,7 @@
\uicontrol {Define Project Details} dialog.
\li Select the Qt version to develop with in the
- \uicontrol {Minimal required Qt version} field.
+ \uicontrol {Minimum required Qt version} field.
The Qt version determines the Qt Quick imports
that are used in the QML files.
@@ -143,8 +143,8 @@
\li Select \l{glossary-buildandrun-kit}{kits} for the platforms that
you want to build the application for.
- \note Kits are listed if they have been specified in \uicontrol
- Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
+ \note Kits are listed if they have been specified in \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol Kits (on Windows and Linux)
or in \uicontrol {\QC} > \uicontrol Preferences >
\uicontrol Kits (on \macos).
For more information, see \l {Adding Kits}.
@@ -168,7 +168,7 @@
Qt Quick UI Prototype projects are useful for testing or prototyping user
interfaces,
or for setting up a separate project just for QML editing, for example. You
- cannot use them for application development, because they do not contain:
+ cannot use them for application development because they do not contain:
\list
\li C++ code
@@ -200,7 +200,7 @@
\li Select \uicontrol Next (or \uicontrol Continue on \macos) to open
the \uicontrol {Define Project Details} dialog.
- \li In the \uicontrol {Minimal required Qt version} field, select the Qt
+ \li In the \uicontrol {Minimum required Qt version} field, select the Qt
version to develop with. The Qt version determines the Qt Quick
imports that are used in the QML files.
@@ -221,8 +221,8 @@
\li Select \l{glossary-buildandrun-kit}{kits} for the platforms that
you want to build the application for.
- \note Kits are listed if they have been specified in \uicontrol
- Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
+ \note Kits are listed if they have been specified in \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol Kits (on Windows and Linux)
or in \uicontrol {\QC} > \uicontrol Preferences >
\uicontrol Kits (on \macos).
For more information, see \l {Adding Kits}.
diff --git a/doc/qtcreator/src/qtquick/creator-only/qtquick-tutorial-create-empty-project.qdocinc b/doc/qtcreator/src/qtquick/creator-only/qtquick-tutorial-create-empty-project.qdocinc
index 4462b218139..35395ae5306 100644
--- a/doc/qtcreator/src/qtquick/creator-only/qtquick-tutorial-create-empty-project.qdocinc
+++ b/doc/qtcreator/src/qtquick/creator-only/qtquick-tutorial-create-empty-project.qdocinc
@@ -56,7 +56,7 @@
\li Select \uicontrol Next to open the
\uicontrol {Define Project Details} dialog.
- \li In the \uicontrol {Minimal required Qt version} field, select
+ \li In the \uicontrol {Minimum required Qt version} field, select
Qt 6.2.
\li Select \uicontrol Next to open the \uicontrol {Translation File}
@@ -70,8 +70,8 @@
applications for mobile devices, select kits also for Android and
iOS.
- \note Kits are listed if they have been specified in \uicontrol
- Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
+ \note Kits are listed if they have been specified in \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol Kits (on Windows and Linux)
or in \uicontrol {\QC} > \uicontrol Preferences >
\uicontrol Kits (on \macos).
For more information, see \l {Adding Kits}.
diff --git a/doc/qtcreator/src/qtquick/qtquick-live-preview-devices.qdoc b/doc/qtcreator/src/qtquick/qtquick-live-preview-devices.qdoc
index c8ef7a11c83..cf680b3af65 100644
--- a/doc/qtcreator/src/qtquick/qtquick-live-preview-devices.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-live-preview-devices.qdoc
@@ -76,7 +76,7 @@
The first time you preview a UI on devices, the preview utility
is copied to them. This might take some time. Thereafter, previewing will
- get faster, because only the UI files need to be copied to the
+ get faster because only the UI files need to be copied to the
device.
\section2 Previewing on Boot2Qt Devices
diff --git a/doc/qtcreator/src/qtquick/qtquick-profiler.qdoc b/doc/qtcreator/src/qtquick/qtquick-profiler.qdoc
index 990acc587fa..5c24eb3b402 100644
--- a/doc/qtcreator/src/qtquick/qtquick-profiler.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-profiler.qdoc
@@ -36,7 +36,7 @@
\nextpage studio-advanced.html
\else
\previouspage creator-analyze-mode.html
- \nextpage creator-valgrind-overview.html
+ \nextpage creator-coco.html
\endif
\title Profiling QML Applications
@@ -53,7 +53,7 @@
\if defined(qtcreator)
Triggering long-running C++ functions, such as paint methods and signal
handlers, also takes time in the GUI thread, but is more difficult to see in
- the QML Profiler, because it does not profile C++ code.
+ the QML Profiler because it does not profile C++ code.
\endif
To find excessive use of JavaScript, check the frame rate in animations and
@@ -65,7 +65,7 @@
frames and check that you are not using too many short bindings or signal
handlers that are updated per frame. You can also \l{Visualizing Overdraw}
{visualize Scene Graph overdraw} to check scene layout and find items that
- are never visible to the users, because they are located outside the screen
+ are never visible to the users because they are located outside the screen
or hidden beneath other, visible elements.
\if defined(qtcreator)
@@ -127,7 +127,7 @@
takes time, and therefore, there might be a delay
before the data is displayed.
- Do not use application commands to exit the application, because data is
+ Do not use application commands to exit the application because data is
sent to the QML Profiler when you select the \uicontrol {Enable Profiling} button.
The application continues to run for some seconds, after which it is stopped
automatically. If you exit the application, the data is not sent.
@@ -146,7 +146,7 @@
You can specify flushing settings for the QML Profiler either globally for
all projects or separately for each project. To specify global settings,
- select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer.
+ select \uicontrol Edit > \uicontrol Preferences > \uicontrol Analyzer.
To specify custom QML Profiler settings for a particular project, select
\uicontrol Projects > \uicontrol Run and then select \uicontrol Custom in
diff --git a/doc/qtcreator/src/qtquick/qtquick-toolbars.qdoc b/doc/qtcreator/src/qtquick/qtquick-toolbars.qdoc
index cbc1af136a3..3d9659b3ae7 100644
--- a/doc/qtcreator/src/qtquick/qtquick-toolbars.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-toolbars.qdoc
@@ -45,13 +45,15 @@
. Select the icon to open the toolbar.
To open toolbars immediately when you select a QML type, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Qt Quick} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Qt Quick} >
\uicontrol {QML/JS Editing} > \uicontrol {Always show Qt Quick Toolbar}.
+ \image qtcreator-qml-js-editing.png "QML/JS Editing preferences"
+
Drag the toolbar to pin it to another location. Select
\inlineimage icons/pin.png
to unpin the toolbar and move it to its default location. To pin toolbars
- by default, select \uicontrol {Pin Quick Toolbar}.
+ by default, select \uicontrol {Pin Qt Quick Toolbar}.
\section1 Previewing Images
diff --git a/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc b/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc
index 22babb5026e..07468b3fa7b 100644
--- a/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc
+++ b/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc
@@ -46,8 +46,8 @@
in the menu (1). Select \uicontrol Home to move to the user's home
directory. Further, you can select a project to move to an open project
or \uicontrol Projects to move to the directory specified in the
- \uicontrol {Projects directory} field in \uicontrol Tools >
- \uicontrol Options > \uicontrol {Build & Run} > \uicontrol General.
+ \uicontrol {Projects directory} field in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Build & Run} > \uicontrol General.
The file that is currently active in the editor determines which folder
is displayed in the \uicontrol {File System} view:
@@ -76,7 +76,7 @@
\li Show the file or directory in the file explorer.
\li Open a terminal window in the selected directory or in the directory
that contains the file. To specify the terminal to use on Linux and
- \macos, select \uicontrol Tools > \uicontrol Options >
+ \macos, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment > \uicontrol System.
\li Search from the selected directory.
\li View file properties, such as name, path, MIME type, default editor,
diff --git a/doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc b/doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc
index ad53a9912c3..058ea3276a9 100644
--- a/doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc
+++ b/doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc
@@ -50,10 +50,10 @@
\section1 Specifying Settings for Opening Files
To specify settings for opening files and handling open files, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Environment >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment >
\uicontrol System:
- \image qtcreator-options-environment-system.png "Environment options System tab"
+ \image qtcreator-options-environment-system.png "Environment preferences System tab"
\list
\li In the \uicontrol {When files are externally modified} field,
diff --git a/doc/qtcreator/src/user-interface/creator-projects-view.qdoc b/doc/qtcreator/src/user-interface/creator-projects-view.qdoc
index be9ba3530d8..e34f1c68145 100644
--- a/doc/qtcreator/src/user-interface/creator-projects-view.qdoc
+++ b/doc/qtcreator/src/user-interface/creator-projects-view.qdoc
@@ -97,8 +97,8 @@
\endif
\li Search from the selected directory.
\li Open a terminal window in the project directory. To specify the
- terminal to use on Linux and \macos, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Environment > \uicontrol System.
+ terminal to use on Linux and \macos, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Environment > \uicontrol System.
\li Open a terminal window in the project directory that is configured
for building or running the project.
\li Expand or collapse the tree view to show or hide all files and
@@ -106,8 +106,8 @@
\li Close all files in a project.
\li Close the selected project or all projects except the selected
one. By default, all files in the projects are also
- closed. To keep them open, deselect the \uicontrol Tools >
- \uicontrol Options > \uicontrol {Build & Run} > \uicontrol General
+ closed. To keep them open, deselect the \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Build & Run} > \uicontrol General
> \uicontrol {Close source files along with project} check box.
\endlist
diff --git a/doc/qtcreator/src/user-interface/creator-ui.qdoc b/doc/qtcreator/src/user-interface/creator-ui.qdoc
index 8e8536d7763..3a701dc6c86 100644
--- a/doc/qtcreator/src/user-interface/creator-ui.qdoc
+++ b/doc/qtcreator/src/user-interface/creator-ui.qdoc
@@ -77,8 +77,8 @@
You can use the kit selector (2) to select the
\l{glossary-buildandrun-kit}{kit} for running (3), debugging (4), or
- building (5) the application. Output from these actions is displayed in the
- output panes (7).
+ building (5) the application. Output from these actions is displayed on
+ the task bar (7).
You can use the \l{Searching with the Locator}{locator} (6) to browse
through projects, files, classes, functions, documentation, and file
@@ -93,7 +93,7 @@
\li \l{Selecting Modes}{Mode selector}
\li \l{Working with Sidebars}{Sidebars}
\li \l{Browsing Project Contents}{Views}
- \li \l{Viewing Output}{Output panes}
+ \li \l{Viewing Output}{Output}
\endlist
\else
@@ -111,7 +111,7 @@
\section1 For \macos Users
\QC uses standard names and locations for standard features, such as
- \e options or \e preferences. In this manual, the names and locations on
+ \e preferences. In this manual, the names and locations on
Windows and Linux are usually used to keep the instructions short. Here are
some places to check if you cannot find a function, dialog, or keyboard
shortcut on \macos when following the instructions:
@@ -121,7 +121,7 @@
\li For
\li Look In
\row
- \li \uicontrol Tools > \uicontrol Options
+ \li \uicontrol Edit > \uicontrol Preferences
\li \uicontrol {\QC} > \uicontrol Preferences
\row
\li \uicontrol Help > \uicontrol {About Plugins}
@@ -141,7 +141,7 @@
To toggle the visibility of these menu items:
\list 1
- \li Go to \uicontrol Tools > \uicontrol Options.
+ \li Go to \uicontrol Edit > \uicontrol Preferences.
\li On the \uicontrol Environment tab, select
\uicontrol{Qt Design Studio Configuration}.
\li Clear the checkbox for the items that you want to be visible.
@@ -156,17 +156,17 @@
\section1 Switching UI Themes
Themes enable you to change the appearance of the UI from dark to light,
- for example. To switch themes, select \uicontrol Tools > \uicontrol Options
+ for example. To switch themes, select \uicontrol Edit > \uicontrol Preferences
> \uicontrol Environment, and then select a theme in the \uicontrol Theme
field.
- \image qtcreator-options-environment-interface.png "Interface settings"
+ \image qtcreator-options-environment-interface.png "Interface preferences"
\section1 Changing Languages
\QC has been localized into several languages. If the system language
is one of the supported languages, it is automatically selected. To
- change the language, select \uicontrol Tools > \uicontrol Options >
+ change the language, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol Environment and select a language in the \uicontrol Language
field. Select \uicontrol {Restart Now} to restart \QC and have the change
take effect.
@@ -183,13 +183,13 @@
\li On Windows, if no \l{High DPI}{scaling environment variables} are
set, \QC instructs Qt to detect the scaling factor and use it for
\QC.
- \li On Linux, \QC leaves it to the user to enable high DPI scaling,
+ \li On Linux, \QC leaves it to the user to enable high DPI scaling
because the process varies so much on different distributions
and windowing systems that it cannot be reliably done automatically.
\endlist
To override the default approach and always enable high-DPI scaling, select
- \uicontrol Tools > \uicontrol Options > \uicontrol Environment >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment >
\uicontrol {Enable high DPI scaling}. The changes will take effect after you
restart \QC.
@@ -220,6 +220,9 @@
\li Export SVG images to pixmaps
+ \li Copy an image as a data URL, which enables you to include it in web
+ pages as if it were an external resource
+
\li Switch between background and outline modes
\li Zoom in and out
@@ -274,13 +277,8 @@
\li On \macos, the files are located in \c {~/.config/QtProject} and
\c {~/Library/Application Support/QtProject/Qt Creator}.
- \li On Windows XP, the files are located in
- \c {%SystemDrive%\Documents and Settings\%USERNAME%\Application Data\QtProject} and
- \c {%SystemDrive%\Documents and Settings\%USERNAME%\Local Settings\Application Data\QtProject}.
-
- \li On Windows 7, the files are located in
- \c {%SystemDrive%\Users\%USERNAME%\AppData\Roaming\QtProject} and
- \c {%SystemDrive%\Users\%USERNAME%\AppData\Local\QtProject}.
+ \li On Windows, the files are located in
+ \c {%appdata%\QtProject} and \c {%localappdata%\QtProject}.
\endlist
\endif
@@ -377,9 +375,9 @@
\title Viewing Output
- \image qtcreator-general-messages.png "General Messages output pane"
+ \image qtcreator-general-messages.png "General Messages"
- The task pane in \QC can display one of the following panes:
+ The taskbar in \QC can display following types of output:
\list
@@ -405,30 +403,30 @@
\endlist
- Output panes are available on the taskbar in all \l{Selecting Modes}{modes}.
+ Output is available on the taskbar in all \l{Selecting Modes}{modes}.
- \image qtcreator-output-panes-taskbar.png "Output panes on the taskbar"
+ \image qtcreator-output-panes-taskbar.png "Output on the taskbar"
- You can open output panes in the following ways:
+ You can view output in the following ways:
\list
- \li Select the output pane on the taskbar.
- \li Select \key Alt (\key Cmd on \macos) and the number of the pane on
+ \li Select the output view on the taskbar.
+ \li Select \key Alt (\key Cmd on \macos) and the number of the view on
the taskbar.
\li Select \inlineimage icons/output-pane-menu.png
- , and then select the pane to open.
- \li Select \uicontrol View > \uicontrol {Output Panes}.
+ , and then select the view to open.
+ \li Select \uicontrol View > \uicontrol Output.
The menu items also display the keyboard shortcuts that you can use.
\endlist
- To maximize an open output pane, select the \inlineimage icons/arrowup.png
- (\uicontrol {Maximize Output Pane}) button or press \key {Alt+Shift+9}.
+ To maximize an open output view, select the \inlineimage icons/arrowup.png
+ (\uicontrol Maximize) button or press \key {Alt+Shift+9}.
To increase or decrease the output text size, select \inlineimage icons/plus.png
(\uicontrol {Zoom In}) or \inlineimage icons/minus.png
(\uicontrol {Zoom Out}), or press \key Ctrl++ or \key Ctrl+-. Zooming is
- not supported in all output panes.
+ not supported in all output views.
To open the \uicontrol{General Messages} and
\if defined(qtcreator)
@@ -436,26 +434,25 @@
\else
\l{Using Git}{Version Control}
\endif
- panes, select \uicontrol View > \uicontrol {Output Panes}.
+ views, select \uicontrol View > \uicontrol Output.
\if defined(qtcreator)
- To display the \uicontrol {To-Do Entries} pane, enable the \uicontrol Todo
- plugin.
+ To view \uicontrol {To-Do Entries}, enable the \uicontrol Todo plugin.
\endif
For more information about the \uicontrol {QML Debugger Console} view, see
\l{Executing JavaScript Expressions}.
- If the text in the output panes is not displayed correctly, \QC might
+ If the text in the output is not displayed correctly, \QC might
be using a different codec from the one used by the tools that generate
- the output. To specify the codec to use, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Environment > \uicontrol Interface, and
+ the output. To specify the codec to use, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Environment > \uicontrol Interface, and
then select the codec in the \uicontrol {Text codec for tools} field.
- \image qtcreator-options-environment-interface.png "Interface tab in the Environment options"
+ \image qtcreator-options-environment-interface.png "Interface tab in the Environment preferences"
\section1 Finding and Filtering Output
- To search from output, press \key {Ctrl+F} when the pane is active. Enter
+ To search from output, press \key {Ctrl+F} when the view is active. Enter
search criteria in the \uicontrol Find field. For more information, see
\l{Finding and Replacing}.
@@ -466,11 +463,11 @@
case-sensitivity. Select \uicontrol {Show Non-matching Lines} to
hide the lines that match the filter.
- Finding and filtering are not supported in all output panes.
+ Finding and filtering are not supported in all output views.
\section1 Issues
- The \uicontrol{Issues} pane provides lists of following types of issues:
+ \uicontrol{Issues} provides lists of following types of issues:
\list
@@ -491,8 +488,8 @@
{Errors and warnings from the current editor}.
\endif
- \li \uicontrol Compile - Selected output from the compiler. Open the
- \uicontrol {Compile Output} pane for more detailed information.
+ \li \uicontrol Compile - Selected output from the compiler. Open
+ \uicontrol {Compile Output} for more detailed information.
\li \uicontrol{Debug Information} - Lists debug information packages that might
be missing.
@@ -510,7 +507,7 @@
\if defined(qtcreator)
\li \uicontrol {My Tasks} - Entries from a task list file (.tasks) generated
- by \l{Showing Task List Files in Issues Pane}
+ by \l{Showing Task List Files in Issues}
{code scanning and analysis tools}.
\li \uicontrol Python - Runtime errors and exceptions of Python scripts.
@@ -522,12 +519,12 @@
\endlist
- The pane filters out irrelevant output from the build tools and presents the
+ The view filters out irrelevant output from the build tools and presents the
issues in an organized way. To further filter the output by type, select
\inlineimage icons/filtericon.png
(\uicontrol {Filter Tree}) and then select a filter.
- \image qtcreator-issues.png "Issues output pane"
+ \image qtcreator-issues.png "Issues"
Select one or several lines to apply context-menu actions to their contents.
You can remove the selected lines or copy their contents to the clipboard.
@@ -539,23 +536,23 @@
select \uicontrol {Show in Editor} in the context menu. The entry must contain the
name of the file where the issue was found.
- To view more information about an issue in the \uicontrol {Compile Output} pane,
+ To view more information about an issue in \l {Compile Output},
select \uicontrol {Show Output} in the context menu.
To jump from one issue to the next or previous one, press \key F6 and
\key Shift+F6.
- By default, the \uicontrol Issues pane is cleared on a new build. To keep
- the issues from the previous build rounds, deselect \uicontrol Tools >
- \uicontrol Options > \uicontrol {Build & Run} > \uicontrol General >
+ By default, the \uicontrol Issues view is cleared on a new build. To keep
+ the issues from the previous build rounds, deselect \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Build & Run} > \uicontrol General >
\uicontrol {Clear issues list on new build}.
\section1 Search Results
- In the \uicontrol{Search Results} pane, you can search through projects, files on
+ In \uicontrol{Search Results}, you can search through projects, files on
a file system or the currently open files:
- \image qtcreator-search-results.png "Search Results output pane"
+ \image qtcreator-search-results.png "Search Results"
The search results are stored in the search history (1) from which you can
select earlier searches.
@@ -570,7 +567,7 @@
\section1 Application Output
- The \uicontrol{Application Output} pane displays the status of a program when
+ \uicontrol{Application Output} displays the status of a program when
it is executed, and the debug output.
\image qtcreator-application-output.png
@@ -586,40 +583,39 @@
running application, and to stop running or debugging.
To specify settings for displaying application output, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Build & Run} >
\uicontrol {Application Output}, or click the \inlineimage icons/settings.png
(\uicontrol {Open Settings Page}) button. You can select whether to open
- the \uicontrol{Application Output} pane on output when running or debugging
+ \uicontrol{Application Output} on output when running or debugging
applications, to clear old output on a new run,
to word-wrap output, and to limit output to the specified number of lines.
\section1 Compile Output
- The \uicontrol{Compile Output} pane provides all output from the compiler.
+ \uicontrol{Compile Output} provides all output from the compiler.
The \uicontrol{Compile Output} is a more detailed version of information
- displayed in the \uicontrol{Issues} pane.
+ displayed in \l Issues.
- \image qtcreator-compile-output.png "Compile Output pane"
+ \image qtcreator-compile-output.png "Compile Output"
Double-click on a file name in an error message to open the file in the
code editor.
Select the \uicontrol {Cancel Build} button to cancel the build.
- To specify whether to open the \uicontrol {Compile Output} pane on output
- when building applications, select \uicontrol Tools > \uicontrol Options >
+ To specify whether to open the \uicontrol {Compile Output} view on output
+ when building applications, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Build & Run} > \uicontrol {Compile Output}, and then select the
- \uicontrol {Open pane when building} check box.
+ \uicontrol {Open Compile Output when building} check box.
In the \uicontrol {Limit output to} field, you can specify the maximum
- amount of build output lines to display in the pane.
+ amount of build output lines to display.
- You can also reach the options page by clicking \inlineimage icons/settings.png
+ You can also open the preferences page by clicking \inlineimage icons/settings.png
(\uicontrol {Open Settings Page}).
- To copy the output from the pane to the clipboard, select
- \uicontrol {Select All} in the context menu, and then select
- \uicontrol Copy. Save the output as a file if you want to
- examine it later without having to build the project again.
+ To copy the output to the clipboard, select \uicontrol {Select All} in the
+ context menu, and then select \uicontrol Copy. Save the output as a file if
+ you want to examine it later without having to build the project again.
This is useful for large projects that take a long time to build.
\section2 Parsing Existing Compile Output
@@ -641,8 +637,8 @@
\li In the \uicontrol {Use parsers from kit} field, select the kit to
use for parsing the output. Select \uicontrol Manage to view
and modify kit settings.
- \li The parser displays the parsed output in the \uicontrol Issues
- pane. By default, the pane is cleared before adding the new output.
+ \li The parser displays the parsed output in \l Issues. By default, the
+ view is cleared before adding the new output.
Deselect the \uicontrol {Clear existing tasks} check box to append
the new output to the old output.
\li Select \uicontrol OK to start parsing.
@@ -651,18 +647,18 @@
\if defined(qtcreator)
\section1 To-Do Entries
- The \uicontrol {To-Do Entries} pane lists the BUG, FIXME, NOTE, TODO, and
+ \uicontrol {To-Do Entries} lists the BUG, FIXME, NOTE, TODO, and
WARNING keywords from the current file, from all project files, or from a
subproject. Click the icons on the toolbar to show only the selected
keywords.
\image qtcreator-todo-pane.png
- To add keywords, select \uicontrol Tools > \uicontrol Options >
+ To add keywords, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {To-Do} > \uicontrol Add. Set an icon and a line background color
for the keyword.
- \image qtcreator-todo-options.png
+ \image qtcreator-todo-options.png "To-Do preferences"
To change the icon and line background color of the selected keyword, select
\uicontrol Edit.
@@ -677,10 +673,17 @@
in the \uicontrol {Scanning scope} group.
To exclude files from scanning, select \uicontrol {Project Settings} >
- \uicontrol {To-Do} in the
- \uicontrol Projects mode. Select \uicontrol Add and enter a regular
- expression that matches the path to files to exclude. Use a forward slash
- (/) as a separator in the path also on Windows.
+ \uicontrol {To-Do} in the \uicontrol Projects mode.
+
+ \image qtcreator-todo-excluded-files.png "Excluded Files in To-Do preferences"
+
+ Select \uicontrol Add and double-click the placeholder text in
+ \uicontrol {Exclude Files} to enter a regular expression that
+ matches the path to files to exclude. Use a forward slash (/)
+ as a separator in the path also on Windows.
+
+ Select the link in \uicontrol {Use global settings} to open global
+ To-Do preferences.
The Todo plugin is disabled by default. To enable the plugin, select
\uicontrol Help > \uicontrol {About Plugins} > \uicontrol Utilities >
@@ -688,8 +691,8 @@
and load the plugin.
In addition, you can open task list files generated by code scanning and
- analysis tools in the \uicontrol Issues pane. For more information, see
- \l{Showing Task List Files in Issues Pane}.
+ analysis tools in \l Issues. For more information, see
+ \l{Showing Task List Files in Issues}.
\endif
*/
diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs-clearcase.qdoc b/doc/qtcreator/src/vcs/creator-only/creator-vcs-clearcase.qdoc
index 4518acc43ef..946c2f2eae8 100644
--- a/doc/qtcreator/src/vcs/creator-only/creator-vcs-clearcase.qdoc
+++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs-clearcase.qdoc
@@ -51,7 +51,7 @@
\li Download \l{http://gnuwin32.sourceforge.net/packages/diffutils.htm}
{Diffutils} and extract it to a directory in your PATH.
- \li Select \uicontrol Tools > \uicontrol Options >
+ \li Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Version Control} > \uicontrol ClearCase.
\li Select the \uicontrol External radio button. The radio button is
@@ -71,12 +71,12 @@
\uicontrol ClearCase > \uicontrol {Check Out}. If you check out files in a
Unified Change Management (UCM) view, they are added to the change set of
a UCM activity. By default, the activities are automatically assigned names.
- To disable this functionality, select \uicontrol Tools > \uicontrol Options
+ To disable this functionality, select \uicontrol Edit > \uicontrol Preferences
> \uicontrol {Version Control} > \uicontrol ClearCase, and then deselect the
\uicontrol {Automatically assign activity names} check box.
- To automatically check out files when you edit them, select \uicontrol Tools
- > \uicontrol Options > \uicontrol {Version Control} > \uicontrol ClearCase,
+ To automatically check out files when you edit them, select \uicontrol Edit
+ > \uicontrol Preferences > \uicontrol {Version Control} > \uicontrol ClearCase,
and then select the \uicontrol {Automatically check out files on edit}
check box.
@@ -91,12 +91,12 @@
To create a permanent new version of the current file or all files in the
versioned object base (VOB), select \uicontrol Tools >
\uicontrol {ClearCase} > \uicontrol {Check In}. To be asked to confirm
- that you want to check in the files, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Version Control} > \uicontrol ClearCase,
+ that you want to check in the files, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Version Control} > \uicontrol ClearCase,
and then select the \uicontrol {Prompt on check-in} check box.
By default, you are asked to enter a comment when checking files out or in.
- To suppress this prompt, select \uicontrol Tools > \uicontrol Options >
+ To suppress this prompt, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Version Control} > \uicontrol ClearCase, and then select the
\uicontrol {Do not prompt for comment during checkout or check-in} check
box.
@@ -107,7 +107,7 @@
\uicontrol Tools > \uicontrol ClearCase > \uicontrol {Undo Hijack}.
By default, the files in the VOBs are indexed for quick access to their
- statuses. To disable indexing, select \uicontrol Tools > \uicontrol Options
+ statuses. To disable indexing, select \uicontrol Edit > \uicontrol Preferences
> \uicontrol {Version Control} > \uicontrol ClearCase, and then select the
\uicontrol {Disable indexer} check box. To only have some VOBs indexed,
specify them in the \uicontrol {Index only VOBs} field.
diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs-cvs.qdoc b/doc/qtcreator/src/vcs/creator-only/creator-vcs-cvs.qdoc
index 9db5e06cd29..9d34990917b 100644
--- a/doc/qtcreator/src/vcs/creator-only/creator-vcs-cvs.qdoc
+++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs-cvs.qdoc
@@ -51,8 +51,8 @@
To unedit files in the local directory, as well as recursively in all
subdirectories, select \uicontrol {Unedit Repository}.
- To specify the CVS root directory, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Version Control} > \uicontrol CVS, and then
+ To specify the CVS root directory, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Version Control} > \uicontrol CVS, and then
specify the path to the directory in the \uicontrol {CVS root} field.
You can specify settings for viewing diff output in the
diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs-gitlab.qdoc b/doc/qtcreator/src/vcs/creator-only/creator-vcs-gitlab.qdoc
new file mode 100644
index 00000000000..7c4e9589a48
--- /dev/null
+++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs-gitlab.qdoc
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Creator documentation.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+**
+****************************************************************************/
+
+/*!
+ \previouspage creator-vcs-git.html
+ \page creator-vcs-gitlab.html
+ \nextpage creator-vcs-mercurial.html
+
+ \title Using GitLab
+
+ GitLab is a DevOps tool developed by GitLab. You can clone projects from
+ GitLab servers and use \l{Using Git}{Git} to manage your local and remote
+ repositories.
+
+ To enable the experimental GitLab plugin, select \uicontrol Help >
+ \uicontrol {About Plugins} > \uicontrol {Version Control} >
+ \uicontrol GitLab. Then select \uicontrol {Restart Now} to
+ restart \QC and load the plugin.
+
+ To use GitLab, you must create a connection to the GitLab server and clone
+ the projects you want to work on. You can also link previously cloned
+ projects to GitLab in the project settings. This enables you to receive
+ event notifications in the \l {Viewing Output}{Version Control} pane.
+
+ \section1 Connecting to GitLab Servers
+
+ To connect to a GitLab server, you need to specify the server host name and
+ port number, as well as an access token that you create in GitLab for \QC.
+ The permission scope of the token must be at least \c read_api or \c api.
+
+ To specify connections to GitLab servers, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Version Control} > \uicontrol GitLab:
+
+ \image qtcreator-gitlab-preferences.png
+
+ To add GitLab servers:
+
+ \list 1
+ \li Select \uicontrol Add to open the \uicontrol {Add Server} dialog:
+ \image qtcreator-gitlab-preferences-add-server.png
+ \li In \uicontrol Host, enter the host name of the GitLab server.
+ \li In \uicontrol Description, enter a free-form text that is displayed
+ in the GitLab settings of a linked project.
+ \li In \uicontrol {Access token}, enter the access token you created for
+ \QC in the GitLab server, in \uicontrol Preferences >
+ \uicontrol {Access Tokens}.
+ \li In \uicontrol Port, enter a port number.
+ \li Deselect the \uicontrol HTTPS check box to use an HTTP connection
+ instead of a secure connection.
+ \li Select \uicontrol Add to create the connection.
+ \endlist
+
+ In the \uicontrol GitLab tab, \uicontrol curl displays the path to the
+ \c curl tool used for HTTP connections. You can specify another path to
+ use another instance of the tool than the one found by \QC.
+
+ To edit the selected connection, select \uicontrol Edit.
+
+ To remove the selected connection, select \uicontrol Remove.
+
+ \section1 Cloning Projects
+
+ You can clone projects from the connected GitLab servers. \QC reads your
+ user name and ID from the access token and displays the available projects
+ in each server. You can search for a particular project or browse projects
+ in the list.
+
+ To clone projects from GitLab:
+
+ \list 1
+ \li Select \uicontrol Tools > \uicontrol GitLab to view a list of
+ connected GitLab servers and available projects in each server:
+ \image qtcreator-gitlab-project-list.png
+ \li In \uicontrol Remote, select a GitLab server.
+ \li In \uicontrol Projects, select the project to clone.
+ \li Select \uicontrol Clone to open the \uicontrol {Clone Repository}
+ dialog:
+ \image qtcreator-gitlab-clone-repository.png
+ \li In \uicontrol Repository, specify the URL of the repository.
+ \li In \uicontrol Path, specify the path where to clone the repository.
+ \li In \uicontrol Directory, specify the name of the directory for the
+ cloned repository.
+ \li Select the \uicontrol Recursive check box to also clone submodules
+ of the repository.
+ \li Select \uicontrol Clone to clone the project to the specified
+ directory.
+ \endlist
+
+ \QC automatically opens the project. If the cloned project has several
+ project files (such as CMakeList.txt, .pro, and .qbs), \QC prompts you to
+ select the one to open. If it does not contain a project file that \QC can
+ open, select \uicontrol File > \uicontrol {New Project} >
+ \uicontrol {Import Project} > \uicontrol {Import Existing Project} to
+ import the project as a generic project. For more information, see
+ \l {Using Project Wizards}.
+
+ \section1 Linking Projects with GitLab
+
+ Link a project with a GitLab token to receive notifications on events, such
+ as merge requests, issues, or comments, in the \uicontrol {Version Control}
+ pane. The information is fetched every 15 minutes. Only events that occurred
+ after the last time you logged into GitLab are displayed when you open the
+ project for the first time. Subsequently, events that occurred after the last
+ successful fetch are listed.
+
+ To link with GitLab:
+
+ \list 1
+ \li In the \uicontrol Projects mode, select \uicontrol {GitLab} to view
+ the GitLab settings for the currently active project:
+ \image qtcreator-gitlab-preferences-project.png
+ \li In \uicontrol Host, select the URL of the GitLab server.
+ \li In \uicontrol {Linked GitLab configuration}, select the GitLab
+ server settings to use.
+ \li Select \uicontrol {Link with GitLab} to receive event notifications
+ in the \uicontrol {Version Control} pane.
+ \endlist
+
+ To test the connection to the host using the access token specified in the
+ GitLab configuration, select \uicontrol {Test Connection}.
+
+ To stop the reception of event notifications, select
+ \uicontrol {Unlink from GitLab}.
+*/
diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs-mercurial.qdoc b/doc/qtcreator/src/vcs/creator-only/creator-vcs-mercurial.qdoc
index 244cb995a8b..e4212947a7b 100644
--- a/doc/qtcreator/src/vcs/creator-only/creator-vcs-mercurial.qdoc
+++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs-mercurial.qdoc
@@ -30,7 +30,7 @@
// **********************************************************************
/*!
- \previouspage creator-vcs-git.html
+ \previouspage creator-vcs-gitlab.html
\page creator-vcs-mercurial.html
\nextpage creator-vcs-perforce.html
diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs-options.qdocinc b/doc/qtcreator/src/vcs/creator-only/creator-vcs-options.qdocinc
index 47727d22e4b..98f763f0ede 100644
--- a/doc/qtcreator/src/vcs/creator-only/creator-vcs-options.qdocinc
+++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs-options.qdocinc
@@ -33,8 +33,8 @@
repositories. To allow access, make sure that the command line clients can
be located using the \c{PATH} environment variable. Alternatively, specify
the path to the command line client executable in the \uicontrol Command
- field in the version control system specific tab in \uicontrol Tools >
- \uicontrol Options > \uicontrol {Version Control}.
+ field in the version control system specific tab in \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Version Control}.
If authentication is required to access the repository, enter the user
credentials in the \uicontrol Username and \uicontrol Password fields.
@@ -54,9 +54,8 @@
\section1 Setting Up General Options
- Select \uicontrol{Tools} > \uicontrol{Options} > \uicontrol{Version Control}
- > \uicontrol{General}
- to specify settings for submit messages:
+ Select \uicontrol Edit > \uicontrol Preferences > \uicontrol {Version Control}
+ > \uicontrol General to specify settings for submit messages:
\list
\li \uicontrol{Wrap submit messages at} limits the line length of a
diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs-perforce.qdoc b/doc/qtcreator/src/vcs/creator-only/creator-vcs-perforce.qdoc
index d1cd6129d99..575fa2cfe92 100644
--- a/doc/qtcreator/src/vcs/creator-only/creator-vcs-perforce.qdoc
+++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs-perforce.qdoc
@@ -46,7 +46,7 @@
\section1 Configuring Perforce
- In the Perforce options, you can specify workspace details:
+ In the Perforce preferences, you can specify workspace details:
\uicontrol {P4 user}, \uicontrol {P4 client}, and \uicontrol {P4 port}. To
specify the details individually for several projects, use configuration
files instead. Create a \c {p4config.txt} configuration file for each
@@ -60,8 +60,8 @@
\l {Using Common Functions}, you can select \uicontrol Tools >
\uicontrol Perforce > \uicontrol {Edit File} to open a file for editing
within the client workspace. By default, files are automatically opened for
- editing. To disable this feature, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Version Control} > \uicontrol Perforce,
+ editing. To disable this feature, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Version Control} > \uicontrol Perforce,
and then deselect the \uicontrol {Automatically open files when editing}
check box.
@@ -75,7 +75,7 @@
\uicontrol Tools > \uicontrol Perforce > \uicontrol Describe.
By default, you are prompted to confirm that you want to submit changes.
- To suppress the prompt, select \uicontrol Tools > \uicontrol Options >
+ To suppress the prompt, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Version Control} > \uicontrol Perforce, and then deselect the
\uicontrol {Prompt on submit} check box.
*/
diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs-subversion.qdoc b/doc/qtcreator/src/vcs/creator-only/creator-vcs-subversion.qdoc
index a84f6450534..a0e9caa3944 100644
--- a/doc/qtcreator/src/vcs/creator-only/creator-vcs-subversion.qdoc
+++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs-subversion.qdoc
@@ -44,7 +44,7 @@
for a revision.
By default, you are prompted to confirm that you want to submit changes.
- To suppress the prompt, select \uicontrol Tools > \uicontrol Options >
+ To suppress the prompt, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Version Control} > \uicontrol Subversion, and then deselect the
\uicontrol {Prompt on submit} check box.
diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc b/doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc
index c00cd06cb1b..27869401a4d 100644
--- a/doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc
+++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -73,6 +73,10 @@
Gerrit version 2.6, or later
\row
+ \li \l{Using GitLab}{GitLab}
+ \li \l{http://gitlab.com/}
+ \li Experimental
+ \row
\li \l{Using Mercurial}{Mercurial}
\li \l{http://mercurial.selenic.com/}
\li
@@ -124,14 +128,15 @@
\li \l{https://doc.qt.io/qtcreator/creator-vcs-fossil.html}
{Qt Creator Fossil Plugin Manual}
\li \l{Using Git}
+ \li \l{Using GitLab}
\li \l{Using Mercurial}
\li \l{Using Perforce}
\li \l{Using Subversion}
\endlist
- The \uicontrol{Version Control} output pane displays the commands that are
+ \uicontrol{Version Control} displays the commands that are
executed, a timestamp, and the relevant output. Select \uicontrol View >
- \uicontrol {Output Panes} > \uicontrol {Version Control} to open the pane.
+ \uicontrol Output > \uicontrol {Version Control} to open the view.
\image qtcreator-vcs-pane.png
diff --git a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
index 348c775ea70..a9a9f55909e 100644
--- a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
+++ b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
@@ -36,7 +36,7 @@
\nextpage studio-porting-projects.html
\else
\previouspage creator-vcs-cvs.html
- \nextpage creator-vcs-mercurial.html
+ \nextpage creator-vcs-gitlab.html
\endif
\title Using Git
@@ -62,7 +62,7 @@
installation directory, and therefore, the authorization fails.
You can set the \c HOME environment variable from \QC. Select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Version Control} >
\uicontrol Git, and then select the
\uicontrol {Set "HOME" environment variable} check box. \c HOME is
set to \c %HOMEDRIVE%%HOMEPATH% when the Git executable is run and
@@ -198,9 +198,9 @@
\section2 Viewing Git Status
- To view the status of the repository in the \uicontrol {Version Control}
- output pane, select \uicontrol Status. The context menu contains additional
- actions, such as selecting and clearing all entries in the pane, copying
+ To view the status of the repository in \uicontrol {Version Control},
+ select \uicontrol Status. The context menu contains additional
+ actions, such as selecting and clearing all entries, copying
text, and opening files.
\section2 Committing Changes to Git
@@ -480,7 +480,7 @@
To pull changes from the remote repository, select \uicontrol Pull. If there
are locally modified files, you are prompted to stash the changes. Select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Version Control} >
\uicontrol Git and then select the \uicontrol {Pull with rebase} check box
to perform a rebase operation while pulling.
@@ -569,7 +569,7 @@
To refresh the list of changes, select \uicontrol Refresh.
The \uicontrol Remote field lists the remotes of the current repository that
- are detected as Gerrit servers. Select \uicontrol Tools > \uicontrol Options
+ are detected as Gerrit servers. Select \uicontrol Edit > \uicontrol Preferences
> \uicontrol {Version Control} > \uicontrol Gerrit to specify a fallback
connection to a Gerrit server over SSH. The Gerrit REST interface and the
\l{https://curl.haxx.se/}{curl} tool are used for HTTP connections.
@@ -577,7 +577,7 @@
Select the \uicontrol HTTPS check box to prepend \c https to the Gerrit URL
if Gerrit does not provide it.
- \image qtcreator-gerrit-options.png
+ \image qtcreator-gerrit-options.png "Gerrit preferences"
\section1 Working with Git Tools
@@ -594,11 +594,11 @@
\uicontrol Git > \uicontrol {Git Tools} > \uicontrol Gitk. You can also
start the tool to view commits in the current document or in the folder that
contains the current document. To specify arguments for running Gitk, select
- \uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol {Version Control} >
\uicontrol Git.
To use some other application for viewing Git history, such as GitX or
- QGit viewer, select \uicontrol Tools > \uicontrol Options >
+ QGit viewer, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Version Control} > \uicontrol Git and specify the path to the
application executable in the \uicontrol {Command} field. To start the
application, select \uicontrol Tools > \uicontrol Git
diff --git a/doc/qtcreator/src/webassembly/creator-webassembly.qdoc b/doc/qtcreator/src/webassembly/creator-webassembly.qdoc
index 9b1a84e1b9d..32119a3bb31 100644
--- a/doc/qtcreator/src/webassembly/creator-webassembly.qdoc
+++ b/doc/qtcreator/src/webassembly/creator-webassembly.qdoc
@@ -93,15 +93,15 @@
To configure \QC for building Qt apps for the web:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices >
\uicontrol WebAssembly.
\li In the \uicontrol {Emscripten SDK path} field, enter the root
directory where \c emsdk is installed.
\li \QC configures the \uicontrol {Emscripten SDK environment} for you
if the \c emsdk is supported by the Qt for WebAssembly version that
you will use for developing the application.
- \image qtcreator-webassembly-options.png "Qt for WebAssembly device options"
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits.
+ \image qtcreator-webassembly-options.png "Qt for WebAssembly device preferences"
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits.
\image qtcreator-kit-webassembly.png "Qt for WebAssembly kit"
\li In the \uicontrol Compiler group, \uicontrol {Emscripten Compiler}
should have been automatically detected for both C++ and C. If not,
@@ -114,7 +114,7 @@
to \QC. To add kits:
\list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
\uicontrol Add.
\li In the \uicontrol Name field, specify a name for the kit.
\li In the \uicontrol {Device type} field, select
diff --git a/doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc b/doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc
index 546cbd20277..50b20ad7369 100644
--- a/doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc
+++ b/doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -68,9 +68,8 @@
\image qtcreator-new-project-build-system-qt-gui.png "Define Build System dialog"
- \li In the \uicontrol {Build system} field, select the build system to
- use for building and running the project: \l qmake,
- \l {Setting Up CMake}{CMake}, or \l {Setting Up Qbs}{Qbs}.
+ \li In the \uicontrol {Build system} field, select \l {Setting Up CMake}
+ {CMake} as the build system to use for building the project.
\li Select \uicontrol Next or \uicontrol Continue to open the
\uicontrol{Class Information} dialog.
@@ -117,8 +116,7 @@
\note The project opens in the \uicontrol Edit mode, and these instructions are
hidden. To return to these instructions, open the \uicontrol Help mode.
- If you selected qmake as the build system, the TextFinder project now
- contains the following files:
+ The TextFinder project now contains the following files:
\list
@@ -126,14 +124,13 @@
\li textfinder.h
\li textfinder.cpp
\li textfinder.ui
- \li textfinder.pro
+ \li CMakeLists.txt
\endlist
\image qtcreator-textfinder-contents.png "TextFinder project contents"
The .h and .cpp files come with the necessary boiler plate code.
- The .pro file is complete.
If you selected CMake as the build system, \QC created a CMakeLists.txt
project file for you.
@@ -312,7 +309,7 @@
\li In the \uicontrol{Name} field, enter \b{textfinder}.
- \li In the \uicontrol{Path} field, enter \c{C:\Qt\examples\TextFinder},
+ \li In the \uicontrol{Path} field, enter the path to the project,
and select \uicontrol Next or \uicontrol Continue.
The \uicontrol{Project Management} dialog opens.
@@ -320,10 +317,16 @@
\image qtcreator-add-resource-wizard3.png "Project Management dialog"
- \li In the \uicontrol{Add to project} field, select \b{TextFinder.pro}
+ \li In the \uicontrol{Add to project} field, select \b{TextFinder}
and select \uicontrol{Finish} or \uicontrol Done to open the file
in the code editor.
+ \li In the \uicontrol Copy to Clipboard dialog, select \uicontrol Yes to
+ copy the path to the resource file to the clipboard for adding it
+ to the CMakeLists.txt file.
+
+ \image qtcreator-add-resource-wizard4.png "Copy to Clipboard dialog"
+
\li Select \uicontrol Add > \uicontrol {Add Prefix}.
\li In the \uicontrol{Prefix} field, replace the default prefix with a slash
@@ -336,10 +339,20 @@
\endlist
- \section1 Compiling and Running Your Program
+ \section1 Adding Resources to Project File
+
+ For the text file to appear when you run the application, you must specify
+ the resource file as a source file in the \e CMakeLists.txt file that the
+ wizard created for you:
+
+ \quotefromfile textfinder/CMakeLists.txt
+ \skipto set(PROJECT_SOURCES
+ \printuntil )
+
+ \section1 Compiling and Running Your Application
Now that you have all the necessary files, select the
\inlineimage icons/run_small.png
- button to compile and run your program.
+ button to compile and run your Application.
*/
diff --git a/doc/qtcreator/src/widgets/qtdesigner-overview.qdoc b/doc/qtcreator/src/widgets/qtdesigner-overview.qdoc
index 42a547d44f9..b0708db98dd 100644
--- a/doc/qtcreator/src/widgets/qtdesigner-overview.qdoc
+++ b/doc/qtcreator/src/widgets/qtdesigner-overview.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -73,10 +73,7 @@
\list
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Designer.
-
- \li Specify settins for generating classes and code in \uicontrol {Class
- Generation}.
+ \li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Designer.
\li Specify embedded device profiles, that determine style, font, and
screen resolution, for example, in \uicontrol{Embedded Design}.
@@ -91,29 +88,40 @@
To preview the settings, select \uicontrol Tools > \uicontrol{Form Editor} >
\uicontrol Preview, or press \key Alt+Shift+R.
- \section1 Previewing Forms Using Device Skins
+ \section1 Previewing Forms Using Device Profiles
- A \e {device skin} is a set of configuration files that describe a mobile
+ A \e {device profile} is a set of configuration files that describe a mobile
device. It includes a border image that surrounds the form and depicts a
mobile device with its buttons.
- To preview your form using device skins:
-
- \list 1
-
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Designer.
+ To preview your form using device profiles, select \uicontrol Tools >
+ \uicontrol {Form Editor} > \uicontrol {Preview In}, and then select a
+ device profile.
- \li Select the \uicontrol{Print/Preview Configuration} check box.
+ \section2 Adding Device Profiles
- \li In the \uicontrol {Device skin} field, select a device skin.
+ To add device profiles:
- \li When the form is open in \uicontrol Design mode, press \key Alt+Shift+R.
-
- \li To end the preview, right-click the skin and select \uicontrol Close in
- the context menu.
+ \list 1
+ \li \uicontrol Edit > \uicontrol Preferences > \uicontrol Designer.
+ \image qtdesigner-embedded-design.png "Qt Designer Embedded Design preferences"
+ \li In \uicontrol {Embedded Design}, select \inlineimage icons/plus.png
+ to open the \uicontrol {Add Profile} dialog.
+ \image qtdesigner-add-profile.png "Add Profile dialog"
+ \li In \uicontrol Name, enter a name for the device. The name is
+ displayed as an option in \uicontrol {Preview In}.
+ \li In \uicontrol Family, select the font to use.
+ \li In \uicontrol {Point Size}, select the font size.
+ \li In \uicontrol Style, select one of the predefined styles.
+ \li In \uicontrol {Device DPI}, select one of the predefined DPI
+ values or \uicontrol {User defined} to specify a custom value.
+ \li Select \uicontrol OK to add the device profile to the list.
\endlist
+ To import device profiles from .qdp files, select \uicontrol Open. To save
+ them as .qdp files, select \uicontrol Save.
+
\section1 Adding Widgets
You can use Qt APIs to create plugins that extend Qt applications. This
diff --git a/doc/qtcreatordev/src/actionmanager.qdoc b/doc/qtcreatordev/src/actionmanager.qdoc
index 49c57d6818d..fb135a073f7 100644
--- a/doc/qtcreatordev/src/actionmanager.qdoc
+++ b/doc/qtcreatordev/src/actionmanager.qdoc
@@ -28,7 +28,7 @@
\title The Action Manager and Commands
\QC provides a central options page for managing shortcuts for actions in
- \uicontrol Tools > \uicontrol Options > \uicontrol Environment >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment >
\uicontrol Keyboard. Plugins must tell \QC about the actions they provide,
so they can appear in the options. Also some actions, like \uicontrol Edit >
\uicontrol Undo, need to be dispatched to different plugins depending on the
diff --git a/doc/qtcreatordev/src/common-extension-tasks.qdoc b/doc/qtcreatordev/src/common-extension-tasks.qdoc
index 7f514af3706..830c85560e3 100644
--- a/doc/qtcreatordev/src/common-extension-tasks.qdoc
+++ b/doc/qtcreatordev/src/common-extension-tasks.qdoc
@@ -83,9 +83,9 @@
\li \l{Core::INavigationWidgetFactory}
\row
- \li Add an options page to the \uicontrol Options dialog.
+ \li Add a page to the \uicontrol Preferences dialog.
\li Add a new page to existing or new category in
- \uicontrol Tools > \uicontrol Options.
+ \uicontrol Edit > \uicontrol Preferences.
\li \l{Core::IOptionsPage}
\row
diff --git a/doc/qtcreatordev/src/qtcreator-dev.qdoc b/doc/qtcreatordev/src/qtcreator-dev.qdoc
index 7a1e1093be8..58ff5e3b568 100644
--- a/doc/qtcreatordev/src/qtcreator-dev.qdoc
+++ b/doc/qtcreatordev/src/qtcreator-dev.qdoc
@@ -199,7 +199,7 @@
Usually, you can use the external tool specification files to start the
tool. If starting the tool and handling its output require more complex
logic, you can add a menu item to \QC with a plugin. If you need a way to
- configure the tool in \QC, you can add an \uicontrol Options page for it.
+ configure the tool in \QC, you can add an options page for it.
\list
\li \l{https://doc.qt.io/qtcreator/creator-editor-external.html}{Using External Tools}
@@ -224,11 +224,11 @@
One way to handle that would be to let the tool create an output file, which
is then opened within \QC. You provide an editor (probably read-only) for
handling this file. For lists of issues, consider creating task list files
- which are shown in the \uicontrol Issues output pane.
+ which are shown in \l Issues.
\list
\li \l{https://doc.qt.io/qtcreator/creator-task-lists.html}
- {Showing Task List Files in the Issues Pane}
+ {Showing Task List Files in Issues}
\li \l{Creating Plugins}
\li \l{Qt Creator Coding Rules}
\omit
diff --git a/doc/qtcreatordev/src/qtcreator-documentation.qdoc b/doc/qtcreatordev/src/qtcreator-documentation.qdoc
index 6723fd745d3..66edefce4c6 100644
--- a/doc/qtcreatordev/src/qtcreator-documentation.qdoc
+++ b/doc/qtcreatordev/src/qtcreator-documentation.qdoc
@@ -179,7 +179,7 @@
The \c {\else} command is sometimes used to replace some \QC specific text
with text that applies to \QDS. For example, the following \c if-else
- statement is needed in the \QC Manual sources, because the project wizards
+ statement is needed in the \QC Manual sources because the project wizards
in \QDS are different from those in \QC, and are therefore described in
a new topic that is located in the \QDS Manual sources:
@@ -251,7 +251,7 @@
It is mostly used in the \QC Manual sources to specify values for the
\c {\previouspage} and \c {\nextpage} commands depending on whether
the \QDS Manual or \QC Manual is being built. For example, the
- following \c if-else statement is needed, because only the Git
+ following \c if-else statement is needed because only the Git
version control system is integrated to \QDS, and information about
the other systems integrated to \QC is hidden:
@@ -349,7 +349,7 @@
topic in the Qt reference documentation.
This improves the consistency of the look and feel of Qt documentation,
- and eliminates the need to describe parts of the UI in the text, because
+ and eliminates the need to describe parts of the UI in the text because
you can just insert the number of the element you are referring to in
brackets.
diff --git a/doc/qtcreatordev/src/qtcreator-ui-text.qdoc b/doc/qtcreatordev/src/qtcreator-ui-text.qdoc
index f7fbad18096..4c14fe704b4 100644
--- a/doc/qtcreatordev/src/qtcreator-ui-text.qdoc
+++ b/doc/qtcreatordev/src/qtcreator-ui-text.qdoc
@@ -259,7 +259,7 @@
Use \c{QDir::toNativeSeparators()} for file and directory names that you
pass to \c{tr().arg()}.
- Do not use markup that spans the whole string, because that can be confusing
+ Do not use markup that spans the whole string because that can be confusing
for translators. For example, instead of:
\code
@@ -404,7 +404,7 @@
\li Dialog that provides feedback to users, in the form of status
information, a warning, or an error message.
\image qtcreator-error-message.png "Message box"
- Output from Qt Creator should be displayed in output panes,
+ Output from Qt Creator should be displayed in output views,
instead.
\li Use the event as the title and provide a solution in the
message box.
@@ -417,10 +417,10 @@
Use descriptive, but short mode names. They have to fit in the
\uicontrol {Mode selector}.
\row
- \li Output pane
- \li A pane displayed in the task pane that displays output from Qt Creator.
- \image qtcreator-output-pane.png "Output pane"
- \li Use descriptive names for output panes.
+ \li Output
+ \li Views to display output from Qt Creator.
+ \image qtcreator-output-pane.png "Output"
+ \li Use descriptive names for output views.
\row
\li Sidebar
\li A view available in the \uicontrol Edit and \uicontrol Debug modes that
diff --git a/doc/qtdesignstudio/config/qtdesignstudio.qdocconf b/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
index c3ba9b4f1ba..f9722725e87 100644
--- a/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
+++ b/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
@@ -41,6 +41,7 @@ excludedirs += ../../qtcreator/examples/accelbubble \
../../qtcreator/src/cmake \
../../qtcreator/src/conan \
../../qtcreator/src/debugger/creator-only \
+ ../../qtcreator/src/docker \
../../qtcreator/src/editors/creator-only \
../../qtcreator/src/howto/creator-only \
../../qtcreator/src/incredibuild \
diff --git a/doc/qtdesignstudio/examples/doc/coffeemachine.qdoc b/doc/qtdesignstudio/examples/doc/coffeemachine.qdoc
index 1f9cfb8baf6..38186fe45de 100644
--- a/doc/qtdesignstudio/examples/doc/coffeemachine.qdoc
+++ b/doc/qtdesignstudio/examples/doc/coffeemachine.qdoc
@@ -168,7 +168,7 @@
\image coffee-machine-timeline-settings.png
We set the start frame for the \c {"selection"} state to 400 and
- the end frame to 200, because we are moving back on the timeline to display
+ the end frame to 200 because we are moving back on the timeline to display
the selection sidebar.
In the \uicontrol {Transition to state} field, we select the state to
diff --git a/doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc b/doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc
index 32cbc60ae3e..2c35cf9bc89 100644
--- a/doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc
+++ b/doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc
@@ -90,7 +90,7 @@
\l {basic-image}{Image}, \l Text, and \l {Mouse Area} components. For the
screen background, we use the \l {basic-rectangle}{Rectangle} component.
- The text might look different on the desktop and MCUs, because on the
+ The text might look different on the desktop and MCUs because on the
desktop we use dynamic font loading, whereas on MCUs fonts are compiled
into application sources. Therefore, the text will always be Maven Pro
on MCUs, whereas on the desktop you'd need to have Maven Pro installed
@@ -227,7 +227,7 @@
\skipto Item {
\printuntil }
- We have to do it this way, because we are developing for MCUs. We have to
+ We have to do it this way because we are developing for MCUs. We have to
use either \c when conditions or set the state directly through code,
which overrides \c when conditions. Otherwise, we could just select the
action to change to the state that we want in the \uicontrol Action field.
diff --git a/doc/qtdesignstudio/images/loader3d-navigator.png b/doc/qtdesignstudio/images/loader3d-navigator.png
new file mode 100644
index 00000000000..0c049a61464
--- /dev/null
+++ b/doc/qtdesignstudio/images/loader3d-navigator.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/loader3d-select-source-component.png b/doc/qtdesignstudio/images/loader3d-select-source-component.png
new file mode 100644
index 00000000000..08bf53eea2a
--- /dev/null
+++ b/doc/qtdesignstudio/images/loader3d-select-source-component.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/loader3d-select-source.png b/doc/qtdesignstudio/images/loader3d-select-source.png
new file mode 100644
index 00000000000..6f9410c4c67
--- /dev/null
+++ b/doc/qtdesignstudio/images/loader3d-select-source.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/loader3d-visibility.png b/doc/qtdesignstudio/images/loader3d-visibility.png
new file mode 100644
index 00000000000..c3518c5e078
--- /dev/null
+++ b/doc/qtdesignstudio/images/loader3d-visibility.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/navigator-show-all-loader.png b/doc/qtdesignstudio/images/navigator-show-all-loader.png
new file mode 100644
index 00000000000..2052be66b38
--- /dev/null
+++ b/doc/qtdesignstudio/images/navigator-show-all-loader.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/qt-sketch-bridge-settings.png b/doc/qtdesignstudio/images/qt-sketch-bridge-settings.png
index 0d7dfe79650..9ce32618b90 100644
--- a/doc/qtdesignstudio/images/qt-sketch-bridge-settings.png
+++ b/doc/qtdesignstudio/images/qt-sketch-bridge-settings.png
Binary files differ
diff --git a/doc/qtdesignstudio/src/components/qtquick-buttons.qdoc b/doc/qtdesignstudio/src/components/qtquick-buttons.qdoc
index 2a6b36695df..21adaeba501 100644
--- a/doc/qtdesignstudio/src/components/qtquick-buttons.qdoc
+++ b/doc/qtdesignstudio/src/components/qtquick-buttons.qdoc
@@ -198,7 +198,7 @@
\inlineimage icons/anchor-fill.png
(\uicontrol {Fill to Parent}) button to always make the
image the same size as its parent. This makes the button
- component scalable, because the image size is bound to the
+ component scalable because the image size is bound to the
component size.
\endlist
\li Select the other border image to edit the values of its properties
diff --git a/doc/qtdesignstudio/src/components/qtquick-controls.qdoc b/doc/qtdesignstudio/src/components/qtquick-controls.qdoc
index 9faf9b85c95..1dba08cf288 100644
--- a/doc/qtdesignstudio/src/components/qtquick-controls.qdoc
+++ b/doc/qtdesignstudio/src/components/qtquick-controls.qdoc
@@ -70,7 +70,7 @@
components, unless it has been explicitly set for them.
\note Take care when enabling wheel events for controls within scrollable
- components, such as \l Flickable, because the control will consume the
+ components, such as \l Flickable because the control will consume the
events, and therefore interrupt scrolling of the flickable.
\uicontrol Spacing is useful for controls that have multiple or repetitive
@@ -130,7 +130,7 @@
The button text should be a verb describing the action, or a noun matching
the title of the popup that will be opened.
- Don't use a button to set state, because a \l Switch is more suitable for
+ Don't use a button to set state because a \l Switch is more suitable for
that purpose.
\section3 Highlighted Buttons
diff --git a/doc/qtdesignstudio/src/components/qtquick-images.qdoc b/doc/qtdesignstudio/src/components/qtquick-images.qdoc
index 256289fd92b..1dabc0aae6d 100644
--- a/doc/qtdesignstudio/src/components/qtquick-images.qdoc
+++ b/doc/qtdesignstudio/src/components/qtquick-images.qdoc
@@ -118,7 +118,7 @@
If the source is an intrinsically scalable image (such as SVG), source size
determines the size of the loaded image regardless of intrinsic size.
- Avoid changing the source size property dynamically, because rendering an
+ Avoid changing the source size property dynamically because rendering an
SVG is slow compared with rendering other image formats.
If the source is a non-scalable image (such as JPEG), the loaded image will
diff --git a/doc/qtdesignstudio/src/components/qtquick-text.qdoc b/doc/qtdesignstudio/src/components/qtquick-text.qdoc
index 33a317f513c..15b34b88a9e 100644
--- a/doc/qtdesignstudio/src/components/qtquick-text.qdoc
+++ b/doc/qtdesignstudio/src/components/qtquick-text.qdoc
@@ -88,7 +88,7 @@
\image qml-translate.png "Text marked for translation"
If you use text IDs instead of plain text, change the default call to
- \c qsTrId(). Select \uicontrol Tools > \uicontrol Options >
+ \c qsTrId(). Select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Qt Quick} > \uicontrol {Qt Quick Designer}, and then select the
\uicontrol {qsTrId()} radio button in the \uicontrol Internationalization
group. For more information about text ID based translations, see
diff --git a/doc/qtdesignstudio/src/overviews/qtquick-placeholder-data.qdoc b/doc/qtdesignstudio/src/overviews/qtquick-placeholder-data.qdoc
index 237cfc67ef6..bfdb708a24e 100644
--- a/doc/qtdesignstudio/src/overviews/qtquick-placeholder-data.qdoc
+++ b/doc/qtdesignstudio/src/overviews/qtquick-placeholder-data.qdoc
@@ -98,7 +98,7 @@
\endqml
This works nicely for applications but \uicontrol {Form Editor} displays a
- zero-sized component. A parent for the opened file does not exist, because
+ zero-sized component. A parent for the opened file does not exist because
the context is missing. To get around the missing context, the idea of a
\e {dummy context} is introduced. If you place a file with the same name as
the application (here, example.qml) in the \c {dummydata/context} directory,
diff --git a/doc/qtdesignstudio/src/overviews/studio-crashpad.qdoc b/doc/qtdesignstudio/src/overviews/studio-crashpad.qdoc
index e195977f8b0..7fb776b619b 100644
--- a/doc/qtdesignstudio/src/overviews/studio-crashpad.qdoc
+++ b/doc/qtdesignstudio/src/overviews/studio-crashpad.qdoc
@@ -43,8 +43,8 @@
of the collected data, see \l {https://sentry.io/security/}
{Security & Compliance} by Sentry.
- To enable sending crash reports, select \uicontrol Tools > \uicontrol
- Options > \uicontrol Environment > \uicontrol System
+ To enable sending crash reports, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol Environment > \uicontrol System
(\uicontrol {Qt Design Studio} > \uicontrol Preferences > \uicontrol
Environment > \uicontrol System on \macos), and then select
\uicontrol {Enable crash reporting}.
diff --git a/doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc b/doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc
index 463148a1c4b..91f03427f2c 100644
--- a/doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc
+++ b/doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc
@@ -42,10 +42,10 @@
For the pop-up survey to appear, you must enable collecting statistics, and
also allow collecting \uicontrol {4 - Detailed usage statistics} in
- \uicontrol Tools > \uicontrol Options > \uicontrol Telemetry >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Telemetry >
\uicontrol {Usage Statistics} > \uicontrol {Telemetry mode}.
You can review the submitted user feedback in
- \uicontrol Tools > \uicontrol Options > \uicontrol Telemetry >
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Telemetry >
\uicontrol {Usage Statistics} > \uicontrol {Collected Data} by selecting
\uicontrol {Qt Quick Designer Usage of views and actions} in
\uicontrol {Data sources}.
diff --git a/doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc b/doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc
index 11980d1128c..99fc659e2ca 100644
--- a/doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc
+++ b/doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc
@@ -104,7 +104,7 @@
You need to install Android SDK packages in \QDS:
\list 1
\li Run \QDS.
- \li Go to \uicontrol Tools > \uicontrol Options > \uicontrol{Devices}.
+ \li Go to \uicontrol Edit > \uicontrol Preferences > \uicontrol{Devices}.
\li Select \uicontrol Yes on the \uicontrol{Missing Android SDK Packages} dialog.
\image qtds-options-dialog-missing-packages.png
\li Select \uicontrol OK on the \uicontrol{Android SDK Changes} dialog.
@@ -117,7 +117,7 @@
have stopped working, try to restart \QDS and run the installation again.
After completing these steps, you should no longer have any errors on the
- \uicontrol Tools > \uicontrol Options > \uicontrol Devices page.
+ \uicontrol Edit > \uicontrol Preferences > \uicontrol Devices page.
\image qtds-options-accept-licenses.png
\section2 Create Android Virtual Devices
@@ -140,7 +140,7 @@
To create an AVD in \QDS:
\list 1
- \li Go to \uicontrol Tools > \uicontrol Options.
+ \li Go to \uicontrol Edit > \uicontrol Preferences.
\li On the \uicontrol Devices tab, select \uicontrol Add and follow the wizard to finalize
the creation. If there is no entry for \e{Android Device} in the
\uicontrol{Available device types} list, try restarting \QDS.
@@ -176,7 +176,7 @@
\image toolbar-show-live-preview.png
\li Select \uicontrol Build > \uicontrol{QML Preview}.
\note The \uicontrol Build menu option is not visible by default. To show
- it, go to \uicontrol Tools > \uicontrol Options > \uicontrol Environment
+ it, go to \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment
> \uicontrol {Qt Design Studio Configuration}.
\image menu-build-qml-preview.png
\endlist
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc
index bc27d5e3484..b8b787face3 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc
@@ -43,10 +43,8 @@
\section1 2D Assets
- You can use the Qt Installer to install \QB if you have a commercial
- \QDS license. You can also purchase a \QB license separately from the
- \l{https://marketplace.qt.io/}{Qt Marketplace} and then install \QB using
- the Qt Installer.
+ You can use the Qt Installer to install \QB if you have a
+ \QDS enterprise license.
\table
\row
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-setup.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-setup.qdoc
index ba43f329238..8dc0620032f 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-setup.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-setup.qdoc
@@ -30,10 +30,10 @@
\title Setting Up \QBPS
- You can purchase a \QBPS license from the \l{https://marketplace.qt.io/}
- {Qt Marketplace}, and then use the Qt Installer to have the \QBPS
- installation package copied to the following path in your Qt installation
- folder:
+ \QBPS is included in the
+ \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
+ You can use the Qt Installer to have the \QBPS plugin package copied to the
+ following path in your Qt installation folder:
\list
\li On Windows: \c {Tools\QtDesignStudio\photoshop_bridge}
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-setup.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-setup.qdoc
index 6f883a1f859..dd507243507 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-setup.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-setup.qdoc
@@ -30,10 +30,10 @@
\title Setting Up \QBSK
- You can purchase a \QBSK license from the \l{https://marketplace.qt.io/}
- {Qt Marketplace}, and then use the Qt Installer to have the \QBSK
- plugin package copied to the following path in your Qt installation
- folder:
+ \QBSK is included in the
+ \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
+ You can use the Qt Installer to have the \QBSK plugin package copied to the
+ following path in your Qt installation folder:
\list
\li On Windows:
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc
index 01f1013b1a5..f5a17f8f693 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc
@@ -245,15 +245,15 @@
component. See \l {Annotating Designs}.
\li Select the \uicontrol Settings tab to specify the export path and
asset format.
- \li Select \uicontrol Export to copy your assets to the export path you
- specified.
+ \li Select \uicontrol Export to export the document into a .qtbridge archive.
\li When the exporting is done, select \uicontrol OK.
\endlist
- All the assets and metadata are copied to the directory you specified. This
- might take a little while depending on the complexity of your project.
+ All the assets and metadata are exported into a .qtbridge archive in the directory
+ you specified. This might take a little while depending on the complexity of
+ your project.
- You can now create a project in \QDS and import the assets to it, as
+ You can now create a project in \QDS and import the .atbrige archive to it, as
described in \l {Creating Projects} and \l{Importing Designs}.
\section1 Specifying Export Path and Asset Format
@@ -263,9 +263,9 @@
\image qt-sketch-bridge-settings.png
- By default, \QBSK exports assets to a directory named after your
- Sketch file located inside the parent directory of the Sketch file
- being exported. You can change the export path in the
+ \QBSK exports assets to a .qtbridge archive named after your
+ Sketch file. By default, the directory is located inside the parent directory
+ of the Sketch file being exported. You can change the export path in the
\uicontrol {Export Path} field.
You can select the default asset format and DPI to use for each
@@ -279,6 +279,12 @@
from PNG files, export assets as progressive JPG or compact SVG,
and include SVG namespaces in SVG files.
+ \section1 Scaling
+
+ You can scale the generated assets and UI artefacts by setting a scaling factor between
+ 0.1 and 10.0 in \uicontrol Factor.
+ \note The factor is independent of the asset scale settings, that is, 2x assets shall
+ have a size of 5x when a scale factor of 2.5 is selected.
\section1 Exporting Library Symbols
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-setup.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-setup.qdoc
index 8ecead5647e..58959166751 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-setup.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-setup.qdoc
@@ -30,10 +30,10 @@
\title Setting Up \QBXD
- You can purchase a \QBXD license from the \l{https://marketplace.qt.io/}
- {Qt Marketplace}, and then use the Qt Installer to have the \QBXD
- plugin package copied to the following path in your Qt installation
- folder:
+ \QBXD is included in the
+ \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
+ You can use the Qt Installer to have the \QBXD plugin package copied to the
+ following path in your Qt installation folder:
\list
\li On Windows:
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-javascript.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-javascript.qdoc
index e1718063404..25e52b7ac93 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-javascript.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-javascript.qdoc
@@ -54,7 +54,7 @@
\list 1
\li In the File Explorer, create a new folder for the mock data
inside the \e imports folder in your project folder (for example, \e Data).
- \note Make sure to capitalize the \e Data folder name, because you
+ \note Make sure to capitalize the \e Data folder name because you
will need to import it as a component later, and component names must
be capitalized.
\note If you place this folder somewhere else in the project, you will
@@ -73,7 +73,7 @@
\li Follow the instructions of the wizard to create the Qt Quick file
in the data folder. In these instructions, the file is called
\e Values.qml.
- \note Make sure to capitalize the filename, because it will become
+ \note Make sure to capitalize the filename because it will become
a custom component.
\li Select \uicontrol File > \uicontrol {New File} >
\uicontrol {JavaScript} >
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-loader-3d.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-loader-3d.qdoc
index bd61ed62f7f..2c7843261c5 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-loader-3d.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-loader-3d.qdoc
@@ -43,19 +43,12 @@
example, when a component should be created on demand or when a component
should not be created unnecessarily for performance reasons.
- Add a \uicontrol Loader3D component to your scene by drag-and-dropping it
- from \uicontrol Components > \uicontrol {Qt Quick 3D} >
- \uicontrol {Qt Quick 3D} to \uicontrol Scene in \uicontrol Navigator.
-
For more information, see the \l{https://doc.qt.io/qt/qml-qtquick3d-loader3d.html}
{Loader3D QML type} in the \uicontrol {Qt Quick 3D} documentation.
\section1 Loader3D Properties
- Select the \uicontrol Loader3D component in \uicontrol Navigator to specify
- its properties in \uicontrol Properties > \uicontrol Loader3D.
-
- \image studio-3d-loader3d-properties.png "Loader3D specific properties"
+ \section2 Active
The \uicontrol Active property is set to \uicontrol true by default, which
makes the \uicontrol Loader3D currently active. Setting \uicontrol Active to
@@ -67,18 +60,24 @@
not affect the files or components defined as \uicontrol Source or
\uicontrol {Source component}.
- Use the dropdown menu of the \uicontrol Source property to define the URL of
+ \section2 Source
+
+ The \uicontrol Source property defines the URL of
the 3D component to instantiate. To unload the currently loaded object, set
this property to an empty string or set the \uicontrol {Source component} to
undefined. Setting \uicontrol Source to a new URL will also cause the item
created by the previous URL to be unloaded.
- The \uicontrol {Source component} property defines the component for
+ \section2 Source Component
+
+ The \uicontrol {Source Component} property defines the component for
\uicontrol Loader3D to instantiate. Currently, the
\uicontrol {Source component} needs to be defined in code using the
\l {Working in Edit Mode}{Edit} mode or \l {Text Editor}.
- Set the \uicontrol Asynchronous property to define whether the component
+ \section2 Asynchronous
+
+ The \uicontrol Asynchronous property defines whether the component
will be instantiated asynchronously. This property is set to \uicontrol false
by default. When used in conjunction with the source property, loading and
compilation will be performed in a background thread. Loading asynchronously
@@ -90,21 +89,53 @@
\uicontrol Loader3D content must be accessed before the asynchronous
loading is completed.
+ \section1 Setting the Loader3D to Load a QML File
+
+ To add a Loader3D component and set it to load a QML file:
+ \list 1
+ \li From \uicontrol {Components}, drag a Loader3D component to
+ \e scene in \uicontrol Navigator or to \uicontrol {3D Editor}.
+ \li In \uicontrol {Navigator}, select \e{loader3D}.
+ \image loader3d-navigator.png
+ \li In \uicontrol {Properties}, select \uicontrol{Source} and select a
+ QML file.
+ \image loader3d-select-source.png
+ \endlist
+
+ \section1 Setting the Loader3D to Load a Component3D Component
+
+ To add a Loader3D component and set it to load a Component3D component:
+ \list 1
+ \li From \uicontrol {Components}, drag a Loader3D Component to
+ \e scene in \uicontrol Navigator or to \uicontrol {3D Editor}.
+ \li From \uicontrol {Components}, drag a Component3D component to
+ \e scene in \uicontrol {Navigator}.
+ \li In \uicontrol {Navigator}, select the filter icon and clear
+ \uicontrol {Show Only Visible Components}. This makes the Component3D
+ component visible in \uicontrol Navigator.
+ \image navigator-show-all-loader.png
+ \li In \uicontrol {Navigator}, select \e{loader3D}.
+ \li In \uicontrol {Properties}, select \uicontrol{Source Component}
+ and select \e {component3D}.
+
+ \image loader3d-select-source-component.png
+ \endlist
+
+ \section1 Setting the Visibility of Loading Components
+
To avoid seeing the components loading progressively, set the \uicontrol
Visibility property for \uicontrol Loader3D appropriately in
\uicontrol {Binding Editor}:
\list 1
\li In \uicontrol Properties > \uicontrol Loader3D, select the
- \uicontrol Asynchronous check box to set the property to
- \uicontrol true.
- \li In \uicontrol Node > \l {Setting Node Opacity and Visibility}{Visibility},
+ \uicontrol Asynchronous check box.
+ \image loader3d-visibility.png
+ \li In \uicontrol {Visibility},
select \inlineimage icons/action-icon.png
to open the actions menu, and then select \uicontrol {Set Binding}.
- \li Type \c {status === Loader3D.Ready} into \uicontrol {Binding Editor},
- as shown in the image below.
+ \li Type \c {status === Loader3D.Ready} into \uicontrol {Binding Editor}.
+ \image studio-3d-loader3d-binding-editor.png "Setting Visibility in Binding Editor"
\li Select \uicontrol OK.
\endlist
- \image studio-3d-loader3d-binding-editor.png "Setting Visibility in Binding Editor"
-
*/
diff --git a/doc/qtdesignstudio/src/qtquickdesigner-components/qtdesignstudio-visual-effects.qdoc b/doc/qtdesignstudio/src/qtquickdesigner-components/qtdesignstudio-visual-effects.qdoc
index 1b3e004d2d1..599be37cc7c 100644
--- a/doc/qtdesignstudio/src/qtquickdesigner-components/qtdesignstudio-visual-effects.qdoc
+++ b/doc/qtdesignstudio/src/qtquickdesigner-components/qtdesignstudio-visual-effects.qdoc
@@ -67,7 +67,7 @@
The \uicontrol Cached property allows the effect output pixels to be cached
in order to improve the rendering performance. Every time the source or
effect properties are changed, the pixels in the cache must be updated.
- Memory consumption is increased, because an extra buffer of memory is
+ Memory consumption is increased because an extra buffer of memory is
required for storing the effect output. We recommend that you disable the
cache when the source or the effect properties are animated.
diff --git a/doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc b/doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc
index bffffa773b2..153f39fd02a 100644
--- a/doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc
@@ -179,14 +179,14 @@
Only one snapping button can be selected at the time. Selecting
one snapping button automatically deselects the others.
- Choose \uicontrol Tools > \uicontrol Options > \uicontrol {Qt Quick} >
+ Choose \uicontrol Edit > \uicontrol Preferences > \uicontrol {Qt Quick} >
\uicontrol {Qt Quick Designer} to specify settings for snapping. In the
\uicontrol {Parent component padding} field, specify the distance in
pixels between the parent and the snapping lines. In the
\uicontrol {Sibling component spacing} field, specify the
distance in pixels between siblings and the snapping lines.
- \image qtquick-designer-options.png "Qt Quick Designer options"
+ \image qtquick-designer-options.png "Qt Quick Designer preferences"
The following image shows the snapping lines (1) when
\uicontrol {Parent component padding} is set to 5 pixels.
@@ -220,14 +220,14 @@
\image qmldesigner-preview-size.png "Component width and height"
- To set the initial size of the root component, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Qt Quick} > \uicontrol {Qt Quick Designer}
+ To set the initial size of the root component, select \uicontrol Edit >
+ \uicontrol Preferences > \uicontrol {Qt Quick} > \uicontrol {Qt Quick Designer}
and specify the component width and height in the
\uicontrol {Root Component Init Size} group.
\section1 Specifying Canvas Size
- To change the canvas size, select \uicontrol Tools > \uicontrol Options >
+ To change the canvas size, select \uicontrol Edit > \uicontrol Preferences >
\uicontrol {Qt Quick} > \uicontrol {Qt Quick Designer} and
specify the canvas width and height in the \uicontrol Canvas group.
diff --git a/doc/qtdesignstudio/src/views/qtquick-properties.qdoc b/doc/qtdesignstudio/src/views/qtquick-properties.qdoc
index 3901be09852..6b0197ffb3d 100644
--- a/doc/qtdesignstudio/src/views/qtquick-properties.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-properties.qdoc
@@ -439,7 +439,7 @@
The value of the \uicontrol Format field specifies the internal OpenGL
format of the texture. Depending on the OpenGL implementation, it might
allow you to save some texture memory. However, use the \uicontrol RGB
- and \uicontrol Alpha values with caution, because the underlying hardware
+ and \uicontrol Alpha values with caution because the underlying hardware
and driver might not support them.
In the \uicontrol {Texture mirroring} field, specify whether the generated
diff --git a/qbs/modules/qtc/qtc.qbs b/qbs/modules/qtc/qtc.qbs
index e505ed2814f..0f7d6dd344a 100644
--- a/qbs/modules/qtc/qtc.qbs
+++ b/qbs/modules/qtc/qtc.qbs
@@ -1,16 +1,19 @@
import qbs
import qbs.Environment
import qbs.FileInfo
+import qbs.Utilities
Module {
- property string qtcreator_display_version: '7.0.3'
- property string ide_version_major: '7'
+ Depends { name: "cpp"; required: false }
+
+ property string qtcreator_display_version: '8.0.2'
+ property string ide_version_major: '8'
property string ide_version_minor: '0'
- property string ide_version_release: '3'
+ property string ide_version_release: '2'
property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.'
+ ide_version_release
- property string ide_compat_version_major: '7'
+ property string ide_compat_version_major: '8'
property string ide_compat_version_minor: '0'
property string ide_compat_version_release: '0'
property string qtcreator_compat_version: ide_compat_version_major + '.'
@@ -92,4 +95,12 @@ Module {
"QT_USE_QSTRINGBUILDER",
].concat(testsEnabled ? ["WITH_TESTS"] : [])
.concat(qbs.toolchain.contains("msvc") ? ["_CRT_SECURE_NO_WARNINGS"] : [])
+
+ Properties {
+ condition: cpp.present && qbs.toolchain.contains("msvc") && product.Qt
+ && Utilities.versionCompare(Qt.core.version, "6.3") >= 0
+ && Utilities.versionCompare(cpp.compilerVersion, "19.10") >= 0
+ && Utilities.versionCompare(qbs.version, "1.23") < 0
+ cpp.cxxFlags: "/permissive-"
+ }
}
diff --git a/qbs/modules/sqlite_sources/sqlite-sources.qbs b/qbs/modules/sqlite_sources/sqlite-sources.qbs
index 392b7c08248..323057754fb 100644
--- a/qbs/modules/sqlite_sources/sqlite-sources.qbs
+++ b/qbs/modules/sqlite_sources/sqlite-sources.qbs
@@ -11,9 +11,9 @@ Module {
cpp.defines: {
var defines = ["SQLITE_CUSTOM_INCLUDE=config.h", "SQLITE_CORE"];
if (buildSharedLib)
- defines.push("BUILD_SQLITE_LIBRARY");
+ defines.push("SQLITE_LIBRARY");
else
- defines.push("BUILD_SQLITE_STATIC_LIBRARY");
+ defines.push("SQLITE_STATIC_LIBRARY");
if (qbs.targetOS.contains("linux"))
defines.push("_POSIX_C_SOURCE=200809L", "_GNU_SOURCE");
else if (qbs.targetOS.contains("macos"))
diff --git a/qtcreator_ide_branding.pri b/qtcreator_ide_branding.pri
index 2b86c06a55a..7b430683b6d 100644
--- a/qtcreator_ide_branding.pri
+++ b/qtcreator_ide_branding.pri
@@ -1,6 +1,6 @@
-QTCREATOR_VERSION = 7.0.3
-QTCREATOR_COMPAT_VERSION = 7.0.0
-QTCREATOR_DISPLAY_VERSION = 7.0.3
+QTCREATOR_VERSION = 8.0.2
+QTCREATOR_COMPAT_VERSION = 8.0.0
+QTCREATOR_DISPLAY_VERSION = 8.0.2
QTCREATOR_COPYRIGHT_YEAR = 2022
IDE_DISPLAY_NAME = Qt Creator
diff --git a/scripts/deployqt.py b/scripts/deployqt.py
index d18b3cc2893..8ef5917a30c 100755
--- a/scripts/deployqt.py
+++ b/scripts/deployqt.py
@@ -227,7 +227,7 @@ def copyPreservingLinks(source, destination):
else:
shutil.copy(source, destination)
-def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
+def deploy_clang(install_dir, llvm_install_dir, chrpath_bin):
# contains pairs of (source, target directory)
deployinfo = []
resourcesource = os.path.join(llvm_install_dir, 'lib', 'clang')
@@ -238,23 +238,17 @@ def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
clanglibdirtarget = os.path.join(install_dir, 'bin', 'clang', 'lib')
if not os.path.exists(clanglibdirtarget):
os.makedirs(clanglibdirtarget)
- deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'libclang.dll'),
- os.path.join(install_dir, 'bin')))
- for binary in ['clang', 'clang-cl', 'clangd', 'clang-tidy', 'clazy-standalone']:
+ for binary in ['clangd', 'clang-tidy', 'clazy-standalone', 'clang-format']:
binary_filepath = os.path.join(llvm_install_dir, 'bin', binary + '.exe')
if os.path.exists(binary_filepath):
deployinfo.append((binary_filepath, clangbindirtarget))
resourcetarget = os.path.join(clanglibdirtarget, 'clang')
else:
- # libclang -> Qt Creator libraries
- libsources = glob(os.path.join(llvm_install_dir, 'lib', 'libclang.so*'))
- for libsource in libsources:
- deployinfo.append((libsource, os.path.join(install_dir, 'lib', 'qtcreator')))
# clang binaries -> clang libexec
clangbinary_targetdir = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'bin')
if not os.path.exists(clangbinary_targetdir):
os.makedirs(clangbinary_targetdir)
- for binary in ['clang', 'clangd', 'clang-tidy', 'clazy-standalone']:
+ for binary in ['clangd', 'clang-tidy', 'clazy-standalone', 'clang-format']:
binary_filepath = os.path.join(llvm_install_dir, 'bin', binary)
if os.path.exists(binary_filepath):
deployinfo.append((binary_filepath, clangbinary_targetdir))
@@ -268,12 +262,12 @@ def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
if not os.path.exists(clanglibs_targetdir):
os.makedirs(clanglibs_targetdir)
# on RHEL ClazyPlugin is in lib64
- for lib_pattern in ['lib64/ClazyPlugin.so', 'lib/ClazyPlugin.so', 'lib/libclang-cpp.so*']:
+ for lib_pattern in ['lib64/ClazyPlugin.so', 'lib/ClazyPlugin.so']:
for lib in glob(os.path.join(llvm_install_dir, lib_pattern)):
deployinfo.append((lib, clanglibs_targetdir))
resourcetarget = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'lib', 'clang')
- print("copying libclang...")
+ print("copying clang...")
for source, target in deployinfo:
print(source, '->', target)
copyPreservingLinks(source, target)
@@ -403,7 +397,7 @@ def main():
copy_qt_libs(qt_deploy_prefix, qt_install.bin, qt_install.lib, qt_install.plugins, qt_install.qml, plugins)
copy_translations(install_dir, qt_install.translations)
if args.llvm_path:
- deploy_libclang(install_dir, args.llvm_path, chrpath_bin)
+ deploy_clang(install_dir, args.llvm_path, chrpath_bin)
if args.elfutils_path:
deploy_elfutils(install_dir, chrpath_bin, args)
diff --git a/scripts/deployqtHelper_mac.sh b/scripts/deployqtHelper_mac.sh
index e85c48ef203..21da15c74e0 100755
--- a/scripts/deployqtHelper_mac.sh
+++ b/scripts/deployqtHelper_mac.sh
@@ -109,28 +109,22 @@ if [ ! -f "$resource_path/translations/qt_de.qm" ]; then
cp "$translation_src"/*.qm "$resource_path/translations/" || exit 1
fi
-# copy libclang if needed
+# copy clang if needed
if [ $LLVM_INSTALL_DIR ]; then
- if [ "$LLVM_INSTALL_DIR"/lib/libclang.dylib -nt "$app_path/Contents/PlugIns"/libclang.dylib ]; then
- echo "- Copying libclang"
+ if [ "$LLVM_INSTALL_DIR"/bin/clangd -nt "$libexec_path"/clang/bin/clangd ]; then
+ echo "- Copying clang"
mkdir -p "$app_path/Contents/Frameworks" || exit 1
# use recursive copy to make it copy symlinks as symlinks
mkdir -p "$libexec_path/clang/bin"
mkdir -p "$libexec_path/clang/lib"
- cp -Rf "$LLVM_INSTALL_DIR"/lib/libclang.*dylib "$app_path/Contents/Frameworks/" || exit 1
cp -Rf "$LLVM_INSTALL_DIR"/lib/clang "$libexec_path/clang/lib/" || exit 1
- cp -Rf "$LLVM_INSTALL_DIR"/lib/libclang-cpp.dylib "$libexec_path/clang/lib/" || exit 1
cp -Rf "$LLVM_INSTALL_DIR"/lib/ClazyPlugin.dylib "$libexec_path/clang/lib/" || exit 1
- clangsource="$LLVM_INSTALL_DIR"/bin/clang
- clanglinktarget="$(readlink "$clangsource")"
- cp -Rf "$clangsource" "$libexec_path/clang/bin/" || exit 1
- if [ $clanglinktarget ]; then
- cp -Rf "$(dirname "$clangsource")/$clanglinktarget" "$libexec_path/clang/bin/$clanglinktarget" || exit 1
- fi
clangdsource="$LLVM_INSTALL_DIR"/bin/clangd
cp -Rf "$clangdsource" "$libexec_path/clang/bin/" || exit 1
clangtidysource="$LLVM_INSTALL_DIR"/bin/clang-tidy
cp -Rf "$clangtidysource" "$libexec_path/clang/bin/" || exit 1
+ clangformatsource="$LLVM_INSTALL_DIR"/bin/clang-format
+ cp -Rf "$clangformatsource" "$libexec_path/clang/bin/" || exit 1
clazysource="$LLVM_INSTALL_DIR"/bin/clazy-standalone
cp -Rf "$clazysource" "$libexec_path/clang/bin/" || exit 1
install_name_tool -add_rpath "@executable_path/../lib" "$libexec_path/clang/bin/clazy-standalone" 2> /dev/null
diff --git a/share/qtcreator/CMakeLists.txt b/share/qtcreator/CMakeLists.txt
index 667ef9259c1..a705c7bcb8d 100644
--- a/share/qtcreator/CMakeLists.txt
+++ b/share/qtcreator/CMakeLists.txt
@@ -1,7 +1,6 @@
set(resource_directories
android
cplusplus
- debugger
glsl
indexer_preincludes
modeleditor
@@ -16,6 +15,28 @@ set(resource_directories
themes
)
+set(resource_files
+ debugger/.pylintrc
+ debugger/boosttypes.py
+ debugger/cdbbridge.py
+ debugger/creatortypes.py
+ debugger/dumper.py
+ debugger/gdbbridge.py
+ debugger/gdbtracepoint.py
+ debugger/LICENSE.GPL3-EXCEPT
+ debugger/lldbbridge.py
+ debugger/misctypes.py
+ debugger/opencvtypes.py
+ debugger/pdbbridge.py
+ debugger/personaltypes.py
+ debugger/qttypes.py
+ debugger/qttypes.py
+ debugger/README.txt
+ debugger/setup.cfg
+ debugger/stdtypes.py
+ debugger/utils.py
+)
+
if (APPLE)
set(resource_directories ${resource_directories} scripts)
endif()
@@ -27,6 +48,12 @@ qtc_copy_to_builddir(copy_share_to_builddir
CREATE_SUBDIRS
)
+# copy resource files during build
+qtc_copy_to_builddir(copy_share_files_to_builddir
+ FILES ${resource_files}
+ DESTINATION ${IDE_DATA_PATH}
+)
+
# create install rule for resource directories
install(
DIRECTORY ${resource_directories}
@@ -34,4 +61,14 @@ install(
USE_SOURCE_PERMISSIONS
)
+# create install rule for resource files
+foreach(file ${resource_files})
+ get_filename_component(path "${file}" DIRECTORY)
+ install(
+ FILES "${file}"
+ DESTINATION "${IDE_DATA_PATH}/${path}"
+ )
+endforeach()
+
+
add_subdirectory(translations)
diff --git a/share/qtcreator/android/sdk_definitions.json b/share/qtcreator/android/sdk_definitions.json
index 56ac6b4f47d..1c7476763be 100644
--- a/share/qtcreator/android/sdk_definitions.json
+++ b/share/qtcreator/android/sdk_definitions.json
@@ -1,12 +1,12 @@
{
"common": {
"sdk_tools_url": {
- "linux": "https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip",
- "linux_sha256": "89f308315e041c93a37a79e0627c47f21d5c5edbe5e80ea8dc0aac8a649e0e92",
- "windows": "https://dl.google.com/android/repository/commandlinetools-win-6609375_latest.zip",
- "windows_sha256": "40bba20275180194bebf89bb58c74d712bb93cc401f36bd2f8f32383acf9826c",
- "mac": "https://dl.google.com/android/repository/commandlinetools-mac-6609375_latest.zip",
- "mac_sha256": "2c3822db1c916655223e5ee8ce0fbf6b73d0b99012045c9dc8eaa6a5736c0c55"
+ "linux": "https://dl.google.com/android/repository/commandlinetools-linux-8092744_latest.zip",
+ "linux_sha256": "d71f75333d79c9c6ef5c39d3456c6c58c613de30e6a751ea0dbd433e8f8b9cbf",
+ "windows": "https://dl.google.com/android/repository/commandlinetools-win-8092744_latest.zip",
+ "windows_sha256": "5de99ed67cb2e30fe443baf8b282d1b0b6247d0c25c6d888a7e8657b3b35c281",
+ "mac": "https://dl.google.com/android/repository/commandlinetools-mac-8092744_latest.zip",
+ "mac_sha256": "1de25523d595198d29666f9976eed65d99bbc5e4a3e8e48e5d6c98bb7e9030cc"
},
"sdk_essential_packages": {
"default": ["platform-tools", "platforms;android-31", "cmdline-tools;latest"],
@@ -18,11 +18,16 @@
"specific_qt_versions": [
{
"versions": ["default"],
+ "sdk_essential_packages": ["build-tools;31.0.0", "ndk;23.1.7779620"],
+ "ndk_path": "ndk/23.1.7779620"
+ },
+ {
+ "versions": ["6.3", "6.2", "5.15.[9-20]"],
"sdk_essential_packages": ["build-tools;31.0.0", "ndk;22.1.7171670"],
"ndk_path": "ndk/22.1.7171670"
},
{
- "versions": ["5.15.[0-8]", "5.14.[0-2]", "5.13.2"],
+ "versions": ["5.15.[0-8]", "5.14.[0-2]", "5.13.2", "6.0", "6.1"],
"sdk_essential_packages": ["build-tools;31.0.0", "ndk;21.3.6528147"],
"ndk_path": "ndk/21.3.6528147"
},
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index fdf64d851fc..14a3d35a8fe 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -29,7 +29,6 @@ import collections
import glob
import struct
import sys
-import base64
import re
import time
import inspect
@@ -45,6 +44,14 @@ except:
"Native combined debugging might not work.")
pass
+try:
+ # That fails on some QNX via Windows installations
+ import base64
+ def hexencode_(s):
+ return base64.b16encode(s).decode('utf8')
+except:
+ def hexencode_(s):
+ return ''.join(["%x" % c for c in s])
if sys.version_info[0] >= 3:
toInteger = int
@@ -195,7 +202,7 @@ class DumperBase():
self.qtCustomEventFunc = 0
self.qtCustomEventPltFunc = 0
self.qtPropertyFunc = 0
- self.fallbackQtVersion = 0x50200
+ self.fallbackQtVersion = 0x60200
self.passExceptions = False
self.isTesting = False
@@ -550,7 +557,7 @@ class DumperBase():
return s.encode('hex')
if isinstance(s, str):
s = s.encode('utf8')
- return base64.b16encode(s).decode('utf8')
+ return hexencode_(s)
def isQt3Support(self):
# assume no Qt 3 support by default
@@ -3191,7 +3198,7 @@ class DumperBase():
return self.cast(self.type.ltarget).extractField(field)
if self.type.code in (TypeCode.Reference, TypeCode.RValueReference):
return self.dereference().extractField(field)
- #DumperBase.warn('FIELD: %s ' % field)
+ #DumperBase.warn('FIELD: %s ' % (field,))
val = self.dumper.Value(self.dumper)
val.name = field.name
val.isBaseClass = field.isBase
@@ -3220,10 +3227,10 @@ class DumperBase():
lbyte = ldata[i]
else:
lbyte = ldata[fieldOffset + fieldSize - 1 - i]
- if sys.version_info[0] >= 3:
- data += lbyte
- else:
+ if isinstance(lbyte, (str, bytes)):
data += ord(lbyte)
+ else:
+ data += lbyte
data = data >> fieldBitpos
data = data & ((1 << fieldBitsize) - 1)
val.lvalue = data
diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py
index e121ece7da5..222c1dc526e 100644
--- a/share/qtcreator/debugger/lldbbridge.py
+++ b/share/qtcreator/debugger/lldbbridge.py
@@ -791,6 +791,7 @@ class Dumper(DumperBase):
def lookupNativeType(self, name):
#DumperBase.warn('LOOKUP TYPE NAME: %s' % name)
+
typeobj = self.typeCache.get(name)
if typeobj is not None:
#DumperBase.warn('CACHED: %s' % name)
@@ -846,6 +847,15 @@ class Dumper(DumperBase):
if typeobj is not None:
return typeobj
+ # For QMetaType based typenames we have to re-format the type name.
+ # Converts "T<A,B<C,D>>"" to "T<A, B<C, D> >" since FindFirstType
+ # expects it that way.
+ name = name.replace(',', ', ').replace('>>', '> >')
+ typeobj = self.target.FindFirstType(name)
+ if typeobj.IsValid():
+ self.typeCache[name] = typeobj
+ return typeobj
+
return lldb.SBType()
def setupInferior(self, args):
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index 2c7725260d2..36c20af6baf 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -652,6 +652,13 @@ def qdump__QKeyEvent(d, value):
d.putFields(value, dumpBase=True)
+def qdump__QKeySequence(d, value):
+ dd = d.extractPointer(value)
+ _, k0, k1, k2, k3 = d.split('iiiii', dd)
+ d.putValue("(0x%x, 0x%x, 0x%x, 0x%x)" % (k0, k1, k2, k3));
+ d.putPlainChildren(value)
+
+
def qdump__QFile(d, value):
# 9fc0965 and a373ffcd change the layout of the private structure
qtVersion = d.qtVersion()
@@ -1740,6 +1747,11 @@ def qdump__QString(d, value):
d.putArrayData(data, size, d.createType('@QChar'))
+def qdump__QSettingsKey(d, value):
+ qdump__QString(d, value)
+ d.putBetterType(value.type)
+
+
def qdump__QStaticStringData(d, value):
size = value.type[0]
(ref, size, alloc, pad, offset, data) = value.split('iii@p%ss' % (2 * size))
@@ -1762,6 +1774,26 @@ def qdump__QStringData(d, value):
d.putPlainChildren(value)
+def qdump__QAnyStringView(d, value):
+ data, size = value.split('pp')
+ bits = d.ptrSize() * 8 - 2
+ tag = size >> bits
+ size = size & (2**bits - 1)
+ elided, shown = d.computeLimit(size, d.displayStringLimit)
+ if tag == 0:
+ mem = d.readMemory(data, shown)
+ d.putValue(mem, 'utf8', elided=elided)
+ elif tag == 1:
+ mem = d.readMemory(data, shown)
+ d.putValue(mem, 'latin1', elided=elided)
+ elif tag == 2:
+ mem = d.readMemory(data, shown * 2)
+ d.putValue(mem, 'utf16', elided=elided)
+ else:
+ d.putSpecialValue('empty')
+ d.putPlainChildren(value)
+
+
def qform__QStringView():
return [DisplayFormat.Simple, DisplayFormat.Separate]
diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py
index 1f4386607d7..41d96b15f32 100644
--- a/share/qtcreator/debugger/stdtypes.py
+++ b/share/qtcreator/debugger/stdtypes.py
@@ -776,28 +776,54 @@ def qdumpHelper__std__string__MSVC(d, value, charType, format):
d.putCharArrayHelper(data, size, charType, format)
+def qdump__std____1__string__alternateLayoutHelper(d, value):
+ try:
+ _d = value['__s']['__data_'].address()
+ alternateLayout = (_d - value.address()) == 0
+ if alternateLayout:
+ lastByte = value.split('b')[-1]
+ if int(lastByte & 0x80) == 0:
+ # Short/internal
+ size = value['__s']['__size_'].integer()
+ data = value.address()
+ else:
+ # Long/external
+ (data, size, _) = value.split('ppp')
+ return size, data
+ else:
+ return None, None
+ except:
+ return None, None
+
+
def qdump__std____1__string(d, value):
- firstByte = value.split('b')[0]
- if int(firstByte & 1) == 0:
- # Short/internal.
- size = int(firstByte / 2)
- data = value.address() + 1
- else:
- # Long/external.
- (dummy, size, data) = value.split('ppp')
+ (size, data) = qdump__std____1__string__alternateLayoutHelper(d, value)
+ if size is None or data is None:
+ firstByte = value.split('b')[0]
+ if int(firstByte & 1) == 0:
+ # Short/internal.
+ size = int(firstByte / 2)
+ data = value.address() + 1
+ else:
+ # Long/external.
+ (_, size, data) = value.split('ppp')
+
d.putCharArrayHelper(data, size, d.charType(), d.currentItemFormat())
d.putType("std::string")
def qdump__std____1__wstring(d, value):
- firstByte = value.split('b')[0]
- if int(firstByte & 1) == 0:
- # Short/internal.
- size = int(firstByte / 2)
- data = value.address() + 4
- else:
- # Long/external.
- (dummy, size, data) = value.split('ppp')
+ (size, data) = qdump__std____1__string__alternateLayoutHelper(d, value)
+ if size is None or data is None:
+ firstByte = value.split('b')[0]
+ if int(firstByte & 1) == 0:
+ # Short/internal.
+ size = int(firstByte / 2)
+ data = value.address() + 4
+ else:
+ # Long/external.
+ (_, size, data) = value.split('ppp')
+
d.putCharArrayHelper(data, size, d.createType('wchar_t'))
d.putType("std::wstring")
diff --git a/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h b/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h
index cfe4529ba1b..95ca0d3ce25 100644
--- a/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h
+++ b/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h
@@ -40,6 +40,7 @@ public:
ActiveSceneChanged,
RenderModelNodePreviewImage,
Import3DSupport,
+ ModelAtPos,
None };
PuppetToCreatorCommand(Type type, const QVariant &data);
diff --git a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h b/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h
index a1dc133032e..4373a1c9ddd 100644
--- a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h
+++ b/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h
@@ -59,9 +59,11 @@ public:
SelectBackgroundColor,
SelectGridColor,
ResetBackgroundColor,
+ SyncBackgroundColor,
+ GetModelAtPos
};
- explicit View3DActionCommand(Type type, const QVariant &value);
+ View3DActionCommand(Type type, const QVariant &value);
View3DActionCommand() = default;
diff --git a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp b/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp
index b556620c54f..38d8a282b2e 100644
--- a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp
+++ b/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp
@@ -98,7 +98,8 @@ static SharedMemory *createSharedMemory(qint32 key, int byteCount)
sharedMemory = new SharedMemory(QString(imageKeyTemplateString).arg(key));
bool sharedMemoryIsCreated = sharedMemory->create(byteCount);
if (sharedMemoryIsCreated) {
- globalSharedMemoryContainer()->insert(key, sharedMemory);
+ if (!globalSharedMemoryContainer()->insert(key, sharedMemory))
+ return nullptr;
} else {
delete sharedMemory;
sharedMemory = nullptr;
diff --git a/share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc b/share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc
index bbe9a910db6..d4127574a69 100644
--- a/share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc
+++ b/share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc
@@ -16,6 +16,8 @@
<file>mockfiles/images/static_floor.png</file>
<file>mockfiles/images/spot.png</file>
<file>mockfiles/images/spot@2x.png</file>
+ <file>mockfiles/images/preview_landscape.hdr</file>
+ <file>mockfiles/images/preview_studio.hdr</file>
<file>mockfiles/qt5/AdjustableArrow.qml</file>
<file>mockfiles/qt5/AreaLightHandle.qml</file>
<file>mockfiles/qt5/Arrow.qml</file>
diff --git a/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc b/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc
index 05459423349..bb29d683a07 100644
--- a/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc
+++ b/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc
@@ -18,6 +18,8 @@
<file>mockfiles/images/floor_tex.png</file>
<file>mockfiles/images/spot.png</file>
<file>mockfiles/images/spot@2x.png</file>
+ <file>mockfiles/images/preview_landscape.hdr</file>
+ <file>mockfiles/images/preview_studio.hdr</file>
<file>mockfiles/qt6/AdjustableArrow.qml</file>
<file>mockfiles/qt6/AreaLightHandle.qml</file>
<file>mockfiles/qt6/Arrow.qml</file>
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_landscape.hdr b/share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_landscape.hdr
new file mode 100644
index 00000000000..2c6b4372d47
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_landscape.hdr
Binary files differ
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_studio.hdr b/share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_studio.hdr
new file mode 100644
index 00000000000..8ab060c1f45
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_studio.hdr
Binary files differ
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml
index 09a4ebdc3f3..1376610984d 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml
@@ -48,6 +48,7 @@ Item {
property color backgroundGradientColorStart: "#222222"
property color backgroundGradientColorEnd: "#999999"
property color gridColor: "#aaaaaa"
+ property bool syncBackgroundColor: false
enum SelectionMode { Item, Group }
enum TransformMode { Move, Rotate, Scale }
@@ -72,15 +73,16 @@ Item {
signal changeObjectProperty(var objects, var propNames)
signal notifyActiveSceneChange()
- onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective)
- onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
- onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
- onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid);
- onShowSelectionBoxChanged: _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox);
- onShowIconGizmoChanged: _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo);
- onShowCameraFrustumChanged: _generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum);
- onSelectionModeChanged: _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode);
- onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode);
+ onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective)
+ onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
+ onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
+ onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid);
+ onSyncBackgroundColorChanged: _generalHelper.storeToolState(sceneId, "syncBackgroundColor", syncBackgroundColor);
+ onShowSelectionBoxChanged: _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox);
+ onShowIconGizmoChanged: _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo);
+ onShowCameraFrustumChanged: _generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum);
+ onSelectionModeChanged: _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode);
+ onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode);
onActiveSceneChanged: updateActiveScene()
@@ -249,6 +251,16 @@ Item {
else if (resetToDefault)
showGrid = true;
+ if ("syncBackgroundColor" in toolStates) {
+ syncBackgroundColor = toolStates.syncBackgroundColor;
+ if (syncBackgroundColor) {
+ var color = _generalHelper.sceneEnvironmentColor(sceneId);
+ updateViewStates({"selectBackgroundColor": color})
+ }
+ } else if (resetToDefault) {
+ syncBackgroundColor = false;
+ }
+
if ("showSelectionBox" in toolStates)
showSelectionBox = toolStates.showSelectionBox;
else if (resetToDefault)
@@ -294,6 +306,7 @@ Item {
{
_generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
_generalHelper.storeToolState(sceneId, "showGrid", showGrid)
+ _generalHelper.storeToolState(sceneId, "syncBackgroundColor", syncBackgroundColor)
_generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox)
_generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo)
_generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum)
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml
index 9fee06e0ad1..067e34928b7 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml
@@ -29,8 +29,12 @@ View3D {
id: root
anchors.fill: parent
environment: sceneEnv
+ camera: envMode === "SkyBox" && envValue === "preview_studio" ? studioCamera : defaultCamera
property Material previewMaterial
+ property string envMode
+ property string envValue
+ property string modelSrc: "#Sphere"
function fitToViewPort(closeUp)
{
@@ -41,28 +45,59 @@ View3D {
id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High
+ backgroundMode: envMode === "Color" ? SceneEnvironment.Color
+ : envMode === "SkyBox" ? SceneEnvironment.SkyBox
+ : SceneEnvironment.Transparent
+ clearColor: envMode === "Color" ? envValue : "#000000"
+ lightProbe: envMode === "SkyBox" ? skyBoxTex : null
+
+ Texture {
+ id: skyBoxTex
+ source: envMode === "SkyBox" ? "../images/" + envValue + ".hdr"
+ : ""
+ }
}
Node {
DirectionalLight {
eulerRotation.x: -26
- eulerRotation.y: -57
+ eulerRotation.y: modelSrc === "#Cube" ? -10 : -50
+ brightness: envMode !== "SkyBox" ? 100 : 0
}
PerspectiveCamera {
- y: 125.331
- z: 120
- eulerRotation.x: -31
+ id: defaultCamera
+ y: 70
+ z: 200
+ eulerRotation.x: -5.71
clipNear: 1
clipFar: 1000
}
- Model {
- id: model
+ PerspectiveCamera {
+ id: studioCamera
+ y: 232
+ z: 85
+ eulerRotation.x: -64.98
+ clipNear: 1
+ clipFar: 1000
+ }
+ Node {
+ rotation: root.camera.rotation
y: 50
- source: "#Sphere"
- materials: previewMaterial
+ Node {
+ y: modelSrc === "#Cone" ? -40 : 10
+ eulerRotation.x: 35
+ Model {
+ id: model
+ source: modelSrc ? modelSrc : "#Sphere"
+ eulerRotation.y: 45
+ materials: previewMaterial
+ scale: !modelSrc || modelSrc === "#Sphere"
+ ? Qt.vector3d(1.7, 1.7, 1.7) : Qt.vector3d(1.2, 1.2, 1.2)
+ }
+ }
}
}
}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml
index 70b9dbc4d0e..d32a1ea915d 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml
@@ -50,25 +50,28 @@ Item {
view.destroy();
}
- function createViewForObject(obj)
+ function createViewForObject(obj, env, envValue, model)
{
if (obj instanceof Material)
- createViewForMaterial(obj);
+ createViewForMaterial(obj, env, envValue, model);
else if (obj instanceof Model)
createViewForModel(obj);
else if (obj instanceof Node)
createViewForNode(obj);
}
- function createViewForMaterial(material)
+ function createViewForMaterial(material, env, envValue, model)
{
if (!materialViewComponent)
materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
// Always recreate the view to ensure material is up to date
- if (materialViewComponent.status === Component.Ready)
- view = materialViewComponent.createObject(viewRect, {"previewMaterial": material});
-
+ if (materialViewComponent.status === Component.Ready) {
+ view = materialViewComponent.createObject(viewRect, {"previewMaterial": material,
+ "envMode": env,
+ "envValue": envValue,
+ "modelSrc": model});
+ }
previewObject = material;
}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml
index a3f14e9d113..721e74ac303 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml
@@ -49,6 +49,7 @@ Item {
property color backgroundGradientColorStart: "#222222"
property color backgroundGradientColorEnd: "#999999"
property color gridColor: "#aaaaaa"
+ property bool syncBackgroundColor: false
enum SelectionMode { Item, Group }
enum TransformMode { Move, Rotate, Scale }
@@ -79,6 +80,7 @@ Item {
onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid);
+ onSyncBackgroundColorChanged: _generalHelper.storeToolState(sceneId, "syncBackgroundColor", syncBackgroundColor);
onShowSelectionBoxChanged: _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox);
onShowIconGizmoChanged: _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo);
onShowCameraFrustumChanged: _generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum);
@@ -243,6 +245,16 @@ Item {
else if (resetToDefault)
showGrid = true;
+ if ("syncBackgroundColor" in toolStates) {
+ syncBackgroundColor = toolStates.syncBackgroundColor;
+ if (syncBackgroundColor) {
+ var color = _generalHelper.sceneEnvironmentColor(sceneId);
+ updateViewStates({"selectBackgroundColor": color})
+ }
+ } else if (resetToDefault) {
+ syncBackgroundColor = false;
+ }
+
if ("showSelectionBox" in toolStates)
showSelectionBox = toolStates.showSelectionBox;
else if (resetToDefault)
@@ -293,6 +305,7 @@ Item {
{
_generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
_generalHelper.storeToolState(sceneId, "showGrid", showGrid)
+ _generalHelper.storeToolState(sceneId, "syncBackgroundColor", syncBackgroundColor)
_generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox)
_generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo)
_generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum)
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml
index 94051d5f6e6..12fdd3048eb 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml
@@ -29,8 +29,12 @@ View3D {
id: root
anchors.fill: parent
environment: sceneEnv
+ camera: envMode === "SkyBox" && envValue === "preview_studio" ? studioCamera : defaultCamera
property Material previewMaterial
+ property string envMode
+ property string envValue
+ property string modelSrc: "#Sphere"
function fitToViewPort(closeUp)
{
@@ -41,30 +45,79 @@ View3D {
id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High
+ backgroundMode: envMode === "Color" ? SceneEnvironment.Color
+ : envMode === "SkyBox" ? SceneEnvironment.SkyBox
+ : SceneEnvironment.Transparent
+ clearColor: envMode === "Color" ? envValue : "#000000"
+ lightProbe: envMode === "SkyBox" ? skyBoxTex : null
+
+ Texture {
+ id: skyBoxTex
+ source: envMode === "SkyBox" ? "../images/" + envValue + ".hdr"
+ : ""
+ }
}
Node {
DirectionalLight {
eulerRotation.x: -26
- eulerRotation.y: -57
+ eulerRotation.y: modelSrc === "#Cube" ? -10 : -50
+ brightness: envMode !== "SkyBox" ? 1 : 0
}
PerspectiveCamera {
- y: 125.331
- z: 120
- eulerRotation.x: -31
+ id: defaultCamera
+ y: 70
+ z: 200
+ eulerRotation.x: -5.71
clipNear: 1
clipFar: 1000
}
- Model {
- id: model
- readonly property bool _edit3dLocked: true // Make this non-pickable
+ PerspectiveCamera {
+ id: studioCamera
+ y: 232
+ z: 85
+ eulerRotation.x: -64.98
+ clipNear: 1
+ clipFar: 1000
+ }
+ Node {
+ rotation: root.camera.rotation
y: 50
- source: "#Sphere"
- materials: previewMaterial
+ Node {
+ y: modelSrc === "#Cone" ? -40 : 10
+ eulerRotation.x: 35
+ Model {
+ id: model
+ readonly property bool _edit3dLocked: true // Make this non-pickable
+ source: modelSrc ? modelSrc : "#Sphere"
+ eulerRotation.y: 45
+ materials: previewMaterial
+ scale: !modelSrc || modelSrc === "#Sphere"
+ ? Qt.vector3d(1.7, 1.7, 1.7) : Qt.vector3d(1.2, 1.2, 1.2)
+ }
+ }
+ }
+ Model {
+ id: floorModel
+ source: "#Rectangle"
+ scale.y: 8
+ scale.x: 8
+ eulerRotation.x: -60
+ visible: !envMode || envMode === "Default"
+ materials: floorMaterial
+ DefaultMaterial {
+ id: floorMaterial
+ diffuseMap: floorTex
+ Texture {
+ id: floorTex
+ source: "../images/floor_tex.png"
+ scaleU: floorModel.scale.x
+ scaleV: floorModel.scale.y
+ }
+ }
}
-
}
}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml
index 031d01d65fb..e409e35aee0 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml
@@ -50,25 +50,31 @@ Item {
view.destroy();
}
- function createViewForObject(obj)
+ function createViewForObject(obj, env, envValue, model)
{
+ backgroundView3d.visible = true;
if (obj instanceof Material)
- createViewForMaterial(obj);
+ createViewForMaterial(obj, env, envValue, model);
else if (obj instanceof Model)
createViewForModel(obj);
else if (obj instanceof Node)
createViewForNode(obj);
}
- function createViewForMaterial(material)
+ function createViewForMaterial(material, env, envValue, model)
{
if (!materialViewComponent)
materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
// Always recreate the view to ensure material is up to date
- if (materialViewComponent.status === Component.Ready)
- view = materialViewComponent.createObject(viewRect, {"previewMaterial": material});
-
+ if (materialViewComponent.status === Component.Ready) {
+ view = materialViewComponent.createObject(viewRect, {"previewMaterial": material,
+ "envMode": env,
+ "envValue": envValue,
+ "modelSrc": model});
+ }
+ // Floor must be in same view as material so material can reflect it, so hide it in this one
+ backgroundView3d.visible = false;
previewObject = material;
}
@@ -129,6 +135,7 @@ Item {
// Use View3D instead of static image to make background look good on all resolutions
View3D {
+ id: backgroundView3d
anchors.fill: parent
environment: sceneEnv
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
index 590785a30e3..f8ab464df23 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
@@ -547,6 +547,16 @@ void GeneralHelper::storeToolState(const QString &sceneId, const QString &tool,
}
}
+void GeneralHelper::setSceneEnvironmentColor(const QString &sceneId, const QColor &color)
+{
+ m_sceneEnvironmentColor[sceneId] = color;
+}
+
+QColor GeneralHelper::sceneEnvironmentColor(const QString &sceneId) const
+{
+ return m_sceneEnvironmentColor[sceneId];
+}
+
void GeneralHelper::initToolStates(const QString &sceneId, const QVariantMap &toolStates)
{
m_toolStates[sceneId] = toolStates;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
index 8014a711875..8bda11ddd27 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
@@ -27,6 +27,7 @@
#ifdef QUICK3D_MODULE
+#include <QColor>
#include <QHash>
#include <QMatrix4x4>
#include <QObject>
@@ -113,6 +114,9 @@ public:
Q_INVOKABLE void scaleMultiSelection(bool commit);
Q_INVOKABLE void rotateMultiSelection(bool commit);
+ void setSceneEnvironmentColor(const QString &sceneId, const QColor &color);
+ Q_INVOKABLE QColor sceneEnvironmentColor(const QString &sceneId) const;
+
bool isMacOS() const;
void addRotationBlocks(const QSet<QQuick3DNode *> &nodes);
@@ -136,6 +140,7 @@ private:
QTimer m_toolStateUpdateTimer;
QHash<QString, QVariantMap> m_toolStates;
QHash<QString, QVariantMap> m_toolStatesPending;
+ QHash<QString, QColor> m_sceneEnvironmentColor;
QSet<QQuick3DNode *> m_rotationBlockedNodes;
struct MultiSelData {
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index 97a60b54059..dae4f975b40 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -101,6 +101,7 @@
#include <QtQuick3D/private/qquick3dscenerootnode_p.h>
#include <QtQuick3D/private/qquick3drepeater_p.h>
#include <QtQuick3D/private/qquick3dloader_p.h>
+#include <QtQuick3D/private/qquick3dsceneenvironment_p.h>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include "../editor3d/qt5compat/qquick3darealight_p.h"
#endif
@@ -338,6 +339,21 @@ void Qt5InformationNodeInstanceServer::resolveImportSupport()
#endif
}
+void Qt5InformationNodeInstanceServer::updateMaterialPreviewData(const QVector<PropertyValueContainer> &valueChanges)
+{
+ const PropertyName matPrevPrefix("matPrev");
+ for (const auto &container : valueChanges) {
+ if (container.instanceId() == 0) {
+ if (container.name() == "matPrevEnv")
+ m_materialPreviewData.env = container.value().toString();
+ else if (container.name() == "matPrevEnvValue")
+ m_materialPreviewData.envValue = container.value().toString();
+ else if (container.name() == "matPrevModel")
+ m_materialPreviewData.model = container.value().toString();
+ }
+ }
+}
+
void Qt5InformationNodeInstanceServer::updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges)
{
#ifdef QUICK3D_MODULE
@@ -867,8 +883,23 @@ void Qt5InformationNodeInstanceServer::updateActiveSceneToEditView3D(bool timerC
updateView3DRect(m_active3DView);
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
- if (helper)
+ if (helper) {
helper->storeToolState(helper->globalStateId(), helper->lastSceneIdKey(), QVariant(sceneId), 0);
+
+ QVariantMap toolStates = helper->getToolStates(sceneId);
+ if (toolStates.contains("syncBackgroundColor")) {
+ bool sync = toolStates["syncBackgroundColor"].toBool();
+ if (sync) {
+ QColor color = helper->sceneEnvironmentColor(sceneId);
+ View3DActionCommand cmd(View3DActionCommand::SelectBackgroundColor,
+ QVariant::fromValue(color));
+ view3DAction(cmd);
+ }
+ }
+ }
+
+#else
+ Q_UNUSED(timerCall)
#endif
}
@@ -1168,7 +1199,10 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView(const Reques
} else {
QMetaObject::invokeMethod(
m_modelNode3DImageViewData.rootItem, "createViewForObject",
- Q_ARG(QVariant, objectToVariant(instanceObj)));
+ Q_ARG(QVariant, objectToVariant(instanceObj)),
+ Q_ARG(QVariant, m_materialPreviewData.env),
+ Q_ARG(QVariant, m_materialPreviewData.envValue),
+ Q_ARG(QVariant, m_materialPreviewData.model));
}
// Need to render twice, first render updates spatial nodes
@@ -1215,6 +1249,8 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView(const Reques
{PuppetToCreatorCommand::RenderModelNodePreviewImage,
QVariant::fromValue(imgContainer)});
}
+#else
+ Q_UNUSED(cmd)
#endif
}
@@ -2009,6 +2045,7 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com
if (ViewConfig::isQuick3DMode()) {
setup3DEditView(instanceList, command);
updateRotationBlocks(command.auxiliaryChanges);
+ updateMaterialPreviewData(command.auxiliaryChanges);
}
QObject::connect(&m_renderModelNodeImageViewTimer, &QTimer::timeout,
@@ -2175,6 +2212,44 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
render3DEditView(2);
}
+void Qt5InformationNodeInstanceServer::setSceneEnvironmentColor(const PropertyValueContainer &container)
+{
+#ifdef QUICK3D_MODULE
+ auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
+ if (!helper || !hasInstanceForId(container.instanceId()) || !m_active3DView)
+ return;
+
+ ServerNodeInstance sceneEnvInstance = instanceForId(container.instanceId());
+ if (!sceneEnvInstance.isSubclassOf("QQuick3DSceneEnvironment"))
+ return;
+
+ auto activeView = qobject_cast<QQuick3DViewport *>(m_active3DView);
+ if (!activeView)
+ return;
+
+ QQuick3DSceneEnvironment *activeEnv = activeView->environment();
+ if (activeEnv != sceneEnvInstance.internalObject())
+ return;
+
+ ServerNodeInstance activeSceneInstance = active3DSceneInstance();
+ const QString sceneId = activeSceneInstance.id();
+
+ QColor color = container.value().value<QColor>();
+ helper->setSceneEnvironmentColor(sceneId, color);
+ QVariantMap toolStates = helper->getToolStates(sceneId);
+
+ if (toolStates.contains("syncBackgroundColor")) {
+ bool sync = toolStates["syncBackgroundColor"].toBool();
+ if (sync) {
+ View3DActionCommand cmd(View3DActionCommand::SelectBackgroundColor, QVariant::fromValue(color));
+ view3DAction(cmd);
+ }
+ }
+#else
+ Q_UNUSED(container)
+#endif
+}
+
void Qt5InformationNodeInstanceServer::changePropertyValues(const ChangeValuesCommand &command)
{
bool hasDynamicProperties = false;
@@ -2182,6 +2257,10 @@ void Qt5InformationNodeInstanceServer::changePropertyValues(const ChangeValuesCo
for (const PropertyValueContainer &container : values) {
if (!container.isReflected()) {
hasDynamicProperties |= container.isDynamic();
+
+ if (container.name() == "clearColor")
+ setSceneEnvironmentColor(container);
+
setInstancePropertyVariant(container);
}
}
@@ -2280,6 +2359,9 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
case View3DActionCommand::ShowCameraFrustum:
updatedToolState.insert("showCameraFrustum", command.isEnabled());
break;
+ case View3DActionCommand::SyncBackgroundColor:
+ updatedToolState.insert("syncBackgroundColor", command.isEnabled());
+ break;
case View3DActionCommand::SelectBackgroundColor:
updatedViewState.insert("selectBackgroundColor", command.value());
break;
@@ -2315,6 +2397,32 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
m_particleAnimationDriver->setSeekerPosition(static_cast<const View3DSeekActionCommand &>(command).position());
break;
#endif
+#ifdef QUICK3D_MODULE
+ case View3DActionCommand::GetModelAtPos: {
+ // pick a Quick3DModel at view position
+ auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
+ if (!helper)
+ return;
+
+ QQmlProperty editViewProp(m_editView3DData.rootItem, "editView", context());
+ QObject *obj = qvariant_cast<QObject *>(editViewProp.read());
+ QQuick3DViewport *editView = qobject_cast<QQuick3DViewport *>(obj);
+
+ QPointF pos = command.value().toPointF();
+ QQuick3DModel *hitModel = helper->pickViewAt(editView, pos.x(), pos.y()).objectHit();
+
+ // filter out picks of models created dynamically or inside components
+ QQuick3DModel *resolvedPick = qobject_cast<QQuick3DModel *>(helper->resolvePick(hitModel));
+
+ if (resolvedPick) {
+ ServerNodeInstance instance = instanceForObject(resolvedPick);
+ nodeInstanceClient()->handlePuppetToCreatorCommand(
+ {PuppetToCreatorCommand::ModelAtPos, QVariant(instance.instanceId())});
+ }
+ return;
+ }
+#endif
+
default:
break;
}
@@ -2342,6 +2450,7 @@ void Qt5InformationNodeInstanceServer::requestModelNodePreviewImage(const Reques
void Qt5InformationNodeInstanceServer::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command)
{
updateRotationBlocks(command.auxiliaryChanges);
+ updateMaterialPreviewData(command.auxiliaryChanges);
Qt5NodeInstanceServer::changeAuxiliaryValues(command);
render3DEditView();
}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index c85a2730c46..ea104442a6e 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -145,6 +145,7 @@ private:
void updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances);
void handleInputEvents();
void resolveImportSupport();
+ void updateMaterialPreviewData(const QVector<PropertyValueContainer> &valueChanges);
void updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges);
void removeRotationBlocks(const QVector<qint32> &instanceIds);
@@ -154,6 +155,7 @@ private:
void resetParticleSystem();
void handleParticleSystemDeselected();
#endif
+ void setSceneEnvironmentColor(const PropertyValueContainer &container);
RenderViewData m_editView3DData;
RenderViewData m_modelNode3DImageViewData;
@@ -190,6 +192,13 @@ private:
QObject *m_3dHelper = nullptr;
int m_need3DEditViewRender = 0;
QSet<QObject *> m_dynamicObjectConstructors;
+
+ struct PreviewData {
+ QString env;
+ QString envValue;
+ QString model;
+ };
+ PreviewData m_materialPreviewData;
};
} // namespace QmlDesigner
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
index 95dd4a7effb..eec52e99927 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
@@ -82,6 +82,9 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo
m_dummyRootViewCreateFunction = "createViewForNode";
Quick3DRenderableNodeInstance::initialize(objectNodeInstance, flags);
+#else
+ Q_UNUSED(objectNodeInstance)
+ Q_UNUSED(flags)
#endif // QUICK3D_MODULE
}
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
index 130ec2aff68..e19b13fc0fb 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
@@ -59,6 +59,10 @@ Item {
width: itemLibraryIconWidth // to be set in Qml context
height: itemLibraryIconHeight // to be set in Qml context
source: itemLibraryIconPath // to be set by model
+
+ // Icons generated for components can change if the component is edited,
+ // so don't cache them locally at Image level.
+ cache: itemComponentSource === ""
}
Text {
diff --git a/share/qtcreator/qmldesigner/landingpage/content/App.qml b/share/qtcreator/qmldesigner/landingpage/content/App.qml
new file mode 100644
index 00000000000..e93ad196e1a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/App.qml
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Quick Studio Components.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.15
+
+Item {
+ id: root
+ width: 1024
+ height: 768
+ visible: true
+
+ Screen01 {
+ id: mainScreen
+ anchors.fill: parent
+ }
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/content/CustomCheckBox.ui.qml b/share/qtcreator/qmldesigner/landingpage/content/CustomCheckBox.ui.qml
new file mode 100644
index 00000000000..8d91f695429
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/CustomCheckBox.ui.qml
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Templates 2.15
+import LandingPage as Theme
+
+CheckBox {
+ id: control
+ autoExclusive: false
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ spacing: Theme.Values.checkBoxSpacing
+ hoverEnabled: true
+ font.family: Theme.Values.baseFont
+
+ indicator: Rectangle {
+ id: checkBoxBackground
+ implicitWidth: Theme.Values.checkBoxSize
+ implicitHeight: Theme.Values.checkBoxSize
+ x: 0
+ y: parent.height / 2 - height / 2
+ color: Theme.Colors.backgroundPrimary
+ border.color: Theme.Colors.foregroundSecondary
+ border.width: Theme.Values.border
+
+ Rectangle {
+ id: checkBoxIndicator
+ width: Theme.Values.checkBoxIndicatorSize
+ height: Theme.Values.checkBoxIndicatorSize
+ x: (Theme.Values.checkBoxSize - Theme.Values.checkBoxIndicatorSize) * 0.5
+ y: (Theme.Values.checkBoxSize - Theme.Values.checkBoxIndicatorSize) * 0.5
+ color: Theme.Colors.accent
+ visible: control.checked
+ }
+ }
+
+ contentItem: Text {
+ id: checkBoxLabel
+ text: control.text
+ font: control.font
+ color: Theme.Colors.text
+ verticalAlignment: Text.AlignVCenter
+ leftPadding: control.indicator.width + control.spacing
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: control.enabled && !control.hovered && !control.pressed
+ PropertyChanges {
+ target: checkBoxBackground
+ color: Theme.Colors.backgroundPrimary
+ border.color: Theme.Colors.foregroundSecondary
+ }
+ PropertyChanges {
+ target: checkBoxLabel
+ color: Theme.Colors.text
+ }
+ },
+ State {
+ name: "hover"
+ when: control.enabled && control.hovered && !control.pressed
+ PropertyChanges {
+ target: checkBoxBackground
+ color: Theme.Colors.hover
+ border.color: Theme.Colors.foregroundSecondary
+ }
+ },
+ State {
+ name: "press"
+ when: control.hovered && control.pressed
+ PropertyChanges {
+ target: checkBoxBackground
+ color: Theme.Colors.hover
+ border.color: Theme.Colors.accent
+ }
+ PropertyChanges {
+ target: checkBoxIndicator
+ color: Theme.Colors.backgroundSecondary
+ }
+ },
+ State {
+ name: "disable"
+ when: !control.enabled
+ PropertyChanges {
+ target: checkBoxBackground
+ color: Theme.Colors.backgroundPrimary
+ border.color: Theme.Colors.disabledLink
+ }
+ PropertyChanges {
+ target: checkBoxIndicator
+ color: Theme.Colors.disabledLink
+ }
+ PropertyChanges {
+ target: checkBoxLabel
+ color: Theme.Colors.disabledLink
+ }
+ }
+ ]
+}
+
+/*##^##
+Designer {
+ D{i:0;height:40;width:142}
+}
+##^##*/
+
diff --git a/share/qtcreator/qmldesigner/landingpage/content/InstallQdsStatusBlock.ui.qml b/share/qtcreator/qmldesigner/landingpage/content/InstallQdsStatusBlock.ui.qml
new file mode 100644
index 00000000000..6948e216bec
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/InstallQdsStatusBlock.ui.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Quick Studio Components.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
+It is supposed to be strictly declarative and only uses a subset of QML. If you edit
+this file manually, you might introduce QML code that is not supported by Qt Design Studio.
+Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
+*/
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import LandingPageApi
+import LandingPage as Theme
+
+Rectangle {
+ id: root
+
+ color: Theme.Colors.backgroundSecondary
+ height: column.childrenRect.height + (2 * Theme.Values.spacing)
+
+ Connections {
+ target: installButton
+ function onClicked() { LandingPageApi.installQds() }
+ }
+
+ Column {
+ id: column
+
+ width: parent.width
+ anchors.centerIn: parent
+
+ PageText {
+ id: statusText
+ width: parent.width
+ topPadding: 0
+ padding: Theme.Values.spacing
+ text: qsTr("No Qt Design Studio installation found")
+ }
+
+ PageText {
+ id: suggestionText
+ width: parent.width
+ padding: Theme.Values.spacing
+ text: qsTr("Would you like to install it now?")
+ }
+
+ PushButton {
+ id: installButton
+ text: qsTr("Install")
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/content/PageText.ui.qml b/share/qtcreator/qmldesigner/landingpage/content/PageText.ui.qml
new file mode 100644
index 00000000000..94fb973084e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/PageText.ui.qml
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Quick Studio Components.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
+It is supposed to be strictly declarative and only uses a subset of QML. If you edit
+this file manually, you might introduce QML code that is not supported by Qt Design Studio.
+Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
+*/
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import LandingPage as Theme
+
+Text {
+ font.family: Theme.Values.baseFont
+ font.pixelSize: Theme.Values.fontSizeSubtitle
+ horizontalAlignment: Text.AlignHCenter
+ color: Theme.Colors.text
+ anchors.horizontalCenter: parent.horizontalCenter
+ wrapMode: Text.WordWrap
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/content/ProjectInfoStatusBlock.ui.qml b/share/qtcreator/qmldesigner/landingpage/content/ProjectInfoStatusBlock.ui.qml
new file mode 100644
index 00000000000..67108eb0860
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/ProjectInfoStatusBlock.ui.qml
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Quick Studio Components.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
+It is supposed to be strictly declarative and only uses a subset of QML. If you edit
+this file manually, you might introduce QML code that is not supported by Qt Design Studio.
+Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
+*/
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import LandingPageApi
+import LandingPage as Theme
+
+Rectangle {
+ id: root
+
+ property bool qdsInstalled: qdsVersionText.text.length > 0
+ property bool projectFileExists: false
+ property string qtVersion: qsTr("Unknown")
+ property string qdsVersion: qsTr("Unknown")
+ property alias generateProjectFileButton: generateProjectFileButton
+
+ color: Theme.Colors.backgroundSecondary
+ height: column.childrenRect.height + (2 * Theme.Values.spacing)
+
+ Connections {
+ target: generateProjectFileButton
+ function onClicked() { LandingPageApi.generateProjectFile() }
+ }
+
+ Column {
+ id: column
+
+ width: parent.width
+ anchors.centerIn: parent
+ spacing: Theme.Values.spacing
+
+ PageText {
+ id: projectFileInfoTitle
+ width: parent.width
+ text: qsTr("QML PROJECT FILE INFO")
+ }
+
+ Column {
+ id: projectFileInfoVersionBox
+ width: parent.width
+ visible: root.projectFileExists
+
+ PageText {
+ id: qtVersionText
+ width: parent.width
+ padding: Theme.Values.spacing
+ text: qsTr("Qt Version - ") + root.qtVersion
+ }
+
+ PageText {
+ id: qdsVersionText
+ width: parent.width
+ padding: Theme.Values.spacing
+ text: qsTr("Qt Design Studio Version - ") + root.qdsVersion
+ }
+ }
+
+ Column {
+ id: projectFileInfoMissingBox
+ width: parent.width
+ visible: !projectFileInfoVersionBox.visible
+
+ PageText {
+ id: projectFileInfoMissingText
+ width: parent.width
+ padding: Theme.Values.spacing
+ text: qsTr("No QML project file found - Would you like to create one?")
+ }
+
+ PushButton {
+ id: generateProjectFileButton
+ text: qsTr("Generate")
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/content/PushButton.ui.qml b/share/qtcreator/qmldesigner/landingpage/content/PushButton.ui.qml
new file mode 100644
index 00000000000..116940870ee
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/PushButton.ui.qml
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Templates 2.15
+import LandingPage as Theme
+
+Button {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+ leftPadding: 4
+ rightPadding: 4
+ hoverEnabled: true
+ font.family: Theme.Values.baseFont
+ font.pixelSize: 16
+
+ background: Rectangle {
+ id: buttonBackground
+ color: Theme.Colors.backgroundPrimary
+ implicitWidth: 100
+ implicitHeight: 35
+ border.color: Theme.Colors.foregroundSecondary
+ anchors.fill: parent
+ }
+
+ contentItem: Text {
+ id: textItem
+ text: control.text
+ font: control.font
+ color: Theme.Colors.text
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ rightPadding: 5
+ leftPadding: 5
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: control.enabled && !control.hovered && !control.pressed && !control.checked
+ PropertyChanges {
+ target: buttonBackground
+ color: Theme.Colors.backgroundPrimary
+ }
+ PropertyChanges {
+ target: textItem
+ color: Theme.Colors.text
+ }
+ },
+ State {
+ name: "hover"
+ extend: "default"
+ when: control.enabled && control.hovered && !control.pressed
+ PropertyChanges {
+ target: buttonBackground
+ color: Theme.Colors.hover
+ }
+ },
+ State {
+ name: "press"
+ extend: "default"
+ when: control.hovered && control.pressed
+ PropertyChanges {
+ target: buttonBackground
+ color: Theme.Colors.accent
+ border.color: Theme.Colors.accent
+ }
+ PropertyChanges {
+ target: textItem
+ color: Theme.Colors.backgroundPrimary
+ }
+ },
+ State {
+ name: "disable"
+ when: !control.enabled
+ PropertyChanges {
+ target: buttonBackground
+ color: Theme.Colors.backgroundPrimary
+ border.color: Theme.Colors.disabledLink
+ }
+ PropertyChanges {
+ target: textItem
+ color: Theme.Colors.disabledLink
+ }
+ }
+ ]
+}
+
+/*##^##
+Designer {
+ D{i:0;height:40;width:142}
+}
+##^##*/
+
diff --git a/share/qtcreator/qmldesigner/landingpage/content/Screen01.ui.qml b/share/qtcreator/qmldesigner/landingpage/content/Screen01.ui.qml
new file mode 100644
index 00000000000..9e1d29197e7
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/Screen01.ui.qml
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Quick Studio Components.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
+It is supposed to be strictly declarative and only uses a subset of QML. If you edit
+this file manually, you might introduce QML code that is not supported by Qt Design Studio.
+Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
+*/
+
+import QtQuick 2.15
+import QtQuick.Controls 6.2
+import QtQuick.Layouts 1.15
+import LandingPageApi
+import LandingPage as Theme
+
+Rectangle {
+ id: root
+
+ width: 1024
+ height: 768
+ color: Theme.Colors.backgroundPrimary
+
+ Connections {
+ target: openQds
+ function onClicked() { LandingPageApi.openQds(rememberCheckbox.checkState === Qt.Checked) }
+ }
+
+ Connections {
+ target: openQtc
+ function onClicked() { LandingPageApi.openQtc(rememberCheckbox.checkState === Qt.Checked) }
+ }
+
+ states: [
+ State {
+ name: "large"
+ when: root.width > Theme.Values.layoutBreakpointLG
+ PropertyChanges {
+ target: Theme.Values
+ fontSizeTitle: Theme.Values.fontSizeTitleLG
+ fontSizeSubtitle: Theme.Values.fontSizeSubtitleLG
+ }
+ PropertyChanges {
+ target: buttonBoxGrid
+ columns: 2
+ }
+ },
+ State {
+ name: "medium"
+ when: root.width <= Theme.Values.layoutBreakpointLG
+ && root.width > Theme.Values.layoutBreakpointMD
+ PropertyChanges {
+ target: Theme.Values
+ fontSizeTitle: Theme.Values.fontSizeTitleMD
+ fontSizeSubtitle: Theme.Values.fontSizeSubtitleMD
+ }
+ PropertyChanges {
+ target: buttonBoxGrid
+ columns: 2
+ }
+ },
+ State {
+ name: "small"
+ when: root.width <= Theme.Values.layoutBreakpointMD
+ PropertyChanges {
+ target: Theme.Values
+ fontSizeTitle: Theme.Values.fontSizeTitleSM
+ fontSizeSubtitle: Theme.Values.fontSizeSubtitleSM
+ }
+ PropertyChanges {
+ target: buttonBoxGrid
+ columns: 1
+ }
+ }
+ ]
+
+ ScrollView {
+ id: scrollView
+ anchors.fill: root
+
+ Column {
+ id: layout
+ spacing: 0
+ width: scrollView.width
+
+ Item {
+ width: layout.width
+ height: logoSection.childrenRect.height + (2 * Theme.Values.spacing)
+
+ Column {
+ id: logoSection
+ spacing: 10
+ anchors.centerIn: parent
+
+ Image {
+ id: qdsLogo
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: "logo.png"
+ }
+
+ Text {
+ id: qdsText
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: qsTr("Qt Design Studio")
+ font.pixelSize: Theme.Values.fontSizeTitle
+ font.family: Theme.Values.baseFont
+ color: Theme.Colors.text
+ }
+ }
+ }
+
+ InstallQdsStatusBlock {
+ id: installQdsStatusBlock
+ width: parent.width
+ visible: !LandingPageApi.qdsInstalled
+ }
+
+ ProjectInfoStatusBlock {
+ id: projectInfoStatusBlock
+ width: parent.width
+ visible: !installQdsStatusBlock.visible
+ projectFileExists: LandingPageApi.projectFileExists
+ qtVersion: LandingPageApi.qtVersion
+ qdsVersion: LandingPageApi.qdsVersion
+ }
+
+ GridLayout {
+ id: buttonBoxGrid
+ anchors.horizontalCenter: parent.horizontalCenter
+ columns: 2
+ rows: 2
+ columnSpacing: 3 * Theme.Values.spacing
+ rowSpacing: Theme.Values.spacing
+
+ property int tmpWidth: textMetrics.width
+
+ TextMetrics {
+ id: textMetrics
+ text: openQtcText.text.length > openQdsText.text.length ? openQtcText.text
+ : openQdsText.text
+ font.pixelSize: Theme.Values.fontSizeSubtitle
+ font.family: Theme.Values.baseFont
+ }
+
+ Column {
+ id: openQdsBox
+ Layout.alignment: Qt.AlignHCenter
+
+ PageText {
+ id: openQdsText
+ width: buttonBoxGrid.tmpWidth
+ padding: Theme.Values.spacing
+ text: qsTr("Open with Qt Design Studio")
+ wrapMode: Text.NoWrap
+ }
+
+ PushButton {
+ id: openQds
+ text: qsTr("Open")
+ enabled: LandingPageApi.qdsInstalled
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+
+ Column {
+ id: openQtcBox
+ Layout.alignment: Qt.AlignHCenter
+
+ PageText {
+ id: openQtcText
+ width: buttonBoxGrid.tmpWidth
+ padding: Theme.Values.spacing
+ text: qsTr("Open with Qt Creator - Text Mode")
+ wrapMode: Text.NoWrap
+ }
+
+ PushButton {
+ id: openQtc
+ text: qsTr("Open")
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+
+ CustomCheckBox {
+ id: rememberCheckbox
+ text: qsTr("Remember my choice")
+ font.family: Theme.Values.baseFont
+ Layout.columnSpan: buttonBoxGrid.columns
+ Layout.alignment: Qt.AlignHCenter
+ Layout.topMargin: Theme.Values.spacing
+ Layout.bottomMargin: Theme.Values.spacing
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/content/logo.png b/share/qtcreator/qmldesigner/landingpage/content/logo.png
new file mode 100644
index 00000000000..e4cf99cfa9b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/logo.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/landingpage/content/logo@2x.png b/share/qtcreator/qmldesigner/landingpage/content/logo@2x.png
new file mode 100644
index 00000000000..4c39c4ff737
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/content/logo@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/+QDS_theming/Colors.qml b/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/+QDS_theming/Colors.qml
new file mode 100644
index 00000000000..a94f82a7ad3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/+QDS_theming/Colors.qml
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.15
+
+QtObject {
+ readonly property color text: "#ffe7e7e7"
+ readonly property color foregroundPrimary: "#ffa3a3a3"
+ readonly property color foregroundSecondary: "#ff808080"
+ readonly property color backgroundPrimary: "#ff333333"
+ readonly property color backgroundSecondary: "#ff232323"
+ readonly property color hover: "#ff404040"
+ readonly property color accent: "#ff57d658"
+ readonly property color link: "#ff67e668"
+ readonly property color disabledLink: "#7fffffff"
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/Colors.qml b/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/Colors.qml
new file mode 100644
index 00000000000..95956290f30
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/Colors.qml
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.15
+import LandingPageTheme
+
+QtObject {
+ readonly property color text: Theme.color(Theme.Welcome_TextColor)
+ readonly property color foregroundPrimary: Theme.color(Theme.Welcome_ForegroundPrimaryColor)
+ readonly property color foregroundSecondary: Theme.color(Theme.Welcome_ForegroundSecondaryColor)
+ readonly property color backgroundPrimary: Theme.color(Theme.Welcome_BackgroundPrimaryColor)
+ readonly property color backgroundSecondary: Theme.color(Theme.Welcome_BackgroundSecondaryColor)
+ readonly property color hover: Theme.color(Theme.Welcome_HoverColor)
+ readonly property color accent: Theme.color(Theme.Welcome_AccentColor)
+ readonly property color link: Theme.color(Theme.Welcome_LinkColor)
+ readonly property color disabledLink: Theme.color(Theme.Welcome_DisabledLinkColor)
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/Values.qml b/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/Values.qml
new file mode 100644
index 00000000000..de4ea147c07
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/Values.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.15
+
+QtObject {
+ id: values
+
+ property string baseFont: "Titillium Web"
+
+ property real scaleFactor: 1.0
+ property real checkBoxSize: Math.round(26 * values.scaleFactor)
+ property real checkBoxIndicatorSize: Math.round(14 * values.scaleFactor)
+ property real checkBoxSpacing: Math.round(6 * values.scaleFactor)
+ property real border: 1
+
+ property int fontSizeTitle: values.fontSizeTitleLG
+ property int fontSizeSubtitle: values.fontSizeSubtitleLG
+
+ readonly property int fontSizeTitleSM: 20
+ readonly property int fontSizeTitleMD: 32
+ readonly property int fontSizeTitleLG: 50
+
+ readonly property int fontSizeSubtitleSM: 14
+ readonly property int fontSizeSubtitleMD: 18
+ readonly property int fontSizeSubtitleLG: 22
+
+ // LG > 1000, MD <= 1000 && > 720, SM <= 720
+ readonly property int layoutBreakpointLG: 1000
+ readonly property int layoutBreakpointMD: 720
+
+ readonly property int spacing: 20
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/qmldir b/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/qmldir
new file mode 100644
index 00000000000..9773fc5d1ab
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/imports/LandingPage/qmldir
@@ -0,0 +1,2 @@
+singleton Values 1.0 Values.qml
+singleton Colors 1.0 Colors.qml
diff --git a/share/qtcreator/qmldesigner/landingpage/landingpage.qmlproject b/share/qtcreator/qmldesigner/landingpage/landingpage.qmlproject
new file mode 100644
index 00000000000..2b6325ada5a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/landingpage.qmlproject
@@ -0,0 +1,86 @@
+import QmlProject 1.1
+
+Project {
+ mainFile: "content/App.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "content"
+ }
+
+ QmlFiles {
+ directory: "imports"
+ }
+
+ QmlFiles {
+ directory: "mockimports"
+ }
+
+ JavaScriptFiles {
+ directory: "content"
+ }
+
+ JavaScriptFiles {
+ directory: "imports"
+ }
+
+ ImageFiles {
+ directory: "content"
+ }
+
+ Files {
+ filter: "*.conf"
+ files: ["qtquickcontrols2.conf"]
+ }
+
+ Files {
+ filter: "qmldir"
+ directory: "."
+ }
+
+ Files {
+ filter: "*.ttf;*.otf"
+ }
+
+ Files {
+ filter: "*.wav;*.mp3"
+ }
+
+ Files {
+ filter: "*.mp4"
+ }
+
+ Files {
+ filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag"
+ }
+
+ Files {
+ filter: "*.mesh"
+ directory: "asset_imports"
+ }
+
+ Environment {
+ QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
+ QT_AUTO_SCREEN_SCALE_FACTOR: "1"
+ QMLSCENE_CORE_PROFILE: "true" // Required for macOS, but can create issues on embedded Linux
+ QT_LOGGING_RULES: "qt.qml.connections=false"
+ QT_ENABLE_HIGHDPI_SCALING: "0"
+ /* Useful for debugging
+ QSG_VISUALIZE=batches
+ QSG_VISUALIZE=clip
+ QSG_VISUALIZE=changes
+ QSG_VISUALIZE=overdraw
+ */
+ }
+
+ /* List of plugin directories passed to QML runtime */
+ importPaths: [ "imports", "../../../../src/share/3rdparty/studiofonts", "mockimports" ]
+
+ fileSelectors: [ "QDS_theming" ]
+
+ qt6Project: true
+
+ qdsVersion: "3.2"
+
+ mainUiFile: "content/Screen01.ui.qml"
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/main.qml b/share/qtcreator/qmldesigner/landingpage/main.qml
new file mode 100644
index 00000000000..0e6d3dfb3cd
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/main.qml
@@ -0,0 +1,9 @@
+/* This file is generated and only relevant for integrating the project into a Qt 6 and cmake based
+C++ project. */
+
+import QtQuick
+import "content"
+
+App {
+
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageApi/LandingPageApi.qml b/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageApi/LandingPageApi.qml
new file mode 100644
index 00000000000..c1148980988
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageApi/LandingPageApi.qml
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.15
+import StudioFonts
+
+QtObject {
+ property bool qdsInstalled: true
+ property bool projectFileExists: true
+ property string qtVersion: "6.1"
+ property string qdsVersion: "3.6"
+
+ function openQtc(rememberSelection) { console.log("openQtc", rememberSelection) }
+ function openQds(rememberSelection) { console.log("openQds", rememberSelection) }
+ function installQds() { console.log("installQds") }
+ function generateProjectFile() { console.log("generateProjectFile") }
+
+ // This property ensures that the Titillium font will be loaded and
+ // can be used by the theme.
+ property string family: StudioFonts.titilliumWeb_regular
+}
diff --git a/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageApi/qmldir b/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageApi/qmldir
new file mode 100644
index 00000000000..d3cbdae478c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageApi/qmldir
@@ -0,0 +1 @@
+singleton LandingPageApi 1.0 LandingPageApi.qml
diff --git a/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageTheme/Dummy.qml b/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageTheme/Dummy.qml
new file mode 100644
index 00000000000..3e1e28bc87a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageTheme/Dummy.qml
@@ -0,0 +1,32 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Quick Studio Components.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.15
+
+QtObject {}
diff --git a/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageTheme/qmldir b/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageTheme/qmldir
new file mode 100644
index 00000000000..9ae3bc301f0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/landingpage/mockimports/LandingPageTheme/qmldir
@@ -0,0 +1 @@
+Dummy 1.0 Dummy.qml
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
index 0419b945b9c..a8692f3ef9d 100644
--- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
+++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
@@ -39,6 +39,8 @@ Item {
property var currentMaterial: null
property int currentMaterialIdx: 0
+ property var matSectionsModel: []
+
// Called also from C++ to close context menu on focus out
function closeContextMenu()
{
@@ -67,8 +69,10 @@ Item {
acceptedButtons: Qt.RightButton
onClicked: {
- root.currentMaterial = null
- contextMenu.popup()
+ if (!materialBrowserModel.hasMaterialRoot) {
+ root.currentMaterial = null
+ contextMenu.popup()
+ }
}
}
@@ -92,27 +96,77 @@ Item {
StudioControls.MenuItem {
text: qsTr("Apply to selected (replace)")
- enabled: currentMaterial && materialBrowserModel.hasModelSelection
- onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, false)
+ enabled: root.currentMaterial && materialBrowserModel.hasModelSelection
+ onTriggered: materialBrowserModel.applyToSelected(root.currentMaterial.materialInternalId, false)
}
StudioControls.MenuItem {
text: qsTr("Apply to selected (add)")
- enabled: currentMaterial && materialBrowserModel.hasModelSelection
- onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, true)
+ enabled: root.currentMaterial && materialBrowserModel.hasModelSelection
+ onTriggered: materialBrowserModel.applyToSelected(root.currentMaterial.materialInternalId, true)
+ }
+
+ StudioControls.MenuSeparator {
+ height: StudioTheme.Values.border
+ }
+
+ StudioControls.Menu {
+ title: qsTr("Copy properties")
+ enabled: root.currentMaterial
+
+ width: parent.width
+
+ onAboutToShow: {
+ root.matSectionsModel = ["All"];
+
+ switch (root.currentMaterial.materialType) {
+ case "DefaultMaterial":
+ root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.defaultMaterialSections);
+ break;
+
+ case "PrincipledMaterial":
+ root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.principledMaterialSections);
+ break;
+
+ case "CustomMaterial":
+ root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.customMaterialSections);
+ break;
+ }
+ }
+
+ Repeater {
+ model: root.matSectionsModel
+
+ StudioControls.MenuItem {
+ text: modelData
+ enabled: root.currentMaterial
+ onTriggered: materialBrowserModel.copyMaterialProperties(root.currentMaterialIdx, modelData)
+ }
+ }
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Paste properties")
+ enabled: root.currentMaterial && root.currentMaterial.materialType
+ === materialBrowserModel.copiedMaterialType
+ onTriggered: materialBrowserModel.pasteMaterialProperties(root.currentMaterialIdx)
+ }
+
+ StudioControls.MenuSeparator {
+ height: StudioTheme.Values.border
}
StudioControls.MenuItem {
text: qsTr("Duplicate")
- enabled: currentMaterial
- onTriggered: materialBrowserModel.duplicateMaterial(currentMaterialIdx)
+ enabled: root.currentMaterial
+ onTriggered: materialBrowserModel.duplicateMaterial(root.currentMaterialIdx)
}
StudioControls.MenuItem {
text: qsTr("Rename")
- enabled: currentMaterial
+ enabled: root.currentMaterial
onTriggered: {
- var item = gridRepeater.itemAt(currentMaterialIdx);
+ var item = gridRepeater.itemAt(root.currentMaterialIdx);
if (item)
item.startRename();
}
@@ -120,9 +174,9 @@ Item {
StudioControls.MenuItem {
text: qsTr("Delete")
- enabled: currentMaterial
+ enabled: root.currentMaterial
- onTriggered: materialBrowserModel.deleteMaterial(currentMaterialIdx)
+ onTriggered: materialBrowserModel.deleteMaterial(root.currentMaterialIdx)
}
StudioControls.MenuSeparator {}
@@ -141,6 +195,7 @@ Item {
Row {
width: root.width
+ enabled: !materialBrowserModel.hasMaterialRoot && materialBrowserModel.hasQuick3DImport
SearchBox {
id: searchBox
@@ -165,22 +220,22 @@ Item {
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFontSize
leftPadding: 10
- visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty && !searchBox.isEmpty()
+ visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty
+ && !searchBox.isEmpty() && !materialBrowserModel.hasMaterialRoot
}
Text {
- text: qsTr("There are no materials in this project.<br>Select '<b>+</b>' to create one.")
- textFormat: Text.RichText
- color: StudioTheme.Values.themeTextColor
- font.pixelSize: StudioTheme.Values.mediumFontSize
- horizontalAlignment: Text.AlignHCenter
- topPadding: 30
- anchors.horizontalCenter: parent.horizontalCenter
- visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty && searchBox.isEmpty()
- }
+ text: {
+ if (materialBrowserModel.hasMaterialRoot)
+ qsTr("<b>Material Browser</b> is disabled inside a material component.")
+ else if (!materialBrowserModel.hasQuick3DImport)
+ qsTr("To use <b>Material Browser</b>, first add the QtQuick3D module in the <b>Components</b> view.")
+ else if (materialBrowserModel.isEmpty && searchBox.isEmpty())
+ qsTr("There are no materials in this project.<br>Select '<b>+</b>' to create one.")
+ else
+ ""
+ }
- Text {
- text: qsTr("To use <b>Material Browser</b>, first add the QtQuick3D module in the <b>Components</b> view.");
textFormat: Text.RichText
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.mediumFontSize
@@ -188,8 +243,7 @@ Item {
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
width: root.width
- anchors.horizontalCenter: parent.horizontalCenter
- visible: !materialBrowserModel.hasQuick3DImport
+ visible: text !== ""
}
ScrollView {
diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml
index a9e272b6d51..50b5ce6a7e8 100644
--- a/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml
+++ b/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml
@@ -33,6 +33,12 @@ PropertyEditorPane {
id: root
signal toolBarAction(int action)
+ signal previewEnvChanged(string env)
+ signal previewModelChanged(string model)
+
+ // Called from C++, dummy methods to avoid warnings
+ function closeContextMenu() {}
+ function initPreviewData(env, model) {}
Column {
id: col
diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml
index cfc037bc24f..19d25e7fdc1 100644
--- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml
+++ b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml
@@ -31,6 +31,8 @@ PropertyEditorPane {
id: itemPane
signal toolBarAction(int action)
+ signal previewEnvChanged(string env)
+ signal previewModelChanged(string model)
// invoked from C++ to refresh material preview image
function refreshPreview()
@@ -38,10 +40,43 @@ PropertyEditorPane {
topSection.refreshPreview()
}
+ // Called also from C++ to close context menu on focus out
+ function closeContextMenu()
+ {
+ topSection.closeContextMenu()
+ }
+
+ // Called from C++ to initialize preview menu checkmarks
+ function initPreviewData(env, model)
+ {
+ topSection.previewEnv = env;
+ topSection.previewModel = model
+ }
+
MaterialEditorTopSection {
id: topSection
onToolBarAction: (action) => itemPane.toolBarAction(action)
+ onPreviewEnvChanged: itemPane.previewEnvChanged(previewEnv)
+ onPreviewModelChanged: itemPane.previewModelChanged(previewModel)
+ }
+
+ Item { width: 1; height: 10 }
+
+ Loader {
+ id: specificsTwo
+
+ property string theSource: specificQmlData
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ visible: theSource !== ""
+ sourceComponent: specificQmlComponent
+
+ onTheSourceChanged: {
+ active = false
+ active = true
+ }
}
Item { width: 1; height: 10 }
diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml
index 80a8d9abbe9..5d53bfc87d3 100644
--- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml
+++ b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml
@@ -47,10 +47,10 @@ Rectangle {
IconButton {
icon: StudioTheme.Constants.applyMaterialToSelected
- normalColor: "transparent"
+ normalColor: StudioTheme.Values.themeSectionHeadBackground
iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: root.height
- enabled: hasMaterial && hasModelSelection && hasQuick3DImport
+ enabled: hasMaterial && hasModelSelection && hasQuick3DImport && !hasMaterialRoot
onClicked: root.toolBarAction(ToolBarAction.ApplyToSelected)
tooltip: qsTr("Apply material to selected model.")
}
@@ -58,10 +58,10 @@ Rectangle {
IconButton {
icon: StudioTheme.Constants.newMaterial
- normalColor: "transparent"
+ normalColor: StudioTheme.Values.themeSectionHeadBackground
iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: root.height
- enabled: hasQuick3DImport
+ enabled: hasQuick3DImport && !hasMaterialRoot
onClicked: root.toolBarAction(ToolBarAction.AddNewMaterial)
tooltip: qsTr("Create new material.")
}
@@ -69,10 +69,10 @@ Rectangle {
IconButton {
icon: StudioTheme.Constants.deleteMaterial
- normalColor: "transparent"
+ normalColor: StudioTheme.Values.themeSectionHeadBackground
iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: root.height
- enabled: hasMaterial && hasQuick3DImport
+ enabled: hasMaterial && hasQuick3DImport && !hasMaterialRoot
onClicked: root.toolBarAction(ToolBarAction.DeleteCurrentMaterial)
tooltip: qsTr("Delete current material.")
}
@@ -80,10 +80,10 @@ Rectangle {
IconButton {
icon: StudioTheme.Constants.openMaterialBrowser
- normalColor: "transparent"
+ normalColor: StudioTheme.Values.themeSectionHeadBackground
iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: root.height
- enabled: hasMaterial && hasQuick3DImport
+ enabled: hasMaterial && hasQuick3DImport && !hasMaterialRoot
onClicked: root.toolBarAction(ToolBarAction.OpenMaterialBrowser)
tooltip: qsTr("Open material browser.")
}
diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml
index 2e21d5814ac..80ac9b2aacb 100644
--- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml
+++ b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml
@@ -29,6 +29,7 @@ import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
import QtQuick.Templates 2.15 as T
import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Column {
@@ -36,12 +37,22 @@ Column {
signal toolBarAction(int action)
+ property string previewEnv
+ property string previewModel
+
function refreshPreview()
{
materialPreview.source = ""
materialPreview.source = "image://materialEditor/preview"
}
+ // Called from C++ to close context menu on focus out
+ function closeContextMenu()
+ {
+ modelMenu.close()
+ envMenu.close()
+ }
+
anchors.left: parent.left
anchors.right: parent.right
@@ -53,20 +64,133 @@ Column {
Item { width: 1; height: 10 } // spacer
- Rectangle {
- width: 152
- height: 152
- color: "#000000"
+
+ StudioControls.Menu {
+ id: modelMenu
+ closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside
+
+ ListModel {
+ id: modelMenuModel
+ ListElement {
+ modelName: qsTr("Cone")
+ modelStr: "#Cone"
+ }
+ ListElement {
+ modelName: qsTr("Cube")
+ modelStr: "#Cube"
+ }
+ ListElement {
+ modelName: qsTr("Cylinder")
+ modelStr: "#Cylinder"
+ }
+ ListElement {
+ modelName: qsTr("Sphere")
+ modelStr: "#Sphere"
+ }
+ }
+
+ Repeater {
+ model: modelMenuModel
+ StudioControls.MenuItemWithIcon {
+ text: modelName
+ onClicked: {
+ // Force property change notifications to keep check mark when reselected
+ root.previewModel = ""
+ root.previewModel = modelStr
+ }
+ checkable: true
+ checked: root.previewModel === modelStr
+ }
+ }
+ }
+
+ StudioControls.Menu {
+ id: envMenu
+ closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside
+
+ ListModel {
+ id: envMenuModel
+ ListElement {
+ envName: qsTr("Default")
+ envStr: "Default"
+ }
+ ListElement {
+ envName: qsTr("Color")
+ envStr: "Color"
+ }
+ ListElement {
+ envName: qsTr("Studio")
+ envStr: "SkyBox=preview_studio"
+ }
+ ListElement {
+ envName: qsTr("Landscape")
+ envStr: "SkyBox=preview_landscape"
+ }
+ }
+
+ Repeater {
+ model: envMenuModel
+ StudioControls.MenuItemWithIcon {
+ text: envName
+ onClicked: {
+ // Force property change notifications to keep check mark when reselected
+ root.previewEnv = ""
+ root.previewEnv = envStr
+ }
+ checkable: true
+ checked: root.previewEnv === envStr
+ }
+ }
+ }
+
+ Item {
anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width
+ height: previewRect.height
+
+ Rectangle {
+ id: previewRect
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 152
+ height: 152
+ color: "#000000"
+
+ Image {
+ id: materialPreview
+ width: 150
+ height: 150
+ anchors.centerIn: parent
+ source: "image://materialEditor/preview"
+ cache: false
+ }
+ }
- Image {
- id: materialPreview
- width: 150
- height: 150
- anchors.centerIn: parent
- source: "image://materialEditor/preview"
- cache: false
+ Item {
+ id: previewOptions
+ width: 40
+ height: previewRect.height
+ anchors.top: previewRect.top
+ anchors.left: previewRect.right
+
+ Column {
+ anchors.horizontalCenter: parent.horizontalCenter
+ IconButton {
+ icon: StudioTheme.Constants.materialPreviewEnvironment
+ iconSize: StudioTheme.Values.bigIconFontSize
+ buttonSize: previewOptions.width
+ tooltip: qsTr("Select preview environment.")
+ onClicked: envMenu.popup()
+ }
+ IconButton {
+ icon: StudioTheme.Constants.materialPreviewModel
+ iconSize: StudioTheme.Values.bigIconFontSize
+ buttonSize: previewOptions.width
+ tooltip: qsTr("Select preview model.")
+ onClicked: modelMenu.popup()
+ }
+ }
}
+
}
Section {
@@ -103,17 +227,8 @@ Column {
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
ComboBox {
- currentIndex: {
- if (backendValues.__classNamePrivateInternal.value === "CustomMaterial")
- return 2
-
- if (backendValues.__classNamePrivateInternal.value === "PrincipledMaterial")
- return 1
-
- return 0
- }
-
- model: ["DefaultMaterial", "PrincipledMaterial", "CustomMaterial"]
+ currentIndex: possibleTypeIndex
+ model: possibleTypes
showExtendedFunctionButton: false
implicitWidth: StudioTheme.Values.singleControlColumnWidth
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
index 260c2507cdf..d2830cbcb36 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml
index 54cf89cf255..eed6afb5c9d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -75,7 +64,7 @@ Section {
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
backendValue: backendValues.display
- model: [ "IconOnly", "TextOnly", "TextBesideIcon" ]
+ model: [ "IconOnly", "TextOnly", "TextBesideIcon", "TextUnderIcon" ]
scope: "AbstractButton"
enabled: backendValue.isAvailable
}
@@ -140,6 +129,7 @@ Section {
SecondColumnLayout {
CheckBox {
+ id: autoRepeat
text: backendValues.autoRepeat.valueToString
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
@@ -148,5 +138,63 @@ Section {
ExpandingSpacer {}
}
+
+ PropertyLabel {
+ text: qsTr("Repeat delay")
+ tooltip: qsTr("Initial delay of auto-repetition in milliseconds.")
+ enabled: autoRepeat.checked
+ }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ width: implicitWidth
+ minimumValue: 0
+ maximumValue: 9999999
+ decimals: 0
+ backendValue: backendValues.autoRepeatDelay
+ enabled: autoRepeat.checked
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ ControlLabel {
+ text: "ms"
+ elide: Text.ElideNone
+ enabled: autoRepeat.checked
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel {
+ text: qsTr("Repeat interval")
+ tooltip: qsTr("Interval of auto-repetition in milliseconds.")
+ enabled: autoRepeat.checked
+ }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ width: implicitWidth
+ minimumValue: 0
+ maximumValue: 9999999
+ decimals: 0
+ backendValue: backendValues.autoRepeatInterval
+ enabled: autoRepeat.checked
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ ControlLabel {
+ text: "ms"
+ elide: Text.ElideNone
+ enabled: autoRepeat.checked
+ }
+
+ ExpandingSpacer {}
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml
index 0a92222b578..190060a7de7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -70,4 +59,6 @@ Column {
ControlSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml
index 63ed1b4436c..c75820e5b9e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml
index 6e57108f627..daea616b9ec 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -48,9 +37,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckBoxSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckBoxSpecifics.qml
index 80b27fabfdb..0c80d55e8c9 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckBoxSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckBoxSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -47,9 +36,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckDelegateSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckDelegateSpecifics.qml
index 0f9e81c6969..148e11197ee 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckDelegateSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckDelegateSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -49,9 +38,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml
index edf449fcaf7..edeba4a0864 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ComboBoxSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ComboBoxSpecifics.qml
index debeeeaecf1..9d75a9bcb58 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ComboBoxSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ComboBoxSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -138,4 +127,6 @@ Column {
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ContainerSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ContainerSection.qml
index e5f3fad767e..881e4d488bb 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ContainerSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ContainerSection.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSection.qml
index 681f2357b79..7ebd381717e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSection.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml
new file mode 100644
index 00000000000..8275a75f6d5
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import QtQuickDesignerTheme 1.0
+import StudioTheme 1.0 as StudioTheme
+
+Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ ControlSection {}
+
+ FontSection {}
+
+ PaddingSection {}
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml
index 995997af65a..43d836efa12 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -67,7 +56,10 @@ Column {
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
- ControlLabel { text: "ms" }
+ ControlLabel {
+ text: "ms"
+ elide: Text.ElideNone
+ }
ExpandingSpacer {}
}
@@ -76,9 +68,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml
index e3fae4a024a..47d86d1d4e4 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -194,4 +183,6 @@ Column {
ControlSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialogSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialogSpecifics.qml
index 47a02fc2845..bbe1453c50d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialogSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialogSpecifics.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DrawerSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DrawerSpecifics.qml
index 38242385db6..df3a568b3bf 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DrawerSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DrawerSpecifics.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml
index 33b98e44814..0df9c220ee5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -50,6 +39,8 @@ Column {
PaddingSection {}
+ InsetSection {}
+
FontSection {
caption: qsTr("Font Inheritance")
expanded: false
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml
index a8b5801fde1..3bebc986605 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -73,4 +62,6 @@ Column {
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/IconSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/IconSection.qml
new file mode 100644
index 00000000000..465d2bc9a7f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/IconSection.qml
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioTheme 1.0 as StudioTheme
+
+Section {
+ id: root
+
+ property bool blockedByContext: backendValues.display.enumeration === "TextOnly"
+
+ caption: qsTr("Icon")
+ width: parent.width
+
+ SectionLayout {
+ // We deliberately kept the "name" property out as it is only properly supported by linux
+ // based operating systems out of the box.
+
+ PropertyLabel {
+ text: qsTr("Source")
+ blockedByTemplate: !backendValues.icon_source.isAvailable
+ enabled: !root.blockedByContext
+ }
+
+ SecondColumnLayout {
+ UrlChooser {
+ backendValue: backendValues.icon_source
+ enabled: backendValues.icon_source.isAvailable && !root.blockedByContext
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel {
+ text: qsTr("Color")
+ blockedByTemplate: !backendValues.icon_color.isAvailable
+ enabled: !root.blockedByContext
+ }
+
+ ColorEditor {
+ backendValue: backendValues.icon_color
+ supportGradient: false
+ enabled: backendValues.icon_color.isAvailable && !root.blockedByContext
+ }
+
+ PropertyLabel {
+ text: qsTr("Size")
+ blockedByTemplate: !backendValues.icon_width.isAvailable
+ enabled: !root.blockedByContext
+ }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.icon_width
+ maximumValue: 0xffff
+ minimumValue: 0
+ decimals: 0
+ enabled: backendValues.icon_width.isAvailable && !root.blockedByContext
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ ControlLabel {
+ //: The width of the object
+ text: qsTr("W", "width")
+ tooltip: qsTr("Width")
+ enabled: backendValues.icon_width.isAvailable && !root.blockedByContext
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlGap }
+
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.icon_height
+ maximumValue: 0xffff
+ minimumValue: 0
+ decimals: 0
+ enabled: backendValues.icon_height.isAvailable && !root.blockedByContext
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ ControlLabel {
+ //: The height of the object
+ text: qsTr("H", "height")
+ tooltip: qsTr("Height")
+ enabled: backendValues.icon_height.isAvailable && !root.blockedByContext
+ }
+/*
+ TODO QDS-4836
+ Spacer { implicitWidth: StudioTheme.Values.controlGap }
+
+ LinkIndicator2D {}
+*/
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel {
+ text: qsTr("Cache")
+ tooltip: qsTr("Whether the icon should be cached.")
+ blockedByTemplate: !backendValues.icon_cache.isAvailable
+ enabled: !root.blockedByContext
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ text: backendValues.icon_cache.valueToString
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.icon_cache
+ enabled: backendValues.icon_cache.isAvailable && !root.blockedByContext
+ }
+
+ ExpandingSpacer {}
+ }
+
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/InsetSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/InsetSection.qml
index 17e35771fef..6e368d59746 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/InsetSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/InsetSection.qml
@@ -1,42 +1,31 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.15
-import HelperWidgets 2.0
import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme
Section {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml
index fc5c0e5f0d5..7d13b86618b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSpecifics.qml
index 88f8dbf86b7..5031f10015b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -46,9 +35,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/LabelSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/LabelSpecifics.qml
index 01e53e244c0..a88b7c5380a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/LabelSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/LabelSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml
index cda496c3d11..f113fe1d741 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -106,4 +95,6 @@ Column {
ControlSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageSpecifics.qml
index e3cac6ca29b..d860a06ed83 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -118,4 +107,6 @@ Column {
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSection.qml
index 78dcd1a9b53..f4104109d7c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSection.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml
index dde8aab73d1..d4cf276d8e3 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -48,6 +37,8 @@ Column {
PaddingSection {}
+ InsetSection {}
+
FontSection {
caption: qsTr("Font Inheritance")
expanded: false
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSection.qml
index acf1df0b2d3..f52c3e9e123 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSection.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSpecifics.qml
index 1f56aff049d..552cd88e601 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PopupSpecifics.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml
index 205df61e8bf..649d917f44b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -129,4 +118,6 @@ Column {
ControlSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioButtonSpecifics.qml
index 8c54760a8a6..5611bdd9d84 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioButtonSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -44,9 +33,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml
index 31e32eeed7a..d71689db1b1 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -48,9 +37,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml
index 430a7b49987..bbd769c84bb 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -213,4 +202,6 @@ Column {
ControlSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml
index b3d316321cc..f6ce86c61a5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -98,9 +87,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml
index a38ea1ce220..b555daa4ae6 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -98,6 +87,8 @@ Column {
PaddingSection {}
+ InsetSection {}
+
FontSection {
caption: qsTr("Font Inheritance")
expanded: false
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml
index f3ff89f91ec..d5d72e975eb 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -197,4 +186,6 @@ Column {
ControlSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml
index 01322a57ba2..b23dbc6af21 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -158,4 +147,6 @@ Column {
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml
index 3f8bb535cf5..9f16e8855cf 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -46,6 +35,8 @@ Column {
PaddingSection {}
+ InsetSection {}
+
FontSection {
caption: qsTr("Font Inheritance")
expanded: false
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeDelegateSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeDelegateSpecifics.qml
index ec3156bd556..6fe6255bb09 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeDelegateSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeDelegateSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -46,9 +35,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml
index aab4f96a29e..d2bb5397262 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -89,6 +78,8 @@ Column {
PaddingSection {}
+ InsetSection {}
+
FontSection {
caption: qsTr("Font Inheritance")
expanded: false
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchDelegateSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchDelegateSpecifics.qml
index b5805ef74c9..618c9f7db5c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchDelegateSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchDelegateSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -46,7 +35,11 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchSpecifics.qml
index b8814131f0e..40660736bfb 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwitchSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -44,9 +33,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml
index ad67f2b0b8c..18bfab40da7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -122,4 +111,6 @@ Column {
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabButtonSpecifics.qml
index 8c54760a8a6..5611bdd9d84 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabButtonSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -44,9 +33,13 @@ Column {
AbstractButtonSection {}
+ IconSection {}
+
ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextAreaSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextAreaSpecifics.qml
index 2efd3333a03..723ae01caa5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextAreaSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextAreaSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml
index 3c4c0dc8dc4..44e5e79e447 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml
index e5b2bcae655..18a0e7bab3d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml
index 445c3bc256b..0a8a20acf3b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -73,6 +62,8 @@ Column {
PaddingSection {}
+ InsetSection {}
+
FontSection {
caption: qsTr("Font Inheritance")
expanded: false
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolButtonSpecifics.qml
index 923f78e9c37..701611eb81c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolButtonSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -46,9 +35,13 @@ Column {
AbstractButtonSection {}
- ControlSection { }
+ IconSection {}
+
+ ControlSection {}
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml
index 53345e711a5..7815bf4bd6f 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -70,4 +59,6 @@ Column {
ControlSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml
index 487cd148606..da309d9b652 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml
@@ -1,36 +1,25 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+** This file is part of Qt Creator.
**
-** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
@@ -106,4 +95,6 @@ Column {
FontSection {}
PaddingSection {}
+
+ InsetSection {}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
index f2df9c0d042..b3a7c1e9fb0 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
@@ -1,3 +1,5 @@
+
+
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
@@ -22,7 +24,6 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
-
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Shapes 1.15
@@ -39,167 +40,43 @@ SecondColumnLayout {
property bool supportGradient: false
property variant backendValue
property variant value: {
- if (colorEditor.backendValue === undefined || colorEditor.backendValue.value === undefined)
+ if (colorEditor.backendValue === undefined
+ || colorEditor.backendValue.value === undefined)
return "white" // default color for Rectangle
if (colorEditor.isVector3D)
return Qt.rgba(colorEditor.backendValue.value.x,
colorEditor.backendValue.value.y,
- colorEditor.backendValue.value.z,
- 1)
+ colorEditor.backendValue.value.z, 1)
else
return colorEditor.backendValue.value
}
- property alias gradientPropertyName: gradientLine.gradientPropertyName
+ property alias gradientPropertyName: cePopup.gradientPropertyName
+
+ property alias gradientThumbnail: gradientThumbnail
+ property alias shapeGradientThumbnail: shapeGradientThumbnail
+
property bool shapeGradients: false
property color originalColor
property bool isVector3D: false
- function isNotInGradientMode() {
- return ceMode.currentValue === "Solid"
- }
-
- function hasLinearGradient() {
- return ceMode.currentValue === "LinearGradient"
- }
-
- function hasConicalGradient() {
- return ceMode.currentValue === "ConicalGradient"
- }
-
- function hasRadialGradient() {
- return ceMode.currentValue === "RadialGradient"
- }
+ property alias spacer: spacer
function resetShapeColor() {
colorEditor.backendValue.resetValue()
}
- function updateThumbnail() {
- if (!gradientLine.hasGradient)
- return
-
- if (!colorEditor.shapeGradients) {
- var gradientString = "import QtQuick 2.15; Gradient {"
- var orientation = gradientOrientation.currentValue === Gradient.Horizontal ? "Gradient.Horizontal"
- : "Gradient.Vertical"
- gradientString += "orientation: " + orientation + ";"
-
- for (var i = 0; i < gradientLine.model.count; i++)
- gradientString += "GradientStop {}"
-
- gradientString += "}"
-
- var gradientObject = Qt.createQmlObject(gradientString, gradientThumbnail, "dynamicGradient")
-
- for (i = 0; i < gradientLine.model.count; i++) {
- gradientObject.stops[i].color = gradientLine.model.getColor(i)
- gradientObject.stops[i].position = gradientLine.model.getPosition(i)
- }
-
- gradientThumbnail.gradient = gradientObject
- } else {
- var gradientStr = "import QtQuick 2.15; import QtQuick.Shapes 1.15; "
- + gradientLine.gradientTypeName + " {"
-
- if (gradientLine.gradientTypeName === "LinearGradient") {
- gradientStr += "x1: 0"
- + ";x2: " + shape.width
- + ";y1: 0"
- + ";y2: " + shape.height + ";"
- } else if (gradientLine.gradientTypeName === "RadialGradient") {
- gradientStr += "centerX: " + shape.width * 0.5
- + ";centerY: " + shape.height * 0.5
- + ";focalX: " + shape.width * 0.5
- + ";focalY: " + shape.height * 0.5
- + ";centerRadius: " + Math.min(shape.width, shape.height) * 0.5
- + ";focalRadius: 0" + ";"
- } else if (gradientLine.gradientTypeName === "ConicalGradient") {
- gradientStr += "centerX: " + shape.width * 0.5
- + ";centerY: " + shape.height * 0.5
- + ";angle: 0" + ";"
- }
-
- for (var j = 0; j < gradientLine.model.count; j++)
- gradientStr += "GradientStop {}"
-
- gradientStr += "}"
-
- var gradientObj = Qt.createQmlObject(gradientStr, shapeGradientThumbnail, "dynamicShapeGradient")
-
- for (j = 0; j < gradientLine.model.count; j++) {
- gradientObj.stops[j].color = gradientLine.model.getColor(j)
- gradientObj.stops[j].position = gradientLine.model.getPosition(j)
- }
-
- shapeGradientThumbnail.fillGradient = gradientObj
- }
- }
-
- function createModel() {
- // Build the color editor combobox model
- ceMode.items.clear()
- ceMode.items.append({
- value: "Solid",
- text: qsTr("Solid"),
- enabled: true
- })
- ceMode.items.append({
- value: "LinearGradient",
- text: qsTr("Linear"),
- enabled: colorEditor.supportGradient
- })
- ceMode.items.append({
- value: "RadialGradient",
- text: qsTr("Radial"),
- enabled: colorEditor.supportGradient && colorEditor.shapeGradients
- })
- ceMode.items.append({
- value: "ConicalGradient",
- text: qsTr("Conical"),
- enabled: colorEditor.supportGradient && colorEditor.shapeGradients
- })
- }
-
- function determineActiveColorMode() {
- if (colorEditor.supportGradient && gradientLine.hasGradient) {
- if (colorEditor.shapeGradients) {
- switch (gradientLine.gradientTypeName) {
- case "LinearGradient":
- ceMode.currentIndex = ceMode.indexOfValue("LinearGradient")
- break
- case "RadialGradient":
- ceMode.currentIndex = ceMode.indexOfValue("RadialGradient")
- break
- case "ConicalGradient":
- ceMode.currentIndex = ceMode.indexOfValue("ConicalGradient")
- break
- default:
- ceMode.currentIndex = ceMode.indexOfValue("LinearGradient")
- }
- } else {
- ceMode.currentIndex = ceMode.indexOfValue("LinearGradient")
- }
- colorEditor.color = gradientLine.currentColor
- } else {
- ceMode.currentIndex = ceMode.indexOfValue("Solid")
- colorEditor.color = colorEditor.value
- }
-
- colorEditor.originalColor = colorEditor.color
- }
-
Connections {
id: backendConnection
target: colorEditor
function onValueChanged() {
- if (isNotInGradientMode())
+ if (cePopup.isNotInGradientMode())
colorEditor.color = colorEditor.value
}
function onBackendValueChanged() {
- if (isNotInGradientMode())
+ if (cePopup.isNotInGradientMode())
colorEditor.color = colorEditor.value
}
}
@@ -214,9 +91,9 @@ SecondColumnLayout {
if (colorEditor.backendValue !== undefined) {
if (colorEditor.isVector3D)
- colorEditor.backendValue.value = Qt.vector3d(colorEditor.color.r,
- colorEditor.color.g,
- colorEditor.color.b)
+ colorEditor.backendValue.value = Qt.vector3d(
+ colorEditor.color.r, colorEditor.color.g,
+ colorEditor.color.b)
else
colorEditor.backendValue.value = colorEditor.color
}
@@ -226,21 +103,23 @@ SecondColumnLayout {
}
onColorChanged: {
- if (!gradientLine.isInValidState)
+ if (!cePopup.isInValidState)
return
- if (colorEditor.supportGradient && gradientLine.hasGradient) {
+ if (colorEditor.supportGradient && cePopup.gradientModel.hasGradient) {
var hexColor = convertColorToString(colorEditor.color)
hexTextField.text = hexColor
- popupHexTextField.text = hexColor
- gradientLine.currentColor = colorEditor.color
+ cePopup.commitGradientColor()
}
- if (isNotInGradientMode())
- colorEditorTimer.restart() // Delay setting the color to keep ui responsive
+ // Delay setting the color to keep ui responsive
+ if (cePopup.isNotInGradientMode())
+ colorEditorTimer.restart()
}
- Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
+ Spacer {
+ implicitWidth: StudioTheme.Values.actionIndicatorWidth
+ }
Rectangle {
id: preview
@@ -254,16 +133,16 @@ SecondColumnLayout {
id: gradientThumbnail
anchors.fill: parent
anchors.margins: StudioTheme.Values.border
- visible: !colorEditor.isNotInGradientMode()
+ visible: !cePopup.isNotInGradientMode()
&& !colorEditor.shapeGradients
- && colorEditor.hasLinearGradient()
+ && cePopup.hasLinearGradient()
}
Shape {
id: shape
anchors.fill: parent
anchors.margins: StudioTheme.Values.border
- visible: !colorEditor.isNotInGradientMode()
+ visible: !cePopup.isNotInGradientMode()
&& colorEditor.shapeGradients
ShapePath {
@@ -273,9 +152,18 @@ SecondColumnLayout {
strokeWidth: -1
strokeColor: "green"
- PathLine { x: shape.x - 1; y: shape.height }
- PathLine { x: shape.width; y: shape.height }
- PathLine { x: shape.width; y: shape.y - 1 }
+ PathLine {
+ x: shape.x - 1
+ y: shape.height
+ }
+ PathLine {
+ x: shape.width
+ y: shape.height
+ }
+ PathLine {
+ x: shape.width
+ y: shape.y - 1
+ }
}
}
@@ -294,1011 +182,34 @@ SecondColumnLayout {
}
}
- T.Popup {
+ ColorEditorPopup {
id: cePopup
-
- WheelHandler {
- onWheel: function(event) {
- Controller.mainScrollView.flick(0, event.angleDelta.y * 5)
- }
- }
-
- // This connection is meant to update the popups y-position and the main scrollviews
- // height as soon as the height of the color picker changes. Initially the height of the
- // color picker is 0 until its completion is done.
- Connections {
- target: colorPicker
- function onHeightChanged() {
- cePopup.setPopupY()
- cePopup.setMainScrollViewHeight()
- }
- }
-
- onOpened: {
- cePopup.setPopupY()
- cePopup.setMainScrollViewHeight()
- }
- onYChanged: cePopup.setMainScrollViewHeight()
- onHeightChanged: cePopup.setMainScrollViewHeight()
-
- function setMainScrollViewHeight() {
- if (Controller.mainScrollView === null)
- return
-
- var mapped = preview.mapToItem(Controller.mainScrollView.contentItem, cePopup.x, cePopup.y)
- Controller.mainScrollView.temporaryHeight = mapped.y + cePopup.height
- + StudioTheme.Values.colorEditorPopupMargin
- }
-
- function setPopupY() {
- if (Controller.mainScrollView === null)
- return
-
- var tmp = preview.mapToItem(Controller.mainScrollView.contentItem, preview.x, preview.y)
- cePopup.y = Math.max(-tmp.y + StudioTheme.Values.colorEditorPopupMargin,
- cePopup.__defaultY)
- }
-
- onClosed: Controller.mainScrollView.temporaryHeight = 0
-
- property real __defaultX: - StudioTheme.Values.colorEditorPopupWidth * 0.5
- + preview.width * 0.5
- property real __defaultY: - StudioTheme.Values.colorEditorPopupPadding
- - (StudioTheme.Values.colorEditorPopupSpacing * 2)
- - StudioTheme.Values.defaultControlHeight
- - StudioTheme.Values.colorEditorPopupLineHeight
- - colorPicker.height * 0.5
- + preview.height * 0.5
-
x: cePopup.__defaultX
y: cePopup.__defaultY
-
- width: StudioTheme.Values.colorEditorPopupWidth
- height: colorColumn.height + sectionColumn.height
- + StudioTheme.Values.colorEditorPopupPadding + 2 // TODO magic number
-
- padding: StudioTheme.Values.border
- margins: -1 // If not defined margin will be -1
-
- closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent
-
- contentItem: Item {
- id: todoItem
-
- property color color
- property bool supportGradient: false
-
- Column {
- id: colorColumn
-
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: StudioTheme.Values.colorEditorPopupPadding
- spacing: StudioTheme.Values.colorEditorPopupSpacing
-
- RowLayout {
- width: parent.width
- Layout.alignment: Qt.AlignTop
-
- StudioControls.ComboBox {
- id: ceMode
-
- property ListModel items: ListModel {}
-
- enabled: isBaseState
- implicitWidth: StudioTheme.Values.colorEditorPopupCmoboBoxWidth
- width: implicitWidth
- actionIndicatorVisible: false
- textRole: "text"
- valueRole: "value"
- model: ceMode.items
- onActivated: {
- switch (ceMode.currentValue) {
- case "Solid":
- gradientLine.deleteGradient()
- hexTextField.text = colorEditor.color
- popupHexTextField.text = colorEditor.color
- colorEditor.resetShapeColor()
- break
- case "LinearGradient":
- colorEditor.resetShapeColor()
-
- if (colorEditor.shapeGradients)
- gradientLine.gradientTypeName = "LinearGradient"
- else
- gradientLine.gradientTypeName = "Gradient"
-
- if (gradientLine.hasGradient)
- gradientLine.updateGradient()
- else {
- gradientLine.deleteGradient()
- gradientLine.addGradient()
- }
- break
- case "RadialGradient":
- colorEditor.resetShapeColor()
- gradientLine.gradientTypeName = "RadialGradient"
-
- if (gradientLine.hasGradient)
- gradientLine.updateGradient()
- else {
- gradientLine.deleteGradient()
- gradientLine.addGradient()
- }
- break
- case "ConicalGradient":
- colorEditor.resetShapeColor()
- gradientLine.gradientTypeName = "ConicalGradient"
-
- if (gradientLine.hasGradient)
- gradientLine.updateGradient()
- else {
- gradientLine.deleteGradient()
- gradientLine.addGradient()
- }
- break
- default:
- console.log("Unknown item selected in color mode ComboBox.")
- }
- colorEditor.updateThumbnail()
- }
-
- ToolTipArea {
- enabled: !isBaseState
- anchors.fill: parent
- tooltip: qsTr("Fill type can only be changed in base state.")
- z: 10
- }
- }
-
- ExpandingSpacer {}
-
- IconIndicator {
- id: transparentIndicator
- icon: StudioTheme.Constants.transparent
- pixelSize: StudioTheme.Values.myIconFontSize * 1.4
- tooltip: qsTr("Transparent")
- onClicked: {
- colorPicker.alpha = 0
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
-
- IconIndicator {
- id: gradientPickerIndicator
- icon: StudioTheme.Constants.gradient
- pixelSize: StudioTheme.Values.myIconFontSize * 1.4
- tooltip: qsTr("Gradient Picker")
- enabled: colorEditor.supportGradient
- onClicked: presetList.show()
-
- GradientPresetList {
- id: presetList
- visible: false
-
- function applyPreset() {
- if (!gradientLine.hasGradient) {
- if (colorEditor.shapeGradients)
- gradientLine.gradientTypeName = "LinearGradient"
- else
- gradientLine.gradientTypeName = "Gradient"
- }
-
- if (presetList.gradientData.presetType == 0) {
- gradientLine.setPresetByID(presetList.gradientData.presetID)
- } else if (presetList.gradientData.presetType == 1) {
- gradientLine.setPresetByStops(
- presetList.gradientData.stops,
- presetList.gradientData.colors,
- presetList.gradientData.stopsCount)
- } else {
- console.log("INVALID GRADIENT TYPE: " +
- presetList.gradientData.presetType)
- }
- }
-
- onApplied: {
- if (presetList.gradientData.stopsCount > 0)
- applyPreset()
- }
-
- onSaved: {
- gradientLine.savePreset()
- presetList.updatePresets()
- }
-
- onAccepted: { // return key
- if (presetList.gradientData.stopsCount > 0)
- applyPreset()
- }
- }
- }
-
- IconIndicator {
- id: eyeDropperIndicator
- icon: StudioTheme.Constants.eyeDropper
- pixelSize: StudioTheme.Values.myIconFontSize * 1.4
- tooltip: qsTr("Eye Dropper")
- onClicked: ColorPaletteBackend.eyeDropper()
- }
-
- IconIndicator {
- id: closeIndicator
- icon: StudioTheme.Constants.colorPopupClose
- pixelSize: StudioTheme.Values.myIconFontSize * 1.4
- onClicked: cePopup.close()
- }
- }
-
- ColorLine {
- id: colorLine
- width: parent.width
- currentColor: colorEditor.color
- visible: isNotInGradientMode()
- }
-
- GradientLine {
- id: gradientLine
- property bool isInValidState: false
- width: parent.width
- visible: !isNotInGradientMode()
-
- onCurrentColorChanged: {
- if (colorEditor.supportGradient && gradientLine.hasGradient) {
- colorEditor.color = gradientLine.currentColor
- colorPicker.color = colorEditor.color
- }
- }
-
- onHasGradientChanged: {
- if (!colorEditor.supportGradient)
- return
-
- colorEditor.determineActiveColorMode()
- }
-
- onSelectedNodeChanged: {
- if (colorEditor.supportGradient && gradientLine.hasGradient)
- colorEditor.originalColor = gradientLine.currentColor
- }
-
- onInvalidated: colorEditor.updateThumbnail()
-
- Connections {
- target: modelNodeBackend
- function onSelectionToBeChanged() {
- colorEditorTimer.stop()
- gradientLine.isInValidState = false
-
- var hexOriginalColor = convertColorToString(colorEditor.originalColor)
- var hexColor = convertColorToString(colorEditor.color)
-
- if (hexOriginalColor !== hexColor) {
- if (colorEditor.color !== "#ffffff"
- && colorEditor.color !== "#000000"
- && colorEditor.color !== "#00000000") {
- colorPalette.addColorToPalette(colorEditor.color)
- }
- }
- }
- }
-
- Connections {
- target: modelNodeBackend
- function onSelectionChanged() {
- if (colorEditor.supportGradient && gradientLine.hasGradient) {
- colorEditor.color = gradientLine.currentColor
- gradientLine.currentColor = colorEditor.color
- hexTextField.text = colorEditor.color
- popupHexTextField.text = colorEditor.color
- }
-
- gradientLine.isInValidState = true
- colorEditor.originalColor = colorEditor.color
- colorPalette.selectedColor = colorEditor.color
- colorPicker.color = colorEditor.color
-
- colorEditor.createModel()
- colorEditor.determineActiveColorMode()
- }
- }
- }
-
- ColorPicker {
- id: colorPicker
-
- width: parent.width
- sliderMargins: 4
-
- onUpdateColor: {
- colorEditor.color = colorPicker.color
-
- if (contextMenu.opened)
- contextMenu.close()
- }
- onRightMouseButtonClicked: contextMenu.popup(colorPicker)
-
- onColorInvalidated: {
- hslHueSpinBox.value = colorPicker.hue
- hslSaturationSpinBox.value = colorPicker.saturationHSL
- hslLightnessSpinBox.value = colorPicker.lightness
- hslAlphaSpinBox.value = colorPicker.alpha
-
- redSpinBox.value = (colorPicker.red * 255)
- greenSpinBox.value = (colorPicker.green * 255)
- blueSpinBox.value = (colorPicker.blue * 255)
- rgbAlphaSpinBox.value = (colorPicker.alpha * 255)
-
- hsvHueSpinBox.value = colorPicker.hue
- hsvSaturationSpinBox.value = colorPicker.saturationHSV
- hsvValueSpinBox.value = colorPicker.value
- hsvAlphaSpinBox.value = colorPicker.alpha
- }
- }
-
- Column {
- id: colorCompare
- width: parent.width
-
- RowLayout {
- width: parent.width
- Layout.alignment: Qt.AlignTop
- spacing: StudioTheme.Values.controlGap
-
- Label {
- text: qsTr("Original")
- width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- + StudioTheme.Values.controlGap
- }
-
- Label {
- text: qsTr("New")
- width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- + StudioTheme.Values.controlGap
- }
- }
-
- RowLayout {
- width: parent.width
- Layout.alignment: Qt.AlignTop
- spacing: StudioTheme.Values.controlGap
-
- Rectangle {
- id: originalColorRectangle
- color: colorEditor.originalColor
- height: StudioTheme.Values.height
- width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- + StudioTheme.Values.controlGap
- border.width: StudioTheme.Values.border
- border.color: StudioTheme.Values.themeControlOutline
-
- Image {
- anchors.fill: parent
- source: "images/checkers.png"
- fillMode: Image.Tile
- z: -1
- }
-
- ToolTipArea {
- anchors.fill: parent
- tooltip: originalColorRectangle.color
- acceptedButtons: Qt.LeftButton | Qt.RightButton
- onClicked: function(mouse) {
- if (mouse.button === Qt.LeftButton)
- colorEditor.color = colorEditor.originalColor
-
- if (mouse.button === Qt.RightButton) {
- contextMenuFavorite.currentColor = colorEditor.originalColor
- contextMenuFavorite.popup()
- }
- }
- }
- }
-
- Rectangle {
- id: newColorRectangle
- color: colorEditor.color
- height: StudioTheme.Values.height
- width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- + StudioTheme.Values.controlGap
- border.width: StudioTheme.Values.border
- border.color: StudioTheme.Values.themeControlOutline
-
- Image {
- anchors.fill: parent
- source: "images/checkers.png"
- fillMode: Image.Tile
- z: -1
- }
-
- ToolTipArea {
- anchors.fill: parent
- tooltip: newColorRectangle.color
- acceptedButtons: Qt.RightButton
- onClicked: function(mouse) {
- if (mouse.button === Qt.RightButton) {
- contextMenuFavorite.currentColor = colorEditor.color
- contextMenuFavorite.popup()
- }
- }
- }
- }
- }
-
- StudioControls.Menu {
- id: contextMenuFavorite
-
- property color currentColor
-
- StudioControls.MenuItem {
- text: qsTr("Add to Favorites")
- onTriggered: ColorPaletteBackend.addFavoriteColor(
- contextMenuFavorite.currentColor)
- }
- }
- }
- }
-
- Column {
- id: sectionColumn
- anchors.topMargin: StudioTheme.Values.colorEditorPopupPadding
- anchors.top: colorColumn.bottom
- anchors.left: parent.left
- anchors.right: parent.right
-
- bottomPadding: 10
-
- Section {
- caption: qsTr("Color Details")
- anchors.left: parent.left
- anchors.right: parent.right
-
- leftPadding: 10
- rightPadding: 10
-
- Column {
- spacing: 10
-
- RowLayout {
- Layout.fillWidth: true
- spacing: 0
-
- LineEdit {
- id: popupHexTextField
- implicitWidth: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- + StudioTheme.Values.controlGap
- width: implicitWidth
- writeValueManually: true
- validator: RegExpValidator { regExp: /#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?/g }
- showTranslateCheckBox: false
- showExtendedFunctionButton: false
- backendValue: colorEditor.backendValue
-
- onAccepted: colorEditor.color = colorFromString(popupHexTextField.text)
- onCommitData: {
- colorEditor.color = colorFromString(popupHexTextField.text)
- if (isNotInGradientMode()) {
- if (colorEditor.isVector3D) {
- backendValue.value = Qt.vector3d(colorEditor.color.r,
- colorEditor.color.g,
- colorEditor.color.b)
- } else {
- backendValue.value = colorEditor.color
- }
- }
- }
- }
-
- Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
-
- ControlLabel {
- text: "Hex"
- width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- + StudioTheme.Values.controlGap
- horizontalAlignment: Text.AlignLeft
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: 0
-
- StudioControls.ComboBox {
- id: colorMode
-
- implicitWidth: 3 * StudioTheme.Values.controlGap
- + 4 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- width: implicitWidth
- actionIndicatorVisible: false
- textRole: "text"
- valueRole: "value"
- model: [
- { value: ColorPicker.Mode.HSVA, text: "HSVA" },
- { value: ColorPicker.Mode.RGBA, text: "RGBA" },
- { value: ColorPicker.Mode.HSLA, text: "HSLA" }
- ]
-
- onActivated: colorPicker.mode = colorMode.currentValue
- }
- }
-
- RowLayout {
- id: rgbaRow
- visible: colorPicker.mode === ColorPicker.Mode.RGBA
- Layout.fillWidth: true
- spacing: StudioTheme.Values.controlGap
-
- DoubleSpinBox {
- id: redSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- stepSize: 1
- minimumValue: 0
- maximumValue: 255
- decimals: 0
-
- onValueModified: {
- var tmp = redSpinBox.value / 255.0
- if (colorPicker.red !== tmp && !colorPicker.block) {
- colorPicker.red = tmp
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
-
- DoubleSpinBox {
- id: greenSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- stepSize: 1
- minimumValue: 0
- maximumValue: 255
- decimals: 0
-
- onValueModified: {
- var tmp = greenSpinBox.value / 255.0
- if (colorPicker.green !== tmp && !colorPicker.block) {
- colorPicker.green = tmp
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
-
- DoubleSpinBox {
- id: blueSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- stepSize: 1
- minimumValue: 0
- maximumValue: 255
- decimals: 0
-
- onValueModified: {
- var tmp = blueSpinBox.value / 255.0
- if (colorPicker.blue !== tmp && !colorPicker.block) {
- colorPicker.blue = tmp
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
-
- DoubleSpinBox {
- id: rgbAlphaSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- stepSize: 1
- minimumValue: 0
- maximumValue: 255
- decimals: 0
-
- onValueModified: {
- var tmp = rgbAlphaSpinBox.value / 255.0
- if (colorPicker.alpha !== tmp && !colorPicker.block) {
- colorPicker.alpha = tmp
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
- }
-
- RowLayout {
- id: hslaRow
- visible: colorPicker.mode === ColorPicker.Mode.HSLA
- Layout.fillWidth: true
- spacing: StudioTheme.Values.controlGap
-
- DoubleSpinBox {
- id: hslHueSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- onValueModified: {
- if (colorPicker.hue !== hslHueSpinBox.value
- && !colorPicker.block) {
- colorPicker.hue = hslHueSpinBox.value
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
-
- DoubleSpinBox {
- id: hslSaturationSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- onValueModified: {
- if (colorPicker.saturationHSL !== hslSaturationSpinBox.value
- && !colorPicker.block) {
- colorPicker.saturationHSL = hslSaturationSpinBox.value
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
-
- DoubleSpinBox {
- id: hslLightnessSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- onValueModified: {
- if (colorPicker.lightness !== hslLightnessSpinBox.value
- && !colorPicker.block) {
- colorPicker.lightness = hslLightnessSpinBox.value
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- }
-
- DoubleSpinBox {
- id: hslAlphaSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- onValueModified: {
- if (colorPicker.alpha !== hslAlphaSpinBox.value
- && !colorPicker.block) {
- colorPicker.alpha = hslAlphaSpinBox.value
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
- }
-
- RowLayout {
- id: hsvaRow
- visible: colorPicker.mode === ColorPicker.Mode.HSVA
- Layout.fillWidth: true
- spacing: StudioTheme.Values.controlGap
-
- DoubleSpinBox {
- id: hsvHueSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- onValueModified: {
- if (colorPicker.hue !== hsvHueSpinBox.value
- && !colorPicker.block) {
- colorPicker.hue = hsvHueSpinBox.value
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
-
- DoubleSpinBox {
- id: hsvSaturationSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- onValueModified: {
- if (colorPicker.saturationHSV !== hsvSaturationSpinBox.value
- && !colorPicker.block) {
- colorPicker.saturationHSV = hsvSaturationSpinBox.value
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
-
- DoubleSpinBox {
- id: hsvValueSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- onValueModified: {
- if (colorPicker.value !== hsvValueSpinBox.value
- && !colorPicker.block) {
- colorPicker.value = hsvValueSpinBox.value
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
-
- DoubleSpinBox {
- id: hsvAlphaSpinBox
- width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
- onValueModified: {
- if (colorPicker.alpha !== hsvAlphaSpinBox.value
- && !colorPicker.block) {
- colorPicker.alpha = hsvAlphaSpinBox.value
- colorPicker.invalidateColor()
- colorPicker.updateColor()
- }
- }
- onDragStarted: colorEditorTimer.stop()
- onIndicatorPressed: colorEditorTimer.stop()
- }
- }
- }
- }
-
- Section {
- caption: qsTr("Palette")
- anchors.left: parent.left
- anchors.right: parent.right
- leftPadding: 10
- rightPadding: 10
- bottomPadding: 5
-
- ColorPalette {
- id: colorPalette
- enableSingletonConnection: cePopup.opened
- onSelectedColorChanged: {
- colorPicker.color = colorPalette.selectedColor
- colorEditor.color = colorPalette.selectedColor
- }
- onDialogColorChanged: {
- colorPicker.color = colorPalette.selectedColor
- colorEditor.color = colorPalette.selectedColor
- }
- }
- }
-
- Section {
- id: gradientControls
- caption: qsTr("Gradient Controls")
- anchors.left: parent.left
- anchors.right: parent.right
- visible: !colorEditor.isNotInGradientMode()
- leftPadding: 10
- rightPadding: 10
-
- component ControlsRow: RowLayout {
- property alias propertyName: spinBox.propertyName
- property alias labelText: label.text
- property alias labelTooltip: label.tooltip
- property alias value: spinBox.value
-
- Layout.fillWidth: true
- spacing: 0
-
- Connections {
- target: ceMode
- function onActivated() {
- spinBox.readValue()
- }
- }
-
- Connections {
- target: modelNodeBackend
- function onSelectionChanged() {
- spinBox.readValue()
- }
- }
-
- GradientPropertySpinBox {
- id: spinBox
- implicitWidth: StudioTheme.Values.controlGap
- + 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- width: implicitWidth
- }
-
- Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
-
- ControlLabel {
- id: label
- horizontalAlignment: Text.AlignLeft
- width: StudioTheme.Values.controlGap
- + 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- }
- }
-
- // Default Gradient Controls
- Column {
- id: defaultGradientControls
- spacing: 10
- visible: colorEditor.hasLinearGradient() && !colorEditor.shapeGradients
-
- RowLayout {
- id: defaultGradientOrientation
- Layout.fillWidth: true
- spacing: 0
-
- StudioControls.ComboBox {
- id: gradientOrientation
- implicitWidth: StudioTheme.Values.controlGap
- + 3 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
- width: implicitWidth
- model: [{ value: Gradient.Vertical, text: qsTr("Vertical") },
- { value: Gradient.Horizontal, text: qsTr("Horizontal") }]
- textRole: "text"
- valueRole: "value"
-
- onActivated: {
- gradientLine.model.setGradientOrientation(gradientOrientation.currentValue)
- colorEditor.updateThumbnail()
- }
-
- Component.onCompleted: {
- var orientation = gradientLine.model.readGradientOrientation()
-
- if (orientation === "Horizontal")
- gradientOrientation.currentIndex =
- gradientOrientation.indexOfValue(Gradient.Horizontal)
- else
- gradientOrientation.currentIndex =
- gradientOrientation.indexOfValue(Gradient.Vertical)
- }
- }
-
- Spacer { implicitWidth: StudioTheme.Values.controlLabelGap + 6 }
-
- IconLabel {
- id: iconLabel
- icon: StudioTheme.Constants.orientation
- pixelSize: StudioTheme.Values.myIconFontSize * 1.4
- tooltip: qsTr("Defines the direction of the gradient.")
- }
- }
- }
-
- // Linear Gradient Controls
- Column {
- id: linearGradientControls
- spacing: 10
- visible: colorEditor.hasLinearGradient() && colorEditor.shapeGradients
-
- ControlsRow {
- id: linearGradientX1
- propertyName: "x1"
- labelText: "X1"
- labelTooltip: qsTr("Defines the start point for color interpolation.")
- }
-
- ControlsRow {
- id: linearGradientX2
- propertyName: "x2"
- labelText: "X2"
- labelTooltip: qsTr("Defines the end point for color interpolation.")
- }
-
- ControlsRow {
- id: linearGradientY1
- propertyName: "y1"
- labelText: "Y1"
- labelTooltip: qsTr("Defines the start point for color interpolation.")
- }
-
- ControlsRow {
- id: linearGradientY2
- propertyName: "y2"
- labelText: "Y2"
- labelTooltip: qsTr("Defines the end point for color interpolation.")
- }
- }
-
- // Radial Gradient Controls
- Column {
- id: radialGradientControls
- spacing: 10
- visible: colorEditor.hasRadialGradient()
-
- ControlsRow {
- propertyName: "centerX"
- labelText: "CenterX"
- labelTooltip: qsTr("Defines the center point.")
- }
-
- ControlsRow {
- propertyName: "centerY"
- labelText: "CenterY"
- labelTooltip: qsTr("Defines the center point.")
- }
-
- ControlsRow {
- propertyName: "focalX"
- labelText: "FocalX"
- labelTooltip: qsTr("Defines the focal point.")
- }
-
- ControlsRow {
- propertyName: "focalY"
- labelText: "FocalY"
- labelTooltip: qsTr("Defines the focal point.")
- }
-
- ControlsRow {
- propertyName: "centerRadius"
- labelText: "Center Radius"
- labelTooltip: qsTr("Defines the center radius.")
- }
-
- ControlsRow {
- propertyName: "focalRadius"
- labelText: "Focal Radius"
- labelTooltip: qsTr("Defines the focal radius. Set to 0 for simple radial gradients.")
- }
- }
-
- // Conical Gradient Controls
- Column {
- id: concialGradientControls
- spacing: 10
- visible: colorEditor.hasConicalGradient()
-
- ControlsRow {
- propertyName: "centerX"
- labelText: "CenterX"
- labelTooltip: qsTr("Defines the center point.")
- }
-
- ControlsRow {
- propertyName: "centerY"
- labelText: "CenterY"
- labelTooltip: qsTr("Defines the center point.")
- }
-
- ControlsRow {
- propertyName: "angle"
- labelText: "Angle"
- labelTooltip: qsTr("Defines the start angle for the conical gradient. The value is in degrees (0-360).")
- }
- }
- }
- }
- }
-
- background: Rectangle {
- color: StudioTheme.Values.themeControlBackground
- border.color: StudioTheme.Values.themeInteraction
- border.width: StudioTheme.Values.border
- }
-
- enter: Transition {}
- exit: Transition {}
}
}
- Spacer { implicitWidth: StudioTheme.Values.twoControlColumnGap }
+ Spacer {
+ implicitWidth: StudioTheme.Values.twoControlColumnGap
+ }
LineEdit {
id: hexTextField
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
- enabled: colorEditor.isNotInGradientMode()
+ enabled: cePopup.isNotInGradientMode()
writeValueManually: true
- validator: RegExpValidator { regExp: /#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?/g }
+ validator: RegExpValidator {
+ regExp: /#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?/g
+ }
showTranslateCheckBox: false
backendValue: colorEditor.backendValue
onAccepted: colorEditor.color = colorFromString(hexTextField.text)
onCommitData: {
colorEditor.color = colorFromString(hexTextField.text)
- if (isNotInGradientMode()) {
+ if (cePopup.isNotInGradientMode()) {
if (colorEditor.isVector3D) {
backendValue.value = Qt.vector3d(colorEditor.color.r,
colorEditor.color.g,
@@ -1310,18 +221,10 @@ SecondColumnLayout {
}
}
- Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
-
- ControlLabel {
- text: "Hex"
- horizontalAlignment: Text.AlignLeft
- width: StudioTheme.Values.controlLabelWidth
- + StudioTheme.Values.controlGap
- + StudioTheme.Values.linkControlWidth
+ ExpandingSpacer {
+ id: spacer
}
- ExpandingSpacer {}
-
StudioControls.Menu {
id: contextMenu
@@ -1331,5 +234,9 @@ SecondColumnLayout {
}
}
- Component.onCompleted: colorEditor.determineActiveColorMode()
+ Component.onCompleted: cePopup.determineActiveColorMode()
+
+ onBackendValueChanged: {
+ cePopup.determineActiveColorMode()
+ }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml
new file mode 100644
index 00000000000..6a015a7c08a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml
@@ -0,0 +1,1175 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Shapes 1.15
+import QtQuick.Templates 2.15 as T
+import QtQuickDesignerTheme 1.0
+import StudioTheme 1.0 as StudioTheme
+import StudioControls 1.0 as StudioControls
+import QtQuickDesignerColorPalette 1.0
+
+T.Popup {
+ id: cePopup
+
+ property alias gradientLine: gradientLine
+ property alias popupHexTextField: popupHexTextField
+ property alias gradientPropertyName: cePopup.gradientModel.gradientPropertyName
+ property alias gradientOrientation: gradientOrientation
+
+ property alias gradientModel: gradientModel
+
+ property bool isInValidState: false
+
+ function commitGradientColor() {
+ var hexColor = convertColorToString(colorEditor.color)
+ cePopup.popupHexTextField.text = hexColor
+ cePopup.gradientLine.currentColor = colorEditor.color
+ }
+
+ function isNotInGradientMode() {
+ return ceMode.currentValue === "Solid"
+ }
+
+ function hasLinearGradient() {
+ return ceMode.currentValue === "LinearGradient"
+ }
+
+ function hasConicalGradient() {
+ return ceMode.currentValue === "ConicalGradient"
+ }
+
+ function hasRadialGradient() {
+ return ceMode.currentValue === "RadialGradient"
+ }
+
+ function createModel() {
+ // Build the color editor combobox model
+ ceMode.items.clear()
+ ceMode.items.append({
+ value: "Solid",
+ text: qsTr("Solid"),
+ enabled: true
+ })
+ ceMode.items.append({
+ value: "LinearGradient",
+ text: qsTr("Linear"),
+ enabled: colorEditor.supportGradient
+ })
+ ceMode.items.append({
+ value: "RadialGradient",
+ text: qsTr("Radial"),
+ enabled: colorEditor.supportGradient && colorEditor.shapeGradients
+ })
+ ceMode.items.append({
+ value: "ConicalGradient",
+ text: qsTr("Conical"),
+ enabled: colorEditor.supportGradient && colorEditor.shapeGradients
+ })
+ }
+
+ function determineActiveColorMode() {
+ if (colorEditor.supportGradient && gradientModel.hasGradient) {
+ if (colorEditor.shapeGradients) {
+ switch (gradientModel.gradientTypeName) {
+ case "LinearGradient":
+ ceMode.currentIndex = ceMode.indexOfValue("LinearGradient")
+ break
+ case "RadialGradient":
+ ceMode.currentIndex = ceMode.indexOfValue("RadialGradient")
+ break
+ case "ConicalGradient":
+ ceMode.currentIndex = ceMode.indexOfValue("ConicalGradient")
+ break
+ default:
+ ceMode.currentIndex = ceMode.indexOfValue("LinearGradient")
+ }
+ } else {
+ ceMode.currentIndex = ceMode.indexOfValue("LinearGradient")
+ }
+ colorEditor.color = gradientLine.currentColor
+ } else {
+ ceMode.currentIndex = ceMode.indexOfValue("Solid")
+ colorEditor.color = colorEditor.value
+ }
+
+ colorEditor.originalColor = colorEditor.color
+ }
+
+ function updateThumbnail() {
+ if (!gradientModel.hasGradient)
+ return
+
+ if (!colorEditor.shapeGradients) {
+ var gradientString = "import QtQuick 2.15; Gradient {"
+ var orientation = cePopup.gradientOrientation.currentValue
+ === Gradient.Horizontal ? "Gradient.Horizontal" : "Gradient.Vertical"
+ gradientString += "orientation: " + orientation + ";"
+
+ for (var i = 0; i < gradientModel.count; i++)
+ gradientString += "GradientStop {}"
+
+ gradientString += "}"
+
+ var gradientObject = Qt.createQmlObject(
+ gradientString, colorEditor.gradientThumbnail,
+ "dynamicGradient")
+
+ for (i = 0; i < gradientModel.count; i++) {
+ gradientObject.stops[i].color = gradientModel.getColor(
+ i)
+ gradientObject.stops[i].position = gradientModel.getPosition(
+ i)
+ }
+
+ colorEditor.gradientThumbnail.gradient = gradientObject
+ } else {
+ var gradientStr = "import QtQuick 2.15; import QtQuick.Shapes 1.15; "
+ + gradientModel.gradientTypeName + " {"
+
+ if (gradientModel.gradientTypeName === "LinearGradient") {
+ gradientStr += "x1: 0" + ";x2: " + shape.width + ";y1: 0"
+ + ";y2: " + shape.height + ";"
+ } else if (gradientModel.gradientTypeName === "RadialGradient") {
+ gradientStr += "centerX: " + shape.width * 0.5 + ";centerY: "
+ + shape.height * 0.5 + ";focalX: " + shape.width * 0.5 + ";focalY: "
+ + shape.height * 0.5 + ";centerRadius: " + Math.min(
+ shape.width, shape.height) * 0.5 + ";focalRadius: 0" + ";"
+ } else if (gradientModel.gradientTypeName === "ConicalGradient") {
+ gradientStr += "centerX: " + shape.width * 0.5 + ";centerY: "
+ + shape.height * 0.5 + ";angle: 0" + ";"
+ }
+
+ for (var j = 0; j < gradientModel.count; j++)
+ gradientStr += "GradientStop {}"
+
+ gradientStr += "}"
+
+ var gradientObj = Qt.createQmlObject(
+ gradientStr, colorEditor.shapeGradientThumbnail,
+ "dynamicShapeGradient")
+
+ for (j = 0; j < gradientModel.count; j++) {
+ gradientObj.stops[j].color = gradientModel.getColor(
+ j)
+ gradientObj.stops[j].position = gradientModel.getPosition(
+ j)
+ }
+
+ colorEditor.shapeGradientThumbnail.fillGradient = gradientObj
+ }
+ }
+
+ GradientModel {
+ id: gradientModel
+ anchorBackendProperty: anchorBackend
+ gradientPropertyName: "gradient"
+ }
+
+ WheelHandler {
+ onWheel: function(event) {
+ Controller.mainScrollView.flick(0, event.angleDelta.y * 5)
+ }
+ }
+
+ // This connection is meant to update the popups y-position and the main scrollviews
+ // height as soon as the height of the color picker changes. Initially the height of the
+ // color picker is 0 until its completion is done.
+ Connections {
+ target: colorPicker
+ function onHeightChanged() {
+ cePopup.setPopupY()
+ cePopup.setMainScrollViewHeight()
+ }
+ }
+
+ onOpened: {
+ cePopup.setPopupY()
+ cePopup.setMainScrollViewHeight()
+ }
+ onYChanged: cePopup.setMainScrollViewHeight()
+ onHeightChanged: cePopup.setMainScrollViewHeight()
+
+ function setMainScrollViewHeight() {
+ if (Controller.mainScrollView === null)
+ return
+
+ var mapped = preview.mapToItem(Controller.mainScrollView.contentItem, cePopup.x, cePopup.y)
+ Controller.mainScrollView.temporaryHeight = mapped.y + cePopup.height
+ + StudioTheme.Values.colorEditorPopupMargin
+ }
+
+ function setPopupY() {
+ if (Controller.mainScrollView === null)
+ return
+
+ var tmp = preview.mapToItem(Controller.mainScrollView.contentItem, preview.x, preview.y)
+ cePopup.y = Math.max(-tmp.y + StudioTheme.Values.colorEditorPopupMargin,
+ cePopup.__defaultY)
+ }
+
+ onClosed: Controller.mainScrollView.temporaryHeight = 0
+
+ property real __defaultX: - StudioTheme.Values.colorEditorPopupWidth * 0.5
+ + preview.width * 0.5
+ property real __defaultY: - StudioTheme.Values.colorEditorPopupPadding
+ - (StudioTheme.Values.colorEditorPopupSpacing * 2)
+ - StudioTheme.Values.defaultControlHeight
+ - StudioTheme.Values.colorEditorPopupLineHeight
+ - colorPicker.height * 0.5
+ + preview.height * 0.5
+
+ width: StudioTheme.Values.colorEditorPopupWidth
+ height: colorColumn.height + sectionColumn.height
+ + StudioTheme.Values.colorEditorPopupPadding + 2 // TODO magic number
+
+ padding: StudioTheme.Values.border
+ margins: -1 // If not defined margin will be -1
+
+ closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent
+
+ contentItem: Item {
+ id: todoItem
+
+ property color color
+ property bool supportGradient: false
+
+ Column {
+ id: colorColumn
+
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.margins: StudioTheme.Values.colorEditorPopupPadding
+ spacing: StudioTheme.Values.colorEditorPopupSpacing
+
+ RowLayout {
+ width: parent.width
+ Layout.alignment: Qt.AlignTop
+
+ StudioControls.ComboBox {
+ id: ceMode
+
+ property ListModel items: ListModel {}
+
+ enabled: isBaseState
+ implicitWidth: StudioTheme.Values.colorEditorPopupCmoboBoxWidth
+ width: implicitWidth
+ actionIndicatorVisible: false
+ textRole: "text"
+ valueRole: "value"
+ model: ceMode.items
+ onActivated: {
+ switch (ceMode.currentValue) {
+ case "Solid":
+ gradientLine.deleteGradient()
+ hexTextField.text = colorEditor.color
+ popupHexTextField.text = colorEditor.color
+ colorEditor.resetShapeColor()
+ break
+ case "LinearGradient":
+ colorEditor.resetShapeColor()
+
+ if (colorEditor.shapeGradients)
+ gradientModel.gradientTypeName = "LinearGradient"
+ else
+ gradientModel.gradientTypeName = "Gradient"
+
+ if (gradientModel.hasGradient)
+ gradientLine.updateGradient()
+ else {
+ gradientLine.deleteGradient()
+ gradientLine.addGradient()
+ }
+ break
+ case "RadialGradient":
+ colorEditor.resetShapeColor()
+ gradientModel.gradientTypeName = "RadialGradient"
+
+ if (gradientLine.hasGradient)
+ gradientLine.updateGradient()
+ else {
+ gradientLine.deleteGradient()
+ gradientLine.addGradient()
+ }
+ break
+ case "ConicalGradient":
+ colorEditor.resetShapeColor()
+ gradientModel.gradientTypeName = "ConicalGradient"
+
+ if (gradientModel.hasGradient)
+ gradientLine.updateGradient()
+ else {
+ gradientLine.deleteGradient()
+ gradientLine.addGradient()
+ }
+ break
+ default:
+ console.log("Unknown item selected in color mode ComboBox.")
+ }
+ cePopup.updateThumbnail()
+ }
+
+ ToolTipArea {
+ enabled: !isBaseState
+ anchors.fill: parent
+ tooltip: qsTr("Fill type can only be changed in base state.")
+ z: 10
+ }
+ }
+
+ ExpandingSpacer {}
+
+ IconIndicator {
+ id: transparentIndicator
+ icon: StudioTheme.Constants.transparent
+ pixelSize: StudioTheme.Values.myIconFontSize * 1.4
+ tooltip: qsTr("Transparent")
+ onClicked: {
+ colorPicker.alpha = 0
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+
+ IconIndicator {
+ id: gradientPickerIndicator
+ icon: StudioTheme.Constants.gradient
+ pixelSize: StudioTheme.Values.myIconFontSize * 1.4
+ tooltip: qsTr("Gradient Picker")
+ enabled: colorEditor.supportGradient
+ onClicked: presetList.show()
+
+ GradientPresetList {
+ id: presetList
+ visible: false
+
+ function applyPreset() {
+ if (!gradientModel.hasGradient) {
+ if (colorEditor.shapeGradients)
+ gradientModel.gradientTypeName = "LinearGradient"
+ else
+ gradientModel.gradientTypeName = "Gradient"
+ }
+
+ if (presetList.gradientData.presetType == 0) {
+ gradientLine.setPresetByID(presetList.gradientData.presetID)
+ } else if (presetList.gradientData.presetType == 1) {
+ gradientLine.setPresetByStops(
+ presetList.gradientData.stops,
+ presetList.gradientData.colors,
+ presetList.gradientData.stopsCount)
+ } else {
+ console.log("INVALID GRADIENT TYPE: " +
+ presetList.gradientData.presetType)
+ }
+ }
+
+ onApplied: {
+ if (presetList.gradientData.stopsCount > 0)
+ applyPreset()
+ }
+
+ onSaved: {
+ gradientLine.savePreset()
+ presetList.updatePresets()
+ }
+
+ onAccepted: { // return key
+ if (presetList.gradientData.stopsCount > 0)
+ applyPreset()
+ }
+ }
+ }
+
+ IconIndicator {
+ id: eyeDropperIndicator
+ icon: StudioTheme.Constants.eyeDropper
+ pixelSize: StudioTheme.Values.myIconFontSize * 1.4
+ tooltip: qsTr("Eye Dropper")
+ onClicked: ColorPaletteBackend.eyeDropper()
+ }
+
+ IconIndicator {
+ id: closeIndicator
+ icon: StudioTheme.Constants.colorPopupClose
+ pixelSize: StudioTheme.Values.myIconFontSize * 1.4
+ onClicked: cePopup.close()
+ }
+ }
+
+ ColorLine {
+ id: colorLine
+ width: parent.width
+ currentColor: colorEditor.color
+ visible: cePopup.isNotInGradientMode()
+ }
+
+ GradientLine {
+ id: gradientLine
+
+ width: parent.width
+ visible: !cePopup.isNotInGradientMode()
+
+ model: gradientModel
+
+ onCurrentColorChanged: {
+ if (colorEditor.supportGradient && gradientModel.hasGradient) {
+ colorEditor.color = gradientLine.currentColor
+ colorPicker.color = colorEditor.color
+ }
+ }
+
+ onHasGradientChanged: {
+ if (!colorEditor.supportGradient)
+ return
+
+ cePopup.determineActiveColorMode()
+ }
+
+ onSelectedNodeChanged: {
+ if (colorEditor.supportGradient && gradientModel.hasGradient)
+ colorEditor.originalColor = gradientLine.currentColor
+ }
+
+ onInvalidated: cePopup.updateThumbnail()
+
+ Connections {
+ target: modelNodeBackend
+ function onSelectionToBeChanged() {
+ colorEditorTimer.stop()
+ cePopup.isInValidState = false
+
+ var hexOriginalColor = convertColorToString(colorEditor.originalColor)
+ var hexColor = convertColorToString(colorEditor.color)
+
+ if (hexOriginalColor !== hexColor) {
+ if (colorEditor.color !== "#ffffff"
+ && colorEditor.color !== "#000000"
+ && colorEditor.color !== "#00000000") {
+ colorPalette.addColorToPalette(colorEditor.color)
+ }
+ }
+ }
+ }
+
+ Connections {
+ target: modelNodeBackend
+ function onSelectionChanged() {
+ if (colorEditor.supportGradient && gradientModel.hasGradient) {
+ colorEditor.color = gradientLine.currentColor
+ gradientLine.currentColor = colorEditor.color
+ hexTextField.text = colorEditor.color
+ popupHexTextField.text = colorEditor.color
+ }
+
+ cePopup.isInValidState = true
+ colorEditor.originalColor = colorEditor.color
+ colorPalette.selectedColor = colorEditor.color
+ colorPicker.color = colorEditor.color
+
+ cePopup.createModel()
+ cePopup.determineActiveColorMode()
+ }
+ }
+ }
+
+ ColorPicker {
+ id: colorPicker
+
+ width: parent.width
+ sliderMargins: 4
+
+ onUpdateColor: {
+ colorEditor.color = colorPicker.color
+
+ if (contextMenu.opened)
+ contextMenu.close()
+ }
+ onRightMouseButtonClicked: contextMenu.popup(colorPicker)
+
+ onColorInvalidated: {
+ hslHueSpinBox.value = colorPicker.hue
+ hslSaturationSpinBox.value = colorPicker.saturationHSL
+ hslLightnessSpinBox.value = colorPicker.lightness
+ hslAlphaSpinBox.value = colorPicker.alpha
+
+ redSpinBox.value = (colorPicker.red * 255)
+ greenSpinBox.value = (colorPicker.green * 255)
+ blueSpinBox.value = (colorPicker.blue * 255)
+ rgbAlphaSpinBox.value = (colorPicker.alpha * 255)
+
+ hsvHueSpinBox.value = colorPicker.hue
+ hsvSaturationSpinBox.value = colorPicker.saturationHSV
+ hsvValueSpinBox.value = colorPicker.value
+ hsvAlphaSpinBox.value = colorPicker.alpha
+ }
+ }
+
+ Column {
+ id: colorCompare
+ width: parent.width
+
+ RowLayout {
+ width: parent.width
+ Layout.alignment: Qt.AlignTop
+ spacing: StudioTheme.Values.controlGap
+
+ Label {
+ text: qsTr("Original")
+ width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ + StudioTheme.Values.controlGap
+ }
+
+ Label {
+ text: qsTr("New")
+ width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ + StudioTheme.Values.controlGap
+ }
+ }
+
+ RowLayout {
+ width: parent.width
+ Layout.alignment: Qt.AlignTop
+ spacing: StudioTheme.Values.controlGap
+
+ Rectangle {
+ id: originalColorRectangle
+ color: colorEditor.originalColor
+ height: StudioTheme.Values.height
+ width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ + StudioTheme.Values.controlGap
+ border.width: StudioTheme.Values.border
+ border.color: StudioTheme.Values.themeControlOutline
+
+ Image {
+ anchors.fill: parent
+ source: "images/checkers.png"
+ fillMode: Image.Tile
+ z: -1
+ }
+
+ ToolTipArea {
+ anchors.fill: parent
+ tooltip: originalColorRectangle.color
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onClicked: function(mouse) {
+ if (mouse.button === Qt.LeftButton)
+ colorEditor.color = colorEditor.originalColor
+
+ if (mouse.button === Qt.RightButton) {
+ contextMenuFavorite.currentColor = colorEditor.originalColor
+ contextMenuFavorite.popup()
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: newColorRectangle
+ color: colorEditor.color
+ height: StudioTheme.Values.height
+ width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ + StudioTheme.Values.controlGap
+ border.width: StudioTheme.Values.border
+ border.color: StudioTheme.Values.themeControlOutline
+
+ Image {
+ anchors.fill: parent
+ source: "images/checkers.png"
+ fillMode: Image.Tile
+ z: -1
+ }
+
+ ToolTipArea {
+ anchors.fill: parent
+ tooltip: newColorRectangle.color
+ acceptedButtons: Qt.RightButton
+ onClicked: function(mouse) {
+ if (mouse.button === Qt.RightButton) {
+ contextMenuFavorite.currentColor = colorEditor.color
+ contextMenuFavorite.popup()
+ }
+ }
+ }
+ }
+ }
+
+ StudioControls.Menu {
+ id: contextMenuFavorite
+
+ property color currentColor
+
+ StudioControls.MenuItem {
+ text: qsTr("Add to Favorites")
+ onTriggered: ColorPaletteBackend.addFavoriteColor(
+ contextMenuFavorite.currentColor)
+ }
+ }
+ }
+ }
+
+ Column {
+ id: sectionColumn
+ anchors.topMargin: StudioTheme.Values.colorEditorPopupPadding
+ anchors.top: colorColumn.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ bottomPadding: 10
+
+ Section {
+ caption: qsTr("Color Details")
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ leftPadding: 10
+ rightPadding: 10
+
+ Column {
+ spacing: 10
+
+ RowLayout {
+ Layout.fillWidth: true
+ spacing: 0
+
+ LineEdit {
+ id: popupHexTextField
+ implicitWidth: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ + StudioTheme.Values.controlGap
+ width: implicitWidth
+ writeValueManually: true
+ validator: RegExpValidator { regExp: /#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?/g }
+ showTranslateCheckBox: false
+ showExtendedFunctionButton: false
+ backendValue: colorEditor.backendValue
+
+ onAccepted: colorEditor.color = colorFromString(popupHexTextField.text)
+ onCommitData: {
+ colorEditor.color = colorFromString(popupHexTextField.text)
+ if (cePopup.isNotInGradientMode()) {
+ if (colorEditor.isVector3D) {
+ backendValue.value = Qt.vector3d(colorEditor.color.r,
+ colorEditor.color.g,
+ colorEditor.color.b)
+ } else {
+ backendValue.value = colorEditor.color
+ }
+ }
+ }
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ ControlLabel {
+ text: "Hex"
+ width: 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ + StudioTheme.Values.controlGap
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ spacing: 0
+
+ StudioControls.ComboBox {
+ id: colorMode
+
+ implicitWidth: 3 * StudioTheme.Values.controlGap
+ + 4 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ width: implicitWidth
+ actionIndicatorVisible: false
+ textRole: "text"
+ valueRole: "value"
+ model: [
+ { value: ColorPicker.Mode.HSVA, text: "HSVA" },
+ { value: ColorPicker.Mode.RGBA, text: "RGBA" },
+ { value: ColorPicker.Mode.HSLA, text: "HSLA" }
+ ]
+
+ onActivated: colorPicker.mode = colorMode.currentValue
+ }
+ }
+
+ RowLayout {
+ id: rgbaRow
+ visible: colorPicker.mode === ColorPicker.Mode.RGBA
+ Layout.fillWidth: true
+ spacing: StudioTheme.Values.controlGap
+
+ DoubleSpinBox {
+ id: redSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ stepSize: 1
+ minimumValue: 0
+ maximumValue: 255
+ decimals: 0
+
+ onValueModified: {
+ var tmp = redSpinBox.value / 255.0
+ if (colorPicker.red !== tmp && !colorPicker.block) {
+ colorPicker.red = tmp
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+
+ DoubleSpinBox {
+ id: greenSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ stepSize: 1
+ minimumValue: 0
+ maximumValue: 255
+ decimals: 0
+
+ onValueModified: {
+ var tmp = greenSpinBox.value / 255.0
+ if (colorPicker.green !== tmp && !colorPicker.block) {
+ colorPicker.green = tmp
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+
+ DoubleSpinBox {
+ id: blueSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ stepSize: 1
+ minimumValue: 0
+ maximumValue: 255
+ decimals: 0
+
+ onValueModified: {
+ var tmp = blueSpinBox.value / 255.0
+ if (colorPicker.blue !== tmp && !colorPicker.block) {
+ colorPicker.blue = tmp
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+
+ DoubleSpinBox {
+ id: rgbAlphaSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ stepSize: 1
+ minimumValue: 0
+ maximumValue: 255
+ decimals: 0
+
+ onValueModified: {
+ var tmp = rgbAlphaSpinBox.value / 255.0
+ if (colorPicker.alpha !== tmp && !colorPicker.block) {
+ colorPicker.alpha = tmp
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+ }
+
+ RowLayout {
+ id: hslaRow
+ visible: colorPicker.mode === ColorPicker.Mode.HSLA
+ Layout.fillWidth: true
+ spacing: StudioTheme.Values.controlGap
+
+ DoubleSpinBox {
+ id: hslHueSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ onValueModified: {
+ if (colorPicker.hue !== hslHueSpinBox.value
+ && !colorPicker.block) {
+ colorPicker.hue = hslHueSpinBox.value
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+
+ DoubleSpinBox {
+ id: hslSaturationSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ onValueModified: {
+ if (colorPicker.saturationHSL !== hslSaturationSpinBox.value
+ && !colorPicker.block) {
+ colorPicker.saturationHSL = hslSaturationSpinBox.value
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+
+ DoubleSpinBox {
+ id: hslLightnessSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ onValueModified: {
+ if (colorPicker.lightness !== hslLightnessSpinBox.value
+ && !colorPicker.block) {
+ colorPicker.lightness = hslLightnessSpinBox.value
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ }
+
+ DoubleSpinBox {
+ id: hslAlphaSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ onValueModified: {
+ if (colorPicker.alpha !== hslAlphaSpinBox.value
+ && !colorPicker.block) {
+ colorPicker.alpha = hslAlphaSpinBox.value
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+ }
+
+ RowLayout {
+ id: hsvaRow
+ visible: colorPicker.mode === ColorPicker.Mode.HSVA
+ Layout.fillWidth: true
+ spacing: StudioTheme.Values.controlGap
+
+ DoubleSpinBox {
+ id: hsvHueSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ onValueModified: {
+ if (colorPicker.hue !== hsvHueSpinBox.value
+ && !colorPicker.block) {
+ colorPicker.hue = hsvHueSpinBox.value
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+
+ DoubleSpinBox {
+ id: hsvSaturationSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ onValueModified: {
+ if (colorPicker.saturationHSV !== hsvSaturationSpinBox.value
+ && !colorPicker.block) {
+ colorPicker.saturationHSV = hsvSaturationSpinBox.value
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+
+ DoubleSpinBox {
+ id: hsvValueSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ onValueModified: {
+ if (colorPicker.value !== hsvValueSpinBox.value
+ && !colorPicker.block) {
+ colorPicker.value = hsvValueSpinBox.value
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+
+ DoubleSpinBox {
+ id: hsvAlphaSpinBox
+ width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ onValueModified: {
+ if (colorPicker.alpha !== hsvAlphaSpinBox.value
+ && !colorPicker.block) {
+ colorPicker.alpha = hsvAlphaSpinBox.value
+ colorPicker.invalidateColor()
+ colorPicker.updateColor()
+ }
+ }
+ onDragStarted: colorEditorTimer.stop()
+ onIndicatorPressed: colorEditorTimer.stop()
+ }
+ }
+ }
+ }
+
+ Section {
+ caption: qsTr("Palette")
+ anchors.left: parent.left
+ anchors.right: parent.right
+ leftPadding: 10
+ rightPadding: 10
+ bottomPadding: 5
+
+ ColorPalette {
+ id: colorPalette
+ enableSingletonConnection: cePopup.opened
+ onSelectedColorChanged: {
+ colorPicker.color = colorPalette.selectedColor
+ colorEditor.color = colorPalette.selectedColor
+ }
+ onDialogColorChanged: {
+ colorPicker.color = colorPalette.selectedColor
+ colorEditor.color = colorPalette.selectedColor
+ }
+ }
+ }
+
+ Section {
+ id: gradientControls
+ caption: qsTr("Gradient Controls")
+ anchors.left: parent.left
+ anchors.right: parent.right
+ visible: !cePopup.isNotInGradientMode()
+ leftPadding: 10
+ rightPadding: 10
+
+ component ControlsRow: RowLayout {
+ property alias propertyName: spinBox.propertyName
+ property alias labelText: label.text
+ property alias labelTooltip: label.tooltip
+ property alias value: spinBox.value
+
+ Layout.fillWidth: true
+ spacing: 0
+
+ Connections {
+ target: ceMode
+ function onActivated() {
+ spinBox.readValue()
+ }
+ }
+
+ Connections {
+ target: modelNodeBackend
+ function onSelectionChanged() {
+ spinBox.readValue()
+ }
+ }
+
+ GradientPropertySpinBox {
+ id: spinBox
+ implicitWidth: StudioTheme.Values.controlGap
+ + 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ width: implicitWidth
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ ControlLabel {
+ id: label
+ horizontalAlignment: Text.AlignLeft
+ width: StudioTheme.Values.controlGap
+ + 2 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ }
+ }
+
+ // Default Gradient Controls
+ Column {
+ id: defaultGradientControls
+ spacing: 10
+ visible: cePopup.hasLinearGradient() && !colorEditor.shapeGradients
+
+ RowLayout {
+ id: defaultGradientOrientation
+ Layout.fillWidth: true
+ spacing: 0
+
+ StudioControls.ComboBox {
+ id: gradientOrientation
+ implicitWidth: StudioTheme.Values.controlGap
+ + 3 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
+ width: implicitWidth
+ model: [{ value: Gradient.Vertical, text: qsTr("Vertical") },
+ { value: Gradient.Horizontal, text: qsTr("Horizontal") }]
+ textRole: "text"
+ valueRole: "value"
+
+ onActivated: {
+ gradientLine.model.setGradientOrientation(gradientOrientation.currentValue)
+ cePopup.updateThumbnail()
+ }
+
+ Component.onCompleted: {
+ var orientation = gradientLine.model.readGradientOrientation()
+
+ if (orientation === "Horizontal")
+ gradientOrientation.currentIndex =
+ gradientOrientation.indexOfValue(Gradient.Horizontal)
+ else
+ gradientOrientation.currentIndex =
+ gradientOrientation.indexOfValue(Gradient.Vertical)
+ }
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap + 6 }
+
+ IconLabel {
+ id: iconLabel
+ icon: StudioTheme.Constants.orientation
+ pixelSize: StudioTheme.Values.myIconFontSize * 1.4
+ tooltip: qsTr("Defines the direction of the gradient.")
+ }
+ }
+ }
+
+ // Linear Gradient Controls
+ Column {
+ id: linearGradientControls
+ spacing: 10
+ visible: cePopup.hasLinearGradient() && colorEditor.shapeGradients
+
+ ControlsRow {
+ id: linearGradientX1
+ propertyName: "x1"
+ labelText: "X1"
+ labelTooltip: qsTr("Defines the start point for color interpolation.")
+ }
+
+ ControlsRow {
+ id: linearGradientX2
+ propertyName: "x2"
+ labelText: "X2"
+ labelTooltip: qsTr("Defines the end point for color interpolation.")
+ }
+
+ ControlsRow {
+ id: linearGradientY1
+ propertyName: "y1"
+ labelText: "Y1"
+ labelTooltip: qsTr("Defines the start point for color interpolation.")
+ }
+
+ ControlsRow {
+ id: linearGradientY2
+ propertyName: "y2"
+ labelText: "Y2"
+ labelTooltip: qsTr("Defines the end point for color interpolation.")
+ }
+ }
+
+ // Radial Gradient Controls
+ Column {
+ id: radialGradientControls
+ spacing: 10
+ visible: cePopup.hasRadialGradient()
+
+ ControlsRow {
+ propertyName: "centerX"
+ labelText: "CenterX"
+ labelTooltip: qsTr("Defines the center point.")
+ }
+
+ ControlsRow {
+ propertyName: "centerY"
+ labelText: "CenterY"
+ labelTooltip: qsTr("Defines the center point.")
+ }
+
+ ControlsRow {
+ propertyName: "focalX"
+ labelText: "FocalX"
+ labelTooltip: qsTr("Defines the focal point.")
+ }
+
+ ControlsRow {
+ propertyName: "focalY"
+ labelText: "FocalY"
+ labelTooltip: qsTr("Defines the focal point.")
+ }
+
+ ControlsRow {
+ propertyName: "centerRadius"
+ labelText: "Center Radius"
+ labelTooltip: qsTr("Defines the center radius.")
+ }
+
+ ControlsRow {
+ propertyName: "focalRadius"
+ labelText: "Focal Radius"
+ labelTooltip: qsTr("Defines the focal radius. Set to 0 for simple radial gradients.")
+ }
+ }
+
+ // Conical Gradient Controls
+ Column {
+ id: concialGradientControls
+ spacing: 10
+ visible: cePopup.hasConicalGradient()
+
+ ControlsRow {
+ propertyName: "centerX"
+ labelText: "CenterX"
+ labelTooltip: qsTr("Defines the center point.")
+ }
+
+ ControlsRow {
+ propertyName: "centerY"
+ labelText: "CenterY"
+ labelTooltip: qsTr("Defines the center point.")
+ }
+
+ ControlsRow {
+ propertyName: "angle"
+ labelText: "Angle"
+ labelTooltip: qsTr("Defines the start angle for the conical gradient. The value is in degrees (0-360).")
+ }
+ }
+ }
+
+
+ }
+ } //content
+
+ background: Rectangle {
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeInteraction
+ border.width: StudioTheme.Values.border
+ }
+
+ enter: Transition {}
+ exit: Transition {}
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml
index c29d8d0689c..da701b8d496 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml
@@ -34,12 +34,10 @@ Item {
height: StudioTheme.Values.colorEditorPopupLineHeight
property color currentColor
- property alias model: repeater.model
+ property GradientModel model
+ property GradientModel gradientModel: root.model
- property bool hasGradient: gradientModel.hasGradient
-
- property alias gradientPropertyName: gradientModel.gradientPropertyName
- property alias gradientTypeName: gradientModel.gradientTypeName
+ property bool hasGradient: root.model.hasGradient
signal selectedNodeChanged
signal invalidated
@@ -49,38 +47,38 @@ Item {
}
onCurrentColorChanged: {
- gradientModel.setColor(colorLine.selectedIndex, root.currentColor)
+ root.gradientModel.setColor(colorLine.selectedIndex, root.currentColor)
colorLine.invalidate()
}
function addGradient() {
- gradientModel.addGradient()
+ root.gradientModel.addGradient()
colorLine.invalidate()
colorLine.select(0)
}
function deleteGradient() {
- gradientModel.deleteGradient()
+ root.gradientModel.deleteGradient()
}
function setPresetByID(presetID) {
- gradientModel.setPresetByID(presetID)
+ root.gradientModel.setPresetByID(presetID)
colorLine.invalidate()
colorLine.select(0)
}
function setPresetByStops(stopsPositions, stopsColors, stopsCount) {
- gradientModel.setPresetByStops(stopsPositions, stopsColors, stopsCount)
+ root.gradientModel.setPresetByStops(stopsPositions, stopsColors, stopsCount)
colorLine.invalidate()
colorLine.select(0)
}
function savePreset() {
- gradientModel.savePreset()
+ root.gradientModel.savePreset()
}
function updateGradient() {
- gradientModel.updateGradient()
+ root.gradientModel.updateGradient()
}
Connections {
@@ -109,9 +107,9 @@ Item {
repeater.itemAt(index).item.highlighted = true
colorLine.selectedIndex = index
- gradientModel.lock()
+ root.gradientModel.lock()
root.currentColor = repeater.itemAt(index).item.color
- gradientModel.unlock()
+ root.gradientModel.unlock()
root.selectedNodeChanged()
}
@@ -119,19 +117,19 @@ Item {
function invalidate() {
var gradientString = "import QtQuick 2.15; Gradient { orientation: Gradient.Horizontal;"
- for (var i = 0; i < gradientModel.count; i++) {
+ for (var i = 0; i < root.gradientModel.count; i++) {
gradientString += "GradientStop {}"
}
gradientString += "}"
var gradientObject = Qt.createQmlObject(gradientString, gradientRectangle, "test")
- for (i = 0; i < gradientModel.count; i++) {
+ for (i = 0; i < root.gradientModel.count; i++) {
if (repeater.itemAt(i) !== null)
repeater.itemAt(i).item.y = 20 // fixes corner case for dragging overlapped items
- gradientObject.stops[i].color = gradientModel.getColor(i)
- gradientObject.stops[i].position = gradientModel.getPosition(i)
+ gradientObject.stops[i].color = root.gradientModel.getColor(i)
+ gradientObject.stops[i].position = root.gradientModel.getPosition(i)
}
gradientRectangle.gradient = gradientObject
@@ -150,7 +148,7 @@ Item {
onClicked: {
var currentPosition = mouseX / colorLine.effectiveWidth
- var newIndex = gradientModel.addStop(currentPosition, root.currentColor)
+ var newIndex = root.gradientModel.addStop(currentPosition, root.currentColor)
if (newIndex > 0)
colorLine.select(newIndex)
@@ -165,11 +163,7 @@ Item {
Repeater {
id: repeater
- model: GradientModel {
- id: gradientModel
- anchorBackendProperty: anchorBackend
- gradientPropertyName: "gradient"
- }
+ model: root.gradientModel
delegate: Loader {
id: loader
@@ -364,14 +358,14 @@ Item {
onReleased: {
if (drag.active) {
- gradientModel.setPosition(colorLine.selectedIndex,
+ root.gradientModel.setPosition(colorLine.selectedIndex,
gradientStopHandle.currentGradiantStopPosition())
gradientStopHandle.refreshToolTip(false)
if (parent.y < 10) {
if (!gradientStopHandle.readOnly) {
colorLine.select(index - 1)
- gradientModel.removeStop(index)
+ root.gradientModel.removeStop(index)
}
}
parent.y = 20
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
index dcd4733134a..9593213e347 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
@@ -51,13 +51,6 @@ Rectangle {
: mouseArea.containsMouse ? hoverColor
: normalColor
- Behavior on color {
- ColorAnimation {
- duration: 300
- easing.type: Easing.OutQuad
- }
- }
-
Text {
id: icon
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SearchBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SearchBox.qml
index 8f0079249db..c50d2e1d68e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SearchBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SearchBox.qml
@@ -136,7 +136,7 @@ Item {
},
State {
name: "hover"
- when: searchFilterText.hovered && !searchFilterText.activeFocus
+ when: root.enabled && searchFilterText.hovered && !searchFilterText.activeFocus
PropertyChanges {
target: textFieldBackground
color: StudioTheme.Values.themeControlBackgroundHover
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
index ecb4936bd7d..9c3f3ec43cb 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
@@ -47,6 +47,9 @@ Row {
// Current item
property string absoluteFilePath: ""
+ property alias comboBox: comboBox
+ property alias spacer: spacer
+
FileResourcesModel {
id: fileModel
modelNodeBackendProperty: modelNodeBackend
@@ -501,7 +504,9 @@ Row {
}
}
- Spacer { implicitWidth: StudioTheme.Values.twoControlColumnGap }
+ Spacer { id: spacer
+ implicitWidth: StudioTheme.Values.twoControlColumnGap
+ }
IconIndicator {
icon: StudioTheme.Constants.addFile
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/FilterComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/FilterComboBox.qml
index c41fe060e50..da0850fb14a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/FilterComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/FilterComboBox.qml
@@ -65,7 +65,8 @@ Item {
property alias actionIndicator: actionIndicator
// This property is used to indicate the global hover state
- property bool hover: actionIndicator.hover || textInput.hover || checkIndicator.hover
+ property bool hover: (actionIndicator.hover || textInput.hover || checkIndicator.hover)
+ && root.enabled
property alias edit: textInput.edit
property alias open: popup.visible
@@ -536,6 +537,7 @@ Item {
PropertyChanges {
target: textInputBackground
color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
}
PropertyChanges {
target: textInput
@@ -742,7 +744,7 @@ Item {
anchors.fill: parent
enabled: popup.visible && popupMouseArea.active
- hoverEnabled: true
+ hoverEnabled: popupMouseArea.enabled
onPositionChanged: { popupMouseArea.active = false }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml
index 5972e56e04c..46b3679198c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml
@@ -122,72 +122,74 @@ QtObject {
readonly property string listView: "\u0075"
readonly property string lockOff: "\u0076"
readonly property string lockOn: "\u0077"
- readonly property string mergeCells: "\u0078"
- readonly property string minus: "\u0079"
- readonly property string mirror: "\u007A"
- readonly property string newMaterial: "\u007B"
- readonly property string openMaterialBrowser: "\u007C"
- readonly property string orientation: "\u007D"
- readonly property string paddingEdge: "\u007E"
- readonly property string paddingFrame: "\u007F"
- readonly property string pasteStyle: "\u0080"
- readonly property string pause: "\u0081"
- readonly property string pin: "\u0082"
- readonly property string play: "\u0083"
- readonly property string plus: "\u0084"
- readonly property string promote: "\u0085"
- readonly property string readOnly: "\u0086"
- readonly property string redo: "\u0087"
- readonly property string rotationFill: "\u0088"
- readonly property string rotationOutline: "\u0089"
- readonly property string search: "\u008A"
- readonly property string sectionToggle: "\u008B"
- readonly property string splitColumns: "\u008C"
- readonly property string splitRows: "\u008D"
- readonly property string startNode: "\u008E"
- readonly property string testIcon: "\u008F"
- readonly property string textAlignBottom: "\u0090"
- readonly property string textAlignCenter: "\u0091"
- readonly property string textAlignJustified: "\u0092"
- readonly property string textAlignLeft: "\u0093"
- readonly property string textAlignMiddle: "\u0094"
- readonly property string textAlignRight: "\u0095"
- readonly property string textAlignTop: "\u0096"
- readonly property string textBulletList: "\u0097"
- readonly property string textFullJustification: "\u0098"
- readonly property string textNumberedList: "\u0099"
- readonly property string tickIcon: "\u009A"
- readonly property string translationCreateFiles: "\u009B"
- readonly property string translationCreateReport: "\u009D"
- readonly property string translationExport: "\u009E"
- readonly property string translationImport: "\u009F"
- readonly property string translationSelectLanguages: "\u00A0"
- readonly property string translationTest: "\u00A1"
- readonly property string transparent: "\u00A2"
- readonly property string triState: "\u00A3"
- readonly property string triangleArcA: "\u00A4"
- readonly property string triangleArcB: "\u00A5"
- readonly property string triangleCornerA: "\u00A6"
- readonly property string triangleCornerB: "\u00A7"
- readonly property string unLinked: "\u00A8"
- readonly property string undo: "\u00A9"
- readonly property string unpin: "\u00AA"
- readonly property string upDownIcon: "\u00AB"
- readonly property string upDownSquare2: "\u00AC"
- readonly property string visibilityOff: "\u00AE"
- readonly property string visibilityOn: "\u00AF"
- readonly property string wildcard: "\u00B0"
- readonly property string wizardsAutomotive: "\u00B1"
- readonly property string wizardsDesktop: "\u00B2"
- readonly property string wizardsGeneric: "\u00B3"
- readonly property string wizardsMcuEmpty: "\u00B4"
- readonly property string wizardsMcuGraph: "\u00B5"
- readonly property string wizardsMobile: "\u00B6"
- readonly property string wizardsUnknown: "\u00B7"
- readonly property string zoomAll: "\u00B8"
- readonly property string zoomIn: "\u00B9"
- readonly property string zoomOut: "\u00BA"
- readonly property string zoomSelection: "\u00BB"
+ readonly property string materialPreviewEnvironment: "\u0078"
+ readonly property string materialPreviewModel: "\u0079"
+ readonly property string mergeCells: "\u007A"
+ readonly property string minus: "\u007B"
+ readonly property string mirror: "\u007C"
+ readonly property string newMaterial: "\u007D"
+ readonly property string openMaterialBrowser: "\u007E"
+ readonly property string orientation: "\u007F"
+ readonly property string paddingEdge: "\u0080"
+ readonly property string paddingFrame: "\u0081"
+ readonly property string pasteStyle: "\u0082"
+ readonly property string pause: "\u0083"
+ readonly property string pin: "\u0084"
+ readonly property string play: "\u0085"
+ readonly property string plus: "\u0086"
+ readonly property string promote: "\u0087"
+ readonly property string readOnly: "\u0088"
+ readonly property string redo: "\u0089"
+ readonly property string rotationFill: "\u008A"
+ readonly property string rotationOutline: "\u008B"
+ readonly property string search: "\u008C"
+ readonly property string sectionToggle: "\u008D"
+ readonly property string splitColumns: "\u008E"
+ readonly property string splitRows: "\u008F"
+ readonly property string startNode: "\u0090"
+ readonly property string testIcon: "\u0091"
+ readonly property string textAlignBottom: "\u0092"
+ readonly property string textAlignCenter: "\u0093"
+ readonly property string textAlignJustified: "\u0094"
+ readonly property string textAlignLeft: "\u0095"
+ readonly property string textAlignMiddle: "\u0096"
+ readonly property string textAlignRight: "\u0097"
+ readonly property string textAlignTop: "\u0098"
+ readonly property string textBulletList: "\u0099"
+ readonly property string textFullJustification: "\u009A"
+ readonly property string textNumberedList: "\u009B"
+ readonly property string tickIcon: "\u009D"
+ readonly property string translationCreateFiles: "\u009E"
+ readonly property string translationCreateReport: "\u009F"
+ readonly property string translationExport: "\u00A0"
+ readonly property string translationImport: "\u00A1"
+ readonly property string translationSelectLanguages: "\u00A2"
+ readonly property string translationTest: "\u00A3"
+ readonly property string transparent: "\u00A4"
+ readonly property string triState: "\u00A5"
+ readonly property string triangleArcA: "\u00A6"
+ readonly property string triangleArcB: "\u00A7"
+ readonly property string triangleCornerA: "\u00A8"
+ readonly property string triangleCornerB: "\u00A9"
+ readonly property string unLinked: "\u00AA"
+ readonly property string undo: "\u00AB"
+ readonly property string unpin: "\u00AC"
+ readonly property string upDownIcon: "\u00AE"
+ readonly property string upDownSquare2: "\u00AF"
+ readonly property string visibilityOff: "\u00B0"
+ readonly property string visibilityOn: "\u00B1"
+ readonly property string wildcard: "\u00B2"
+ readonly property string wizardsAutomotive: "\u00B3"
+ readonly property string wizardsDesktop: "\u00B4"
+ readonly property string wizardsGeneric: "\u00B5"
+ readonly property string wizardsMcuEmpty: "\u00B6"
+ readonly property string wizardsMcuGraph: "\u00B7"
+ readonly property string wizardsMobile: "\u00B8"
+ readonly property string wizardsUnknown: "\u00B9"
+ readonly property string zoomAll: "\u00BA"
+ readonly property string zoomIn: "\u00BB"
+ readonly property string zoomOut: "\u00BC"
+ readonly property string zoomSelection: "\u00BD"
readonly property font iconFont: Qt.font({
"family": controlIcons.name,
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
index cefd1d7d866..934c22110e5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
Binary files differ
diff --git a/share/qtcreator/qmldesigner/qt4mcu/qul-22.qml b/share/qtcreator/qmldesigner/qt4mcu/qul-22.qml
index a539a0aeb25..93682263778 100644
--- a/share/qtcreator/qmldesigner/qt4mcu/qul-22.qml
+++ b/share/qtcreator/qmldesigner/qt4mcu/qul-22.qml
@@ -165,7 +165,7 @@ VersionData {
}
QtQuick.Controls.AbstractButton {
- bannedProperties: ["display", "autoExclusive"]
+ bannedProperties: ["display", "autoExclusive", "icon"]
}
QtQuick.Controls.ProgressBar {
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
index 3e7ef11beb7..6912200c14b 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
@@ -318,8 +318,7 @@
},
{
"source": "Screen01.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen01.ui.qml",
- "openInEditor": true
+ "target": "%{ProjectDirectory}/content/Screen01.ui.qml"
},
{
"source": "../common/fonts.txt",
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl
index 6b2195d6d1c..2dc38e566a2 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl
@@ -59,6 +59,11 @@ Project {
directory: "asset_imports"
}
+ Files {
+ filter: "*.qml"
+ directory: "asset_imports"
+ }
+
Environment {
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk
index fba5f4a822f..4ed1c599c3c 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk
@@ -1,48 +1 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" containers="1">
- <container floating="false">
- <splitter orientation="Horizontal" count="3">
- <splitter orientation="Vertical" count="2">
- <area tabs="4" current="Components">
- <widget name="Components" closed="false"/>
- <widget name="Assets" closed="false"/>
- <widget name="Navigator" closed="false"/>
- <widget name="DebugView" closed="false"/>
- </area>
- <area tabs="3" current="Projects">
- <widget name="Projects" closed="false"/>
- <widget name="FileSystem" closed="false"/>
- <widget name="OpenDocuments" closed="false"/>
- </area>
- <sizes>653 436</sizes>
- </splitter>
- <splitter orientation="Vertical" count="4">
- <area tabs="2" current="FormEditor">
- <widget name="FormEditor" closed="false"/>
- <widget name="TextEditor" closed="false"/>
- </area>
- <area tabs="1" current="Editor3D">
- <widget name="Editor3D" closed="false"/>
- </area>
- <area tabs="2" current="Timelines">
- <widget name="StatesEditor" closed="true"/>
- <widget name="Timelines" closed="true"/>
- </area>
- <area tabs="1" current="OutputPane">
- <widget name="OutputPane" closed="true"/>
- </area>
- <sizes>600 600 0 0</sizes>
- </splitter>
- <splitter orientation="Vertical" count="2">
- <area tabs="1" current="Properties">
- <widget name="Properties" closed="false"/>
- </area>
- <area tabs="1" current="ConnectionView">
- <widget name="ConnectionView" closed="false"/>
- </area>
- <sizes>762 327</sizes>
- </splitter>
- <sizes>376 1127 376</sizes>
- </splitter>
- </container>
-</QtAdvancedDockingSystem>
+<?xml version="1.0" encoding="UTF-8"?><QtAdvancedDockingSystem version="1" userVersion="0" containers="1"><container floating="false"><splitter orientation="Horizontal" count="3"><splitter orientation="Vertical" count="3"><area tabs="2" current="Navigator"><widget name="Navigator" closed="false"/><widget name="DebugView" closed="false"/></area><area tabs="2" current="Assets"><widget name="Assets" closed="false"/><widget name="Components" closed="false"/></area><area tabs="3" current="Projects"><widget name="Projects" closed="false"/><widget name="FileSystem" closed="false"/><widget name="OpenDocuments" closed="false"/></area><sizes>355 428 404</sizes></splitter><splitter orientation="Vertical" count="4"><splitter orientation="Horizontal" count="2"><area tabs="2" current="FormEditor"><widget name="FormEditor" closed="false"/><widget name="TextEditor" closed="false"/></area><area tabs="1" current="MaterialEditor"><widget name="MaterialEditor" closed="false"/></area><sizes>678 678</sizes></splitter><splitter orientation="Horizontal" count="2"><area tabs="1" current="Editor3D"><widget name="Editor3D" closed="false"/></area><area tabs="1" current="MaterialBrowser"><widget name="MaterialBrowser" closed="false"/></area><sizes>678 678</sizes></splitter><area tabs="2" current="Timelines"><widget name="StatesEditor" closed="true"/><widget name="Timelines" closed="true"/></area><area tabs="1" current="OutputPane"><widget name="OutputPane" closed="true"/></area><sizes>641 547 0 0</sizes></splitter><splitter orientation="Vertical" count="2"><area tabs="1" current="Properties"><widget name="Properties" closed="false"/></area><area tabs="1" current="ConnectionView"><widget name="ConnectionView" closed="false"/></area><sizes>831 357</sizes></splitter><sizes>453 1357 453</sizes></splitter></container></QtAdvancedDockingSystem>
diff --git a/share/qtcreator/styles/creator-dark.xml b/share/qtcreator/styles/creator-dark.xml
index b86483f30f7..dbb18ae47c8 100644
--- a/share/qtcreator/styles/creator-dark.xml
+++ b/share/qtcreator/styles/creator-dark.xml
@@ -7,6 +7,7 @@
<style name="SearchResult" background="#8a7f2c"/>
<style name="SearchResultAlt1" foreground="#aaaaff" background="#363655"/>
<style name="SearchResultAlt2" foreground="#ffaaaa" background="#553636"/>
+ <style name="SearchResultContainingFunction" foreground="#d6cf9a" background="#2e2f30"/>
<style name="SearchScope" background="#8a602c"/>
<style name="Parentheses" foreground="#bec0c2" background="#1d545c"/>
<style name="ParenthesesMismatch" background="#ff6aad"/>
@@ -26,6 +27,7 @@
<style name="Static" foreground="#66a334" italic="true"/>
<style name="VirtualMethod" italic="true"/>
<style name="Function"/>
+ <style name="Macro"/>
<style name="Keyword" foreground="#45c6d6" italic="true"/>
<style name="PrimitiveType" foreground="#d69aa7"/>
<style name="Punctuation"/>
diff --git a/share/qtcreator/styles/dark.xml b/share/qtcreator/styles/dark.xml
index b7edf68469e..1e169a69b02 100644
--- a/share/qtcreator/styles/dark.xml
+++ b/share/qtcreator/styles/dark.xml
@@ -15,6 +15,7 @@
<style name="Doxygen.Tag" foreground="#00a0a0"/>
<style name="Field"/>
<style name="Function"/>
+ <style name="Macro"/>
<style name="Global"/>
<style name="Keyword" foreground="#ffff55"/>
<style name="PrimitiveType" foreground="#ffff55"/>
@@ -36,6 +37,7 @@
<style name="SearchResult" background="#555500"/>
<style name="SearchResultAlt1" foreground="#aaaaff" background="#363655"/>
<style name="SearchResultAlt2" foreground="#ffaaaa" background="#553636"/>
+ <style name="SearchResultContainingFunction" foreground="#aaaaaa" background="#000000"/>
<style name="SearchScope" background="#222200"/>
<style name="Selection" foreground="#000000" background="#aaaaaa"/>
<style name="Static" foreground="#55ff55" italic="true"/>
diff --git a/share/qtcreator/styles/default_classic.xml b/share/qtcreator/styles/default_classic.xml
index 04939c70329..08d9fd0e812 100644
--- a/share/qtcreator/styles/default_classic.xml
+++ b/share/qtcreator/styles/default_classic.xml
@@ -23,6 +23,7 @@
<style name="Static" foreground="#800080"/>
<style name="VirtualMethod" foreground="#000000" background="#ffffff" italic="true"/>
<style name="Function" background="#ffffff"/>
+ <style name="Macro" background="#ffffff"/>
<style name="Keyword" foreground="#808000"/>
<style name="PrimitiveType" foreground="#808000"/>
<style name="Punctuation"/>
diff --git a/share/qtcreator/styles/grayscale.xml b/share/qtcreator/styles/grayscale.xml
index 09a09f1ba93..8d7cbfb6cd2 100644
--- a/share/qtcreator/styles/grayscale.xml
+++ b/share/qtcreator/styles/grayscale.xml
@@ -15,6 +15,7 @@
<style name="Doxygen.Tag" foreground="#808080" italic="true"/>
<style name="Field"/>
<style name="Function"/>
+ <style name="Macro"/>
<style name="Keyword" bold="true"/>
<style name="PrimitiveType" bold="true"/>
<style name="Label"/>
diff --git a/share/qtcreator/styles/inkpot.xml b/share/qtcreator/styles/inkpot.xml
index 780be74d46d..761b931deda 100644
--- a/share/qtcreator/styles/inkpot.xml
+++ b/share/qtcreator/styles/inkpot.xml
@@ -20,6 +20,7 @@
<style name="Doxygen.Tag" foreground="#4e5ab3"/>
<style name="Field" bold="true"/>
<style name="Function"/>
+ <style name="Macro"/>
<style name="Global"/>
<style name="Keyword" foreground="#808bed"/>
<style name="PrimitiveType" foreground="#808bed"/>
@@ -43,6 +44,7 @@
<style name="SearchResult" foreground="#000000" background="#ffef0b"/>
<style name="SearchResultAlt1" foreground="#000000" background="#6464ff"/>
<style name="SearchResultAlt2" foreground="#000000" background="#ff6464"/>
+ <style name="SearchResultContainingFunction" foreground="#cfbfad" background="#1e1e27"/>
<style name="SearchScope" foreground="#000000" background="#f8fafc"/>
<style name="Selection" foreground="#ffffff" background="#4e4e8f"/>
<style name="Static" foreground="#cb6ecb"/>
diff --git a/share/qtcreator/styles/intellij.xml b/share/qtcreator/styles/intellij.xml
index ee579f0e36d..aedb2df64f9 100644
--- a/share/qtcreator/styles/intellij.xml
+++ b/share/qtcreator/styles/intellij.xml
@@ -9,6 +9,7 @@
<style name="Doxygen.Tag" foreground="#808080" bold="true" italic="true"/>
<style name="Field" foreground="#660e7a" bold="true"/>
<style name="Function" foreground="#000000"/>
+ <style name="Macro" foreground="#000000"/>
<style name="Keyword" foreground="#000080" bold="true"/>
<style name="PrimitiveType" foreground="#000080" bold="true"/>
<style name="Label" foreground="#800000" bold="true"/>
diff --git a/share/qtcreator/styles/modnokai_night_shift_v2.xml b/share/qtcreator/styles/modnokai_night_shift_v2.xml
index 316b0293df5..1b062ae7dfa 100644
--- a/share/qtcreator/styles/modnokai_night_shift_v2.xml
+++ b/share/qtcreator/styles/modnokai_night_shift_v2.xml
@@ -16,6 +16,7 @@
<style name="SearchResult" background="#555500"/>
<style name="SearchResultAlt1" foreground="#aaaaff" background="#363655"/>
<style name="SearchResultAlt2" foreground="#ffaaaa" background="#553636"/>
+ <style name="SearchResultContainingFunction" foreground="#ffffff" background="#000000"/>
<style name="SearchScope" background="#222200"/>
<style name="Parentheses" foreground="#ffffff" background="#11404c"/>
<style name="CurrentLine" background="#373737"/>
@@ -32,6 +33,7 @@
<style name="Static" foreground="#55ff55" italic="true"/>
<style name="VirtualMethod" italic="true"/>
<style name="Function"/>
+ <style name="Macro"/>
<style name="Keyword" foreground="#78d7ec" italic="true"/>
<style name="PrimitiveType" foreground="#ff8080"/>
<style name="Punctuation"/>
diff --git a/share/qtcreator/styles/solarized-dark.xml b/share/qtcreator/styles/solarized-dark.xml
index 6930af67e06..1a6c5a53ab4 100644
--- a/share/qtcreator/styles/solarized-dark.xml
+++ b/share/qtcreator/styles/solarized-dark.xml
@@ -13,6 +13,7 @@
<style name="SearchResult" background="#073642"/>
<style name="SearchResultAlt1" foreground="#aaaaff" background="#363655"/>
<style name="SearchResultAlt2" foreground="#ffaaaa" background="#553636"/>
+ <style name="SearchResultContainingFunction" foreground="#839496" background="#002b36"/>
<style name="SearchScope" background="#073642"/>
<style name="Parentheses" foreground="#dc322f" background="#586e75" bold="true"/>
<style name="ParenthesesMismatch" foreground="#fdff2c" background="#d33682" bold="true"/>
@@ -32,6 +33,7 @@
<style name="Static" foreground="#b58900" italic="true"/>
<style name="VirtualMethod" foreground="#839496" italic="true"/>
<style name="Function" foreground="#839496"/>
+ <style name="Macro" foreground="#839496"/>
<style name="Keyword" foreground="#709d06"/>
<style name="PrimitiveType" foreground="#808000"/>
<style name="Punctuation"/>
diff --git a/share/qtcreator/styles/solarized-light.xml b/share/qtcreator/styles/solarized-light.xml
index 221fc8c211f..ede48e7d0bc 100644
--- a/share/qtcreator/styles/solarized-light.xml
+++ b/share/qtcreator/styles/solarized-light.xml
@@ -13,6 +13,7 @@
<style name="SearchResult" background="#eee8d5"/>
<style name="SearchResultAlt1" background="#93a1a1"/>
<style name="SearchResultAlt2" background="#e0dbcb"/>
+ <style name="SearchResultContainingFunction" foreground="#657b83" background="#fdf6e3"/>
<style name="SearchScope" background="#073642"/>
<style name="Parentheses" foreground="#dc322f" background="#93a1a1" bold="true"/>
<style name="ParenthesesMismatch" foreground="#ffff00" background="#ff00ff" bold="true"/>
@@ -32,6 +33,7 @@
<style name="Static" foreground="#b58900" italic="true"/>
<style name="VirtualMethod" foreground="#657b83" italic="true"/>
<style name="Function" foreground="#657b83"/>
+ <style name="Macro" foreground="#657b83"/>
<style name="Keyword" foreground="#709d06"/>
<style name="PrimitiveType" foreground="#808000"/>
<style name="Punctuation"/>
diff --git a/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl b/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl
index 5d3da10b700..e87c3dee134 100644
--- a/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl
+++ b/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.15
import QtTest 1.0
TestCase {
diff --git a/share/qtcreator/templates/wizards/classes/python/wizard.json b/share/qtcreator/templates/wizards/classes/python/wizard.json
index 7a86aa341e5..d42d8f0ab52 100644
--- a/share/qtcreator/templates/wizards/classes/python/wizard.json
+++ b/share/qtcreator/templates/wizards/classes/python/wizard.json
@@ -38,7 +38,7 @@
"type": "ComboBox",
"data":
{
- "items": ["<None>", "PySide2", "PySide6", "PyQt5"]
+ "items": ["<None>", "PySide6", "PySide2", "PyQt6", "PyQt5"]
}
},
{
diff --git a/share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl b/share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl
index 9c36e13c5bf..53df26f056d 100644
--- a/share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl
+++ b/share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick %{QtQuickVersion}
Item {
diff --git a/share/qtcreator/templates/wizards/files/qtquick2/wizard.json b/share/qtcreator/templates/wizards/files/qtquick2/wizard.json
index 0fa070cf934..bcb8ca994fe 100644
--- a/share/qtcreator/templates/wizards/files/qtquick2/wizard.json
+++ b/share/qtcreator/templates/wizards/files/qtquick2/wizard.json
@@ -3,13 +3,16 @@
"supportedProjectTypes": [ ],
"id": "Q.Qml.2",
"category": "R.Qt",
- "trDescription": "Creates a QML file with boilerplate code, starting with \"import QtQuick 2.0\".",
+ "trDescription": "Creates a QML file with boilerplate code, starting with \"import QtQuick\".",
"trDisplayName": "QML File (Qt Quick 2)",
"trDisplayCategory": "Qt",
"iconText": "qml",
"enabled": "%{JS: value('Plugins').indexOf('QmlJSEditor') >= 0}",
- "options": { "key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-qml')}" },
+ "options": [
+ {"key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-qml')}"},
+ {"key": "QtQuickVersion", "value": "%{JS: Util.qtQuickVersion(value('TargetPath'))}"}
+ ],
"pages" :
[
diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt
index b27ac6d8cab..0b864f908c2 100644
--- a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt
@@ -36,3 +36,6 @@ else()
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
endif()
@endif
+
+install(TARGETS %{ProjectName}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt
index 5af2f09fb67..53d5f414ca0 100644
--- a/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt
@@ -3,3 +3,6 @@ cmake_minimum_required(VERSION 3.5)
project(%{ProjectName} LANGUAGES C)
add_executable(%{ProjectName} %{CFileName})
+
+install(TARGETS %{ProjectName}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt
index 214e8979d4a..008eb2ff62e 100644
--- a/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt
@@ -6,3 +6,6 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(%{ProjectName} %{CppFileName})
+
+install(TARGETS %{ProjectName}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json
index 268fc6bd9e6..fecabd09428 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json
@@ -4,7 +4,7 @@
"id": "F.QtForPythonApplicationEmpty",
"category": "F.ApplicationPySide",
"trDescription": "Creates a Qt for Python application that contains only the main code for a QApplication.",
- "trDisplayName": "Qt for Python - Empty",
+ "trDisplayName": "Empty Application",
"trDisplayCategory": "Application (Qt for Python)",
"icon": "icon.png",
"iconKind": "Themed",
@@ -33,7 +33,11 @@
"name": "PySideVersion",
"trDisplayName": "PySide version:",
"type": "ComboBox",
- "data": { "items": [ "PySide2", "PySide6" ] }
+ "data":
+ {
+ "index": 1,
+ "items": [ "PySide2", "PySide6" ]
+ }
}
]
},
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_empty.py b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_empty.py
index ec9a1ffa718..e8a45b363c0 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_empty.py
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_empty.py
@@ -4,6 +4,10 @@ from %{PySideVersion}.QtWidgets import QApplication
if __name__ == "__main__":
- app = QApplication([])
+ app = QApplication(sys.argv)
# ...
+@if '%{PySideVersion}' === 'PySide6'
+ sys.exit(app.exec())
+@else
sys.exit(app.exec_())
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py
index b0afe88e987..102840cc298 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py
@@ -16,12 +16,9 @@ class %{Class}(%{BaseCB}):
@else
class %{Class}:
@endif
- def __init__(self):
-@if '%{BaseCB}' === 'QWidget'
- QWidget.__init__(self)
-@endif
-@if '%{BaseCB}' === 'QMainWindow'
- QMainWindow.__init__(self)
+ def __init__(self, parent=None):
+@if '%{BaseCB}' === 'QWidget' || '%{BaseCB}' === 'QMainWindow'
+ super().__init__(parent)
@endif
@if '%{BaseCB}' === ''
pass # call __init__(self) of the custom base class here
@@ -36,4 +33,8 @@ if __name__ == "__main__":
@else
window.show()
@endif
+@if '%{PySideVersion}' === 'PySide6'
+ sys.exit(app.exec())
+@else
sys.exit(app.exec_())
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_qtquick.py b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_qtquick.py
index 2bb159fd05c..2c410825c8b 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_qtquick.py
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_qtquick.py
@@ -1,7 +1,6 @@
# This Python file uses the following encoding: utf-8
-import os
-from pathlib import Path
import sys
+from pathlib import Path
from %{PySideVersion}.QtGui import QGuiApplication
from %{PySideVersion}.QtQml import QQmlApplicationEngine
@@ -10,7 +9,16 @@ from %{PySideVersion}.QtQml import QQmlApplicationEngine
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
- engine.load(os.fspath(Path(__file__).resolve().parent / "%{QmlFileName}"))
+ qml_file = Path(__file__).resolve().parent / "%{QmlFileName}"
+@if '%{PySideVersion}' === 'PySide6'
+ engine.load(qml_file)
+@else
+ engine.load(str(qml_file))
+@endif
if not engine.rootObjects():
sys.exit(-1)
+@if '%{PySideVersion}' === 'PySide6'
+ sys.exit(app.exec())
+@else
sys.exit(app.exec_())
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget.py b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget.py
index e00ab451e5d..02b7ab79115 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget.py
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget.py
@@ -21,21 +21,29 @@ class %{Class}(%{BaseCB}):
@else
class %{Class}:
@endif
- def __init__(self):
- super(%{Class}, self).__init__()
+ def __init__(self, parent=None):
+ super().__init__(parent)
self.load_ui()
def load_ui(self):
loader = QUiLoader()
- path = os.fspath(Path(__file__).resolve().parent / "form.ui")
+ path = Path(__file__).resolve().parent / "form.ui"
+@if '%{PySideVersion}' === 'PySide6'
ui_file = QFile(path)
+@else
+ ui_file = QFile(str(path))
+@endif
ui_file.open(QFile.ReadOnly)
loader.load(ui_file, self)
ui_file.close()
if __name__ == "__main__":
- app = QApplication([])
+ app = QApplication(sys.argv)
widget = %{Class}()
widget.show()
+@if '%{PySideVersion}' === 'PySide6'
+ sys.exit(app.exec())
+@else
sys.exit(app.exec_())
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget_gen.py b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget_gen.py
new file mode 100644
index 00000000000..bd7d4fa807d
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_widget_gen.py
@@ -0,0 +1,39 @@
+# This Python file uses the following encoding: utf-8
+import sys
+
+@if '%{BaseCB}' === 'QWidget'
+from %{PySideVersion}.QtWidgets import QApplication, QWidget
+@endif
+@if '%{BaseCB}' === 'QMainWindow'
+from %{PySideVersion}.QtWidgets import QApplication, QMainWindow
+@endif
+@if '%{BaseCB}' === 'QDialog'
+from %{PySideVersion}.QtWidgets import QApplication, QDialog
+@endif
+
+# Important:
+# You need to run the following command to generate the ui_form.py file
+# pyside6-uic form.ui -o ui_form.py, or
+# pyside2-uic form.ui -o ui_form.py
+from ui_form import Ui_%{Class}
+
+@if '%{BaseCB}'
+class %{Class}(%{BaseCB}):
+@else
+class %{Class}:
+@endif
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.ui = Ui_%{Class}()
+ self.ui.setupUi(self)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ widget = %{Class}()
+ widget.show()
+@if '%{PySideVersion}' === 'PySide6'
+ sys.exit(app.exec())
+@else
+ sys.exit(app.exec_())
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json
index a16b7fd900a..d9f575ecd9b 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json
@@ -4,7 +4,7 @@
"id": "F.QtForPythonApplicationWindow",
"category": "F.ApplicationPySide",
"trDescription": "Creates a Qt for Python application that contains an empty window.",
- "trDisplayName": "Qt for Python - Window",
+ "trDisplayName": "Empty Window",
"trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png",
"iconKind": "Themed",
@@ -34,7 +34,11 @@
"name": "PySideVersion",
"trDisplayName": "PySide version:",
"type": "ComboBox",
- "data": { "items": [ "PySide2", "PySide6" ] }
+ "data":
+ {
+ "index": 1,
+ "items": [ "PySide2", "PySide6" ]
+ }
},
{
"name": "Class",
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/qtquickapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/qtquickapplication/wizard.json
index 268367d1f6f..7ab73b917f4 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/qtquickapplication/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/qtquickapplication/wizard.json
@@ -4,7 +4,7 @@
"id": "F.QtQuickQtForPythonApplicationEmpty",
"category": "F.ApplicationPySide",
"trDescription": "Creates a Qt Quick application that contains an empty window.",
- "trDisplayName": "Qt for Python - Qt Quick Application - Empty",
+ "trDisplayName": "Qt Quick Application - Empty",
"trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png",
"iconKind": "Themed",
@@ -39,7 +39,7 @@
"type": "ComboBox",
"data":
{
- "index": 2,
+ "index": 0,
"items":
[
{
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget/wizard.json b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget/wizard.json
index 6a068d5fd3c..b9c96c97886 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget/wizard.json
@@ -3,8 +3,8 @@
"supportedProjectTypes": [ "PythonProject" ],
"id": "F.QtForPythonApplicationWindowWidget",
"category": "F.ApplicationPySide",
- "trDescription": "Creates a Qt for Python application that includes a Qt Designer-based widget (ui file)",
- "trDisplayName": "Qt for Python - Window (UI file)",
+ "trDescription": "Creates a Qt for Python application that includes a Qt Designer-based widget (.ui file) - Load the forms dynamically/at runtime",
+ "trDisplayName": "Window UI - Dynamic load",
"trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png",
"iconKind": "Themed",
@@ -34,7 +34,11 @@
"name": "PySideVersion",
"trDisplayName": "PySide version:",
"type": "ComboBox",
- "data": { "items": [ "PySide2", "PySide6" ] }
+ "data":
+ {
+ "index": 1,
+ "items": [ "PySide2", "PySide6" ]
+ }
},
{
"name": "Class",
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget_gen/main.pyproject b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget_gen/main.pyproject
new file mode 100644
index 00000000000..64c2987a8fb
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget_gen/main.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["%{SrcFileName}", "form.ui"]
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget_gen/wizard.json b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget_gen/wizard.json
new file mode 100644
index 00000000000..91572c2bdd2
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/widget_gen/wizard.json
@@ -0,0 +1,114 @@
+{
+ "version": 1,
+ "supportedProjectTypes": [ "PythonProject" ],
+ "id": "F.QtForPythonApplicationWindowWidgetGen",
+ "category": "F.ApplicationPySide",
+ "trDescription": "Creates a Qt for Python application that includes a Qt Designer-based widget (ui file) - Requires .ui to Python conversion",
+ "trDisplayName": "Window UI",
+ "trDisplayCategory": "Application (Qt for Python)",
+ "icon": "../icons/icon.png",
+ "iconKind": "Themed",
+ "enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
+
+ "options":
+ [
+ { "key": "SrcFileName", "value": "%{MainFileName}" },
+ { "key": "PyProjectFile", "value": "%{ProjectFileName}" }
+ ],
+
+ "pages":
+ [
+ {
+ "trDisplayName": "Project Location",
+ "trShortTitle": "Location",
+ "typeId": "Project",
+ "name": "ProjectPath"
+ },
+ {
+ "trDisplayName": "Define Class",
+ "trShortTitle": "Details",
+ "typeId": "Fields",
+ "data" :
+ [
+ {
+ "name": "PySideVersion",
+ "trDisplayName": "PySide version:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 1,
+ "items": [ "PySide2", "PySide6" ]
+ }
+ },
+ {
+ "name": "Class",
+ "trDisplayName": "Class name:",
+ "mandatory": true,
+ "type": "LineEdit",
+ "data":
+ {
+ "validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*|)",
+ "trText": "%{JS: value('BaseCB') ? value('BaseCB').slice(1) : 'MyClass'}"
+ }
+
+ },
+ {
+ "name": "BaseCB",
+ "trDisplayName": "Base class:",
+ "type": "ComboBox",
+ "data":
+ {
+ "items": [ "QWidget", "QDialog", "QMainWindow" ]
+ }
+ },
+ {
+ "name": "MainFileName",
+ "type": "LineEdit",
+ "trDisplayName": "Source file:",
+ "mandatory": true,
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-python'))}" }
+ },
+ {
+ "name": "ProjectFileName",
+ "type": "LineEdit",
+ "trDisplayName": "Project file:",
+ "mandatory": true,
+ "data": { "trText": "%{JS: Util.fileName('%{ProjectName}', 'pyproject')}" }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Project Management",
+ "trShortTitle": "Summary",
+ "typeId": "Summary"
+ }
+ ],
+ "generators":
+ [
+ {
+ "typeId": "File",
+ "data":
+ [
+ {
+ "source": "main.pyproject",
+ "target": "%{PyProjectFile}",
+ "openAsProject": true
+ },
+ {
+ "source": "../main_widget_gen.py",
+ "target": "%{SrcFileName}",
+ "openInEditor": true
+ },
+ {
+ "source": "../main_widget.ui",
+ "target": "form.ui"
+ },
+ {
+ "source": "../../git.ignore",
+ "target": ".gitignore",
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
+ }
+ ]
+ }
+ ]
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/CMakeLists.6.x.txt b/share/qtcreator/templates/wizards/projects/qtquick2-extension/CMakeLists.6.x.txt
new file mode 100644
index 00000000000..a6ddf3cb48f
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/CMakeLists.6.x.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(%{ProjectName} VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+
+find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
+
+qt_add_library(%{ProjectName} STATIC)
+qt_add_qml_module(%{ProjectName}
+ URI %{ProjectName}
+ VERSION 1.0
+ QML_FILES %{ObjectQml}
+ SOURCES %{ObjectSrc} %{ObjectHdr}
+)
+
+set_target_properties(%{ProjectName} PROPERTIES
+ MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
+ MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
+ MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
+ MACOSX_BUNDLE TRUE
+ WIN32_EXECUTABLE TRUE
+)
+
+target_compile_definitions(%{ProjectName}
+ PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
+target_link_libraries(%{ProjectName}
+ PRIVATE Qt6::Quick)
+
+target_include_directories(%{ProjectName} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+
+@if %{CreateExampleProject}
+# Example Project
+qt_add_executable(ExampleProject example/example.cpp)
+qt_add_qml_module(ExampleProject
+ URI ExampleProjectApp
+ VERSION 1.0
+ QML_FILES example/example.qml
+)
+target_link_libraries(ExampleProject PRIVATE Qt6::Quick %{ProjectName}plugin)
+target_compile_definitions(ExampleProject PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.cpp b/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.cpp
new file mode 100644
index 00000000000..b7b83acf554
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.cpp
@@ -0,0 +1,23 @@
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QtQml/qqmlextensionplugin.h>
+
+Q_IMPORT_QML_PLUGIN(%{ProjectName}Plugin)
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ // The first subfolder is the libraryName followed by the regular
+ // folder structure: LibraryName/Subfolder
+ const QUrl url(u"qrc:/ExampleProjectApp/example/example.qml"_qs);
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
+ &app, [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ }, Qt::QueuedConnection);
+ engine.load(url);
+
+ return app.exec();
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.qml.tpl
new file mode 100644
index 00000000000..ea6222d39dc
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.qml.tpl
@@ -0,0 +1,29 @@
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import QtQuick.Controls.Material
+import %{ProjectName}
+
+Window {
+ width: 640
+ height: 400
+ visible: true
+ title: qsTr("Example Project")
+
+ %{ObjectName}Controls {
+ id: controls
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: 20
+ width: 100
+ height: 100
+ }
+ %{ObjectName} {
+ id: rect
+ anchors.left: controls.right
+ anchors.top: parent.top
+ anchors.margins: 20
+ width: 100
+ height: 100
+ }
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.cpp b/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.cpp
index a2288c47c1c..fa74fbd6944 100644
--- a/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.cpp
+++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.cpp
@@ -1,7 +1,9 @@
#include "%{ObjectHdr}"
+#include <QPainter>
+
%{ObjectName}::%{ObjectName}(QQuickItem *parent)
- : QQuickItem(parent)
+ : QQuickPaintedItem(parent)
{
// By default, QQuickItem does not draw anything. If you subclass
// QQuickItem to create a visual item, you will need to uncomment the
@@ -10,6 +12,16 @@
// setFlag(ItemHasContents, true);
}
+void %{ObjectName}::paint(QPainter *painter)
+{
+ QPen pen(QColorConstants::Red, 2);
+ QBrush brush(QColorConstants::Red);
+
+ painter->setPen(pen);
+ painter->setBrush(brush);
+ painter->drawRect(0, 0, 100, 100);
+}
+
%{ObjectName}::~%{ObjectName}()
{
}
diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.h b/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.h
index e74c4233e87..62144e14e54 100644
--- a/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.h
+++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.h
@@ -6,15 +6,16 @@
#define %{OBJECTGUARD}
@endif
-#include <QQuickItem>
+#include <QtQuick/QQuickPaintedItem>
-class %{ObjectName} : public QQuickItem
+class %{ObjectName} : public QQuickPaintedItem
{
Q_OBJECT
+ QML_ELEMENT
Q_DISABLE_COPY(%{ObjectName})
-
public:
explicit %{ObjectName}(QQuickItem *parent = nullptr);
+ void paint(QPainter *painter) override;
~%{ObjectName}() override;
};
diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.qml.tpl
new file mode 100644
index 00000000000..d27870185b3
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/object.qml.tpl
@@ -0,0 +1,10 @@
+import QtQuick %{QtQuickVersion}
+
+Item {
+ id: root
+
+ Rectangle {
+ anchors.fill: root
+ color: "green"
+ }
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json b/share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json
index 45989fb7de2..0164a9f3d57 100644
--- a/share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json
@@ -13,16 +13,23 @@
"options":
[
- { "key": "ProjectFile", "value": "%{ProFile}" },
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : value('CMakeFile')}" },
{ "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "PluginBaseFileName", "value": "%{JS: value('ProjectName') + '_plugin'}" },
{ "key": "PluginSrc", "value": "%{JS: Cpp.classToFileName(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++src'))}" },
{ "key": "PluginHdr", "value": "%{JS: Cpp.classToFileName(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++hdr'))}" },
{ "key": "ObjectSrc", "value": "%{JS: Cpp.classToFileName(value('ObjectName'), Util.preferredSuffix('text/x-c++src'))}" },
{ "key": "ObjectHdr", "value": "%{JS: Cpp.classToFileName(value('ObjectName'), Util.preferredSuffix('text/x-c++hdr'))}" },
+ { "key": "ObjectQml", "value": "%{JS: Util.fileName(value('ObjectName') + 'Controls', 'qml')}" },
{ "key": "PluginName", "value": "%{JS: value('ProjectName').charAt(0).toUpperCase() + value('ProjectName').slice(1) + 'Plugin' }" },
{ "key": "PLUGINGUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++hdr'))}" },
- { "key": "OBJECTGUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('ObjectName'), Util.preferredSuffix('text/x-c++hdr'))}" }
+ { "key": "OBJECTGUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('ObjectName'), Util.preferredSuffix('text/x-c++hdr'))}" },
+ { "key": "IsQt6", "value": "%{JS: value('QtVersion').IsQt6}" },
+ { "key": "QtQuickVersion", "value": "%{JS: value('QtVersion').QtQuickVersion}" },
+ { "key": "QtQuickFeature", "value": "%{JS: (value('QtQuickVersion')=='') ? 'QtSupport.Wizards.FeatureQt.6.2' : 'QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}'}" },
+ { "key": "CreateExampleProjectDefault", "value": false },
+ { "key": "TargetName", "value": "%{JS: 'lib' + value('ProjectName')}" }
],
"pages":
@@ -33,12 +40,102 @@
"typeId": "Project"
},
{
+ "trDisplayName": "Define Build System",
+ "trShortTitle": "Build System",
+ "typeId": "Fields",
+ "enabled": "%{JS: !value('IsSubproject')}",
+ "data":
+ [
+ {
+ "name": "BuildSystem",
+ "trDisplayName": "Build system:",
+ "type": "ComboBox",
+ "persistenceKey": "BuildSystemType",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+
+ {
+ "trKey": "CMake",
+ "value": "cmake",
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "qmake",
+ "value": "qmake",
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
"trDisplayName": "Custom Parameters",
"trShortTitle": "Details",
"typeId": "Fields",
"data":
[
{
+ "name": "QtVersion",
+ "trDisplayName": "Minimum required Qt version:",
+ "type": "ComboBox",
+ "persistenceKey": "QtQuick.minimumQtVersion",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Qt 6.2",
+ "value":
+ {
+ "QtQuickVersion": "",
+ "IsQt6": true
+ }
+ },
+ {
+ "trKey": "Qt 5.15",
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}",
+ "value":
+ {
+ "QtQuickVersion": "2.15",
+ "IsQt6": false
+ }
+ },
+ {
+ "trKey": "Qt 5.14",
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}",
+ "value":
+ {
+ "QtQuickVersion": "2.14",
+ "IsQt6": false
+ }
+ },
+ {
+ "trKey": "Qt 5.13",
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}",
+ "value":
+ {
+ "QtQuickVersion": "2.13",
+ "IsQt6": false
+ }
+ },
+ {
+ "trKey": "Qt 5.12",
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}",
+ "value":
+ {
+ "QtQuickVersion": "2.12",
+ "IsQt6": false
+ }
+ }
+ ]
+ }
+ },
+ {
"name": "ObjectName",
"trDisplayName": "Object class-name:",
"mandatory": true,
@@ -59,6 +156,16 @@
"validator": "^[A-Za-z0-9]+([A-Za-z0-9-]*[A-Za-z0-9]+)?(\\.[A-Za-z0-9]+([-A-Za-z0-9]*[A-Za-z0-9]+)?)*$",
"trText": "com.mycompany.qmlcomponents"
}
+ },
+ {
+ "name": "CreateExampleProject",
+ "trDisplayName": "Create example project",
+ "visible": "%{JS: value('BuildSystem') === 'cmake'}",
+ "type": "CheckBox",
+ "data":
+ {
+ "checked": "%{CreateExampleProjectDefault}"
+ }
}
]
},
@@ -69,7 +176,7 @@
"enabled": "%{JS: !value('IsSubproject')}",
"data": {
"projectFilePath": "%{ProjectFile}",
- "requiredFeatures": [ "QtSupport.Wizards.FeatureQtQuick", "QtSupport.Wizards.FeatureQtQuick.2" ]
+ "requiredFeatures": [ "QtSupport.Wizards.FeatureQtQuick", "%{QtQuickFeature}" ]
}
},
{
@@ -87,7 +194,14 @@
{
"source": "project.pro",
"target": "%{ProFile}",
- "openAsProject": true
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
+ },
+ {
+ "source": "CMakeLists.6.x.txt",
+ "target": "CMakeLists.txt",
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
},
{
"source": "qmldir",
@@ -96,11 +210,13 @@
{
"source": "plugin.cpp",
"target": "%{PluginSrc}",
- "openInEditor": true
+ "openInEditor": true,
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "plugin.h",
- "target": "%{PluginHdr}"
+ "target": "%{PluginHdr}",
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "object.cpp",
@@ -111,6 +227,20 @@
"target": "%{ObjectHdr}"
},
{
+ "source": "object.qml.tpl",
+ "target": "%{ObjectQml}"
+ },
+ {
+ "source": "example/example.cpp",
+ "target": "example/example.cpp",
+ "condition": "%{JS: value('CreateExampleProject')}"
+ },
+ {
+ "source": "example/example.qml.tpl",
+ "target": "example/example.qml",
+ "condition": "%{JS: value('CreateExampleProject')}"
+ },
+ {
"source": "../git.ignore",
"target": ".gitignore",
"condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt
index bfe160ea937..9d2fc4a82cc 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt
@@ -25,7 +25,9 @@ set_target_properties(%{TargetName} PROPERTIES
WIN32_EXECUTABLE TRUE
)
-target_compile_definitions(%{TargetName}
- PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(%{TargetName}
PRIVATE Qt6::Quick)
+
+install(TARGETS %{TargetName}
+ BUNDLE DESTINATION .
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
index f814cbcd978..58af2d44a2b 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
@@ -60,8 +60,6 @@ else()
@endif
endif()
-target_compile_definitions(%{ProjectName}
- PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(%{ProjectName}
PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick)
@@ -73,6 +71,10 @@ set_target_properties(%{ProjectName} PROPERTIES
WIN32_EXECUTABLE TRUE
)
+install(TARGETS %{ProjectName}
+ BUNDLE DESTINATION .
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
if(QT_VERSION_MAJOR EQUAL 6)
qt_import_qml_plugins(%{ProjectName})
qt_finalize_executable(%{ProjectName})
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json
index 60397cbd2e1..ca2eb44b280 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json
@@ -83,7 +83,7 @@
[
{
"name": "QtVersion",
- "trDisplayName": "Minimal required Qt version:",
+ "trDisplayName": "Minimum required Qt version:",
"type": "ComboBox",
"persistenceKey": "QtQuick.minimumQtVersion",
"data":
diff --git a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
index 78dbbd99561..ac45450734c 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
@@ -38,7 +38,7 @@
[
{
"name": "QtVersion",
- "trDisplayName": "Minimal required Qt version:",
+ "trDisplayName": "Minimum required Qt version:",
"type": "ComboBox",
"data":
{
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt
index 32ceeffc55b..b682c95f228 100644
--- a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt
@@ -74,6 +74,10 @@ set_target_properties(%{ProjectName} PROPERTIES
WIN32_EXECUTABLE TRUE
)
+install(TARGETS %{ProjectName}
+ BUNDLE DESTINATION .
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(%{ProjectName})
endif()
diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts
index dece10295e4..8013bb9b20e 100644
--- a/share/qtcreator/translations/qtcreator_de.ts
+++ b/share/qtcreator/translations/qtcreator_de.ts
@@ -19692,7 +19692,7 @@ should a repository require SSH-authentication (see documentation on SSH and the
<translation>(SDK-Version: %1, NDK-Version: %2)</translation>
</message>
<message>
- <source>Download and install Android SDK Tools to: %1?</source>
+ <source>Download and install Android SDK Tools to %1?</source>
<translation>Android-SDK-Tools herunterladen und nach %1 installieren?</translation>
</message>
<message>
diff --git a/share/qtcreator/translations/qtcreator_ja.ts b/share/qtcreator/translations/qtcreator_ja.ts
index c65ccab4138..c56df2bab00 100644
--- a/share/qtcreator/translations/qtcreator_ja.ts
+++ b/share/qtcreator/translations/qtcreator_ja.ts
@@ -66,6 +66,10 @@
<source>Details:</source>
<translation>詳細:</translation>
</message>
+ <message>
+ <source>Plugin Loader Messages</source>
+ <translation>プラグインローダーã‹ã‚‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸</translation>
+ </message>
</context>
<context>
<name>ExtensionSystem::Internal::PluginErrorView</name>
@@ -300,6 +304,18 @@
<translation>é¸æŠž...</translation>
</message>
<message>
+ <source>The ssh-keygen tool was not found.</source>
+ <translation>ssh-keygen ツールãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Refusing to overwrite existing private key file &quot;%1&quot;.</source>
+ <translation>既存ã®ç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; ã®ä¸Šæ›¸ãã‚’æ‹’å¦ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The ssh-keygen tool at &quot;%1&quot; failed: %2</source>
+ <translation>&quot;%1&quot;ã® ssh-keygen ツールãŒå¤±æ•—ã—ã¾ã—ãŸ: %2</translation>
+ </message>
+ <message>
<source>Key Generation Failed</source>
<translation>éµã®ç”Ÿæˆã«å¤±æ•—</translation>
</message>
@@ -477,6 +493,10 @@
<translation>ファイルåãŒæœªå…¥åŠ›ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Enter project name</source>
+ <translation>プロジェクトåを入力ã—ã¦ãã ã•ã„</translation>
+ </message>
+ <message>
<source>Name does not match &quot;%1&quot;.</source>
<translation>åå‰ãŒ &quot;%1&quot; ã¨åˆè‡´ã—ã¾ã›ã‚“。</translation>
</message>
@@ -515,6 +535,18 @@
<source>ABI:</source>
<translation>ABI:</translation>
</message>
+ <message>
+ <source>Architecture (ABI):</source>
+ <translation>アーキテクãƒãƒ£ (ABI):</translation>
+ </message>
+ <message>
+ <source>Device definition:</source>
+ <translation>デãƒã‚¤ã‚¹ã®å®šç¾©:</translation>
+ </message>
+ <message>
+ <source>Overwrite existing AVD name</source>
+ <translation>既存㮠AVD åを上書ãã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>AndroidCreateKeystoreCertificate</name>
@@ -669,6 +701,10 @@
<translation>&lt;p&gt;Android SDK ã®ãƒ„ール adb ã‚’ &amp;quot;adb devices&amp;quot; ã¨å®Ÿè¡Œã™ã‚‹ã¨ã€ã™ã¹ã¦ã®æŽ¥ç¶šã•ã‚Œã¦ã„るデãƒã‚¤ã‚¹ãŒç¢ºèªã§ãã¾ã™ã€‚&lt;/p&gt;</translation>
</message>
<message>
+ <source>Always use this device for this project</source>
+ <translation>ã“ã®ãƒ—ロジェクトã§ã¯å¸¸ã«ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã‚’使用ã™ã‚‹</translation>
+ </message>
+ <message>
<source>No Device Found</source>
<translation>デãƒã‚¤ã‚¹ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</translation>
</message>
@@ -772,18 +808,86 @@
<source>Use Gradle instead of Ant</source>
<translation>Ant ã§ã¯ãªã Gradle を使用ã™ã‚‹</translation>
</message>
+ <message>
+ <source>Java Settings</source>
+ <translation>Java ã®è¨­å®š</translation>
+ </message>
+ <message>
+ <source>Open JDK download URL in the system&apos;s browser.</source>
+ <translation>JDK ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ URL をシステムã®ãƒ–ラウザã§é–‹ã。</translation>
+ </message>
+ <message>
+ <source>Android Settings</source>
+ <translation>Android ã®è¨­å®š</translation>
+ </message>
+ <message>
+ <source>Add the selected custom NDK. The toolchains and debuggers will be created automatically.</source>
+ <translation>é¸æŠžã—ãŸã‚«ã‚¹ã‚¿ãƒ  NDK を追加ã—ã¾ã™ã€‚ツールãƒã‚§ã‚¤ãƒ³ã¨ãƒ‡ãƒãƒƒã‚¬ãŒè‡ªå‹•çš„ã«ä½œæˆã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Remove the selected NDK if it has been added manually.</source>
+ <translation>é¸æŠžã—㟠NDK ãŒæ‰‹å‹•ã§è¿½åŠ ã•ã‚Œã¦ã„ã‚‹å ´åˆã€ãれを削除ã—ã¦ä¸‹ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Android NDK list:</source>
+ <translation>Android NDK ã®ä¸€è¦§:</translation>
+ </message>
+ <message>
+ <source>Open Android SDK download URL in the system&apos;s browser.</source>
+ <translation>システムã®ãƒ–ラウザ㧠Android SDK ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ URL ã‚’é–‹ã。</translation>
+ </message>
+ <message>
+ <source>Open Android NDK download URL in the system&apos;s browser.</source>
+ <translation>システムã®ãƒ–ラウザ㧠Android NDK ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ URL ã‚’é–‹ã。</translation>
+ </message>
+ <message>
+ <source>Set Up SDK</source>
+ <translation>SDK ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—</translation>
+ </message>
+ <message>
+ <source>Android OpenSSL settings (Optional)</source>
+ <translation>Android OpenSSL ã®è¨­å®š (オプション)</translation>
+ </message>
+ <message>
+ <source>OpenSSL binaries location:</source>
+ <translation>OpenSSL ãƒã‚¤ãƒŠãƒªã®å ´æ‰€:</translation>
+ </message>
+ <message>
+ <source>Download OpenSSL</source>
+ <translation>OpenSSL をダウンロードã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Select the path of the prebuilt OpenSSL binaries.</source>
+ <translation>プリビルドã•ã‚ŒãŸ OpenSSL ãƒã‚¤ãƒŠãƒªã®ãƒ‘スをé¸æŠžã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Refresh List</source>
+ <translation>リストを更新</translation>
+ </message>
+ <message>
+ <source>Advanced Options...</source>
+ <translation>詳細オプション...</translation>
+ </message>
+ <message>
+ <source>SDK Manager</source>
+ <translation>SDK マãƒãƒ¼ã‚¸ãƒ£</translation>
+ </message>
</context>
<context>
<name>BareMetal::Internal::BareMetalDeviceConfigurationWizardSetupPage</name>
<message>
- <source>Set up GDB Server or Hardware Debugger</source>
- <translation>GDB サーãƒã¾ãŸã¯ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒ‡ãƒãƒƒã‚¬ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—</translation>
+ <source>Set up Debug Server or Hardware Debugger</source>
+ <translation>デãƒãƒƒã‚°ã‚µãƒ¼ãƒãƒ¼ã¾ãŸã¯ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒ‡ãƒãƒƒã‚¬ã‚’セットアップ</translation>
</message>
<message>
<source>Name:</source>
<translation>åå‰:</translation>
</message>
<message>
+ <source>Debug server provider:</source>
+ <translation>デãƒãƒƒã‚°ã‚µãƒ¼ãƒãƒ¼ã‚’é¸æŠž:</translation>
+ </message>
+ <message>
<source>GDB server provider:</source>
<translation>GDB サーãƒãƒ¼ãƒ—ロãƒã‚¤ãƒ€:</translation>
</message>
@@ -1149,8 +1253,16 @@ Local pulls are not applied to the master branch.</source>
<translation>更新後ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³(&amp;U)</translation>
</message>
<message>
- <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;NOTE: You will not be able to check in this file without merging the changes (not supported by the plugin)&lt;/b&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
- <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;注æ„: 変更内容をマージã™ã‚‹å‰ã«ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容を確èªã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“(プラグインãŒæœªã‚µãƒãƒ¼ãƒˆã®ç‚º)&lt;/b&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ <source>Multiple versions of &quot;%1&quot; can be checked out. Select the version to check out:</source>
+ <translation>複数ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® &quot;%1&quot; ã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã§ãã¾ã™ã€‚ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã™ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’é¸æŠžã—ã¦ãã ã•ã„:</translation>
+ </message>
+ <message>
+ <source>&amp;Loaded version</source>
+ <translation>ロードã•ã‚ŒãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Note: You will not be able to check in this file without merging the changes (not supported by the plugin)</source>
+ <translation>注: 変更をマージã—ãªã„ã¨ã€ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ (プラグインã§ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“)</translation>
</message>
</context>
<context>
@@ -1302,6 +1414,10 @@ Local pulls are not applied to the master branch.</source>
<source>Change...</source>
<translation>変更...</translation>
</message>
+ <message>
+ <source>Base environment:</source>
+ <translation>ベースã¨ãªã‚‹ç’°å¢ƒ:</translation>
+ </message>
</context>
<context>
<name>Core::Internal::NewDialog</name>
@@ -1407,6 +1523,38 @@ Local pulls are not applied to the master branch.</source>
<translation>ä¿å­˜ã—ãªã„</translation>
</message>
<message>
+ <source>&amp;Diff</source>
+ <translation>差分表示(&amp;D)</translation>
+ </message>
+ <message>
+ <source>Do &amp;Not Save</source>
+ <translation>ä¿å­˜ã—ãªã„(&amp;N)</translation>
+ </message>
+ <message>
+ <source>&amp;Save</source>
+ <translation>ä¿å­˜(&amp;S)</translation>
+ </message>
+ <message>
+ <source>&amp;Diff &amp;&amp; Cancel</source>
+ <translation>差分表示ã—ã¦ã‚­ãƒ£ãƒ³ã‚»ãƒ«(&amp;D)</translation>
+ </message>
+ <message>
+ <source>&amp;Save All</source>
+ <translation>ã™ã¹ã¦ä¿å­˜(&amp;S)</translation>
+ </message>
+ <message>
+ <source>&amp;Diff All &amp;&amp; Cancel</source>
+ <translation>ã™ã¹ã¦å·®åˆ†è¡¨ç¤ºã—ã¦ã‚­ãƒ£ãƒ³ã‚»ãƒ«(&amp;D)</translation>
+ </message>
+ <message>
+ <source>&amp;Save Selected</source>
+ <translation>é¸æŠžã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’ä¿å­˜(&amp;S)</translation>
+ </message>
+ <message>
+ <source>&amp;Diff Selected &amp;&amp; Cancel</source>
+ <translation>é¸æŠžã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’差分表示ã—ã¦ã‚­ãƒ£ãƒ³ã‚»ãƒ«(&amp;D)</translation>
+ </message>
+ <message>
<source>Save All</source>
<translation>ã™ã¹ã¦ä¿å­˜</translation>
</message>
@@ -1416,7 +1564,7 @@ Local pulls are not applied to the master branch.</source>
</message>
<message>
<source>Save Selected</source>
- <translation>é¸æŠžã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’ä¿å­˜</translation>
+ <translation>é¸æŠžã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’ä¿å­˜</translation>
</message>
</context>
<context>
@@ -1451,10 +1599,30 @@ Local pulls are not applied to the master branch.</source>
<translation>&lt;システム言語&gt;</translation>
</message>
<message>
+ <source>Show keyboard shortcuts in context menus (default: %1)</source>
+ <translation>コンテキストメニューã«ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆã‚’表示ã™ã‚‹ (デフォルト: %1)</translation>
+ </message>
+ <message>
+ <source>on</source>
+ <translation>オン</translation>
+ </message>
+ <message>
+ <source>off</source>
+ <translation>オフ</translation>
+ </message>
+ <message>
<source>Restart Required</source>
<translation>å†èµ·å‹•ãŒå¿…è¦ã§ã™</translation>
</message>
<message>
+ <source>The high DPI settings will take effect after restart.</source>
+ <translation>高 DPI 設定ã¯å†èµ·å‹•å¾Œã«æœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The language change will take effect after restart.</source>
+ <translation>言語ã®å¤‰æ›´ã¯ã€Qt Creator ã‚’å†èµ·å‹•ã—ãŸå¾Œã«å映ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>The language change will take effect after a restart of Qt Creator.</source>
<translation>言語ã®å¤‰æ›´ã¯ã€Qt Creator ã‚’å†èµ·å‹•ã—ãŸå¾Œã«å映ã•ã‚Œã¾ã™ã€‚</translation>
</message>
@@ -1471,6 +1639,14 @@ Local pulls are not applied to the master branch.</source>
<source>Theme:</source>
<translation>テーマ:</translation>
</message>
+ <message>
+ <source>Enable high DPI scaling</source>
+ <translation>高 DPI スケーリングを有効ã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Text codec for tools:</source>
+ <translation>ツール用文字コード:</translation>
+ </message>
</context>
<context>
<name>Core::Internal::MimeTypeMagicDialog</name>
@@ -1504,7 +1680,7 @@ Local pulls are not applied to the master branch.</source>
</message>
<message>
<source>Add Magic Header</source>
- <translation>マジックヘッダーã®è¿½åŠ </translation>
+ <translation>マジックヘッダã®è¿½åŠ </translation>
</message>
<message>
<source>Error</source>
@@ -1562,6 +1738,10 @@ Local pulls are not applied to the master branch.</source>
<source>Range end:</source>
<translation>終了ä½ç½®:</translation>
</message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Note: Wide range values might impact performance when opening files.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;注æ„:広ã„範囲ã®å€¤ã¯ã€ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ãéš›ã®ãƒ‘フォーマンスã«å½±éŸ¿ã‚’与ãˆã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
</context>
<context>
<name>Core::Internal::MimeTypeSettingsPage</name>
@@ -1617,6 +1797,26 @@ Local pulls are not applied to the master branch.</source>
<source>Remove</source>
<translation>削除</translation>
</message>
+ <message>
+ <source>Reset all MIME type definitions to their defaults.</source>
+ <translation>ã™ã¹ã¦ã® MIME タイプ定義をデフォルトã«æˆ»ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Reset MIME Types</source>
+ <translation>MIME タイプã®ãƒªã‚»ãƒƒãƒˆ</translation>
+ </message>
+ <message>
+ <source>Reset the assigned handler for all MIME type definitions to the default.</source>
+ <translation>ã™ã¹ã¦ã® MIME タイプ定義ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸãƒãƒ³ãƒ‰ãƒ©ãƒ¼ã‚’デフォルトã«æˆ»ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Reset Handlers</source>
+ <translation>ãƒãƒ³ãƒ‰ãƒ©ãƒ¼ã®ãƒªã‚»ãƒƒãƒˆ</translation>
+ </message>
+ <message>
+ <source>A semicolon-separated list of wildcarded file names.</source>
+ <translation>セミコロンã§åŒºåˆ‡ã‚‰ã‚ŒãŸãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰ã®ãƒ•ã‚¡ã‚¤ãƒ«åã®ä¸€è¦§ã€‚</translation>
+ </message>
</context>
<context>
<name>Core::RemoveFileDialog</name>
@@ -1748,6 +1948,10 @@ p, li { white-space: pre-wrap; }
<source> Days</source>
<translation> æ—¥</translation>
</message>
+ <message>
+ <source>Make public:</source>
+ <translation>公開ã™ã‚‹:</translation>
+ </message>
</context>
<context>
<name>CodePaster::Internal::SettingsPage</name>
@@ -1775,6 +1979,10 @@ p, li { white-space: pre-wrap; }
<source> Days</source>
<translation> æ—¥</translation>
</message>
+ <message>
+ <source>Make pasted content public by default</source>
+ <translation>貼り付ã‘ãŸã‚³ãƒ³ãƒ†ãƒ³ãƒ„をデフォルトã§å…¬é–‹</translation>
+ </message>
</context>
<context>
<name>CppEditor::Internal::CppPreProcessorDialog</name>
@@ -1945,6 +2153,22 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
<source>Completion</source>
<translation>補完</translation>
</message>
+ <message>
+ <source>Character threshold:</source>
+ <translation>文字数ã®ã—ãã„値:</translation>
+ </message>
+ <message>
+ <source>Skip automatically inserted character if re-typed manually after completion or by pressing tab.</source>
+ <translation>補完後ã«è‡ªå‹•çš„ã«æŒ¿å…¥ã•ã‚ŒãŸæ–‡å­—ãŒæ‰‹å‹•ã§å†åº¦ã‚¿ã‚¤ãƒ—ã•ã‚ŒãŸå ´åˆã‚„ã€ã‚¿ãƒ–を押ã•ã‚ŒãŸå ´åˆã¯ã‚¹ã‚­ãƒƒãƒ—ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Automatically overwrite closing parentheses and quotes.</source>
+ <translation>é–‰ã˜æ‹¬å¼§ã‚„引用符を自動的ã«ä¸Šæ›¸ãã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Overwrite closing punctuation</source>
+ <translation>é–‰ã˜è¨˜å·ã‚’上書ãã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>CppTools::Internal::CppCodeModelSettingsPage</name>
@@ -1976,6 +2200,34 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
<source>&lt;i&gt;The Clang Code Model is disabled because the corresponding plugin is not loaded.&lt;/i&gt;</source>
<translation>&lt;i&gt;対応ã™ã‚‹ãƒ—ラグインãŒèª­ã¿è¾¼ã¾ã‚Œãªã‹ã£ãŸãŸã‚ã€Clang コードモデルを無効ã«ã—ã¾ã™ã€‚&lt;/i&gt;</translation>
</message>
+ <message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+ <message>
+ <source>Interpret ambiguous headers as C headers</source>
+ <translation>曖昧ãªãƒ˜ãƒƒãƒ€ã‚’ C ヘッダã¨ã—ã¦è§£é‡ˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When precompiled headers are not ignored, the parsing for code completion and semantic highlighting will process the precompiled header before processing any file.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;コンパイル済ã¿ãƒ˜ãƒƒãƒ€ã‚’無視ã—ãªã„å ´åˆã€ã‚³ãƒ¼ãƒ‰è£œå®Œã‚„ãƒã‚¤ãƒ©ã‚¤ãƒˆç”¨ã®è§£æžã«ã¯ãã®ä»–ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚ˆã‚Šã‚‚コンパイル済ã¿ãƒ˜ãƒƒãƒ€ã‚’優先ã—ã¦ä½¿ç”¨ã—ã¾ã™ã€‚&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <source>Ignore precompiled headers</source>
+ <translation>コンパイル済ã¿ã®ãƒ˜ãƒƒãƒ€ã‚’無視ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Do not index files greater than</source>
+ <translation>インデックスã—ãªã„最å°ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã®æŒ‡å®š</translation>
+ </message>
+ <message>
+ <source>MB</source>
+ <translation>MB</translation>
+ </message>
+ <message>
+ <source>Clang Code Model</source>
+ <translation>Clang コードモデル</translation>
+ </message>
</context>
<context>
<name>CppTools::Internal::CppCodeStyleSettingsPage</name>
@@ -1989,7 +2241,7 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
</message>
<message>
<source>Content</source>
- <translation>内容</translation>
+ <translation>コンテンツ</translation>
</message>
<message>
<source>Indent</source>
@@ -2215,7 +2467,7 @@ if they would align to the next line</source>
<name>CppTools::Internal::CppFileSettingsPage</name>
<message>
<source>Headers</source>
- <translation>ヘッダー</translation>
+ <translation>ヘッダ</translation>
</message>
<message>
<source>&amp;Suffix:</source>
@@ -2231,11 +2483,11 @@ if they would align to the next line</source>
Paths can be absolute or relative to the directory of the current open document.
These paths are used in addition to current directory on Switch Header/Source.</source>
- <translation>コンマã§åŒºåˆ‡ã‚‰ã‚ŒãŸãƒ˜ãƒƒãƒ€ãƒ¼ã®ãƒ‘スã®ãƒªã‚¹ãƒˆã§ã™ã€‚
+ <translation>コンマã§åŒºåˆ‡ã‚‰ã‚ŒãŸãƒ˜ãƒƒãƒ€ã®ãƒ‘スã®ãƒªã‚¹ãƒˆã§ã™ã€‚
パスã¯çµ¶å¯¾ãƒ‘スã§ã‚‚ç¾åœ¨é–‹ã„ã¦ã„るドキュメントã®ã‚るディレクトリã‹ã‚‰ã®ç›¸å¯¾ãƒ‘スã§ã‚‚ã‹ã¾ã„ã¾ã›ã‚“。
-ã“れらã®ãƒ‘スã«åŠ ãˆã¦ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒãƒ˜ãƒƒãƒ€ãƒ¼ã¨ã‚½ãƒ¼ã‚¹ã®åˆ‡æ›¿æ™‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
+ã“れらã®ãƒ‘スã«åŠ ãˆã¦ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒãƒ˜ãƒƒãƒ€ã¨ã‚½ãƒ¼ã‚¹ã®åˆ‡æ›¿æ™‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
</message>
<message>
<source>Sources</source>
@@ -2259,7 +2511,7 @@ These paths are used in addition to current directory on Switch Header/Source.</
パスã¯çµ¶å¯¾ãƒ‘スã§ã‚‚ç¾åœ¨é–‹ã„ã¦ã„るドキュメントã®ã‚るディレクトリã‹ã‚‰ã®ç›¸å¯¾ãƒ‘スã§ã‚‚ã‹ã¾ã„ã¾ã›ã‚“。
-ã“れらã®ãƒ‘スã«åŠ ãˆã¦ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒãƒ˜ãƒƒãƒ€ãƒ¼ã¨ã‚½ãƒ¼ã‚¹ã®åˆ‡æ›¿æ™‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
+ã“れらã®ãƒ‘スã«åŠ ãˆã¦ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒãƒ˜ãƒƒãƒ€ã¨ã‚½ãƒ¼ã‚¹ã®åˆ‡æ›¿æ™‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
</message>
<message>
<source>&amp;Lower case file names</source>
@@ -2277,9 +2529,9 @@ These paths are used in addition to current directory on Switch Header/Source.</
<source>Comma-separated list of header prefixes.
These prefixes are used in addition to current file name on Switch Header/Source.</source>
- <translation>コンマã§åŒºåˆ‡ã‚‰ã‚ŒãŸãƒ˜ãƒƒãƒ€ãƒ¼ãƒ—レフィックスã®ãƒªã‚¹ãƒˆã€‚
+ <translation>コンマã§åŒºåˆ‡ã‚‰ã‚ŒãŸãƒ˜ãƒƒãƒ€ãƒ—レフィックスã®ãƒªã‚¹ãƒˆã€‚
-ã“れらã®ãƒ—レフィックスã¯ãƒ˜ãƒƒãƒ€ãƒ¼/ソースã®åˆ‡æ›¿æ™‚ã«ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«åã«ä»˜ä¸Žã™ã‚‹å½¢ã§ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
+ã“れらã®ãƒ—レフィックスã¯ãƒ˜ãƒƒãƒ€/ソースã®åˆ‡æ›¿æ™‚ã«ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«åã«ä»˜ä¸Žã™ã‚‹å½¢ã§ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
</message>
<message>
<source>P&amp;refixes:</source>
@@ -2291,7 +2543,19 @@ These prefixes are used in addition to current file name on Switch Header/Source
These prefixes are used in addition to current file name on Switch Header/Source.</source>
<translation>コンマã§åŒºåˆ‡ã‚‰ã‚ŒãŸã‚½ãƒ¼ã‚¹ãƒ—レフィックスã®ãƒªã‚¹ãƒˆã€‚
-ã“れらã®ãƒ—レフィックスã¯ãƒ˜ãƒƒãƒ€ãƒ¼/ソースã®åˆ‡æ›¿æ™‚ã«ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«åã«ä»˜ä¸Žã™ã‚‹å½¢ã§ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
+ã“れらã®ãƒ—レフィックスã¯ãƒ˜ãƒƒãƒ€/ソースã®åˆ‡æ›¿æ™‚ã«ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«åã«ä»˜ä¸Žã™ã‚‹å½¢ã§ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Include guards</source>
+ <translation>インクルードガード</translation>
+ </message>
+ <message>
+ <source>Uses &quot;#pragma once&quot; instead of &quot;#ifndef&quot; include guards.</source>
+ <translation>&quot;#ifndef&quot;インクルードガードã®ä»£ã‚ã‚Šã«&quot;#pragma once&quot;を使用ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Use &quot;#pragma once&quot; instead of &quot;#ifndef&quot; guards</source>
+ <translation>&quot;#ifndef&quot;ガードã®ä»£ã‚ã‚Šã«&quot;#pragma once&quot;を使用ã™ã‚‹</translation>
</message>
</context>
<context>
@@ -2377,6 +2641,10 @@ These prefixes are used in addition to current file name on Switch Header/Source
<translation>ランタイムエラーメッセージ(ãŸã¨ãˆã° assert() ã‹ã‚‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸)ã‚’æ•æ‰ã™ã‚‹ã®ã«ä¾¿åˆ©ã§ã™ã€‚</translation>
</message>
<message>
+ <source>CDB</source>
+ <translation>CDB</translation>
+ </message>
+ <message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Uses CDB&apos;s native console instead of Qt Creator&apos;s console for console applications. The native console does not prompt on application exit. It is suitable for diagnosing cases in which the application does not start up properly in Qt Creator&apos;s console and the subsequent attach fails.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;コンソールアプリケーション㧠Qt Creator ã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã®ä»£ã‚ã‚Šã« CDB ã®ãƒã‚¤ãƒ†ã‚£ãƒ–コンソールを使用ã—ã¾ã™ã€‚ãƒã‚¤ãƒ†ã‚£ãƒ–コンソールã¯ã‚¢ãƒ—リケーション終了時ã«ãƒ—ロンプトを表示ã—ã¾ã›ã‚“。アプリケーション㌠Qt Creator ã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã§æ­£å¸¸ã«èµ·å‹•ã§ããšã«ã‚¢ã‚¿ãƒƒãƒã«å¤±æ•—ã—ã¦ã—ã¾ã†ã‚ˆã†ãªã‚±ãƒ¼ã‚¹ã‚’診断ã™ã‚‹ã®ã«é©ã—ã¦ã„ã¾ã™ã€‚&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
@@ -2384,6 +2652,26 @@ These prefixes are used in addition to current file name on Switch Header/Source
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Attempts to correct the location of a breakpoint based on file and line number should it be in a comment or in a line for which no code is generated. The correction is based on the code model.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;コメントや実行コードãŒç”Ÿæˆã•ã‚Œãªã„部分ã¸ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã®æƒ…å ±(ファイルや行番å·)ã®è£œæ­£ã‚’試ã¿ã¾ã™ã€‚補正ã¯ã‚³ãƒ¼ãƒ‰ãƒ¢ãƒ‡ãƒ«ã«åŸºã¥ã„ã¦è¡Œã‚ã‚Œã¾ã™ã€‚&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Uses CDB&apos;s native console for console applications. This overrides the setting in Environment &gt; System. The native console does not prompt on application exit. It is suitable for diagnosing cases in which the application does not start up properly in the configured console and the subsequent attach fails.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;コンソールアプリケーション㧠CDB ã®ãƒã‚¤ãƒ†ã‚£ãƒ–コンソールを使用ã—ã¾ã™ã€‚ã“ã®è¨­å®šã¯ã€ï¼»ç’°å¢ƒï¼½ï¼žï¼»ã‚·ã‚¹ãƒ†ãƒ ï¼½ã®è¨­å®šã‚ˆã‚Šã‚‚優先ã•ã‚Œã¾ã™ã€‚ãƒã‚¤ãƒ†ã‚£ãƒ–コンソールã¯ã‚¢ãƒ—リケーション終了時ã«ãƒ—ロンプトを表示ã—ã¾ã›ã‚“。アプリケーション㌠Qt Creator ã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã§æ­£å¸¸ã«èµ·å‹•ã§ããšã«ã‚¢ã‚¿ãƒƒãƒã«å¤±æ•—ã—ã¦ã—ã¾ã†ã‚ˆã†ãªã‚±ãƒ¼ã‚¹ã‚’診断ã™ã‚‹ã®ã«é©ã—ã¦ã„ã¾ã™ã€‚&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <source>Use Python dumper</source>
+ <translation>Python ダンパを使ã†</translation>
+ </message>
+ <message>
+ <source>Add Exceptions to Issues View</source>
+ <translation>å•é¡Œãƒ“ューã«ä¾‹å¤–を追加</translation>
+ </message>
+ <message>
+ <source>First chance exceptions</source>
+ <translation>ファーストãƒãƒ£ãƒ³ã‚¹ã®ä¾‹å¤–</translation>
+ </message>
+ <message>
+ <source>Second chance exceptions</source>
+ <translation>セカンドãƒãƒ£ãƒ³ã‚¹ã®ä¾‹å¤–</translation>
+ </message>
</context>
<context>
<name>Debugger::Internal::SymbolPathsDialog</name>
@@ -2549,6 +2837,42 @@ These prefixes are used in addition to current file name on Switch Header/Source
<source>Vim tabstop option.</source>
<translation>Vim ã® tabstop オプションã§ã™ã€‚</translation>
</message>
+ <message>
+ <source>Does not interpret key sequences like Ctrl-S in FakeVim but handles them as regular shortcuts. This gives easier access to core functionality at the price of losing some features of FakeVim.</source>
+ <translation>FakeVim ã® Ctrl-S ã®ã‚ˆã†ãªã‚­ãƒ¼ã‚·ãƒ¼ã‚±ãƒ³ã‚¹ã‚’解釈ã›ãšã€é€šå¸¸ã®ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆã¨ã—ã¦æ‰±ã„ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ã‚³ã‚¢æ©Ÿèƒ½ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒå®¹æ˜“ã«ãªã‚Šã¾ã™ãŒã€ FakeVim ã®ã„ãã¤ã‹ã®æ©Ÿèƒ½ã¯å¤±ã‚ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Does not interpret some key presses in insert mode so that code can be properly completed and expanded.</source>
+ <translation>挿入モードã§ä¸€éƒ¨ã®ã‚­ãƒ¼ã‚’押ã—ã¦ã‚‚解釈ã—ãªã„ãŸã‚ã€ã‚³ãƒ¼ãƒ‰ãŒé©åˆ‡ã«è£œå®Œãƒ»å±•é–‹ã•ã‚Œã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Blinking cursor</source>
+ <translation>カーソルã®ç‚¹æ»…</translation>
+ </message>
+ <message>
+ <source>Plugin Emulation</source>
+ <translation>プラグイン・エミュレーション</translation>
+ </message>
+ <message>
+ <source>vim-exchange</source>
+ <translation>vim-exchange</translation>
+ </message>
+ <message>
+ <source>argtextobj.vim</source>
+ <translation>argtextobj.vim</translation>
+ </message>
+ <message>
+ <source>ReplaceWithRegister</source>
+ <translation>ReplaceWithRegister</translation>
+ </message>
+ <message>
+ <source>vim-commentary</source>
+ <translation>vim-commentary</translation>
+ </message>
+ <message>
+ <source>vim-surround</source>
+ <translation>vim-surround</translation>
+ </message>
</context>
<context>
<name>GenericProjectManager::Internal::GenericMakeStep</name>
@@ -2588,12 +2912,32 @@ These prefixes are used in addition to current file name on Switch Header/Source
<translation>ブランãƒåã®å¤‰æ›´</translation>
</message>
<message>
+ <source>Add Tag</source>
+ <translation>タグを追加</translation>
+ </message>
+ <message>
+ <source>Tag name:</source>
+ <translation>ã‚¿ã‚°å:</translation>
+ </message>
+ <message>
+ <source>Rename Tag</source>
+ <translation>ã‚¿ã‚°åã®å¤‰æ›´</translation>
+ </message>
+ <message>
+ <source>Track remote branch &quot;%1&quot;</source>
+ <translation>リモート・ブランム&quot;%1&quot; を追跡ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Track local branch &quot;%1&quot;</source>
+ <translation>ローカル・ブランム&quot;%1&quot; を追跡ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Track remote branch &apos;%1&apos;</source>
<translation>リモートブランム&apos;%1&apos; を追跡ã™ã‚‹</translation>
</message>
<message>
- <source>Track local branch &apos;%1&apos;</source>
- <translation>ローカルブランム&apos;%1&apos; を追跡ã™ã‚‹</translation>
+ <source>Checkout new branch</source>
+ <translation>æ–°ã—ã„ブランãƒã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ</translation>
</message>
</context>
<context>
@@ -2655,7 +2999,7 @@ These prefixes are used in addition to current file name on Switch Header/Source
</message>
<message>
<source>Re&amp;name</source>
- <translation>åå‰ã‚’変更(&amp;R)</translation>
+ <translation type="vanished">åå‰ã‚’変更(&amp;N)</translation>
</message>
<message>
<source>&amp;Checkout</source>
@@ -2822,6 +3166,10 @@ These prefixes are used in addition to current file name on Switch Header/Source
<source>Select a Git Commit</source>
<translation>Git コミットã®é¸æŠž</translation>
</message>
+ <message>
+ <source>&amp;Archive...</source>
+ <translation>アーカイブã™ã‚‹(&amp;A)...</translation>
+ </message>
</context>
<context>
<name>Gerrit::Internal::GerritPushDialog</name>
@@ -2850,10 +3198,44 @@ These prefixes are used in addition to current file name on Switch Header/Source
<translation>レビュアー(&amp;R):</translation>
</message>
<message>
+ <source>Cannot find a Gerrit remote. Add one and try again.</source>
+ <translation>リモート㮠Gerrit ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。追加ã—ã¦å†åº¦ãŠè©¦ã—ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>Number of commits between %1 and %2: %3</source>
<translation>%1 㨠%2 é–“ã®ã‚³ãƒŸãƒƒãƒˆæ•°: %3</translation>
</message>
<message>
+ <source>Are you sure you selected the right target branch?</source>
+ <translation>ターゲットブランãƒã®é¸æŠžã¯é–“é•ã£ã¦ã„ãªã„ã§ã—ょã†ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Checked - Mark change as WIP.
+Unchecked - Mark change as ready for review.
+Partially checked - Do not change current state.</source>
+ <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆ - 変更点を WIP ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¾ã™ã€‚
+未ãƒã‚§ãƒƒã‚¯ - 変更点をレビューã™ã‚‹æº–å‚™ãŒã§ãã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã™ã€‚
+一部ãƒã‚§ãƒƒã‚¯ - ç¾åœ¨ã®çŠ¶æ…‹ã‚’変更ã—ãªã„。</translation>
+ </message>
+ <message>
+ <source>Supported on Gerrit 2.15 and later.</source>
+ <translation>Gerrit 2.15 以é™ã§ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Checked - The change is a draft.
+Unchecked - The change is not a draft.</source>
+ <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆ - 変更点ã¯ãƒ‰ãƒ©ãƒ•ãƒˆã§ã™ã€‚
+未ãƒã‚§ãƒƒã‚¯ - 変更点ã¯ãƒ‰ãƒ©ãƒ•ãƒˆã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>No remote branches found. This is probably the initial commit.</source>
+ <translation>リモートブランãƒã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ã“ã‚ŒãŒæœ€åˆã®ã‚³ãƒŸãƒƒãƒˆã§ã‚ã‚‹å¯èƒ½æ€§ãŒé«˜ã„ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Branch name</source>
+ <translation>ブランãƒå</translation>
+ </message>
+ <message>
<source>... Include older branches ...</source>
<translation>... よりå¤ã„ブランãƒã‚’å«ã‚ã‚‹ ...</translation>
</message>
@@ -2885,6 +3267,22 @@ Partial names can be used if they are unambiguous.</source>
<source>To:</source>
<translation>To:</translation>
</message>
+ <message>
+ <source>Checked - Mark change as private.
+Unchecked - Remove mark.
+Partially checked - Do not change current state.</source>
+ <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆ - 変更点をプライベートã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¾ã™ã€‚
+未ãƒã‚§ãƒƒã‚¯ - マークを削除ã—ã¾ã™ã€‚
+一部ãƒã‚§ãƒƒã‚¯ - ç¾åœ¨ã®çŠ¶æ…‹ã‚’変更ã—ãªã„。</translation>
+ </message>
+ <message>
+ <source>&amp;Draft/private</source>
+ <translation>ドラフト/プライベート(&amp;D)</translation>
+ </message>
+ <message>
+ <source>&amp;Work-in-progress</source>
+ <translation>作業中(&amp;WIP)</translation>
+ </message>
</context>
<context>
<name>Git::Internal::GitSubmitPanel</name>
@@ -2923,6 +3321,15 @@ Partial names can be used if they are unambiguous.</source>
<message>
<source>By&amp;pass hooks:</source>
<translation>フックをãƒã‚¤ãƒ‘スã™ã‚‹(&amp;P):</translation>
+ <translation type="vanished">フックをãƒã‚¤ãƒ‘スã™ã‚‹(&amp;P):</translation>
+ </message>
+ <message>
+ <source>By&amp;pass hooks</source>
+ <translation>フックをãƒã‚¤ãƒ‘スã™ã‚‹(&amp;P)</translation>
+ </message>
+ <message>
+ <source>Sign off</source>
+ <translation>サインオフ</translation>
</message>
</context>
<context>
@@ -2967,6 +3374,14 @@ Partial names can be used if they are unambiguous.</source>
<translation>削除(&amp;R)</translation>
</message>
<message>
+ <source>A remote with the name &quot;%1&quot; already exists.</source>
+ <translation>&quot;%1&quot; ã¨ã„ã†åå‰ã®ãƒªãƒ¢ãƒ¼ãƒˆã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The URL may not be valid.</source>
+ <translation>URL ãŒæœ‰åŠ¹ã§ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Delete Remote</source>
<translation>リモートを削除</translation>
</message>
@@ -3353,6 +3768,15 @@ Add, modify, and remove document filters, which determine the documentation set
<translation>一般</translation>
</message>
<message>
+ <source>Change takes effect after reloading help pages.</source>
+ <translation>ヘルプページã®å†èª­ã¿è¾¼ã¿å¾Œã«å¤‰æ›´ãŒå映ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Default (%1)</source>
+ <comment>Default viewer backend</comment>
+ <translation>デフォルト (%1)</translation>
+ </message>
+ <message>
<source>Import Bookmarks</source>
<translation>ブックマークをインãƒãƒ¼ãƒˆ</translation>
</message>
@@ -3384,6 +3808,26 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Always Show in External Window</source>
<translation>常ã«åˆ¥ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§è¡¨ç¤º</translation>
</message>
+ <message>
+ <source>Note: The above setting takes effect only if the HTML file does not use a style sheet.</source>
+ <translation>注:上記ã®è¨­å®šã¯ã€HTML ファイルãŒã‚¹ã‚¿ã‚¤ãƒ«ã‚·ãƒ¼ãƒˆã‚’使用ã—ã¦ã„ãªã„å ´åˆã«ã®ã¿æœ‰åŠ¹ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Zoom:</source>
+ <translation>拡大率:</translation>
+ </message>
+ <message>
+ <source>%</source>
+ <translation>%</translation>
+ </message>
+ <message>
+ <source>Enable scroll wheel zooming</source>
+ <translation>スクロールホイールã«ã‚ˆã‚‹ã‚ºãƒ¼ãƒ ã‚’有効ã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Viewer backend:</source>
+ <translation>ビューアーã®ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰:</translation>
+ </message>
</context>
<context>
<name>Help::Internal::RemoteFilterOptions</name>
@@ -3430,6 +3874,10 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Export as Image</source>
<translation>ç”»åƒã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ</translation>
</message>
+ <message>
+ <source>Export Images of Multiple Sizes</source>
+ <translation>複数ã®ã‚µã‚¤ã‚ºã®ç”»åƒã‚’エクスãƒãƒ¼ãƒˆã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>Ios::Internal::IosBuildStep</name>
@@ -3446,6 +3894,11 @@ Add, modify, and remove document filters, which determine the documentation set
<translation>追加引数:</translation>
</message>
<message>
+ <source>iOS build</source>
+ <comment>iOS BuildStep display name.</comment>
+ <translation>iOS ビルド</translation>
+ </message>
+ <message>
<source>xcodebuild</source>
<translation>xcodebuild</translation>
</message>
@@ -3502,6 +3955,10 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Description:</source>
<translation>説明:</translation>
</message>
+ <message>
+ <source>Macros</source>
+ <translation>マクロ</translation>
+ </message>
</context>
<context>
<name>Macros::Internal::SaveDialog</name>
@@ -3666,7 +4123,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>For example: &apos;https://[user[:pass]@]host[:port]/[path]&apos;.</source>
- <translation>例: &apos;https://[user[:pass]@]host[:port]/[path]&apos;</translation>
+ <translation>例: &apos;https://[user[:pass]@]host[:port]/[path]&apos;.</translation>
</message>
</context>
<context>
@@ -3765,6 +4222,18 @@ Add, modify, and remove document filters, which determine the documentation set
<translation>テスト</translation>
</message>
<message>
+ <source>Perforce Command</source>
+ <translation>Perforce コマンド</translation>
+ </message>
+ <message>
+ <source>Testing...</source>
+ <translation>自動テスト...</translation>
+ </message>
+ <message>
+ <source>Test succeeded (%1).</source>
+ <translation>テストãŒæˆåŠŸã—ã¾ã—㟠(%1)。</translation>
+ </message>
+ <message>
<source>Perforce</source>
<translation>Perforce</translation>
</message>
@@ -3998,6 +4467,10 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Show Running Processes...</source>
<translation>実行中ã®ãƒ—ロセスを表示...</translation>
</message>
+ <message>
+ <source>Devices</source>
+ <translation>デãƒã‚¤ã‚¹</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::DeviceTestDialog</name>
@@ -4051,6 +4524,14 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Display right &amp;margin at column:</source>
<translation>å³ãƒžãƒ¼ã‚¸ãƒ³ã‚’表示ã™ã‚‹åˆ—ä½ç½®(&amp;M):</translation>
</message>
+ <message>
+ <source>If available, use a different margin. For example, the ColumnLimit from the ClangFormat plugin.</source>
+ <translation type="vanished">å¯èƒ½ã§ã‚ã‚Œã°ã€åˆ¥ã®ãƒžãƒ¼ã‚¸ãƒ³ã‚’使用ã—ã¦ãã ã•ã„。例ãˆã°ã€clangFormatプラグインã®ColumnLimitãªã©ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Use context-specific margin</source>
+ <translation>文脈ã«å¿œã˜ãŸãƒžãƒ¼ã‚¸ãƒ³ã‚’使用ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::ProcessStepWidget</name>
@@ -4177,6 +4658,62 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Same Build Directory</source>
<translation>åŒä¸€ãƒ“ルドディレクトリ</translation>
</message>
+ <message>
+ <source>Closing Projects</source>
+ <translation>プロジェクトを閉ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close source files along with project</source>
+ <translation>プロジェクトã¨ä¸€ç·’ã«ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Abort on error when building all projects</source>
+ <translation>ã™ã¹ã¦ã®ãƒ—ロジェクトをビルドã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸã‚‰ä¸­æ­¢ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Enable this if your system becomes unresponsive while building.</source>
+ <translation>ビルド中ã«ã‚·ã‚¹ãƒ†ãƒ ãŒåå¿œã—ãªããªã‚‹å ´åˆã«æœ‰åŠ¹ã«ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Start build processes with low priority</source>
+ <translation>優先度ã®ä½Žã„ビルドプロセスを開始ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add linker library search paths to run environment</source>
+ <translation>リンカã®ãƒ©ã‚¤ãƒ–ラリ検索パスを実行環境ã«è¿½åŠ ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Creates suitable run configurations automatically when setting up a new kit.</source>
+ <translation>æ–°ã—ã„キットをセットアップã™ã‚‹éš›ã«ã€é©åˆ‡ãªå®Ÿè¡Œæ§‹æˆã‚’自動的ã«ä½œæˆã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Create suitable run configurations automatically</source>
+ <translation>é©åˆ‡ãªå®Ÿè¡Œæ§‹æˆã‚’自動的ã«ä½œæˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Clear issues list on new build</source>
+ <translation>æ–°ã—ã„ビルド時ã«èª²é¡Œãƒªã‚¹ãƒˆã‚’クリアã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Build before deploying:</source>
+ <translation>デプロイã™ã‚‹å‰ã«ãƒ“ルドã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>Default for &quot;Run in terminal&quot;:</source>
+ <translation>&quot;ターミナルã§å®Ÿè¡Œ&quot;ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆ:</translation>
+ </message>
+ <message>
+ <source>Enabled</source>
+ <translation>有効</translation>
+ </message>
+ <message>
+ <source>Disabled</source>
+ <translation>無効</translation>
+ </message>
+ <message>
+ <source>Deduced from Project</source>
+ <translation>プロジェクトã‹ã‚‰æŽ¨æ¸¬ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::WizardPage</name>
@@ -4251,6 +4788,10 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Rename Session</source>
<translation>セッションã®ãƒªãƒãƒ¼ãƒ </translation>
</message>
+ <message>
+ <source>&amp;Switch To</source>
+ <translation>切り替ãˆ(&amp;S)</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::TargetSettingsWidget</name>
@@ -4290,6 +4831,22 @@ Add, modify, and remove document filters, which determine the documentation set
<translation>フラグ:</translation>
</message>
<message>
+ <source>Installation flags:</source>
+ <translation>インストールフラグ:</translation>
+ </message>
+ <message>
+ <source>Installation directory:</source>
+ <translation>インストールディレクトリ:</translation>
+ </message>
+ <message>
+ <source>Use default location</source>
+ <translation>デフォルトã®ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Property &quot;%1&quot; cannot be set here. Please use the dedicated UI element.</source>
+ <translation>プロパティ &quot;%1&quot; ã¯ã“ã“ã§ã¯è¨­å®šã§ãã¾ã›ã‚“。専用㮠UI è¦ç´ ã‚’使用ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>Keep going</source>
<translation>ビルドを継続ã™ã‚‹</translation>
</message>
@@ -4412,7 +4969,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>The header file</source>
- <translation>ヘッダーファイル</translation>
+ <translation>ヘッダファイル</translation>
</message>
<message>
<source>&amp;Sources</source>
@@ -4428,11 +4985,11 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Widget h&amp;eader file:</source>
- <translation>ウィジェットヘッダーファイル(&amp;E):</translation>
+ <translation>ウィジェットヘッダファイル(&amp;E):</translation>
</message>
<message>
<source>The header file has to be specified in source code.</source>
- <translation>ソースコードã§æŒ‡å®šã•ã‚Œã‚‹ãƒ˜ãƒƒãƒ€ãƒ¼ãƒ•ã‚¡ã‚¤ãƒ«ã€‚</translation>
+ <translation>ソースコードã§æŒ‡å®šã•ã‚Œã‚‹ãƒ˜ãƒƒãƒ€ãƒ•ã‚¡ã‚¤ãƒ«ã€‚</translation>
</message>
<message>
<source>Widge&amp;t source file:</source>
@@ -4452,7 +5009,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Plugin &amp;header file:</source>
- <translation>プラグインヘッダーファイル(&amp;H):</translation>
+ <translation>プラグインヘッダファイル(&amp;H):</translation>
</message>
<message>
<source>Plugin sou&amp;rce file:</source>
@@ -4531,7 +5088,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Collection header file:</source>
- <translation>コレクションヘッダーファイル:</translation>
+ <translation>コレクションヘッダファイル:</translation>
</message>
<message>
<source>Collection source file:</source>
@@ -4655,6 +5212,10 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Remove &quot;d&quot; suffix for release version</source>
<translation>リリース版ã‹ã‚‰ã¯ &quot;d&quot; 後置詞を削除ã™ã‚‹</translation>
</message>
+ <message>
+ <source>Library type:</source>
+ <translation>ライブラリタイプ:</translation>
+ </message>
</context>
<context>
<name>QmakeProjectManager::Internal::MakeStep</name>
@@ -4829,7 +5390,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Checked</source>
- <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆã¿</translation>
+ <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆ</translation>
</message>
<message>
<source>Text displayed on the button.</source>
@@ -4908,7 +5469,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Checked</source>
- <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆã¿</translation>
+ <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆ</translation>
</message>
<message>
<source>Focus on press</source>
@@ -4950,7 +5511,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Checked</source>
- <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆã¿</translation>
+ <translation>ãƒã‚§ãƒƒã‚¯æ¸ˆ</translation>
</message>
<message>
<source>Determines whether the radio button is checked or not.</source>
@@ -4989,7 +5550,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Document margins</source>
- <translation>ドキュメントマージン</translation>
+ <translation>ドキュメントã®ãƒžãƒ¼ã‚¸ãƒ³</translation>
</message>
<message>
<source>Frame width</source>
@@ -5188,6 +5749,10 @@ Add, modify, and remove document filters, which determine the documentation set
<translation>高ã•</translation>
</message>
<message>
+ <source>The made changes will take effect after a restart of the QML Emulation layer or %1.</source>
+ <translation>変更ã—ãŸå†…容ã¯ã€QML Emulation レイヤã¾ãŸã¯ %1 ã®å†èµ·å‹•å¾Œã«æœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Qt Quick Designer</source>
<translation>Qt Quick Designer</translation>
</message>
@@ -5319,6 +5884,70 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Warn about using .qml files instead of .ui.qml files</source>
<translation>.ui.qml ファイルã§ã¯ãªã .qml ファイルを使用ã™ã‚‹å ´åˆã«è­¦å‘Šã™ã‚‹</translation>
</message>
+ <message>
+ <source>Parent component padding:</source>
+ <translation>親コンãƒãƒ¼ãƒãƒ³ãƒˆã®ãƒ‘ディング:</translation>
+ </message>
+ <message>
+ <source>Sibling component spacing:</source>
+ <translation>兄弟コンãƒãƒ¼ãƒãƒ³ãƒˆã¨ã®é–“éš”:</translation>
+ </message>
+ <message>
+ <source>Width:</source>
+ <translation>å¹…:</translation>
+ </message>
+ <message>
+ <source>Height:</source>
+ <translation>高ã•:</translation>
+ </message>
+ <message>
+ <source>Root Item Init Size</source>
+ <translation type="vanished">ルートアイテム イニシャルサイズ</translation>
+ </message>
+ <message>
+ <source>Controls 2 style:</source>
+ <translation>Controls 2 ã®ã‚¹ã‚¿ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Path to the QML emulation layer executable (qmlpuppet).</source>
+ <translation>QML エミュレーションレイヤーã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ« (qmlpuppet) ã¸ã®ãƒ‘ス。</translation>
+ </message>
+ <message>
+ <source>Resets the path to the built-in QML emulation layer.</source>
+ <translation>パスを内蔵㮠QML エミュレーションレイヤーã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Use QML emulation layer that is built with the selected Qt</source>
+ <translation>é¸æŠžã—㟠Qt ã§ãƒ“ルドã•ã‚ŒãŸ QML エミュレーション・レイヤーを使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Warn about unsupported features of .ui.qml files in code editor</source>
+ <translation>.ui.qml ファイル ã§æœªå¯¾å¿œã®æ©Ÿèƒ½ã‚’コードエディタ内ã§è­¦å‘Šã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>qsTranslate()</source>
+ <translation>qsTranslate()</translation>
+ </message>
+ <message>
+ <source>Features</source>
+ <translation>機能</translation>
+ </message>
+ <message>
+ <source>Enable Timeline editor</source>
+ <translation>タイムライン・エディターを有効ã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Always open ui.qml files in Design mode</source>
+ <translation>ui.qml ファイルを常ã«ãƒ‡ã‚¶ã‚¤ãƒ³ãƒ¢ãƒ¼ãƒ‰ã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Root Component Init Size</source>
+ <translation>ルートコンãƒãƒ¼ãƒãƒ³ãƒˆã®åˆæœŸã‚µã‚¤ã‚º</translation>
+ </message>
+ <message>
+ <source>Warn about unsupported features in .ui.qml files</source>
+ <translation>.ui.qml ファイルã§æœªå¯¾å¿œã®æ©Ÿèƒ½ã‚’警告ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>QmlJSEditor::Internal::ComponentNameDialog</name>
@@ -5347,6 +5976,14 @@ Add, modify, and remove document filters, which determine the documentation set
<translation>無効ãªãƒ‘ス</translation>
</message>
<message>
+ <source>Component already exists</source>
+ <translation>コンãƒãƒ¼ãƒãƒ³ãƒˆã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Component exists already</source>
+ <translation type="vanished">コンãƒãƒ¼ãƒãƒ³ãƒˆãŒæ—¢ã«å­˜åœ¨ã—ã¦ã„ã‚‹</translation>
+ </message>
+ <message>
<source>Property assignments for</source>
<translation>残ã™ãƒ—ロパティ</translation>
</message>
@@ -5354,6 +5991,10 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Component Name</source>
<translation>コンãƒãƒ¼ãƒãƒ³ãƒˆå</translation>
</message>
+ <message>
+ <source>ui.qml file</source>
+ <translation>ui.qml ファイル</translation>
+ </message>
</context>
<context>
<name>QmlJSEditor::Internal::QuickToolBarSettingsPage</name>
@@ -5400,6 +6041,10 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Duration</source>
<translation>æŒç¶šæ™‚é–“</translation>
</message>
+ <message>
+ <source>Close</source>
+ <translation>é–‰ã˜ã‚‹</translation>
+ </message>
</context>
<context>
<name>QmlProfiler::Internal::QmlProfilerAttachDialog</name>
@@ -5428,6 +6073,10 @@ Add, modify, and remove document filters, which determine the documentation set
<translation>QML プロファイラã®é–‹å§‹</translation>
</message>
<message>
+ <source>Select an externally started QML-debug enabled application.&lt;p&gt;Commonly used command-line arguments are:</source>
+ <translation>外部ã‹ã‚‰èµ·å‹•ã•ã‚ŒãŸ QML-debug 対応ã®ã‚¢ãƒ—リケーションをé¸æŠžã—ã¾ã™ã€‚&lt;p&gt;一般的ã«ä½¿ç”¨ã•ã‚Œã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³å¼•æ•°ã¯ä»¥ä¸‹ã®é€šã‚Šã§ã™:</translation>
+ </message>
+ <message>
<source>Kit:</source>
<translation>キット:</translation>
</message>
@@ -5461,6 +6110,14 @@ Add, modify, and remove document filters, which determine the documentation set
<source>Clean Up</source>
<translation>クリーンアップ</translation>
</message>
+ <message>
+ <source>Register documentation:</source>
+ <translation>ドキュメントを登録ã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>Link with Qt...</source>
+ <translation>Qt ã«ãƒªãƒ³ã‚¯ã™ã‚‹...</translation>
+ </message>
</context>
<context>
<name>QtSupport::Internal::ShowBuildLog</name>
@@ -5563,6 +6220,14 @@ Add, modify, and remove document filters, which determine the documentation set
<source>&amp;Check host key</source>
<translation>ホストéµã®ç¢ºèª(&amp;C)</translation>
</message>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+ <message>
+ <source>Specific &amp;key</source>
+ <translation>特定ã®ã‚­ãƒ¼(&amp;K)</translation>
+ </message>
</context>
<context>
<name>RemoteLinux::Internal::GenericLinuxDeviceConfigurationWizardSetupPage</name>
@@ -5646,7 +6311,15 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Remove Missing Files</source>
- <translation>存在ã—ãªã„ファイルã®å‰Šé™¤</translation>
+ <translation>存在ã—ãªã„ファイルを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add Prefix</source>
+ <translation>プレフィックスã®è¿½åŠ </translation>
+ </message>
+ <message>
+ <source>Add Files</source>
+ <translation>ファイルã®è¿½åŠ </translation>
</message>
</context>
<context>
@@ -5907,6 +6580,42 @@ Backspace キーãŒæŠ¼ã•ã‚ŒãŸæ™‚ã®ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã®å‹•ä½œã‚’指定ã—ã¾ã™ã
<source>Enable smart selection changing</source>
<translation>スマートãªé¸æŠžå¤‰æ›´ã‚’有効ã«ã™ã‚‹</translation>
</message>
+ <message>
+ <source>For the file patterns listed, do not trim trailing whitespace.</source>
+ <translation>リストアップã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ãƒ‘ターンã§ã¯ã€æœ«å°¾ã®ç©ºç™½æ–‡å­—を削除ã—ãªã„。</translation>
+ </message>
+ <message>
+ <source>Skip clean whitespace for file types:</source>
+ <translation>空白文字除去をスキップã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚¿ã‚¤ãƒ—:</translation>
+ </message>
+ <message>
+ <source>List of wildcard-aware file patterns, separated by commas or semicolons.</source>
+ <translation>ワイルドカード形å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ãƒ‘ターンをカンマã¾ãŸã¯ã‚»ãƒŸã‚³ãƒ­ãƒ³ã§åŒºåˆ‡ã£ãŸä¸€è¦§ã«ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;
+&lt;p&gt;How text editors should deal with UTF-8 Byte Order Marks. The options are:&lt;/p&gt;
+&lt;ul &gt;&lt;li&gt;&lt;i&gt;Add If Encoding Is UTF-8:&lt;/i&gt; always add a BOM when saving a file in UTF-8 encoding. Note that this will not work if the encoding is &lt;i&gt;System&lt;/i&gt;, as the text editor does not know what it actually is.&lt;/li&gt;
+&lt;li&gt;&lt;i&gt;Keep If Already Present: &lt;/i&gt;save the file with a BOM if it already had one when it was loaded.&lt;/li&gt;
+&lt;li&gt;&lt;i&gt;Always Delete:&lt;/i&gt; never write an UTF-8 BOM, possibly deleting a pre-existing one.&lt;/li&gt;&lt;/ul&gt;
+&lt;p&gt;Note that UTF-8 BOMs are uncommon and treated incorrectly by some editors, so it usually makes little sense to add any.&lt;/p&gt;
+&lt;p&gt;This setting does &lt;b&gt;not&lt;/b&gt; influence the use of UTF-16 and UTF-32 BOMs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;
+&lt;p&gt;ã“ã®ã‚ªãƒ—ションã§ã€ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ã«ãŠã‘ã‚‹ UTF-8 ã® BOM (Byte Order Mark) ã®å‡¦ç†æ–¹æ³•ã‚’指定ã—ã¾ã™ã€‚&lt;/p&gt;
+&lt;ul &gt;&lt;li&gt;&lt;i&gt;文字コード㌠UTF-8 ã®æ™‚ã«è¿½åŠ :&lt;/i&gt; ファイルã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ãŒ UTF-8 ã®æ™‚ã«ã¯å¸¸ã« BOM を追加ã—ã¾ã™ã€‚エンコーディング㌠&lt;i&gt;System&lt;/i&gt; ã®å ´åˆã€Qt Creator ãŒå®Ÿéš›ã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚’知るã“ã¨ãŒã§ããªã„ãŸã‚ã€ã“ã®ã‚ªãƒ—ションã¯æ©Ÿèƒ½ã—ã¾ã›ã‚“。&lt;/li&gt;
+&lt;li&gt;&lt;i&gt;読込時ã®çŠ¶æ…‹ã‚’ä¿å­˜:&lt;/i&gt; ファイルã®èª­è¾¼æ™‚ã« BOM ãŒå­˜åœ¨ã—ãŸå ´åˆã®ã¿ã€BOM 付ãã§ä¿å­˜ã—ã¾ã™ã€‚&lt;/li&gt;
+&lt;li&gt;&lt;i&gt;常ã«å‰Šé™¤ã™ã‚‹:&lt;/i&gt; UTF-8 BOM を常ã«å‰Šé™¤ã—ã¾ã™ã€‚読込時㫠BOM ãŒå­˜åœ¨ã—ã¦ã„ãŸå ´åˆã§ã‚‚削除ã—ã¾ã™ã€‚&lt;/li&gt;&lt;/ul&gt;
+&lt;p&gt;UTF-8 BOM ã®åˆ©ç”¨ã¯ä¸€èˆ¬çš„ã§ã¯ç„¡ãã€ã‚¨ãƒ‡ã‚£ã‚¿ã«ã‚ˆã£ã¦ã¯æ­£å¸¸ã«æ‰±ãˆãªã„ã“ã¨ãŒã‚ã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。多ãã®å ´åˆã¯ BOM を追加ã™ã‚‹ã“ã¨ã«æ„味ã¯ã‚ã‚Šã¾ã›ã‚“。&lt;/p&gt;
+&lt;p&gt;ã“ã®è¨­å®šã¯ UTF-16 ã‚„ UTF-32 ã® BOM ã«ã¯&lt;b&gt;影響ã—ã¾ã›ã‚“&lt;/b&gt;。&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <source>Default line endings:</source>
+ <translation>デフォルトã®æ”¹è¡Œã‚³ãƒ¼ãƒ‰:</translation>
+ </message>
+ <message>
+ <source>Prefer single line comments</source>
+ <translation>一行形å¼ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’優先ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>TextEditor::Internal::CodeStyleSelectorWidget</name>
@@ -5975,7 +6684,7 @@ Backspace キーãŒæŠ¼ã•ã‚ŒãŸæ™‚ã®ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã®å‹•ä½œã‚’指定ã—ã¾ã™ã
</message>
<message>
<source>No Underline</source>
- <translation>下線ãªã— </translation>
+ <translation>下線ãªã—</translation>
</message>
<message>
<source>Single Underline</source>
@@ -6001,6 +6710,38 @@ Backspace キーãŒæŠ¼ã•ã‚ŒãŸæ™‚ã®ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã®å‹•ä½œã‚’指定ã—ã¾ã™ã
<source>Dash-Dot-Dot Underline</source>
<translation>二点鎖線</translation>
</message>
+ <message>
+ <source>&lt;p align=&apos;center&apos;&gt;&lt;b&gt;Builtin color schemes need to be &lt;a href=&quot;copy&quot;&gt;copied&lt;/a&gt;&lt;br/&gt; before they can be changed&lt;/b&gt;&lt;/p&gt;</source>
+ <translation>&lt;p align=&apos;center&apos;&gt;&lt;b&gt;組ã¿è¾¼ã¿ã®é…色を変更ã™ã‚‹ã«ã¯ã€&lt;a href=&quot;copy&quot;&gt;コピー&lt;/a&gt;&lt;br/&gt;ãŒå¿…è¦ã§ã™</translation>
+ </message>
+ <message>
+ <source>Lightness:</source>
+ <translation>è¼åº¦:</translation>
+ </message>
+ <message>
+ <source>Saturation:</source>
+ <translation>彩度:</translation>
+ </message>
+ <message>
+ <source>Underline</source>
+ <translation>下線</translation>
+ </message>
+ <message>
+ <source>Relative Foreground</source>
+ <translation>相対的ãªå‰æ™¯è‰²</translation>
+ </message>
+ <message>
+ <source>Relative Background</source>
+ <translation>相対的ãªèƒŒæ™¯è‰²</translation>
+ </message>
+ <message>
+ <source>Font</source>
+ <translation>フォント</translation>
+ </message>
+ <message>
+ <source>Color:</source>
+ <translation>色:</translation>
+ </message>
</context>
<context>
<name>TextEditor::Internal::DisplaySettingsPage</name>
@@ -6076,6 +6817,46 @@ Backspace キーãŒæŠ¼ã•ã‚ŒãŸæ™‚ã®ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã®å‹•ä½œã‚’指定ã—ã¾ã™ã
<source>Highlight search results on the scrollbar</source>
<translation>検索çµæžœã‚’スクロールãƒãƒ¼ä¸Šã§ãƒã‚¤ãƒ©ã‚¤ãƒˆè¡¨ç¤ºã™ã‚‹</translation>
</message>
+ <message>
+ <source>Animate navigation within file</source>
+ <translation>ファイル内ã®ãƒŠãƒ“ゲーションをアニメーション化ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Line annotations</source>
+ <translation>ラインアノテーション</translation>
+ </message>
+ <message>
+ <source>Next to editor content</source>
+ <translation>エディターコンテンツã®éš£</translation>
+ </message>
+ <message>
+ <source>Next to right margin</source>
+ <translation>å³ãƒžãƒ¼ã‚¸ãƒ³ã®éš£</translation>
+ </message>
+ <message>
+ <source>Aligned at right side</source>
+ <translation>å³å´ã«æ•´åˆ—</translation>
+ </message>
+ <message>
+ <source>Between lines</source>
+ <translation>行間</translation>
+ </message>
+ <message>
+ <source>If available, use a different margin. For example, the ColumnLimit from the clang-format plugin.</source>
+ <translation type="vanished">å¯èƒ½ã§ã‚ã‚Œã°ã€åˆ¥ã®ãƒžãƒ¼ã‚¸ãƒ³ã‚’使用ã—ã¦ãã ã•ã„。例ãˆã°ã€clang-formatプラグインã®ColumnLimitãªã©ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Use context specific margin</source>
+ <translation type="vanished">文脈ã«å¿œã˜ãŸãƒžãƒ¼ã‚¸ãƒ³ã‚’使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>If available, use a different margin. For example, the ColumnLimit from the ClangFormat plugin.</source>
+ <translation>å¯èƒ½ã§ã‚ã‚Œã°ã€åˆ¥ã®ãƒžãƒ¼ã‚¸ãƒ³ã‚’使用ã—ã¦ãã ã•ã„。例ãˆã°ã€clangFormat プラグイン㮠ColumnLimit ãªã©ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Use context-specific margin</source>
+ <translation>文脈ã«å¿œã˜ãŸãƒžãƒ¼ã‚¸ãƒ³ã‚’使用ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>TextEditor::Internal::FontSettingsPage</name>
@@ -6148,6 +6929,46 @@ Backspace キーãŒæŠ¼ã•ã‚ŒãŸæ™‚ã®ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã®å‹•ä½œã‚’指定ã—ã¾ã™ã
<source>Ignored file patterns:</source>
<translation>無視ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ãƒ‘ターン:</translation>
</message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Highlight definitions are provided by the &lt;a href=&quot;https://api.kde.org/frameworks/syntax-highlighting/html/index.html&quot;&gt;KSyntaxHighlighting&lt;/a&gt; engine.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ãƒã‚¤ãƒ©ã‚¤ãƒˆã®å®šç¾©ã¯ã€&lt;a href=&quot;https://api.kde.org/frameworks/syntax-highlighting/html/index.html&quot;&gt;KSyntaxHighlighting&lt;/a&gt; engineã«ã‚ˆã£ã¦æä¾›ã•ã‚Œã¾ã™ã€‚&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <source>Download missing and update existing syntax definition files.</source>
+ <translation>ä¸è¶³ã‚‚ã—ãã¯æ›´æ–°ã®ã‚る構文定義ファイルをダウンロードã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Download Definitions</source>
+ <translation>定義をダウンロード</translation>
+ </message>
+ <message>
+ <source>User Highlight Definition Files</source>
+ <translation>ユーザーãƒã‚¤ãƒ©ã‚¤ãƒˆå®šç¾©ãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message>
+ <source>Reload externally modified definition files.</source>
+ <translation>外部ã‹ã‚‰å¤‰æ›´ã•ã‚ŒãŸå®šç¾©ãƒ•ã‚¡ã‚¤ãƒ«ã‚’å†èª­ã¿è¾¼ã¿ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Reload Definitions</source>
+ <translation>定義をå†èª­ã¿è¾¼ã¿ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Reset definitions remembered for files that can be associated with more than one highlighter definition.</source>
+ <translation>複数ã®ãƒã‚¤ãƒ©ã‚¤ãƒˆã®å®šç¾©ã¨é–¢é€£ä»˜ã‘ã‚‹ã“ã¨ãŒã§ãるファイルã«è¨˜æ†¶ã•ã‚ŒãŸå®šç¾©ã‚’リセットã™ã‚‹.</translation>
+ </message>
+ <message>
+ <source>Reset Remembered Definitions</source>
+ <translation>記憶ã•ã‚ŒãŸå®šç¾©ã‚’リセットã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Generic Highlighter</source>
+ <translation>汎用ãƒã‚¤ãƒ©ã‚¤ã‚¿</translation>
+ </message>
+ <message>
+ <source>Download finished</source>
+ <translation>ダウンロードã®å®Œäº†</translation>
+ </message>
</context>
<context>
<name>TextEditor::Internal::ManageDefinitionsDialog</name>
@@ -6208,7 +7029,7 @@ Backspace キーãŒæŠ¼ã•ã‚ŒãŸæ™‚ã®ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã®å‹•ä½œã‚’指定ã—ã¾ã™ã
</message>
<message>
<source>Group: </source>
- <translation>グループ:</translation>
+ <translation>グループ: </translation>
</message>
<message>
<source>Add</source>
@@ -6230,6 +7051,22 @@ Backspace キーãŒæŠ¼ã•ã‚ŒãŸæ™‚ã®ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã®å‹•ä½œã‚’指定ã—ã¾ã™ã
<source>Reset All</source>
<translation>ã™ã¹ã¦æˆ»ã™</translation>
</message>
+ <message>
+ <source>Error While Saving Snippet Collection</source>
+ <translation>テンプレートコレクションä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+ <message>
+ <source>No snippet selected.</source>
+ <translation>テンプレートãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Snippets</source>
+ <translation>テンプレート</translation>
+ </message>
</context>
<context>
<name>TextEditor::Internal::TabSettingsWidget</name>
@@ -6446,6 +7283,10 @@ Influences the indentation of continuation lines.
<source>Check Now</source>
<translation>今ã™ã確èª</translation>
</message>
+ <message>
+ <source>Automatically runs a scheduled check for updates on a time interval basis. The automatic check for updates will be performed at the scheduled date, or the next startup following it.</source>
+ <translation>時間間隔ã§ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã•ã‚ŒãŸã‚¢ãƒƒãƒ—デートã®ãƒã‚§ãƒƒã‚¯ã‚’自動的ã«å®Ÿè¡Œã—ã¾ã™ã€‚アップデートã®è‡ªå‹•ãƒã‚§ãƒƒã‚¯ã¯ã€ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã•ã‚ŒãŸæ—¥ä»˜ã€ã¾ãŸã¯ãã®æ¬¡ã®èµ·å‹•æ™‚ã«å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>Valgrind::Internal::ValgrindConfigWidget</name>
@@ -6566,6 +7407,10 @@ Influences the indentation of continuation lines.
<translation>Valgrind コマンド</translation>
</message>
<message>
+ <source>KCachegrind Command</source>
+ <translation>KCachegrind コマンド</translation>
+ </message>
+ <message>
<source>Valgrind Suppression Files</source>
<translation>Valgrind 抑制ファイル</translation>
</message>
@@ -6574,6 +7419,10 @@ Influences the indentation of continuation lines.
<translation>Valgrind 抑制ファイル (*.supp);;ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*)</translation>
</message>
<message>
+ <source>Valgrind</source>
+ <translation>Valgrind</translation>
+ </message>
+ <message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;
&lt;p&gt;Does full cache simulation.&lt;/p&gt;
&lt;p&gt;By default, only instruction read accesses will be counted (&quot;Ir&quot;).&lt;/p&gt;
@@ -6615,6 +7464,34 @@ With cache simulation, further event counters are enabled:
<source>Collects information for system call times.</source>
<translation>システムコールã®å‡¦ç†æ™‚é–“ã‚’åŽé›†ã—ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>KCachegrind executable:</source>
+ <translation>KCachegrind ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Valgrind Generic Settings</source>
+ <translation>Valgrind ã®æ±Žç”¨è¨­å®š</translation>
+ </message>
+ <message>
+ <source>Valgrind arguments:</source>
+ <translation>Valgrind ã®å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>MemCheck Memory Analysis Options</source>
+ <translation>MemCheck ã®ãƒ¡ãƒ¢ãƒªè§£æžã‚ªãƒ—ション</translation>
+ </message>
+ <message>
+ <source>Extra MemCheck arguments:</source>
+ <translation>MemCheck ã®è¿½åŠ å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>CallGrind Profiling Options</source>
+ <translation>CallGrind ã®ãƒ—ロファイリングオプション</translation>
+ </message>
+ <message>
+ <source>Extra CallGrind arguments:</source>
+ <translation>CallGrind ã®è¿½åŠ å¼•æ•°:</translation>
+ </message>
</context>
<context>
<name>VcsBase::Internal::CleanDialog</name>
@@ -6670,8 +7547,8 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<message>
<source>A file listing nicknames in a 4-column mailmap format:
&apos;name &lt;email&gt; alias &lt;email&gt;&apos;.</source>
- <translation>4列㮠mailmap フォーマットã§ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’記述ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«:
-&apos;name &lt;email&gt; alias &lt;email&gt;&apos;</translation>
+ <translation>4列ã®ãƒ¡ãƒ¼ãƒ«ãƒžãƒƒãƒ—å½¢å¼ã§ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã‚’リストアップã—ãŸãƒ•ã‚¡ã‚¤ãƒ«:
+&apos;name &lt;email&gt; alias &lt;email&gt;&apos;.</translation>
</message>
<message>
<source>Reset information about which version control system handles which directory.</source>
@@ -6726,6 +7603,44 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
</translation>
</message>
<message>
+ <source>Warning: The commit message is very short.</source>
+ <translation>警告: コミットメッセージãŒçŸ­éŽãŽã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Warning: The commit subject is too long.</source>
+ <translation>警告: コミット件åãŒé•·éŽãŽã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Hint: Aim for a shorter commit subject.</source>
+ <translation>ヒント: コミットã®ä»¶åを短ãã™ã‚‹ã“ã¨ã‚’目指ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Hint: The second line of a commit message should be empty.</source>
+ <translation>ヒント:コミットメッセージã®2行目ã¯ç©ºæ¬„ã«ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>&lt;p&gt;Writing good commit messages&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Avoid very short commit messages.&lt;/li&gt;&lt;li&gt;Consider the first line as subject (like in email) and keep it shorter than %1 characters.&lt;/li&gt;&lt;li&gt;After an empty second line, a longer description can be added.&lt;/li&gt;&lt;li&gt;Describe why the change was done, not how it was done.&lt;/li&gt;&lt;/ul&gt;</source>
+ <translation type="vanished">&lt;p&gt;良ã„コミットメッセージを書ããŸã‚ã«&lt;/p&gt;&lt;ul&gt;&lt;li&gt;。éžå¸¸ã«çŸ­ã„コミットメッセージã¯é¿ã‘ã¾ã—ょã†ã€‚&lt;/li&gt;&lt;li&gt;1行目を(é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚ˆã†ã«)件åã¨è€ƒãˆã€%1文字より短ãã—ã¾ã™ã€‚&lt;/li&gt;&lt;li&gt;空ã®2行目ã®å¾Œã«ã€ã‚ˆã‚Šé•·ã„説明を追加ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚&lt;/li&gt;&lt;li&gt;ã©ã®ã‚ˆã†ã«è¡Œã‚ã‚ŒãŸã‹ã§ã¯ãªãã€ãªãœãã®å¤‰æ›´ãŒè¡Œã‚ã‚ŒãŸã®ã‹ã‚’記述ã—ã¦ãã ã•ã„</translation>
+ </message>
+ <message numerus="yes">
+ <source>&lt;p&gt;Writing good commit messages&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Avoid very short commit messages.&lt;/li&gt;&lt;li&gt;Consider the first line as subject (like in email) and keep it shorter than %n characters.&lt;/li&gt;&lt;li&gt;After an empty second line, a longer description can be added.&lt;/li&gt;&lt;li&gt;Describe why the change was done, not how it was done.&lt;/li&gt;&lt;/ul&gt;</source>
+ <translation>
+ <numerusform>&lt;p&gt;良ã„コミットメッセージを書ããŸã‚ã«&lt;/p&gt;&lt;ul&gt;&lt;li&gt;。éžå¸¸ã«çŸ­ã„コミットメッセージã¯é¿ã‘ã¾ã—ょã†ã€‚&lt;/li&gt;&lt;li&gt;1行目を(é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚ˆã†ã«)件åã¨è€ƒãˆã€ %n 文字より短ãã—ã¾ã™ã€‚&lt;/li&gt;&lt;li&gt;空ã®2行目ã®å¾Œã«ã€ã‚ˆã‚Šé•·ã„説明を追加ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚&lt;/li&gt;&lt;li&gt;ã©ã®ã‚ˆã†ã«è¡Œã‚ã‚ŒãŸã‹ã§ã¯ãªãã€ãªãœãã®å¤‰æ›´ãŒè¡Œã‚ã‚ŒãŸã®ã‹ã‚’記述ã—ã¦ãã ã•ã„</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Update in progress</source>
+ <translation>アップデート中</translation>
+ </message>
+ <message>
+ <source>Description is empty</source>
+ <translation>説明文ãŒç©ºæ¬„ã§ã™</translation>
+ </message>
+ <message>
+ <source>No files checked</source>
+ <translation>ファイルãŒãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
+ </message>
+ <message>
<source>&amp;Commit</source>
<translation>コミット(&amp;C)</translation>
</message>
@@ -6772,7 +7687,7 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
</message>
<message>
<source>Delete Folder</source>
- <translation>フォルダã®å‰Šé™¤</translation>
+ <translation>フォルダを削除ã™ã‚‹</translation>
</message>
<message>
<source>Rename Folder</source>
@@ -6825,18 +7740,47 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
</message>
</context>
<context>
- <name>StandardTextGroupBox</name>
- <message>
- <source></source>
- <translation></translation>
- </message>
-</context>
-<context>
<name>TextEditor</name>
<message>
<source>Text Editor</source>
<translation>テキストエディタ</translation>
</message>
+ <message>
+ <source>Cannot create temporary file &quot;%1&quot;: %2.</source>
+ <translation>一時ファイル &quot;%1&quot; を作æˆã§ãã¾ã›ã‚“: %2.</translation>
+ </message>
+ <message>
+ <source>Failed to format: %1.</source>
+ <translation>æ•´å½¢ã«å¤±æ•—ã—ã¾ã—ãŸ: %1.</translation>
+ </message>
+ <message>
+ <source>Cannot read file &quot;%1&quot;: %2.</source>
+ <translation>ファイル &quot;%1&quot; ãŒèª­ã¿è¾¼ã‚ã¾ã›ã‚“: %2.</translation>
+ </message>
+ <message>
+ <source>Cannot call %1 or some other error occurred.</source>
+ <translation>%1 ãŒå‘¼ã³å‡ºã›ãªã„ã‹ãã®ä»–ã®ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Cannot call %1 or some other error occurred. Timeout reached while formatting file %2.</source>
+ <translation>%1 ãŒå‘¼ã³å‡ºã›ãªã„ã‹ãã®ä»–ã®ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ファイル %2 ã®æ•´å½¢ä¸­ã«ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Error in text formatting: %1</source>
+ <translation>テキストフォーマットã®ã‚¨ãƒ©ãƒ¼: %1</translation>
+ </message>
+ <message>
+ <source>Could not format file %1.</source>
+ <translation>ファイル %1 ã‚’æ•´å½¢ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>File %1 was closed.</source>
+ <translation>ファイル %1 ãŒé–‰ã˜ã‚‰ã‚Œã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>File was modified.</source>
+ <translation>ファイルã¯ç·¨é›†ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>BorderImageSpecifics</name>
@@ -6845,6 +7789,62 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>ソース</translation>
</message>
<message>
+ <source>Border left</source>
+ <translation>å·¦ã®æž å¹…</translation>
+ </message>
+ <message>
+ <source>Border right</source>
+ <translation>å³ã®æž å¹…</translation>
+ </message>
+ <message>
+ <source>Border top</source>
+ <translation>上ã®æž å¹…</translation>
+ </message>
+ <message>
+ <source>Border bottom</source>
+ <translation>下ã®æž å¹…</translation>
+ </message>
+ <message>
+ <source>Horizontal tile mode</source>
+ <translation>水平方å‘ã®ã‚¿ã‚¤ãƒ«ãƒ¢ãƒ¼ãƒ‰</translation>
+ </message>
+ <message>
+ <source>Vertical tile mode</source>
+ <translation>åž‚ç›´æ–¹å‘ã®ã‚¿ã‚¤ãƒ«ãƒ¢ãƒ¼ãƒ‰</translation>
+ </message>
+ <message>
+ <source>Mirror</source>
+ <translation>ミラー</translation>
+ </message>
+ <message>
+ <source>Specifies whether the image should be horizontally inverted.</source>
+ <translation>ç”»åƒã‚’水平方å‘ã«å転ã•ã›ã‚‹ã‹ã©ã†ã‹ã‚’指定ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Smooth</source>
+ <translation>スムーズ</translation>
+ </message>
+ <message>
+ <source>Specifies whether the image is smoothly filtered when scaled or transformed.</source>
+ <translation>ç”»åƒã‚’拡大・縮å°ãƒ»å¤‰æ›ã™ã‚‹éš›ã«ã€ã‚¹ãƒ ãƒ¼ã‚ºã«ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã™ã‚‹ã‹ã©ã†ã‹ã‚’指定ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Cache</source>
+ <translation>キャッシュ</translation>
+ </message>
+ <message>
+ <source>Specifies whether the image should be cached.</source>
+ <translation>ç”»åƒã‚’キャッシュã™ã‚‹ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Asynchronous</source>
+ <translation>éžåŒæœŸ</translation>
+ </message>
+ <message>
+ <source>Specifies that images on the local filesystem should be loaded asynchronously in a separate thread.</source>
+ <translation>ローカルファイルシステム上ã®ç”»åƒã‚’ã€åˆ¥ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã§éžåŒæœŸã«èª­ã¿è¾¼ã‚€ã“ã¨ã‚’指定ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Border Image</source>
<translation>æž ç”»åƒ</translation>
</message>
@@ -6882,6 +7882,11 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<message>
<source>None or multiple items selected.</source>
<translation>何もé¸æŠžã•ã‚Œã¦ã„ãªã„ã‹è¤‡æ•°ã®ã‚¢ã‚¤ãƒ†ãƒ ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ <translation type="vanished">何もé¸æŠžã•ã‚Œã¦ã„ãªã„ã‹è¤‡æ•°ã®ã‚¢ã‚¤ãƒ†ãƒ ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>None or multiple components selected.</source>
+ <translation>何もé¸æŠžã•ã‚Œã¦ã„ãªã„ã‹è¤‡æ•°ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
</message>
</context>
<context>
@@ -6891,6 +7896,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>フローレイアウト</translation>
</message>
<message>
+ <source>Layout direction</source>
+ <translation>レイアウト方å‘</translation>
+ </message>
+ <message>
<source>Spacing</source>
<translation>é–“éš”</translation>
</message>
@@ -6918,6 +7927,26 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>優先レイアウト軸</translation>
</message>
<message>
+ <source>Layout direction</source>
+ <translation>レイアウト方å‘</translation>
+ </message>
+ <message>
+ <source>Horizontal component alignment</source>
+ <translation>水平方å‘ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆé…ç½®</translation>
+ </message>
+ <message>
+ <source>Vertical component alignment</source>
+ <translation>åž‚ç›´æ–¹å‘ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆé…ç½®</translation>
+ </message>
+ <message>
+ <source>Horizontal item alignment</source>
+ <translation type="vanished">水平方å‘ã®ã‚¢ã‚¤ãƒ†ãƒ é…ç½®</translation>
+ </message>
+ <message>
+ <source>Vertical item alignment</source>
+ <translation type="vanished">åž‚ç›´æ–¹å‘ã®ã‚¢ã‚¤ãƒ†ãƒ é…ç½®</translation>
+ </message>
+ <message>
<source>Spacing</source>
<translation>é–“éš”</translation>
</message>
@@ -6941,6 +7970,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>キャッシュãƒãƒƒãƒ•ã‚¡</translation>
</message>
<message>
+ <source>Cell size</source>
+ <translation>セルサイズ</translation>
+ </message>
+ <message>
<source>Flow</source>
<translation>優先レイアウト軸</translation>
</message>
@@ -6951,6 +7984,15 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<message>
<source>Determines whether the grid wraps key navigation.</source>
<translation>キーボードã§ã®ç§»å‹•æ™‚ã«æŠ˜ã‚Šè¿”ã™ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™ã€‚</translation>
+ <translation type="vanished">キーボードã§ã®ç§»å‹•æ™‚ã«æŠ˜ã‚Šè¿”ã™ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Whether the grid wraps key navigation.</source>
+ <translation>グリッドãŒã‚­ãƒ¼ãƒŠãƒ“ゲーションをラップã™ã‚‹ã‹ã©ã†ã‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Layout direction</source>
+ <translation>レイアウト方å‘</translation>
</message>
<message>
<source>Snap mode</source>
@@ -6981,6 +8023,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>ãƒã‚¤ãƒ©ã‚¤ãƒˆãƒ‡ãƒªã‚²ãƒ¼ãƒˆãŒç§»å‹•ã™ã‚‹æ™‚ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®æŒç¶šæ™‚é–“ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Whether the highlight is managed by the view.</source>
+ <translation>ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚’ビューã§ç®¡ç†ã™ã‚‹ã‹ã©ã†ã‹ã€‚</translation>
+ </message>
+ <message>
<source>Move speed</source>
<translation>移動速度</translation>
</message>
@@ -7039,6 +8085,62 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<source>Source size</source>
<translation>ソースサイズ</translation>
</message>
+ <message>
+ <source>Horizontal alignment</source>
+ <translation>水平方å‘ã®é…ç½®</translation>
+ </message>
+ <message>
+ <source>Vertical alignment</source>
+ <translation>åž‚ç›´æ–¹å‘ã®é…ç½®</translation>
+ </message>
+ <message>
+ <source>Asynchronous</source>
+ <translation>éžåŒæœŸ</translation>
+ </message>
+ <message>
+ <source>Loads images on the local filesystem asynchronously in a separate thread.</source>
+ <translation>ローカルファイルシステム上ã®ç”»åƒã‚’ã€åˆ¥ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã§éžåŒæœŸã«èª­ã¿è¾¼ã¿ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Auto transform</source>
+ <translation>自動変æ›</translation>
+ </message>
+ <message>
+ <source>Automatically applies image transformation metadata such as EXIF orientation.</source>
+ <translation>EXIF オリエンテーションãªã©ã®ç”»åƒå¤‰æ›ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã‚’自動的ã«é©ç”¨ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Cache</source>
+ <translation>キャッシュ</translation>
+ </message>
+ <message>
+ <source>Caches the image.</source>
+ <translation>ç”»åƒã‚’キャッシュã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Mipmap</source>
+ <translation>ミップマップ</translation>
+ </message>
+ <message>
+ <source>Uses mipmap filtering when the image is scaled or transformed.</source>
+ <translation>ç”»åƒã®æ‹¡å¤§ãƒ»ç¸®å°ãƒ»å¤‰æ›æ™‚ã«ãƒŸãƒƒãƒ—マップフィルタリングを行ã†ã€‚</translation>
+ </message>
+ <message>
+ <source>Mirror</source>
+ <translation>ミラー</translation>
+ </message>
+ <message>
+ <source>Inverts the image horizontally.</source>
+ <translation>ç”»åƒã‚’水平方å‘ã«å転ã•ã›ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Smooth</source>
+ <translation>スムーズ</translation>
+ </message>
+ <message>
+ <source>Smoothly filters the image when it is scaled or transformed.</source>
+ <translation>ç”»åƒã‚’拡大・縮å°ãƒ»å¤‰å½¢ã™ã‚‹éš›ã«ã€ã‚¹ãƒ ãƒ¼ã‚ºã«ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’ã‹ã‘る。</translation>
+ </message>
</context>
<context>
<name>ListViewSpecifics</name>
@@ -7063,6 +8165,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>キーボードã§ã®ç§»å‹•æ™‚ã«æŠ˜ã‚Šè¿”ã™ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Whether the grid wraps key navigation.</source>
+ <translation>グリッドãŒã‚­ãƒ¼ãƒŠãƒ“ゲーションをラップã™ã‚‹ã‹ã©ã†ã‹ã€‚</translation>
+ </message>
+ <message>
<source>Orientation</source>
<translation>æ–¹å‘</translation>
</message>
@@ -7071,6 +8177,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>リストã®æ–¹å‘ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Layout direction</source>
+ <translation>レイアウト方å‘</translation>
+ </message>
+ <message>
<source>Snap mode</source>
<translation>接ç€ãƒ¢ãƒ¼ãƒ‰</translation>
</message>
@@ -7107,12 +8217,28 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>ãƒã‚¤ãƒ©ã‚¤ãƒˆãƒ‡ãƒªã‚²ãƒ¼ãƒˆãŒç§»å‹•ã™ã‚‹æ™‚ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®æŒç¶šæ™‚é–“ã§ã™ã€‚</translation>
</message>
<message>
- <source>Move speed</source>
+ <source>Move velocity</source>
<translation>移動速度</translation>
</message>
<message>
+ <source>Move animation velocity of the highlight delegate.</source>
+ <translation>highlight デリゲートã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®ç§»å‹•é€Ÿåº¦ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Whether the highlight is managed by the view.</source>
+ <translation>ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚’ビューã§ç®¡ç†ã™ã‚‹ã‹ã©ã†ã‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Move speed</source>
+ <translation type="vanished">移動速度</translation>
+ </message>
+ <message>
<source>Move animation speed of the highlight delegate.</source>
- <translation>ãƒã‚¤ãƒ©ã‚¤ãƒˆãƒ‡ãƒªã‚²ãƒ¼ãƒˆãŒç§»å‹•ã™ã‚‹æ™‚ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®é€Ÿåº¦ã§ã™ã€‚</translation>
+ <translation type="vanished">ãƒã‚¤ãƒ©ã‚¤ãƒˆãƒ‡ãƒªã‚²ãƒ¼ãƒˆãŒç§»å‹•ã™ã‚‹æ™‚ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®é€Ÿåº¦ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Spacing between components.</source>
+ <translation>コンãƒãƒ¼ãƒãƒ³ãƒˆåŒå£«ã®é–“éš”ã§ã™ã€‚</translation>
</message>
<message>
<source>Resize duration</source>
@@ -7123,6 +8249,14 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>ãƒã‚¤ãƒ©ã‚¤ãƒˆãƒ‡ãƒªã‚²ãƒ¼ãƒˆãŒãƒªã‚µã‚¤ã‚ºã™ã‚‹æ™‚ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®æŒç¶šæ™‚é–“ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Resize velocity</source>
+ <translation>リサイズ速度</translation>
+ </message>
+ <message>
+ <source>Resize animation velocity of the highlight delegate.</source>
+ <translation>ãƒã‚¤ãƒ©ã‚¤ãƒˆãƒ‡ãƒªã‚²ãƒ¼ãƒˆãŒãƒªã‚µã‚¤ã‚ºã™ã‚‹æ™‚ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®é€Ÿåº¦ã§ã™ã€‚</translation>
+ </message>
+ <message>
<source>Preferred begin</source>
<translation>推奨開始ä½ç½®</translation>
</message>
@@ -7158,6 +8292,116 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>有効化</translation>
</message>
<message>
+ <source>Accepts mouse events.</source>
+ <translation>マウスイベントをå—ä¿¡ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Hover enabled</source>
+ <translation>ホãƒãƒ¼ã®æœ‰åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Handles hover events.</source>
+ <translation>ホãƒãƒ¼ã‚¤ãƒ™ãƒ³ãƒˆã‚’処ç†ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Accepted buttons</source>
+ <translation>å—ã‘入れるボタン</translation>
+ </message>
+ <message>
+ <source>Mouse buttons that the mouse area reacts to.</source>
+ <translation>マウスエリアãŒåå¿œã™ã‚‹ãƒžã‚¦ã‚¹ãƒœã‚¿ãƒ³ã€‚</translation>
+ </message>
+ <message>
+ <source>Press and hold interval</source>
+ <translation>長押ã—時ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒ«</translation>
+ </message>
+ <message>
+ <source>Overrides the elapsed time in milliseconds before pressAndHold signal is emitted.</source>
+ <translation>PressAndHold シグナルãŒç™ºã›ã‚‰ã‚Œã‚‹ã¾ã§ã®çµŒéŽæ™‚間をミリ秒å˜ä½ã§ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Scroll gesture enabled</source>
+ <translation>スクロールジェスãƒãƒ£ãƒ¼å¯¾å¿œ</translation>
+ </message>
+ <message>
+ <source>Responds to scroll gestures from non-mouse devices.</source>
+ <translation>éžãƒžã‚¦ã‚¹ãƒ‡ãƒã‚¤ã‚¹ã‹ã‚‰ã®ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã«å¯¾å¿œã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Cursor shape</source>
+ <translation>カーソル形状</translation>
+ </message>
+ <message>
+ <source>Cursor shape for this mouse area.</source>
+ <translation>ã“ã®ãƒžã‚¦ã‚¹ã‚¨ãƒªã‚¢ã®ã‚«ãƒ¼ã‚½ãƒ«å½¢çŠ¶ã€‚</translation>
+ </message>
+ <message>
+ <source>Prevent stealing</source>
+ <translation>盗難を防止ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Stops mouse events from being stolen from this mouse area.</source>
+ <translation>ã“ã®ãƒžã‚¦ã‚¹ã‚¨ãƒªã‚¢ã‹ã‚‰ãƒžã‚¦ã‚¹ã‚¤ãƒ™ãƒ³ãƒˆãŒç›—ã¾ã‚Œã‚‹ã®ã‚’防止ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Propagate composed events</source>
+ <translation>åˆæˆã•ã‚ŒãŸã‚¤ãƒ™ãƒ³ãƒˆã‚’ä¼æ’­ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Automatically propagates composed mouse events to other mouse areas.</source>
+ <translation>åˆæˆã•ã‚ŒãŸãƒžã‚¦ã‚¹ã‚¤ãƒ™ãƒ³ãƒˆã‚’ä»–ã®ãƒžã‚¦ã‚¹ã‚¨ãƒªã‚¢ã«è‡ªå‹•çš„ã«ä¼æ¬ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Drag</source>
+ <translation>ドラッグ</translation>
+ </message>
+ <message>
+ <source>Target</source>
+ <translation>ターゲット</translation>
+ </message>
+ <message>
+ <source>ID of the component to drag.</source>
+ <translation>ドラッグã™ã‚‹ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã® ID。</translation>
+ </message>
+ <message>
+ <source>Id of the item to drag.</source>
+ <translation type="vanished">ドラッグã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ ã®ID。</translation>
+ </message>
+ <message>
+ <source>Axis</source>
+ <translation>軸</translation>
+ </message>
+ <message>
+ <source>Whether dragging can be done horizontally, vertically, or both.</source>
+ <translation>ドラッグãŒæ°´å¹³æ–¹å‘ã€åž‚ç›´æ–¹å‘ã€ã¾ãŸã¯ãã®ä¸¡æ–¹ã§ã§ãã‚‹ã‹ã©ã†ã‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Filter children</source>
+ <translation>å­ä¾›ãŸã¡ã‚’フィルタリングã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Whether dragging overrides descendant mouse areas.</source>
+ <translation>ドラッグãŒãƒžã‚¦ã‚¹ã®å­å­«é ˜åŸŸã‚’オーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã™ã‚‹ã‹ã©ã†ã‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Threshold</source>
+ <translation>ã—ãã„値</translation>
+ </message>
+ <message>
+ <source>Threshold in pixels of when the drag operation should start.</source>
+ <translation>ドラッグæ“作を開始ã™ã‚‹ã‚¿ã‚¤ãƒŸãƒ³ã‚°ã®ãƒ”クセルå˜ä½ã®ã—ãã„値。</translation>
+ </message>
+ <message>
+ <source>Smoothed</source>
+ <translation>平滑化ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Moves targets only after the drag operation has started.
+When disabled, moves targets straight to the current mouse position.</source>
+ <translation>ドラッグæ“作ãŒé–‹å§‹ã•ã‚Œã¦ã‹ã‚‰ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã‚’移動ã—ã¾ã™ã€‚
+無効ã«ã—ãŸå ´åˆã€ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã¯ç¾åœ¨ã®ãƒžã‚¦ã‚¹ã®ä½ç½®ã«ã¾ã£ã™ã移動ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>This property holds whether the item accepts mouse events.</source>
<translation>マウスイベントをå—ã‘å–ã‚‹ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™ã€‚</translation>
</message>
@@ -7182,7 +8426,7 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
</message>
<message>
<source>Drag margin</source>
- <translation>ドラッグマージン</translation>
+ <translation>ドラッグã®ãƒžãƒ¼ã‚¸ãƒ³</translation>
</message>
<message>
<source>Flick deceleration</source>
@@ -7245,6 +8489,14 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>インタラクティブ</translation>
</message>
<message>
+ <source>Allows users to drag or flick a path view.</source>
+ <translation>ユーザーã«ã‚ˆã‚‹ PathView ã®ãƒ‰ãƒ©ãƒƒã‚°ã‚„フリックをå¯èƒ½ã«ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Number of items visible on the path at any one time.</source>
+ <translation>一度ã«ãƒ‘ス上ã«è¡¨ç¤ºã•ã‚Œã‚‹ã‚¢ã‚¤ãƒ†ãƒ æ•°ã€‚</translation>
+ </message>
+ <message>
<source>Range</source>
<translation>範囲</translation>
</message>
@@ -7252,6 +8504,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<context>
<name>RectangleSpecifics</name>
<message>
+ <source>Rectangle</source>
+ <translation>矩形</translation>
+ </message>
+ <message>
<source>Border</source>
<translation>æž ç·š</translation>
</message>
@@ -7275,6 +8531,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>行</translation>
</message>
<message>
+ <source>Layout direction</source>
+ <translation>レイアウト方å‘</translation>
+ </message>
+ <message>
<source>Spacing</source>
<translation>é–“éš”</translation>
</message>
@@ -7293,6 +8553,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<source>Selection Color</source>
<translation>é¸æŠžæ™‚ã®è‰²</translation>
</message>
+ <message>
+ <source>Selected Text Color</source>
+ <translation>é¸æŠžã—ãŸãƒ†ã‚­ã‚¹ãƒˆã®è‰²</translation>
+ </message>
</context>
<context>
<name>FlickableSection</name>
@@ -7301,10 +8565,72 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>Flickable</translation>
</message>
<message>
+ <source>Whether the surface may be dragged beyond the Flickable&apos;s boundaries, or overshoot the Flickable&apos;s boundaries when flicked.</source>
+ <translation>フリックã—ãŸã¨ãã«ã€ã‚µãƒ¼ãƒ•ã‚§ã‚¹ãŒ Flickable ã®å¢ƒç•Œã‚’超ãˆã¦ãƒ‰ãƒ©ãƒƒã‚°ã•ã‚Œã‚‹ã‹ã©ã†ã‹ã€ã¾ãŸã¯ Flickable ã®å¢ƒç•Œã‚’オーãƒãƒ¼ã‚·ãƒ¥ãƒ¼ãƒˆã™ã‚‹ã‹ã©ã†ã‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Movement</source>
+ <translation>移動</translation>
+ </message>
+ <message>
+ <source>Whether the Flickable will give a feeling that the edges of the view are soft, rather than a hard physical boundary.</source>
+ <translation>Flickable ã®å¢ƒç•Œã®å‹•ä½œãŒã€ç‰©ç†çš„ã«æŸ”らã‹ã„å°è±¡ã‚’与ãˆã‚‹ã‹ã©ã†ã‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Allows users to drag or flick a flickable item.</source>
+ <translation type="vanished">ユーザーãŒãƒ•ãƒªãƒƒã‚¯å¯èƒ½ãªã‚¢ã‚¤ãƒ†ãƒ ã‚’ドラッグã¾ãŸã¯ãƒ•ãƒªãƒƒã‚¯ã§ãるよã†ã«ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Maximum flick velocity.</source>
+ <translation>最大フリック速度。</translation>
+ </message>
+ <message>
+ <source>Flick deceleration.</source>
+ <translation>フリック終了時ã®åŠ é€Ÿåº¦ã€‚</translation>
+ </message>
+ <message>
+ <source>Press delay</source>
+ <translation>é…延時間</translation>
+ </message>
+ <message>
+ <source>Time to delay delivering a press to children of the Flickable in milliseconds.</source>
+ <translation>Flickable ã®å­ã‚¨ãƒ¬ãƒ¡ãƒ³ãƒˆãŸã¡ã«ãƒ—レスを届ã‘ã‚‹ã®ã‚’é…らã›ã‚‹æ™‚é–“(å˜ä½ï¼šãƒŸãƒªç§’)。</translation>
+ </message>
+ <message>
+ <source>Pixel aligned</source>
+ <translation>ピクセルã®æƒãˆæ–¹</translation>
+ </message>
+ <message>
+ <source>Sets the alignment of contentX and contentY to pixels (true) or subpixels (false).</source>
+ <translation>contentX 㨠contentY ã®ã‚¢ãƒ©ã‚¤ãƒ¡ãƒ³ãƒˆã‚’ピクセル(true)ã¾ãŸã¯ã‚µãƒ–ピクセル(false)ã«è¨­å®šã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Synchronous drag</source>
+ <translation>ドラッグã®åŒæœŸ</translation>
+ </message>
+ <message>
+ <source>If set to true, then when the mouse or touchpoint moves far enough to begin dragging
+the content, the content will jump, such that the content pixel which was under the
+cursor or touchpoint when pressed remains under that point.</source>
+ <translation>trueã«è¨­å®šã™ã‚‹ã¨ã€ãƒžã‚¦ã‚¹ã‚„タッãƒãƒã‚¤ãƒ³ãƒˆãŒã‚³ãƒ³ãƒ†ãƒ³ãƒ„をドラッグã™ã‚‹ã®ã«å分ãªè·é›¢ã‚’移動ã—ãŸã¨ãã«ã€ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ãŒã‚¸ãƒ£ãƒ³ãƒ—ã—ã€æŠ¼ã—ãŸã¨ãã«ã‚«ãƒ¼ã‚½ãƒ«ã‚„タッãƒãƒã‚¤ãƒ³ãƒˆã®ä¸‹ã«ã‚ã£ãŸã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®ãƒ”クセルãŒã€ãã®ãƒã‚¤ãƒ³ãƒˆã®ä¸‹ã«æ®‹ã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Content size</source>
<translation>コンテンツサイズ</translation>
</message>
<message>
+ <source>Content</source>
+ <translation>コンテンツ</translation>
+ </message>
+ <message>
+ <source>Origin</source>
+ <translation>基点</translation>
+ </message>
+ <message>
+ <source>Margins</source>
+ <translation>マージン</translation>
+ </message>
+ <message>
<source>Flick direction</source>
<translation>フリック方å‘</translation>
</message>
@@ -7321,6 +8647,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>インタラクティブ</translation>
</message>
<message>
+ <source>Allows users to drag or flick a flickable component.</source>
+ <translation>ユーザーãŒãƒ•ãƒªãƒƒã‚¯å¯èƒ½ãªã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’ドラッグã¾ãŸã¯ãƒ•ãƒªãƒƒã‚¯ã§ãるよã†ã«ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Max. velocity</source>
<translation>最高速度</translation>
</message>
@@ -7352,9 +8682,86 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>フォントスタイル</translation>
</message>
<message>
+ <source>Font capitalization</source>
+ <translation>フォントã®å¤§æ–‡å­—化</translation>
+ </message>
+ <message>
+ <source>Capitalization for the text.</source>
+ <translation>テキストã®å¤§æ–‡å­—化。</translation>
+ </message>
+ <message>
+ <source>Font weight</source>
+ <translation>フォントã®å¤ªã•</translation>
+ </message>
+ <message>
+ <source>Font&apos;s weight.</source>
+ <translation>フォントã®å¤ªã•ã€‚</translation>
+ </message>
+ <message>
+ <source>Style name</source>
+ <translation>スタイルå</translation>
+ </message>
+ <message>
+ <source>Font&apos;s style.</source>
+ <translation>フォントã®ã‚¹ã‚¿ã‚¤ãƒ«ã€‚</translation>
+ </message>
+ <message>
<source>Style</source>
<translation>スタイル</translation>
</message>
+ <message>
+ <source>Spacing</source>
+ <translation>é–“éš”</translation>
+ </message>
+ <message>
+ <source>Word</source>
+ <translation>å˜èªž</translation>
+ </message>
+ <message>
+ <source>Word spacing for the font.</source>
+ <translation>フォントã®å˜èªžé–“隔。</translation>
+ </message>
+ <message>
+ <source>Letter</source>
+ <translation>文字</translation>
+ </message>
+ <message>
+ <source>Letter spacing for the font.</source>
+ <translation>フォントã®æ–‡å­—間隔。</translation>
+ </message>
+ <message>
+ <source>Performance</source>
+ <translation>性能</translation>
+ </message>
+ <message>
+ <source>Kerning</source>
+ <translation>カーニング</translation>
+ </message>
+ <message>
+ <source>Enables or disables the kerning OpenType feature when shaping the text. Disabling this may improve performance when creating or changing the text, at the expense of some cosmetic features.</source>
+ <translation>テキストを整形ã™ã‚‹éš›ã«ã€OpenType ã®ã‚«ãƒ¼ãƒ‹ãƒ³ã‚°æ©Ÿèƒ½ã‚’有効ã¾ãŸã¯ç„¡åŠ¹ã«ã—ã¾ã™ã€‚ã“ã®æ©Ÿèƒ½ã‚’無効ã«ã™ã‚‹ã¨ã€ãƒ†ã‚­ã‚¹ãƒˆã®ä½œæˆã‚„変更時ã®ãƒ‘フォーマンスãŒå‘上ã—ã¾ã™ãŒã€ä¸€éƒ¨ã®å¤–観上ã®æ©Ÿèƒ½ãŒçŠ ç‰²ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Prefer shaping</source>
+ <translation>シェイピングを好む</translation>
+ </message>
+ <message>
+ <source>Sometimes, a font will apply complex rules to a set of characters in order to display them correctly.
+In some writing systems, such as Brahmic scripts, this is required in order for the text to be legible, whereas in Latin script,
+ it is merely a cosmetic feature. Setting the preferShaping property to false will disable all such features
+when they are not required, which will improve performance in most cases.</source>
+ <translation>フォントã¯ã€æ–‡å­—ã‚’æ­£ã—ã表示ã™ã‚‹ãŸã‚ã«ã€è¤‡é›‘ãªãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
+ãƒãƒ©ãƒ¢ãƒ³æ–‡å­—ãªã©ã®ä¸€éƒ¨ã®æ–‡å­—体系ã§ã¯ã€ãƒ†ã‚­ã‚¹ãƒˆã‚’読ã¿ã‚„ã™ãã™ã‚‹ãŸã‚ã«ã“ã®ã‚ˆã†ãªå‡¦ç†ãŒå¿…è¦ã¨ãªã‚Šã¾ã™ãŒã€ãƒ©ãƒ†ãƒ³æ–‡å­—ã§ã¯ã€ã“ã‚Œã¯å˜ãªã‚‹åŒ–粧å“ã®ã‚ˆã†ãªæ©Ÿèƒ½ã§ã™ã€‚
+preferShaping プロパティを false ã«è¨­å®šã™ã‚‹ã¨ã€ã“ã®ã‚ˆã†ãªæ©Ÿèƒ½ãŒå¿…è¦ã¨ã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã™ã¹ã¦ç„¡åŠ¹ã«ãªã‚Šã€ã»ã¨ã‚“ã©ã®å ´åˆã€ãƒ‘フォーマンスãŒå‘上ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Hinting preference</source>
+ <translation>ヒントã®å„ªå…ˆé †ä½</translation>
+ </message>
+ <message>
+ <source>Preferred hinting on the text.</source>
+ <translation>テキストã«é©ç”¨ã—ãŸã„ヒントをé¸æŠžã—ã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>StandardTextSection</name>
@@ -7367,6 +8774,18 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>折り返ã—</translation>
</message>
<message>
+ <source>Elide</source>
+ <translation>çœç•¥</translation>
+ </message>
+ <message>
+ <source>Maximum line count</source>
+ <translation>最大行数</translation>
+ </message>
+ <message>
+ <source>Limits the number of lines that the text item will show.</source>
+ <translation type="vanished">テキストアイテムãŒè¡¨ç¤ºã™ã‚‹è¡Œæ•°ã‚’制é™ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Alignment</source>
<translation>整列</translation>
</message>
@@ -7374,6 +8793,66 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<source>Format</source>
<translation>フォーマット</translation>
</message>
+ <message>
+ <source>Render type</source>
+ <translation>レンダリングタイプ</translation>
+ </message>
+ <message>
+ <source>Overrides the default rendering type for this item.</source>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã‚¿ã‚¤ãƒ—をオーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Limits the number of lines that the text component will show.</source>
+ <translation>テキストコンãƒãƒ¼ãƒãƒ³ãƒˆãŒè¡¨ç¤ºã™ã‚‹è¡Œæ•°ã‚’制é™ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Overrides the default rendering type for this component.</source>
+ <translation>ã“ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã‚¿ã‚¤ãƒ—をオーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Font size mode</source>
+ <translation>フォントサイズモード</translation>
+ </message>
+ <message>
+ <source>Specifies how the font size of the displayed text is determined.</source>
+ <translation>表示ã•ã‚Œã‚‹ãƒ†ã‚­ã‚¹ãƒˆã®ãƒ•ã‚©ãƒ³ãƒˆã‚µã‚¤ã‚ºã‚’ã©ã®ã‚ˆã†ã«æ±ºå®šã™ã‚‹ã‹ã‚’指定ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Minimum size</source>
+ <translation>最å°ã‚µã‚¤ã‚º</translation>
+ </message>
+ <message>
+ <source>Pixel</source>
+ <translation>ピクセル</translation>
+ </message>
+ <message>
+ <source>Minimum font pixel size of scaled text.</source>
+ <translation>スケーリングã•ã‚ŒãŸãƒ†ã‚­ã‚¹ãƒˆã®æœ€å°ãƒ•ã‚©ãƒ³ãƒˆãƒ”クセルサイズ。</translation>
+ </message>
+ <message>
+ <source>Point</source>
+ <translation>ãƒã‚¤ãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Minimum font point size of scaled text.</source>
+ <translation>スケーリングã•ã‚ŒãŸãƒ†ã‚­ã‚¹ãƒˆã®æœ€å°ãƒ•ã‚©ãƒ³ãƒˆãƒã‚¤ãƒ³ãƒˆã‚µã‚¤ã‚ºã€‚</translation>
+ </message>
+ <message>
+ <source>Line height</source>
+ <translation>è¡Œã®é«˜ã•</translation>
+ </message>
+ <message>
+ <source>Line height for the text.</source>
+ <translation>テキスト行ã®é«˜ã•ã€‚</translation>
+ </message>
+ <message>
+ <source>Line height mode</source>
+ <translation>è¡Œã®é«˜ã•ãƒ¢ãƒ¼ãƒ‰</translation>
+ </message>
+ <message>
+ <source>Determines how the line height is specified.</source>
+ <translation>è¡Œã®é«˜ã•ã‚’ã©ã®ã‚ˆã†ã«æŒ‡å®šã™ã‚‹ã‹ã‚’決定ã—ã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>AdvancedSection</name>
@@ -7394,6 +8873,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>回転</translation>
</message>
<message>
+ <source>State</source>
+ <translation>状態</translation>
+ </message>
+ <message>
<source>Enabled</source>
<translation>有効</translation>
</message>
@@ -7417,6 +8900,42 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<source>Anti-aliasing active</source>
<translation>アンãƒã‚¨ã‚¤ãƒªã‚¢ã‚¹ã®æœ‰åŠ¹åŒ–</translation>
</message>
+ <message>
+ <source>Focus</source>
+ <translation>フォーカス</translation>
+ </message>
+ <message>
+ <source>Sets focus on the component within the enclosing focus scope.</source>
+ <translation>フォーカススコープ内ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã«ãƒ•ã‚©ãƒ¼ã‚«ã‚¹ã‚’設定ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Adds the component to the tab focus chain.</source>
+ <translation>タブã®ãƒ•ã‚©ãƒ¼ã‚«ã‚¹ãƒã‚§ãƒ¼ãƒ³ã«ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’追加ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Position of the component&apos;s baseline in local coordinates.</source>
+ <translation>ローカル座標ã«ãŠã‘るコンãƒãƒ¼ãƒãƒ³ãƒˆã®ãƒ™ãƒ¼ã‚¹ãƒ©ã‚¤ãƒ³ã®ä½ç½®ã€‚</translation>
+ </message>
+ <message>
+ <source>Sets focus on the item within the enclosing focus scope.</source>
+ <translation type="vanished">フォーカススコープ内ã®ã‚¢ã‚¤ãƒ†ãƒ ã«ãƒ•ã‚©ãƒ¼ã‚«ã‚¹ã‚’設定ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Active focus on tab</source>
+ <translation>タブã¸ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–フォーカス</translation>
+ </message>
+ <message>
+ <source>Adds the item to the tab focus chain.</source>
+ <translation type="vanished">タブã®ãƒ•ã‚©ãƒ¼ã‚«ã‚¹ãƒã‚§ãƒ¼ãƒ³ã«ã‚¢ã‚¤ãƒ†ãƒ ã‚’追加ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Baseline offset</source>
+ <translation>ベースラインオフセット</translation>
+ </message>
+ <message>
+ <source>Position of the item&apos;s baseline in local coordinates.</source>
+ <translation type="vanished">ローカル座標ã«ãŠã‘るアイテムã®ãƒ™ãƒ¼ã‚¹ãƒ©ã‚¤ãƒ³ã®ä½ç½®ã€‚</translation>
+ </message>
</context>
<context>
<name>ColumnSpecifics</name>
@@ -7458,18 +8977,62 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>åž‹</translation>
</message>
<message>
+ <source>Changes the type of this item.</source>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã®ã‚¿ã‚¤ãƒ—を変更ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
<source>id</source>
<translation>ID</translation>
</message>
<message>
+ <source>Exports this item as an alias property of the root item.</source>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ã€ãƒ«ãƒ¼ãƒˆã‚¢ã‚¤ãƒ†ãƒ ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãƒ—ロパティã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Custom id</source>
+ <translation type="vanished">カスタムID</translation>
+ </message>
+ <message>
+ <source>Component</source>
+ <translation>コンãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Changes the type of this component.</source>
+ <translation>ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã®åž‹ã‚’変更ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Exports this component as an alias property of the root component.</source>
+ <translation>ã“ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’ã€ãƒ«ãƒ¼ãƒˆã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãƒ—ロパティã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Custom ID</source>
+ <translation>Custom ID</translation>
+ </message>
+ <message>
+ <source>customId</source>
+ <translation>customId</translation>
+ </message>
+ <message>
+ <source>Add Annotation</source>
+ <translation>アノテーションを追加ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Visibility</source>
<translation>å¯è¦–性</translation>
</message>
<message>
- <source>Is Visible</source>
+ <source>Is visible</source>
<translation>表示</translation>
</message>
<message>
+ <source>Is Visible</source>
+ <translation type="vanished">表示</translation>
+ </message>
+ <message>
<source>Clip</source>
<translation>クリッピング</translation>
</message>
@@ -7500,13 +9063,37 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<context>
<name>QtObjectPane</name>
<message>
+ <source>Component</source>
+ <translation>コンãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+ <message>
<source>Type</source>
<translation>åž‹</translation>
</message>
<message>
+ <source>Changes the type of this component.</source>
+ <translation>ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã®åž‹ã‚’変更ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Exports this component as an alias property of the root component.</source>
+ <translation>ã“ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’ã€ãƒ«ãƒ¼ãƒˆã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãƒ—ロパティã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Changes the type of this item.</source>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã®ã‚¿ã‚¤ãƒ—を変更ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
<source>id</source>
<translation>ID</translation>
</message>
+ <message>
+ <source>Exports this item as an alias property of the root item.</source>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ã€ãƒ«ãƒ¼ãƒˆã‚¢ã‚¤ãƒ†ãƒ ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãƒ—ロパティã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>TextInputSection</name>
@@ -7515,6 +9102,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>テキスト入力</translation>
</message>
<message>
+ <source>Mouse selection mode</source>
+ <translation>マウスé¸æŠžãƒ¢ãƒ¼ãƒ‰</translation>
+ </message>
+ <message>
<source>Input mask</source>
<translation>入力マスク</translation>
</message>
@@ -7524,13 +9115,45 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
</message>
<message>
<source>Pass. char</source>
- <translation>パスワード文字</translation>
+ <translation type="vanished">パスワード文字</translation>
</message>
<message>
<source>Character displayed when users enter passwords.</source>
<translation>ユーザーãŒãƒ‘スワードを入力ã—ãŸæ™‚ã«è¡¨ç¤ºã•ã‚Œã‚‹æ–‡å­—ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Tab stop distance</source>
+ <translation>タブåœæ­¢è·é›¢</translation>
+ </message>
+ <message>
+ <source>Default distance between tab stops in device units.</source>
+ <translation>タブストップ間ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®è·é›¢(デãƒã‚¤ã‚¹å˜ä½)。</translation>
+ </message>
+ <message>
+ <source>Text margin</source>
+ <translation>テキストã®ãƒžãƒ¼ã‚¸ãƒ³</translation>
+ </message>
+ <message>
+ <source>Margin around the text in the Text Edit in pixels.</source>
+ <translation>テキストエディットã®ãƒ†ã‚­ã‚¹ãƒˆã®å‘¨ã‚Šã®ãƒžãƒ¼ã‚¸ãƒ³ã‚’ピクセルå˜ä½ã§è¡¨ç¤ºã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Maximum length</source>
+ <translation>最大ã®é•·ã•</translation>
+ </message>
+ <message>
+ <source>Maximum permitted length of the text in the TextInput.</source>
+ <translation type="vanished">TextInputã«è¡¨ç¤ºã•ã‚Œã‚‹ãƒ†ã‚­ã‚¹ãƒˆã®æœ€å¤§è¨±å®¹é•·ã€‚</translation>
+ </message>
+ <message>
+ <source>Password character</source>
+ <translation>パスワード文字列</translation>
+ </message>
+ <message>
+ <source>Maximum permitted length of the text in the Text Input.</source>
+ <translation>TextInput ã«è¡¨ç¤ºã•ã‚Œã‚‹ãƒ†ã‚­ã‚¹ãƒˆã®æœ€å¤§è¨±å®¹é•·ã€‚</translation>
+ </message>
+ <message>
<source>Flags</source>
<translation>フラグ</translation>
</message>
@@ -7550,6 +9173,22 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<source>Auto scroll</source>
<translation>自動スクロール</translation>
</message>
+ <message>
+ <source>Overwrite mode</source>
+ <translation>オーãƒãƒ¼ãƒ©ã‚¤ãƒˆãƒ¢ãƒ¼ãƒ‰</translation>
+ </message>
+ <message>
+ <source>Persistent selection</source>
+ <translation>æŒç¶šçš„ãªé¸æŠž</translation>
+ </message>
+ <message>
+ <source>Select by mouse</source>
+ <translation>マウスã§é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Select by keyboard</source>
+ <translation>キーボードã§é¸æŠž</translation>
+ </message>
</context>
<context>
<name>TextInputSpecifics</name>
@@ -7561,6 +9200,10 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<source>Selection Color</source>
<translation>é¸æŠžæ™‚ã®è‰²</translation>
</message>
+ <message>
+ <source>Selected Text Color</source>
+ <translation>é¸æŠžã—ãŸãƒ†ã‚­ã‚¹ãƒˆã®è‰²</translation>
+ </message>
</context>
<context>
<name>TextSpecifics</name>
@@ -7876,6 +9519,20 @@ SSH èªè¨¼ãŒå¿…è¦ã¨ã•ã‚Œã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ä½¿ç”¨ã•ã‚Œã¾ã™(SSH ã® SSH_
<translation>循環ä¾å­˜é–¢ä¿‚ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ:</translation>
</message>
<message>
+ <source>%1 (%2) depends on</source>
+ <translation>%1 (%2) ã¯ä»¥ä¸‹ã«ä¾å­˜ã—ã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
+ <source>%1 (%2)</source>
+ <translation>%1 (%2)</translation>
+ </message>
+ <message>
+ <source>Cannot load plugin because dependency failed to load: %1 (%2)
+Reason: %3</source>
+ <translation>ä¾å­˜é–¢ä¿‚ãŒè§£æ±ºã§ããªã‹ã£ãŸãŸã‚ã€ä»¥ä¸‹ã®ãƒ—ラグインを読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ: %1(%2)
+ç†ç”±: %3</translation>
+ </message>
+ <message>
<source>%1(%2) depends on</source>
<translation>%1(%2) ã®ä¾å­˜é–¢ä¿‚</translation>
</message>
@@ -7988,6 +9645,10 @@ Reason: %3</source>
<translation>ã“ã®ãƒ—ラットフォームã§ã¯ãƒ—ラグインã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>%1 (experimental)</source>
+ <translation>%1 (実験的)</translation>
+ </message>
+ <message>
<source>Path: %1
Plugin is not available on this platform.</source>
<translation>パス: %1
@@ -8185,6 +9846,114 @@ will also disable the following plugins:
<source>Expected token &quot;%1&quot;.</source>
<translation>期待ã•ã‚Œã‚‹ãƒˆãƒ¼ã‚¯ãƒ³ã¯ &quot;%1&quot; ã§ã™ã€‚</translation>
</message>
+ <message>
+ <source>Illegal unicode escape sequence</source>
+ <translation>無効㪠UNICODE エスケープシーケンスã§ã™</translation>
+ </message>
+ <message>
+ <source>Unexpected token &apos;.&apos;</source>
+ <translation>&apos;.&apos; ã¯äºˆæœŸã—ãªã„トークンã§ã™</translation>
+ </message>
+ <message>
+ <source>Stray newline in string literal</source>
+ <translation>文字列リテラル内ã«æ”¹è¡ŒãŒå­˜åœ¨ã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>End of file reached at escape sequence</source>
+ <translation>エスケープシーケンスã§ãƒ•ã‚¡ã‚¤ãƒ«ã®çµ‚端ã«åˆ°é”</translation>
+ </message>
+ <message>
+ <source>Illegal hexadecimal escape sequence</source>
+ <translation>無効ãª16進数ã®ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—シーケンスã§ã™</translation>
+ </message>
+ <message>
+ <source>Octal escape sequences are not allowed</source>
+ <translation>8進数ã®ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—シーケンスã¯åˆ©ç”¨ã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Unclosed string at end of line</source>
+ <translation>文末ã§é–‰ã˜ã‚‰ã‚Œã¦ã„ãªã„文字列ã§ã™</translation>
+ </message>
+ <message>
+ <source>At least one hexadecimal digit is required after &apos;0%1&apos;</source>
+ <translation>一æ¡ä»¥ä¸Šã®16進数㌠&quot;0%1&quot; ã®å¾Œã«å¿…è¦ã§ã™</translation>
+ </message>
+ <message>
+ <source>At least one octal digit is required after &apos;0%1&apos;</source>
+ <translation>一æ¡ä»¥ä¸Šã®8進数㌠&quot;0%1&quot; ã®å¾Œã«å¿…è¦ã§ã™</translation>
+ </message>
+ <message>
+ <source>At least one binary digit is required after &apos;0%1&apos;</source>
+ <translation>一æ¡ä»¥ä¸Šã®2進数㌠&quot;0%1&quot; ã®å¾Œã«å¿…è¦ã§ã™</translation>
+ </message>
+ <message>
+ <source>Decimal numbers can&apos;t start with &apos;0&apos;</source>
+ <translation>10進数㯠&quot;0&quot; ã§é–‹å§‹ã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Illegal syntax for exponential number</source>
+ <translation>無効ãªæŒ‡æ•°ã‚·ãƒ³ã‚¿ãƒƒã‚¯ã‚¹ã§ã™</translation>
+ </message>
+ <message>
+ <source>Invalid regular expression flag &apos;%0&apos;</source>
+ <translation>&quot;%0&quot; ã¯ç„¡åŠ¹ãªæ­£è¦è¡¨ç¾ãƒ•ãƒ©ã‚°ã§ã™</translation>
+ </message>
+ <message>
+ <source>Unterminated regular expression backslash sequence</source>
+ <translation>é–‰ã˜ã‚‰ã‚Œã¦ã„ãªã„æ­£è¦è¡¨ç¾ã®ãƒãƒƒã‚¯ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã‚·ãƒ¼ã‚±ãƒ³ã‚¹ã§ã™</translation>
+ </message>
+ <message>
+ <source>Unterminated regular expression class</source>
+ <translation>é–‰ã˜ã‚‰ã‚Œã¦ã„ãªã„æ­£è¦è¡¨ç¾ã‚¯ãƒ©ã‚¹ã§ã™</translation>
+ </message>
+ <message>
+ <source>Unterminated regular expression literal</source>
+ <translation>é–‰ã˜ã‚‰ã‚Œã¦ã„ãªã„æ­£è¦è¡¨ç¾ãƒªãƒ†ãƒ©ãƒ«ã§ã™</translation>
+ </message>
+ <message>
+ <source>Syntax error</source>
+ <translation>シンタックスエラーã§ã™</translation>
+ </message>
+ <message>
+ <source>Imported file must be a script</source>
+ <translation>インãƒãƒ¼ãƒˆã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚¹ã‚¯ãƒªãƒ—トã§ã¯ã‚ã‚Šã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Invalid module URI</source>
+ <translation>無効ãªãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã® URI ã§ã™</translation>
+ </message>
+ <message>
+ <source>Module import requires a version</source>
+ <translation>モジュールをインãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™</translation>
+ </message>
+ <message>
+ <source>Module import requires a minor version (missing dot)</source>
+ <translation>モジュールをインãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ãƒžã‚¤ãƒŠãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™(ドットãŒæŠœã‘ã¦ã„ã¾ã™)</translation>
+ </message>
+ <message>
+ <source>Module import requires a minor version (missing number)</source>
+ <translation>モジュールをインãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ãƒžã‚¤ãƒŠãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™(番å·ãŒæŠœã‘ã¦ã„ã¾ã™)</translation>
+ </message>
+ <message>
+ <source>File import requires a qualifier</source>
+ <translation>ファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã«ã¯ä¿®é£¾å­ãŒå¿…è¦ã§ã™</translation>
+ </message>
+ <message>
+ <source>Module import requires a qualifier</source>
+ <translation>修飾å­ãŒå¿…è¦ãªãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ã™</translation>
+ </message>
+ <message>
+ <source>Invalid import qualifier</source>
+ <translation>無効ãªã‚¤ãƒ³ãƒãƒ¼ãƒˆä¿®é£¾å­ã§ã™</translation>
+ </message>
+ <message>
+ <source>Unexpected token `%1&apos;</source>
+ <translation>&quot;%1&quot; ã¯äºˆæœŸã—ãªã„トークンã§ã™</translation>
+ </message>
+ <message>
+ <source>Expected token `%1&apos;</source>
+ <translation>期待ã•ã‚Œã‚‹ãƒˆãƒ¼ã‚¯ãƒ³ã¯ &quot;%1&quot; ã§ã™</translation>
+ </message>
</context>
<context>
<name>QmlJS::Bind</name>
@@ -8193,9 +9962,17 @@ will also disable the following plugins:
<translation>ドットã§åŒºåˆ‡ã‚‰ã‚ŒãŸ2ã¤ã®æ•°å­—ãŒã‚ã‚Šã¾ã›ã‚“</translation>
</message>
<message>
+ <source>Hit maximal recursion depth in AST visit</source>
+ <translation>AST ã®æŽ¢ç´¢ã§æœ€å¤§ã®å†å¸°æ·±åº¦ã«åˆ°é”ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
<source>package import requires a version number</source>
<translation>パッケージをインãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™</translation>
</message>
+ <message>
+ <source>Nested inline components are not supported</source>
+ <translation>インラインコンãƒãƒ¼ãƒãƒ³ãƒˆã®ãƒã‚¹ãƒˆã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
+ </message>
</context>
<context>
<name>QmlJS::Check</name>
@@ -8359,6 +10136,18 @@ will also disable the following plugins:
<translation>コロンã®å¾Œã®ã‚ªãƒ–ジェクトリテラルã«å¯¾å¿œã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Expected expression after colon.</source>
+ <translation>コロンã®å¾Œã«æœŸå¾…ã•ã‚Œã‚‹å¼ã€‚</translation>
+ </message>
+ <message>
+ <source>Expected strings as enum keys.</source>
+ <translation>enum ã®ã‚­ãƒ¼ã¨ã—ã¦æœŸå¾…ã•ã‚Œã‚‹æ–‡å­—列。</translation>
+ </message>
+ <message>
+ <source>Expected either array or object literal as enum definition.</source>
+ <translation>enum ã®å®šç¾©ã¨ã—ã¦ã€æœŸå¾…ã•ã‚Œã‚‹é…列ã¾ãŸã¯ã‚ªãƒ–ジェクトリテラル。</translation>
+ </message>
+ <message>
<source>Expected object literal to contain only &apos;string: number&apos; elements.</source>
<translation>エレメント㫠&apos;string: number&apos; ã®ã¿ã‚’å«ã‚€ã‚ªãƒ–ジェクトリテラルã«å¯¾å¿œã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
@@ -8374,6 +10163,54 @@ will also disable the following plugins:
<translation>ファイルã¾ãŸã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>QML module not found (%1).
+
+Import paths:
+%2
+
+For qmake projects, use the QML_IMPORT_PATH variable to add import paths.
+For Qbs projects, declare and set a qmlImportPaths property in your product to add import paths.
+For qmlproject projects, use the importPaths property to add import paths.
+For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.
+</source>
+ <translation>QML モジュールãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。(%1).
+
+インãƒãƒ¼ãƒˆãƒ‘ス:
+%2
+
+qmake プロジェクトã§ã¯ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ãƒ‘スを QML_IMPORT_PATH 変数を使用ã—ã¦è¿½åŠ ã—ã¾ã™ã€‚
+Qbs プロジェクトã§ã¯ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ãƒ‘スを qmlImportPaths プロパティを宣言ã—ã¦è¨­å®šã—ã¾ã™ã€‚
+qmlproject プロジェクトã§ã¯ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ãƒ‘スを importPaths プロパティを使用ã—ã¦è¿½åŠ ã—ã¾ã™ã€‚
+CMake プロジェクトã§ã¯ã€CMakeCache.txt 内㧠QML_IMPORT_PATH 変数を使用ã—ã¾ã™ã€‚
+</translation>
+ </message>
+ <message>
+ <source>Implicit import &apos;%1&apos; of QML module &apos;%2&apos; not found.
+
+Import paths:
+%3
+
+For qmake projects, use the QML_IMPORT_PATH variable to add import paths.
+For Qbs projects, declare and set a qmlImportPaths property in your product to add import paths.
+For qmlproject projects, use the importPaths property to add import paths.
+For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.
+</source>
+ <translation>QML モジュール &apos;%2&apos; ã®æš—é»™ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ &apos;%1&apos; ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+
+インãƒãƒ¼ãƒˆãƒ»ãƒ‘スã§ã™ã€‚
+%3
+
+qmake プロジェクトã§ã¯ã€QML_IMPORT_PATH 変数を使用ã—ã¦ã‚¤ãƒ³ãƒãƒ¼ãƒˆãƒ»ãƒ‘スを追加ã—ã¾ã™ã€‚
+Qbs プロジェクトã§ã¯ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆãƒ»ãƒ‘スを追加ã™ã‚‹ãŸã‚ã«ã€è£½å“㧠qmlImportPaths プロパティを宣言ãŠã‚ˆã³è¨­å®šã—ã¦ãã ã•ã„。
+qmlproject プロジェクトã§ã¯ã€importPaths プロパティを使用ã—ã¦ã‚¤ãƒ³ãƒãƒ¼ãƒˆ パスを追加ã—ã¾ã™ã€‚
+CMakeプロジェクトã§ã¯ã€QML_IMPORT_PATH変数ãŒCMakeCache.txtã«ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+</translation>
+ </message>
+ <message>
+ <source>QML module contains C++ plugins, currently reading type information... %1</source>
+ <translation>QML モジュール㯠C++ プラグインをå«ã‚“ã§ã„ã¾ã™ã€‚ç¾åœ¨ã€åž‹æƒ…報を読ã¿è¾¼ã¿ä¸­...%1</translation>
+ </message>
+ <message>
<source>QML module not found.
Import paths:
@@ -8444,6 +10281,14 @@ CMake プロジェクトã§ã¯ã€CMakeCache.txt 内㧠QML_IMPORT_PATH 変数を
<context>
<name>QmlJS::StaticAnalysisMessages</name>
<message>
+ <source>Do not use &quot;%1&quot; as a constructor.
+
+For more information, see the &quot;Checking Code Syntax&quot; documentation.</source>
+ <translation>コンストラクタã¨ã—㦠&quot;%1&quot; を使用ã—ãªã„ã§ãã ã•ã„。
+
+詳細ã«ã¤ã„ã¦ã¯ã€&quot;コード構文ã®ãƒã‚§ãƒƒã‚¯&quot; ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>Invalid value for enum.</source>
<translation>無効ãªå€¤ã® enum ã§ã™ã€‚</translation>
</message>
@@ -8600,6 +10445,10 @@ CMake プロジェクトã§ã¯ã€CMakeCache.txt 内㧠QML_IMPORT_PATH 変数を
<translation>Qt Quick Designer ã§ã¯ %1 型を使用ã§ãã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>This id might be ambiguous and is not supported in the Qt Quick Designer.</source>
+ <translation>ã“ã® ID ã¯æ›–昧ã§ã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã€Qt Quick Designer ã§ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>This type (%1) is not supported as a root element by Qt Quick Designer.</source>
<translation>Qt Quick Designer ã§ã¯ãƒ«ãƒ¼ãƒˆã‚¨ãƒ¬ãƒ¡ãƒ³ãƒˆã« %1 型を使用ã§ãã¾ã›ã‚“。</translation>
</message>
@@ -8636,6 +10485,22 @@ CMake プロジェクトã§ã¯ã€CMakeCache.txt 内㧠QML_IMPORT_PATH 変数を
<translation>State ã¯å­ã‚¢ã‚¤ãƒ†ãƒ  (%1) ã‚’æŒã¤ã“ã¨ãŒã§ãã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Duplicate import (%1).</source>
+ <translation>é‡è¤‡ã—ãŸã‚¤ãƒ³ãƒãƒ¼ãƒˆ (%1)。</translation>
+ </message>
+ <message>
+ <source>Hit maximum recursion limit when visiting AST.</source>
+ <translation>AST ã®æŽ¢ç´¢ã§æœ€å¤§ã®å†å¸°æ·±åº¦ã«åˆ°é”ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Type cannot be instantiated recursively (%1).</source>
+ <translation>åž‹ã‚’å†å¸°çš„ã«ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹åŒ–ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ (%1)。</translation>
+ </message>
+ <message>
+ <source>Logical value does not depend on actual values</source>
+ <translation>è«–ç†å€¤ãŒå®Ÿéš›ã®å€¤ã«ä¾å­˜ã—ãªã„</translation>
+ </message>
+ <message>
<source>Do not use &quot;%1&quot; as a constructor.</source>
<translation>&quot;%1&quot; ã¯ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã¨ã—ã¦ä½¿ç”¨ã§ãã¾ã›ã‚“。</translation>
</message>
@@ -8866,6 +10731,10 @@ CMake プロジェクトã§ã¯ã€CMakeCache.txt 内㧠QML_IMPORT_PATH 変数を
<translation>ファイルå</translation>
</message>
<message>
+ <source>Error listing root directory &quot;%1&quot;: %2</source>
+ <translation>ルート・ディレクトリ &quot;%1&quot; ã®ãƒªã‚¹ãƒˆä½œæˆã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚%2</translation>
+ </message>
+ <message>
<source>Error getting &quot;stat&quot; info about &quot;%1&quot;: %2</source>
<translation>&quot;%1&quot; ã® &quot;stat&quot; 情報å–得時ã®ã‚¨ãƒ©ãƒ¼: %2</translation>
</message>
@@ -9106,6 +10975,14 @@ with a password, which you can enter below.</source>
<translation>今後ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„</translation>
</message>
<message>
+ <source>Show Details...</source>
+ <translation>詳細を表示ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Hide Details...</source>
+ <translation>詳細を隠ã™...</translation>
+ </message>
+ <message>
<source>Do not &amp;ask again</source>
<translation>今後ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„(&amp;A)</translation>
</message>
@@ -9280,6 +11157,10 @@ with a password, which you can enter below.</source>
<context>
<name>Utils::FancyMainWindow</name>
<message>
+ <source>Central Widget</source>
+ <translation>中央ã®ã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆ</translation>
+ </message>
+ <message>
<source>Reset to Default Layout</source>
<translation>既定ã®ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆã«æˆ»ã™</translation>
</message>
@@ -9307,6 +11188,10 @@ with a password, which you can enter below.</source>
<translation>&quot;%1&quot; ã¯ç„¡åŠ¹ãªæ–‡å­—列ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Name matches MS Windows device (CON, AUX, PRN, NUL, COM1, COM2, ..., COM9, LPT1, LPT2, ..., LPT9)</source>
+ <translation>MS Windows ã®ãƒ‡ãƒã‚¤ã‚¹(CON, AUX, PRN, NUL, COM1, COM2, ..., COM9, LPT1, LPT2, ..., LPT9)ã¨ä¸€è‡´ã™ã‚‹åå‰</translation>
+ </message>
+ <message>
<source>Name matches MS Windows device. (%1).</source>
<translation>ファイルå㌠MS Windows デãƒã‚¤ã‚¹ (%1) ã¨ä¸€è‡´ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
@@ -9333,6 +11218,18 @@ with a password, which you can enter below.</source>
<numerusform>%1 %2 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ã« %n 件見ã¤ã‹ã‚Šã¾ã—ãŸã€‚</numerusform>
</translation>
</message>
+ <message>
+ <source>Fi&amp;le pattern:</source>
+ <translation>ファイルパターン(&amp;L):</translation>
+ </message>
+ <message>
+ <source>Excl&amp;usion pattern:</source>
+ <translation>排除ã™ã‚‹ãƒ‘ターン(&amp;U):</translation>
+ </message>
+ <message>
+ <source>List of comma separated wildcard filters. Files with file name or full file path matching any filter are included.</source>
+ <translation>コンマã§åŒºåˆ‡ã‚‰ã‚ŒãŸãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã®ãƒªã‚¹ãƒˆã§ã™ã€‚ファイルåã¾ãŸã¯ãƒ•ãƒ«ãƒ•ã‚¡ã‚¤ãƒ«ãƒ‘スãŒã„ãšã‚Œã‹ã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã«ä¸€è‡´ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ãŒå«ã¾ã‚Œã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>Utils::FileUtils</name>
@@ -9373,10 +11270,18 @@ with a password, which you can enter below.</source>
<translation>ファイルエラー</translation>
</message>
<message>
+ <source>Cannot write file %1: %2</source>
+ <translation>ファイル %1 を書ãè¾¼ã¿ã§ãã¾ã›ã‚“: %2</translation>
+ </message>
+ <message>
<source>Cannot write file %1. Disk full?</source>
<translation>ファイル %1 を書ã‘ã¾ã›ã‚“。ディスクフルã§ã¯ã‚ã‚Šã¾ã›ã‚“ã‹ï¼Ÿ</translation>
</message>
<message>
+ <source>%1: Is a reserved filename on Windows. Cannot save.</source>
+ <translation>%1: Windows ã§äºˆç´„ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«åã§ã™ã€‚ä¿å­˜ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Cannot overwrite file %1: %2</source>
<translation>ファイル %1 を上書ãã§ãã¾ã›ã‚“: %2</translation>
</message>
@@ -9388,6 +11293,14 @@ with a password, which you can enter below.</source>
<source>Cannot create temporary file in %1: %2</source>
<translation>%1 ã«ä¸€æ™‚ファイルを作æˆã§ãã¾ã›ã‚“: %2</translation>
</message>
+ <message>
+ <source>Overwrite File?</source>
+ <translation>ファイルã®ä¸Šæ›¸ã?</translation>
+ </message>
+ <message>
+ <source>Overwrite existing file &quot;%1&quot;?</source>
+ <translation>既存ã®ãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; を上書ãã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
</context>
<context>
<name>Utils::PathChooser</name>
@@ -9428,14 +11341,26 @@ with a password, which you can enter below.</source>
<translation>パス &quot;%1&quot; ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>The path &quot;%1&quot; is not a file.</source>
+ <translation>パス &quot;%1&quot; ã¯ãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>The directory &quot;%1&quot; does not exist.</source>
<translation>ディレクトリ &quot;%1&quot; ã¯å­˜åœ¨ã—ã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>The path &quot;%1&quot; is not an executable file.</source>
+ <translation>パス &quot;%1&quot; ã¯å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Cannot execute &quot;%1&quot;.</source>
<translation>&quot;%1&quot; を実行ã§ãã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Full path: &quot;%1&quot;</source>
+ <translation>フルパス: &quot;%1&quot;</translation>
+ </message>
+ <message>
<source>The path &lt;b&gt;%1&lt;/b&gt; is not a file.</source>
<translation>パス &lt;b&gt;%1&lt;/b&gt; ã¯ãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
@@ -9481,6 +11406,22 @@ with a password, which you can enter below.</source>
<translation>ファイルã¯å¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™</translation>
</message>
<message>
+ <source>The unsaved file &lt;i&gt;%1&lt;/i&gt; has been changed on disk. Do you want to reload it and discard your changes?</source>
+ <translation>未ä¿å­˜ã®ãƒ•ã‚¡ã‚¤ãƒ« &lt;i&gt;%1&lt;/i&gt; ãŒãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã§å¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚å†èª­ã¿è¾¼ã¿ã—ã¦ã€å¤‰æ›´å†…容を破棄ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>The file &lt;i&gt;%1&lt;/i&gt; has been changed on disk. Do you want to reload it?</source>
+ <translation>ファイル &lt;i&gt;%1&lt;/i&gt; ãŒãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã§å¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚å†èª­ã¿è¾¼ã¿ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>The default behavior can be set in Tools &gt; Options &gt; Environment &gt; System.</source>
+ <translation>デフォルトã®å‹•ä½œã¯ã€ã€Œãƒ„ールã€â†’「オプションã€â†’「環境ã€â†’「システムã€ã§è¨­å®šã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>No to All &amp;&amp; &amp;Diff</source>
+ <translation>å…¨ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’å†èª­ã¿è¾¼ã¿ã›ãšã«ã€å·®åˆ†è¡¨ç¤º(&amp;D)</translation>
+ </message>
+ <message>
<source>The unsaved file &lt;i&gt;%1&lt;/i&gt; has changed outside Qt Creator. Do you want to reload it and discard your changes?</source>
<translation>ä¿å­˜ã•ã‚Œã¦ã„ãªã„ファイル &lt;i&gt;%1&lt;/i&gt; ㌠Qt Creator 以外ã§å¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™ã€‚変更内容を破棄ã—ã¦å†èª­è¾¼ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
@@ -9508,6 +11449,14 @@ with a password, which you can enter below.</source>
<translation>ファイル %1 ã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚別åã§ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿãã‚Œã¨ã‚‚エディタを閉ã˜ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
+ <source>File Has Been Removed</source>
+ <translation>ファイルã¯æ—¢ã«å‰Šé™¤ã•ã‚Œã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
+ <source>The file %1 has been removed from disk. Do you want to save it under a different name, or close the editor?</source>
+ <translation>ファイル %1 㯠ディスクã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’別åã§ä¿å­˜ã™ã‚‹ã‹ã‚¨ãƒ‡ã‚£ã‚¿ã‚’é–‰ã˜ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
<source>&amp;Close</source>
<translation>é–‰ã˜ã‚‹(&amp;C)</translation>
</message>
@@ -9647,6 +11596,12 @@ with a password, which you can enter below.</source>
<message>
<source>Invalid country code.</source>
<translation>無効ãªå›½ã‚³ãƒ¼ãƒ‰ã§ã™ã€‚</translation>
+ <source>&lt;span style=&quot; color:#ff0000;&quot;&gt;Invalid country code&lt;/span&gt;</source>
+ <translation>&lt;span style=&quot; color:#ff0000;&quot;&gt;無効ãªå›½ã‚³ãƒ¼ãƒ‰ã§ã™&lt;/span&gt;</translation>
+ </message>
+ <message>
+ <source>Keystore Filename</source>
+ <translation>キーストアã®ãƒ•ã‚¡ã‚¤ãƒ«å</translation>
</message>
<message>
<source>Keystore file name</source>
@@ -9710,6 +11665,22 @@ with a password, which you can enter below.</source>
<translation>androiddeploy JSON ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Uninstall the existing app first</source>
+ <translation>ã¾ãšæ—¢å­˜ã®ã‚¢ãƒ—リをアンインストールã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Initializing deployment to Android device/simulator</source>
+ <translation>Android 端末/シミュレータã¸ã®ãƒ‡ãƒ—ロイã®åˆæœŸåŒ–</translation>
+ </message>
+ <message>
+ <source>Android: The main ABI of the deployment device (%1) is not selected. The app execution or debugging might not work properly. Add it from Projects &gt; Build &gt; Build Steps &gt; qmake &gt; ABIs.</source>
+ <translation>Android: デプロイをã™ã‚‹ãƒ‡ãƒã‚¤ã‚¹ (%1) ã®ãƒ¡ã‚¤ãƒ³ ABI ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。アプリã®å®Ÿè¡Œã‚„デãƒãƒƒã‚°ãŒæ­£å¸¸ã«è¡Œã‚ã‚Œãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚「プロジェクトã€â†’「ビルドã€â†’「ビルドステップã€â†’「qmakeã€â†’「ABIã€ã‹ã‚‰è¿½åŠ ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Deploying to %1</source>
+ <translation>%1 ã«ãƒ‡ãƒ—ロイ</translation>
+ </message>
+ <message>
<source>Cannot find the package name.</source>
<translation>パッケージåãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
</message>
@@ -9718,6 +11689,46 @@ with a password, which you can enter below.</source>
<translation>å¤ã„パッケージ %1 をアンインストールã—ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Starting: &quot;%1&quot;</source>
+ <translation>起動中: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Deployment failed with the following errors:
+
+</source>
+ <translation>以下ã®ã‚¨ãƒ©ãƒ¼ã§ãƒ‡ãƒ—ロイãŒå¤±æ•—ã—ã¾ã—ãŸ:
+
+</translation>
+ </message>
+ <message>
+ <source>
+Uninstalling the installed package may solve the issue.
+Do you want to uninstall the existing package?</source>
+ <translation>
+インストールã•ã‚Œã¦ã„るパッケージをアンインストールã™ã‚‹ã¨ã€å•é¡ŒãŒè§£æ±ºã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+既存ã®ãƒ‘ッケージをアンインストールã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Package deploy: Running command &quot;%1&quot;.</source>
+ <translation>パッケージをデプロイã—ã¾ã™ã€‚コマンド &quot;%1&quot; を実行ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Reset Default Deployment Devices</source>
+ <translation>既定ã®ãƒ‡ãƒ—ロイメントデãƒã‚¤ã‚¹ã‚’リセットã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Install an APK File</source>
+ <translation>APK ファイルをインストールã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Qt Android Installer</source>
+ <translation>Qt Android インストーラ</translation>
+ </message>
+ <message>
+ <source>Android package (*.apk)</source>
+ <translation>Android パッケージ (*.apk)</translation>
+ </message>
+ <message>
<source>Starting: &quot;%1&quot; %2</source>
<translation>起動中: &quot;%1&quot; %2</translation>
</message>
@@ -9781,6 +11792,10 @@ Do you want to uninstall the existing package?</source>
<source>Android</source>
<translation>Android</translation>
</message>
+ <message>
+ <source>Android Device</source>
+ <translation>Android デãƒã‚¤ã‚¹</translation>
+ </message>
</context>
<context>
<name>Android::Internal::AndroidDeviceFactory</name>
@@ -9987,6 +12002,42 @@ Do you want to uninstall the existing package?</source>
<translation>追加</translation>
</message>
<message>
+ <source>Style extraction:</source>
+ <translation>スタイルã®æŠ½å‡º:</translation>
+ </message>
+ <message>
+ <source>Screen orientation:</source>
+ <translation>ç”»é¢ã®å‘ã:</translation>
+ </message>
+ <message>
+ <source>Advanced</source>
+ <translation>æ‹¡å¼µ</translation>
+ </message>
+ <message>
+ <source>Application icon</source>
+ <translation>アプリケーションアイコン</translation>
+ </message>
+ <message>
+ <source>Android services</source>
+ <translation>Android サービス</translation>
+ </message>
+ <message>
+ <source>Splash screen</source>
+ <translation>スプラッシュスクリーン</translation>
+ </message>
+ <message>
+ <source>Service Definition Invalid</source>
+ <translation>サービス定義ãŒç„¡åŠ¹</translation>
+ </message>
+ <message>
+ <source>Cannot switch to source when there are invalid services.</source>
+ <translation>無効ãªã‚µãƒ¼ãƒ“スãŒã‚ã‚‹å ´åˆã€ã‚½ãƒ¼ã‚¹ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã“ã¨ãŒã§ããªã„。</translation>
+ </message>
+ <message>
+ <source>Cannot save when there are invalid services.</source>
+ <translation>無効ãªã‚µãƒ¼ãƒ“スãŒã‚ã‚‹å ´åˆã¯ä¿å­˜ã§ããªã„。</translation>
+ </message>
+ <message>
<source>The structure of the Android manifest file is corrupted. Expected a top level &apos;manifest&apos; node.</source>
<translation>Android manifest ファイルã®æ§‹é€ ãŒå£Šã‚Œã¦ã„ã¾ã™ã€‚トップレベル &apos;manifest&apos; ノードãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
</message>
@@ -10011,6 +12062,10 @@ Do you want to uninstall the existing package?</source>
<translation>エラー箇所ã¸é£›ã¶</translation>
</message>
<message>
+ <source>Services invalid. Manifest cannot be saved. Correct the service definitions before saving.</source>
+ <translation>サービスãŒç„¡åŠ¹ã§ã™ã€‚マニフェストã¯ä¿å­˜ã§ãã¾ã›ã‚“。サービス定義を修正ã—ã¦ã‹ã‚‰ä¿å­˜ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>Choose Low DPI Icon</source>
<translation>低 DPI アイコンをé¸æŠž</translation>
</message>
@@ -10026,6 +12081,10 @@ Do you want to uninstall the existing package?</source>
<source>Choose High DPI Icon</source>
<translation>高 DPI アイコンをé¸æŠž</translation>
</message>
+ <message>
+ <source>Android Manifest editor</source>
+ <translation>Android Manifest エディタ</translation>
+ </message>
</context>
<context>
<name>Android::Internal::AndroidQtVersion</name>
@@ -10034,6 +12093,18 @@ Do you want to uninstall the existing package?</source>
<translation>Qt ã§ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹ ABI ã®æ¤œå‡ºã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
</message>
<message>
+ <source>NDK is not configured in Devices &gt; Android.</source>
+ <translation>「デãƒã‚¤ã‚¹ã€â†’「Androidã€ã§ NDK ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„。</translation>
+ </message>
+ <message>
+ <source>SDK is not configured in Devices &gt; Android.</source>
+ <translation>「デãƒã‚¤ã‚¹ã€â†’「 Android ã€ã§ SDK ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„。</translation>
+ </message>
+ <message>
+ <source>Failed to detect the ABIs used by the Qt version. Check the settings in Devices &gt; Android for errors.</source>
+ <translation>Qt ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹ ABI ã®æ¤œå‡ºã«å¤±æ•—ã—ã¾ã—ãŸã€‚「デãƒã‚¤ã‚¹ã€â†’「 Android ã€ã‹ã‚‰è¨­å®šã«ã‚¨ãƒ©ãƒ¼ãŒãªã„ã‹ç¢ºèªã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>Android</source>
<extracomment>Qt Version is meant for Android</extracomment>
<translation>Android</translation>
@@ -10100,6 +12171,22 @@ Do you want to uninstall the existing package?</source>
<translation>AVD å</translation>
</message>
<message>
+ <source>API</source>
+ <translation>API</translation>
+ </message>
+ <message>
+ <source>Device Type</source>
+ <translation>デãƒã‚¤ã‚¹ç¨®é¡ž</translation>
+ </message>
+ <message>
+ <source>Target</source>
+ <translation>ターゲット</translation>
+ </message>
+ <message>
+ <source>SD-card Size</source>
+ <translation>SD カードサイズ</translation>
+ </message>
+ <message>
<source>AVD Target</source>
<translation>AVD ターゲット</translation>
</message>
@@ -10153,14 +12240,208 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>&quot;%1&quot; 㯠JDK ã®ãƒ•ã‚©ãƒ«ãƒ€ã¨ã¯ç•°ãªã‚‹ã‚ˆã†ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Select an NDK</source>
+ <translation>NDK ã‚’é¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add Custom NDK</source>
+ <translation>カスタム NDK を追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>The selected path has an invalid NDK. This might mean that the path contains space characters, or that it does not have a &quot;toolchains&quot; sub-directory, or that the NDK version could not be retrieved because of a missing &quot;source.properties&quot; or &quot;RELEASE.TXT&quot; file</source>
+ <translation>é¸æŠžã—ãŸãƒ‘スã«ç„¡åŠ¹ãª NDK ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯ã€ãƒ‘スã«ã‚¹ãƒšãƒ¼ã‚¹æ–‡å­—ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã‹ã€&quot;toolchains&quot; サブディレクトリãŒãªã„ã‹ã€&quot;source.properties&quot; ã¾ãŸã¯ &quot;RELEASE.TXT&quot; ファイルãŒãªã„ãŸã‚ã« NDK ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’å–å¾—ã§ããªã‹ã£ãŸã“ã¨ã‚’æ„味ã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>JDK path exists.</source>
+ <translation>JDK パス。</translation>
+ </message>
+ <message>
+ <source>JDK path is a valid JDK root folder.</source>
+ <translation>JDK パスã¯ã€æœ‰åŠ¹ãª JDK ルートフォルダã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Java Settings are OK.</source>
+ <translation>Java ã®è¨­å®šã¯ OK ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Java settings have errors.</source>
+ <translation>Java ã®è¨­å®šã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Android SDK path exists.</source>
+ <translation>Android SDK パス。</translation>
+ </message>
+ <message>
+ <source>Android SDK path writable.</source>
+ <translation>Android SDK パスã¯æ›¸ãè¾¼ã¿å¯èƒ½ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>SDK tools installed.</source>
+ <translation>SDK ツールãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Platform tools installed.</source>
+ <translation>プラットフォームツールãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>SDK manager runs (SDK Tools versions &lt;= 26.x require exactly Java 1.8).</source>
+ <translation>SDK Manager ãŒå‹•ä½œã—ã¾ã™(SDK Tools ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ 26.x 以下ã®å ´åˆã¯ Java 1.8 ãŒå¿…è¦ã§ã™)。</translation>
+ </message>
+ <message>
+ <source>All essential packages installed for all installed Qt versions.</source>
+ <translation>インストールã•ã‚Œã¦ã„ã‚‹å…¨ã¦ã® Qt ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«å¿…è¦ãªãƒ‘ッケージãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Build tools installed.</source>
+ <translation>ビルドツールãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Platform SDK installed.</source>
+ <translation>Platform SDK ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Android settings are OK.</source>
+ <translation>Android ã®è¨­å®šã¯ OK ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Android settings have errors.</source>
+ <translation>Android ã®è¨­å®šã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>OpenSSL path exists.</source>
+ <translation>OpenSSL パス。</translation>
+ </message>
+ <message>
+ <source>QMake include project (openssl.pri) exists.</source>
+ <translation>QMake ã®ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ãƒ—ロジェクト (openssl.pri) ãŒå­˜åœ¨ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>CMake include project (CMakeLists.txt) exists.</source>
+ <translation>CMake ã®ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ãƒ—ロジェクト (CMakeLists.txt) ãŒå­˜åœ¨ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>OpenSSL Settings are OK.</source>
+ <translation>OpenSSL ã®è¨­å®šã¯ OK ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>OpenSSL settings have errors.</source>
+ <translation>OpenSSL ã®è¨­å®šã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Select Android SDK Folder</source>
+ <translation>Android SDK フォルダã®é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Select OpenSSL Include Project File</source>
+ <translation>OpenSSL Include Project File ã‚’é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Automatically download Android SDK Tools to selected location.
+
+If the selected path contains no valid SDK Tools, the SDK Tools package is downloaded
+from %1,
+and extracted to the selected path.
+After the SDK Tools are properly set up, you are prompted to install any essential
+packages required for Qt to build for Android.</source>
+ <translation>Android SDK Tools ã‚’é¸æŠžã•ã‚ŒãŸå ´æ‰€ã«è‡ªå‹•çš„ã«ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã€‚
+
+é¸æŠžã—ãŸãƒ‘スã«æœ‰åŠ¹ãª SDK Tools ãŒãªã„å ´åˆã¯ã€SDK Tools パッケージを %1 ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¦ã€é¸æŠžã—ãŸãƒ‘スã«è§£å‡ã—ã¾ã™ã€‚
+SDK Tools ãŒæ­£ã—ãセットアップã•ã‚ŒãŸå¾Œã€Qt ㌠Android 用ã«ãƒ“ルドã™ã‚‹ãŸã‚ã«å¿…è¦ãªå¿…須パッケージをインストールã™ã‚‹ã‚ˆã†ã«æ±‚ã‚られã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Automatically download OpenSSL prebuilt libraries.
+
+These libraries can be shipped with your application if any SSL operations
+are performed. Find the checkbox under &quot;Projects &gt; Build &gt; Build Steps &gt;
+Build Android APK &gt; Additional Libraries&quot;.
+If the automatic download fails, Qt Creator proposes to open the download URL
+in the system&apos;s browser for manual download.</source>
+ <translation>OpenSSL ã®ãƒ“ルド済ã¿ãƒ©ã‚¤ãƒ–ラリを自動的ã«ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã€‚
+
+ã“れらã®ãƒ©ã‚¤ãƒ–ラリã¯ã€SSL æ“作ãŒè¡Œã‚れる場åˆã€ã‚¢ãƒ—リケーションã¨ä¸€ç·’ã«
+アプリケーションã«åŒæ¢±ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã¯ã€Œãƒ—ロジェクトã€â†’「ビルドã€â†’「ビルドステップã€â†’「Android APK ã®ãƒ“ルドã€â†’「Additional Librariesã€ã«ã‚ã‚Šã¾ã™ã€‚
+
+自動ダウンロードã«å¤±æ•—ã—ãŸå ´åˆã€Qt Creator ã¯ã‚·ã‚¹ãƒ†ãƒ ã®ãƒ–ラウザã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ URL ã‚’é–‹ãã€æ‰‹å‹•ã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ã‚’æ案ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Android SDK installation is missing necessary packages. Do you want to install the missing packages?</source>
+ <translation>Android SDK ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¿…è¦ãªãƒ‘ッケージãŒã‚ã‚Šã¾ã›ã‚“。ä¸è¶³ã—ã¦ã„るパッケージをインストールã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Missing Android SDK Packages</source>
+ <translation>Android SDK ã®ãƒ‘ッケージãŒè¦‹ã¤ã‹ã‚‰ãªã„</translation>
+ </message>
+ <message>
+ <source>OpenSSL Cloning</source>
+ <translation>OpenSSL ã®è¤‡è£½ä½œæˆ</translation>
+ </message>
+ <message>
+ <source>OpenSSL prebuilt libraries repository is already configured.</source>
+ <translation>OpenSSL ã®ãƒ—レビルドライブラリã®ãƒªãƒã‚¸ãƒˆãƒªãŒã™ã§ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The selected download path (%1) for OpenSSL already exists and the directory is not empty. Select a different path or make sure it is an empty directory.</source>
+ <translation>é¸æŠžã—㟠OpenSSL ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ãƒ»ãƒ‘ス (%1) ã¯æ—¢ã«å­˜åœ¨ã—ã€ãã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¯ç©ºã§ã¯ã‚ã‚Šã¾ã›ã‚“。別ã®ãƒ‘スをé¸æŠžã™ã‚‹ã‹ã€ç©ºã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Cloning OpenSSL prebuilt libraries...</source>
+ <translation>OpenSSL ã®ãƒ“ルド済ã¿ãƒ©ã‚¤ãƒ–ラリを複製ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>キャンセル</translation>
+ </message>
+ <message>
+ <source>OpenSSL prebuilt libraries cloning failed.</source>
+ <translation>OpenSSL ã®ãƒ“ルド済ã¿ãƒ©ã‚¤ãƒ–ラリã®è¤‡è£½ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Opening OpenSSL URL for manual download.</source>
+ <translation>手動ã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã§ãã‚‹ OpenSSL ã® URL ã‚’é–‹ã。</translation>
+ </message>
+ <message>
+ <source>Open Download URL</source>
+ <translation>ダウンロード URL ã‚’é–‹ã</translation>
+ </message>
+ <message>
+ <source>The Git tool might not be installed properly on your system.</source>
+ <translation>ãŠä½¿ã„ã®ã‚·ã‚¹ãƒ†ãƒ ã« Git ツールãŒæ­£ã—ãインストールã•ã‚Œã¦ã„ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Remove Android Virtual Device</source>
- <translation>Android 仮想デãƒã‚¤ã‚¹(AVD)ã®å‰Šé™¤</translation>
+ <translation>Android 仮想デãƒã‚¤ã‚¹(AVD)を削除ã™ã‚‹</translation>
</message>
<message>
<source>Remove device &quot;%1&quot;? This cannot be undone.</source>
<translation>デãƒã‚¤ã‚¹ &quot;%1&quot; を削除ã—ã¾ã™ã‹ï¼Ÿ 削除ã—ãŸãƒ‡ãƒã‚¤ã‚¹ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Emulator Command-line Startup Options</source>
+ <translation>エミュレータã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³èµ·å‹•ã‚ªãƒ—ション</translation>
+ </message>
+ <message>
+ <source>Emulator command-line startup options (&lt;a href=&quot;%1&quot;&gt;Help Web Page&lt;/a&gt;):</source>
+ <translation>エミュレータã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³èµ·å‹•ã‚ªãƒ—ション(&lt;a href=&quot;%1&quot;&gt;Help Web Page&lt;/a&gt;):</translation>
+ </message>
+ <message>
+ <source>(SDK Version: %1, NDK Version: %2)</source>
+ <translation>(SDK ãƒãƒ¼ã‚¸ãƒ§ãƒ³: %1, NDK ãƒãƒ¼ã‚¸ãƒ§ãƒ³: %2)</translation>
+ </message>
+ <message>
+ <source>The selected path already has a valid SDK Tools package.</source>
+ <translation>é¸æŠžã—ãŸãƒ‘スã«ã¯ã€ã™ã§ã«æœ‰åŠ¹ãª SDK Tools パッケージãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Download and install Android SDK Tools to: %1?</source>
+ <translation>Android SDK Tools をダウンロードã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã«ã¯: %1?</translation>
+ </message>
+ <message>
+ <source>Android</source>
+ <translation>Android</translation>
+ </message>
+ <message>
<source>Unsupported GDB</source>
<translation>サãƒãƒ¼ãƒˆå¯¾è±¡å¤–ã® GDB</translation>
</message>
@@ -10210,9 +12491,18 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>Autogen</translation>
</message>
<message>
+ <source>Arguments:</source>
+ <translation>引数:</translation>
+ </message>
+ <message>
<source>Configuration unchanged, skipping autogen step.</source>
<translation>設定ãŒå¤‰æ›´ã•ã‚Œã¦ã„ãªã„為ã€autogen ステップをスキップã—ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>Autogen</source>
+ <comment>Display name for AutotoolsProjectManager::AutogenStep id.</comment>
+ <translation>Autogen</translation>
+ </message>
</context>
<context>
<name>AutotoolsProjectManager::Internal::AutogenStepConfigWidget</name>
@@ -10241,9 +12531,18 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>Autoreconf</translation>
</message>
<message>
+ <source>Arguments:</source>
+ <translation>引数:</translation>
+ </message>
+ <message>
<source>Configuration unchanged, skipping autoreconf step.</source>
<translation>設定ãŒå¤‰æ›´ã•ã‚Œã¦ã„ãªã„為ã€autoreconf ステップをスキップã—ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>Autoreconf</source>
+ <comment>Display name for AutotoolsProjectManager::AutoreconfStep id.</comment>
+ <translation>Autoreconf</translation>
+ </message>
</context>
<context>
<name>AutotoolsProjectManager::Internal::AutoreconfStepConfigWidget</name>
@@ -10301,6 +12600,10 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>プロジェクトをビルドã™ã‚‹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’指定ã—ã¦ãã ã•ã„。Qt Creator ã§ã¯ã‚½ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªå†…ã§ã®ãƒ“ルドã¯æŽ¨å¥¨ã—ã¦ã„ã¾ã›ã‚“。ソースディレクトリã¨ãƒ“ルドディレクトリを分ã‘る事ã§ã‚½ãƒ¼ã‚¹ã‚’ãã‚Œã„ã«ä¿ã¡ã€ç•°ãªã‚‹è¨­å®šã§ã®è¤‡æ•°ã®ãƒ“ルドを行ã†äº‹ãŒã§ãã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Please enter the directory in which you want to build your project. It is not recommended to use the source directory for building. This ensures that the source directory remains clean and enables multiple builds with different settings.</source>
+ <translation>プロジェクトをビルドã™ã‚‹ãŸã‚ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’入力ã—ã¦ãã ã•ã„。ビルドã«ã‚½ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’使用ã™ã‚‹ã“ã¨ã¯ãŠå‹§ã‚ã—ã¾ã›ã‚“。ã“ã‚Œã«ã‚ˆã‚Šã€ã‚½ãƒ¼ã‚¹ãƒ»ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒã‚¯ãƒªãƒ¼ãƒ³ãªçŠ¶æ…‹ã«ä¿ãŸã‚Œã€ç•°ãªã‚‹è¨­å®šã§ã®è¤‡æ•°å›žã®ãƒ“ルドãŒå¯èƒ½ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Build directory:</source>
<translation>ビルドディレクトリ:</translation>
</message>
@@ -10324,9 +12627,18 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>設定ã™ã‚‹</translation>
</message>
<message>
+ <source>Arguments:</source>
+ <translation>引数:</translation>
+ </message>
+ <message>
<source>Configuration unchanged, skipping configure step.</source>
<translation>設定ãŒå¤‰æ›´ã•ã‚Œã¦ã„ãªã„為ã€configure ステップをスキップã—ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>Configure</source>
+ <comment>Display name for AutotoolsProjectManager::ConfigureStep id.</comment>
+ <translation>設定ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>AutotoolsProjectManager::Internal::ConfigureStepConfigWidget</name>
@@ -10384,6 +12696,10 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<source>Bare Metal</source>
<translation>ベアメタル</translation>
</message>
+ <message>
+ <source>Bare Metal Device</source>
+ <translation>ベアメタルデãƒã‚¤ã‚¹</translation>
+ </message>
</context>
<context>
<name>BareMetal::Internal::BareMetalGdbCommandsDeployStepWidget</name>
@@ -10732,6 +13048,18 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>Git ファイルログエディタ</translation>
</message>
<message>
+ <source>Git SVN Log Editor</source>
+ <translation>Git SVN ログエディタ</translation>
+ </message>
+ <message>
+ <source>Git Log Editor</source>
+ <translation>Git ログエディタ</translation>
+ </message>
+ <message>
+ <source>Git Reflog Editor</source>
+ <translation>Git Reflog エディタ</translation>
+ </message>
+ <message>
<source>Git Annotation Editor</source>
<translation>Git アノテーションエディタ</translation>
</message>
@@ -10798,6 +13126,10 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<source>Bazaar Command</source>
<translation>Bazaar コマンド</translation>
</message>
+ <message>
+ <source>Bazaar</source>
+ <translation>Bazaar</translation>
+ </message>
</context>
<context>
<name>OpenWith::Editors</name>
@@ -10857,6 +13189,26 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<source>Nim Editor</source>
<translation>Nim エディタ</translation>
</message>
+ <message>
+ <source>Java Editor</source>
+ <translation>Java エディタ</translation>
+ </message>
+ <message>
+ <source>CMake Editor</source>
+ <translation>CMake エディタ</translation>
+ </message>
+ <message>
+ <source>Compilation Database</source>
+ <translation>コンピレーションデータベース</translation>
+ </message>
+ <message>
+ <source>Qt Quick Designer</source>
+ <translation>Qt Quick Designer</translation>
+ </message>
+ <message>
+ <source>SCXML Editor</source>
+ <translation>SCXML エディタ</translation>
+ </message>
</context>
<context>
<name>Bookmarks::Internal::BookmarkView</name>
@@ -10886,7 +13238,7 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
</message>
<message>
<source>Remove All Bookmarks</source>
- <translation>ã™ã¹ã¦ã®ãƒ–ックマークã®å‰Šé™¤</translation>
+ <translation>ã™ã¹ã¦ã®ãƒ–ックマークを削除ã™ã‚‹</translation>
</message>
<message>
<source>Are you sure you want to remove all bookmarks from all files in the current session?</source>
@@ -11338,6 +13690,10 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<source>DiffUtils is available for free download at http://gnuwin32.sourceforge.net/packages/diffutils.htm. Extract it to a directory in your PATH.</source>
<translation>DiffUtils 㯠http://gnuwin32.sourceforge.net/packages/diffutils.htm ã‹ã‚‰ãƒ•ãƒªãƒ¼ã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã§ãã¾ã™ã€‚PATH ã®é€šã£ãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å±•é–‹ã—ã¦ãã ã•ã„。</translation>
</message>
+ <message>
+ <source>ClearCase</source>
+ <translation>ClearCase</translation>
+ </message>
</context>
<context>
<name>CMakeProjectManager::Internal::CMakeBuildConfigurationFactory</name>
@@ -11381,10 +13737,30 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>ビルドディレクトリ:</translation>
</message>
<message>
+ <source>Re-configure with Initial Parameters</source>
+ <translation>åˆæœŸãƒ‘ラメータã§å†è¨­å®šã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Clear CMake configuration and configure with initial parameters?</source>
+ <translation>CMake 設定をクリアã—ã¦ã€åˆæœŸãƒ‘ラメータã§è¨­å®šã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Do not ask again</source>
+ <translation>今後ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„</translation>
+ </message>
+ <message>
+ <source>Filter</source>
+ <translation>フィルタ</translation>
+ </message>
+ <message>
<source>&amp;Add</source>
<translation>追加(&amp;A)</translation>
</message>
<message>
+ <source>Add a new configuration value.</source>
+ <translation>æ–°ã—ã„設定値を追加ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
<source>&amp;Boolean</source>
<translation>真å½å€¤(&amp;B)</translation>
</message>
@@ -11405,10 +13781,50 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>編集(&amp;E)</translation>
</message>
<message>
+ <source>Edit the current CMake configuration value.</source>
+ <translation>ç¾åœ¨ã® CMake ã®è¨­å®šå€¤ã‚’編集ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Set</source>
+ <translation>設定(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Set a value in the CMake configuration.</source>
+ <translation>CMake ã®è¨­å®šã§å€¤ã‚’設定ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Unset</source>
+ <translation>解除(&amp;U)</translation>
+ </message>
+ <message>
+ <source>Unset a value in the CMake configuration.</source>
+ <translation>CMake ã®è¨­å®šã§å€¤ã‚’解除ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>リセット(&amp;R)</translation>
</message>
<message>
+ <source>Reset all unapplied changes.</source>
+ <translation>é©ç”¨ã•ã‚Œã¦ã„ãªã„ã™ã¹ã¦ã®å¤‰æ›´ã‚’リセットã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Clear Selection</source>
+ <translation>é¸æŠžçŠ¶æ…‹ã‚’解除</translation>
+ </message>
+ <message>
+ <source>Clear selection.</source>
+ <translation>é¸æŠžçŠ¶æ…‹ã‚’解除。</translation>
+ </message>
+ <message>
+ <source>Batch Edit...</source>
+ <translation>一括編集...</translation>
+ </message>
+ <message>
+ <source>Set or reset multiple values in the CMake Configuration.</source>
+ <translation>CMake Configuration ã®è¤‡æ•°ã®å€¤ã‚’設定ã¾ãŸã¯ãƒªã‚»ãƒƒãƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Advanced</source>
<translation>æ‹¡å¼µ</translation>
</message>
@@ -11421,6 +13837,50 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>&lt;未定義&gt;</translation>
</message>
<message>
+ <source>Edit CMake Configuration</source>
+ <translation>CMake 設定ã®ç·¨é›†</translation>
+ </message>
+ <message>
+ <source>Enter one CMake variable per line.
+To set or change a variable, use -D&lt;variable&gt;:&lt;type&gt;=&lt;value&gt;.
+&lt;type&gt; can have one of the following values: FILEPATH, PATH, BOOL, INTERNAL, or STRING.
+To unset a variable, use -U&lt;variable&gt;.
+</source>
+ <translation>1è¡Œã«1ã¤ã® CMake 変数を入力ã—ã¾ã™ã€‚
+変数を設定ã¾ãŸã¯å¤‰æ›´ã™ã‚‹ã«ã¯ã€-D&lt;variable&gt;:&lt;type&gt;=&lt;value&gt; を使用ã—ã¾ã™ã€‚
+&lt;type&gt; ã«ã¯ã€æ¬¡ã®ã„ãšã‚Œã‹ã®å€¤ã‚’指定ã—ã¾ã™ã€‚FILEPATH, PATH, BOOL, INTERNAL, STRING ã®ã„ãšã‚Œã‹ã§ã™ã€‚
+変数ã®è¨­å®šã‚’解除ã™ã‚‹ã«ã¯ã€-U&lt;variable&gt;を使用ã—ã¾ã™ã€‚
+</translation>
+ </message>
+ <message>
+ <source>bool</source>
+ <comment>display string for cmake type BOOLEAN</comment>
+ <translation>ブーリアン型</translation>
+ </message>
+ <message>
+ <source>file</source>
+ <comment>display string for cmake type FILE</comment>
+ <translation>ファイル</translation>
+ </message>
+ <message>
+ <source>directory</source>
+ <comment>display string for cmake type DIRECTORY</comment>
+ <translation>ディレクトリ</translation>
+ </message>
+ <message>
+ <source>string</source>
+ <comment>display string for cmake type STRING</comment>
+ <translation>文字列</translation>
+ </message>
+ <message>
+ <source>Force to %1</source>
+ <translation>強制的ã«%1ã«</translation>
+ </message>
+ <message>
+ <source>Copy</source>
+ <translation>コピー</translation>
+ </message>
+ <message>
<source>CMake</source>
<translation>CMake</translation>
</message>
@@ -11436,6 +13896,30 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>CMake 設定ã®ã‚¯ãƒªã‚¢</translation>
</message>
<message>
+ <source>Rescan Project</source>
+ <translation>プロジェクトをå†ã‚¹ã‚­ãƒ£ãƒ³</translation>
+ </message>
+ <message>
+ <source>Build</source>
+ <translation>ビルド</translation>
+ </message>
+ <message>
+ <source>Build File</source>
+ <translation>ファイルã®ãƒ“ルド</translation>
+ </message>
+ <message>
+ <source>Build File &quot;%1&quot;</source>
+ <translation>ファイル &quot;%1&quot; ã®ãƒ“ルド</translation>
+ </message>
+ <message>
+ <source>Ctrl+Alt+B</source>
+ <translation>Ctrl+Alt+B</translation>
+ </message>
+ <message>
+ <source>Build File is not supported for generator &quot;%1&quot;</source>
+ <translation>ビルド・ファイルã¯ã‚¸ã‚§ãƒãƒ¬ãƒ¼ã‚¿ &quot;%1&quot; ã§ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
+ </message>
+ <message>
<source>Failed opening project &quot;%1&quot;: Project is not a file</source>
<translation>プロジェクト &quot;%1&quot; ãŒé–‹ã‘ã¾ã›ã‚“: プロジェクトãŒãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“</translation>
</message>
@@ -11485,6 +13969,14 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>ã™ã¹ã¦ã‚’既定ã«æˆ»ã—ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Reset</source>
+ <translation>リセット</translation>
+ </message>
+ <message>
+ <source>Reset to default.</source>
+ <translation>既定ã«æˆ»ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Import...</source>
<translation>インãƒãƒ¼ãƒˆ...</translation>
</message>
@@ -11508,6 +14000,22 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>サイドãƒãƒ¼ã‚’éš ã™</translation>
</message>
<message>
+ <source>Show Left Sidebar</source>
+ <translation>左サイドãƒãƒ¼ã‚’表示ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Hide Left Sidebar</source>
+ <translation>左サイドãƒãƒ¼ã‚’éš ã™</translation>
+ </message>
+ <message>
+ <source>Show Right Sidebar</source>
+ <translation>å³ã‚µã‚¤ãƒ‰ãƒãƒ¼ã‚’表示ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Hide Right Sidebar</source>
+ <translation>å³ã‚µã‚¤ãƒ‰ãƒãƒ¼ã‚’éš ã™</translation>
+ </message>
+ <message>
<source>Qt</source>
<translation>Qt</translation>
</message>
@@ -11538,6 +14046,16 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<comment>msgShowOptionsDialogToolTip (non-mac version)</comment>
<translation>オプションダイアログを開ã。</translation>
</message>
+ <message>
+ <source>All Files (*.*)</source>
+ <comment>On Windows</comment>
+ <translation>ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)</translation>
+ </message>
+ <message>
+ <source>All Files (*)</source>
+ <comment>On Linux/macOS</comment>
+ <translation>ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*)</translation>
+ </message>
</context>
<context>
<name>Core::DesignMode</name>
@@ -11588,9 +14106,45 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<context>
<name>Core::Internal::ShortcutSettings</name>
<message>
+ <source>Keyboard Shortcuts</source>
+ <translation>キーボードショートカット</translation>
+ </message>
+ <message>
+ <source>Shortcut</source>
+ <translation>ショートカット</translation>
+ </message>
+ <message>
<source>Keyboard</source>
<translation>キーボード</translation>
</message>
+ <message>
+ <source>Add</source>
+ <translation>追加</translation>
+ </message>
+ <message>
+ <source>Invalid key sequence.</source>
+ <translation>無効ãªã‚­ãƒ¼ã‚·ãƒ¼ã‚±ãƒ³ã‚¹ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Key sequence will not work in editor.</source>
+ <translation>キーシーケンスãŒã‚¨ãƒ‡ã‚£ã‚¿ã§å‹•ä½œã—ãªã„。</translation>
+ </message>
+ <message>
+ <source>Import Keyboard Mapping Scheme</source>
+ <translation>キーボードマップスキームã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Keyboard Mapping Scheme (*.kms)</source>
+ <translation>キーボードマップスキーム (*.kms)</translation>
+ </message>
+ <message>
+ <source>Export Keyboard Mapping Scheme</source>
+ <translation>キーボードマップスキームã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Key sequence has potential conflicts. &lt;a href=&quot;#conflicts&quot;&gt;Show.&lt;/a&gt;</source>
+ <translation>ä»–ã®ã‚­ãƒ¼ã‚·ãƒ¼ã‚±ãƒ³ã‚¹ã¨ç«¶åˆã—ã¦ã„ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。 &lt;a href=&quot;#conflicts&quot;&gt;確èªã™ã‚‹ã€‚&lt;/a&gt;</translation>
+ </message>
</context>
<context>
<name>Core::DocumentManager</name>
@@ -11674,6 +14228,10 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>進む</translation>
</message>
<message>
+ <source>Go to Last Edit</source>
+ <translation>最後ã®ç·¨é›†ç®‡æ‰€ã«ç§»å‹•ã™ã‚‹</translation>
+ </message>
+ <message>
<source>&amp;Save</source>
<translation>ä¿å­˜(&amp;S)</translation>
</message>
@@ -11714,6 +14272,18 @@ Qt を追加ã™ã‚‹ã«ã¯ã‚ªãƒ—ションã‹ã‚‰ã€Œãƒ“ルドã¨å®Ÿè¡Œã€â†’「Qt ãƒ
<translation>ä»–ã®ã‚¨ãƒ‡ã‚£ã‚¿ã‚’é–‰ã˜ã‚‹</translation>
</message>
<message>
+ <source>Unpin &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®å›ºå®šè§£é™¤</translation>
+ </message>
+ <message>
+ <source>Pin &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®å›ºå®š</translation>
+ </message>
+ <message>
+ <source>Pin Editor</source>
+ <translation>ピンエディタ</translation>
+ </message>
+ <message>
<source>Open With</source>
<translation>エディタを指定ã—ã¦é–‹ã</translation>
</message>
@@ -11782,6 +14352,10 @@ Continue?</source>
<translation>システムエディタ</translation>
</message>
<message>
+ <source>Could not open URL %1.</source>
+ <translation>URL %1 ã‚’é–‹ã‘ã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>Could not open url %1.</source>
<translation>URL %1 ã‚’é–‹ã‘ã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
</message>
@@ -11816,6 +14390,10 @@ Continue?</source>
<translation>実行ファイル &quot;%1&quot; ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ(展開後 &quot;%2&quot;)</translation>
</message>
<message>
+ <source>Starting external tool &quot;%1&quot;</source>
+ <translation>外部ツール &quot;%1&quot; ã‚’èµ·å‹•ã—ã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
<source>Starting external tool &quot;%1&quot; %2</source>
<translation>外部ツール &quot;%1&quot; %2 ã‚’èµ·å‹•ã—ã¦ã„ã¾ã™</translation>
</message>
@@ -11945,6 +14523,14 @@ Continue?</source>
<translation>Windows Explorer ã‚’èµ·å‹•ã™ã‚‹ç‚ºã® explorer.exe ã«ãƒ‘スãŒé€šã£ã¦ã„ã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>The command for file browser is not set.</source>
+ <translation>ファイルブラウザ用ã®ã‚³ãƒžãƒ³ãƒ‰ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Error while starting file browser.</source>
+ <translation>ファイルブラウザã®èµ·å‹•æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>Find in This Directory...</source>
<translation>ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’検索...</translation>
</message>
@@ -11969,6 +14555,24 @@ Continue?</source>
<translation>ã“ã“ã§ã‚¿ãƒ¼ãƒŸãƒŠãƒ«ã‚’é–‹ã</translation>
</message>
<message>
+ <source>Open Command Prompt With</source>
+ <comment>Opens a submenu for choosing an environment, such as &quot;Run Environment&quot;</comment>
+ <translation>環境を指定ã—ã¦ã‚³ãƒžãƒ³ãƒ‰ãƒ—ロンプトを開ã</translation>
+ </message>
+ <message>
+ <source>Open Terminal With</source>
+ <comment>Opens a submenu for choosing an environment, such as &quot;Run Environment&quot;</comment>
+ <translation>環境を指定ã—ã¦ã‚¿ãƒ¼ãƒŸãƒŠãƒ«ã‚’é–‹ã</translation>
+ </message>
+ <message>
+ <source>Failed to remove file &quot;%1&quot;.</source>
+ <translation>ファイル &quot;%1&quot; ã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Failed to remove file &quot;%1&quot;)1.</source>
+ <translation type="vanished">ファイル &quot;%1&quot;)1.ã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>Deleting File Failed</source>
<translation>ファイル削除ã«å¤±æ•—</translation>
</message>
@@ -12046,6 +14650,10 @@ Continue?</source>
<translation>編集(&amp;E)</translation>
</message>
<message>
+ <source>&amp;View</source>
+ <translation>表示(&amp;V)</translation>
+ </message>
+ <message>
<source>&amp;Tools</source>
<translation>ツール(&amp;T)</translation>
</message>
@@ -12146,15 +14754,87 @@ Continue?</source>
<translation>Ctrl+L</translation>
</message>
<message>
+ <source>Zoom In</source>
+ <translation>拡大</translation>
+ </message>
+ <message>
+ <source>Ctrl++</source>
+ <translation>Ctrl++</translation>
+ </message>
+ <message>
+ <source>Zoom Out</source>
+ <translation>縮å°</translation>
+ </message>
+ <message>
+ <source>Ctrl+-</source>
+ <translation>Ctrl+-</translation>
+ </message>
+ <message>
+ <source>Ctrl+Shift+-</source>
+ <translation>Ctrl+Shift+-</translation>
+ </message>
+ <message>
+ <source>Original Size</source>
+ <translation>オリジナルサイズ</translation>
+ </message>
+ <message>
+ <source>Meta+0</source>
+ <translation>Meta+0</translation>
+ </message>
+ <message>
<source>&amp;Options...</source>
<translation>オプション(&amp;O)...</translation>
</message>
<message>
+ <source>About &amp;%1</source>
+ <translation>&amp;%1 ã«ã¤ã„ã¦</translation>
+ </message>
+ <message>
+ <source>About &amp;%1...</source>
+ <translation>&amp;%1 ã«ã¤ã„ã¦...</translation>
+ </message>
+ <message>
+ <source>Contact...</source>
+ <translation>ãŠå•ã„åˆã‚ã›...</translation>
+ </message>
+ <message>
+ <source>Cycle Mode Selector Styles</source>
+ <translation>次ã®ãƒ¢ãƒ¼ãƒ‰ã‚»ãƒ¬ã‚¯ã‚¿ãƒ¼ã®ã‚¹ã‚¿ã‚¤ãƒ«ã«åˆ‡ã‚Šæ›¿ãˆã‚‹</translation>
+ </message>
+ <message>
+ <source>Mode Selector Style</source>
+ <translation>モードセレクターã®è¡¨ç¤º</translation>
+ </message>
+ <message>
+ <source>Icons and Text</source>
+ <translation>アイコンã¨ãƒ†ã‚­ã‚¹ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Icons Only</source>
+ <translation>アイコンã®ã¿</translation>
+ </message>
+ <message>
+ <source>Hidden</source>
+ <translation>éžè¡¨ç¤ºã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Contact</source>
+ <translation>コンタクト</translation>
+ </message>
+ <message>
+ <source>&lt;p&gt;Qt Creator developers can be reached at the Qt Creator mailing list:&lt;/p&gt;%1&lt;p&gt;or the #qt-creator channel on FreeNode IRC:&lt;/p&gt;%2&lt;p&gt;Our bug tracker is located at %3.&lt;/p&gt;&lt;p&gt;Please use %4 for bigger chunks of text.&lt;/p&gt;</source>
+ <translation>&lt;p&gt;Qt Creator ã®é–‹ç™ºè€…ã¯ã€Qt Creator メーリング リスト:&lt;/p&gt;%1&lt;p&gt;ã¾ãŸã¯ FreeNode IRC ã® #qt-Creator ãƒãƒ£ãƒ³ãƒãƒ«:&lt;/p&gt;%2&lt;p&gt;ã§é€£çµ¡ã‚’å–ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ç§ãŸã¡ã®ãƒã‚°ãƒˆãƒ©ãƒƒã‚«ãƒ¼ã¯ %3.&lt;/p&gt;&lt;p&gt;ã«ã‚ã‚Šã¾ã™ã€‚容é‡ã®å¤§ãã„テキスト情報ã«å¯¾ã—ã¦ã¯ã€%4ã‚’ãŠä½¿ã„ãã ã•ã„ &lt;/p&gt;</translation>
+ </message>
+ <message>
<source>New File or Project</source>
<comment>Title of dialog</comment>
<translation>æ–°ã—ã„ファイルã¾ãŸã¯ãƒ—ロジェクト</translation>
</message>
<message>
+ <source>Exit %1?</source>
+ <translation>%1 を終了ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
<source>Minimize</source>
<translation>最å°åŒ–</translation>
</message>
@@ -12199,6 +14879,14 @@ Continue?</source>
<translation>Ctrl+Shift+F11</translation>
</message>
<message>
+ <source>Ctrl+Shift+0</source>
+ <translation>Ctrl+Shift+0</translation>
+ </message>
+ <message>
+ <source>Alt+Shift+0</source>
+ <translation>Alt+Shift+0</translation>
+ </message>
+ <message>
<source>&amp;Views</source>
<translation>表示(&amp;V)</translation>
</message>
@@ -12319,6 +15007,18 @@ Continue?</source>
<source>Additional output omitted</source>
<translation>追加ã®å‡ºåŠ›ã¯çœç•¥ã•ã‚Œã¾ã—ãŸ</translation>
</message>
+ <message numerus="yes">
+ <source>Elided %n characters due to Application Output settings</source>
+ <translation>
+ <numerusform>アプリケーション出力ã®è¨­å®šã«ã‚ˆã‚Š %n 文字をçœç•¥ã—ã¾ã—ãŸ</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>[Discarding excessive amount of pending output.]
+</source>
+ <translation>[ä¿ç•™ä¸­ã®å¤§é‡ã®å‡ºåŠ›çµæžœã‚’破棄ã—ã¦ã„ã¾ã™]
+</translation>
+ </message>
</context>
<context>
<name>Core::Internal::PluginDialog</name>
@@ -12335,6 +15035,10 @@ Continue?</source>
<translation>é–‰ã˜ã‚‹</translation>
</message>
<message>
+ <source>Install Plugin...</source>
+ <translation>プラグインをインストールã™ã‚‹...</translation>
+ </message>
+ <message>
<source>Restart required.</source>
<translation>å†èµ·å‹•ãŒå¿…è¦ã§ã™ã€‚</translation>
</message>
@@ -12343,6 +15047,10 @@ Continue?</source>
<translation>インストール済ã¿ãƒ—ラグイン</translation>
</message>
<message>
+ <source>Plugin changes will take effect after restart.</source>
+ <translation>プラグインã®å¤‰æ›´ã¯ã€å†èµ·å‹•å¾Œã«æœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Plugin Details of %1</source>
<translation>プラグイン %1 ã®è©³ç´°</translation>
</message>
@@ -12439,6 +15147,14 @@ Note: This might remove the local file.</source>
注æ„: ローカルã«ã‚るファイルも一緒ã«å‰Šé™¤ã•ã‚Œã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Remove the following files from from the version control system (%2)?%1Note: This might remove the local file.</source>
+ <translation type="vanished">以下ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ  (%2) ã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã‹? %1注: ã“ã‚Œã«ã‚ˆã‚Šã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ»ãƒ•ã‚¡ã‚¤ãƒ«ãŒå‰Šé™¤ã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Remove the following files from the version control system (%2)?%1Note: This might remove the local file.</source>
+ <translation>以下ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ  (%2) ã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã‹? %1注: ã“ã‚Œã«ã‚ˆã‚Šã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ•ã‚¡ã‚¤ãƒ«ãŒå‰Šé™¤ã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Add to Version Control</source>
<translation>ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ ã«è¿½åŠ </translation>
</message>
@@ -12467,9 +15183,10 @@ to version control (%2)?</source>
%1
to version control (%2)
</source>
- <translation>ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ  (%2) ã«
-ファイル %1 を
-追加ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
+ <translation>ファイル
+%1
+ã‚’ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã«è¿½åŠ ã§ãã¾ã›ã‚“ã§ã—㟠(%2)
+</translation>
</message>
<message>
<source>Could not add the following files to version control (%1)
@@ -12485,6 +15202,10 @@ to version control (%2)
<translation>Qt Creator ã«ã¤ã„ã¦</translation>
</message>
<message>
+ <source>About %1</source>
+ <translation>%1 ã«ã¤ã„ã¦</translation>
+ </message>
+ <message>
<source>&lt;br/&gt;From revision %1&lt;br/&gt;</source>
<extracomment>This gets conditionally inserted as argument %8 into the description string.</extracomment>
<translation>&lt;br/&gt;リビジョン %1&lt;br/&gt;</translation>
@@ -12495,7 +15216,7 @@ to version control (%2)
</message>
<message>
<source>&lt;h3&gt;%1&lt;/h3&gt;%2&lt;br/&gt;%3%4%5&lt;br/&gt;Copyright 2008-%6 %7. All rights reserved.&lt;br/&gt;&lt;br/&gt;The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;h3&gt;%1&lt;/h3&gt;%2&lt;br/&gt;%3%4%5&lt;br/&gt;Copyright 2008-%6 %7. All rights reserved.&lt;br/&gt;&lt;br/&gt;The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.&lt;br/&gt;</translation>
</message>
</context>
<context>
@@ -12636,6 +15357,21 @@ to version control (%2)
<context>
<name>CppEditor::Internal::CppEditorPlugin</name>
<message>
+ <source>C++</source>
+ <comment>SnippetProvider</comment>
+ <translation>C++</translation>
+ </message>
+ <message>
+ <source>Header/Source</source>
+ <comment>text on macOS touch bar</comment>
+ <translation>ヘッダ/ソース</translation>
+ </message>
+ <message>
+ <source>Follow</source>
+ <comment>text on macOS touch bar</comment>
+ <translation>フォロー</translation>
+ </message>
+ <message>
<source>Additional Preprocessor Directives...</source>
<translation>追加ã®ãƒ—リプロセッサディレクティブ...</translation>
</message>
@@ -12648,6 +15384,11 @@ to version control (%2)
<translation>Shift+F2</translation>
</message>
<message>
+ <source>Decl/Def</source>
+ <comment>text on macOS touch bar</comment>
+ <translation>宣言/定義</translation>
+ </message>
+ <message>
<source>Open Function Declaration/Definition in Next Split</source>
<translation>関数ã®å®£è¨€ã‚ã‚‹ã„ã¯å®šç¾©ã‚’次ã®åˆ†å‰²ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ã</translation>
</message>
@@ -12866,6 +15607,10 @@ to version control (%2)
<translation>ローカル宣言を追加</translation>
</message>
<message>
+ <source>Convert to Binary</source>
+ <translation>2進数ã«å¤‰æ›</translation>
+ </message>
+ <message>
<source>Convert to Camel Case</source>
<translation>キャメルケースã«å¤‰æ›</translation>
</message>
@@ -12874,6 +15619,10 @@ to version control (%2)
<translation>#include %1 を追加</translation>
</message>
<message>
+ <source>Add forward declaration for %1</source>
+ <translation>%1 ã®å‰æ–¹å®£è¨€ã‚’追加ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Switch with Previous Parameter</source>
<translation>å‰ã®ãƒ‘ラメータã«åˆ‡ã‚Šæ›¿ãˆã‚‹</translation>
</message>
@@ -12905,6 +15654,14 @@ to version control (%2)
<source>Optimize for-Loop</source>
<translation>for ループを最é©åŒ–ã™ã‚‹</translation>
</message>
+ <message>
+ <source>Remove All Occurrences of &quot;using namespace %1&quot; in Global Scope and Adjust Type Names Accordingly</source>
+ <translation>グローãƒãƒ«ãƒ»ã‚¹ã‚³ãƒ¼ãƒ—ã§ã® &quot;using namespace %1&quot; ã®ã™ã¹ã¦ã®å‡ºç¾ç®‡æ‰€ã‚’削除ã—ã€ãã‚Œã«å¿œã˜ã¦åž‹åを調整ã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Remove &quot;using namespace %1&quot; and Adjust Type Names Accordingly</source>
+ <translation>&quot;using namespace %1&quot;を削除ã—ã€ãã‚Œã«å¿œã˜ã¦ã‚¿ã‚¤ãƒ—åを調整ã—ã¾ã™</translation>
+ </message>
</context>
<context>
<name>CppEditor::InsertDeclOperation</name>
@@ -13077,6 +15834,14 @@ to version control (%2)
<source>Derived</source>
<translation>派生</translation>
</message>
+ <message>
+ <source>Evaluating Type Hierarchy</source>
+ <translation>型階層を評価ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Evaluating type hierarchy...</source>
+ <translation>型階層を評価ã™ã‚‹...</translation>
+ </message>
</context>
<context>
<name>CppEditor::Internal::CppTypeHierarchyFactory</name>
@@ -13161,6 +15926,22 @@ to version control (%2)
</translation>
</message>
<message>
+ <source>/**************************************************************************
+** %1 license header template
+** Special keywords: %USER% %DATE% %YEAR%
+** Environment variables: %$VARIABLE%
+** To protect a percent sign, use &apos;%%&apos;.
+**************************************************************************/
+</source>
+ <translation>/**************************************************************************
+** %1 ライセンスヘッダテンプレート
+** 特別ãªã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰: %USER% %DATE% %YEAR%
+** 環境変数: %$VARIABLE%
+** パーセント記å·ã‚’ä¿è­·ã™ã‚‹ã«ã¯ã€&apos;%%&apos;を使用ã—ã¾ã™ã€‚
+**************************************************************************/
+</translation>
+ </message>
+ <message>
<source>Edit...</source>
<translation>編集...</translation>
</message>
@@ -13172,6 +15953,22 @@ to version control (%2)
<context>
<name>CppTools::Internal::CppFindReferences</name>
<message>
+ <source>Reads</source>
+ <translation>読ã¿å‡ºã—</translation>
+ </message>
+ <message>
+ <source>Writes</source>
+ <translation>書ãè¾¼ã¿</translation>
+ </message>
+ <message>
+ <source>Declarations</source>
+ <translation>宣言</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>ãã®ä»–</translation>
+ </message>
+ <message>
<source>C++ Usages:</source>
<translation>C++ 出ç¾ç®‡æ‰€:</translation>
</message>
@@ -13179,6 +15976,18 @@ to version control (%2)
<source>Searching for Usages</source>
<translation>使用方法ã®æ¤œç´¢ä¸­</translation>
</message>
+ <message numerus="yes">
+ <source>Re&amp;name %n files</source>
+ <translation>
+ <numerusform>%n 個ã®ãƒ•ã‚¡ã‚¤ãƒ«åを変更(&amp;R)</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Files:
+%1</source>
+ <translation>Files:
+%1</translation>
+ </message>
<message>
<source>C++ Macro Usages:</source>
<translation>C++ マクロ出ç¾ç®‡æ‰€:</translation>
@@ -13204,6 +16013,10 @@ to version control (%2)
<source>Qt Creator Built-in</source>
<translation>Qt Creator ビルトイン</translation>
</message>
+ <message>
+ <source>%1 Built-in</source>
+ <translation>%1 ビルトイン</translation>
+ </message>
</context>
<context>
<name>CppTools</name>
@@ -13216,6 +16029,38 @@ to version control (%2)
<translation>ファイル命åè¦å‰‡</translation>
</message>
<message>
+ <source>Diagnostic Configurations</source>
+ <translation>診断設定</translation>
+ </message>
+ <message>
+ <source>C++ Symbols in Current Document</source>
+ <translation>ç¾åœ¨ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã® C++ シンボル</translation>
+ </message>
+ <message>
+ <source>C++ Classes</source>
+ <translation>C++ クラス</translation>
+ </message>
+ <message>
+ <source>C++ Functions</source>
+ <translation>C++ 関数</translation>
+ </message>
+ <message>
+ <source>All Included C/C++ Files</source>
+ <translation>インクルードã•ã‚Œã‚‹ã™ã¹ã¦ã® C/C++ ファイル</translation>
+ </message>
+ <message>
+ <source>C++ Classes, Enums, Functions and Type Aliases</source>
+ <translation>C++ クラスã€åˆ—挙型ã€é–¢æ•°ã€ãŠã‚ˆã³åž‹ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹</translation>
+ </message>
+ <message>
+ <source>C++ Classes, Enums and Functions</source>
+ <translation type="vanished">C++ クラスã€åˆ—挙型ã€é–¢æ•°</translation>
+ </message>
+ <message>
+ <source>C++ Symbols</source>
+ <translation>C++ シンボル</translation>
+ </message>
+ <message>
<source>Code Model</source>
<translation>コードモデル</translation>
</message>
@@ -13239,6 +16084,18 @@ to version control (%2)
<source>Obj-C++11</source>
<translation>Obj-C++11</translation>
</message>
+ <message>
+ <source>Quick Fixes</source>
+ <translation>迅速ãªä¿®æ­£</translation>
+ </message>
+ <message>
+ <source>The project contains C source files, but the currently active kit has no C compiler. The code model will not be fully functional.</source>
+ <translation>プロジェクトã«ã¯C言語ã®ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ãŒã€ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªã‚­ãƒƒãƒˆã«ã¯C言語ã®ã‚³ãƒ³ãƒ‘イラãŒã‚ã‚Šã¾ã›ã‚“。ã“ã®å ´åˆã€ã‚³ãƒ¼ãƒ‰ãƒ¢ãƒ‡ãƒ«ã¯å®Œå…¨ã«ã¯æ©Ÿèƒ½ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>The project contains C++ source files, but the currently active kit has no C++ compiler. The code model will not be fully functional.</source>
+ <translation>プロジェクトã«ã¯ C++ 言語ã®ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ãŒã€ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªã‚­ãƒƒãƒˆã«ã¯ C++ 言語ã®ã‚³ãƒ³ãƒ‘イラãŒã‚ã‚Šã¾ã›ã‚“。ã“ã®å ´åˆã€ã‚³ãƒ¼ãƒ‰ãƒ¢ãƒ‡ãƒ«ã¯å®Œå…¨ã«ã¯æ©Ÿèƒ½ã—ã¾ã›ã‚“。</translation>
+ </message>
</context>
<context>
<name>CppTools::Internal::CppToolsPlugin</name>
@@ -13248,11 +16105,11 @@ to version control (%2)
</message>
<message>
<source>Switch Header/Source</source>
- <translation>ヘッダー/ソースã®åˆ‡æ›¿</translation>
+ <translation>ヘッダ/ソースã®åˆ‡æ›¿</translation>
</message>
<message>
<source>Open Corresponding Header/Source in Next Split</source>
- <translation>対応ã™ã‚‹ãƒ˜ãƒƒãƒ€ãƒ¼/ソースを次ã®åˆ†å‰²ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ã</translation>
+ <translation>対応ã™ã‚‹ãƒ˜ãƒƒãƒ€/ソースを次ã®åˆ†å‰²ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ã</translation>
</message>
<message>
<source>Meta+E, F4</source>
@@ -13270,6 +16127,10 @@ to version control (%2)
<source>The configured path to the license template</source>
<translation>設定ã•ã‚ŒãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ†ãƒ³ãƒ—レートã®ãƒ‘ス</translation>
</message>
+ <message>
+ <source>Insert &quot;#pragma once&quot; instead of &quot;#ifndef&quot; include guards into header file</source>
+ <translation>「#ifndefã€ã®ä»£ã‚ã‚Šã«ã€Œ#pragma onceã€ã‚’インクルードガードã¨ã—ã¦ãƒ˜ãƒƒãƒ€ãƒ¼ãƒ•ã‚¡ã‚¤ãƒ«ã«æŒ¿å…¥ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>CppTools::CppToolsSettings</name>
@@ -13399,6 +16260,22 @@ Flags: %3</source>
<translation>&amp;CVS</translation>
</message>
<message>
+ <source>Ignore Whitespace</source>
+ <translation>空白を無視</translation>
+ </message>
+ <message>
+ <source>Ignore Blank Lines</source>
+ <translation>空行を無視</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>編集(&amp;E)</translation>
+ </message>
+ <message>
+ <source>CVS Checkout</source>
+ <translation>CVS ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ</translation>
+ </message>
+ <message>
<source>Diff Current File</source>
<translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®å·®åˆ†è¡¨ç¤º</translation>
</message>
@@ -13691,6 +16568,10 @@ Flags: %3</source>
<source>CVS Command</source>
<translation>CVS コマンド</translation>
</message>
+ <message>
+ <source>CVS</source>
+ <translation>CVS</translation>
+ </message>
</context>
<context>
<name>Debugger::Internal::BreakHandler</name>
@@ -13776,6 +16657,166 @@ Flags: %3</source>
<translation>未知ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã®ç¨®é¡ž</translation>
</message>
<message>
+ <source>Edit Breakpoint Properties</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®ãƒ—ロパティを編集</translation>
+ </message>
+ <message>
+ <source>Basic</source>
+ <translation>基本</translation>
+ </message>
+ <message>
+ <source>File Name and Line Number</source>
+ <translation>ファイルåã¨è¡Œç•ªå·</translation>
+ </message>
+ <message>
+ <source>Function Name</source>
+ <translation>関数å</translation>
+ </message>
+ <message>
+ <source>Break on Memory Address</source>
+ <translation>メモリアドレスã§ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break When C++ Exception Is Thrown</source>
+ <translation>C++ 例外㌠throw ã•ã‚ŒãŸæ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break When C++ Exception Is Caught</source>
+ <translation>C++ 例外を catch ã—ãŸæ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break When Function &quot;main&quot; Starts</source>
+ <translation>&quot;main&quot; 関数ã®é–‹å§‹æ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break When a New Process Is Forked</source>
+ <translation>æ–°ã—ã„プロセスãŒèµ·å‹•ã•ã‚ŒãŸæ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break When a New Process Is Executed</source>
+ <translation>æ–°ã—ã„プロセスãŒå®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break When a System Call Is Executed</source>
+ <translation>システムコールãŒå®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break on Data Access at Fixed Address</source>
+ <translation>固定アドレスã®ãƒ‡ãƒ¼ã‚¿ã‚¢ã‚¯ã‚»ã‚¹æ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break on Data Access at Address Given by Expression</source>
+ <translation>å¼ã«ã‚ˆã£ã¦å¾—られるアドレスã®ãƒ‡ãƒ¼ã‚¿ã‚¢ã‚¯ã‚»ã‚¹æ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break on QML Signal Emit</source>
+ <translation>QML シグナル発生ã§ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Break When JavaScript Exception Is Thrown</source>
+ <translation>JavaScript 例外㌠throw ã•ã‚ŒãŸæ™‚ã«ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Breakpoint &amp;type:</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®ç¨®é¡ž(&amp;T):</translation>
+ </message>
+ <message>
+ <source>&amp;File name:</source>
+ <translation>ファイルå(&amp;F):</translation>
+ </message>
+ <message>
+ <source>&amp;Line number:</source>
+ <translation>行番å·(&amp;L):</translation>
+ </message>
+ <message>
+ <source>&amp;Enabled:</source>
+ <translation>有効(&amp;E):</translation>
+ </message>
+ <message>
+ <source>&amp;Address:</source>
+ <translation>アドレス(&amp;A):</translation>
+ </message>
+ <message>
+ <source>&amp;Expression:</source>
+ <translation>å¼(&amp;E):</translation>
+ </message>
+ <message>
+ <source>Fun&amp;ction:</source>
+ <translation>関数(&amp;C):</translation>
+ </message>
+ <message>
+ <source>Advanced</source>
+ <translation>æ‹¡å¼µ</translation>
+ </message>
+ <message>
+ <source>T&amp;racepoint only:</source>
+ <translation>トレースãƒã‚¤ãƒ³ãƒˆã®ã¿(&amp;R):</translation>
+ </message>
+ <message>
+ <source>&amp;One shot only:</source>
+ <translation>1回ã ã‘(&amp;O):</translation>
+ </message>
+ <message>
+ <source>&lt;p&gt;Determines how the path is specified when setting breakpoints:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;Use Engine Default&lt;/i&gt;: Preferred setting of the debugger engine.&lt;/li&gt;&lt;li&gt;&lt;i&gt;Use Full Path&lt;/i&gt;: Pass full path, avoiding ambiguities should files of the same name exist in several modules. This is the engine default for CDB and LLDB.&lt;/li&gt;&lt;li&gt;&lt;i&gt;Use File Name&lt;/i&gt;: Pass the file name only. This is useful when using a source tree whose location does not match the one used when building the modules. It is the engine default for GDB as using full paths can be slow with this engine.&lt;/li&gt;&lt;/ul&gt;</source>
+ <translation>&lt;p&gt;ブレークãƒã‚¤ãƒ³ãƒˆè¨­å®šæ™‚ã®ãƒ‘ス指定方法ã®æ±ºå®š:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;エンジン既定ã®æ–¹æ³•ã‚’使用&lt;/i&gt;: デãƒãƒƒã‚°ã‚¨ãƒ³ã‚¸ãƒ³æ—¢å®šã®æ–¹æ³•ã‚’使用ã—ã¾ã™ã€‚&lt;/li&gt;&lt;li&gt;&lt;i&gt;フルパスを使用&lt;/i&gt;: フルパスを使用ã—ã¾ã™ã€‚複数ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã«åŒåã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒå­˜åœ¨ã™ã‚‹å ´åˆã®æ›–昧性を回é¿ã§ãã¾ã™ã€‚CDB 㨠LLDB デãƒãƒƒã‚°ã‚¨ãƒ³ã‚¸ãƒ³ã®æ—¢å®šå€¤ã§ã™ã€‚&lt;/li&gt;&lt;li&gt;&lt;i&gt;ファイルåを使用&lt;/i&gt;: ファイルåã®ã¿ã‚’使用ã—ã¾ã™ã€‚ã“ã®æ–¹æ³•ã¯ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ãƒ“ルド時ã«ä½¿ç”¨ã•ã‚ŒãŸãƒ‘スã«åˆè‡´ã—ãªã„ソースツリーã§ã¯ä¾¿åˆ©ã§ã™ã€‚GDB デãƒãƒƒã‚°ã‚¨ãƒ³ã‚¸ãƒ³ã¯ãƒ•ãƒ«ãƒ‘ス使用時ã«é…ããªã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ãŸã‚ã€ã“ã®å€¤ãŒæ—¢å®šå€¤ã¨ãªã‚Šã¾ã™ã€‚&lt;/li&gt;&lt;/ul&gt;</translation>
+ </message>
+ <message>
+ <source>Use Engine Default</source>
+ <translation>エンジン既定ã®æ–¹æ³•ã‚’使用</translation>
+ </message>
+ <message>
+ <source>Use Full Path</source>
+ <translation>フルパスを使用</translation>
+ </message>
+ <message>
+ <source>Use File Name</source>
+ <translation>ファイルåを使用</translation>
+ </message>
+ <message>
+ <source>Pat&amp;h:</source>
+ <translation>パス(&amp;H):</translation>
+ </message>
+ <message>
+ <source>Specifying the module (base name of the library or executable) for function or file type breakpoints can significantly speed up debugger startup times (CDB, LLDB).</source>
+ <translation>関数åやファイルåã§æŒ‡å®šã™ã‚‹ãƒ–レークãƒã‚¤ãƒ³ãƒˆã¯ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«(ライブラリや実行ファイルã®ãƒ™ãƒ¼ã‚¹å)を指定ã™ã‚‹ã“ã¨ã§å¤§å¹…ã«é«˜é€ŸåŒ–ã—ã¾ã™(CDB, LLDB)。</translation>
+ </message>
+ <message>
+ <source>&amp;Module:</source>
+ <translation>モジュール(&amp;M):</translation>
+ </message>
+ <message>
+ <source>Debugger commands to be executed when the breakpoint is hit. This feature is only available for GDB.</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã«åˆ°é”ã—ãŸéš›ã«å®Ÿè¡Œã•ã‚Œã‚‹ãƒ‡ãƒãƒƒã‚¬ã®ã‚³ãƒžãƒ³ãƒ‰ã§ã™ã€‚ã“ã®æ©Ÿèƒ½ã¯ GDB ã®ã¿å¯¾å¿œã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Commands:</source>
+ <translation>コマンド(&amp;C):</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>メッセージ(&amp;M):</translation>
+ </message>
+ <message>
+ <source>C&amp;ondition:</source>
+ <translation>æ¡ä»¶(&amp;O):</translation>
+ </message>
+ <message>
+ <source>&amp;Ignore count:</source>
+ <translation>無視ã™ã‚‹å›žæ•°(&amp;I):</translation>
+ </message>
+ <message>
+ <source>&amp;Thread specification:</source>
+ <translation>スレッド指定 (&amp;T):</translation>
+ </message>
+ <message>
+ <source>Propagate Change to Preset Breakpoint</source>
+ <translation>事å‰ã«è¨­å®šã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã«å¤‰æ›´ã‚’ä¼æ¬ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>&amp;Condition:</source>
+ <translation>æ¡ä»¶(&amp;C):</translation>
+ </message>
+ <message>
<source>Number</source>
<translation>番å·</translation>
</message>
@@ -13832,6 +16873,70 @@ Flags: %3</source>
<translation>指定ã•ã‚ŒãŸã‚¹ãƒ¬ãƒƒãƒ‰å†…ã ã‘ã§æœ‰åŠ¹ã«ãªã‚‹ãƒ–レークãƒã‚¤ãƒ³ãƒˆã§ã™ã€‚</translation>
</message>
<message>
+ <source>Add Breakpoint...</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã‚’追加...</translation>
+ </message>
+ <message>
+ <source>Delete Selected Breakpoints</source>
+ <translation>é¸æŠžã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Edit Selected Breakpoints...</source>
+ <translation>é¸æŠžã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’編集ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Disable Selected Breakpoints</source>
+ <translation>é¸æŠžã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã®ç„¡åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Enable Selected Breakpoints</source>
+ <translation>é¸æŠžã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã®æœ‰åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Disable Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®ç„¡åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Enable Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®æœ‰åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Disable Selected Locations</source>
+ <translation>é¸æŠžã—ãŸãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã®ç„¡åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Enable Selected Locations</source>
+ <translation>é¸æŠžã—ãŸãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã®æœ‰åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Disable Location</source>
+ <translation>ロケーションã®ç„¡åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Enable Location</source>
+ <translation>ロケーションã®æœ‰åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Delete All Breakpoints</source>
+ <translation>ã™ã¹ã¦ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete Breakpoints of &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete Breakpoints of File</source>
+ <translation>ファイル内ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Internal ID:</source>
+ <translation>内部ID:</translation>
+ </message>
+ <message>
<source>State:</source>
<translation>状態:</translation>
</message>
@@ -13844,6 +16949,22 @@ Flags: %3</source>
<translation>無効</translation>
</message>
<message>
+ <source>pending</source>
+ <translation>待機中</translation>
+ </message>
+ <message>
+ <source>Display Name:</source>
+ <translation>表示å:</translation>
+ </message>
+ <message>
+ <source>Stopped at breakpoint %1 in thread %2.</source>
+ <translation>スレッド %2 ã«ãŠã„ã¦ãƒ–レークãƒã‚¤ãƒ³ãƒˆ %1ã§åœæ­¢ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Unclaimed Breakpoint</source>
+ <translation>未請求ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆ</translation>
+ </message>
+ <message>
<source>, pending</source>
<translation>, 待機中</translation>
</message>
@@ -14236,10 +17357,34 @@ Flags: %3</source>
<translation>CDB 実行ファイルãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Internal error: The extension %1 cannot be found.
+If you have updated %2 via Maintenance Tool, you may need to rerun the Tool and select &quot;Add or remove components&quot; and then select the Qt &gt; Tools &gt; Qt Creator CDB Debugger Support component.
+If you build %2 from sources and want to use a CDB executable with another bitness than your %2 build, you will need to build a separate CDB extension with the same bitness as the CDB you want to use.</source>
+ <translation>内部エラーã§ã™ã€‚æ‹¡å¼µå­ %1 ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+Maintenance Tool 㧠%2 ã‚’æ›´æ–°ã—ãŸå ´åˆã¯ã€Maintenance Tool ã‚’å†å®Ÿè¡Œã—ã¦ã€[Add or remove components] ã‚’é¸æŠžã—ã€Qt &gt; Tools &gt; Qt Creator CDB Debugger Support コンãƒãƒ¼ãƒãƒ³ãƒˆã‚’é¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+ソースã‹ã‚‰ %2 をビルドã—ã¦ã€%2 ã®ãƒ“ルドã¨ã¯ç•°ãªã‚‹ãƒ“ット㮠CDB 実行ファイルを使用ã™ã‚‹å ´åˆã¯ã€ä½¿ç”¨ã™ã‚‹ CDB ã¨åŒã˜ãƒ“ットã§åˆ¥ã® CDB 拡張をビルドã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Interrupting is not possible in remote sessions.</source>
<translation>リモートセッションã«ã¯å‰²ã‚Šè¾¼ã¿ã§ãã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Trace point %1 in thread %2 triggered.</source>
+ <translation>スレッド %2 ã§ãƒˆãƒ¬ãƒ¼ã‚¹ãƒã‚¤ãƒ³ãƒˆ %1ã«åˆ°é”ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Conditional breakpoint %1 in thread %2 triggered, examining expression &quot;%3&quot;.</source>
+ <translation>スレッド %2 ã§æ¡ä»¶ä»˜ãブレークãƒã‚¤ãƒ³ãƒˆ %1 ã«åˆ°é”ã—ãŸç‚ºã€å¼ &quot;%3&quot; を評価ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Debugger encountered an exception: %1</source>
+ <translation>デãƒãƒƒã‚¬ã§ä¾‹å¤–ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Module loaded: %1</source>
+ <translation>読込済ã¿ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«: %1</translation>
+ </message>
+ <message>
<source>Trace point %1 (%2) in thread %3 triggered.</source>
<translation>スレッド %3 ã§ãƒˆãƒ¬ãƒ¼ã‚¹ãƒã‚¤ãƒ³ãƒˆ %1 (%2) ã«åˆ°é”ã—ã¾ã—ãŸã€‚</translation>
</message>
@@ -14328,6 +17473,10 @@ Flags: %3</source>
<source>Source Paths</source>
<translation>ソースã®ãƒ‘ス</translation>
</message>
+ <message>
+ <source>CDB Paths</source>
+ <translation>CDB ã®ãƒ‘ス</translation>
+ </message>
</context>
<context>
<name>Debugger::Internal::CdbPathsPage</name>
@@ -14359,6 +17508,18 @@ Flags: %3</source>
<translation>メインエディタã®ãƒ•ã‚©ãƒ³ãƒˆã‚µã‚¤ã‚ºãŒå¤‰æ›´ã•ã‚ŒãŸã¨ãã«ã€ãƒ‡ãƒãƒƒã‚¬è¡¨ç¤ºã®ãƒ•ã‚©ãƒ³ãƒˆã‚µã‚¤ã‚ºã‚‚変更ã—ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Use annotations in main editor while debugging</source>
+ <translation>デãƒãƒƒã‚°ä¸­ã«ãƒ¡ã‚¤ãƒ³ã‚¨ãƒ‡ã‚£ã‚¿ã§ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Closes automatically opened source views when the debugger exits.</source>
+ <translation>デãƒãƒƒã‚¬ãƒ¼ã®çµ‚了時ã«ã€è‡ªå‹•çš„ã«é–‹ã„ã¦ã„ãŸã‚½ãƒ¼ã‚¹ãƒ“ューを閉ã˜ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Closes automatically opened memory views when the debugger exits.</source>
+ <translation>デãƒãƒƒã‚¬ãƒ¼ã®çµ‚了時ã«ã€è‡ªå‹•çš„ã«é–‹ã‹ã‚ŒãŸãƒ¡ãƒ¢ãƒªãƒ¼ãƒ“ューを閉ã˜ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Switch to previous mode on debugger exit</source>
<translation>デãƒãƒƒã‚¬çµ‚了時ã«ç›´å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹</translation>
</message>
@@ -14415,6 +17576,18 @@ Flags: %3</source>
<translation>ãƒã‚¹ãƒˆãƒ¢ãƒ€ãƒ³ãƒ‡ãƒãƒƒã‚°ã« Qt Creator を使用ã™ã‚‹</translation>
</message>
<message>
+ <source>Bring %1 to foreground when application interrupts</source>
+ <translation>アプリケーションã®å‰²ã‚Šè¾¼ã¿æ™‚ã« %1 をフォアグラウンドã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Registers %1 for debugging crashed applications.</source>
+ <translation>クラッシュã—ãŸã‚¢ãƒ—リケーションをデãƒãƒƒã‚°ã™ã‚‹ãŸã‚ã« %1 を登録ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Use %1 for post-mortem debugging</source>
+ <translation>ãƒã‚¹ãƒˆãƒ¢ãƒ¼ãƒ†ãƒ ãƒ»ãƒ‡ãƒãƒƒã‚°ã« %1 を使用ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Warn when debugging &quot;Release&quot; builds</source>
<translation>&quot;リリース&quot; ビルドã®ãƒ‡ãƒãƒƒã‚°æ™‚ã«è­¦å‘Šã™ã‚‹</translation>
</message>
@@ -14434,6 +17607,14 @@ Flags: %3</source>
<source>&lt;unlimited&gt;</source>
<translation>&lt;無制é™&gt;</translation>
</message>
+ <message>
+ <source>Stop when %1() is called</source>
+ <translation>%1() ãŒå‘¼ã³å‡ºã•ã‚ŒãŸã‚‰åœæ­¢ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Always adds a breakpoint on the &lt;i&gt;%1()&lt;/i&gt; function.</source>
+ <translation>常㫠&lt;i&gt;%1()&lt;/i&gt; 関数ã«ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’追加ã™ã‚‹ã€‚</translation>
+ </message>
</context>
<context>
<name>Debugger</name>
@@ -14509,6 +17690,10 @@ Flags: %3</source>
<translation>自動的ã«ãƒã‚¤ãƒ³ã‚¿ã‚’逆å‚ç…§ã™ã‚‹</translation>
</message>
<message>
+ <source>&lt;p&gt;This switches the Locals and Expressions views to automatically dereference pointers. This saves a level in the tree view, but also loses data for the now-missing intermediate level.</source>
+ <translation>&lt;p&gt;ローカル変数ã¨å¼ãƒ“ューã§ãƒã‚¤ãƒ³ã‚¿ã‚’自動的ã«é€†å‚ç…§ã™ã‚‹ã‹ã©ã†ã‹ã‚’切り替ãˆã¾ã™ã€‚ツリービューã®éšŽå±¤ã‚’減らã™ã“ã¨ãŒã§ãã¾ã™ãŒã€è¡¨ç¤ºã•ã‚Œãªã„中間レベルã®ãƒ‡ãƒ¼ã‚¿ãŒå¤±ã‚ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Show &quot;std::&quot; Namespace in Types</source>
<translation>型情報㫠&quot;std::&quot; åå‰ç©ºé–“ã‚’å«ã‚ã‚‹</translation>
</message>
@@ -14601,6 +17786,14 @@ Flags: %3</source>
<translation>デãƒãƒƒã‚¬ã‚’自動的ã«çµ‚了ã™ã‚‹</translation>
</message>
<message>
+ <source>Use annotations in main editor when debugging</source>
+ <translation>デãƒãƒƒã‚°ä¸­ã«ãƒ¡ã‚¤ãƒ³ã‚¨ãƒ‡ã‚£ã‚¿ã§ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>&lt;p&gt;Checking this will show simple variable values as annotations in the main editor during debugging.</source>
+ <translation>&lt;p&gt;ã“れをãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨ã€ãƒ‡ãƒãƒƒã‚°æ™‚ã«ã‚·ãƒ³ãƒ—ルãªå¤‰æ•°ã®å€¤ãŒãƒ¡ã‚¤ãƒ³ã‚¨ãƒ‡ã‚£ã‚¿ã«ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã¨ã—ã¦è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Use tooltips in main editor when debugging</source>
<translation>デãƒãƒƒã‚°ä¸­ã®ãƒ¡ã‚¤ãƒ³ã‚¨ãƒ‡ã‚£ã‚¿ã§ãƒ„ールãƒãƒƒãƒ—を使用ã™ã‚‹</translation>
</message>
@@ -14633,6 +17826,10 @@ Flags: %3</source>
<translation>&lt;p&gt;デãƒãƒƒã‚°ä¸­ã€ã‚¹ã‚¿ãƒƒã‚¯ãƒ“ューã§ãƒ„ールãƒãƒƒãƒ—を有効ã«ã—ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>&lt;p&gt;The maximum length of string entries in the Locals and Expressions views. Longer than that are cut off and displayed with an ellipsis attached.</source>
+ <translation>&lt;p&gt;ローカル変数ã¨å¼ãƒ“ューã«è¡¨ç¤ºã™ã‚‹æ–‡å­—列ã®æœ€å¤§é•·ã§ã™ã€‚ã“ã®å€¤ã‚ˆã‚Šã‚‚é•·ã„文字列ã¯çœç•¥è¨˜å·ã‚’付ã‘ã¦é€”中ã¾ã§ã‚’表示ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Show Address Data in Breakpoints View when Debugging</source>
<translation>デãƒãƒƒã‚°ä¸­ã«ãƒ–レークãƒã‚¤ãƒ³ãƒˆãƒ“ューã§ã‚¢ãƒ‰ãƒ¬ã‚¹ãƒ‡ãƒ¼ã‚¿ã‚’表示ã™ã‚‹</translation>
</message>
@@ -14724,10 +17921,57 @@ Flags: %3</source>
<translation>ã“ã®ã‚ªãƒ—ションã¯ãƒ‡ãƒãƒƒã‚°ã‚µãƒ¼ãƒã‚’èµ·å‹•ã™ã‚‹ã®ã«ç”¨ã„られるスクリプトを指定ã™ã‚‹ã®ã«ä½¿ç”¨ã—ã¾ã™ã€‚空欄ã«ã—ãŸå ´åˆã¯ Qt Creator 既定ã®æ–¹æ³•ã§ãƒ‡ãƒãƒƒã‚°ã‚µãƒ¼ãƒã‚’èµ·å‹•ã—ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Normally, the running server is identified by the IP of the device in the kit and the server port selected above.
+You can choose another communication channel here, such as a serial line or custom ip:port.</source>
+ <translation>通常ã€å®Ÿè¡Œä¸­ã®ã‚µãƒ¼ãƒãƒ¼ã¯ã€ã‚­ãƒƒãƒˆå†…ã®ãƒ‡ãƒã‚¤ã‚¹ã® IP ã¨ã€ä¸Šè¨˜ã§é¸æŠžã—ãŸã‚µãƒ¼ãƒãƒ¼ãƒãƒ¼ãƒˆã§è­˜åˆ¥ã•ã‚Œã¾ã™ã€‚
+ã“ã“ã§ã¯ã€ã‚·ãƒªã‚¢ãƒ«ãƒ©ã‚¤ãƒ³ã‚„カスタム ip:port ãªã©ã€åˆ¥ã®é€šä¿¡ãƒãƒ£ãƒãƒ«ã‚’é¸æŠžã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Override server channel:</source>
+ <translation>サーãƒãƒ¼ãƒãƒ£ãƒ³ãƒãƒ«ã‚’上書ãã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>For example, %1</source>
+ <extracomment>&quot;For example, /dev/ttyS0, COM1, 127.0.0.1:1234&quot;</extracomment>
+ <translation>例: %1</translation>
+ </message>
+ <message>
+ <source>This option can be used to point to a script that will be used to start a debug server. If the field is empty, default methods to set up debug servers will be used.</source>
+ <translation>ã“ã®ã‚ªãƒ—ションã¯ãƒ‡ãƒãƒƒã‚°ã‚µãƒ¼ãƒãƒ¼ã‚’èµ·å‹•ã™ã‚‹ã®ã«ç”¨ã„られるスクリプトを指定ã™ã‚‹ã®ã«ä½¿ç”¨ã—ã¾ã™ã€‚空欄ã«ã—ãŸå ´åˆã¯ã€æ—¢å®šã®æ–¹æ³•ã§ãƒ‡ãƒãƒƒã‚°ã‚µãƒ¼ãƒãƒ¼ã‚’èµ·å‹•ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>&amp;Server start script:</source>
<translation>サーãƒãƒ¼èµ·å‹•ã‚¹ã‚¯ãƒªãƒ—ト(&amp;S):</translation>
</message>
<message>
+ <source>Select SysRoot Directory</source>
+ <translation>SysRoot ディレクトリをé¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>This option can be used to override the kit&apos;s SysRoot setting.</source>
+ <translation>ã“ã®ã‚ªãƒ—ションを使用ã™ã‚‹ã¨ã€ã‚­ãƒƒãƒˆã® SysRoot 設定を上書ãã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Override S&amp;ysRoot:</source>
+ <translation>S&amp;ysRoot を上書ãã—ã¾ã™:</translation>
+ </message>
+ <message>
+ <source>This option can be used to send the target init commands.</source>
+ <translation>ã“ã®ã‚ªãƒ—ションã¯ã€ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã® init コマンドをé€ä¿¡ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Init commands:</source>
+ <translation>åˆæœŸåŒ–コマンド(&amp;I):</translation>
+ </message>
+ <message>
+ <source>This option can be used to send the target reset commands.</source>
+ <translation>ã“ã®ã‚ªãƒ—ションを使用ã—ã¦ã€ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã®ãƒªã‚»ãƒƒãƒˆã‚³ãƒžãƒ³ãƒ‰ã‚’é€ä¿¡ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Reset commands:</source>
+ <translation>リセットコマンド(&amp;R):</translation>
+ </message>
+ <message>
<source>Select Location of Debugging Information</source>
<translation>デãƒãƒƒã‚°æƒ…å ±ã®ãƒ‘スをé¸æŠž</translation>
</message>
@@ -14757,16 +18001,20 @@ Flags: %3</source>
</message>
<message>
<source>Break at &quot;&amp;main&quot;:</source>
- <translation>&quot;&amp;main&quot; 関数ã§ãƒ–レーク(&amp;m):</translation>
+ <translation>&quot;&amp;main&quot; 関数ã§ãƒ–レーク(&amp;M):</translation>
</message>
<message>
<source>Debug &amp;information:</source>
- <translation>デãƒãƒƒã‚°æƒ…å ±(&amp;i):</translation>
+ <translation>デãƒãƒƒã‚°æƒ…å ±(&amp;I):</translation>
</message>
<message>
<source>&amp;Recent:</source>
<translation>ç›´è¿‘(&amp;R):</translation>
</message>
+ <message>
+ <source>Attach to %1</source>
+ <translation>%1 ã«ã‚¢ã‚¿ãƒƒãƒ</translation>
+ </message>
</context>
<context>
<name>Debugger::Internal::AttachToQmlPortDialog</name>
@@ -14790,6 +18038,10 @@ Flags: %3</source>
<translation>&lt;html&gt;&lt;body&gt;&lt;p&gt;リモート CDB ã«ã¯å¯¾å¿œã™ã‚‹ Qt Creator CDB エクステンション(&lt;code&gt;%1&lt;/code&gt; ã‹ &lt;code&gt;%2&lt;/code&gt;)ãŒå¿…è¦ã§ã™ã€‚&lt;/p&gt;&lt;p&gt;エクステンションをリモートマシンã«ã‚³ãƒ”ーã—ã¦ã€ç’°å¢ƒå¤‰æ•° &lt;code&gt;%3&lt;/code&gt; ã«ãã®ãƒ•ã‚©ãƒ«ãƒ€ã‚’設定ã—ã¦ãã ã•ã„。&lt;/p&gt;&lt;p&gt;リモート CDB 㯠TCP/IP を接続プロトコルã¨ã—ã¦ä½¿ç”¨ã™ã‚‹ã‚ˆã†ã« &lt;code&gt;%4 &amp;lt;executable&amp;gt;&lt;/code&gt; ã¨å®Ÿè¡Œã—ã¦ãã ã•ã„。&lt;/p&gt;&lt;p&gt;接続パラメータã«ã¯ä»¥ä¸‹ã‚’使用ã—ã¦ãã ã•ã„:&lt;/p&gt;&lt;pre&gt;%5&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
+ <source>&lt;html&gt;&lt;body&gt;&lt;p&gt;The remote CDB needs to load the matching %1 CDB extension (&lt;code&gt;%2&lt;/code&gt; or &lt;code&gt;%3&lt;/code&gt;, respectively).&lt;/p&gt;&lt;p&gt;Copy it onto the remote machine and set the environment variable &lt;code&gt;%4&lt;/code&gt; to point to its folder.&lt;/p&gt;&lt;p&gt;Launch the remote CDB as &lt;code&gt;%5 &amp;lt;executable&amp;gt;&lt;/code&gt; to use TCP/IP as communication protocol.&lt;/p&gt;&lt;p&gt;Enter the connection parameters as:&lt;/p&gt;&lt;pre&gt;%6&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;body&gt;&lt;p&gt;リモート CDB ã«ã¯å¯¾å¿œã™ã‚‹ %1 CDB エクステンション(&lt;code&gt;%2&lt;/code&gt; ã‹ &lt;code&gt;%3&lt;/code&gt;)ãŒå¿…è¦ã§ã™ã€‚&lt;/p&gt;&lt;p&gt;エクステンションをリモートマシンã«ã‚³ãƒ”ーã—ã¦ã€ç’°å¢ƒå¤‰æ•° &lt;code&gt;%4&lt;/code&gt; ã«ãã®ãƒ•ã‚©ãƒ«ãƒ€ã‚’設定ã—ã¦ãã ã•ã„。&lt;/p&gt;&lt;p&gt;リモート CDB 㯠TCP/IP を接続プロトコルã¨ã—ã¦ä½¿ç”¨ã™ã‚‹ã‚ˆã†ã« &lt;code&gt;%5 &amp;lt;executable&amp;gt;&lt;/code&gt; ã¨å®Ÿè¡Œã—ã¦ãã ã•ã„。&lt;/p&gt;&lt;p&gt;接続パラメータã«ã¯ä»¥ä¸‹ã‚’使用ã—ã¦ãã ã•ã„:&lt;/p&gt;&lt;pre&gt;%6&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
<source>Start a CDB Remote Session</source>
<translation>CDB リモートセッションを開始</translation>
</message>
@@ -14862,6 +18114,47 @@ Flags: %3</source>
<context>
<name>Debugger::DebuggerItemManager</name>
<message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+ <message>
+ <source>Name:</source>
+ <translation>åå‰:</translation>
+ </message>
+ <message>
+ <source>Path:</source>
+ <translation>パス:</translation>
+ </message>
+ <message>
+ <source>Type:</source>
+ <translation>タイプ:</translation>
+ </message>
+ <message>
+ <source>ABIs:</source>
+ <translation>ABI:</translation>
+ </message>
+ <message>
+ <source>Version:</source>
+ <translation>ãƒãƒ¼ã‚¸ãƒ§ãƒ³:</translation>
+ </message>
+ <message>
+ <source>Working directory:</source>
+ <translation>作業ディレクトリ:</translation>
+ </message>
+ <message>
+ <source>64-bit version</source>
+ <translation>64 bit ãƒãƒ¼ã‚¸ãƒ§ãƒ³</translation>
+ </message>
+ <message>
+ <source>32-bit version</source>
+ <translation>32 bit ãƒãƒ¼ã‚¸ãƒ§ãƒ³</translation>
+ </message>
+ <message>
+ <source>Specify the path to the &lt;a href=&quot;%1&quot;&gt;Windows Console Debugger executable&lt;/a&gt; (%2) here.</source>
+ <extracomment>Label text for path configuration. %2 is &quot;x-bit version&quot;.</extracomment>
+ <translation>ã“ã“ã§ã¯ã€&lt;a href=&quot;%1&quot;&gt;Windows コンソールデãƒãƒƒã‚¬ãƒ¼ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«&lt;/a&gt; (%2)ã®ãƒ‘スを指定ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Auto-detected CDB at %1</source>
<translation>%1 ã« CDB を自動検出ã—ã¾ã—ãŸ</translation>
</message>
@@ -14873,6 +18166,20 @@ Flags: %3</source>
<message>
<source>Extracted from Kit %1</source>
<translation>キット %1 ã‹ã‚‰æŠ½å‡ºã—ã¾ã—ãŸ</translation>
+ <source>Auto-detected uVision at %1</source>
+ <translation>%1 ã§è‡ªå‹•æ¤œå‡ºã•ã‚ŒãŸ uVersion</translation>
+ </message>
+ <message>
+ <source>Extracted from Kit %1</source>
+ <translation type="vanished">キット %1 ã‹ã‚‰æŠ½å‡ºã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Not recognized</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+ <message>
+ <source>Could not determine debugger type</source>
+ <translation>デãƒãƒƒã‚¬ã®ç¨®é¡žãŒè­˜åˆ¥ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
</message>
</context>
<context>
@@ -15042,6 +18349,10 @@ Flags: %3</source>
<translation>デãƒãƒƒã‚¬</translation>
</message>
<message>
+ <source>Start debugging of startup project</source>
+ <translation>起動プロジェクトã®ãƒ‡ãƒãƒƒã‚°ã‚’開始ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>警告</translation>
</message>
@@ -15217,7 +18528,7 @@ Qt Creator ã¯ã‚¢ã‚¿ãƒƒãƒã§ãã¾ã›ã‚“。</translation>
</message>
<message>
<source>Run to Selected Function</source>
- <translation>é¸æŠžã•ã‚ŒãŸé–¢æ•°ã¾ã§å®Ÿè¡Œ</translation>
+ <translation>é¸æŠžã—ãŸé–¢æ•°ã¾ã§å®Ÿè¡Œ</translation>
</message>
<message>
<source>Immediately Return From Inner Function</source>
@@ -15288,6 +18599,26 @@ Qt Creator ã¯ã‚¢ã‚¿ãƒƒãƒã§ãã¾ã›ã‚“。</translation>
<translation>リモート CDB セッションã«ã‚¢ã‚¿ãƒƒãƒ...</translation>
</message>
<message>
+ <source>Start and Break on Main</source>
+ <translation>デãƒãƒƒã‚°ã‚’開始ã—㦠Main ã§ãƒ–レーク</translation>
+ </message>
+ <message>
+ <source>Breakpoint Preset</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®ãƒ—リセット</translation>
+ </message>
+ <message>
+ <source>Running Debuggers</source>
+ <translation>デãƒãƒƒã‚¬ã®å®Ÿè¡Œ</translation>
+ </message>
+ <message>
+ <source>Debugger Perspectives</source>
+ <translation>デãƒãƒƒã‚¬ã®è¦³ç‚¹</translation>
+ </message>
+ <message>
+ <source>Start Debugging or Continue</source>
+ <translation>デãƒãƒƒã‚°é–‹å§‹ã¾ãŸã¯ç¶šè¡Œ</translation>
+ </message>
+ <message>
<source>Detach Debugger</source>
<translation>デãƒãƒƒã‚¬ã‚’デタッãƒ</translation>
</message>
@@ -15356,6 +18687,28 @@ Qt Creator ã¯ã‚¢ã‚¿ãƒƒãƒã§ãã¾ã›ã‚“。</translation>
<translation>Ctrl+F6</translation>
</message>
<message>
+ <source>The process %1 is already under the control of a debugger.
+%2 cannot attach to it.</source>
+ <translation>プロセス %1 ã¯æ—¢ã«ãƒ‡ãƒãƒƒã‚¬ã®åˆ¶å¾¡ä¸‹ã«ã‚る為
+%2 ã¯ã‚¢ã‚¿ãƒƒãƒã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Remove Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Disable Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®ç„¡åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Enable Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®æœ‰åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Edit Breakpoint...</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã‚’編集...</translation>
+ </message>
+ <message>
<source>F12</source>
<translation>F12</translation>
</message>
@@ -15417,6 +18770,26 @@ Qt Creator ã¯ã‚¢ã‚¿ãƒƒãƒã§ãã¾ã›ã‚“。</translation>
<source>Debugger settings</source>
<translation>デãƒãƒƒã‚¬è¨­å®š</translation>
</message>
+ <message>
+ <source>Enable C++</source>
+ <translation>C++ を有効化</translation>
+ </message>
+ <message>
+ <source>Enable QML</source>
+ <translation>QML を有効化</translation>
+ </message>
+ <message>
+ <source>&lt;a href=&quot;qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html&quot;&gt;What are the prerequisites?&lt;/a&gt;</source>
+ <translation>&lt;a href=&quot;qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html&quot;&gt;å‰ææ¡ä»¶ã¯ï¼Ÿ&lt;/a&gt;</translation>
+ </message>
+ <message>
+ <source>Enable Debugging of Subprocesses</source>
+ <translation>サブプロセスã®ãƒ‡ãƒãƒƒã‚°ã‚’有効ã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Additional startup commands:</source>
+ <translation>追加ã®èµ·å‹•ã‚³ãƒžãƒ³ãƒ‰:</translation>
+ </message>
</context>
<context>
<name>Debugger::DebuggerRunControl</name>
@@ -15488,6 +18861,10 @@ Qt Creator ã¯ã‚¢ã‚¿ãƒƒãƒã§ãã¾ã›ã‚“。</translation>
<translation>ソースパスマップ</translation>
</message>
<message>
+ <source>&lt;p&gt;Mappings of source file folders to be used in the debugger can be entered here.&lt;/p&gt;&lt;p&gt;This is useful when using a copy of the source tree at a location different from the one at which the modules where built, for example, while doing remote debugging.&lt;/p&gt;&lt;p&gt;If source is specified as a regular expression by starting it with an open parenthesis, the paths in the ELF are matched with the regular expression to automatically determine the source path.&lt;/p&gt;&lt;p&gt;Example: &lt;b&gt;(/home/.*/Project)/KnownSubDir -&gt; D:\Project&lt;/b&gt; will substitute ELF built by any user to your local project directory.&lt;/p&gt;</source>
+ <translation>&lt;p&gt;デãƒãƒƒã‚¬ã§ä½¿ç”¨ã™ã‚‹ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ãƒ•ã‚©ãƒ«ãƒ€ã¨ã®å¯¾å¿œã‚’入力ã—ã¾ã™ã€‚&lt;/p&gt;&lt;p&gt;例ãˆã°ã€ãƒªãƒ¢ãƒ¼ãƒˆãƒ‡ãƒãƒƒã‚°æ™‚ãªã©ã€ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’ビルドã—ãŸã¨ãã¨ã¯åˆ¥ã®ãƒ‘スã«ã‚½ãƒ¼ã‚¹ãƒ„リーãŒç½®ã‹ã‚Œã¦ã„ã‚‹å ´åˆã«æœ‰ç”¨ã§ã™ã€‚&lt;/p&gt;&lt;p&gt;ソースãŒæ‹¬å¼§å†…ã®æ­£è¦è¡¨ç¾ã§é–‹å§‹ã•ã‚Œã‚‹å ´åˆã€ELF ãƒã‚¤ãƒŠãƒªå†…ã®ãƒ‘スを正è¦è¡¨ç¾ã¨æ¯”較ã—ã¦è‡ªå‹•çš„ã«ã‚½ãƒ¼ã‚¹ãƒ‘スを決定ã—ã¾ã™ã€‚&lt;/p&gt;&lt;p&gt;例: &lt;b&gt;(/home/.*/Project)/KnownSubDir → D:\Project&lt;/b&gt; ã®å ´åˆã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒãƒ“ルドã—㟠ELF ãƒã‚¤ãƒŠãƒªã‚’ローカルã®ãƒ—ロジェクトディレクトリã«å¯¾å¿œã•ã›ã¾ã™ã€‚&lt;/p&gt;</translation>
+ </message>
+ <message>
<source>&lt;p&gt;Mappings of source file folders to be used in the debugger can be entered here.&lt;/p&gt;&lt;p&gt;This is useful when using a copy of the source tree at a location different from the one at which the modules where built, for example, while doing remote debugging.&lt;/p&gt;&lt;p&gt;If source is specified as a regular expression by starting it with an open parenthesis, Qt Creator matches the paths in the ELF with the regular expression to automatically determine the source path.&lt;/p&gt;&lt;p&gt;Example: &lt;b&gt;(/home/.*/Project)/KnownSubDir -&gt; D:\Project&lt;/b&gt; will substitute ELF built by any user to your local project directory.&lt;/p&gt;</source>
<translation>&lt;p&gt;デãƒãƒƒã‚¬ã§ä½¿ç”¨ã™ã‚‹ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ãƒ•ã‚©ãƒ«ãƒ€ã¨ã®å¯¾å¿œã‚’入力ã—ã¾ã™ã€‚&lt;/p&gt;&lt;p&gt;例ãˆã°ã€ãƒªãƒ¢ãƒ¼ãƒˆãƒ‡ãƒãƒƒã‚°æ™‚ãªã©ã€ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’ビルドã—ãŸã¨ãã¨ã¯åˆ¥ã®ãƒ‘スã«ã‚½ãƒ¼ã‚¹ãƒ„リーãŒç½®ã‹ã‚Œã¦ã„ã‚‹å ´åˆã«æœ‰ç”¨ã§ã™ã€‚&lt;/p&gt;&lt;p&gt;ソースãŒæ‹¬å¼§å†…ã®æ­£è¦è¡¨ç¾ã§é–‹å§‹ã•ã‚Œã‚‹å ´åˆã€Qt Creator ã§ã¯ ELF ãƒã‚¤ãƒŠãƒªå†…ã®ãƒ‘スを正è¦è¡¨ç¾ã¨æ¯”較ã—ã¦è‡ªå‹•çš„ã«ã‚½ãƒ¼ã‚¹ãƒ‘スを決定ã—ã¾ã™ã€‚&lt;/p&gt;&lt;p&gt;例: &lt;b&gt;(/home/.*/Project)/KnownSubDir → D:\Project&lt;/b&gt; ã®å ´åˆã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒãƒ“ルドã—㟠ELF ãƒã‚¤ãƒŠãƒªã‚’ローカルã®ãƒ—ロジェクトディレクトリã«å¯¾å¿œã•ã›ã¾ã™ã€‚&lt;/p&gt;</translation>
</message>
@@ -15777,6 +19154,97 @@ You can choose between waiting longer or aborting debugging.</source>
<translation>続ã‘ã¦å‘½ä»¤æ¯Žã«ã‚¹ãƒ†ãƒƒãƒ—実行ã—よã†ã¨ã—ã¦ã„ã¾ã™...</translation>
</message>
<message>
+ <source>The gdb process failed to start.</source>
+ <translation>gdb プロセスã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Library %1 loaded.</source>
+ <translation>ライブラリ &apos;%1&apos; を読ã¿è¾¼ã¿ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Library %1 unloaded.</source>
+ <translation>ライブラリ &apos;%1&apos; を解放ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Thread group %1 created.</source>
+ <translation>スレッドグループ %1 を作æˆã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Thread %1 created.</source>
+ <translation>スレッド %1 を作æˆã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Thread group %1 exited.</source>
+ <translation>スレッドグループ %1 ãŒçµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Thread %1 in group %2 exited.</source>
+ <translation>スレッドグループ %2 ã®ã‚¹ãƒ¬ãƒƒãƒ‰ %1 ãŒçµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Thread %1 selected.</source>
+ <translation>スレッド %1 ã‚’é¸æŠžã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Stopping temporarily.</source>
+ <translation>一時åœæ­¢ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message numerus="yes">
+ <source>The gdb process has not responded to a command within %n seconds. This could mean it is stuck in an endless loop or taking longer than expected to perform the operation.
+You can choose between waiting longer or aborting debugging.</source>
+ <translation>
+ <numerusform>gdb プロセス㌠%n 秒間åå¿œãŒã‚ã‚Šã¾ã›ã‚“。無é™ãƒ«ãƒ¼ãƒ—ã«é™¥ã£ã¦ã„ã‚‹ã‹ã€æ“作ã«æ™‚é–“ã‚’è¦ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>GDB Not Responding</source>
+ <translation>GDB ãŒå¿œç­”ã—ã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Give GDB More Time</source>
+ <translation>GDB ã®å¿œç­”ã‚’å¾…ã¤</translation>
+ </message>
+ <message>
+ <source>Stop Debugging</source>
+ <translation>デãƒãƒƒã‚°ã‚’åœæ­¢</translation>
+ </message>
+ <message>
+ <source>Process failed to start.</source>
+ <translation>プロセスã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Setting Breakpoints Failed</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®è¨­å®šã«å¤±æ•—</translation>
+ </message>
+ <message>
+ <source>Cannot jump. Stopped.</source>
+ <translation>移動ã§ãã¾ã›ã‚“。åœæ­¢ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Jumped. Stopped.</source>
+ <translation>ジャンプã—ã¦åœæ­¢ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Target line hit, and therefore stopped.</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã«ãƒ’ットã—ã€åœæ­¢ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Application exited normally.</source>
+ <translation>アプリケーションã¯æ­£å¸¸ã«çµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>The selected build of GDB supports Python scripting, but the used version %1.%2 is not sufficient for %3. Supported versions are Python 2.7 and 3.x.</source>
+ <translation>é¸æŠžã—㟠GDB ãƒã‚¤ãƒŠãƒªã¯ Python スクリプトをサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ãŒã€ä½¿ç”¨ã™ã‚‹ Python ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1.%2 ã¨ãªã£ã¦ãŠã‚Šã€%3 ãŒå¯¾å¿œã—ã¦ã„ã‚‹ Python 2.7 ã‚„ 3.x ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Failed to Shut Down Application</source>
+ <translation>アプリケーションã®çµ‚了ã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>There is no GDB binary available for binaries in format &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; フォーマットã®ãƒã‚¤ãƒŠãƒªã§åˆ©ç”¨å¯èƒ½ãª GDB ã®ãƒã‚¤ãƒŠãƒªãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Run to line %1 requested...</source>
<translation>%1 行目ã¾ã§å®Ÿè¡Œã—よã†ã¨ã—ã¦ã„ã¾ã™...</translation>
</message>
@@ -15797,6 +19265,122 @@ You can choose between waiting longer or aborting debugging.</source>
<translation>モジュール &quot;%1&quot; ã®ã‚·ãƒ³ãƒœãƒ«ãŒèª­ã‚ã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Retrieving data for stack view thread %1...</source>
+ <translation>スタックビュースレッド %1 用ã®ãƒ‡ãƒ¼ã‚¿ã‚’å—信中...</translation>
+ </message>
+ <message>
+ <source>Cannot Find Debugger Initialization Script</source>
+ <translation>デãƒãƒƒã‚¬åˆæœŸåŒ–スクリプトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>The debugger settings point to a script file at &quot;%1&quot;, which is not accessible. If a script file is not needed, consider clearing that entry to avoid this warning.</source>
+ <translation>デãƒãƒƒã‚¬ã«è¨­å®šã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トファイル &quot;%1&quot; ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。スクリプトãŒä¸è¦ãªå ´åˆã€ã‚¹ã‚¯ãƒªãƒ—トファイルã®è¨­å®šã‚’消去ã—ã¦ã¿ã¦ãã ã•ã„。ãã†ã™ã‚Œã°ã“ã®è­¦å‘ŠãŒå‡ºã‚‹ã®ã‚’回é¿ã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Adapter Start Failed</source>
+ <translation>アダプタã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Failed to Start Application</source>
+ <translation>アプリケーションã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Application started.</source>
+ <translation>アプリケーションãŒèµ·å‹•ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Application running.</source>
+ <translation>アプリケーション実行中。</translation>
+ </message>
+ <message>
+ <source>Attached to stopped application.</source>
+ <translation>åœæ­¢æ¸ˆã¿ã‚¢ãƒ—リケーションã«ã‚¢ã‚¿ãƒƒãƒã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>No symbol file given.</source>
+ <translation>シンボルファイルãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Error Loading Core File</source>
+ <translation>コアファイルã®èª­è¾¼ã«å¤±æ•—</translation>
+ </message>
+ <message>
+ <source>The specified file does not appear to be a core file.</source>
+ <translation>指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã¯ã‚³ã‚¢ãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ãªã„よã†ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Error Loading Symbols</source>
+ <translation>シンボルã®èª­è¾¼ã«å¤±æ•—</translation>
+ </message>
+ <message>
+ <source>No executable to load symbols from specified core.</source>
+ <translation>指定ã•ã‚ŒãŸã‚³ã‚¢ã‹ã‚‰ã‚·ãƒ³ãƒœãƒ«ã‚’ロードã™ã‚‹å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Attaching to process %1.</source>
+ <translation>プロセス %1 ã«ã‚¢ã‚¿ãƒƒãƒã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Attached to running application.</source>
+ <translation>実行中ã®ã‚¢ãƒ—リケーションã«ã‚¢ã‚¿ãƒƒãƒã€‚</translation>
+ </message>
+ <message>
+ <source>Failed to attach to application: %1</source>
+ <translation>アプリケーションã¸ã®ã‚¢ã‚¿ãƒƒãƒã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Debugger Error</source>
+ <translation>デãƒãƒƒã‚¬ã‚¨ãƒ©ãƒ¼</translation>
+ </message>
+ <message>
+ <source>Interrupting not possible.</source>
+ <translation>割り込ã¿ä¸å¯ã€‚</translation>
+ </message>
+ <message>
+ <source>Symbols found.</source>
+ <translation>シンボルãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>No symbols found in the core file &quot;%1&quot;.</source>
+ <translation>コアファイル &quot;%1&quot;ã«ã‚·ãƒ³ãƒœãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>This can be caused by a path length limitation in the core file.</source>
+ <translation>コアファイルã®ãƒ‘スã®é•·ã•ãŒåŽŸå› ã®å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Try to specify the binary in Debug &gt; Start Debugging &gt; Load Core File.</source>
+ <translation>デãƒãƒƒã‚°&gt;デãƒãƒƒã‚°é–‹å§‹&gt;コアファイルを読ã¿è¾¼ã¿ã§ãƒã‚¤ãƒŠãƒªãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Starting executable failed:</source>
+ <translation>実行ファイルã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸ:</translation>
+ </message>
+ <message>
+ <source>No Remote Executable or Process ID Specified</source>
+ <translation>リモートã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã¾ãŸã¯ãƒ—ロセスIDãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>No remote executable could be determined from your build system files.&lt;p&gt;In case you use qmake, consider adding&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;target.path = /tmp/your_executable # path on device&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;INSTALLS += target&lt;/p&gt;to your .pro file.</source>
+ <translation>ビルドシステムファイルã‹ã‚‰ãƒªãƒ¢ãƒ¼ãƒˆå®Ÿè¡Œå¯èƒ½ãªãƒ•ã‚¡ã‚¤ãƒ«ã‚’特定ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;target.path = /tmp/your_executable # path on device &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;INSTALLS += target&lt;/p&gt;qmake を使用ã—ã¦ã„ã‚‹å ´åˆã¯ã€.pro ファイルã«ä»¥ä¸‹ã®è¡Œã‚’追加ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Continue Debugging</source>
+ <translation>デãƒãƒƒã‚°ã®ç¶šè¡Œ</translation>
+ </message>
+ <message>
+ <source>Attached to core.</source>
+ <translation>コアファイルã«ã‚¢ã‚¿ãƒƒãƒã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Attach to core &quot;%1&quot; failed:</source>
+ <translation>core &quot;%1&quot; ã¸ã®ã‚¢ã‚¿ãƒƒãƒã«å¤±æ•—ã—ã¾ã—ãŸ:</translation>
+ </message>
+ <message>
+ <source>Continuing nevertheless.</source>
+ <translation>デãƒãƒƒã‚°ã‚’継続ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Retrieving data for stack view thread 0x%1...</source>
<translation>スタックビュースレッド 0x%1 用ã®ãƒ‡ãƒ¼ã‚¿ã‚’å—信中...</translation>
</message>
@@ -15829,6 +19413,14 @@ You can choose between waiting longer or aborting debugging.</source>
<translation>逆アセンブル失敗: %1</translation>
</message>
<message>
+ <source>Cannot set up communication with child process: %1</source>
+ <translation>å­ãƒ—ロセスã¨ã®é€šä¿¡ã‚’設定ã§ãã¾ã›ã‚“: %1</translation>
+ </message>
+ <message>
+ <source>The working directory &quot;%1&quot; is not usable.</source>
+ <translation>作業ディレクトリ &quot;%1&quot; ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Setting up inferior...</source>
<translation>プログラムã®æº–備中...</translation>
</message>
@@ -15966,6 +19558,16 @@ that on slow machines. In this case, the value should be increased.</source>
ソースファイルã®ä¸€è¦§ã‚’表示ã™ã‚‹å ´åˆã¯ä¸å分ã‹ã‚‚知れã¾ã›ã‚“。ãã®ã‚ˆã†ãªå ´åˆã¯ã€ã“ã®å€¤ã‚’大ããã—ã¦ãã ã•ã„。</translation>
</message>
<message>
+ <source>The number of seconds before a non-responsive GDB process is terminated.
+The default value of 20 seconds should be sufficient for most
+applications, but there are situations when loading big libraries or
+listing source files takes much longer than that on slow machines.
+In this case, the value should be increased.</source>
+ <translation>応答ã—ãªã„ GDB プロセスを強制終了ã•ã›ã‚‹ã®ã‚’ã€ã“ã“ã§æŒ‡å®šã•ã‚ŒãŸæ™‚é–“(秒å˜ä½)ã ã‘å¾…æ©Ÿã—ã¾ã™ã€‚
+既定ã§ã¯ 20 秒ã§å¤§ä½“ã®ã‚¢ãƒ—リケーションã«ã¯å分ã§ã™ãŒã€ä½Žé€Ÿãªãƒžã‚·ãƒ³ã§å·¨å¤§ãªãƒ©ã‚¤ãƒ–ラリã®èª­ã¿è¾¼ã¿ã‚„
+ソースファイルã®ä¸€è¦§ã‚’表示ã™ã‚‹å ´åˆã¯ä¸å分ã‹ã‚‚知れã¾ã›ã‚“。ãã®ã‚ˆã†ãªå ´åˆã¯ã€ã“ã®å€¤ã‚’大ããã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>sec</source>
<translation>秒</translation>
</message>
@@ -16039,6 +19641,26 @@ markers in the source code editor.</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;GDB ã¯æ—¢å®šã§ã¯ AT&amp;&amp;T スタイルã®é€†ã‚¢ã‚»ãƒ³ãƒ–ラã§è¡¨ç¤ºã—ã¾ã™ã€‚&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
+ <source>Use pseudo message tracepoints</source>
+ <translation>疑似メッセージã®ãƒˆãƒ¬ãƒ¼ã‚¹ãƒã‚¤ãƒ³ãƒˆã‚’使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Uses Python to extend the ordinary GDB breakpoint class.</source>
+ <translation>python を使用ã—ã¦ã€é€šå¸¸ã® GDB ブレークãƒã‚¤ãƒ³ãƒˆã‚¯ãƒ©ã‚¹ã‚’æ‹¡å¼µã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Uses python to extend the ordinary GDB breakpoint class.</source>
+ <translation type="vanished">pythonを使用ã—ã¦ã€é€šå¸¸ã®GDBブレークãƒã‚¤ãƒ³ãƒˆã‚¯ãƒ©ã‚¹ã‚’æ‹¡å¼µã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Debug all child processes</source>
+ <translation>ã™ã¹ã¦ã®å­ãƒ—ロセスをデãƒãƒƒã‚°ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>GDB Extended</source>
+ <translation>GDB æ‹¡å¼µ</translation>
+ </message>
+ <message>
<source>Create tasks from missing packages</source>
<translation>ä¸è¶³ã™ã‚‹ãƒ‘ッケージã‹ã‚‰ã‚¿ã‚¹ã‚¯ã‚’作æˆã™ã‚‹</translation>
</message>
@@ -16312,6 +19934,10 @@ markers in the source code editor.</source>
<translation>アダプタã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
</message>
<message>
+ <source>Stopping temporarily</source>
+ <translation>一時åœæ­¢ã—ã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
<source>Setting up inferior...</source>
<translation>プログラムã®æº–備中...</translation>
</message>
@@ -16386,10 +20012,26 @@ markers in the source code editor.</source>
<translation>コアファイルã®é¸æŠž</translation>
</message>
<message>
+ <source>Select Executable or Symbol File</source>
+ <translation>実行ファイルã¾ãŸã¯ã‚·ãƒ³ãƒœãƒ«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Select a file containing debug information corresponding to the core file. Typically, this is the executable or a *.debug file if the debug information is stored separately from the executable.</source>
+ <translation>コアファイルã«å¯¾å¿œã™ã‚‹ãƒ‡ãƒãƒƒã‚°æƒ…報をå«ã‚€ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¾ã™ã€‚一般的ã«ã¯ã€å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã€ã¾ãŸã¯ãƒ‡ãƒãƒƒã‚°æƒ…å ±ãŒå®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã¨ã¯åˆ¥ã«ä¿å­˜ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯*.debugファイルã§ã™ã€‚</translation>
+ </message>
+ <message>
<source>Select Startup Script</source>
<translation>起動スクリプトã®é¸æŠž</translation>
</message>
<message>
+ <source>Select SysRoot Directory</source>
+ <translation>SysRoot ディレクトリをé¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>This option can be used to override the kit&apos;s SysRoot setting</source>
+ <translation>ã“ã®ã‚ªãƒ—ションを使用ã™ã‚‹ã¨ã€ã‚­ãƒƒãƒˆã® SysRoot 設定を上書ãã™ã‚‹ã“ã¨ãŒã§ãã¾ã™</translation>
+ </message>
+ <message>
<source>Kit:</source>
<translation>キット:</translation>
</message>
@@ -16402,10 +20044,18 @@ markers in the source code editor.</source>
<translation>コアファイル:</translation>
</message>
<message>
+ <source>&amp;Executable or symbol file:</source>
+ <translation>実行ファイルã¾ãŸã¯ã‚·ãƒ³ãƒœãƒ«ãƒ•ã‚¡ã‚¤ãƒ«(&amp;E):</translation>
+ </message>
+ <message>
<source>Override &amp;start script:</source>
<translation>起動スクリプトを上書ã(&amp;S):</translation>
</message>
<message>
+ <source>Override S&amp;ysRoot:</source>
+ <translation>S&amp;ysRoot を上書ãã—ã¾ã™:</translation>
+ </message>
+ <message>
<source>Select Remote Core File</source>
<translation>リモートコアファイルã®é¸æŠž</translation>
</message>
@@ -16439,6 +20089,10 @@ markers in the source code editor.</source>
<translation>デãƒãƒƒã‚¬ãƒ­ã‚°</translation>
</message>
<message>
+ <source>Debugger &amp;Log</source>
+ <translation>デãƒãƒƒã‚¬ãƒ­ã‚°(&amp;L)</translation>
+ </message>
+ <message>
<source>Repeat last command for debug reasons.</source>
<translation>デãƒãƒƒã‚°ç›®çš„ã§ç›´å‰ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’ç¹°ã‚Šè¿”ã™ã€‚</translation>
</message>
@@ -16447,6 +20101,16 @@ markers in the source code editor.</source>
<translation>コマンド:</translation>
</message>
<message>
+ <source>Note: This log contains possibly confidential information about your machine, environment variables, in-memory data of the processes you are debugging, and more. It is never transferred over the internet by %1, and only stored to disk if you manually use the respective option from the context menu, or through mechanisms that are not under the control of %1&apos;s Debugger plugin, for instance in swap files, or other plugins you might use.
+You may be asked to share the contents of this log when reporting bugs related to debugger operation. In this case, make sure your submission does not contain data you do not want to or you are not allowed to share.
+
+</source>
+ <translation>注æ„: ã“ã®ãƒ­ã‚°ã«ã¯ã€ãŠä½¿ã„ã®ãƒžã‚·ãƒ³ã®æ©Ÿå¯†æƒ…å ±ã€ç’°å¢ƒå¤‰æ•°ã€ãƒ‡ãƒãƒƒã‚°ä¸­ã®ãƒ—ロセスã®ã‚¤ãƒ³ãƒ¡ãƒ¢ãƒªãƒ‡ãƒ¼ã‚¿ãªã©ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ãƒ­ã‚°ã¯ã€%1 ã«ã‚ˆã£ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã«è»¢é€ã•ã‚Œã‚‹ã“ã¨ã¯ãªãã€ã‚³ãƒ³ãƒ†ã‚¯ã‚¹ãƒˆ メニューã®å„オプションを手動ã§ä½¿ç”¨ã—ãŸå ´åˆã«ã®ã¿ãƒ‡ã‚£ã‚¹ã‚¯ã«ä¿å­˜ã•ã‚Œã¾ã™ã€‚ã¾ãŸã€%1 ã®ãƒ‡ãƒãƒƒã‚¬ プラグインã®åˆ¶å¾¡ä¸‹ã«ãªã„メカニズム (スワップ ファイルや使用ã—ã¦ã„ã‚‹ä»–ã®ãƒ—ラグインãªã©) を通ã˜ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+デãƒãƒƒã‚¬ãƒ¼ã®æ“作ã«é–¢é€£ã™ã‚‹ãƒã‚°ã‚’報告ã™ã‚‹éš›ã«ã€ã“ã®ãƒ­ã‚°ã®å†…容を共有ã™ã‚‹ã‚ˆã†æ±‚ã‚られるã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ã‚ˆã†ãªå ´åˆã«ã¯ã€é€ä¿¡ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã«ã€å…±æœ‰ã—ãŸããªã„ã€ã¾ãŸã¯å…±æœ‰ã™ã‚‹ã“ã¨ãŒè¨±å¯ã•ã‚Œã¦ã„ãªã„データãŒå«ã¾ã‚Œã¦ã„ãªã„ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„.
+
+</translation>
+ </message>
+ <message>
<source>NOTE: This log contains possibly confidential information about your machine, environment variables, in-memory data of the processes you are debugging, and more. It is never transferred over the internet by Qt Creator, and only stored to disk if you manually use the respective option from the context menu, or through mechanisms that are not under Qt Creator&apos;s control, for instance in swap files.
You may be asked to share the contents of this log when reporting bugs related to debugger operation. In this case, make sure your submission does not contain data you do not want to or you are not allowed to share.
@@ -16468,6 +20132,14 @@ You may be asked to share the contents of this log when reporting bugs related t
<context>
<name>Debugger::Internal::MemoryAgent</name>
<message>
+ <source>Memory at Register &quot;%1&quot; (0x%2)</source>
+ <translation>レジスタ &quot;%1&quot; (0x%2) ã®æŒ‡ã™ãƒ¡ãƒ¢ãƒª</translation>
+ </message>
+ <message>
+ <source>Register &quot;%1&quot;</source>
+ <translation>レジスタ &quot;%1&quot;</translation>
+ </message>
+ <message>
<source>Memory at 0x%1</source>
<translation>0x%1 ã®ãƒ¡ãƒ¢ãƒª</translation>
</message>
@@ -16759,6 +20431,10 @@ Do you want to retry?</source>
<translation>QML デãƒãƒƒã‚°ãƒãƒ¼ãƒˆãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。%1 ã¯ç¬¦å·ç„¡ã—æ•´æ•°ã«å¤‰æ›ã§ãã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Starting %1</source>
+ <translation>%1 を起動中</translation>
+ </message>
+ <message>
<source>Waiting for JavaScript engine to interrupt on next statement.</source>
<translation>JavaScript エンジンãŒæ¬¡ã®æ–‡ã«å‰²ã‚Šè¾¼ã‚€ã®ã‚’å¾…æ©Ÿã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
@@ -16770,6 +20446,22 @@ Do you want to retry?</source>
<source>QML Debugger disconnected.</source>
<translation>QML デãƒãƒƒã‚¬ã¯åˆ‡æ–­ã—ã¾ã—ãŸã€‚</translation>
</message>
+ <message>
+ <source>Cannot evaluate %1 in current stack frame.</source>
+ <translation>ç¾åœ¨ã®ã‚¹ã‚¿ãƒƒã‚¯ãƒ»ãƒ•ãƒ¬ãƒ¼ãƒ ã§ã¯ã€%1 を評価ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Context:</source>
+ <translation>コンテキスト:</translation>
+ </message>
+ <message>
+ <source>Global QML Context</source>
+ <translation>グローãƒãƒ« QML コンテクスト</translation>
+ </message>
+ <message>
+ <source>QML Debugger: Connection failed.</source>
+ <translation>QML デãƒãƒƒã‚¬ã®æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
</context>
<context>
<name>Debugger::Internal::QmlInspectorAgent</name>
@@ -16778,6 +20470,10 @@ Do you want to retry?</source>
<translation>æˆåŠŸ:</translation>
</message>
<message>
+ <source>&lt;anonymous&gt;</source>
+ <translation>&lt;ç„¡å関数&gt;</translation>
+ </message>
+ <message>
<source>Properties</source>
<translation>プロパティ</translation>
</message>
@@ -16813,6 +20509,14 @@ Do you want to retry?</source>
<translation>%1ビット浮動å°æ•°ç‚¹ã¨ã—ã¦ã®å€¤</translation>
</message>
<message>
+ <source>Registers group</source>
+ <translation type="vanished">レジスタグループ</translation>
+ </message>
+ <message>
+ <source>A group of registers.</source>
+ <translation>レジスターã®ã‚°ãƒ«ãƒ¼ãƒ—ã§ã™ã€‚</translation>
+ </message>
+ <message>
<source>Name</source>
<translation>åå‰</translation>
</message>
@@ -16821,6 +20525,54 @@ Do you want to retry?</source>
<translation>値</translation>
</message>
<message>
+ <source>Reload Register Listing</source>
+ <translation>レジスタã®ãƒªã‚¹ãƒˆã®å†èª­è¾¼</translation>
+ </message>
+ <message>
+ <source>Open Memory View at Value of Register %1 0x%2</source>
+ <translation>レジスタ %1 0x%2 ã®å€¤ã‚’メモリビューã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory View at Value of Register</source>
+ <translation>レジスタã®å€¤ã‚’メモリビューã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor at 0x%1</source>
+ <translation>アドレス 0x%1 をメモリエディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor</source>
+ <translation>メモリエディタを開ã</translation>
+ </message>
+ <message>
+ <source>Open Disassembler at 0x%1</source>
+ <translation>アドレス 0x%1 を逆アセンブラã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Disassembler</source>
+ <translation>逆アセンブラを開ã</translation>
+ </message>
+ <message>
+ <source>Open Disassembler...</source>
+ <translation>逆アセンブラを開ã...</translation>
+ </message>
+ <message>
+ <source>Hexadecimal</source>
+ <translation>16進数</translation>
+ </message>
+ <message>
+ <source>Decimal</source>
+ <translation>10進数</translation>
+ </message>
+ <message>
+ <source>Octal</source>
+ <translation>8進数</translation>
+ </message>
+ <message>
+ <source>Binary</source>
+ <translation>2進数</translation>
+ </message>
+ <message>
<source>Edit bits %1...%2 of register %3</source>
<translation>レジスタ %3 ã® %1..%2 ビットã®ç·¨é›†</translation>
</message>
@@ -16966,6 +20718,18 @@ Do you want to retry?</source>
<source>Full Name</source>
<translation>完全å</translation>
</message>
+ <message>
+ <source>Reload Data</source>
+ <translation>データã®å†èª­è¾¼</translation>
+ </message>
+ <message>
+ <source>Open File</source>
+ <translation>ファイルを開ã</translation>
+ </message>
+ <message>
+ <source>Open File &quot;%1&quot;</source>
+ <translation>ファイル &quot;%1&quot; ã‚’é–‹ã</translation>
+ </message>
</context>
<context>
<name>Debugger::Internal::SourceFilesTreeView</name>
@@ -17065,6 +20829,70 @@ Do you want to retry?</source>
<translation>アドレス</translation>
</message>
<message>
+ <source>Disassemble Function</source>
+ <translation>関数を逆アセンブル</translation>
+ </message>
+ <message>
+ <source>Cannot open &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; ã‚’é–‹ã‘ã¾ã›ã‚“: %2</translation>
+ </message>
+ <message>
+ <source>Cannot Open Task File</source>
+ <translation>タスクファイルを開ã‘ã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Copy Contents to Clipboard</source>
+ <translation>内容をクリップボードã«ã‚³ãƒ”ー</translation>
+ </message>
+ <message>
+ <source>Copy Selection to Clipboard</source>
+ <translation>é¸æŠžç¯„囲をクリップボードã«ã‚³ãƒ”ーã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Save as Task File...</source>
+ <translation>åå‰ã‚’付ã‘ã¦ã‚¿ã‚¹ã‚¯ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ä¿å­˜...</translation>
+ </message>
+ <message>
+ <source>Load QML Stack</source>
+ <translation>QML スタックã®èª­è¾¼</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor at 0x%1</source>
+ <translation>アドレス 0x%1 をメモリエディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor</source>
+ <translation>メモリエディタを開ã</translation>
+ </message>
+ <message>
+ <source>Memory at Frame #%1 (%2) 0x%3</source>
+ <translation>ãƒ•ãƒ¬ãƒ¼ãƒ ç•ªå· #%1 (%2) 0x%3 ã®ãƒ¡ãƒ¢ãƒªå†…容</translation>
+ </message>
+ <message>
+ <source>Frame #%1 (%2)</source>
+ <translation>ãƒ•ãƒ¬ãƒ¼ãƒ ç•ªå· #%1 (%2)</translation>
+ </message>
+ <message>
+ <source>Open Disassembler at 0x%1</source>
+ <translation>アドレス 0x%1 を逆アセンブラã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Disassembler</source>
+ <translation>逆アセンブラを開ã</translation>
+ </message>
+ <message>
+ <source>Open Disassembler at Address...</source>
+ <translation>アドレスを逆アセンブラã§é–‹ã...</translation>
+ </message>
+ <message>
+ <source>Disassemble Function...</source>
+ <translation>関数を逆アセンブル...</translation>
+ </message>
+ <message>
+ <source>Try to Load Unknown Symbols</source>
+ <translation>ä¸æ˜Žãªã‚·ãƒ³ãƒœãƒ«ã®èª­ã¿è¾¼ã¿ã‚’è¡Œã†</translation>
+ </message>
+ <message>
<source>Module:</source>
<translation>モジュール:</translation>
</message>
@@ -17257,7 +21085,15 @@ Do you want to retry?</source>
</message>
<message>
<source>Internal ID</source>
- <translation>内部ID</translation>
+ <translation>内部 ID</translation>
+ </message>
+ <message>
+ <source>Creation Time in ms</source>
+ <translation>作æˆæ™‚é–“(å˜ä½ï¼šãƒŸãƒªç§’)</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>ソース</translation>
</message>
<message>
<source>Debugger - Qt Creator</source>
@@ -17315,6 +21151,10 @@ Do you want to retry?</source>
<source>Are you sure you want to remove all expression evaluators?</source>
<translation>本当ã«ã™ã¹ã¦ã®å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
+ <message>
+ <source>Debugger - %1</source>
+ <translation>デãƒãƒƒã‚¬ - %1</translation>
+ </message>
</context>
<context>
<name>Debugger::Internal::WatchModel</name>
@@ -17375,6 +21215,256 @@ Do you want to retry?</source>
<translation>別ウィンドウ㫠Latin1 文字列</translation>
</message>
<message>
+ <source>Time</source>
+ <translation>タイム</translation>
+ </message>
+ <message>
+ <source>&lt;i&gt;%1&lt;/i&gt; %2 at #%3</source>
+ <extracomment>HTML tooltip of a variable in the memory editor</extracomment>
+ <translation>#%3 ã® &lt;i&gt;%1&lt;/i&gt; %2</translation>
+ </message>
+ <message>
+ <source>&lt;i&gt;%1&lt;/i&gt; %2</source>
+ <extracomment>HTML tooltip of a variable in the memory editor</extracomment>
+ <translation>&lt;i&gt;%1&lt;/i&gt; %2</translation>
+ </message>
+ <message>
+ <source>Press Ctrl to select widget at (%1, %2). Press any other keyboard modifier to stop selection.</source>
+ <translation>Ctrl キーを押ã—ã¦ã€(%1, %2) ã«ã‚るウィジェットをé¸æŠžã—ã¾ã™ã€‚ä»–ã®ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ä¿®é£¾å­ã‚’押ã™ã¨ã€é¸æŠžãŒåœæ­¢ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Selecting widget at (%1, %2).</source>
+ <translation>(%1, %2)ã§ã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆã‚’é¸æŠžã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Selection aborted.</source>
+ <translation>é¸æŠžã‚’中止ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Register &lt;i&gt;%1&lt;/i&gt;</source>
+ <translation>レジスタ &lt;i&gt;%1&lt;/i&gt;</translation>
+ </message>
+ <message>
+ <source>Memory at Pointer&apos;s Address &quot;%1&quot; (0x%2)</source>
+ <translation>ãƒã‚¤ãƒ³ã‚¿ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ &quot;%1&quot; (0x%2) ãŒæŒ‡ã™ãƒ¡ãƒ¢ãƒª</translation>
+ </message>
+ <message>
+ <source>Memory at Object&apos;s Address &quot;%1&quot; (0x%2)</source>
+ <translation>オブジェクトã®ã‚¢ãƒ‰ãƒ¬ã‚¹ &quot;%1&quot; (0x%2) ãŒæŒ‡ã™ãƒ¡ãƒ¢ãƒª</translation>
+ </message>
+ <message>
+ <source>Cannot Display Stack Layout</source>
+ <translation>スタックレイアウトを表示ã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Could not determine a suitable address range.</source>
+ <translation>é©å¿œã™ã‚‹ã‚¢ãƒ‰ãƒ¬ã‚¹ç¯„囲ãŒç‰¹å®šã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Memory Layout of Local Variables at 0x%1</source>
+ <translation>0x%1 ã®ãƒ­ãƒ¼ã‚«ãƒ«å¤‰æ•°ã®ãƒ¡ãƒ¢ãƒªãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Add Expression Evaluator</source>
+ <translation>å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ã‚’追加</translation>
+ </message>
+ <message>
+ <source>Add Expression Evaluator for &quot;%1&quot;</source>
+ <translation>å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ &quot;%1&quot; を追加</translation>
+ </message>
+ <message>
+ <source>Remove Expression Evaluator</source>
+ <translation>å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ã‚’削除</translation>
+ </message>
+ <message>
+ <source>Remove Expression Evaluator for &quot;%1&quot;</source>
+ <translation>å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ &quot;%1&quot; を削除</translation>
+ </message>
+ <message>
+ <source>Enter an expression to evaluate.</source>
+ <translation>評価ã™ã‚‹å¼ã‚’入力ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Note: Evaluators will be re-evaluated after each step. For details, see the &lt;a href=&quot;qthelp://org.qt-project.qtcreator/doc/creator-debug-mode.html#locals-and-expressions&quot;&gt;documentation&lt;/a&gt;.</source>
+ <translation>注æ„: å¼ã¯å„ステップ実行ã”ã¨ã«å†è©•ä¾¡ã•ã‚Œã¾ã™ã€‚詳細㯠&lt;a href=&quot;qthelp://org.qt-project.qtcreator/doc/creator-debug-mode.html#locals-and-expressions&quot;&gt;ドキュメント&lt;/a&gt; ã‚’å‚ç…§ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>New Evaluated Expression</source>
+ <translation>æ–°ã—ã„評価済ã¿å¼</translation>
+ </message>
+ <message>
+ <source>Add New Expression Evaluator...</source>
+ <translation>æ–°ã—ã„å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ã‚’追加...</translation>
+ </message>
+ <message>
+ <source>Remove All Expression Evaluators</source>
+ <translation>ã™ã¹ã¦ã®å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ã‚’削除</translation>
+ </message>
+ <message>
+ <source>Select Widget to Add into Expression Evaluator</source>
+ <translation>å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ã«è¿½åŠ ã™ã‚‹ã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆã®é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Expand All Children</source>
+ <translation>ã™ã¹ã¦ã®å­ãƒ—ロセスを展開ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Collapse All Children</source>
+ <translation>ã™ã¹ã¦ã®å­ãƒ—ロセスを折りãŸãŸã‚€</translation>
+ </message>
+ <message>
+ <source>Close Editor Tooltips</source>
+ <translation>エディタã®ãƒ„ールãƒãƒƒãƒ—ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Copy View Contents to Clipboard</source>
+ <translation>表示内容をクリップボードã«ã‚³ãƒ”ー</translation>
+ </message>
+ <message>
+ <source>Copy Current Value to Clipboard</source>
+ <translation>ç¾åœ¨ã®å€¤ã‚’クリップボードã«ã‚³ãƒ”ー</translation>
+ </message>
+ <message>
+ <source>Open View Contents in Editor</source>
+ <translation>表示内容をエディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Locals &amp; Expressions</source>
+ <translation>ローカル変数ã¨å¼</translation>
+ </message>
+ <message>
+ <source>Add Data Breakpoint</source>
+ <translation>データブレークãƒã‚¤ãƒ³ãƒˆã‚’追加</translation>
+ </message>
+ <message>
+ <source>Add Data Breakpoint at Object&apos;s Address (0x%1)</source>
+ <translation>オブジェクトã®ã‚¢ãƒ‰ãƒ¬ã‚¹ (0x%1) ã«ãƒ‡ãƒ¼ã‚¿ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’追加</translation>
+ </message>
+ <message>
+ <source>Stop the program when the data at the address is modified.</source>
+ <translation>ãã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã®ãƒ‡ãƒ¼ã‚¿ãŒå¤‰æ›´ã•ã‚ŒãŸã‚‰ã€ãƒ—ログラムをåœæ­¢ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Add Data Breakpoint at Pointer&apos;s Address (0x%1)</source>
+ <translation>ãƒã‚¤ãƒ³ã‚¿ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ (0x%1) ã«ãƒ‡ãƒ¼ã‚¿ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’追加</translation>
+ </message>
+ <message>
+ <source>Add Data Breakpoint at Pointer&apos;s Address</source>
+ <translation>ãƒã‚¤ãƒ³ã‚¿ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãƒ‡ãƒ¼ã‚¿ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’追加</translation>
+ </message>
+ <message>
+ <source>Add Data Breakpoint at Expression &quot;%1&quot;</source>
+ <translation>å¼ &quot;%1&quot; ã«ãƒ‡ãƒ¼ã‚¿ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’追加</translation>
+ </message>
+ <message>
+ <source>Add Data Breakpoint at Expression</source>
+ <translation>å¼ã«ãƒ‡ãƒ¼ã‚¿ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’追加</translation>
+ </message>
+ <message>
+ <source>Stop the program when the data at the address given by the expression is modified.</source>
+ <translation>å¼ã§æŒ‡å®šã•ã‚ŒãŸã‚¢ãƒ‰ãƒ¬ã‚¹ã®ãƒ‡ãƒ¼ã‚¿ãŒå¤‰æ›´ã•ã‚ŒãŸã‚‰ã€ãƒ—ログラムをåœæ­¢ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor</source>
+ <translation>メモリエディタを開ã</translation>
+ </message>
+ <message>
+ <source>Open Memory View at Object&apos;s Address (0x%1)</source>
+ <translation>オブジェクトã®ã‚¢ãƒ‰ãƒ¬ã‚¹ (0x%1) をメモリビューã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory View at Object&apos;s Address</source>
+ <translation>オブジェクトã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’メモリビューã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory View at Pointer&apos;s Address (0x%1)</source>
+ <translation>ãƒã‚¤ãƒ³ã‚¿ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ (0x%1) をメモリビューã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory View at Pointer&apos;s Address</source>
+ <translation>ãƒã‚¤ãƒ³ã‚¿ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’メモリビューã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory View Showing Stack Layout</source>
+ <translation>表示ã—ã¦ã„るスタックレイアウトをメモリビューã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor at Object&apos;s Address (0x%1)</source>
+ <translation>オブジェクトã®ã‚¢ãƒ‰ãƒ¬ã‚¹ (0x%1) をメモリエディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor at Object&apos;s Address</source>
+ <translation>オブジェクトã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’メモリエディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor at Pointer&apos;s Address (0x%1)</source>
+ <translation>ãƒã‚¤ãƒ³ã‚¿ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ (0x%1) をメモリエディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor at Pointer&apos;s Address</source>
+ <translation>ãƒã‚¤ãƒ³ã‚¿ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’メモリエディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor Showing Stack Layout</source>
+ <translation>表示ã—ã¦ã„るスタックレイアウトをメモリエディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Memory Editor...</source>
+ <translation>メモリエディタを開ã...</translation>
+ </message>
+ <message>
+ <source>Treat All Characters as Printable</source>
+ <translation>ã™ã¹ã¦ã®æ–‡å­—ã‚’å°åˆ·å¯èƒ½æ–‡å­—ã¨ã—ã¦æ‰±ã†</translation>
+ </message>
+ <message>
+ <source>Show Unprintable Characters as Escape Sequences</source>
+ <translation>å°åˆ·ä¸å¯æ–‡å­—をエスケープシーケンスã¨ã—ã¦è¡¨ç¤º</translation>
+ </message>
+ <message>
+ <source>Show Unprintable Characters as Octal</source>
+ <translation>å°åˆ·ä¸å¯æ–‡å­—ã‚’8進数ã®æ–‡å­—ã¨ã—ã¦è¡¨ç¤º</translation>
+ </message>
+ <message>
+ <source>Show Unprintable Characters as Hexadecimal</source>
+ <translation>å°åˆ·ä¸å¯æ–‡å­—ã‚’16進数ã®æ–‡å­—ã¨ã—ã¦è¡¨ç¤º</translation>
+ </message>
+ <message>
+ <source>Change Value Display Format</source>
+ <translation>値ã®è¡¨ç¤ºå½¢å¼ã‚’変更</translation>
+ </message>
+ <message>
+ <source>Change Display for Object Named &quot;%1&quot;:</source>
+ <translation>&quot;%1&quot; ã¨ã„ã†åå‰ã®ã‚ªãƒ–ジェクトã®è¡¨ç¤ºå½¢å¼ã‚’変更:</translation>
+ </message>
+ <message>
+ <source>Use Format for Type (Currently %1)</source>
+ <translation>åž‹ã®è¡¨ç¤ºå½¢å¼ã‚’使ã†(ç¾åœ¨ã¯ %1)</translation>
+ </message>
+ <message>
+ <source>Use Display Format Based on Type</source>
+ <translation>åž‹ã«åŸºã¥ã„ãŸãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã§è¡¨ç¤ºã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Reset All Individual Formats</source>
+ <translation>ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã‚’リセットã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Change Display for Type &quot;%1&quot;:</source>
+ <translation>åž‹ &quot;%1&quot; ã®è¡¨ç¤ºå½¢å¼ã‚’変更:</translation>
+ </message>
+ <message>
+ <source>Reset All Formats for Types</source>
+ <translation>ã™ã¹ã¦ã®åž‹ã®è¡¨ç¤ºå½¢å¼ã‚’リセットã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Change Display Format for Selected Values</source>
+ <translation>é¸æŠžã—ãŸå€¤ã®è¡¨ç¤ºå½¢å¼ã‚’変更ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Change Display for Objects</source>
+ <translation>オブジェクトã®è¡¨ç¤ºå½¢å¼ã‚’変更ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Normal</source>
<translation>ノーマル</translation>
</message>
@@ -17443,6 +21533,10 @@ Do you want to retry?</source>
<translation>ä¸æ˜Žãªã‚¢ãƒ‰ãƒ¬ã‚¹ã® %1 åž‹ã®ã‚ªãƒ–ジェクト</translation>
</message>
<message>
+ <source>Are you sure you want to remove all expression evaluators?</source>
+ <translation>本当ã«ã™ã¹ã¦ã®å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
<source>returned value</source>
<translation>戻り値</translation>
</message>
@@ -17699,13 +21793,13 @@ Do you want to retry?</source>
<message>
<source>The generated header of the form &quot;%1&quot; could not be found.
Rebuilding the project might help.</source>
- <translation>フォーム &quot;%1&quot; ã‹ã‚‰ç”Ÿæˆã•ã‚ŒãŸãƒ˜ãƒƒãƒ€ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+ <translation>フォーム &quot;%1&quot; ã‹ã‚‰ç”Ÿæˆã•ã‚ŒãŸãƒ˜ãƒƒãƒ€ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
プロジェクトã®ãƒªãƒ“ルドをãŠå¥¨ã‚ã—ã¾ã™ã€‚</translation>
</message>
<message>
<source>The generated header &quot;%1&quot; could not be found in the code model.
Rebuilding the project might help.</source>
- <translation>生æˆã•ã‚ŒãŸãƒ˜ãƒƒãƒ€ãƒ¼ãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; ãŒã‚³ãƒ¼ãƒ‰ãƒ¢ãƒ‡ãƒ«å†…ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+ <translation>生æˆã•ã‚ŒãŸãƒ˜ãƒƒãƒ€ãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; ãŒã‚³ãƒ¼ãƒ‰ãƒ¢ãƒ‡ãƒ«å†…ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
プロジェクトã®ãƒªãƒ“ルドをãŠå¥¨ã‚ã—ã¾ã™ã€‚</translation>
</message>
</context>
@@ -17736,7 +21830,7 @@ Rebuilding the project might help.</source>
</message>
<message>
<source>Creates a Qt Designer form along with a matching class (C++ header and source file) for implementation purposes. You can add the form and class to an existing Qt Widget Project.</source>
- <translation>既存㮠Qt ウィジェットプロジェクトã«è¿½åŠ å¯èƒ½ãª Qt Designer フォームã¨ãã‚Œã«å¯¾å¿œã—ãŸã‚¯ãƒ©ã‚¹ (C++ ヘッダーã¨ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«) を作æˆã—ã¾ã™ã€‚</translation>
+ <translation>既存㮠Qt ウィジェットプロジェクトã«è¿½åŠ å¯èƒ½ãª Qt Designer フォームã¨ãã‚Œã«å¯¾å¿œã—ãŸã‚¯ãƒ©ã‚¹ (C++ ヘッダã¨ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«) を作æˆã—ã¾ã™ã€‚</translation>
</message>
</context>
<context>
@@ -17790,6 +21884,42 @@ Rebuilding the project might help.</source>
<translation>差分...</translation>
</message>
<message>
+ <source>&amp;Diff</source>
+ <translation>差分表示(&amp;D)</translation>
+ </message>
+ <message>
+ <source>Diff Current File</source>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®å·®åˆ†è¡¨ç¤º</translation>
+ </message>
+ <message>
+ <source>Meta+H</source>
+ <translation>Meta+H</translation>
+ </message>
+ <message>
+ <source>Ctrl+H</source>
+ <translation>Ctrl+H</translation>
+ </message>
+ <message>
+ <source>Diff Open Files</source>
+ <translation>é–‹ã„ã¦ã„るファイルã®å·®åˆ†è¡¨ç¤º</translation>
+ </message>
+ <message>
+ <source>Meta+Shift+H</source>
+ <translation>Meta+Shift+H</translation>
+ </message>
+ <message>
+ <source>Ctrl+Shift+H</source>
+ <translation>Ctrl+Shift+H</translation>
+ </message>
+ <message>
+ <source>Diff External Files...</source>
+ <translation>外部ファイルã®å·®åˆ†è¡¨ç¤º...</translation>
+ </message>
+ <message>
+ <source>Diff &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®å·®åˆ†è¡¨ç¤º</translation>
+ </message>
+ <message>
<source>Select First File for Diff</source>
<translation>差分をå–る最åˆã®ãƒ•ã‚¡ã‚¤ãƒ«ã®é¸æŠž</translation>
</message>
@@ -17872,6 +22002,10 @@ Rebuilding the project might help.</source>
<source>Edit Files...</source>
<translation>ファイルを編集...</translation>
</message>
+ <message>
+ <source>Remove Directory</source>
+ <translation>ディレクトリを削除ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>GenericProjectManager::Internal::GenericProjectWizardDialog</name>
@@ -17903,6 +22037,10 @@ Rebuilding the project might help.</source>
<translation>既存プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ</translation>
</message>
<message>
+ <source>Imports existing projects that do not use qmake, CMake, Qbs, Meson, or Autotools. This allows you to use %1 as a code editor.</source>
+ <translation>qmakeã€CMakeã€Qbsã€Mesonã€ã¾ãŸã¯ Autotools を使用ã—ã¦ã„ãªã„既存ã®ãƒ—ロジェクトをインãƒãƒ¼ãƒˆã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€%1 をコード・エディタã¨ã—ã¦ä½¿ç”¨ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Imports existing projects that do not use qmake, CMake or Autotools. This allows you to use Qt Creator as a code editor.</source>
<translation>qmake ã¾ãŸã¯ CMake ã‚„ Autotools を使用ã—ãªã„既存ã®ãƒ—ロジェクトをインãƒãƒ¼ãƒˆã—ã¾ã™ã€‚Qt Creator をコーディングã™ã‚‹æ™‚ã®ã‚¨ãƒ‡ã‚£ã‚¿ã¨ã—ã¦ä½¿ç”¨ã™ã‚‹äº‹ãŒã§ãã¾ã™ã€‚</translation>
</message>
@@ -17918,6 +22056,10 @@ Rebuilding the project might help.</source>
<translation>リモートブランãƒ</translation>
</message>
<message>
+ <source>Detached HEAD</source>
+ <translation>デタッãƒã•ã‚ŒãŸ HEAD</translation>
+ </message>
+ <message>
<source>Tags</source>
<translation>ã‚¿ã‚°</translation>
</message>
@@ -17953,16 +22095,20 @@ Rebuilding the project might help.</source>
<translation>コピー</translation>
</message>
<message>
+ <source>typechange</source>
+ <translation>型変更</translation>
+ </message>
+ <message>
<source> by both</source>
- <translation>åŒæ–¹</translation>
+ <translation> åŒæ–¹</translation>
</message>
<message>
<source> by us</source>
- <translation>ローカルå´</translation>
+ <translation> ローカルå´</translation>
</message>
<message>
<source> by them</source>
- <translation>リモートå´</translation>
+ <translation> リモートå´</translation>
</message>
</context>
<context>
@@ -18011,10 +22157,34 @@ Rebuilding the project might help.</source>
<source>Fetching &quot;%1&quot;...</source>
<translation>&quot;%1 ã‚’å–得中...</translation>
</message>
+ <message>
+ <source>Gerrit</source>
+ <translation>Gerrit</translation>
+ </message>
+ <message>
+ <source>Remote:</source>
+ <translation>リモート:</translation>
+ </message>
+ <message>
+ <source>Certificate Error</source>
+ <translation>証明書エラー</translation>
+ </message>
+ <message>
+ <source>Server certificate for %1 cannot be authenticated.
+Do you want to disable SSL verification for this server?
+Note: This can expose you to man-in-the-middle attack.</source>
+ <translation>%1 ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’èªè¨¼ã§ãã¾ã›ã‚“。
+ã“ã®ã‚µãƒ¼ãƒãƒ¼ã® SSL èªè¨¼ã‚’無効ã«ã—ã¾ã™ã‹ï¼Ÿ
+注æ„:ã“ã‚Œã«ã‚ˆã‚Šã€ä¸­é–“者攻撃(man-in-the-middle attack)ã‚’å—ã‘ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>Gerrit::Internal::GerritModel</name>
<message>
+ <source> (Draft)</source>
+ <translation> (下書ã)</translation>
+ </message>
+ <message>
<source>Subject</source>
<translation>件å</translation>
</message>
@@ -18132,12 +22302,20 @@ Would you like to terminate it?</source>
<translation>&amp;ssh:</translation>
</message>
<message>
+ <source>cur&amp;l:</source>
+ <translation>cur&amp;l:</translation>
+ </message>
+ <message>
+ <source>SSH &amp;Port:</source>
+ <translation>SSH ãƒãƒ¼ãƒˆ(&amp;P):</translation>
+ </message>
+ <message>
<source>&amp;Port:</source>
<translation>ãƒãƒ¼ãƒˆ(&amp;P):</translation>
</message>
<message>
<source>P&amp;rotocol:</source>
- <translation>プロトコル(&amp;r):</translation>
+ <translation>プロトコル(&amp;R):</translation>
</message>
<message>
<source>Determines the protocol used to form a URL in case
@@ -18251,6 +22429,26 @@ were not verified among remotes in %3. Select different folder?</source>
<source>Ignore whitespace only changes.</source>
<translation>空白ã ã‘ã®å¤‰æ›´ã‚’無視ã—ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>No Move Detection</source>
+ <translation>移動検出ãªã—</translation>
+ </message>
+ <message>
+ <source>Detect Moves Within File</source>
+ <translation>ファイル内ã®å‹•ãを検出ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Detect Moves Between Files</source>
+ <translation>ファイル間ã®ç§»å‹•ã‚’検出ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Detect Moves and Copies Between Files</source>
+ <translation>ファイル間ã®ç§»å‹•ã¨ã‚³ãƒ”ーを検出ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Move detection</source>
+ <translation>移動検出</translation>
+ </message>
</context>
<context>
<name>Git::Internal::GitLogArgumentsWidget</name>
@@ -18263,6 +22461,14 @@ were not verified among remotes in %3. Select different folder?</source>
<translation>差分を表示ã—ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>First Parent</source>
+ <translation>最åˆã®è¦ª</translation>
+ </message>
+ <message>
+ <source>Follow only the first parent on merge commits.</source>
+ <translation>マージコミットã§æœ€åˆã®è¦ªã®ã¿ã«å¾“ã†ã€‚</translation>
+ </message>
+ <message>
<source>Graph</source>
<translation>グラフ</translation>
</message>
@@ -18270,6 +22476,22 @@ were not verified among remotes in %3. Select different folder?</source>
<source>Show textual graph log.</source>
<translation>テキストã«ã‚ˆã‚‹ã‚°ãƒ©ãƒ•ãƒ­ã‚°ã‚’表示ã—ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>Color</source>
+ <translation>色</translation>
+ </message>
+ <message>
+ <source>Use colors in log.</source>
+ <translation>ログã«è‰²ã‚’使用ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Follow</source>
+ <translation>フォロー</translation>
+ </message>
+ <message>
+ <source>Show log also for previous names of the file.</source>
+ <translation>以å‰ã®ãƒ•ã‚¡ã‚¤ãƒ«åã«ã¤ã„ã¦ã‚‚ログを表示ã™ã‚‹ã€‚</translation>
+ </message>
</context>
<context>
<name>Git::Internal::GitClient</name>
@@ -18285,6 +22507,18 @@ were not verified among remotes in %3. Select different folder?</source>
<source>Cannot launch &quot;%1&quot;.</source>
<translation>&quot;%1&quot; ã‚’èµ·å‹•ã§ãã¾ã›ã‚“。</translation>
</message>
+ <message numerus="yes">
+ <source>Stage Selection (%n Lines)</source>
+ <translation>
+ <numerusform>é¸æŠžã—ãŸã‚‚ã®ã‚’ステージã™ã‚‹ (%n è¡Œ)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>Unstage Selection (%n Lines)</source>
+ <translation>
+ <numerusform>é¸æŠžã—ãŸã‚‚ã®ã‚’アンステージã™ã‚‹ (%n è¡Œ)</numerusform>
+ </translation>
+ </message>
<message>
<source>Git Diff Project</source>
<translation>Git プロジェクトã®å·®åˆ†è¡¨ç¤º</translation>
@@ -18314,6 +22548,26 @@ were not verified among remotes in %3. Select different folder?</source>
<translation>Git &quot;%1&quot; ã®è¡¨ç¤º</translation>
</message>
<message>
+ <source>Tarball (*.tar.gz)</source>
+ <translation>Tarball (*.tar.gz)</translation>
+ </message>
+ <message>
+ <source>Zip archive (*.zip)</source>
+ <translation>ZIP アーカイブ (*.zip)</translation>
+ </message>
+ <message>
+ <source>Generate %1 archive</source>
+ <translation>%1ã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–を生æˆã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Overwrite?</source>
+ <translation>上書ãã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>An item named &quot;%1&quot; already exists at this location. Do you want to overwrite it?</source>
+ <translation>&quot;%1&quot; ã¨ã„ã†åå‰ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯æ—¢ã«åŒã˜ãƒ‘スã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚上書ãã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
<source>Git Blame &quot;%1&quot;</source>
<translation>Git &quot;%1&quot; ã®ç·¨é›†è€…を表示</translation>
</message>
@@ -18330,6 +22584,14 @@ were not verified among remotes in %3. Select different folder?</source>
<translation>作業ディレクトリã®ã™ã¹ã¦ã®å¤‰æ›´ãŒç ´æ£„ã•ã‚Œã¾ã™ã€‚破棄ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
+ <source>Nothing to recover</source>
+ <translation>リカãƒãƒªã™ã‚‹ã‚‚ã®ãŒãªã„</translation>
+ </message>
+ <message>
+ <source>Files recovered</source>
+ <translation>復元ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message>
<source>Cannot obtain log of &quot;%1&quot;: %2</source>
<translation>&quot;%1&quot; ã®ãƒ­ã‚°ã‚’å–å¾—ã§ãã¾ã›ã‚“: %2</translation>
</message>
@@ -18339,6 +22601,12 @@ were not verified among remotes in %3. Select different folder?</source>
<numerusform>&quot;%1&quot; 内㮠%n 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒãƒªã‚»ãƒƒãƒˆã§ãã¾ã›ã‚“: %2</numerusform>
</translation>
</message>
+ <message numerus="yes">
+ <source>Cannot reset %n files in &quot;%1&quot;: %2</source>
+ <translation>
+ <numerusform>&quot;%1&quot; 内㮠%n 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒãƒªã‚»ãƒƒãƒˆã§ãã¾ã›ã‚“: %2</numerusform>
+ </translation>
+ </message>
<message>
<source>Cannot checkout &quot;%1&quot; of %2 in &quot;%3&quot;: %4</source>
<extracomment>Meaning of the arguments: %1: revision, %2: files, %3: repository, %4: Error message</extracomment>
@@ -18478,10 +22746,97 @@ Commit now?</source>
<source>The repository &quot;%1&quot; is not initialized.</source>
<translation>リãƒã‚¸ãƒˆãƒª &quot;%1&quot; ã¯åˆæœŸåŒ–ã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
</message>
+ <message numerus="yes">
+ <source>Committed %n files.</source>
+ <translation>
+ <numerusform>%n 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã—ãŸã€‚</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>Amended &quot;%1&quot; (%n files).</source>
+ <translation>
+ <numerusform>&quot;%1&quot; ã®ãƒ­ã‚°ã‚’修正ã—ã¾ã—ãŸ(%n 個ã®ãƒ•ã‚¡ã‚¤ãƒ«)。</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>Cannot commit %n files
+</source>
+ <translation>
+ <numerusform>%n 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’コミットã§ãã¾ã›ã‚“
+</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Cherr&amp;y-Pick Change %1</source>
+ <translation>コミット %1 ã‚’ãƒã‚§ãƒªãƒ¼ãƒ”ック(&amp;Y)</translation>
+ </message>
+ <message>
+ <source>Re&amp;vert Change %1</source>
+ <translation>コミット %1 をリãƒãƒ¼ãƒˆ(&amp;V)</translation>
+ </message>
+ <message>
+ <source>C&amp;heckout Change %1</source>
+ <translation>コミット %1 ã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ(&amp;H)</translation>
+ </message>
+ <message>
+ <source>&amp;Interactive Rebase from Change %1...</source>
+ <translation>%1ã®å¤‰æ›´ã‹ã‚‰å¯¾è©±çš„ãª(&amp;I) リベース...</translation>
+ </message>
+ <message>
+ <source>&amp;Log for Change %1</source>
+ <translation>コミット %1 ã®ãƒ­ã‚°(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Sh&amp;ow file &quot;%1&quot; on revision %2</source>
+ <translation>リビジョン %2 ã®ãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; を表示ã™ã‚‹(&amp;O)</translation>
+ </message>
+ <message>
+ <source>Add &amp;Tag for Change %1...</source>
+ <translation>コミット %1 ã®è¿½åŠ ã¨ã‚¿ã‚°ä»˜ã‘(&amp;T)...</translation>
+ </message>
+ <message>
+ <source>&amp;Reset to Change %1</source>
+ <translation>コミット %1 ã¸ãƒªã‚»ãƒƒãƒˆ(&amp;R)</translation>
+ </message>
+ <message>
+ <source>&amp;Hard</source>
+ <translation>ãƒãƒ¼ãƒ‰(&amp;H)</translation>
+ </message>
+ <message>
+ <source>&amp;Mixed</source>
+ <translation>混在(&amp;M)</translation>
+ </message>
+ <message>
+ <source>&amp;Soft</source>
+ <translation>ソフト(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Di&amp;ff Against %1</source>
+ <translation>%1 ã«å¯¾ã™ã‚‹å·®åˆ†è¡¨ç¤º(&amp;F)</translation>
+ </message>
+ <message>
+ <source>Diff &amp;Against Saved %1</source>
+ <translation>ä¿å­˜ã•ã‚ŒãŸ %1 ã«å¯¾ã™ã‚‹(&amp;A)差分表示</translation>
+ </message>
+ <message>
+ <source>&amp;Save for Diff</source>
+ <translation>差分をä¿å­˜ã™ã‚‹(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Git Show %1:%2</source>
+ <translation>Git Show %1:%2</translation>
+ </message>
<message>
<source>Cannot retrieve last commit data of repository &quot;%1&quot;.</source>
<translation>リãƒã‚¸ãƒˆãƒª &quot;%1&quot; ã®æœ€å¾Œã®ã‚³ãƒŸãƒƒãƒˆãƒ‡ãƒ¼ã‚¿ã‚’å—ä¿¡ã§ãã¾ã›ã‚“。</translation>
</message>
+ <message numerus="yes">
+ <source>and %n more</source>
+ <extracomment>Displayed after the untranslated message &quot;Branches: branch1, branch2 &apos;and %n more&apos;&quot;</extracomment>
+ <translation>
+ <numerusform>ãã®ä»–(%n)</numerusform>
+ </translation>
+ </message>
<message>
<source>Stage Chunk</source>
<translation>ãƒãƒ£ãƒ³ã‚¯ã‚’ステージã«è¿½åŠ </translation>
@@ -18569,6 +22924,10 @@ Commit now?</source>
<translation>マージツールã®å®Ÿè¡Œ(&amp;M)</translation>
</message>
<message>
+ <source>Only graphical merge tools are supported. Please configure merge.tool.</source>
+ <translation>グラフィカルãªãƒžãƒ¼ã‚¸ãƒ„ールã®ã¿ãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚merge.tool を設定ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>&amp;Skip</source>
<translation>スキップ(&amp;S)</translation>
</message>
@@ -18577,6 +22936,26 @@ Commit now?</source>
<translation>Git SVN ログ</translation>
</message>
<message>
+ <source>Force Push</source>
+ <translation>プッシュを強制ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Push failed. Would you like to force-push &lt;span style=&quot;color:#%1&quot;&gt;(rewrites remote history)&lt;/span&gt;?</source>
+ <translation>プッシュã«å¤±æ•—ã—ã¾ã—ãŸã€‚&lt;span style=&quot;color:#%1&quot;&gt;(リモートã®å±¥æ­´ã‚’書ãæ›ãˆã¾ã™)&lt;/span&gt;を強制プッシュã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>No Upstream Branch</source>
+ <translation>上æµãƒ–ランãƒãŒã‚ã‚Šã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Push failed because the local branch &quot;%1&quot; does not have an upstream branch on the remote.
+
+Would you like to create the branch &quot;%1&quot; on the remote and set it as upstream?</source>
+ <translation>ローカル・ブランãƒ&quot;%1&quot;ãŒãƒªãƒ¢ãƒ¼ãƒˆã®ä¸Šæµãƒ–ランãƒã‚’æŒã£ã¦ã„ãªã„ã®ã§ã€ãƒ—ッシュã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+
+リモートã§ãƒ–ランãƒ&quot;%1&quot;を作æˆã—ã€ãれを上æµãƒ–ランãƒã¨ã—ã¦è¨­å®šã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
<source>Rebase, merge or am is in progress. Finish or abort it and then try again.</source>
<translation>リベースã€ãƒžãƒ¼ã‚¸ã€ãƒ‘ッãƒé©ç”¨ãªã©ãŒå®Ÿè¡Œä¸­ã§ã™ã€‚完了ã‚ã‚‹ã„ã¯ä¸­æ–­å¾Œã«å†åº¦å®Ÿè¡Œã—ã¦ãã ã•ã„。</translation>
</message>
@@ -19107,6 +23486,14 @@ Commit now?</source>
<source>Patch %1 successfully applied to %2</source>
<translation>パッム%1 ã‚’ %2 ã«é©ç”¨ã—ã¾ã—ãŸ</translation>
</message>
+ <message>
+ <source>&lt;No repository&gt;</source>
+ <translation>&lt;リãƒã‚¸ãƒˆãƒªãªã—&gt;</translation>
+ </message>
+ <message>
+ <source>Repository: %1</source>
+ <translation>リãƒã‚¸ãƒˆãƒª: %1</translation>
+ </message>
</context>
<context>
<name>Git::Internal::GitSettings</name>
@@ -19142,6 +23529,18 @@ Commit now?</source>
<translation>コミットã—㦠&amp;Gerrit ã¸ãƒ—ッシュ</translation>
</message>
<message>
+ <source>Invalid author</source>
+ <translation>無効ãªè‘—作者</translation>
+ </message>
+ <message>
+ <source>Invalid email</source>
+ <translation>無効ãªEメール</translation>
+ </message>
+ <message>
+ <source>Unresolved merge conflicts</source>
+ <translation>未解決ãªãƒžãƒ¼ã‚¸ã®è¡çª</translation>
+ </message>
+ <message>
<source>&amp;Commit and Push</source>
<translation>コミットã—ã¦ãƒ—ッシュ(&amp;C)</translation>
</message>
@@ -19275,6 +23674,18 @@ Remote: %4</source>
<translation>ä»–ã®æœªè§£æ±ºãªãƒ‘スã®ãƒžãƒ¼ã‚¸ã‚’継続ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
+ <source>Merge Tool</source>
+ <translation>マージツール</translation>
+ </message>
+ <message>
+ <source>Merge tool is not configured.</source>
+ <translation>マージツールãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Run git config --global merge.tool &amp;lt;tool&amp;gt; to configure it, then try again.</source>
+ <translation>git config --global merge.tool &amp;lt;tool&amp;gt;を実行ã—ã¦è¨­å®šã—ã¦ã‹ã‚‰ã€ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>Merge tool process finished successfully.</source>
<translation>マージツールãŒæ­£å¸¸ã«çµ‚了ã—ã¾ã—ãŸã€‚</translation>
</message>
@@ -19296,6 +23707,16 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
ãã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªå†…㧠SSH éµã‚’探索ã™ã‚‹ã‹ã‚‰ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Set the environment variable HOME to &quot;%1&quot;
+(%2).
+This causes Git to look for the SSH-keys in that location
+instead of its installation directory when run outside git bash.</source>
+ <translation>環境変数 HOME ã‚’ &quot;%1&quot; ã«è¨­å®šã—ã¾ã™ã€‚
+(%2).
+
+ã“ã‚Œã«ã‚ˆã‚Šã€git bash ã®å¤–ã§å®Ÿè¡Œã—ãŸã¨ãã«ã€Git ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã¯ãªããã®å ´æ‰€ã§ SSH キーを探ã™ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>not currently set</source>
<translation>設定ã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
</message>
@@ -19307,6 +23728,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>Git Repository Browser Command</source>
<translation>Git リãƒã‚¸ãƒˆãƒªãƒ–ラウザコマンド</translation>
</message>
+ <message>
+ <source>Git</source>
+ <translation>Git</translation>
+ </message>
</context>
<context>
<name>GLSLEditor</name>
@@ -19379,10 +23804,18 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>技術サãƒãƒ¼ãƒˆ</translation>
</message>
<message>
+ <source>Technical Support...</source>
+ <translation>技術サãƒãƒ¼ãƒˆ...</translation>
+ </message>
+ <message>
<source>Report Bug...</source>
<translation>ãƒã‚°ã®å ±å‘Š...</translation>
</message>
<message>
+ <source>System Information...</source>
+ <translation>システム情報...</translation>
+ </message>
+ <message>
<source>No Documentation</source>
<translation>ドキュメントãŒã‚ã‚Šã¾ã›ã‚“</translation>
</message>
@@ -19391,6 +23824,18 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>使用å¯èƒ½ãªãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆãŒã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>System Information</source>
+ <translation>システム情報</translation>
+ </message>
+ <message>
+ <source>Use the following to provide more detailed information about your system to bug reports:</source>
+ <translation>システムã®ã‚ˆã‚Šè©³ç´°ãªæƒ…報をãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã«æä¾›ã™ã‚‹ãŸã‚ã«ä»¥ä¸‹ã‚’使用ã—ã¾ã™:</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>クリップボードã«ã‚³ãƒ”ーã™ã‚‹</translation>
+ </message>
+ <message>
<source>Open Pages</source>
<translation>ページを開ã</translation>
</message>
@@ -19494,6 +23939,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>%1 %2</source>
<translation>%1 %2</translation>
</message>
+ <message>
+ <source>%1 Simulator</source>
+ <translation>%1 シミュレータ</translation>
+ </message>
</context>
<context>
<name>Ios</name>
@@ -19505,6 +23954,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<context>
<name>Ios::Internal::IosDebugSupport</name>
<message>
+ <source>Application not running.</source>
+ <translation>アプリケーションãŒå®Ÿè¡Œã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Could not find device specific debug symbols at %1. Debugging initialization will be slow until you open the Organizer window of Xcode with the device connected to have the symbols generated.</source>
<translation>%1 ã«ãƒ‡ãƒã‚¤ã‚¹å›ºæœ‰ã®ãƒ‡ãƒãƒƒã‚°ã‚·ãƒ³ãƒœãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚Xcode ã® Organaizer ウィンドウを生æˆã•ã‚ŒãŸã‚·ãƒ³ãƒœãƒ«ã‚’æŒã¤ãƒ‡ãƒã‚¤ã‚¹ã§é–‹ãã¾ã§ã¯ã€ãƒ‡ãƒãƒƒã‚°ã®åˆæœŸåŒ–ãŒé…ããªã‚Šã¾ã™ã€‚</translation>
</message>
@@ -19559,7 +24012,11 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
</message>
<message>
<source>Deployment failed. No iOS device found.</source>
- <translation>ã§ãƒ–ロイã«å¤±æ•—ã—ã¾ã—ãŸã€‚iOS デãƒã‚¤ã‚¹ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ <translation>デプロイã«å¤±æ•—ã—ã¾ã—ãŸã€‚iOS デãƒã‚¤ã‚¹ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Transferring application</source>
+ <translation>アプリケーション転é€ä¸­</translation>
</message>
<message>
<source>Deployment failed. The settings in the Devices window of Xcode might be incorrect.</source>
@@ -19577,6 +24034,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>The provisioning profile &quot;%1&quot; (%2) used to sign the application does not cover the device %3 (%4). Deployment to it will fail.</source>
<translation>アプリケーションã®ç½²åã«ä½¿ç”¨ã™ã‚‹ãŸã‚ã«æº–å‚™ã•ã‚ŒãŸãƒ—ロファイル &quot;%1&quot; (%2) ãŒãƒ‡ãƒã‚¤ã‚¹ %3 (%4) ã‚’ã‚«ãƒãƒ¼ã—ã¦ã„ã¾ã›ã‚“。デプロイã¯å¤±æ•—ã™ã‚‹ã§ã—ょã†ã€‚</translation>
</message>
+ <message>
+ <source>Deploy to iOS device</source>
+ <translation>iOS デãƒã‚¤ã‚¹ã«ãƒ‡ãƒ—ロイ</translation>
+ </message>
</context>
<context>
<name>Ios::Internal::IosDeployStepFactory</name>
@@ -19595,6 +24056,22 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>iOS Device</source>
<translation>iOS デãƒã‚¤ã‚¹</translation>
</message>
+ <message>
+ <source>Device name:</source>
+ <translation>デãƒã‚¤ã‚¹å:</translation>
+ </message>
+ <message>
+ <source>Identifier:</source>
+ <translation>識別å­:</translation>
+ </message>
+ <message>
+ <source>OS Version:</source>
+ <translation>OS ãƒãƒ¼ã‚¸ãƒ§ãƒ³:</translation>
+ </message>
+ <message>
+ <source>CPU Architecture:</source>
+ <translation>CPU アーキテクãƒãƒ£:</translation>
+ </message>
</context>
<context>
<name>Ios::Internal::IosDeviceManager</name>
@@ -19732,6 +24209,14 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>%1 ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
</message>
<message>
+ <source>Could not get necessary ports for the debugger connection.</source>
+ <translation>デãƒãƒƒã‚¬ã®æŽ¥ç¶šã«å¿…è¦ãªãƒãƒ¼ãƒˆã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Could not get inferior PID.</source>
+ <translation>PID ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>Run failed. The settings in the Organizer window of Xcode might be incorrect.</source>
<translation>実行ã«å¤±æ•—ã—ã¾ã—ãŸã€‚Xcode ã® Organizer ウィンドウã§ã®è¨­å®šãŒæ­£ã—ããªã„ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。</translation>
</message>
@@ -19739,6 +24224,14 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>The device is locked, please unlock.</source>
<translation>デãƒã‚¤ã‚¹ãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚ロックを解除ã—ã¦ãã ã•ã„。</translation>
</message>
+ <message>
+ <source>Run ended.</source>
+ <translation>実行ãŒçµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Run ended with error.</source>
+ <translation>エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
</context>
<context>
<name>Ios::Internal::IosSettingsPage</name>
@@ -19825,6 +24318,22 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>Alt+)</translation>
</message>
<message>
+ <source>Ctrl+[</source>
+ <translation>Ctrl+[</translation>
+ </message>
+ <message>
+ <source>Alt+[</source>
+ <translation>Alt+[</translation>
+ </message>
+ <message>
+ <source>Ctrl+]</source>
+ <translation>Ctrl+]</translation>
+ </message>
+ <message>
+ <source>Alt+]</source>
+ <translation>Alt+]</translation>
+ </message>
+ <message>
<source>Play Last Macro</source>
<translation>ç›´å‰ã®ãƒžã‚¯ãƒ­ã‚’å†ç”Ÿ</translation>
</message>
@@ -19866,6 +24375,14 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>Hg outgoing %1</source>
<translation>Hg %1 ã¨ã®å·®åˆ†ã‚’検出</translation>
</message>
+ <message>
+ <source>Mercurial Diff</source>
+ <translation>Mercurial 差分</translation>
+ </message>
+ <message>
+ <source>Mercurial Diff &quot;%1&quot;</source>
+ <translation>Mercurial 差分 &quot;%1&quot;</translation>
+ </message>
</context>
<context>
<name>Mercurial::Internal::MercurialDiffParameterWidget</name>
@@ -20044,6 +24561,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>サーãƒãƒ¼ã¨ã®å·®åˆ†æ¤œå‡º</translation>
</message>
<message>
+ <source>Mercurial</source>
+ <translation>Mercurial</translation>
+ </message>
+ <message>
<source>Commit</source>
<translation>コミット</translation>
</message>
@@ -20090,6 +24611,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>Mercurial Command</source>
<translation>Mercurial コマンド</translation>
</message>
+ <message>
+ <source>Mercurial</source>
+ <translation>Mercurial</translation>
+ </message>
</context>
<context>
<name>Perforce::Internal::PerforceChecker</name>
@@ -20342,6 +24867,14 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>ファイルログ...</translation>
</message>
<message>
+ <source>&amp;Edit</source>
+ <translation>編集(&amp;E)</translation>
+ </message>
+ <message>
+ <source>&amp;Hijack</source>
+ <translation>ãƒã‚¤ã‚¸ãƒ£ãƒƒã‚¯(&amp;H)</translation>
+ </message>
+ <message>
<source>Submit</source>
<translation>サブミット</translation>
</message>
@@ -20575,6 +25108,14 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
</message>
<message>
<source>Filter: %1
+Excluding: %2
+%3</source>
+ <translation>フィルタ: %1
+除外: %2
+%3</translation>
+ </message>
+ <message>
+ <source>Filter: %1
%2</source>
<translation>フィルタ: %1
%2</translation>
@@ -20587,6 +25128,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<context>
<name>ProjectExplorer::ApplicationLauncher</name>
<message>
+ <source>User requested stop. Shutting down...</source>
+ <translation>ユーザーãŒåœæ­¢ã‚’è¦æ±‚ã—ã¾ã—ãŸã€‚シャットダウンã—ã¾ã™...</translation>
+ </message>
+ <message>
<source>Failed to start program. Path or permissions wrong?</source>
<translation>プログラムを開始ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚パスã‹ãƒ‘ーミッションã«èª¤ã‚Šã¯ã‚ã‚Šã¾ã›ã‚“ã‹ï¼Ÿ</translation>
</message>
@@ -20602,6 +25147,30 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>Cannot retrieve debugging output.</source>
<translation>デãƒãƒƒã‚°å‡ºåŠ›ã‚’å–å¾—ã§ãã¾ã›ã‚“。</translation>
</message>
+ <message>
+ <source>Cannot run: No device.</source>
+ <translation>実行エラー: デãƒã‚¤ã‚¹ãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Cannot run: Device is not able to create processes.</source>
+ <translation>実行エラー: デãƒã‚¤ã‚¹ãŒãƒ—ロセスを作æˆã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Cannot run: No command given.</source>
+ <translation>実行エラー: コマンドãŒæ¸¡ã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Application failed to start: %1</source>
+ <translation>アプリケーションã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Application finished with exit code %1.</source>
+ <translation>アプリケーションã¯çµ‚了コード %1 ã§çµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Application finished with exit code 0.</source>
+ <translation>アプリケーションã¯çµ‚了コード 0 ã§çµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::AppOutputPane</name>
@@ -20630,6 +25199,18 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>ä»–ã®ã‚¿ãƒ–ã‚’é–‰ã˜ã‚‹</translation>
</message>
<message>
+ <source>Re-run this run-configuration.</source>
+ <translation>ã“ã®å®Ÿè¡Œæ§‹æˆã§å†å®Ÿè¡Œã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Stop running program.</source>
+ <translation>実行中ã®ãƒ—ログラムをåœæ­¢ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Open Settings Page</source>
+ <translation>設定画é¢ã‚’é–‹ã</translation>
+ </message>
+ <message>
<source>Re-run this run-configuration</source>
<translation>ã“ã®å®Ÿè¡Œè¨­å®šã§å†å®Ÿè¡Œã—ã¾ã™</translation>
</message>
@@ -20679,6 +25260,30 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>ビルドディレクトリ</translation>
</message>
<message>
+ <source>Name of current build</source>
+ <translation>ç¾åœ¨ã®ãƒ“ルドã®åå‰</translation>
+ </message>
+ <message>
+ <source>Name of the build configuration</source>
+ <translation>ビルド構æˆã®åå‰</translation>
+ </message>
+ <message>
+ <source>Variables in the current build environment</source>
+ <translation>ç¾åœ¨ã®ãƒ“ルド環境ã§ã®å¤‰æ•°</translation>
+ </message>
+ <message>
+ <source>Variables in the build configuration&apos;s environment</source>
+ <translation>ビルド構æˆã®ç’°å¢ƒå¤‰æ•°</translation>
+ </message>
+ <message>
+ <source>Tooltip in target selector:</source>
+ <translation>ターゲットセレクタã®ãƒ„ールãƒãƒƒãƒ—:</translation>
+ </message>
+ <message>
+ <source>Appears as a tooltip when hovering the build configuration</source>
+ <translation>ビルド構æˆã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’åˆã‚ã›ã‚‹ã¨ã€ãƒ„ールãƒãƒƒãƒ—ã¨ã—ã¦è¡¨ç¤ºã•ã‚Œã‚‹</translation>
+ </message>
+ <message>
<source>System Environment</source>
<translation>システム環境変数</translation>
</message>
@@ -20686,6 +25291,22 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>Clean Environment</source>
<translation>環境変数ãªã—</translation>
</message>
+ <message>
+ <source>The project was not parsed successfully.</source>
+ <translation>プロジェクトãŒæ­£å¸¸ã«è§£æžã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Variables in the current build environment.</source>
+ <translation>ç¾åœ¨ã®ãƒ“ルド環境ã§ã®å¤‰æ•°ã€‚</translation>
+ </message>
+ <message>
+ <source>Variables in the active build environment of the project containing the currently open document.</source>
+ <translation>ç¾åœ¨é–‹ã„ã¦ã„るドキュメントをå«ã‚€ãƒ—ロジェクトã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªãƒ“ルド環境ã®å¤‰æ•°ã€‚</translation>
+ </message>
+ <message>
+ <source>Variables in the active build environment of the active project.</source>
+ <translation>アクティブãªãƒ—ロジェクトã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªãƒ“ルド環境ã®å¤‰æ•°ã€‚</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::BuildEnvironmentWidget</name>
@@ -20707,6 +25328,18 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
</translation>
</message>
<message>
+ <source>Stop Applications</source>
+ <translation>アプリケーションã®åœæ­¢</translation>
+ </message>
+ <message>
+ <source>Stop these applications before building?</source>
+ <translation>ビルドå‰ã«ä»¥ä¸‹ã®ã‚¢ãƒ—リケーションをåœæ­¢ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>The project %1 is not configured, skipping it.</source>
+ <translation>プロジェクト %1 ã¯è¨­å®šã•ã‚Œã¦ã„ãªã„ãŸã‚ã€ã‚¹ã‚­ãƒƒãƒ—ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Compile</source>
<comment>Category for compiler issues listed under &apos;Issues&apos;</comment>
<translation>コンパイル</translation>
@@ -20722,6 +25355,26 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>デプロイ</translation>
</message>
<message>
+ <source>Autotests</source>
+ <comment>Category for autotest issues listed under &apos;Issues&apos;</comment>
+ <translation>自動テスト</translation>
+ </message>
+ <message>
+ <source>Clean</source>
+ <extracomment>Displayed name for a &quot;cleaning&quot; build step</extracomment>
+ <translation>クリーン</translation>
+ </message>
+ <message>
+ <source>Deploy</source>
+ <extracomment>Displayed name for a deploy step</extracomment>
+ <translation>デプロイ</translation>
+ </message>
+ <message>
+ <source>Build</source>
+ <extracomment>Displayed name for a normal build step</extracomment>
+ <translation>ビルド</translation>
+ </message>
+ <message>
<source>Elapsed time: %1.</source>
<translation>経éŽæ™‚é–“: %1.</translation>
</message>
@@ -20788,6 +25441,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>é¸æŠžã•ã‚ŒãŸè¨­å®šã‚’複製(&amp;C)</translation>
</message>
<message>
+ <source>Clone...</source>
+ <translation>複製...</translation>
+ </message>
+ <message>
<source>New Configuration</source>
<translation>æ–°ã—ã„設定</translation>
</message>
@@ -20849,7 +25506,11 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
</message>
<message>
<source>Remove Item</source>
- <translation>é …ç›®ã®å‰Šé™¤</translation>
+ <translation>項目を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Enable</source>
+ <translation>有効</translation>
</message>
<message>
<source>%1 Steps</source>
@@ -20909,6 +25570,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>Decrease Font Size</source>
<translation>フォントをå°ã•ã</translation>
</message>
+ <message>
+ <source>Open Settings Page</source>
+ <translation>設定画é¢ã‚’é–‹ã</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::CopyTaskHandler</name>
@@ -20955,6 +25620,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<context>
<name>CustomToolChain</name>
<message>
+ <source>Parser for toolchain %1</source>
+ <translation>ツールãƒã‚§ãƒ¼ãƒ³ %1 用ã®ãƒ‘ーサー</translation>
+ </message>
+ <message>
<source>GCC</source>
<translation>GCC</translation>
</message>
@@ -20995,12 +25664,16 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>カスタムパーサ設定...</translation>
</message>
<message>
+ <source>MACRO[=VALUE]</source>
+ <translation>MACRO[=VALUE]</translation>
+ </message>
+ <message>
<source>Each line defines a macro. Format is MACRO[=VALUE].</source>
<translation>マクロを一行ã«ã²ã¨ã¤ãšã¤å®šç¾©ã—ã¦ãã ã•ã„。書å¼ã¯ MACRO[=VALUE] ã§ã™ã€‚</translation>
</message>
<message>
<source>Each line adds a global header lookup path.</source>
- <translation>ヘッダーを検索ã™ã‚‹ã‚°ãƒ­ãƒ¼ãƒãƒ«ãªãƒ‘スを一行ã«ã²ã¨ã¤ãšã¤è¨˜è¿°ã—ã¦ãã ã•ã„。</translation>
+ <translation>ヘッダを検索ã™ã‚‹ã‚°ãƒ­ãƒ¼ãƒãƒ«ãªãƒ‘スを一行ã«ã²ã¨ã¤ãšã¤è¨˜è¿°ã—ã¦ãã ã•ã„。</translation>
</message>
<message>
<source>Comma-separated list of flags that turn on C++11 support.</source>
@@ -21028,7 +25701,7 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
</message>
<message>
<source>&amp;Header paths:</source>
- <translation>ヘッダーã®ãƒ‘ス(&amp;H):</translation>
+ <translation>ヘッダã®ãƒ‘ス(&amp;H):</translation>
</message>
<message>
<source>C++11 &amp;flags:</source>
@@ -21223,6 +25896,11 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>ローカルã«ãƒ‡ãƒ—ロイ</translation>
</message>
<message>
+ <source>Deploy Configuration</source>
+ <extracomment>Display name of the default deploy configuration</extracomment>
+ <translation>デプロイ設定</translation>
+ </message>
+ <message>
<source>Deploy Settings</source>
<translation>デプロイ設定</translation>
</message>
@@ -21279,6 +25957,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>DebugBreakProcess ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ:</translation>
</message>
<message>
+ <source>%1 does not exist. If you built %2 yourself, check out https://code.qt.io/cgit/qt-creator/binary-artifacts.git/.</source>
+ <translation>%1 ãŒå­˜åœ¨ã—ã¾ã›ã‚“。%2を独自ã«ãƒ“ルドã—ãŸå ´åˆã¯ã€https://code.qt.io/cgit/qt-creator/binary-artifacts.git/ を確èªã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>%1 does not exist. If you built Qt Creator yourself, check out https://code.qt.io/cgit/qt-creator/binary-artifacts.git/.</source>
<translation>%1 ãŒå­˜åœ¨ã—ã¾ã›ã‚“。Qt Creator を独自ã«ãƒ“ルドã—ãŸå ´åˆã¯ã€https://code.qt.io/cgit/qt-creator/binary-artifacts.git/ を確èªã—ã¦ãã ã•ã„。</translation>
</message>
@@ -21408,16 +26090,58 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>ç¾åœ¨ã®ãƒ—ロジェクトã®ãƒ¡ã‚¤ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«</translation>
</message>
<message>
+ <source>Main file of the project</source>
+ <translation>プロジェクトã®ãƒ¡ã‚¤ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message>
<source>Name of current project</source>
<translation>ç¾åœ¨ã®ãƒ—ロジェクトã®åå‰</translation>
</message>
<message>
+ <source>Name of the project</source>
+ <translation>プロジェクトå</translation>
+ </message>
+ <message>
+ <source>Name of the project&apos;s active build configuration</source>
+ <translation>プロジェクトã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªãƒ“ルド構æˆã®åå‰</translation>
+ </message>
+ <message>
<source>Type of current build</source>
<translation>ç¾åœ¨ã®ãƒ“ルドã®ã‚¿ã‚¤ãƒ—</translation>
</message>
<message>
<source>The currently active run configuration&apos;s name.</source>
<translation>ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªå®Ÿè¡Œè¨­å®šã®åå‰ã§ã™ã€‚</translation>
+ <source>Type of the project&apos;s active build configuration</source>
+ <translation>プロジェクトã®æœ‰åŠ¹ãªãƒ“ルド構æˆã®åž‹</translation>
+ </message>
+ <message>
+ <source>The currently active run configuration&apos;s name.</source>
+ <translation type="vanished">ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªå®Ÿè¡Œè¨­å®šã®åå‰ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>SSH</source>
+ <translation>SSH</translation>
+ </message>
+ <message>
+ <source>Kits</source>
+ <translation>キット</translation>
+ </message>
+ <message>
+ <source>Kit is not valid.</source>
+ <translation>無効ãªã‚­ãƒƒãƒˆã€‚</translation>
+ </message>
+ <message>
+ <source>Auto-detected</source>
+ <translation>自動検出</translation>
+ </message>
+ <message>
+ <source>Automatically managed by %1 or the installer.</source>
+ <translation>自動的㫠%1 ã¾ãŸã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Manual</source>
+ <translation>手動</translation>
</message>
</context>
<context>
@@ -21522,12 +26246,16 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>Run Environment</source>
<translation>実行時ã®ç’°å¢ƒå¤‰æ•°</translation>
</message>
+ <message>
+ <source>Environment</source>
+ <translation>環境</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::EnvironmentAspectWidget</name>
<message>
<source>Base environment for this run configuration:</source>
- <translation>ã“ã®å®Ÿè¡Œè¨­å®šç”¨ã®åŸºæœ¬ç’°å¢ƒ:</translation>
+ <translation>ã“ã®å®Ÿè¡Œæ§‹æˆç”¨ã®åŸºæœ¬ç’°å¢ƒ:</translation>
</message>
</context>
<context>
@@ -21537,6 +26265,14 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>編集(&amp;E)</translation>
</message>
<message>
+ <source>Variable already exists.</source>
+ <translation>変数ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Ed&amp;it</source>
+ <translation>編集(&amp;I)</translation>
+ </message>
+ <message>
<source>&amp;Add</source>
<translation>追加(&amp;A)</translation>
</message>
@@ -21549,10 +26285,30 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>解除(&amp;U)</translation>
</message>
<message>
+ <source>Disable</source>
+ <translation>無効化</translation>
+ </message>
+ <message>
+ <source>Append Path...</source>
+ <translation>パスを追加ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Prepend Path...</source>
+ <translation>パスを先頭ã«è¿½åŠ ã™ã‚‹...</translation>
+ </message>
+ <message>
<source>&amp;Batch Edit...</source>
<translation>一括編集(&amp;B)...</translation>
</message>
<message>
+ <source>Open &amp;Terminal</source>
+ <translation>ターミナル(&amp;T)ã‚’é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open a terminal with this environment set up.</source>
+ <translation>ã“ã®ç’°å¢ƒã‚’設定ã—ãŸã‚¿ãƒ¼ãƒŸãƒŠãƒ«ã‚’é–‹ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Unset &lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;&lt;/a&gt; を未設定ã«ã™ã‚‹</translation>
</message>
@@ -21561,27 +26317,91 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>&lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;&lt;/a&gt; ã‚’ &lt;b&gt;%2&lt;/b&gt; ã«è¨­å®šã™ã‚‹</translation>
</message>
<message>
+ <source>Append &lt;b&gt;%2&lt;/b&gt; to &lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;&lt;/a&gt;</source>
+ <translation>&lt;b&gt;%2&lt;/b&gt;ã‚’&lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;&lt;/a&gt;ã«è¿½åŠ ã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Prepend &lt;b&gt;%2&lt;/b&gt; to &lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;&lt;/a&gt;</source>
+ <translation>&lt;b&gt;%2&lt;/b&gt;ã‚’&lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;ã®å…ˆé ­ã«è¿½åŠ ã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Set &lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;&lt;/a&gt; to &lt;b&gt;%2&lt;/b&gt; [disabled]</source>
+ <translation>&lt;a href=&quot;%1&quot;&gt;&lt;b&gt;%1&lt;/b&gt;ã‚’&lt;b&gt;%2&lt;/b&gt;ã«è¨­å®šã™ã‚‹ [無効]</translation>
+ </message>
+ <message>
<source>Use &lt;b&gt;%1&lt;/b&gt;</source>
<extracomment>%1 is &quot;System Environment&quot; or some such.</extracomment>
<translation>&lt;b&gt;%1&lt;/b&gt; を使用</translation>
</message>
<message>
+ <source>&lt;b&gt;No environment changes&lt;/b&gt;</source>
+ <translation>&lt;b&gt;環境変化ãªã—&lt;/b&gt;</translation>
+ </message>
+ <message>
<source>Use &lt;b&gt;%1&lt;/b&gt; and</source>
<extracomment>Yup, word puzzle. The Set/Unset phrases above are appended to this. %1 is &quot;System Environment&quot; or some such.</extracomment>
<translation>&lt;b&gt;%1&lt;/b&gt; を使用</translation>
</message>
+ <message>
+ <source>Choose Directory</source>
+ <translation>ディレクトリをé¸æŠžã—ã¦ãã ã•ã„</translation>
+ </message>
+ <message>
+ <source>Enable</source>
+ <translation>有効</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::FolderNavigationWidget</name>
<message>
+ <source>The file &quot;%1&quot; was renamed to &quot;%2&quot;, but the following projects could not be automatically changed: %3</source>
+ <translation>ファイル &quot;%1&quot; ㌠&quot;%2&quot; ã«åå‰å¤‰æ›´ã•ã‚Œã¾ã—ãŸãŒã€ä»¥ä¸‹ã®ãƒ—ロジェクトã¯è‡ªå‹•çš„ã«å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸ:&quot;%3&quot;</translation>
+ </message>
+ <message>
<source>Show Hidden Files</source>
<translation>éš ã—ファイルã®è¡¨ç¤º</translation>
</message>
<message>
+ <source>Show Bread Crumbs</source>
+ <translation>パンããšãƒªã‚¹ãƒˆã‚’表示ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Show Folders on Top</source>
+ <translation>フォルダを最å‰é¢ã«è¡¨ç¤ºã™ã‚‹</translation>
+ </message>
+ <message>
<source>Synchronize with Editor</source>
<translation>エディタã¨åŒæœŸ</translation>
</message>
<message>
+ <source>Synchronize Root Directory with Editor</source>
+ <translation>エディタã¨ãƒ«ãƒ¼ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’åŒæœŸã•ã›ã‚‹</translation>
+ </message>
+ <message>
+ <source>The following projects failed to automatically remove the file: %1</source>
+ <translation>次ã®ãƒ—ロジェクトã§ã¯ã€ãƒ•ã‚¡ã‚¤ãƒ«ã®è‡ªå‹•å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>New Folder</source>
+ <translation>æ–°ã—ã„フォルダ</translation>
+ </message>
+ <message>
+ <source>Open Project &quot;%1&quot;</source>
+ <translation>プロジェクト &quot;%1&quot; ã‚’é–‹ã</translation>
+ </message>
+ <message>
+ <source>Computer</source>
+ <translation>コンピュータ</translation>
+ </message>
+ <message>
+ <source>Home</source>
+ <translation>ホーム</translation>
+ </message>
+ <message>
+ <source>Projects</source>
+ <translation>プロジェクト</translation>
+ </message>
+ <message>
<source>Open</source>
<translation>é–‹ã</translation>
</message>
@@ -21613,6 +26433,30 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>ファイルシステム</translation>
</message>
<message>
+ <source>Meta+Y,Meta+F</source>
+ <translation>Meta+Y,Meta+F</translation>
+ </message>
+ <message>
+ <source>Alt+Y,Alt+F</source>
+ <translation>Alt+Y,Alt+F</translation>
+ </message>
+ <message>
+ <source>Options</source>
+ <translation>オプション</translation>
+ </message>
+ <message>
+ <source>Add New...</source>
+ <translation>æ–°ã—ã„ファイルを追加...</translation>
+ </message>
+ <message>
+ <source>Rename...</source>
+ <translation>åå‰ã‚’変更...</translation>
+ </message>
+ <message>
+ <source>Remove...</source>
+ <translation>削除...</translation>
+ </message>
+ <message>
<source>Meta+Y</source>
<translation>Meta+Y</translation>
</message>
@@ -21631,6 +26475,14 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<source>%1 (%2 %3 in %4)</source>
<translation>%1(%2 %3 パス: %4)</translation>
</message>
+ <message>
+ <source>GCC</source>
+ <translation>GCC</translation>
+ </message>
+ <message>
+ <source>%1 (%2, %3 %4 in %5)</source>
+ <translation>%1(%2 %3 %4 パス: %5)</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::GccToolChainFactory</name>
@@ -21713,14 +26565,26 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªã‚­ãƒƒãƒˆã®åå‰ã§ã™ã€‚</translation>
</message>
<message>
+ <source>The name of the kit.</source>
+ <translation>キットã®åå‰ã€‚</translation>
+ </message>
+ <message>
<source>The name of the currently active kit in a filesystem-friendly version.</source>
<translation>ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªã‚­ãƒƒãƒˆã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚·ã‚¹ãƒ†ãƒ ç”¨ã®åå‰ã§ã™ã€‚</translation>
</message>
<message>
+ <source>The name of the kit in a filesystem-friendly version.</source>
+ <translation>ファイルシステムã«é©ã—ãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚­ãƒƒãƒˆå。</translation>
+ </message>
+ <message>
<source>The id of the currently active kit.</source>
<translation>ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªã‚­ãƒƒãƒˆã® ID ã§ã™ã€‚</translation>
</message>
<message>
+ <source>The id of the kit.</source>
+ <translation>キット㮠ID。</translation>
+ </message>
+ <message>
<source>Clone of %1</source>
<translation>%1 を複製</translation>
</message>
@@ -21868,6 +26732,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<context>
<name>ProjectExplorer::KitManager</name>
<message>
+ <source>Desktop (%1)</source>
+ <translation>デスクトップ (%1)</translation>
+ </message>
+ <message>
<source>Desktop</source>
<translation>デスクトップ</translation>
</message>
@@ -21891,6 +26759,18 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>åå‰:</translation>
</message>
<message>
+ <source>Kit icon.</source>
+ <translation>キットã®ã‚¢ã‚¤ã‚³ãƒ³ã€‚</translation>
+ </message>
+ <message>
+ <source>Select Icon...</source>
+ <translation>アイコンã®é¸æŠž...</translation>
+ </message>
+ <message>
+ <source>Reset to Device Default Icon</source>
+ <translation>既定ã®ãƒ‡ãƒã‚¤ã‚¹ã‚¢ã‚¤ã‚³ãƒ³ã«æˆ»ã™</translation>
+ </message>
+ <message>
<source>Display name is not unique.</source>
<translation>表示åãŒä¸€æ„ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
@@ -21899,6 +26779,10 @@ msysgit ãŒã€git bash 外ã§å®Ÿè¡Œã•ã‚ŒãŸæ™‚ã«è‡ªèº«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆ
<translation>Mutable ã¨ã—ã¦ãƒžãƒ¼ã‚¯</translation>
</message>
<message>
+ <source>Default for %1</source>
+ <translation>%1 å‘ã‘ã®æ—¢å®š</translation>
+ </message>
+ <message>
<source>Select Icon</source>
<translation>アイコンã®é¸æŠž</translation>
</message>
@@ -22096,6 +26980,12 @@ Please close all running instances of your application before starting a build.<
<translation>ファイルãŒä»–ã®ãƒ—ロセスã§ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã“ã®ãƒ—ロセスã‹ã‚‰ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。
ビルドを開始ã™ã‚‹å‰ã«ã™ã¹ã¦ã®å®Ÿè¡Œä¸­ã®ã‚¢ãƒ—リケーションを閉ã˜ã¦ãã ã•ã„。</translation>
</message>
+ <message>
+ <source>The process cannot access the file because it is being used by another process.
+Please close all running instances of your application before starting a build.</source>
+ <translation>ファイルãŒä»–ã®ãƒ—ロセスã§ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã“ã®ãƒ—ロセスã‹ã‚‰ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。
+ビルドを開始ã™ã‚‹å‰ã«ã™ã¹ã¦ã®å®Ÿè¡Œä¸­ã®ã‚¢ãƒ—リケーションを閉ã˜ã¦ãã ã•ã„。</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::ProjectFileFactory</name>
@@ -22190,6 +27080,14 @@ Please close all running instances of your application before starting a build.<
<translation>ファイルを開ã</translation>
</message>
<message>
+ <source>Build Environment</source>
+ <translation>ビルド時ã®ç’°å¢ƒå¤‰æ•°</translation>
+ </message>
+ <message>
+ <source>Run Environment</source>
+ <translation>実行時ã®ç’°å¢ƒå¤‰æ•°</translation>
+ </message>
+ <message>
<source>Recent P&amp;rojects</source>
<translation>最近使ã£ãŸãƒ—ロジェクト(&amp;R)</translation>
</message>
@@ -22242,6 +27140,14 @@ Please close all running instances of your application before starting a build.<
<translation>Ctrl+B</translation>
</message>
<message>
+ <source>Build for &amp;Run Configuration</source>
+ <translation>実行構æˆã®ãƒ“ルド(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Build for &amp;Run Configuration &quot;%1&quot;</source>
+ <translation>実行構æˆã®ãƒ“ルド(&amp;R) &quot;%1&quot;</translation>
+ </message>
+ <message>
<source>Deploy Project</source>
<translation>プロジェクトをデプロイ</translation>
</message>
@@ -22420,7 +27326,7 @@ Please close all running instances of your application before starting a build.<
</message>
<message>
<source>The kit &quot;%1&quot; for the project &quot;%2&quot; has no active run configuration.</source>
- <translation>プロジェクト &quot;%2&quot; 用ã®ã‚­ãƒƒãƒˆ &quot;%1&quot; ã«ã¯ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªå®Ÿè¡Œè¨­å®šãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ <translation>プロジェクト &quot;%2&quot; 用ã®ã‚­ãƒƒãƒˆ &quot;%1&quot; ã«ã¯ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªå®Ÿè¡Œæ§‹æˆãŒã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
<source>Cannot run &quot;%1&quot;.</source>
@@ -22471,10 +27377,154 @@ Please close all running instances of your application before starting a build.<
<translation>ビルドを中止ã—ã¦ãƒ—ロジェクトを解放</translation>
</message>
<message>
+ <source>C</source>
+ <translation>C</translation>
+ </message>
+ <message>
+ <source>C++</source>
+ <translation>C++</translation>
+ </message>
+ <message>
+ <source>Open...</source>
+ <translation>é–‹ã...</translation>
+ </message>
+ <message>
+ <source>&amp;Manage...</source>
+ <translation>管ç†(&amp;M)...</translation>
+ </message>
+ <message>
+ <source>Close Pro&amp;ject &quot;%1&quot;</source>
+ <translation>プロジェクト &quot;%1&quot; ã‚’é–‰ã˜ã‚‹(&amp;J)</translation>
+ </message>
+ <message>
+ <source>Close All Files in Project</source>
+ <translation>プロジェクト内ã®ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close All Files in Project &quot;%1&quot;</source>
+ <translation>プロジェクト &quot;%1&quot; 内ã®ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close Pro&amp;ject</source>
+ <translation>プロジェクトを閉ã˜ã‚‹(&amp;J)</translation>
+ </message>
+ <message>
+ <source>Build All Projects</source>
+ <translation>ã™ã¹ã¦ã®ãƒ—ロジェクトをビルド</translation>
+ </message>
+ <message>
+ <source>Build All Projects for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ã™ã¹ã¦ã®ãƒ—ロジェクトをビルド</translation>
+ </message>
+ <message>
+ <source>Deploy All Projects</source>
+ <translation>ã™ã¹ã¦ã®ãƒ—ロジェクトをデプロイ</translation>
+ </message>
+ <message>
+ <source>Rebuild All Projects</source>
+ <translation>ã™ã¹ã¦ã®ãƒ—ロジェクトをリビルド</translation>
+ </message>
+ <message>
+ <source>Rebuild All Projects for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ã™ã¹ã¦ã®ãƒ—ロジェクトをリビルド</translation>
+ </message>
+ <message>
+ <source>Clean All Projects</source>
+ <translation>ã™ã¹ã¦ã®ãƒ—ロジェクトをクリーン</translation>
+ </message>
+ <message>
+ <source>Clean All Projects for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ã™ã¹ã¦ã®ãƒ—ロジェクトをクリーン</translation>
+ </message>
+ <message>
+ <source>Build Project for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ãƒ—ロジェクトをビルド</translation>
+ </message>
+ <message>
+ <source>Build Project &quot;%1&quot; for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ãƒ—ロジェクト&quot;%1&quot;をビルド</translation>
+ </message>
+ <message>
+ <source>Rebuild Project for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ãƒ—ロジェクトをリビルド</translation>
+ </message>
+ <message>
+ <source>Rebuild Project &quot;%1&quot; for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ãƒ—ロジェクト&quot;%1&quot;をリビルド</translation>
+ </message>
+ <message>
+ <source>Clean Project for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ãƒ—ロジェクトをクリーン</translation>
+ </message>
+ <message>
+ <source>Clean Project &quot;%1&quot; for All Configurations</source>
+ <translation>ã™ã¹ã¦ã®æ§‹æˆã§ãƒ—ロジェクト &quot;%1 をクリーン</translation>
+ </message>
+ <message>
+ <source>Meta+Backspace</source>
+ <translation>Meta+Backspace</translation>
+ </message>
+ <message>
+ <source>Alt+Backspace</source>
+ <translation>Alt+Backspace</translation>
+ </message>
+ <message>
+ <source>Add Existing Projects...</source>
+ <translation>既存ã®ãƒ—ロジェクトを追加ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Close All Files</source>
+ <translation>ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Properties...</source>
+ <translation>プロパティ...</translation>
+ </message>
+ <message>
+ <source>Expand</source>
+ <translation>展開</translation>
+ </message>
+ <message>
+ <source>Expand All</source>
+ <translation>ã™ã¹ã¦å±•é–‹</translation>
+ </message>
+ <message>
<source>Current project&apos;s main file.</source>
<translation>ç¾åœ¨ã®ãƒ—ロジェクトã®ãƒ¡ã‚¤ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Main file of the project the current document belongs to.</source>
+ <translation>ç¾åœ¨ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆãŒå±žã—ã¦ã„るプロジェクトã®ãƒ¡ã‚¤ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã€‚</translation>
+ </message>
+ <message>
+ <source>The name of the project the current document belongs to.</source>
+ <translation>ç¾åœ¨ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆãŒå±žã—ã¦ã„るプロジェクトã®åå‰ã€‚</translation>
+ </message>
+ <message>
+ <source>Current Build Environment</source>
+ <translation>ç¾åœ¨ã®ãƒ“ルド時ã®ç’°å¢ƒå¤‰æ•°</translation>
+ </message>
+ <message>
+ <source>The name of the active project.</source>
+ <translation>有効ãªãƒ—ロジェクトã®åå‰ã€‚</translation>
+ </message>
+ <message>
+ <source>Active project&apos;s main file.</source>
+ <translation>有効ãªãƒ—ロジェクトã®ãƒ¡ã‚¤ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The type of the active project&apos;s active build configuration.</source>
+ <translation>有効ãªãƒ—ロジェクトã®æœ‰åŠ¹ãªãƒ“ルド構æˆã®åž‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Full build path of the active project&apos;s active build configuration.</source>
+ <translation>有効ãªãƒ—ロジェクトã®æœ‰åŠ¹ãªãƒ“ルド設定ã®ãƒ“ルドパスã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Active build environment of the active project.</source>
+ <translation>有効ãªãƒ—ロジェクトã®æœ‰åŠ¹ãªãƒ“ルド環境。</translation>
+ </message>
+ <message>
<source>Do Not Unload</source>
<translation>解放ã—ãªã„</translation>
</message>
@@ -22491,6 +27541,44 @@ Please close all running instances of your application before starting a build.<
<translation>強制的ã«ãƒ“ルドプロセスを中止ã—ã¦ãƒ—ロジェクトを解放ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
+ <source>Close %1?</source>
+ <translation>%1ã‚’é–‰ã˜ã¾ã™ã‹?</translation>
+ </message>
+ <message>
+ <source>Do you want to cancel the build process and close %1 anyway?</source>
+ <translation>強制的ã«ãƒ“ルドプロセスを中止ã—㦠%1 ã‚’é–‰ã˜ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>%1 in %2</source>
+ <translation>%2 ã® %1</translation>
+ </message>
+ <message>
+ <source>File &quot;%1&quot; was not removed, because the project has changed in the meantime.
+Please try again.</source>
+ <translation>途中ã§ãƒ—ロジェクトãŒå¤‰æ›´ã•ã‚ŒãŸãŸã‚ã€ãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; ã¯å‰Šé™¤ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚
+ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Could not remove file &quot;%1&quot; from project &quot;%2&quot;.</source>
+ <translation>プロジェクト &quot;%2&quot;ã‹ã‚‰ãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot;を削除ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Choose File Name</source>
+ <translation>ファイルåã‚’é¸æŠžã—ã¦ãã ã•ã„</translation>
+ </message>
+ <message>
+ <source>New file name:</source>
+ <translation>æ–°ã—ã„ファイルåã§ã™:</translation>
+ </message>
+ <message>
+ <source>Failed to copy file &quot;%1&quot; to &quot;%2&quot;: %3.</source>
+ <translation>ファイル &quot;%1&quot; ã‚’ &quot;%2&quot; ã«ã‚³ãƒ”ーã™ã‚‹ã“ã¨ã«å¤±æ•—ã—ã¾ã—ãŸ: %3.</translation>
+ </message>
+ <message>
+ <source>Failed to add new file &quot;%1&quot; to the project.</source>
+ <translation>プロジェクトã¸ã®æ–°è¦ãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; ã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>The username with which to log into the device in the currently active kit.</source>
<translation>ç¾åœ¨æœ‰åŠ¹ãªã‚­ãƒƒãƒˆã®ãƒ‡ãƒã‚¤ã‚¹ã«ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹éš›ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã§ã™ã€‚</translation>
</message>
@@ -22503,6 +27591,10 @@ Please close all running instances of your application before starting a build.<
<translation>ã™ã¹ã¦ã®ãƒ—ロジェクト</translation>
</message>
<message>
+ <source>Parse Build Output...</source>
+ <translation>ビルドã®å‡ºåŠ›ã‚’解æžã™ã‚‹...</translation>
+ </message>
+ <message>
<source>New Project</source>
<comment>Title of dialog</comment>
<translation>æ–°ã—ã„プロジェクト</translation>
@@ -22516,6 +27608,10 @@ Please close all running instances of your application before starting a build.<
<translation>&lt;h3&gt;プロジェクトã¯æ—¢ã«é–‹ã‹ã‚Œã¦ã„ã¾ã™&lt;/h3&gt;</translation>
</message>
<message>
+ <source>Failed opening project &quot;%1&quot;: Project is not a file.</source>
+ <translation>プロジェクト &quot;%1&quot; ãŒé–‹ã‘ã¾ã›ã‚“: プロジェクトãŒãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Failed opening project &quot;%1&quot;: No plugin can open project type &quot;%2&quot;.</source>
<translation>プロジェクト &quot;%1&quot; ãŒé–‹ã‘ã¾ã›ã‚“: 種類㌠&quot;%2&quot; ã§ã‚るプロジェクトã«å¯¾å¿œã—ãŸãƒ—ラグインãŒã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
@@ -22539,7 +27635,7 @@ Do you want to ignore them?</source>
</message>
<message>
<source>Run Configuration Removed</source>
- <translation>実行設定ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ</translation>
+ <translation>実行構æˆãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ</translation>
</message>
<message>
<source>The configuration that was supposed to run is no longer available.</source>
@@ -22615,6 +27711,10 @@ Do you want to ignore them?</source>
<translation>ã¾ã ãƒ“ルドを実行ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>A run action is already scheduled for the active project.</source>
+ <translation>有効ãªãƒ—ロジェクトã«ã¯ã€ã™ã§ã«å®Ÿè¡Œã‚¢ã‚¯ã‚·ãƒ§ãƒ³ãŒäºˆå®šã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Run %1</source>
<translation>%1 を実行</translation>
</message>
@@ -22629,6 +27729,18 @@ Do you want to ignore them?</source>
<translation>æ–°ã—ã„サブプロジェクト</translation>
</message>
<message>
+ <source>Choose Project File</source>
+ <translation>プロジェクトファイルをé¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>The following subprojects could not be added to project &quot;%1&quot;:</source>
+ <translation>次ã®ã‚µãƒ–プロジェクトをプロジェクト &quot;%1&quot; ã«è¿½åŠ ã§ãã¾ã›ã‚“ã§ã—ãŸ:</translation>
+ </message>
+ <message>
+ <source>Adding Subproject Failed</source>
+ <translation>サブプロジェクトã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
<source>Add Existing Files</source>
<translation>既存ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’追加</translation>
</message>
@@ -22641,6 +27753,16 @@ Do you want to ignore them?</source>
<translation>プロジェクトã¸ã®ãƒ•ã‚¡ã‚¤ãƒ«è¿½åŠ ã«å¤±æ•—</translation>
</message>
<message>
+ <source>Remove More Files?</source>
+ <translation>ä»–ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Remove these files as well?
+ %1</source>
+ <translation>ã“れらã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚‚削除ã—ã¾ã™ã‹ï¼Ÿ
+...%1</translation>
+ </message>
+ <message>
<source>Removing File Failed</source>
<translation>ファイル削除ã«å¤±æ•—</translation>
</message>
@@ -22696,7 +27818,7 @@ Rename %2 to %3 anyway?</source>
</message>
<message>
<source>The file %1 was renamed to %2, but the project file %3 could not be automatically changed.</source>
- <translation>ファイル %1 ㌠%2 ã«ãƒªãƒãƒ¼ãƒ ã•ã‚Œã¾ã—ãŸãŒã€ãƒ—ロジェクトファイル %3 ã§ã€è‡ªå‹•çš„ã«å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ <translation>ファイル %1 ㌠%2 ã«åå‰å¤‰æ›´ã•ã‚Œã¾ã—ãŸãŒã€ãƒ—ロジェクトファイル %3 ã§ã€è‡ªå‹•çš„ã«å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
</message>
</context>
<context>
@@ -22735,6 +27857,26 @@ to project &quot;%2&quot;.</source>
<source>%1 - temporary</source>
<translation>%1 - テンãƒãƒ©ãƒª</translation>
</message>
+ <message>
+ <source>No Build Found</source>
+ <translation>ビルドãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>No build found in %1 matching project %2.</source>
+ <translation>%1 ã«ãƒ—ロジェクト %2 ã®ãƒ“ルドãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Import Warning</source>
+ <translation>インãƒãƒ¼ãƒˆã«é–¢ã™ã‚‹è­¦å‘Š</translation>
+ </message>
+ <message>
+ <source>Import Build</source>
+ <translation>ビルドをインãƒãƒ¼ãƒˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Imported Kit</source>
+ <translation>インãƒãƒ¼ãƒˆã•ã‚ŒãŸã‚­ãƒƒãƒˆ</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::ProjectTreeWidget</name>
@@ -22747,6 +27889,26 @@ to project &quot;%2&quot;.</source>
<translation>生æˆã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’éžè¡¨ç¤º</translation>
</message>
<message>
+ <source>Hide Disabled Files</source>
+ <translation>無効化ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’éžè¡¨ç¤º</translation>
+ </message>
+ <message>
+ <source>Focus Document in Project Tree</source>
+ <translation>プロジェクトツリー内ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã«ãƒ•ã‚©ãƒ¼ã‚«ã‚¹ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Meta+Shift+L</source>
+ <translation>Meta+Shift+L</translation>
+ </message>
+ <message>
+ <source>Alt+Shift+L</source>
+ <translation>Alt+Shift+L</translation>
+ </message>
+ <message>
+ <source>Hide Empty Directories</source>
+ <translation>空ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’éžè¡¨ç¤ºã«ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Synchronize with Editor</source>
<translation>エディタã¨åŒæœŸ</translation>
</message>
@@ -22776,6 +27938,46 @@ to project &quot;%2&quot;.</source>
<source>New session name</source>
<translation>æ–°ã—ã„セッションã®åå‰</translation>
</message>
+ <message>
+ <source>Session</source>
+ <translation>セッション</translation>
+ </message>
+ <message>
+ <source>Last Modified</source>
+ <translation>最終変更日</translation>
+ </message>
+ <message>
+ <source>New Session Name</source>
+ <translation>æ–°ã—ã„セッションå</translation>
+ </message>
+ <message>
+ <source>&amp;Create</source>
+ <translation>作æˆ(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Create and &amp;Open</source>
+ <translation>作æˆã—ã¦é–‹ã(&amp;O)</translation>
+ </message>
+ <message>
+ <source>&amp;Clone</source>
+ <translation>複製(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Clone and &amp;Open</source>
+ <translation>クローンã—ã¦é–‹ã(&amp;O)</translation>
+ </message>
+ <message>
+ <source>Rename Session</source>
+ <translation>セッションã®åå‰å¤‰æ›´</translation>
+ </message>
+ <message>
+ <source>&amp;Rename</source>
+ <translation>åå‰ã‚’変更(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Rename and &amp;Open</source>
+ <translation>åå‰å¤‰æ›´ã—ã¦é–‹ã(&amp;O)</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::ProjectWelcomePage</name>
@@ -22784,6 +27986,88 @@ to project &quot;%2&quot;.</source>
<translation>æ–°ã—ã„プロジェクト</translation>
</message>
<message>
+ <source>Open Session #%1</source>
+ <translation>セッション #%1 ã‚’é–‹ã</translation>
+ </message>
+ <message>
+ <source>Ctrl+Meta+%1</source>
+ <translation>Ctrl+Meta+%1</translation>
+ </message>
+ <message>
+ <source>Ctrl+Alt+%1</source>
+ <translation>Ctrl+Alt+%1</translation>
+ </message>
+ <message>
+ <source>Open Recent Project #%1</source>
+ <translation>最近ã®ãƒ—ロジェクト #%1 ã‚’é–‹ã</translation>
+ </message>
+ <message>
+ <source>Ctrl+Shift+%1</source>
+ <translation>Ctrl+Shift+%1</translation>
+ </message>
+ <message>
+ <source>Open %1 &quot;%2&quot;</source>
+ <translation>%1 &quot;%2&quot; ã‚’é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open %1 &quot;%2&quot; (%3)</source>
+ <translation>%1 &quot;%2&quot; (%3)ã‚’é–‹ã</translation>
+ </message>
+ <message>
+ <source>session</source>
+ <comment>Appears in &quot;Open session &lt;name&gt;&quot;</comment>
+ <translation>セッション</translation>
+ </message>
+ <message>
+ <source>%1 (last session)</source>
+ <translation>%1 (最後ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³)</translation>
+ </message>
+ <message>
+ <source>%1 (current session)</source>
+ <translation>%1 (ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³)</translation>
+ </message>
+ <message>
+ <source>Clone</source>
+ <translation>複製</translation>
+ </message>
+ <message>
+ <source>Rename</source>
+ <translation>åå‰ã‚’変更</translation>
+ </message>
+ <message>
+ <source>Delete</source>
+ <translation>削除</translation>
+ </message>
+ <message>
+ <source>project</source>
+ <comment>Appears in &quot;Open project &lt;name&gt;&quot;</comment>
+ <translation>プロジェクト</translation>
+ </message>
+ <message>
+ <source>Remove Project from Recent Projects</source>
+ <translation>最近ã®ãƒ—ロジェクトã‹ã‚‰ãƒ—ロジェクトを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Clear Recent Project List</source>
+ <translation>最近ã®ãƒ—ロジェクトリストを消去ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Manage</source>
+ <translation>管ç†</translation>
+ </message>
+ <message>
+ <source>New</source>
+ <translation>æ–°è¦ä½œæˆ</translation>
+ </message>
+ <message>
+ <source>Open</source>
+ <translation>é–‹ã</translation>
+ </message>
+ <message>
+ <source>Sessions</source>
+ <translation>セッション</translation>
+ </message>
+ <message>
<source>Projects</source>
<translation>プロジェクト</translation>
</message>
@@ -22854,6 +28138,10 @@ to project &quot;%2&quot;.</source>
<translation>無効</translation>
</message>
<message>
+ <source>Unexpected run control state %1 when worker %2 started.</source>
+ <translation>ワーカー %2 ãŒèµ·å‹•ã—ãŸã¨ãã®äºˆæœŸã—ãªã„実行制御状態 %1。</translation>
+ </message>
+ <message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;center&gt;&lt;i&gt;%1&lt;/i&gt; is still running.&lt;center/&gt;&lt;center&gt;Force it to quit?&lt;/center&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;center&gt;&lt;i&gt;%1&lt;/i&gt; ã¯ã€ã¾ã å®Ÿè¡Œä¸­ã§ã™ã€‚&lt;center/&gt;&lt;center&gt;強制終了ã—ã¾ã™ã‹ï¼Ÿ&lt;/center&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
@@ -22862,6 +28150,22 @@ to project &quot;%2&quot;.</source>
<translation>アプリケーションã¯ã¾ã å®Ÿè¡Œä¸­ã§ã™</translation>
</message>
<message>
+ <source>Force &amp;Quit</source>
+ <translation>強制終了(&amp;Q)</translation>
+ </message>
+ <message>
+ <source>&amp;Keep Running</source>
+ <translation>ãã®ã¾ã¾ã«ã™ã‚‹(&amp;K)</translation>
+ </message>
+ <message>
+ <source>Starting %1 %2...</source>
+ <translation>起動中 %1 %2...</translation>
+ </message>
+ <message>
+ <source>No executable specified.</source>
+ <translation>実行ファイルãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Force Quit</source>
<translation>強制終了</translation>
</message>
@@ -22877,6 +28181,25 @@ to project &quot;%2&quot;.</source>
<translation>実行時ã®è¨­å®š</translation>
</message>
<message>
+ <source>No build system active</source>
+ <translation>アクティブãªãƒ“ルドシステムãŒã‚ã‚Šã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Run on %{Device:Name}</source>
+ <extracomment>Shown in Run configuration if no executable is given, %1 is device name</extracomment>
+ <translation>%{Device:Name}ã§å®Ÿè¡Œ</translation>
+ </message>
+ <message>
+ <source>%1 (on %{Device:Name})</source>
+ <extracomment>Shown in Run configuration, Add menu: &quot;name of runnable (on device name)&quot;</extracomment>
+ <translation>%1 (%{Device:Name}上)</translation>
+ </message>
+ <message>
+ <source>Run on %1</source>
+ <extracomment>Shown in Run configuration if no executable is given, %1 is device name</extracomment>
+ <translation type="vanished">%1 ã§å®Ÿè¡Œ</translation>
+ </message>
+ <message>
<source>Unknown error.</source>
<translation>ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ã§ã™ã€‚</translation>
</message>
@@ -22900,6 +28223,14 @@ to project &quot;%2&quot;.</source>
<translation>åå‰ã‚’変更...</translation>
</message>
<message>
+ <source>Add...</source>
+ <translation>追加...</translation>
+ </message>
+ <message>
+ <source>Clone...</source>
+ <translation>複製...</translation>
+ </message>
+ <message>
<source>Deployment</source>
<translation>デプロイ</translation>
</message>
@@ -22913,7 +28244,7 @@ to project &quot;%2&quot;.</source>
</message>
<message>
<source>Run configuration:</source>
- <translation>実行設定:</translation>
+ <translation>実行構æˆ:</translation>
</message>
<message>
<source>&amp;Clone Selected</source>
@@ -22930,15 +28261,15 @@ to project &quot;%2&quot;.</source>
</message>
<message>
<source>Remove Run Configuration?</source>
- <translation>実行設定を削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ <translation>実行構æˆã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
<source>Do you really want to delete the run configuration &lt;b&gt;%1&lt;/b&gt;?</source>
- <translation>本当ã«å®Ÿè¡Œè¨­å®š &lt;b&gt;%1&lt;/b&gt; を削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ <translation>本当ã«å®Ÿè¡Œæ§‹æˆ &lt;b&gt;%1&lt;/b&gt; を削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
<source>New name for run configuration &lt;b&gt;%1&lt;/b&gt;:</source>
- <translation>実行設定 &lt;b&gt;%1&lt;/b&gt; ã®æ–°ã—ã„åå‰:</translation>
+ <translation>å®Ÿè¡Œæ§‹æˆ &lt;b&gt;%1&lt;/b&gt; ã®æ–°ã—ã„åå‰:</translation>
</message>
<message>
<source>Cancel Build &amp;&amp; Remove Deploy Configuration</source>
@@ -22980,6 +28311,10 @@ to project &quot;%2&quot;.</source>
<translation>セッションã®ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼</translation>
</message>
<message>
+ <source>Could not save session %1</source>
+ <translation>セッション %1 ã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
+ </message>
+ <message>
<source>Could not save session to file %1</source>
<translation>セッション %1 ã‚’ä¿å­˜ã§ãã¾ã›ã‚“</translation>
</message>
@@ -22992,10 +28327,20 @@ to project &quot;%2&quot;.</source>
<translation>セッションを削除</translation>
</message>
<message>
+ <source>Delete Sessions</source>
+ <translation>セッションを削除</translation>
+ </message>
+ <message>
<source>Delete session %1?</source>
<translation>セッション %1 を削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
+ <source>Delete these sessions?
+ %1</source>
+ <translation>ã“れらã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ
+ %1</translation>
+ </message>
+ <message>
<source>Failed to restore project files</source>
<translation>プロジェクトファイルã®å¾©å…ƒå¤±æ•—</translation>
</message>
@@ -23205,10 +28550,22 @@ to project &quot;%2&quot;.</source>
<translation>&lt;a href=&quot;buildandrun&quot;&gt;オプション&lt;/a&gt; ã‚ã‚‹ã„㯠SDK ã®ãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹ãƒ„ールã§ã‚­ãƒƒãƒˆã‚’追加ã—ã¦ãã ã•ã„。</translation>
</message>
<message>
+ <source>No suitable kits found.</source>
+ <translation>é©åˆ‡ãªã‚­ãƒƒãƒˆãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Add a kit in the &lt;a href=&quot;buildandrun&quot;&gt;options&lt;/a&gt; or via the maintenance tool of the SDK.</source>
+ <translation>&lt;a href=&quot;buildandrun&quot;&gt;options&lt;/a&gt; ã¾ãŸã¯ SDK ã®ãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹ãƒ„ールã§ã‚­ãƒƒãƒˆã‚’追加ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Select all kits</source>
<translation>ã™ã¹ã¦ã®ã‚­ãƒƒãƒˆã‚’é¸æŠž</translation>
</message>
<message>
+ <source>Type to filter kits by name...</source>
+ <translation>キットをåå‰ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã™ã‚‹ã«ã¯ã€ã‚¿ã‚¤ãƒ—ã—ã¦ãã ã•ã„...</translation>
+ </message>
+ <message>
<source>Select Kits for Your Project</source>
<translation>プロジェクトã®ã‚­ãƒƒãƒˆã‚’é¸æŠž</translation>
</message>
@@ -23221,6 +28578,11 @@ to project &quot;%2&quot;.</source>
<translation>キット</translation>
</message>
<message>
+ <source>The following kits can be used for project &lt;b&gt;%1&lt;/b&gt;:</source>
+ <comment>%1: Project name</comment>
+ <translation>以下ã®ã‚­ãƒƒãƒˆã¯ã€ãƒ—ロジェクト&lt;b&gt;%1&lt;/b&gt;ã«ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™:</translation>
+ </message>
+ <message>
<source>Qt Creator can use the following kits for project &lt;b&gt;%1&lt;/b&gt;:</source>
<comment>%1: Project name</comment>
<translation>Qt Creator ã¯ä»¥ä¸‹ã®ã‚­ãƒƒãƒˆã‚’プロジェクト &lt;b&gt;%1&lt;/b&gt; ã§ä½¿ç”¨ã§ãã¾ã™:</translation>
@@ -23286,6 +28648,10 @@ to project &quot;%2&quot;.</source>
<translation>追加</translation>
</message>
<message>
+ <source>This toolchain is invalid.</source>
+ <translation>ã“ã®ãƒ„ールãƒã‚§ãƒ¼ãƒ³ã¯ç„¡åŠ¹ã§ã™ã€‚</translation>
+ </message>
+ <message>
<source>&lt;nobr&gt;&lt;b&gt;ABI:&lt;/b&gt; %1</source>
<translation>&lt;nobr&gt;&lt;b&gt;ABI:&lt;/b&gt; %1</translation>
</message>
@@ -23294,6 +28660,22 @@ to project &quot;%2&quot;.</source>
<translation>最新ã§ã¯ãªã„</translation>
</message>
<message>
+ <source>Toolchain Auto-detection Settings</source>
+ <translation>ツールãƒã‚§ãƒ¼ãƒ³ã®è‡ªå‹•æ¤œå‡ºè¨­å®š</translation>
+ </message>
+ <message>
+ <source>Detect x86_64 GCC compilers as x86_64 and x86</source>
+ <translation>x86_64 GCC コンパイラを x86_64 ãŠã‚ˆã³ x86 ã¨ã—ã¦æ¤œå‡ºã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>If checked, %1 will set up two instances of each x86_64 compiler:
+One for the native x86_64 target, and one for a plain x86 target.
+Enable this if you plan to create 32-bit x86 binaries without using a dedicated cross compiler.</source>
+ <translation>ã“れをãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨ã€%1 ã¯å„ x86_64 コンパイラ㮠2 ã¤ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’セットアップã—ã¾ã™ã€‚
+1 ã¤ã¯ãƒã‚¤ãƒ†ã‚£ãƒ–ã® x86_64 ターゲット用ã§ã€ã‚‚ㆠ1 ã¤ã¯ãƒ—レーン㮠x86 ターゲット用ã§ã™ã€‚
+専用ã®ã‚¯ãƒ­ã‚¹ãƒ»ã‚³ãƒ³ãƒ‘イラを使用ã›ãšã« 32 ビット x86 ãƒã‚¤ãƒŠãƒªã‚’作æˆã™ã‚‹å ´åˆã¯ã€ã“ã®æ©Ÿèƒ½ã‚’有効ã«ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>Name</source>
<translation>åå‰</translation>
</message>
@@ -23318,6 +28700,18 @@ to project &quot;%2&quot;.</source>
<translation>削除</translation>
</message>
<message>
+ <source>Remove All</source>
+ <translation>ã™ã¹ã¦å‰Šé™¤</translation>
+ </message>
+ <message>
+ <source>Re-detect</source>
+ <translation>å†æ¤œå‡º</translation>
+ </message>
+ <message>
+ <source>Auto-detection Settings...</source>
+ <translation>自動検出設定...</translation>
+ </message>
+ <message>
<source>Duplicate Compilers Detected</source>
<translation>é‡è¤‡ã—ãŸã‚³ãƒ³ãƒ‘イラã®æ¤œå‡º</translation>
</message>
@@ -23396,6 +28790,26 @@ to project &quot;%2&quot;.</source>
<source>Parsing of Qbs project has failed.</source>
<translation>Qbs プロジェクトã®è§£æžã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
</message>
+ <message>
+ <source>Configuration name:</source>
+ <translation>設定å:</translation>
+ </message>
+ <message>
+ <source>The qbs project build root</source>
+ <translation>qbs プロジェクトã®ãƒ“ルドルート</translation>
+ </message>
+ <message>
+ <source>Debug</source>
+ <comment>Shadow build directory suffix</comment>
+ <extracomment>Non-ASCII characters in directory suffix may cause build issues.</extracomment>
+ <translation>デãƒãƒƒã‚°</translation>
+ </message>
+ <message>
+ <source>Release</source>
+ <comment>Shadow build directory suffix</comment>
+ <extracomment>Non-ASCII characters in directory suffix may cause build issues.</extracomment>
+ <translation>リリース</translation>
+ </message>
</context>
<context>
<name>QbsProjectManager::Internal::QbsBuildConfigurationFactory</name>
@@ -23439,6 +28853,70 @@ to project &quot;%2&quot;.</source>
<source>Qbs Build</source>
<translation>Qbs ビルド</translation>
</message>
+ <message>
+ <source>&lt;b&gt;Qbs:&lt;/b&gt; %1</source>
+ <translation>&lt;b&gt;Qbs:&lt;/b&gt; %1</translation>
+ </message>
+ <message>
+ <source>Build variant:</source>
+ <translation>ビルド種類:</translation>
+ </message>
+ <message>
+ <source>Debug</source>
+ <translation>デãƒãƒƒã‚°</translation>
+ </message>
+ <message>
+ <source>Release</source>
+ <translation>リリース</translation>
+ </message>
+ <message>
+ <source>ABIs:</source>
+ <translation>ABI:</translation>
+ </message>
+ <message>
+ <source>Keep going when errors occur (if at all possible).</source>
+ <translation>エラーãŒç™ºç”Ÿã—ãŸå ´åˆã§ã‚‚(å¯èƒ½ãªé™ã‚Š)ビルドを継続ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Keep going</source>
+ <translation>継続ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Parallel jobs:</source>
+ <translation>並列ジョブ数:</translation>
+ </message>
+ <message>
+ <source>Number of concurrent build jobs.</source>
+ <translation>並列ビルド時ã®ã‚¸ãƒ§ãƒ–æ•°ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Show command lines</source>
+ <translation>コマンドラインを表示ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Install</source>
+ <translation>インストールã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Clean install root</source>
+ <translation>インストールルートã®ã‚¯ãƒªã‚¢</translation>
+ </message>
+ <message>
+ <source>Force probes</source>
+ <translation>プローブを強制ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Equivalent command line:</source>
+ <translation>等価ãªã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³:</translation>
+ </message>
+ <message>
+ <source>No qbs session exists for this target.</source>
+ <translation>ã“ã®ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã«ã¯ qbs セッションãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Build canceled: Qbs session failed.</source>
+ <translation>ビルドãŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã¾ã—ãŸã€‚Qbs ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
</context>
<context>
<name>QbsProjectManager::Internal::QbsBuildStepFactory</name>
@@ -23453,6 +28931,30 @@ to project &quot;%2&quot;.</source>
<source>Qbs Clean</source>
<translation>Qbs クリーン</translation>
</message>
+ <message>
+ <source>Dry run:</source>
+ <translation>実行ã—ãªã„:</translation>
+ </message>
+ <message>
+ <source>Keep going:</source>
+ <translation>継続ã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>Equivalent command line:</source>
+ <translation>等価ãªã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³:</translation>
+ </message>
+ <message>
+ <source>&lt;b&gt;Qbs:&lt;/b&gt; %1</source>
+ <translation>&lt;b&gt;Qbs:&lt;/b&gt; %1</translation>
+ </message>
+ <message>
+ <source>No qbs session exists for this target.</source>
+ <translation>ã“ã®ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã«ã¯ qbs セッションãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Cleaning canceled: Qbs session failed.</source>
+ <translation>クリーニングãŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã¾ã—ãŸã€‚Qbs ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
</context>
<context>
<name>QbsProjectManager::Internal::QbsCleanStepFactory</name>
@@ -23474,6 +28976,38 @@ to project &quot;%2&quot;.</source>
<source>Qbs Install</source>
<translation>Qbs インストール</translation>
</message>
+ <message>
+ <source>&lt;b&gt;Qbs:&lt;/b&gt; %1</source>
+ <translation>&lt;b&gt;Qbs:&lt;/b&gt; %1</translation>
+ </message>
+ <message>
+ <source>Dry run</source>
+ <translation>実行ã—ãªã„</translation>
+ </message>
+ <message>
+ <source>Keep going</source>
+ <translation>継続ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove first</source>
+ <translation>ã¯ã˜ã‚ã«å‰Šé™¤ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Installing canceled: Qbs session failed.</source>
+ <translation>インストールãŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã¾ã—ãŸ: Qbs ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Equivalent command line:</source>
+ <translation>等価ãªã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³:</translation>
+ </message>
+ <message>
+ <source>Install root:</source>
+ <translation>インストールルート:</translation>
+ </message>
+ <message>
+ <source>Flags:</source>
+ <translation>フラグ:</translation>
+ </message>
</context>
<context>
<name>QbsProjectManager::Internal::QbsInstallStepFactory</name>
@@ -23543,6 +29077,30 @@ to project &quot;%2&quot;.</source>
<translation>Ctrl+Alt+Shift+B</translation>
</message>
<message>
+ <source>Clean</source>
+ <translation>クリーン</translation>
+ </message>
+ <message>
+ <source>Clean Product</source>
+ <translation>プロダクトをクリーン</translation>
+ </message>
+ <message>
+ <source>Clean Product &quot;%1&quot;</source>
+ <translation>プロダクト &quot;%1&quot;をクリーン</translation>
+ </message>
+ <message>
+ <source>Rebuild</source>
+ <translation>リビルド</translation>
+ </message>
+ <message>
+ <source>Rebuild Product</source>
+ <translation>プロダクトã®ãƒªãƒ“ルド</translation>
+ </message>
+ <message>
+ <source>Rebuild Product &quot;%1&quot;</source>
+ <translation>プロダクト&quot;%1&quot;ã®ãƒªãƒ“ルド</translation>
+ </message>
+ <message>
<source>Build Subproject</source>
<translation>サブプロジェクトをビルド</translation>
</message>
@@ -23871,6 +29429,35 @@ Neither the path to the library nor the path to its includes is added to the .pr
<context>
<name>QmakeProjectManager::QmakeBuildConfiguration</name>
<message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+ <message>
+ <source>This kit cannot build this project since it does not define a Qt version.</source>
+ <translation>ã“ã®ã‚­ãƒƒãƒˆã«ã¯ Qt ãŒå®šç¾©ã•ã‚Œã¦ã„ãªã„ãŸã‚ã€ã“ã®ãƒ—ロジェクトをビルドã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Error:</source>
+ <translation>エラー:</translation>
+ </message>
+ <message>
+ <source>Warning:</source>
+ <translation>警告:</translation>
+ </message>
+ <message>
+ <source>The build directory contains a build for a different project, which will be overwritten.</source>
+ <translation>ビルドディレクトリã«ã¯ã€åˆ¥ã®ãƒ—ロジェクト用ã®ãƒ“ルドãŒå«ã¾ã‚Œã¦ã„ã¾ã™ãŒã€ã“ã‚Œã¯ä¸Šæ›¸ãã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>%1 The build will be overwritten.</source>
+ <comment>%1 error message</comment>
+ <translation>%1 ビルドã¯ä¸Šæ›¸ãã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The build directory should be at the same level as the source directory.</source>
+ <translation>ビルドディレクトリã¯ã€ã‚½ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨åŒã˜ãƒ¬ãƒ™ãƒ«ã«ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Could not parse Makefile.</source>
<translation>Makefile を解æžã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
</message>
@@ -23891,6 +29478,24 @@ Neither the path to the library nor the path to its includes is added to the .pr
<translation>mkspec ãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚</translation>
</message>
<message>
+ <source>Release</source>
+ <comment>Shadow build directory suffix</comment>
+ <extracomment>Non-ASCII characters in directory suffix may cause build issues.</extracomment>
+ <translation>リリース</translation>
+ </message>
+ <message>
+ <source>Debug</source>
+ <comment>Shadow build directory suffix</comment>
+ <extracomment>Non-ASCII characters in directory suffix may cause build issues.</extracomment>
+ <translation>デãƒãƒƒã‚°</translation>
+ </message>
+ <message>
+ <source>Profile</source>
+ <comment>Shadow build directory suffix</comment>
+ <extracomment>Non-ASCII characters in directory suffix may cause build issues.</extracomment>
+ <translation>プロファイル</translation>
+ </message>
+ <message>
<source>Parsing the .pro file</source>
<translation>.pro ファイルã®è§£æžä¸­</translation>
</message>
@@ -24015,6 +29620,18 @@ Neither the path to the library nor the path to its includes is added to the .pr
<translation>キット㫠Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Qt version is invalid.</source>
+ <translation>Qt ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒç„¡åŠ¹ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>No C++ compiler set in kit.</source>
+ <translation>キット㫠C++ コンパイラãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Project is part of Qt sources that do not match the Qt defined in the kit.</source>
+ <translation>プロジェクトã¯ã€ã‚­ãƒƒãƒˆã§å®šç¾©ã•ã‚Œã¦ã„ã‚‹ Qt ã¨ã¯ä¸€è‡´ã—ãªã„ Qt ソースã®ä¸€éƒ¨ã§ã™ã€‚</translation>
+ </message>
+ <message>
<source>The .pro file &quot;%1&quot; does not exist.</source>
<translation>.pro ファイル &quot;%1&quot; ãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
</message>
@@ -24077,6 +29694,14 @@ Neither the path to the library nor the path to its includes is added to the .pr
<translation>サブプロジェクト &quot;%1&quot; をビルド</translation>
</message>
<message>
+ <source>Build &amp;Subproject</source>
+ <translation>サブプロジェクトをビルド(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Build &amp;Subproject &quot;%1&quot;</source>
+ <translation>サブプロジェクト &quot;%1&quot; をビルド(&amp;S)</translation>
+ </message>
+ <message>
<source>Rebuild Subproject</source>
<translation>サブプロジェクトをリビルド</translation>
</message>
@@ -24108,6 +29733,10 @@ Neither the path to the library nor the path to its includes is added to the .pr
<source>Add Library...</source>
<translation>ライブラリã®è¿½åŠ ...</translation>
</message>
+ <message>
+ <source>QMake</source>
+ <translation>QMake</translation>
+ </message>
</context>
<context>
<name>QmakeProjectManager::QMakeStep</name>
@@ -24117,6 +29746,42 @@ Neither the path to the library nor the path to its includes is added to the .pr
<translation>qmake</translation>
</message>
<message>
+ <source>qmake build configuration:</source>
+ <translation>qmake ビルド設定:</translation>
+ </message>
+ <message>
+ <source>Debug</source>
+ <translation>デãƒãƒƒã‚°</translation>
+ </message>
+ <message>
+ <source>Release</source>
+ <translation>リリース</translation>
+ </message>
+ <message>
+ <source>Additional arguments:</source>
+ <translation>追加ã®å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>Effective qmake call:</source>
+ <translation>実際㮠qmake コマンドライン:</translation>
+ </message>
+ <message>
+ <source>&lt;b&gt;qmake:&lt;/b&gt; No Qt version set. Cannot run qmake.</source>
+ <translation>&lt;b&gt;qmake:&lt;/b&gt; Qt ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。qmake を実行ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>&lt;b&gt;qmake:&lt;/b&gt; %1 %2</source>
+ <translation>&lt;b&gt;qmake:&lt;/b&gt; %1 %2</translation>
+ </message>
+ <message>
+ <source>No Qt version configured.</source>
+ <translation>Qt ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Could not determine which &quot;make&quot; command to run. Check the &quot;make&quot; step in the build configuration.</source>
+ <translation>ã©ã® &quot;make &quot;コマンドを実行ã™ã¹ãã‹åˆ¤æ–­ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ビルド構æˆã® &quot;make &quot;ステップを確èªã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
<source>Configuration unchanged, skipping qmake step.</source>
<translation>設定ãŒå¤‰æ›´ã•ã‚Œã¦ã„ãªã„為ã€qmake ステップをスキップã—ã¾ã™ã€‚</translation>
</message>
@@ -24128,6 +29793,26 @@ Neither the path to the library nor the path to its includes is added to the .pr
<source>&lt;no Make step found&gt;</source>
<translation>&lt;Make コマンドãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“&gt;</translation>
</message>
+ <message>
+ <source>ABIs:</source>
+ <translation>ABI:</translation>
+ </message>
+ <message>
+ <source>QML Debugging</source>
+ <translation>QML デãƒãƒƒã‚°</translation>
+ </message>
+ <message>
+ <source>Qt Quick Compiler</source>
+ <translation>Qt Quick Compiler</translation>
+ </message>
+ <message>
+ <source>Separate Debug Information</source>
+ <translation>デãƒãƒƒã‚°æƒ…報を分離ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>The option will only take effect if the project is recompiled. Do you want to recompile now?</source>
+ <translation>ã“ã®ã‚ªãƒ—ションã¯ãƒ—ロジェクトã®å†ã‚³ãƒ³ãƒ‘イル時ã«æœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚å†ã‚³ãƒ³ãƒ‘イルを行ã„ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
</context>
<context>
<name>QmakeProjectManager::QMakeStepConfigWidget</name>
@@ -24435,6 +30120,10 @@ Preselects a desktop Qt for building the application if available.</source>
<translation>é¸æŠž: %1</translation>
</message>
<message>
+ <source>Connect: %1</source>
+ <translation>接続ã™ã‚‹: %1</translation>
+ </message>
+ <message>
<source>Deselect: </source>
<translation>é¸æŠžè§£é™¤: </translation>
</message>
@@ -24507,6 +30196,70 @@ Preselects a desktop Qt for building the application if available.</source>
<translation>コンãƒãƒ¼ãƒãƒ³ãƒˆã¸ç§»å‹•</translation>
</message>
<message>
+ <source>Connect</source>
+ <translation>接続ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Select Effect</source>
+ <translation>エフェクトをé¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Arrange</source>
+ <translation>æ•´ãˆã‚‹</translation>
+ </message>
+ <message>
+ <source>Group</source>
+ <translation>グループ</translation>
+ </message>
+ <message>
+ <source>Flow</source>
+ <translation>フローレイアウト</translation>
+ </message>
+ <message>
+ <source>Flow Effects</source>
+ <translation>フローエフェクト</translation>
+ </message>
+ <message>
+ <source>Stacked Container</source>
+ <translation>スタックコンテナ</translation>
+ </message>
+ <message>
+ <source>Bring to Front</source>
+ <translation>最å‰é¢ã«ç§»å‹•ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Send to Back</source>
+ <translation>最背é¢ã«ç§»å‹•ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Bring Forward</source>
+ <translation>å‰é¢ã«ç§»å‹•ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Send Backward</source>
+ <translation>背é¢ã«ç§»å‹•ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Merge File With Template</source>
+ <translation>テンプレートã¨ãƒ•ã‚¡ã‚¤ãƒ«ã‚’マージã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Move Component into Separate File</source>
+ <translation>コンãƒãƒ¼ãƒãƒ³ãƒˆã‚’別ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ç§»å‹•ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Edit Annotation</source>
+ <translation>アノテーションを編集ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Open Signal Dialog</source>
+ <translation>シグナルダイアログを開ã</translation>
+ </message>
+ <message>
+ <source>Update 3D Asset</source>
+ <translation>3D アセットを更新ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Set Id</source>
<translation>id ã®ä»˜ä¸Ž</translation>
</message>
@@ -24515,6 +30268,10 @@ Preselects a desktop Qt for building the application if available.</source>
<translation>z プロパティã®ãƒªã‚»ãƒƒãƒˆ</translation>
</message>
<message>
+ <source>Reverse</source>
+ <translation>リãƒãƒ¼ã‚¹</translation>
+ </message>
+ <message>
<source>Fill</source>
<translation>Fill</translation>
</message>
@@ -24540,11 +30297,147 @@ Preselects a desktop Qt for building the application if available.</source>
</message>
<message>
<source>Remove Positioner</source>
- <translation>レイアウトã®å‰Šé™¤</translation>
+ <translation>レイアウトを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Create Flow Action</source>
+ <translation>フローアクションを作æˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Set Flow Start</source>
+ <translation>フロー開始を設定ã™ã‚‹</translation>
</message>
<message>
<source>Remove Layout</source>
- <translation>レイアウトã®å‰Šé™¤</translation>
+ <translation>レイアウトを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Group in GroupItem</source>
+ <translation>GroupItem 内ã®ã‚°ãƒ«ãƒ¼ãƒ—</translation>
+ </message>
+ <message>
+ <source>Remove GroupItem</source>
+ <translation>GroupItem を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add Component</source>
+ <translation>コンãƒãƒ¼ãƒãƒ³ãƒˆã®è¿½åŠ </translation>
+ </message>
+ <message>
+ <source>Raise selected component.</source>
+ <translation>é¸æŠžã•ã‚ŒãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’å‰é¢ã«ç§»å‹•ã€‚</translation>
+ </message>
+ <message>
+ <source>Lower selected component.</source>
+ <translation>é¸æŠžã•ã‚ŒãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’背é¢ã«ç§»å‹•ã€‚</translation>
+ </message>
+ <message>
+ <source>Fill selected component to parent.</source>
+ <translation>é¸æŠžã•ã‚ŒãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’親ã®ã‚µã‚¤ã‚ºã«åˆã‚ã›ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Reset anchors for selected component.</source>
+ <translation>é¸æŠžã—ãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã®ã‚¢ãƒ³ã‚«ãƒ¼ã‚’リセットã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Layout selected components in column layout.</source>
+ <translation>column layout 内ã«é¸æŠžã•ã‚ŒãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’レイアウトã«ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Layout selected components in row layout.</source>
+ <translation>row layout 内ã«é¸æŠžã•ã‚ŒãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’レイアウトã«ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Layout selected components in grid layout.</source>
+ <translation>grid layout 内ã«é¸æŠžã•ã‚ŒãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’レイアウトã«ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Add component to stacked container.</source>
+ <translation>スタックå¼ã‚³ãƒ³ãƒ†ãƒŠã«ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’追加ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Add Item</source>
+ <translation type="vanished">アイテムを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add Tab Bar</source>
+ <translation>タブãƒãƒ¼ã‚’追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Increase Index</source>
+ <translation>インデックスã®å¢—加</translation>
+ </message>
+ <message>
+ <source>Decrease Index</source>
+ <translation>インデックスã®æ¸›å°‘</translation>
+ </message>
+ <message>
+ <source>Layout in Column Layout</source>
+ <translation>Column Layout ã§ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Layout in Row Layout</source>
+ <translation>Row Layout ã§ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Layout in Grid Layout</source>
+ <translation>Grid Layout ã§ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Raise selected item.</source>
+ <translation type="vanished">é¸æŠžã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’上ã’る。</translation>
+ </message>
+ <message>
+ <source>Lower selected item.</source>
+ <translation type="vanished">é¸æŠžã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’下ã«ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Reset size and use implicit size.</source>
+ <translation>サイズをリセットã—ã¦ã€æš—é»™ã®ã‚µã‚¤ã‚ºã‚’使用ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Reset position and use implicit position.</source>
+ <translation>ä½ç½®ã‚’リセットã—ã¦ã€æš—é»™ã®ä½ç½®ã‚’使用ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Fill selected item to parent.</source>
+ <translation type="vanished">é¸æŠžã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’親ã«æµã—込む。</translation>
+ </message>
+ <message>
+ <source>Reset anchors for selected item.</source>
+ <translation type="vanished">é¸æŠžã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã®ã‚¢ãƒ³ã‚«ãƒ¼ã‚’リセットã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Layout selected items in column layout.</source>
+ <translation type="vanished">column layout内ã«é¸æŠžã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’レイアウトã«ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Layout selected items in row layout.</source>
+ <translation type="vanished">row layout内ã«é¸æŠžã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’レイアウトã«ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Layout selected items in grid layout.</source>
+ <translation type="vanished">grid layout内ã«é¸æŠžã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’レイアウトã«ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Increase index of stacked container.</source>
+ <translation>スタックå¼ã‚³ãƒ³ãƒ†ãƒŠã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’増やã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Decrease index of stacked container.</source>
+ <translation>スタックå¼ã‚³ãƒ³ãƒ†ãƒŠã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’減らã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Add item to stacked container.</source>
+ <translation type="vanished">スタックå¼ã‚³ãƒ³ãƒ†ãƒŠã«ã‚¢ã‚¤ãƒ†ãƒ ã‚’追加ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Add flow action.</source>
+ <translation>フローアクションを追加ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Edit List Model...</source>
+ <translation>リストモデルを編集ã™ã‚‹...</translation>
</message>
<message>
<source>Layout in ColumnLayout</source>
@@ -24574,6 +30467,26 @@ Preselects a desktop Qt for building the application if available.</source>
<source>Position</source>
<translation>ä½ç½®</translation>
</message>
+ <message>
+ <source>Timeline</source>
+ <translation>タイムライン</translation>
+ </message>
+ <message>
+ <source>Copy All Keyframes</source>
+ <translation>ã™ã¹ã¦ã®ã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ã‚’コピーã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Paste Keyframes</source>
+ <translation>キーフレームを貼り付ã‘ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add Keyframes at Current Frame</source>
+ <translation>ç¾åœ¨ã®ãƒ•ãƒ¬ãƒ¼ãƒ ã«ã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ã‚’追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete All Keyframes</source>
+ <translation>ã™ã¹ã¦ã®ã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ã‚’削除ã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>TabViewToolAction</name>
@@ -24649,6 +30562,14 @@ Preselects a desktop Qt for building the application if available.</source>
<translation>デãƒãƒƒã‚°ãƒ“ューãŒæœ‰åŠ¹åŒ–ã•ã‚Œã¾ã—ãŸ</translation>
</message>
<message>
+ <source>::nodeReparented:</source>
+ <translation>::nodeReparented:</translation>
+ </message>
+ <message>
+ <source>::nodeIdChanged:</source>
+ <translation>::nodeIdChanged:</translation>
+ </message>
+ <message>
<source>Child node:</source>
<translation>å­ãƒŽãƒ¼ãƒ‰:</translation>
</message>
@@ -24758,6 +30679,86 @@ Preselects a desktop Qt for building the application if available.</source>
<source>Reset view (R).</source>
<translation>表示をリセットã—ã¾ã™(R)。</translation>
</message>
+ <message>
+ <source>No snapping.</source>
+ <translation>スナップã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Snap to parent or sibling items and generate anchors.</source>
+ <translation type="vanished">親や兄弟アイテムã«ã‚¹ãƒŠãƒƒãƒ—ã—ã¦ã€ã‚¢ãƒ³ã‚«ãƒ¼ã‚’生æˆã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Snap to parent or sibling items but do not generate anchors.</source>
+ <translation type="vanished">親や兄弟アイテムã«ã‚¹ãƒŠãƒƒãƒ—ã—ã¾ã™ãŒã€ã‚¢ãƒ³ã‚«ãƒ¼ã¯ç”Ÿæˆã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Show bounding rectangles and stripes for empty items.</source>
+ <translation type="vanished">空アイテムã®ãƒã‚¦ãƒ³ãƒ€ãƒªé ˜åŸŸã‚’縞模様付ãã®çŸ©å½¢ã§è¡¨ç¤ºã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Override Width</source>
+ <translation>幅を上書ãã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Override width of root item.</source>
+ <translation type="vanished">ルートアイテムã®å¹…を上書ãã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Override Height</source>
+ <translation>高ã•ã‚’上書ãã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Override height of root item.</source>
+ <translation type="vanished">ルートアイテムã®é«˜ã•ã‚’上書ãã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Snap to parent or sibling components and generate anchors.</source>
+ <translation>親や兄弟コンãƒãƒ¼ãƒãƒ³ãƒˆã«ã‚¹ãƒŠãƒƒãƒ—ã—ã¦ã€ã‚¢ãƒ³ã‚«ãƒ¼ã‚’生æˆã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Snap to parent or sibling components but do not generate anchors.</source>
+ <translation>親や兄弟コンãƒãƒ¼ãƒãƒ³ãƒˆã«ã‚¹ãƒŠãƒƒãƒ—ã—ã¾ã™ãŒã€ã‚¢ãƒ³ã‚«ãƒ¼ã¯ç”Ÿæˆã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Show bounding rectangles and stripes for empty components.</source>
+ <translation>空コンãƒãƒ¼ãƒãƒ³ãƒˆã®ãƒã‚¦ãƒ³ãƒ€ãƒªé ˜åŸŸã‚’縞模様付ãã®çŸ©å½¢ã§è¡¨ç¤ºã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Override width of root component.</source>
+ <translation>ルートコンãƒãƒ¼ãƒãƒ³ãƒˆã®å¹…を上書ãã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Override height of root component.</source>
+ <translation>ルートコンãƒãƒ¼ãƒãƒ³ãƒˆã®é«˜ã•ã‚’上書ãã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Zoom in</source>
+ <translation>拡大</translation>
+ </message>
+ <message>
+ <source>Zoom out</source>
+ <translation>縮å°</translation>
+ </message>
+ <message>
+ <source>Zoom screen to fit all content</source>
+ <translation>ã™ã¹ã¦ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã«åˆã‚ã›ã¦ç”»é¢ã‚’拡大ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Zoom screen to fit current selection</source>
+ <translation>ç¾åœ¨ã®é¸æŠžç¯„囲ã«åˆã‚ã›ã¦ç”»é¢ã‚’拡大ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Reset View</source>
+ <translation>表示をリセットã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Export Current QML File as Image</source>
+ <translation>ç¾åœ¨ã® QML ファイルを画åƒã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>PNG (*.png);;JPG (*.jpg)</source>
+ <translation>PNG (*.png);;JPG (*.jpg)</translation>
+ </message>
</context>
<context>
<name>QmlDesigner::ImportLabel</name>
@@ -24813,7 +30814,23 @@ Preselects a desktop Qt for building the application if available.</source>
<message>
<source>QML Types</source>
<comment>Title of library QML types view</comment>
- <translation>エレメント</translation>
+ <translation type="vanished">エレメント</translation>
+ </message>
+ <message>
+ <source>All Files (%1)</source>
+ <translation>ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (%1)</translation>
+ </message>
+ <message>
+ <source>Add Assets</source>
+ <translation>アセットを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Failed to Add Files</source>
+ <translation>ファイルã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Could not add %1 to project.</source>
+ <translation>プロジェクト㫠%1 を追加ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
</message>
<message>
<source>Resources</source>
@@ -24835,29 +30852,51 @@ Preselects a desktop Qt for building the application if available.</source>
<name>QmlDesigner::NavigatorTreeModel</name>
<message>
<source>Unknown item: %1</source>
- <translation>ä¸æ˜Žãªã‚¢ã‚¤ãƒ†ãƒ : %1</translation>
+ <translation type="vanished">ä¸æ˜Žãªã‚¢ã‚¤ãƒ†ãƒ : %1</translation>
+ </message>
+ <message>
+ <source>Unknown component: %1</source>
+ <translation>ä¸æ˜Žãªã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆ: %1</translation>
+ </message>
+ <message>
+ <source>Changing the setting &quot;%1&quot; might solve the issue.</source>
+ <translation>設定 &quot;%1&quot; を変更ã™ã‚‹ã¨ã€å•é¡ŒãŒè§£æ±ºã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Use QML emulation layer that is built with the selected Qt</source>
+ <translation>é¸æŠžã—㟠Qt ã§ãƒ“ルドã•ã‚ŒãŸ QML エミュレーション・レイヤーを使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Toggles whether this component is exported as an alias property of the root component.</source>
+ <translation>ã“ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’ルートコンãƒãƒ¼ãƒãƒ³ãƒˆã® alias プロパティã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹ã‹ã©ã†ã‹ã‚’切りæ›ãˆã¾ã™ã€‚</translation>
</message>
<message>
<source>Toggles whether this item is exported as an alias property of the root item.</source>
- <translation>ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ルートアイテム㮠alias プロパティã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹ã‹ã©ã†ã‹ã‚’切りæ›ãˆã¾ã™ã€‚</translation>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ルートアイテム㮠alias プロパティã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹ã‹ã©ã†ã‹ã‚’切りæ›ãˆã¾ã™ã€‚</translation>
</message>
<message>
<source>Toggles the visibility of this item in the form editor.
This is independent of the visibility property in QML.</source>
- <translation>ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã® Designer 内ã§ã®è¡¨ç¤ºãƒ»éžè¡¨ç¤ºã‚’切りæ›ãˆã¾ã™ã€‚
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã® Designer 内ã§ã®è¡¨ç¤ºãƒ»éžè¡¨ç¤ºã‚’切りæ›ãˆã¾ã™ã€‚
QML ã®å¯è¦–性(visible)プロパティã®å€¤ã‹ã‚‰ã¯ç‹¬ç«‹ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Toggles whether this item is locked.
+Locked items cannot be modified or selected.</source>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ロックã™ã‚‹ã‹ã©ã†ã‹ã‚’切り替ãˆã¾ã™ã€‚
+ロックã•ã‚Œã¦ã„るアイテムã¯ã€ä¿®æ­£ã‚„é¸æŠžãŒã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Invalid Id</source>
- <translation>無効㪠ID</translation>
+ <translation type="vanished">無効㪠ID</translation>
</message>
<message>
<source>%1 is an invalid id.</source>
- <translation>%1 ã¯ç„¡åŠ¹ãª id ã§ã™ã€‚</translation>
+ <translation type="vanished">%1 ã¯ç„¡åŠ¹ãª id ã§ã™ã€‚</translation>
</message>
<message>
<source>%1 already exists.</source>
- <translation>%1 ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ <translation type="vanished">%1 ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
</context>
<context>
@@ -24883,6 +30922,26 @@ QML ã®å¯è¦–性(visible)プロパティã®å€¤ã‹ã‚‰ã¯ç‹¬ç«‹ã—ã¦ã„ã¾ã™ã€‚<
<source>Move up (CTRL + Up).</source>
<translation>上ã«ç§»å‹•ã—ã¾ã™(CTRL + Up)。</translation>
</message>
+ <message>
+ <source>Filter Tree</source>
+ <translation>フィルタツリー</translation>
+ </message>
+ <message>
+ <source>Show Only Visible Components</source>
+ <translation>å¯è¦–化ã•ã‚ŒãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã ã‘を表示ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Reverse Component Order</source>
+ <translation>コンãƒãƒ¼ãƒãƒ³ãƒˆã®é †åºã‚’逆ã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Show only visible items.</source>
+ <translation type="vanished">å¯è¦–化ã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã ã‘を表示ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Reverse item order.</source>
+ <translation type="vanished">アイテムã®é †åºã‚’逆ã«ã™ã‚‹ã€‚</translation>
+ </message>
</context>
<context>
<name>WidgetPluginManager</name>
@@ -24898,6 +30957,18 @@ QML ã®å¯è¦–性(visible)プロパティã®å€¤ã‹ã‚‰ã¯ç‹¬ç«‹ã—ã¦ã„ã¾ã™ã€‚<
<source>File &apos;%1&apos; is not a QmlDesigner plugin.</source>
<translation>ファイル &apos;%1&apos; 㯠QmlDesigner プラグインã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
+ <message>
+ <source>Failed to create instance of file &quot;%1&quot;: %2</source>
+ <translation>ファイル &apos;%1&apos; ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ: %2</translation>
+ </message>
+ <message>
+ <source>Failed to create instance of file &quot;%1&quot;.</source>
+ <translation>ファイル &apos;%1&apos; ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>File &quot;%1&quot; is not a Qt Quick Designer plugin.</source>
+ <translation>ファイル &quot;%1&quot; 㯠Qt Quick Designer ã®ãƒ—ラグインã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
</context>
<context>
<name>FileResourcesModel</name>
@@ -24921,9 +30992,29 @@ QML ã®å¯è¦–性(visible)プロパティã®å€¤ã‹ã‚‰ã¯ç‹¬ç«‹ã—ã¦ã„ã¾ã™ã€‚<
<translation>%1 ã¯ç„¡åŠ¹ãª id ã§ã™ã€‚</translation>
</message>
<message>
+ <source>Invalid ID</source>
+ <translation>無効㪠ID</translation>
+ </message>
+ <message>
+ <source>%1 is an invalid ID.</source>
+ <translation>%1 ã¯ç„¡åŠ¹ãª id ã§ã™ã€‚</translation>
+ </message>
+ <message>
<source>%1 already exists.</source>
<translation>%1 ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>Cannot Export Property as Alias</source>
+ <translation>プロパティを別åã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Property %1 does already exist for root component.</source>
+ <translation>プロパティ %1 ã¯ã€ãƒ«ãƒ¼ãƒˆã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã«æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Property %1 does already exist for root item.</source>
+ <translation type="vanished">プロパティ %1 ã¯ã€ãƒ«ãƒ¼ãƒˆé …ç›®ã«æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>QmlDesigner::StatesEditorModel</name>
@@ -24952,8 +31043,28 @@ QML ã®å¯è¦–性(visible)プロパティã®å€¤ã‹ã‚‰ã¯ç‹¬ç«‹ã—ã¦ã„ã¾ã™ã€‚<
<translation>ステートエディタ</translation>
</message>
<message>
+ <source>States</source>
+ <translation>状態</translation>
+ </message>
+ <message>
+ <source>Locked items:</source>
+ <translation type="vanished">ロックã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ :</translation>
+ </message>
+ <message>
+ <source>Remove State</source>
+ <translation>状態を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Removing this state will modify locked items.</source>
+ <translation type="vanished">ã“ã®çŠ¶æ…‹ã‚’削除ã™ã‚‹ã¨ã€ãƒ­ãƒƒã‚¯ã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ãŒå¤‰æ›´ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Continue by removing the state?</source>
+ <translation>状態を削除ã—ã¦ç¶™ç¶šã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
<source>base state</source>
- <translation>åˆæœŸã‚¹ãƒ†ãƒ¼ãƒˆ</translation>
+ <translation>基底状態</translation>
</message>
</context>
<context>
@@ -24963,6 +31074,14 @@ QML ã®å¯è¦–性(visible)プロパティã®å€¤ã‹ã‚‰ã¯ç‹¬ç«‹ã—ã¦ã„ã¾ã™ã€‚<
<comment>Title of Editor widget</comment>
<translation>状態</translation>
</message>
+ <message>
+ <source>Cannot Create QtQuick View</source>
+ <translation>QtQuick ビューãŒä½œæˆã§ããªã„</translation>
+ </message>
+ <message>
+ <source>StatesEditorWidget: %1 cannot be created. Most likely QtQuick.Controls 1 are not installed.</source>
+ <translation>StatesEditorWidget: %1 を作æˆã§ãã¾ã›ã‚“。QtQuick.Controls 1 ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>QmlDesigner::InvalidArgumentException</name>
@@ -25094,6 +31213,10 @@ Ids must begin with a lowercase letter.</source>
<source>Unsupported QtQuick version</source>
<translation>サãƒãƒ¼ãƒˆã—ã¦ã„ãªã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® QtQuick</translation>
</message>
+ <message>
+ <source>No import for Qt Quick found.</source>
+ <translation>Qt Quick ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
</context>
<context>
<name>QmlDesigner::Internal::DocumentWarningWidget</name>
@@ -25148,6 +31271,18 @@ Ids must begin with a lowercase letter.</source>
<source>Qt Quick emulation layer crashed</source>
<translation>Qt Quick エミュレーションレイヤãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸ</translation>
</message>
+ <message>
+ <source>&amp;Workspaces</source>
+ <translation>ワークスペース(&amp;W)</translation>
+ </message>
+ <message>
+ <source>Switch the active workspace.</source>
+ <translation>有効ãªãƒ¯ãƒ¼ã‚¯ã‚¹ãƒšãƒ¼ã‚¹ã‚’切り替ãˆã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Edit global annotation for current file.</source>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚°ãƒ­ãƒ¼ãƒãƒ«ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’編集ã™ã‚‹ã€‚</translation>
+ </message>
</context>
<context>
<name>QmlDesigner::QmlDesignerPlugin</name>
@@ -25228,13 +31363,21 @@ Ids must begin with a lowercase letter.</source>
</message>
<message>
<source>Toggle &amp;Right Sidebar</source>
- <translation>å³ã‚µã‚¤ãƒ‰ãƒãƒ¼è¡¨ç¤ºã®åˆ‡æ›¿(&amp;L)</translation>
+ <translation type="vanished">å³ã‚µã‚¤ãƒ‰ãƒãƒ¼è¡¨ç¤ºã®åˆ‡æ›¿(&amp;R)</translation>
</message>
<message>
<source>&amp;Go into Component</source>
<translation>コンãƒãƒ¼ãƒãƒ³ãƒˆå†…ã¸ç§»å‹•(&amp;G)</translation>
</message>
<message>
+ <source>Export as &amp;Image...</source>
+ <translation>ç”»åƒã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ(&amp;I)...</translation>
+ </message>
+ <message>
+ <source>Toggle States</source>
+ <translation>状態を切り替ãˆã‚‹</translation>
+ </message>
+ <message>
<source>Save %1 As...</source>
<translation>%1 ã«åå‰ã‚’ã¤ã‘ã¦ä¿å­˜...</translation>
</message>
@@ -25292,6 +31435,11 @@ Ids must begin with a lowercase letter.</source>
<translation>Ctrl+Shift+R</translation>
</message>
<message>
+ <source>QML</source>
+ <comment>SnippetProvider</comment>
+ <translation>QML</translation>
+ </message>
+ <message>
<source>Run Checks</source>
<translation>ãƒã‚§ãƒƒã‚¯ã®å®Ÿè¡Œ</translation>
</message>
@@ -25424,6 +31572,17 @@ Qt Creator know about a likely URI.</source>
&quot;// @uri My.Module.Uri&quot; を記述ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ Qt Creator ã« URI を通知ã§ãã¾ã™ã€‚</translation>
</message>
<message>
+ <source>The type will only be available in the QML editors when the type name is a string literal</source>
+ <translation>ã“ã®åž‹ã¯åž‹åãŒæ–‡å­—列リテラルã§ã‚ã‚‹ãŸã‚ã€QML エディタã§ã®ã¿åˆ©ç”¨å¯èƒ½ã§ãã¾ã™</translation>
+ </message>
+ <message>
+ <source>The module URI cannot be determined by static analysis. The type will be available
+globally in the QML editor. You can add a &quot;// @uri My.Module.Uri&quot; annotation to let
+the QML editor know about a likely URI.</source>
+ <translation>é™çš„解æžã§ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã® URI を確èªã§ãã¾ã›ã‚“。ã“ã®åž‹ã¯ QML エディタ全体ã§æœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚
+&quot;// @uri My.Module.Uri&quot; を記述ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ QML エディタ ã« URI を通知ã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>must be a string literal to be available in the QML editor</source>
<translation>QML エディタ内ã§ã¯æ–‡å­—列リテラルã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“</translation>
</message>
@@ -25520,6 +31679,18 @@ Do you want to retry?</source>
<source>Trying to set unknown state in events list.</source>
<translation>イベントリストã«æœªçŸ¥ã®çŠ¶æ…‹ã‚’設定ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>Failed to replay QML events from stash file.</source>
+ <translation>スタッシュファイルã‹ã‚‰ã® QML イベントã®å†ç”Ÿã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>&lt;bytecode&gt;</source>
+ <translation>&lt;ãƒã‚¤ãƒˆã‚³ãƒ¼ãƒ‰&gt;</translation>
+ </message>
+ <message>
+ <source>anonymous function</source>
+ <translation>ç„¡å関数</translation>
+ </message>
</context>
<context>
<name>QmlProfiler::Internal::QmlProfilerTool</name>
@@ -25548,6 +31719,20 @@ Do you want to retry?</source>
<translation>イベントカテゴリーã®è¡¨ç¤ºãƒ»éžè¡¨ç¤ºã‚’切り替ãˆã¾ã™ã€‚</translation>
</message>
<message>
+ <source>The application finished before a connection could be established. No data was loaded.</source>
+ <translation>接続を確立ã™ã‚‹å‰ã«ã‚¢ãƒ—リケーションãŒçµ‚了ã—ã¾ã—ãŸã€‚データã¯èª­ã¿è¾¼ã¾ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Could not connect to the in-process QML profiler within %1 s.
+Do you want to retry and wait %2 s?</source>
+ <translation>プロセス内 QML プロファイラ㫠%1 秒以内ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+å†è©¦è¡Œã—㦠%2 秒間待ã¡ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Failed to connect.</source>
+ <translation>接続ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>QML Profiler</source>
<translation>QML プロファイラ</translation>
</message>
@@ -25588,6 +31773,14 @@ Do you want to retry?</source>
<translation>経éŽ: %1</translation>
</message>
<message>
+ <source>Saving Trace Data</source>
+ <translation>トレースデータã®ä¿å­˜ä¸­</translation>
+ </message>
+ <message>
+ <source>Loading Trace Data</source>
+ <translation>トレースデータã®èª­è¾¼ä¸­</translation>
+ </message>
+ <message>
<source>You are about to discard the profiling data, including unsaved notes. Do you want to continue?</source>
<translation>未ä¿å­˜ã®ãƒ¡ãƒ¢ã‚’å«ã‚€ãƒ—ロファイリングデータを破棄ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚継続ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
@@ -25610,6 +31803,12 @@ Do you want to save the data first?</source>
<source>Profiling application: %1 events</source>
<translation>アプリケーションã®ãƒ—ロファイリング: %1 イベント</translation>
</message>
+ <message numerus="yes">
+ <source>Profiling application: %n events</source>
+ <translation>
+ <numerusform>アプリケーションã®ãƒ—ロファイリング: %n イベント</numerusform>
+ </translation>
+ </message>
<message>
<source>Profiling application</source>
<translation>アプリケーションã®ãƒ—ロファイリング</translation>
@@ -25618,6 +31817,18 @@ Do you want to save the data first?</source>
<source>No QML events recorded</source>
<translation>QML イベントã®è¨˜éŒ²ãªã—</translation>
</message>
+ <message numerus="yes">
+ <source>Loading buffered data: %n events</source>
+ <translation>
+ <numerusform>ãƒãƒƒãƒ•ã‚¡ãƒªãƒ³ã‚°æ¸ˆã¿ãƒ‡ãƒ¼ã‚¿ã®èª­è¾¼ä¸­: %n イベント</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>Loading offline data: %n events</source>
+ <translation>
+ <numerusform>オフラインデータã®èª­è¾¼ä¸­: %n イベント</numerusform>
+ </translation>
+ </message>
<message>
<source>Processing data: %1 / %2</source>
<translation>データ処ç†ä¸­: %1 / %2</translation>
@@ -25775,7 +31986,7 @@ Do you want to save the data first?</source>
</message>
<message>
<source>Texture Delete</source>
- <translation>テクスãƒãƒ£ã®å‰Šé™¤</translation>
+ <translation>テクスãƒãƒ£ã‚’削除ã™ã‚‹</translation>
</message>
</context>
<context>
@@ -25804,6 +32015,10 @@ Do you want to save the data first?</source>
<context>
<name>QmlProfiler::Internal::QmlProfilerTraceView</name>
<message>
+ <source>Timeline</source>
+ <translation>タイムライン</translation>
+ </message>
+ <message>
<source>Analyze Current Range</source>
<translation>ç¾åœ¨ã®ç¯„囲ã®è§£æž</translation>
</message>
@@ -25849,6 +32064,14 @@ Do you want to save the data first?</source>
<translation>デãƒã‚¤ã‚¹ç¨®é¡žãŒãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Would you like to open the project in Qt Design Studio?</source>
+ <translation>Qt Design Studio ã§ãƒ—ロジェクトを開ãã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Open in Qt Design Studio</source>
+ <translation>Qt Design Studio ã§é–‹ã</translation>
+ </message>
+ <message>
<source>No Qt version set in kit.</source>
<translation>キット㫠Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
</message>
@@ -25856,6 +32079,18 @@ Do you want to save the data first?</source>
<source>Qt version is too old.</source>
<translation>Qt ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒå¤ã™ãŽã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>Kit has no device.</source>
+ <translation>キットã«ãƒ‡ãƒã‚¤ã‚¹ãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Qt version has no qmlscene command.</source>
+ <translation>Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯ qmlscene コマンドãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Non-desktop Qt is used with a desktop device.</source>
+ <translation>デスクトップ用ã§ã¯ãªã„ Qt ãŒã€ãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—端末ã§ä½¿ã‚ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>QmlProjectManager::QmlProjectEnvironmentAspect</name>
@@ -25869,24 +32104,45 @@ Do you want to save the data first?</source>
</message>
</context>
<context>
- <name>QmlProjectManager::Internal::Manager</name>
- <message>
- <source>Failed opening project &quot;%1&quot;: Project is not a file.</source>
- <translation>プロジェクト &quot;%1&quot; ãŒé–‹ã‘ã¾ã›ã‚“: プロジェクトãŒãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
- </message>
-</context>
-<context>
<name>QmlProjectManager::QmlProjectRunConfiguration</name>
<message>
<source>No qmlviewer or qmlscene found.</source>
<translation>qmlviewer ã‚„ qmlscene ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>QML Viewer:</source>
+ <translation>QML ビューア:</translation>
+ </message>
+ <message>
+ <source>System Environment</source>
+ <translation>システム環境変数</translation>
+ </message>
+ <message>
+ <source>Clean Environment</source>
+ <translation>環境変数ãªã—</translation>
+ </message>
+ <message>
<source>QML Scene</source>
<comment>QMLRunConfiguration display name.</comment>
<translation>QML Scene</translation>
</message>
<message>
+ <source>No script file to execute.</source>
+ <translation>実行ã™ã‚‹ã‚¹ã‚¯ãƒªãƒ—トファイルãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>No qmlscene found.</source>
+ <translation>qmlscene ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>No qmlscene binary specified for target device.</source>
+ <translation>ターゲットデãƒã‚¤ã‚¹ã«æŒ‡å®šã•ã‚ŒãŸ qmlscene ãƒã‚¤ãƒŠãƒªãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>QML Scene</source>
+ <translation>QML Scene</translation>
+ </message>
+ <message>
<source>QML Viewer</source>
<comment>QMLRunConfiguration display name.</comment>
<translation>QML ビューア</translation>
@@ -25954,6 +32210,14 @@ Do you want to save the data first?</source>
<translation>リモートå´ã®æº–å‚™...</translation>
</message>
<message>
+ <source>Project source directory:</source>
+ <translation>プロジェクトソースディレクトリ:</translation>
+ </message>
+ <message>
+ <source>Local executable:</source>
+ <translation>ローカル実行ファイル:</translation>
+ </message>
+ <message>
<source>The %1 process closed unexpectedly.</source>
<translation>プロセス %1 ãŒã€äºˆæœŸã›ãšçµ‚了ã—ã¾ã—ãŸã€‚</translation>
</message>
@@ -25980,6 +32244,10 @@ Do you want to save the data first?</source>
<translation>QNX</translation>
</message>
<message>
+ <source>QNX Device</source>
+ <translation>QNX デãƒã‚¤ã‚¹</translation>
+ </message>
+ <message>
<source>Deploy Qt libraries...</source>
<translation>Qt ライブラリã®ãƒ‡ãƒ—ロイ...</translation>
</message>
@@ -26005,6 +32273,22 @@ Do you want to save the data first?</source>
<context>
<name>Qnx::Internal::QnxDeviceTester</name>
<message>
+ <source>Checking that files can be created in /var/run...</source>
+ <translation>/var/run ã«ãƒ•ã‚¡ã‚¤ãƒ«ãŒä½œæˆã§ãã‚‹ã“ã¨ã‚’確èªã—ã¦ã„ã¾ã™...</translation>
+ </message>
+ <message>
+ <source>Files can be created in /var/run.</source>
+ <translation>/var/run ã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’作æˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Files cannot be created in /var/run.</source>
+ <translation>/var/run ã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’作æˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>An error occurred while checking that files can be created in /var/run.</source>
+ <translation>/var/run ã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’作æˆã§ãã‚‹ã‹ã©ã†ã‹ã®ãƒã‚§ãƒƒã‚¯ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>%1 found.</source>
<translation>%1 ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸã€‚</translation>
</message>
@@ -26013,6 +32297,10 @@ Do you want to save the data first?</source>
<translation>%1 ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>An error occurred while checking for %1.</source>
+ <translation>%1 ã®ç¢ºèªä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>An error occurred checking for %1.</source>
<translation>%1 ã®ç¢ºèªä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
</message>
@@ -26033,6 +32321,10 @@ Do you want to save the data first?</source>
<translation>QNX %1</translation>
</message>
<message>
+ <source>No SDP path was set up.</source>
+ <translation>SDP ã®ãƒ‘スãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>No SDK path was set up.</source>
<translation>SDK ã®ãƒ‘スãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
</message>
@@ -26043,6 +32335,22 @@ Do you want to save the data first?</source>
<source>Path to Qt libraries on device:</source>
<translation>デãƒã‚¤ã‚¹ä¸Šã® Qt ライブラリã®ãƒ‘ス:</translation>
</message>
+ <message>
+ <source>Executable on device:</source>
+ <translation>デãƒã‚¤ã‚¹ä¸Šã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Remote path not set</source>
+ <translation>リモートã®ãƒ‘スãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Executable on host:</source>
+ <translation>ホスト上ã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Path to Qt libraries on device</source>
+ <translation>デãƒã‚¤ã‚¹ä¸Šã® Qt ライブラリã®ãƒ‘ス</translation>
+ </message>
</context>
<context>
<name>Qnx::Internal::QnxRunConfigurationFactory</name>
@@ -26065,6 +32373,11 @@ Do you want to save the data first?</source>
<translation>コンパイラã®ãƒ‘ス(&amp;C):</translation>
</message>
<message>
+ <source>SDP path:</source>
+ <extracomment>SDP refers to &apos;Software Development Platform&apos;.</extracomment>
+ <translation>SDP ã®ãƒ‘ス:</translation>
+ </message>
+ <message>
<source>NDK/SDP path:</source>
<extracomment>SDP refers to &apos;Software Development Platform&apos;.</extracomment>
<translation>NDK/SDP ã®ãƒ‘ス:</translation>
@@ -26077,6 +32390,10 @@ Do you want to save the data first?</source>
<context>
<name>Qnx::Internal::Slog2InfoRunner</name>
<message>
+ <source>Warning: &quot;slog2info&quot; is not found on the device, debug output not available.</source>
+ <translation>警告: &quot;slog2info&quot; ãŒãƒ‡ãƒã‚¤ã‚¹ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。デãƒãƒƒã‚°å‡ºåŠ›ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Cannot show slog2info output. Error: %1</source>
<translation>slog2info ã®å‡ºåŠ›ã‚’表示ã§ãã¾ã›ã‚“。エラー: %1</translation>
</message>
@@ -26170,6 +32487,11 @@ Do you want to save the data first?</source>
<comment>Qt Version is used for embedded Linux development</comment>
<translation>Embedded Linux</translation>
</message>
+ <message>
+ <source>Boot2Qt</source>
+ <comment>Qt version is used for Boot2Qt development</comment>
+ <translation>Boot2Qt</translation>
+ </message>
</context>
<context>
<name>BaseQtVersion</name>
@@ -26295,6 +32617,10 @@ cannot be found in the path.</source>
<source>Run %1</source>
<translation>%1 を実行</translation>
</message>
+ <message>
+ <source>You need to set an executable in the custom run configuration.</source>
+ <translation>カスタム実行構æˆã«å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::CustomExecutableRunConfigurationFactory</name>
@@ -26345,6 +32671,14 @@ cannot be found in the path.</source>
<source>Cannot Copy Project</source>
<translation>プロジェクトをコピーã§ãã¾ã›ã‚“</translation>
</message>
+ <message>
+ <source>Search in Examples...</source>
+ <translation>サンプルを検索...</translation>
+ </message>
+ <message>
+ <source>Search in Tutorials...</source>
+ <translation>ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã‚’検索...</translation>
+ </message>
</context>
<context>
<name>QtSupport::Internal::QtKitConfigWidget</name>
@@ -26480,7 +32814,7 @@ cannot be found in the path.</source>
</message>
<message>
<source>Remove Invalid Qt Versions</source>
- <translation>ä¸æ­£ãª Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®å‰Šé™¤</translation>
+ <translation>ä¸æ­£ãª Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’削除ã™ã‚‹</translation>
</message>
<message>
<source>Do you want to remove all invalid Qt Versions?&lt;br&gt;&lt;ul&gt;&lt;li&gt;%1&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;will be removed.</source>
@@ -26507,6 +32841,26 @@ cannot be found in the path.</source>
<translation>次㮠ABI ã¯æœªã‚µãƒãƒ¼ãƒˆã§ã™:&lt;ul&gt;&lt;li&gt;%1&lt;/li&gt;&lt;/ul&gt;</translation>
</message>
<message>
+ <source>Highest Version Only</source>
+ <translation>最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã¿</translation>
+ </message>
+ <message>
+ <source>All</source>
+ <translation>ã™ã¹ã¦</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>ã—ãªã„</translation>
+ </message>
+ <message>
+ <source>No compiler can produce code for this Qt version. Please define one or more compilers for: %1</source>
+ <translation>ã“ã® Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚³ãƒ¼ãƒ‰ã‚’生æˆã§ãるコンパイラãŒã‚ã‚Šã¾ã›ã‚“。1ã¤ä»¥ä¸Šã®ã‚³ãƒ³ãƒ‘イラを定義ã—ã¦ãã ã•ã„: %1</translation>
+ </message>
+ <message>
+ <source>The following ABIs are currently not supported: %1</source>
+ <translation>次㮠ABI ã¯æœªã‚µãƒãƒ¼ãƒˆã§ã™: %1</translation>
+ </message>
+ <message>
<source>Select a qmake Executable</source>
<translation>qmake 実行ファイルã®é¸æŠž</translation>
</message>
@@ -26532,7 +32886,11 @@ cannot be found in the path.</source>
</message>
<message>
<source>The Qt version selected must match the device type.</source>
- <translation>é¸æŠžã•ã‚ŒãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Qt ã¨ãƒ‡ãƒã‚¤ã‚¹ã®ç¨®é¡žãŒåŒã˜ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ <translation>é¸æŠžã—ãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Qt ã¨ãƒ‡ãƒã‚¤ã‚¹ã®ç¨®é¡žãŒåŒã˜ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>キャンセル</translation>
</message>
<message>
<source>Debugging Helper Build Log for &quot;%1&quot;</source>
@@ -26687,6 +33045,14 @@ cannot be found in the path.</source>
<context>
<name>RemoteLinux::GenericDirectUploadStep</name>
<message>
+ <source>Incremental deployment</source>
+ <translation>増分デプロイ</translation>
+ </message>
+ <message>
+ <source>Ignore missing files</source>
+ <translation>存在ã—ãªã„ファイルを無視ã™ã‚‹</translation>
+ </message>
+ <message>
<source>Upload files via SFTP</source>
<translation>SFTP 経由ã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’アップロード</translation>
</message>
@@ -26740,6 +33106,10 @@ In addition, device connectivity will be tested.</source>
<translation>一般的㪠Linux</translation>
</message>
<message>
+ <source>Generic Linux Device</source>
+ <translation>一般的㪠Linux デãƒã‚¤ã‚¹</translation>
+ </message>
+ <message>
<source>Deploy Public Key...</source>
<translation>公開éµã‚’デプロイ...</translation>
</message>
@@ -26884,6 +33254,10 @@ In addition, device connectivity will be tested.</source>
<numerusform>リモートã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚·ã‚¹ãƒ†ãƒ ã¯ %n MBytes ã—ã‹ç©ºã容é‡ãŒã‚ã‚Šã¾ã›ã‚“ãŒã€%1 MBytes å¿…è¦ã§ã™ã€‚</numerusform>
</translation>
</message>
+ <message>
+ <source>Remote process failed: %1</source>
+ <translation type="unfinished">リモートプロセスãŒå¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
<message numerus="yes">
<source>The remote file system has %n megabytes of free space, going ahead.</source>
<translation>
@@ -26901,6 +33275,18 @@ In addition, device connectivity will be tested.</source>
<context>
<name>RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep</name>
<message>
+ <source>Remote path to check for free space:</source>
+ <translation>空ã容é‡ã‚’確èªã™ã‚‹ãƒªãƒ¢ãƒ¼ãƒˆã®ãƒ‘ス:</translation>
+ </message>
+ <message>
+ <source>Required disk space:</source>
+ <translation>å¿…è¦ãªãƒ‡ã‚£ã‚¹ã‚¯å®¹é‡:</translation>
+ </message>
+ <message>
+ <source>MB</source>
+ <translation>MB</translation>
+ </message>
+ <message>
<source>Check for free disk space</source>
<translation>ディスクã®ç©ºã容é‡ãƒã‚§ãƒƒã‚¯</translation>
</message>
@@ -26923,6 +33309,10 @@ In addition, device connectivity will be tested.</source>
<translation>リモートコマンド &quot;%1&quot; ã‚’èµ·å‹•ã—ã¦ã„ã¾ã™...</translation>
</message>
<message>
+ <source>Remote process failed: %1</source>
+ <translation type="unfinished">リモートプロセスãŒå¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
<source>Remote process failed to start.</source>
<translation>リモートプロセスã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
</message>
@@ -27158,6 +33548,22 @@ In addition, device connectivity will be tested.</source>
<translation>tarball 作æˆä¸­...</translation>
</message>
<message>
+ <source>Ignore missing files</source>
+ <translation>存在ã—ãªã„ファイルを無視ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Package modified files only</source>
+ <translation>変更ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã®ã¿ã‚’パッケージ化</translation>
+ </message>
+ <message>
+ <source>Tarball creation not possible.</source>
+ <translation>tarball を作æˆã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Create tarball:</source>
+ <translation>tarball ã®ä½œæˆ:</translation>
+ </message>
+ <message>
<source>Tarball up to date, skipping packaging.</source>
<translation>tarball ã¯æœ€æ–°ã§ã™ã€ãƒ‘ッケージ作æˆã‚’スキップã—ã¾ã™ã€‚</translation>
</message>
@@ -27313,11 +33719,11 @@ In addition, device connectivity will be tested.</source>
</message>
<message>
<source>Remove Prefix...</source>
- <translation>プレフィックスã®å‰Šé™¤...</translation>
+ <translation>プレフィックスを削除ã™ã‚‹...</translation>
</message>
<message>
<source>Remove Missing Files</source>
- <translation>存在ã—ãªã„ファイルã®å‰Šé™¤</translation>
+ <translation>存在ã—ãªã„ファイルを削除ã™ã‚‹</translation>
</message>
<message>
<source>Rename...</source>
@@ -27325,7 +33731,7 @@ In addition, device connectivity will be tested.</source>
</message>
<message>
<source>Remove File...</source>
- <translation>ファイルã®å‰Šé™¤...</translation>
+ <translation>ファイルを削除ã™ã‚‹...</translation>
</message>
<message>
<source>Open in Editor</source>
@@ -27349,7 +33755,7 @@ In addition, device connectivity will be tested.</source>
</message>
<message>
<source>Remove Prefix</source>
- <translation>プレフィックスã®å‰Šé™¤</translation>
+ <translation>プレフィックスを削除ã™ã‚‹</translation>
</message>
<message>
<source>Remove prefix %1 and all its files?</source>
@@ -27386,6 +33792,10 @@ In addition, device connectivity will be tested.</source>
<source>Copy Resource Path to Clipboard</source>
<translation>リソースã®ãƒ‘スをクリップボードã«ã‚³ãƒ”ー</translation>
</message>
+ <message>
+ <source>Sort Alphabetically</source>
+ <translation>アルファベット順ã«ã‚½ãƒ¼ãƒˆ</translation>
+ </message>
</context>
<context>
<name>Subversion::Internal::SettingsPageWidget</name>
@@ -27393,6 +33803,10 @@ In addition, device connectivity will be tested.</source>
<source>Subversion Command</source>
<translation>Subversion コマンド</translation>
</message>
+ <message>
+ <source>Subversion</source>
+ <translation>Subversion</translation>
+ </message>
</context>
<context>
<name>Subversion::Internal::SubversionPlugin</name>
@@ -27638,6 +34052,12 @@ In addition, device connectivity will be tested.</source>
<translation>検索中</translation>
</message>
<message numerus="yes">
+ <source>%n found.</source>
+ <translation>
+ <numerusform>%n 個ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸã€‚</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
<source>%n occurrences replaced.</source>
<translation>
<numerusform>%n 個置æ›ã—ã¾ã—ãŸã€‚</numerusform>
@@ -27666,6 +34086,10 @@ In addition, device connectivity will be tested.</source>
<comment>Settings</comment>
<translation>グローãƒãƒ«</translation>
</message>
+ <message>
+ <source>Behavior</source>
+ <translation>動作</translation>
+ </message>
</context>
<context>
<name>TextEditor::FunctionHintProposalWidget</name>
@@ -27966,6 +34390,10 @@ Filter: %2
<source>Filter tree</source>
<translation>フィルタツリー</translation>
</message>
+ <message>
+ <source>Sort Alphabetically</source>
+ <translation>アルファベット順ã«ã‚½ãƒ¼ãƒˆ</translation>
+ </message>
</context>
<context>
<name>TextEditor::Internal::OutlineFactory</name>
@@ -28060,6 +34488,11 @@ Filter: %2
<translation>Alt+Return</translation>
</message>
<message>
+ <source>Text</source>
+ <comment>SnippetProvider</comment>
+ <translation>テキスト</translation>
+ </message>
+ <message>
<source>Selected text within the current document.</source>
<translation>ç¾åœ¨ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆå†…ã§é¸æŠžã•ã‚Œã¦ã„るテキストã§ã™ã€‚</translation>
</message>
@@ -28645,6 +35078,11 @@ Will not be applied to whitespace in comments and strings.</source>
<translation>æ–°ã—ã„æ›´æ–°ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸã€‚更新を開始ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
+ <source>%1 (%2)</source>
+ <comment>Package name and version</comment>
+ <translation>%1 (%2)</translation>
+ </message>
+ <message>
<source>Could not determine location of maintenance tool. Please check your installation if you did not enable this plugin manually.</source>
<translation>メンテナンスツールã®ãƒ‘スを特定ã§ãã¾ã›ã‚“。ã“ã®ãƒ—ラグインを手動ã§æœ‰åŠ¹ã«ã—ãŸã®ã§ãªã‘ã‚Œã°ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’確èªã—ã¦ãã ã•ã„。</translation>
</message>
@@ -28973,6 +35411,10 @@ Will not be applied to whitespace in comments and strings.</source>
<translation>Valgrind メモリ解æž</translation>
</message>
<message>
+ <source>Analyzing Memory</source>
+ <translation>メモリ解æžä¸­</translation>
+ </message>
+ <message>
<source>Load External XML Log File</source>
<translation>外部㮠XML ログファイルを読ã¿è¾¼ã‚€</translation>
</message>
@@ -29441,6 +35883,10 @@ When a problem is detected, the application is interrupted and can be debugged.<
<translation>コミットå‰ã«ç¢ºèªã™ã‚‹</translation>
</message>
<message>
+ <source>&amp;Close</source>
+ <translation>é–‰ã˜ã‚‹(&amp;C)</translation>
+ </message>
+ <message>
<source>Submit Message Check Failed</source>
<translation>メッセージãƒã‚§ãƒƒã‚¯ã®ã‚µãƒ–ミットã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
</message>
@@ -29509,7 +35955,7 @@ When a problem is detected, the application is interrupted and can be debugged.<
<name>BookmarkWidget</name>
<message>
<source>Delete Folder</source>
- <translation>フォルダã®å‰Šé™¤</translation>
+ <translation>フォルダを削除ã™ã‚‹</translation>
</message>
<message>
<source>Rename Folder</source>
@@ -29525,7 +35971,7 @@ When a problem is detected, the application is interrupted and can be debugged.<
</message>
<message>
<source>Delete Bookmark</source>
- <translation>ブックマークã®å‰Šé™¤</translation>
+ <translation>ブックマークを削除ã™ã‚‹</translation>
</message>
<message>
<source>Rename Bookmark</source>
@@ -29550,6 +35996,10 @@ When a problem is detected, the application is interrupted and can be debugged.<
<source>New Folder</source>
<translation>æ–°ã—ã„フォルダ</translation>
</message>
+ <message>
+ <source>Bookmark</source>
+ <translation>ブックマーク</translation>
+ </message>
</context>
<context>
<name>ContentWindow</name>
@@ -30012,6 +36462,10 @@ Ex. &quot;Revision: 15&quot; を指定ã—ãŸå ´åˆã€ãƒ–ランãƒã¯ãƒªãƒ“ジョ
<source>Sco&amp;pe:</source>
<translation>スコープ(&amp;P):</translation>
</message>
+ <message>
+ <source>Case &amp;sensitive</source>
+ <translation>大文字/å°æ–‡å­—を区別ã™ã‚‹(&amp;S)</translation>
+ </message>
</context>
<context>
<name>Core::Internal::FindWidget</name>
@@ -30122,6 +36576,26 @@ To do this, you type this shortcut and a space in the Locator entry field, and t
<source> min</source>
<translation> 分</translation>
</message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Prefix</source>
+ <translation>プレフィックス</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+ <message>
+ <source>Built-in</source>
+ <translation>ビルトイン</translation>
+ </message>
+ <message>
+ <source>Custom</source>
+ <translation>カスタム</translation>
+ </message>
</context>
<context>
<name>WinRt::Internal::WinRtPackageDeploymentStepWidget</name>
@@ -30718,6 +37192,10 @@ kill ã—ã¾ã™ã‹ï¼Ÿ</translation>
<source>Create and Open &quot;%1&quot;</source>
<translation>&quot;%1&quot; を作æˆã—ã¦é–‹ã</translation>
</message>
+ <message>
+ <source>Create</source>
+ <translation>生æˆ</translation>
+ </message>
</context>
<context>
<name>Core::ILocatorFilter</name>
@@ -30757,6 +37235,10 @@ kill ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation>パスを入力ã—ã¦ãã ã•ã„ (%1)</translation>
</message>
<message>
+ <source>Locate...</source>
+ <translation>クイックアクセス...</translation>
+ </message>
+ <message>
<source>&lt;html&gt;&lt;body style=&quot;color:#909090; font-size:14px&quot;&gt;&lt;div align=&apos;center&apos;&gt;&lt;div style=&quot;font-size:20px&quot;&gt;Open a document&lt;/div&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;hr/&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; File &gt; Open File or Project (%1)&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; File &gt; Recent Files&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; Tools &gt; Locate (%2) and&lt;/div&gt;&lt;div style=&quot;margin-left: 1em&quot;&gt;- type to open file from any open project&lt;/div&gt;%4%5&lt;div style=&quot;margin-left: 1em&quot;&gt;- type &lt;code&gt;%3&amp;lt;space&amp;gt;&amp;lt;filename&amp;gt;&lt;/code&gt; to open file from file system&lt;/div&gt;&lt;div style=&quot;margin-left: 1em&quot;&gt;- select one of the other filters for jumping to a location&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; Drag and drop files here&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;body style=&quot;color:#909090; font-size:14px&quot;&gt;&lt;div align=&apos;center&apos;&gt;&lt;div style=&quot;font-size:20px&quot;&gt;ドキュメントã®é–‹ãæ–¹&lt;/div&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;hr/&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; ファイル → ファイル/プロジェクトを開ã (%1)&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; ファイル → 最近使ã£ãŸãƒ•ã‚¡ã‚¤ãƒ«&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; ツール → クイックアクセス (%2) ã‹ã‚‰&lt;/div&gt;&lt;div style=&quot;margin-left: 1em&quot;&gt;- æ—¢ã«é–‹ã„ã¦ã„るプロジェクト内ã®é–‹ããŸã„ファイルåを入力ã—ã¦ãã ã•ã„&lt;/div&gt;%4%5&lt;div style=&quot;margin-left: 1em&quot;&gt;- ファイルシステム上ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®å ´åˆã¯ &lt;code&gt;%3&amp;lt;スペース&amp;gt;&amp;lt;ファイルå&amp;gt;&lt;/code&gt; ã¨å…¥åŠ›ã—ã¦ãã ã•ã„&lt;/div&gt;&lt;div style=&quot;margin-left: 1em&quot;&gt;- ãã®ä»–ã®ãƒ•ã‚£ãƒ«ã‚¿ã‹ã‚‰é–‹ããŸã„ドキュメントã«é©åˆ‡ãªã‚‚ã®ã‚’é¸æŠžã—ã¦ãã ã•ã„&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; ファイルをã“ã“ã«ãƒ‰ãƒ©ãƒƒã‚°&amp;amp;ドロップã—ã¦ãã ã•ã„&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
@@ -30780,6 +37262,14 @@ kill ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation>æ›´æ–°</translation>
</message>
<message>
+ <source>Type to locate</source>
+ <translation>パスを入力ã—ã¦ãã ã•ã„</translation>
+ </message>
+ <message>
+ <source>Type to locate (%1)</source>
+ <translation>パスを入力ã—ã¦ãã ã•ã„ (%1)</translation>
+ </message>
+ <message>
<source>Locate...</source>
<translation>クイックアクセス...</translation>
</message>
@@ -30831,11 +37321,11 @@ kill ã—ã¾ã™ã‹ï¼Ÿ</translation>
</message>
<message>
<source>Kit: </source>
- <translation>キット:</translation>
+ <translation>キット: </translation>
</message>
<message>
<source>Executable: </source>
- <translation>実行ファイル:</translation>
+ <translation>実行ファイル: </translation>
</message>
<message>
<source>Select valid executable.</source>
@@ -31105,6 +37595,10 @@ kill ã—ã¾ã™ã‹ï¼Ÿ</translation>
<context>
<name>WinRt::Internal::WinRtRunConfiguration</name>
<message>
+ <source>Uninstall package after application stops</source>
+ <translation>アプリケーションåœæ­¢å¾Œã«ãƒ‘ッケージをアンインストールã™ã‚‹</translation>
+ </message>
+ <message>
<source>Run App Package</source>
<translation>アプリケーションパッケージã®å®Ÿè¡Œ</translation>
</message>
@@ -31134,6 +37628,10 @@ kill ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation>ターゲット</translation>
</message>
<message>
+ <source>Margin</source>
+ <translation>マージン</translation>
+ </message>
+ <message>
<source>Anchor to the top of the target.</source>
<translation>ターゲットã®ä¸Šç«¯ã«ã‚¢ãƒ³ã‚«ãƒ¼ã—ã¾ã™ã€‚</translation>
</message>
@@ -31395,6 +37893,10 @@ Are you sure you want to continue?</source>
%1?</translation>
</message>
<message>
+ <source>QNX</source>
+ <translation>QNX</translation>
+ </message>
+ <message>
<source>Add...</source>
<translation>追加...</translation>
</message>
@@ -31425,10 +37927,18 @@ Are you sure you want to continue?</source>
<context>
<name>ColorEditor</name>
<message>
+ <source>Color</source>
+ <translation>色</translation>
+ </message>
+ <message>
<source>Solid Color</source>
<translation>å˜è‰²</translation>
</message>
<message>
+ <source>New</source>
+ <translation>æ–°è¦ä½œæˆ</translation>
+ </message>
+ <message>
<source>Gradient</source>
<translation>グラデーション</translation>
</message>
@@ -31527,6 +38037,10 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
<extracomment>Bare Metal run configuration default run name</extracomment>
<translation>GDB サーãƒãƒ¼ã‚ã‚‹ã„ã¯ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒ‡ãƒãƒƒã‚¬ä¸Šã§å®Ÿè¡Œ</translation>
</message>
+ <message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
</context>
<context>
<name>BareMetal::Internal::BareMetalRunConfigurationWidget</name>
@@ -31643,6 +38157,18 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
<translation>デãƒãƒƒã‚°ãƒ˜ãƒ«ãƒ‘㯠&amp;quot;ローカル変数ã¨å¼&amp;quot; ã«ãŠã„㦠QString ã‚„ std::map ã®ã‚ˆã†ãªç‰¹å®šã®åž‹ã‚’ã‚ã‹ã‚Šã‚„ã™ãã«è¡¨ç¤ºã™ã‚‹ç‚ºã«ä½¿ã‚ã‚Œã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Debugging Helper Customization</source>
+ <translation>デãƒãƒƒã‚°ãƒ˜ãƒ«ãƒ‘ã®ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚º</translation>
+ </message>
+ <message>
+ <source>Extra Debugging Helpers</source>
+ <translation>追加ã®ãƒ‡ãƒãƒƒã‚°ãƒ˜ãƒ«ãƒ‘</translation>
+ </message>
+ <message>
+ <source>Path to a Python file containing additional data dumpers.</source>
+ <translation>追加ã™ã‚‹ãƒ‡ãƒ¼ã‚¿è¡¨ç¤ºæ©Ÿèƒ½ã‚’æŒã¤ Python ファイルã¸ã®ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
<source>&lt;unlimited&gt;</source>
<translation>&lt;無制é™&gt;</translation>
</message>
@@ -31659,15 +38185,15 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
<name>EmacsKeys::Internal::EmacsKeysPlugin</name>
<message>
<source>Delete Character</source>
- <translation>文字ã®å‰Šé™¤</translation>
+ <translation>文字を削除ã™ã‚‹</translation>
</message>
<message>
<source>Kill Word</source>
- <translation>å˜èªžã®å‰Šé™¤</translation>
+ <translation>å˜èªžã‚’削除ã™ã‚‹</translation>
</message>
<message>
<source>Kill Line</source>
- <translation>è¡Œã®å‰Šé™¤</translation>
+ <translation>行を削除ã™ã‚‹</translation>
</message>
<message>
<source>Insert New Line and Indent</source>
@@ -31767,6 +38293,10 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
<translation>ヘルプモードã«ç§»è¡Œ</translation>
</message>
<message>
+ <source>(Untitled)</source>
+ <translation>(無題)</translation>
+ </message>
+ <message>
<source>Home</source>
<translation>ホーム</translation>
</message>
@@ -31803,6 +38333,14 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
<translation>フォントサイズをリセット</translation>
</message>
<message>
+ <source>Reload</source>
+ <translation>å†èª­è¾¼</translation>
+ </message>
+ <message>
+ <source>Unfiltered</source>
+ <translation>フィルタãªã—</translation>
+ </message>
+ <message>
<source>Meta+Shift+C</source>
<translation>Meta+Shift+C</translation>
</message>
@@ -31975,7 +38513,11 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
</message>
<message>
<source>You asked to build the current Run Configuration&apos;s build target only, but it is not associated with a build target. Update the Make Step in your build settings.</source>
- <translation>ç¾åœ¨ã®å®Ÿè¡Œè¨­å®šã®ãƒ“ルドターゲットをビルドã—よã†ã¨ã—ã¾ã—ãŸãŒã€ãã®ãƒ“ルドターゲットãŒãƒ“ルド設定ã«å­˜åœ¨ã—ã¾ã›ã‚“。ビルド設定ã®ãƒ“ルドステップを更新ã—ã¦ãã ã•ã„。</translation>
+ <translation>ç¾åœ¨ã®å®Ÿè¡Œæ§‹æˆã®ãƒ“ルドターゲットをビルドã—よã†ã¨ã—ã¾ã—ãŸãŒã€ãã®ãƒ“ルドターゲットãŒãƒ“ルド設定ã«å­˜åœ¨ã—ã¾ã›ã‚“。ビルド設定ã®ãƒ“ルドステップを更新ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>%1 needs a compiler set up to build. Configure a compiler in the kit options.</source>
+ <translation>%1 をビルドã™ã‚‹ç‚ºã«ã¯ã‚³ãƒ³ãƒ‘イラã®è¨­å®šãŒå¿…è¦ã§ã™ã€‚キットオプションã§ã‚³ãƒ³ãƒ‘イラを設定ã—ã¦ãã ã•ã„。</translation>
</message>
</context>
<context>
@@ -32124,8 +38666,24 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
<context>
<name>RemoteLinux::Internal::RemoteLinuxCustomRunConfiguration</name>
<message>
+ <source>Remote executable:</source>
+ <translation>リモート実行ファイル:</translation>
+ </message>
+ <message>
+ <source>Local executable:</source>
+ <translation>ローカル実行ファイル:</translation>
+ </message>
+ <message>
+ <source>Custom Executable</source>
+ <translation>カスタム実行ファイル</translation>
+ </message>
+ <message>
+ <source>Run &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; を実行</translation>
+ </message>
+ <message>
<source>The remote executable must be set in order to run a custom remote run configuration.</source>
- <translation>カスタムãªãƒªãƒ¢ãƒ¼ãƒˆå®Ÿè¡Œè¨­å®šã§å®Ÿè¡Œã™ã‚‹ãŸã‚ã«ã¯ãƒªãƒ¢ãƒ¼ãƒˆã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
+ <translation>カスタムãªãƒªãƒ¢ãƒ¼ãƒˆå®Ÿè¡Œæ§‹æˆã§å®Ÿè¡Œã™ã‚‹ãŸã‚ã«ã¯ãƒªãƒ¢ãƒ¼ãƒˆã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
</message>
<message>
<source>Run &quot;%1&quot; on Linux Device</source>
@@ -32185,6 +38743,10 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
<translation>Qt Creator ã« WinRT デãƒãƒƒã‚°ãƒ˜ãƒ«ãƒ‘ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。通常㯠%1 ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã™</translation>
</message>
<message>
+ <source>The WinRT debugging helper is missing from your %1 installation. It was assumed to be located at %2</source>
+ <translation>%1 ã« WinRT デãƒãƒƒã‚°ãƒ˜ãƒ«ãƒ‘ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。通常㯠%2 ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã™</translation>
+ </message>
+ <message>
<source>Cannot start the WinRT Runner Tool.</source>
<translation>WinRT Runner Tool ã‚’èµ·å‹•ã§ãã¾ã›ã‚“。</translation>
</message>
@@ -32198,7 +38760,7 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
</message>
<message>
<source>Cannot create an appropriate run control for the current run configuration.</source>
- <translation>ç¾åœ¨ã®å®Ÿè¡Œè¨­å®šã«é©åˆ‡ãªå®Ÿè¡Œã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã‚’作æˆã§ãã¾ã›ã‚“。</translation>
+ <translation>ç¾åœ¨ã®å®Ÿè¡Œæ§‹æˆã«é©åˆ‡ãªå®Ÿè¡Œã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã‚’作æˆã§ãã¾ã›ã‚“。</translation>
</message>
</context>
<context>
@@ -32218,7 +38780,8 @@ API ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ %1 以上㮠SDK をインストールã—ã¦ãã ã•ã„ã
<message>
<source>Error while executing the WinRT Runner Tool: %1
</source>
- <translation>WinRT Runner Tool 実行中ã®ã‚¨ãƒ©ãƒ¼: %1</translation>
+ <translation>WinRT Runner Tool 実行中ã®ã‚¨ãƒ©ãƒ¼: %1
+</translation>
</message>
</context>
<context>
@@ -32350,7 +38913,7 @@ Android 5 ã§ã¯ãƒ­ãƒ¼ã‚«ãƒ«ã® Qt ライブラリをデプロイã§ãã¾ã›ã‚“
</message>
<message>
<source>Omit run configuration warnings</source>
- <translation>実行設定ã®è­¦å‘Šã‚’çœç•¥ã™ã‚‹</translation>
+ <translation>実行構æˆã®è­¦å‘Šã‚’çœç•¥ã™ã‚‹</translation>
</message>
<message>
<source>Limit result output to 100000 characters.</source>
@@ -32488,6 +39051,22 @@ Android 5 ã§ã¯ãƒ­ãƒ¼ã‚«ãƒ«ã® Qt ライブラリをデプロイã§ãã¾ã›ã‚“
<source>Select the test frameworks to be handled by the AutoTest plugin.</source>
<translation>AutoTest プラグインã§ä½¿ç”¨ã™ã‚‹ãƒ†ã‚¹ãƒˆãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠžã—ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>All</source>
+ <translation>ã™ã¹ã¦</translation>
+ </message>
+ <message>
+ <source>Selected</source>
+ <translation>é¸æŠžã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Framework</source>
+ <translation>フレームワーク</translation>
+ </message>
+ <message>
+ <source>Group</source>
+ <translation type="unfinished">グループ</translation>
+ </message>
</context>
<context>
<name>ClangCodeModel::Internal::ClangProjectSettingsWidget</name>
@@ -32691,6 +39270,14 @@ Android 5 ã§ã¯ãƒ­ãƒ¼ã‚«ãƒ«ã® Qt ライブラリをデプロイã§ãã¾ã›ã‚“
<source>Files to keep open:</source>
<translation>維æŒã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«æ•°:</translation>
</message>
+ <message>
+ <source>Environment:</source>
+ <translation>環境変数:</translation>
+ </message>
+ <message>
+ <source>Change...</source>
+ <translation>変更...</translation>
+ </message>
</context>
<context>
<name>CppTools::ClangDiagnosticConfigsWidget</name>
@@ -32726,6 +39313,18 @@ Android 5 ã§ã¯ãƒ­ãƒ¼ã‚«ãƒ«ã® Qt ライブラリをデプロイã§ãã¾ã›ã‚“
<source>%1 (Copy)</source>
<translation>%1 (コピー)</translation>
</message>
+ <message>
+ <source>%1</source>
+ <translation>%1</translation>
+ </message>
+ <message>
+ <source>Rename...</source>
+ <translation>åå‰ã‚’変更...</translation>
+ </message>
+ <message>
+ <source>Diagnostic Configurations</source>
+ <translation type="unfinished">診断設定</translation>
+ </message>
</context>
<context>
<name>QbsProjectManager::Internal::CustomQbsPropertiesDialog</name>
@@ -33083,6 +39682,14 @@ the program.</source>
ã“ã®æ‰‹æ³•ã§ã¯è¤‡æ•°ã®ãƒ—ロファイルçµæžœã‚’一ã¤ã®ãƒˆãƒ¬ãƒ¼ã‚¹çµæžœã«ã¾ã¨ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
例ãˆã°å˜ä¸€ã®ãƒ—ログラム内ã§è¤‡æ•°ã® QML エンジンをé€æ¬¡å®Ÿè¡Œã™ã‚‹å ´åˆãªã©ã«æœ‰åŠ¹ã§ã™ã€‚</translation>
</message>
+ <message>
+ <source>QML Profiler</source>
+ <translation>QML プロファイラ</translation>
+ </message>
+ <message>
+ <source>Analyzer</source>
+ <translation>解æž</translation>
+ </message>
</context>
<context>
<name>FlameGraphView</name>
@@ -33119,6 +39726,10 @@ the program.</source>
<translation>パス</translation>
</message>
<message>
+ <source>unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+ <message>
<source>No data available</source>
<translation>データãŒã‚ã‚Šã¾ã›ã‚“</translation>
</message>
@@ -33333,7 +39944,7 @@ the program.</source>
</message>
<message>
<source>Remove Object</source>
- <translation>オブジェクトã®å‰Šé™¤</translation>
+ <translation>オブジェクトを削除ã™ã‚‹</translation>
</message>
<message>
<source>Cut</source>
@@ -33354,10 +39965,22 @@ the program.</source>
<source>Show Definition</source>
<translation>定義ã®è¡¨ç¤º</translation>
</message>
+ <message>
+ <source>Inheritance</source>
+ <translation>継承</translation>
+ </message>
+ <message>
+ <source>Association</source>
+ <translation>関連</translation>
+ </message>
</context>
<context>
<name>qmt::ObjectItem</name>
<message>
+ <source>Dependency</source>
+ <translation>ä¾å­˜é–¢ä¿‚</translation>
+ </message>
+ <message>
<source>Open Diagram</source>
<translation>図を開ã</translation>
</message>
@@ -33506,7 +40129,7 @@ the program.</source>
</message>
<message>
<source>Delete Object</source>
- <translation>オブジェクトã®å‰Šé™¤</translation>
+ <translation>オブジェクトを削除ã™ã‚‹</translation>
</message>
<message>
<source>Add Relation</source>
@@ -33514,7 +40137,7 @@ the program.</source>
</message>
<message>
<source>Delete Relation</source>
- <translation>関係ã®å‰Šé™¤</translation>
+ <translation>関係を削除ã™ã‚‹</translation>
</message>
<message>
<source>Cut</source>
@@ -33730,6 +40353,14 @@ the program.</source>
<translation>関係:</translation>
</message>
<message>
+ <source>Connection</source>
+ <translation>接続</translation>
+ </message>
+ <message>
+ <source>Connections</source>
+ <translation>コãƒã‚¯ã‚·ãƒ§ãƒ³</translation>
+ </message>
+ <message>
<source>Position and size:</source>
<translation>ä½ç½®ã¨ã‚µã‚¤ã‚º:</translation>
</message>
@@ -33850,6 +40481,10 @@ the program.</source>
<translation>境界</translation>
</message>
<message>
+ <source>Multi-Selection</source>
+ <translation>複数é¸æŠž</translation>
+ </message>
+ <message>
<source>&lt;font color=red&gt;Invalid syntax!&lt;/font&gt;</source>
<translation>&lt;font color=red&gt;無効ãªã‚·ãƒ³ã‚¿ãƒƒã‚¯ã‚¹ï¼&lt;/font&gt;</translation>
</message>
@@ -33958,6 +40593,10 @@ the program.</source>
<source>Error: Unknown socket error %1</source>
<translation>エラー: 未知ã®ã‚½ã‚±ãƒƒãƒˆã‚¨ãƒ©ãƒ¼ %1</translation>
</message>
+ <message>
+ <source>Error: %1</source>
+ <translation>エラー: %1</translation>
+ </message>
</context>
<context>
<name>Utils::HostOsInfo</name>
@@ -34402,6 +41041,14 @@ the program.</source>
<translation>個ã®ãƒ–ラックリストテスト</translation>
</message>
<message>
+ <source>Run This Test</source>
+ <translation>ã“ã®ãƒ†ã‚¹ãƒˆã®å®Ÿè¡Œ</translation>
+ </message>
+ <message>
+ <source>Debug This Test</source>
+ <translation>ã“ã®ãƒ†ã‚¹ãƒˆã®ãƒ‡ãƒãƒƒã‚°</translation>
+ </message>
+ <message>
<source>, %1 disabled</source>
<translation>, %1 個ã®ç„¡åŠ¹åŒ–ã•ã‚ŒãŸãƒ†ã‚¹ãƒˆ</translation>
</message>
@@ -34482,7 +41129,7 @@ Only desktop kits are supported. Make sure the currently active kit is a desktop
</message>
<message>
<source>Failed to get run configuration.</source>
- <translation>実行設定ã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ <translation>実行構æˆã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
</message>
<message>
<source>Failed to create run configuration.
@@ -34524,8 +41171,16 @@ Only desktop kits are supported. Make sure the currently active kit is a desktop
<context>
<name>BareMetal::Internal::BareMetalCustomRunConfiguration</name>
<message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+ <message>
+ <source>Custom Executable</source>
+ <translation>カスタム実行ファイル</translation>
+ </message>
+ <message>
<source>The remote executable must be set in order to run a custom remote run configuration.</source>
- <translation>カスタムリモート実行設定ã§å®Ÿè¡Œã™ã‚‹ãŸã‚ã«ã¯ãƒªãƒ¢ãƒ¼ãƒˆã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
+ <translation>カスタムリモート実行構æˆã§å®Ÿè¡Œã™ã‚‹ãŸã‚ã«ã¯ãƒªãƒ¢ãƒ¼ãƒˆã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
</message>
<message>
<source>Custom Executable (on GDB server or hardware debugger)</source>
@@ -34546,6 +41201,14 @@ Only desktop kits are supported. Make sure the currently active kit is a desktop
<source>Starting GDB server...</source>
<translation>GDB サーãƒãƒ¼èµ·å‹•ä¸­...</translation>
</message>
+ <message>
+ <source>Cannot debug: Kit has no device.</source>
+ <translation>デãƒãƒƒã‚°ã‚¨ãƒ©ãƒ¼: キットã«ãƒ‡ãƒã‚¤ã‚¹ãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>No debug server provider found for %1</source>
+ <translation>デãƒãƒƒã‚°ãƒ»ã‚µãƒ¼ãƒãƒ¼ãƒ»ãƒ—ロãƒã‚¤ãƒ€ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚%1</translation>
+ </message>
</context>
<context>
<name>BareMetal::Internal::BareMetalDeviceConfigurationWidget</name>
@@ -34553,6 +41216,10 @@ Only desktop kits are supported. Make sure the currently active kit is a desktop
<source>GDB server provider:</source>
<translation>GDB サーãƒãƒ¼ãƒ—ロãƒã‚¤ãƒ€:</translation>
</message>
+ <message>
+ <source>Debug server provider:</source>
+ <translation>サーãƒãƒ¼ãƒ»ãƒ—ロãƒã‚¤ãƒ€ãƒ¼ã‚’デãƒãƒƒã‚°ã™ã‚‹:</translation>
+ </message>
</context>
<context>
<name>BareMetal::Internal::DefaultGdbServerProviderFactory</name>
@@ -34602,6 +41269,18 @@ Only desktop kits are supported. Make sure the currently active kit is a desktop
<translation>起動モード:</translation>
</message>
<message>
+ <source>Peripheral description files (*.svd)</source>
+ <translation>ペリフェラル説明ファイル (*.svd)</translation>
+ </message>
+ <message>
+ <source>Select Peripheral Description File</source>
+ <translation>ペリフェラル説明ファイルをé¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Peripheral description file:</source>
+ <translation>ペリフェラル説明ファイル:</translation>
+ </message>
+ <message>
<source>No Startup</source>
<translation>èµ·å‹•ã—ãªã„</translation>
</message>
@@ -34624,6 +41303,14 @@ Only desktop kits are supported. Make sure the currently active kit is a desktop
<source>Enter TCP/IP port which will be listened by the GDB server provider.</source>
<translation>GDB サーãƒãƒ¼ãƒ—ロãƒã‚¤ãƒ€ãŒå¾…ã¡å—ã‘ã«ä½¿ç”¨ã—ã¦ã„ã‚‹ TCP/IP ãƒãƒ¼ãƒˆç•ªå·ã‚’入力ã—ã¦ãã ã•ã„。</translation>
</message>
+ <message>
+ <source>Enter TCP/IP hostname of the debug server, like &quot;localhost&quot; or &quot;192.0.2.1&quot;.</source>
+ <translation>デãƒãƒƒã‚° サーãƒãƒ¼ã® TCP/IP ホストåを入力ã—ã¦ãã ã•ã„。例: &quot;localhost&quot; ã‚„ &quot;192.0.2.1&quot;.</translation>
+ </message>
+ <message>
+ <source>Enter TCP/IP port which will be listened by the debug server.</source>
+ <translation>デãƒãƒƒã‚° サーãƒãƒ¼ãŒå¾…ã¡å—ã‘ã«ä½¿ç”¨ã—ã¦ã„ã‚‹ TCP/IP ãƒãƒ¼ãƒˆç•ªå·ã‚’入力ã—ã¦ãã ã•ã„。</translation>
+ </message>
</context>
<context>
<name>BareMetal::Internal::GdbServerProviderChooser</name>
@@ -35193,9 +41880,67 @@ clang ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
<translation>Make</translation>
</message>
<message>
+ <source>Current executable</source>
+ <translation>ç¾åœ¨ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message>
+ <source>Build the executable used in the active run configuration. Currently: %1</source>
+ <translation>有効ãªå®Ÿè¡Œæ§‹æˆã§ä½¿ç”¨ã•ã‚Œã‚‹å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’ビルドã—ã¾ã™ã€‚ç¾åœ¨: %1</translation>
+ </message>
+ <message>
+ <source>Target: %1</source>
+ <translation>ターゲット:%1</translation>
+ </message>
+ <message>
+ <source>CMake arguments:</source>
+ <translation>CMake ã®å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>Tool arguments:</source>
+ <translation>ツールã®å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>Target</source>
+ <translation>ターゲット</translation>
+ </message>
+ <message>
+ <source>The build configuration is currently disabled.</source>
+ <translation>ビルド設定ã¯ç¾åœ¨ç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>A CMake tool must be set up for building. Configure a CMake tool in the kit options.</source>
+ <translation>ビルドã™ã‚‹ãŸã‚ã«ã¯ã€CMake ツールを設定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚キットã®ã‚ªãƒ—ション㧠CMake ツールを設定ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>There is a CMakeCache.txt file in &quot;%1&quot;, which suggest an in-source build was done before. You are now building in &quot;%2&quot;, and the CMakeCache.txt file might confuse CMake.</source>
+ <translation>&quot;%1&quot;ã« CMakeCache.txt ファイルãŒã‚ã‚Šã€ä»¥å‰ã«ã‚¤ãƒ³ã‚½ãƒ¼ã‚¹ãƒ»ãƒ“ルドãŒè¡Œã‚ã‚ŒãŸã“ã¨ã‚’示ã—ã¦ã„ã¾ã™ã€‚ç¾åœ¨ã€&quot;%2&quot; ã§ãƒ“ルドã—ã¦ã„ã¾ã™ãŒã€CMakeCache.txt ファイル㌠CMake ã‚’æ··ä¹±ã•ã›ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Persisting CMake state...</source>
<translation>CMake ã®çŠ¶æ…‹ã‚’維æŒã—ã¦ã„ã¾ã™...</translation>
</message>
+ <message>
+ <source>Running CMake in preparation to build...</source>
+ <translation>ビルドã®æº–å‚™ã®ãŸã‚ã« CMake を実行ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Project did not parse successfully, cannot build.</source>
+ <translation>プロジェクトãŒæ­£å¸¸ã«è§£æžã•ã‚Œãšã€ãƒ“ルドã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Build</source>
+ <comment>ConfigWidget display name.</comment>
+ <translation>ビルド</translation>
+ </message>
+ <message>
+ <source>Targets:</source>
+ <translation>ターゲット:</translation>
+ </message>
+ <message>
+ <source>CMake Build</source>
+ <comment>Display name for CMakeProjectManager::CMakeBuildStep id.</comment>
+ <translation>CMake ビルド</translation>
+ </message>
</context>
<context>
<name>CMakeProjectManager::CMakeBuildStep</name>
@@ -35360,10 +42105,22 @@ clang ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
<source>No cmake tool set.</source>
<translation>CMake ツールãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
</message>
+ <message>
+ <source>No compilers set in kit.</source>
+ <translation>キットã«ã‚³ãƒ³ãƒ‘イラãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
</context>
<context>
<name>CMakeProjectManager::CMakeSettingsPage</name>
<message>
+ <source>yes</source>
+ <translation>ã¯ã„</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>ã„ã„ãˆ</translation>
+ </message>
+ <message>
<source> (Default)</source>
<translation> (既定)</translation>
</message>
@@ -35391,6 +42148,10 @@ clang ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
<source>Path:</source>
<translation>パス:</translation>
</message>
+ <message>
+ <source>Help file:</source>
+ <translation>ヘルプファイル:</translation>
+ </message>
</context>
<context>
<name>CMakeProjectManager::Internal::CMakeToolConfigWidget</name>
@@ -35422,6 +42183,10 @@ clang ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
<source>New CMake</source>
<translation>æ–°ã—ã„ CMake</translation>
</message>
+ <message>
+ <source>CMake</source>
+ <translation>CMake</translation>
+ </message>
</context>
<context>
<name>CMakeProjectManager::CMakeToolManager</name>
@@ -35433,10 +42198,18 @@ clang ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã‚’設定ã—ã¦ãã ã•ã„。</translation>
<source>System CMake at %1</source>
<translation>システム㮠CMake(パス: %1)</translation>
</message>
+ <message>
+ <source>CMake</source>
+ <translation>CMake</translation>
+ </message>
</context>
<context>
<name>CMakeProjectManager::ConfigModel</name>
<message>
+ <source> (ADVANCED)</source>
+ <translation> (æ‹¡å¼µ)</translation>
+ </message>
+ <message>
<source>&lt;UNSET&gt;</source>
<translation>&lt;未定義&gt;</translation>
</message>
@@ -35698,6 +42471,10 @@ Do you want to check them out now?</source>
<context>
<name>Core::Internal::EditorManagerPrivate</name>
<message>
+ <source>Properties...</source>
+ <translation>プロパティ...</translation>
+ </message>
+ <message>
<source>Revert File to Saved</source>
<translation>ファイルをä¿å­˜æ™‚ã®çŠ¶æ…‹ã«æˆ»ã™</translation>
</message>
@@ -35886,10 +42663,6 @@ Do you want to check them out now?</source>
<translation>%1 ã«åå‰ã‚’ã¤ã‘ã¦ä¿å­˜(&amp;A)...</translation>
</message>
<message>
- <source>Revert %1 to Saved</source>
- <translation>%1 ã‚’ä¿å­˜æ™‚ã®çŠ¶æ…‹ã«æˆ»ã™</translation>
- </message>
- <message>
<source>Reload %1</source>
<translation>%1 ã®å†èª­è¾¼</translation>
</message>
@@ -35906,6 +42679,10 @@ Do you want to check them out now?</source>
<translation>ä»–ã‚’é–‰ã˜ã‚‹</translation>
</message>
<message>
+ <source>Cancel &amp;&amp; &amp;Diff</source>
+ <translation>キャンセルã—ã¦å·®åˆ†è¡¨ç¤º(&amp;D)</translation>
+ </message>
+ <message>
<source>Qt Creator</source>
<translation>Qt Creator</translation>
</message>
@@ -36014,6 +42791,10 @@ Do you want to check them out now?</source>
<translation>MIME タイプã®ãƒªã‚»ãƒƒãƒˆ</translation>
</message>
<message>
+ <source>Changes will take effect after restart.</source>
+ <translation>変更㯠Qt Creator ã‚’å†èµ·å‹•ã—ãŸå¾Œã«å映ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
<source>Changes will take effect after Qt Creator restart.</source>
<translation>変更㯠Qt Creator ã‚’å†èµ·å‹•ã—ãŸå¾Œã«å映ã•ã‚Œã¾ã™ã€‚</translation>
</message>
@@ -36046,7 +42827,11 @@ Do you want to check them out now?</source>
<translation>å†èµ·å‹•ãŒå¿…è¦ã§ã™</translation>
</message>
<message>
- <source>The theme change will take effect after a restart of Qt Creator.</source>
+ <source>Current theme: %1</source>
+ <translation>ç¾åœ¨ã®ãƒ†ãƒ¼ãƒž: %1</translation>
+ </message>
+ <message>
+ <source>The theme change will take effect after restart.</source>
<translation>テーマã®å¤‰æ›´ã¯ Qt Creator ã‚’å†èµ·å‹•ã—ãŸå¾Œã«å映ã•ã‚Œã¾ã™ã€‚</translation>
</message>
</context>
@@ -36197,6 +42982,94 @@ Do you want to check them out now?</source>
<source>Attempting to interrupt.</source>
<translation>中断ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
+ <message>
+ <source>Debugger finished.</source>
+ <translation>デãƒãƒƒã‚¬ã¯çµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Continue</source>
+ <translation>続行</translation>
+ </message>
+ <message>
+ <source>Stop Debugger</source>
+ <translation>デãƒãƒƒã‚¬ã‚’åœæ­¢</translation>
+ </message>
+ <message>
+ <source>Interrupt</source>
+ <translation>割り込ã¿</translation>
+ </message>
+ <message>
+ <source>Abort Debugging</source>
+ <translation>デãƒãƒƒã‚°ä¸­æ­¢</translation>
+ </message>
+ <message>
+ <source>Step Into</source>
+ <translation>ステップイン</translation>
+ </message>
+ <message>
+ <source>Step Out</source>
+ <translation>ステップアウト</translation>
+ </message>
+ <message>
+ <source>Run to Line</source>
+ <translation>ã“ã®è¡Œã¾ã§å®Ÿè¡Œ</translation>
+ </message>
+ <message>
+ <source>Run to Selected Function</source>
+ <translation>é¸æŠžã—ãŸé–¢æ•°ã¾ã§å®Ÿè¡Œ</translation>
+ </message>
+ <message>
+ <source>Jump to Line</source>
+ <translation>指定行ã«ã‚¸ãƒ£ãƒ³ãƒ—</translation>
+ </message>
+ <message>
+ <source>Immediately Return From Inner Function</source>
+ <translation>内部関数ã‹ã‚‰ã™ãã«æŠœã‘ã‚‹</translation>
+ </message>
+ <message>
+ <source>Step Over</source>
+ <translation>ステップオーãƒãƒ¼</translation>
+ </message>
+ <message>
+ <source>Add Expression Evaluator</source>
+ <translation>å¼ã‚¨ãƒãƒªãƒ¥ã‚¨ãƒ¼ã‚¿ã‚’追加</translation>
+ </message>
+ <message>
+ <source>Toggle Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®åˆ‡æ›¿</translation>
+ </message>
+ <message>
+ <source>Restart Debugging</source>
+ <translation>デãƒãƒƒã‚°ã®å†é–‹</translation>
+ </message>
+ <message>
+ <source>Operate by Instruction</source>
+ <translation>命令ã§æ“作</translation>
+ </message>
+ <message>
+ <source>Reverse Direction</source>
+ <translation>逆方å‘</translation>
+ </message>
+ <message>
+ <source>Launching Debugger</source>
+ <translation>デãƒãƒƒã‚¬ã®èµ·å‹•ä¸­</translation>
+ </message>
+ <message>
+ <source>Source Files</source>
+ <translation>ソースファイル</translation>
+ </message>
+ <message>
+ <source>Locals</source>
+ <translation>ローカル</translation>
+ </message>
+ <message>
+ <source>Aborts debugging and resets the debugger to the initial state.</source>
+ <translation>デãƒãƒƒã‚°ã‚’中止ã—ã¦ã€åˆæœŸçŠ¶æ…‹ã«æˆ»ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Threads:</source>
+ <translation>スレッド:</translation>
+ </message>
</context>
<context>
<name>Debugger::Internal::DebuggerEngine</name>
@@ -36209,6 +43082,18 @@ Do you want to check them out now?</source>
<translation>セットアップã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
</message>
<message>
+ <source>No Memory Viewer Available</source>
+ <translation>利用å¯èƒ½ãªãƒ¡ãƒ¢ãƒªãƒ“ューアãŒã‚ã‚Šã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>The memory contents cannot be shown as no viewer plugin for binary data has been loaded.</source>
+ <translation>ãƒã‚¤ãƒŠãƒªãƒ‡ãƒ¼ã‚¿ã‚’表示ã™ã‚‹ç‚ºã®ãƒ“ューアプラグインãŒèª­ã¿è¾¼ã¾ã‚Œã¦ã„ãªã„為ã€ãƒ¡ãƒ¢ãƒªã®å†…容を表示ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Debugger</source>
+ <translation>デãƒãƒƒã‚¬</translation>
+ </message>
+ <message>
<source>Loading finished.</source>
<translation>読ã¿è¾¼ã¿ã¯å®Œäº†ã—ã¾ã—ãŸã€‚</translation>
</message>
@@ -36245,6 +43130,14 @@ Do you want to check them out now?</source>
<translation>PID %1 ã®é€šçŸ¥ã‚’å—ã‘ã‚‹</translation>
</message>
<message>
+ <source>Attempting to interrupt.</source>
+ <translation>中断ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Could not find a widget.</source>
+ <translation>ウィジェットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
<source>This debugger cannot handle user input.</source>
<translation>ã“ã®ãƒ‡ãƒãƒƒã‚¬ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼å…¥åŠ›ã‚’処ç†ã§ãã¾ã›ã‚“。</translation>
</message>
@@ -36291,6 +43184,54 @@ Do you want to check them out now?</source>
<translation>例外ãŒç™ºç”Ÿã—ã¾ã—ãŸ</translation>
</message>
<message>
+ <source>No function selected.</source>
+ <translation>関数ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Running to function &quot;%1&quot;.</source>
+ <translation>関数 &quot;%1&quot; を実行ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Symbol</source>
+ <translation>シンボル</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>アドレス</translation>
+ </message>
+ <message>
+ <source>Code</source>
+ <translation>コード</translation>
+ </message>
+ <message>
+ <source>Section</source>
+ <translation>セクション</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Symbols in &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ã‚·ãƒ³ãƒœãƒ«</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>From</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>To</translation>
+ </message>
+ <message>
+ <source>Flags</source>
+ <translation>フラグ</translation>
+ </message>
+ <message>
+ <source>Sections in &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³</translation>
+ </message>
+ <message>
<source>The inferior is in the Portable Executable format.
Selecting CDB as debugger would improve the debugging experience for this binary format.</source>
<translation>プログラム㯠PE(Portable Executable) å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ã§ã™ã€‚
@@ -36451,10 +43392,26 @@ Setting breakpoints by file name and line number may fail.</source>
<translation>ビュー</translation>
</message>
<message>
+ <source>&amp;Views</source>
+ <translation>表示(&amp;V)</translation>
+ </message>
+ <message>
<source>Toolbar</source>
<translation>ツールãƒãƒ¼</translation>
</message>
<message>
+ <source>Editor</source>
+ <translation>エディタ</translation>
+ </message>
+ <message>
+ <source>Next Item</source>
+ <translation>次ã®é …ç›®</translation>
+ </message>
+ <message>
+ <source>Previous Item</source>
+ <translation>å‰ã®é …ç›®</translation>
+ </message>
+ <message>
<source>Start</source>
<translation>開始</translation>
</message>
@@ -36490,6 +43447,38 @@ Setting breakpoints by file name and line number may fail.</source>
<translation>プロセス %1</translation>
</message>
<message>
+ <source>Cannot start %1 without a project. Please open the project and try again.</source>
+ <translation>プロジェクト無ã—ã§ã¯ %1 を開始ã§ãã¾ã›ã‚“。プロジェクトを開ã„ãŸå¾Œã«å†åº¦è©¦ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>in Debug mode</source>
+ <translation>デãƒãƒƒã‚°ãƒ¢ãƒ¼ãƒ‰</translation>
+ </message>
+ <message>
+ <source>in Profile mode</source>
+ <translation>プロファイルモード</translation>
+ </message>
+ <message>
+ <source>in Release mode</source>
+ <translation>リリースモード</translation>
+ </message>
+ <message>
+ <source>with debug symbols (Debug or Profile mode)</source>
+ <translation>デãƒãƒƒã‚°ã‚·ãƒ³ãƒœãƒ«è¾¼ã¿(デãƒãƒƒã‚°ã‚ã‚‹ã„ã¯ãƒ—ロファイルモード)</translation>
+ </message>
+ <message>
+ <source>on optimized code (Profile or Release mode)</source>
+ <translation>最é©åŒ–済ã¿ã‚³ãƒ¼ãƒ‰(プロファイルã‚ã‚‹ã„ã¯ãƒªãƒªãƒ¼ã‚¹ãƒ¢ãƒ¼ãƒ‰)</translation>
+ </message>
+ <message>
+ <source>Run %1 in %2 Mode?</source>
+ <translation>%1 ã‚’%2モードã§å®Ÿè¡Œã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;You are trying to run the tool &quot;%1&quot; on an application in %2 mode. The tool is designed to be used %3.&lt;/p&gt;&lt;p&gt;Run-time characteristics differ significantly between optimized and non-optimized binaries. Analytical findings for one mode may or may not be relevant for the other.&lt;/p&gt;&lt;p&gt;Running tools that need debug symbols on binaries that don&apos;t provide any may lead to missing function names or otherwise insufficient output.&lt;/p&gt;&lt;p&gt;Do you want to continue and run the tool in %2 mode?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;%2モードã®ã‚¢ãƒ—リケーションã«å¯¾ã—ã¦ãƒ„ール &quot;%1&quot; を実行ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã®ãƒ„ールã¯%3モードã§ã®åˆ©ç”¨ã‚’想定ã—ã¦ã„ã¾ã™ã€‚&lt;/p&gt;&lt;p&gt;ãƒã‚¤ãƒŠãƒªãŒæœ€é©åŒ–済ã¿ã‹ã©ã†ã‹ã«ã‚ˆã£ã¦å®Ÿè¡Œæ™‚ã®ç‰¹æ€§ã¯å¤§ããç•°ãªã‚Šã¾ã™ã€‚ã‚るモードã§ã®è§£æžçµæžœãŒåˆ¥ã®ãƒ¢ãƒ¼ãƒ‰ã«ã¯å½“ã¦ã¯ã¾ã‚‰ãªã„å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚&lt;/p&gt;&lt;p&gt;デãƒãƒƒã‚°ã‚·ãƒ³ãƒœãƒ«ãŒå«ã¾ã‚Œãªã„ãƒã‚¤ãƒŠãƒªã«å¯¾ã—ã¦ãƒ‡ãƒãƒƒã‚°ã‚·ãƒ³ãƒœãƒ«ãŒå¿…è¦ãªãƒ„ールを実行ã™ã‚‹å ´åˆã«ã¯é–¢æ•°åãŒå–å¾—ã§ããªã‹ã£ãŸã‚ŠçµæžœãŒä¸å分ãªã‚‚ã®ã«ãªã‚‹ã“ã¨ã‚‚ã‚ã‚Šã¾ã™ã€‚&lt;/p&gt;&lt;p&gt;%2モードã§ã®ãƒ„ールã®å®Ÿè¡Œã‚’継続ã—ã¾ã™ã‹ï¼Ÿ&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
<source>Symbol</source>
<translation>シンボル</translation>
</message>
@@ -36545,6 +43534,10 @@ Affected are breakpoints %1</source>
<translation>QML デãƒãƒƒã‚°ç”¨ã®ç©ºããƒãƒ¼ãƒˆãŒã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Debugging complex command lines is currently not supported on Windows.</source>
+ <translation>ç¾åœ¨ã€Windows 上ã§ã®è¤‡é›‘ãªã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã®ãƒ‡ãƒãƒƒã‚°ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>Unknown debugger type &quot;%1&quot;</source>
<translation>未知ã®ç¨®é¡žã®ãƒ‡ãƒãƒƒã‚¬ &quot;%1&quot;</translation>
</message>
@@ -36847,6 +43840,10 @@ Affected are breakpoints %1</source>
<translation>&quot;Form&quot; ページ㮠&quot;data&quot; ã¯æœªè¨­å®šã‹ç©ºã‚ªãƒ–ジェクトã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Choose Project File</source>
+ <translation type="unfinished">プロジェクトファイルをé¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
<source>Check whether a variable exists.&lt;br&gt;Returns &quot;true&quot; if it does and an empty string if not.</source>
<translation>変数ãŒå­˜åœ¨ã™ã‚‹ã‹ã©ã†ã‹ã‚’確èªã—ã¾ã™ã€‚&lt;br&gt;存在ã™ã‚‹å ´åˆã¯ &quot;true&quot; ã‚’ã€å­˜åœ¨ã—ãªã„å ´åˆã¯ç©ºæ–‡å­—列を返ã—ã¾ã™ã€‚</translation>
</message>
@@ -37006,7 +44003,7 @@ Affected are breakpoints %1</source>
</message>
<message>
<source>Header file:</source>
- <translation>ヘッダーファイル:</translation>
+ <translation>ヘッダファイル:</translation>
</message>
<message>
<source>%{JS: Cpp.classToFileName(&apos;%{Class}&apos;, &apos;%{JS: Util.preferredSuffix(&apos;text/x-c++src&apos;)}&apos;)}</source>
@@ -37038,7 +44035,7 @@ Affected are breakpoints %1</source>
</message>
<message>
<source>Creates a C++ header and a source file for a new class that you can add to a C++ project.</source>
- <translation>プロジェクトã¸è¿½åŠ ã™ã‚‹ C++ ã®æ–°ã—ã„クラス用ã®ãƒ˜ãƒƒãƒ€ãƒ¼ã¨ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’作æˆã—ã¾ã™ã€‚</translation>
+ <translation>プロジェクトã¸è¿½åŠ ã™ã‚‹ C++ ã®æ–°ã—ã„クラス用ã®ãƒ˜ãƒƒãƒ€ã¨ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’作æˆã—ã¾ã™ã€‚</translation>
</message>
<message>
<source>C++</source>
@@ -37050,7 +44047,7 @@ Affected are breakpoints %1</source>
</message>
<message>
<source>Customize header row</source>
- <translation>ヘッダー行ã®ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚º</translation>
+ <translation>ヘッダ行ã®ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚º</translation>
</message>
<message>
<source>Items are editable</source>
@@ -37269,6 +44266,22 @@ Affected are breakpoints %1</source>
<translation>プロジェクトパス</translation>
</message>
<message>
+ <source>Google Test</source>
+ <translation>Google Test</translation>
+ </message>
+ <message>
+ <source>Qt Quick Test</source>
+ <translation>Qt Quick Test</translation>
+ </message>
+ <message>
+ <source>Boost Test</source>
+ <translation>Boost Test</translation>
+ </message>
+ <message>
+ <source>Test framework:</source>
+ <translation>テストフレームワーク:</translation>
+ </message>
+ <message>
<source>qmake</source>
<translation>qmake</translation>
</message>
@@ -37465,10 +44478,170 @@ Preselects a desktop Qt for building the application if available.</source>
<translation>OpenGL/ES 2.0 ã®ã‚·ã‚§ãƒ¼ãƒ€è¨˜è¿°è¨€èªž(GLSL/ES)ã§ãƒãƒ¼ãƒ†ãƒƒã‚¯ã‚¹ã‚·ã‚§ãƒ¼ãƒ€ã‚’作æˆã—ã¾ã™ã€‚ãƒãƒ¼ãƒ†ãƒƒã‚¯ã‚¹ã‚·ã‚§ãƒ¼ãƒ€(頂点シェーダ)㯠OpenGL ã§æç”»ã•ã‚Œã‚‹ãƒãƒªã‚´ãƒ³ã‚„ã€ç‚¹ã€ç·šåˆ†ã®ä½ç½®ã‚„法線ã€ãƒ†ã‚¯ã‚¹ãƒãƒ£åº§æ¨™ã‚’変形ã—ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Specify basic information about the classes for which you want to generate skeleton source code files.</source>
+ <translation>ソースコードã®ã‚¹ã‚±ãƒ«ãƒˆãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’生æˆã—ãŸã„クラスã®åŸºæœ¬çš„ãªæƒ…報を指定ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Shared Library</source>
+ <translation>共有ライブラリ</translation>
+ </message>
+ <message>
+ <source>Statically Linked Library</source>
+ <translation>スタティックリンクライブラリ</translation>
+ </message>
+ <message>
+ <source>Qt Plugin</source>
+ <translation>Qt プラグイン</translation>
+ </message>
+ <message>
+ <source>Core</source>
+ <translation>Core</translation>
+ </message>
+ <message>
+ <source>Library</source>
+ <translation>ライブラリ</translation>
+ </message>
+ <message>
+ <source>C++ Library</source>
+ <translation>C++ ライブラリ</translation>
+ </message>
+ <message>
+ <source>Binary</source>
+ <translation>2進数</translation>
+ </message>
+ <message>
+ <source>Author:</source>
+ <translation>作æˆè€…:</translation>
+ </message>
+ <message>
+ <source>Description:</source>
+ <translation>説明:</translation>
+ </message>
+ <message>
+ <source>0.1.0</source>
+ <translation>0.1.0</translation>
+ </message>
+ <message>
+ <source>Version:</source>
+ <translation>ãƒãƒ¼ã‚¸ãƒ§ãƒ³:</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation type="unfinished">ãã®ä»–</translation>
+ </message>
+ <message>
+ <source>License:</source>
+ <translation>ライセンス:</translation>
+ </message>
+ <message>
+ <source>C</source>
+ <translation type="unfinished">C</translation>
+ </message>
+ <message>
+ <source>1.0.0</source>
+ <translation>1.0.0</translation>
+ </message>
+ <message>
+ <source>Project file:</source>
+ <translation>プロジェクトファイル:</translation>
+ </message>
+ <message>
+ <source>Object class-name:</source>
+ <translation>オブジェクトクラスå:</translation>
+ </message>
+ <message>
+ <source>URI:</source>
+ <translation>URI:</translation>
+ </message>
+ <message>
+ <source>Qt Quick 2 Extension Plugin</source>
+ <translation>Qt Quick 2 拡張プラグイン</translation>
+ </message>
+ <message>
+ <source>Qt 5.15</source>
+ <translation>Qt 5.15</translation>
+ </message>
+ <message>
+ <source>Qt 5.14</source>
+ <translation>Qt 5.14</translation>
+ </message>
+ <message>
+ <source>Qt 5.13</source>
+ <translation>Qt 5.13</translation>
+ </message>
+ <message>
+ <source>Qt 5.12</source>
+ <translation>Qt 5.12</translation>
+ </message>
+ <message>
+ <source>Qt 5.11</source>
+ <translation>Qt 5.11</translation>
+ </message>
+ <message>
+ <source>Qt 5.10</source>
+ <translation>Qt 5.10</translation>
+ </message>
+ <message>
+ <source>Qt 5.9</source>
+ <translation>Qt 5.9</translation>
+ </message>
+ <message>
+ <source>Qt 5.8</source>
+ <translation>Qt 5.8</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+ <message>
+ <source>This wizard generates a Qt Widgets Application project. The application derives by default from QApplication and includes an empty widget.</source>
+ <translation>ã“ã®ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã¯ Qt ウイジェットアプリケーションプロジェクトを生æˆã—ã¾ã™ã€‚アプリケーション㯠QApplication を使用ã—ã€ç©ºã®ã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆã‚’æŒã¡ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Form file:</source>
+ <translation>フォームファイル:</translation>
+ </message>
+ <message>
+ <source>Class Information</source>
+ <translation>クラス情報</translation>
+ </message>
+ <message>
+ <source>Qt Widgets Application</source>
+ <translation>Qt ウィジェットアプリケーション</translation>
+ </message>
+ <message>
<source>&quot;%{JS: Util.toNativeSeparators(&apos;%{TargetPath}&apos;)}&quot; exists in the filesystem.</source>
<translation>&quot;%{JS: Util.toNativeSeparators(&apos;%{TargetPath}&apos;)}&quot; ã¯æ—¢ã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚·ã‚¹ãƒ†ãƒ ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Plugin name:</source>
+ <translation>プラグインå:</translation>
+ </message>
+ <message>
+ <source>Vendor name:</source>
+ <translation>ベンダå:</translation>
+ </message>
+ <message>
+ <source>Copyright:</source>
+ <translation>Copyright:</translation>
+ </message>
+ <message>
+ <source>URL:</source>
+ <translation>URL:</translation>
+ </message>
+ <message>
+ <source>Qt Creator build:</source>
+ <translation>Qt Creator ビルド:</translation>
+ </message>
+ <message>
+ <source>Creates a custom Qt Creator plugin.</source>
+ <translation>独自㮠Qt Creator プラグインを作æˆã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Qt Creator Plugin</source>
+ <translation>Qt Creator プラグイン</translation>
+ </message>
+ <message>
<source>This wizard creates a simple Qmake based project with additional auto test skeleton.</source>
<translation>ã“ã®ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã¯è‡ªå‹•ãƒ†ã‚¹ãƒˆã®ã‚¹ã‚±ãƒ«ãƒˆãƒ³ãŒè¿½åŠ ã•ã‚ŒãŸã‚·ãƒ³ãƒ—ル㪠qmake ベースã®ãƒ—ロジェクトを作æˆã—ã¾ã™ã€‚</translation>
</message>
@@ -37884,6 +45057,10 @@ Preselects a desktop Qt for building the application if available.</source>
<translation>何行ã‹ã‚’スキップ...</translation>
</message>
<message>
+ <source>No difference.</source>
+ <translation>差分ãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
<source>No difference</source>
<translation>差分ãŒã‚ã‚Šã¾ã›ã‚“</translation>
</message>
@@ -38602,22 +45779,42 @@ Would you like to overwrite it?</source>
<translation>図をファイル&lt;br&gt;&quot;%1&quot;&lt;br&gt;ã¸ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
</message>
<message>
+ <source>New %1</source>
+ <translation>æ–°ã—ã„ %1</translation>
+ </message>
+ <message>
<source>Package</source>
<translation>パッケージ</translation>
</message>
<message>
+ <source>New Package</source>
+ <translation>æ–°ã—ã„パッケージ</translation>
+ </message>
+ <message>
<source>Component</source>
<translation>コンãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
</message>
<message>
+ <source>New Component</source>
+ <translation>æ–°ã—ã„コンãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+ <message>
<source>Class</source>
<translation>クラス</translation>
</message>
<message>
+ <source>New Class</source>
+ <translation>æ–°ã—ã„クラス</translation>
+ </message>
+ <message>
<source>Item</source>
<translation>アイテム</translation>
</message>
<message>
+ <source>New Item</source>
+ <translation>æ–°ã—ã„アイテム</translation>
+ </message>
+ <message>
<source>Annotation</source>
<translation>アノテーション</translation>
</message>
@@ -38901,12 +46098,14 @@ to project &quot;%2&quot;.</source>
<message>
<source>Path &quot;%1&quot; does not exist when checking Json wizard search paths.
</source>
- <translation>Json ウィザードã®æ¤œç´¢ãƒ‘スを確èªã—ã¾ã—ãŸãŒã€ãƒ‘ス &quot;%1&quot; ã¯å­˜åœ¨ã—ã¾ã›ã‚“。</translation>
+ <translation>Json ウィザードã®æ¤œç´¢ãƒ‘スを確èªã—ã¾ã—ãŸãŒã€ãƒ‘ス &quot;%1&quot; ã¯å­˜åœ¨ã—ã¾ã›ã‚“。
+</translation>
</message>
<message>
<source>Checking &quot;%1&quot; for %2.
</source>
- <translation>%2 å‘ã‘ã« &quot;%1&quot; を確èªã—ã¦ã„ã¾ã™ã€‚</translation>
+ <translation>%2 å‘ã‘ã« &quot;%1&quot; を確èªã—ã¦ã„ã¾ã™ã€‚
+</translation>
</message>
<message>
<source>* Failed to parse &quot;%1&quot;:%2:%3: %4
@@ -38934,7 +46133,7 @@ to project &quot;%2&quot;.</source>
</message>
<message>
<source>The platform selected for the wizard.</source>
- <translation>ã“ã®ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã§é¸æŠžã•ã‚ŒãŸãƒ—ラットフォームã§ã™ã€‚</translation>
+ <translation>ã“ã®ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã§é¸æŠžã—ãŸãƒ—ラットフォームã§ã™ã€‚</translation>
</message>
<message>
<source>The features available to this wizard.</source>
@@ -39084,6 +46283,14 @@ to project &quot;%2&quot;.</source>
<source>LLVM:</source>
<translation>LLVM:</translation>
</message>
+ <message>
+ <source>Initialization:</source>
+ <translation>åˆæœŸåŒ–:</translation>
+ </message>
+ <message>
+ <source>&amp;Compiler path:</source>
+ <translation>コンパイラã®ãƒ‘ス(&amp;C):</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::ClangToolChainFactory</name>
@@ -39103,6 +46310,10 @@ to project &quot;%2&quot;.</source>
<translation>プロジェクトå</translation>
</message>
<message>
+ <source>Kit is not valid.</source>
+ <translation>無効ãªã‚­ãƒƒãƒˆã€‚</translation>
+ </message>
+ <message>
<source>Incompatible Kit</source>
<translation>互æ›æ€§ã®ãªã„キット</translation>
</message>
@@ -39120,7 +46331,7 @@ to project &quot;%2&quot;.</source>
</message>
<message>
<source>Run configurations:</source>
- <translation>実行設定:</translation>
+ <translation>実行構æˆ:</translation>
</message>
<message>
<source>Partially Incompatible Kit</source>
@@ -39178,6 +46389,10 @@ to project &quot;%2&quot;.</source>
<source>Command line arguments:</source>
<translation>コマンドライン引数:</translation>
</message>
+ <message>
+ <source>Reset to Default</source>
+ <translation>既定ã«æˆ»ã™</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::SelectableFilesWidget</name>
@@ -39228,6 +46443,10 @@ These files are preserved.</source>
<source>Source directory</source>
<translation>ソースディレクトリ</translation>
</message>
+ <message>
+ <source>The currently active run configuration&apos;s name.</source>
+ <translation>ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªå®Ÿè¡Œæ§‹æˆã®åå‰ã§ã™ã€‚</translation>
+ </message>
</context>
<context>
<name>ProjectExplorer::Internal::WaitForStopDialog</name>
@@ -39513,7 +46732,7 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
</message>
<message>
<source>Invalid item.</source>
- <translation>無効ãªã‚¢ã‚¤ãƒ†ãƒ ã§ã™ã€‚</translation>
+ <translation type="vanished">無効ãªã‚¢ã‚¤ãƒ†ãƒ ã§ã™ã€‚</translation>
</message>
<message>
<source>Cannot find an implementation.</source>
@@ -39624,7 +46843,7 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
</message>
<message>
<source>Remove selected binding or connection.</source>
- <translation>é¸æŠžã•ã‚ŒãŸãƒã‚¤ãƒ³ãƒ‡ã‚£ãƒ³ã‚°ã‚„コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã€‚</translation>
+ <translation>é¸æŠžã—ãŸãƒã‚¤ãƒ³ãƒ‡ã‚£ãƒ³ã‚°ã‚„コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã€‚</translation>
</message>
</context>
<context>
@@ -40281,10 +47500,22 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
<source>Show Highlighter Options...</source>
<translation>ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚ªãƒ—ションã®è¡¨ç¤º...</translation>
</message>
+ <message>
+ <source>Download Definitions</source>
+ <translation>定義をダウンロード</translation>
+ </message>
</context>
<context>
<name>TextEditor::TextEditorWidget</name>
<message>
+ <source>Line: 9999, Col: 999</source>
+ <translation>行番å·: 9999, 列ä½ç½®: 999</translation>
+ </message>
+ <message>
+ <source>Line: %1, Col: %2</source>
+ <translation>行番å·: %1, 列ä½ç½®: %2</translation>
+ </message>
+ <message>
<source>Print Document</source>
<translation>ドキュメントã®å°åˆ·</translation>
</message>
@@ -40297,6 +47528,14 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
<translation>表示ã™ã‚‹ã«ã¯ãƒ†ã‚­ã‚¹ãƒˆãŒå¤§ãã™ãŽã¾ã™ (%1 MB)。</translation>
</message>
<message>
+ <source>&lt;b&gt;Error:&lt;/b&gt; Could not decode &quot;%1&quot; with &quot;%2&quot;-encoding. Editing not possible.</source>
+ <translation>&lt;b&gt;エラー:&lt;/b&gt; &quot;%1&quot; を文字コード &quot;%2&quot; ã§ã¯ãƒ‡ã‚³ãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚編集ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Select Encoding</source>
+ <translation>文字コードã®é¸æŠž</translation>
+ </message>
+ <message>
<source>Zoom: %1%</source>
<translation>拡大率: %1%</translation>
</message>
@@ -40343,6 +47582,10 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
<translation>ã‚„ã‚Šç›´ã™(&amp;R)</translation>
</message>
<message>
+ <source>&lt;line&gt;:&lt;column&gt;</source>
+ <translation>&lt;行&gt;:&lt;列&gt;</translation>
+ </message>
+ <message>
<source>Delete &amp;Line</source>
<translation>行削除(&amp;L)</translation>
</message>
@@ -40463,6 +47706,18 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
<translation>Ctrl+E, F2</translation>
</message>
<message>
+ <source>Ctrl+Shift+U</source>
+ <translation>Ctrl+Shift+U</translation>
+ </message>
+ <message>
+ <source>Rename Symbol Under Cursor</source>
+ <translation>カーソルä½ç½®ã®ã‚·ãƒ³ãƒœãƒ«ã®åå‰ã‚’変更ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Ctrl+Shift+R</source>
+ <translation>Ctrl+Shift+R</translation>
+ </message>
+ <message>
<source>Jump to File Under Cursor</source>
<translation>カーソルä½ç½®ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¸ç§»å‹•ã™ã‚‹</translation>
</message>
@@ -40848,6 +48103,10 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
<translation>外部ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã‚’読ã¿è¾¼ã‚€</translation>
</message>
<message>
+ <source>Open results in KCachegrind.</source>
+ <translation>KCachegrind ã§çµæžœã‚’é–‹ã。</translation>
+ </message>
+ <message>
<source>Request the dumping of profile information. This will update the Callgrind visualization.</source>
<translation>プロファイル情報ã®ãƒ€ãƒ³ãƒ—ã‚’è¦æ±‚ã—ã¾ã™ã€‚ãã®çµæžœ Callgrind ã®è¡¨ç¤ºãŒæ›´æ–°ã•ã‚Œã¾ã™ã€‚</translation>
</message>
@@ -40860,8 +48119,12 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
<translation>イベントログã®è¨˜éŒ²ã‚’一時åœæ­¢ã—ã¾ã™ã€‚イベントãŒã‚«ã‚¦ãƒ³ãƒˆã•ã‚Œãªã„為ã€ãƒ—ロファイリング中ã®ãƒ—ログラムã®å®Ÿè¡Œé€Ÿåº¦ãŒå‘上ã•ã‚Œã¾ã™ã€‚</translation>
</message>
<message>
+ <source>Discard Data</source>
+ <translation>データを破棄</translation>
+ </message>
+ <message>
<source>Go back one step in history. This will select the previously selected item.</source>
- <translation>履歴を1ã¤æˆ»ã—ã¾ã™ã€‚以å‰é¸æŠžã•ã‚Œã¦ã„ãŸã‚¢ã‚¤ãƒ†ãƒ ãŒé¸æŠžã•ã‚Œã¾ã™ã€‚</translation>
+ <translation>履歴を1ã¤æˆ»ã—ã¾ã™ã€‚以å‰é¸æŠžã—ãŸã‚¢ã‚¤ãƒ†ãƒ ãŒé¸æŠžã•ã‚Œã¾ã™ã€‚</translation>
</message>
<message>
<source>Go forward one step in history.</source>
@@ -41244,6 +48507,10 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
<source>Google Tests</source>
<translation>Google Tests</translation>
</message>
+ <message>
+ <source>Google Test</source>
+ <translation>Google Test</translation>
+ </message>
</context>
<context>
<name>GTestTreeItem</name>
@@ -41262,6 +48529,10 @@ Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドデ
<source>Qt Tests</source>
<translation>Qt テスト</translation>
</message>
+ <message>
+ <source>Qt Test</source>
+ <translation>Qt Test</translation>
+ </message>
</context>
<context>
<name>QuickTestFramework</name>
@@ -41414,6 +48685,14 @@ Output:
<source>CMake configuration set by the kit was overridden in the project.</source>
<translation>キットã§è¨­å®šã•ã‚ŒãŸ CMake 設定ã¯ãƒ—ロジェクトã§ä¸Šæ›¸ãã•ã‚Œã¾ã—ãŸã€‚</translation>
</message>
+ <message>
+ <source>Minimum Size Release</source>
+ <translation type="vanished">最å°ã‚µã‚¤ã‚ºãƒªãƒªãƒ¼ã‚¹</translation>
+ </message>
+ <message>
+ <source>Release with Debug Information</source>
+ <translation type="vanished">デãƒãƒƒã‚°æƒ…報付ãリリース</translation>
+ </message>
</context>
<context>
<name>CMakeProjectManager::Internal::CMakeEditorFactory</name>
@@ -41535,6 +48814,10 @@ Output:
<translation>ビルドディレクトリ &quot;%1&quot; ãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
</message>
<message>
+ <source>Working directory:</source>
+ <translation>作業ディレクトリ:</translation>
+ </message>
+ <message>
<source>Failed to delete the cache directory.</source>
<translation>キャッシュディレクトリã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
</message>
@@ -41628,6 +48911,10 @@ Output:
<context>
<name>QmlProfiler::Internal::FlameGraphModel</name>
<message>
+ <source>Could not re-read events from temporary trace file: %1</source>
+ <translation>一時的ãªãƒˆãƒ¬ãƒ¼ã‚¹ãƒ»ãƒ•ã‚¡ã‚¤ãƒ«ã‹ã‚‰ã‚¤ãƒ™ãƒ³ãƒˆã‚’å†èª­ã¿å–ã‚Šã§ãã¾ã›ã‚“ã§ã—ãŸ: %1</translation>
+ </message>
+ <message>
<source>Compile</source>
<translation>コンパイル</translation>
</message>
@@ -41658,6 +48945,14 @@ Output:
<source>Show Full Range</source>
<translation>全体を表示</translation>
</message>
+ <message>
+ <source>Flame Graph</source>
+ <translation>フレームグラフ</translation>
+ </message>
+ <message>
+ <source>Reset Flame Graph</source>
+ <translation>フレームグラフをリセットã™ã‚‹</translation>
+ </message>
</context>
<context>
<name>QmlProfiler::Internal::InputEventsModel</name>
@@ -41741,6 +49036,10 @@ Output:
<source>Mouse Event</source>
<translation>マウスイベント</translation>
</message>
+ <message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
</context>
<context>
<name>QmlProfiler::Internal::MemoryUsageModel</name>
@@ -41844,4 +49143,10653 @@ Output:
<translation>高ã•</translation>
</message>
</context>
+<context>
+ <name>AddImport</name>
+ <message>
+ <source>Select a Module to Add</source>
+ <translation>追加ã™ã‚‹ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’é¸æŠžã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ItemsView</name>
+ <message>
+ <source>Remove Module</source>
+ <translation>モジュールを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Expand All</source>
+ <translation>ã™ã¹ã¦å±•é–‹</translation>
+ </message>
+ <message>
+ <source>Collapse All</source>
+ <translation>ã™ã¹ã¦æŠ˜ã‚ŠãŸãŸã‚€</translation>
+ </message>
+ <message>
+ <source>Import Module: </source>
+ <translation type="vanished">モジュールをインãƒãƒ¼ãƒˆã™ã‚‹: </translation>
+ </message>
+</context>
+<context>
+ <name>LibraryHeader</name>
+ <message>
+ <source>Components</source>
+ <translation>コンãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Add Module</source>
+ <translation>モジュールを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Assets</source>
+ <translation>アセット</translation>
+ </message>
+ <message>
+ <source>Add new assets to project.</source>
+ <translation>プロジェクトã«æ–°ã—ã„アセットを追加ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Search</source>
+ <translation>検索</translation>
+ </message>
+</context>
+<context>
+ <name>ColorCheckButton</name>
+ <message>
+ <source>Toggle color picker view.</source>
+ <translation>カラーピッカーã®è¡¨ç¤ºã‚’切り替ãˆã‚‹ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>ComponentButton</name>
+ <message>
+ <source>This item is an instance of a Component</source>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã€ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã§ã™</translation>
+ </message>
+ <message>
+ <source>Edit Master Component</source>
+ <translation type="vanished">マスターコンãƒãƒ¼ãƒãƒ³ãƒˆã®ç·¨é›†</translation>
+ </message>
+</context>
+<context>
+ <name>ExtendedFunctionLogic</name>
+ <message>
+ <source>Reset</source>
+ <translation>リセット</translation>
+ </message>
+ <message>
+ <source>Set Binding</source>
+ <translation>ãƒã‚¤ãƒ³ãƒ‡ã‚£ãƒ³ã‚°ã®è¨­å®š</translation>
+ </message>
+ <message>
+ <source>Export Property as Alias</source>
+ <translation>プロパティを別åã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Insert Keyframe</source>
+ <translation>キーフレームを挿入ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>GradientDialogPopup</name>
+ <message>
+ <source>Gradient Properties</source>
+ <translation>グラデーションã®ãƒ—ロパティ</translation>
+ </message>
+</context>
+<context>
+ <name>GradientPopupIndicator</name>
+ <message>
+ <source>Edit Gradient Properties</source>
+ <translation>グラデーションã®ãƒ—ロパティを編集ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>GradientPresetList</name>
+ <message>
+ <source>Gradient Picker</source>
+ <translation>グラデーションピッカー</translation>
+ </message>
+ <message>
+ <source>System Presets</source>
+ <translation>システムプリセット</translation>
+ </message>
+ <message>
+ <source>User Presets</source>
+ <translation>ユーザープリセット</translation>
+ </message>
+ <message>
+ <source>Delete preset?</source>
+ <translation>プリセットを削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to delete this preset?</source>
+ <translation>ã“ã®ã‚³ãƒ¼ãƒ‰ã‚¹ã‚¿ã‚¤ãƒ«ã‚’完全ã«å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Save</source>
+ <translation>ä¿å­˜</translation>
+ </message>
+ <message>
+ <source>Apply</source>
+ <translation>é©ç”¨</translation>
+ </message>
+</context>
+<context>
+ <name>ItemFilterComboBox</name>
+ <message>
+ <source>[None]</source>
+ <translation>[ãªã—]</translation>
+ </message>
+</context>
+<context>
+ <name>Label</name>
+ <message>
+ <source>This property is not available in this configuration.</source>
+ <translation>ã“ã®ãƒ—ロパティã¯æœ¬è¨­å®šã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>MarginSection</name>
+ <message>
+ <source>Margin</source>
+ <translation>マージン</translation>
+ </message>
+ <message>
+ <source>Vertical</source>
+ <translation>åž‚ç›´æ–¹å‘</translation>
+ </message>
+ <message>
+ <source>Top</source>
+ <translation>最上部</translation>
+ </message>
+ <message>
+ <source>The margin above the item.</source>
+ <translation>アイテムã®ä¸Šã®ãƒžãƒ¼ã‚¸ãƒ³ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Bottom</source>
+ <translation>下</translation>
+ </message>
+ <message>
+ <source>The margin below the item.</source>
+ <translation>アイテムã®ä¸‹ã®ãƒžãƒ¼ã‚¸ãƒ³ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Horizontal</source>
+ <translation>水平方å‘</translation>
+ </message>
+ <message>
+ <source>Left</source>
+ <translation>å·¦</translation>
+ </message>
+ <message>
+ <source>The margin left of the item.</source>
+ <translation>アイテムã®å·¦ã®ãƒžãƒ¼ã‚¸ãƒ³ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Right</source>
+ <translation>å³</translation>
+ </message>
+ <message>
+ <source>The margin right of the item.</source>
+ <translation>アイテムã®å³ã®ãƒžãƒ¼ã‚¸ãƒ³ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Margins</source>
+ <translation>マージン</translation>
+ </message>
+ <message>
+ <source>The margins around the item.</source>
+ <translation>アイテムã®å‘¨ã‚Šã®ãƒžãƒ¼ã‚¸ãƒ³ã§ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>AlignDistributeSection</name>
+ <message>
+ <source>Align</source>
+ <translation>整列</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>警告</translation>
+ </message>
+</context>
+<context>
+ <name>AnimationSection</name>
+ <message>
+ <source>Running</source>
+ <translation>実行中</translation>
+ </message>
+ <message>
+ <source>Duration</source>
+ <translation>æŒç¶šæ™‚é–“</translation>
+ </message>
+</context>
+<context>
+ <name>AnimationTargetSection</name>
+ <message>
+ <source>Target</source>
+ <translation>ターゲット</translation>
+ </message>
+ <message>
+ <source>Property</source>
+ <translation>プロパティ</translation>
+ </message>
+ <message>
+ <source>Properties</source>
+ <translation>プロパティ</translation>
+ </message>
+</context>
+<context>
+ <name>ConnectionsSpecifics</name>
+ <message>
+ <source>Connections</source>
+ <translation>コãƒã‚¯ã‚·ãƒ§ãƒ³</translation>
+ </message>
+ <message>
+ <source>Target</source>
+ <translation>ターゲット</translation>
+ </message>
+</context>
+<context>
+ <name>DialogSpecifics</name>
+ <message>
+ <source>Dialog</source>
+ <translation>ダイアログ</translation>
+ </message>
+ <message>
+ <source>Title</source>
+ <translation>タイトル</translation>
+ </message>
+</context>
+<context>
+ <name>DrawerSpecifics</name>
+ <message>
+ <source>Drag Margin</source>
+ <translation>ドラッグã®ãƒžãƒ¼ã‚¸ãƒ³</translation>
+ </message>
+</context>
+<context>
+ <name>PopupSection</name>
+ <message>
+ <source>Popup</source>
+ <translation>ãƒãƒƒãƒ—アップ</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>サイズ</translation>
+ </message>
+ <message>
+ <source>Visibility</source>
+ <translation>å¯è¦–性</translation>
+ </message>
+ <message>
+ <source>Is visible</source>
+ <translation>表示</translation>
+ </message>
+ <message>
+ <source>Clip</source>
+ <translation>クリッピング</translation>
+ </message>
+ <message>
+ <source>Behavior</source>
+ <translation>動作</translation>
+ </message>
+ <message>
+ <source>Modal</source>
+ <translation>モデル</translation>
+ </message>
+ <message>
+ <source>Opacity</source>
+ <translation>ä¸é€æ˜Žåº¦</translation>
+ </message>
+ <message>
+ <source>Scale</source>
+ <translation>å€çŽ‡</translation>
+ </message>
+ <message>
+ <source>Spacing</source>
+ <translation>é–“éš”</translation>
+ </message>
+</context>
+<context>
+ <name>LayerSection</name>
+ <message>
+ <source>Format</source>
+ <translation>フォーマット</translation>
+ </message>
+ <message>
+ <source>Mipmap</source>
+ <translation type="unfinished">ミップマップ</translation>
+ </message>
+ <message>
+ <source>Smooth</source>
+ <translation>スムーズ</translation>
+ </message>
+ <message>
+ <source>Wrap mode</source>
+ <translation>折り返ã—</translation>
+ </message>
+</context>
+<context>
+ <name>NumberAnimationSpecifics</name>
+ <message>
+ <source>From</source>
+ <translation>From</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>To</translation>
+ </message>
+</context>
+<context>
+ <name>PropertyActionSpecifics</name>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+</context>
+<context>
+ <name>StateSpecifics</name>
+ <message>
+ <source>State</source>
+ <translation>状態</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+</context>
+<context>
+ <name>Object3DPane</name>
+ <message>
+ <source>Component</source>
+ <translation type="unfinished">コンãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation type="unfinished">ID</translation>
+ </message>
+ <message>
+ <source>id</source>
+ <translation type="vanished">ID</translation>
+ </message>
+ <message>
+ <source>Toggles whether this item is exported as an alias property of the root item.</source>
+ <translation type="vanished">ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ルートアイテム㮠alias プロパティã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹ã‹ã©ã†ã‹ã‚’切りæ›ãˆã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>StatesDelegate</name>
+ <message>
+ <source>Edit Annotation</source>
+ <translation>アノテーションを編集ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add Annotation</source>
+ <translation>アノテーションを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove Annotation</source>
+ <translation>アノテーションを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+</context>
+<context>
+ <name>ADS::WorkspaceDialog</name>
+ <message>
+ <source>&amp;New</source>
+ <translation>æ–°è¦ä½œæˆ(&amp;N)</translation>
+ </message>
+ <message>
+ <source>&amp;Rename</source>
+ <translation>åå‰ã‚’変更(&amp;R)</translation>
+ </message>
+ <message>
+ <source>C&amp;lone</source>
+ <translation>複製(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Reset</source>
+ <translation>リセット</translation>
+ </message>
+ <message>
+ <source>&amp;Switch To</source>
+ <translation type="unfinished">切り替ãˆ(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Import</source>
+ <translation>インãƒãƒ¼ãƒˆ</translation>
+ </message>
+</context>
+<context>
+ <name>Utils::RemoveFileDialog</name>
+ <message>
+ <source>Remove File</source>
+ <translation>ファイルを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>File to remove:</source>
+ <translation>削除ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>&amp;Delete file permanently</source>
+ <translation>完全ã«å‰Šé™¤ã™ã‚‹(&amp;D)</translation>
+ </message>
+</context>
+<context>
+ <name>Android::Internal::AndroidSdkManagerWidget</name>
+ <message>
+ <source>Expand All</source>
+ <translation>ã™ã¹ã¦å±•é–‹</translation>
+ </message>
+ <message>
+ <source>Apply</source>
+ <translation type="unfinished">é©ç”¨</translation>
+ </message>
+ <message>
+ <source>Available</source>
+ <translation>利用å¯èƒ½</translation>
+ </message>
+ <message>
+ <source>Installed</source>
+ <translation>インストール済</translation>
+ </message>
+ <message>
+ <source>All</source>
+ <translation>ã™ã¹ã¦</translation>
+ </message>
+ <message>
+ <source>Advanced Options...</source>
+ <translation type="unfinished">詳細オプション...</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>キャンセル</translation>
+ </message>
+</context>
+<context>
+ <name>BoostSettingsPage</name>
+ <message>
+ <source>Seed:</source>
+ <translation>シード:</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::Internal::GTestSettingsPage</name>
+ <message>
+ <source>Executes disabled tests when performing a test run.</source>
+ <translation>テスト実行時ã«ç„¡åŠ¹åŒ–ã•ã‚ŒãŸãƒ†ã‚¹ãƒˆã‚‚実行ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Run disabled tests</source>
+ <translation>無効化ã•ã‚ŒãŸãƒ†ã‚¹ãƒˆã‚’実行ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Iterations:</source>
+ <translation>実行回数:</translation>
+ </message>
+ <message>
+ <source>Shuffle tests</source>
+ <translation>テストをシャッフルã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Repeats a test run (you might be required to increase the timeout to avoid canceling the tests).</source>
+ <translation>テストを繰り返ã—実行ã—ã¾ã™(テストãŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œãªã„よã†ã«ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã‚’é•·ãã™ã‚‹å¿…è¦ãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“)。</translation>
+ </message>
+ <message>
+ <source>Repeat tests</source>
+ <translation>テストを繰り返ã—実行ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Seed:</source>
+ <translation>シード:</translation>
+ </message>
+ <message>
+ <source>A seed of 0 generates a seed based on the current timestamp.</source>
+ <translation>シード㌠0 ã®å ´åˆã€ç¾åœ¨æ™‚刻ã‹ã‚‰ã‚·ãƒ¼ãƒ‰ãŒç”Ÿæˆã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Directory</source>
+ <translation>ディレクトリ</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::Internal::QtTestSettingsPage</name>
+ <message>
+ <source>Benchmark Metrics</source>
+ <translation>ベンãƒãƒžãƒ¼ã‚¯æ¸¬å®šåŸºæº–</translation>
+ </message>
+ <message>
+ <source>Uses walltime metrics for executing benchmarks (default).</source>
+ <translation>ベンãƒãƒžãƒ¼ã‚¯å®Ÿè¡Œæ™‚ã«å¾…ã¡æ™‚間を基準ã«ç”¨ã„ã¾ã™(既定)。</translation>
+ </message>
+ <message>
+ <source>Walltime</source>
+ <translation>ç·çµŒéŽæ™‚é–“</translation>
+ </message>
+ <message>
+ <source>Uses tick counter when executing benchmarks.</source>
+ <translation>ベンãƒãƒžãƒ¼ã‚¯å®Ÿè¡Œæ™‚ã«ãƒãƒƒã‚¯ã‚«ã‚¦ãƒ³ã‚¿ã‚’基準ã«ç”¨ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Tick counter</source>
+ <translation>ãƒãƒƒã‚¯ã‚«ã‚¦ãƒ³ã‚¿</translation>
+ </message>
+ <message>
+ <source>Uses event counter when executing benchmarks.</source>
+ <translation>ベンãƒãƒžãƒ¼ã‚¯å®Ÿè¡Œæ™‚ã«ã‚¤ãƒ™ãƒ³ãƒˆã‚«ã‚¦ãƒ³ã‚¿ã‚’基準ã«ç”¨ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Event counter</source>
+ <translation>イベントカウンタ</translation>
+ </message>
+ <message>
+ <source>Uses Valgrind Callgrind when executing benchmarks (it must be installed).</source>
+ <translation>ベンãƒãƒžãƒ¼ã‚¯å®Ÿè¡Œæ™‚ã« Valgrind Callgrind を用ã„ã¾ã™(インストールãŒå¿…è¦ã§ã™)。</translation>
+ </message>
+ <message>
+ <source>Callgrind</source>
+ <translation>Callgrind</translation>
+ </message>
+ <message>
+ <source>Uses Perf when executing benchmarks (it must be installed).</source>
+ <translation>ベンãƒãƒžãƒ¼ã‚¯å®Ÿè¡Œæ™‚ã« Perf を用ã„ã¾ã™(インストールãŒå¿…è¦ã§ã™)。</translation>
+ </message>
+ <message>
+ <source>Perf</source>
+ <translation>Perf</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal::ArtisticStyleOptionsPage</name>
+ <message>
+ <source>Configuration</source>
+ <translation>設定</translation>
+ </message>
+ <message>
+ <source>Artistic Style command:</source>
+ <translation>Artistic スタイルコマンド:</translation>
+ </message>
+ <message>
+ <source>Restrict to MIME types:</source>
+ <translation>制é™ã™ã‚‹ MIME タイプ:</translation>
+ </message>
+ <message>
+ <source>Options</source>
+ <translation>オプション</translation>
+ </message>
+ <message>
+ <source>Use file *.astylerc defined in project files</source>
+ <translation>プロジェクトファイルã«å®šç¾©ã•ã‚Œã¦ã„ã‚‹ *.astylerc ファイルを使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Use file .astylerc or astylerc in HOME</source>
+ <extracomment>HOME is replaced by the user&apos;s home directory</extracomment>
+ <translation>HOME ã«ã‚ã‚‹ .astylerc ã‹ astylerc ファイルを使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Use customized style:</source>
+ <translation>カスタムスタイルを使用ã™ã‚‹:</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal::ClangFormatOptionsPage</name>
+ <message>
+ <source>Options</source>
+ <translation>オプション</translation>
+ </message>
+ <message>
+ <source>Use customized style:</source>
+ <translation>カスタムスタイルを使用ã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>Use predefined style:</source>
+ <translation>定義済ã¿ã‚¹ã‚¿ã‚¤ãƒ«ã‚’使用ã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>Fallback style:</source>
+ <translation>フォールãƒãƒƒã‚¯ã‚¹ã‚¿ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Configuration</source>
+ <translation>設定</translation>
+ </message>
+ <message>
+ <source>Clang Format command:</source>
+ <translation>Clang Format コマンド:</translation>
+ </message>
+ <message>
+ <source>Restrict to MIME types:</source>
+ <translation>制é™ã™ã‚‹ MIME タイプ:</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal::UncrustifyOptionsPage</name>
+ <message>
+ <source>Configuration</source>
+ <translation>設定</translation>
+ </message>
+ <message>
+ <source>Uncrustify command:</source>
+ <translation>Uncrustify コマンド:</translation>
+ </message>
+ <message>
+ <source>Restrict to MIME types:</source>
+ <translation>制é™ã™ã‚‹ MIME タイプ:</translation>
+ </message>
+ <message>
+ <source>Options</source>
+ <translation>オプション</translation>
+ </message>
+ <message>
+ <source>Use file uncrustify.cfg defined in project files</source>
+ <translation>プロジェクトファイルã«å®šç¾©ã•ã‚Œã¦ã„ã‚‹ uncrustify.cfg ファイルを使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Use file specific uncrustify.cfg</source>
+ <translation>ファイル固有ã®uncrustify.cfgを使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Use file uncrustify.cfg in HOME</source>
+ <extracomment>HOME is replaced by the user&apos;s home directory</extracomment>
+ <translation>HOME ã«ã‚ã‚‹ uncrustify.cfg ファイルを使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Use customized style:</source>
+ <translation>カスタムスタイルを使用ã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>For action Format Selected Text</source>
+ <translation>é¸æŠžã—ãŸæ–‡å­—列を整形ã™ã‚‹ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ç”¨</translation>
+ </message>
+ <message>
+ <source>Format entire file if no text was selected</source>
+ <translation>未é¸æŠžæ™‚ã«ã¯ãƒ•ã‚¡ã‚¤ãƒ«å…¨ä½“ã‚’æ•´å½¢ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ClangFormat::ClangFormatConfigWidget</name>
+ <message>
+ <source>Format instead of indenting</source>
+ <translation>インデントã®ä»£ã‚ã‚Šã«ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã‚’è¡Œã†</translation>
+ </message>
+ <message>
+ <source>Format while typing</source>
+ <translation>入力中ã«ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Format edited code on file save</source>
+ <translation>編集ã—ãŸã‚³ãƒ¼ãƒ‰ã‚’ファイルä¿å­˜æ™‚ã«ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Override Clang Format configuration file</source>
+ <translation>Clang Format ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’上書ãã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Fallback configuration</source>
+ <translation>フォールãƒãƒƒã‚¯è¨­å®š</translation>
+ </message>
+ <message>
+ <source>Apply</source>
+ <translation>é©ç”¨</translation>
+ </message>
+ <message>
+ <source>Override Clang Format configuration file with the fallback configuration.</source>
+ <translation>Clang Format 設定ファイルをフォールãƒãƒƒã‚¯è¨­å®šã§ä¸Šæ›¸ãã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Current project has its own overridden .clang-format file and can be configured in Projects &gt; Code Style &gt; C++.</source>
+ <translation>ç¾åœ¨ã®ãƒ—ロジェクトã«ã¯ã€ç‹¬è‡ªã®ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã•ã‚ŒãŸ.clang-formatファイルãŒã‚ã‚Šã€ã€Œãƒ—ロジェクトã€&gt;「コードスタイルã€&gt;「C++ã€ã§è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Error in ClangFormat configuration</source>
+ <translation>Clang Format 設定ã§ã®ã‚¨ãƒ©ãƒ¼</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::ProjectSettingsWidget</name>
+ <message>
+ <source>Use Global Settings</source>
+ <translation>グローãƒãƒ«è¨­å®šã‚’使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Use Customized Settings</source>
+ <translation>カスタム設定を使用ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove Selected</source>
+ <translation>é¸æŠžé …目を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove All</source>
+ <translation>ã™ã¹ã¦å‰Šé™¤</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::ClazyChecks</name>
+ <message>
+ <source>Filters</source>
+ <translation type="unfinished">フィルタ</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::FilterDialog</name>
+ <message>
+ <source>Select All</source>
+ <translation>ã™ã¹ã¦ã‚’é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Clear Selection</source>
+ <translation>é¸æŠžçŠ¶æ…‹ã‚’解除</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::RunSettingsWidget</name>
+ <message>
+ <source>Parallel jobs:</source>
+ <translation>並列ジョブ数:</translation>
+ </message>
+</context>
+<context>
+ <name>FilePropertiesDialog</name>
+ <message>
+ <source>Group:</source>
+ <translation>グループ:</translation>
+ </message>
+ <message>
+ <source>Size:</source>
+ <translation>サイズ:</translation>
+ </message>
+ <message>
+ <source>Name:</source>
+ <translation>åå‰:</translation>
+ </message>
+ <message>
+ <source>Path:</source>
+ <translation>パス:</translation>
+ </message>
+ <message>
+ <source>Executable:</source>
+ <translation>実行ファイル:</translation>
+ </message>
+ <message>
+ <source>Undefined</source>
+ <translation>未定義</translation>
+ </message>
+</context>
+<context>
+ <name>Core::Internal::UrlFilterOptions</name>
+ <message>
+ <source>Name:</source>
+ <translation>åå‰:</translation>
+ </message>
+ <message>
+ <source>Move Up</source>
+ <translation>上ã«ç§»å‹•</translation>
+ </message>
+ <message>
+ <source>Move Down</source>
+ <translation>下ã«ç§»å‹•</translation>
+ </message>
+</context>
+<context>
+ <name>CppQuickFixProjectSettingsWidget</name>
+ <message>
+ <source>Form</source>
+ <translation type="vanished">フォーム</translation>
+ </message>
+</context>
+<context>
+ <name>CppQuickFixSettingsWidget</name>
+ <message>
+ <source>Form</source>
+ <translation type="vanished">フォーム</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+ <message>
+ <source>lines</source>
+ <translation>行</translation>
+ </message>
+ <message>
+ <source>Types:</source>
+ <translation>åž‹:</translation>
+ </message>
+</context>
+<context>
+ <name>CppTools::ClangBaseChecks</name>
+ <message>
+ <source>For appropriate options, consult the GCC or Clang manual pages or the &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html&quot;&gt;GCC online documentation&lt;/a&gt;.</source>
+ <translation>オプションã®è©³ç´°ã¯ GCC ã‚„ Clang ã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã€ã¾ãŸã¯ &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html&quot;&gt;GCC ã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ&lt;/a&gt; ã‚’å‚ç…§ã—ã¦ãã ã•ã„。</translation>
+ </message>
+</context>
+<context>
+ <name>Designer::Internal::NewClassWidget</name>
+ <message>
+ <source>&amp;Class name:</source>
+ <translation>クラスå(&amp;C):</translation>
+ </message>
+ <message>
+ <source>&amp;Base class:</source>
+ <translation>基底クラス(&amp;B):</translation>
+ </message>
+ <message>
+ <source>&amp;Type information:</source>
+ <translation>型情報(&amp;T):</translation>
+ </message>
+ <message>
+ <source>Inherits QObject</source>
+ <translation>QObject を継承</translation>
+ </message>
+ <message>
+ <source>Inherits QWidget</source>
+ <translation>QWidget を継承</translation>
+ </message>
+ <message>
+ <source>Inherits QDeclarativeItem - Qt Quick 1</source>
+ <translation>QDeclarativeItem を継承 - Qt Quick 1</translation>
+ </message>
+ <message>
+ <source>Inherits QQuickItem - Qt Quick 2</source>
+ <translation>QQuickItem を継承 - Qt Quick 2</translation>
+ </message>
+ <message>
+ <source>Based on QSharedData</source>
+ <translation>QSharedData ã«åŸºã¥ã</translation>
+ </message>
+ <message>
+ <source>&amp;Header file:</source>
+ <translation>ヘッダファイル(&amp;H):</translation>
+ </message>
+ <message>
+ <source>&amp;Source file:</source>
+ <translation>ソースファイル(&amp;S):</translation>
+ </message>
+ <message>
+ <source>&amp;Form file:</source>
+ <translation>フォームファイル(&amp;F):</translation>
+ </message>
+ <message>
+ <source>&amp;Path:</source>
+ <translation>パス(&amp;P):</translation>
+ </message>
+ <message>
+ <source>Invalid header file name: &quot;%1&quot;</source>
+ <translation>無効ãªãƒ˜ãƒƒãƒ€ãƒ•ã‚¡ã‚¤ãƒ«å: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Invalid source file name: &quot;%1&quot;</source>
+ <translation>無効ãªã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«å: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Invalid form file name: &quot;%1&quot;</source>
+ <translation>無効ãªãƒ•ã‚©ãƒ¼ãƒ ãƒ•ã‚¡ã‚¤ãƒ«å: &quot;%1&quot;</translation>
+ </message>
+</context>
+<context>
+ <name>Gerrit::Internal::AuthenticationDialog</name>
+ <message>
+ <source>Authentication</source>
+ <translation>èªè¨¼æƒ…å ±</translation>
+ </message>
+ <message>
+ <source>&amp;User:</source>
+ <translation>ユーザー(&amp;U):</translation>
+ </message>
+ <message>
+ <source>&amp;Password:</source>
+ <translation>パスワード(&amp;P):</translation>
+ </message>
+</context>
+<context>
+ <name>Ios::Internal::CreateSimulatorDialog</name>
+ <message>
+ <source>Device type:</source>
+ <translation>デãƒã‚¤ã‚¹ç¨®é¡ž:</translation>
+ </message>
+</context>
+<context>
+ <name>Ios::Internal::IosSettingsWidget</name>
+ <message>
+ <source>iOS Configuration</source>
+ <translation>iOS 設定</translation>
+ </message>
+ <message>
+ <source>Devices</source>
+ <translation>デãƒã‚¤ã‚¹</translation>
+ </message>
+ <message>
+ <source>Ask about devices not in developer mode</source>
+ <translation>デãƒã‚¤ã‚¹ãŒãƒ‡ãƒ™ãƒ­ãƒƒãƒ‘ーモードã‹ã©ã†ã‹ç¢ºèªã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Rename</source>
+ <translation>åå‰ã‚’変更</translation>
+ </message>
+ <message>
+ <source>Reset</source>
+ <translation>リセット</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>生æˆ</translation>
+ </message>
+ <message>
+ <source>Start</source>
+ <translation>開始</translation>
+ </message>
+ <message>
+ <source>iOS</source>
+ <translation>iOS</translation>
+ </message>
+</context>
+<context>
+ <name>Ios::Internal::SimulatorOperationDialog</name>
+ <message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::MesonBuildSettingsWidget</name>
+ <message>
+ <source>Apply Configuration Changes</source>
+ <translation>設定ã®å¤‰æ›´ã‚’é©ç”¨</translation>
+ </message>
+ <message>
+ <source>Filter</source>
+ <translation>フィルタ</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::ToolItemSettings</name>
+ <message>
+ <source>Name:</source>
+ <translation>åå‰:</translation>
+ </message>
+ <message>
+ <source>Path:</source>
+ <translation>パス:</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::ToolsSettingsWidget</name>
+ <message>
+ <source>Clone</source>
+ <translation>複製</translation>
+ </message>
+ <message>
+ <source>Make Default</source>
+ <translation>既定ã«ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::NimToolsSettingsWidget</name>
+ <message>
+ <source>Path</source>
+ <translation>パス</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfiler::Internal::PerfConfigWidget</name>
+ <message>
+ <source>Additional arguments:</source>
+ <translation>追加ã®å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>Reset</source>
+ <translation>リセット</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfiler::Internal::PerfLoadDialog</name>
+ <message>
+ <source>&amp;Browse...</source>
+ <translation type="unfinished">å‚ç…§(&amp;B)...</translation>
+ </message>
+ <message>
+ <source>Kit:</source>
+ <translation>キット:</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AssetExportDialog</name>
+ <message>
+ <source>Open</source>
+ <translation>é–‹ã</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AnnotationCommentTab</name>
+ <message>
+ <source>Title</source>
+ <translation>タイトル</translation>
+ </message>
+ <message>
+ <source>Text</source>
+ <translation>テキスト</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AnnotationEditorDialog</name>
+ <message>
+ <source>Annotation</source>
+ <translation type="vanished">アノテーション</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::GlobalAnnotationEditorDialog</name>
+ <message>
+ <source>Annotation</source>
+ <translation type="vanished">アノテーション</translation>
+ </message>
+ <message>
+ <source>Tab View</source>
+ <translation type="unfinished">タブビュー</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::Internal::AssetImportUpdateDialog</name>
+ <message>
+ <source>Select Files to Update</source>
+ <translation>æ›´æ–°ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Expand All</source>
+ <translation>ã™ã¹ã¦å±•é–‹</translation>
+ </message>
+ <message>
+ <source>Collapse All</source>
+ <translation>ã™ã¹ã¦æŠ˜ã‚ŠãŸãŸã‚€</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::ItemLibraryAssetImportDialog</name>
+ <message>
+ <source>Import</source>
+ <translation>インãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>キャンセル</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>é–‰ã˜ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::HyperlinkDialog</name>
+ <message>
+ <source>Link</source>
+ <translation>リンク</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::SetFrameValueDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>ダイアログ</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TimelineAnimationForm</name>
+ <message>
+ <source>Invalid Id</source>
+ <translation>無効㪠ID</translation>
+ </message>
+ <message>
+ <source>%1 is an invalid id.</source>
+ <translation>%1 ã¯ç„¡åŠ¹ãª id ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>%1 already exists.</source>
+ <translation>%1 ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TimelineForm</name>
+ <message>
+ <source>Invalid Id</source>
+ <translation>無効㪠ID</translation>
+ </message>
+ <message>
+ <source>%1 is an invalid id.</source>
+ <translation>%1 ã¯ç„¡åŠ¹ãª id ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>%1 already exists.</source>
+ <translation>%1 ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TransitionEditorSettingsDialog</name>
+ <message>
+ <source>Add Transition</source>
+ <translation type="unfinished">トランジションを追加ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>QmlJSEditor::Internal::QmlJsEditingSettingsPage</name>
+ <message>
+ <source>Qt Quick Toolbars</source>
+ <translation>Qt Quick ツールãƒãƒ¼</translation>
+ </message>
+ <message>
+ <source>If enabled, the toolbar will remain pinned to an absolute position.</source>
+ <translation>有効ã«ãªã£ã¦ã„ã‚‹å ´åˆã€ãƒ„ールãƒãƒ¼ã¯çµ¶å¯¾ä½ç½®ã«å›ºå®šã•ã‚ŒãŸã¾ã¾ã«ãªã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Pin Qt Quick Toolbar</source>
+ <translation>Qt Quick ツールãƒãƒ¼ã‚’固定ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Always show Qt Quick Toolbar</source>
+ <translation>常㫠Qt Quick ツールãƒãƒ¼ã‚’表示ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Automatic Formatting on File Save</source>
+ <translation>ファイルä¿å­˜æ™‚ã«è‡ªå‹•çš„ã«æ•´å½¢ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Enable auto format on file save</source>
+ <translation>ファイルä¿å­˜æ™‚ã®è‡ªå‹•æ•´å½¢ã‚’有効ã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Restrict to files contained in the current project</source>
+ <translation>ç¾åœ¨ã®ãƒ—ロジェクトã«å«ã¾ã‚Œã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã®ã¿ã«åˆ¶é™ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Features</source>
+ <translation type="unfinished">機能</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::ColorSettings</name>
+ <message>
+ <source>+</source>
+ <translation>+</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::ColorThemeDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>ダイアログ</translation>
+ </message>
+ <message>
+ <source>OK</source>
+ <translation>OK</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>キャンセル</translation>
+ </message>
+ <message>
+ <source>Apply</source>
+ <translation type="unfinished">é©ç”¨</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::NavigatorSlider</name>
+ <message>
+ <source>+</source>
+ <translation>+</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::Search</name>
+ <message>
+ <source>Search</source>
+ <translation>検索</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::StateView</name>
+ <message>
+ <source>Back</source>
+ <translation>戻る</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::Statistics</name>
+ <message>
+ <source>Time</source>
+ <translation type="unfinished">タイム</translation>
+ </message>
+ <message>
+ <source>0</source>
+ <translation>0</translation>
+ </message>
+ <message>
+ <source>File</source>
+ <translation>ファイル</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::StatisticsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>ダイアログ</translation>
+ </message>
+ <message>
+ <source>OK</source>
+ <translation>OK</translation>
+ </message>
+</context>
+<context>
+ <name>main</name>
+ <message>
+ <source>Recent Projects</source>
+ <translation>最近使ã£ãŸãƒ—ロジェクト</translation>
+ </message>
+ <message>
+ <source>Examples</source>
+ <translation>サンプル</translation>
+ </message>
+ <message>
+ <source>Tutorials</source>
+ <translation>ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«</translation>
+ </message>
+ <message>
+ <source>Open Project</source>
+ <translation>プロジェクトを開ã</translation>
+ </message>
+ <message>
+ <source>Help</source>
+ <translation>ヘルプ</translation>
+ </message>
+ <message>
+ <source>Continue</source>
+ <translation type="unfinished">続行</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation type="unfinished">キャンセル</translation>
+ </message>
+ <message>
+ <source>Open</source>
+ <translation type="unfinished">é–‹ã</translation>
+ </message>
+ <message>
+ <source>Details</source>
+ <translation type="unfinished">詳細</translation>
+ </message>
+</context>
+<context>
+ <name>Welcome_splash</name>
+ <message>
+ <source>%</source>
+ <translation>%</translation>
+ </message>
+</context>
+<context>
+ <name>RangeDetails</name>
+ <message>
+ <source>View event information on mouseover.</source>
+ <translation>マウスオーãƒãƒ¼æ™‚ã«ã‚¤ãƒ™ãƒ³ãƒˆæƒ…報を表示ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>é–‰ã˜ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfilerFlameGraphView</name>
+ <message>
+ <source>Function</source>
+ <translation>関数</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>ソース</translation>
+ </message>
+ <message>
+ <source>Binary</source>
+ <translation>2進数</translation>
+ </message>
+ <message>
+ <source>Allocations</source>
+ <translation>確ä¿</translation>
+ </message>
+ <message>
+ <source>Various</source>
+ <translation>ãã®ä»–</translation>
+ </message>
+</context>
+<context>
+ <name>QmlProfilerFlameGraphView</name>
+ <message>
+ <source>Total Time</source>
+ <translation>åˆè¨ˆæ™‚é–“</translation>
+ </message>
+ <message>
+ <source>Calls</source>
+ <translation>呼出回数</translation>
+ </message>
+ <message>
+ <source>Details</source>
+ <translation>詳細</translation>
+ </message>
+ <message>
+ <source>Mean Time</source>
+ <translation>å¹³å‡æ™‚é–“</translation>
+ </message>
+ <message>
+ <source>In Percent</source>
+ <translation>割åˆ</translation>
+ </message>
+ <message>
+ <source>Location</source>
+ <translation>パス</translation>
+ </message>
+ <message>
+ <source>Allocations</source>
+ <translation>確ä¿</translation>
+ </message>
+ <message>
+ <source>Various Events</source>
+ <translation>å„種イベント</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Close Tab</source>
+ <translation>タブを閉ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>C++ Usages:</source>
+ <translation>C++ 出ç¾ç®‡æ‰€:</translation>
+ </message>
+ <message>
+ <source>&lt;Filter&gt;</source>
+ <comment>Library search input hint text</comment>
+ <translation>&lt;フィルタ&gt;</translation>
+ </message>
+ <message>
+ <source>MB</source>
+ <translation>MB</translation>
+ </message>
+</context>
+<context>
+ <name>ADS::DockAreaTitleBar</name>
+ <message>
+ <source>Detach Area</source>
+ <translation>エリアを切り離ã™</translation>
+ </message>
+ <message>
+ <source>Close Area</source>
+ <translation>エリアを閉ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close Other Areas</source>
+ <translation>ãã®ä»–ã®ã‚¨ãƒªã‚¢ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ADS::DockManager</name>
+ <message>
+ <source>Cannot Save Workspace</source>
+ <translation>ワークスペースをä¿å­˜ã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Could not save workspace to file %1</source>
+ <translation>ワークスペースをファイル%1 ã«ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Delete Workspace</source>
+ <translation>ワークスペースを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete Workspaces</source>
+ <translation>ワークスペースを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete workspace %1?</source>
+ <translation>ワークスペース %1 を削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Delete these workspaces?
+ %1</source>
+ <translation>ã“れらã®ãƒ¯ãƒ¼ã‚¯ã‚¹ãƒšãƒ¼ã‚¹ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ
+ %1</translation>
+ </message>
+ <message>
+ <source>Cannot Restore Workspace</source>
+ <translation>ワークスペースを復元ã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Could not restore workspace %1</source>
+ <translation>ワークスペース %1 を復元ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
+ </message>
+</context>
+<context>
+ <name>Utils::FileSaverBase</name>
+ <message>
+ <source>File Error</source>
+ <translation>ファイルエラー</translation>
+ </message>
+</context>
+<context>
+ <name>ADS::DockWidgetTab</name>
+ <message>
+ <source>Detach</source>
+ <translation>切り離ã™</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close Others</source>
+ <translation>ä»–ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ADS::WorkspaceNameInputDialog</name>
+ <message>
+ <source>Enter the name of the workspace:</source>
+ <translation>ワークスペースã®åå‰ã‚’入力ã—ã¦ãã ã•ã„:</translation>
+ </message>
+</context>
+<context>
+ <name>ADS::WorkspaceModel</name>
+ <message>
+ <source>Workspace</source>
+ <translation>ワークスペース</translation>
+ </message>
+ <message>
+ <source>Last Modified</source>
+ <translation>最終変更日</translation>
+ </message>
+ <message>
+ <source>New Workspace Name</source>
+ <translation>æ–°ã—ã„ワークスペースå</translation>
+ </message>
+ <message>
+ <source>&amp;Create</source>
+ <translation>作æˆ(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Create and &amp;Open</source>
+ <translation>作æˆã—ã¦é–‹ã(&amp;O)</translation>
+ </message>
+ <message>
+ <source>&amp;Clone</source>
+ <translation>複製(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Clone and &amp;Open</source>
+ <translation>クローンã—ã¦é–‹ã(&amp;O)</translation>
+ </message>
+ <message>
+ <source>Rename Workspace</source>
+ <translation>ワークスペースã®åå‰å¤‰æ›´</translation>
+ </message>
+ <message>
+ <source>&amp;Rename</source>
+ <translation>åå‰ã‚’変更(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Rename and &amp;Open</source>
+ <translation>åå‰å¤‰æ›´ã—ã¦é–‹ã(&amp;O)</translation>
+ </message>
+</context>
+<context>
+ <name>ADS::WorkspaceView</name>
+ <message>
+ <source>Import Workspace</source>
+ <translation>ワークスペースをインãƒãƒ¼ãƒˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Export Workspace</source>
+ <translation>ワークスペースをエクスãƒãƒ¼ãƒˆã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ProcessCreator</name>
+ <message>
+ <source>Executable does not exist: %1</source>
+ <translation>実行ファイル ãŒå­˜åœ¨ã—ã¾ã›ã‚“ %1</translation>
+ </message>
+ <message>
+ <source>Unknown error occurred.</source>
+ <translation>ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Process crashed.</source>
+ <translation>プロセスãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Process failed at startup.</source>
+ <translation>起動時ã«ãƒ—ロセスãŒå¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Process timed out.</source>
+ <translation>プロセスãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Cannot write to process.</source>
+ <translation>プロセスã¸ã®æ›¸ãè¾¼ã¿ãŒã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Cannot read from process.</source>
+ <translation>プロセスã‹ã‚‰ã®èª­ã¿å–ã‚ŠãŒã§ãã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>ExtensionSystem::Internal::PluginManagerPrivate</name>
+ <message>
+ <source>%1 &gt; About Plugins</source>
+ <translation>%1 &gt; プラグインã«ã¤ã„ã¦</translation>
+ </message>
+ <message>
+ <source>Help &gt; About Plugins</source>
+ <translation>ヘルプ &gt; プラグインã«ã¤ã„ã¦</translation>
+ </message>
+ <message>
+ <source>The following plugins depend on %1 and are also disabled: %2.
+
+</source>
+ <translation>以下ã®ãƒ—ラグイン㯠%1 ã«ä¾å­˜ã—ã¦ã„ã‚‹ãŸã‚ã€ç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™: %2。
+
+</translation>
+ </message>
+ <message>
+ <source>Disable plugins permanently in %1.</source>
+ <translation>%1 ã§ãƒ—ラグインを常ã«ç„¡åŠ¹ã«ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>It looks like %1 closed because of a problem with the &quot;%2&quot; plugin. Temporarily disable the plugin?</source>
+ <translation>%1 ã¯ã€&quot;%2&quot; プラグインã®å•é¡Œã§é–‰ã˜ãŸã‚ˆã†ã§ã™ã€‚プラグインを一時的ã«ç„¡åŠ¹ã«ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Disable Plugin</source>
+ <translation>プラグインを無効ã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Continue</source>
+ <translation>続行</translation>
+ </message>
+</context>
+<context>
+ <name>BaseMessage</name>
+ <message>
+ <source>Cannot decode content with &quot;%1&quot;. Falling back to &quot;%2&quot;.</source>
+ <translation>コンテンツを &quot;%1&quot; ã§ãƒ‡ã‚³ãƒ¼ãƒ‰ã§ãã¾ã›ã‚“。&quot;%2&quot; ã«ãƒ•ã‚©ãƒ¼ãƒ«ãƒãƒƒã‚¯ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Expected an integer in &quot;%1&quot;, but got &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot; ã®ä¸­èº«ã¯æ•´æ•°ã‚’期待ã—ã¦ã„ã¾ã—ãŸãŒã€&quot;%2&quot; ã§ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageServerProtocol::JsonObject</name>
+ <message>
+ <source>Expected type %1 but value contained %2</source>
+ <translation>期待ã•ã‚Œã‚‹åž‹ã¯ %1 ã§ã™ãŒã€å€¤ã«ã¯ %2 ãŒå«ã¾ã‚Œã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
+ <source>None of the following variants could be correctly parsed:</source>
+ <translation>以下ã®ãƒ‡ãƒ¼ã‚¿ã®ã„ãšã‚Œã‚‚æ­£ã—ã解æžã§ãã¾ã›ã‚“ã§ã—ãŸ:</translation>
+ </message>
+</context>
+<context>
+ <name>JsonRpcMessageHandler</name>
+ <message>
+ <source>Could not parse JSON message &quot;%1&quot;.</source>
+ <translation>JSON メッセージ &quot;%1&quot; を解æžã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Expected a JSON object, but got a JSON &quot;%1&quot;.</source>
+ <translation>読ã¿è¾¼ã¾ã‚ŒãŸ JSON &quot;%1&quot; 㯠JSON オブジェクトã§ã¯ã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageServerProtocol::Notification</name>
+ <message>
+ <source>No parameters in &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; ã«ã¯ãƒ‘ラメータãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageClient::ResponseError</name>
+ <message>
+ <source>Error %1</source>
+ <translation>エラー: %1</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageServerProtocol::Request</name>
+ <message>
+ <source>No ID set in &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;ã« ID ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageServerProtocol::HoverContent</name>
+ <message>
+ <source>HoverContent should be either MarkedString, MarkupContent, or QList&lt;MarkedString&gt;.</source>
+ <translation>HoverContent ã¯ã€MarkedStringã€MarkupContentã€ã¾ãŸã¯ QList&lt;MarkedString&gt; ã®ã„ãšã‚Œã‹ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageServerProtocol::MarkedString</name>
+ <message>
+ <source>DocumentFormattingProperty should be either bool, double, or QString.</source>
+ <translation>DocumentFormattingProperty ã¯ã€boolã€doubleã€ã¾ãŸã¯ QString ã®ã„ãšã‚Œã‹ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageServerProtocoll::MarkupOrString</name>
+ <message>
+ <source>Expected a string or MarkupContent in MarkupOrString.</source>
+ <translation>MarkupOrString ã¯æ–‡å­—列ã¾ãŸã¯ MarkupContent ã«å¯¾å¿œã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>qmt::Exception</name>
+ <message>
+ <source>Unacceptable null object.</source>
+ <translation>å—付ä¸å¯èƒ½ãª null オブジェクトã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>File not found.</source>
+ <translation>ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Unable to create file.</source>
+ <translation>ファイルを作æˆã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Writing to file failed.</source>
+ <translation>ファイルã¸ã®æ›¸ãè¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Reading from file failed.</source>
+ <translation>ファイルã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Illegal XML file.</source>
+ <translation>無効㪠XML ファイルã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Unable to handle file version %1.</source>
+ <translation>%1 ã¯æœªçŸ¥ã®ãƒ•ã‚¡ã‚¤ãƒ«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDebug::QmlDebugConnectionManager</name>
+ <message>
+ <source>Debug connection opened.</source>
+ <translation>デãƒãƒƒã‚°æŽ¥ç¶šã‚’é–‹ãã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Debug connection closed.</source>
+ <translation>デãƒãƒƒã‚°æŽ¥ç¶šã‚’切断ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Debug connection failed.</source>
+ <translation>デãƒãƒƒã‚°æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QSsh::SftpSession</name>
+ <message>
+ <source>sftp failed to start: %1</source>
+ <translation>sftp ã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>sftp crashed.</source>
+ <translation>sftp ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Cannot establish SFTP session: sftp binary &quot;%1&quot; does not exist.</source>
+ <translation>SFTP セッションを確立ã§ãã¾ã›ã‚“: sftp ãƒã‚¤ãƒŠãƒª &quot;%1&quot; ãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>QSsh::SftpTransfer</name>
+ <message>
+ <source>sftp failed to start: %1</source>
+ <translation>sftp ã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>sftp crashed.</source>
+ <translation>sftp ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>sftp binary &quot;%1&quot; does not exist.</source>
+ <translation>sftp ãƒã‚¤ãƒŠãƒª &quot;%1&quot; ãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Could not create temporary file: %1</source>
+ <translation>一時ファイルを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Failed to create local directory &quot;%1&quot;.</source>
+ <translation>ローカルディレクトリ &quot;%1&quot; ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>File transfer failed: %1</source>
+ <translation>ファイル転é€ã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+</context>
+<context>
+ <name>QSsh::SshConnection</name>
+ <message>
+ <source>Cannot establish SSH connection: Control process failed to start: %1</source>
+ <translation>SSH 接続を確立ã§ãã¾ã›ã‚“。制御プロセスã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>SSH connection failure.</source>
+ <translation>SSH 接続エラー。</translation>
+ </message>
+ <message>
+ <source>Cannot establish SSH connection: ssh binary &quot;%1&quot; does not exist.</source>
+ <translation>SSH 接続を確立ã§ãã¾ã›ã‚“: ssh ãƒã‚¤ãƒŠãƒª &quot;%1&quot; ãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Cannot establish SSH connection: Failed to create temporary directory for control socket: %1</source>
+ <translation>SSH 接続を確立ã§ãã¾ã›ã‚“。制御ソケット用ã®ä¸€æ™‚ディレクトリã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+</context>
+<context>
+ <name>QSsh::SshRemoteProcess</name>
+ <message>
+ <source>The ssh process crashed: %1</source>
+ <translation>ssh プロセスãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Remote process crashed.</source>
+ <translation>リモートプロセスãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Timeline::TimelineTraceManager</name>
+ <message>
+ <source>Could not open %1 for writing.</source>
+ <translation>書ãè¾¼ã¿ç”¨ã« %1 ã‚’é–‹ã‘ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Could not open %1 for reading.</source>
+ <translation>読ã¿è¾¼ã¿ç”¨ã« %1 ã‚’é–‹ã‘ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Could not re-read events from temporary trace file: %1
+The trace data is lost.</source>
+ <translation>一時的ãªãƒˆãƒ¬ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‹ã‚‰ã‚¤ãƒ™ãƒ³ãƒˆã‚’å†èª­ã¿å–ã‚Šã§ãã¾ã›ã‚“ã§ã—ãŸ: %1
+トレースデータã¯å¤±ã‚ã‚Œã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Utils::Archive</name>
+ <message>
+ <source>File format not supported.</source>
+ <translation>未対応ã®ãƒ•ã‚¡ã‚¤ãƒ«å½¢å¼ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Could not find any unarchiving executable in PATH (%1).</source>
+ <translation>PATH (%1) ã«ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–展開用ã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Unarchiving File</source>
+ <translation>アーカイブ展開用ã®ãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message>
+ <source>Unzipping &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot; ã‚’ &quot;%2&quot; ã«å±•é–‹ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Command failed.</source>
+ <translation>コマンドãŒå¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Running %1
+in &quot;%2&quot;.
+
+</source>
+ <comment>Running &lt;cmd&gt; in &lt;workingdirectory&gt;</comment>
+ <translation>%2 㧠&quot;%1&quot; を実行ã—ã¦ã„ã¾ã™ã€‚
+
+</translation>
+ </message>
+</context>
+<context>
+ <name>Utils::TriStateAspect</name>
+ <message>
+ <source>Enable</source>
+ <translation>有効</translation>
+ </message>
+ <message>
+ <source>Disable</source>
+ <translation>無効化</translation>
+ </message>
+ <message>
+ <source>Leave at Default</source>
+ <translation>デフォルトã®ã¾ã¾ã§</translation>
+ </message>
+</context>
+<context>
+ <name>Utils::BaseTreeView</name>
+ <message>
+ <source>Show %1 Column</source>
+ <translation>%1 列を表示ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>Utils::InfoBarDisplay</name>
+ <message>
+ <source>Do Not Show Again</source>
+ <translation>今後ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>é–‰ã˜ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>JsonTreeModelItem</name>
+ <message>
+ <source>String</source>
+ <translation>文字列</translation>
+ </message>
+ <message>
+ <source>Object</source>
+ <translation>オブジェクト</translation>
+ </message>
+ <message>
+ <source>Undefined</source>
+ <translation>未定義</translation>
+ </message>
+</context>
+<context>
+ <name>Utils::NameValueModel</name>
+ <message>
+ <source>&lt;UNSET&gt;</source>
+ <translation>&lt;未定義&gt;</translation>
+ </message>
+ <message>
+ <source>Variable</source>
+ <translation>変数</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+ <message>
+ <source>&lt;VARIABLE&gt;</source>
+ <extracomment>Name when inserting a new variable</extracomment>
+ <translation>&lt;変数&gt;</translation>
+ </message>
+ <message>
+ <source>&lt;VALUE&gt;</source>
+ <extracomment>Value when inserting a new variable</extracomment>
+ <translation>&lt;値&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>StringUtils</name>
+ <message>
+ <source>Elapsed time: %1.</source>
+ <translation>経éŽæ™‚é–“: %1.</translation>
+ </message>
+</context>
+<context>
+ <name>Utils::VariableChooser</name>
+ <message>
+ <source>Insert Variable</source>
+ <translation>変数ã®æŒ¿å…¥</translation>
+ </message>
+ <message>
+ <source>Current Value: %1</source>
+ <translation>ç¾åœ¨å€¤: %1</translation>
+ </message>
+ <message>
+ <source>Insert Unexpanded Value</source>
+ <translation>展開å‰ã®å€¤ã®æŒ¿å…¥</translation>
+ </message>
+ <message>
+ <source>Insert &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®æŒ¿å…¥</translation>
+ </message>
+ <message>
+ <source>Insert Expanded Value</source>
+ <translation>展開後ã®å€¤ã®æŒ¿å…¥</translation>
+ </message>
+ <message>
+ <source>Select a variable to insert.</source>
+ <translation>挿入ã™ã‚‹å¤‰æ•°ã‚’é¸æŠžã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Variables</source>
+ <translation>変数</translation>
+ </message>
+</context>
+<context>
+ <name>AndroidAvdManager</name>
+ <message>
+ <source>Could not start process &quot;%1 %2&quot;</source>
+ <translation>プロセス &quot;%1 %2&quot; ã‚’èµ·å‹•ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
+ </message>
+</context>
+<context>
+ <name>Android::Internal::AndroidBuildApkStep</name>
+ <message>
+ <source>Application</source>
+ <translation>アプリケーション</translation>
+ </message>
+ <message>
+ <source>Android build SDK:</source>
+ <translation>Android SDK:</translation>
+ </message>
+ <message>
+ <source>Create Templates</source>
+ <translation>テンプレートã®ä½œæˆ</translation>
+ </message>
+ <message>
+ <source>Keystore:</source>
+ <translation>キーストア:</translation>
+ </message>
+ <message>
+ <source>Keystore files (*.keystore *.jks)</source>
+ <translation>キーストアファイル (*.keystore *.jks)</translation>
+ </message>
+ <message>
+ <source>Select Keystore File</source>
+ <translation>キーストアファイルã®é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Create...</source>
+ <translation>作æˆ...</translation>
+ </message>
+ <message>
+ <source>Sign package</source>
+ <translation>パッケージã«ç½²åã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Signing a debug package</source>
+ <translation>デãƒãƒƒã‚°ãƒ‘ッケージã«ç½²åã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Certificate alias:</source>
+ <translation>証明書エイリアス:</translation>
+ </message>
+ <message>
+ <source>Advanced Actions</source>
+ <translation>高度ãªã‚¢ã‚¯ã‚·ãƒ§ãƒ³</translation>
+ </message>
+ <message>
+ <source>Open package location after build</source>
+ <translation>ビルド後ã«ãƒ‘ッケージã®ãƒ‘スを開ã</translation>
+ </message>
+ <message>
+ <source>Verbose output</source>
+ <translation>詳細出力</translation>
+ </message>
+ <message>
+ <source>Additional Libraries</source>
+ <translation>追加ライブラリ</translation>
+ </message>
+ <message>
+ <source>List of extra libraries to include in Android package and load on startup.</source>
+ <translation>Android ã®ãƒ‘ッケージã«åŒæ¢±ã•ã‚Œèµ·å‹•æ™‚ã«èª­ã¿è¾¼ã¾ã‚Œã‚‹è¿½åŠ ãƒ©ã‚¤ãƒ–ラリã®ãƒªã‚¹ãƒˆã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Add...</source>
+ <translation>追加...</translation>
+ </message>
+ <message>
+ <source>Select library to include in package.</source>
+ <translation>パッケージã«åŒæ¢±ã™ã‚‹ãƒ©ã‚¤ãƒ–ラリをé¸æŠžã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Select additional libraries</source>
+ <translation>追加ライブラリã®é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Libraries (*.so)</source>
+ <translation>ライブラリ (*.so)</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>削除</translation>
+ </message>
+ <message>
+ <source>Remove currently selected library from list.</source>
+ <translation>ç¾åœ¨é¸æŠžã—ã¦ã„るライブラリをリストã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Build Android APK</source>
+ <translation>Android APK ã®ãƒ“ルド</translation>
+ </message>
+ <message>
+ <source>Warning: Signing a debug or profile package.</source>
+ <translation>警告: デãƒãƒƒã‚°ç”¨ã‚ã‚‹ã„ã¯ãƒ—ロファイル用パッケージを署åã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Starting: &quot;%1&quot; %2</source>
+ <translation>起動中: &quot;%1&quot; %2</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+ <message>
+ <source>Failed to run keytool.</source>
+ <translation>keytool ã®å®Ÿè¡Œã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Keystore</source>
+ <translation>キーストア</translation>
+ </message>
+ <message>
+ <source>Certificate</source>
+ <translation>証明書</translation>
+ </message>
+</context>
+<context>
+ <name>Android::Internal::AndroidManifestEditorIconWidget</name>
+ <message>
+ <source>Icon scaled up.</source>
+ <translation type="unfinished">アイコンをスケールアップ。</translation>
+ </message>
+ <message>
+ <source>Click to select...</source>
+ <translation type="unfinished">クリックã—ã¦é¸æŠž...</translation>
+ </message>
+</context>
+<context>
+ <name>Android::AndroidPackageInstallationStep</name>
+ <message>
+ <source>Copy application data</source>
+ <translation>アプリケーションデータã®ã‚³ãƒ”ー</translation>
+ </message>
+ <message>
+ <source>Removing directory %1</source>
+ <translation>ディレクトリ %1 を削除ã—ã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Deploy to device</source>
+ <translation>デãƒã‚¤ã‚¹ã«ãƒ‡ãƒ—ロイ</translation>
+ </message>
+</context>
+<context>
+ <name>Android::AndroidRunConfiguration</name>
+ <message>
+ <source>Clean Environment</source>
+ <translation>環境変数ãªã—</translation>
+ </message>
+</context>
+<context>
+ <name>Android::Internal::AndroidRunnerWorker</name>
+ <message>
+ <source>No free ports available on host for QML debugging.</source>
+ <translation>ホスト㫠QML デãƒãƒƒã‚°ç”¨ã®ç©ºããƒãƒ¼ãƒˆãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>&quot;%1&quot; died.</source>
+ <translation>&quot;%1&quot; ã¯ç•°å¸¸çµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Android::Internal::AndroidSdkDownloader</name>
+ <message>
+ <source>Cancel</source>
+ <translation>キャンセル</translation>
+ </message>
+</context>
+<context>
+ <name>AndroidSdkManager</name>
+ <message>
+ <source>Failed.</source>
+ <translation>失敗ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Failed</source>
+ <translation>失敗</translation>
+ </message>
+</context>
+<context>
+ <name>Android::Internal::AndroidSdkModel</name>
+ <message>
+ <source>Package</source>
+ <translation>パッケージ</translation>
+ </message>
+ <message>
+ <source>API</source>
+ <translation>API</translation>
+ </message>
+ <message>
+ <source>Install</source>
+ <translation>インストールã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>Android::NoApplicationProFilePage</name>
+ <message>
+ <source>No application .pro file found in this project.</source>
+ <translation>ã“ã®ãƒ—ロジェクトã«ã‚¢ãƒ—リケーション .pro ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>No Application .pro File</source>
+ <translation>アプリケーション .pro ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</translation>
+ </message>
+</context>
+<context>
+ <name>Android::ChooseProfilePage</name>
+ <message>
+ <source>Select the .pro file for which you want to create the Android template files.</source>
+ <translation>Android テンプレートファイルを作æˆã—ãŸã„ .pro ファイルをé¸æŠžã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>.pro file:</source>
+ <translation>.pro ファイル:</translation>
+ </message>
+ <message>
+ <source>Select a .pro File</source>
+ <translation>.pro ファイルã®é¸æŠž</translation>
+ </message>
+</context>
+<context>
+ <name>Android::ChooseDirectoryPage</name>
+ <message>
+ <source>Android package source directory:</source>
+ <translation>Android パッケージソースディレクトリ:</translation>
+ </message>
+ <message>
+ <source>The Android package source directory cannot be the same as the project directory.</source>
+ <translation>Android パッケージソースディレクトリをプロジェクトã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨åŒã˜ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Copy the Gradle files to Android directory</source>
+ <translation>Gradle ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ Android ディレクトリã«ã‚³ãƒ”ーã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>It is highly recommended if you are planning to extend the Java part of your Qt application.</source>
+ <translation>Qt アプリケーション㮠Java 部を拡張ã™ã‚‹éš›ã«ã¯æœ‰åŠ¹ã«ã™ã‚‹ã“ã¨ã‚’å¼·ã推奨ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Select the Android package source directory.
+
+The files in the Android package source directory are copied to the build directory&apos;s Android directory and the default files are overwritten.</source>
+ <translation>Android パッケージソースディレクトリをé¸æŠžã—ã¦ãã ã•ã„。
+
+Android パッケージソースディレクトリã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ“ルドディレクトリ㮠Android ディレクトリã«æ—¢å®šã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’上書ãã™ã‚‹å½¢ã§ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The Android template files will be created in the ANDROID_PACKAGE_SOURCE_DIR set in the .pro file.</source>
+ <translation type="vanished">Android テンプレートファイル㯠.pro ファイル㮠ANDROID_PACKAGE_SOURCE_DIR 変数ã«è¨­å®šã•ã‚ŒãŸãƒ‘スã«ä½œæˆã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Android::CreateAndroidManifestWizard</name>
+ <message>
+ <source>Create Android Template Files Wizard</source>
+ <translation>Android テンプレートファイル作æˆã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰</translation>
+ </message>
+ <message>
+ <source>Project File not Updated</source>
+ <translation>プロジェクトファイルã¯æœªæ›´æ–°ã§ã™</translation>
+ </message>
+</context>
+<context>
+ <name>JLSSettingsWidget</name>
+ <message>
+ <source>Name:</source>
+ <translation>åå‰:</translation>
+ </message>
+ <message>
+ <source>Java:</source>
+ <translation>Java:</translation>
+ </message>
+ <message>
+ <source>Java Language Server:</source>
+ <translation>Java 言語サーãƒãƒ¼:</translation>
+ </message>
+ <message>
+ <source>Path to equinox launcher jar</source>
+ <translation>equinox launcher jarã¸ã®ãƒ‘ス</translation>
+ </message>
+</context>
+<context>
+ <name>Android::Internal::SplashScreenContainerWidget</name>
+ <message>
+ <source>Splash screen</source>
+ <translation>スプラッシュスクリーン</translation>
+ </message>
+</context>
+<context>
+ <name>Android::Internal::SplashScreenWidget</name>
+ <message>
+ <source>Icon scaled up.</source>
+ <translation>アイコンをスケールアップ。</translation>
+ </message>
+ <message>
+ <source>Click to select...</source>
+ <translation>クリックã—ã¦é¸æŠž...</translation>
+ </message>
+</context>
+<context>
+ <name>AutoTest</name>
+ <message>
+ <source>Testing</source>
+ <translation>自動テスト</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::Internal::AutotestPluginPrivate</name>
+ <message>
+ <source>Testing</source>
+ <translation>自動テスト</translation>
+ </message>
+ <message>
+ <source>&amp;Tests</source>
+ <translation>テスト(&amp;T)</translation>
+ </message>
+ <message>
+ <source>Run &amp;All Tests</source>
+ <translation>ã™ã¹ã¦ã®ãƒ†ã‚¹ãƒˆã®å®Ÿè¡Œ(&amp;A)</translation>
+ </message>
+ <message>
+ <source>Run All Tests</source>
+ <translation>ã™ã¹ã¦ã®ãƒ†ã‚¹ãƒˆã®å®Ÿè¡Œ</translation>
+ </message>
+ <message>
+ <source>Ctrl+Meta+T, Ctrl+Meta+A</source>
+ <translation>Ctrl+Meta+T, Ctrl+Meta+A</translation>
+ </message>
+ <message>
+ <source>Alt+Shift+T,Alt+A</source>
+ <translation>Alt+Shift+T,Alt+A</translation>
+ </message>
+ <message>
+ <source>&amp;Run Selected Tests</source>
+ <translation>é¸æŠžã—ãŸãƒ†ã‚¹ãƒˆã®å®Ÿè¡Œ(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Run Selected Tests</source>
+ <translation>é¸æŠžã—ãŸãƒ†ã‚¹ãƒˆã®å®Ÿè¡Œ</translation>
+ </message>
+ <message>
+ <source>Ctrl+Meta+T, Ctrl+Meta+R</source>
+ <translation>Ctrl+Meta+T, Ctrl+Meta+R</translation>
+ </message>
+ <message>
+ <source>Alt+Shift+T,Alt+R</source>
+ <translation>Alt+Shift+T,Alt+R</translation>
+ </message>
+ <message>
+ <source>Run &amp;Failed Tests</source>
+ <translation>実行ã•ã‚Œå¤±æ•—ã—ãŸãƒ†ã‚¹ãƒˆ(&amp;F)</translation>
+ </message>
+ <message>
+ <source>Run Failed Tests</source>
+ <translation>実行ã•ã‚Œå¤±æ•—ã—ãŸãƒ†ã‚¹ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Ctrl+Meta+T, Ctrl+Meta+F</source>
+ <translation>Ctrl+Meta+T, Ctrl+Meta+F</translation>
+ </message>
+ <message>
+ <source>Alt+Shift+T,Alt+F</source>
+ <translation>Alt+Shift+T,Alt+F</translation>
+ </message>
+ <message>
+ <source>Run Tests for &amp;Current File</source>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«å¯¾ã™ã‚‹ãƒ†ã‚¹ãƒˆã‚’実行ã™ã‚‹(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Run Tests for Current File</source>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«å¯¾ã™ã‚‹ãƒ†ã‚¹ãƒˆã‚’実行ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Ctrl+Meta+T, Ctrl+Meta+C</source>
+ <translation>Ctrl+Meta+T, Ctrl+Meta+C</translation>
+ </message>
+ <message>
+ <source>Alt+Shift+T,Alt+C</source>
+ <translation>Alt+Shift+T,Alt+C</translation>
+ </message>
+ <message>
+ <source>Re&amp;scan Tests</source>
+ <translation>テストã®å†ã‚¹ã‚­ãƒ£ãƒ³(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Ctrl+Meta+T, Ctrl+Meta+S</source>
+ <translation>Ctrl+Meta+T, Ctrl+Meta+S</translation>
+ </message>
+ <message>
+ <source>Alt+Shift+T,Alt+S</source>
+ <translation>Alt+Shift+T,Alt+S</translation>
+ </message>
+ <message>
+ <source>Selected test was not found (%1).</source>
+ <translation>é¸æŠžã—ãŸãƒ†ã‚¹ãƒˆãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—㟠(%1)。</translation>
+ </message>
+</context>
+<context>
+ <name>BoostTestFramework</name>
+ <message>
+ <source>Boost Test</source>
+ <translation>Boost Test</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::Internal::BoostTestOutputReader</name>
+ <message>
+ <source>Test execution took %1</source>
+ <translation>テストã®å®Ÿè¡Œæ™‚é–“: %1</translation>
+ </message>
+</context>
+<context>
+ <name>BoostTestTreeItem</name>
+ <message>
+ <source>parameterized</source>
+ <translation>パラメータ化</translation>
+ </message>
+ <message>
+ <source>fixture</source>
+ <translation>フィクスãƒãƒ£</translation>
+ </message>
+ <message>
+ <source>templated</source>
+ <translation>テンプレ化</translation>
+ </message>
+</context>
+<context>
+ <name>CatchFramework</name>
+ <message>
+ <source>Catch Test</source>
+ <translation>Catch Test</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::Internal::CatchOutputReader</name>
+ <message>
+ <source>Executing %1 &quot;%2&quot;</source>
+ <translation>実行中: %1 &quot;%2&quot;</translation>
+ </message>
+ <message>
+ <source>%1 &quot;%2&quot; passed</source>
+ <translation>%1 &quot;%2&quot; ã‚’æˆåŠŸã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Expression passed</source>
+ <translation>å¼ãŒæˆåŠŸã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Expression failed: %1</source>
+ <translation>å¼ãŒå¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Finished executing %1 &quot;%2&quot;</source>
+ <translation>%1 &quot;%2&quot; ã®å®Ÿè¡Œã‚’終了ã—ã¾ã—ãŸ</translation>
+ </message>
+</context>
+<context>
+ <name>CatchTestFramework</name>
+ <message>
+ <source>Catch Test</source>
+ <translation>キャッãƒãƒ†ã‚¹ãƒˆ</translation>
+ </message>
+</context>
+<context>
+ <name>CatchTreeItem</name>
+ <message>
+ <source>parameterized</source>
+ <translation>パラメータ化</translation>
+ </message>
+ <message>
+ <source>fixture</source>
+ <translation>フィクスãƒãƒ£</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::Internal::CTestOutputReader</name>
+ <message>
+ <source>Running tests for %1</source>
+ <translation>%1ã®ãƒ†ã‚¹ãƒˆã‚’実行中</translation>
+ </message>
+</context>
+<context>
+ <name>CTestTool</name>
+ <message>
+ <source>CTest</source>
+ <translation>CTest</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::Internal::ProjectTestSettingsWidget</name>
+ <message>
+ <source>Global</source>
+ <translation>グローãƒãƒ«</translation>
+ </message>
+ <message>
+ <source>Custom</source>
+ <translation>カスタム</translation>
+ </message>
+ <message>
+ <source>Active frameworks:</source>
+ <translation>有効ãªãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¯ãƒ¼ã‚¯:</translation>
+ </message>
+ <message>
+ <source>Automatically run tests after build</source>
+ <translation>ビルド後ã«è‡ªå‹•çš„ã«ãƒ†ã‚¹ãƒˆã‚’実行ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>ãªã—</translation>
+ </message>
+ <message>
+ <source>All</source>
+ <translation>ã™ã¹ã¦</translation>
+ </message>
+ <message>
+ <source>Selected</source>
+ <translation>é¸æŠžã—ãŸ</translation>
+ </message>
+</context>
+<context>
+ <name>QtTestTreeItem</name>
+ <message>
+ <source>inherited</source>
+ <translation>継承</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::TestOutputReader</name>
+ <message>
+ <source>Test executable crashed.</source>
+ <translation>テストã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Autotest::Internal::RunConfigurationSelectionDialog</name>
+ <message>
+ <source>Select Run Configuration</source>
+ <translation>実行構æˆã‚’é¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Could not determine which run configuration to choose for running tests</source>
+ <translation>テスト実行時ã«ã©ã®å®Ÿè¡Œæ§‹æˆã‚’é¸æŠžã™ã¹ãã‹åˆ¤æ–­ã§ããªã‹ã£ãŸ</translation>
+ </message>
+ <message>
+ <source>Remember choice. Cached choices can be reset by switching projects or using the option to clear the cache.</source>
+ <translation>é¸æŠžè‚¢ã‚’記憶ã™ã‚‹ã€‚キャッシュã•ã‚ŒãŸé¸æŠžè‚¢ã¯ã€ãƒ—ロジェクトを切り替ãˆã‚‹ã‹ã€ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’クリアã™ã‚‹ã‚ªãƒ—ションを使用ã™ã‚‹ã“ã¨ã§ãƒªã‚»ãƒƒãƒˆã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Run Configuration:</source>
+ <translation>実行構æˆ:</translation>
+ </message>
+ <message>
+ <source>Executable:</source>
+ <translation>実行ファイル:</translation>
+ </message>
+ <message>
+ <source>Arguments:</source>
+ <translation>引数:</translation>
+ </message>
+ <message>
+ <source>Working Directory:</source>
+ <translation>作業ディレクトリ:</translation>
+ </message>
+</context>
+<context>
+ <name>AutotoolsProjectManager::Internal::AutotoolsBuildConfiguration</name>
+ <message>
+ <source>Autotools Manager</source>
+ <translation>Autotools マãƒãƒ¼ã‚¸ãƒ£</translation>
+ </message>
+</context>
+<context>
+ <name>BuildConfiguration</name>
+ <message>
+ <source>Build</source>
+ <translation>ビルド</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <extracomment>The name of the build configuration created by default for a autotools project.
+----------
+The name of the build configuration created by default for a generic project.</extracomment>
+ <translation>既定</translation>
+ </message>
+ <message>
+ <source>Debug</source>
+ <extracomment>The name of the debug build configuration created by default for a qbs project.
+----------
+The name of the debug build configuration created by default for a qmake project.</extracomment>
+ <translation>デãƒãƒƒã‚°</translation>
+ </message>
+ <message>
+ <source>Release</source>
+ <extracomment>The name of the release build configuration created by default for a qbs project.
+----------
+The name of the release build configuration created by default for a qmake project.</extracomment>
+ <translation>リリース</translation>
+ </message>
+ <message>
+ <source>Profile</source>
+ <extracomment>The name of the profile build configuration created by default for a qmake project.</extracomment>
+ <translation>プロファイル</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetalDeployConfiguration</name>
+ <message>
+ <source>Deploy to BareMetal Device</source>
+ <translation>ベアメタルデãƒã‚¤ã‚¹ã«ãƒ‡ãƒ—ロイ</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::DebugServerProviderChooser</name>
+ <message>
+ <source>Manage...</source>
+ <translation>管ç†...</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>ã—ãªã„</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::DebugServerProviderModel</name>
+ <message>
+ <source>Not recognized</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+ <message>
+ <source>GDB</source>
+ <translation>GDB</translation>
+ </message>
+ <message>
+ <source>UVSC</source>
+ <translation>UVSC</translation>
+ </message>
+ <message>
+ <source>GDB compatible provider engine
+(used together with the GDB debuggers).</source>
+ <translation>GDB 互æ›ãƒ—ロãƒã‚¤ãƒ€ã‚¨ãƒ³ã‚¸ãƒ³
+(GDB デãƒãƒƒã‚¬ã¨ä½µç”¨)。</translation>
+ </message>
+ <message>
+ <source>UVSC compatible provider engine
+(used together with the KEIL uVision).</source>
+ <translation>UVSC 対応プロãƒã‚¤ãƒ€ãƒ¼ã‚¨ãƒ³ã‚¸ãƒ³
+(KEIL uVision ã¨ä½µç”¨)。</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>åž‹</translation>
+ </message>
+ <message>
+ <source>Engine</source>
+ <translation>エンジン</translation>
+ </message>
+ <message>
+ <source>Duplicate Providers Detected</source>
+ <translation>é‡è¤‡ã—ãŸãƒ—ロãƒã‚¤ãƒ€ã®æ¤œå‡º</translation>
+ </message>
+ <message>
+ <source>The following providers were already configured:&lt;br&gt;&amp;nbsp;%1&lt;br&gt;They were not configured again.</source>
+ <translation>以下ã®ãƒ—ロãƒã‚¤ãƒ€ã¯æ—¢ã«è¨­å®šæ¸ˆã¿ã§ã™ã€‚&lt;br&gt;&amp;nbsp;%1&lt;br&gt;é‡è¤‡ã—ãŸè¨­å®šã¯è¡Œã„ã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::DebugServerProvidersSettingsPage</name>
+ <message>
+ <source>Add</source>
+ <translation>追加</translation>
+ </message>
+ <message>
+ <source>Clone</source>
+ <translation>複製</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>削除</translation>
+ </message>
+ <message>
+ <source>Debug Server Providers</source>
+ <translation>サーãƒãƒ¼ãƒ»ãƒ—ロãƒã‚¤ãƒ€ãƒ¼ã‚’デãƒãƒƒã‚°ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Clone of %1</source>
+ <translation>%1 を複製</translation>
+ </message>
+ <message>
+ <source>Bare Metal</source>
+ <translation>ベアメタル</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::GdbServerProvider</name>
+ <message>
+ <source>EBlink</source>
+ <translation>EBlink</translation>
+ </message>
+ <message>
+ <source>Generic</source>
+ <translation>汎用</translation>
+ </message>
+ <message>
+ <source>JLink</source>
+ <translation>JLink</translation>
+ </message>
+ <message>
+ <source>OpenOCD</source>
+ <translation>OpenOCD</translation>
+ </message>
+ <message>
+ <source>ST-LINK Utility</source>
+ <translation>ST-LINK ユーティリティ</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::EBlinkGdbServerProviderConfigWidget</name>
+ <message>
+ <source>Host:</source>
+ <translation>ホスト:</translation>
+ </message>
+ <message>
+ <source>Executable file:</source>
+ <translation>実行ファイル:</translation>
+ </message>
+ <message>
+ <source>Script file:</source>
+ <translation>スクリプトファイル:</translation>
+ </message>
+ <message>
+ <source>Specify the verbosity level (0 to 7).</source>
+ <translation>詳細レベル (0 ~ 7) を指定ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Verbosity level:</source>
+ <translation>詳細レベル:</translation>
+ </message>
+ <message>
+ <source>Connect under reset (hotplug).</source>
+ <translation>リセット状態ã§ã®æŽ¥ç¶š(ホットプラグ)。</translation>
+ </message>
+ <message>
+ <source>Connect under reset:</source>
+ <translation>リセット状態ã§ã®æŽ¥ç¶š:</translation>
+ </message>
+ <message>
+ <source>Interface type.</source>
+ <translation>インターフェース型。</translation>
+ </message>
+ <message>
+ <source>Type:</source>
+ <translation>åž‹:</translation>
+ </message>
+ <message>
+ <source>Specify the speed of the interface (120 to 8000) in kilohertz (kHz).</source>
+ <translation>インターフェイスã®é€Ÿåº¦(120~8000)をキロヘルツ(kHz)ã§æŒ‡å®šã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Speed:</source>
+ <translation>速度:</translation>
+ </message>
+ <message>
+ <source>Do not use EBlink flash cache.</source>
+ <translation>EBlink フラッシュキャッシュã¯ä½¿ç”¨ã—ãªã„ã§ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Disable cache:</source>
+ <translation>キャッシュを無効化ã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>Shut down EBlink server after disconnect.</source>
+ <translation>EBlink サーãƒãƒ¼ã‚’切断後ã«ã‚·ãƒ£ãƒƒãƒˆãƒ€ã‚¦ãƒ³ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Auto shutdown:</source>
+ <translation>自動シャットダウン:</translation>
+ </message>
+ <message>
+ <source>Init commands:</source>
+ <translation>åˆæœŸåŒ–コマンド:</translation>
+ </message>
+ <message>
+ <source>Reset commands:</source>
+ <translation>リセットコマンド:</translation>
+ </message>
+ <message>
+ <source>SWD</source>
+ <translation>SWD</translation>
+ </message>
+ <message>
+ <source>JTAG</source>
+ <translation>JTAG</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetalDebugSupport</name>
+ <message>
+ <source>Cannot debug: Local executable is not set.</source>
+ <translation>デãƒãƒƒã‚°ã‚¨ãƒ©ãƒ¼: ローカル実行ファイルãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Cannot debug: Could not find executable for &quot;%1&quot;.</source>
+ <translation>デãƒãƒƒã‚°ã‚¨ãƒ©ãƒ¼: &quot;%1&quot; ã«å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Unable to create a uVision project options template.</source>
+ <translation>uVision プロジェクトã®ã‚ªãƒ—ションテンプレートを作æˆã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Unable to create a uVision project template.</source>
+ <translation>uVision プロジェクトã®ãƒ†ãƒ³ãƒ—レートを作æˆã§ãã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::GenericGdbServerProviderConfigWidget</name>
+ <message>
+ <source>Host:</source>
+ <translation>ホスト:</translation>
+ </message>
+ <message>
+ <source>Extended mode:</source>
+ <translation>拡張モード:</translation>
+ </message>
+ <message>
+ <source>Init commands:</source>
+ <translation>åˆæœŸåŒ–コマンド:</translation>
+ </message>
+ <message>
+ <source>Reset commands:</source>
+ <translation>リセットコマンド:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::JLinkGdbServerProviderConfigWidget</name>
+ <message>
+ <source>Host:</source>
+ <translation>ホスト:</translation>
+ </message>
+ <message>
+ <source>Executable file:</source>
+ <translation>実行ファイル:</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+ <message>
+ <source>JTAG</source>
+ <translation type="unfinished">JTAG</translation>
+ </message>
+ <message>
+ <source>SWD</source>
+ <translation type="unfinished">SWD</translation>
+ </message>
+ <message>
+ <source>Device:</source>
+ <translation>デãƒã‚¤ã‚¹:</translation>
+ </message>
+ <message>
+ <source>Additional arguments:</source>
+ <translation>追加ã®å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>Init commands:</source>
+ <translation>åˆæœŸåŒ–コマンド:</translation>
+ </message>
+ <message>
+ <source>Reset commands:</source>
+ <translation>リセットコマンド:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::UvscServerProvider</name>
+ <message>
+ <source>uVision JLink</source>
+ <translation>uVision JLink</translation>
+ </message>
+ <message>
+ <source>uVision Simulator</source>
+ <translation>uVision シミュレータ</translation>
+ </message>
+ <message>
+ <source>uVision St-Link</source>
+ <translation>uVision St-Link</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::JLinkUvscServerProviderConfigWidget</name>
+ <message>
+ <source>Adapter options:</source>
+ <translation>アダプタオプション:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::JLinkUvscAdapterOptionsWidget</name>
+ <message>
+ <source>Port:</source>
+ <translation>ãƒãƒ¼ãƒˆ:</translation>
+ </message>
+ <message>
+ <source>Speed:</source>
+ <translation>速度:</translation>
+ </message>
+ <message>
+ <source>JTAG</source>
+ <translation>JTAG</translation>
+ </message>
+ <message>
+ <source>SWD</source>
+ <translation>SWD</translation>
+ </message>
+ <message>
+ <source>50MHz</source>
+ <translation>50MHz</translation>
+ </message>
+ <message>
+ <source>33MHz</source>
+ <translation>33MHz</translation>
+ </message>
+ <message>
+ <source>25MHz</source>
+ <translation>25MHz</translation>
+ </message>
+ <message>
+ <source>20MHz</source>
+ <translation>20MHz</translation>
+ </message>
+ <message>
+ <source>10MHz</source>
+ <translation>10MHz</translation>
+ </message>
+ <message>
+ <source>5MHz</source>
+ <translation>5MHz</translation>
+ </message>
+ <message>
+ <source>3MHz</source>
+ <translation>3MHz</translation>
+ </message>
+ <message>
+ <source>2MHz</source>
+ <translation>2MHz</translation>
+ </message>
+ <message>
+ <source>1MHz</source>
+ <translation>1MHz</translation>
+ </message>
+ <message>
+ <source>500kHz</source>
+ <translation>500kHz</translation>
+ </message>
+ <message>
+ <source>200kHz</source>
+ <translation>200kHz</translation>
+ </message>
+ <message>
+ <source>100kHz</source>
+ <translation>100kHz</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::SimulatorUvscServerProviderConfigWidget</name>
+ <message>
+ <source>Limit speed to real-time.</source>
+ <translation>速度をリアルタイムã«åˆ¶é™ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Limit speed to real-time:</source>
+ <translation>速度をリアルタイムã«åˆ¶é™ã™ã‚‹:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::StLinkUvscServerProviderConfigWidget</name>
+ <message>
+ <source>Adapter options:</source>
+ <translation>アダプタオプション:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::StLinkUvscAdapterOptionsWidget</name>
+ <message>
+ <source>Port:</source>
+ <translation>ãƒãƒ¼ãƒˆ:</translation>
+ </message>
+ <message>
+ <source>Speed:</source>
+ <translation>速度:</translation>
+ </message>
+ <message>
+ <source>JTAG</source>
+ <translation>JTAG</translation>
+ </message>
+ <message>
+ <source>SWD</source>
+ <translation>SWD</translation>
+ </message>
+ <message>
+ <source>9MHz</source>
+ <translation>9MHz</translation>
+ </message>
+ <message>
+ <source>4.5MHz</source>
+ <translation>4.5MHz</translation>
+ </message>
+ <message>
+ <source>2.25MHz</source>
+ <translation>2.25MHz</translation>
+ </message>
+ <message>
+ <source>1.12MHz</source>
+ <translation>1.12MHz</translation>
+ </message>
+ <message>
+ <source>560kHz</source>
+ <translation>560kHz</translation>
+ </message>
+ <message>
+ <source>280kHz</source>
+ <translation>280kHz</translation>
+ </message>
+ <message>
+ <source>140kHz</source>
+ <translation>140kHz</translation>
+ </message>
+ <message>
+ <source>4MHz</source>
+ <translation>4MHz</translation>
+ </message>
+ <message>
+ <source>1.8MHz</source>
+ <translation>1.8MHz</translation>
+ </message>
+ <message>
+ <source>950kHz</source>
+ <translation>950kHz</translation>
+ </message>
+ <message>
+ <source>480kHz</source>
+ <translation>480kHz</translation>
+ </message>
+ <message>
+ <source>240kHz</source>
+ <translation>240kHz</translation>
+ </message>
+ <message>
+ <source>125kHz</source>
+ <translation>125kHz</translation>
+ </message>
+ <message>
+ <source>100kHz</source>
+ <translation>100kHz</translation>
+ </message>
+ <message>
+ <source>50kHz</source>
+ <translation>50kHz</translation>
+ </message>
+ <message>
+ <source>25kHz</source>
+ <translation>25kHz</translation>
+ </message>
+ <message>
+ <source>15kHz</source>
+ <translation>15kHz</translation>
+ </message>
+ <message>
+ <source>5kHz</source>
+ <translation>5kHz</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::UvscServerProviderConfigWidget</name>
+ <message>
+ <source>Host:</source>
+ <translation>ホスト:</translation>
+ </message>
+ <message>
+ <source>Choose Keil Toolset Configuration File</source>
+ <translation>Keil Toolset ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Tools file path:</source>
+ <translation>ツールã®ãƒ•ã‚¡ã‚¤ãƒ«ãƒ‘ス:</translation>
+ </message>
+ <message>
+ <source>Target device:</source>
+ <translation>ターゲットデãƒã‚¤ã‚¹:</translation>
+ </message>
+ <message>
+ <source>Target driver:</source>
+ <translation>ターゲットドライãƒãƒ¼:</translation>
+ </message>
+</context>
+<context>
+ <name>RunControl</name>
+ <message>
+ <source>%1 crashed.</source>
+ <translation>%1 ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>%2 exited with code %1</source>
+ <translation>%2 ã¯ã‚³ãƒ¼ãƒ‰ %1 ã§çµ‚了ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Starting %1 %2...</source>
+ <translation>起動中 %1 %2...</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DeviceSelectionModel</name>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>ãƒãƒ¼ã‚¸ãƒ§ãƒ³</translation>
+ </message>
+ <message>
+ <source>Vendor</source>
+ <translation>ベンダー</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DeviceSelectionMemoryModel</name>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Start</source>
+ <translation>開始</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>サイズ</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DeviceSelectionAlgorithmModel</name>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>FLASH Start</source>
+ <translation>FLASH スタート</translation>
+ </message>
+ <message>
+ <source>FLASH Size</source>
+ <translation>FLASH サイズ</translation>
+ </message>
+ <message>
+ <source>RAM Start</source>
+ <translation>RAM スタート</translation>
+ </message>
+ <message>
+ <source>RAM Size</source>
+ <translation>RAM サイズ</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DeviceSelectionAlgorithmView</name>
+ <message>
+ <source>Algorithm path.</source>
+ <translation>アルゴリズムã®ãƒ‘ス。</translation>
+ </message>
+ <message>
+ <source>FLASH:</source>
+ <translation>FLASH:</translation>
+ </message>
+ <message>
+ <source>Start address.</source>
+ <translation>開始アドレス。</translation>
+ </message>
+ <message>
+ <source>Size.</source>
+ <translation>サイズ。</translation>
+ </message>
+ <message>
+ <source>RAM:</source>
+ <translation>RAM:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DeviceSelectorToolPanel</name>
+ <message>
+ <source>Manage...</source>
+ <translation>管ç†...</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DeviceSelectorDetailsPanel</name>
+ <message>
+ <source>Vendor:</source>
+ <translation>ベンダー:</translation>
+ </message>
+ <message>
+ <source>Package:</source>
+ <translation>パッケージ:</translation>
+ </message>
+ <message>
+ <source>Description:</source>
+ <translation>説明:</translation>
+ </message>
+ <message>
+ <source>Memory:</source>
+ <translation>メモリ:</translation>
+ </message>
+ <message>
+ <source>Flash algorithm:</source>
+ <translation>FLASH アルゴリズム:</translation>
+ </message>
+ <message>
+ <source>Peripheral description files (*.svd)</source>
+ <translation>ペリフェラル説明ファイル (*.svd)</translation>
+ </message>
+ <message>
+ <source>Select Peripheral Description File</source>
+ <translation>ペリフェラル説明ファイルをé¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Peripheral description file:</source>
+ <translation>ペリフェラル説明ファイル:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DeviceSelector</name>
+ <message>
+ <source>Target device not selected.</source>
+ <translation>ターゲットデãƒã‚¤ã‚¹ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DeviceSelectionDialog</name>
+ <message>
+ <source>Available Target Devices</source>
+ <translation>使用å¯èƒ½ãªã‚¿ãƒ¼ã‚²ãƒƒãƒˆãƒ‡ãƒã‚¤ã‚¹</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DriverSelectionModel</name>
+ <message>
+ <source>Path</source>
+ <translation>パス</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DriverSelectionCpuDllModel</name>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DriverSelectionCpuDllView</name>
+ <message>
+ <source>Debugger CPU library (depends on a CPU core).</source>
+ <translation>デãƒãƒƒã‚¬ CPU ライブラリ(CPU コアã«ä¾å­˜)。</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DriverSelectorToolPanel</name>
+ <message>
+ <source>Manage...</source>
+ <translation>管ç†...</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DriverSelectorDetailsPanel</name>
+ <message>
+ <source>Debugger driver library.</source>
+ <translation>デãƒãƒƒã‚¬ãƒ‰ãƒ©ã‚¤ãƒãƒ©ã‚¤ãƒ–ラリ。</translation>
+ </message>
+ <message>
+ <source>Driver library:</source>
+ <translation>ドライãƒãƒ©ã‚¤ãƒ–ラリ:</translation>
+ </message>
+ <message>
+ <source>CPU library:</source>
+ <translation>CPU ライブラリ:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DriverSelector</name>
+ <message>
+ <source>Target driver not selected.</source>
+ <translation>ターゲットドライãƒãƒ¼ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::Uv::DriverSelectionDialog</name>
+ <message>
+ <source>Available Target Drivers</source>
+ <translation>使用å¯èƒ½ãªã‚¿ãƒ¼ã‚²ãƒƒãƒˆãƒ‰ãƒ©ã‚¤ãƒãƒ¼</translation>
+ </message>
+</context>
+<context>
+ <name>IarToolChain</name>
+ <message>
+ <source>IAREW %1 (%2, %3)</source>
+ <translation>IAREW %1 (%2, %3)</translation>
+ </message>
+ <message>
+ <source>IAREW</source>
+ <translation>IAREW</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::IarToolChainConfigWidget</name>
+ <message>
+ <source>&amp;Compiler path:</source>
+ <translation>コンパイラã®ãƒ‘ス(&amp;C):</translation>
+ </message>
+ <message>
+ <source>Platform codegen flags:</source>
+ <translation>プラットフォーム用コード生æˆã‚ªãƒ—ション:</translation>
+ </message>
+ <message>
+ <source>&amp;ABI:</source>
+ <translation>&amp;ABI:</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::IDebugServerProviderConfigWidget</name>
+ <message>
+ <source>Enter the name of the debugger server provider.</source>
+ <translation>デãƒãƒƒã‚¬ サーãƒãƒ¼ プロãƒã‚¤ãƒ€ã®åå‰ã‚’入力ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Name:</source>
+ <translation>åå‰:</translation>
+ </message>
+</context>
+<context>
+ <name>KeilToolChain</name>
+ <message>
+ <source>KEIL %1 (%2, %3)</source>
+ <translation>KEIL %1 (%2, %3)</translation>
+ </message>
+ <message>
+ <source>KEIL</source>
+ <translation>KEIL</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::KeilToolChainConfigWidget</name>
+ <message>
+ <source>&amp;Compiler path:</source>
+ <translation>コンパイラã®ãƒ‘ス(&amp;C):</translation>
+ </message>
+ <message>
+ <source>Platform codegen flags:</source>
+ <translation>プラットフォーム用コード生æˆã‚ªãƒ—ション:</translation>
+ </message>
+ <message>
+ <source>&amp;ABI:</source>
+ <translation>&amp;ABI:</translation>
+ </message>
+</context>
+<context>
+ <name>SdccToolChain</name>
+ <message>
+ <source>SDCC %1 (%2, %3)</source>
+ <translation>SDCC %1 (%2, %3)</translation>
+ </message>
+ <message>
+ <source>SDCC</source>
+ <translation>SDCC</translation>
+ </message>
+</context>
+<context>
+ <name>BareMetal::Internal::SdccToolChainConfigWidget</name>
+ <message>
+ <source>&amp;Compiler path:</source>
+ <translation>コンパイラã®ãƒ‘ス(&amp;C):</translation>
+ </message>
+ <message>
+ <source>&amp;ABI:</source>
+ <translation>&amp;ABI:</translation>
+ </message>
+</context>
+<context>
+ <name>Bazaar::Internal::BazaarDiffConfig</name>
+ <message>
+ <source>Ignore Whitespace</source>
+ <translation>空白を無視</translation>
+ </message>
+ <message>
+ <source>Ignore Blank Lines</source>
+ <translation>空行を無視</translation>
+ </message>
+</context>
+<context>
+ <name>Bazaar::Internal::BazaarLogConfig</name>
+ <message>
+ <source>Verbose</source>
+ <translation>冗長表示</translation>
+ </message>
+ <message>
+ <source>Show files changed in each revision.</source>
+ <translation>å„リビジョンã§å¤‰æ›´ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’表示ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Forward</source>
+ <translation>進む</translation>
+ </message>
+ <message>
+ <source>Show from oldest to newest.</source>
+ <translation>å¤ã„リビジョンã‹ã‚‰é–‹å§‹ã—ã¦æœ€æ–°ã®ãƒªãƒ“ジョンを最後ã«è¡¨ç¤ºã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Include Merges</source>
+ <translation>マージ込ã¿</translation>
+ </message>
+ <message>
+ <source>Show merged revisions.</source>
+ <translation>マージã•ã‚ŒãŸãƒªãƒ“ジョンを表示ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Detailed</source>
+ <translation>詳細形å¼</translation>
+ </message>
+ <message>
+ <source>Moderately Short</source>
+ <translation>概略表示</translation>
+ </message>
+ <message>
+ <source>One Line</source>
+ <translation>一行表示</translation>
+ </message>
+ <message>
+ <source>GNU Change Log</source>
+ <translation>GNUå½¢å¼</translation>
+ </message>
+ <message>
+ <source>Format</source>
+ <translation>フォーマット</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal::ArtisticStyle</name>
+ <message>
+ <source>&amp;Artistic Style</source>
+ <translation>&amp;Artistic スタイル</translation>
+ </message>
+ <message>
+ <source>AStyle (*.astylerc)</source>
+ <translation>AStyle (*.astylerc)</translation>
+ </message>
+ <message>
+ <source>Artistic Style</source>
+ <translation>Artistic スタイル</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal</name>
+ <message>
+ <source>Artistic Style</source>
+ <translation>Artistic スタイル</translation>
+ </message>
+ <message>
+ <source>Uncrustify</source>
+ <translation>Uncrustify</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal::ClangFormat</name>
+ <message>
+ <source>&amp;ClangFormat</source>
+ <translation>&amp;Clang フォーマット</translation>
+ </message>
+ <message>
+ <source>ClangFormat</source>
+ <translation>Clang フォーマット</translation>
+ </message>
+ <message>
+ <source>Clang Format</source>
+ <translation>Clang フォーマット</translation>
+ </message>
+ <message>
+ <source>Uncrustify file (*.cfg)</source>
+ <translation>Uncrustifyファイル (*.cfg)</translation>
+ </message>
+ <message>
+ <source>Uncrustify</source>
+ <translation>Uncrustify</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal::ClangFormatSettings</name>
+ <message>
+ <source>No description available.</source>
+ <translation>記述ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal::GeneralOptionsPageWidget</name>
+ <message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+</context>
+<context>
+ <name>Beautifier::Internal::Uncrustify</name>
+ <message>
+ <source>&amp;Uncrustify</source>
+ <translation>&amp;Uncrustify</translation>
+ </message>
+</context>
+<context>
+ <name>BinEditor::Internal::BinEditorWidget</name>
+ <message>
+ <source>Memory at 0x%1</source>
+ <translation>0x%1 ã®ãƒ¡ãƒ¢ãƒª</translation>
+ </message>
+ <message>
+ <source>Decimal&amp;nbsp;unsigned&amp;nbsp;value:</source>
+ <translation>符å·ç„¡ã—10進数:</translation>
+ </message>
+ <message>
+ <source>Decimal&amp;nbsp;signed&amp;nbsp;value:</source>
+ <translation>符å·ä»˜ã10進数:</translation>
+ </message>
+ <message>
+ <source>Previous&amp;nbsp;decimal&amp;nbsp;unsigned&amp;nbsp;value:</source>
+ <translation>ç›´å‰ã®ç¬¦å·ç„¡ã—10進数:</translation>
+ </message>
+ <message>
+ <source>Previous&amp;nbsp;decimal&amp;nbsp;signed&amp;nbsp;value:</source>
+ <translation>ç›´å‰ã®ç¬¦å·ä»˜ã10進数:</translation>
+ </message>
+ <message>
+ <source>%1-bit&amp;nbsp;Integer&amp;nbsp;Type</source>
+ <translation>%1 ビット整数型</translation>
+ </message>
+ <message>
+ <source>Little Endian</source>
+ <translation>リトルエンディアン</translation>
+ </message>
+ <message>
+ <source>Big Endian</source>
+ <translation>ビッグエンディアン</translation>
+ </message>
+ <message>
+ <source>Binary&amp;nbsp;value:</source>
+ <translation>2進数:</translation>
+ </message>
+ <message>
+ <source>Octal&amp;nbsp;value:</source>
+ <translation>8進数:</translation>
+ </message>
+ <message>
+ <source>Previous&amp;nbsp;binary&amp;nbsp;value:</source>
+ <translation>ç›´å‰ã®2進数:</translation>
+ </message>
+ <message>
+ <source>Previous&amp;nbsp;octal&amp;nbsp;value:</source>
+ <translation>ç›´å‰ã®8進数:</translation>
+ </message>
+ <message>
+ <source>&lt;i&gt;double&lt;/i&gt;&amp;nbsp;value:</source>
+ <translation>&lt;i&gt;å€ç²¾åº¦æµ®å‹•å°æ•°ç‚¹&lt;/i&gt;æ•°:</translation>
+ </message>
+ <message>
+ <source>Previous &lt;i&gt;double&lt;/i&gt;&amp;nbsp;value:</source>
+ <translation>ç›´å‰ã®&lt;i&gt;å€ç²¾åº¦æµ®å‹•å°æ•°ç‚¹&lt;/i&gt;æ•°:</translation>
+ </message>
+ <message>
+ <source>&lt;i&gt;float&lt;/i&gt;&amp;nbsp;value:</source>
+ <translation>&lt;i&gt;å˜ç²¾åº¦æµ®å‹•å°æ•°ç‚¹&lt;/i&gt;æ•°:</translation>
+ </message>
+ <message>
+ <source>Previous &lt;i&gt;float&lt;/i&gt;&amp;nbsp;value:</source>
+ <translation>ç›´å‰ã®&lt;i&gt;å˜ç²¾åº¦æµ®å‹•å°æ•°ç‚¹&lt;/i&gt;æ•°:</translation>
+ </message>
+ <message>
+ <source>Copying Failed</source>
+ <translation>コピー失敗</translation>
+ </message>
+ <message>
+ <source>You cannot copy more than 4 MB of binary data.</source>
+ <translation>4MB より大ããªãƒã‚¤ãƒŠãƒªãƒ‡ãƒ¼ã‚¿ã¯ã‚³ãƒ”ーã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Copy Selection as ASCII Characters</source>
+ <translation>é¸æŠžå†…容を ASCII 文字列ã¨ã—ã¦ã‚³ãƒ”ーã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Copy Selection as Hex Values</source>
+ <translation>é¸æŠžå†…容を16進数ã®å€¤ã¨ã—ã¦ã‚³ãƒ”ーã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Set Data Breakpoint on Selection</source>
+ <translation>é¸æŠžã—ãŸç®‡æ‰€ã«ãƒ‡ãƒ¼ã‚¿ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’設定</translation>
+ </message>
+ <message>
+ <source>Copy 0x%1</source>
+ <translation>0x%1をコピー</translation>
+ </message>
+ <message>
+ <source>Jump to Address in This Window</source>
+ <translation>ウィンドウ内ã§ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ç§»å‹•</translation>
+ </message>
+ <message>
+ <source>Jump to Address in New Window</source>
+ <translation>æ–°è¦ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ç§»å‹•</translation>
+ </message>
+ <message>
+ <source>Copy Value</source>
+ <translation>値をコピー</translation>
+ </message>
+ <message>
+ <source>Jump to Address 0x%1 in This Window</source>
+ <translation>ウィンドウ内ã§ã‚¢ãƒ‰ãƒ¬ã‚¹ 0x%1 ã«ç§»å‹•</translation>
+ </message>
+ <message>
+ <source>Jump to Address 0x%1 in New Window</source>
+ <translation>æ–°è¦ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§ã‚¢ãƒ‰ãƒ¬ã‚¹ 0x%1 ã«ç§»å‹•</translation>
+ </message>
+</context>
+<context>
+ <name>BinEditorWidget::TextEditorWidget</name>
+ <message>
+ <source>Zoom: %1%</source>
+ <translation>拡大率: %1%</translation>
+ </message>
+</context>
+<context>
+ <name>Bookmarks::Internal::BookmarkFilter</name>
+ <message>
+ <source>Bookmarks</source>
+ <translation>ブックマーク</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::DeviceDetector</name>
+ <message>
+ <source>Device &quot;%1&quot; %2</source>
+ <translation>デãƒã‚¤ã‚¹ &quot;%1&quot; %2</translation>
+ </message>
+ <message>
+ <source>Qt Debug Bridge device %1</source>
+ <translation>Qt デãƒãƒƒã‚°ãƒ–リッジデãƒã‚¤ã‚¹ %1</translation>
+ </message>
+ <message>
+ <source>Device detection error: %1</source>
+ <translation>デãƒã‚¤ã‚¹æ¤œå‡ºã‚¨ãƒ©ãƒ¼: %1</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::QdbDeviceTracker</name>
+ <message>
+ <source>Shutting down device discovery due to unexpected response: %1</source>
+ <translation>予期ã—ãªã„応答ãŒã‚ã£ãŸãŸã‚ã€ãƒ‡ãƒã‚¤ã‚¹ã®æœç´¢ã‚’åœæ­¢ã—ã¾ã™: %1</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::QdbMessageTracker</name>
+ <message>
+ <source>Shutting down message reception due to unexpected response: %1</source>
+ <translation>予期ã—ãªã„応答ãŒã‚ã£ãŸãŸã‚ã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸å—ä¿¡ã‚’åœæ­¢ã—ã¾ã™: %1</translation>
+ </message>
+ <message>
+ <source>QDB message: %1</source>
+ <translation>QDB メッセージ: %1</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::QdbWatcher</name>
+ <message>
+ <source>Unexpected QLocalSocket error: %1</source>
+ <translation>予期ã—ã¦ã„ãªã„ QLocalSocket エラー: %1</translation>
+ </message>
+ <message>
+ <source>Could not connect to QDB host server even after trying to start it.</source>
+ <translation>QDB ホスト・サーãƒãƒ¼ã‚’èµ·å‹•ã—ã¦ã‚‚ã€æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Invalid JSON response received from QDB server: %1</source>
+ <translation>QDB サーãƒãƒ¼ã‹ã‚‰ç„¡åŠ¹ãª JSON 応答をå—ã‘å–ã‚Šã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Could not find QDB host server executable. You can set the location with environment variable %1.</source>
+ <translation>QDB ホスト・サーãƒãƒ¼ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚環境変数 %1 ã§å ´æ‰€ã‚’設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QDB host server started.</source>
+ <translation>QDB ホストサーãƒãƒ¼ãŒèµ·å‹•ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Could not start QDB host server in %1</source>
+ <translation>QDB ホスト・サーãƒãƒ¼ã‚’ %1 ã§èµ·å‹•ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Starting QDB host server.</source>
+ <translation>GDB ホストサーãƒãƒ¼èµ·å‹•ä¸­ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::QdbDeployConfiguration</name>
+ <message>
+ <source>Deploy to Boot2Qt target</source>
+ <translation>Boot2Qt ターゲットã«ãƒ‡ãƒ—ロイ</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::QdbDevice</name>
+ <message>
+ <source>Starting command &quot;%1&quot; on device &quot;%2&quot;.</source>
+ <translation>デãƒã‚¤ã‚¹ &quot;%2&quot; ã§ã‚³ãƒžãƒ³ãƒ‰ &quot;%1&quot; を開始ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>WizardPage</source>
+ <translation>ウィザードページ</translation>
+ </message>
+ <message>
+ <source>Device name:</source>
+ <translation type="unfinished">デãƒã‚¤ã‚¹å:</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::QdbMakeDefaultAppService</name>
+ <message>
+ <source>Remote process failed: %1</source>
+ <translation>リモートプロセスãŒå¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Application set as the default one.</source>
+ <translation>デフォルトã§è¨­å®šã•ã‚Œã¦ã„るアプリケーション。</translation>
+ </message>
+ <message>
+ <source>Reset the default application.</source>
+ <translation>デフォルトã®ã‚¢ãƒ—リケーションをリセットã—ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::QdbMakeDefaultAppStep</name>
+ <message>
+ <source>Set this application to start by default</source>
+ <translation>ã“ã®ã‚¢ãƒ—リケーションをデフォルトã§èµ·å‹•ã™ã‚‹ã‚ˆã†ã«è¨­å®šã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Reset default application</source>
+ <translation>デフォルトã®ã‚¢ãƒ—リケーションをリセットã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Change default application</source>
+ <translation>デフォルトã®ã‚¢ãƒ—リケーションを変更ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb</name>
+ <message>
+ <source>Flash wizard &quot;%1&quot; failed to start.</source>
+ <translation>Flash ウィザード &quot;%1&quot; ã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Flash wizard executable &quot;%1&quot; not found.</source>
+ <translation>Flash ウィザードã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>Qdb::Internal::QdbRunConfiguration</name>
+ <message>
+ <source>Executable on device:</source>
+ <translation>デãƒã‚¤ã‚¹ä¸Šã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Remote path not set</source>
+ <translation>リモートã®ãƒ‘スãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Executable on host:</source>
+ <translation>ホスト上ã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+</context>
+<context>
+ <name>Boot2Qt</name>
+ <message>
+ <source>Boot2Qt: %1</source>
+ <translation>Boot2Qt: %1</translation>
+ </message>
+</context>
+<context>
+ <name>ClangCodeModel::ClangAssistProposalItem</name>
+ <message>
+ <source>Requires changing &quot;%1&quot; to &quot;%2&quot;</source>
+ <translation>&quot;%1&quot;ã‚’&quot;%2 &quot;ã«å¤‰æ›´ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™</translation>
+ </message>
+</context>
+<context>
+ <name>ClangCodeModel::Internal::BackendCommunicator</name>
+ <message>
+ <source>Clang Code Model: Error: The clangbackend executable &quot;%1&quot; does not exist.</source>
+ <translation>Clang コードモデル: エラー: clangbackend ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; ãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Clang Code Model: Error: The clangbackend executable &quot;%1&quot; could not be started (timeout after %2ms).</source>
+ <translation>Clang コードモデル: エラー: clangbackend ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ« &quot;%1&quot; ã‚’èµ·å‹•ã§ãã¾ã›ã‚“ã§ã—㟠(%2ms 後ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ)。</translation>
+ </message>
+ <message>
+ <source>Clang Code Model: Error: The clangbackend process has finished unexpectedly and was restarted.</source>
+ <translation>Clang コードモデル: エラー: clangbackend プロセスãŒäºˆæœŸã›ãšçµ‚了ã—ã€å†èµ·å‹•ã•ã‚Œã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>ClangCodeModel::Internal::ClangCodeModelPlugin</name>
+ <message>
+ <source>Generating Compilation DB</source>
+ <translation>コンパイル DB ã®ç”Ÿæˆ</translation>
+ </message>
+ <message>
+ <source>Clang Code Model</source>
+ <translation>Clang コードモデル</translation>
+ </message>
+ <message>
+ <source>Generate Compilation Database</source>
+ <translation>コンパイル DB ã®ç”Ÿæˆ</translation>
+ </message>
+ <message>
+ <source>Generate Compilation Database for &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ã‚³ãƒ³ãƒ‘イル・データベースを生æˆã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Clang compilation database generated at &quot;%1&quot;.</source>
+ <translation>Clang ã®ã‚³ãƒ³ãƒ‘イル・データベース㌠&quot;%1&quot; ã§ç”Ÿæˆã•ã‚Œã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Generating Clang compilation database failed: %1</source>
+ <translation>Clang ã®ã‚³ãƒ³ãƒ‘イル・データベースã®ç”Ÿæˆã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+</context>
+<context>
+ <name>ClangHoverHandler</name>
+ <message>
+ <source>%1 bytes</source>
+ <translation>%1 ãƒã‚¤ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Value: %1</source>
+ <translation>値: %1</translation>
+ </message>
+</context>
+<context>
+ <name>ClangCodeModel</name>
+ <message>
+ <source>&lt;No Symbols&gt;</source>
+ <translation>&lt;シンボルãªã—&gt;</translation>
+ </message>
+ <message>
+ <source>&lt;Select Symbol&gt;</source>
+ <translation>&lt;シンボルã®é¸æŠž&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>ClangDiagnosticConfig</name>
+ <message>
+ <source>Project: %1 (based on %2)</source>
+ <translation>プロジェクト: %1 (%2 を使用)</translation>
+ </message>
+ <message>
+ <source>Changes applied in Projects Mode &gt; Clang Code Model</source>
+ <translation>Projects Mode &gt; Clang コードモデルã§é©ç”¨ã•ã‚Œã‚‹å¤‰æ›´ç‚¹</translation>
+ </message>
+</context>
+<context>
+ <name>Clang Code Model Marks</name>
+ <message>
+ <source>Code Model Warning</source>
+ <translation>コードモデルã®è­¦å‘Š</translation>
+ </message>
+ <message>
+ <source>Code Model Error</source>
+ <translation>コードモデルã®ã‚¨ãƒ©ãƒ¼</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>クリップボードã«ã‚³ãƒ”ーã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Disable Diagnostic in Current Project</source>
+ <translation>ç¾åœ¨ã®ãƒ—ロジェクトã®è¨ºæ–­ã‚’無効化ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ClangUtils</name>
+ <message>
+ <source>Could not retrieve build directory.</source>
+ <translation>ビルドディレクトリをå–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Could not create &quot;%1&quot;: %2</source>
+ <translation>ファイル %1 を作æˆã§ãã¾ã›ã‚“ã§ã—ãŸ: %2</translation>
+ </message>
+</context>
+<context>
+ <name>ClangDiagnosticWidget</name>
+ <message>
+ <source>Clazy Issue</source>
+ <translation>Clazy ã®å•é¡Œ</translation>
+ </message>
+ <message>
+ <source>Clang-Tidy Issue</source>
+ <translation>Clang-Tidy ã®å•é¡Œ</translation>
+ </message>
+</context>
+<context>
+ <name>ClangFormat::ClangFormatPlugin</name>
+ <message>
+ <source>Open Used .clang-format Configuration File</source>
+ <translation>使用ã—㟠clang-format 設定ファイルを開ã</translation>
+ </message>
+ <message>
+ <source>The ClangFormat plugin has been built against an unmodified Clang. You might experience formatting glitches in certain circumstances. See https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/README.md for more information.</source>
+ <translation>ClangFormat プラグインã¯ã€å¤‰æ›´ã•ã‚Œã¦ã„ãªã„ Clang ã«å¯¾ã—ã¦ãƒ“ルドã•ã‚Œã¦ã„ã¾ã™ã€‚特定ã®çŠ¶æ³ä¸‹ã§ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã®ä¸å…·åˆãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚詳ã—ã㯠https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/README.md ã‚’ã”覧ãã ã•ã„。</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::ClangTool</name>
+ <message>
+ <source>Clear</source>
+ <translation>クリア</translation>
+ </message>
+ <message>
+ <source>Expand All</source>
+ <translation>ã™ã¹ã¦å±•é–‹</translation>
+ </message>
+ <message>
+ <source>Collapse All</source>
+ <translation>ã™ã¹ã¦æŠ˜ã‚ŠãŸãŸã‚€</translation>
+ </message>
+ <message>
+ <source>Run %1 in %2 Mode?</source>
+ <translation>%1 ã‚’%2モードã§å®Ÿè¡Œã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::ClangToolRunWorker</name>
+ <message>
+ <source>Analyzing</source>
+ <translation>解æžä¸­</translation>
+ </message>
+ <message>
+ <source>Failed to analyze &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; ã®è§£æžã«å¤±æ•—ã—ã¾ã—ãŸ: %2</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::ClangToolRunner</name>
+ <message>
+ <source>%1 crashed.</source>
+ <translation>%1 ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Command line: %1
+Process Error: %2
+Output:
+%3</source>
+ <translation>コマンドライン:%1
+プロセスエラー: %2
+出力:
+%3</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::ExplainingStep</name>
+ <message>
+ <source>Message:</source>
+ <translation>メッセージ:</translation>
+ </message>
+ <message>
+ <source>Location:</source>
+ <translation>パス:</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::DiagnosticView</name>
+ <message>
+ <source>Filter...</source>
+ <translation>フィルタ...</translation>
+ </message>
+ <message>
+ <source>Suppress This Diagnostic</source>
+ <translation>ã“ã®è¨ºæ–­ã‚’抑制ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>LogFileReader</name>
+ <message>
+ <source>File &quot;%1&quot; does not exist or is not readable.</source>
+ <translation>ファイル &quot;%1&quot; ãŒå­˜åœ¨ã—ãªã„ã‹èª­ã¿è¾¼ã¿å¯èƒ½ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::SuppressedDiagnosticsModel</name>
+ <message>
+ <source>File</source>
+ <translation>ファイル</translation>
+ </message>
+ <message>
+ <source>Diagnostic</source>
+ <translation>診断</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Diagnostic</name>
+ <message>
+ <source>Category:</source>
+ <translation>カテゴリ:</translation>
+ </message>
+ <message>
+ <source>Description:</source>
+ <translation>説明:</translation>
+ </message>
+ <message>
+ <source>Location:</source>
+ <translation>パス:</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::TidyOptionsDialog</name>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::TidyChecksTreeModel</name>
+ <message>
+ <source>Options</source>
+ <translation>オプション</translation>
+ </message>
+</context>
+<context>
+ <name>ClangTools::Internal::DiagnosticMark</name>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>クリップボードã«ã‚³ãƒ”ーã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ClearCase::Internal::ClearCasePluginPrivate</name>
+ <message>
+ <source>Editing Derived Object: %1</source>
+ <translation>派生オブジェクトã®ç·¨é›†ä¸­: %1</translation>
+ </message>
+ <message>
+ <source>C&amp;learCase</source>
+ <translation>C&amp;learCase</translation>
+ </message>
+ <message>
+ <source>Check Out...</source>
+ <translation>ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ...</translation>
+ </message>
+ <message>
+ <source>Check &amp;Out &quot;%1&quot;...</source>
+ <translation>&quot;%1&quot; ã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ(&amp;O)...</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+O</source>
+ <translation>Meta+L,Meta+O</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+O</source>
+ <translation>Alt+L,Alt+O</translation>
+ </message>
+ <message>
+ <source>Check &amp;In...</source>
+ <translation>ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³(&amp;I)...</translation>
+ </message>
+ <message>
+ <source>Check &amp;In &quot;%1&quot;...</source>
+ <translation>&quot;%1&quot; ã‚’ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³(&amp;I)...</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+I</source>
+ <translation>Meta+L,Meta+I</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+I</source>
+ <translation>Alt+L,Alt+I</translation>
+ </message>
+ <message>
+ <source>Undo Check Out</source>
+ <translation>ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã‚’å…ƒã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>&amp;Undo Check Out &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã‚’å…ƒã«æˆ»ã™(&amp;U)</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+U</source>
+ <translation>Meta+L,Meta+U</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+U</source>
+ <translation>Alt+L,Alt+U</translation>
+ </message>
+ <message>
+ <source>Undo Hijack</source>
+ <translation>ãƒã‚¤ã‚¸ãƒ£ãƒƒã‚¯ã‚’å…ƒã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Undo Hi&amp;jack &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ãƒã‚¤ã‚¸ãƒ£ãƒƒã‚¯ã‚’å…ƒã«æˆ»ã™(&amp;J)</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+R</source>
+ <translation>Meta+L,Meta+R</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+R</source>
+ <translation>Alt+L,Alt+R</translation>
+ </message>
+ <message>
+ <source>&amp;Diff &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®å·®åˆ†è¡¨ç¤º(&amp;D)</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+D</source>
+ <translation>Meta+L,Meta+D</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+D</source>
+ <translation>Alt+L,Alt+D</translation>
+ </message>
+ <message>
+ <source>History Current File</source>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®å±¥æ­´</translation>
+ </message>
+ <message>
+ <source>&amp;History &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®å±¥æ­´(&amp;H)</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+H</source>
+ <translation>Meta+L,Meta+H</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+H</source>
+ <translation>Alt+L,Alt+H</translation>
+ </message>
+ <message>
+ <source>&amp;Annotate &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³(&amp;A)</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+A</source>
+ <translation>Meta+L,Meta+A</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+A</source>
+ <translation>Alt+L,Alt+A</translation>
+ </message>
+ <message>
+ <source>Add File...</source>
+ <translation>ファイルを追加...</translation>
+ </message>
+ <message>
+ <source>Add File &quot;%1&quot;</source>
+ <translation>ファイル &quot;%1&quot; を追加</translation>
+ </message>
+ <message>
+ <source>Diff A&amp;ctivity...</source>
+ <translation>アクティビティã®å·®åˆ†è¡¨ç¤º(&amp;C)...</translation>
+ </message>
+ <message>
+ <source>Ch&amp;eck In Activity</source>
+ <translation>アクティビティをãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³(&amp;E)</translation>
+ </message>
+ <message>
+ <source>Chec&amp;k In Activity &quot;%1&quot;...</source>
+ <translation>アクティビティ &quot;%1&quot; ã‚’ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³(&amp;K)...</translation>
+ </message>
+ <message>
+ <source>Update Index</source>
+ <translation>インデックス更新</translation>
+ </message>
+ <message>
+ <source>Update View</source>
+ <translation>ビュー更新</translation>
+ </message>
+ <message>
+ <source>U&amp;pdate View &quot;%1&quot;</source>
+ <translation>ビュー &quot;%1&quot; 更新(&amp;P)</translation>
+ </message>
+ <message>
+ <source>Check In All &amp;Files...</source>
+ <translation>ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³(&amp;F)...</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+F</source>
+ <translation>Meta+L,Meta+F</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+F</source>
+ <translation>Alt+L,Alt+F</translation>
+ </message>
+ <message>
+ <source>View &amp;Status</source>
+ <translation>ステータス更新(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Meta+L,Meta+S</source>
+ <translation>Meta+L,Meta+S</translation>
+ </message>
+ <message>
+ <source>Alt+L,Alt+S</source>
+ <translation>Alt+L,Alt+S</translation>
+ </message>
+ <message>
+ <source>Check In</source>
+ <translation>ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³</translation>
+ </message>
+ <message>
+ <source>Do you want to undo the check out of &quot;%1&quot;?</source>
+ <translation>&quot;%1&quot; ã®ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã‚’å…ƒã«æˆ»ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Undo Hijack File</source>
+ <translation>ãƒã‚¤ã‚¸ãƒ£ãƒƒã‚¯ãƒ•ã‚¡ã‚¤ãƒ«ã‚’å…ƒã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Do you want to undo hijack of &quot;%1&quot;?</source>
+ <translation>&quot;%1&quot; ã®ãƒã‚¤ã‚¸ãƒ£ãƒƒã‚¯ã‚’å…ƒã«æˆ»ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>External diff is required to compare multiple files.</source>
+ <translation>外部 diff ツールã¯ã€è¤‡æ•°ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’比較ã§ãã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Enter Activity</source>
+ <translation>アクティビティã«å…¥ã‚‹</translation>
+ </message>
+ <message>
+ <source>Activity Name</source>
+ <translation>アクティビティå</translation>
+ </message>
+ <message>
+ <source>Check In Activity</source>
+ <translation>アクティビティをãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³</translation>
+ </message>
+ <message>
+ <source>Another check in is currently being executed.</source>
+ <translation>別ã®ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³ãŒå®Ÿè¡Œä¸­ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>There are no modified files.</source>
+ <translation>変更ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>No ClearCase executable specified.</source>
+ <translation>実行å¯èƒ½ãª ClearCase ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>ClearCase Checkout</source>
+ <translation>ClearCase ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ</translation>
+ </message>
+ <message>
+ <source>File is already checked out.</source>
+ <translation>ファイルã¯ã€æ—¢ã«ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Set current activity failed: %1</source>
+ <translation>アクティビティ設定失敗: %1</translation>
+ </message>
+ <message>
+ <source>Enter &amp;comment:</source>
+ <translation>コメントを入力(&amp;C):</translation>
+ </message>
+ <message>
+ <source>ClearCase Add File %1</source>
+ <translation>ClearCase ファイル %1 を追加</translation>
+ </message>
+ <message>
+ <source>ClearCase Remove Element %1</source>
+ <translation>ClearCase è¦ç´  %1 を削除</translation>
+ </message>
+ <message>
+ <source>This operation is irreversible. Are you sure?</source>
+ <translation>ã“ã®æ“作ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“ãŒã€ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>ClearCase Remove File %1</source>
+ <translation>ClearCase ファイル %1 を削除</translation>
+ </message>
+ <message>
+ <source>ClearCase Rename File %1 -&gt; %2</source>
+ <translation>ClearCase ファイルå変更 %1 -&gt; %2</translation>
+ </message>
+ <message>
+ <source>Activity Headline</source>
+ <translation>アクティビティ ヘッドライン</translation>
+ </message>
+ <message>
+ <source>Enter activity headline</source>
+ <translation>アクティビティ ヘッドラインã«å…¥ã‚‹</translation>
+ </message>
+ <message>
+ <source>Updating ClearCase Index</source>
+ <translation>ClearCase インデックスã®æ›´æ–°ä¸­</translation>
+ </message>
+ <message>
+ <source>Check &amp;Out</source>
+ <translation>ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ(&amp;O)</translation>
+ </message>
+ <message>
+ <source>&amp;Hijack</source>
+ <translation>ãƒã‚¤ã‚¸ãƒ£ãƒƒã‚¯(&amp;H)</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::CMakeBuildConfiguration</name>
+ <message>
+ <source>Changing Build Directory</source>
+ <translation>ビルドディレクトリã®å¤‰æ›´</translation>
+ </message>
+ <message>
+ <source>Change the build directory and start with a basic CMake configuration?</source>
+ <translation>ビルドディレクトリを変更ã—ã¦ã€åŸºæœ¬çš„㪠CMake ã®è¨­å®šã‹ã‚‰å§‹ã‚ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>The CMake flag for the development team</source>
+ <translation>開発ãƒãƒ¼ãƒ ã® CMake フラグ</translation>
+ </message>
+ <message>
+ <source>The CMake flag for the provisioning profile</source>
+ <translation>プロビジョニングプロファイル㮠CMake フラグ</translation>
+ </message>
+ <message>
+ <source>Minimum Size Release</source>
+ <translation>最å°ã‚µã‚¤ã‚ºãƒªãƒªãƒ¼ã‚¹</translation>
+ </message>
+ <message>
+ <source>Release with Debug Information</source>
+ <translation>デãƒãƒƒã‚°æƒ…報付ãリリース</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::CMakeConfigItem</name>
+ <message>
+ <source>Failed to open %1 for reading.</source>
+ <translation>読ã¿è¾¼ã¿ç”¨ã« %1 ã‚’é–‹ãã®ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::Internal::CMakeKitAspect</name>
+ <message>
+ <source>&lt;No CMake Tool available&gt;</source>
+ <translation>&lt;CMake ツールãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::CMakeKitAspect</name>
+ <message>
+ <source>The CMake Tool to use when building a project with CMake.&lt;br&gt;This setting is ignored when using other build systems.</source>
+ <translation>CMake ツールã¯ãƒ—ロジェクトを CMake ã§ãƒ“ルドã™ã‚‹éš›ã«ä½¿ç”¨ã—ã¾ã™ã€‚&lt;br&gt;ä»–ã®ãƒ“ルドシステム使用時ã«ã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>CMake</source>
+ <translation>CMake</translation>
+ </message>
+ <message>
+ <source>Unconfigured</source>
+ <translation>未設定</translation>
+ </message>
+ <message>
+ <source>Path to the cmake executable</source>
+ <translation>cmake 実行ファイルã¸ã®ãƒ‘ス</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::Internal::CMakeGeneratorKitAspect</name>
+ <message>
+ <source>Change...</source>
+ <translation>変更...</translation>
+ </message>
+ <message>
+ <source>CMake Generator</source>
+ <translation>CMake ジェãƒãƒ¬ãƒ¼ã‚¿</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::CMakeGeneratorKitAspect</name>
+ <message>
+ <source>CMake generator defines how a project is built when using CMake.&lt;br&gt;This setting is ignored when using other build systems.</source>
+ <translation>CMake ジェãƒãƒ¬ãƒ¼ã‚¿ã¯ CMake 使用時ã®ãƒ—ロジェクトビルド方法を定義ã—ã¾ã™ã€‚&lt;br&gt;ä»–ã®ãƒ“ルドシステム使用時ã«ã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>CMake Tool is unconfigured, CMake generator will be ignored.</source>
+ <translation>CMake ツールãŒè¨­å®šã•ã‚Œã¦ã„ãªã„ãŸã‚ã€CMake ジェãƒãƒ¬ãƒ¼ã‚¿ã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>CMake Tool does not support the configured generator.</source>
+ <translation>CMake ツールãŒã‚¸ã‚§ãƒãƒ¬ãƒ¼ã‚¿ã«å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>&lt;Use Default Generator&gt;</source>
+ <translation>&lt;既定ã®ã‚¸ã‚§ãƒãƒ¬ãƒ¼ã‚¿ã‚’使用&gt;</translation>
+ </message>
+ <message>
+ <source>CMake Generator</source>
+ <translation>CMake ジェãƒãƒ¬ãƒ¼ã‚¿</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::Internal::CMakeConfigurationKitAspect</name>
+ <message>
+ <source>Change...</source>
+ <translation>変更...</translation>
+ </message>
+ <message>
+ <source>Edit CMake Configuration</source>
+ <translation>CMake 設定ã®ç·¨é›†</translation>
+ </message>
+ <message>
+ <source>Enter one variable per line with the variable name separated from the variable value by &quot;=&quot;.&lt;br&gt;You may provide a type hint by adding &quot;:TYPE&quot; before the &quot;=&quot;.</source>
+ <translation>一行ã«ä»˜ã一ã¤ã®å¤‰æ•°ã‚’ãã®åã¨å€¤ã‚’ &quot;=&quot; ã§ç¹‹ãå½¢å¼ã§å…¥åŠ›ã—ã¦ãã ã•ã„。&lt;br&gt;&quot;=&quot; ã®å‰ã« &quot;:TYPE&quot; å½¢å¼ã§åž‹ã®ãƒ’ントを指定ã§ãã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::CMakeConfigurationKitAspect</name>
+ <message>
+ <source>CMake Configuration</source>
+ <translation>CMake 設定</translation>
+ </message>
+ <message>
+ <source>Default configuration passed to CMake when setting up a project.</source>
+ <translation>プロジェクト設定時ã«æ—¢å®šã®è¨­å®šãŒ CMake ã«æ¸¡ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>CMake configuration has no path to qmake binary set, even though the kit has a valid Qt version.</source>
+ <translation>キットã«æœ‰åŠ¹ãª Qt ãŒå­˜åœ¨ã™ã‚‹ã«ã‚‚ã‹ã‹ã‚らãšã€CMake ã®è¨­å®šã« qmake ã¸ã®ãƒ‘スãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>CMake configuration has a path to a qmake binary set, even though the kit has no valid Qt version.</source>
+ <translation>キットã«æœ‰åŠ¹ãª Qt ãŒå­˜åœ¨ã—ãªã„ã«ã‚‚ã‹ã‹ã‚らãšã€CMake ã®è¨­å®šã« qmake ã¸ã®ãƒ‘スãŒå­˜åœ¨ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>CMake configuration has no path to a C++ compiler set, even though the kit has a valid tool chain.</source>
+ <translation>キットã«æœ‰åŠ¹ãªãƒ„ールãƒã‚§ã‚¤ãƒ³ãŒå­˜åœ¨ã™ã‚‹ã«ã‚‚ã‹ã‹ã‚らãšã€CMake ã®è¨­å®šã« C++ コンパイラã¸ã®ãƒ‘スãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>CMake configuration has a path to a C++ compiler set, even though the kit has no valid tool chain.</source>
+ <translation>キットã«æœ‰åŠ¹ãªãƒ„ールãƒã‚§ã‚¤ãƒ³ãŒå­˜åœ¨ã—ãªã„ã«ã‚‚ã‹ã‹ã‚らãšã€CMake ã®è¨­å®šã« C++ コンパイラã¸ã®ãƒ‘スãŒå­˜åœ¨ã—ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::Internal::BuildCMakeTargetLocatorFilter</name>
+ <message>
+ <source>Build CMake target</source>
+ <translation>CMake ターゲットをビルド</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::Internal::CMakeProcess</name>
+ <message>
+ <source>Configuring &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®è¨­å®šä¸­</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::Internal::CMakeProjectPlugin</name>
+ <message>
+ <source>Build</source>
+ <translation>ビルド</translation>
+ </message>
+ <message>
+ <source>Build &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ãƒ“ルド</translation>
+ </message>
+ <message>
+ <source>CMake</source>
+ <comment>SnippetProvider</comment>
+ <translation>CMake</translation>
+ </message>
+</context>
+<context>
+ <name>CMakeProjectManager::Internal::CMakeSpecificSettingWidget</name>
+ <message>
+ <source>CMake</source>
+ <translation>CMake</translation>
+ </message>
+</context>
+<context>
+ <name>ConanPackageManager::Internal::ConanInstallStep</name>
+ <message>
+ <source>Additional arguments:</source>
+ <translation>追加ã®å¼•æ•°:</translation>
+ </message>
+</context>
+<context>
+ <name>Core::CodecSelector</name>
+ <message>
+ <source>Text Encoding</source>
+ <translation>文字コードã®æŒ‡å®š</translation>
+ </message>
+ <message>
+ <source>The following encodings are likely to fit:</source>
+ <translation>以下ã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ãŒé©ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™:</translation>
+ </message>
+ <message>
+ <source>Select encoding for &quot;%1&quot;.%2</source>
+ <translation>&quot;%1&quot; ã®æ–‡å­—コードをé¸æŠžã—ã¦ãã ã•ã„。%2</translation>
+ </message>
+ <message>
+ <source>Reload with Encoding</source>
+ <translation>指定ã•ã‚ŒãŸæ–‡å­—コードã§å†èª­è¾¼</translation>
+ </message>
+ <message>
+ <source>Save with Encoding</source>
+ <translation>指定ã•ã‚ŒãŸæ–‡å­—コードã§ä¿å­˜</translation>
+ </message>
+</context>
+<context>
+ <name>Core::ExternalToolConfig</name>
+ <message>
+ <source>Uncategorized</source>
+ <translation>未分類</translation>
+ </message>
+ <message>
+ <source>Tools that will appear directly under the External Tools menu.</source>
+ <translation>ツールã¯å¤–部ツールメニューã®ç›´ä¸‹ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>New Category</source>
+ <translation>æ–°ã—ã„カテゴリ</translation>
+ </message>
+ <message>
+ <source>New Tool</source>
+ <translation>æ–°ã—ã„ツール</translation>
+ </message>
+ <message>
+ <source>This tool prints a line of useful text</source>
+ <translation>ã“ã®ãƒ„ールã¯ãƒ†ã‚­ã‚¹ãƒˆã‚’1行を出力ã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Useful text</source>
+ <extracomment>Sample external tool text</extracomment>
+ <translation>テキスト</translation>
+ </message>
+ <message>
+ <source>Add Tool</source>
+ <translation>ツールを追加</translation>
+ </message>
+ <message>
+ <source>Add Category</source>
+ <translation>カテゴリを追加</translation>
+ </message>
+ <message>
+ <source>PATH=C:\dev\bin;${PATH}</source>
+ <translation>PATH=C:\dev\bin;${PATH}</translation>
+ </message>
+ <message>
+ <source>PATH=/opt/bin:${PATH}</source>
+ <translation>PATH=/opt/bin:${PATH}</translation>
+ </message>
+ <message>
+ <source>No changes to apply.</source>
+ <translation>変更ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>External Tools</source>
+ <translation>外部ツール</translation>
+ </message>
+</context>
+<context>
+ <name>ExternalTool</name>
+ <message>
+ <source>System Environment</source>
+ <translation>システム環境変数</translation>
+ </message>
+</context>
+<context>
+ <name>Core::RestartDialog</name>
+ <message>
+ <source>Restart Required</source>
+ <translation>å†èµ·å‹•ãŒå¿…è¦ã§ã™</translation>
+ </message>
+</context>
+<context>
+ <name>Core::Internal::ShortcutInput</name>
+ <message>
+ <source>Key sequence:</source>
+ <translation>キーシーケンス:</translation>
+ </message>
+ <message>
+ <source>Use &quot;Cmd&quot;, &quot;Opt&quot;, &quot;Ctrl&quot;, and &quot;Shift&quot; for modifier keys. Use &quot;Escape&quot;, &quot;Backspace&quot;, &quot;Delete&quot;, &quot;Insert&quot;, &quot;Home&quot;, and so on, for special keys. Combine individual keys with &quot;+&quot;, and combine multiple shortcuts to a shortcut sequence with &quot;,&quot;. For example, if the user must hold the Ctrl and Shift modifier keys while pressing Escape, and then release and press A, enter &quot;Ctrl+Shift+Escape,A&quot;.</source>
+ <translation>修飾キーã«ã¯ &quot;Cmd&quot; ã‚„ &quot;Opt&quot;, &quot;Ctrl&quot;, &quot;Shift&quot; を使用ã—ã¦ãã ã•ã„。特殊キーã¨ã—㦠&quot;Escape&quot; ã‚„ &quot;Backspace&quot;, &quot;Delete&quot;, &quot;Insert&quot;, &quot;Home&quot; ãªã©ã‚‚使用ã§ãã¾ã™ã€‚å„キーを組ã¿åˆã‚ã›ã‚‹å ´åˆã¯ &quot;+&quot; ã‚’ã€è¤‡æ•°ã®ã‚·ãƒ¼ã‚±ãƒ³ã‚¹ã§æ§‹æˆã•ã‚Œã‚‹ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆã¯ &quot;,&quot; を使用ã—ã¦ãã ã•ã„。例ãˆã°ã€Ctrl キー㨠Shift キーを押ã—ãªãŒã‚‰ Escape キーを押ã—ã¦ã€ãれらを離ã—ãŸå¾Œã« A キーを押ã™å ´åˆã¯ &quot;Ctrl+Shift+Escape,A&quot; ã¨å…¥åŠ›ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Use &quot;Ctrl&quot;, &quot;Alt&quot;, &quot;Meta&quot;, and &quot;Shift&quot; for modifier keys. Use &quot;Escape&quot;, &quot;Backspace&quot;, &quot;Delete&quot;, &quot;Insert&quot;, &quot;Home&quot;, and so on, for special keys. Combine individual keys with &quot;+&quot;, and combine multiple shortcuts to a shortcut sequence with &quot;,&quot;. For example, if the user must hold the Ctrl and Shift modifier keys while pressing Escape, and then release and press A, enter &quot;Ctrl+Shift+Escape,A&quot;.</source>
+ <translation>修飾キーã«ã¯ &quot;Ctrl&quot; ã‚„ &quot;Alt&quot;, &quot;Meta&quot;, &quot;Shift&quot; を使用ã—ã¦ãã ã•ã„。特殊キーã¨ã—㦠&quot;Escape&quot; ã‚„ &quot;Backspace&quot;, &quot;Delete&quot;, &quot;Insert&quot;, &quot;Home&quot; ãªã©ã‚‚使用ã§ãã¾ã™ã€‚å„キーを組ã¿åˆã‚ã›ã‚‹å ´åˆã¯ &quot;+&quot; ã‚’ã€è¤‡æ•°ã®ã‚·ãƒ¼ã‚±ãƒ³ã‚¹ã§æ§‹æˆã•ã‚Œã‚‹ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆã¯ &quot;,&quot; を使用ã—ã¦ãã ã•ã„。例ãˆã°ã€Ctrl キー㨠Shift キーを押ã—ãªãŒã‚‰ Escape キーを押ã—ã¦ã€ãれらを離ã—ãŸå¾Œã« A キーを押ã™å ´åˆã¯ &quot;Ctrl+Shift+Escape,A&quot; ã¨å…¥åŠ›ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Enter key sequence as text</source>
+ <translation>キーシーケンスを文字列ã§å…¥åŠ›ã—ã¦ãã ã•ã„</translation>
+ </message>
+</context>
+<context>
+ <name>Core::Internal::DocumentManagerPrivate</name>
+ <message>
+ <source>Ctrl+Shift+S</source>
+ <translation>Ctrl+Shift+S</translation>
+ </message>
+ <message>
+ <source>Save A&amp;ll</source>
+ <translation>ã™ã¹ã¦ä¿å­˜(&amp;L)</translation>
+ </message>
+</context>
+<context>
+ <name>OpenEditorsWidget</name>
+ <message>
+ <source>Open Documents</source>
+ <translation>é–‹ã„ã¦ã„るドキュメント</translation>
+ </message>
+ <message>
+ <source>Meta+O</source>
+ <translation>Meta+O</translation>
+ </message>
+ <message>
+ <source>Alt+O</source>
+ <translation>Alt+O</translation>
+ </message>
+</context>
+<context>
+ <name>EditorManager</name>
+ <message>
+ <source>Revert to Saved</source>
+ <translation type="vanished">ä¿å­˜æ™‚ã®çŠ¶æ…‹ã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation type="vanished">é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close All</source>
+ <translation type="vanished">ã™ã¹ã¦é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close Others</source>
+ <translation type="vanished">ä»–ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close All Except Visible</source>
+ <translation type="vanished">表示ã•ã‚Œã¦ã„ãªã„ファイルをã™ã¹ã¦é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Next Open Document in History</source>
+ <translation type="vanished">履歴内ã®æ¬¡ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã«ç§»å‹•</translation>
+ </message>
+ <message>
+ <source>Previous Open Document in History</source>
+ <translation type="vanished">履歴内ã®å‰ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã«ç§»å‹•</translation>
+ </message>
+ <message>
+ <source>Go Back</source>
+ <translation>戻る</translation>
+ </message>
+ <message>
+ <source>Go Forward</source>
+ <translation>進む</translation>
+ </message>
+ <message>
+ <source>Copy Full Path</source>
+ <translation type="vanished">フルパスをコピー</translation>
+ </message>
+ <message>
+ <source>Copy Path and Line Number</source>
+ <translation type="vanished">パスã¨è¡Œç•ªå·ã‚’コピー</translation>
+ </message>
+ <message>
+ <source>Copy File Name</source>
+ <translation type="vanished">ファイルåをコピー</translation>
+ </message>
+ <message>
+ <source>&amp;Save</source>
+ <translation>ä¿å­˜(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Save &amp;As...</source>
+ <translation>åå‰ã‚’付ã‘ã¦ä¿å­˜(&amp;A)...</translation>
+ </message>
+ <message>
+ <source>Continue Opening Huge Text File?</source>
+ <translation type="vanished">巨大ãªãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’引ã続ãé–‹ãã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>The text file &quot;%1&quot; has the size %2MB and might take more memory to open and process than available.
+
+Continue?</source>
+ <translation type="vanished">テキストファイル &quot;%1&quot; ã®ã‚µã‚¤ã‚ºã¯ %2MB ã‚ã‚Šã€é–‹ã„ã¦å‡¦ç†ã™ã‚‹ã®ã«ä½™åˆ†ã«ãƒ¡ãƒ¢ãƒªã‚’å¿…è¦ã¨ã—ã¾ã™ã€‚
+
+継続ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>File Error</source>
+ <translation type="vanished">ファイルエラー</translation>
+ </message>
+ <message>
+ <source>Split</source>
+ <translation>上下ã«åˆ†å‰²</translation>
+ </message>
+ <message>
+ <source>Split Side by Side</source>
+ <translation>å·¦å³ã«åˆ†å‰²</translation>
+ </message>
+ <message>
+ <source>Open in New Window</source>
+ <translation>æ–°è¦ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Close Document</source>
+ <translation>ドキュメントを閉ã˜ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>Core::ICore</name>
+ <message>
+ <source> (%1)</source>
+ <translation> (%1)</translation>
+ </message>
+ <message>
+ <source>%1 %2%3</source>
+ <translation>%1 %2%3</translation>
+ </message>
+ <message>
+ <source>Based on Qt %1 (%2, %3 bit)</source>
+ <translation>Qt %1 (%2, %3 ビット) を使用</translation>
+ </message>
+</context>
+<context>
+ <name>Core::DirectoryFilter</name>
+ <message>
+ <source>Generic Directory Filter</source>
+ <translation>一般的ãªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ•ã‚£ãƒ«ã‚¿</translation>
+ </message>
+ <message>
+ <source>Select Directory</source>
+ <translation>ディレクトリã®é¸æŠž</translation>
+ </message>
+ <message>
+ <source>%1 filter update: 0 files</source>
+ <translation>フィルタ %1 ã®æ›´æ–°: 0 個ã®ãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message numerus="yes">
+ <source>%1 filter update: %n files</source>
+ <translation>
+ <numerusform>フィルタ %1 ã®æ›´æ–°: %n 個ã®ãƒ•ã‚¡ã‚¤ãƒ«</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>%1 filter update: canceled</source>
+ <translation>フィルタ %1 ã®æ›´æ–°: キャンセルã—ã¾ã—ãŸ</translation>
+ </message>
+</context>
+<context>
+ <name>Core::UrlLocatorFilter</name>
+ <message>
+ <source>Web Search</source>
+ <translation>Web 検索</translation>
+ </message>
+</context>
+<context>
+ <name>Core::LocatorManager</name>
+ <message>
+ <source>&lt;type here&gt;</source>
+ <translation>&lt;入力ã—ã¦ãã ã•ã„&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>Core::IOutputPane</name>
+ <message>
+ <source>Use Regular Expressions</source>
+ <translation>æ­£è¦è¡¨ç¾ã‚’使用ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>Core::Internal::PluginInstallWizard</name>
+ <message>
+ <source>Source</source>
+ <translation>ソース</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>キャンセル</translation>
+ </message>
+ <message>
+ <source>Summary</source>
+ <translation>概è¦</translation>
+ </message>
+ <message>
+ <source>Overwrite</source>
+ <translation>上書ãã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>Core::Internal::SystemSettingsWidget</name>
+ <message>
+ <source>Command line arguments used for &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; ã«ä½¿ç”¨ã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³å¼•æ•°ã€‚</translation>
+ </message>
+ <message>
+ <source>Command used for reverting diff chunks.</source>
+ <translation>差分ãƒãƒ£ãƒ³ã‚¯ã‚’å…ƒã«æˆ»ã™éš›ã«ä½¿ç”¨ã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Automatically creates temporary copies of modified files. If %1 is restarted after a crash or power failure, it asks whether to recover the auto-saved content.</source>
+ <translation>変更ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã®ä¸€æ™‚çš„ãªã‚³ãƒ”ーを自動的ã«ä½œæˆã—ã¾ã™ã€‚%1 ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã‚„é›»æºæ–­ãªã©ã‹ã‚‰å¾©å¸°ã—ãŸéš›ã«ã€è‡ªå‹•ä¿å­˜ã—ãŸå†…容を復元ã™ã‚‹ã‹ã©ã†ã‹ã‚’確èªã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Crash Reporting</source>
+ <translation>クラッシュレãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>The change will take effect after restart.</source>
+ <translation>変更㯠Qt Creator ã‚’å†èµ·å‹•ã—ãŸå¾Œã«å映ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Case Sensitive (Default)</source>
+ <translation>大文字å°æ–‡å­—を区別ã™ã‚‹ (既定)</translation>
+ </message>
+ <message>
+ <source>Case Sensitive</source>
+ <translation>大文字å°æ–‡å­—を区別ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Case Insensitive (Default)</source>
+ <translation>大文字å°æ–‡å­—を区別ã—ãªã„ (既定)</translation>
+ </message>
+ <message>
+ <source>Case Insensitive</source>
+ <translation>大文字å°æ–‡å­—を区別ã—ãªã„</translation>
+ </message>
+ <message>
+ <source>No changes to apply.</source>
+ <translation>変更ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Variables</source>
+ <translation>変数</translation>
+ </message>
+ <message>
+ <source>System</source>
+ <translation>システム</translation>
+ </message>
+</context>
+<context>
+ <name>Core::ListItemDelegate</name>
+ <message>
+ <source>Tags:</source>
+ <translation>ã‚¿ã‚°:</translation>
+ </message>
+</context>
+<context>
+ <name>Cppcheck::Internal::DiagnosticsModel</name>
+ <message>
+ <source>Diagnostic</source>
+ <translation>診断</translation>
+ </message>
+</context>
+<context>
+ <name>CppcheckOptionsPage</name>
+ <message>
+ <source>Warnings</source>
+ <translation>警告</translation>
+ </message>
+ <message>
+ <source>Style</source>
+ <translation>スタイル</translation>
+ </message>
+ <message>
+ <source>Performance</source>
+ <translation>性能</translation>
+ </message>
+ <message>
+ <source>Ignored file patterns:</source>
+ <translation>無視ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ãƒ‘ターン:</translation>
+ </message>
+</context>
+<context>
+ <name>Cppcheck::Internal::CppcheckPlugin</name>
+ <message>
+ <source>Clear</source>
+ <translation>クリア</translation>
+ </message>
+</context>
+<context>
+ <name>CppEditor::Internal::CppIncludeHierarchyWidget</name>
+ <message>
+ <source>No include hierarchy available</source>
+ <translation>インクルード階層ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Synchronize with Editor</source>
+ <translation>エディタã¨åŒæœŸ</translation>
+ </message>
+</context>
+<context>
+ <name>CppEditor::Internal::MinimizableInfoBars</name>
+ <message>
+ <source>Minimize</source>
+ <translation>最å°åŒ–</translation>
+ </message>
+</context>
+<context>
+ <name>CppEditor::CppQuickFixFactory</name>
+ <message>
+ <source>Create Getter and Setter Member Functions</source>
+ <translation>ゲッターåŠã³ã‚»ãƒƒã‚¿ãƒ¼ãƒ¡ãƒ³ãƒé–¢æ•°ã‚’作æˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Convert to Stack Variable</source>
+ <translation>スタック変数ã«å¤‰æ›</translation>
+ </message>
+ <message>
+ <source>Convert to Pointer</source>
+ <translation>ãƒã‚¤ãƒ³ã‚¿ã«å¤‰æ›</translation>
+ </message>
+ <message>
+ <source>Base Class Constructors</source>
+ <translation>ベースクラスã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿</translation>
+ </message>
+</context>
+<context>
+ <name>GenerateGettersSettersDialog</name>
+ <message>
+ <source>Signal</source>
+ <translation>シグナル</translation>
+ </message>
+ <message>
+ <source>Reset</source>
+ <translation>リセット</translation>
+ </message>
+</context>
+<context>
+ <name>CppEditor::Internal::ConstructorParams</name>
+ <message>
+ <source>Initialize in Constructor</source>
+ <translation>コンストラクタã§ã®åˆæœŸåŒ–</translation>
+ </message>
+ <message>
+ <source>Member Name</source>
+ <translation>メンãƒãƒ¼å</translation>
+ </message>
+ <message>
+ <source>Parameter Name</source>
+ <translation>パラメータå</translation>
+ </message>
+ <message>
+ <source>Default Value</source>
+ <translation>デフォルト値</translation>
+ </message>
+</context>
+<context>
+ <name>GenerateConstructorDialog</name>
+ <message>
+ <source>Access</source>
+ <translation>アクセス</translation>
+ </message>
+</context>
+<context>
+ <name>CppTypeHierarchyTreeView</name>
+ <message>
+ <source>Open in Editor</source>
+ <translation>エディタã§é–‹ã</translation>
+ </message>
+ <message>
+ <source>Open Type Hierarchy</source>
+ <translation>型階層を開ã</translation>
+ </message>
+ <message>
+ <source>Expand All</source>
+ <translation>ã™ã¹ã¦å±•é–‹</translation>
+ </message>
+ <message>
+ <source>Collapse All</source>
+ <translation>ã™ã¹ã¦æŠ˜ã‚ŠãŸãŸã‚€</translation>
+ </message>
+</context>
+<context>
+ <name>CppTools::ConfigsModel</name>
+ <message>
+ <source>Built-in</source>
+ <translation>ビルトイン</translation>
+ </message>
+ <message>
+ <source>Custom</source>
+ <translation>カスタム</translation>
+ </message>
+</context>
+<context>
+ <name>CppTools::Internal::CppCodeModelSettingsWidget</name>
+ <message>
+ <source>Code Model</source>
+ <translation>コードモデル</translation>
+ </message>
+</context>
+<context>
+ <name>CppTools::OverviewModel</name>
+ <message>
+ <source>&lt;Select Symbol&gt;</source>
+ <translation>&lt;シンボルã®é¸æŠž&gt;</translation>
+ </message>
+ <message>
+ <source>&lt;No Symbols&gt;</source>
+ <translation>&lt;シンボルãªã—&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>CtfVisualizer::Internal::CtfStatisticsModel</name>
+ <message>
+ <source>Title</source>
+ <translation>タイトル</translation>
+ </message>
+ <message>
+ <source>Count</source>
+ <translation>カウント</translation>
+ </message>
+ <message>
+ <source>Total Time</source>
+ <translation>åˆè¨ˆæ™‚é–“</translation>
+ </message>
+</context>
+<context>
+ <name>CtfVisualizer::Internal::CtfTimelineModel</name>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+ <message>
+ <source>Start</source>
+ <translation>開始</translation>
+ </message>
+ <message>
+ <source>Arguments</source>
+ <translation>引数</translation>
+ </message>
+</context>
+<context>
+ <name>CtfVisualizer::Internal::CtfVisualizerTool</name>
+ <message>
+ <source>Timeline</source>
+ <translation>タイムライン</translation>
+ </message>
+ <message>
+ <source>Reset Zoom</source>
+ <translation>縮尺を戻ã™</translation>
+ </message>
+ <message>
+ <source>Statistics</source>
+ <translation>統計</translation>
+ </message>
+</context>
+<context>
+ <name>BreakHandler</name>
+ <message>
+ <source>Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆ</translation>
+ </message>
+</context>
+<context>
+ <name>Debugger::Internal::BreakpointManager</name>
+ <message>
+ <source>Function</source>
+ <translation>関数</translation>
+ </message>
+ <message>
+ <source>File</source>
+ <translation>ファイル</translation>
+ </message>
+ <message>
+ <source>Line</source>
+ <translation>行番å·</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>アドレス</translation>
+ </message>
+ <message>
+ <source>Condition</source>
+ <translation>æ¡ä»¶</translation>
+ </message>
+ <message>
+ <source>Ignore</source>
+ <translation>無視</translation>
+ </message>
+ <message>
+ <source>Threads</source>
+ <translation>スレッド</translation>
+ </message>
+ <message>
+ <source>Add Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã‚’追加</translation>
+ </message>
+ <message>
+ <source>Add Breakpoint...</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã‚’追加...</translation>
+ </message>
+ <message>
+ <source>Delete Selected Breakpoints</source>
+ <translation>é¸æŠžã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Edit Selected Breakpoints...</source>
+ <translation>é¸æŠžã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’編集ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Disable Selected Breakpoints</source>
+ <translation>é¸æŠžã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã®ç„¡åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Enable Selected Breakpoints</source>
+ <translation>é¸æŠžã—ãŸãƒ–レークãƒã‚¤ãƒ³ãƒˆã®æœ‰åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Disable Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®ç„¡åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Enable Breakpoint</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®æœ‰åŠ¹åŒ–</translation>
+ </message>
+ <message>
+ <source>Delete All Breakpoints</source>
+ <translation>ã™ã¹ã¦ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete Breakpoints of &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete Breakpoints of File</source>
+ <translation>ファイル内ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove All Breakpoints</source>
+ <translation>ã™ã¹ã¦ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to remove all breakpoints from all files in the current session?</source>
+ <translation>ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‹ã‚‰ã™ã¹ã¦ã®ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’本当ã«å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+</context>
+<context>
+ <name>Debugger::DebuggerKitAspect</name>
+ <message>
+ <source>Type of Debugger Backend</source>
+ <translation>デãƒãƒƒã‚¬ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã®ç¨®é¡ž</translation>
+ </message>
+ <message>
+ <source>Debugger</source>
+ <translation>デãƒãƒƒã‚¬</translation>
+ </message>
+ <message>
+ <source>Unknown debugger version</source>
+ <translation>未知ãªãƒ‡ãƒãƒƒã‚¬ãƒãƒ¼ã‚¸ãƒ§ãƒ³</translation>
+ </message>
+ <message>
+ <source>Unknown debugger ABI</source>
+ <translation>未知ãªãƒ‡ãƒãƒƒã‚¬ ABI</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>ã—ãªã„</translation>
+ </message>
+ <message>
+ <source>The debugger to use for this kit.</source>
+ <translation>ã“ã®ã‚­ãƒƒãƒˆã§ä½¿ç”¨ã™ã‚‹ãƒ‡ãƒãƒƒã‚¬ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>No debugger set up.</source>
+ <translation>デãƒãƒƒã‚¬ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Debugger &quot;%1&quot; not found.</source>
+ <translation>デãƒãƒƒã‚¬ &quot;%1&quot; ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Debugger &quot;%1&quot; not executable.</source>
+ <translation>デãƒãƒƒã‚¬ &quot;%1&quot; ã¯å®Ÿè¡Œå¯èƒ½ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>The debugger location must be given as an absolute path (%1).</source>
+ <translation>デãƒãƒƒã‚¬ã®ãƒ‘スã¯çµ¶å¯¾ãƒ‘スを指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ (%1)。</translation>
+ </message>
+ <message>
+ <source>The ABI of the selected debugger does not match the toolchain ABI.</source>
+ <translation>é¸æŠžã—ãŸãƒ‡ãƒãƒƒã‚¬ã® ABI ãŒãƒ„ールãƒã‚§ã‚¤ãƒ³ã® ABI ã¨åˆè‡´ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Name of Debugger</source>
+ <translation>デãƒãƒƒã‚¬ã®åå‰</translation>
+ </message>
+ <message>
+ <source>Unknown debugger</source>
+ <translation>未知ã®ãƒ‡ãƒãƒƒã‚¬</translation>
+ </message>
+ <message>
+ <source>Unknown debugger type</source>
+ <translation>ä¸æ˜Žãªãƒ‡ãƒãƒƒã‚¬ç¨®é¡ž</translation>
+ </message>
+ <message>
+ <source>No Debugger</source>
+ <translation>デãƒãƒƒã‚¬ãªã—</translation>
+ </message>
+ <message>
+ <source>%1 Engine</source>
+ <translation>%1 エンジン</translation>
+ </message>
+ <message>
+ <source>%1 &lt;None&gt;</source>
+ <translation>%1 &lt;ãªã—&gt;</translation>
+ </message>
+ <message>
+ <source>%1 using &quot;%2&quot;</source>
+ <translation>%1 (&quot;%2&quot; を使用)</translation>
+ </message>
+</context>
+<context>
+ <name>DeviceProcessesDialog</name>
+ <message>
+ <source>&amp;Attach to Process</source>
+ <translation>プロセスã«ã‚¢ã‚¿ãƒƒãƒ(&amp;A)</translation>
+ </message>
+</context>
+<context>
+ <name>Debugger::Internal::LocalProcessRunner</name>
+ <message>
+ <source>The upload process failed to start. Shell missing?</source>
+ <translation>アップロードプロセスã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸã€‚シェルãŒå¤±ã‚ã‚Œã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>The upload process crashed some time after starting successfully.</source>
+ <translation>アップロードプロセス起動ãŒæˆåŠŸã—ãŸå¾Œã«ã€ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.</source>
+ <translation>ç›´å‰ã® waitFor...() 関数ã¯ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚QProcess ã®çŠ¶æ…‹ã«å¤‰åŒ–ãŒãªã„ãŸã‚ã€å†åº¦ waitFor...() を呼ã³å‡ºã›ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>An error occurred when attempting to write to the upload process. For example, the process may not be running, or it may have closed its input channel.</source>
+ <translation>アップロードプロセスã¸ã®æ›¸ãè¾¼ã¿æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚プロセスãŒå‹•ä½œã—ã¦ã„ãªã„ã‹ã€å…¥åŠ›ãƒãƒ£ãƒãƒ«ãŒé–‰ã˜ã‚‰ã‚Œã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>An error occurred when attempting to read from the upload process. For example, the process may not be running.</source>
+ <translation>アップロードプロセスã‹ã‚‰ã®èª­ã¿è¾¼ã¿æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚アップロードプロセスãŒå‹•ä½œã—ã¦ã„ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>An unknown error in the upload process occurred. This is the default return value of error().</source>
+ <translation>アップロードプロセスã§ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚error() ã®æ—¢å®šã®è¿”り値ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+</context>
+<context>
+ <name>Debugger::DebuggerRunTool</name>
+ <message>
+ <source>Cannot debug: Local executable is not set.</source>
+ <translation>デãƒãƒƒã‚°ã‚¨ãƒ©ãƒ¼: ローカル実行ファイルãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>No executable specified.</source>
+ <translation>実行ファイルãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Debugged executable</source>
+ <translation>デãƒãƒƒã‚°ã™ã‚‹å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message>
+ <source>Unsupported CDB host system.</source>
+ <translation>サãƒãƒ¼ãƒˆå¯¾è±¡å¤–ã® CDB ホストシステムã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Debugger</source>
+ <translation>デãƒãƒƒã‚¬</translation>
+ </message>
+ <message>
+ <source>&amp;Show this message again.</source>
+ <translation>ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å†ã³è¡¨ç¤ºã™ã‚‹(&amp;S)。</translation>
+ </message>
+ <message>
+ <source>Debugging starts</source>
+ <translation type="vanished">デãƒãƒƒã‚°ã‚’開始</translation>
+ </message>
+ <message>
+ <source>Starting debugger &quot;%1&quot; for ABI &quot;%2&quot;...</source>
+ <translation>ABI &quot;%2&quot; ã®ãƒ‡ãƒãƒƒã‚¬ &quot;%1&quot; を開始ã—ã¦ã„ã¾ã™...</translation>
+ </message>
+ <message>
+ <source>Debugging has finished</source>
+ <translation type="vanished">デãƒãƒƒã‚°ãŒçµ‚了ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Close Debugging Session</source>
+ <translation>デãƒãƒƒã‚°ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>A debugging session is still in progress. Terminating the session in the current state can leave the target in an inconsistent state. Would you still like to terminate it?</source>
+ <translation>デãƒãƒƒã‚°ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ã€ã¾ã å®Ÿè¡Œä¸­ã§ã™ã€‚終了ã—よã†ã¨ã—ã¦ã„るセッションã®çŠ¶æ…‹ã§ã€çµ‚了ã™ã‚‹ã¨ä¸æ•´åˆçŠ¶æ…‹ã«ãªã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ãã‚Œã§ã‚‚デãƒãƒƒã‚°ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’終了ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+</context>
+<context>
+ <name>Debugger::Internal::EngineManager</name>
+ <message>
+ <source>Create Snapshot</source>
+ <translation>スナップショットを作æˆ</translation>
+ </message>
+</context>
+<context>
+ <name>Debuggger::Internal::ModulesHandler</name>
+ <message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation>ã¯ã„</translation>
+ </message>
+ <message>
+ <source>Plain</source>
+ <translation>プレーン</translation>
+ </message>
+ <message>
+ <source>Fast</source>
+ <translation>高速</translation>
+ </message>
+ <message>
+ <source>debuglnk</source>
+ <translation>debuglnk</translation>
+ </message>
+ <message>
+ <source>buildid</source>
+ <translation>buildid</translation>
+ </message>
+ <message>
+ <source>It is unknown whether this module contains debug information.
+Use &quot;Examine Symbols&quot; from the context menu to initiate a check.</source>
+ <translation>ã“ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã«ãƒ‡ãƒãƒƒã‚°æƒ…å ±ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã‹ã¯ä¸æ˜Žã§ã™ã€‚
+コンテキストメニューã‹ã‚‰ &quot;ã™ã¹ã¦ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’調査&quot; を実行ã—ã¦ç¢ºèªã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>This module neither contains nor references debug information.
+Stepping into the module or setting breakpoints by file and line will not work.</source>
+ <translation>ã“ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã«ã¯ãƒ‡ãƒãƒƒã‚°æƒ…å ±ãŒå«ã¾ã‚Œã¦ã„ã¾ã›ã‚“。
+ステップ実行やã€ãƒ•ã‚¡ã‚¤ãƒ«ã¨è¡Œç•ªå·ã«ã‚ˆã‚‹ãƒ–レークãƒã‚¤ãƒ³ãƒˆã®è¨­å®šã¯æ­£ã—ã動作ã—ãªã„ã§ã—ょã†ã€‚</translation>
+ </message>
+ <message>
+ <source>This module contains debug information.
+Stepping into the module or setting breakpoints by file and line is expected to work.</source>
+ <translation>ã“ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã«ã¯ãƒ‡ãƒãƒƒã‚°æƒ…å ±ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚
+ステップ実行やã€ãƒ•ã‚¡ã‚¤ãƒ«ã¨è¡Œç•ªå·ã«ã‚ˆã‚‹ãƒ–レークãƒã‚¤ãƒ³ãƒˆã®è¨­å®šã‚‚期待通りã«å‹•ä½œã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>This module does not contain debug information itself, but contains a reference to external debug information.</source>
+ <translation>ã“ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«è‡ªä½“ã«ã¯ãƒ‡ãƒãƒƒã‚°æƒ…å ±ãŒå«ã¾ã‚Œã¦ã„ã¾ã›ã‚“ãŒã€å¤–部ã®ãƒ‡ãƒãƒƒã‚°æƒ…å ±ã¸ã®å‚ç…§ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>&lt;unknown&gt;</source>
+ <comment>address</comment>
+ <extracomment>End address of loaded module</extracomment>
+ <translation>&lt;ä¸æ˜Ž&gt;</translation>
+ </message>
+ <message>
+ <source>Update Module List</source>
+ <translation>モジュールリストを更新</translation>
+ </message>
+ <message>
+ <source>Show Source Files for Module &quot;%1&quot;</source>
+ <translation>モジュール &quot;%1&quot; ã®ã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’表示</translation>
+ </message>
+ <message>
+ <source>Show Dependencies of &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ä¾å­˜é–¢ä¿‚を表示</translation>
+ </message>
+ <message>
+ <source>Show Dependencies</source>
+ <translation>ä¾å­˜é–¢ä¿‚を表示</translation>
+ </message>
+ <message>
+ <source>Load Symbols for All Modules</source>
+ <translation>ã™ã¹ã¦ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®ã‚·ãƒ³ãƒœãƒ«ã®èª­è¾¼</translation>
+ </message>
+ <message>
+ <source>Examine All Modules</source>
+ <translation>ã™ã¹ã¦ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’調査</translation>
+ </message>
+ <message>
+ <source>Load Symbols for Module &quot;%1&quot;</source>
+ <translation>モジュール &quot;%1&quot; ã®ã‚·ãƒ³ãƒœãƒ«ã®èª­è¾¼</translation>
+ </message>
+ <message>
+ <source>Load Symbols for Module</source>
+ <translation>モジュールã®ã‚·ãƒ³ãƒœãƒ«ã®èª­è¾¼</translation>
+ </message>
+ <message>
+ <source>Edit File &quot;%1&quot;</source>
+ <translation>ファイル &quot;%1&quot; を編集</translation>
+ </message>
+ <message>
+ <source>Edit File</source>
+ <translation>ファイルを編集</translation>
+ </message>
+ <message>
+ <source>Show Symbols in File &quot;%1&quot;</source>
+ <translation>ファイル &quot;%1&quot; ã®ã‚·ãƒ³ãƒœãƒ«ã‚’表示ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Show Symbols</source>
+ <translation>シンボルを表示</translation>
+ </message>
+ <message>
+ <source>Show Sections in File &quot;%1&quot;</source>
+ <translation>ファイル &quot;%1&quot; ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’表示ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Show Sections</source>
+ <translation>セクションを表示</translation>
+ </message>
+</context>
+<context>
+ <name>Debugger::Internal::PeripheralRegisterHandler</name>
+ <message>
+ <source>N/A</source>
+ <translation>N/A</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+ <message>
+ <source>Access</source>
+ <translation>アクセス</translation>
+ </message>
+ <message>
+ <source>Format</source>
+ <translation>フォーマット</translation>
+ </message>
+ <message>
+ <source>Hexadecimal</source>
+ <translation>16進数</translation>
+ </message>
+ <message>
+ <source>Decimal</source>
+ <translation>10進数</translation>
+ </message>
+ <message>
+ <source>Octal</source>
+ <translation>8進数</translation>
+ </message>
+ <message>
+ <source>Binary</source>
+ <translation>2進数</translation>
+ </message>
+</context>
+<context>
+ <name>Debugger::Internal::UvscClient</name>
+ <message>
+ <source>%1.%2</source>
+ <translation>%1.%2</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ã§ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Debugger::Internal::UvscEngine</name>
+ <message>
+ <source>Application started.</source>
+ <translation>アプリケーションãŒèµ·å‹•ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Setting breakpoints...</source>
+ <translation>ブレークãƒã‚¤ãƒ³ãƒˆã®è¨­å®š...</translation>
+ </message>
+ <message>
+ <source>Failed to Shut Down Application</source>
+ <translation>アプリケーションã®çµ‚了ã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Running requested...</source>
+ <translation>実行ã—よã†ã¨ã—ã¦ã„ã¾ã™...</translation>
+ </message>
+ <message>
+ <source>Execution Error</source>
+ <translation>実行エラー</translation>
+ </message>
+</context>
+<context>
+ <name>DiffEditor::Internal::DiffCurrentFileController</name>
+ <message>
+ <source>Modified</source>
+ <translation>変更</translation>
+ </message>
+</context>
+<context>
+ <name>DiffEditor::Internal::DiffOpenFilesController</name>
+ <message>
+ <source>Modified</source>
+ <translation>変更</translation>
+ </message>
+</context>
+<context>
+ <name>DiffEditor::Internal::DiffModifiedFilesController</name>
+ <message>
+ <source>Modified</source>
+ <translation>変更</translation>
+ </message>
+</context>
+<context>
+ <name>DiffEditor::Internal::DiffEditorWidgetController</name>
+ <message>
+ <source>Revert Chunk</source>
+ <translation>ãƒãƒ£ãƒ³ã‚¯ã‚’å…ƒã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Apply Chunk</source>
+ <translation>ãƒãƒ£ãƒ³ã‚¯ã®é©ç”¨</translation>
+ </message>
+ <message>
+ <source>Would you like to revert the chunk?</source>
+ <translation>ãƒãƒ£ãƒ³ã‚¯ã‚’å…ƒã«æˆ»ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Would you like to apply the chunk?</source>
+ <translation>ãƒãƒ£ãƒ³ã‚¯ã‚’é©ç”¨ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Send Chunk to CodePaster...</source>
+ <translation>CodePaster ã«ãƒãƒ£ãƒ³ã‚¯ã‚’é€ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Apply Chunk...</source>
+ <translation>ãƒãƒ£ãƒ³ã‚¯ã®é©ç”¨...</translation>
+ </message>
+ <message>
+ <source>Revert Chunk...</source>
+ <translation>ãƒãƒ£ãƒ³ã‚¯ã‚’å…ƒã«æˆ»ã™...</translation>
+ </message>
+ <message>
+ <source>Select Encoding</source>
+ <translation>文字コードã®é¸æŠž</translation>
+ </message>
+</context>
+<context>
+ <name>GenericProjectManager::Internal::GenericBuildConfiguration</name>
+ <message>
+ <source>Generic Manager</source>
+ <translation>一般マãƒãƒ¼ã‚¸ãƒ£</translation>
+ </message>
+</context>
+<context>
+ <name>Git::Internal::BranchView</name>
+ <message>
+ <source>Refresh</source>
+ <translation>æ›´æ–°</translation>
+ </message>
+ <message numerus="yes">
+ <source>Include branches and tags that have not been active for %n days.</source>
+ <translation>
+ <numerusform>ç›´è¿‘ã® %n æ—¥ã«ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã§ã¯ãªã„ブランãƒã‚„ã‚¿ã‚°ã‚’å«ã¿ã¾ã™ã€‚</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>&lt;No repository&gt;</source>
+ <translation>&lt;リãƒã‚¸ãƒˆãƒªãªã—&gt;</translation>
+ </message>
+ <message>
+ <source>&amp;Add...</source>
+ <translation>追加(&amp;A)...</translation>
+ </message>
+ <message>
+ <source>&amp;Checkout</source>
+ <translation>ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ(&amp;C)</translation>
+ </message>
+ <message>
+ <source>&amp;Diff</source>
+ <translation>差分表示(&amp;D)</translation>
+ </message>
+ <message>
+ <source>&amp;Log</source>
+ <translation>ログ表示(&amp;L)</translation>
+ </message>
+ <message>
+ <source>&amp;Hard</source>
+ <translation>ãƒãƒ¼ãƒ‰(&amp;H)</translation>
+ </message>
+ <message>
+ <source>&amp;Mixed</source>
+ <translation>混在(&amp;M)</translation>
+ </message>
+ <message>
+ <source>&amp;Soft</source>
+ <translation>ソフト(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Cherry &amp;Pick</source>
+ <translation>ãƒã‚§ãƒªãƒ¼ãƒ”ック(&amp;P)</translation>
+ </message>
+ <message>
+ <source>&amp;Track</source>
+ <translation>トラック(&amp;T)</translation>
+ </message>
+ <message>
+ <source>&amp;Push</source>
+ <translation>プッシュ(&amp;P)</translation>
+ </message>
+ <message>
+ <source>Would you like to delete the tag &quot;%1&quot;?</source>
+ <translation>ã‚¿ã‚° &quot;%1&quot; を削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Would you like to delete the branch &quot;%1&quot;?</source>
+ <translation>ブランム&quot;%1&quot; を削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Would you like to delete the &lt;b&gt;unmerged&lt;/b&gt; branch &quot;%1&quot;?</source>
+ <translation>&lt;b&gt;マージã•ã‚Œã¦ã„ãªã„&lt;/b&gt;ブランムâ€%1&quot; を削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Delete Tag</source>
+ <translation>タグを削除</translation>
+ </message>
+ <message>
+ <source>Delete Branch</source>
+ <translation>ブランãƒã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Git Reset</source>
+ <translation>Git リセット</translation>
+ </message>
+</context>
+<context>
+ <name>Git::Internal::BranchViewFactory</name>
+ <message>
+ <source>Filter</source>
+ <translation>フィルタ</translation>
+ </message>
+</context>
+<context>
+ <name>Git::Internal::GitBaseDiffEditorController</name>
+ <message>
+ <source>&lt;None&gt;</source>
+ <translation>&lt;ãªã—&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>Git::Internal::BaseGitLogArgumentsWidget</name>
+ <message>
+ <source>Show difference.</source>
+ <translation>差分を表示ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Filter</source>
+ <translation>フィルタ</translation>
+ </message>
+</context>
+<context>
+ <name>Git::Internal::GitLogFilterWidget</name>
+ <message>
+ <source>Filter:</source>
+ <translation>フィルタ:</translation>
+ </message>
+</context>
+<context>
+ <name>Git::Internal::GitPluginPrivate</name>
+ <message>
+ <source>&amp;Describe Change %1</source>
+ <translation>変更 %1 ã®èª¬æ˜Ž(&amp;D)</translation>
+ </message>
+ <message>
+ <source>Git Settings</source>
+ <translation>Git ã®è¨­å®š</translation>
+ </message>
+ <message>
+ <source>&amp;Git</source>
+ <translation>&amp;Git</translation>
+ </message>
+ <message>
+ <source>Current &amp;File</source>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«(&amp;F)</translation>
+ </message>
+ <message>
+ <source>Diff of &quot;%1&quot;</source>
+ <comment>Avoid translating &quot;Diff&quot;</comment>
+ <translation>&quot;%1&quot; ã®å·®åˆ†è¡¨ç¤º (Diff)</translation>
+ </message>
+ <message>
+ <source>Meta+G,Meta+D</source>
+ <translation>Meta+G,Meta+D</translation>
+ </message>
+ <message>
+ <source>Alt+G,Alt+D</source>
+ <translation>Alt+G,Alt+D</translation>
+ </message>
+ <message>
+ <source>Log of &quot;%1&quot;</source>
+ <comment>Avoid translating &quot;Log&quot;</comment>
+ <translation>&quot;%1&quot; ã®ãƒ­ã‚° (Log)</translation>
+ </message>
+ <message>
+ <source>Meta+G,Meta+L</source>
+ <translation>Meta+G,Meta+L</translation>
+ </message>
+ <message>
+ <source>Alt+G,Alt+L</source>
+ <translation>Alt+G,Alt+L</translation>
+ </message>
+ <message>
+ <source>Blame Current File</source>
+ <comment>Avoid translating &quot;Blame&quot;</comment>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®ç·¨é›†è€…を表示 (Blame)</translation>
+ </message>
+ <message>
+ <source>Blame for &quot;%1&quot;</source>
+ <comment>Avoid translating &quot;Blame&quot;</comment>
+ <translation>&quot;%1&quot; ã®ç·¨é›†è€…を表示 (Blame)</translation>
+ </message>
+ <message>
+ <source>Meta+G,Meta+B</source>
+ <translation>Meta+G,Meta+B</translation>
+ </message>
+ <message>
+ <source>Alt+G,Alt+B</source>
+ <translation>Alt+G,Alt+B</translation>
+ </message>
+ <message>
+ <source>Stage File for Commit</source>
+ <translation>ファイルをステージ(コミット予定)ã«è¿½åŠ  (Add)</translation>
+ </message>
+ <message>
+ <source>Stage &quot;%1&quot; for Commit</source>
+ <translation>&quot;%1&quot; をステージ(コミット予定)ã«è¿½åŠ  (Add)</translation>
+ </message>
+ <message>
+ <source>Meta+G,Meta+A</source>
+ <translation>Meta+G,Meta+A</translation>
+ </message>
+ <message>
+ <source>Alt+G,Alt+A</source>
+ <translation>Alt+G,Alt+A</translation>
+ </message>
+ <message>
+ <source>Unstage File from Commit</source>
+ <translation>ファイルをステージ(コミット予定)ã‹ã‚‰å‰Šé™¤ (Reset)</translation>
+ </message>
+ <message>
+ <source>Unstage &quot;%1&quot; from Commit</source>
+ <translation>&quot;%1&quot; をステージ(コミット予定)ã‹ã‚‰å‰Šé™¤ (Reset)</translation>
+ </message>
+ <message>
+ <source>Undo Unstaged Changes</source>
+ <translation>ステージã«ç„¡ã„変更を元ã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Undo Unstaged Changes for &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã«ç„¡ã„変更を元ã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Undo Uncommitted Changes</source>
+ <translation>コミットã•ã‚Œã¦ã„ãªã„変更を元ã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Undo Uncommitted Changes for &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ã‚³ãƒŸãƒƒãƒˆã•ã‚Œã¦ã„ãªã„変更を元ã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Meta+G,Meta+U</source>
+ <translation>Meta+G,Meta+U</translation>
+ </message>
+ <message>
+ <source>Alt+G,Alt+U</source>
+ <translation>Alt+G,Alt+U</translation>
+ </message>
+ <message>
+ <source>Current &amp;Project</source>
+ <translation>ç¾åœ¨ã®ãƒ—ロジェクト(&amp;P)</translation>
+ </message>
+ <message>
+ <source>Diff Current Project</source>
+ <comment>Avoid translating &quot;Diff&quot;</comment>
+ <translation>ç¾åœ¨ã®ãƒ—ロジェクトã®å·®åˆ†è¡¨ç¤º (Diff)</translation>
+ </message>
+ <message>
+ <source>Meta+G,Meta+Shift+D</source>
+ <translation>Meta+G,Meta+Shift+D</translation>
+ </message>
+ <message>
+ <source>Alt+G,Alt+Shift+D</source>
+ <translation>Alt+G,Alt+Shift+D</translation>
+ </message>
+ <message>
+ <source>Meta+G,Meta+K</source>
+ <translation>Meta+G,Meta+K</translation>
+ </message>
+ <message>
+ <source>Alt+G,Alt+K</source>
+ <translation>Alt+G,Alt+K</translation>
+ </message>
+ <message>
+ <source>Clean Project...</source>
+ <comment>Avoid translating &quot;Clean&quot;</comment>
+ <translation>プロジェクトをクリーン (Clean)...</translation>
+ </message>
+ <message>
+ <source>Clean Project &quot;%1&quot;...</source>
+ <comment>Avoid translating &quot;Clean&quot;</comment>
+ <translation>プロジェクト &quot;%1&quot; をクリーン (Clean)...</translation>
+ </message>
+ <message>
+ <source>&amp;Local Repository</source>
+ <translation>ローカルリãƒã‚¸ãƒˆãƒª(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Meta+G,Meta+C</source>
+ <translation>Meta+G,Meta+C</translation>
+ </message>
+ <message>
+ <source>Alt+G,Alt+C</source>
+ <translation>Alt+G,Alt+C</translation>
+ </message>
+ <message>
+ <source>Amend Last Commit...</source>
+ <comment>Avoid translating &quot;Commit&quot;</comment>
+ <translation>最終コミットログを修正...</translation>
+ </message>
+ <message>
+ <source>Fixup Previous Commit...</source>
+ <comment>Avoid translating &quot;Commit&quot;</comment>
+ <translation>ç›´å‰ã®ã‚³ãƒŸãƒƒãƒˆã‚’修正...</translation>
+ </message>
+ <message>
+ <source>Interactive Rebase...</source>
+ <comment>Avoid translating &quot;Rebase&quot;</comment>
+ <translation>対話的ãªãƒªãƒ™ãƒ¼ã‚¹ (Rebase)...</translation>
+ </message>
+ <message>
+ <source>Update Submodules</source>
+ <translation>サブモジュールを更新</translation>
+ </message>
+ <message>
+ <source>Abort Merge</source>
+ <comment>Avoid translating &quot;Merge&quot;</comment>
+ <translation>マージã®ä¸­æ­¢</translation>
+ </message>
+ <message>
+ <source>Abort Rebase</source>
+ <comment>Avoid translating &quot;Rebase&quot;</comment>
+ <translation>リベースã®ä¸­æ­¢</translation>
+ </message>
+ <message>
+ <source>Abort Cherry Pick</source>
+ <comment>Avoid translating &quot;Cherry Pick&quot;</comment>
+ <translation>ãƒã‚§ãƒªãƒ¼ãƒ”ックã®ä¸­æ­¢</translation>
+ </message>
+ <message>
+ <source>Abort Revert</source>
+ <comment>Avoid translating &quot;Revert&quot;</comment>
+ <translation>コミット打ã¡æ¶ˆã—ã®ä¸­æ­¢</translation>
+ </message>
+ <message>
+ <source>Continue Rebase</source>
+ <translation>リベースã®ç¶šè¡Œ</translation>
+ </message>
+ <message>
+ <source>Continue Cherry Pick</source>
+ <translation>ãƒã‚§ãƒªãƒ¼ãƒ”ックã®ç¶šè¡Œ</translation>
+ </message>
+ <message>
+ <source>Continue Revert</source>
+ <translation>コミットã®æ‰“ã¡æ¶ˆã—ã®ç¶šè¡Œ</translation>
+ </message>
+ <message>
+ <source>Branches...</source>
+ <translation>ブランム(Branch)...</translation>
+ </message>
+ <message>
+ <source>&amp;Patch</source>
+ <translation>パッãƒ(&amp;P)</translation>
+ </message>
+ <message>
+ <source>Apply from Editor</source>
+ <translation>エディタã‹ã‚‰é©ç”¨</translation>
+ </message>
+ <message>
+ <source>Apply &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®é©ç”¨</translation>
+ </message>
+ <message>
+ <source>Apply from File...</source>
+ <translation>ファイルã‹ã‚‰é©ç”¨...</translation>
+ </message>
+ <message>
+ <source>&amp;Stash</source>
+ <translation>スタッシュ (&amp;Stash)</translation>
+ </message>
+ <message>
+ <source>Saves the current state of your work and resets the repository.</source>
+ <translation>ç¾åœ¨ã®çŠ¶æ…‹ã‚’ä¿æŒã—ã€ãƒªãƒã‚¸ãƒˆãƒªã‚’å…ƒã®çŠ¶æ…‹ã«æˆ»ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Stash Unstaged Files</source>
+ <comment>Avoid translating &quot;Stash&quot;</comment>
+ <translation>ステージã«ãªã„ファイルをスタッシュ (Stash)</translation>
+ </message>
+ <message>
+ <source>Saves the current state of your unstaged files and resets the repository to its staged state.</source>
+ <translation>ステージã«ãªã„ファイルã®ç¾åœ¨ã®çŠ¶æ…‹ã‚’ä¿å­˜ã—ã¦ãƒªãƒã‚¸ãƒˆãƒªã‚’ステージ状態ã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Take Snapshot...</source>
+ <translation>スナップショットをå–ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Saves the current state of your work.</source>
+ <translation>ç¾åœ¨ã®ä½œæ¥­çŠ¶æ³ã‚’ä¿å­˜ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Stash Pop</source>
+ <comment>Avoid translating &quot;Stash&quot;</comment>
+ <translation>スタッシュã®ãƒãƒƒãƒ— (Stash Pop)</translation>
+ </message>
+ <message>
+ <source>Restores changes saved to the stash list using &quot;Stash&quot;.</source>
+ <translation>&quot;スタッシュ (Stash)&quot;ã§ä¿å­˜ã•ã›ãŸä½œæ¥­çŠ¶æ³ã‚’復元ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Remote Repository</source>
+ <translation>リモートリãƒã‚¸ãƒˆãƒª(&amp;R)</translation>
+ </message>
+ <message>
+ <source>&amp;Subversion</source>
+ <translation>&amp;Subversion</translation>
+ </message>
+ <message>
+ <source>Manage Remotes...</source>
+ <translation>リモートã®ç®¡ç†...</translation>
+ </message>
+ <message>
+ <source>Git &amp;Tools</source>
+ <translation>Git ツール(&amp;T)</translation>
+ </message>
+ <message>
+ <source>Gitk Current File</source>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ Gitk ã§è¡¨ç¤ºã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Gitk of &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã‚’ Gitk ã§è¡¨ç¤ºã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Gitk for folder of Current File</source>
+ <translation>ç¾åœ¨ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã‚’ Gitk ã§è¡¨ç¤ºã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Gitk for folder of &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã‚’ Gitk ã§è¡¨ç¤ºã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Git Gui</source>
+ <translation>Git GUI</translation>
+ </message>
+ <message>
+ <source>Repository Browser</source>
+ <translation>リãƒã‚¸ãƒˆãƒªãƒ–ラウザ</translation>
+ </message>
+ <message>
+ <source>Merge Tool</source>
+ <translation>マージツール</translation>
+ </message>
+ <message>
+ <source>Actions on Commits...</source>
+ <translation>コミット時ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³...</translation>
+ </message>
+ <message>
+ <source>Create Repository...</source>
+ <translation>リãƒã‚¸ãƒˆãƒªã®ä½œæˆ...</translation>
+ </message>
+ <message>
+ <source>Undo Changes to %1</source>
+ <translation>コミット %1 ã¾ã§å…ƒã«æˆ»ã™</translation>
+ </message>
+ <message>
+ <source>Interactive Rebase</source>
+ <translation>対話的ãªãƒªãƒ™ãƒ¼ã‚¹</translation>
+ </message>
+ <message>
+ <source>Another submit is currently being executed.</source>
+ <translation>別ã®ã‚µãƒ–ミットãŒå®Ÿè¡Œä¸­ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Unsupported version of Git found. Git %1 or later required.</source>
+ <translation>サãƒãƒ¼ãƒˆå¯¾è±¡å¤–ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Git ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸã€‚Git %1 以é™ãŒå¿…è¦ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Amend %1</source>
+ <translation>%1 ã®ãƒ­ã‚°ã‚’修正ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Git Fixup Commit</source>
+ <translation>Git コミット㮠Fixup</translation>
+ </message>
+ <message>
+ <source>Git Commit</source>
+ <translation>Git コミット</translation>
+ </message>
+ <message>
+ <source>Repository Clean</source>
+ <translation>リãƒã‚¸ãƒˆãƒªã‚’クリーン</translation>
+ </message>
+ <message>
+ <source>The repository is clean.</source>
+ <translation>リãƒã‚¸ãƒˆãƒªã¯å¤‰æ›´ã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Patches (*.patch *.diff)</source>
+ <translation>パッム(*.patch *.diff)</translation>
+ </message>
+ <message>
+ <source>Choose Patch</source>
+ <translation>パッãƒã®é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Patch %1 successfully applied to %2</source>
+ <translation>パッム%1 ã‚’ %2 ã«é©ç”¨ã—ã¾ã—ãŸ</translation>
+ </message>
+</context>
+<context>
+ <name>Help::DocSettingsPageWidget</name>
+ <message>
+ <source>%1 (auto-detected)</source>
+ <translation>%1 (自動検出)</translation>
+ </message>
+ <message>
+ <source>Add Documentation</source>
+ <translation>ドキュメントã®è¿½åŠ </translation>
+ </message>
+ <message>
+ <source>Qt Help Files (*.qch)</source>
+ <translation>Qt ヘルプファイル (*.qch)</translation>
+ </message>
+ <message>
+ <source>Invalid documentation file:</source>
+ <translation>無効ãªãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Namespace already registered:</source>
+ <translation>åå‰ç©ºé–“ã¯æ—¢ã«ç™»éŒ²æ¸ˆã¿:</translation>
+ </message>
+ <message>
+ <source>Unable to register documentation.</source>
+ <translation>ドキュメントã®ç™»éŒ²ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Documentation</source>
+ <translation>ドキュメント</translation>
+ </message>
+</context>
+<context>
+ <name>Help::HelpViewer</name>
+ <message>
+ <source>Zoom: %1%</source>
+ <translation>拡大率: %1%</translation>
+ </message>
+</context>
+<context>
+ <name>Imageviewer::Internal::ImageViewerPlugin</name>
+ <message>
+ <source>Fit to Screen</source>
+ <translation>ç”»é¢å†…ã«åŽã‚ã‚‹</translation>
+ </message>
+ <message>
+ <source>Ctrl+=</source>
+ <translation>Ctrl+=</translation>
+ </message>
+ <message>
+ <source>Switch Background</source>
+ <translation>ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰åˆ‡æ›¿</translation>
+ </message>
+ <message>
+ <source>Ctrl+[</source>
+ <translation>Ctrl+[</translation>
+ </message>
+ <message>
+ <source>Switch Outline</source>
+ <translation>外枠表示切替</translation>
+ </message>
+ <message>
+ <source>Ctrl+]</source>
+ <translation>Ctrl+]</translation>
+ </message>
+ <message>
+ <source>Toggle Animation</source>
+ <translation>アニメーションã®åˆ‡æ›¿</translation>
+ </message>
+ <message>
+ <source>Export Image</source>
+ <translation>ç”»åƒã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ</translation>
+ </message>
+</context>
+<context>
+ <name>ImageViewer::Internal::MultiExportDialog</name>
+ <message>
+ <source>File:</source>
+ <translation>ファイル:</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>クリア</translation>
+ </message>
+</context>
+<context>
+ <name>IncrediBuild::Internal::BuildConsoleBuildStep</name>
+ <message>
+ <source>Miscellaneous</source>
+ <translation>ãã®ä»–</translation>
+ </message>
+</context>
+<context>
+ <name>IncrediBuild::Internal::CMakeCommandBuilder</name>
+ <message>
+ <source>CMake</source>
+ <translation>CMake</translation>
+ </message>
+</context>
+<context>
+ <name>IncrediBuild::Internal::CommandBuilderAspect</name>
+ <message>
+ <source>Make arguments:</source>
+ <translation>Make ã®å¼•æ•°:</translation>
+ </message>
+</context>
+<context>
+ <name>IncrediBuild::Internal::MakeCommandBuilder</name>
+ <message>
+ <source>Make</source>
+ <translation>Make</translation>
+ </message>
+</context>
+<context>
+ <name>Ios::Internal::IosQmakeBuildConfiguration</name>
+ <message>
+ <source>iOS Settings</source>
+ <translation>iOS ã®è¨­å®š</translation>
+ </message>
+ <message>
+ <source>Reset</source>
+ <translation>リセット</translation>
+ </message>
+ <message>
+ <source>Automatically manage signing</source>
+ <translation>ç½²åを自動的ã«ç®¡ç†ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Development team:</source>
+ <translation>開発ãƒãƒ¼ãƒ :</translation>
+ </message>
+ <message>
+ <source>Provisioning profile:</source>
+ <translation>プロビジョニングプロファイル:</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>ãªã—</translation>
+ </message>
+ <message>
+ <source>Development team is not selected.</source>
+ <translation>開発ãƒãƒ¼ãƒ ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Provisioning profile is not selected.</source>
+ <translation>プロビジョニングプロファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Using default development team and provisioning profile.</source>
+ <translation>デフォルトã®é–‹ç™ºãƒãƒ¼ãƒ ã¨ãƒ—ロビジョニングプロファイルを使用。</translation>
+ </message>
+ <message>
+ <source>Development team: %1 (%2)</source>
+ <translation>開発ãƒãƒ¼ãƒ : %1 (%2)</translation>
+ </message>
+ <message>
+ <source>Settings defined here override the QMake environment.</source>
+ <translation>ã“ã“ã§å®šç¾©ã•ã‚ŒãŸè¨­å®šã¯ã€QMake ã®ç’°å¢ƒã‚’上書ãã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>%1 not configured. Use Xcode and Apple developer account to configure the provisioning profiles and teams.</source>
+ <translation>%1 ãŒæ§‹æˆã•ã‚Œã¦ã„ã¾ã›ã‚“。Xcode 㨠Apple 開発者アカウントを使用ã—ã¦ã€ãƒ—ロビジョニングプロファイルã¨ãƒãƒ¼ãƒ ã‚’構æˆã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Development teams</source>
+ <translation>開発ãƒãƒ¼ãƒ </translation>
+ </message>
+ <message>
+ <source>Provisioning profiles</source>
+ <translation>プロビジョニングプロファイル</translation>
+ </message>
+ <message>
+ <source>No provisioning profile found for the selected team.</source>
+ <translation>é¸æŠžã—ãŸãƒãƒ¼ãƒ ã®ãƒ—ロビジョニングプロファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Provisioning profile expired. Expiration date: %1</source>
+ <translation>プロビジョニング・プロファイルã®æœ‰åŠ¹æœŸé™ãŒåˆ‡ã‚Œã¦ã„ã¾ã™ã€‚有効期é™: %1</translation>
+ </message>
+</context>
+<context>
+ <name>DevelopmentTeam</name>
+ <message>
+ <source>Yes</source>
+ <translation>ã¯ã„</translation>
+ </message>
+</context>
+<context>
+ <name>Ios::Internal::IosDsymBuildStep</name>
+ <message>
+ <source>Command:</source>
+ <translation>コマンド:</translation>
+ </message>
+ <message>
+ <source>Arguments:</source>
+ <translation>引数:</translation>
+ </message>
+ <message>
+ <source>Reset to Default</source>
+ <translation>既定ã«æˆ»ã™</translation>
+ </message>
+</context>
+<context>
+ <name>Ios::Internal</name>
+ <message>
+ <source>Deploy on iOS</source>
+ <translation>iOS ã«ãƒ‡ãƒ—ロイ</translation>
+ </message>
+</context>
+<context>
+ <name>Ios::Internal::IosRunSupport</name>
+ <message>
+ <source>Starting remote process.</source>
+ <translation>リモートプロセスを起動ã—ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageClient::DiagnosticManager</name>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation type="unfinished">クリップボードã«ã‚³ãƒ”ーã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageClient::LanguageClientPlugin</name>
+ <message>
+ <source>Generic StdIO Language Server</source>
+ <translation>汎用 StdIO 言語サーãƒãƒ¼</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageClientSettingsPage</name>
+ <message>
+ <source>&amp;Add</source>
+ <translation>追加(&amp;A)</translation>
+ </message>
+ <message>
+ <source>New %1</source>
+ <translation type="unfinished">æ–°ã—ã„ %1</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageClient::BaseSettingsWidget</name>
+ <message>
+ <source>Name</source>
+ <translation type="vanished">åå‰</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation type="vanished">値</translation>
+ </message>
+ <message>
+ <source>Name:</source>
+ <translation>åå‰:</translation>
+ </message>
+ <message>
+ <source>Language:</source>
+ <translation>言語:</translation>
+ </message>
+</context>
+<context>
+ <name>MimeTypeDialog</name>
+ <message>
+ <source>Filter</source>
+ <translation>フィルタ</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageClient::StdIOSettingsWidget</name>
+ <message>
+ <source>Executable:</source>
+ <translation>実行ファイル:</translation>
+ </message>
+ <message>
+ <source>Arguments:</source>
+ <translation>引数:</translation>
+ </message>
+</context>
+<context>
+ <name>LanguageClient::LspInspector</name>
+ <message>
+ <source>Expand All</source>
+ <translation>ã™ã¹ã¦å±•é–‹</translation>
+ </message>
+ <message>
+ <source>Client Message</source>
+ <translation type="unfinished">クライアントメッセージ</translation>
+ </message>
+ <message>
+ <source>Messages</source>
+ <translation type="unfinished">メッセージ</translation>
+ </message>
+ <message>
+ <source>Server Message</source>
+ <translation type="unfinished">サーãƒãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸</translation>
+ </message>
+ <message>
+ <source>Log File</source>
+ <translation type="unfinished">ログファイル</translation>
+ </message>
+</context>
+<context>
+ <name>LspCapabilitiesWidget</name>
+ <message>
+ <source>Capabilities:</source>
+ <translation>ケイパビリティ:</translation>
+ </message>
+ <message>
+ <source>Dynamic Capabilities:</source>
+ <translation>ダイナミック ケイパビリティ:</translation>
+ </message>
+ <message>
+ <source>Method:</source>
+ <translation>メソッド:</translation>
+ </message>
+ <message>
+ <source>Options:</source>
+ <translation>オプション:</translation>
+ </message>
+ <message>
+ <source>Server Capabilities</source>
+ <translation>サーãƒãƒ¼ ケイパビリティ</translation>
+ </message>
+</context>
+<context>
+ <name>LspInspectorWidget</name>
+ <message>
+ <source>Language Client Inspector</source>
+ <translation>言語クライアントインスペクター</translation>
+ </message>
+ <message>
+ <source>Log</source>
+ <translation>ログ</translation>
+ </message>
+ <message>
+ <source>Capabilities</source>
+ <translation>ケイパビリティ</translation>
+ </message>
+</context>
+<context>
+ <name>McuSupport::Internal::McuPackage</name>
+ <message>
+ <source>Path %1 exists, but does not contain %2.</source>
+ <translation type="unfinished">パス %1 ã¯å­˜åœ¨ã—ã¾ã™ãŒã€%2 ã‚’å«ã‚“ã§ã„ã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>McuSupport::Internal::McuSupportOptions</name>
+ <message>
+ <source>Qt for MCUs Demos</source>
+ <translation>Qt for MCUs ã®ãƒ‡ãƒ¢</translation>
+ </message>
+ <message>
+ <source>Qt for MCUs Examples</source>
+ <translation>Qt for MCUs ã®ã‚µãƒ³ãƒ—ル</translation>
+ </message>
+ <message>
+ <source>Path %1 exists, but does not contain %2.</source>
+ <translation>パス %1 ã¯å­˜åœ¨ã—ã¾ã™ãŒã€%2 ã‚’å«ã‚“ã§ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Path %1 does not exist. Add the path in Tools &gt; Options &gt; Devices &gt; MCU.</source>
+ <translation>パス %1 ãŒå­˜åœ¨ã—ã¾ã›ã‚“。「ツールã€â†’「オプションã€â†’「デãƒã‚¤ã‚¹ã€â†’「MCUã€ã§ãƒ‘スを追加ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Missing %1. Add the path in Tools &gt; Options &gt; Devices &gt; MCU.</source>
+ <translation>%1ãŒè¦‹å½“ãŸã‚Šã¾ã›ã‚“。「ツールã€â†’「オプションã€â†’「デãƒã‚¤ã‚¹ã€â†’「MCUã€ã§ãƒ‘スを追加ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>No CMake tool was detected. Add a CMake tool in Tools &gt; Options &gt; Kits &gt; CMake.</source>
+ <translation>CMake ツールãŒæ¤œå‡ºã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚「ツールã€â†’「オプションã€â†’「キットã€â†’「 CMake ã€ã§ CMake ツールを追加ã—ã¦ãã ã•ã„。</translation>
+ </message>
+</context>
+<context>
+ <name>McuSupport::Internal::McuTarget</name>
+ <message>
+ <source>Warning for target %1: missing CMake Toolchain File expected at %2.</source>
+ <translation>ターゲット %1 ã«å¯¾ã™ã‚‹è­¦å‘Š: CMake Toolchain ファイル㌠%2 ã§è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Warning for target %1: missing QulGenerators expected at %2.</source>
+ <translation>ターゲット %1 ã«å¯¾ã™ã‚‹è­¦å‘Š: QulGenerators㌠%2 ã§è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Skipped %1 - Unsupported version &quot;%2&quot; (should be &gt;= %3)</source>
+ <translation>%1をスキップã—ã¾ã—㟠- サãƒãƒ¼ãƒˆå¯¾è±¡å¤–ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ &quot;%2&quot; (%3 以上ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™)</translation>
+ </message>
+ <message>
+ <source>No valid kit descriptions found at %1.</source>
+ <translation>%1ã§æœ‰åŠ¹ãªã‚­ãƒƒãƒˆã®èª¬æ˜ŽãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Skipped creating fallback desktop kit: Could not find any of %1.</source>
+ <translation>予備ã®ãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—・キットã®ä½œæˆã‚’スキップã—ã¾ã—ãŸã€‚%1 ã®ã„ãšã‚Œã‚‚見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QtForMCUs</name>
+ <message>
+ <source>Qt for MCUs: %1</source>
+ <translation>Qt for MCUs: %1</translation>
+ </message>
+</context>
+<context>
+ <name>McuSupport::Internal::McuSupportOptionsWidget</name>
+ <message>
+ <source>Remove Kit</source>
+ <translation>キットを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>No valid kit descriptions found at %1.</source>
+ <translation>%1 ã§æœ‰åŠ¹ãªã‚­ãƒƒãƒˆã®èª¬æ˜ŽãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::MesonActionsManager</name>
+ <message>
+ <source>Configure</source>
+ <translation>設定ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Build</source>
+ <translation>ビルド</translation>
+ </message>
+ <message>
+ <source>Build &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; ã®ãƒ“ルド</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::BuidOptionsModel</name>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::MesonProcess</name>
+ <message>
+ <source>Process timed out.</source>
+ <translation>プロセスãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Executable does not exist: %1</source>
+ <translation>実行ファイル ãŒå­˜åœ¨ã—ã¾ã›ã‚“: %1</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::NinjaBuildStep</name>
+ <message>
+ <source>Build</source>
+ <comment>MesonProjectManager::MesonBuildStepConfigWidget display name.</comment>
+ <translation>ビルド</translation>
+ </message>
+ <message>
+ <source>Tool arguments:</source>
+ <translation>ツールã®å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>Targets:</source>
+ <translation>ターゲット:</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::GeneralSettingsPage</name>
+ <message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::MesonToolKitAspect</name>
+ <message>
+ <source>Unconfigured</source>
+ <translation>未設定</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::NinjaToolKitAspect</name>
+ <message>
+ <source>Unconfigured</source>
+ <translation>未設定</translation>
+ </message>
+</context>
+<context>
+ <name>MesonProjectManager::Internal::ToolsSettingsPage</name>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Location</source>
+ <translation>パス</translation>
+ </message>
+ <message>
+ <source>Auto-detected</source>
+ <translation type="vanished">自動検出</translation>
+ </message>
+ <message>
+ <source>Manual</source>
+ <translation type="vanished">手動</translation>
+ </message>
+ <message>
+ <source>Clone of %1</source>
+ <translation>%1 を複製</translation>
+ </message>
+</context>
+<context>
+ <name>NimToolsSettingsPage</name>
+ <message>
+ <source>Nim</source>
+ <translation>Nim</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::NimPlugin</name>
+ <message>
+ <source>Nim</source>
+ <comment>SnippetProvider</comment>
+ <translation>Nim</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::NimbleBuildConfiguration</name>
+ <message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::NimBuildConfiguration</name>
+ <message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::NimCompilerBuildStep</name>
+ <message>
+ <source>Nim build step</source>
+ <translation>Nim ビルドステップ</translation>
+ </message>
+ <message>
+ <source>Target:</source>
+ <translation>ターゲット:</translation>
+ </message>
+ <message>
+ <source>Default arguments:</source>
+ <translation>デフォルト引数:</translation>
+ </message>
+ <message>
+ <source>Extra arguments:</source>
+ <translation>追加引数:</translation>
+ </message>
+ <message>
+ <source>Command:</source>
+ <translation>コマンド:</translation>
+ </message>
+ <message>
+ <source>Nim Compiler Build Step</source>
+ <translation>Nim コンパイラビルドステップ</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::NimRunConfiguration</name>
+ <message>
+ <source>Current Build Target</source>
+ <translation>ç¾åœ¨ã®ãƒ“ルドターゲット</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::NimToolChain</name>
+ <message>
+ <source>Nim</source>
+ <translation>Nim</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::NimToolChainConfigWidget</name>
+ <message>
+ <source>&amp;Compiler path:</source>
+ <translation>コンパイラã®ãƒ‘ス(&amp;C):</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::CodeStyleSettings</name>
+ <message>
+ <source>Nim</source>
+ <translation>Nim</translation>
+ </message>
+</context>
+<context>
+ <name>Nim::ToolSettingsPage</name>
+ <message>
+ <source>Nim</source>
+ <translation>Nim</translation>
+ </message>
+</context>
+<context>
+ <name>Perforce::Internal::PerforceDiffConfig</name>
+ <message>
+ <source>Ignore Whitespace</source>
+ <translation>空白を無視</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfiler::Internal::PerfConfigEventsModel</name>
+ <message>
+ <source>Result</source>
+ <translation>çµæžœ</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfiler::Internal::PerfProfilerFlameGraphModel</name>
+ <message>
+ <source>[unknown]</source>
+ <translation>[ä¸æ˜Ž]</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfilerStatisticsView</name>
+ <message>
+ <source>Address</source>
+ <translation>アドレス</translation>
+ </message>
+ <message>
+ <source>Function</source>
+ <translation>関数</translation>
+ </message>
+ <message>
+ <source>Caller</source>
+ <translation>呼ã³å‡ºã—å…ƒ</translation>
+ </message>
+ <message>
+ <source>Callee</source>
+ <translation>呼ã³å‡ºã—å…ˆ</translation>
+ </message>
+ <message>
+ <source>Occurrences</source>
+ <translation>出ç¾ç®‡æ‰€</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfiler::Internal::PerfProfilerTool</name>
+ <message>
+ <source>Show Full Range</source>
+ <translation>全体を表示</translation>
+ </message>
+ <message>
+ <source>Timeline</source>
+ <translation>タイムライン</translation>
+ </message>
+ <message>
+ <source>Statistics</source>
+ <translation>統計</translation>
+ </message>
+ <message>
+ <source>Flame Graph</source>
+ <translation type="unfinished">フレームグラフ</translation>
+ </message>
+ <message>
+ <source>Reset Zoom</source>
+ <translation>縮尺を戻ã™</translation>
+ </message>
+ <message>
+ <source>Copy Table</source>
+ <translation>表をコピー</translation>
+ </message>
+ <message>
+ <source>Copy Row</source>
+ <translation>行をコピー</translation>
+ </message>
+ <message>
+ <source>Reset Flame Graph</source>
+ <translation type="unfinished">フレームグラフをリセットã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfiler::Internal::PerfProfilerTraceManager</name>
+ <message>
+ <source>Invalid</source>
+ <translation>無効</translation>
+ </message>
+ <message>
+ <source>Loading Trace Data</source>
+ <translation>トレースデータã®èª­è¾¼ä¸­</translation>
+ </message>
+ <message>
+ <source>Saving Trace Data</source>
+ <translation>トレースデータã®ä¿å­˜ä¸­</translation>
+ </message>
+</context>
+<context>
+ <name>PerfProfiler::Internal::PerfTimelineModel</name>
+ <message>
+ <source>[unknown]</source>
+ <translation>[ä¸æ˜Ž]</translation>
+ </message>
+ <message>
+ <source>Details</source>
+ <translation>詳細</translation>
+ </message>
+ <message>
+ <source>Timestamp</source>
+ <translation>タイムスタンプ</translation>
+ </message>
+ <message>
+ <source>System</source>
+ <translation>システム</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Duration</source>
+ <translation>æŒç¶šæ™‚é–“</translation>
+ </message>
+ <message>
+ <source>Binary</source>
+ <translation>2進数</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>アドレス</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>ソース</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::AddRunConfigDialog</name>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>ソース</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>生æˆ</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::AppOutputSettingsPage</name>
+ <message>
+ <source>Merge stderr and stdout</source>
+ <translation>標準エラー出力ã¨æ¨™æº–出力をマージã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Never</source>
+ <translation>実行ã—ãªã„</translation>
+ </message>
+ <message>
+ <source>Application Output</source>
+ <translation>アプリケーション出力</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::BuildDirectoryAspect</name>
+ <message>
+ <source>Build directory:</source>
+ <translation>ビルドディレクトリ:</translation>
+ </message>
+ <message>
+ <source>Shadow build:</source>
+ <translation>シャドウビルド:</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::BuildEnvironmentWidget</name>
+ <message>
+ <source>Build Environment</source>
+ <translation>ビルド時ã®ç’°å¢ƒå¤‰æ•°</translation>
+ </message>
+ <message>
+ <source>Clear system environment</source>
+ <translation>システム環境変数をéžè¡¨ç¤ºã«ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::BuildPropertiesSettingsPage</name>
+ <message>
+ <source>Enable</source>
+ <translation>有効化</translation>
+ </message>
+ <message>
+ <source>Disable</source>
+ <translation>無効化</translation>
+ </message>
+ <message>
+ <source>Reset</source>
+ <translation>リセット</translation>
+ </message>
+ <message>
+ <source>Default build directory:</source>
+ <translation>既定ã®ãƒ“ルドディレクトリ:</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::BuildStepList</name>
+ <message>
+ <source>Build</source>
+ <extracomment>Display name of the build build step list. Used as part of the labels in the project window.</extracomment>
+ <translation>ビルド</translation>
+ </message>
+ <message>
+ <source>Clean</source>
+ <extracomment>Display name of the clean build step list. Used as part of the labels in the project window.</extracomment>
+ <translation>クリーン</translation>
+ </message>
+ <message>
+ <source>Deploy</source>
+ <extracomment>Display name of the deploy build step list. Used as part of the labels in the project window.</extracomment>
+ <translation>デプロイ</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::CompileOutputSettingsPage</name>
+ <message>
+ <source>Compile Output</source>
+ <translation>コンパイル出力</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::CustomParsersSettingsPage</name>
+ <message>
+ <source>Add...</source>
+ <translation>追加...</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::DeploymentDataView</name>
+ <message>
+ <source>Local File Path</source>
+ <translation>ローカルファイルã®ãƒ‘ス</translation>
+ </message>
+ <message>
+ <source>Remote Directory</source>
+ <translation>リモートディレクトリ</translation>
+ </message>
+ <message>
+ <source>Files to deploy:</source>
+ <translation>デプロイã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::DesktopRunConfiguration</name>
+ <message>
+ <source>Qt Run Configuration</source>
+ <translation>Qt 実行構æˆ</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::PortsGatherer</name>
+ <message>
+ <source>Checking available ports...</source>
+ <translation>使用å¯èƒ½ãªãƒãƒ¼ãƒˆã‚’確èªä¸­...</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::SshSettingsWidget</name>
+ <message>
+ <source>SSH</source>
+ <translation type="unfinished">SSH</translation>
+ </message>
+</context>
+<context>
+ <name>EnvironmentWidget</name>
+ <message>
+ <source>Add...</source>
+ <translation>追加...</translation>
+ </message>
+ <message>
+ <source>Edit...</source>
+ <translation>編集...</translation>
+ </message>
+ <message>
+ <source>Choose Directory</source>
+ <translation>ディレクトリをé¸æŠžã—ã¦ãã ã•ã„</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::FilterKitAspectsDialog</name>
+ <message>
+ <source>Setting</source>
+ <translation>設定</translation>
+ </message>
+ <message>
+ <source>Visible</source>
+ <translation>å¯è¦–性</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::ClangToolChain</name>
+ <message>
+ <source>Clang</source>
+ <translation>Clang</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::MingwToolChain</name>
+ <message>
+ <source>MinGW</source>
+ <translation>MinGW</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::LinuxIccToolChain</name>
+ <message>
+ <source>ICC</source>
+ <translation>ICC</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::SysRootKitAspect</name>
+ <message>
+ <source>The root directory of the system image to use.&lt;br&gt;Leave empty when building for the desktop.</source>
+ <translation>システムイメージãŒä½¿ç”¨ã™ã‚‹ãƒ«ãƒ¼ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã€‚&lt;br&gt;デスクトップ用ビルドã®å ´åˆã¯ç©ºã®ã¾ã¾ã«ã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Sys Root &quot;%1&quot; does not exist in the file system.</source>
+ <translation>ファイルシステム上㫠Sys Root &quot;%1&quot; ãŒå­˜åœ¨ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Sys Root &quot;%1&quot; is not a directory.</source>
+ <translation>Sys Root &quot;%1&quot; ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Sys Root &quot;%1&quot; is empty.</source>
+ <translation>Sys Root &quot;%1&quot; ãŒç©ºã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Sys Root</source>
+ <translation>Sys Root</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::ToolChainKitAspect</name>
+ <message>
+ <source>&lt;No compiler&gt;</source>
+ <translation>&lt;コンパイラãªã—&gt;</translation>
+ </message>
+ <message>
+ <source>Compiler</source>
+ <translation>コンパイラ</translation>
+ </message>
+ <message>
+ <source>The compiler to use for building.&lt;br&gt;Make sure the compiler will produce binaries compatible with the target device, Qt version and other libraries used.</source>
+ <translation>é¸æŠžã—ãŸã‚³ãƒ³ãƒ‘イラãŒãƒ“ルド時ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚&lt;br&gt;コンパイラãŒå¯¾è±¡ã¨ãªã‚‹ãƒ‡ãƒã‚¤ã‚¹ã‚„é¸æŠžã—ãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Qtã€ãã®ä»–ã®ä½¿ç”¨ã—ã¦ã„るライブラリã¨ãƒã‚¤ãƒŠãƒªäº’æ›ãŒã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。</translation>
+ </message>
+ <message>
+ <source>Path to the compiler executable</source>
+ <translation>コンパイラã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã®ãƒ‘ス</translation>
+ </message>
+ <message>
+ <source>No compiler set in kit.</source>
+ <translation>キットã«ã‚³ãƒ³ãƒ‘イラãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::DeviceTypeKitAspect</name>
+ <message>
+ <source>Device type</source>
+ <translation>デãƒã‚¤ã‚¹ç¨®é¡ž</translation>
+ </message>
+ <message>
+ <source>The type of device to run applications on.</source>
+ <translation>アプリケーションを実行ã™ã‚‹ãƒ‡ãƒã‚¤ã‚¹ã®ç¨®é¡žã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Unknown device type</source>
+ <translation>ä¸æ˜Žãªãƒ‡ãƒã‚¤ã‚¹ç¨®é¡ž</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::DeviceKitAspect</name>
+ <message>
+ <source>Device</source>
+ <translation>デãƒã‚¤ã‚¹</translation>
+ </message>
+ <message>
+ <source>The device to run the applications on.</source>
+ <translation>アプリケーションを実行ã™ã‚‹ãƒ‡ãƒã‚¤ã‚¹ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>No device set.</source>
+ <translation>デãƒã‚¤ã‚¹ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Device is incompatible with this kit.</source>
+ <translation>デãƒã‚¤ã‚¹ã¨ã“ã®ã‚­ãƒƒãƒˆã«äº’æ›æ€§ãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Unconfigured</source>
+ <translation>未設定</translation>
+ </message>
+ <message>
+ <source>Host address</source>
+ <translation>ホストアドレス</translation>
+ </message>
+ <message>
+ <source>SSH port</source>
+ <translation>SSH ãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>User name</source>
+ <translation>ユーザーå</translation>
+ </message>
+ <message>
+ <source>Private key file</source>
+ <translation>秘密éµãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message>
+ <source>Device name</source>
+ <translation>デãƒã‚¤ã‚¹å</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::EnvironmentKitAspect</name>
+ <message>
+ <source>Change...</source>
+ <translation>変更...</translation>
+ </message>
+ <message>
+ <source>No changes to apply.</source>
+ <translation>変更ã—ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Environment</source>
+ <translation>環境</translation>
+ </message>
+ <message>
+ <source>Additional build environment settings when using this kit.</source>
+ <translation>ã“ã®ã‚­ãƒƒãƒˆä½¿ç”¨æ™‚ã«è¿½åŠ ã™ã‚‹ãƒ“ルド用環境変数ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The environment setting value is invalid.</source>
+ <translation>環境変数ã®è¨­å®šã«ç„¡åŠ¹ãªå€¤ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::KitAspectWidget</name>
+ <message>
+ <source>Manage...</source>
+ <translation>管ç†...</translation>
+ </message>
+</context>
+<context>
+ <name>ProjextExplorer::Internal::KitOptionsPageWidget</name>
+ <message>
+ <source>Clone</source>
+ <translation>複製</translation>
+ </message>
+ <message>
+ <source>Make Default</source>
+ <translation>既定ã«ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Kits</source>
+ <translation>キット</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::MakeStep</name>
+ <message>
+ <source>Make arguments:</source>
+ <translation>Make ã®å¼•æ•°:</translation>
+ </message>
+ <message>
+ <source>Parallel jobs:</source>
+ <translation>並列ジョブ数:</translation>
+ </message>
+ <message>
+ <source>Targets:</source>
+ <translation>ターゲット:</translation>
+ </message>
+ <message>
+ <source>Make:</source>
+ <translation>Make:</translation>
+ </message>
+ <message>
+ <source>Override %1:</source>
+ <translation>%1 ã®ä»£ã‚ã‚Šã«ä½¿ç”¨ã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰:</translation>
+ </message>
+ <message>
+ <source>Make</source>
+ <translation>Make</translation>
+ </message>
+ <message>
+ <source>&lt;b&gt;Make:&lt;/b&gt; %1</source>
+ <translation>&lt;b&gt;Make:&lt;/b&gt; %1</translation>
+ </message>
+ <message>
+ <source>&lt;b&gt;Make:&lt;/b&gt; %1 not found in the environment.</source>
+ <translation>&lt;b&gt;Make:&lt;/b&gt; 環境㫠%1 ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>RunConfigSelector</name>
+ <message>
+ <source>Run Without Deployment</source>
+ <translation>デプロイã›ãšã«å®Ÿè¡Œ</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::MsvcToolChain</name>
+ <message>
+ <source>MSVC</source>
+ <translation>MSVC</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::MsvcToolChainConfigWidget</name>
+ <message>
+ <source>&lt;empty&gt;</source>
+ <translation>&lt;空&gt;</translation>
+ </message>
+ <message>
+ <source>Initialization:</source>
+ <translation>åˆæœŸåŒ–:</translation>
+ </message>
+ <message>
+ <source>&amp;ABI:</source>
+ <translation>&amp;ABI:</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::ParseIssuesDialog</name>
+ <message>
+ <source>Choose File</source>
+ <translation>ファイルをé¸æŠžã—ã¦ãã ã•ã„</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::ProcessStep</name>
+ <message>
+ <source>Command:</source>
+ <translation>コマンド:</translation>
+ </message>
+ <message>
+ <source>Arguments:</source>
+ <translation>引数:</translation>
+ </message>
+ <message>
+ <source>Working directory:</source>
+ <translation>作業ディレクトリ:</translation>
+ </message>
+ <message>
+ <source>Custom Process Step</source>
+ <extracomment>Default ProcessStep display name</extracomment>
+ <translation>独自プロセスステップ</translation>
+ </message>
+</context>
+<context>
+ <name>EnvironmentPanelFactory</name>
+ <message>
+ <source>Environment</source>
+ <translation>環境</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorerPluginPrivate</name>
+ <message>
+ <source>Building &quot;%1&quot; is disabled: %2&lt;br&gt;</source>
+ <translation>&quot;%1&quot; ã®ãƒ“ルドã¯ç„¡åŠ¹åŒ–ã•ã‚Œã¦ã„ã¾ã™: %2&lt;br&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>ProjextExplorer::Internal::ProjectExplorerSettings</name>
+ <message>
+ <source>All</source>
+ <translation>ã™ã¹ã¦</translation>
+ </message>
+ <message>
+ <source>Same Project</source>
+ <translation>åŒä¸€ãƒ—ロジェクト</translation>
+ </message>
+ <message>
+ <source>Same Build Directory</source>
+ <translation>åŒä¸€ãƒ“ルドディレクトリ</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::ProjectWindow</name>
+ <message>
+ <source>Build &amp; Run</source>
+ <translation>ビルドã¨å®Ÿè¡Œ</translation>
+ </message>
+ <message>
+ <source>Projects</source>
+ <translation>プロジェクト</translation>
+ </message>
+ <message>
+ <source>Manage Kits...</source>
+ <translation>キットã®ç®¡ç†...</translation>
+ </message>
+ <message>
+ <source>Active Project</source>
+ <translation>アクティブプロジェクト</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::ExecutableAspect</name>
+ <message>
+ <source>&lt;unknown&gt;</source>
+ <translation>&lt;ä¸æ˜Ž&gt;</translation>
+ </message>
+ <message>
+ <source>Executable:</source>
+ <translation>実行ファイル:</translation>
+ </message>
+ <message>
+ <source>Alternate executable on device:</source>
+ <translation>デãƒã‚¤ã‚¹ä¸Šã®ä»£æ›¿å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Use this command instead</source>
+ <translation>代ã‚ã‚Šã«ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使ã†</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::UseLibraryPathsAspect</name>
+ <message>
+ <source>Add build library search path to DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH</source>
+ <translation>DYLD_LIBRARY_PATH 㨠DYLD_FRAMEWORK_PATH ã«ãƒ“ルドライブラリ検索パスを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add build library search path to PATH</source>
+ <translation>PATH ã«ãƒ“ルドライブラリ検索パスを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add build library search path to LD_LIBRARY_PATH</source>
+ <translation>LD_LIBRARY_PATH ã«ãƒ“ルドライブラリ検索パスを追加ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::UseDyldSuffixAspect</name>
+ <message>
+ <source>Use debug version of frameworks (DYLD_IMAGE_SUFFIX=_debug)</source>
+ <translation>デãƒãƒƒã‚°ç‰ˆã®ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¯ãƒ¼ã‚¯ã‚’使用ã™ã‚‹ (DYLD_IMAGE_SUFFIX=_debug)</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::RunAsRootAspect</name>
+ <message>
+ <source>Run as root user</source>
+ <translation>管ç†è€…ã¨ã—ã¦å®Ÿè¡Œã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>TaskHub</name>
+ <message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>警告</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::SimpleTargetRunner</name>
+ <message>
+ <source>%1 crashed.</source>
+ <translation>%1 ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>%2 exited with code %1</source>
+ <translation>%2 ã¯ã‚³ãƒ¼ãƒ‰ %1 ã§çµ‚了ã—ã¾ã—ãŸ</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::FilesSelectionWizardPage</name>
+ <message>
+ <source>Files</source>
+ <translation>ファイル</translation>
+ </message>
+</context>
+<context>
+ <name>ProjectExplorer::Internal::SimpleProjectWizardDialog</name>
+ <message>
+ <source>Import Existing Project</source>
+ <translation>既存プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Project Name and Location</source>
+ <translation>プロジェクトåã¨ãƒ‘ス</translation>
+ </message>
+ <message>
+ <source>Project name:</source>
+ <translation>プロジェクトå:</translation>
+ </message>
+ <message>
+ <source>Location:</source>
+ <translation>パス:</translation>
+ </message>
+ <message>
+ <source>File Selection</source>
+ <translation>ファイルé¸æŠž</translation>
+ </message>
+</context>
+<context>
+ <name>TargetSettingsPanelWidget</name>
+ <message>
+ <source>Do Not Remove</source>
+ <translation>削除ã—ãªã„</translation>
+ </message>
+ <message>
+ <source>The kit &lt;b&gt;%1&lt;/b&gt; is currently being built.</source>
+ <translation>キット &lt;b&gt;%1&lt;/b&gt; をビルドã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Do you want to cancel the build process and remove the kit anyway?</source>
+ <translation>強制的ã«ãƒ“ルドプロセスを中止ã—ã¦ã‚­ãƒƒãƒˆã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Build</source>
+ <translation>ビルド</translation>
+ </message>
+ <message>
+ <source>Run</source>
+ <translation>実行</translation>
+ </message>
+</context>
+<context>
+ <name>TargetSettingsPanelItem</name>
+ <message>
+ <source>No kit defined in this project.</source>
+ <translation>ã“ã®ãƒ—ロジェクトã«ã¯ã€ã‚­ãƒƒãƒˆãŒå®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Configure Project</source>
+ <translation>プロジェクトã®è¨­å®š</translation>
+ </message>
+</context>
+<context>
+ <name>Python::Internal::InterpreterAspect</name>
+ <message>
+ <source>Manage...</source>
+ <translation>管ç†...</translation>
+ </message>
+</context>
+<context>
+ <name>Python::Internal::PythonRunConfiguration</name>
+ <message>
+ <source>Run %1</source>
+ <translation>%1 を実行</translation>
+ </message>
+</context>
+<context>
+ <name>Python::Internal::PythonSettings</name>
+ <message>
+ <source>Name:</source>
+ <translation>åå‰:</translation>
+ </message>
+ <message>
+ <source>&amp;Add</source>
+ <translation>追加(&amp;A)</translation>
+ </message>
+ <message>
+ <source>Python</source>
+ <translation>Python</translation>
+ </message>
+</context>
+<context>
+ <name>Python::Internal::PyLSConfigureAssistant</name>
+ <message>
+ <source>Install</source>
+ <translation>インストールã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Enable</source>
+ <translation type="unfinished">有効</translation>
+ </message>
+</context>
+<context>
+ <name>QbsProjectManager::Internal::AspectWidget</name>
+ <message>
+ <source>Change...</source>
+ <translation>変更...</translation>
+ </message>
+</context>
+<context>
+ <name>QbsProjectNode</name>
+ <message>
+ <source>Qbs files</source>
+ <translation>Qbs ファイル</translation>
+ </message>
+</context>
+<context>
+ <name>QbsProjectManager::Internal::ProfileModel</name>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+</context>
+<context>
+ <name>QbsProjectManager::Internal::QbsBuildSystem</name>
+ <message>
+ <source>Failed</source>
+ <translation>失敗</translation>
+ </message>
+ <message>
+ <source>Could not write project file %1.</source>
+ <translation>プロジェクトファイル %1 ã«æ›¸ãè¾¼ã¿ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Reading Project &quot;%1&quot;</source>
+ <translation>プロジェクト &quot;%1&quot; ã®èª­è¾¼ä¸­</translation>
+ </message>
+ <message>
+ <source>Error retrieving run environment: %1</source>
+ <translation>実行環境å–得中ã®ã‚¨ãƒ©ãƒ¼: %1</translation>
+ </message>
+</context>
+<context>
+ <name>QbsProjectManager::Internal::QbsSettingsPage</name>
+ <message>
+ <source>Qbs version:</source>
+ <translation>Qbs ãƒãƒ¼ã‚¸ãƒ§ãƒ³:</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>一般</translation>
+ </message>
+</context>
+<context>
+ <name>QmakeProjectManager::RunSystemAspect</name>
+ <message>
+ <source>Run</source>
+ <translation>実行</translation>
+ </message>
+ <message>
+ <source>Ignore</source>
+ <translation>無視</translation>
+ </message>
+</context>
+<context>
+ <name>QmakeProjectManager::Internal::QmakeKitAspect</name>
+ <message>
+ <source>The mkspec to use when building the project with qmake.&lt;br&gt;This setting is ignored when using other build systems.</source>
+ <translation>qmake ã§ã“ã®ãƒ—ロジェクトをビルドã™ã‚‹ã¨ãã«ç”¨ã„ã‚‹ mkspec ã§ã™ã€‚&lt;br&gt;ä»–ã®ãƒ“ルドシステムを使用ã™ã‚‹å ´åˆã«ã¯ã“ã®è¨­å®šã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>No Qt version set, so mkspec is ignored.</source>
+ <translation>Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„ãŸã‚ã€mkspec を無視ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Mkspec not found for Qt version.</source>
+ <translation>指定ã•ã‚ŒãŸ mkspec ㌠Qt ã«ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>mkspec</source>
+ <translation>mkspec</translation>
+ </message>
+</context>
+<context>
+ <name>QmakeProjectManager::QmakeMakeStep</name>
+ <message>
+ <source>Cannot find Makefile. Check your build settings.</source>
+ <translation>Makefile ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。ビルド設定を確èªã—ã¦ãã ã•ã„。</translation>
+ </message>
+</context>
+<context>
+ <name>QmakeProjectManager::QmakePriFile</name>
+ <message>
+ <source>Headers</source>
+ <translation>ヘッダ</translation>
+ </message>
+ <message>
+ <source>Sources</source>
+ <translation>ソース</translation>
+ </message>
+ <message>
+ <source>Forms</source>
+ <translation>フォーム</translation>
+ </message>
+ <message>
+ <source>State charts</source>
+ <translation>状態é·ç§»å›³</translation>
+ </message>
+ <message>
+ <source>Resources</source>
+ <translation>リソース</translation>
+ </message>
+ <message>
+ <source>QML</source>
+ <translation>QML</translation>
+ </message>
+ <message>
+ <source>Other files</source>
+ <translation>ãã®ä»–ã®ãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+</context>
+<context>
+ <name>QmakePriFile</name>
+ <message>
+ <source>Failed</source>
+ <translation>失敗</translation>
+ </message>
+ <message>
+ <source>Could not write project file %1.</source>
+ <translation>プロジェクトファイル %1 ã«æ›¸ãè¾¼ã¿ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>File Error</source>
+ <translation>ファイルエラー</translation>
+ </message>
+</context>
+<context>
+ <name>QmakeProFile</name>
+ <message>
+ <source>Error while parsing file %1. Giving up.</source>
+ <translation>ファイル %1 ã®è§£æžä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚中断ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Could not find .pro file for subdirectory &quot;%1&quot; in &quot;%2&quot;.</source>
+ <translation>&quot;%2&quot; 㫠サブディレクトリ &quot;%1&quot; 用 .pro ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmakeProjectManager::QmakeBuildSystem</name>
+ <message>
+ <source>Reading Project &quot;%1&quot;</source>
+ <translation>プロジェクト &quot;%1&quot; ã®èª­è¾¼ä¸­</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AssetExporter</name>
+ <message>
+ <source>Yes</source>
+ <translation>ã¯ã„</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AssetExporterPlugin</name>
+ <message>
+ <source>Asset Export</source>
+ <translation>アセットエクスãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Export QML</source>
+ <translation type="vanished">QMLã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Export QML code of the current project.</source>
+ <translation type="vanished">ç¾åœ¨ã®ãƒ—ロジェクトã®QMLコードをエクスãƒãƒ¼ãƒˆã™ã‚‹ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Component</name>
+ <message>
+ <source>Error exporting node %1. Cannot parse type %2.</source>
+ <translation>ノード %1 ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚タイプ %2 を解æžã§ãã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::FilePathModel</name>
+ <message>
+ <source>Canceling QML files preparation.</source>
+ <translation type="vanished">QMLファイルã®æº–備をキャンセルã™ã‚‹ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AnnotationEditor</name>
+ <message>
+ <source>Annotation</source>
+ <translation>アノテーション</translation>
+ </message>
+ <message>
+ <source>Delete this annotation?</source>
+ <translation>ã“ã®ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AnnotationTableView</name>
+ <message>
+ <source>Title</source>
+ <translation type="unfinished">タイトル</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation type="unfinished">値</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AnnotationTabWidget</name>
+ <message>
+ <source>Annotation</source>
+ <translation type="unfinished">アノテーション</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::GlobalAnnotationEditor</name>
+ <message>
+ <source>Global Annotation</source>
+ <translation>グローãƒãƒ«ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³</translation>
+ </message>
+ <message>
+ <source>Delete this annotation?</source>
+ <translation>ã“ã®ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AbstractEditorDialog</name>
+ <message>
+ <source>Untitled Editor</source>
+ <translation>ç„¡é¡Œã®ã‚¨ãƒ‡ã‚£ã‚¿</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::ActionEditorDialog</name>
+ <message>
+ <source>Connection Editor</source>
+ <translation>コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚¨ãƒ‡ã‚£ã‚¿</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::BindingEditorDialog</name>
+ <message>
+ <source>Binding Editor</source>
+ <translation>ãƒã‚¤ãƒ³ãƒ‡ã‚£ãƒ³ã‚°ã‚¨ãƒ‡ã‚£ã‚¿</translation>
+ </message>
+ <message>
+ <source>NOT</source>
+ <translation>NOT</translation>
+ </message>
+ <message>
+ <source>Invert the boolean expression.</source>
+ <translation>ブーリアンå¼ã‚’å転ã•ã›ã‚‹ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::BindingEditorWidget</name>
+ <message>
+ <source>Trigger Completion</source>
+ <translation>補完ã®é–‹å§‹</translation>
+ </message>
+ <message>
+ <source>Meta+Space</source>
+ <translation>Meta+Space</translation>
+ </message>
+ <message>
+ <source>Ctrl+Space</source>
+ <translation>Ctrl+Space</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::SignalListModel</name>
+ <message>
+ <source>Item ID</source>
+ <translation>アイテムID</translation>
+ </message>
+ <message>
+ <source>Signal</source>
+ <translation>シグナル</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::SignalList</name>
+ <message>
+ <source>Signal List for %1</source>
+ <translation>%1 å‘ã‘シグナルリスト</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::SignalListDelegate</name>
+ <message>
+ <source>Release</source>
+ <translation>リリース</translation>
+ </message>
+ <message>
+ <source>Connect</source>
+ <translation>接続ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>AddImageToResources</name>
+ <message>
+ <source>File Name</source>
+ <translation>ファイルå</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>サイズ</translation>
+ </message>
+ <message>
+ <source>Add Resources</source>
+ <translation>リソースを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>&amp;Browse...</source>
+ <translation>å‚ç…§(&amp;B)...</translation>
+ </message>
+ <message>
+ <source>Target Directory</source>
+ <translation>ターゲットディレクトリ</translation>
+ </message>
+ <message>
+ <source>In directory:</source>
+ <translation>ディレクトリ内:</translation>
+ </message>
+</context>
+<context>
+ <name>ChangeStyleWidgetAction</name>
+ <message>
+ <source>Change style for Qt Quick Controls 2.</source>
+ <translation>Qt Quick Controls 2ã®ã‚¹ã‚¿ã‚¤ãƒ«ã‚’変更ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Change style for Qt Quick Controls 2. Configuration file qtquickcontrols2.conf not found.</source>
+ <translation>Qt Quick Controls 2ã®ã‚¹ã‚¿ã‚¤ãƒ«ã‚’変更ã—ã¾ã™ã€‚設定ファイルqtquickcontrols2.confãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesignerAddResources</name>
+ <message>
+ <source>Image Files</source>
+ <translation>ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«</translation>
+ </message>
+ <message>
+ <source>Font Files</source>
+ <translation>フォントファイル</translation>
+ </message>
+ <message>
+ <source>Sound Files</source>
+ <translation>音声ファイル</translation>
+ </message>
+ <message>
+ <source>Shader Files</source>
+ <translation>シェーダファイル</translation>
+ </message>
+ <message>
+ <source>Add Custom Effect</source>
+ <translation>カスタムエフェクトを追加ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>DesignerActionManager</name>
+ <message>
+ <source>Document Has Errors</source>
+ <translation>ドキュメントã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚‹</translation>
+ </message>
+ <message>
+ <source>The document which contains the list model contains errors. So we cannot edit it.</source>
+ <translation>リストモデルをå«ã‚“ã ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã«ã¯ã‚¨ãƒ©ãƒ¼ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ãã®ãŸã‚ã€ç·¨é›†ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Document Cannot Be Written</source>
+ <translation>ドキュメントã«æ›¸ãè¾¼ã¿ã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>An error occurred during a write attemp.</source>
+ <translation>書ãè¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>TemplateMerge</name>
+ <message>
+ <source>Merge With Template</source>
+ <translation>テンプレートã¨ãƒžãƒ¼ã‚¸ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>&amp;Browse...</source>
+ <translation>å‚ç…§(&amp;B)...</translation>
+ </message>
+ <message>
+ <source>Template:</source>
+ <translation>テンプレート:</translation>
+ </message>
+ <message>
+ <source>Browse Template</source>
+ <translation>テンプレートをå‚ç…§ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::Internal::BackendModel</name>
+ <message>
+ <source>Type</source>
+ <translation>åž‹</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Singleton</source>
+ <translation>シングルトン</translation>
+ </message>
+ <message>
+ <source>Local</source>
+ <translation>ローカル変数</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::CurveEditor</name>
+ <message>
+ <source>Set Default</source>
+ <translation>デフォルト設定</translation>
+ </message>
+ <message>
+ <source>Unify</source>
+ <translation>統一ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Start Frame</source>
+ <translation>開始フレーム</translation>
+ </message>
+ <message>
+ <source>End Frame</source>
+ <translation>終了フレーム</translation>
+ </message>
+ <message>
+ <source>Current Frame</source>
+ <translation>ç¾è¡Œãƒ•ãƒ¬ãƒ¼ãƒ </translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::CurveEditorView</name>
+ <message>
+ <source>CurveEditor</source>
+ <translation>カーブエディタ</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::GraphicsView</name>
+ <message>
+ <source>Open Style Editor</source>
+ <translation>スタイルエディタを開ã</translation>
+ </message>
+ <message>
+ <source>Insert Keyframe</source>
+ <translation>キーフレームを挿入ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete Selected Keyframes</source>
+ <translation>é¸æŠžã—ãŸã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ã‚’削除ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::Edit3DView</name>
+ <message>
+ <source>3D Editor</source>
+ <translation>3D エディタ</translation>
+ </message>
+ <message>
+ <source>Failed to Add Import</source>
+ <translation>インãƒãƒ¼ãƒˆã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Could not add QtQuick3D import to project.</source>
+ <translation>QtQuick3D インãƒãƒ¼ãƒˆã‚’プロジェクトã«è¿½åŠ ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>SelectionModeToggleAction</name>
+ <message>
+ <source>Toggle Group/Single Selection Mode</source>
+ <translation>グループ/シングルé¸æŠžãƒ¢ãƒ¼ãƒ‰ã‚’切り替ãˆã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>MoveToolAction</name>
+ <message>
+ <source>Activate Move Tool</source>
+ <translation>移動ツールを起動ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>RotateToolAction</name>
+ <message>
+ <source>Activate Rotate Tool</source>
+ <translation>回転ツールを起動ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ScaleToolAction</name>
+ <message>
+ <source>Activate Scale Tool</source>
+ <translation>スケールツールを起動ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>FitToViewAction</name>
+ <message>
+ <source>Fit Selected Object to View</source>
+ <translation>é¸æŠžã—ãŸã‚ªãƒ–ジェクトを表示ã«åˆã‚ã›ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>CameraToggleAction</name>
+ <message>
+ <source>Toggle Perspective/Orthographic Edit Camera</source>
+ <translation>パースï¼æ­£æŠ•å½±å›³ç·¨é›†ã‚«ãƒ¡ãƒ©ã®åˆ‡ã‚Šæ›¿ãˆ</translation>
+ </message>
+</context>
+<context>
+ <name>OrientationToggleAction</name>
+ <message>
+ <source>Toggle Global/Local Orientation</source>
+ <translation>グローãƒãƒ«ï¼ãƒ­ãƒ¼ã‚«ãƒ«å¿—å‘を切り替ãˆã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>EditLightToggleAction</name>
+ <message>
+ <source>Toggle Edit Light On/Off</source>
+ <translation>編集ライトã®ã‚ªãƒ³/オフを切り替ãˆã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ShowGridAction</name>
+ <message>
+ <source>Toggle Grid Visibility</source>
+ <translation>グリッド表示ã®åˆ‡ã‚Šæ›¿ãˆ</translation>
+ </message>
+</context>
+<context>
+ <name>ResetView</name>
+ <message>
+ <source>Reset View</source>
+ <translation>表示をリセットã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::Edit3DWidget</name>
+ <message>
+ <source>Your file does not import Qt Quick 3D.&lt;br&gt;&lt;br&gt;To create a 3D view, add the QtQuick3D import to your file in the QML Imports tab of the Library view. Or click &lt;a href=&quot;#add_import&quot;&gt;&lt;span style=&quot;text-decoration:none;color:%1&quot;&gt;here&lt;/span&gt;&lt;/a&gt; here to add it immediately.&lt;br&gt;&lt;br&gt;To import 3D assets from another tool, click on the &quot;Add New Assets...&quot; button in the Assets tab of the Library view.</source>
+ <translation>ã‚ãªãŸã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ Qt Quick 3D をインãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“。
+&lt;br&gt;&lt;br&gt; 3D ビューを作æˆã™ã‚‹ã«ã¯ã€Library ビュー㮠QML Imports タブã§ã€QtQuick3D ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚’ファイルã«è¿½åŠ ã—ã¦ãã ã•ã„。ã¾ãŸã¯ã€&lt;a href=&quot;#add_import&quot;&gt;&lt;span style=&quot;text-decoration:none;color:%1&quot;&gt;ã“ã“&lt;/span&gt;をクリックã™ã‚Œã°ã€ã™ãã«è¿½åŠ ã§ãã¾ã™ã€‚
+&lt;br&gt;&lt;br&gt;ä»–ã®ãƒ„ールã‹ã‚‰ 3D アセットをインãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€Library ビュー㮠Assets タブã«ã‚る「Add New Assets...ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::FormEditorAnnotationIcon</name>
+ <message>
+ <source>Annotation</source>
+ <translation>アノテーション</translation>
+ </message>
+ <message>
+ <source>Edit Annotation</source>
+ <translation>アノテーションを編集ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove Annotation</source>
+ <translation>アノテーションを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>By: </source>
+ <translation>By: </translation>
+ </message>
+ <message>
+ <source>Edited: </source>
+ <translation>編集: </translation>
+ </message>
+ <message>
+ <source>Delete this annotation?</source>
+ <translation>ã“ã®ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TransitionTool</name>
+ <message>
+ <source>Add Transition</source>
+ <translation>トランジションを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove Transitions</source>
+ <translation>トランジションを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove All Transitions</source>
+ <translation>ã™ã¹ã¦ã®ãƒˆãƒ©ãƒ³ã‚¸ã‚·ãƒ§ãƒ³ã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Do you really want to remove all transitions?</source>
+ <translation>本当ã«ã™ã¹ã¦ã®ãƒˆãƒ©ãƒ³ã‚¸ã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Remove Dangling Transitions</source>
+ <translation>é·ç§»å…ˆãŒè¦‹å½“ãŸã‚‰ãªã„トランジションを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Transition Tool</source>
+ <translation>トランジションツール</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::DesignDocument</name>
+ <message>
+ <source>Locked items:</source>
+ <translation>ロックã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ :</translation>
+ </message>
+ <message>
+ <source>Delete/Cut Item</source>
+ <translation>アイテムを削除ï¼ã‚«ãƒƒãƒˆã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Deleting or cutting this item will modify locked items.</source>
+ <translation>ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’削除ã¾ãŸã¯ã‚«ãƒƒãƒˆã™ã‚‹ã¨ã€ãƒ­ãƒƒã‚¯ã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ãŒå¤‰æ›´ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Do you want to continue by removing the item (Delete) or removing it and copying it to the clipboard (Cut)?</source>
+ <translation>継続ã—ã¦ã‚¢ã‚¤ãƒ†ãƒ ã‚’削除ã™ã‚‹ã‹(Delete)ã€ã‚¢ã‚¤ãƒ†ãƒ ã‚’削除ã—ã¦ã‚¯ãƒªãƒƒãƒ—ボードã«ã‚³ãƒ”ーã—ã¾ã™ã‹(Cut)?</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::ItemLibraryAssetImporter</name>
+ <message>
+ <source>Could not create a temporary directory for import.</source>
+ <translation>インãƒãƒ¼ãƒˆç”¨ã®ä¸€æ™‚ディレクトリを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Failed to start import 3D asset process</source>
+ <translation>3D アセットã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆå‡¦ç†ã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Importing 3D assets.</source>
+ <translation>3D アセットã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã€‚</translation>
+ </message>
+ <message>
+ <source>Asset import process failed for: &quot;%1&quot;</source>
+ <translation>アセットã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆå‡¦ç†ã«å¤±æ•—ã—ã¾ã—ãŸ: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>No files selected for overwrite, skipping import: &quot;%1&quot;</source>
+ <translation>上書ã用ã«é¸æŠžã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ãŒãªãã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆãŒã‚¹ã‚­ãƒƒãƒ—ã•ã‚Œã¾ã—ãŸ: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Asset already exists. Overwrite existing or skip?
+&quot;%1&quot;</source>
+ <translation>アセットã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚既存ã®ã‚‚ã®ã‚’上書ãã™ã‚‹ã‹ã€ã‚¹ã‚­ãƒƒãƒ—ã™ã‚‹ã‹ï¼Ÿ
+&quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Overwrite Selected Files</source>
+ <translation>é¸æŠžã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’上書ãã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Overwrite All Files</source>
+ <translation>ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’上書ãã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Skip</source>
+ <translation>スキップ</translation>
+ </message>
+ <message>
+ <source>Generating icons.</source>
+ <translation>アイコンを生æˆã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Failed to update imports: %1</source>
+ <translation>インãƒãƒ¼ãƒˆã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>Parsing files.</source>
+ <translation>ファイルã®è§£æžä¸­ã€‚</translation>
+ </message>
+ <message>
+ <source>Skipped import of duplicate asset: &quot;%1&quot;</source>
+ <translation>é‡è¤‡ã™ã‚‹ã‚¢ã‚»ãƒƒãƒˆã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚’スキップã—ã¾ã—ãŸ: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Skipped import of existing asset: &quot;%1&quot;</source>
+ <translation>既存アセットã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚’スキップã—ã¾ã—ãŸ: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Could not access temporary asset directory: &quot;%1&quot;</source>
+ <translation>一時的ãªã‚¢ã‚»ãƒƒãƒˆãƒ»ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“ã§ã—ãŸ: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Failed to create qmldir file for asset: &quot;%1&quot;</source>
+ <translation>アセット:&quot;%1&quot; ã® qmldir ファイルã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Removing old overwritten assets.</source>
+ <translation>å¤ã„上書ãã•ã‚ŒãŸã‚¢ã‚»ãƒƒãƒˆã‚’削除ã™ã‚‹ã€‚</translation>
+ </message>
+ <message>
+ <source>Copying asset files.</source>
+ <translation>アセットファイルã®ã‚³ãƒ”ー。</translation>
+ </message>
+ <message>
+ <source>Overwrite Existing Asset?</source>
+ <translation>既存アセットを上書ãã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Updating data model.</source>
+ <translation>データモデルã®æ›´æ–°ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::ItemLibraryImport</name>
+ <message>
+ <source>Default Components</source>
+ <translation>既定ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>My Components</source>
+ <translation>ç§ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>My 3D Components</source>
+ <translation>ç§ã® 3D コンãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>All Other Components</source>
+ <translation>ãã®ä»–ã™ã¹ã¦ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆ</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::ItemLibraryResourceView</name>
+ <message>
+ <source>Large Icons</source>
+ <translation>大アイコン</translation>
+ </message>
+ <message>
+ <source>Medium Icons</source>
+ <translation>中アイコン</translation>
+ </message>
+ <message>
+ <source>Small Icons</source>
+ <translation>å°ã‚¢ã‚¤ã‚³ãƒ³</translation>
+ </message>
+ <message>
+ <source>List</source>
+ <translation>リスト</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::ItemLibraryView</name>
+ <message>
+ <source>Library</source>
+ <translation>ライブラリ</translation>
+ </message>
+ <message>
+ <source>3D Assets</source>
+ <translation>3D アセット</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::ListModelEditorDialog</name>
+ <message>
+ <source>Add Row</source>
+ <translation>è¡Œã®è¿½åŠ </translation>
+ </message>
+ <message>
+ <source>Remove Columns</source>
+ <translation>列を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add Column</source>
+ <translation>列ã®è¿½åŠ </translation>
+ </message>
+ <message>
+ <source>Move down (CTRL + Down).</source>
+ <translation>下ã«ç§»å‹•ã—ã¾ã™(CTRL + Down)。</translation>
+ </message>
+ <message>
+ <source>Move up (CTRL + Up).</source>
+ <translation>上ã«ç§»å‹•ã—ã¾ã™(CTRL + Up)。</translation>
+ </message>
+ <message>
+ <source>Add Property</source>
+ <translation>プロパティã®è¿½åŠ </translation>
+ </message>
+ <message>
+ <source>Property name:</source>
+ <translation>プロパティå:</translation>
+ </message>
+ <message>
+ <source>Change Property</source>
+ <translation>プロパティを変更ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Column name:</source>
+ <translation>コラムå:</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::ChooseTexturePropertyDialog</name>
+ <message>
+ <source>Select Texture Property</source>
+ <translation>テクスãƒãƒ£ãƒ—ロパティをé¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Set texture to property:</source>
+ <translation>テクスãƒãƒ£ã‚’プロパティã«è¨­å®šã™ã‚‹:</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::NavigatorTreeView</name>
+ <message>
+ <source>Invalid Id</source>
+ <translation>無効㪠ID</translation>
+ </message>
+ <message>
+ <source>%1 is an invalid id.</source>
+ <translation>%1 ã¯ç„¡åŠ¹ãª id ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>%1 already exists.</source>
+ <translation>%1 ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::NavigatorView</name>
+ <message>
+ <source>Navigator</source>
+ <translation>ナビゲータ</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::AlignDistribute</name>
+ <message>
+ <source>Cannot Distribute Perfectly</source>
+ <translation>完璧ãªåˆ†é…ã¯ã§ããªã„</translation>
+ </message>
+ <message>
+ <source>These objects cannot be distributed to equal pixel values. Do you want to distribute to the nearest possible values?</source>
+ <translation>ã“れらã®ã‚ªãƒ–ジェクトã¯ã€ç­‰ã—ã„ピクセル値ã«åˆ†é…ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。å¯èƒ½ãªé™ã‚Šè¿‘ã„値ã«åˆ†é…ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::PropertyEditorContextObject</name>
+ <message>
+ <source>Invalid Type</source>
+ <translation>無効ãªåž‹</translation>
+ </message>
+ <message>
+ <source>%1 is an invalid type.</source>
+ <translation>%1 ã¯ç„¡åŠ¹ãªåž‹ ã§ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::QmlModelNodeProxy</name>
+ <message>
+ <source>multiselection</source>
+ <translation>複数é¸æŠž</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::RichTextEditor</name>
+ <message>
+ <source>&amp;Undo</source>
+ <translation>å…ƒã«æˆ»ã™(&amp;U)</translation>
+ </message>
+ <message>
+ <source>&amp;Redo</source>
+ <translation>ã‚„ã‚Šç›´ã™(&amp;R)</translation>
+ </message>
+ <message>
+ <source>&amp;Bold</source>
+ <translation>太字(&amp;B)</translation>
+ </message>
+ <message>
+ <source>&amp;Italic</source>
+ <translation>斜体(&amp;I)</translation>
+ </message>
+ <message>
+ <source>&amp;Underline</source>
+ <translation>下線(&amp;U)</translation>
+ </message>
+ <message>
+ <source>Select Image</source>
+ <translation>ç”»åƒã‚’é¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Image files (*.png *.jpg)</source>
+ <translation>ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«(*.png *.jpg)</translation>
+ </message>
+ <message>
+ <source>Insert &amp;Image</source>
+ <translation>ç”»åƒã‚’挿入ã™ã‚‹(&amp;I)</translation>
+ </message>
+ <message>
+ <source>Hyperlink Settings</source>
+ <translation>ãƒã‚¤ãƒ‘ーリンクã®è¨­å®š</translation>
+ </message>
+ <message>
+ <source>&amp;Left</source>
+ <translation>å·¦(&amp;L)</translation>
+ </message>
+ <message>
+ <source>C&amp;enter</source>
+ <translation>中央(&amp;E)</translation>
+ </message>
+ <message>
+ <source>&amp;Right</source>
+ <translation>å³(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Bullet List</source>
+ <translation>箇æ¡æ›¸ã</translation>
+ </message>
+ <message>
+ <source>Numbered List</source>
+ <translation>番å·ä»˜ãリスト</translation>
+ </message>
+ <message>
+ <source>Create Table</source>
+ <translation>テーブル作æˆ</translation>
+ </message>
+ <message>
+ <source>Remove Table</source>
+ <translation>テーブルを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Add Row</source>
+ <translation>行を追加</translation>
+ </message>
+ <message>
+ <source>Add Column</source>
+ <translation>列ã®è¿½åŠ </translation>
+ </message>
+ <message>
+ <source>Remove Row</source>
+ <translation>行を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove Column</source>
+ <translation>列を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Merge Cells</source>
+ <translation>セルã®çµåˆ</translation>
+ </message>
+ <message>
+ <source>Split Row</source>
+ <translation>è¡Œã®åˆ†å‰²</translation>
+ </message>
+ <message>
+ <source>Split Column</source>
+ <translation>列ã®åˆ†å‰²</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TextEditorView</name>
+ <message>
+ <source>Trigger Completion</source>
+ <translation>補完ã®é–‹å§‹</translation>
+ </message>
+ <message>
+ <source>Meta+Space</source>
+ <translation>Meta+Space</translation>
+ </message>
+ <message>
+ <source>Ctrl+Space</source>
+ <translation>Ctrl+Space</translation>
+ </message>
+ <message>
+ <source>Text Editor</source>
+ <translation>テキストエディタ</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::PresetList</name>
+ <message>
+ <source>Add Preset</source>
+ <translation>プリセットを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete Selected Preset</source>
+ <translation>é¸æŠžã—ãŸãƒ—リセットを削除ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::PresetEditor</name>
+ <message>
+ <source>Save Preset</source>
+ <translation>プリセットã®ä¿å­˜</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::SplineEditor</name>
+ <message>
+ <source>Delete Point</source>
+ <translation>ãƒã‚¤ãƒ³ãƒˆã‚’削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Smooth Point</source>
+ <translation>スムーズãƒã‚¤ãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Corner Point</source>
+ <translation>コーナーãƒã‚¤ãƒ³ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Add Point</source>
+ <translation>ãƒã‚¤ãƒ³ãƒˆã‚’追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Reset Zoom</source>
+ <translation>縮尺を戻ã™</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesignerTimeline</name>
+ <message>
+ <source>Playhead frame %1</source>
+ <translation>å†ç”Ÿãƒ˜ãƒƒãƒ‰ãƒ•ãƒ¬ãƒ¼ãƒ  %1</translation>
+ </message>
+ <message>
+ <source>Keyframe %1</source>
+ <translation>キーフレーム %1</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TimelinePropertyItem</name>
+ <message>
+ <source>Previous Frame</source>
+ <translation>å‰ã®ãƒ•ãƒ¬ãƒ¼ãƒ </translation>
+ </message>
+ <message>
+ <source>Next Frame</source>
+ <translation>次ã®ãƒ•ãƒ¬ãƒ¼ãƒ </translation>
+ </message>
+ <message>
+ <source>Auto Record</source>
+ <translation>自動記録</translation>
+ </message>
+ <message>
+ <source>Insert Keyframe</source>
+ <translation>キーフレームを挿入ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Delete Keyframe</source>
+ <translation>キーフレームを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Edit Easing Curve...</source>
+ <translation>イージング・カーブを編集ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Edit Keyframe...</source>
+ <translation>キーフレームを編集ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Remove Property</source>
+ <translation>プロパティを削除ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>TimelineKeyframeItem</name>
+ <message>
+ <source>Delete Keyframe</source>
+ <translation>キーフレームを削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Edit Easing Curve...</source>
+ <translation>イージング・カーブを編集ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Edit Keyframe...</source>
+ <translation>キーフレームを編集ã™ã‚‹...</translation>
+ </message>
+</context>
+<context>
+ <name>TimelineBarItem</name>
+ <message>
+ <source>Range from %1 to %2</source>
+ <translation>範囲㯠%1 ã‹ã‚‰ %2 ã¾ã§</translation>
+ </message>
+ <message>
+ <source>Override Color</source>
+ <translation>色を上書ãã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Reset Color</source>
+ <translation>色をリセットã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TimelineSettingsModel</name>
+ <message>
+ <source>State</source>
+ <translation>状態</translation>
+ </message>
+ <message>
+ <source>Timeline</source>
+ <translation>タイムライン</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TimelineToolBar</name>
+ <message>
+ <source>Previous</source>
+ <translation>å‰ã¸</translation>
+ </message>
+ <message>
+ <source>Next</source>
+ <translation>次ã¸</translation>
+ </message>
+ <message>
+ <source>Zoom Out</source>
+ <translation>縮å°</translation>
+ </message>
+ <message>
+ <source>Zoom In</source>
+ <translation>拡大</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TimelineView</name>
+ <message>
+ <source>Timeline</source>
+ <translation>タイムライン</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TimelineWidget</name>
+ <message>
+ <source>Timeline</source>
+ <comment>Title of timeline view</comment>
+ <translation>タイムライン</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TransitionEditorToolBar</name>
+ <message>
+ <source>Zoom Out</source>
+ <translation>縮å°</translation>
+ </message>
+ <message>
+ <source>Zoom In</source>
+ <translation>拡大</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TransitionEditorWidget</name>
+ <message>
+ <source>Transition</source>
+ <comment>Title of transition view</comment>
+ <translation type="unfinished">トランジション</translation>
+ </message>
+ <message>
+ <source>Add Transition</source>
+ <translation type="unfinished">トランジションを追加ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::TransitionForm</name>
+ <message>
+ <source>Invalid Id</source>
+ <translation>無効㪠ID</translation>
+ </message>
+ <message>
+ <source>%1 is an invalid id.</source>
+ <translation>%1 ã¯ç„¡åŠ¹ãª id ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>%1 already exists.</source>
+ <translation>%1 ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::CapturingConnectionManager</name>
+ <message>
+ <source>QML Emulation Layer (QML Puppet) Crashed</source>
+ <translation>QML エミュレーションレイヤ(QML パペット)ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>You are recording a puppet stream and the emulations layer crashed. It is recommended to reopen the Qt Quick Designer and start again.</source>
+ <translation>パペットã‹ã‚‰ã®å‡ºåŠ›ã®å–得中ã«ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ¬ã‚¤ãƒ¤ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚Qt Quick Designer ã‚’å†åº¦é–‹ãã®ã‚’推奨ã—ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::InteractiveConnectionManager</name>
+ <message>
+ <source>Cannot Connect to QML Emulation Layer (QML Puppet)</source>
+ <translation>QML エミュレーションレイヤ(QML パペット)ã«æŽ¥ç¶šã§ãã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>The executable of the QML emulation layer (QML Puppet) may not be responding. Switching to another kit might help.</source>
+ <translation>QML エミュレーションレイヤ(QML パペット)ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ãŒå¿œç­”ã—ã¦ã„ãªã„よã†ã§ã™ã€‚ä»–ã®ã‚­ãƒƒãƒˆã¸ã®å¤‰æ›´ã‚’検討ã—ã¦ãã ã•ã„。</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::NodeInstanceView</name>
+ <message>
+ <source>MB</source>
+ <translation type="unfinished">MB</translation>
+ </message>
+</context>
+<context>
+ <name>MetaInfoReader</name>
+ <message>
+ <source>Invalid type %1</source>
+ <translation>無効ãªåž‹ %1</translation>
+ </message>
+ <message>
+ <source>Unknown property for Type %1</source>
+ <translation>Type %1 ã®æœªçŸ¥ã®ãƒ—ロパティ</translation>
+ </message>
+ <message>
+ <source>Unknown property for ItemLibraryEntry %1</source>
+ <translation>ItemLibraryEntry %1 ã®æœªçŸ¥ã®ãƒ—ロパティ</translation>
+ </message>
+ <message>
+ <source>Unknown property for Property %1</source>
+ <translation>Property %1 ã®æœªçŸ¥ã®ãƒ—ロパティ</translation>
+ </message>
+ <message>
+ <source>Unknown property for QmlSource %1</source>
+ <translation>QmlSource %1 ã®æœªçŸ¥ã®ãƒ—ロパティ</translation>
+ </message>
+ <message>
+ <source>Invalid or duplicate item library entry %1</source>
+ <translation type="vanished">無効ã‚ã‚‹ã„ã¯é‡è¤‡ã—ãŸã‚¢ã‚¤ãƒ†ãƒ ãƒ©ã‚¤ãƒ–ラリエントリー %1</translation>
+ </message>
+</context>
+<context>
+ <name>DocumentMessage</name>
+ <message>
+ <source>Error parsing</source>
+ <translation>解æžä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿ</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation>内部エラー</translation>
+ </message>
+ <message>
+ <source>line %1</source>
+ <translation>%1 行目</translation>
+ </message>
+ <message>
+ <source>column %1</source>
+ <translation>%1 文字目</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::DocumentWarningWidget</name>
+ <message>
+ <source>Cannot open this QML document because of an error in the QML file:</source>
+ <translation>エラーãŒç™ºç”Ÿã—ãŸãŸã‚ QML ファイルを開ã‘ã¾ã›ã‚“:</translation>
+ </message>
+ <message>
+ <source>OK</source>
+ <translation>OK</translation>
+ </message>
+ <message>
+ <source>This QML file contains features which are not supported by Qt Quick Designer at:</source>
+ <translation>ã“ã® QML ファイルã«ã¯ Qt Quick Designer ã§æœªå¯¾å¿œã®æ©Ÿèƒ½ãŒå«ã¾ã‚Œã¦ã„ã¾ã™:</translation>
+ </message>
+ <message>
+ <source>Ignore</source>
+ <translation>無視</translation>
+ </message>
+ <message>
+ <source>Previous</source>
+ <translation>å‰ã¸</translation>
+ </message>
+ <message>
+ <source>Next</source>
+ <translation>次ã¸</translation>
+ </message>
+ <message>
+ <source>Go to error</source>
+ <translation>エラー箇所ã¸é£›ã¶</translation>
+ </message>
+ <message>
+ <source>Go to warning</source>
+ <translation>警告箇所ã¸é£›ã¶</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::GenerateResource</name>
+ <message>
+ <source>A timeout occurred running &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; を実行中ã«ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆãŒç™ºç”Ÿã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>&quot;%1&quot; crashed.</source>
+ <translation>&quot;%1&quot; ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>&quot;%1&quot; failed (exit code %2).</source>
+ <translation>&quot;%1&quot; ãŒå¤±æ•—ã—ã¾ã—ãŸ(終了コード %2)。</translation>
+ </message>
+</context>
+<context>
+ <name>QmlDesigner::SwitchLanguageComboboxAction</name>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+</context>
+<context>
+ <name>QmlJSEditor::QmlJSEditorWidget</name>
+ <message>
+ <source>Show Qt Quick ToolBar</source>
+ <translation>Qt Quick ツールãƒãƒ¼ã‚’表示ã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Code Model Not Available</source>
+ <translation>コードモデル利用ä¸èƒ½</translation>
+ </message>
+ <message>
+ <source>Code model not available.</source>
+ <translation>コードモデルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Code Model of %1</source>
+ <translation>%1 ã®ã‚³ãƒ¼ãƒ‰ãƒ¢ãƒ‡ãƒ«</translation>
+ </message>
+ <message>
+ <source>Refactoring</source>
+ <translation>リファクタリング</translation>
+ </message>
+</context>
+<context>
+ <name>QmlJSEditor::QmlJSEditorDocument</name>
+ <message>
+ <source>This file should only be edited in &lt;b&gt;Design&lt;/b&gt; mode.</source>
+ <translation>ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯&lt;b&gt;デザイン&lt;/b&gt;モードã§ã®ã¿ç·¨é›†ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Switch Mode</source>
+ <translation>モード切替</translation>
+ </message>
+</context>
+<context>
+ <name>QmlJSHoverHandler</name>
+ <message>
+ <source>Library at %1</source>
+ <translation>%1 ã®ãƒ©ã‚¤ãƒ–ラリ</translation>
+ </message>
+ <message>
+ <source>Dumped plugins successfully.</source>
+ <translation>プラグインã®ãƒ€ãƒ³ãƒ—ã«æˆåŠŸã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Read typeinfo files successfully.</source>
+ <translation>typeinfo ファイルã®èª­ã¿è¾¼ã¿ã«æˆåŠŸã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>AddAnalysisMessageSuppressionComment</name>
+ <message>
+ <source>Add a Comment to Suppress This Message</source>
+ <translation>ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’抑止ã™ã‚‹ç‚ºã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’追加ã—ã¾ã™</translation>
+ </message>
+</context>
+<context>
+ <name>QmlJS Code Model Marks</name>
+ <message>
+ <source>Code Model Warning</source>
+ <translation type="unfinished">コードモデルã®è­¦å‘Š</translation>
+ </message>
+ <message>
+ <source>Code Model Error</source>
+ <translation type="unfinished">コードモデルã®ã‚¨ãƒ©ãƒ¼</translation>
+ </message>
+</context>
+<context>
+ <name>QmlPreview::QmlDebugTranslationWidget</name>
+ <message>
+ <source>Elide warning</source>
+ <translation>çœç•¥ã®è­¦å‘Š</translation>
+ </message>
+ <message>
+ <source>Load</source>
+ <translation>読込</translation>
+ </message>
+ <message>
+ <source>Save</source>
+ <translation>ä¿å­˜</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>クリア</translation>
+ </message>
+ <message>
+ <source>Empty</source>
+ <translation>空</translation>
+ </message>
+ <message>
+ <source>Stop</source>
+ <translation>åœæ­¢</translation>
+ </message>
+</context>
+<context>
+ <name>QmlProfiler::Internal::QmlProfilerActions</name>
+ <message>
+ <source>The QML Profiler can be used to find performance bottlenecks in applications using QML.</source>
+ <translation>QML プロファイラã¯ã€QML を使ã£ã¦ã„るアプリケーションã®æ€§èƒ½ã®ãƒœãƒˆãƒ«ãƒãƒƒã‚¯ã‚’探ã™ã®ã«ä½¿ç”¨ã™ã‚‹äº‹ãŒã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML Profiler</source>
+ <translation>QML プロファイラ</translation>
+ </message>
+ <message>
+ <source>Load QML Trace</source>
+ <translation>QML トレースを読ã¿è¾¼ã‚€</translation>
+ </message>
+ <message>
+ <source>Save QML Trace</source>
+ <translation>QML トレースをä¿å­˜</translation>
+ </message>
+ <message>
+ <source>QML Profiler Options</source>
+ <translation>QML プロファイラオプション</translation>
+ </message>
+</context>
+<context>
+ <name>QmlProfiler::QmlProfilerStatisticsModel</name>
+ <message>
+ <source>Painting</source>
+ <translation>æç”»</translation>
+ </message>
+ <message>
+ <source>Compiling</source>
+ <translation>コンパイル</translation>
+ </message>
+ <message>
+ <source>Creating</source>
+ <translation>生æˆ</translation>
+ </message>
+ <message>
+ <source>Binding</source>
+ <translation>ãƒã‚¤ãƒ³ãƒ‡ã‚£ãƒ³ã‚°</translation>
+ </message>
+ <message>
+ <source>Handling Signal</source>
+ <translation>ãƒãƒ³ãƒ‰ãƒªãƒ³ã‚°ä¸­ã®ã‚·ã‚°ãƒŠãƒ«</translation>
+ </message>
+ <message>
+ <source>JavaScript</source>
+ <translation>JavaScript</translation>
+ </message>
+ <message>
+ <source>Could not re-read events from temporary trace file: %1</source>
+ <translation type="unfinished">一時的ãªãƒˆãƒ¬ãƒ¼ã‚¹ãƒ»ãƒ•ã‚¡ã‚¤ãƒ«ã‹ã‚‰ã‚¤ãƒ™ãƒ³ãƒˆã‚’å†èª­ã¿å–ã‚Šã§ãã¾ã›ã‚“ã§ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>&lt;bytecode&gt;</source>
+ <translation>&lt;ãƒã‚¤ãƒˆã‚³ãƒ¼ãƒ‰&gt;</translation>
+ </message>
+ <message>
+ <source>Source code not available</source>
+ <translation>ソースコードãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Calls</source>
+ <translation>呼出回数</translation>
+ </message>
+ <message>
+ <source>Details</source>
+ <translation>詳細</translation>
+ </message>
+ <message>
+ <source>Location</source>
+ <translation>パス</translation>
+ </message>
+ <message>
+ <source>Mean Time</source>
+ <translation>å¹³å‡æ™‚é–“</translation>
+ </message>
+ <message>
+ <source>Total Time</source>
+ <translation>åˆè¨ˆæ™‚é–“</translation>
+ </message>
+</context>
+<context>
+ <name>QmlProfiler::QmlProfilerStatisticsRelativesModel</name>
+ <message>
+ <source>Main Program</source>
+ <translation>メインプログラム</translation>
+ </message>
+ <message>
+ <source>&lt;bytecode&gt;</source>
+ <translation>&lt;ãƒã‚¤ãƒˆã‚³ãƒ¼ãƒ‰&gt;</translation>
+ </message>
+ <message>
+ <source>Source code not available</source>
+ <translation>ソースコードãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Callee</source>
+ <translation>呼ã³å‡ºã—å…ˆ</translation>
+ </message>
+ <message>
+ <source>Caller</source>
+ <translation>呼ã³å‡ºã—å…ƒ</translation>
+ </message>
+ <message>
+ <source>Total Time</source>
+ <translation>åˆè¨ˆæ™‚é–“</translation>
+ </message>
+ <message>
+ <source>Calls</source>
+ <translation>呼出回数</translation>
+ </message>
+</context>
+<context>
+ <name>QmlProfiler::Internal::QmlProfilerTraceFile</name>
+ <message>
+ <source>Error while parsing trace data file: %1</source>
+ <translation>トレースデータファイルã®è§£æžä¸­ã®ã‚¨ãƒ©ãƒ¼: %1</translation>
+ </message>
+ <message>
+ <source>Invalid magic: %1</source>
+ <translation>無効ãªãƒžã‚¸ãƒƒã‚¯: %1</translation>
+ </message>
+ <message>
+ <source>Unknown data stream version: %1</source>
+ <translation>未知ã®ãƒ‡ãƒ¼ã‚¿ã‚¹ãƒˆãƒªãƒ¼ãƒ ãƒãƒ¼ã‚¸ãƒ§ãƒ³: %1</translation>
+ </message>
+ <message>
+ <source>Invalid type index %1</source>
+ <translation>無効ãªã‚¿ã‚¤ãƒ—インデックス: %1</translation>
+ </message>
+ <message>
+ <source>Corrupt data before position %1.</source>
+ <translation>ä½ç½® %1 以å‰ã®ãƒ‡ãƒ¼ã‚¿ãŒå£Šã‚Œã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QmlProjectManager::QmlMainFileAspect</name>
+ <message>
+ <source>Main QML file:</source>
+ <translation>メイン QML ファイル:</translation>
+ </message>
+</context>
+<context>
+ <name>QmlProjectManager::QmlBuildSystem</name>
+ <message>
+ <source>Error while loading project file %1.</source>
+ <translation>プロジェクトファイル %1 ã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Warning while loading project file %1.</source>
+ <translation>プロジェクトファイル %1 を読ã¿è¾¼ã¿ä¸­ã«è­¦å‘ŠãŒã‚ã‚Šã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Qnx::Internal::QnxQmlProfilerSupport</name>
+ <message>
+ <source>Preparing remote side...</source>
+ <translation>リモートå´ã®æº–å‚™...</translation>
+ </message>
+</context>
+<context>
+ <name>Qnx::Internal::QnxDeployConfiguration</name>
+ <message>
+ <source>Deploy to QNX Device</source>
+ <translation>QNX デãƒã‚¤ã‚¹ã«ãƒ‡ãƒ—ロイ</translation>
+ </message>
+</context>
+<context>
+ <name>Qnx::Internal::QnxToolChain</name>
+ <message>
+ <source>QCC</source>
+ <translation>QCC</translation>
+ </message>
+</context>
+<context>
+ <name>QtSupport::BaseQtVersion</name>
+ <message>
+ <source>Device type is not supported by Qt version.</source>
+ <translation>Qt ãŒã‚µãƒãƒ¼ãƒˆã—ã¦ã„ãªã„デãƒã‚¤ã‚¹ã®ç¨®é¡žã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The compiler &quot;%1&quot; (%2) cannot produce code for the Qt version &quot;%3&quot; (%4).</source>
+ <translation>コンパイラ &quot;%1&quot; (%2) ã¯ã€Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ &quot;%3&quot; (%4) 用ã®ã‚³ãƒ¼ãƒ‰ã‚’生æˆã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>The compiler &quot;%1&quot; (%2) may not produce code compatible with the Qt version &quot;%3&quot; (%4).</source>
+ <translation>コンパイラ &quot;%1&quot; (%2) 㯠Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ &quot;%3&quot; (%4) ã¨äº’æ›æ€§ã®ã‚るコードを生æˆã—ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QtSupport::QtKitAspect</name>
+ <message>
+ <source>Qt version</source>
+ <translation>Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³</translation>
+ </message>
+ <message>
+ <source>The version string of the current Qt version.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’表ã™æ–‡å­—列ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The type of the current Qt version.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ç¨®é¡žã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The mkspec of the current Qt version.</source>
+ <translation>ç¾åœ¨ã® Qt ã® mkspec ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation prefix of the current Qt version.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ—レフィックスã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s data.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ãƒ‡ãƒ¼ã‚¿ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s header files.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ãƒ˜ãƒƒãƒ€ãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s library files.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ãƒ©ã‚¤ãƒ–ラリã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s documentation files.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s executable files.</source>
+ <translation>ç¾åœ¨ã® Qt ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s plugins.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ãƒ—ラグインã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s imports.</source>
+ <translation>ç¾åœ¨ã® Qt ã® QML モジュールã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s translation files.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ç¿»è¨³ãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s examples.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ã‚µãƒ³ãƒ—ルã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The installation location of the current Qt version&apos;s demos.</source>
+ <translation>ç¾åœ¨ã® Qt ã®ãƒ‡ãƒ¢ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‘スã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The current Qt version&apos;s default mkspecs (Qt 4).</source>
+ <translation>ç¾åœ¨ã® Qt ã®æ—¢å®šã® mkspec (Qt 4) ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The current Qt version&apos;s default mkspec (Qt 5; target system).</source>
+ <translation>ç¾åœ¨ã® Qt ã®æ—¢å®šã® mkspec (Qt 5ã€ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã‚·ã‚¹ãƒ†ãƒ ) ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The current Qt&apos;s qmake version.</source>
+ <translation>ç¾åœ¨ã® Qt ã® qmake ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>The Qt library to use for all projects using this kit.&lt;br&gt;A Qt version is required for qmake-based projects and optional when using other build systems.</source>
+ <translation>ã“ã®ã‚­ãƒƒãƒˆã‚’用ã„ã‚‹ã™ã¹ã¦ã®ãƒ—ロジェクトã§ä½¿ç”¨ã™ã‚‹ Qt ライブラリã§ã™ã€‚&lt;br&gt;Qt ã«ã¯ qmake ベースã®ãƒ—ロジェクトãŒå¿…è¦ã§ã™ãŒã€ã‚ªãƒ—ションã¨ã—ã¦ãã®ä»–ã®ãƒ“ルドシステムも使用ã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Name of Qt Version</source>
+ <translation>Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³å</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+ <message>
+ <source>Path to the qmake executable</source>
+ <translation>qmake 実行ファイルã®ãƒ‘ス</translation>
+ </message>
+</context>
+<context>
+ <name>ProMessageHandler</name>
+ <message>
+ <source>[Inexact] </source>
+ <extracomment>Prefix used for output from the cumulative evaluation of project files.</extracomment>
+ <translation>[ä¸å®Œå…¨] </translation>
+ </message>
+</context>
+<context>
+ <name>QtSupport::QtQuickCompilerAspect</name>
+ <message>
+ <source>Disables QML debugging. QML profiling will still work.</source>
+ <translation>QML デãƒãƒƒã‚°ã‚’無効化ã—ã¾ã™ã€‚QML プロファイラã¯åˆ©ç”¨å¯èƒ½ã§ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>QtSupport::QtKitAspectWidget</name>
+ <message>
+ <source>%1 (invalid)</source>
+ <translation>%1 (無効)</translation>
+ </message>
+</context>
+<context>
+ <name>QtSupport::Internal::TranslationWizardPage</name>
+ <message>
+ <source>Language:</source>
+ <translation>言語:</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::GenericLinuxDeviceConfigurationWizardKeyDeploymentPage</name>
+ <message>
+ <source>Choose a Private Key File</source>
+ <translation>秘密éµãƒ•ã‚¡ã‚¤ãƒ«ã®é¸æŠž</translation>
+ </message>
+ <message>
+ <source>Private key file:</source>
+ <translation>秘密éµãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::MakeInstallStep</name>
+ <message>
+ <source>Command:</source>
+ <translation>コマンド:</translation>
+ </message>
+ <message>
+ <source>Install root:</source>
+ <translation>インストールルート:</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::RemoteLinuxCustomCommandDeploymentStep</name>
+ <message>
+ <source>Command line:</source>
+ <translation>コマンドライン:</translation>
+ </message>
+ <message>
+ <source>Run custom remote command</source>
+ <translation>カスタムリモートコマンド実行</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::RemoteLinuxKillAppService</name>
+ <message>
+ <source>Trying to kill &quot;%1&quot; on remote device...</source>
+ <translation>リモート・デãƒã‚¤ã‚¹ä¸Šã® &quot;%1&quot; を終了中ã§ã™...</translation>
+ </message>
+ <message>
+ <source>Remote application killed.</source>
+ <translation>リモートアプリケーションãŒçµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Failed to kill remote application. Assuming it was not running.</source>
+ <translation>リモートアプリケーションã®å¼·åˆ¶çµ‚了ã«å¤±æ•—ã—ã¾ã—ãŸã€‚実行中ã§ã¯ãªã„ã“ã¨ã¨å‰æã«ã—ã¦ã„ã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::RemoteLinuxKillAppStep</name>
+ <message>
+ <source>Kill current application instance</source>
+ <translation>ç¾åœ¨ã®ã‚¢ãƒ—リケーションã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’強制終了</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::Internal::RemoteLinuxRunConfiguration</name>
+ <message>
+ <source>Executable on device:</source>
+ <translation>デãƒã‚¤ã‚¹ä¸Šã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+ <message>
+ <source>Remote path not set</source>
+ <translation>リモートã®ãƒ‘スãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
+ </message>
+ <message>
+ <source>Executable on host:</source>
+ <translation>ホスト上ã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«:</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::X11ForwardingAspect</name>
+ <message>
+ <source>X11 Forwarding</source>
+ <translation>X11 フォワーディング</translation>
+ </message>
+ <message>
+ <source>Forward to local display</source>
+ <translation>ローカルディスプレイã«è»¢é€ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::Internal::RsyncDeployService</name>
+ <message>
+ <source>Failed to create remote directories: %1</source>
+ <translation>リモート・ディレクトリã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>rsync failed to start: %1</source>
+ <translation>rsync ã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸ: %1</translation>
+ </message>
+ <message>
+ <source>rsync crashed.</source>
+ <translation>rsync ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>rsync failed with exit code %1.</source>
+ <translation>rsync ã¯çµ‚了コード %1 ã§å¤±æ•—ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteLinux::RsyncDeployStep</name>
+ <message>
+ <source>Flags:</source>
+ <translation>フラグ:</translation>
+ </message>
+ <message>
+ <source>Ignore missing files:</source>
+ <translation>存在ã—ãªã„ファイルを無視ã™ã‚‹:</translation>
+ </message>
+ <message>
+ <source>Deploy files via rsync</source>
+ <translation>rsync 経由ã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’デプロイã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::ColorThemes</name>
+ <message>
+ <source>Modify Color Themes...</source>
+ <translation>色ã®ãƒ†ãƒ¼ãƒžã‚’変更ã™ã‚‹...</translation>
+ </message>
+ <message>
+ <source>Modify Color Theme</source>
+ <translation>色ã®ãƒ†ãƒ¼ãƒžã‚’変更ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Select Color Theme</source>
+ <translation>色ã®ãƒ†ãƒ¼ãƒžã‚’é¸æŠžã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Factory Default</source>
+ <translation>工場出è·æ™‚設定</translation>
+ </message>
+ <message>
+ <source>Colors from SCXML Document</source>
+ <translation>SCXML ドキュメントã‹ã‚‰ã®è‰²</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::ColorThemeItem</name>
+ <message>
+ <source>Pick Color</source>
+ <translation>色をé¸ã¶</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::ColorToolButton</name>
+ <message>
+ <source>Automatic Color</source>
+ <translation>自動カラー</translation>
+ </message>
+ <message>
+ <source>More Colors...</source>
+ <translation>ä»–ã®è‰²...</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::GraphicsView</name>
+ <message>
+ <source>SCXML Generation Failed</source>
+ <translation>SCXML ã®ç”Ÿæˆã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Loading document...</source>
+ <translation>ドキュメントã®èª­ã¿è¾¼ã¿...</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::MainWidget</name>
+ <message>
+ <source>State Color</source>
+ <translation>状態ã®è‰²</translation>
+ </message>
+ <message>
+ <source>Font Color</source>
+ <translation>フォントã®è‰²</translation>
+ </message>
+ <message>
+ <source>Align Left</source>
+ <translation>å·¦æƒãˆ</translation>
+ </message>
+ <message>
+ <source>Adjust Width</source>
+ <translation>å¹…ã®èª¿æ•´</translation>
+ </message>
+ <message>
+ <source>Alignment</source>
+ <translation>整列</translation>
+ </message>
+ <message>
+ <source>Adjustment</source>
+ <translation>調整</translation>
+ </message>
+ <message>
+ <source>Images (%1)</source>
+ <translation>ç”»åƒ (%1)</translation>
+ </message>
+ <message>
+ <source>Untitled</source>
+ <translation>無題</translation>
+ </message>
+ <message>
+ <source>Export Canvas to Image</source>
+ <translation>キャンãƒã‚¹ã‚’ç”»åƒã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Export Failed</source>
+ <translation>エクスãƒãƒ¼ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Could not export to image.</source>
+ <translation>イメージã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Save Screenshot</source>
+ <translation>スクリーンショットをä¿å­˜ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Saving Failed</source>
+ <translation>ä¿å­˜ã®å¤±æ•—</translation>
+ </message>
+ <message>
+ <source>Could not save the screenshot.</source>
+ <translation>スクリーンショットをä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::Navigator</name>
+ <message>
+ <source>Navigator</source>
+ <translation>ナビゲータ</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::SearchModel</name>
+ <message>
+ <source>Type</source>
+ <translation>åž‹</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::StateProperties</name>
+ <message>
+ <source>Attributes</source>
+ <translation>属性</translation>
+ </message>
+ <message>
+ <source>Content</source>
+ <translation>コンテンツ</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::StatisticsModel</name>
+ <message>
+ <source>Tag</source>
+ <translation>ã‚¿ã‚°</translation>
+ </message>
+ <message>
+ <source>Count</source>
+ <translation>カウント</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::Structure</name>
+ <message>
+ <source>Common states</source>
+ <translation>共通ã™ã‚‹çŠ¶æ…‹</translation>
+ </message>
+ <message>
+ <source>Metadata</source>
+ <translation>メタデータ</translation>
+ </message>
+ <message>
+ <source>Other tags</source>
+ <translation>ãã®ä»–ã®ã‚¿ã‚°</translation>
+ </message>
+ <message>
+ <source>Unknown tags</source>
+ <translation>ä¸æ˜Žãªã‚¿ã‚°</translation>
+ </message>
+ <message>
+ <source>Remove items</source>
+ <translation>項目を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Structure</source>
+ <translation>構造体</translation>
+ </message>
+ <message>
+ <source>Expand All</source>
+ <translation>ã™ã¹ã¦å±•é–‹</translation>
+ </message>
+ <message>
+ <source>Collapse All</source>
+ <translation>ã™ã¹ã¦æŠ˜ã‚ŠãŸãŸã‚€</translation>
+ </message>
+ <message>
+ <source>Add child</source>
+ <translation>å­ã‚’追加ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Common::StructureModel</name>
+ <message>
+ <source>Change parent</source>
+ <translation>親を変更ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::OutputPane::ErrorWidget</name>
+ <message>
+ <source>Errors(%1) / Warnings(%2) / Info(%3)</source>
+ <translation>エラー(%1) / 警告(%2) / 情報(%3)</translation>
+ </message>
+ <message>
+ <source>Export to File</source>
+ <translation>ファイルã¸ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>CSV files (*.csv)</source>
+ <translation>CSV ファイル (*.csv)</translation>
+ </message>
+ <message>
+ <source>Export Failed</source>
+ <translation>エクスãƒãƒ¼ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>Cannot open file %1.</source>
+ <translation>ファイル %1 ã‚’é–‹ã‘ã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::OutputPane::WarningModel</name>
+ <message>
+ <source>Severity</source>
+ <translation>é‡è¦åº¦</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>åž‹</translation>
+ </message>
+ <message>
+ <source>Reason</source>
+ <translation>ç†ç”±</translation>
+ </message>
+ <message>
+ <source>Description</source>
+ <translation>説明</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>警告</translation>
+ </message>
+ <message>
+ <source>Info</source>
+ <translation>情報</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+ <message>
+ <source>Severity: %1
+Type: %2
+Reason: %3
+Description: %4</source>
+ <translation>é‡è¦åº¦: %1
+åž‹: %2
+ç†ç”±: %3
+説明: %4</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::ActionHandler</name>
+ <message>
+ <source>Zoom In</source>
+ <translation>拡大</translation>
+ </message>
+ <message>
+ <source>Zoom Out</source>
+ <translation>縮å°</translation>
+ </message>
+ <message>
+ <source>Navigator</source>
+ <translation>ナビゲータ</translation>
+ </message>
+ <message>
+ <source>Copy</source>
+ <translation>コピー</translation>
+ </message>
+ <message>
+ <source>Cut</source>
+ <translation>切りå–ã‚Š</translation>
+ </message>
+ <message>
+ <source>Paste</source>
+ <translation>貼り付ã‘</translation>
+ </message>
+ <message>
+ <source>Align Left</source>
+ <translation>å·¦æƒãˆ</translation>
+ </message>
+ <message>
+ <source>Align Right</source>
+ <translation>å³æƒãˆ</translation>
+ </message>
+ <message>
+ <source>Align Top</source>
+ <translation>上æƒãˆ</translation>
+ </message>
+ <message>
+ <source>Align Bottom</source>
+ <translation>下æƒãˆ</translation>
+ </message>
+ <message>
+ <source>Adjust Width</source>
+ <translation type="unfinished">å¹…ã®èª¿æ•´</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::BaseItem</name>
+ <message>
+ <source>Add child</source>
+ <translation>å­ã‚’追加ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::ConnectableItem</name>
+ <message>
+ <source>Add new state</source>
+ <translation>æ–°ã—ã„状態を追加ã—ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Move State</source>
+ <translation>状態をé·ç§»ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::GraphicsScene</name>
+ <message>
+ <source>Align states</source>
+ <translation>状態をæƒãˆã‚‹</translation>
+ </message>
+ <message>
+ <source>Adjust states</source>
+ <translation>状態を調整ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Cut</source>
+ <translation>切りå–ã‚Š</translation>
+ </message>
+ <message>
+ <source>Remove items</source>
+ <translation>項目を削除ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Re-layout</source>
+ <translation>リレイアウト</translation>
+ </message>
+ <message>
+ <source>Add new state</source>
+ <translation>æ–°ã—ã„状態を追加ã—ã¾ã™</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::IdWarningItem</name>
+ <message>
+ <source>State</source>
+ <translation>状態</translation>
+ </message>
+ <message>
+ <source>Each state must have a unique ID.</source>
+ <translation>å„状態ã¯å›ºæœ‰ã®IDã‚’æŒãŸãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Missing ID.</source>
+ <translation>IDãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Duplicate ID (%1).</source>
+ <translation>é‡è¤‡ã—ãŸID (%1)。</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::InitialWarningItem</name>
+ <message>
+ <source>Initial</source>
+ <translation>åˆæœŸ</translation>
+ </message>
+ <message>
+ <source>One level can contain only one initial state.</source>
+ <translation>1ã¤ã®ãƒ¬ãƒ™ãƒ«ã«ã¯ã€1ã¤ã®åˆæœŸçŠ¶æ…‹ã—ã‹å«ã¾ã‚Œã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Too many initial states at the same level.</source>
+ <translation>åŒã˜ãƒ¬ãƒ™ãƒ«ã®åˆæœŸçŠ¶æ…‹ãŒå¤šã™ãŽã¾ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::QuickTransitionItem</name>
+ <message>
+ <source>H</source>
+ <translation>H</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::SCAttributeItemModel</name>
+ <message>
+ <source>Name</source>
+ <translation>åå‰</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>値</translation>
+ </message>
+ <message>
+ <source>- name -</source>
+ <translation>- åå‰ -</translation>
+ </message>
+ <message>
+ <source> - value -</source>
+ <translation> - 値 -</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::SCShapeProvider</name>
+ <message>
+ <source>Common States</source>
+ <translation>共通ã™ã‚‹çŠ¶æ…‹</translation>
+ </message>
+ <message>
+ <source>Initial</source>
+ <translation>åˆæœŸ</translation>
+ </message>
+ <message>
+ <source>Final</source>
+ <translation>最終</translation>
+ </message>
+ <message>
+ <source>State</source>
+ <translation>状態</translation>
+ </message>
+ <message>
+ <source>Parallel</source>
+ <translation>並列</translation>
+ </message>
+ <message>
+ <source>History</source>
+ <translation>履歴</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::ScxmlDocument</name>
+ <message>
+ <source>Unexpected element.</source>
+ <translation>予想外ã®ã‚¨ãƒ¬ãƒ¡ãƒ³ãƒˆã€‚</translation>
+ </message>
+ <message>
+ <source>Not well formed.</source>
+ <translation>ã†ã¾ãå½¢æˆã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Premature end of document.</source>
+ <translation>ドキュメントã®çµ‚了ãŒæ—©ã„。</translation>
+ </message>
+ <message>
+ <source>Custom error.</source>
+ <translation>カスタムエラー。</translation>
+ </message>
+ <message>
+ <source>Error in reading XML.
+Type: %1 (%2)
+Description: %3
+
+Row: %4, Column: %5
+%6</source>
+ <translation>XMLã®èª­ã¿è¾¼ã¿ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
+åž‹: %1 (%2)
+説明: %3
+
+行: %4, 列: %5
+%6</translation>
+ </message>
+ <message>
+ <source>Current tag is not selected.</source>
+ <translation>ç¾åœ¨ã®ã‚¿ã‚°ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Pasted data is empty.</source>
+ <translation>貼り付ã‘ãŸãƒ‡ãƒ¼ã‚¿ã¯ç©ºã£ã½ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Paste items</source>
+ <translation>アイテムã®è²¼ã‚Šä»˜ã‘</translation>
+ </message>
+ <message>
+ <source>Cannot save XML to the file %1.</source>
+ <translation>XML をファイル %1 ã«ä¿å­˜ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Cannot open file %1.</source>
+ <translation>ファイル %1. ã‚’é–‹ã‘ã¾ã›ã‚“.</translation>
+ </message>
+ <message>
+ <source>Add Tag</source>
+ <translation>タグを追加ã™ã‚‹</translation>
+ </message>
+ <message>
+ <source>Remove Tag</source>
+ <translation>タグを削除ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>SXCMLTag::UnknownAttributeValue</name>
+ <message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+</context>
+<context>
+ <name>SXCMLTag::UnknownAttributeName</name>
+ <message>
+ <source>Unknown</source>
+ <translation>ä¸æ˜Ž</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::ScxmlTag</name>
+ <message>
+ <source>Error in reading XML </source>
+ <translation>XML ã®èª­ã¿è¾¼ã¿ã«å¤±æ•— </translation>
+ </message>
+ <message>
+ <source>New Tag</source>
+ <translation>æ–°ã—ã„ã‚¿ã‚°</translation>
+ </message>
+ <message>
+ <source>Item</source>
+ <translation>アイテム</translation>
+ </message>
+ <message>
+ <source>Metadata</source>
+ <translation>メタデータ</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>削除</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::ScxmlUiFactory</name>
+ <message>
+ <source>Created editor-instance.</source>
+ <translation>エディタインスタンスを作æˆã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Editor-instance is not of the type ISCEditor.</source>
+ <translation>エディタインスタンス㯠ISCEditor åž‹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::StateItem</name>
+ <message>
+ <source>Set as Initial</source>
+ <translation>åˆæœŸè¨­å®š</translation>
+ </message>
+ <message>
+ <source>Zoom to State</source>
+ <translation>状態ã¸ã®ã‚ºãƒ¼ãƒ </translation>
+ </message>
+ <message>
+ <source>Re-Layout</source>
+ <translation>リレイアウト</translation>
+ </message>
+ <message>
+ <source>Change initial state</source>
+ <translation>åˆæœŸçŠ¶æ…‹ã‚’変更ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::StateWarningItem</name>
+ <message>
+ <source>State</source>
+ <translation>状態</translation>
+ </message>
+ <message>
+ <source>Draw some transitions to state.</source>
+ <translation>状態ã¸ã®é·ç§»ã‚’ã„ãã¤ã‹æã„ã¦ã¿ã¾ã—ょã†ã€‚</translation>
+ </message>
+ <message>
+ <source>No input connection.</source>
+ <translation>入力ã®æŽ¥ç¶šãŒã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>No input or output connections (%1).</source>
+ <translation>入力ã¾ãŸã¯å‡ºåŠ›ã®æŽ¥ç¶šãŒã‚ã‚Šã¾ã›ã‚“(%1)。</translation>
+ </message>
+ <message>
+ <source>Draw some transitions to or from state.</source>
+ <translation>状態ã¸ã®é·ç§»ã‚„状態ã‹ã‚‰ã®é·ç§»ã‚’æã„ã¦ã¿ã¾ã—ょã†ã€‚</translation>
+ </message>
+ <message>
+ <source>No output connections (%1).</source>
+ <translation>出力ã®æŽ¥ç¶šãŒã‚ã‚Šã¾ã›ã‚“(%1)。</translation>
+ </message>
+ <message>
+ <source>Draw some transitions from state.</source>
+ <translation>状態ã‹ã‚‰ã®é·ç§»ã‚’æã„ã¦ã¿ã¾ã—ょã†ã€‚</translation>
+ </message>
+ <message>
+ <source>No input connections (%1).</source>
+ <translation>入力ã®æŽ¥ç¶šãŒã‚ã‚Šã¾ã›ã‚“ (%1)。</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::TransitionItem</name>
+ <message>
+ <source>Remove Point</source>
+ <translation>ãƒã‚¤ãƒ³ãƒˆã‚’削除</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::PluginInterface::TransitionWarningItem</name>
+ <message>
+ <source>Transition</source>
+ <translation>トランジション</translation>
+ </message>
+ <message>
+ <source>Transitions should be connected.</source>
+ <translation>トランジションã¯ã¤ãªãŒã£ã¦ã„ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Not connected (%1).</source>
+ <translation>接続ã•ã‚Œã¦ã„ã¾ã›ã‚“(%1)。</translation>
+ </message>
+</context>
+<context>
+ <name>ScxmlEditor::Internal::ScxmlEditorData</name>
+ <message>
+ <source>Undo (Ctrl + Z)</source>
+ <translation>å…ƒã«æˆ»ã™(Ctrl + Z)</translation>
+ </message>
+ <message>
+ <source>Redo (Ctrl + Y)</source>
+ <translation>ã‚„ã‚Šç›´ã—(Ctrl + Y)</translation>
+ </message>
+ <message>
+ <source>This file can only be edited in &lt;b&gt;Design&lt;/b&gt; mode.</source>
+ <translation>ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯&lt;b&gt;デザイン&lt;/b&gt;モード以外ã§ã¯ç·¨é›†ã§ãã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Switch Mode</source>
+ <translation>モード切替</translation>
+ </message>
+</context>
+<context>
+ <name>SerialTerminal::Internal::SerialControl</name>
+ <message>
+ <source>Unable to open port %1: %2.</source>
+ <translation>ãƒãƒ¼ãƒˆ %1 ã‚’é–‹ã‘ã¾ã›ã‚“ã§ã—ãŸ: %2。</translation>
+ </message>
+ <message>
+ <source>Session resumed.</source>
+ <translation>セッションãŒå†é–‹ã•ã‚Œã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>SerialTerminal::Internal::SerialOutputPane</name>
+ <message>
+ <source>Close Tab</source>
+ <translation>タブを閉ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close All Tabs</source>
+ <translation>ã™ã¹ã¦ã®ã‚¿ãƒ–ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Close Other Tabs</source>
+ <translation>ä»–ã®ã‚¿ãƒ–ã‚’é–‰ã˜ã‚‹</translation>
+ </message>
+ <message>
+ <source>Connect</source>
+ <translation>接続ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>FileExtractor</name>
+ <message>
+ <source>Choose Directory</source>
+ <translation>ディレクトリをé¸æŠžã—ã¦ãã ã•ã„</translation>
+ </message>
+</context>
+<context>
+ <name>Subversion::Internal::SubversionLogConfig</name>
+ <message>
+ <source>Show files changed in each revision</source>
+ <translation>リビジョン毎ã®å·®åˆ†ãƒ•ã‚¡ã‚¤ãƒ«ã‚’表示ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>TextEditor::DisplaySettingsPage</name>
+ <message>
+ <source>Display</source>
+ <translation>表示</translation>
+ </message>
+</context>
+<context>
+ <name>TextEditor::FontSettingsPageWidget</name>
+ <message>
+ <source>Copy Color Scheme</source>
+ <translation>カラースキームをコピー</translation>
+ </message>
+ <message>
+ <source>Color scheme name:</source>
+ <translation>カラースキームå:</translation>
+ </message>
+ <message>
+ <source>%1 (copy)</source>
+ <translation>%1 (コピー)</translation>
+ </message>
+ <message>
+ <source>Delete Color Scheme</source>
+ <translation>カラースキームを削除</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to delete this color scheme permanently?</source>
+ <translation>ã“ã®ã‚«ãƒ©ãƒ¼ã‚¹ã‚­ãƒ¼ãƒ ã‚’完全ã«å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Color Scheme Changed</source>
+ <translation>変更ã•ã‚ŒãŸã‚«ãƒ©ãƒ¼ã‚¹ã‚­ãƒ¼ãƒ </translation>
+ </message>
+ <message>
+ <source>The color scheme &quot;%1&quot; was modified, do you want to save the changes?</source>
+ <translation>ã“ã®ã‚«ãƒ©ãƒ¼ã‚¹ã‚­ãƒ¼ãƒ  &quot;%1&quot; ã¯å¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™ã€‚変更内容をセーブã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Discard</source>
+ <translation>破棄</translation>
+ </message>
+ <message>
+ <source>Font &amp;&amp; Colors</source>
+ <translation>フォント &amp;&amp; 色</translation>
+ </message>
+</context>
+<context>
+ <name>TextEditor::TextEditorSettings</name>
+ <message>
+ <source>Text</source>
+ <translation>テキスト</translation>
+ </message>
+ <message>
+ <source>Link</source>
+ <translation>リンク</translation>
+ </message>
+ <message>
+ <source>Links that follow symbol under cursor.</source>
+ <translation>カーソルä½ç½®ã®ã‚·ãƒ³ãƒœãƒ«ã®å®šç¾©ã¸ã®ãƒªãƒ³ã‚¯ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Selection</source>
+ <translation>é¸æŠžéƒ¨åˆ†</translation>
+ </message>
+ <message>
+ <source>Selected text.</source>
+ <translation>é¸æŠžã—ãŸãƒ†ã‚­ã‚¹ãƒˆã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Line Number</source>
+ <translation>行番å·</translation>
+ </message>
+ <message>
+ <source>Line numbers located on the left side of the editor.</source>
+ <translation>エディタã®å·¦å´ã«é…ç½®ã•ã‚Œã‚‹è¡Œç•ªå·ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Search Result</source>
+ <translation>検索çµæžœ</translation>
+ </message>
+ <message>
+ <source>Highlighted search results inside the editor.</source>
+ <translation>エディタ内ã§å¼·èª¿è¡¨ç¤ºã•ã‚Œã‚‹æ¤œç´¢çµæžœã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Search Scope</source>
+ <translation>検索範囲</translation>
+ </message>
+ <message>
+ <source>Section where the pattern is searched in.</source>
+ <translation>パターンã®æ¤œç´¢ç¯„囲ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Parentheses</source>
+ <translation>括弧</translation>
+ </message>
+ <message>
+ <source>Displayed when matching parentheses, square brackets or curly brackets are found.</source>
+ <translation>対応ã™ã‚‹æ‹¬å¼§ã‚„éµæ‹¬å¼§ã€æ³¢æ‹¬å¼§ãŒè¦‹ã¤ã‹ã£ã¦ã„る時ã®è¡¨ç¤ºã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Mismatched Parentheses</source>
+ <translation>未対応ã®æ‹¬å¼§</translation>
+ </message>
+ <message>
+ <source>Displayed when mismatched parentheses, square brackets, or curly brackets are found.</source>
+ <translation>対応ã™ã‚‹æ‹¬å¼§ã‚„éµæ‹¬å¼§ã€æ³¢æ‹¬å¼§ãŒè¦‹ã¤ã‹ã‚‰ãªã„時ã®è¡¨ç¤ºã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Auto Complete</source>
+ <translation>自動補完</translation>
+ </message>
+ <message>
+ <source>Displayed when a character is automatically inserted like brackets or quotes.</source>
+ <translation>括弧や引用符ãªã©ã®æ–‡å­—ãŒè‡ªå‹•çš„ã«æŒ¿å…¥ã•ã‚ŒãŸå ´åˆã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Current Line</source>
+ <translation>ç¾åœ¨è¡Œ</translation>
+ </message>
+ <message>
+ <source>Line where the cursor is placed in.</source>
+ <translation>カーソルã®å­˜åœ¨ã™ã‚‹è¡Œã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Current Line Number</source>
+ <translation>ç¾åœ¨ã®è¡Œç•ªå·</translation>
+ </message>
+ <message>
+ <source>Line number located on the left side of the editor where the cursor is placed in.</source>
+ <translation>カーソルãŒå­˜åœ¨ã™ã‚‹ã‚¨ãƒ‡ã‚£ã‚¿ã®å·¦å´ã«é…ç½®ã•ã‚Œã‚‹è¡Œç•ªå·ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Occurrences</source>
+ <translation>出ç¾ç®‡æ‰€</translation>
+ </message>
+ <message>
+ <source>Occurrences of the symbol under the cursor.
+(Only the background will be applied.)</source>
+ <translation>カーソルã®ä½ç½®ã«ã‚るシンボルã®å‡ºç¾ç®‡æ‰€ã§ã™ã€‚
+(ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã ã‘é©ç”¨ã•ã‚Œã¾ã™ã€‚)</translation>
+ </message>
+ <message>
+ <source>Unused Occurrence</source>
+ <translation>未使用変数ã®å‡ºç¾ç®‡æ‰€</translation>
+ </message>
+ <message>
+ <source>Occurrences of unused variables.</source>
+ <translation>未使用ã®å¤‰æ•°ã®å‡ºç¾ç®‡æ‰€ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Renaming Occurrence</source>
+ <translation>åå‰å¤‰æ›´ä¸­ã‚·ãƒ³ãƒœãƒ«ã®å‡ºç¾ç®‡æ‰€</translation>
+ </message>
+ <message>
+ <source>Occurrences of a symbol that will be renamed.</source>
+ <translation>åå‰ã‚’変更ã—よã†ã¨ã—ã¦ã„るシンボルã®å‡ºç¾ç®‡æ‰€ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Number literal.</source>
+ <translation>数字リテラルã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>String</source>
+ <translation>文字列</translation>
+ </message>
+ <message>
+ <source>Character and string literals.</source>
+ <translation>文字ã¨æ–‡å­—列リテラルã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Primitive Type</source>
+ <translation>プリミティブ型</translation>
+ </message>
+ <message>
+ <source>Name of a primitive data type.</source>
+ <translation>プリミティブãªãƒ‡ãƒ¼ã‚¿åž‹ã®åå‰ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Name of a type.</source>
+ <translation>åž‹åã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Local variables.</source>
+ <translation>ローカル変数ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Field</source>
+ <translation>フィールド</translation>
+ </message>
+ <message>
+ <source>Class&apos; data members.</source>
+ <translation>クラスã®ãƒ‡ãƒ¼ã‚¿ãƒ¡ãƒ³ãƒã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Global variables.</source>
+ <translation>グローãƒãƒ«å¤‰æ•°ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Enumeration</source>
+ <translation>列挙型</translation>
+ </message>
+ <message>
+ <source>Applied to enumeration items.</source>
+ <translation>列挙型ã®ã‚¢ã‚¤ãƒ†ãƒ ã«é©ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Function</source>
+ <translation>関数</translation>
+ </message>
+ <message>
+ <source>Name of a function.</source>
+ <translation>関数åã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Virtual Function</source>
+ <translation>仮想関数</translation>
+ </message>
+ <message>
+ <source>Name of function declared as virtual.</source>
+ <translation>virtual ã¨ã—ã¦å®£è¨€ã•ã‚Œã¦ã„る関数åã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML Binding</source>
+ <translation>QML ãƒã‚¤ãƒ³ãƒ‡ã‚£ãƒ³ã‚°</translation>
+ </message>
+ <message>
+ <source>QML item property, that allows a binding to another property.</source>
+ <translation>別ã®ãƒ—ロパティã«ãƒã‚¤ãƒ³ãƒ‰å¯èƒ½ãª QML アイテムã®ãƒ—ロパティã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML Local Id</source>
+ <translation>QML ローカル ID</translation>
+ </message>
+ <message>
+ <source>QML item id within a QML file.</source>
+ <translation>QML ファイル内㮠QML アイテム㮠ID ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML Root Object Property</source>
+ <translation>QML ルートオブジェクトプロパティ</translation>
+ </message>
+ <message>
+ <source>QML property of a parent item.</source>
+ <translation>親アイテム㮠QML プロパティã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML Scope Object Property</source>
+ <translation>QML スコープオブジェクトプロパティ</translation>
+ </message>
+ <message>
+ <source>Property of the same QML item.</source>
+ <translation>åŒä¸€ QML アイテムã®ãƒ—ロパティã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML State Name</source>
+ <translation>QML 状態å</translation>
+ </message>
+ <message>
+ <source>Name of a QML state.</source>
+ <translation>QML ã®çŠ¶æ…‹åã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML Type Name</source>
+ <translation>QML åž‹å</translation>
+ </message>
+ <message>
+ <source>Name of a QML type.</source>
+ <translation>QML ã®åž‹åã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML External Id</source>
+ <translation>QML 外部 ID</translation>
+ </message>
+ <message>
+ <source>QML id defined in another QML file.</source>
+ <translation>別㮠QML ファイルã§å®šç¾©ã•ã‚Œã¦ã„ã‚‹ QML ID ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>QML External Object Property</source>
+ <translation>QML 外部オブジェクトプロパティ</translation>
+ </message>
+ <message>
+ <source>QML property defined in another QML file.</source>
+ <translation>別㮠QML ファイルã§å®šç¾©ã•ã‚Œã¦ã„ã‚‹ QML プロパティã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>JavaScript Scope Var</source>
+ <translation>JavaScript スコープ変数</translation>
+ </message>
+ <message>
+ <source>Variables defined inside the JavaScript file.</source>
+ <translation>JavaScript ファイル内ã§å®šç¾©ã•ã‚Œã¦ã„る変数ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>JavaScript Import</source>
+ <translation>JavaScript Import</translation>
+ </message>
+ <message>
+ <source>Name of a JavaScript import inside a QML file.</source>
+ <translation>QML ファイル内ã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã‚‹ JavaScript ã®åå‰ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>JavaScript Global Variable</source>
+ <translation>JavaScript グローãƒãƒ«å¤‰æ•°</translation>
+ </message>
+ <message>
+ <source>Variables defined outside the script.</source>
+ <translation>外部ã®ã‚¹ã‚¯ãƒªãƒ—トã§å®šç¾©ã•ã‚Œã¦ã„る変数ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Keyword</source>
+ <translation>キーワード</translation>
+ </message>
+ <message>
+ <source>Reserved keywords of the programming language except keywords denoting primitive types.</source>
+ <translation>プログラム言語ã«ã‚ˆã£ã¦äºˆç´„ã•ã‚Œã¦ã„るキーワードã§ã™(プリミティブ型を示ã™ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã‚’除ã)。</translation>
+ </message>
+ <message>
+ <source>Operator</source>
+ <translation>演算å­</translation>
+ </message>
+ <message>
+ <source>Preprocessor</source>
+ <translation>プリプロセッサ</translation>
+ </message>
+ <message>
+ <source>Preprocessor directives.</source>
+ <translation>プリプロセッサディレクティブã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>ラベル</translation>
+ </message>
+ <message>
+ <source>Labels for goto statements.</source>
+ <translation>goto ステートメント用ã®ãƒ©ãƒ™ãƒ«ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>コメント</translation>
+ </message>
+ <message>
+ <source>All style of comments except Doxygen comments.</source>
+ <translation>Doxgen 用ã®ã‚³ãƒ¡ãƒ³ãƒˆä»¥å¤–ã®ã™ã¹ã¦ã®ã‚³ãƒ¡ãƒ³ãƒˆã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Doxygen Comment</source>
+ <translation>Doxygen 用コメント</translation>
+ </message>
+ <message>
+ <source>Doxygen comments.</source>
+ <translation>Doxygen 用ã®ã‚³ãƒ¡ãƒ³ãƒˆã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Doxygen Tag</source>
+ <translation>Doxygen 用タグ</translation>
+ </message>
+ <message>
+ <source>Doxygen tags.</source>
+ <translation>Doxygen 用ã®ã‚¿ã‚°ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Visual Whitespace</source>
+ <translation>空白ã®å¯è¦–化</translation>
+ </message>
+ <message>
+ <source>Whitespace.
+Will not be applied to whitespace in comments and strings.</source>
+ <translation>空白ã§ã™ã€‚
+コメントや文字列内ã®ç©ºç™½ã«ã¯é©ç”¨ã•ã‚Œã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Disabled Code</source>
+ <translation>無効化ã•ã‚ŒãŸã‚³ãƒ¼ãƒ‰</translation>
+ </message>
+ <message>
+ <source>Code disabled by preprocessor directives.</source>
+ <translation>プリプロセッサ ディレクティブã«ã‚ˆã£ã¦ç„¡åŠ¹åŒ–ã•ã‚ŒãŸã‚³ãƒ¼ãƒ‰ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Added Line</source>
+ <translation>追加ã•ã‚ŒãŸè¡Œ</translation>
+ </message>
+ <message>
+ <source>Applied to added lines in differences (in diff editor).</source>
+ <translation>差分内ã®è¿½åŠ ã•ã‚ŒãŸè¡Œã«é©ç”¨ã•ã‚Œã¾ã™ (差分エディタ)。</translation>
+ </message>
+ <message>
+ <source>Removed Line</source>
+ <translation>削除ã•ã‚ŒãŸè¡Œ</translation>
+ </message>
+ <message>
+ <source>Applied to removed lines in differences (in diff editor).</source>
+ <translation>差分内ã®å‰Šé™¤ã•ã‚ŒãŸè¡Œã«é©ç”¨ã•ã‚Œã¾ã™ (差分エディタ)。</translation>
+ </message>
+ <message>
+ <source>Diff File</source>
+ <translation>差分ファイル</translation>
+ </message>
+ <message>
+ <source>Compared files (in diff editor).</source>
+ <translation>比較ã—ã¦ã„るファイルã§ã™ (差分エディタ)。</translation>
+ </message>
+ <message>
+ <source>Diff Location</source>
+ <translation>差分ã®ä½ç½®</translation>
+ </message>
+ <message>
+ <source>Location in the files where the difference is (in diff editor).</source>
+ <translation>ファイルã®å·®åˆ†ãŒã‚ã‚‹ä½ç½®ã§ã™(差分エディタ)。</translation>
+ </message>
+ <message>
+ <source>Diff File Line</source>
+ <translation>差分ã®ãƒ•ã‚¡ã‚¤ãƒ«è¡Œ</translation>
+ </message>
+ <message>
+ <source>Applied to lines with file information in differences (in side-by-side diff editor).</source>
+ <translation>差分ã®ãƒ•ã‚¡ã‚¤ãƒ«æƒ…å ±ãŒå«ã¾ã‚Œã‚‹è¡Œã«é©ç”¨ã•ã‚Œã¾ã™(サイドãƒã‚¤ã‚µã‚¤ãƒ‰å·®åˆ†ã‚¨ãƒ‡ã‚£ã‚¿ã«ã¦)。</translation>
+ </message>
+ <message>
+ <source>Diff Context Line</source>
+ <translation>差分ã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆè¡Œ</translation>
+ </message>
+ <message>
+ <source>Applied to lines describing hidden context in differences (in side-by-side diff editor).</source>
+ <translation>差分ã®éš ã•ã‚ŒãŸã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãŒè¨˜è¿°ã•ã‚ŒãŸè¡Œã«é©ç”¨ã•ã‚Œã¾ã™(サイドãƒã‚¤ã‚µã‚¤ãƒ‰å·®åˆ†ã‚¨ãƒ‡ã‚£ã‚¿ã«ã¦)。</translation>
+ </message>
+ <message>
+ <source>Diff Source Line</source>
+ <translation>差分ã®æ¯”較元ã®è¡Œ</translation>
+ </message>
+ <message>
+ <source>Applied to source lines with changes in differences (in side-by-side diff editor).</source>
+ <translation>差分ã®æ¯”較元ã®å¤‰æ›´ã•ã‚ŒãŸè¡Œã«é©ç”¨ã•ã‚Œã¾ã™(サイドãƒã‚¤ã‚µã‚¤ãƒ‰å·®åˆ†ã‚¨ãƒ‡ã‚£ã‚¿ã«ã¦)。</translation>
+ </message>
+ <message>
+ <source>Diff Source Character</source>
+ <translation>差分ã®æ¯”較元ã®æ–‡å­—</translation>
+ </message>
+ <message>
+ <source>Applied to removed characters in differences (in side-by-side diff editor).</source>
+ <translation>差分ã®å‰Šé™¤ã•ã‚ŒãŸæ–‡å­—列ã«é©ç”¨ã•ã‚Œã¾ã™(サイドãƒã‚¤ã‚µã‚¤ãƒ‰å·®åˆ†ã‚¨ãƒ‡ã‚£ã‚¿ã«ã¦)。</translation>
+ </message>
+ <message>
+ <source>Diff Destination Line</source>
+ <translation>差分ã®æ¯”較先ã®è¡Œ</translation>
+ </message>
+ <message>
+ <source>Applied to destination lines with changes in differences (in side-by-side diff editor).</source>
+ <translation>差分ã®æ¯”較先ã®å¤‰æ›´ã•ã‚ŒãŸè¡Œã«é©ç”¨ã•ã‚Œã¾ã™(サイドãƒã‚¤ã‚µã‚¤ãƒ‰å·®åˆ†ã‚¨ãƒ‡ã‚£ã‚¿ã«ã¦)。</translation>
+ </message>
+ <message>
+ <source>Diff Destination Character</source>
+ <translation>差分ã®æ¯”較先ã®æ–‡å­—</translation>
+ </message>
+ <message>
+ <source>Applied to added characters in differences (in side-by-side diff editor).</source>
+ <translation>差分ã®è¿½åŠ ã•ã‚ŒãŸæ–‡å­—列ã«é©ç”¨ã•ã‚Œã¾ã™(サイドãƒã‚¤ã‚µã‚¤ãƒ‰å·®åˆ†ã‚¨ãƒ‡ã‚£ã‚¿ã«ã¦)。</translation>
+ </message>
+ <message>
+ <source>Log Change Line</source>
+ <translation>ログã®å¤‰æ›´è¡Œ</translation>
+ </message>
+ <message>
+ <source>Applied to lines describing changes in VCS log.</source>
+ <translation>ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ ã®ãƒ­ã‚°ã«ãŠã„ã¦å¤‰æ›´ã‚’記載ã—ãŸè¡Œã«é©ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+ <message>
+ <source>Underline color of error diagnostics.</source>
+ <translation>エラー判定時ã®ä¸‹ç·šã®è‰²ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Error Context</source>
+ <translation>エラーコンテキスト</translation>
+ </message>
+ <message>
+ <source>Underline color of the contexts of error diagnostics.</source>
+ <translation>エラー判定時ã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã®ä¸‹ç·šã®è‰²ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>警告</translation>
+ </message>
+ <message>
+ <source>Underline color of warning diagnostics.</source>
+ <translation>警告判定時ã®ä¸‹ç·šã®è‰²ã§ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>Warning Context</source>
+ <translation>警告コンテキスト</translation>
+ </message>
+ <message>
+ <source>Underline color of the contexts of warning diagnostics.</source>
+ <translation>警告判定時ã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã®ä¸‹ç·šã®è‰²ã§ã™ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>TextEditor::TextMark</name>
+ <message>
+ <source>Show Diagnostic Settings</source>
+ <translation>診断設定を表示ã™ã‚‹</translation>
+ </message>
+</context>
+<context>
+ <name>Todo::Internal::TodoOptionsPage</name>
+ <message>
+ <source>To-Do</source>
+ <translation>To-Do</translation>
+ </message>
+</context>
+<context>
+ <name>UpdateInfo::Internal::UpdateInfoSettingsPage</name>
+ <message>
+ <source>Daily</source>
+ <translation>毎日</translation>
+ </message>
+ <message>
+ <source>Weekly</source>
+ <translation>毎週</translation>
+ </message>
+ <message>
+ <source>Monthly</source>
+ <translation>毎月</translation>
+ </message>
+ <message>
+ <source>New updates are available.</source>
+ <translation>æ–°ã—ã„更新を利用ã§ãã¾ã™ã€‚</translation>
+ </message>
+ <message>
+ <source>No new updates are available.</source>
+ <translation>æ–°ã—ã„æ›´æ–°ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Checking for updates...</source>
+ <translation>æ›´æ–°ã®ç¢ºèªä¸­...</translation>
+ </message>
+ <message>
+ <source>Not checked yet</source>
+ <translation>未確èª</translation>
+ </message>
+ <message>
+ <source>Update</source>
+ <comment>Update</comment>
+ <translation>æ›´æ–°</translation>
+ </message>
+</context>
+<context>
+ <name>Valgrind::Internal::CallgrindToolRunner</name>
+ <message>
+ <source>Profiling</source>
+ <translation>プロファイル中</translation>
+ </message>
+ <message>
+ <source>Profiling %1</source>
+ <translation>%1 ã®ãƒ—ロファイル中</translation>
+ </message>
+</context>
+<context>
+ <name>Valgrind::Internal::Visualization</name>
+ <message>
+ <source>All functions with an inclusive cost ratio higher than %1 (%2 are hidden)</source>
+ <translation>全体ã®ã‚³ã‚¹ãƒˆçŽ‡ãŒ %1 より高ã„ã™ã¹ã¦ã®é–¢æ•° (%2 個ã®é–¢æ•°ãŒéžè¡¨ç¤º)</translation>
+ </message>
+</context>
+<context>
+ <name>HeobDialog</name>
+ <message>
+ <source>New</source>
+ <translation>æ–°è¦ä½œæˆ</translation>
+ </message>
+ <message>
+ <source>Extra arguments:</source>
+ <translation>追加引数:</translation>
+ </message>
+ <message>
+ <source>OK</source>
+ <translation>OK</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <translation>既定</translation>
+ </message>
+ <message>
+ <source>%1 (copy)</source>
+ <translation>%1 (コピー)</translation>
+ </message>
+</context>
+<context>
+ <name>HeobData</name>
+ <message>
+ <source>Process %1</source>
+ <translation>プロセス %1</translation>
+ </message>
+</context>
+<context>
+ <name>Valgrind::Internal::ValgrindToolRunner</name>
+ <message>
+ <source>Valgrind options: %1</source>
+ <translation>Valgrind オプション: %1</translation>
+ </message>
+ <message>
+ <source>Working directory: %1</source>
+ <translation>作業ディレクトリ: %1</translation>
+ </message>
+ <message>
+ <source>Command line arguments: %1</source>
+ <translation>コマンドライン引数: %1</translation>
+ </message>
+ <message>
+ <source>Analyzing finished.</source>
+ <translation>解æžãŒçµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Error: &quot;%1&quot; could not be started: %2</source>
+ <translation>エラー: &quot;%1&quot; を開始ã§ãã¾ã›ã‚“ã§ã—ãŸ: %2</translation>
+ </message>
+ <message>
+ <source>Error: no Valgrind executable set.</source>
+ <translation>エラー: Valgrind ã®å®Ÿè¡Œãƒ•ã‚¡ã‚¤ãƒ«ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+ </message>
+ <message>
+ <source>Process terminated.</source>
+ <translation>プロセスãŒçµ‚了ã—ã¾ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Valgrind::ValgrindRunner</name>
+ <message>
+ <source>XmlServer on %1:</source>
+ <translation>%1 ã® XmlServer:</translation>
+ </message>
+ <message>
+ <source>LogServer on %1:</source>
+ <translation>%1 ã® LogServer:</translation>
+ </message>
+</context>
+<context>
+ <name>VcsBase::VcsSubmitEditorFactory</name>
+ <message>
+ <source>&amp;Undo</source>
+ <translation>å…ƒã«æˆ»ã™(&amp;U)</translation>
+ </message>
+ <message>
+ <source>&amp;Redo</source>
+ <translation>ã‚„ã‚Šç›´ã™(&amp;R)</translation>
+ </message>
+</context>
+<context>
+ <name>VcsBase::VcsBaseEditorConfig</name>
+ <message>
+ <source>Reload</source>
+ <translation>å†èª­è¾¼</translation>
+ </message>
+</context>
+<context>
+ <name>VcsBase::VcsBasePluginPrivate</name>
+ <message>
+ <source>The file &quot;%1&quot; could not be deleted.</source>
+ <translation>ファイル &quot;%1&quot; ã¯å‰Šé™¤ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Choose Repository Directory</source>
+ <translation>リãƒã‚¸ãƒˆãƒªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„</translation>
+ </message>
+ <message>
+ <source>The directory &quot;%1&quot; is already managed by a version control system (%2). Would you like to specify another directory?</source>
+ <translation>ディレクトリ &quot;%1&quot; ã¯æ—¢ã«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ  (%2) ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã¦ã„ã¾ã™ã€‚別ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’指定ã—ã¾ã™ã‹ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>Repository already under version control</source>
+ <translation>リãƒã‚¸ãƒˆãƒªã¯æ—¢ã«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã•ã‚Œã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
+ <source>Repository Created</source>
+ <translation>リãƒã‚¸ãƒˆãƒªã‚’作æˆã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>A version control repository has been created in %1.</source>
+ <translation>%1 ã«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ãƒªãƒã‚¸ãƒˆãƒªã‚’作æˆã—ã¾ã—ãŸã€‚</translation>
+ </message>
+ <message>
+ <source>Repository Creation Failed</source>
+ <translation>リãƒã‚¸ãƒˆãƒªã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ</translation>
+ </message>
+ <message>
+ <source>A version control repository could not be created in %1.</source>
+ <translation>%1 ã«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ãƒªãƒã‚¸ãƒˆãƒªã‚’作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>Welcome::Internal::IntroductionWidget</name>
+ <message>
+ <source>Locator</source>
+ <translation>クイックアクセス</translation>
+ </message>
+</context>
+<context>
+ <name>Welcome::Internal::SideBar</name>
+ <message>
+ <source>New to Qt?</source>
+ <translation>Qt を始ã‚よã†ï¼</translation>
+ </message>
+ <message>
+ <source>Get Started Now</source>
+ <translation>ã“ã“ã‹ã‚‰ã‚¹ã‚¿ãƒ¼ãƒˆ</translation>
+ </message>
+ <message>
+ <source>Qt Account</source>
+ <translation>Qt アカウント</translation>
+ </message>
+ <message>
+ <source>Online Community</source>
+ <translation>オンラインコミュニティ</translation>
+ </message>
+ <message>
+ <source>Blogs</source>
+ <translation>ブログ</translation>
+ </message>
+ <message>
+ <source>User Guide</source>
+ <translation>ユーザーガイド</translation>
+ </message>
+</context>
+<context>
+ <name>WinRt::Internal::WinRtArgumentsAspect</name>
+ <message>
+ <source>Arguments:</source>
+ <translation>引数:</translation>
+ </message>
+ <message>
+ <source>Restore Default Arguments</source>
+ <translation>既定ã®å¼•æ•°ã®å¾©å…ƒ</translation>
+ </message>
+</context>
</TS>
diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts
index 0a7cda15516..ca1e07984e3 100644
--- a/share/qtcreator/translations/qtcreator_ru.ts
+++ b/share/qtcreator/translations/qtcreator_ru.ts
@@ -1967,7 +1967,7 @@ Prefix with : if the process is private, use a lowercase name if the process is
<translation>Выбранный путь уже Ñодержит корректный пакет инÑтрументов SDK.</translation>
</message>
<message>
- <source>Download and install Android SDK Tools to: %1?</source>
+ <source>Download and install Android SDK Tools to %1?</source>
<translation>Загрузить и уÑтановить инÑтрументы Android SDK в %1?</translation>
</message>
<message>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 70dfa9b5f6e..b567bbe120e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -7,8 +7,8 @@ install(TARGETS app_version EXPORT QtCreator)
add_subdirectory(libs)
add_subdirectory(share)
add_subdirectory(shared)
-add_subdirectory(app)
add_subdirectory(plugins)
+add_subdirectory(app)
add_subdirectory(tools)
install(
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index e30d9fe6abd..cc56d7703ed 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -35,6 +35,43 @@ if (NOT TARGET qtcreator)
return()
endif()
+if (QTC_STATIC_BUILD)
+ set(plugins_to_import "")
+ set(source_file_content "#include <QtPlugin>\n")
+ foreach(plugin IN LISTS __QTC_PLUGINS)
+ if(TARGET ${plugin})
+ list(APPEND plugins_to_import "${plugin}")
+ # TODO ${plugin}Plugin is not correct for all plugins as the class name
+ get_target_property(plugin_class ${plugin} QTC_PLUGIN_CLASS_NAME)
+ string(APPEND source_file_content "Q_IMPORT_PLUGIN(${plugin_class})\n")
+ endif()
+ endforeach()
+
+ string(APPEND source_file_content
+ "struct ResourcesInitializer {\n"
+ " ResourcesInitializer() {\n")
+ foreach(resource_file IN LISTS __QTC_RESOURCE_FILES)
+ string(APPEND source_file_content " Q_INIT_RESOURCE(${resource_file});\n")
+ endforeach()
+ string(APPEND source_file_content
+ " }\n"
+ "} g_resources_initializer;\n")
+
+ file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/plugin_imports.cpp"
+ CONTENT "${source_file_content}"
+ )
+ extend_qtc_target(qtcreator
+ DEPENDS ${plugins_to_import}
+ SOURCES "${CMAKE_CURRENT_BINARY_DIR}/plugin_imports.cpp"
+ )
+
+ if (Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0 AND TARGET QmlDesigner)
+ qt6_import_qml_plugins(qtcreator
+ PATH_TO_SCAN "${CMAKE_CURRENT_SOURCE_DIR}/../../share/qtcreator/qmldesigner")
+ endif()
+endif()
+
if (WIN32)
set(RC_APPLICATION_NAME "${IDE_DISPLAY_NAME}")
set(RC_VERSION "${IDE_VERSION}.0")
diff --git a/src/app/main.cpp b/src/app/main.cpp
index 202b0461df9..ee7ddbd2035 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -289,12 +289,6 @@ static void setHighDpiEnvironmentVariable()
&& !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
} else {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp
index 9a9cf34cbce..2a911fb0da2 100644
--- a/src/libs/3rdparty/cplusplus/Bind.cpp
+++ b/src/libs/3rdparty/cplusplus/Bind.cpp
@@ -2024,7 +2024,7 @@ bool Bind::visit(SimpleDeclarationAST *ast)
decl->setInitializer(asStringLiteral(initializer));
}
- if (_scope->isClass()) {
+ if (_scope->asClass()) {
decl->setVisibility(_visibility);
if (Function *funTy = decl->type()->asFunctionType()) {
@@ -2050,7 +2050,7 @@ bool Bind::visit(EmptyDeclarationAST *ast)
{
(void) ast;
int semicolon_token = ast->semicolon_token;
- if (_scope && (_scope->isClass() || _scope->isNamespace())) {
+ if (_scope && (_scope->asClass() || _scope->asNamespace())) {
const Token &tk = tokenAt(semicolon_token);
if (! tk.generated())
@@ -2227,7 +2227,7 @@ bool Bind::visit(AliasDeclarationAST *ast)
decl->setType(ty);
decl->setStorage(Symbol::Typedef);
ast->symbol = decl;
- if (_scope->isClass())
+ if (_scope->asClass())
decl->setVisibility(_visibility);
_scope->addMember(decl);
@@ -2299,7 +2299,7 @@ bool Bind::visit(FunctionDefinitionAST *ast)
setDeclSpecifiers(fun, declSpecifiers);
fun->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
- if (_scope->isClass()) {
+ if (_scope->asClass()) {
fun->setVisibility(_visibility);
fun->setMethodKey(methodKey);
}
@@ -3147,7 +3147,7 @@ bool Bind::visit(ClassSpecifierAST *ast)
klass->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
_scope->addMember(klass);
- if (_scope->isClass())
+ if (_scope->asClass())
klass->setVisibility(_visibility);
// set the class key
@@ -3210,7 +3210,7 @@ bool Bind::visit(EnumSpecifierAST *ast)
ast->symbol = e;
_scope->addMember(e);
- if (_scope->isClass())
+ if (_scope->asClass())
e->setVisibility(_visibility);
Scope *previousScope = switchScope(e);
@@ -3398,7 +3398,7 @@ void Bind::ensureValidClassName(const Name **name, int sourceLocation)
const QualifiedNameId *qName = (*name)->asQualifiedNameId();
const Name *uqName = qName ? qName->name() : *name;
- if (!uqName->isNameId() && !uqName->isTemplateNameId()) {
+ if (!uqName->asNameId() && !uqName->asTemplateNameId()) {
translationUnit()->error(sourceLocation, "expected a class-name");
*name = uqName->identifier();
diff --git a/src/libs/3rdparty/cplusplus/CMakeLists.txt b/src/libs/3rdparty/cplusplus/CMakeLists.txt
index f2515c9c3a0..41c653aa48e 100644
--- a/src/libs/3rdparty/cplusplus/CMakeLists.txt
+++ b/src/libs/3rdparty/cplusplus/CMakeLists.txt
@@ -1,6 +1,5 @@
add_qtc_library(3rd_cplusplus OBJECT
PUBLIC_DEPENDS Qt5::Core Utils
- DEFINES CPLUSPLUS_BUILD_LIB
SOURCES
AST.cpp AST.h
ASTClone.cpp
@@ -45,6 +44,12 @@ add_qtc_library(3rd_cplusplus OBJECT
PROPERTIES POSITION_INDEPENDENT_CODE ON
)
+set(export_symbol_declaration DEFINES CPLUSPLUS_BUILD_LIB)
+if (QTC_STATIC_BUILD)
+ set(export_symbol_declaration PUBLIC_DEFINES CPLUSPLUS_BUILD_STATIC_LIB)
+endif()
+extend_qtc_target(3rd_cplusplus ${export_symbol_declaration})
+
if(TARGET 3rd_cplusplus)
qtc_enable_release_for_debug_configuration()
if (BUILD_WITH_PCH)
diff --git a/src/libs/3rdparty/cplusplus/CoreTypes.cpp b/src/libs/3rdparty/cplusplus/CoreTypes.cpp
index 0561f660584..4519eabc036 100644
--- a/src/libs/3rdparty/cplusplus/CoreTypes.cpp
+++ b/src/libs/3rdparty/cplusplus/CoreTypes.cpp
@@ -21,10 +21,11 @@
#include "CoreTypes.h"
#include "TypeVisitor.h"
#include "Matcher.h"
-#include "Names.h"
#include <algorithm>
-using namespace CPlusPlus;
+namespace CPlusPlus {
+
+UndefinedType UndefinedType::instance;
void UndefinedType::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }
@@ -204,3 +205,5 @@ bool NamedType::match0(const Type *otherType, Matcher *matcher) const
return false;
}
+
+} // CPlusPlus
diff --git a/src/libs/3rdparty/cplusplus/CoreTypes.h b/src/libs/3rdparty/cplusplus/CoreTypes.h
index 0db1dd81837..5f2c30e89c6 100644
--- a/src/libs/3rdparty/cplusplus/CoreTypes.h
+++ b/src/libs/3rdparty/cplusplus/CoreTypes.h
@@ -29,11 +29,7 @@ namespace CPlusPlus {
class CPLUSPLUS_EXPORT UndefinedType : public Type
{
public:
- static UndefinedType *instance()
- {
- static UndefinedType t;
- return &t;
- }
+ static UndefinedType instance;
const UndefinedType *asUndefinedType() const override
{ return this; }
diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
index 81c608a3dc0..27be623821b 100644
--- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
+++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
@@ -26,24 +26,20 @@
using namespace CPlusPlus;
+FullySpecifiedType::FullySpecifiedType() :
+ _type(&UndefinedType::instance), _flags(0)
+{}
+
FullySpecifiedType::FullySpecifiedType(Type *type) :
_type(type), _flags(0)
{
if (! type)
- _type = UndefinedType::instance();
+ _type = &UndefinedType::instance;
}
-FullySpecifiedType::~FullySpecifiedType()
-{ }
-
bool FullySpecifiedType::isValid() const
-{ return _type != UndefinedType::instance(); }
-
-Type *FullySpecifiedType::type() const
-{ return _type; }
+{ return _type != &UndefinedType::instance; }
-void FullySpecifiedType::setType(Type *type)
-{ _type = type; }
FullySpecifiedType FullySpecifiedType::qualifiedType() const
{
@@ -178,7 +174,7 @@ Type &FullySpecifiedType::operator*()
{ return *_type; }
FullySpecifiedType::operator bool() const
-{ return _type != UndefinedType::instance(); }
+{ return _type != &UndefinedType::instance; }
const Type &FullySpecifiedType::operator*() const
{ return *_type; }
@@ -215,12 +211,6 @@ FullySpecifiedType FullySpecifiedType::simplified() const
return *this;
}
-unsigned FullySpecifiedType::flags() const
-{ return _flags; }
-
-void FullySpecifiedType::setFlags(unsigned flags)
-{ _flags = flags; }
-
bool FullySpecifiedType::match(const FullySpecifiedType &otherTy, Matcher *matcher) const
{
static const unsigned flagsMask = [](){
diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
index a8462d503a3..03f82b788ea 100644
--- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
+++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
@@ -25,17 +25,18 @@
namespace CPlusPlus {
-class CPLUSPLUS_EXPORT FullySpecifiedType
+class CPLUSPLUS_EXPORT FullySpecifiedType final
{
public:
- FullySpecifiedType(Type *type = nullptr);
- ~FullySpecifiedType();
+ FullySpecifiedType();
+ FullySpecifiedType(Type *type);
+ ~FullySpecifiedType() = default;
bool isValid() const;
explicit operator bool() const;
- Type *type() const;
- void setType(Type *type);
+ Type *type() const { return _type; }
+ void setType(Type *type) { _type = type; }
FullySpecifiedType qualifiedType() const;
@@ -109,8 +110,8 @@ public:
FullySpecifiedType simplified() const;
- unsigned flags() const;
- void setFlags(unsigned flags);
+ unsigned flags() const { return _flags; }
+ void setFlags(unsigned flags) { _flags = flags; }
private:
Type *_type;
diff --git a/src/libs/3rdparty/cplusplus/Literals.h b/src/libs/3rdparty/cplusplus/Literals.h
index f15fa5a8048..d4f59d9987d 100644
--- a/src/libs/3rdparty/cplusplus/Literals.h
+++ b/src/libs/3rdparty/cplusplus/Literals.h
@@ -105,7 +105,7 @@ private:
};
};
-class CPLUSPLUS_EXPORT Identifier: public Literal, public Name
+class CPLUSPLUS_EXPORT Identifier final : public Literal, public Name
{
public:
Identifier(const char *chars, int size)
@@ -114,8 +114,7 @@ public:
const Identifier *identifier() const override { return this; }
- const Identifier *asNameId() const override
- { return this; }
+ const Identifier *asNameId() const override { return this; }
protected:
void accept0(NameVisitor *visitor) const override;
diff --git a/src/libs/3rdparty/cplusplus/Name.cpp b/src/libs/3rdparty/cplusplus/Name.cpp
index 05ef8277f6c..7236a21954e 100644
--- a/src/libs/3rdparty/cplusplus/Name.cpp
+++ b/src/libs/3rdparty/cplusplus/Name.cpp
@@ -35,30 +35,6 @@ Name::Name()
Name::~Name()
{ }
-bool Name::isNameId() const
-{ return asNameId() != nullptr; }
-
-bool Name::isAnonymousNameId() const
-{ return asAnonymousNameId() != nullptr; }
-
-bool Name::isTemplateNameId() const
-{ return asTemplateNameId() != nullptr; }
-
-bool Name::isDestructorNameId() const
-{ return asDestructorNameId() != nullptr; }
-
-bool Name::isOperatorNameId() const
-{ return asOperatorNameId() != nullptr; }
-
-bool Name::isConversionNameId() const
-{ return asConversionNameId() != nullptr; }
-
-bool Name::isQualifiedNameId() const
-{ return asQualifiedNameId() != nullptr; }
-
-bool Name::isSelectorNameId() const
-{ return asSelectorNameId() != nullptr; }
-
void Name::accept(NameVisitor *visitor) const
{
if (visitor->preVisit(this))
diff --git a/src/libs/3rdparty/cplusplus/Name.h b/src/libs/3rdparty/cplusplus/Name.h
index 1806a1e4cb8..d1ba99ae36b 100644
--- a/src/libs/3rdparty/cplusplus/Name.h
+++ b/src/libs/3rdparty/cplusplus/Name.h
@@ -35,15 +35,6 @@ public:
virtual const Identifier *identifier() const = 0;
- bool isNameId() const;
- bool isAnonymousNameId() const;
- bool isTemplateNameId() const;
- bool isDestructorNameId() const;
- bool isOperatorNameId() const;
- bool isConversionNameId() const;
- bool isQualifiedNameId() const;
- bool isSelectorNameId() const;
-
virtual const Identifier *asNameId() const { return nullptr; }
virtual const AnonymousNameId *asAnonymousNameId() const { return nullptr; }
virtual const TemplateNameId *asTemplateNameId() const { return nullptr; }
diff --git a/src/libs/3rdparty/cplusplus/Names.cpp b/src/libs/3rdparty/cplusplus/Names.cpp
index 0d3029ae5d1..d240ac536b5 100644
--- a/src/libs/3rdparty/cplusplus/Names.cpp
+++ b/src/libs/3rdparty/cplusplus/Names.cpp
@@ -171,9 +171,6 @@ bool OperatorNameId::match0(const Name *otherName, Matcher *matcher) const
OperatorNameId::Kind OperatorNameId::kind() const
{ return _kind; }
-const Identifier *OperatorNameId::identifier() const
-{ return nullptr; }
-
ConversionNameId::ConversionNameId(const FullySpecifiedType &type)
: _type(type)
{ }
@@ -191,11 +188,7 @@ bool ConversionNameId::match0(const Name *otherName, Matcher *matcher) const
return false;
}
-FullySpecifiedType ConversionNameId::type() const
-{ return _type; }
-const Identifier *ConversionNameId::identifier() const
-{ return nullptr; }
SelectorNameId::~SelectorNameId()
{ }
@@ -249,5 +242,4 @@ bool AnonymousNameId::match0(const Name *otherName, Matcher *matcher) const
return false;
}
-const Identifier *AnonymousNameId::identifier() const
-{ return nullptr; }
+
diff --git a/src/libs/3rdparty/cplusplus/Names.h b/src/libs/3rdparty/cplusplus/Names.h
index 5b915bdfb4e..7913c9b0bc2 100644
--- a/src/libs/3rdparty/cplusplus/Names.h
+++ b/src/libs/3rdparty/cplusplus/Names.h
@@ -234,10 +234,8 @@ public:
Kind kind() const;
- const Identifier *identifier() const override;
-
- const OperatorNameId *asOperatorNameId() const override
- { return this; }
+ const Identifier *identifier() const override { return nullptr; }
+ const OperatorNameId *asOperatorNameId() const override { return this; }
protected:
void accept0(NameVisitor *visitor) const override;
@@ -253,12 +251,9 @@ public:
ConversionNameId(const FullySpecifiedType &type);
virtual ~ConversionNameId();
- FullySpecifiedType type() const;
-
- const Identifier *identifier() const override;
-
- const ConversionNameId *asConversionNameId() const override
- { return this; }
+ FullySpecifiedType type() const { return _type; }
+ const Identifier *identifier() const override { return nullptr; }
+ const ConversionNameId *asConversionNameId() const override { return this; }
protected:
void accept0(NameVisitor *visitor) const override;
@@ -300,7 +295,7 @@ private:
bool _hasArguments;
};
-class CPLUSPLUS_EXPORT AnonymousNameId: public Name
+class CPLUSPLUS_EXPORT AnonymousNameId final : public Name
{
public:
AnonymousNameId(int classTokenIndex);
@@ -308,10 +303,9 @@ public:
int classTokenIndex() const;
- const Identifier *identifier() const override;
+ const Identifier *identifier() const override { return nullptr; }
- const AnonymousNameId *asAnonymousNameId() const override
- { return this; }
+ const AnonymousNameId *asAnonymousNameId() const override { return this; }
protected:
void accept0(NameVisitor *visitor) const override;
diff --git a/src/libs/3rdparty/cplusplus/Scope.cpp b/src/libs/3rdparty/cplusplus/Scope.cpp
index dcafc0c0665..23fa2aad67d 100644
--- a/src/libs/3rdparty/cplusplus/Scope.cpp
+++ b/src/libs/3rdparty/cplusplus/Scope.cpp
@@ -154,7 +154,7 @@ Symbol *SymbolTable::lookat(const Identifier *id) const
} else if (const DestructorNameId *d = identity->asDestructorNameId()) {
if (d->identifier()->match(id))
break;
- } else if (identity->isQualifiedNameId()) {
+ } else if (identity->asQualifiedNameId()) {
return nullptr;
} else if (const SelectorNameId *selectorNameId = identity->asSelectorNameId()) {
if (selectorNameId->identifier()->match(id))
diff --git a/src/libs/3rdparty/cplusplus/Symbol.cpp b/src/libs/3rdparty/cplusplus/Symbol.cpp
index 05254e9d96a..01410ecea95 100644
--- a/src/libs/3rdparty/cplusplus/Symbol.cpp
+++ b/src/libs/3rdparty/cplusplus/Symbol.cpp
@@ -142,23 +142,7 @@ void Symbol::visitSymbol(Symbol *symbol, SymbolVisitor *visitor)
symbol->visitSymbol(visitor);
}
-int Symbol::sourceLocation() const
-{ return _sourceLocation; }
-bool Symbol::isGenerated() const
-{ return _isGenerated; }
-
-bool Symbol::isDeprecated() const
-{ return _isDeprecated; }
-
-void Symbol::setDeprecated(bool isDeprecated)
-{ _isDeprecated = isDeprecated; }
-
-bool Symbol::isUnavailable() const
-{ return _isUnavailable; }
-
-void Symbol::setUnavailable(bool isUnavailable)
-{ _isUnavailable = isUnavailable; }
void Symbol::setSourceLocation(int sourceLocation, TranslationUnit *translationUnit)
{
@@ -176,21 +160,6 @@ void Symbol::setSourceLocation(int sourceLocation, TranslationUnit *translationU
}
}
-int Symbol::line() const
-{
- return _line;
-}
-
-int Symbol::column() const
-{
- return _column;
-}
-
-const StringLiteral *Symbol::fileId() const
-{
- return _fileId;
-}
-
const char *Symbol::fileName() const
{ return _fileId ? _fileId->chars() : ""; }
@@ -208,9 +177,6 @@ const Name *Symbol::unqualifiedName() const
return _name;
}
-const Name *Symbol::name() const
-{ return _name; }
-
void Symbol::setName(const Name *name)
{
_name = name;
@@ -231,9 +197,6 @@ const Identifier *Symbol::identifier() const
return nullptr;
}
-Scope *Symbol::enclosingScope() const
-{ return _enclosingScope; }
-
void Symbol::setEnclosingScope(Scope *scope)
{
CPP_CHECK(! _enclosingScope);
@@ -299,126 +262,6 @@ Block *Symbol::enclosingBlock() const
return nullptr;
}
-unsigned Symbol::index() const
-{ return _index; }
-
-Symbol *Symbol::next() const
-{ return _next; }
-
-unsigned Symbol::hashCode() const
-{ return _hashCode; }
-
-int Symbol::storage() const
-{ return _storage; }
-
-void Symbol::setStorage(int storage)
-{ _storage = storage; }
-
-int Symbol::visibility() const
-{ return _visibility; }
-
-void Symbol::setVisibility(int visibility)
-{ _visibility = visibility; }
-
-bool Symbol::isFriend() const
-{ return _storage == Friend; }
-
-bool Symbol::isRegister() const
-{ return _storage == Register; }
-
-bool Symbol::isStatic() const
-{ return _storage == Static; }
-
-bool Symbol::isExtern() const
-{ return _storage == Extern; }
-
-bool Symbol::isMutable() const
-{ return _storage == Mutable; }
-
-bool Symbol::isTypedef() const
-{ return _storage == Typedef; }
-
-bool Symbol::isPublic() const
-{ return _visibility == Public; }
-
-bool Symbol::isProtected() const
-{ return _visibility == Protected; }
-
-bool Symbol::isPrivate() const
-{ return _visibility == Private; }
-
-bool Symbol::isScope() const
-{ return asScope() != nullptr; }
-
-bool Symbol::isEnum() const
-{ return asEnum() != nullptr; }
-
-bool Symbol::isFunction() const
-{ return asFunction() != nullptr; }
-
-bool Symbol::isNamespace() const
-{ return asNamespace() != nullptr; }
-
-bool Symbol::isTemplate() const
-{ return asTemplate() != nullptr; }
-
-bool Symbol::isClass() const
-{ return asClass() != nullptr; }
-
-bool Symbol::isForwardClassDeclaration() const
-{ return asForwardClassDeclaration() != nullptr; }
-
-bool Symbol::isQtPropertyDeclaration() const
-{ return asQtPropertyDeclaration() != nullptr; }
-
-bool Symbol::isQtEnum() const
-{ return asQtEnum() != nullptr; }
-
-bool Symbol::isBlock() const
-{ return asBlock() != nullptr; }
-
-bool Symbol::isUsingNamespaceDirective() const
-{ return asUsingNamespaceDirective() != nullptr; }
-
-bool Symbol::isUsingDeclaration() const
-{ return asUsingDeclaration() != nullptr; }
-
-bool Symbol::isDeclaration() const
-{ return asDeclaration() != nullptr; }
-
-bool Symbol::isArgument() const
-{ return asArgument() != nullptr; }
-
-bool Symbol::isTypenameArgument() const
-{ return asTypenameArgument() != nullptr; }
-
-bool Symbol::isBaseClass() const
-{ return asBaseClass() != nullptr; }
-
-bool Symbol::isObjCBaseClass() const
-{ return asObjCBaseClass() != nullptr; }
-
-bool Symbol::isObjCBaseProtocol() const
-{ return asObjCBaseProtocol() != nullptr; }
-
-bool Symbol::isObjCClass() const
-{ return asObjCClass() != nullptr; }
-
-bool Symbol::isObjCForwardClassDeclaration() const
-{ return asObjCForwardClassDeclaration() != nullptr; }
-
-bool Symbol::isObjCProtocol() const
-{ return asObjCProtocol() != nullptr; }
-
-bool Symbol::isObjCForwardProtocolDeclaration() const
-{ return asObjCForwardProtocolDeclaration() != nullptr; }
-
-bool Symbol::isObjCMethod() const
-{ return asObjCMethod() != nullptr; }
-
-bool Symbol::isObjCPropertyDeclaration() const
-{ return asObjCPropertyDeclaration() != nullptr; }
-
void Symbol::copy(Symbol *other)
{
_sourceLocation = other->_sourceLocation;
diff --git a/src/libs/3rdparty/cplusplus/Symbol.h b/src/libs/3rdparty/cplusplus/Symbol.h
index 3e1b525a62e..33fe77d80d3 100644
--- a/src/libs/3rdparty/cplusplus/Symbol.h
+++ b/src/libs/3rdparty/cplusplus/Symbol.h
@@ -61,16 +61,16 @@ public:
virtual ~Symbol();
/// Returns this Symbol's source location.
- int sourceLocation() const;
+ int sourceLocation() const { return _sourceLocation; }
/// \returns this Symbol's line number. The line number is 1-based.
- int line() const;
+ int line() const { return _line; }
/// \returns this Symbol's column number. The column number is 1-based.
- int column() const;
+ int column() const { return _column; }
/// Returns this Symbol's file name.
- const StringLiteral *fileId() const;
+ const StringLiteral *fileId() const { return _fileId; }
/// Returns this Symbol's file name.
const char *fileName() const;
@@ -79,7 +79,7 @@ public:
int fileNameLength() const;
/// Returns this Symbol's name.
- const Name *name() const;
+ const Name *name() const { return _name; }
/// Sets this Symbol's name.
void setName(const Name *name); // ### dangerous
@@ -88,115 +88,46 @@ public:
const Identifier *identifier() const;
/// Returns this Symbol's storage class specifier.
- int storage() const;
+ int storage() const { return _storage; }
/// Sets this Symbol's storage class specifier.
- void setStorage(int storage);
+ void setStorage(int storage) { _storage = storage; }
/// Returns this Symbol's visibility.
- int visibility() const;
+ int visibility() const { return _visibility; }
/// Sets this Symbol's visibility.
- void setVisibility(int visibility);
+ void setVisibility(int visibility) { _visibility = visibility; }
/// Returns the next chained Symbol.
- Symbol *next() const;
+ Symbol *next() const { return _next; }
/// Returns true if this Symbol has friend storage specifier.
- bool isFriend() const;
+ bool isFriend() const { return _storage == Friend; }
/// Returns true if this Symbol has register storage specifier.
- bool isRegister() const;
+ bool isRegister() const { return _storage == Register; }
/// Returns true if this Symbol has static storage specifier.
- bool isStatic() const;
+ bool isStatic() const { return _storage == Static; }
/// Returns true if this Symbol has extern storage specifier.
- bool isExtern() const;
+ bool isExtern() const { return _storage == Extern; }
/// Returns true if this Symbol has mutable storage specifier.
- bool isMutable() const;
+ bool isMutable() const { return _storage == Mutable; }
/// Returns true if this Symbol has typedef storage specifier.
- bool isTypedef() const;
+ bool isTypedef() const { return _storage == Typedef; }
/// Returns true if this Symbol's visibility is public.
- bool isPublic() const;
+ bool isPublic() const { return _visibility == Public; }
/// Returns true if this Symbol's visibility is protected.
- bool isProtected() const;
+ bool isProtected() const { return _visibility == Protected; }
/// Returns true if this Symbol's visibility is private.
- bool isPrivate() const;
-
- /// Returns true if this Symbol is a Scope.
- bool isScope() const;
-
- /// Returns true if this Symbol is an Enum.
- bool isEnum() const;
-
- /// Returns true if this Symbol is an Function.
- bool isFunction() const;
-
- /// Returns true if this Symbol is a Namespace.
- bool isNamespace() const;
-
- /// Returns true if this Symbol is a Template.
- bool isTemplate() const;
-
- /// Returns true if this Symbol is a Class.
- bool isClass() const;
-
- /// Returns true if this Symbol is a Block.
- bool isBlock() const;
-
- /// Returns true if this Symbol is a UsingNamespaceDirective.
- bool isUsingNamespaceDirective() const;
-
- /// Returns true if this Symbol is a UsingDeclaration.
- bool isUsingDeclaration() const;
-
- /// Returns true if this Symbol is a Declaration.
- bool isDeclaration() const;
-
- /// Returns true if this Symbol is an Argument.
- bool isArgument() const;
-
- /// Returns true if this Symbol is a Typename argument.
- bool isTypenameArgument() const;
-
- /// Returns true if this Symbol is a BaseClass.
- bool isBaseClass() const;
-
- /// Returns true if this Symbol is a ForwardClassDeclaration.
- bool isForwardClassDeclaration() const;
-
- /// Returns true if this Symbol is a QtPropertyDeclaration.
- bool isQtPropertyDeclaration() const;
-
- /// Returns true if this Symbol is a QtEnum.
- bool isQtEnum() const;
-
- bool isObjCBaseClass() const;
- bool isObjCBaseProtocol() const;
-
- /// Returns true if this Symbol is an Objective-C Class declaration.
- bool isObjCClass() const;
-
- /// Returns true if this Symbol is an Objective-C Class forward declaration.
- bool isObjCForwardClassDeclaration() const;
-
- /// Returns true if this Symbol is an Objective-C Protocol declaration.
- bool isObjCProtocol() const;
-
- /// Returns true if this Symbol is an Objective-C Protocol forward declaration.
- bool isObjCForwardProtocolDeclaration() const;
-
- /// Returns true if this Symbol is an Objective-C method declaration.
- bool isObjCMethod() const;
-
- /// Returns true if this Symbol is an Objective-C @property declaration.
- bool isObjCPropertyDeclaration() const;
+ bool isPrivate() const { return _visibility == Private; }
Utils::Link toLink() const;
@@ -226,53 +157,98 @@ public:
virtual const ObjCMethod *asObjCMethod() const { return nullptr; }
virtual const ObjCPropertyDeclaration *asObjCPropertyDeclaration() const { return nullptr; }
+ /// Returns this Symbol as a Scope.
virtual Scope *asScope() { return nullptr; }
+
+ /// Returns this Symbol as an Enum.
virtual Enum *asEnum() { return nullptr; }
+
+ /// Returns this Symbol as an Function.
virtual Function *asFunction() { return nullptr; }
+
+ /// Returns this Symbol as a Namespace.
virtual Namespace *asNamespace() { return nullptr; }
+
+ /// Returns this Symbol as a Template.
virtual Template *asTemplate() { return nullptr; }
+
virtual NamespaceAlias *asNamespaceAlias() { return nullptr; }
+
+ /// Returns this Symbol as a Class.
virtual Class *asClass() { return nullptr; }
+
+ /// Returns this Symbol as a Block.
virtual Block *asBlock() { return nullptr; }
+
+ /// Returns this Symbol as a UsingNamespaceDirective.
virtual UsingNamespaceDirective *asUsingNamespaceDirective() { return nullptr; }
+
+ /// Returns this Symbol as a UsingDeclaration.
virtual UsingDeclaration *asUsingDeclaration() { return nullptr; }
+
+ /// Returns this Symbol as a Declaration.
virtual Declaration *asDeclaration() { return nullptr; }
+
+ /// Returns this Symbol as an Argument.
virtual Argument *asArgument() { return nullptr; }
+
+ /// Returns this Symbol as a Typename argument.
virtual TypenameArgument *asTypenameArgument() { return nullptr; }
+
+ /// Returns this Symbol as a BaseClass.
virtual BaseClass *asBaseClass() { return nullptr; }
+
+ /// Returns this Symbol as a ForwardClassDeclaration.
virtual ForwardClassDeclaration *asForwardClassDeclaration() { return nullptr; }
+
+ /// Returns this Symbol as a QtPropertyDeclaration.
virtual QtPropertyDeclaration *asQtPropertyDeclaration() { return nullptr; }
+
+ /// Returns this Symbol as a QtEnum.
virtual QtEnum *asQtEnum() { return nullptr; }
+
virtual ObjCBaseClass *asObjCBaseClass() { return nullptr; }
virtual ObjCBaseProtocol *asObjCBaseProtocol() { return nullptr; }
+
+ /// Returns this Symbol as an Objective-C Class declaration.
virtual ObjCClass *asObjCClass() { return nullptr; }
+
+ /// Returns this Symbol as an Objective-C Class forward declaration.
virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() { return nullptr; }
+
+ /// Returns this Symbol as an Objective-C Protocol declaration.
virtual ObjCProtocol *asObjCProtocol() { return nullptr; }
+
+ /// Returns this Symbol as an Objective-C Protocol forward declaration.
virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() { return nullptr; }
+
+ /// Returns this Symbol as an Objective-C method declaration.
virtual ObjCMethod *asObjCMethod() { return nullptr; }
+
+ /// Returns this Symbol as an Objective-C @property declaration.
virtual ObjCPropertyDeclaration *asObjCPropertyDeclaration() { return nullptr; }
/// Returns this Symbol's type.
virtual FullySpecifiedType type() const = 0;
/// Returns this Symbol's hash value.
- unsigned hashCode() const;
+ unsigned hashCode() const { return _hashCode; }
/// Returns this Symbol's index.
- unsigned index() const;
+ unsigned index() const { return _index; }
const Name *unqualifiedName() const;
- bool isGenerated() const;
+ bool isGenerated() const { return _isGenerated; }
- bool isDeprecated() const;
- void setDeprecated(bool isDeprecated);
+ bool isDeprecated() const { return _isDeprecated; }
+ void setDeprecated(bool isDeprecated) { _isDeprecated = isDeprecated; }
- bool isUnavailable() const;
- void setUnavailable(bool isUnavailable);
+ bool isUnavailable() const { return _isUnavailable; }
+ void setUnavailable(bool isUnavailable) { _isUnavailable = isUnavailable; }
/// Returns this Symbol's eclosing scope.
- Scope *enclosingScope() const;
+ Scope *enclosingScope() const { return _enclosingScope; }
/// Returns the eclosing namespace scope.
Namespace *enclosingNamespace() const;
diff --git a/src/libs/3rdparty/cplusplus/Symbols.cpp b/src/libs/3rdparty/cplusplus/Symbols.cpp
index a6a96192bcf..0a14375aed0 100644
--- a/src/libs/3rdparty/cplusplus/Symbols.cpp
+++ b/src/libs/3rdparty/cplusplus/Symbols.cpp
@@ -42,15 +42,13 @@ UsingNamespaceDirective::UsingNamespaceDirective(Clone *clone, Subst *subst, Usi
: Symbol(clone, subst, original)
{ }
-UsingNamespaceDirective::~UsingNamespaceDirective()
-{ }
-
FullySpecifiedType UsingNamespaceDirective::type() const
{ return FullySpecifiedType(); }
void UsingNamespaceDirective::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }
+
NamespaceAlias::NamespaceAlias(TranslationUnit *translationUnit,
int sourceLocation, const Name *name)
: Symbol(translationUnit, sourceLocation, name), _namespaceName(nullptr)
@@ -61,15 +59,6 @@ NamespaceAlias::NamespaceAlias(Clone *clone, Subst *subst, NamespaceAlias *origi
, _namespaceName(clone->name(original->_namespaceName, subst))
{ }
-NamespaceAlias::~NamespaceAlias()
-{ }
-
-const Name *NamespaceAlias::namespaceName() const
-{ return _namespaceName; }
-
-void NamespaceAlias::setNamespaceName(const Name *namespaceName)
-{ _namespaceName = namespaceName; }
-
FullySpecifiedType NamespaceAlias::type() const
{ return FullySpecifiedType(); }
@@ -86,15 +75,13 @@ UsingDeclaration::UsingDeclaration(Clone *clone, Subst *subst, UsingDeclaration
: Symbol(clone, subst, original)
{ }
-UsingDeclaration::~UsingDeclaration()
-{ }
-
FullySpecifiedType UsingDeclaration::type() const
{ return FullySpecifiedType(); }
-void UsingDeclaration::visitSymbol0(SymbolVisitor *visitor)
+void CPlusPlus::UsingDeclaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }
+
Declaration::Declaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name)
: Symbol(translationUnit, sourceLocation, name)
, _initializer(nullptr)
@@ -204,41 +191,16 @@ Declaration::Declaration(Clone *clone, Subst *subst, Declaration *original)
_type = newType;
}
-Declaration::~Declaration()
-{ }
-
-void Declaration::setType(const FullySpecifiedType &type)
-{ _type = type; }
-
-void Declaration::setInitializer(const StringLiteral *initializer)
-{
- _initializer = initializer;
-}
-
-FullySpecifiedType Declaration::type() const
-{ return _type; }
-
-const StringLiteral *Declaration::getInitializer() const
-{
- return _initializer;
-}
-
void Declaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }
+
EnumeratorDeclaration::EnumeratorDeclaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name)
: Declaration(translationUnit, sourceLocation, name)
, _constantValue(nullptr)
{}
-EnumeratorDeclaration::~EnumeratorDeclaration()
-{}
-const StringLiteral *EnumeratorDeclaration::constantValue() const
-{ return _constantValue; }
-
-void EnumeratorDeclaration::setConstantValue(const StringLiteral *constantValue)
-{ _constantValue = constantValue; }
Argument::Argument(TranslationUnit *translationUnit, int sourceLocation, const Name *name)
: Symbol(translationUnit, sourceLocation, name),
@@ -251,27 +213,10 @@ Argument::Argument(Clone *clone, Subst *subst, Argument *original)
, _type(clone->type(original->_type, subst))
{ }
-Argument::~Argument()
-{ }
-
-bool Argument::hasInitializer() const
-{ return _initializer != nullptr; }
-
-const StringLiteral *Argument::initializer() const
-{ return _initializer; }
-
-void Argument::setInitializer(const StringLiteral *initializer)
-{ _initializer = initializer; }
-
-void Argument::setType(const FullySpecifiedType &type)
-{ _type = type; }
-
-FullySpecifiedType Argument::type() const
-{ return _type; }
-
void Argument::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }
+
TypenameArgument::TypenameArgument(TranslationUnit *translationUnit, int sourceLocation, const Name *name)
: Symbol(translationUnit, sourceLocation, name)
, _isClassDeclarator(false)
@@ -283,18 +228,10 @@ TypenameArgument::TypenameArgument(Clone *clone, Subst *subst, TypenameArgument
, _isClassDeclarator(original->_isClassDeclarator)
{ }
-TypenameArgument::~TypenameArgument()
-{ }
-
-void TypenameArgument::setType(const FullySpecifiedType &type)
-{ _type = type; }
-
-FullySpecifiedType TypenameArgument::type() const
-{ return _type; }
-
void TypenameArgument::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }
+
Function::Function(TranslationUnit *translationUnit, int sourceLocation, const Name *name)
: Scope(translationUnit, sourceLocation, name),
_flags(0)
@@ -307,27 +244,6 @@ Function::Function(Clone *clone, Subst *subst, Function *original)
, _flags(original->_flags)
{ }
-Function::~Function()
-{ }
-
-bool Function::isNormal() const
-{ return f._methodKey == NormalMethod; }
-
-bool Function::isSignal() const
-{ return f._methodKey == SignalMethod; }
-
-bool Function::isSlot() const
-{ return f._methodKey == SlotMethod; }
-
-bool Function::isInvokable() const
-{ return f._methodKey == InvokableMethod; }
-
-int Function::methodKey() const
-{ return f._methodKey; }
-
-void Function::setMethodKey(int key)
-{ f._methodKey = key; }
-
bool Function::isSignatureEqualTo(const Function *other, Matcher *matcher) const
{
if (! other)
@@ -409,12 +325,6 @@ FullySpecifiedType Function::type() const
return ty;
}
-FullySpecifiedType Function::returnType() const
-{ return _returnType; }
-
-void Function::setReturnType(const FullySpecifiedType &returnType)
-{ _returnType = returnType; }
-
bool Function::hasReturnType() const
{
const FullySpecifiedType ty = returnType();
@@ -431,7 +341,7 @@ int Function::argumentCount() const
// arguments with a lambda as default argument will also have more blocks.
int argc = 0;
for (int it = 0; it < memCnt; ++it)
- if (memberAt(it)->isArgument())
+ if (memberAt(it)->asArgument())
++argc;
return argc;
}
@@ -470,66 +380,6 @@ int Function::minimumArgumentCount() const
return index;
}
-bool Function::isVirtual() const
-{ return f._isVirtual; }
-
-void Function::setVirtual(bool isVirtual)
-{ f._isVirtual = isVirtual; }
-
-bool Function::isOverride() const
-{ return f._isOverride; }
-
-void Function::setOverride(bool isOverride)
-{ f._isOverride = isOverride; }
-
-bool Function::isFinal() const
-{ return f._isFinal; }
-
-void Function::setFinal(bool isFinal)
-{ f._isFinal = isFinal; }
-
-bool Function::isVariadic() const
-{ return f._isVariadic; }
-
-void Function::setVariadic(bool isVariadic)
-{ f._isVariadic = isVariadic; }
-
-bool Function::isVariadicTemplate() const
-{ return f._isVariadicTemplate; }
-
-void Function::setVariadicTemplate(bool isVariadicTemplate)
-{ f._isVariadicTemplate = isVariadicTemplate; }
-
-bool Function::isConst() const
-{ return f._isConst; }
-
-void Function::setConst(bool isConst)
-{ f._isConst = isConst; }
-
-bool Function::isVolatile() const
-{ return f._isVolatile; }
-
-void Function::setVolatile(bool isVolatile)
-{ f._isVolatile = isVolatile; }
-
-bool Function::isPureVirtual() const
-{ return f._isPureVirtual; }
-
-void Function::setPureVirtual(bool isPureVirtual)
-{ f._isPureVirtual = isPureVirtual; }
-
-Function::RefQualifier Function::refQualifier() const
-{ return static_cast<RefQualifier>(f._refQualifier); }
-
-void Function::setRefQualifier(Function::RefQualifier refQualifier)
-{ f._refQualifier = refQualifier; }
-
-bool Function::isAmbiguous() const
-{ return f._isAmbiguous; }
-
-void Function::setAmbiguous(bool isAmbiguous)
-{ f._isAmbiguous = isAmbiguous; }
-
void Function::visitSymbol0(SymbolVisitor *visitor)
{
if (visitor->visit(this)) {
@@ -569,11 +419,6 @@ bool Function::maybeValidPrototype(int actualArgumentCount) const
return true;
}
-const StringLiteral *Function::exceptionSpecification()
-{ return _exceptionSpecification; }
-
-void Function::setExceptionSpecification(const StringLiteral *spec)
-{ _exceptionSpecification = spec; }
Block::Block(TranslationUnit *translationUnit, int sourceLocation)
: Scope(translationUnit, sourceLocation, /*name = */ nullptr)
@@ -583,9 +428,6 @@ Block::Block(Clone *clone, Subst *subst, Block *original)
: Scope(clone, subst, original)
{ }
-Block::~Block()
-{ }
-
FullySpecifiedType Block::type() const
{ return FullySpecifiedType(); }
@@ -608,21 +450,9 @@ Enum::Enum(Clone *clone, Subst *subst, Enum *original)
, _isScoped(original->isScoped())
{ }
-Enum::~Enum()
-{ }
-
FullySpecifiedType Enum::type() const
{ return FullySpecifiedType(const_cast<Enum *>(this)); }
-bool Enum::isScoped() const
-{
- return _isScoped;
-}
-
-void Enum::setScoped(bool scoped)
-{
- _isScoped = scoped;
-}
void Enum::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }
@@ -652,9 +482,6 @@ Template::Template(Clone *clone, Subst *subst, Template *original)
: Scope(clone, subst, original)
{ }
-Template::~Template()
-{ }
-
int Template::templateParameterCount() const
{
if (declaration() != nullptr)
@@ -663,17 +490,14 @@ int Template::templateParameterCount() const
return 0;
}
-Symbol *Template::templateParameterAt(int index) const
-{ return memberAt(index); }
-
Symbol *Template::declaration() const
{
if (isEmpty())
return nullptr;
if (Symbol *s = memberAt(memberCount() - 1)) {
- if (s->isClass() || s->isForwardClassDeclaration() ||
- s->isTemplate() || s->isFunction() || s->isDeclaration())
+ if (s->asClass() || s->asForwardClassDeclaration() ||
+ s->asTemplate() || s->asFunction() || s->asDeclaration())
return s;
}
@@ -712,9 +536,6 @@ Namespace::Namespace(Clone *clone, Subst *subst, Namespace *original)
, _isInline(original->_isInline)
{ }
-Namespace::~Namespace()
-{ }
-
void Namespace::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }
@@ -749,30 +570,10 @@ BaseClass::BaseClass(Clone *clone, Subst *subst, BaseClass *original)
, _type(clone->type(original->_type, subst))
{ }
-BaseClass::~BaseClass()
-{ }
-
-FullySpecifiedType BaseClass::type() const
-{ return _type; }
-
-void BaseClass::setType(const FullySpecifiedType &type)
-{ _type = type; }
-
-bool BaseClass::isVirtual() const
-{ return _isVirtual; }
-
-void BaseClass::setVirtual(bool isVirtual)
-{ _isVirtual = isVirtual; }
-
-bool BaseClass::isVariadic() const
-{ return _isVariadic; }
-
-void BaseClass::setVariadic(bool isVariadic)
-{ _isVariadic = isVariadic; }
-
void BaseClass::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }
+
ForwardClassDeclaration::ForwardClassDeclaration(TranslationUnit *translationUnit,
int sourceLocation, const Name *name)
: Symbol(translationUnit, sourceLocation, name)
@@ -782,9 +583,6 @@ ForwardClassDeclaration::ForwardClassDeclaration(Clone *clone, Subst *subst, For
: Symbol(clone, subst, original)
{ }
-ForwardClassDeclaration::~ForwardClassDeclaration()
-{ }
-
FullySpecifiedType ForwardClassDeclaration::type() const
{ return FullySpecifiedType(const_cast<ForwardClassDeclaration *>(this)); }
@@ -815,24 +613,6 @@ Class::Class(Clone *clone, Subst *subst, Class *original)
addBaseClass(clone->symbol(original->_baseClasses.at(i), subst)->asBaseClass());
}
-Class::~Class()
-{ }
-
-bool Class::isClass() const
-{ return _key == ClassKey; }
-
-bool Class::isStruct() const
-{ return _key == StructKey; }
-
-bool Class::isUnion() const
-{ return _key == UnionKey; }
-
-Class::Key Class::classKey() const
-{ return _key; }
-
-void Class::setClassKey(Key key)
-{ _key = key; }
-
void Class::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }
@@ -880,21 +660,6 @@ QtPropertyDeclaration::QtPropertyDeclaration(Clone *clone, Subst *subst, QtPrope
, _flags(original->_flags)
{ }
-QtPropertyDeclaration::~QtPropertyDeclaration()
-{ }
-
-void QtPropertyDeclaration::setType(const FullySpecifiedType &type)
-{ _type = type; }
-
-void QtPropertyDeclaration::setFlags(int flags)
-{ _flags = flags; }
-
-int QtPropertyDeclaration::flags() const
-{ return _flags; }
-
-FullySpecifiedType QtPropertyDeclaration::type() const
-{ return _type; }
-
void QtPropertyDeclaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }
@@ -907,12 +672,6 @@ QtEnum::QtEnum(Clone *clone, Subst *subst, QtEnum *original)
: Symbol(clone, subst, original)
{ }
-QtEnum::~QtEnum()
-{ }
-
-FullySpecifiedType QtEnum::type() const
-{ return FullySpecifiedType(); }
-
void QtEnum::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }
@@ -925,8 +684,6 @@ ObjCBaseClass::ObjCBaseClass(Clone *clone, Subst *subst, ObjCBaseClass *original
: Symbol(clone, subst, original)
{ }
-ObjCBaseClass::~ObjCBaseClass()
-{ }
FullySpecifiedType ObjCBaseClass::type() const
{ return FullySpecifiedType(); }
@@ -942,9 +699,6 @@ ObjCBaseProtocol::ObjCBaseProtocol(Clone *clone, Subst *subst, ObjCBaseProtocol
: Symbol(clone, subst, original)
{ }
-ObjCBaseProtocol::~ObjCBaseProtocol()
-{ }
-
FullySpecifiedType ObjCBaseProtocol::type() const
{ return FullySpecifiedType(); }
@@ -970,30 +724,6 @@ ObjCClass::ObjCClass(Clone *clone, Subst *subst, ObjCClass *original)
addProtocol(clone->symbol(original->_protocols.at(i), subst)->asObjCBaseProtocol());
}
-ObjCClass::~ObjCClass()
-{}
-
-bool ObjCClass::isInterface() const
-{ return _isInterface; }
-
-void ObjCClass::setInterface(bool isInterface)
-{ _isInterface = isInterface; }
-
-bool ObjCClass::isCategory() const
-{ return _categoryName != nullptr; }
-
-const Name *ObjCClass::categoryName() const
-{ return _categoryName; }
-
-void ObjCClass::setCategoryName(const Name *categoryName)
-{ _categoryName = categoryName; }
-
-ObjCBaseClass *ObjCClass::baseClass() const
-{ return _baseClass; }
-
-void ObjCClass::setBaseClass(ObjCBaseClass *baseClass)
-{ _baseClass = baseClass; }
-
int ObjCClass::protocolCount() const
{ return int(_protocols.size()); }
@@ -1043,9 +773,6 @@ ObjCProtocol::ObjCProtocol(Clone *clone, Subst *subst, ObjCProtocol *original)
addProtocol(clone->symbol(original->_protocols.at(i), subst)->asObjCBaseProtocol());
}
-ObjCProtocol::~ObjCProtocol()
-{}
-
int ObjCProtocol::protocolCount() const
{ return int(_protocols.size()); }
@@ -1087,9 +814,6 @@ ObjCForwardClassDeclaration::ObjCForwardClassDeclaration(Clone *clone, Subst *su
: Symbol(clone, subst, original)
{ }
-ObjCForwardClassDeclaration::~ObjCForwardClassDeclaration()
-{}
-
FullySpecifiedType ObjCForwardClassDeclaration::type() const
{ return FullySpecifiedType(); }
@@ -1117,9 +841,6 @@ ObjCForwardProtocolDeclaration::ObjCForwardProtocolDeclaration(Clone *clone, Sub
: Symbol(clone, subst, original)
{ }
-ObjCForwardProtocolDeclaration::~ObjCForwardProtocolDeclaration()
-{}
-
FullySpecifiedType ObjCForwardProtocolDeclaration::type() const
{ return FullySpecifiedType(); }
@@ -1148,9 +869,6 @@ ObjCMethod::ObjCMethod(Clone *clone, Subst *subst, ObjCMethod *original)
, _flags(original->_flags)
{ }
-ObjCMethod::~ObjCMethod()
-{ }
-
void ObjCMethod::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }
@@ -1165,12 +883,6 @@ bool ObjCMethod::match0(const Type *otherType, Matcher *matcher) const
FullySpecifiedType ObjCMethod::type() const
{ return FullySpecifiedType(const_cast<ObjCMethod *>(this)); }
-FullySpecifiedType ObjCMethod::returnType() const
-{ return _returnType; }
-
-void ObjCMethod::setReturnType(const FullySpecifiedType &returnType)
-{ _returnType = returnType; }
-
bool ObjCMethod::hasReturnType() const
{
const FullySpecifiedType ty = returnType();
@@ -1180,7 +892,7 @@ bool ObjCMethod::hasReturnType() const
int ObjCMethod::argumentCount() const
{
const int c = memberCount();
- if (c > 0 && memberAt(c - 1)->isBlock())
+ if (c > 0 && memberAt(c - 1)->asBlock())
return c - 1;
return c;
}
@@ -1196,12 +908,6 @@ bool ObjCMethod::hasArguments() const
(argumentCount() == 1 && argumentAt(0)->type()->isVoidType()));
}
-bool ObjCMethod::isVariadic() const
-{ return f._isVariadic; }
-
-void ObjCMethod::setVariadic(bool isVariadic)
-{ f._isVariadic = isVariadic; }
-
void ObjCMethod::visitSymbol0(SymbolVisitor *visitor)
{
if (visitor->visit(this)) {
@@ -1228,39 +934,6 @@ ObjCPropertyDeclaration::ObjCPropertyDeclaration(Clone *clone, Subst *subst, Obj
, _propertyAttributes(original->_propertyAttributes)
{ }
-ObjCPropertyDeclaration::~ObjCPropertyDeclaration()
-{}
-
-bool ObjCPropertyDeclaration::hasAttribute(int attribute) const
-{ return _propertyAttributes & attribute; }
-
-void ObjCPropertyDeclaration::setAttributes(int attributes)
-{ _propertyAttributes = attributes; }
-
-bool ObjCPropertyDeclaration::hasGetter() const
-{ return hasAttribute(Getter); }
-
-bool ObjCPropertyDeclaration::hasSetter() const
-{ return hasAttribute(Setter); }
-
-const Name *ObjCPropertyDeclaration::getterName() const
-{ return _getterName; }
-
-void ObjCPropertyDeclaration::setGetterName(const Name *getterName)
-{ _getterName = getterName; }
-
-const Name *ObjCPropertyDeclaration::setterName() const
-{ return _setterName; }
-
-void ObjCPropertyDeclaration::setSetterName(const Name *setterName)
-{ _setterName = setterName; }
-
-void ObjCPropertyDeclaration::setType(const FullySpecifiedType &type)
-{ _type = type; }
-
-FullySpecifiedType ObjCPropertyDeclaration::type() const
-{ return _type; }
-
void ObjCPropertyDeclaration::visitSymbol0(SymbolVisitor *visitor)
{
if (visitor->visit(this)) {
diff --git a/src/libs/3rdparty/cplusplus/Symbols.h b/src/libs/3rdparty/cplusplus/Symbols.h
index eb926a1b860..da29692e7b1 100644
--- a/src/libs/3rdparty/cplusplus/Symbols.h
+++ b/src/libs/3rdparty/cplusplus/Symbols.h
@@ -31,64 +31,55 @@ namespace CPlusPlus {
class StringLiteral;
-class CPLUSPLUS_EXPORT UsingNamespaceDirective: public Symbol
+class CPLUSPLUS_EXPORT UsingNamespaceDirective final : public Symbol
{
public:
UsingNamespaceDirective(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
UsingNamespaceDirective(Clone *clone, Subst *subst, UsingNamespaceDirective *original);
- virtual ~UsingNamespaceDirective();
+ ~UsingNamespaceDirective() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
- const UsingNamespaceDirective *asUsingNamespaceDirective() const override
- { return this; }
-
- UsingNamespaceDirective *asUsingNamespaceDirective() override
- { return this; }
+ const UsingNamespaceDirective *asUsingNamespaceDirective() const override { return this; }
+ UsingNamespaceDirective *asUsingNamespaceDirective() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
};
-class CPLUSPLUS_EXPORT UsingDeclaration: public Symbol
+class CPLUSPLUS_EXPORT UsingDeclaration final : public Symbol
{
public:
UsingDeclaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
UsingDeclaration(Clone *clone, Subst *subst, UsingDeclaration *original);
- virtual ~UsingDeclaration();
+ ~UsingDeclaration() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
- const UsingDeclaration *asUsingDeclaration() const override
- { return this; }
-
- UsingDeclaration *asUsingDeclaration() override
- { return this; }
+ const UsingDeclaration *asUsingDeclaration() const override { return this; }
+ UsingDeclaration *asUsingDeclaration() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
};
-class CPLUSPLUS_EXPORT NamespaceAlias: public Symbol
+class CPLUSPLUS_EXPORT NamespaceAlias final : public Symbol
{
public:
NamespaceAlias(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
NamespaceAlias(Clone *clone, Subst *subst, NamespaceAlias *original);
- virtual ~NamespaceAlias();
+ ~NamespaceAlias() override = default;
- const Name *namespaceName() const;
- void setNamespaceName(const Name *namespaceName);
+ const Name *namespaceName() const { return _namespaceName; }
+ void setNamespaceName(const Name *namespaceName) { _namespaceName = namespaceName; }
// Symbol's interface
FullySpecifiedType type() const override;
- const NamespaceAlias *asNamespaceAlias() const override
- { return this; }
-
- NamespaceAlias *asNamespaceAlias() override
- { return this; }
+ const NamespaceAlias *asNamespaceAlias() const override { return this; }
+ NamespaceAlias *asNamespaceAlias() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -97,31 +88,25 @@ private:
const Name *_namespaceName;
};
-class CPLUSPLUS_EXPORT Declaration: public Symbol
+class CPLUSPLUS_EXPORT Declaration : public Symbol
{
public:
Declaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
Declaration(Clone *clone, Subst *subst, Declaration *original);
- virtual ~Declaration();
+ ~Declaration() override = default;
- void setType(const FullySpecifiedType &type);
- void setInitializer(StringLiteral const* initializer);
+ void setType(const FullySpecifiedType &type) { _type = type; }
+ void setInitializer(StringLiteral const* initializer) { _initializer = initializer; }
// Symbol's interface
- FullySpecifiedType type() const override;
- const StringLiteral *getInitializer() const;
+ FullySpecifiedType type() const override { return _type; }
+ const StringLiteral *getInitializer() const { return _initializer; }
- const Declaration *asDeclaration() const override
- { return this; }
+ const Declaration *asDeclaration() const override { return this; }
+ Declaration *asDeclaration() override { return this; }
- Declaration *asDeclaration() override
- { return this; }
-
- virtual EnumeratorDeclaration *asEnumeratorDeclarator()
- { return nullptr; }
-
- virtual const EnumeratorDeclaration *asEnumeratorDeclarator() const
- { return nullptr; }
+ virtual EnumeratorDeclaration *asEnumeratorDeclarator() { return nullptr; }
+ virtual const EnumeratorDeclaration *asEnumeratorDeclarator() const { return nullptr; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -131,47 +116,41 @@ private:
const StringLiteral *_initializer;
};
-class CPLUSPLUS_EXPORT EnumeratorDeclaration: public Declaration
+class CPLUSPLUS_EXPORT EnumeratorDeclaration final : public Declaration
{
public:
EnumeratorDeclaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
- virtual ~EnumeratorDeclaration();
-
- const StringLiteral *constantValue() const;
- void setConstantValue(const StringLiteral *constantValue);
+ ~EnumeratorDeclaration() override = default;
- EnumeratorDeclaration *asEnumeratorDeclarator() override
- { return this; }
+ const StringLiteral *constantValue() const { return _constantValue; }
+ void setConstantValue(const StringLiteral *constantValue) { _constantValue = constantValue; }
- const EnumeratorDeclaration *asEnumeratorDeclarator() const override
- { return this; }
+ EnumeratorDeclaration *asEnumeratorDeclarator() override { return this; }
+ const EnumeratorDeclaration *asEnumeratorDeclarator() const override { return this; }
private:
const StringLiteral *_constantValue;
};
-class CPLUSPLUS_EXPORT Argument: public Symbol
+class CPLUSPLUS_EXPORT Argument final : public Symbol
{
public:
Argument(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
Argument(Clone *clone, Subst *subst, Argument *original);
- virtual ~Argument();
+ ~Argument() override = default;
- void setType(const FullySpecifiedType &type);
+ void setType(const FullySpecifiedType &type) { _type = type; }
- bool hasInitializer() const;
+ bool hasInitializer() const { return _initializer != nullptr; }
- const StringLiteral *initializer() const;
- void setInitializer(const StringLiteral *initializer);
+ const StringLiteral *initializer() const { return _initializer; }
+ void setInitializer(const StringLiteral *initializer) { _initializer = initializer; }
// Symbol's interface
- FullySpecifiedType type() const override;
-
- const Argument *asArgument() const override
- { return this; }
+ FullySpecifiedType type() const override { return _type; }
- Argument *asArgument() override
- { return this; }
+ const Argument *asArgument() const override { return this; }
+ Argument *asArgument() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -181,25 +160,22 @@ private:
FullySpecifiedType _type;
};
-class CPLUSPLUS_EXPORT TypenameArgument: public Symbol
+class CPLUSPLUS_EXPORT TypenameArgument final : public Symbol
{
public:
TypenameArgument(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
TypenameArgument(Clone *clone, Subst *subst, TypenameArgument *original);
- virtual ~TypenameArgument();
+ ~TypenameArgument() = default;
- void setType(const FullySpecifiedType &type);
+ void setType(const FullySpecifiedType &type) { _type = type; }
void setClassDeclarator(bool isClassDecl) { _isClassDeclarator = isClassDecl; }
bool isClassDeclarator() const { return _isClassDeclarator; }
// Symbol's interface
- FullySpecifiedType type() const override;
+ FullySpecifiedType type() const override { return _type; }
- const TypenameArgument *asTypenameArgument() const override
- { return this; }
-
- TypenameArgument *asTypenameArgument() override
- { return this; }
+ const TypenameArgument *asTypenameArgument() const override { return this; }
+ TypenameArgument *asTypenameArgument() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -209,12 +185,12 @@ private:
bool _isClassDeclarator;
};
-class CPLUSPLUS_EXPORT Block: public Scope
+class CPLUSPLUS_EXPORT Block final : public Scope
{
public:
Block(TranslationUnit *translationUnit, int sourceLocation);
Block(Clone *clone, Subst *subst, Block *original);
- virtual ~Block();
+ ~Block() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
@@ -229,28 +205,22 @@ protected:
void visitSymbol0(SymbolVisitor *visitor) override;
};
-class CPLUSPLUS_EXPORT ForwardClassDeclaration: public Symbol, public Type
+class CPLUSPLUS_EXPORT ForwardClassDeclaration final : public Symbol, public Type
{
public:
ForwardClassDeclaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
ForwardClassDeclaration(Clone *clone, Subst *subst, ForwardClassDeclaration *original);
- virtual ~ForwardClassDeclaration();
+ ~ForwardClassDeclaration() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
- const ForwardClassDeclaration *asForwardClassDeclaration() const override
- { return this; }
-
- ForwardClassDeclaration *asForwardClassDeclaration() override
- { return this; }
+ const ForwardClassDeclaration *asForwardClassDeclaration() const override { return this; }
+ ForwardClassDeclaration *asForwardClassDeclaration() override { return this; }
// Type's interface
- const ForwardClassDeclaration *asForwardClassDeclarationType() const override
- { return this; }
-
- ForwardClassDeclaration *asForwardClassDeclarationType() override
- { return this; }
+ const ForwardClassDeclaration *asForwardClassDeclarationType() const override { return this; }
+ ForwardClassDeclaration *asForwardClassDeclarationType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -258,31 +228,25 @@ protected:
bool match0(const Type *otherType, Matcher *matcher) const override;
};
-class CPLUSPLUS_EXPORT Enum: public Scope, public Type
+class CPLUSPLUS_EXPORT Enum final : public Scope, public Type
{
public:
Enum(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
Enum(Clone *clone, Subst *subst, Enum *original);
- virtual ~Enum();
+ ~Enum() override = default;
- bool isScoped() const;
- void setScoped(bool scoped);
+ bool isScoped() const { return _isScoped; }
+ void setScoped(bool scoped) { _isScoped = scoped; }
// Symbol's interface
FullySpecifiedType type() const override;
- const Enum *asEnum() const override
- { return this; }
-
- Enum *asEnum() override
- { return this; }
+ const Enum *asEnum() const override { return this; }
+ Enum *asEnum() override { return this; }
// Type's interface
- const Enum *asEnumType() const override
- { return this; }
-
- Enum *asEnumType() override
- { return this; }
+ const Enum *asEnumType() const override { return this; }
+ Enum *asEnumType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -293,7 +257,7 @@ private:
bool _isScoped;
};
-class CPLUSPLUS_EXPORT Function: public Scope, public Type
+class CPLUSPLUS_EXPORT Function final : public Scope, public Type
{
public:
enum MethodKey {
@@ -312,17 +276,18 @@ public:
public:
Function(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
Function(Clone *clone, Subst *subst, Function *original);
- virtual ~Function();
+ ~Function() override = default;
+
+ bool isNormal() const { return f._methodKey == NormalMethod; }
+ bool isSignal() const { return f._methodKey == SignalMethod; }
+ bool isSlot() const { return f._methodKey == SlotMethod; }
+ bool isInvokable() const { return f._methodKey == InvokableMethod; }
- bool isNormal() const;
- bool isSignal() const;
- bool isSlot() const;
- bool isInvokable() const;
- int methodKey() const;
- void setMethodKey(int key);
+ int methodKey() const { return f._methodKey; }
+ void setMethodKey(int key) { f._methodKey = key; }
- FullySpecifiedType returnType() const;
- void setReturnType(const FullySpecifiedType &returnType);
+ FullySpecifiedType returnType() const { return _returnType; }
+ void setReturnType(const FullySpecifiedType &returnType) { _returnType = returnType; }
/** Convenience function that returns whether the function returns something (including void). */
bool hasReturnType() const;
@@ -334,61 +299,55 @@ public:
bool hasArguments() const;
int minimumArgumentCount() const;
- bool isVirtual() const;
- void setVirtual(bool isVirtual);
+ bool isVirtual() const { return f._isVirtual; }
+ void setVirtual(bool isVirtual) { f._isVirtual = isVirtual; }
- bool isOverride() const;
- void setOverride(bool isOverride);
+ bool isOverride() const { return f._isOverride; }
+ void setOverride(bool isOverride) { f._isOverride = isOverride; }
- bool isFinal() const;
- void setFinal(bool isFinal);
+ bool isFinal() const { return f._isFinal; }
+ void setFinal(bool isFinal) { f._isFinal = isFinal; }
- bool isVariadic() const;
- void setVariadic(bool isVariadic);
+ bool isVariadic() const { return f._isVariadic; }
+ void setVariadic(bool isVariadic) { f._isVariadic = isVariadic; }
- bool isVariadicTemplate() const;
- void setVariadicTemplate(bool isVariadicTemplate);
+ bool isVariadicTemplate() const { return f._isVariadicTemplate; }
+ void setVariadicTemplate(bool isVariadicTemplate) { f._isVariadicTemplate = isVariadicTemplate; }
- bool isConst() const;
- void setConst(bool isConst);
+ bool isConst() const { return f._isConst; }
+ void setConst(bool isConst) { f._isConst = isConst; }
bool isStatic() const { return f._isStatic; }
void setStatic(bool isStatic) { f._isStatic = isStatic; }
- bool isVolatile() const;
- void setVolatile(bool isVolatile);
+ bool isVolatile() const { return f._isVolatile; }
+ void setVolatile(bool isVolatile) { f._isVolatile = isVolatile; }
- bool isPureVirtual() const;
- void setPureVirtual(bool isPureVirtual);
+ bool isPureVirtual() const { return f._isPureVirtual; }
+ void setPureVirtual(bool isPureVirtual) { f._isPureVirtual = isPureVirtual; }
- RefQualifier refQualifier() const;
- void setRefQualifier(RefQualifier refQualifier);
+ RefQualifier refQualifier() const { return static_cast<RefQualifier>(f._refQualifier); }
+ void setRefQualifier(RefQualifier refQualifier) { f._refQualifier = refQualifier; }
bool isSignatureEqualTo(const Function *other, Matcher *matcher = nullptr) const;
- bool isAmbiguous() const; // internal
- void setAmbiguous(bool isAmbiguous); // internal
+ bool isAmbiguous() const { return f._isAmbiguous; } // internal
+ void setAmbiguous(bool isAmbiguous) { f._isAmbiguous = isAmbiguous; } // internal
bool maybeValidPrototype(int actualArgumentCount) const;
- const StringLiteral *exceptionSpecification();
- void setExceptionSpecification(const StringLiteral *spec);
+ const StringLiteral *exceptionSpecification() { return _exceptionSpecification; }
+ void setExceptionSpecification(const StringLiteral *spec) { _exceptionSpecification = spec; }
// Symbol's interface
FullySpecifiedType type() const override;
- const Function *asFunction() const override
- { return this; }
-
- Function *asFunction() override
- { return this; }
+ const Function *asFunction() const override { return this; }
+ Function *asFunction() override { return this; }
// Type's interface
- const Function *asFunctionType() const override
- { return this; }
-
- Function *asFunctionType() override
- { return this; }
+ const Function *asFunctionType() const override { return this; }
+ Function *asFunctionType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -418,32 +377,26 @@ private:
};
};
-class CPLUSPLUS_EXPORT Template: public Scope, public Type
+class CPLUSPLUS_EXPORT Template final : public Scope, public Type
{
public:
Template(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
Template(Clone *clone, Subst *subst, Template *original);
- virtual ~Template();
+ ~Template() override = default;
int templateParameterCount() const;
- Symbol *templateParameterAt(int index) const;
+ Symbol *templateParameterAt(int index) const { return memberAt(index); }
Symbol *declaration() const;
// Symbol's interface
FullySpecifiedType type() const override;
- const Template *asTemplate() const override
- { return this; }
-
- Template *asTemplate() override
- { return this; }
+ const Template *asTemplate() const override { return this; }
+ Template *asTemplate() override { return this; }
// Type's interface
- const Template *asTemplateType() const override
- { return this; }
-
- Template *asTemplateType() override
- { return this; }
+ const Template *asTemplateType() const override { return this; }
+ Template *asTemplateType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -452,34 +405,25 @@ protected:
};
-class CPLUSPLUS_EXPORT Namespace: public Scope, public Type
+class CPLUSPLUS_EXPORT Namespace final : public Scope, public Type
{
public:
Namespace(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
Namespace(Clone *clone, Subst *subst, Namespace *original);
- virtual ~Namespace();
+ ~Namespace() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
- const Namespace *asNamespace() const override
- { return this; }
-
- Namespace *asNamespace() override
- { return this; }
+ const Namespace *asNamespace() const override { return this; }
+ Namespace *asNamespace() override { return this; }
// Type's interface
- const Namespace *asNamespaceType() const override
- { return this; }
-
- Namespace *asNamespaceType() override
- { return this; }
+ const Namespace *asNamespaceType() const override { return this; }
+ Namespace *asNamespaceType() override { return this; }
- bool isInline() const
- { return _isInline; }
-
- void setInline(bool onoff)
- { _isInline = onoff; }
+ bool isInline() const { return _isInline; }
+ void setInline(bool onoff) { _isInline = onoff; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -490,28 +434,25 @@ private:
bool _isInline;
};
-class CPLUSPLUS_EXPORT BaseClass: public Symbol
+class CPLUSPLUS_EXPORT BaseClass final : public Symbol
{
public:
BaseClass(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
BaseClass(Clone *clone, Subst *subst, BaseClass *original);
- virtual ~BaseClass();
+ ~BaseClass() override = default;
- bool isVirtual() const;
- void setVirtual(bool isVirtual);
+ bool isVirtual() const { return _isVirtual; }
+ void setVirtual(bool isVirtual) { _isVirtual = isVirtual; }
- bool isVariadic() const;
- void setVariadic(bool isVariadic);
+ bool isVariadic() const { return _isVariadic; }
+ void setVariadic(bool isVariadic) { _isVariadic = isVariadic; }
// Symbol's interface
- FullySpecifiedType type() const override;
- void setType(const FullySpecifiedType &type);
-
- const BaseClass *asBaseClass() const override
- { return this; }
+ FullySpecifiedType type() const override { return _type; }
+ void setType(const FullySpecifiedType &type) { _type = type; }
- BaseClass *asBaseClass() override
- { return this; }
+ const BaseClass *asBaseClass() const override { return this; }
+ BaseClass *asBaseClass() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -522,12 +463,12 @@ private:
FullySpecifiedType _type;
};
-class CPLUSPLUS_EXPORT Class: public Scope, public Type
+class CPLUSPLUS_EXPORT Class final : public Scope, public Type
{
public:
Class(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
Class(Clone *clone, Subst *subst, Class *original);
- virtual ~Class();
+ ~Class() override = default;
enum Key {
ClassKey,
@@ -535,11 +476,12 @@ public:
UnionKey
};
- bool isClass() const;
- bool isStruct() const;
- bool isUnion() const;
- Key classKey() const;
- void setClassKey(Key key);
+ bool isClass() const { return _key == ClassKey; }
+ bool isStruct() const { return _key == StructKey; }
+ bool isUnion() const { return _key == UnionKey; }
+
+ Key classKey() const { return _key; }
+ void setClassKey(Key key) { _key = key; }
int baseClassCount() const;
BaseClass *baseClassAt(int index) const;
@@ -549,18 +491,12 @@ public:
// Symbol's interface
FullySpecifiedType type() const override;
- const Class *asClass() const override
- { return this; }
-
- Class *asClass() override
- { return this; }
+ const Class *asClass() const override { return this; }
+ Class *asClass() override { return this; }
// Type's interface
- const Class *asClassType() const override
- { return this; }
-
- Class *asClassType() override
- { return this; }
+ const Class *asClassType() const override { return this; }
+ Class *asClassType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -572,7 +508,7 @@ private:
std::vector<BaseClass *> _baseClasses;
};
-class CPLUSPLUS_EXPORT QtPropertyDeclaration: public Symbol
+class CPLUSPLUS_EXPORT QtPropertyDeclaration final : public Symbol
{
public:
enum Flag {
@@ -597,21 +533,17 @@ public:
public:
QtPropertyDeclaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
QtPropertyDeclaration(Clone *clone, Subst *subst, QtPropertyDeclaration *original);
- virtual ~QtPropertyDeclaration();
-
- void setType(const FullySpecifiedType &type);
+ ~QtPropertyDeclaration() = default;
- void setFlags(int flags);
- int flags() const;
+ void setType(const FullySpecifiedType &type) { _type = type; }
+ void setFlags(int flags) { _flags = flags; }
+ int flags() const { return _flags; }
// Symbol's interface
- FullySpecifiedType type() const override;
+ FullySpecifiedType type() const override { return _type; }
- const QtPropertyDeclaration *asQtPropertyDeclaration() const override
- { return this; }
-
- QtPropertyDeclaration *asQtPropertyDeclaration() override
- { return this; }
+ const QtPropertyDeclaration *asQtPropertyDeclaration() const override { return this; }
+ QtPropertyDeclaration *asQtPropertyDeclaration() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -621,88 +553,73 @@ private:
int _flags;
};
-class CPLUSPLUS_EXPORT QtEnum: public Symbol
+class CPLUSPLUS_EXPORT QtEnum final : public Symbol
{
public:
QtEnum(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
QtEnum(Clone *clone, Subst *subst, QtEnum *original);
- virtual ~QtEnum();
+ ~QtEnum() override = default;
// Symbol's interface
- FullySpecifiedType type() const override;
+ FullySpecifiedType type() const override { return FullySpecifiedType(); }
- const QtEnum *asQtEnum() const override
- { return this; }
-
- QtEnum *asQtEnum() override
- { return this; }
+ const QtEnum *asQtEnum() const override { return this; }
+ QtEnum *asQtEnum() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
};
-class CPLUSPLUS_EXPORT ObjCBaseClass: public Symbol
+class CPLUSPLUS_EXPORT ObjCBaseClass final : public Symbol
{
public:
ObjCBaseClass(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
ObjCBaseClass(Clone *clone, Subst *subst, ObjCBaseClass *original);
- virtual ~ObjCBaseClass();
+ ~ObjCBaseClass() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
- const ObjCBaseClass *asObjCBaseClass() const override
- { return this; }
-
- ObjCBaseClass *asObjCBaseClass() override
- { return this; }
+ const ObjCBaseClass *asObjCBaseClass() const override { return this; }
+ ObjCBaseClass *asObjCBaseClass() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
};
-class CPLUSPLUS_EXPORT ObjCBaseProtocol: public Symbol
+class CPLUSPLUS_EXPORT ObjCBaseProtocol final : public Symbol
{
public:
ObjCBaseProtocol(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
ObjCBaseProtocol(Clone *clone, Subst *subst, ObjCBaseProtocol *original);
- virtual ~ObjCBaseProtocol();
+ ~ObjCBaseProtocol() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
- const ObjCBaseProtocol *asObjCBaseProtocol() const override
- { return this; }
-
- ObjCBaseProtocol *asObjCBaseProtocol() override
- { return this; }
+ const ObjCBaseProtocol *asObjCBaseProtocol() const override { return this; }
+ ObjCBaseProtocol *asObjCBaseProtocol() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
};
-class CPLUSPLUS_EXPORT ObjCForwardProtocolDeclaration: public Symbol, public Type
+class CPLUSPLUS_EXPORT ObjCForwardProtocolDeclaration final : public Symbol, public Type
{
public:
ObjCForwardProtocolDeclaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
ObjCForwardProtocolDeclaration(Clone *clone, Subst *subst, ObjCForwardProtocolDeclaration *original);
- virtual ~ObjCForwardProtocolDeclaration();
+ ~ObjCForwardProtocolDeclaration() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
- const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() const override
- { return this; }
-
- ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() override
- { return this; }
+ const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() const override { return this; }
+ ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() override { return this; }
// Type's interface
- const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() const override
- { return this; }
-
- ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() override
- { return this; }
+ const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() const override { return this; }
+ ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -710,12 +627,12 @@ protected:
bool match0(const Type *otherType, Matcher *matcher) const override;
};
-class CPLUSPLUS_EXPORT ObjCProtocol: public Scope, public Type
+class CPLUSPLUS_EXPORT ObjCProtocol final : public Scope, public Type
{
public:
ObjCProtocol(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
ObjCProtocol(Clone *clone, Subst *subst, ObjCProtocol *original);
- virtual ~ObjCProtocol();
+ ~ObjCProtocol() override = default;
int protocolCount() const;
ObjCBaseProtocol *protocolAt(int index) const;
@@ -724,18 +641,12 @@ public:
// Symbol's interface
FullySpecifiedType type() const override;
- const ObjCProtocol *asObjCProtocol() const override
- { return this; }
-
- ObjCProtocol *asObjCProtocol() override
- { return this; }
+ const ObjCProtocol *asObjCProtocol() const override { return this; }
+ ObjCProtocol *asObjCProtocol() override { return this; }
// Type's interface
- const ObjCProtocol *asObjCProtocolType() const override
- { return this; }
-
- ObjCProtocol *asObjCProtocolType() override
- { return this; }
+ const ObjCProtocol *asObjCProtocolType() const override { return this; }
+ ObjCProtocol *asObjCProtocolType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -746,28 +657,22 @@ private:
std::vector<ObjCBaseProtocol *> _protocols;
};
-class CPLUSPLUS_EXPORT ObjCForwardClassDeclaration: public Symbol, public Type
+class CPLUSPLUS_EXPORT ObjCForwardClassDeclaration final : public Symbol, public Type
{
public:
ObjCForwardClassDeclaration(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
ObjCForwardClassDeclaration(Clone *clone, Subst *subst, ObjCForwardClassDeclaration *original);
- virtual ~ObjCForwardClassDeclaration();
+ ~ObjCForwardClassDeclaration() override = default;
// Symbol's interface
FullySpecifiedType type() const override;
- const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const override
- { return this; }
-
- ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() override
- { return this; }
+ const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const override { return this; }
+ ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() override { return this; }
// Type's interface
- const ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() const override
- { return this; }
-
- ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() override
- { return this; }
+ const ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() const override { return this; }
+ ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -775,22 +680,22 @@ protected:
bool match0(const Type *otherType, Matcher *matcher) const override;
};
-class CPLUSPLUS_EXPORT ObjCClass: public Scope, public Type
+class CPLUSPLUS_EXPORT ObjCClass final : public Scope, public Type
{
public:
ObjCClass(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
ObjCClass(Clone *clone, Subst *subst, ObjCClass *original);
- virtual ~ObjCClass();
+ ~ObjCClass() override = default;
- bool isInterface() const;
- void setInterface(bool isInterface);
+ bool isInterface() const { return _isInterface; }
+ void setInterface(bool isInterface) { _isInterface = isInterface; }
- bool isCategory() const;
- const Name *categoryName() const;
- void setCategoryName(const Name *categoryName);
+ bool isCategory() const { return _categoryName != nullptr; }
+ const Name *categoryName() const { return _categoryName; }
+ void setCategoryName(const Name *categoryName) { _categoryName = categoryName; }
- ObjCBaseClass *baseClass() const;
- void setBaseClass(ObjCBaseClass *baseClass);
+ ObjCBaseClass *baseClass() const { return _baseClass; }
+ void setBaseClass(ObjCBaseClass *baseClass) { _baseClass = baseClass; }
int protocolCount() const;
ObjCBaseProtocol *protocolAt(int index) const;
@@ -799,18 +704,12 @@ public:
// Symbol's interface
FullySpecifiedType type() const override;
- const ObjCClass *asObjCClass() const override
- { return this; }
-
- ObjCClass *asObjCClass() override
- { return this; }
+ const ObjCClass *asObjCClass() const override { return this; }
+ ObjCClass *asObjCClass() override { return this; }
// Type's interface
- const ObjCClass *asObjCClassType() const override
- { return this; }
-
- ObjCClass *asObjCClassType() override
- { return this; }
+ const ObjCClass *asObjCClassType() const override { return this; }
+ ObjCClass *asObjCClassType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -824,15 +723,15 @@ private:
bool _isInterface;
};
-class CPLUSPLUS_EXPORT ObjCMethod: public Scope, public Type
+class CPLUSPLUS_EXPORT ObjCMethod final : public Scope, public Type
{
public:
ObjCMethod(TranslationUnit *translationUnit, int sourceLocation, const Name *name);
ObjCMethod(Clone *clone, Subst *subst, ObjCMethod *original);
- virtual ~ObjCMethod();
+ ~ObjCMethod() override = default;
- FullySpecifiedType returnType() const;
- void setReturnType(const FullySpecifiedType &returnType);
+ FullySpecifiedType returnType() const { return _returnType; }
+ void setReturnType(const FullySpecifiedType &returnType) { _returnType = returnType; }
/** Convenience function that returns whether the function returns something (including void). */
bool hasReturnType() const;
@@ -843,24 +742,18 @@ public:
/** Convenience function that returns whether the function receives any arguments. */
bool hasArguments() const;
- bool isVariadic() const;
- void setVariadic(bool isVariadic);
+ bool isVariadic() const { return f._isVariadic; }
+ void setVariadic(bool isVariadic) { f._isVariadic = isVariadic; }
// Symbol's interface
FullySpecifiedType type() const override;
- const ObjCMethod *asObjCMethod() const override
- { return this; }
-
- ObjCMethod *asObjCMethod() override
- { return this; }
+ const ObjCMethod *asObjCMethod() const override { return this; }
+ ObjCMethod *asObjCMethod() override { return this; }
// Type's interface
- const ObjCMethod *asObjCMethodType() const override
- { return this; }
-
- ObjCMethod *asObjCMethodType() override
- { return this; }
+ const ObjCMethod *asObjCMethodType() const override { return this; }
+ ObjCMethod *asObjCMethodType() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
@@ -878,7 +771,7 @@ private:
};
};
-class CPLUSPLUS_EXPORT ObjCPropertyDeclaration: public Symbol
+class CPLUSPLUS_EXPORT ObjCPropertyDeclaration final : public Symbol
{
public:
enum PropertyAttributes {
@@ -901,31 +794,27 @@ public:
int sourceLocation,
const Name *name);
ObjCPropertyDeclaration(Clone *clone, Subst *subst, ObjCPropertyDeclaration *original);
- virtual ~ObjCPropertyDeclaration();
+ ~ObjCPropertyDeclaration() override = default;
- bool hasAttribute(int attribute) const;
- void setAttributes(int attributes);
+ bool hasAttribute(int attribute) const { return _propertyAttributes & attribute; }
+ void setAttributes(int attributes) { _propertyAttributes = attributes; }
- bool hasGetter() const;
- bool hasSetter() const;
+ bool hasGetter() const { return hasAttribute(Getter); }
+ bool hasSetter() const { return hasAttribute(Setter); }
- const Name *getterName() const;
+ const Name *getterName() const { return _getterName; }
+ void setGetterName(const Name *getterName) { _getterName = getterName; }
- void setGetterName(const Name *getterName);
+ const Name *setterName() const { return _setterName; }
+ void setSetterName(const Name *setterName) { _setterName = setterName; }
- const Name *setterName() const;
- void setSetterName(const Name *setterName);
-
- void setType(const FullySpecifiedType &type);
+ void setType(const FullySpecifiedType &type) { _type = type; }
// Symbol's interface
- FullySpecifiedType type() const override;
+ FullySpecifiedType type() const override { return _type; }
- const ObjCPropertyDeclaration *asObjCPropertyDeclaration() const override
- { return this; }
-
- ObjCPropertyDeclaration *asObjCPropertyDeclaration() override
- { return this; }
+ const ObjCPropertyDeclaration *asObjCPropertyDeclaration() const override { return this; }
+ ObjCPropertyDeclaration *asObjCPropertyDeclaration() override { return this; }
protected:
void visitSymbol0(SymbolVisitor *visitor) override;
diff --git a/src/libs/3rdparty/cplusplus/Type.cpp b/src/libs/3rdparty/cplusplus/Type.cpp
index e9b0f2d3c17..00e84b0a61c 100644
--- a/src/libs/3rdparty/cplusplus/Type.cpp
+++ b/src/libs/3rdparty/cplusplus/Type.cpp
@@ -33,7 +33,7 @@ Type::~Type()
{ }
bool Type::isUndefinedType() const
-{ return this == UndefinedType::instance(); }
+{ return this == &UndefinedType::instance; }
bool Type::isVoidType() const
{ return asVoidType() != nullptr; }
diff --git a/src/libs/3rdparty/sqlite/carray.c b/src/libs/3rdparty/sqlite/carray.c
index b8cda21bc73..e38f2614be6 100644
--- a/src/libs/3rdparty/sqlite/carray.c
+++ b/src/libs/3rdparty/sqlite/carray.c
@@ -52,6 +52,7 @@
** as the number of elements in the array. The virtual table steps through
** the array, element by element.
*/
+#include "config.h"
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
diff --git a/src/libs/3rdparty/sqlite/config.h b/src/libs/3rdparty/sqlite/config.h
index f1463dc31b6..236ca49d1d8 100644
--- a/src/libs/3rdparty/sqlite/config.h
+++ b/src/libs/3rdparty/sqlite/config.h
@@ -85,3 +85,284 @@
#define SQLITE_OMIT_TRACE 1
#define SQLITE_DEFAULT_LOCKING_MODE 1
#define SQLITE_WIN32_GETVERSIONEX 0
+
+#ifdef SQLITE_STATIC_LIBRARY
+ // Make sure to avoid any other sqlite3 static libraries symbols present in the project
+ #define sqlite3_aggregate_context qtc_sqlite3_aggregate_context
+ #define sqlite3_auto_extension qtc_sqlite3_auto_extension
+ #define sqlite3_autovacuum_pages qtc_sqlite3_autovacuum_pages
+ #define sqlite3_backup_finish qtc_sqlite3_backup_finish
+ #define sqlite3_backup_init qtc_sqlite3_backup_init
+ #define sqlite3_backup_pagecount qtc_sqlite3_backup_pagecount
+ #define sqlite3_backup_remaining qtc_sqlite3_backup_remaining
+ #define sqlite3_backup_step qtc_sqlite3_backup_step
+ #define sqlite3_bind_blob qtc_sqlite3_bind_blob
+ #define sqlite3_bind_blob64 qtc_sqlite3_bind_blob64
+ #define sqlite3_bind_double qtc_sqlite3_bind_double
+ #define sqlite3_bind_int qtc_sqlite3_bind_int
+ #define sqlite3_bind_int64 qtc_sqlite3_bind_int64
+ #define sqlite3_bind_null qtc_sqlite3_bind_null
+ #define sqlite3_bind_parameter_count qtc_sqlite3_bind_parameter_count
+ #define sqlite3_bind_parameter_index qtc_sqlite3_bind_parameter_index
+ #define sqlite3_bind_parameter_name qtc_sqlite3_bind_parameter_name
+ #define sqlite3_bind_pointer qtc_sqlite3_bind_pointer
+ #define sqlite3_bind_text qtc_sqlite3_bind_text
+ #define sqlite3_bind_text64 qtc_sqlite3_bind_text64
+ #define sqlite3_bind_value qtc_sqlite3_bind_value
+ #define sqlite3_bind_zeroblob qtc_sqlite3_bind_zeroblob
+ #define sqlite3_bind_zeroblob64 qtc_sqlite3_bind_zeroblob64
+ #define sqlite3_blob_bytes qtc_sqlite3_blob_bytes
+ #define sqlite3_blob_close qtc_sqlite3_blob_close
+ #define sqlite3_blob_open qtc_sqlite3_blob_open
+ #define sqlite3_blob_read qtc_sqlite3_blob_read
+ #define sqlite3_blob_reopen qtc_sqlite3_blob_reopen
+ #define sqlite3_blob_write qtc_sqlite3_blob_write
+ #define sqlite3_busy_handler qtc_sqlite3_busy_handler
+ #define sqlite3_busy_timeout qtc_sqlite3_busy_timeout
+ #define sqlite3_cancel_auto_extension qtc_sqlite3_cancel_auto_extension
+ #define sqlite3_changes qtc_sqlite3_changes
+ #define sqlite3_changes64 qtc_sqlite3_changes64
+ #define sqlite3_clear_bindings qtc_sqlite3_clear_bindings
+ #define sqlite3_close qtc_sqlite3_close
+ #define sqlite3_close_v2 qtc_sqlite3_close_v2
+ #define sqlite3_collation_needed qtc_sqlite3_collation_needed
+ #define sqlite3_column_blob qtc_sqlite3_column_blob
+ #define sqlite3_column_bytes qtc_sqlite3_column_bytes
+ #define sqlite3_column_bytes16 qtc_sqlite3_column_bytes16
+ #define sqlite3_column_count qtc_sqlite3_column_count
+ #define sqlite3_column_double qtc_sqlite3_column_double
+ #define sqlite3_column_int qtc_sqlite3_column_int
+ #define sqlite3_column_int64 qtc_sqlite3_column_int64
+ #define sqlite3_column_name qtc_sqlite3_column_name
+ #define sqlite3_column_text qtc_sqlite3_column_text
+ #define sqlite3_column_type qtc_sqlite3_column_type
+ #define sqlite3_column_value qtc_sqlite3_column_value
+ #define sqlite3_commit_hook qtc_sqlite3_commit_hook
+ #define sqlite3_compileoption_get qtc_sqlite3_compileoption_get
+ #define sqlite3_compileoption_used qtc_sqlite3_compileoption_used
+ #define sqlite3_config qtc_sqlite3_config
+ #define sqlite3_context_db_handle qtc_sqlite3_context_db_handle
+ #define sqlite3_create_collation qtc_sqlite3_create_collation
+ #define sqlite3_create_collation_v2 qtc_sqlite3_create_collation_v2
+ #define sqlite3_create_filename qtc_sqlite3_create_filename
+ #define sqlite3_create_function qtc_sqlite3_create_function
+ #define sqlite3_create_function_v2 qtc_sqlite3_create_function_v2
+ #define sqlite3_create_module qtc_sqlite3_create_module
+ #define sqlite3_create_module_v2 qtc_sqlite3_create_module_v2
+ #define sqlite3_create_window_function qtc_sqlite3_create_window_function
+ #define sqlite3_data_count qtc_sqlite3_data_count
+ #define sqlite3_database_file_object qtc_sqlite3_database_file_object
+ #define sqlite3_db_cacheflush qtc_sqlite3_db_cacheflush
+ #define sqlite3_db_config qtc_sqlite3_db_config
+ #define sqlite3_db_filename qtc_sqlite3_db_filename
+ #define sqlite3_db_handle qtc_sqlite3_db_handle
+ #define sqlite3_db_mutex qtc_sqlite3_db_mutex
+ #define sqlite3_db_readonly qtc_sqlite3_db_readonly
+ #define sqlite3_db_release_memory qtc_sqlite3_db_release_memory
+ #define sqlite3_db_status qtc_sqlite3_db_status
+ #define sqlite3_declare_vtab qtc_sqlite3_declare_vtab
+ #define sqlite3_deserialize qtc_sqlite3_deserialize
+ #define sqlite3_drop_modules qtc_sqlite3_drop_modules
+ #define sqlite3_errcode qtc_sqlite3_errcode
+ #define sqlite3_errmsg qtc_sqlite3_errmsg
+ #define sqlite3_errstr qtc_sqlite3_errstr
+ #define sqlite3_exec qtc_sqlite3_exec
+ #define sqlite3_expanded_sql qtc_sqlite3_expanded_sql
+ #define sqlite3_extended_errcode qtc_sqlite3_extended_errcode
+ #define sqlite3_extended_result_codes qtc_sqlite3_extended_result_codes
+ #define sqlite3_file_control qtc_sqlite3_file_control
+ #define sqlite3_filename_database qtc_sqlite3_filename_database
+ #define sqlite3_filename_journal qtc_sqlite3_filename_journal
+ #define sqlite3_filename_wal qtc_sqlite3_filename_wal
+ #define sqlite3_finalize qtc_sqlite3_finalize
+ #define sqlite3_free qtc_sqlite3_free
+ #define sqlite3_free_filename qtc_sqlite3_free_filename
+ #define sqlite3_free_table qtc_sqlite3_free_table
+ #define sqlite3_get_autocommit qtc_sqlite3_get_autocommit
+ #define sqlite3_get_auxdata qtc_sqlite3_get_auxdata
+ #define sqlite3_get_table qtc_sqlite3_get_table
+ #define sqlite3_hard_heap_limit64 qtc_sqlite3_hard_heap_limit64
+ #define sqlite3_initialize qtc_sqlite3_initialize
+ #define sqlite3_interrupt qtc_sqlite3_interrupt
+ #define sqlite3_keyword_check qtc_sqlite3_keyword_check
+ #define sqlite3_keyword_count qtc_sqlite3_keyword_count
+ #define sqlite3_keyword_name qtc_sqlite3_keyword_name
+ #define sqlite3_last_insert_rowid qtc_sqlite3_last_insert_rowid
+ #define sqlite3_libversion qtc_sqlite3_libversion
+ #define sqlite3_libversion_number qtc_sqlite3_libversion_number
+ #define sqlite3_limit qtc_sqlite3_limit
+ #define sqlite3_log qtc_sqlite3_log
+ #define sqlite3_malloc qtc_sqlite3_malloc
+ #define sqlite3_malloc64 qtc_sqlite3_malloc64
+ #define sqlite3_memory_highwater qtc_sqlite3_memory_highwater
+ #define sqlite3_memory_used qtc_sqlite3_memory_used
+ #define sqlite3_mprintf qtc_sqlite3_mprintf
+ #define sqlite3_msize qtc_sqlite3_msize
+ #define sqlite3_mutex_alloc qtc_sqlite3_mutex_alloc
+ #define sqlite3_mutex_enter qtc_sqlite3_mutex_enter
+ #define sqlite3_mutex_free qtc_sqlite3_mutex_free
+ #define sqlite3_mutex_leave qtc_sqlite3_mutex_leave
+ #define sqlite3_mutex_try qtc_sqlite3_mutex_try
+ #define sqlite3_next_stmt qtc_sqlite3_next_stmt
+ #define sqlite3_open qtc_sqlite3_open
+ #define sqlite3_open_v2 qtc_sqlite3_open_v2
+ #define sqlite3_os_end qtc_sqlite3_os_end
+ #define sqlite3_os_init qtc_sqlite3_os_init
+ #define sqlite3_overload_function qtc_sqlite3_overload_function
+ #define sqlite3_prepare qtc_sqlite3_prepare
+ #define sqlite3_prepare_v2 qtc_sqlite3_prepare_v2
+ #define sqlite3_prepare_v3 qtc_sqlite3_prepare_v3
+ #define sqlite3_progress_handler qtc_sqlite3_progress_handler
+ #define sqlite3_randomness qtc_sqlite3_randomness
+ #define sqlite3_realloc qtc_sqlite3_realloc
+ #define sqlite3_realloc64 qtc_sqlite3_realloc64
+ #define sqlite3_release_memory qtc_sqlite3_release_memory
+ #define sqlite3_reset qtc_sqlite3_reset
+ #define sqlite3_reset_auto_extension qtc_sqlite3_reset_auto_extension
+ #define sqlite3_result_blob qtc_sqlite3_result_blob
+ #define sqlite3_result_blob64 qtc_sqlite3_result_blob64
+ #define sqlite3_result_double qtc_sqlite3_result_double
+ #define sqlite3_result_error qtc_sqlite3_result_error
+ #define sqlite3_result_error_code qtc_sqlite3_result_error_code
+ #define sqlite3_result_error_nomem qtc_sqlite3_result_error_nomem
+ #define sqlite3_result_error_toobig qtc_sqlite3_result_error_toobig
+ #define sqlite3_result_int qtc_sqlite3_result_int
+ #define sqlite3_result_int64 qtc_sqlite3_result_int64
+ #define sqlite3_result_null qtc_sqlite3_result_null
+ #define sqlite3_result_pointer qtc_sqlite3_result_pointer
+ #define sqlite3_result_subtype qtc_sqlite3_result_subtype
+ #define sqlite3_result_text qtc_sqlite3_result_text
+ #define sqlite3_result_text64 qtc_sqlite3_result_text64
+ #define sqlite3_result_value qtc_sqlite3_result_value
+ #define sqlite3_result_zeroblob qtc_sqlite3_result_zeroblob
+ #define sqlite3_result_zeroblob64 qtc_sqlite3_result_zeroblob64
+ #define sqlite3_rollback_hook qtc_sqlite3_rollback_hook
+ #define sqlite3_serialize qtc_sqlite3_serialize
+ #define sqlite3_set_authorizer qtc_sqlite3_set_authorizer
+ #define sqlite3_set_auxdata qtc_sqlite3_set_auxdata
+ #define sqlite3_set_last_insert_rowid qtc_sqlite3_set_last_insert_rowid
+ #define sqlite3_shutdown qtc_sqlite3_shutdown
+ #define sqlite3_sleep qtc_sqlite3_sleep
+ #define sqlite3_snprintf qtc_sqlite3_snprintf
+ #define sqlite3_soft_heap_limit qtc_sqlite3_soft_heap_limit
+ #define sqlite3_soft_heap_limit64 qtc_sqlite3_soft_heap_limit64
+ #define sqlite3_sourceid qtc_sqlite3_sourceid
+ #define sqlite3_sql qtc_sqlite3_sql
+ #define sqlite3_status qtc_sqlite3_status
+ #define sqlite3_status64 qtc_sqlite3_status64
+ #define sqlite3_step qtc_sqlite3_step
+ #define sqlite3_stmt_busy qtc_sqlite3_stmt_busy
+ #define sqlite3_stmt_isexplain qtc_sqlite3_stmt_isexplain
+ #define sqlite3_stmt_readonly qtc_sqlite3_stmt_readonly
+ #define sqlite3_stmt_status qtc_sqlite3_stmt_status
+ #define sqlite3_str_append qtc_sqlite3_str_append
+ #define sqlite3_str_appendall qtc_sqlite3_str_appendall
+ #define sqlite3_str_appendchar qtc_sqlite3_str_appendchar
+ #define sqlite3_str_appendf qtc_sqlite3_str_appendf
+ #define sqlite3_str_errcode qtc_sqlite3_str_errcode
+ #define sqlite3_str_finish qtc_sqlite3_str_finish
+ #define sqlite3_str_length qtc_sqlite3_str_length
+ #define sqlite3_str_new qtc_sqlite3_str_new
+ #define sqlite3_str_reset qtc_sqlite3_str_reset
+ #define sqlite3_str_value qtc_sqlite3_str_value
+ #define sqlite3_str_vappendf qtc_sqlite3_str_vappendf
+ #define sqlite3_strglob qtc_sqlite3_strglob
+ #define sqlite3_stricmp qtc_sqlite3_stricmp
+ #define sqlite3_strlike qtc_sqlite3_strlike
+ #define sqlite3_strnicmp qtc_sqlite3_strnicmp
+ #define sqlite3_system_errno qtc_sqlite3_system_errno
+ #define sqlite3_table_column_metadata qtc_sqlite3_table_column_metadata
+ #define sqlite3_test_control qtc_sqlite3_test_control
+ #define sqlite3_threadsafe qtc_sqlite3_threadsafe
+ #define sqlite3_total_changes qtc_sqlite3_total_changes
+ #define sqlite3_total_changes64 qtc_sqlite3_total_changes64
+ #define sqlite3_txn_state qtc_sqlite3_txn_state
+ #define sqlite3_unlock_notify qtc_sqlite3_unlock_notify
+ #define sqlite3_update_hook qtc_sqlite3_update_hook
+ #define sqlite3_uri_boolean qtc_sqlite3_uri_boolean
+ #define sqlite3_uri_int64 qtc_sqlite3_uri_int64
+ #define sqlite3_uri_key qtc_sqlite3_uri_key
+ #define sqlite3_uri_parameter qtc_sqlite3_uri_parameter
+ #define sqlite3_user_data qtc_sqlite3_user_data
+ #define sqlite3_value_blob qtc_sqlite3_value_blob
+ #define sqlite3_value_bytes qtc_sqlite3_value_bytes
+ #define sqlite3_value_bytes16 qtc_sqlite3_value_bytes16
+ #define sqlite3_value_double qtc_sqlite3_value_double
+ #define sqlite3_value_dup qtc_sqlite3_value_dup
+ #define sqlite3_value_free qtc_sqlite3_value_free
+ #define sqlite3_value_frombind qtc_sqlite3_value_frombind
+ #define sqlite3_value_int qtc_sqlite3_value_int
+ #define sqlite3_value_int64 qtc_sqlite3_value_int64
+ #define sqlite3_value_nochange qtc_sqlite3_value_nochange
+ #define sqlite3_value_numeric_type qtc_sqlite3_value_numeric_type
+ #define sqlite3_value_pointer qtc_sqlite3_value_pointer
+ #define sqlite3_value_subtype qtc_sqlite3_value_subtype
+ #define sqlite3_value_text qtc_sqlite3_value_text
+ #define sqlite3_value_type qtc_sqlite3_value_type
+ #define sqlite3_vfs_find qtc_sqlite3_vfs_find
+ #define sqlite3_vfs_register qtc_sqlite3_vfs_register
+ #define sqlite3_vfs_unregister qtc_sqlite3_vfs_unregister
+ #define sqlite3_vmprintf qtc_sqlite3_vmprintf
+ #define sqlite3_vsnprintf qtc_sqlite3_vsnprintf
+ #define sqlite3_vtab_collation qtc_sqlite3_vtab_collation
+ #define sqlite3_vtab_config qtc_sqlite3_vtab_config
+ #define sqlite3_vtab_nochange qtc_sqlite3_vtab_nochange
+ #define sqlite3_vtab_on_conflict qtc_sqlite3_vtab_on_conflict
+ #define sqlite3_wal_autocheckpoint qtc_sqlite3_wal_autocheckpoint
+ #define sqlite3_wal_checkpoint qtc_sqlite3_wal_checkpoint
+ #define sqlite3_wal_checkpoint_v2 qtc_sqlite3_wal_checkpoint_v2
+ #define sqlite3_wal_hook qtc_sqlite3_wal_hook
+ #define sqlite3_win32_is_nt qtc_sqlite3_win32_is_nt
+ #define sqlite3_win32_mbcs_to_utf8 qtc_sqlite3_win32_mbcs_to_utf8
+ #define sqlite3_win32_mbcs_to_utf8_v2 qtc_sqlite3_win32_mbcs_to_utf8_v2
+ #define sqlite3_win32_set_directory qtc_sqlite3_win32_set_directory
+ #define sqlite3_win32_set_directory16 qtc_sqlite3_win32_set_directory16
+ #define sqlite3_win32_set_directory8 qtc_sqlite3_win32_set_directory8
+ #define sqlite3_win32_sleep qtc_sqlite3_win32_sleep
+ #define sqlite3_win32_unicode_to_utf8 qtc_sqlite3_win32_unicode_to_utf8
+ #define sqlite3_win32_utf8_to_mbcs qtc_sqlite3_win32_utf8_to_mbcs
+ #define sqlite3_win32_utf8_to_mbcs_v2 qtc_sqlite3_win32_utf8_to_mbcs_v2
+ #define sqlite3_win32_utf8_to_unicode qtc_sqlite3_win32_utf8_to_unicode
+ #define sqlite3_win32_write_debug qtc_sqlite3_win32_write_debug
+ #define sqlite3_version qtc_sqlite3_version
+ #define sqlite3_temp_directory qtc_sqlite3_temp_directory
+ #define sqlite3_data_directory qtc_sqlite3_data_directory
+ #define sqlite3changeset_finalize qtc_sqlite3changeset_finalize
+ #define sqlite3changeset_op qtc_sqlite3changeset_op
+
+ // Redefine structures in order to avoid ODR violations
+ #define sqlite3 qtc_sqlite3
+ #define sqlite3_file qtc_sqlite3_file
+ #define sqlite3_io_methods qtc_sqlite3_io_methods
+ #define sqlite3_mutex qtc_sqlite3_mutex
+ #define sqlite3_api_routines qtc_sqlite3_api_routines
+ #define sqlite3_vfs qtc_sqlite3_vfs
+ #define sqlite3_mem_methods qtc_sqlite3_mem_methods
+ #define sqlite3_stmt qtc_sqlite3_stmt
+ #define sqlite3_value qtc_sqlite3_value
+ #define sqlite3_context qtc_sqlite3_context
+ #define sqlite3_vtab qtc_sqlite3_vtab
+ #define sqlite3_index_info qtc_sqlite3_index_info
+ #define sqlite3_vtab_cursor qtc_sqlite3_vtab_cursor
+ #define sqlite3_module qtc_sqlite3_module
+ #define sqlite3_mutex_methods qtc_sqlite3_mutex_methods
+ #define sqlite3_str qtc_sqlite3_str
+ #define sqlite3_pcache qtc_sqlite3_pcache
+ #define sqlite3_pcache_page qtc_sqlite3_pcache_page
+ #define sqlite3_pcache_methods2 qtc_sqlite3_pcache_methods2
+ #define sqlite3_pcache_methods qtc_sqlite3_pcache_methods
+ #define sqlite3_backup qtc_sqlite3_backup
+ #define sqlite3_snapshot qtc_sqlite3_snapshot
+ #define sqlite3_rtree_geometry qtc_sqlite3_rtree_geometry
+ #define sqlite3_rtree_query_info qtc_sqlite3_rtree_query_info
+ #define sqlite3_session qtc_sqlite3_session
+ #define sqlite3_changeset_iter qtc_sqlite3_changeset_iter
+ #define sqlite3_changegroup qtc_sqlite3_changegroup
+ #define sqlite3_rebaser qtc_sqlite3_rebaser
+ #define Fts5ExtensionApi qtc_Fts5ExtensionApi
+ #define Fts5Context qtc_Fts5Context
+ #define Fts5PhraseIter qtc_Fts5PhraseIter
+ #define Fts5Tokenizer qtc_Fts5Tokenizer
+ #define fts5_tokenizer qtc_fts5_tokenizer
+ #define fts5_api qtc_fts5_api
+#endif
diff --git a/src/libs/3rdparty/syntax-highlighting/.git-blame-ignore-revs b/src/libs/3rdparty/syntax-highlighting/.git-blame-ignore-revs
index 8b2ba6d3d5f..eba140cf12f 100644
--- a/src/libs/3rdparty/syntax-highlighting/.git-blame-ignore-revs
+++ b/src/libs/3rdparty/syntax-highlighting/.git-blame-ignore-revs
@@ -1,4 +1,5 @@
# clang-format
56ed6f3f5f505eb0dbffc630729d67c3fb510546
+ba947348217c468a0cea117289f3a3fc43bb66e6
#clang-tidy
0960472cc3f57831a97697a4ae0cd139e2cc5551
diff --git a/src/libs/3rdparty/syntax-highlighting/.gitlab-ci.yml b/src/libs/3rdparty/syntax-highlighting/.gitlab-ci.yml
index 8950fb6d61c..a5df0fb27a2 100644
--- a/src/libs/3rdparty/syntax-highlighting/.gitlab-ci.yml
+++ b/src/libs/3rdparty/syntax-highlighting/.gitlab-ci.yml
@@ -3,3 +3,8 @@
include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android-qt6.yml
diff --git a/src/libs/3rdparty/syntax-highlighting/.kde-ci.yml b/src/libs/3rdparty/syntax-highlighting/.kde-ci.yml
index cf1d3363f9d..51e4f4e72f1 100644
--- a/src/libs/3rdparty/syntax-highlighting/.kde-ci.yml
+++ b/src/libs/3rdparty/syntax-highlighting/.kde-ci.yml
@@ -5,3 +5,8 @@ Dependencies:
Options:
test-before-installing: True
+ require-passing-tests-on: [ 'Linux', 'FreeBSD', 'Windows' ]
+
+ # exclude stuff from cppcheck that takes too long
+ cppcheck-ignore-files:
+ - 'src/lib/abstracthighlighter.cpp'
diff --git a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt
index 4d352af3d65..d6b3f83d738 100644
--- a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt
@@ -4,13 +4,13 @@ else()
set(HIGHLIGHTING_BUILD_DEFAULT ON)
endif()
-add_qtc_library(KSyntaxHighlighting SHARED
+add_qtc_library(KSyntaxHighlighting
BUILD_DEFAULT ${HIGHLIGHTING_BUILD_DEFAULT}
INCLUDES autogenerated/
PUBLIC_INCLUDES
src/lib
+ autogenerated/include
autogenerated/src/lib
- DEFINES KF5SyntaxHighlighting_EXPORTS
DEPENDS Qt5::Network Qt5::Widgets
SOURCES
autogenerated/src/lib/ksyntaxhighlighting_logging.cpp autogenerated/src/lib/ksyntaxhighlighting_logging.h
@@ -43,7 +43,14 @@ add_qtc_library(KSyntaxHighlighting SHARED
src/lib/worddelimiters.cpp src/lib/worddelimiters_p.h
src/lib/xml_p.h
)
-qtc_add_public_header(autogenerated/src/lib/State)
+
+set(export_symbol_declaration DEFINES KF5SyntaxHighlighting_EXPORTS)
+if (QTC_STATIC_BUILD)
+ set(export_symbol_declaration PUBLIC_DEFINES KSYNTAXHIGHLIGHTING_STATIC_DEFINE)
+endif()
+extend_qtc_library(KSyntaxHighlighting ${export_symbol_declaration})
+
+qtc_add_public_header(autogenerated/include/KSyntaxHighlighting/State)
if(TARGET KSyntaxHighlighting)
install(
diff --git a/src/libs/3rdparty/syntax-highlighting/KF5SyntaxHighlightingConfig.cmake.in b/src/libs/3rdparty/syntax-highlighting/KF5SyntaxHighlightingConfig.cmake.in
index aa822b88dc9..b576ae1b48c 100644
--- a/src/libs/3rdparty/syntax-highlighting/KF5SyntaxHighlightingConfig.cmake.in
+++ b/src/libs/3rdparty/syntax-highlighting/KF5SyntaxHighlightingConfig.cmake.in
@@ -1,8 +1,8 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
-find_dependency(Qt5Core @REQUIRED_QT_VERSION@)
-find_dependency(Qt5Gui @REQUIRED_QT_VERSION@)
+find_dependency(Qt@QT_MAJOR_VERSION@Core @REQUIRED_QT_VERSION@)
+find_dependency(Qt@QT_MAJOR_VERSION@Gui @REQUIRED_QT_VERSION@)
include("${CMAKE_CURRENT_LIST_DIR}/KF5SyntaxHighlightingTargets.cmake")
@PACKAGE_INCLUDE_QCHTARGETS@
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/AbstractHighlighter b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/AbstractHighlighter
index b7878737718..b7878737718 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/AbstractHighlighter
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/AbstractHighlighter
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Definition b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Definition
index 2c3241f8416..2c3241f8416 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Definition
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Definition
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/DefinitionDownloader b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/DefinitionDownloader
index 2a82740d19b..2a82740d19b 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/DefinitionDownloader
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/DefinitionDownloader
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/FoldingRegion b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/FoldingRegion
index 005b829d539..005b829d539 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/FoldingRegion
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/FoldingRegion
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Format b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Format
index b0d6a102468..b0d6a102468 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Format
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Format
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Repository b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Repository
index 189dbc2f699..189dbc2f699 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Repository
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Repository
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/State b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/State
index e148d70391a..e148d70391a 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/State
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/State
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/SyntaxHighlighter b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/SyntaxHighlighter
index b42982473b0..b42982473b0 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/SyntaxHighlighter
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/SyntaxHighlighter
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Theme b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Theme
index 34a3e98e604..34a3e98e604 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/Theme
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/Theme
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/WildcardMatcher b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/WildcardMatcher
index ecea1b09bd9..ecea1b09bd9 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/WildcardMatcher
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/include/KSyntaxHighlighting/WildcardMatcher
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h b/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h
index 4336b19ce5d..9d25202a4bb 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h
@@ -3,10 +3,10 @@
#ifndef SyntaxHighlighting_VERSION_H
#define SyntaxHighlighting_VERSION_H
-#define SyntaxHighlighting_VERSION_STRING "5.90.0"
+#define SyntaxHighlighting_VERSION_STRING "5.95.0"
#define SyntaxHighlighting_VERSION_MAJOR 5
-#define SyntaxHighlighting_VERSION_MINOR 90
+#define SyntaxHighlighting_VERSION_MINOR 95
#define SyntaxHighlighting_VERSION_PATCH 0
-#define SyntaxHighlighting_VERSION ((5<<16)|(90<<8)|(0))
+#define SyntaxHighlighting_VERSION ((5<<16)|(95<<8)|(0))
#endif
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h b/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h
index 25fb987a978..6591b59e810 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h
@@ -88,7 +88,7 @@
#define KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(major, minor) 1
#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED
-# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0x55a00
+# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0x55f00
#endif
#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0
@@ -98,7 +98,7 @@
# ifdef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# else
-# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0x55a00
+# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0x55f00
# endif
#endif
@@ -178,7 +178,7 @@
#define KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(major, minor) 1
#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED
-# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0x55a00
+# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0x55f00
#endif
#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0
@@ -188,7 +188,7 @@
# ifdef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# else
-# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0x55a00
+# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0x55f00
# endif
#endif
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp b/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp
index 8b3d9e6f49d..af482ef3db2 100644
--- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp
@@ -3,9 +3,5 @@
#include "ksyntaxhighlighting_logging.h"
namespace KSyntaxHighlighting {
-#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
Q_LOGGING_CATEGORY(Log, "kf.syntaxhighlighting", QtInfoMsg)
-#else
-Q_LOGGING_CATEGORY(Log, "kf.syntaxhighlighting")
-#endif
}
diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/.gitignore b/src/libs/3rdparty/syntax-highlighting/data/generators/.gitignore
new file mode 100644
index 00000000000..8f4dc5cfcf4
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/data/generators/.gitignore
@@ -0,0 +1 @@
+Pipfile.lock
diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/Pipfile b/src/libs/3rdparty/syntax-highlighting/data/generators/Pipfile
new file mode 100644
index 00000000000..8e9c570084c
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/data/generators/Pipfile
@@ -0,0 +1,11 @@
+# kate: hl toml;
+
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+click = "~= 8.0"
+jinja2 = "~= 3.0"
+PyYAML = "*"
diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml b/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml
index f5437900627..e02b950765b 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml
+++ b/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml
@@ -1,4 +1,4 @@
-version: 37
+version: 38
global-properties:
- ALLOW_DUPLICATE_CUSTOM_TARGETS
@@ -168,6 +168,7 @@ target-properties:
- DEPLOYMENT_REMOTE_DIRECTORY
- DEPRECATION # Since 3.17
- DISABLE_PRECOMPILE_HEADERS # Since 3.16
+ - DOTNET_SDK # Since 3.23
- DOTNET_TARGET_FRAMEWORK # Since 3.17
- DOTNET_TARGET_FRAMEWORK_VERSION # Since 3.12
- EchoString
@@ -188,6 +189,15 @@ target-properties:
- GENERATOR_FILE_NAME
- GNUtoMS
- HAS_CXX
+ - HEADER_DIRS # Since 3.23
+ - HEADER_DIRS_<NAME> # Since 3.23
+ - HEADER_SET # Since 3.23
+ - HEADER_SET_<NAME> # Since 3.23
+ - HEADER_SETS # Since 3.23
+ - HIP_ARCHITECTURES # Since 3.21
+ - HIP_EXTENSIONS # Since 3.21
+ - HIP_STANDARD # Since 3.21
+ - HIP_STANDARD_REQUIRED # Since 3.21
- IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
- IMPORTED_COMMON_LANGUAGE_RUNTIME # Since 3.12
- IMPORTED_CONFIGURATIONS
@@ -208,6 +218,7 @@ target-properties:
- IMPORTED_LOCATION
- IMPORTED_NO_SONAME_<CONFIG>
- IMPORTED_NO_SONAME
+ - IMPORTED_NO_SYSTEM # Since 3.23
- IMPORTED_OBJECTS_<CONFIG>
- IMPORTED_OBJECTS
- IMPORTED
@@ -224,6 +235,7 @@ target-properties:
- INTERFACE_COMPILE_DEFINITIONS
- INTERFACE_COMPILE_FEATURES
- INTERFACE_COMPILE_OPTIONS
+ - INTERFACE_HEADER_SETS # Since 3.23
- INTERFACE_INCLUDE_DIRECTORIES
- INTERFACE_LINK_DEPENDS # Since 3.13
- INTERFACE_LINK_DIRECTORIES # Since 3.13
@@ -264,6 +276,7 @@ target-properties:
- LINK_INTERFACE_MULTIPLICITY_<CONFIG>
- LINK_INTERFACE_MULTIPLICITY
- LINK_LIBRARIES
+ - LINK_LIBRARIES_ONLY_TARGETS # Since 3.23
- LINK_OPTIONS # Since 3.13
- LINK_SEARCH_END_STATIC
- LINK_SEARCH_START_STATIC
@@ -390,6 +403,7 @@ target-properties:
- XCODE_SCHEME_ARGUMENTS # Since 3.13
- XCODE_SCHEME_DEBUG_AS_ROOT # Since 3.15
- XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING # Since 3.16
+ - XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE # Since 3.23
- XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER # Since 3.13
- XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE # Since 3.13
- XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS # Since 3.13
@@ -622,6 +636,7 @@ variables:
- CMAKE_CURRENT_SOURCE_DIR
- CMAKE_DIRECTORY_LABELS # Since 3.10
- CMAKE_DL_LIBS
+ - CMAKE_DOTNET_SDK # Since 3.23
- CMAKE_DOTNET_TARGET_FRAMEWORK # Since 3.17
- CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION # Since 3.12
- CMAKE_EDIT_COMMAND
@@ -690,6 +705,7 @@ variables:
- CMAKE_VS_DEVENV_COMMAND
- CMAKE_VS_MSBUILD_COMMAND
- CMAKE_VS_NsightTegra_VERSION
+ - CMAKE_VS_NUGET_PACKAGE_RESTORE # Since 3.23
- CMAKE_VS_PLATFORM_NAME
- CMAKE_VS_PLATFORM_TOOLSET
- CMAKE_VS_PLATFORM_TOOLSET_CUDA
@@ -771,6 +787,7 @@ variables:
- CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY # Since 3.16
- CMAKE_FRAMEWORK_PATH
- CMAKE_IGNORE_PATH
+ - CMAKE_IGNORE_PREFIX_PATH # Since 3.23
- CMAKE_INCLUDE_DIRECTORIES_BEFORE
- CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
- CMAKE_INCLUDE_PATH
@@ -781,6 +798,7 @@ variables:
- CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
- CMAKE_LIBRARY_PATH
- CMAKE_LINK_DIRECTORIES_BEFORE # Since 3.13
+ - CMAKE_LINK_LIBRARIES_ONLY_TARGETS # Since 3.23
- CMAKE_MAXIMUM_RECURSION_DEPTH # Since 3.14
- CMAKE_MFC_FLAG
- CMAKE_MODULE_PATH
@@ -803,6 +821,7 @@ variables:
- CMAKE_SYSTEM_APPBUNDLE_PATH
- CMAKE_SYSTEM_FRAMEWORK_PATH
- CMAKE_SYSTEM_IGNORE_PATH
+ - CMAKE_SYSTEM_IGNORE_PREFIX_PATH # Since 3.23
- CMAKE_SYSTEM_INCLUDE_PATH
- CMAKE_SYSTEM_LIBRARY_PATH
- CMAKE_SYSTEM_PREFIX_PATH
@@ -817,6 +836,7 @@ variables:
- CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN # Since 3.13
- CMAKE_XCODE_SCHEME_WORKING_DIRECTORY # Since 3.17
- CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING # Since 3.16
+ - CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE # Since 3.23
- CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER # Since 3.13
- CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE # Since 3.13
- CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS # Since 3.13
@@ -1186,6 +1206,7 @@ variables:
- CTEST_RUN_CURRENT_SCRIPT # Since 3.11
- CTEST_SCP_COMMAND
- CTEST_SITE
+ - CTEST_SUBMIT_INACTIVITY_TIMEOUT # Since 3.23
- CTEST_SUBMIT_URL # Since 3.14
- CTEST_SOURCE_DIRECTORY
- CTEST_SVN_COMMAND
@@ -1313,6 +1334,15 @@ variables:
- CMAKE_C_LINK_NO_PIE_SUPPORTED
- CMAKE_CXX_LINK_NO_PIE_SUPPORTED
- CMAKE_Fortran_LINK_NO_PIE_SUPPORTED
+ # Since 3.23
+ - CMAKE_OBJC_LINK_PIE_SUPPORTED
+ - CMAKE_OBJC_LINK_NO_PIE_SUPPORTED
+ - CMAKE_OBJCXX_LINK_PIE_SUPPORTED
+ - CMAKE_OBJCXX_LINK_NO_PIE_SUPPORTED
+ - CMAKE_CUDA_LINK_PIE_SUPPORTED
+ - CMAKE_CUDA_LINK_NO_PIE_SUPPORTED
+ - CMAKE_HIP_LINK_PIE_SUPPORTED
+ - CMAKE_HIP_LINK_NO_PIE_SUPPORTED
# - CheckPrototypeDefinition
# - CheckStructHasMember
# - CheckSymbolExists
@@ -1475,11 +1505,19 @@ variables:
- CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE
- CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS
- CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH
+ - CPACK_IFW_PACKAGE_DISABLE_COMMAND_LINE_INTERFACE # Since 3.23
- CPACK_IFW_PACKAGE_CONTROL_SCRIPT
- CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR # Since 3.11
- CPACK_IFW_PACKAGE_RESOURCES
- CPACK_IFW_REPOSITORIES_ALL
- CPACK_IFW_DOWNLOAD_ALL
+ - CPACK_IFW_PACKAGE_PRODUCT_IMAGES # Since 3.23
+ - CPACK_IFW_PACKAGE_RUN_PROGRAM # Since 3.23
+ - CPACK_IFW_PACKAGE_RUN_PROGRAM_ARGUMENTS # Since 3.23
+ - CPACK_IFW_PACKAGE_RUN_PROGRAM_DESCRIPTION # Since 3.23
+ - CPACK_IFW_PACKAGE_SIGNING_IDENTITY # Since 3.23
+ - CPACK_IFW_ARCHIVE_FORMAT # Since 3.23
+ - CPACK_IFW_ARCHIVE_COMPRESSION # Since 3.23
- CPACK_IFW_RESOLVE_DUPLICATE_NAMES
- CPACK_IFW_PACKAGES_DIRECTORIES
- CPACK_IFW_FRAMEWORK_VERSION
@@ -1567,6 +1605,7 @@ variables:
# - CPackPackageMaker is deprecated and gonna be removed in next versions of CPack
# - CPackProductBuild
- CPACK_COMMAND_PRODUCTBUILD
+ - CPACK_PRODUCTBUILD_IDENTIFIER # Since 3.23
- CPACK_PRODUCTBUILD_IDENTITY_NAME
- CPACK_PRODUCTBUILD_KEYCHAIN_PATH
- CPACK_COMMAND_PKGBUILD
@@ -1575,6 +1614,10 @@ variables:
- CPACK_PREFLIGHT_<COMP>_SCRIPT # Since 3.1?
- CPACK_POSTFLIGHT_<COMP>_SCRIPT # Since 3.1?
- CPACK_PRODUCTBUILD_RESOURCES_DIR
+ - CPACK_PRODUCTBUILD_DOMAINS # Since 3.23
+ - CPACK_PRODUCTBUILD_DOMAINS_ANYWHERE # Since 3.23
+ - CPACK_PRODUCTBUILD_DOMAINS_USER # Since 3.23
+ - CPACK_PRODUCTBUILD_DOMAINS_ROOT # Since 3.23
- CPACK_PRODUCTBUILD_BACKGROUND # Since 3.17
- CPACK_PRODUCTBUILD_BACKGROUND_ALIGNMENT # Since 3.17
- CPACK_PRODUCTBUILD_BACKGROUND_SCALING # Since 3.17
@@ -1750,6 +1793,7 @@ variables:
- CPACK_WIX_ROOT_FOLDER_ID
- CPACK_WIX_ROOT
- CPACK_WIX_CUSTOM_XMLNS # Since 3.19
+ - CPACK_WIX_SKIP_WIX_UI_EXTENSION # Since 3.23
# - CTest
# - Dart
- BUILD_TESTING
@@ -2535,6 +2579,8 @@ environment-variables:
- CMAKE_FRAMEWORK_PATH
- CMAKE_APPBUNDLE_PATH
- PATH
+ # Environment Variables recognized by some standard modules
+ - QTIFWDIR
scripting-commands:
-
@@ -3389,7 +3435,20 @@ project-commands:
named-args: [EXTRA_INCLUDE, FUNCTION]
-
name: define_property
- named-args: [GLOBAL, DIRECTORY, DIRECTORY, SOURCE, TEST, VARIABLE, CACHED_VARIABLE, PROPERTY, INHERITED, BRIEF_DOCS, FULL_DOCS]
+ named-args: [
+ GLOBAL
+ , DIRECTORY
+ , DIRECTORY
+ , SOURCE
+ , TEST
+ , VARIABLE
+ , CACHED_VARIABLE
+ , PROPERTY
+ , INHERITED
+ , BRIEF_DOCS
+ , FULL_DOCS
+ , INITIALIZE_FROM_VARIABLE # Since 3.23
+ ]
property-args: *get-property
-
name: enable_language
@@ -3468,6 +3527,7 @@ project-commands:
, PRIVATE_HEADER
, PUBLIC_HEADER
, RESOURCE
+ , FILE_SET # Since 3.23
, INCLUDES
, NAMELINK_ONLY
, NAMELINK_SKIP
@@ -3707,7 +3767,16 @@ project-commands:
first-arg-is-target?: true
-
name: target_sources
- named-args: *target_compile_definitions
+ named-args: [
+ INTERFACE
+ , PUBLIC
+ , PRIVATE
+ # Since 3.23
+ , FILE_SET
+ , TYPE
+ , BASE_DIRS
+ , FILES
+ ]
first-arg-is-target?: true
-
name: try_compile
@@ -4230,7 +4299,11 @@ standard-module-commands:
-
name: check_pie_supported
named-args: [OUTPUT_VARIABLE, LANGUAGES]
- special-args: *ccxxf
+ special-args: [
+ C, CXX, Fortran,
+ # Since 3.23
+ OBJC, OBJCXX, CUDA, HIP
+ ]
# CheckPrototypeDefinition
- name: check_prototype_definition
# CheckSourceCompiles
@@ -4536,6 +4609,7 @@ standard-module-commands:
- LOG_OUTPUT_ON_FAILURE
- USES_TERMINAL_DOWNLOAD
- USES_TERMINAL_UPDATE
+ - USES_TERMINAL_PATCH # Since 3.23
- USES_TERMINAL_CONFIGURE
- USES_TERMINAL_BUILD
- USES_TERMINAL_INSTALL
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml
index 72e200cce2d..935041cd586 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml
@@ -39,7 +39,7 @@
<!ENTITY arithmetic_as_subshell "\(((?:[^`'&quot;()$]++|\$\{[^`'&quot;(){}$]+\}|\$(?=[^{`'&quot;()])|`[^`]*+`|\((?1)(?:[)]|(?=['&quot;])))++)(?:[)](?=$|[^)])|[&quot;'])">
]>
-<language name="Bash" version="34" kateversion="5.79" section="Scripts" extensions="*.sh;*.bash;*.ebuild;*.eclass;*.exlib;*.exheres-0;.bashrc;.bash_profile;.bash_login;.profile;PKGBUILD;APKBUILD" mimetype="application/x-shellscript" casesensitive="1" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL">
+<language name="Bash" version="39" kateversion="5.79" section="Scripts" extensions="*.sh;*.bash;*.ebuild;*.eclass;*.exlib;*.exheres-0;.bashrc;.bash_profile;.bash_login;.profile;PKGBUILD;APKBUILD" mimetype="application/x-shellscript" casesensitive="1" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL">
<!-- (c) 2004 by Wilbert Berendsen (wilbert@kde.nl)
Changes by Matthew Woehlke (mw_triad@users.sourceforge.net)
@@ -553,6 +553,8 @@
<AnyChar attribute="Error" context="#stay" String=")}"/>
<LineContinue attribute="Escape" context="#stay"/>
+
+ <Detect2Chars attribute="Expression" context="#stay" char="!" char1=" "/>
</context>
<context attribute="Normal Text" lineEndContext="#pop" name="MaybeBracketExpression" fallthroughContext="#pop!Command">
<!-- start expression in double brackets -->
@@ -785,16 +787,30 @@
<!-- FindPathThenPopInAlternateValue consumes path in ${xx:here}-->
<context attribute="Normal Text" lineEndContext="#pop" name="FindPathThenPopInAlternateValue">
- <IncludeRules context="FindExtGlobAndPopInAlternateValue"/>
- <AnyChar attribute="Glob" context="PathThenPopInAlternateValue" String="?*"/>
- <RegExpr attribute="Path" context="PathThenPopInAlternateValue" String="&pathpart_alt;"/>
+ <Detect2Chars context="#pop!PathThenPopInAlternateValue" char="?" char1="(" lookAhead="1"/>
+ <Detect2Chars context="#pop!PathThenPopInAlternateValue" char="*" char1="(" lookAhead="1"/>
+ <Detect2Chars context="#pop!PathThenPopInAlternateValue" char="+" char1="(" lookAhead="1"/>
+ <Detect2Chars context="#pop!PathThenPopInAlternateValue" char="@" char1="(" lookAhead="1"/>
+ <Detect2Chars context="#pop!PathThenPopInAlternateValue" char="!" char1="(" lookAhead="1"/>
+ <AnyChar attribute="Glob" context="#pop!PathThenPopInAlternateValue" String="?*"/>
+ <RegExpr attribute="Path" context="#pop!PathThenPopInAlternateValue" String="&pathpart_alt;"/>
</context>
- <context attribute="Path" lineEndContext="#stay" name="FindExtGlobAndPopInAlternateValue">
+ <context attribute="Path" lineEndContext="#pop#pop" name="PathThenPopInAlternateValue">
+ <DetectChar attribute="Parameter Expansion" context="#pop" char="}"/>
+ <IncludeRules context="FindWord"/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="?" char1="("/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="*" char1="("/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="+" char1="("/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="@" char1="("/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="!" char1="("/>
+ <AnyChar attribute="Glob" context="#stay" String="?*"/>
+ <RegExpr attribute="Path" context="#stay" String="&path_alt;"/>
+ </context>
+ <context attribute="Path" lineEndContext="#stay" name="ExtGlobAndPopInAlternateValue">
+ <DetectChar attribute="Glob" context="#pop" char=")"/>
+ <DetectChar attribute="Error" context="#pop#pop" char="}"/>
+ <IncludeRules context="FindWord"/>
+ <IncludeRules context="FindExtGlobInAlternateValue"/>
</context>
<context attribute="Path" lineEndContext="#stay" name="FindExtGlobInAlternateValue">
<Detect2Chars attribute="Glob" context="RecursiveExtGlobInAlternateValue" char="?" char1="("/>
@@ -810,19 +826,6 @@
<IncludeRules context="FindWord"/>
<IncludeRules context="FindExtGlobInAlternateValue"/>
</context>
- <context attribute="Path" lineEndContext="#stay" name="ExtGlobAndPopInAlternateValue">
- <DetectChar attribute="Glob" context="#pop!PathThenPopInAlternateValue" char=")"/>
- <DetectChar attribute="Error" context="#pop#pop" char="}"/>
- <IncludeRules context="FindWord"/>
- <IncludeRules context="FindExtGlobInAlternateValue"/>
- </context>
- <context attribute="Path" lineEndContext="#pop#pop" name="PathThenPopInAlternateValue">
- <DetectChar attribute="Parameter Expansion" context="#pop#pop" char="}"/>
- <IncludeRules context="FindWord"/>
- <IncludeRules context="FindExtGlobAndPopInAlternateValue"/>
- <AnyChar attribute="Glob" context="#stay" String="?*"/>
- <RegExpr attribute="Path" context="#stay" String="&path_alt;"/>
- </context>
<context attribute="Pattern" lineEndContext="#stay" name="FindPattern">
<Detect2Chars attribute="Glob" context="ExtPattern" char="?" char1="("/>
@@ -1402,6 +1405,7 @@
<!-- ExprDblBracket consumes an expression till ]] -->
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblBracket" fallthroughContext="#pop!ExprDblBracketNot">
<DetectSpaces attribute="Normal Text" context="#stay"/>
+ <DetectChar attribute="Comment" context="Comment" char="#"/>
<IncludeRules context="FindExprDblBracketEnd"/>
</context>
@@ -1415,10 +1419,13 @@
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblBracketParam1" fallthroughContext="ExprDblBracketValue">
<DetectSpaces attribute="Normal Text" context="#pop!ExprDblBracketParam2"/>
- <DetectChar context="TestMaybeUnary" char="-" lookAhead="1"/>
+ <DetectChar context="TestMaybeUnary2" char="-" lookAhead="1"/>
<AnyChar attribute="Expression" context="#pop!ExprDblBracketParam3Spe" String="&lt;>"/>
<IncludeRules context="FindExprDblBracketEnd"/>
</context>
+ <context attribute="Normal Text" lineEndContext="#pop" name="TestMaybeUnary2" fallthroughContext="#pop!ExprDblBracketValue">
+ <IncludeRules context="TestMaybeUnary"/>
+ </context>
<context attribute="Normal Text" lineEndContext="#pop" name="ExprDblBracketValue">
<Detect2Chars context="ExprDblBracketDblParentOrSubValue" char="(" char1="(" lookAhead="1"/>
@@ -1465,7 +1472,7 @@
<DetectSpaces attribute="Normal Text" context="#pop!ExprDblBracketParam3"/>
</context>
- <context attribute="Normal Text" lineEndContext="ExprDblBracketFinal" name="ExprDblBracketParam3" fallthroughContext="ExprDblBracketValue">
+ <context attribute="Normal Text" lineEndContext="#stay" name="ExprDblBracketParam3" fallthroughContext="ExprDblBracketValue">
<DetectSpaces attribute="Normal Text" context="#pop!ExprDblBracketFinal"/>
<IncludeRules context="FindExprDblBracketEnd"/>
<AnyChar attribute="Error" context="#stay" String="&lt;>"/>
@@ -1474,6 +1481,7 @@
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblBracketFinal" fallthroughContext="ExprDblBracketValue">
<DetectSpaces attribute="Normal Text" context="#stay"/>
<IncludeRules context="FindExprDblBracketEnd"/>
+ <DetectChar attribute="Comment" context="Comment" char="#"/>
<RegExpr attribute="Error" context="#pop" String="(?:[^] &tab;]++|\](?:[^]]|\][^ &tab;]))++" endRegion="expression"/>
</context>
@@ -1489,7 +1497,7 @@
</context>
<context attribute="Pattern" lineEndContext="#stay" name="Regex">
<DetectSpaces attribute="Normal Text" context="#pop!ExprDblBracketFinal"/>
- <DetectChar attribute="Error" context="#stay" char=")"/>
+ <DetectChar attribute="Operator" context="#pop" char=")"/>
<Detect2Chars attribute="Operator" context="RegexChar" char="[" char1="^"/>
<DetectChar attribute="Operator" context="RegexChar" char="["/>
<IncludeRules context="FindRegex"/>
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml
index e94885b856f..e03d054c07a 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml
@@ -25,7 +25,7 @@
<language
name="CMake"
- version="37"
+ version="38"
kateversion="5.0"
section="Other"
extensions="CMakeLists.txt;*.cmake;*.cmake.in"
@@ -966,6 +966,7 @@
<item>FULL_DOCS</item>
<item>GLOBAL</item>
<item>INHERITED</item>
+ <item>INITIALIZE_FROM_VARIABLE</item>
<item>PROPERTY</item>
<item>SOURCE</item>
<item>TEST</item>
@@ -1034,6 +1035,7 @@
<item>FILES</item>
<item>FILES_MATCHING</item>
<item>FILE_PERMISSIONS</item>
+ <item>FILE_SET</item>
<item>FRAMEWORK</item>
<item>IMPORTED_RUNTIME_ARTIFACTS</item>
<item>INCLUDES</item>
@@ -1263,9 +1265,13 @@
<item>REUSE_FROM</item>
</list>
<list name="target_sources_nargs">
+ <item>BASE_DIRS</item>
+ <item>FILES</item>
+ <item>FILE_SET</item>
<item>INTERFACE</item>
<item>PRIVATE</item>
<item>PUBLIC</item>
+ <item>TYPE</item>
</list>
<list name="try_compile_nargs">
<item>CMAKE_FLAGS</item>
@@ -1470,8 +1476,12 @@
</list>
<list name="check_pie_supported_sargs">
<item>C</item>
+ <item>CUDA</item>
<item>CXX</item>
<item>Fortran</item>
+ <item>HIP</item>
+ <item>OBJC</item>
+ <item>OBJCXX</item>
</list>
<list name="check_source_compiles_nargs">
<item>FAIL_REGEX</item>
@@ -1729,6 +1739,7 @@
<item>USES_TERMINAL_CONFIGURE</item>
<item>USES_TERMINAL_DOWNLOAD</item>
<item>USES_TERMINAL_INSTALL</item>
+ <item>USES_TERMINAL_PATCH</item>
<item>USES_TERMINAL_TEST</item>
<item>USES_TERMINAL_UPDATE</item>
</list>
@@ -2256,6 +2267,8 @@
<item>CMAKE_CUDA_COMPILE_FEATURES</item>
<item>CMAKE_CUDA_EXTENSIONS</item>
<item>CMAKE_CUDA_HOST_COMPILER</item>
+ <item>CMAKE_CUDA_LINK_NO_PIE_SUPPORTED</item>
+ <item>CMAKE_CUDA_LINK_PIE_SUPPORTED</item>
<item>CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS</item>
<item>CMAKE_CUDA_RUNTIME_LIBRARY</item>
<item>CMAKE_CUDA_SEPARABLE_COMPILATION</item>
@@ -2291,6 +2304,7 @@
<item>CMAKE_DIRECTORY_LABELS</item>
<item>CMAKE_DISABLE_PRECOMPILE_HEADERS</item>
<item>CMAKE_DL_LIBS</item>
+ <item>CMAKE_DOTNET_SDK</item>
<item>CMAKE_DOTNET_TARGET_FRAMEWORK</item>
<item>CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION</item>
<item>CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES</item>
@@ -2370,6 +2384,8 @@
<item>CMAKE_HAS_ANSI_STRING_STREAM</item>
<item>CMAKE_HIP_ARCHITECTURES</item>
<item>CMAKE_HIP_EXTENSIONS</item>
+ <item>CMAKE_HIP_LINK_NO_PIE_SUPPORTED</item>
+ <item>CMAKE_HIP_LINK_PIE_SUPPORTED</item>
<item>CMAKE_HIP_STANDARD</item>
<item>CMAKE_HIP_STANDARD_REQUIRED</item>
<item>CMAKE_HOST_APPLE</item>
@@ -2382,6 +2398,7 @@
<item>CMAKE_HOST_WIN32</item>
<item>CMAKE_HP_PTHREADS_INIT</item>
<item>CMAKE_IGNORE_PATH</item>
+ <item>CMAKE_IGNORE_PREFIX_PATH</item>
<item>CMAKE_IMPORT_LIBRARY_PREFIX</item>
<item>CMAKE_IMPORT_LIBRARY_SUFFIX</item>
<item>CMAKE_INCLUDE_CURRENT_DIR</item>
@@ -2461,6 +2478,7 @@
<item>CMAKE_LINK_DEPENDS_NO_SHARED</item>
<item>CMAKE_LINK_DIRECTORIES_BEFORE</item>
<item>CMAKE_LINK_INTERFACE_LIBRARIES</item>
+ <item>CMAKE_LINK_LIBRARIES_ONLY_TARGETS</item>
<item>CMAKE_LINK_LIBRARY_FILE_FLAG</item>
<item>CMAKE_LINK_LIBRARY_FLAG</item>
<item>CMAKE_LINK_LIBRARY_SUFFIX</item>
@@ -2496,9 +2514,13 @@
<item>CMAKE_NO_STD_NAMESPACE</item>
<item>CMAKE_NO_SYSTEM_FROM_IMPORTED</item>
<item>CMAKE_OBJCXX_EXTENSIONS</item>
+ <item>CMAKE_OBJCXX_LINK_NO_PIE_SUPPORTED</item>
+ <item>CMAKE_OBJCXX_LINK_PIE_SUPPORTED</item>
<item>CMAKE_OBJCXX_STANDARD</item>
<item>CMAKE_OBJCXX_STANDARD_REQUIRED</item>
<item>CMAKE_OBJC_EXTENSIONS</item>
+ <item>CMAKE_OBJC_LINK_NO_PIE_SUPPORTED</item>
+ <item>CMAKE_OBJC_LINK_PIE_SUPPORTED</item>
<item>CMAKE_OBJC_STANDARD</item>
<item>CMAKE_OBJC_STANDARD_REQUIRED</item>
<item>CMAKE_OBJECT_PATH_MAX</item>
@@ -2564,6 +2586,7 @@
<item>CMAKE_SYSTEM_APPBUNDLE_PATH</item>
<item>CMAKE_SYSTEM_FRAMEWORK_PATH</item>
<item>CMAKE_SYSTEM_IGNORE_PATH</item>
+ <item>CMAKE_SYSTEM_IGNORE_PREFIX_PATH</item>
<item>CMAKE_SYSTEM_INCLUDE_PATH</item>
<item>CMAKE_SYSTEM_LIBRARY_PATH</item>
<item>CMAKE_SYSTEM_NAME</item>
@@ -2596,6 +2619,7 @@
<item>CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD</item>
<item>CMAKE_VS_JUST_MY_CODE_DEBUGGING</item>
<item>CMAKE_VS_MSBUILD_COMMAND</item>
+ <item>CMAKE_VS_NUGET_PACKAGE_RESTORE</item>
<item>CMAKE_VS_NsightTegra_VERSION</item>
<item>CMAKE_VS_PLATFORM_NAME</item>
<item>CMAKE_VS_PLATFORM_TOOLSET</item>
@@ -2625,6 +2649,7 @@
<item>CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER</item>
<item>CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS</item>
<item>CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE</item>
+ <item>CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE</item>
<item>CMAKE_XCODE_SCHEME_ENVIRONMENT</item>
<item>CMAKE_XCODE_SCHEME_GUARD_MALLOC</item>
<item>CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP</item>
@@ -2714,6 +2739,8 @@
<item>CPACK_EXTERNAL_REQUESTED_VERSIONS</item>
<item>CPACK_GENERATOR</item>
<item>CPACK_IFW_ADMIN_TARGET_DIRECTORY</item>
+ <item>CPACK_IFW_ARCHIVE_COMPRESSION</item>
+ <item>CPACK_IFW_ARCHIVE_FORMAT</item>
<item>CPACK_IFW_BINARYCREATOR_EXECUTABLE</item>
<item>CPACK_IFW_DEVTOOL_EXECUTABLE</item>
<item>CPACK_IFW_DOWNLOAD_ALL</item>
@@ -2725,15 +2752,21 @@
<item>CPACK_IFW_PACKAGE_BACKGROUND</item>
<item>CPACK_IFW_PACKAGE_BANNER</item>
<item>CPACK_IFW_PACKAGE_CONTROL_SCRIPT</item>
+ <item>CPACK_IFW_PACKAGE_DISABLE_COMMAND_LINE_INTERFACE</item>
<item>CPACK_IFW_PACKAGE_GROUP</item>
<item>CPACK_IFW_PACKAGE_ICON</item>
<item>CPACK_IFW_PACKAGE_LOGO</item>
<item>CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE</item>
<item>CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME</item>
<item>CPACK_IFW_PACKAGE_NAME</item>
+ <item>CPACK_IFW_PACKAGE_PRODUCT_IMAGES</item>
<item>CPACK_IFW_PACKAGE_PUBLISHER</item>
<item>CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR</item>
<item>CPACK_IFW_PACKAGE_RESOURCES</item>
+ <item>CPACK_IFW_PACKAGE_RUN_PROGRAM</item>
+ <item>CPACK_IFW_PACKAGE_RUN_PROGRAM_ARGUMENTS</item>
+ <item>CPACK_IFW_PACKAGE_RUN_PROGRAM_DESCRIPTION</item>
+ <item>CPACK_IFW_PACKAGE_SIGNING_IDENTITY</item>
<item>CPACK_IFW_PACKAGE_START_MENU_DIRECTORY</item>
<item>CPACK_IFW_PACKAGE_STYLE_SHEET</item>
<item>CPACK_IFW_PACKAGE_TITLE</item>
@@ -2846,6 +2879,11 @@
<item>CPACK_PRODUCTBUILD_BACKGROUND_MIME_TYPE</item>
<item>CPACK_PRODUCTBUILD_BACKGROUND_SCALING</item>
<item>CPACK_PRODUCTBUILD_BACKGROUND_UTI</item>
+ <item>CPACK_PRODUCTBUILD_DOMAINS</item>
+ <item>CPACK_PRODUCTBUILD_DOMAINS_ANYWHERE</item>
+ <item>CPACK_PRODUCTBUILD_DOMAINS_ROOT</item>
+ <item>CPACK_PRODUCTBUILD_DOMAINS_USER</item>
+ <item>CPACK_PRODUCTBUILD_IDENTIFIER</item>
<item>CPACK_PRODUCTBUILD_IDENTITY_NAME</item>
<item>CPACK_PRODUCTBUILD_KEYCHAIN_PATH</item>
<item>CPACK_PRODUCTBUILD_RESOURCES_DIR</item>
@@ -2944,6 +2982,7 @@
<item>CPACK_WIX_ROOT_FEATURE_TITLE</item>
<item>CPACK_WIX_ROOT_FOLDER_ID</item>
<item>CPACK_WIX_SKIP_PROGRAM_FOLDER</item>
+ <item>CPACK_WIX_SKIP_WIX_UI_EXTENSION</item>
<item>CPACK_WIX_TEMPLATE</item>
<item>CPACK_WIX_UI_BANNER</item>
<item>CPACK_WIX_UI_DIALOG</item>
@@ -3010,6 +3049,7 @@
<item>CTEST_SCP_COMMAND</item>
<item>CTEST_SITE</item>
<item>CTEST_SOURCE_DIRECTORY</item>
+ <item>CTEST_SUBMIT_INACTIVITY_TIMEOUT</item>
<item>CTEST_SUBMIT_URL</item>
<item>CTEST_SVN_COMMAND</item>
<item>CTEST_SVN_OPTIONS</item>
@@ -3523,6 +3563,7 @@
<item>LDFLAGS</item>
<item>MACOSX_DEPLOYMENT_TARGET</item>
<item>PATH</item>
+ <item>QTIFWDIR</item>
<item>RC</item>
<item>RCFLAGS</item>
<item>SWIFTC</item>
@@ -3682,6 +3723,7 @@
<item>DEPLOYMENT_REMOTE_DIRECTORY</item>
<item>DEPRECATION</item>
<item>DISABLE_PRECOMPILE_HEADERS</item>
+ <item>DOTNET_SDK</item>
<item>DOTNET_TARGET_FRAMEWORK</item>
<item>DOTNET_TARGET_FRAMEWORK_VERSION</item>
<item>ENABLE_EXPORTS</item>
@@ -3700,6 +3742,13 @@
<item>GENERATOR_FILE_NAME</item>
<item>GNUtoMS</item>
<item>HAS_CXX</item>
+ <item>HEADER_DIRS</item>
+ <item>HEADER_SET</item>
+ <item>HEADER_SETS</item>
+ <item>HIP_ARCHITECTURES</item>
+ <item>HIP_EXTENSIONS</item>
+ <item>HIP_STANDARD</item>
+ <item>HIP_STANDARD_REQUIRED</item>
<item>IMPLICIT_DEPENDS_INCLUDE_TRANSFORM</item>
<item>IMPORTED</item>
<item>IMPORTED_COMMON_LANGUAGE_RUNTIME</item>
@@ -3713,6 +3762,7 @@
<item>IMPORTED_LINK_INTERFACE_MULTIPLICITY</item>
<item>IMPORTED_LOCATION</item>
<item>IMPORTED_NO_SONAME</item>
+ <item>IMPORTED_NO_SYSTEM</item>
<item>IMPORTED_OBJECTS</item>
<item>IMPORTED_SONAME</item>
<item>IMPORT_PREFIX</item>
@@ -3726,6 +3776,7 @@
<item>INTERFACE_COMPILE_DEFINITIONS</item>
<item>INTERFACE_COMPILE_FEATURES</item>
<item>INTERFACE_COMPILE_OPTIONS</item>
+ <item>INTERFACE_HEADER_SETS</item>
<item>INTERFACE_INCLUDE_DIRECTORIES</item>
<item>INTERFACE_LINK_DEPENDS</item>
<item>INTERFACE_LINK_DIRECTORIES</item>
@@ -3753,6 +3804,7 @@
<item>LINK_INTERFACE_LIBRARIES</item>
<item>LINK_INTERFACE_MULTIPLICITY</item>
<item>LINK_LIBRARIES</item>
+ <item>LINK_LIBRARIES_ONLY_TARGETS</item>
<item>LINK_OPTIONS</item>
<item>LINK_SEARCH_END_STATIC</item>
<item>LINK_SEARCH_START_STATIC</item>
@@ -3864,6 +3916,7 @@
<item>XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER</item>
<item>XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS</item>
<item>XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE</item>
+ <item>XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE</item>
<item>XCODE_SCHEME_ENVIRONMENT</item>
<item>XCODE_SCHEME_EXECUTABLE</item>
<item>XCODE_SCHEME_GUARD_MALLOC</item>
@@ -7284,7 +7337,7 @@
</context>
<context attribute="Normal Text" lineEndContext="#stay" name="Detect More target-properties">
- <RegExpr attribute="Property" context="#stay" String="\b(?:XCODE_EMBED_&var_ref_re;_REMOVE_HEADERS_ON_COPY|XCODE_EMBED_&var_ref_re;_PATH|XCODE_EMBED_&var_ref_re;_CODE_SIGN_ON_COPY|XCODE_EMBED_&var_ref_re;|XCODE_ATTRIBUTE_&var_ref_re;|VS_SOURCE_SETTINGS_&var_ref_re;|VS_GLOBAL_&var_ref_re;|VS_DOTNET_REFERENCE_&var_ref_re;|VS_DOTNET_REFERENCEPROP_&var_ref_re;_TAG_&var_ref_re;|STATIC_LIBRARY_FLAGS_&var_ref_re;|RUNTIME_OUTPUT_NAME_&var_ref_re;|RUNTIME_OUTPUT_DIRECTORY_&var_ref_re;|PDB_OUTPUT_DIRECTORY_&var_ref_re;|PDB_NAME_&var_ref_re;|OUTPUT_NAME_&var_ref_re;|OSX_ARCHITECTURES_&var_ref_re;|MAP_IMPORTED_CONFIG_&var_ref_re;|LOCATION_&var_ref_re;|LINK_INTERFACE_MULTIPLICITY_&var_ref_re;|LINK_INTERFACE_LIBRARIES_&var_ref_re;|LINK_FLAGS_&var_ref_re;|LIBRARY_OUTPUT_NAME_&var_ref_re;|LIBRARY_OUTPUT_DIRECTORY_&var_ref_re;|INTERPROCEDURAL_OPTIMIZATION_&var_ref_re;|IMPORTED_SONAME_&var_ref_re;|IMPORTED_OBJECTS_&var_ref_re;|IMPORTED_NO_SONAME_&var_ref_re;|IMPORTED_LOCATION_&var_ref_re;|IMPORTED_LINK_INTERFACE_MULTIPLICITY_&var_ref_re;|IMPORTED_LINK_INTERFACE_LIBRARIES_&var_ref_re;|IMPORTED_LINK_INTERFACE_LANGUAGES_&var_ref_re;|IMPORTED_LINK_DEPENDENT_LIBRARIES_&var_ref_re;|IMPORTED_LIBNAME_&var_ref_re;|IMPORTED_IMPLIB_&var_ref_re;|FRAMEWORK_MULTI_CONFIG_POSTFIX_&var_ref_re;|EXCLUDE_FROM_DEFAULT_BUILD_&var_ref_re;|COMPILE_PDB_OUTPUT_DIRECTORY_&var_ref_re;|COMPILE_PDB_NAME_&var_ref_re;|ARCHIVE_OUTPUT_NAME_&var_ref_re;|ARCHIVE_OUTPUT_DIRECTORY_&var_ref_re;|&var_ref_re;_VISIBILITY_PRESET|&var_ref_re;_POSTFIX|&var_ref_re;_OUTPUT_NAME|&var_ref_re;_LINKER_LAUNCHER|&var_ref_re;_INCLUDE_WHAT_YOU_USE|&var_ref_re;_CPPLINT|&var_ref_re;_CPPCHECK|&var_ref_re;_COMPILER_LAUNCHER|&var_ref_re;_CLANG_TIDY)\b" />
+ <RegExpr attribute="Property" context="#stay" String="\b(?:XCODE_EMBED_&var_ref_re;_REMOVE_HEADERS_ON_COPY|XCODE_EMBED_&var_ref_re;_PATH|XCODE_EMBED_&var_ref_re;_CODE_SIGN_ON_COPY|XCODE_EMBED_&var_ref_re;|XCODE_ATTRIBUTE_&var_ref_re;|VS_SOURCE_SETTINGS_&var_ref_re;|VS_GLOBAL_&var_ref_re;|VS_DOTNET_REFERENCE_&var_ref_re;|VS_DOTNET_REFERENCEPROP_&var_ref_re;_TAG_&var_ref_re;|STATIC_LIBRARY_FLAGS_&var_ref_re;|RUNTIME_OUTPUT_NAME_&var_ref_re;|RUNTIME_OUTPUT_DIRECTORY_&var_ref_re;|PDB_OUTPUT_DIRECTORY_&var_ref_re;|PDB_NAME_&var_ref_re;|OUTPUT_NAME_&var_ref_re;|OSX_ARCHITECTURES_&var_ref_re;|MAP_IMPORTED_CONFIG_&var_ref_re;|LOCATION_&var_ref_re;|LINK_INTERFACE_MULTIPLICITY_&var_ref_re;|LINK_INTERFACE_LIBRARIES_&var_ref_re;|LINK_FLAGS_&var_ref_re;|LIBRARY_OUTPUT_NAME_&var_ref_re;|LIBRARY_OUTPUT_DIRECTORY_&var_ref_re;|INTERPROCEDURAL_OPTIMIZATION_&var_ref_re;|IMPORTED_SONAME_&var_ref_re;|IMPORTED_OBJECTS_&var_ref_re;|IMPORTED_NO_SONAME_&var_ref_re;|IMPORTED_LOCATION_&var_ref_re;|IMPORTED_LINK_INTERFACE_MULTIPLICITY_&var_ref_re;|IMPORTED_LINK_INTERFACE_LIBRARIES_&var_ref_re;|IMPORTED_LINK_INTERFACE_LANGUAGES_&var_ref_re;|IMPORTED_LINK_DEPENDENT_LIBRARIES_&var_ref_re;|IMPORTED_LIBNAME_&var_ref_re;|IMPORTED_IMPLIB_&var_ref_re;|HEADER_SET_&var_ref_re;|HEADER_DIRS_&var_ref_re;|FRAMEWORK_MULTI_CONFIG_POSTFIX_&var_ref_re;|EXCLUDE_FROM_DEFAULT_BUILD_&var_ref_re;|COMPILE_PDB_OUTPUT_DIRECTORY_&var_ref_re;|COMPILE_PDB_NAME_&var_ref_re;|ARCHIVE_OUTPUT_NAME_&var_ref_re;|ARCHIVE_OUTPUT_DIRECTORY_&var_ref_re;|&var_ref_re;_VISIBILITY_PRESET|&var_ref_re;_POSTFIX|&var_ref_re;_OUTPUT_NAME|&var_ref_re;_LINKER_LAUNCHER|&var_ref_re;_INCLUDE_WHAT_YOU_USE|&var_ref_re;_CPPLINT|&var_ref_re;_CPPCHECK|&var_ref_re;_COMPILER_LAUNCHER|&var_ref_re;_CLANG_TIDY)\b" />
</context>
<context attribute="Normal Text" lineEndContext="#stay" name="Detect More source-properties">
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/css.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/css.xml
index 37da5ea3746..d929ba9a345 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/css.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/css.xml
@@ -38,7 +38,7 @@ Changelog:
-->
-<language name="CSS" version="12" kateversion="5.53" section="Markup" extensions="*.css" indenter="cstyle" mimetype="text/css" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL" priority="10">
+<language name="CSS" version="13" kateversion="5.53" section="Markup" extensions="*.css" indenter="cstyle" mimetype="text/css" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL" priority="10">
<!-- https://www.w3.org/Style/CSS/current-work -->
<highlighting>
@@ -665,6 +665,7 @@ Changelog:
<list name="values">
<item>none</item>
<item>hidden</item>
+ <item>initial</item>
<item>dotted</item>
<item>dashed</item>
<item>solid</item>
@@ -729,23 +730,9 @@ Changelog:
<item>katakana</item>
<item>hiragana-iroha</item>
<item>katakana-iroha</item>
- <item>inline</item>
- <item>inline-block</item>
- <item>block</item>
<item>list-item</item>
- <item>run-in</item>
<item>compact</item>
<item>marker</item>
- <item>table</item>
- <item>inline-table</item>
- <item>table-row-group</item>
- <item>table-header-group</item>
- <item>table-footer-group</item>
- <item>table-row</item>
- <item>table-column-group</item>
- <item>table-column</item>
- <item>table-cell</item>
- <item>table-caption</item>
<item>crosshair</item>
<item>default</item>
<item>pointer</item>
@@ -765,15 +752,20 @@ Changelog:
<item>absolute</item>
<item>always</item>
<item>avoid</item>
+ <item>avoid-page</item>
+ <item>avoid-column</item>
+ <item>avoid-region</item>
<item>below</item>
<item>bidi-override</item>
<item>blink</item>
<item>both</item>
+ <item>break-word</item>
<item>capitalize</item>
<item>caption</item>
<item>clip</item>
<item>close-quote</item>
<item>collapse</item>
+ <item>column</item>
<item>condensed</item>
<item>crop</item>
<item>cross</item>
@@ -843,6 +835,41 @@ Changelog:
<item>contain</item>
<item>cover</item>
+ <!-- display -->
+ <!-- https://developer.mozilla.org/fr/docs/Web/CSS/display -->
+ <item>block</item>
+ <item>inline</item>
+ <item>run-in</item>
+
+ <item>flow</item>
+ <item>flow-root</item>
+ <item>table</item>
+ <item>flex</item>
+ <item>grid</item>
+ <item>ruby</item>
+
+ <item>list-item</item>
+
+ <item>table-row-group</item>
+ <item>table-header-group</item>
+ <item>table-footer-group</item>
+ <item>table-row</item>
+ <item>table-cell</item>
+ <item>table-column-group</item>
+ <item>table-column</item>
+ <item>table-caption</item>
+ <item>ruby-base</item>
+ <item>ruby-text</item>
+ <item>ruby-base-container</item>
+ <item>ruby-text-container</item>
+
+ <item>contents</item>
+
+ <item>inline-block</item>
+ <item>inline-table</item>
+ <item>inline-flex</item>
+ <item>inline-grid</item>
+
<!-- transition and animation -->
<item>all</item>
<item>ease</item>
@@ -991,6 +1018,7 @@ Changelog:
<item>pink</item>
<item>plum</item>
<item>powderblue</item>
+ <item>rebeccapurple</item>
<item>rosybrown</item>
<item>royalblue</item>
<item>saddlebrown</item>
@@ -1060,6 +1088,22 @@ Changelog:
<item>var</item>
<item>url</item>
+ <!-- CSS4 -->
+ <item>min</item>
+ <item>max</item>
+ <item>clamp</item>
+ <item>toggle</item>
+ <item>hwb</item>
+ <item>device-cmyk</item>
+ <item>color</item>
+ <item>element</item>
+ <item>image</item>
+ <item>image-set</item>
+ <item>conic-gradient</item>
+
+ <!-- counter style -->
+ <item>symbols</item>
+
<!-- clip -->
<item>rect</item>
@@ -1678,6 +1722,7 @@ Changelog:
<DetectChar attribute="Function" context="#pop#pop" char=")" />
<IncludeRules context="FindComments" />
<IncludeRules context="FindStrings" />
+ <IncludeRules context="FindFunctions" />
<IncludeRules context="FindValues" />
<DetectChar attribute="Separator Symbol" context="#stay" char="," />
</context>
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/python.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/python.xml
index 676872f03fc..76649eeaddd 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/python.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/python.xml
@@ -52,7 +52,7 @@
<!-- v2.07 add support for %prog and co, see bug 142832 -->
<!-- v2.08 add missing overloaders, new Python 3 statements, builtins, and keywords -->
<!-- v2.29 recognize escape sequenzes correctly -->
-<language name="Python" version="22" style="python" indenter="python" kateversion="5.0" section="Scripts" extensions="*.py;*.pyw;SConstruct;SConscript;*.FCMacro" mimetype="application/x-python;text/x-python;text/x-python3" casesensitive="1" author="Michael Bueker" license="">
+<language name="Python" version="23" style="python" indenter="python" kateversion="5.0" section="Scripts" extensions="*.py;*.pyw;SConstruct;SConscript;*.FCMacro" mimetype="application/x-python;text/x-python;text/x-python3" casesensitive="1" author="Michael Bueker" license="">
<highlighting>
<list name="import">
<item>import</item>
@@ -408,10 +408,16 @@
<DetectIdentifier attribute="Normal Text"/>
<RegExpr attribute="Decorator" String="@[_a-zA-Z[:^ascii:]][\._a-zA-Z0-9[:^ascii:]]*" firstNonSpace="true"/>
- <AnyChar attribute="Operator" String="+*/%\|=;&lt;&gt;!^&amp;~-@" context="#stay"/>
+ <AnyChar attribute="Operator" String="+*/%|=;&lt;&gt;!^&amp;~-@" context="#stay"/>
+
+ <LineContinue attribute="Operator" context="MultiLineExpr"/>
<Int attribute="Error"/>
</context>
+ <context name="MultiLineExpr" attribute="Normal Text" lineEndContext="#pop" fallthrough="1" fallthroughContext="#pop">
+ <DetectSpaces attribute="Normal Text"/>
+ <IncludeRules context="StringVariants" />
+ </context>
<!-- https://docs.python.org/2/reference/lexical_analysis.html#integer-and-long-integer-literals -->
<!-- https://docs.python.org/3/reference/lexical_analysis.html#integer-literals -->
diff --git a/src/libs/3rdparty/syntax-highlighting/data/themes/homunculus.theme b/src/libs/3rdparty/syntax-highlighting/data/themes/homunculus.theme
new file mode 100644
index 00000000000..ab48ead1706
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/data/themes/homunculus.theme
@@ -0,0 +1,177 @@
+{
+ "custom-styles": {
+ "Common Lisp": {
+ "Brackets": {
+ "selected-text-color": "#904200",
+ "text-color": "#005f88"
+ }
+ }
+ },
+ "editor-colors": {
+ "BackgroundColor": "#f7f3f3",
+ "BracketMatching": "#fceae2",
+ "CodeFolding": "#94caef",
+ "CurrentLine": "#daecf7",
+ "CurrentLineNumber": "#1e1e1e",
+ "IconBorder": "#f0f0f0",
+ "IndentationLine": "#d2d2d2",
+ "LineNumbers": "#a0a0a0",
+ "MarkBookmark": "#005275",
+ "MarkBreakpointActive": "#ff0000",
+ "MarkBreakpointDisabled": "#ff00ff",
+ "MarkBreakpointReached": "#ffff00",
+ "MarkError": "#ff0000",
+ "MarkExecution": "#a0a0a4",
+ "MarkWarning": "#00ff00",
+ "ModifiedLines": "#fdbc4b",
+ "ReplaceHighlight": "#25d970",
+ "SavedLines": "#2ecc71",
+ "SearchHighlight": "#e0af82",
+ "Separator": "#d5d5d5",
+ "SpellChecking": "#bf0303",
+ "TabMarker": "#d2d2d2",
+ "TemplateBackground": "#d6d2d0",
+ "TemplateFocusedPlaceholder": "#76da98",
+ "TemplatePlaceholder": "#baf8ce",
+ "TemplateReadOnlyPlaceholder": "#f6e6e6",
+ "TextSelection": "#bcbcbc",
+ "WordWrapMarker": "#ededed"
+ },
+ "metadata": {
+ "copyright": [
+ "SPDX-FileCopyrightText: 2021 shenlebantongying <shenlebantongying@gmail.com>"
+ ],
+ "license": "SPDX-License-Identifier: MIT",
+ "name": "Homunculus",
+ "revision": 1
+ },
+ "text-styles": {
+ "Alert": {
+ "background-color": "#f7e6e6",
+ "bold": true,
+ "selected-text-color": "#9c0e0e",
+ "text-color": "#bf0303"
+ },
+ "Annotation": {
+ "selected-text-color": "#000000",
+ "text-color": "#ca60ca"
+ },
+ "Attribute": {
+ "selected-text-color": "#000000",
+ "text-color": "#0057ae"
+ },
+ "BaseN": {
+ "selected-text-color": "#000000",
+ "text-color": "#b08000"
+ },
+ "BuiltIn": {
+ "selected-text-color": "#000000",
+ "text-color": "#644a9b"
+ },
+ "Char": {
+ "selected-text-color": "#000000",
+ "text-color": "#924c9d"
+ },
+ "Comment": {
+ "selected-text-color": "#000000",
+ "text-color": "#505050"
+ },
+ "CommentVar": {
+ "selected-text-color": "#ffffff",
+ "text-color": "#0095ff"
+ },
+ "Constant": {
+ "selected-text-color": "#000000",
+ "text-color": "#aa5500"
+ },
+ "ControlFlow": {
+ "selected-text-color": "#000000",
+ "text-color": "#005f88"
+ },
+ "DataType": {
+ "selected-text-color": "#000000",
+ "text-color": "#0057ae"
+ },
+ "DecVal": {
+ "selected-text-color": "#000000",
+ "text-color": "#b08000"
+ },
+ "Documentation": {
+ "selected-text-color": "#000000",
+ "text-color": "#2a486a"
+ },
+ "Error": {
+ "selected-text-color": "#9c0e0e",
+ "text-color": "#bf0303",
+ "underline": true
+ },
+ "Extension": {
+ "selected-text-color": "#000000",
+ "text-color": "#0095ff"
+ },
+ "Float": {
+ "selected-text-color": "#000000",
+ "text-color": "#b08000"
+ },
+ "Function": {
+ "selected-text-color": "#000000",
+ "text-color": "#721045"
+ },
+ "Import": {
+ "selected-text-color": "#000000",
+ "text-color": "#813e00"
+ },
+ "Information": {
+ "selected-text-color": "#000000",
+ "text-color": "#b08000"
+ },
+ "Keyword": {
+ "selected-text-color": "#000000",
+ "text-color": "#5317ac"
+ },
+ "Normal": {
+ "selected-text-color": "#000000",
+ "text-color": "#303030"
+ },
+ "Operator": {
+ "selected-text-color": "#000000",
+ "text-color": "#b455b4"
+ },
+ "Others": {
+ "selected-text-color": "#000000",
+ "text-color": "#006e28"
+ },
+ "Preprocessor": {
+ "selected-text-color": "#000000",
+ "text-color": "#006e28"
+ },
+ "RegionMarker": {
+ "selected-text-color": "#000000",
+ "text-color": "#0057ae"
+ },
+ "SpecialChar": {
+ "selected-text-color": "#000000",
+ "text-color": "#3daee9"
+ },
+ "SpecialString": {
+ "selected-text-color": "#000000",
+ "text-color": "#854001"
+ },
+ "String": {
+ "selected-text-color": "#000000",
+ "text-color": "#2544bb"
+ },
+ "Variable": {
+ "selected-text-color": "#000000",
+ "text-color": "#0057ae"
+ },
+ "VerbatimString": {
+ "selected-text-color": "#000000",
+ "text-color": "#2544bb"
+ },
+ "Warning": {
+ "selected-text-color": "#9c0e0e",
+ "text-color": "#bf0303"
+ }
+ }
+}
diff --git a/src/libs/3rdparty/syntax-highlighting/patches/0003-Add-qmake-Qbs-files-and-files-generated-by-CMake.patch b/src/libs/3rdparty/syntax-highlighting/patches/0003-Add-qmake-Qbs-files-and-files-generated-by-CMake.patch
index c35188fbec5..2d74873de65 100644
--- a/src/libs/3rdparty/syntax-highlighting/patches/0003-Add-qmake-Qbs-files-and-files-generated-by-CMake.patch
+++ b/src/libs/3rdparty/syntax-highlighting/patches/0003-Add-qmake-Qbs-files-and-files-generated-by-CMake.patch
@@ -4,34 +4,34 @@ Date: Tue, 12 Feb 2019 19:45:08 +0100
Subject: [PATCH 3/6] Add qmake/Qbs files and files generated by CMake
---
- autogenerated/autogenerated.pri | 9 ++
+ autogenerated/autogenerated.pri | 10 +++
+ .../KSyntaxHighlighting/AbstractHighlighter | 1 +
+ .../include/KSyntaxHighlighting/Definition | 1 +
+ .../include/KSyntaxHighlighting/FoldingRegion | 1 +
+ .../include/KSyntaxHighlighting/Format | 1 +
+ .../include/KSyntaxHighlighting/Repository | 1 +
+ .../include/KSyntaxHighlighting/State | 1 +
+ .../KSyntaxHighlighting/SyntaxHighlighter | 1 +
+ .../include/KSyntaxHighlighting/Theme | 1 +
autogenerated/ksyntaxhighlighting_version.h | 12 +++
- autogenerated/src/lib/AbstractHighlighter | 1 +
- autogenerated/src/lib/Definition | 1 +
- autogenerated/src/lib/FoldingRegion | 1 +
- autogenerated/src/lib/Format | 1 +
- autogenerated/src/lib/Repository | 1 +
- autogenerated/src/lib/State | 1 +
- autogenerated/src/lib/SyntaxHighlighter | 1 +
- autogenerated/src/lib/Theme | 1 +
.../src/lib/ksyntaxhighlighting_logging.cpp | 11 +++
.../src/lib/ksyntaxhighlighting_logging.h | 11 +++
data/data.pro | 11 +++
src/lib/ksyntaxhighlighting_export.h | 34 +++++++
syntax-highlighting.pro | 55 ++++++++++++
- syntax-highlighting.qbs | 88 +++++++++++++++++++
+ syntax-highlighting.qbs | 90 +++++++++++++++++++
syntax-highlighting_dependencies.pri | 3 +
- 17 files changed, 242 insertions(+)
+ 17 files changed, 245 insertions(+)
create mode 100644 autogenerated/autogenerated.pri
+ create mode 100644 autogenerated/include/KSyntaxHighlighting/AbstractHighlighter
+ create mode 100644 autogenerated/include/KSyntaxHighlighting/Definition
+ create mode 100644 autogenerated/include/KSyntaxHighlighting/FoldingRegion
+ create mode 100644 autogenerated/include/KSyntaxHighlighting/Format
+ create mode 100644 autogenerated/include/KSyntaxHighlighting/Repository
+ create mode 100644 autogenerated/include/KSyntaxHighlighting/State
+ create mode 100644 autogenerated/include/KSyntaxHighlighting/SyntaxHighlighter
+ create mode 100644 autogenerated/include/KSyntaxHighlighting/Theme
create mode 100644 autogenerated/ksyntaxhighlighting_version.h
- create mode 100644 autogenerated/src/lib/AbstractHighlighter
- create mode 100644 autogenerated/src/lib/Definition
- create mode 100644 autogenerated/src/lib/FoldingRegion
- create mode 100644 autogenerated/src/lib/Format
- create mode 100644 autogenerated/src/lib/Repository
- create mode 100644 autogenerated/src/lib/State
- create mode 100644 autogenerated/src/lib/SyntaxHighlighter
- create mode 100644 autogenerated/src/lib/Theme
create mode 100644 autogenerated/src/lib/ksyntaxhighlighting_logging.cpp
create mode 100644 autogenerated/src/lib/ksyntaxhighlighting_logging.h
create mode 100644 data/data.pro
@@ -42,10 +42,11 @@ Subject: [PATCH 3/6] Add qmake/Qbs files and files generated by CMake
diff --git a/autogenerated/autogenerated.pri b/autogenerated/autogenerated.pri
new file mode 100644
-index 0000000..aee620a
+index 0000000..4121aaf
--- /dev/null
+++ b/autogenerated/autogenerated.pri
-@@ -0,0 +1,9 @@
+@@ -0,0 +1,10 @@
++INCLUDEPATH *= $$PWD/include
+INCLUDEPATH *= $$PWD/src/lib
+INCLUDEPATH *= $$PWD
+
@@ -55,80 +56,80 @@ index 0000000..aee620a
+HEADERS += \
+ $$PWD/ksyntaxhighlighting_version.h \
+ $$PWD/src/lib/ksyntaxhighlighting_logging.h
-diff --git a/autogenerated/ksyntaxhighlighting_version.h b/autogenerated/ksyntaxhighlighting_version.h
-new file mode 100644
-index 0000000..bd31a4d
---- /dev/null
-+++ b/autogenerated/ksyntaxhighlighting_version.h
-@@ -0,0 +1,12 @@
-+// This file was generated by ecm_setup_version(): DO NOT EDIT!
-+
-+#ifndef SyntaxHighlighting_VERSION_H
-+#define SyntaxHighlighting_VERSION_H
-+
-+#define SyntaxHighlighting_VERSION_STRING "5.52.0"
-+#define SyntaxHighlighting_VERSION_MAJOR 5
-+#define SyntaxHighlighting_VERSION_MINOR 52
-+#define SyntaxHighlighting_VERSION_PATCH 0
-+#define SyntaxHighlighting_VERSION ((5<<16)|(52<<8)|(0))
-+
-+#endif
-diff --git a/autogenerated/src/lib/AbstractHighlighter b/autogenerated/src/lib/AbstractHighlighter
+diff --git a/autogenerated/include/KSyntaxHighlighting/AbstractHighlighter b/autogenerated/include/KSyntaxHighlighting/AbstractHighlighter
new file mode 100644
index 0000000..b787873
--- /dev/null
-+++ b/autogenerated/src/lib/AbstractHighlighter
++++ b/autogenerated/include/KSyntaxHighlighting/AbstractHighlighter
@@ -0,0 +1 @@
+#include "abstracthighlighter.h"
-diff --git a/autogenerated/src/lib/Definition b/autogenerated/src/lib/Definition
+diff --git a/autogenerated/include/KSyntaxHighlighting/Definition b/autogenerated/include/KSyntaxHighlighting/Definition
new file mode 100644
index 0000000..2c3241f
--- /dev/null
-+++ b/autogenerated/src/lib/Definition
++++ b/autogenerated/include/KSyntaxHighlighting/Definition
@@ -0,0 +1 @@
+#include "definition.h"
-diff --git a/autogenerated/src/lib/FoldingRegion b/autogenerated/src/lib/FoldingRegion
+diff --git a/autogenerated/include/KSyntaxHighlighting/FoldingRegion b/autogenerated/include/KSyntaxHighlighting/FoldingRegion
new file mode 100644
index 0000000..005b829
--- /dev/null
-+++ b/autogenerated/src/lib/FoldingRegion
++++ b/autogenerated/include/KSyntaxHighlighting/FoldingRegion
@@ -0,0 +1 @@
+#include "foldingregion.h"
-diff --git a/autogenerated/src/lib/Format b/autogenerated/src/lib/Format
+diff --git a/autogenerated/include/KSyntaxHighlighting/Format b/autogenerated/include/KSyntaxHighlighting/Format
new file mode 100644
index 0000000..b0d6a10
--- /dev/null
-+++ b/autogenerated/src/lib/Format
++++ b/autogenerated/include/KSyntaxHighlighting/Format
@@ -0,0 +1 @@
+#include "format.h"
-diff --git a/autogenerated/src/lib/Repository b/autogenerated/src/lib/Repository
+diff --git a/autogenerated/include/KSyntaxHighlighting/Repository b/autogenerated/include/KSyntaxHighlighting/Repository
new file mode 100644
index 0000000..189dbc2
--- /dev/null
-+++ b/autogenerated/src/lib/Repository
++++ b/autogenerated/include/KSyntaxHighlighting/Repository
@@ -0,0 +1 @@
+#include "repository.h"
-diff --git a/autogenerated/src/lib/State b/autogenerated/src/lib/State
+diff --git a/autogenerated/include/KSyntaxHighlighting/State b/autogenerated/include/KSyntaxHighlighting/State
new file mode 100644
index 0000000..e148d70
--- /dev/null
-+++ b/autogenerated/src/lib/State
++++ b/autogenerated/include/KSyntaxHighlighting/State
@@ -0,0 +1 @@
+#include "state.h"
-diff --git a/autogenerated/src/lib/SyntaxHighlighter b/autogenerated/src/lib/SyntaxHighlighter
+diff --git a/autogenerated/include/KSyntaxHighlighting/SyntaxHighlighter b/autogenerated/include/KSyntaxHighlighting/SyntaxHighlighter
new file mode 100644
index 0000000..b429824
--- /dev/null
-+++ b/autogenerated/src/lib/SyntaxHighlighter
++++ b/autogenerated/include/KSyntaxHighlighting/SyntaxHighlighter
@@ -0,0 +1 @@
+#include "syntaxhighlighter.h"
-diff --git a/autogenerated/src/lib/Theme b/autogenerated/src/lib/Theme
+diff --git a/autogenerated/include/KSyntaxHighlighting/Theme b/autogenerated/include/KSyntaxHighlighting/Theme
new file mode 100644
index 0000000..34a3e98
--- /dev/null
-+++ b/autogenerated/src/lib/Theme
++++ b/autogenerated/include/KSyntaxHighlighting/Theme
@@ -0,0 +1 @@
+#include "theme.h"
+diff --git a/autogenerated/ksyntaxhighlighting_version.h b/autogenerated/ksyntaxhighlighting_version.h
+new file mode 100644
+index 0000000..4336b19
+--- /dev/null
++++ b/autogenerated/ksyntaxhighlighting_version.h
+@@ -0,0 +1,12 @@
++// This file was generated by ecm_setup_version(): DO NOT EDIT!
++
++#ifndef SyntaxHighlighting_VERSION_H
++#define SyntaxHighlighting_VERSION_H
++
++#define SyntaxHighlighting_VERSION_STRING "5.90.0"
++#define SyntaxHighlighting_VERSION_MAJOR 5
++#define SyntaxHighlighting_VERSION_MINOR 90
++#define SyntaxHighlighting_VERSION_PATCH 0
++#define SyntaxHighlighting_VERSION ((5<<16)|(90<<8)|(0))
++
++#endif
diff --git a/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp b/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp
new file mode 100644
index 0000000..4082ac4
@@ -283,10 +284,10 @@ index 0000000..38127e1
+ src/lib/wildcardmatcher.cpp \
diff --git a/syntax-highlighting.qbs b/syntax-highlighting.qbs
new file mode 100644
-index 0000000..248ebe0
+index 0000000..4f6de09
--- /dev/null
+++ b/syntax-highlighting.qbs
-@@ -0,0 +1,88 @@
+@@ -0,0 +1,90 @@
+import qbs 1.0
+import qbs.File
+import qbs.FileInfo
@@ -324,6 +325,7 @@ index 0000000..248ebe0
+ cpp.defines: base.concat("KSYNTAXHIGHLIGHTING_LIBRARY")
+ cpp.includePaths: [
+ product.sourceDirectory + "/src/lib/",
++ product.sourceDirectory + "/autogenerated/include/",
+ product.sourceDirectory + "/autogenerated/src/lib/",
+ product.sourceDirectory + "/autogenerated/"
+ ]
@@ -370,6 +372,7 @@ index 0000000..248ebe0
+ Depends { name: "cpp" }
+ cpp.includePaths: [
+ product.sourceDirectory + "/src/lib/",
++ product.sourceDirectory + "/autogenerated/include/",
+ product.sourceDirectory + "/autogenerated/src/lib/",
+ ]
+ }
diff --git a/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt
index 9aede60ad78..77a16faf22e 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt
@@ -19,6 +19,7 @@ elseif(CMAKE_CROSSCOMPILING)
CMAKE_ARGS -DKSYNTAXHIGHLIGHTING_USE_GUI=OFF
-DECM_DIR=${ECM_DIR} -DCMAKE_PREFIX_PATH=${NATIVE_PREFIX}
-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}
+ -DQT_MAJOR_VERSION=${QT_MAJOR_VERSION}
INSTALL_COMMAND ""
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/native_katehighlightingindexer-prefix/src/native_katehighlightingindexer-build/bin/katehighlightingindexer
)
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
index 2ab0e603a29..58533cc7130 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
@@ -47,7 +47,7 @@ set_target_properties(KF5SyntaxHighlighting PROPERTIES
SOVERSION ${SyntaxHighlighting_SOVERSION}
EXPORT_NAME SyntaxHighlighting
)
-target_include_directories(KF5SyntaxHighlighting INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KSyntaxHighlighting;${KDE_INSTALL_INCLUDEDIR_KF}>")
+target_include_directories(KF5SyntaxHighlighting INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KSyntaxHighlighting>")
target_include_directories(KF5SyntaxHighlighting PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR};>")
target_link_libraries(KF5SyntaxHighlighting
PUBLIC
@@ -56,26 +56,38 @@ target_link_libraries(KF5SyntaxHighlighting
Qt${QT_MAJOR_VERSION}::Network
)
-ecm_generate_headers(SyntaxHighlighting_HEADERS
- HEADER_NAMES
- AbstractHighlighter
- Definition
- DefinitionDownloader
- FoldingRegion
- Format
- Repository
- State
- SyntaxHighlighter
- Theme
- WildcardMatcher
+set(Forwarding_Header_Names
+ AbstractHighlighter
+ Definition
+ DefinitionDownloader
+ FoldingRegion
+ Format
+ Repository
+ State
+ SyntaxHighlighter
+ Theme
+ WildcardMatcher
+)
+
+ecm_generate_headers(CamelCase_HEADERS
+ HEADER_NAMES ${Forwarding_Header_Names}
REQUIRED_HEADERS SyntaxHighlighting_HEADERS
+ # Avoid unprefixed headers in build dir (which is part of library's build interface include directories)
+ # and thus visible to anything linking it in the same build, incl. when used with CMake's FetchContent.
+ # E.g. there can be look-up clashes on case-insensitive filesystems with C++20's <format> file and
+ # the library's generated "Format" file.
+ # See BUG: 453759
+ OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/camelcaseheaders
)
install(TARGETS KF5SyntaxHighlighting EXPORT KF5SyntaxHighlightingTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
+
install(FILES
+ ${CamelCase_HEADERS}
${SyntaxHighlighting_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_export.h
- DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KSyntaxHighlighting)
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KSyntaxHighlighting/KSyntaxHighlighting
+)
if(BUILD_QCH)
ecm_add_qch(
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
index 9e19ecda566..3739b55e784 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
@@ -9,9 +9,9 @@
#include "ksyntaxhighlighting_export.h"
+#include <QVector>
#include <memory>
#include <qglobal.h>
-#include <qvector.h>
QT_BEGIN_NAMESPACE
class QString;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt
new file mode 100644
index 00000000000..f40b3ae1ca2
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt
@@ -0,0 +1,17 @@
+# SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org>
+# SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_library(kquicksyntaxhighlightingplugin)
+target_sources(kquicksyntaxhighlightingplugin PRIVATE
+ kquicksyntaxhighlightingplugin.cpp
+ kquicksyntaxhighlighter.cpp
+ repositorywrapper.cpp
+)
+target_link_libraries(kquicksyntaxhighlightingplugin PRIVATE
+ KF5SyntaxHighlighting
+ Qt${QT_MAJOR_VERSION}::Quick
+)
+
+install(TARGETS kquicksyntaxhighlightingplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/syntaxhighlighting)
+install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/syntaxhighlighting)
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp
new file mode 100644
index 00000000000..428a6c40cba
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp
@@ -0,0 +1,112 @@
+/*
+ SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org>
+ SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
+
+ SPDX-License-Identifier: MIT
+*/
+
+#include "kquicksyntaxhighlighter.h"
+
+#include <repository.h>
+#include <syntaxhighlighter.h>
+
+#include <QGuiApplication>
+#include <QPalette>
+#include <QQuickTextDocument>
+#include <QTextDocument>
+
+using namespace KSyntaxHighlighting;
+
+extern Repository *defaultRepository();
+
+KQuickSyntaxHighlighter::KQuickSyntaxHighlighter(QObject *parent)
+ : QObject(parent)
+ , m_textEdit(nullptr)
+ , m_highlighter(new KSyntaxHighlighting::SyntaxHighlighter(this))
+{
+}
+
+KQuickSyntaxHighlighter::~KQuickSyntaxHighlighter() = default;
+
+QObject *KQuickSyntaxHighlighter::textEdit() const
+{
+ return m_textEdit;
+}
+
+void KQuickSyntaxHighlighter::setTextEdit(QObject *textEdit)
+{
+ if (m_textEdit != textEdit) {
+ m_textEdit = textEdit;
+ m_highlighter->setDocument(m_textEdit->property("textDocument").value<QQuickTextDocument *>()->textDocument());
+ }
+}
+
+QVariant KQuickSyntaxHighlighter::definition() const
+{
+ return QVariant::fromValue(m_definition);
+}
+
+void KQuickSyntaxHighlighter::setDefinition(const QVariant &definition)
+{
+ Definition def;
+ if (definition.type() == QVariant::String) {
+ def = unwrappedRepository()->definitionForName(definition.toString());
+ } else {
+ def = definition.value<Definition>();
+ }
+
+ if (m_definition != def) {
+ m_definition = def;
+
+ m_highlighter->setTheme(m_theme.isValid() ? m_theme : unwrappedRepository()->themeForPalette(QGuiApplication::palette()));
+ m_highlighter->setDefinition(def);
+
+ Q_EMIT definitionChanged();
+ }
+}
+
+QVariant KQuickSyntaxHighlighter::theme() const
+{
+ return QVariant::fromValue(m_theme);
+}
+
+void KQuickSyntaxHighlighter::setTheme(const QVariant &theme)
+{
+ Theme t;
+ if (theme.type() == QVariant::String) {
+ t = unwrappedRepository()->theme(theme.toString());
+ } else if (theme.type() == QVariant::Int) {
+ t = unwrappedRepository()->defaultTheme(static_cast<Repository::DefaultTheme>(theme.toInt()));
+ } else {
+ t = theme.value<Theme>();
+ }
+
+ if (m_theme.name() != t.name()) {
+ m_theme = t;
+ m_highlighter->setTheme(m_theme);
+ m_highlighter->rehighlight();
+ Q_EMIT themeChanged();
+ }
+}
+
+RepositoryWrapper *KQuickSyntaxHighlighter::repository() const
+{
+ return m_repository;
+}
+
+void KQuickSyntaxHighlighter::setRepository(RepositoryWrapper *repository)
+{
+ if (m_repository == repository) {
+ return;
+ }
+ m_repository = repository;
+ Q_EMIT repositoryChanged();
+}
+
+Repository *KQuickSyntaxHighlighter::unwrappedRepository() const
+{
+ if (m_repository) {
+ return m_repository->m_repository;
+ }
+ return defaultRepository();
+}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h
new file mode 100644
index 00000000000..38cd7b52af1
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h
@@ -0,0 +1,66 @@
+/*
+ SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org>
+ SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
+
+ SPDX-License-Identifier: MIT
+*/
+
+#ifndef KQUICKSYNTAXHIGHLIGHTER_H
+#define KQUICKSYNTAXHIGHLIGHTER_H
+
+#include "repositorywrapper.h"
+
+#include <definition.h>
+#include <theme.h>
+
+#include <QObject>
+#include <QVariant>
+
+namespace KSyntaxHighlighting
+{
+class Repository;
+class SyntaxHighlighter;
+}
+
+class KQuickSyntaxHighlighter : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QObject *textEdit READ textEdit WRITE setTextEdit NOTIFY textEditChanged)
+ Q_PROPERTY(QVariant definition READ definition WRITE setDefinition NOTIFY definitionChanged)
+ Q_PROPERTY(QVariant theme READ theme WRITE setTheme NOTIFY themeChanged)
+ Q_PROPERTY(RepositoryWrapper *repository READ repository WRITE setRepository NOTIFY repositoryChanged)
+
+public:
+ explicit KQuickSyntaxHighlighter(QObject *parent = nullptr);
+ ~KQuickSyntaxHighlighter() override;
+
+ QObject *textEdit() const;
+ void setTextEdit(QObject *textEdit);
+
+ QVariant definition() const;
+ void setDefinition(const QVariant &definition);
+
+ QVariant theme() const;
+ void setTheme(const QVariant &theme);
+
+ RepositoryWrapper *repository() const;
+ void setRepository(RepositoryWrapper *repository);
+
+Q_SIGNALS:
+ void textEditChanged() const;
+ void definitionChanged() const;
+ void themeChanged();
+ void repositoryChanged();
+
+private:
+ KSyntaxHighlighting::Repository *unwrappedRepository() const;
+
+ QObject *m_textEdit;
+ KSyntaxHighlighting::Definition m_definition;
+ KSyntaxHighlighting::Theme m_theme;
+ RepositoryWrapper *m_repository = nullptr;
+ KSyntaxHighlighting::SyntaxHighlighter *m_highlighter = nullptr;
+};
+
+#endif // KQUICKSYNTAXHIGHLIGHTER_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp
new file mode 100644
index 00000000000..62c571e1b68
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp
@@ -0,0 +1,47 @@
+/*
+ SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org>
+ SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
+
+ SPDX-License-Identifier: MIT
+*/
+
+#include "kquicksyntaxhighlightingplugin.h"
+#include "kquicksyntaxhighlighter.h"
+#include "repositorywrapper.h"
+
+#include <definition.h>
+#include <repository.h>
+#include <theme.h>
+
+
+#include <memory>
+
+using namespace KSyntaxHighlighting;
+
+Repository *defaultRepository()
+{
+ static std::unique_ptr<Repository> s_instance;
+ if (!s_instance) {
+ s_instance = std::make_unique<Repository>();
+ }
+ return s_instance.get();
+}
+
+void KQuickSyntaxHighlightingPlugin::registerTypes(const char *uri)
+{
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.syntaxhighlighting"));
+ qRegisterMetaType<Definition>();
+ qRegisterMetaType<QVector<Definition>>();
+ qRegisterMetaType<Theme>();
+ qRegisterMetaType<QVector<Theme>>();
+ qmlRegisterType<KQuickSyntaxHighlighter>(uri, 1, 0, "SyntaxHighlighter");
+ qmlRegisterUncreatableType<Definition>(uri, 1, 0, "Definition", {});
+ qmlRegisterUncreatableType<Theme>(uri, 1, 0, "Theme", {});
+ qmlRegisterSingletonType<RepositoryWrapper>(uri, 1, 0, "Repository", [](auto engine, auto scriptEngine) {
+ (void)engine;
+ (void)scriptEngine;
+ auto repo = new RepositoryWrapper;
+ repo->m_repository = defaultRepository();
+ return repo;
+ });
+}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.h b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.h
new file mode 100644
index 00000000000..a92405bb156
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.h
@@ -0,0 +1,22 @@
+/*
+ SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org>
+
+ SPDX-License-Identifier: MIT
+*/
+
+#ifndef KQUICKSYNTAXHIGHLIGHTINGPLUGIN_H
+#define KQUICKSYNTAXHIGHLIGHTINGPLUGIN_H
+
+#include <QQmlEngine>
+#include <QQmlExtensionPlugin>
+
+class KQuickSyntaxHighlightingPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+
+public:
+ void registerTypes(const char *uri) override;
+};
+
+#endif // KQUICKSYNTAXHIGHLIGHTINGPLUGIN_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/qmldir b/src/libs/3rdparty/syntax-highlighting/src/quick/qmldir
new file mode 100644
index 00000000000..0837f1bed18
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/qmldir
@@ -0,0 +1,2 @@
+module org.kde.syntaxhighlighting
+plugin kquicksyntaxhighlightingplugin
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/qmldir.license b/src/libs/3rdparty/syntax-highlighting/src/quick/qmldir.license
new file mode 100644
index 00000000000..c475521fa54
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/qmldir.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org>
+SPDX-License-Identifier: CC0-1.0
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp
new file mode 100644
index 00000000000..88030c3912f
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp
@@ -0,0 +1,65 @@
+/*
+ SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
+
+ SPDX-License-Identifier: MIT
+*/
+
+#include "repositorywrapper.h"
+
+#include <definition.h>
+#include <repository.h>
+#include <theme.h>
+
+using namespace KSyntaxHighlighting;
+
+RepositoryWrapper::RepositoryWrapper(QObject *parent)
+ : QObject(parent)
+{
+}
+
+Definition RepositoryWrapper::definitionForName(const QString &defName) const
+{
+ return m_repository->definitionForName(defName);
+}
+
+Definition RepositoryWrapper::definitionForFileName(const QString &fileName) const
+{
+ return m_repository->definitionForFileName(fileName);
+}
+
+QVector<Definition> RepositoryWrapper::definitionsForFileName(const QString &fileName) const
+{
+ return m_repository->definitionsForFileName(fileName);
+}
+
+Definition RepositoryWrapper::definitionForMimeType(const QString &mimeType) const
+{
+ return m_repository->definitionForMimeType(mimeType);
+}
+
+QVector<Definition> RepositoryWrapper::definitionsForMimeType(const QString &mimeType) const
+{
+ return m_repository->definitionsForMimeType(mimeType);
+}
+
+QVector<Definition> RepositoryWrapper::definitions() const
+{
+ return m_repository->definitions();
+}
+
+QVector<Theme> RepositoryWrapper::themes() const
+{
+ return m_repository->themes();
+}
+
+Theme RepositoryWrapper::theme(const QString &themeName) const
+{
+ return m_repository->theme(themeName);
+}
+
+Theme RepositoryWrapper::defaultTheme(DefaultTheme t) const
+{
+ return m_repository->defaultTheme(static_cast<Repository::DefaultTheme>(t));
+}
+
+#include "moc_repositorywrapper.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h b/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h
new file mode 100644
index 00000000000..d4fb8d251cc
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h
@@ -0,0 +1,45 @@
+/*
+ SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
+
+ SPDX-License-Identifier: MIT
+*/
+
+#ifndef REPOSITORYWRAPPER_H
+#define REPOSITORYWRAPPER_H
+
+#include <QObject>
+
+namespace KSyntaxHighlighting
+{
+class Definition;
+class Repository;
+class Theme;
+}
+
+// TODO KF6: merge this into KSyntaxHighlighting::Repository
+class RepositoryWrapper : public QObject
+{
+ Q_OBJECT
+ // TODO KF6: NOTIFY on reload
+ Q_PROPERTY(QVector<KSyntaxHighlighting::Definition> definitions READ definitions CONSTANT)
+ Q_PROPERTY(QVector<KSyntaxHighlighting::Theme> themes READ themes CONSTANT)
+public:
+ explicit RepositoryWrapper(QObject *parent = nullptr);
+
+ Q_INVOKABLE KSyntaxHighlighting::Definition definitionForName(const QString &defName) const;
+ Q_INVOKABLE KSyntaxHighlighting::Definition definitionForFileName(const QString &fileName) const;
+ Q_INVOKABLE QVector<KSyntaxHighlighting::Definition> definitionsForFileName(const QString &fileName) const;
+ Q_INVOKABLE KSyntaxHighlighting::Definition definitionForMimeType(const QString &mimeType) const;
+ Q_INVOKABLE QVector<KSyntaxHighlighting::Definition> definitionsForMimeType(const QString &mimeType) const;
+ QVector<KSyntaxHighlighting::Definition> definitions() const;
+
+ QVector<KSyntaxHighlighting::Theme> themes() const;
+ Q_INVOKABLE KSyntaxHighlighting::Theme theme(const QString &themeName) const;
+ enum DefaultTheme { LightTheme, DarkTheme };
+ Q_ENUM(DefaultTheme)
+ Q_INVOKABLE KSyntaxHighlighting::Theme defaultTheme(DefaultTheme t = LightTheme) const;
+
+ KSyntaxHighlighting::Repository *m_repository = nullptr;
+};
+
+#endif // REPOSITORYWRAPPER_H
diff --git a/src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs b/src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs
index 82b5ea8f753..5dbb334b74d 100644
--- a/src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs
+++ b/src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs
@@ -28,6 +28,7 @@ Project {
cpp.defines: base.concat("KF5SyntaxHighlighting_EXPORTS")
cpp.includePaths: [
product.sourceDirectory + "/src/lib/",
+ product.sourceDirectory + "/autogenerated/include/",
product.sourceDirectory + "/autogenerated/src/lib/",
product.sourceDirectory + "/autogenerated/"
]
@@ -122,6 +123,7 @@ Project {
Depends { name: "cpp" }
cpp.includePaths: [
exportingProduct.sourceDirectory + "/src/lib/",
+ exportingProduct.sourceDirectory + "/autogenerated/include/",
exportingProduct.sourceDirectory + "/autogenerated/src/lib/",
]
}
diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt
index b4ef8af90cd..72658107376 100644
--- a/src/libs/CMakeLists.txt
+++ b/src/libs/CMakeLists.txt
@@ -13,9 +13,7 @@ add_subdirectory(qmldebug)
add_subdirectory(qmleditorwidgets)
add_subdirectory(glsl)
add_subdirectory(languageserverprotocol)
-add_subdirectory(ssh)
add_subdirectory(sqlite)
-add_subdirectory(clangsupport)
add_subdirectory(tracing)
add_subdirectory(qtcreatorcdbext)
@@ -24,13 +22,17 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/qlitehtml/src/CMakeLists.txt)
option(BUILD_LIBRARY_QLITEHTML "Build library qlitehtml." ${BUILD_LIBRARIES_BY_DEFAULT})
set(QLITEHTML_VERSION_COMPAT ${IDE_VERSION_COMPAT} CACHE STRING "")
if(BUILD_LIBRARY_QLITEHTML)
- set(QLITEHTML_BIN_PATH ${IDE_BIN_PATH})
- set(QLITEHTML_LIBRARY_PATH ${IDE_LIBRARY_PATH})
set(QLITEHTML_LIBRARY_ARCHIVE_PATH ${IDE_LIBRARY_ARCHIVE_PATH})
set(QLITEHTML_EXPORT QtCreator)
set(QLITEHTML_DEVEL_COMPONENT Devel)
set(QLITEHTML_DEVEL_EXCLUDE_FROM_ALL ON)
set(QLITEHTML_HEADER_PATH "${IDE_HEADER_INSTALL_PATH}/src/lib/qlitehtml")
+ if (QTC_STATIC_BUILD)
+ set(QLITEHTML_LIBRARY_TYPE STATIC)
+ else()
+ set(QLITEHTML_BIN_PATH ${IDE_BIN_PATH})
+ set(QLITEHTML_LIBRARY_PATH ${IDE_LIBRARY_PATH})
+ endif()
set(QT_VERSION_MAJOR ${Qt5_VERSION_MAJOR})
option(BUILD_TESTING "Build litehtml tests" OFF) # otherwise litehtml downloads googletest
add_subdirectory(qlitehtml/src)
diff --git a/src/libs/advanceddockingsystem/ads_globals.cpp b/src/libs/advanceddockingsystem/ads_globals.cpp
index a93139bd7c9..df8979a1214 100644
--- a/src/libs/advanceddockingsystem/ads_globals.cpp
+++ b/src/libs/advanceddockingsystem/ads_globals.cpp
@@ -39,6 +39,8 @@
#include "docksplitter.h"
#include "iconprovider.h"
+#include <utils/hostosinfo.h>
+
#include <QAbstractButton>
#include <QPainter>
#include <QStyle>
diff --git a/src/libs/advanceddockingsystem/ads_globals.h b/src/libs/advanceddockingsystem/ads_globals.h
index 0de0b4c20c9..19b89155568 100644
--- a/src/libs/advanceddockingsystem/ads_globals.h
+++ b/src/libs/advanceddockingsystem/ads_globals.h
@@ -47,14 +47,12 @@ class QAbstractButton;
class QSplitter;
QT_END_NAMESPACE
-#ifndef ADS_STATIC
-#ifdef ADVANCEDDOCKINGSYSTEM_LIBRARY
-#define ADS_EXPORT Q_DECL_EXPORT
+#if defined(ADVANCEDDOCKINGSYSTEM_LIBRARY)
+# define ADS_EXPORT Q_DECL_EXPORT
+#elif defined(ADVANCEDDOCKINGSYSTEM_STATIC_LIBRARY)
+# define ADS_EXPORT
#else
-#define ADS_EXPORT Q_DECL_IMPORT
-#endif
-#else
-#define ADS_EXPORT
+# define ADS_EXPORT Q_DECL_IMPORT
#endif
//#define ADS_DEBUG_PRINT
diff --git a/src/libs/advanceddockingsystem/dockmanager.cpp b/src/libs/advanceddockingsystem/dockmanager.cpp
index a4c81ff244c..31d6c5ee3f0 100644
--- a/src/libs/advanceddockingsystem/dockmanager.cpp
+++ b/src/libs/advanceddockingsystem/dockmanager.cpp
@@ -49,6 +49,7 @@
#include "workspacedialog.h"
#include <utils/algorithm.h>
+#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <algorithm>
diff --git a/src/libs/advanceddockingsystem/dockoverlay.cpp b/src/libs/advanceddockingsystem/dockoverlay.cpp
index 904425ef13d..046e02dcb81 100644
--- a/src/libs/advanceddockingsystem/dockoverlay.cpp
+++ b/src/libs/advanceddockingsystem/dockoverlay.cpp
@@ -39,7 +39,6 @@
#include "dockareatitlebar.h"
#include <utils/hostosinfo.h>
-#include <utils/porting.h>
#include <QCursor>
#include <QGridLayout>
@@ -422,6 +421,7 @@ namespace ADS {
d->m_lastLocation = InvalidDockWidgetArea;
// Move it over the target.
+ hide();
resize(target->size());
QPoint topLeft = target->mapToGlobal(target->rect().topLeft());
move(topLeft);
@@ -759,9 +759,9 @@ namespace ADS {
{"Arrow", DockOverlayCross::ArrowColor},
{"Shadow", DockOverlayCross::ShadowColor}};
- auto colorList = colors.split(' ', Utils::SkipEmptyParts);
+ auto colorList = colors.split(' ', Qt::SkipEmptyParts);
for (const auto &colorListEntry : colorList) {
- auto componentColor = colorListEntry.split('=', Utils::SkipEmptyParts);
+ auto componentColor = colorListEntry.split('=', Qt::SkipEmptyParts);
int component = colorCompenentStringMap.value(componentColor[0], -1);
if (component < 0)
continue;
diff --git a/src/libs/advanceddockingsystem/floatingdockcontainer.cpp b/src/libs/advanceddockingsystem/floatingdockcontainer.cpp
index 3865f287da9..73e2485db09 100644
--- a/src/libs/advanceddockingsystem/floatingdockcontainer.cpp
+++ b/src/libs/advanceddockingsystem/floatingdockcontainer.cpp
@@ -41,6 +41,9 @@
#include "dockoverlay.h"
#include "dockwidget.h"
#include "linux/floatingwidgettitlebar.h"
+
+#include <utils/hostosinfo.h>
+
#ifdef Q_OS_WIN
#include <windows.h>
#ifdef _MSC_VER
diff --git a/src/libs/advanceddockingsystem/floatingdragpreview.cpp b/src/libs/advanceddockingsystem/floatingdragpreview.cpp
index ece71843417..d56d879decf 100644
--- a/src/libs/advanceddockingsystem/floatingdragpreview.cpp
+++ b/src/libs/advanceddockingsystem/floatingdragpreview.cpp
@@ -41,6 +41,8 @@
#include "dockoverlay.h"
#include "dockwidget.h"
+#include <utils/hostosinfo.h>
+
#include <QApplication>
#include <QEvent>
#include <QKeyEvent>
diff --git a/src/libs/advanceddockingsystem/workspacemodel.cpp b/src/libs/advanceddockingsystem/workspacemodel.cpp
index fc76ce31804..b23cf394f46 100644
--- a/src/libs/advanceddockingsystem/workspacemodel.cpp
+++ b/src/libs/advanceddockingsystem/workspacemodel.cpp
@@ -161,13 +161,9 @@ QHash<int, QByteArray> WorkspaceModel::roleNames() const
{LastWorkspaceRole, "activeWorkspace"},
{ActiveWorkspaceRole, "lastWorkspace"}};
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
auto defaultRoles = QAbstractTableModel::roleNames();
defaultRoles.insert(extraRoles);
return defaultRoles;
-#else
- return QAbstractTableModel::roleNames().unite(extraRoles);
-#endif
}
void WorkspaceModel::sort(int column, Qt::SortOrder order)
diff --git a/src/libs/aggregation/aggregation_global.h b/src/libs/aggregation/aggregation_global.h
index e91129202ab..c8eca8e71cb 100644
--- a/src/libs/aggregation/aggregation_global.h
+++ b/src/libs/aggregation/aggregation_global.h
@@ -29,6 +29,8 @@
#if defined(AGGREGATION_LIBRARY)
# define AGGREGATION_EXPORT Q_DECL_EXPORT
+#elif defined(AGGREGATION_STATIC_LIBRARY)
+# define AGGREGATION_EXPORT
#else
# define AGGREGATION_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/libs/clangsupport/CMakeLists.txt b/src/libs/clangsupport/CMakeLists.txt
deleted file mode 100644
index aa3c0ec3da2..00000000000
--- a/src/libs/clangsupport/CMakeLists.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-set(CLANG_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH})
-
-add_qtc_library(ClangSupport
- DEPENDS Threads::Threads
- PUBLIC_DEPENDS Utils Qt5::Core Qt5::Network
- PUBLIC_DEFINES
- CLANG_VERSION="${CLANG_VERSION}"
- CLANG_INCLUDE_DIR="${LLVM_LIBRARY_DIR}/clang/${CLANG_VERSION}/include"
- CLANG_BINDIR="${LLVM_TOOLS_BINARY_DIR}"
- DEFINES CLANGSUPPORT_BUILD_LIB
- PUBLIC_INCLUDES
- "${CMAKE_CURRENT_LIST_DIR}"
- SOURCES
- alivemessage.cpp alivemessage.h
- annotationsmessage.cpp annotationsmessage.h
- baseserverproxy.cpp baseserverproxy.h
- clangcodemodelclientinterface.cpp clangcodemodelclientinterface.h
- clangcodemodelclientmessages.h
- clangcodemodelclientproxy.cpp clangcodemodelclientproxy.h
- clangcodemodelconnectionclient.cpp clangcodemodelconnectionclient.h
- clangcodemodelserverinterface.cpp clangcodemodelserverinterface.h
- clangcodemodelservermessages.h
- clangcodemodelserverproxy.cpp clangcodemodelserverproxy.h
- clangsupport_global.h
- clangsupportdebugutils.cpp clangsupportdebugutils.h
- codecompletion.cpp codecompletion.h
- codecompletionchunk.cpp codecompletionchunk.h
- completionsmessage.cpp completionsmessage.h
- connectionclient.cpp connectionclient.h
- connectionserver.cpp connectionserver.h
- diagnosticcontainer.cpp diagnosticcontainer.h
- documentschangedmessage.cpp documentschangedmessage.h
- documentsclosedmessage.cpp documentsclosedmessage.h
- documentsopenedmessage.cpp documentsopenedmessage.h
- documentvisibilitychangedmessage.cpp documentvisibilitychangedmessage.h
- echomessage.cpp echomessage.h
- endmessage.cpp endmessage.h
- filecontainer.cpp filecontainer.h
- fixitcontainer.cpp fixitcontainer.h
- followsymbolmessage.cpp followsymbolmessage.h
- ipcclientinterface.h
- ipcclientprovider.h
- ipcinterface.h
- ipcserverinterface.h
- lineprefixer.cpp lineprefixer.h
- messageenvelop.cpp messageenvelop.h
- processcreator.cpp processcreator.h
- processexception.cpp processexception.h
- processhandle.h
- processstartedevent.cpp processstartedevent.h
- readmessageblock.cpp readmessageblock.h
- referencesmessage.cpp referencesmessage.h
- requestannotationsmessage.cpp requestannotationsmessage.h
- requestcompletionsmessage.cpp requestcompletionsmessage.h
- requestfollowsymbolmessage.cpp requestfollowsymbolmessage.h
- requestreferencesmessage.cpp requestreferencesmessage.h
- requesttooltipmessage.cpp requesttooltipmessage.h
- sourcelocationcontainer.cpp sourcelocationcontainer.h
- sourcelocationscontainer.cpp sourcelocationscontainer.h
- sourcerangecontainer.cpp sourcerangecontainer.h
- tokeninfocontainer.cpp tokeninfocontainer.h
- tooltipinfo.cpp tooltipinfo.h
- tooltipmessage.cpp tooltipmessage.h
- unsavedfilesremovedmessage.cpp unsavedfilesremovedmessage.h
- unsavedfilesupdatedmessage.cpp unsavedfilesupdatedmessage.h
- utf8string.cpp utf8string.h
- utf8stringvector.cpp utf8stringvector.h
- writemessageblock.cpp writemessageblock.h
-)
-
-if (NOT TARGET libclang)
- return()
-endif()
diff --git a/src/libs/clangsupport/alivemessage.cpp b/src/libs/clangsupport/alivemessage.cpp
deleted file mode 100644
index 99392fc0fde..00000000000
--- a/src/libs/clangsupport/alivemessage.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "alivemessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const AliveMessage &/*message*/)
-{
- return debug.nospace() << "AliveMessage()";
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/alivemessage.h b/src/libs/clangsupport/alivemessage.h
deleted file mode 100644
index d5f519ac2dc..00000000000
--- a/src/libs/clangsupport/alivemessage.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class AliveMessage
-{
-public:
- friend QDataStream &operator<<(QDataStream &out, const AliveMessage &/*message*/)
- {
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, AliveMessage &/*message*/)
- {
- return in;
- }
-
- friend bool operator==(const AliveMessage &/*first*/, const AliveMessage &/*second*/)
- {
- return true;
- }
-
- friend CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const AliveMessage &message);
-};
-
-DECLARE_MESSAGE(AliveMessage)
-}
diff --git a/src/libs/clangsupport/annotationsmessage.cpp b/src/libs/clangsupport/annotationsmessage.cpp
deleted file mode 100644
index 65349f6801e..00000000000
--- a/src/libs/clangsupport/annotationsmessage.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "annotationsmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const AnnotationsMessage &message)
-{
- debug.nospace() << "AnnotationsMessage("
- << message.fileContainer
- << ", " << message.diagnostics.size()
- << ", " << !message.firstHeaderErrorDiagnostic.text.isEmpty()
- << ", " << message.tokenInfos.size()
- << ", " << message.skippedPreprocessorRanges.size()
- << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/annotationsmessage.h b/src/libs/clangsupport/annotationsmessage.h
deleted file mode 100644
index fcafd002661..00000000000
--- a/src/libs/clangsupport/annotationsmessage.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-#include "diagnosticcontainer.h"
-#include "filecontainer.h"
-#include "tokeninfocontainer.h"
-#include "sourcerangecontainer.h"
-
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT AnnotationsMessage
-{
-public:
- AnnotationsMessage() = default;
- // For pure token infos update
- AnnotationsMessage(const FileContainer &fileContainer,
- const QVector<TokenInfoContainer> &tokenInfos)
- : fileContainer(fileContainer),
- tokenInfos(tokenInfos),
- onlyTokenInfos(true)
- {
- }
- AnnotationsMessage(const FileContainer &fileContainer,
- const QVector<DiagnosticContainer> &diagnostics,
- const DiagnosticContainer &firstHeaderErrorDiagnostic,
- const QVector<TokenInfoContainer> &tokenInfos,
- const QVector<SourceRangeContainer> &skippedPreprocessorRanges)
- : fileContainer(fileContainer)
- , tokenInfos(tokenInfos)
- , diagnostics(diagnostics)
- , firstHeaderErrorDiagnostic(firstHeaderErrorDiagnostic)
- , skippedPreprocessorRanges(skippedPreprocessorRanges)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const AnnotationsMessage &message)
- {
- out << message.onlyTokenInfos;
- out << message.fileContainer;
- out << message.tokenInfos;
- if (message.onlyTokenInfos)
- return out;
- out << message.diagnostics;
- out << message.firstHeaderErrorDiagnostic;
- out << message.skippedPreprocessorRanges;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, AnnotationsMessage &message)
- {
- in >> message.onlyTokenInfos;
- in >> message.fileContainer;
- in >> message.tokenInfos;
- if (message.onlyTokenInfos)
- return in;
- in >> message.diagnostics;
- in >> message.firstHeaderErrorDiagnostic;
- in >> message.skippedPreprocessorRanges;
-
- return in;
- }
-
- friend bool operator==(const AnnotationsMessage &first, const AnnotationsMessage &second)
- {
- return first.fileContainer == second.fileContainer
- && first.diagnostics == second.diagnostics
- && first.firstHeaderErrorDiagnostic == second.firstHeaderErrorDiagnostic
- && first.tokenInfos == second.tokenInfos
- && first.skippedPreprocessorRanges == second.skippedPreprocessorRanges;
- }
-
- friend CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const AnnotationsMessage &message);
-
-public:
- FileContainer fileContainer;
- QVector<TokenInfoContainer> tokenInfos;
- QVector<DiagnosticContainer> diagnostics;
- DiagnosticContainer firstHeaderErrorDiagnostic;
- QVector<SourceRangeContainer> skippedPreprocessorRanges;
- bool onlyTokenInfos = false;
-};
-
-DECLARE_MESSAGE(AnnotationsMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/baseserverproxy.cpp b/src/libs/clangsupport/baseserverproxy.cpp
deleted file mode 100644
index 0c565de269b..00000000000
--- a/src/libs/clangsupport/baseserverproxy.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "baseserverproxy.h"
-#include "messageenvelop.h"
-
-#include <QLocalSocket>
-
-namespace ClangBackEnd {
-
-BaseServerProxy::BaseServerProxy(IpcClientInterface *client, QLocalSocket *localSocket)
- : m_writeMessageBlock(localSocket)
- , m_readMessageBlock(localSocket)
- , m_client(client)
-{
- if (localSocket)
- QObject::connect(localSocket, &QIODevice::readyRead, [this]() {
- BaseServerProxy::readMessages();
- });
-}
-
-BaseServerProxy::BaseServerProxy(IpcClientInterface *client, QIODevice *ioDevice)
- : m_writeMessageBlock(ioDevice)
- , m_readMessageBlock(ioDevice)
- , m_client(client)
-{
- if (ioDevice)
- QObject::connect(ioDevice, &QIODevice::readyRead, [this] () { BaseServerProxy::readMessages(); });
-}
-
-void BaseServerProxy::readMessages()
-{
- for (const auto &message : m_readMessageBlock.readAll())
- m_client->dispatch(message);
-}
-
-void BaseServerProxy::resetState()
-{
- m_writeMessageBlock.resetState();
- m_readMessageBlock.resetState();
-}
-
-void BaseServerProxy::setLocalSocket(QLocalSocket *localSocket)
-{
- QObject::connect(localSocket, &QIODevice::readyRead, [this]() {
- BaseServerProxy::readMessages();
- });
- m_writeMessageBlock.setLocalSocket(localSocket);
- m_readMessageBlock.setIoDevice(localSocket);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/baseserverproxy.h b/src/libs/clangsupport/baseserverproxy.h
deleted file mode 100644
index 797f02999dc..00000000000
--- a/src/libs/clangsupport/baseserverproxy.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ipcclientinterface.h"
-#include "readmessageblock.h"
-#include "writemessageblock.h"
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT BaseServerProxy
-{
- BaseServerProxy(const BaseServerProxy&) = delete;
- BaseServerProxy &operator=(const BaseServerProxy&) = delete;
-
-public:
- BaseServerProxy(IpcClientInterface *client, QLocalSocket *localSocket);
- BaseServerProxy(IpcClientInterface *client, QIODevice *ioDevice);
-
- void readMessages();
-
- void resetState();
-
- void setLocalSocket(QLocalSocket *localSocket);
-
-protected:
- ~BaseServerProxy() = default;
-
-protected:
- ClangBackEnd::WriteMessageBlock m_writeMessageBlock;
- ClangBackEnd::ReadMessageBlock m_readMessageBlock;
- IpcClientInterface *m_client;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangcodemodelclientinterface.cpp b/src/libs/clangsupport/clangcodemodelclientinterface.cpp
deleted file mode 100644
index 5093308fa20..00000000000
--- a/src/libs/clangsupport/clangcodemodelclientinterface.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcodemodelclientinterface.h"
-#include "clangcodemodelclientmessages.h"
-#include "messageenvelop.h"
-
-#include <QDebug>
-#include <QVariant>
-
-namespace ClangBackEnd {
-
-void ClangCodeModelClientInterface::dispatch(const MessageEnvelop &messageEnvelop)
-{
- switch (messageEnvelop.messageType()) {
- case MessageType::AliveMessage:
- alive();
- break;
- case MessageType::EchoMessage:
- echo(messageEnvelop.message<EchoMessage>());
- break;
- case MessageType::CompletionsMessage:
- completions(messageEnvelop.message<CompletionsMessage>());
- break;
- case MessageType::AnnotationsMessage:
- annotations(messageEnvelop.message<AnnotationsMessage>());
- break;
- case MessageType::ReferencesMessage:
- references(messageEnvelop.message<ReferencesMessage>());
- break;
- case MessageType::FollowSymbolMessage:
- followSymbol(messageEnvelop.message<FollowSymbolMessage>());
- break;
- case MessageType::ToolTipMessage:
- tooltip(messageEnvelop.message<ToolTipMessage>());
- break;
- default:
- qWarning() << "Unknown ClangCodeModelClientMessage";
- }
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/clangcodemodelclientinterface.h b/src/libs/clangsupport/clangcodemodelclientinterface.h
deleted file mode 100644
index c366a055c47..00000000000
--- a/src/libs/clangsupport/clangcodemodelclientinterface.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ipcclientinterface.h"
-
-namespace ClangBackEnd {
-
-class ClangCodeModelServerInterface;
-
-class AnnotationsMessage;
-class CompletionsMessage;
-class DocumentVisibilityChangedMessage;
-class DocumentsChangedMessage;
-class DocumentsClosedMessage;
-class DocumentsOpenedMessage;
-class EchoMessage;
-class FollowSymbolMessage;
-class ReferencesMessage;
-class RequestAnnotationsMessage;
-class RequestCompletionsMessage;
-class RequestFollowSymbolMessage;
-class RequestReferencesMessage;
-class RequestToolTipMessage;
-class ToolTipMessage;
-class UnsavedFilesRemovedMessage;
-class UnsavedFilesUpdatedMessage;
-
-class CLANGSUPPORT_EXPORT ClangCodeModelClientInterface : public IpcClientInterface
-{
-public:
- void dispatch(const MessageEnvelop &messageEnvelop) override;
-
- virtual void alive() = 0;
- virtual void echo(const EchoMessage &message) = 0;
- virtual void completions(const CompletionsMessage &message) = 0;
- virtual void annotations(const AnnotationsMessage &message) = 0;
- virtual void references(const ReferencesMessage &message) = 0;
- virtual void followSymbol(const FollowSymbolMessage &message) = 0;
- virtual void tooltip(const ToolTipMessage &message) = 0;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangcodemodelclientmessages.h b/src/libs/clangsupport/clangcodemodelclientmessages.h
deleted file mode 100644
index e73f4b99af1..00000000000
--- a/src/libs/clangsupport/clangcodemodelclientmessages.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "alivemessage.h"
-#include "completionsmessage.h"
-#include "echomessage.h"
-#include "annotationsmessage.h"
-#include "referencesmessage.h"
-#include "followsymbolmessage.h"
-#include "tooltipmessage.h"
diff --git a/src/libs/clangsupport/clangcodemodelclientproxy.cpp b/src/libs/clangsupport/clangcodemodelclientproxy.cpp
deleted file mode 100644
index cf3e699e217..00000000000
--- a/src/libs/clangsupport/clangcodemodelclientproxy.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcodemodelclientproxy.h"
-
-#include "clangcodemodelclientmessages.h"
-#include "clangcodemodelserverinterface.h"
-#include "ipcserverinterface.h"
-#include "messageenvelop.h"
-
-#include <QDebug>
-#include <QLocalSocket>
-#include <QVariant>
-#include <QVector>
-
-namespace ClangBackEnd {
-
-ClangCodeModelClientProxy::ClangCodeModelClientProxy(ClangCodeModelServerInterface *server,
- QLocalSocket *localSocket)
- : m_writeMessageBlock(localSocket)
- , m_readMessageBlock(localSocket)
- , m_server(server)
- , m_ioDevice(localSocket)
-{
- QObject::connect(m_ioDevice, &QIODevice::readyRead, [this]() {
- ClangCodeModelClientProxy::readMessages();
- });
-}
-
-ClangCodeModelClientProxy::ClangCodeModelClientProxy(ClangCodeModelServerInterface *server,
- QIODevice *ioDevice)
- : m_writeMessageBlock(ioDevice)
- , m_readMessageBlock(ioDevice)
- , m_server(server)
- , m_ioDevice(ioDevice)
-{
- QObject::connect(m_ioDevice, &QIODevice::readyRead, [this]() {
- ClangCodeModelClientProxy::readMessages();
- });
-}
-
-ClangCodeModelClientProxy::ClangCodeModelClientProxy(ClangCodeModelClientProxy &&other)
- : m_writeMessageBlock(std::move(other.m_writeMessageBlock)),
- m_readMessageBlock(std::move(other.m_readMessageBlock)),
- m_server(std::move(other.m_server)),
- m_ioDevice(std::move(other.m_ioDevice))
-{
-
-}
-
-ClangCodeModelClientProxy &ClangCodeModelClientProxy::operator=(ClangCodeModelClientProxy &&other)
-{
- m_writeMessageBlock = std::move(other.m_writeMessageBlock);
- m_readMessageBlock = std::move(other.m_readMessageBlock);
- m_server = std::move(other.m_server);
- m_ioDevice = std::move(other.m_ioDevice);
-
- return *this;
-}
-
-void ClangCodeModelClientProxy::alive()
-{
- m_writeMessageBlock.write(AliveMessage());
-}
-
-void ClangCodeModelClientProxy::echo(const EchoMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelClientProxy::completions(const CompletionsMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelClientProxy::annotations(const AnnotationsMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelClientProxy::references(const ReferencesMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelClientProxy::followSymbol(const FollowSymbolMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelClientProxy::tooltip(const ToolTipMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelClientProxy::readMessages()
-{
- for (const MessageEnvelop &message : m_readMessageBlock.readAll())
- m_server->dispatch(message);
-}
-
-bool ClangCodeModelClientProxy::isUsingThatIoDevice(QIODevice *ioDevice) const
-{
- return m_ioDevice == ioDevice;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/clangcodemodelclientproxy.h b/src/libs/clangsupport/clangcodemodelclientproxy.h
deleted file mode 100644
index 4b0e1f9d2a5..00000000000
--- a/src/libs/clangsupport/clangcodemodelclientproxy.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-#include "clangcodemodelclientinterface.h"
-#include "readmessageblock.h"
-#include "writemessageblock.h"
-
-#include <QtGlobal>
-
-#include <memory>
-
-QT_BEGIN_NAMESPACE
-class QLocalServer;
-class QLocalSocket;
-class QIODevice;
-QT_END_NAMESPACE
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT ClangCodeModelClientProxy : public ClangCodeModelClientInterface
-{
-public:
- explicit ClangCodeModelClientProxy(ClangCodeModelServerInterface *server,
- QLocalSocket *localSocket);
- explicit ClangCodeModelClientProxy(ClangCodeModelServerInterface *server, QIODevice *ioDevice);
- ClangCodeModelClientProxy(const ClangCodeModelClientProxy&) = delete;
- const ClangCodeModelClientProxy &operator=(const ClangCodeModelClientProxy&) = delete;
-
- ClangCodeModelClientProxy(ClangCodeModelClientProxy&&other);
- ClangCodeModelClientProxy &operator=(ClangCodeModelClientProxy&&other);
-
- void alive() override;
- void echo(const EchoMessage &message) override;
- void completions(const CompletionsMessage &message) override;
- void annotations(const AnnotationsMessage &message) override;
- void references(const ReferencesMessage &message) override;
- void followSymbol(const FollowSymbolMessage &message) override;
- void tooltip(const ToolTipMessage &message) override;
-
- void readMessages();
-
- bool isUsingThatIoDevice(QIODevice *ioDevice) const;
-
-private:
- ClangBackEnd::WriteMessageBlock m_writeMessageBlock;
- ClangBackEnd::ReadMessageBlock m_readMessageBlock;
- ClangCodeModelServerInterface *m_server = nullptr;
- QIODevice *m_ioDevice = nullptr;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangcodemodelconnectionclient.cpp b/src/libs/clangsupport/clangcodemodelconnectionclient.cpp
deleted file mode 100644
index 618782d1d82..00000000000
--- a/src/libs/clangsupport/clangcodemodelconnectionclient.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcodemodelconnectionclient.h"
-
-#include <utils/environment.h>
-#include <utils/temporarydirectory.h>
-
-#include <QCoreApplication>
-
-namespace ClangBackEnd {
-
-namespace {
-
-QString currentProcessId()
-{
- return QString::number(QCoreApplication::applicationPid());
-}
-
-}
-
-ClangCodeModelConnectionClient::ClangCodeModelConnectionClient(ClangCodeModelClientInterface *client)
- : ConnectionClient(Utils::TemporaryDirectory::masterDirectoryPath()
- + QStringLiteral("/ClangBackEnd-") + currentProcessId())
- , m_serverProxy(client)
-{
- m_processCreator.setTemporaryDirectoryPattern("clangbackend-XXXXXX");
- m_processCreator.setArguments({connectionName()});
-
- Utils::Environment environment;
- environment.set(QStringLiteral("LIBCLANG_NOTHREADS"), QString());
- environment.set(QStringLiteral("LIBCLANG_DISABLE_CRASH_RECOVERY"), QString());
- m_processCreator.setEnvironment(environment);
-
- stdErrPrefixer().setPrefix("clangbackend.stderr: ");
- stdOutPrefixer().setPrefix("clangbackend.stdout: ");
-}
-
-ClangCodeModelConnectionClient::~ClangCodeModelConnectionClient()
-{
- finishProcess();
-}
-
-ClangCodeModelServerProxy &ClangCodeModelConnectionClient::serverProxy()
-{
- return m_serverProxy;
-}
-
-void ClangCodeModelConnectionClient::sendEndCommand()
-{
- m_serverProxy.end();
-}
-
-void ClangCodeModelConnectionClient::resetState()
-{
- m_serverProxy.resetState();
-}
-
-QString ClangCodeModelConnectionClient::outputName() const
-{
- return QStringLiteral("ClangCodeModelConnectionClient");
-}
-
-void ClangCodeModelConnectionClient::newConnectedServer(QLocalSocket *localSocket)
-{
- m_serverProxy.setLocalSocket(localSocket);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangcodemodelconnectionclient.h b/src/libs/clangsupport/clangcodemodelconnectionclient.h
deleted file mode 100644
index 9b0e49ae5b3..00000000000
--- a/src/libs/clangsupport/clangcodemodelconnectionclient.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "connectionclient.h"
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT ClangCodeModelConnectionClient : public ConnectionClient
-{
-public:
- ClangCodeModelConnectionClient(ClangCodeModelClientInterface *client);
- ~ClangCodeModelConnectionClient();
-
- ClangCodeModelServerProxy &serverProxy();
-
-protected:
- void sendEndCommand() override;
- void resetState() override;
- QString outputName() const override;
- void newConnectedServer(QLocalSocket *localSocket) override;
-
-private:
- ClangCodeModelServerProxy m_serverProxy;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangcodemodelserverinterface.cpp b/src/libs/clangsupport/clangcodemodelserverinterface.cpp
deleted file mode 100644
index 440a6e36397..00000000000
--- a/src/libs/clangsupport/clangcodemodelserverinterface.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcodemodelserverinterface.h"
-#include "clangcodemodelservermessages.h"
-#include "messageenvelop.h"
-
-#include <QDebug>
-#include <QVariant>
-
-namespace ClangBackEnd {
-
-void ClangCodeModelServerInterface::dispatch(const MessageEnvelop &messageEnvelop)
-{
- switch (messageEnvelop.messageType()) {
- case MessageType::EndMessage:
- end();
- break;
- case MessageType::DocumentsOpenedMessage:
- documentsOpened(messageEnvelop.message<DocumentsOpenedMessage>());
- break;
- case MessageType::DocumentsChangedMessage:
- documentsChanged(messageEnvelop.message<DocumentsChangedMessage>());
- break;
- case MessageType::DocumentsClosedMessage:
- documentsClosed(messageEnvelop.message<DocumentsClosedMessage>());
- break;
- case MessageType::DocumentVisibilityChangedMessage:
- documentVisibilityChanged(messageEnvelop.message<DocumentVisibilityChangedMessage>());
- break;
- case MessageType::UnsavedFilesUpdatedMessage:
- unsavedFilesUpdated(messageEnvelop.message<UnsavedFilesUpdatedMessage>());
- break;
- case MessageType::UnsavedFilesRemovedMessage:
- unsavedFilesRemoved(messageEnvelop.message<UnsavedFilesRemovedMessage>());
- break;
- case MessageType::RequestCompletionsMessage:
- requestCompletions(messageEnvelop.message<RequestCompletionsMessage>());
- break;
- case MessageType::RequestAnnotationsMessage:
- requestAnnotations(messageEnvelop.message<RequestAnnotationsMessage>());
- break;
- case MessageType::RequestReferencesMessage:
- requestReferences(messageEnvelop.message<RequestReferencesMessage>());
- break;
- case MessageType::RequestFollowSymbolMessage:
- requestFollowSymbol(messageEnvelop.message<RequestFollowSymbolMessage>());
- break;
- case MessageType::RequestToolTipMessage:
- requestToolTip(messageEnvelop.message<RequestToolTipMessage>());
- break;
- default:
- qWarning() << "Unknown ClangCodeModelServerMessage";
- }
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/clangcodemodelserverinterface.h b/src/libs/clangsupport/clangcodemodelserverinterface.h
deleted file mode 100644
index d582b232ea2..00000000000
--- a/src/libs/clangsupport/clangcodemodelserverinterface.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ipcserverinterface.h"
-
-#include "clangcodemodelclientinterface.h"
-
-namespace ClangBackEnd {
-
-class ClangCodeModelClientInterface;
-
-class CLANGSUPPORT_EXPORT ClangCodeModelServerInterface : public IpcServerInterface
-{
-public:
- ~ClangCodeModelServerInterface() override = default;
-
- void dispatch(const MessageEnvelop &messageEnvelop) override;
-
- virtual void end() = 0;
-
- virtual void documentsOpened(const DocumentsOpenedMessage &message) = 0;
- virtual void documentsChanged(const DocumentsChangedMessage &message) = 0;
- virtual void documentsClosed(const DocumentsClosedMessage &message) = 0;
- virtual void documentVisibilityChanged(const DocumentVisibilityChangedMessage &message) = 0;
-
- virtual void unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message) = 0;
- virtual void unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message) = 0;
-
- virtual void requestCompletions(const RequestCompletionsMessage &message) = 0;
- virtual void requestAnnotations(const RequestAnnotationsMessage &message) = 0;
- virtual void requestReferences(const RequestReferencesMessage &message) = 0;
- virtual void requestFollowSymbol(const RequestFollowSymbolMessage &message) = 0;
- virtual void requestToolTip(const RequestToolTipMessage &message) = 0;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangcodemodelservermessages.h b/src/libs/clangsupport/clangcodemodelservermessages.h
deleted file mode 100644
index 5d207d5bcb2..00000000000
--- a/src/libs/clangsupport/clangcodemodelservermessages.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "echomessage.h"
-#include "endmessage.h"
-
-#include "documentsopenedmessage.h"
-#include "documentsclosedmessage.h"
-#include "documentschangedmessage.h"
-#include "documentvisibilitychangedmessage.h"
-
-#include "unsavedfilesupdatedmessage.h"
-#include "unsavedfilesremovedmessage.h"
-
-#include "requestannotationsmessage.h"
-#include "requestcompletionsmessage.h"
-#include "requestfollowsymbolmessage.h"
-#include "requestreferencesmessage.h"
-#include "requesttooltipmessage.h"
diff --git a/src/libs/clangsupport/clangcodemodelserverproxy.cpp b/src/libs/clangsupport/clangcodemodelserverproxy.cpp
deleted file mode 100644
index d77e27bffd0..00000000000
--- a/src/libs/clangsupport/clangcodemodelserverproxy.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcodemodelserverproxy.h"
-
-#include <clangcodemodelclientinterface.h>
-#include <clangcodemodelservermessages.h>
-#include <messageenvelop.h>
-
-namespace ClangBackEnd {
-
-ClangCodeModelServerProxy::ClangCodeModelServerProxy(ClangCodeModelClientInterface *client,
- QLocalSocket *localSocket)
- : BaseServerProxy(client, localSocket)
-{}
-
-ClangCodeModelServerProxy::ClangCodeModelServerProxy(ClangCodeModelClientInterface *client,
- QIODevice *ioDevice)
- : BaseServerProxy(client, ioDevice)
-{
-}
-
-void ClangCodeModelServerProxy::end()
-{
- m_writeMessageBlock.write(EndMessage());
-}
-
-void ClangCodeModelServerProxy::documentsOpened(const DocumentsOpenedMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::documentsChanged(const DocumentsChangedMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::documentsClosed(const DocumentsClosedMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::requestCompletions(const RequestCompletionsMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::requestAnnotations(const RequestAnnotationsMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::requestReferences(const RequestReferencesMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::requestFollowSymbol(const RequestFollowSymbolMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::requestToolTip(const RequestToolTipMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelServerProxy::documentVisibilityChanged(
- const DocumentVisibilityChangedMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/clangcodemodelserverproxy.h b/src/libs/clangsupport/clangcodemodelserverproxy.h
deleted file mode 100644
index 356d0f51f93..00000000000
--- a/src/libs/clangsupport/clangcodemodelserverproxy.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "baseserverproxy.h"
-#include "clangcodemodelserverinterface.h"
-
-#include <QtGlobal>
-#include <QTimer>
-
-#include <memory>
-
-QT_BEGIN_NAMESPACE
-class QVariant;
-class QLocalServer;
-class QLocalSocket;
-QT_END_NAMESPACE
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT ClangCodeModelServerProxy : public BaseServerProxy,
- public ClangCodeModelServerInterface
-{
-public:
- ClangCodeModelServerProxy(ClangCodeModelClientInterface *client, QLocalSocket *localSocket = {});
- ClangCodeModelServerProxy(ClangCodeModelClientInterface *client, QIODevice *ioDevice);
-
- void end() override;
-
- void documentsOpened(const DocumentsOpenedMessage &message) override;
- void documentsChanged(const DocumentsChangedMessage &message) override;
- void documentsClosed(const DocumentsClosedMessage &message) override;
- void documentVisibilityChanged(const DocumentVisibilityChangedMessage &message) override;
-
- void unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message) override;
- void unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message) override;
-
- void requestCompletions(const RequestCompletionsMessage &message) override;
- void requestAnnotations(const RequestAnnotationsMessage &message) override;
- void requestReferences(const RequestReferencesMessage &message) override;
- void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
- void requestToolTip(const RequestToolTipMessage &message) override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangsupport.qbs b/src/libs/clangsupport/clangsupport.qbs
deleted file mode 100644
index f2ca80ce551..00000000000
--- a/src/libs/clangsupport/clangsupport.qbs
+++ /dev/null
@@ -1,27 +0,0 @@
-import qbs 1.0
-
-QtcLibrary {
- name: "ClangSupport"
- targetName: "Clangbackendipc"
-
- Depends { name: "Qt.network" }
- Depends { name: "Utils" }
-
- cpp.defines: base.concat("CLANGSUPPORT_BUILD_LIB")
- cpp.includePaths: base.concat(".")
-
- Group {
- files: [
- "*.h",
- "*.cpp"
- ]
- }
-
- Export {
- Depends { name: "Utils" }
- Depends { name: "Qt.network" }
- cpp.includePaths: [
- "."
- ]
- }
-}
diff --git a/src/libs/clangsupport/clangsupport_global.h b/src/libs/clangsupport/clangsupport_global.h
deleted file mode 100644
index f8428e8ecf1..00000000000
--- a/src/libs/clangsupport/clangsupport_global.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/sizedarray.h>
-
-#include <QtCore/qglobal.h>
-
-#include <utils/smallstringfwd.h>
-
-#if defined(CLANGSUPPORT_BUILD_LIB)
-# define CLANGSUPPORT_EXPORT Q_DECL_EXPORT
-#elif defined(CLANGSUPPORT_BUILD_STATIC_LIB)
-# define CLANGSUPPORT_EXPORT
-#else
-# define CLANGSUPPORT_EXPORT Q_DECL_IMPORT
-#endif
-
-#ifdef Q_CC_GNU
-# define CLANGSUPPORT_GCCEXPORT __attribute__((visibility("default")))
-#else
-# define CLANGSUPPORT_GCCEXPORT
-#endif
-
-#ifndef CLANGBACKENDPROCESSPATH
-# define CLANGBACKENDPROCESSPATH ""
-#endif
-
-#ifdef UNIT_TESTS
-#define unittest_public public
-#else
-#define unittest_public private
-#endif
-
-namespace ClangBackEnd {
-
-enum class DiagnosticSeverity : quint32 // one to one mapping of the clang enum numbers
-{
- Ignored = 0,
- Note = 1,
- Warning = 2,
- Error = 3,
- Fatal = 4
-};
-
-enum class HighlightingType : quint8
-{
- Invalid,
- Keyword,
- StringLiteral,
- NumberLiteral,
- Comment,
- Function,
- VirtualFunction,
- Type,
- PrimitiveType,
- LocalVariable,
- Parameter,
- Field,
- GlobalVariable,
- Enumeration,
- Operator,
- OverloadedOperator,
- Preprocessor,
- PreprocessorDefinition,
- PreprocessorExpansion,
- Punctuation,
- Label,
- Declaration,
- FunctionDefinition,
- OutputArgument,
- Namespace,
- Class,
- Struct,
- Enum,
- Union,
- TypeAlias,
- Typedef,
- QtProperty,
- ObjectiveCClass,
- ObjectiveCCategory,
- ObjectiveCProtocol,
- ObjectiveCInterface,
- ObjectiveCImplementation,
- ObjectiveCProperty,
- ObjectiveCMethod,
- TemplateTypeParameter,
- TemplateTemplateParameter,
- AngleBracketOpen,
- AngleBracketClose,
- DoubleAngleBracketClose, // clang parses ">>" as one token, even if it's closing a nested template
- TernaryIf,
- TernaryElse,
-};
-
-enum class StorageClass : quint8
-{
- Invalid,
- None,
- Extern,
- Static,
- PrivateExtern,
- Auto,
- Register
-};
-
-enum class AccessSpecifier : quint8
-{
- Invalid,
- Public,
- Protected,
- Private
-};
-
-enum class CompletionCorrection : quint32
-{
- NoCorrection,
- DotToArrowCorrection
-};
-
-enum class MessageType : quint8 {
- InvalidMessage,
- AliveMessage,
- EchoMessage,
- EndMessage,
-
- DocumentsOpenedMessage,
- DocumentsChangedMessage,
- DocumentsClosedMessage,
- DocumentVisibilityChangedMessage,
-
- UnsavedFilesUpdatedMessage,
- UnsavedFilesRemovedMessage,
-
- RequestAnnotationsMessage,
- AnnotationsMessage,
-
- RequestReferencesMessage,
- ReferencesMessage,
-
- RequestFollowSymbolMessage,
- FollowSymbolMessage,
-
- RequestToolTipMessage,
- ToolTipMessage,
-
- RequestCompletionsMessage,
- CompletionsMessage,
-};
-
-template<MessageType messageEnumeration>
-struct MessageTypeTrait;
-
-template<class Message>
-struct MessageTrait;
-
-#define DECLARE_MESSAGE(Message) \
-template<> \
-struct MessageTrait<Message> \
-{ \
- static const MessageType enumeration = MessageType::Message; \
-};
-
-using MixinHighlightingTypes = Utils::SizedArray<HighlightingType, 6>;
-
-struct HighlightingTypes {
- HighlightingType mainHighlightingType = HighlightingType::Invalid;
- MixinHighlightingTypes mixinHighlightingTypes;
-};
-
-enum class SourceLocationKind : uchar {
- Definition = 1,
- Declaration,
- DeclarationReference,
- MacroDefinition = 128,
- MacroUndefinition,
- MacroUsage,
- None = 255,
-};
-
-enum class SymbolKind : uchar
-{
- None = 0,
- Enumeration,
- Record,
- Function,
- Variable,
- Macro
-};
-
-using SymbolKinds = Utils::SizedArray<SymbolKind, 8>;
-
-enum class SymbolTag : uchar
-{
- None = 0,
- Class,
- Struct,
- Union,
- MsvcInterface
-};
-
-using SymbolTags = Utils::SizedArray<SymbolTag, 7>;
-
-enum class ProgressType { Invalid, PrecompiledHeader, Indexing, DependencyCreation };
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangsupportdebugutils.cpp b/src/libs/clangsupport/clangsupportdebugutils.cpp
deleted file mode 100644
index 3d49694884a..00000000000
--- a/src/libs/clangsupport/clangsupportdebugutils.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangsupportdebugutils.h"
-
-#include "filecontainer.h"
-
-#include "utf8string.h"
-
-#include <QDir>
-#include <QLoggingCategory>
-#include <QString>
-#include <QTemporaryDir>
-#include <QTemporaryFile>
-
-namespace {
-
-static Q_LOGGING_CATEGORY(timersLog, "qtc.clangbackend.timers", QtWarningMsg);
-
-class DebugInspectionDir : public QTemporaryDir
-{
-public:
- DebugInspectionDir()
- : QTemporaryDir(QDir::tempPath() + QLatin1String("/qtc-clangsupport-XXXXXX"))
- {
- setAutoRemove(false); // Keep around for later inspection.
- }
-};
-
-class DebugInspectionFile : public QTemporaryFile
-{
-public:
- DebugInspectionFile(const QString &directoryPath,
- const Utf8String &id,
- const Utf8String &fileContent)
- : QTemporaryFile(directoryPath + QString::fromUtf8("/%1-XXXXXX").arg(id.toString()))
- {
- setAutoRemove(false); // Keep around for later inspection.
- m_isValid = open() && write(fileContent.constData(), fileContent.byteSize());
- }
-
- bool isValid() const
- {
- return m_isValid;
- }
-
-private:
- bool m_isValid = false;
-};
-
-}
-
-namespace ClangBackEnd {
-
-Utf8String debugWriteFileForInspection(const Utf8String &fileContent, const Utf8String &id)
-{
- static DebugInspectionDir debugInspectionDir;
- if (!debugInspectionDir.isValid())
- return Utf8String();
-
- DebugInspectionFile file(debugInspectionDir.path(), id, fileContent);
- if (file.isValid())
- return Utf8String::fromString(file.fileName());
- return Utf8String();
-}
-
-Utf8String debugId(const FileContainer &fileContainer)
-{
- Utf8String id(Utf8StringLiteral("unsavedfilecontent-"));
- id.append(QFileInfo(fileContainer.filePath).fileName());
- return id;
-}
-
-VerboseScopeDurationTimer::VerboseScopeDurationTimer(const char *id)
- : m_id(id)
-{
- if (timersLog().isDebugEnabled())
- m_timer.start();
-}
-
-VerboseScopeDurationTimer::~VerboseScopeDurationTimer()
-{
- qCDebug(timersLog) << m_id << "needed" << m_timer.elapsed() << "ms";
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangsupportdebugutils.h b/src/libs/clangsupport/clangsupportdebugutils.h
deleted file mode 100644
index 0e4a6da9a82..00000000000
--- a/src/libs/clangsupport/clangsupportdebugutils.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include <QElapsedTimer>
-
-class FileContainer;
-class Utf8String;
-
-namespace ClangBackEnd {
-
-Utf8String debugWriteFileForInspection(const Utf8String &fileContent, const Utf8String &id);
-Utf8String debugId(const FileContainer &fileContainer);
-
-class CLANGSUPPORT_EXPORT VerboseScopeDurationTimer
-{
-public:
- VerboseScopeDurationTimer(const char *id = nullptr);
- ~VerboseScopeDurationTimer();
-
-private:
- const char * const m_id;
- QElapsedTimer m_timer;
-};
-
-} // namespace ClangBackEnd
-
-#define TIME_SCOPE_DURATION(id) ClangBackEnd::VerboseScopeDurationTimer scopeDurationTimer(id)
diff --git a/src/libs/clangsupport/codecompletion.cpp b/src/libs/clangsupport/codecompletion.cpp
deleted file mode 100644
index 6e1b9ca53fe..00000000000
--- a/src/libs/clangsupport/codecompletion.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "codecompletion.h"
-
-#include <QDebug>
-
-#include <ostream>
-
-namespace ClangBackEnd {
-
-static const char *completionKindToString(CodeCompletion::Kind kind)
-{
- switch (kind) {
- case CodeCompletion::Other: return "Other";
- case CodeCompletion::FunctionCompletionKind: return "Function";
- case CodeCompletion::FunctionDefinitionCompletionKind: return "FunctionDefinitionCompletion";
- case CodeCompletion::TemplateFunctionCompletionKind: return "TemplateFunction";
- case CodeCompletion::FunctionOverloadCompletionKind: return "FunctionOverload";
- case CodeCompletion::ConstructorCompletionKind: return "Constructor";
- case CodeCompletion::DestructorCompletionKind: return "Destructor";
- case CodeCompletion::VariableCompletionKind: return "Variable";
- case CodeCompletion::ClassCompletionKind: return "Class";
- case CodeCompletion::TypeAliasCompletionKind: return "TypeAlias";
- case CodeCompletion::TemplateClassCompletionKind: return "TemplateClass";
- case CodeCompletion::EnumerationCompletionKind: return "Enumeration";
- case CodeCompletion::EnumeratorCompletionKind: return "Enumerator";
- case CodeCompletion::NamespaceCompletionKind: return "Namespace";
- case CodeCompletion::PreProcessorCompletionKind: return "PreProcessor";
- case CodeCompletion::SignalCompletionKind: return "Signal";
- case CodeCompletion::SlotCompletionKind: return "Slot";
- case CodeCompletion::ObjCMessageCompletionKind: return "ObjCMessage";
- case CodeCompletion::KeywordCompletionKind: return "Keyword";
- case CodeCompletion::ClangSnippetKind: return "ClangSnippet";
- }
-
- return nullptr;
-}
-
-static const char *availabilityToString(CodeCompletion::Availability availability)
-{
- switch (availability) {
- case CodeCompletion::Available: return "Available";
- case CodeCompletion::Deprecated: return "Deprecated";
- case CodeCompletion::NotAvailable: return "NotAvailable";
- case CodeCompletion::NotAccessible: return "NotAccessible";
- }
- return nullptr;
-}
-
-QDebug operator<<(QDebug debug, const CodeCompletion &message)
-{
- debug.nospace() << "CodeCompletion(";
-
- debug.nospace() << message.text << ", ";
- debug.nospace() << message.priority << ", ";
- debug.nospace() << completionKindToString(message.completionKind) << ", ";
- debug.nospace() << availabilityToString(message.availability) << ", ";
- if (!message.requiredFixIts.isEmpty())
- debug.nospace() << message.requiredFixIts << ", ";
- debug.nospace() << message.hasParameters;
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-std::ostream &operator<<(std::ostream &os, const CodeCompletion::Kind kind)
-{
- return os << completionKindToString(kind);
-}
-
-std::ostream &operator<<(std::ostream &os, const CodeCompletion::Availability availability)
-{
- return os << availabilityToString(availability);
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/codecompletion.h b/src/libs/clangsupport/codecompletion.h
deleted file mode 100644
index a8f0e142b2f..00000000000
--- a/src/libs/clangsupport/codecompletion.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-#include "codecompletionchunk.h"
-#include "fixitcontainer.h"
-
-#include "utf8string.h"
-
-#include <QDataStream>
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class CodeCompletion;
-using CodeCompletions = QVector<CodeCompletion>;
-
-class CodeCompletion
-{
-public:
- enum Kind : uint8_t {
- Other = 0,
- FunctionCompletionKind,
- FunctionDefinitionCompletionKind,
- FunctionOverloadCompletionKind,
- TemplateFunctionCompletionKind,
- ClassCompletionKind,
- ConstructorCompletionKind,
- DestructorCompletionKind,
- VariableCompletionKind,
- TypeAliasCompletionKind,
- TemplateClassCompletionKind,
- EnumerationCompletionKind,
- EnumeratorCompletionKind,
- NamespaceCompletionKind,
- PreProcessorCompletionKind,
- SignalCompletionKind,
- SlotCompletionKind,
- ObjCMessageCompletionKind,
- KeywordCompletionKind,
- ClangSnippetKind
- };
-
- enum Availability : quint32 {
- Available,
- Deprecated,
- NotAvailable,
- NotAccessible
- };
-
-public:
- CodeCompletion() = default;
- CodeCompletion(const Utf8String &text,
- quint32 priority = 0,
- Kind completionKind = Other,
- Availability availability = Available,
- bool hasParameters = false)
- : text(text),
- priority(priority),
- completionKind(completionKind),
- availability(availability),
- hasParameters(hasParameters)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const CodeCompletion &message)
- {
- out << message.text;
- out << message.briefComment;
- out << message.chunks;
- out << message.requiredFixIts;
- out << message.priority;
- out << static_cast<quint32>(message.completionKind);
- out << static_cast<quint32>(message.availability);
- out << message.hasParameters;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, CodeCompletion &message)
- {
- quint32 completionKind;
- quint32 availability;
-
- in >> message.text;
- in >> message.briefComment;
- in >> message.chunks;
- in >> message.requiredFixIts;
- in >> message.priority;
- in >> completionKind;
- in >> availability;
- in >> message.hasParameters;
-
- message.completionKind = static_cast<CodeCompletion::Kind>(completionKind);
- message.availability = static_cast<CodeCompletion::Availability>(availability);
-
- return in;
- }
-
- friend bool operator==(const CodeCompletion &first, const CodeCompletion &second)
- {
- return first.text == second.text
- && first.completionKind == second.completionKind
- && first.requiredFixIts == second.requiredFixIts;
- }
-
-public:
- Utf8String text;
- Utf8String briefComment;
- CodeCompletionChunks chunks;
- QVector<FixItContainer> requiredFixIts;
- quint32 priority = 0;
- Kind completionKind = Other;
- Availability availability = NotAvailable;
- bool hasParameters = false;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const CodeCompletion &message);
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, CodeCompletion::Kind kind);
-
-CLANGSUPPORT_EXPORT std::ostream &operator<<(std::ostream &os, const CodeCompletion::Kind kind);
-CLANGSUPPORT_EXPORT std::ostream &operator<<(std::ostream &os, const CodeCompletion::Availability availability);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/codecompletionchunk.cpp b/src/libs/clangsupport/codecompletionchunk.cpp
deleted file mode 100644
index b4371f24019..00000000000
--- a/src/libs/clangsupport/codecompletionchunk.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "codecompletionchunk.h"
-
-#include <QDebug>
-
-#include <ostream>
-
-namespace ClangBackEnd {
-
-static const char *completionChunkKindToString(CodeCompletionChunk::Kind kind)
-{
- switch (kind) {
- case CodeCompletionChunk::Optional: return "Optional";
- case CodeCompletionChunk::TypedText: return "TypedText";
- case CodeCompletionChunk::Text: return "Text";
- case CodeCompletionChunk::Placeholder: return "Placeholder";
- case CodeCompletionChunk::Informative: return "Informative";
- case CodeCompletionChunk::CurrentParameter: return "CurrentParameter";
- case CodeCompletionChunk::LeftParen: return "LeftParen";
- case CodeCompletionChunk::RightParen: return "RightParen";
- case CodeCompletionChunk::LeftBracket: return "LeftBracket";
- case CodeCompletionChunk::RightBracket: return "RightBracket";
- case CodeCompletionChunk::LeftBrace: return "LeftBrace";
- case CodeCompletionChunk::RightBrace: return "RightBrace";
- case CodeCompletionChunk::LeftAngle: return "LeftAngle";
- case CodeCompletionChunk::RightAngle: return "RightAngle";
- case CodeCompletionChunk::Comma: return "Comma";
- case CodeCompletionChunk::ResultType: return "ResultType";
- case CodeCompletionChunk::Colon: return "Colon";
- case CodeCompletionChunk::SemiColon: return "SemiColon";
- case CodeCompletionChunk::Equal: return "Equal";
- case CodeCompletionChunk::HorizontalSpace: return "HorizontalSpace";
- case CodeCompletionChunk::VerticalSpace: return "VerticalSpace";
- case CodeCompletionChunk::Invalid: return "Invalid";
- }
-
- return nullptr;
-}
-
-QDebug operator<<(QDebug debug, const CodeCompletionChunk &chunk)
-{
- debug.nospace() << "CodeCompletionChunk(";
- debug.nospace() << completionChunkKindToString(chunk.kind) << ", ";
- debug.nospace() << chunk.text;
-
- if (chunk.isOptional)
- debug.nospace() << ", optional";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-std::ostream &operator<<(std::ostream &os, const CodeCompletionChunk::Kind &kind)
-{
- return os << completionChunkKindToString(kind);
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/codecompletionchunk.h b/src/libs/clangsupport/codecompletionchunk.h
deleted file mode 100644
index e04d3351af1..00000000000
--- a/src/libs/clangsupport/codecompletionchunk.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "utf8string.h"
-
-#include <QDataStream>
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class CodeCompletionChunk;
-using CodeCompletionChunks = QVector<CodeCompletionChunk>;
-
-class CodeCompletionChunk
-{
-public:
- enum Kind : quint8 {
- Optional,
- TypedText,
- Text,
- Placeholder,
- Informative,
- CurrentParameter,
- LeftParen,
- RightParen,
- LeftBracket,
- RightBracket,
- LeftBrace,
- RightBrace,
- LeftAngle,
- RightAngle,
- Comma,
- ResultType,
- Colon,
- SemiColon,
- Equal,
- HorizontalSpace,
- VerticalSpace,
- Invalid = 255
- };
-
- CodeCompletionChunk() = default;
- CodeCompletionChunk(Kind kind,
- const Utf8String &text,
- bool isOptional = false)
- : text(text),
- kind(kind),
- isOptional(isOptional)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const CodeCompletionChunk &chunk)
- {
- out << static_cast<quint8>(chunk.kind);
- out << chunk.text;
- out << chunk.isOptional;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, CodeCompletionChunk &chunk)
- {
- quint8 kind;
-
- in >> kind;
- in >> chunk.text;
- in >> chunk.isOptional;
-
- chunk.kind = static_cast<CodeCompletionChunk::Kind>(kind);
-
- return in;
- }
-
- friend bool operator==(const CodeCompletionChunk &first, const CodeCompletionChunk &second)
- {
- return first.kind == second.kind
- && first.text == second.text
- && first.isOptional == second.isOptional;
- }
-
-public:
- Utf8String text;
- Kind kind = Invalid;
- bool isOptional = false;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const CodeCompletionChunk &chunk);
-
-CLANGSUPPORT_EXPORT std::ostream &operator<<(std::ostream &os, const CodeCompletionChunk::Kind &kind);
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/completionsmessage.cpp b/src/libs/clangsupport/completionsmessage.cpp
deleted file mode 100644
index d41f3dfe971..00000000000
--- a/src/libs/clangsupport/completionsmessage.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "completionsmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const CompletionsMessage &message)
-{
- debug.nospace() << "CompletionsMessage(";
-
- debug.nospace() << message.codeCompletions << ", "
- << message.ticketNumber;
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/completionsmessage.h b/src/libs/clangsupport/completionsmessage.h
deleted file mode 100644
index f23256c06fc..00000000000
--- a/src/libs/clangsupport/completionsmessage.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "codecompletion.h"
-
-#include <utf8stringvector.h>
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class CompletionsMessage
-{
-public:
- CompletionsMessage() = default;
- CompletionsMessage(const CodeCompletions &codeCompletions,
- quint64 ticketNumber)
- : codeCompletions(codeCompletions)
- , ticketNumber(ticketNumber)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const CompletionsMessage &message)
- {
- out << message.codeCompletions;
- out << message.ticketNumber;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, CompletionsMessage &message)
- {
- in >> message.codeCompletions;
- in >> message.ticketNumber;
-
- return in;
- }
-
- friend bool operator==(const CompletionsMessage &first, const CompletionsMessage &second)
- {
- return first.ticketNumber == second.ticketNumber
- && first.codeCompletions == second.codeCompletions;
- }
-
-public:
- CodeCompletions codeCompletions;
- quint64 ticketNumber = 0;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const CompletionsMessage &message);
-
-DECLARE_MESSAGE(CompletionsMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/connectionclient.cpp b/src/libs/clangsupport/connectionclient.cpp
deleted file mode 100644
index d9addc6ecee..00000000000
--- a/src/libs/clangsupport/connectionclient.cpp
+++ /dev/null
@@ -1,400 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "connectionclient.h"
-
-#include "clangsupportdebugutils.h"
-#include "processstartedevent.h"
-#include "processexception.h"
-
-#include <utils/hostosinfo.h>
-
-#include <QCoreApplication>
-#include <QMetaMethod>
-#include <QProcess>
-#include <QThread>
-
-using namespace Utils;
-
-namespace ClangBackEnd {
-
-ConnectionClient::ConnectionClient(const QString &connectionName)
- : m_connectionName(connectionName)
-{
- m_processCreator.setObserver(this);
-
- listenForConnections();
-
- m_processAliveTimer.setInterval(10000);
- resetTemporaryDirectory();
-
- static const bool startAliveTimer = !qEnvironmentVariableIntValue("QTC_CLANG_NO_ALIVE_TIMER");
-
- if (startAliveTimer)
- connectAliveTimer();
-
- connectNewConnection();
-}
-
-ConnectionClient::~ConnectionClient()
-{
- QLocalServer::removeServer(connectionName());
-}
-
-void ConnectionClient::startProcessAndConnectToServerAsynchronously()
-{
- m_processIsStarting = true;
-
- m_processFuture = m_processCreator.createProcess();
-}
-
-void ConnectionClient::disconnectFromServer()
-{
- if (m_localSocket)
- m_localSocket->disconnectFromServer();
-}
-
-bool ConnectionClient::isConnected() const
-{
- return m_localSocket && m_localSocket->state() == QLocalSocket::ConnectedState;
-}
-
-void ConnectionClient::ensureMessageIsWritten()
-{
- while (isConnected() && m_localSocket->bytesToWrite() > 0)
- m_localSocket->waitForBytesWritten(50);
-}
-
-void ConnectionClient::sendEndMessage()
-{
- sendEndCommand();
- m_localSocket->flush();
- ensureMessageIsWritten();
-}
-
-void ConnectionClient::resetProcessAliveTimer()
-{
- m_isAliveTimerResetted = true;
- m_processAliveTimer.start();
-}
-
-void ConnectionClient::setProcessAliveTimerInterval(int processTimerInterval)
-{
- m_processAliveTimer.setInterval(processTimerInterval);
-}
-
-const QTemporaryDir &ConnectionClient::temporaryDirectory() const
-{
- return m_processCreator.temporaryDirectory();
-}
-
-LinePrefixer &ConnectionClient::stdErrPrefixer()
-{
- return m_stdErrPrefixer;
-}
-
-LinePrefixer &ConnectionClient::stdOutPrefixer()
-{
- return m_stdOutPrefixer;
-}
-
-QString ConnectionClient::connectionName() const
-{
- return m_connectionName;
-}
-
-bool ConnectionClient::event(QEvent *event)
-{
- if (event->type() == int(ProcessStartedEvent::ProcessStarted)) {
- getProcessFromFuture();
-
- return true;
- };
-
- return false;
-}
-
-void ConnectionClient::restartProcessAsynchronously()
-{
- getProcessFromFuture();
-
- finishProcess(std::move(m_process));
- resetTemporaryDirectory(); // clear left-over preambles
-
- startProcessAndConnectToServerAsynchronously();
-
-}
-
-void ConnectionClient::restartProcessIfTimerIsNotResettedAndSocketIsEmpty()
-{
- if (m_isAliveTimerResetted) {
- m_isAliveTimerResetted = false;
- return; // Already reset, but we were scheduled after.
- }
-
- if (!m_localSocket || m_localSocket->bytesAvailable() > 0)
- return; // We come first, the incoming data was not yet processed.
-
- disconnectLocalSocketDisconnected();
- disconnectFromServer();
- restartProcessAsynchronously();
-}
-
-void ConnectionClient::endProcess(QtcProcess *process)
-{
- if (isProcessRunning(process) && isConnected()) {
- sendEndMessage();
- process->waitForFinished();
- }
-}
-
-void ConnectionClient::terminateProcess(QtcProcess *process)
-{
- if (!HostOsInfo::isWindowsHost() && isProcessRunning()) {
- process->terminate();
- process->waitForFinished(1000);
- }
-}
-
-void ConnectionClient::killProcess(QtcProcess *process)
-{
- if (isProcessRunning(process)) {
- process->kill();
- process->waitForFinished(1000);
- }
-}
-
-void ConnectionClient::finishConnection()
-{
- if (m_localSocket) {
- if (m_localSocket->state() != QLocalSocket::UnconnectedState)
- m_localSocket->disconnectFromServer();
- m_localSocket = nullptr;
- }
-}
-
-void ConnectionClient::printLocalSocketError(QLocalSocket::LocalSocketError socketError)
-{
- if (m_localSocket && socketError != QLocalSocket::ServerNotFoundError)
- qWarning() << outputName() << "LocalSocket Error:" << m_localSocket->errorString();
-}
-
-void ConnectionClient::printStandardOutput()
-{
- qDebug("%s", m_stdOutPrefixer.prefix(m_process->readAllStandardOutput()).constData());
-}
-
-void ConnectionClient::printStandardError()
-{
- qDebug("%s", m_stdErrPrefixer.prefix(m_process->readAllStandardError()).constData());
-}
-
-void ConnectionClient::resetTemporaryDirectory()
-{
- m_processCreator.resetTemporaryDirectory();
-}
-
-void ConnectionClient::initializeProcess(QtcProcess *process)
-{
- connectStandardOutputAndError(process);
-
- resetProcessAliveTimer();
-}
-
-void ConnectionClient::connectLocalSocketDisconnected()
-{
- connect(m_localSocket,
- &QLocalSocket::disconnected,
- this,
- &ConnectionClient::disconnectedFromLocalSocket);
- connect(m_localSocket,
- &QLocalSocket::disconnected,
- this,
- &ConnectionClient::restartProcessAsynchronously);
-}
-
-void ConnectionClient::disconnectLocalSocketDisconnected()
-{
- if (m_localSocket) {
- disconnect(m_localSocket,
- &QLocalSocket::disconnected,
- this,
- &ConnectionClient::restartProcessAsynchronously);
- }
-}
-
-void ConnectionClient::finishProcess()
-{
- finishProcess(std::move(m_process));
- emit processFinished();
-}
-
-bool ConnectionClient::isProcessRunning()
-{
- getProcessFromFuture();
-
- return isProcessRunning(m_process.get());
-}
-
-void ConnectionClient::finishProcess(QProcessUniquePointer &&process)
-{
- disconnectLocalSocketDisconnected();
-
- if (process) {
- m_processAliveTimer.stop();
-
- endProcess(process.get());
- finishConnection();
- terminateProcess(process.get());
- killProcess(process.get());
-
- resetState();
- } else {
- finishConnection();
- }
-}
-
-bool ConnectionClient::waitForEcho()
-{
- return m_localSocket->waitForReadyRead();
-}
-
-bool ConnectionClient::waitForConnected()
-{
- bool isConnected = false;
-
- for (int counter = 0; counter < 100; counter++) {
- isConnected = m_localSocket && m_localSocket->waitForConnected(20);
- if (isConnected)
- return isConnected;
- else {
- QThread::msleep(30);
- QCoreApplication::processEvents();
- }
- }
-
- if (m_localSocket)
- qWarning() << outputName() << "cannot connect:" << m_localSocket->errorString();
-
- return isConnected;
-}
-
-
-QtcProcess *ConnectionClient::processForTestOnly()
-{
- getProcessFromFuture();
-
- return m_process.get();
-}
-
-QIODevice *ConnectionClient::ioDevice()
-{
- return m_localSocket;
-}
-
-bool ConnectionClient::isProcessRunning(QtcProcess *process)
-{
- return process && process->state() == QProcess::Running;
-}
-
-void ConnectionClient::connectStandardOutputAndError(QtcProcess *process) const
-{
- connect(process, &QtcProcess::readyReadStandardOutput, this, &ConnectionClient::printStandardOutput);
- connect(process, &QtcProcess::readyReadStandardError, this, &ConnectionClient::printStandardError);
-}
-
-void ConnectionClient::connectLocalSocketError() const
-{
- void (QLocalSocket::*LocalSocketErrorFunction)(QLocalSocket::LocalSocketError)
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- = &QLocalSocket::error;
-#else
- = &QLocalSocket::errorOccurred;
-#endif
-
- connect(m_localSocket,
- LocalSocketErrorFunction,
- this,
- &ConnectionClient::printLocalSocketError);
-}
-
-void ConnectionClient::connectAliveTimer()
-{
- connect(&m_processAliveTimer,
- &QTimer::timeout,
- this,
- &ConnectionClient::restartProcessIfTimerIsNotResettedAndSocketIsEmpty);
-}
-
-void ConnectionClient::connectNewConnection()
-{
- QObject::connect(&m_localServer,
- &QLocalServer::newConnection,
- this,
- &ConnectionClient::handleNewConnection);
-}
-
-void ConnectionClient::handleNewConnection()
-{
- m_localSocket = m_localServer.nextPendingConnection();
-
- connectLocalSocketError();
- connectLocalSocketDisconnected();
-
- newConnectedServer(m_localSocket);
-
- emit connectedToLocalSocket();
-}
-
-void ConnectionClient::getProcessFromFuture()
-{
- try {
- if (m_processFuture.valid()) {
- m_process = m_processFuture.get();
- m_processIsStarting = false;
-
- initializeProcess(m_process.get());
- }
- } catch (const ProcessException &processExeption) {
- qWarning() << "Clang backend process is not working."
- << QLatin1String(processExeption.what());
- }
-}
-
-void ConnectionClient::listenForConnections()
-{
- bool isListing = m_localServer.listen(connectionName());
-
- if (!isListing)
- qWarning() << "ConnectionClient: QLocalServer is not listing for connections!";
-}
-
-void ConnectionClient::setProcessPath(const QString &processPath)
-{
- m_processCreator.setProcessPath(processPath);
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/connectionclient.h b/src/libs/clangsupport/connectionclient.h
deleted file mode 100644
index aae1864ff5b..00000000000
--- a/src/libs/clangsupport/connectionclient.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangcodemodelserverproxy.h"
-#include "lineprefixer.h"
-#include "processcreator.h"
-#include "processhandle.h"
-
-#include <QLocalServer>
-#include <QLocalSocket>
-#include <QScopedPointer>
-#include <QTemporaryDir>
-
-#include <future>
-#include <memory>
-
-namespace Utils { class QtcProcess; }
-
-class Utf8String;
-class Utf8StringVector;
-
-namespace ClangBackEnd {
-
-class FileContainer;
-
-class CLANGSUPPORT_EXPORT ConnectionClient : public QObject
-{
- Q_OBJECT
-
-public:
- ConnectionClient(const QString &connectionName);
-
- ConnectionClient(const ConnectionClient &) = delete;
- ConnectionClient &operator=(const ConnectionClient &) = delete;
-
- void startProcessAndConnectToServerAsynchronously();
- void disconnectFromServer();
- bool isConnected() const;
-
- void sendEndMessage();
-
- void resetProcessAliveTimer();
- void setProcessAliveTimerInterval(int processTimerInterval);
-
- void setProcessPath(const QString &processPath);
-
- void restartProcessAsynchronously();
- void restartProcessIfTimerIsNotResettedAndSocketIsEmpty();
- void finishProcess();
- bool isProcessRunning();
-
- bool waitForEcho();
- bool waitForConnected();
-
- Utils::QtcProcess *processForTestOnly();
-
-signals:
- void connectedToLocalSocket();
- void disconnectedFromLocalSocket();
- void processFinished();
-
-protected:
- ~ConnectionClient();
-
-protected:
- QIODevice *ioDevice();
- const QTemporaryDir &temporaryDirectory() const;
- LinePrefixer &stdErrPrefixer();
- LinePrefixer &stdOutPrefixer();
-
- virtual void sendEndCommand() = 0;
- virtual void resetState() = 0;
- virtual QString outputName() const = 0;
-
- QString connectionName() const;
- bool event(QEvent* event) override;
-
- virtual void newConnectedServer(QLocalSocket *localSocket) = 0;
-
-private:
- static bool isProcessRunning(Utils::QtcProcess *process);
- void finishProcess(QProcessUniquePointer &&process);
- void endProcess(Utils::QtcProcess *process);
- void terminateProcess(Utils::QtcProcess *process);
- void killProcess(Utils::QtcProcess *process);
- void finishConnection();
- void printLocalSocketError(QLocalSocket::LocalSocketError socketError);
- void printStandardOutput();
- void printStandardError();
- void initializeProcess(Utils::QtcProcess *process);
-
- void resetTemporaryDirectory();
-
- void connectLocalSocketDisconnected();
- void disconnectLocalSocketDisconnected();
- void connectStandardOutputAndError(Utils::QtcProcess *process) const;
- void connectLocalSocketError() const;
- void connectAliveTimer();
- void connectNewConnection();
- void handleNewConnection();
- void getProcessFromFuture();
- void listenForConnections();
-
- void ensureMessageIsWritten();
-
-protected:
- ProcessCreator m_processCreator;
-
-private:
- LinePrefixer m_stdErrPrefixer;
- LinePrefixer m_stdOutPrefixer;
- QLocalServer m_localServer;
- std::future<QProcessUniquePointer> m_processFuture;
- mutable QProcessUniquePointer m_process;
- QLocalSocket *m_localSocket = nullptr;
- QTimer m_processAliveTimer;
- QString m_connectionName;
- bool m_isAliveTimerResetted = false;
- bool m_processIsStarting = false;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/connectionserver.cpp b/src/libs/clangsupport/connectionserver.cpp
deleted file mode 100644
index ae6a3a11360..00000000000
--- a/src/libs/clangsupport/connectionserver.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "connectionserver.h"
-
-namespace ClangBackEnd {
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/connectionserver.h b/src/libs/clangsupport/connectionserver.h
deleted file mode 100644
index 941423b0d15..00000000000
--- a/src/libs/clangsupport/connectionserver.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include <QCoreApplication>
-#include <QLocalServer>
-#include <QLocalSocket>
-#include <QTimer>
-#include <QDebug>
-
-#include <cstdlib>
-#include <memory>
-#include <vector>
-
-namespace ClangBackEnd {
-
-class ClangCodeModelServerInterface;
-class ClangCodeModelClientProxy;
-
-template <typename ServerInterface,
- typename ClientProxy>
-class ConnectionServer
-{
-public:
- ConnectionServer()
- {
- m_aliveTimer.start(5000);
-
- connectAliveTimer();
- connectLocalSocketDisconnet();
- }
-
- ~ConnectionServer()
- {
- if (m_localSocket.state() != QLocalSocket::UnconnectedState)
- m_localSocket.disconnectFromServer();
- }
-
- void start(const QString &connectionName)
- {
- connectToLocalServer(connectionName);
- }
-
- void setServer(ServerInterface *ipcServer)
- {
- this->m_ipcServer = ipcServer;
-
- }
-
- void ensureAliveMessageIsSent()
- {
- if (m_aliveTimer.remainingTime() == 0)
- sendAliveMessage();
- }
-
-private:
- void connectToLocalServer(const QString &connectionName)
- {
- void (QLocalSocket::*LocalSocketErrorFunction)(QLocalSocket::LocalSocketError)
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- = &QLocalSocket::error;
-#else
- = &QLocalSocket::errorOccurred;
-#endif
-
- QObject::connect(&m_localSocket,
- LocalSocketErrorFunction,
- [&] (QLocalSocket::LocalSocketError) {
- qWarning() << "ConnectionServer error:" << m_localSocket.errorString() << connectionName;
- });
-
- m_localSocket.connectToServer(connectionName);
- m_ipcClientProxy = std::make_unique<ClientProxy>(m_ipcServer, &m_localSocket);
-
- m_ipcServer->setClient(m_ipcClientProxy.get());
- }
-
- void sendAliveMessage()
- {
- if (m_ipcClientProxy)
- m_ipcClientProxy->alive();
- }
-
- void handleSocketDisconnect()
- {
- m_ipcClientProxy.reset();
-
- delayedExitApplicationIfNoSockedIsConnected();
- }
-
- void delayedExitApplicationIfNoSockedIsConnected()
- {
- QTimer::singleShot(60000, [&] { exitApplicationIfNoSockedIsConnected(); });
- }
-
- void exitApplicationIfNoSockedIsConnected()
- {
- if (m_localSocket.state() != QLocalSocket::UnconnectedState)
- m_localSocket.disconnectFromServer();
- QCoreApplication::exit();
- }
-
- void connectAliveTimer()
- {
- QObject::connect(&m_aliveTimer,
- &QTimer::timeout,
- [&] { sendAliveMessage(); });
- }
-
- void connectLocalSocketDisconnet()
- {
- QObject::connect(&m_localSocket,
- &QLocalSocket::disconnected,
- [&] { handleSocketDisconnect(); });
- }
-
-private:
- QLocalSocket m_localSocket;
- QTimer m_aliveTimer;
- std::unique_ptr<ClientProxy> m_ipcClientProxy;
- ServerInterface *m_ipcServer = nullptr;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/diagnosticcontainer.cpp b/src/libs/clangsupport/diagnosticcontainer.cpp
deleted file mode 100644
index 1f7c013f0b5..00000000000
--- a/src/libs/clangsupport/diagnosticcontainer.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "diagnosticcontainer.h"
-
-#include <utf8stringvector.h>
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const DiagnosticContainer &container)
-{
- debug.nospace() << "DiagnosticContainer("
- << container.text << ", "
- << container.category << ", "
- << container.enableOption << ", "
- << container.disableOption << ", "
- << container.location << ", "
- << container.ranges << ", "
- << container.fixIts << ", "
- << container.children
- << ")";
-
- return debug;
-}
-
-QDebug operator<<(QDebug debug, const QVector<DiagnosticContainer> &containers)
-{
- debug.nospace() << "{";
- for (int i = 0; i < containers.size(); i++) {
- debug.nospace() << containers[i];
- if (i < containers.size() - 1)
- debug.nospace() << ", ";
- }
- debug.nospace() << "}";
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/diagnosticcontainer.h b/src/libs/clangsupport/diagnosticcontainer.h
deleted file mode 100644
index 65306bf8a6b..00000000000
--- a/src/libs/clangsupport/diagnosticcontainer.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sourcerangecontainer.h"
-#include "fixitcontainer.h"
-
-#include <QDataStream>
-#include <QVector>
-
-#include <utility>
-
-namespace ClangBackEnd {
-
-class DiagnosticContainer
-{
-public:
- DiagnosticContainer() = default;
- DiagnosticContainer(const Utf8String &text,
- const Utf8String &category,
- const std::pair<Utf8String,Utf8String> &options,
- DiagnosticSeverity severity,
- const SourceLocationContainer &location,
- const QVector<SourceRangeContainer> &ranges,
- const QVector<FixItContainer> &fixIts,
- const QVector<DiagnosticContainer> &children)
- : location(location),
- ranges(ranges),
- text(text),
- category(category),
- enableOption(options.first),
- disableOption(options.second),
- children(children),
- fixIts(fixIts),
- severity(severity)
- {
- for (auto it = this->children.begin(); it != this->children.end(); ++it) {
- if (it->text == "note: remove constant to silence this warning") {
- this->children.erase(it);
- break;
- }
- }
- }
-
- friend QDataStream &operator<<(QDataStream &out, const DiagnosticContainer &container)
- {
- out << container.text;
- out << container.category;
- out << container.enableOption;
- out << container.disableOption;
- out << container.location;
- out << static_cast<quint32>(container.severity);
- out << container.ranges;
- out << container.fixIts;
- out << container.children;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, DiagnosticContainer &container)
- {
- quint32 severity;
-
- in >> container.text;
- in >> container.category;
- in >> container.enableOption;
- in >> container.disableOption;
- in >> container.location;
- in >> severity;
- in >> container.ranges;
- in >> container.fixIts;
- in >> container.children;
-
- container.severity = static_cast<DiagnosticSeverity>(severity);
-
- return in;
- }
-
- friend bool operator==(const DiagnosticContainer &first, const DiagnosticContainer &second)
- {
- return first.text == second.text
- && first.location == second.location;
- }
-
- friend bool operator!=(const DiagnosticContainer &first, const DiagnosticContainer &second)
- {
- return !(first == second);
- }
-
-public:
- SourceLocationContainer location;
- QVector<SourceRangeContainer> ranges;
- Utf8String text;
- Utf8String category;
- Utf8String enableOption;
- Utf8String disableOption;
- QVector<DiagnosticContainer> children;
- QVector<FixItContainer> fixIts;
- DiagnosticSeverity severity = DiagnosticSeverity::Ignored;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const DiagnosticContainer &container);
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const QVector<DiagnosticContainer> &container);
-
-
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/documentschangedmessage.cpp b/src/libs/clangsupport/documentschangedmessage.cpp
deleted file mode 100644
index 41512d8081a..00000000000
--- a/src/libs/clangsupport/documentschangedmessage.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "documentschangedmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const DocumentsChangedMessage &message)
-{
- debug.nospace() << "DocumentsChangedMessage(";
-
- for (const FileContainer &fileContainer : message.fileContainers)
- debug.nospace() << fileContainer<< ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/documentschangedmessage.h b/src/libs/clangsupport/documentschangedmessage.h
deleted file mode 100644
index 3d3f6138e8c..00000000000
--- a/src/libs/clangsupport/documentschangedmessage.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "filecontainer.h"
-
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class DocumentsChangedMessage
-{
-public:
- DocumentsChangedMessage() = default;
- DocumentsChangedMessage(const QVector<FileContainer> &fileContainers)
- : fileContainers(fileContainers)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const DocumentsChangedMessage &message)
- {
- out << message.fileContainers;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, DocumentsChangedMessage &message)
- {
- in >> message.fileContainers;
-
- return in;
- }
-
- friend bool operator==(const DocumentsChangedMessage &first,
- const DocumentsChangedMessage &second)
- {
- return first.fileContainers == second.fileContainers;
- }
-
-public:
- QVector<FileContainer> fileContainers;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const DocumentsChangedMessage &message);
-
-DECLARE_MESSAGE(DocumentsChangedMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/documentsclosedmessage.cpp b/src/libs/clangsupport/documentsclosedmessage.cpp
deleted file mode 100644
index 7c23586b836..00000000000
--- a/src/libs/clangsupport/documentsclosedmessage.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "documentsclosedmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const DocumentsClosedMessage &message)
-{
- debug.nospace() << "DocumentsClosedMessage(";
-
- for (const FileContainer &fileContainer : message.fileContainers)
- debug.nospace() << fileContainer << ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/documentsclosedmessage.h b/src/libs/clangsupport/documentsclosedmessage.h
deleted file mode 100644
index 458a78fa8c9..00000000000
--- a/src/libs/clangsupport/documentsclosedmessage.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "filecontainer.h"
-
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class DocumentsClosedMessage
-{
-public:
- DocumentsClosedMessage() = default;
- DocumentsClosedMessage(const QVector<FileContainer> &fileContainers)
- : fileContainers(fileContainers)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const DocumentsClosedMessage &message)
- {
- out << message.fileContainers;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, DocumentsClosedMessage &message)
- {
- in >> message.fileContainers;
-
- return in;
- }
-
- friend bool operator==(const DocumentsClosedMessage &first, const DocumentsClosedMessage &second)
- {
- return first.fileContainers == second.fileContainers;
- }
-
-public:
- QVector<FileContainer> fileContainers;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const DocumentsClosedMessage &message);
-
-DECLARE_MESSAGE(DocumentsClosedMessage);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/documentsopenedmessage.cpp b/src/libs/clangsupport/documentsopenedmessage.cpp
deleted file mode 100644
index 647899b3fe1..00000000000
--- a/src/libs/clangsupport/documentsopenedmessage.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "documentsopenedmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const DocumentsOpenedMessage &message)
-{
- debug.nospace() << "DocumentsOpenedMessage(";
-
- for (const FileContainer &fileContainer : message.fileContainers)
- debug.nospace() << fileContainer<< ", ";
-
- debug.nospace() << message.currentEditorFilePath << ", ";
-
- for (const Utf8String &visibleEditorFilePath : message.visibleEditorFilePaths)
- debug.nospace() << visibleEditorFilePath << ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/documentsopenedmessage.h b/src/libs/clangsupport/documentsopenedmessage.h
deleted file mode 100644
index d56596ef7b8..00000000000
--- a/src/libs/clangsupport/documentsopenedmessage.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "filecontainer.h"
-
-#include <QDataStream>
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class DocumentsOpenedMessage
-{
-public:
- DocumentsOpenedMessage() = default;
- DocumentsOpenedMessage(const QVector<FileContainer> &fileContainers,
- const Utf8String &currentEditorFilePath,
- const Utf8StringVector &visibleEditorFilePaths)
- : fileContainers(fileContainers)
- , currentEditorFilePath(currentEditorFilePath)
- , visibleEditorFilePaths(visibleEditorFilePaths)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const DocumentsOpenedMessage &message)
- {
- out << message.fileContainers;
- out << message.currentEditorFilePath;
- out << message.visibleEditorFilePaths;
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, DocumentsOpenedMessage &message)
- {
- in >> message.fileContainers;
- in >> message.currentEditorFilePath;
- in >> message.visibleEditorFilePaths;
-
- return in;
- }
-
- friend bool operator==(const DocumentsOpenedMessage &first, const DocumentsOpenedMessage &second)
- {
- return first.fileContainers == second.fileContainers
- && first.currentEditorFilePath == second.currentEditorFilePath
- && first.visibleEditorFilePaths == second.visibleEditorFilePaths;
- }
-
-public:
- QVector<FileContainer> fileContainers;
- Utf8String currentEditorFilePath;
- Utf8StringVector visibleEditorFilePaths;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const DocumentsOpenedMessage &message);
-
-DECLARE_MESSAGE(DocumentsOpenedMessage);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/documentvisibilitychangedmessage.cpp b/src/libs/clangsupport/documentvisibilitychangedmessage.cpp
deleted file mode 100644
index f82efe65818..00000000000
--- a/src/libs/clangsupport/documentvisibilitychangedmessage.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "documentvisibilitychangedmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const DocumentVisibilityChangedMessage &message)
-{
- debug.nospace() << "DocumentVisibilityChangedMessage(";
-
- debug.nospace() << message.currentEditorFilePath << ", ";
-
- for (const Utf8String &visibleEditorFilePath : message.visibleEditorFilePaths)
- debug.nospace() << visibleEditorFilePath << ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/documentvisibilitychangedmessage.h b/src/libs/clangsupport/documentvisibilitychangedmessage.h
deleted file mode 100644
index cb8b0f2679e..00000000000
--- a/src/libs/clangsupport/documentvisibilitychangedmessage.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include <utf8stringvector.h>
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class DocumentVisibilityChangedMessage
-{
-public:
- DocumentVisibilityChangedMessage() = default;
- DocumentVisibilityChangedMessage(const Utf8String &currentEditorFilePath,
- const Utf8StringVector &visibleEditorFilePaths)
- : currentEditorFilePath(currentEditorFilePath)
- , visibleEditorFilePaths(visibleEditorFilePaths)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const DocumentVisibilityChangedMessage &message)
- {
- out << message.currentEditorFilePath;
- out << message.visibleEditorFilePaths;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, DocumentVisibilityChangedMessage &message)
- {
- in >> message.currentEditorFilePath;
- in >> message.visibleEditorFilePaths;
-
- return in;
- }
-
- friend bool operator==(const DocumentVisibilityChangedMessage &first,
- const DocumentVisibilityChangedMessage &second)
- {
- return first.currentEditorFilePath == second.currentEditorFilePath
- && first.visibleEditorFilePaths == second.visibleEditorFilePaths;
- }
-
-public:
- Utf8String currentEditorFilePath;
- Utf8StringVector visibleEditorFilePaths;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const DocumentVisibilityChangedMessage &message);
-
-DECLARE_MESSAGE(DocumentVisibilityChangedMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/echomessage.cpp b/src/libs/clangsupport/echomessage.cpp
deleted file mode 100644
index a8842b537b5..00000000000
--- a/src/libs/clangsupport/echomessage.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "echomessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const EchoMessage &)
-{
- return debug.nospace() << "EchoMessage()";
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/echomessage.h b/src/libs/clangsupport/echomessage.h
deleted file mode 100644
index 0b2bf22641c..00000000000
--- a/src/libs/clangsupport/echomessage.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "messageenvelop.h"
-
-namespace ClangBackEnd {
-
-class EchoMessage
-{
-public:
- EchoMessage() = default;
- explicit EchoMessage(const MessageEnvelop &message)
- : message(message)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const EchoMessage &message)
- {
- out << message.message;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, EchoMessage &message)
- {
- in >> message.message;
-
- return in;
- }
-
- friend bool operator==(const EchoMessage &first, const EchoMessage &second)
- {
- return first.message == second.message;
- }
-
-public:
- MessageEnvelop message;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const EchoMessage &message);
-
-DECLARE_MESSAGE(EchoMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/endmessage.cpp b/src/libs/clangsupport/endmessage.cpp
deleted file mode 100644
index 23132d456a4..00000000000
--- a/src/libs/clangsupport/endmessage.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "endmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const EndMessage &/*message*/)
-{
- return debug.nospace() << "EndMessage()";
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/endmessage.h b/src/libs/clangsupport/endmessage.h
deleted file mode 100644
index 8ecb2646b82..00000000000
--- a/src/libs/clangsupport/endmessage.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class EndMessage
-{
-public:
- friend QDataStream &operator<<(QDataStream &out, const EndMessage &/*message*/)
- {
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, EndMessage &/*message*/)
- {
- return in;
- }
-
- friend bool operator==(const EndMessage &/*first*/, const EndMessage &/*second*/)
- {
- return true;
- }
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const EndMessage &message);
-
-DECLARE_MESSAGE(EndMessage)
-}
diff --git a/src/libs/clangsupport/filecontainer.cpp b/src/libs/clangsupport/filecontainer.cpp
deleted file mode 100644
index 0f6f8288c90..00000000000
--- a/src/libs/clangsupport/filecontainer.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "filecontainer.h"
-
-#include "clangsupportdebugutils.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const FileContainer &container)
-{
- debug.nospace() << "FileContainer("
- << container.filePath << ", "
- << container.compilationArguments << ", "
- << container.headerPaths << ", "
- << container.documentRevision << ", "
- << container.textCodecName;
-
- if (container.hasUnsavedFileContent) {
- const Utf8String fileWithContent = debugWriteFileForInspection(
- container.unsavedFileContent,
- debugId(container));
- debug.nospace() << ", "
- << "<" << fileWithContent << ">";
- }
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/filecontainer.h b/src/libs/clangsupport/filecontainer.h
deleted file mode 100644
index 2c7eb088513..00000000000
--- a/src/libs/clangsupport/filecontainer.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "utf8string.h"
-#include <utf8stringvector.h>
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class FileContainer
-{
-public:
- FileContainer() = default;
- FileContainer(const Utf8String &filePath,
- const Utf8String &unsavedFileContent = Utf8String(),
- bool hasUnsavedFileContent = false,
- quint32 documentRevision = 0,
- const Utf8String &textCodecName = Utf8String())
- : filePath(filePath),
- unsavedFileContent(unsavedFileContent),
- textCodecName(textCodecName),
- documentRevision(documentRevision),
- hasUnsavedFileContent(hasUnsavedFileContent)
- {
- }
-
- FileContainer(const Utf8String &filePath,
- const Utf8StringVector &compilationArguments,
- const Utf8StringVector &headerPaths,
- const Utf8String &unsavedFileContent = Utf8String(),
- bool hasUnsavedFileContent = false,
- quint32 documentRevision = 0)
- : filePath(filePath),
- compilationArguments(compilationArguments),
- headerPaths(headerPaths),
- unsavedFileContent(unsavedFileContent),
- documentRevision(documentRevision),
- hasUnsavedFileContent(hasUnsavedFileContent)
- {
- }
-
- FileContainer(const Utf8String &filePath,
- const Utf8StringVector &compilationArguments,
- const Utf8StringVector &headerPaths,
- quint32 documentRevision)
- : filePath(filePath),
- compilationArguments(compilationArguments),
- headerPaths(headerPaths),
- documentRevision(documentRevision),
- hasUnsavedFileContent(false)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const FileContainer &container)
- {
- out << container.filePath;
- out << container.compilationArguments;
- out << container.headerPaths;
- out << container.unsavedFileContent;
- out << container.textCodecName;
- out << container.documentRevision;
- out << container.hasUnsavedFileContent;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, FileContainer &container)
- {
- in >> container.filePath;
- in >> container.compilationArguments;
- in >> container.headerPaths;
- in >> container.unsavedFileContent;
- in >> container.textCodecName;
- in >> container.documentRevision;
- in >> container.hasUnsavedFileContent;
-
- return in;
- }
-
- friend bool operator==(const FileContainer &first, const FileContainer &second)
- {
- return first.filePath == second.filePath;
- }
-
- friend CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const FileContainer &container);
-
-public:
- Utf8String filePath;
- Utf8StringVector compilationArguments;
- Utf8StringVector headerPaths;
- Utf8String unsavedFileContent;
- Utf8String textCodecName;
- quint32 documentRevision = 0;
- bool hasUnsavedFileContent = false;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/fixitcontainer.cpp b/src/libs/clangsupport/fixitcontainer.cpp
deleted file mode 100644
index 7b1404ac9ec..00000000000
--- a/src/libs/clangsupport/fixitcontainer.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "fixitcontainer.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const FixItContainer &container)
-{
- debug.nospace() << "FixItContainer("
- << container.text << ", "
- << container.range
- << ")";
-
- return debug;
-}
-
-QDebug operator<<(QDebug debug, const QVector<FixItContainer> &containers)
-{
- debug.nospace() << "{";
- for (int i = 0; i < containers.size(); i++) {
- debug.nospace() << containers[i];
- if (i < containers.size() - 1)
- debug.nospace() << ", ";
- }
- debug.nospace() << "}";
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/fixitcontainer.h b/src/libs/clangsupport/fixitcontainer.h
deleted file mode 100644
index 81667fe76e0..00000000000
--- a/src/libs/clangsupport/fixitcontainer.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sourcerangecontainer.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class FixItContainer
-{
-public:
- FixItContainer() = default;
- FixItContainer(const Utf8String &text,
- const SourceRangeContainer &range)
- : range(range),
- text(text)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const FixItContainer &container)
- {
- out << container.text;
- out << container.range;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, FixItContainer &container)
- {
- in >> container.text;
- in >> container.range;
-
- return in;
- }
-
- friend bool operator==(const FixItContainer &first, const FixItContainer &second)
- {
- return first.text == second.text && first.range == second.range;
- }
-
-public:
- SourceRangeContainer range;
- Utf8String text;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const FixItContainer &container);
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const QVector<FixItContainer> &container);
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/followsymbolmessage.cpp b/src/libs/clangsupport/followsymbolmessage.cpp
deleted file mode 100644
index df2d1f5e6f6..00000000000
--- a/src/libs/clangsupport/followsymbolmessage.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "followsymbolmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const FollowSymbolResult &result)
-{
- debug.nospace() << "FollowSymbolResult("
- << result.range
- << ", " << result.isResultOnlyForFallBack;
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-QDebug operator<<(QDebug debug, const FollowSymbolMessage &message)
-{
- debug.nospace() << "FollowSymbolMessage("
- << message.fileContainer
- << ", " << message.ticketNumber
- << ", " << message.result;
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/followsymbolmessage.h b/src/libs/clangsupport/followsymbolmessage.h
deleted file mode 100644
index b63820a4ad9..00000000000
--- a/src/libs/clangsupport/followsymbolmessage.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "filecontainer.h"
-#include "sourcerangecontainer.h"
-
-#include <QDataStream>
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class FollowSymbolResult
-{
-public:
- FollowSymbolResult() = default;
- FollowSymbolResult(SourceRangeContainer range)
- : range(std::move(range))
- {}
- FollowSymbolResult(SourceRangeContainer range, bool isResultOnlyForFallBack)
- : range(std::move(range))
- , isResultOnlyForFallBack(isResultOnlyForFallBack)
- {}
-
- friend QDataStream &operator<<(QDataStream &out, const FollowSymbolResult &container)
- {
- out << container.range;
- out << container.isResultOnlyForFallBack;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, FollowSymbolResult &container)
- {
- in >> container.range;
- in >> container.isResultOnlyForFallBack;
-
- return in;
- }
-
- friend bool operator==(const FollowSymbolResult &first, const FollowSymbolResult &second)
- {
- return first.range == second.range
- && first.isResultOnlyForFallBack == second.isResultOnlyForFallBack;
- }
-
- SourceRangeContainer range;
- bool isResultOnlyForFallBack = false;
-};
-
-class FollowSymbolMessage
-{
-public:
- FollowSymbolMessage() = default;
- FollowSymbolMessage(const FileContainer &fileContainer,
- const FollowSymbolResult &result,
- quint64 ticketNumber)
- : fileContainer(fileContainer)
- , result(result)
- , ticketNumber(ticketNumber)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const FollowSymbolMessage &message)
- {
- out << message.fileContainer;
- out << message.result;
- out << message.ticketNumber;
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, FollowSymbolMessage &message)
- {
- in >> message.fileContainer;
- in >> message.result;
- in >> message.ticketNumber;
- return in;
- }
-
- friend bool operator==(const FollowSymbolMessage &first, const FollowSymbolMessage &second)
- {
- return first.ticketNumber == second.ticketNumber
- && first.fileContainer == second.fileContainer
- && first.result == second.result;
- }
-
-public:
- FileContainer fileContainer;
- FollowSymbolResult result;
- quint64 ticketNumber = 0;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolResult &result);
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message);
-
-DECLARE_MESSAGE(FollowSymbolMessage);
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/ipcclientinterface.h b/src/libs/clangsupport/ipcclientinterface.h
deleted file mode 100644
index 7ffc2fa1443..00000000000
--- a/src/libs/clangsupport/ipcclientinterface.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ipcinterface.h"
-
-namespace ClangBackEnd {
-
-class IpcClientInterface : public IpcInterface
-{};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/ipcclientprovider.h b/src/libs/clangsupport/ipcclientprovider.h
deleted file mode 100644
index a4bcb7705cc..00000000000
--- a/src/libs/clangsupport/ipcclientprovider.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-namespace ClangBackEnd {
-
-template <typename ClientType>
-class IpcClientProvider
-{
-public:
- void setClient(ClientType *client)
- {
- client_ = client;
- }
-
- void resetClient()
- {
- client_ = nullptr;
- }
-
- ClientType *client()
- {
- return client_;
- }
-
-private:
- ClientType *client_;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/ipcinterface.h b/src/libs/clangsupport/ipcinterface.h
deleted file mode 100644
index 43a0be2a643..00000000000
--- a/src/libs/clangsupport/ipcinterface.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include <QtGlobal>
-
-namespace ClangBackEnd {
-
-class MessageEnvelop;
-
-class IpcInterface
-{
-public:
- IpcInterface() = default;
- IpcInterface(const IpcInterface &) = delete;
- IpcInterface &operator=(const IpcInterface &) = delete;
-
- virtual void dispatch(const MessageEnvelop &messageEnvelop) = 0;
-
-protected:
- virtual ~IpcInterface() = default;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/ipcserverinterface.h b/src/libs/clangsupport/ipcserverinterface.h
deleted file mode 100644
index df8518fd917..00000000000
--- a/src/libs/clangsupport/ipcserverinterface.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ipcinterface.h"
-
-namespace ClangBackEnd {
-
-class IpcServerInterface : public IpcInterface
-{};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/lineprefixer.cpp b/src/libs/clangsupport/lineprefixer.cpp
deleted file mode 100644
index bdd8df4667b..00000000000
--- a/src/libs/clangsupport/lineprefixer.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "lineprefixer.h"
-
-namespace ClangBackEnd {
-
-LinePrefixer::LinePrefixer(const QByteArray &prefix)
- : m_prefix(prefix)
-{}
-
-void LinePrefixer::setPrefix(const QByteArray &prefix)
-{
- m_prefix = prefix;
-}
-
-QByteArray LinePrefixer::prefix(const QByteArray &text)
-{
- QByteArray output = text;
-
- if (m_previousIsEndingWithNewLine)
- output.prepend(m_prefix);
-
- if (output.endsWith('\n')) {
- m_previousIsEndingWithNewLine = true;
- output.chop(1);
- } else {
- m_previousIsEndingWithNewLine = false;
- }
-
- output.replace("\n", QByteArray("\n" + m_prefix));
- if (m_previousIsEndingWithNewLine)
- output.append('\n');
-
- return output;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/lineprefixer.h b/src/libs/clangsupport/lineprefixer.h
deleted file mode 100644
index 010a5247ea7..00000000000
--- a/src/libs/clangsupport/lineprefixer.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "utf8string.h"
-#include <QString>
-#include <QTextStream>
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT LinePrefixer
-{
-public:
- LinePrefixer() = default;
- LinePrefixer(const QByteArray &prefix);
- void setPrefix(const QByteArray &prefix);
- QByteArray prefix(const QByteArray &text);
-
-private:
- QByteArray m_prefix;
- bool m_previousIsEndingWithNewLine = true;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/messageenvelop.cpp b/src/libs/clangsupport/messageenvelop.cpp
deleted file mode 100644
index f9984f4f693..00000000000
--- a/src/libs/clangsupport/messageenvelop.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "messageenvelop.h"
-
-#include "clangcodemodelclientmessages.h"
-#include "clangcodemodelservermessages.h"
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop)
-{
- debug.nospace() << "MessageEnvelop(";
-
- switch (messageEnvelop.messageType()) {
- case MessageType::EndMessage:
- qDebug() << "EndMessage()";
- break;
- case MessageType::DocumentsOpenedMessage:
- qDebug() << messageEnvelop.message<DocumentsOpenedMessage>();
- break;
- case MessageType::DocumentsChangedMessage:
- qDebug() << messageEnvelop.message<DocumentsChangedMessage>();
- break;
- case MessageType::DocumentsClosedMessage:
- qDebug() << messageEnvelop.message<DocumentsClosedMessage>();
- break;
- case MessageType::DocumentVisibilityChangedMessage:
- qDebug() << messageEnvelop.message<DocumentVisibilityChangedMessage>();
- break;
- case MessageType::UnsavedFilesUpdatedMessage:
- qDebug() << messageEnvelop.message<UnsavedFilesUpdatedMessage>();
- break;
- case MessageType::UnsavedFilesRemovedMessage:
- qDebug() << messageEnvelop.message<UnsavedFilesRemovedMessage>();
- break;
- case MessageType::RequestCompletionsMessage:
- qDebug() << messageEnvelop.message<RequestCompletionsMessage>();
- break;
- case MessageType::RequestAnnotationsMessage:
- qDebug() << messageEnvelop.message<RequestAnnotationsMessage>();
- break;
- case MessageType::RequestReferencesMessage:
- qDebug() << messageEnvelop.message<RequestReferencesMessage>();
- break;
- case MessageType::RequestToolTipMessage:
- qDebug() << messageEnvelop.message<RequestToolTipMessage>();
- break;
- case MessageType::AliveMessage:
- qDebug() << "AliveMessage()";
- break;
- case MessageType::EchoMessage:
- qDebug() << messageEnvelop.message<EchoMessage>();
- break;
- case MessageType::CompletionsMessage:
- qDebug() << messageEnvelop.message<CompletionsMessage>();
- break;
- case MessageType::ReferencesMessage:
- qDebug() << messageEnvelop.message<ReferencesMessage>();
- break;
- case MessageType::ToolTipMessage:
- qDebug() << messageEnvelop.message<ToolTipMessage>();
- break;
- case MessageType::AnnotationsMessage:
- qDebug() << messageEnvelop.message<AnnotationsMessage>();
- break;
- default:
- qWarning() << "Unknown Message";
- }
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/messageenvelop.h b/src/libs/clangsupport/messageenvelop.h
deleted file mode 100644
index 699e8ddf42e..00000000000
--- a/src/libs/clangsupport/messageenvelop.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include <QByteArray>
-#include <QDataStream>
-#include <QDebug>
-#include <QIODevice>
-
-namespace ClangBackEnd {
-
-class MessageEnvelop
-{
-public:
- MessageEnvelop() = default;
-
- template <class Message, typename = std::enable_if_t<
- std::is_enum_v<decltype(MessageTrait<Message>::enumeration)>>>
- MessageEnvelop(const Message &message)
- : messageType_(MessageTrait<Message>::enumeration)
- {
- QDataStream stream(&data, QIODevice::WriteOnly);
- stream << message;
- }
-
- template <class Message>
- Message message() const
- {
- Message message;
-
- QDataStream stream(&data, QIODevice::ReadOnly);
- stream >> message;
-
- return message;
- }
-
- MessageType messageType() const
- {
- return messageType_;
- }
-
- bool isValid() const
- {
- return messageType_ != MessageType::InvalidMessage;
- }
-
- friend
- QDataStream &operator >>(QDataStream& in, MessageType& messageType)
- {
- quint32 messageTypeAsInt;
- in >> messageTypeAsInt;
- messageType = MessageType(messageTypeAsInt);
-
- return in;
- }
-
- friend
- QDataStream &operator<<(QDataStream &out, const MessageEnvelop &messageEnvelop)
- {
- out << static_cast<quint8>(messageEnvelop.messageType_);
- out << messageEnvelop.data;
-
- return out;
- }
-
- friend
- QDataStream &operator>>(QDataStream &in, MessageEnvelop &messageEnvelop)
- {
- quint8 messageType;
-
- in >> messageType;
- in >> messageEnvelop.data;
-
- messageEnvelop.messageType_ = static_cast<MessageType>(messageType);
-
- return in;
- }
-
- friend
- bool operator==(const MessageEnvelop &first, const MessageEnvelop &second)
- {
- return first.messageType_ == second.messageType_
- && first.data == second.data;
- }
-
- friend QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop);
-
-private:
- mutable QByteArray data;
- MessageType messageType_ = MessageType::InvalidMessage;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/processcreator.cpp b/src/libs/clangsupport/processcreator.cpp
deleted file mode 100644
index 9425336e0fc..00000000000
--- a/src/libs/clangsupport/processcreator.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "processcreator.h"
-
-#include "processexception.h"
-#include "processstartedevent.h"
-
-#include <utils/commandline.h>
-#include <utils/qtcprocess.h>
-
-#include <QCoreApplication>
-#include <QFileInfo>
-#include <QTemporaryDir>
-
-using namespace Utils;
-
-namespace ClangBackEnd {
-
-using namespace std::chrono_literals;
-
-ProcessCreator::ProcessCreator()
-{
-}
-
-void ProcessCreator::setTemporaryDirectoryPattern(const QString &temporaryDirectoryPattern)
-{
- m_temporaryDirectoryPattern = temporaryDirectoryPattern;
- resetTemporaryDirectory();
-}
-
-void ProcessCreator::setProcessPath(const QString &processPath)
-{
- m_processPath = processPath;
-}
-
-void ProcessCreator::setArguments(const QStringList &arguments)
-{
- m_arguments = arguments;
-}
-
-void ProcessCreator::setEnvironment(const Environment &environment)
-{
- m_environment = environment;
-}
-
-std::future<QProcessUniquePointer> ProcessCreator::createProcess() const
-{
- return std::async(std::launch::async, [&] {
- checkIfProcessPathExists();
- auto process = QProcessUniquePointer(new QtcProcess());
- process->setProcessChannelMode(QProcess::ForwardedChannels);
- process->setEnvironment(processEnvironment());
- process->setCommand(CommandLine(FilePath::fromString(m_processPath), m_arguments));
- process->start();
- process->waitForStarted(5000);
-
- checkIfProcessWasStartingSuccessful(process.get());
-
- postProcessStartedEvent();
-
- process->moveToThread(QCoreApplication::instance()->thread());
-
- return process;
- });
-}
-
-void ProcessCreator::setObserver(QObject *observer)
-{
- this->m_observer = observer;
-}
-
-void ProcessCreator::checkIfProcessPathExists() const
-{
- if (!QFileInfo::exists(m_processPath)) {
- const QString messageTemplate = QCoreApplication::translate("ProcessCreator",
- "Executable does not exist: %1");
- throwProcessException(messageTemplate.arg(m_processPath));
- }
-}
-
-void ProcessCreator::checkIfProcessWasStartingSuccessful(QtcProcess *process) const
-{
- if (process->exitStatus() == QProcess::CrashExit || process->exitCode() != 0)
- dispatchProcessError(process);
-}
-
-void ProcessCreator::dispatchProcessError(QtcProcess *process) const
-{
- switch (process->error()) {
- case QProcess::UnknownError: {
- const QString message = QCoreApplication::translate("ProcessCreator",
- "Unknown error occurred.");
- throwProcessException(message);
- };
- case QProcess::Crashed: {
- const QString message = QCoreApplication::translate("ProcessCreator",
- "Process crashed.");
- throwProcessException(message);
- };
- case QProcess::FailedToStart: {
- const QString message = QCoreApplication::translate("ProcessCreator",
- "Process failed at startup.");
- throwProcessException(message);
- };
- case QProcess::Timedout: {
- const QString message = QCoreApplication::translate("ProcessCreator",
- "Process timed out.");
- throwProcessException(message);
- };
- case QProcess::WriteError: {
- const QString message = QCoreApplication::translate("ProcessCreator",
- "Cannot write to process.");
- throwProcessException(message);
- };
- case QProcess::ReadError: {
- const QString message = QCoreApplication::translate("ProcessCreator",
- "Cannot read from process.");
- throwProcessException(message);
- };
- }
-
- throwProcessException("Internal impossible error!");
-}
-
-void ProcessCreator::postProcessStartedEvent() const
-{
- if (m_observer)
- QCoreApplication::postEvent(m_observer, new ProcessStartedEvent);
-}
-
-void ProcessCreator::throwProcessException(const QString &message) const
-{
- postProcessStartedEvent();
- throw ProcessException(message);
-}
-
-const QTemporaryDir &ProcessCreator::temporaryDirectory() const
-{
- return *m_temporaryDirectory.get();
-}
-
-void ProcessCreator::resetTemporaryDirectory()
-{
- m_temporaryDirectory = std::make_unique<TemporaryDirectory>(m_temporaryDirectoryPattern);
-}
-
-Environment ProcessCreator::processEnvironment() const
-{
- auto processEnvironment = Environment::systemEnvironment();
-
- if (temporaryDirectory().isValid()) {
- const QString temporaryDirectoryPath = temporaryDirectory().path();
- processEnvironment.set("TMPDIR", temporaryDirectoryPath);
- processEnvironment.set("TMP", temporaryDirectoryPath);
- processEnvironment.set("TEMP", temporaryDirectoryPath);
- }
-
- const Environment &env = m_environment;
- for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
- if (env.isEnabled(it))
- processEnvironment.set(env.key(it), env.expandedValueForKey(env.key(it)));
- }
-
- return processEnvironment;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/processcreator.h b/src/libs/clangsupport/processcreator.h
deleted file mode 100644
index 5fdb797e30f..00000000000
--- a/src/libs/clangsupport/processcreator.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport_global.h>
-
-#include "processhandle.h"
-
-#include <utils/environment.h>
-#include <utils/temporarydirectory.h>
-
-#include <QStringList>
-
-#include <future>
-#include <memory>
-
-QT_BEGIN_NAMESPACE
-class QTemporaryDir;
-QT_END_NAMESPACE
-
-namespace Utils {
-class Environment;
-class QtcProcess;
-}
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT ProcessCreator
-{
-public:
- ProcessCreator();
-
- void setTemporaryDirectoryPattern(const QString &temporaryDirectoryPattern);
- void setProcessPath(const QString &m_processPath);
- void setArguments(const QStringList &m_arguments);
- void setEnvironment(const Utils::Environment &environment);
- void setObserver(QObject *m_observer);
-
- std::future<QProcessUniquePointer> createProcess() const;
-
- const QTemporaryDir &temporaryDirectory() const;
- void resetTemporaryDirectory();
-
-private:
- void checkIfProcessPathExists() const;
- void checkIfProcessWasStartingSuccessful(Utils::QtcProcess *process) const;
- [[noreturn]] void dispatchProcessError(Utils::QtcProcess *process) const;
- void postProcessStartedEvent() const;
- [[noreturn]] void throwProcessException(const QString &message) const;
-
- Utils::Environment processEnvironment() const;
-
-private:
- std::unique_ptr<Utils::TemporaryDirectory> m_temporaryDirectory;
- QString m_processPath;
- QString m_temporaryDirectoryPattern;
- QStringList m_arguments;
- Utils::Environment m_environment;
- QObject *m_observer = nullptr;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/processexception.cpp b/src/libs/clangsupport/processexception.cpp
deleted file mode 100644
index e96367e53cf..00000000000
--- a/src/libs/clangsupport/processexception.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "processexception.h"
-
-namespace ClangBackEnd {
-
-ProcessException::ProcessException(Utils::SmallString &&what)
- : what_(std::move(what))
-{
-}
-
-const char *ProcessException::what() const noexcept
-{
- return what_.data();
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/processexception.h b/src/libs/clangsupport/processexception.h
deleted file mode 100644
index 3ad10ba4fc4..00000000000
--- a/src/libs/clangsupport/processexception.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/smallstring.h>
-
-#include <exception>
-
-#include "clangsupport_global.h"
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT ProcessException : public std::exception
-{
-public:
- ProcessException() = default;
- ProcessException(Utils::SmallString &&what);
-
- const char *what() const noexcept final;
-
-private:
- Utils::SmallString what_;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/processhandle.h b/src/libs/clangsupport/processhandle.h
deleted file mode 100644
index 3f7444499b8..00000000000
--- a/src/libs/clangsupport/processhandle.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/qtcprocess.h>
-
-#include <memory>
-
-namespace ClangBackEnd {
-
-class QProcessUniquePointerDeleter
-{
-public:
- void operator()(Utils::QtcProcess* process)
- {
- process->kill();
- process->waitForFinished();
- delete process;
- }
-};
-
-using QProcessUniquePointer = std::unique_ptr<Utils::QtcProcess, QProcessUniquePointerDeleter>;
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/processstartedevent.cpp b/src/libs/clangsupport/processstartedevent.cpp
deleted file mode 100644
index 3db8c128c4d..00000000000
--- a/src/libs/clangsupport/processstartedevent.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "processstartedevent.h"
-
-namespace ClangBackEnd {
-
-ProcessStartedEvent::~ProcessStartedEvent()
-{
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/processstartedevent.h b/src/libs/clangsupport/processstartedevent.h
deleted file mode 100644
index 4e02f3d8d5a..00000000000
--- a/src/libs/clangsupport/processstartedevent.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include <QEvent>
-
-namespace ClangBackEnd {
-
-class ProcessStartedEvent : public QEvent
-{
-public:
- enum Type {
- ProcessStarted = QEvent::User + 3456
- };
-
- ProcessStartedEvent()
- : QEvent(static_cast<QEvent::Type>(ProcessStarted))
- {}
-
- ~ProcessStartedEvent() override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/readmessageblock.cpp b/src/libs/clangsupport/readmessageblock.cpp
deleted file mode 100644
index e08406c1338..00000000000
--- a/src/libs/clangsupport/readmessageblock.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "readmessageblock.h"
-
-#include "messageenvelop.h"
-
-#include <QDataStream>
-#include <QDebug>
-#include <QIODevice>
-#include <QVariant>
-
-namespace ClangBackEnd {
-
-ReadMessageBlock::ReadMessageBlock(QIODevice *ioDevice)
- : m_ioDevice(ioDevice),
- m_messageCounter(0),
- m_blockSize(0)
-{
-}
-
-bool ReadMessageBlock::checkIfMessageIsLost(QDataStream &in)
-{
- qint64 currentMessageCounter;
-
- in >> currentMessageCounter;
-
- bool messageIsLost = false;
-#ifndef DONT_CHECK_MESSAGE_COUNTER
- messageIsLost = !((currentMessageCounter == 0 && m_messageCounter == 0) || (m_messageCounter + 1 == currentMessageCounter));
- if (messageIsLost)
- qWarning() << "message lost: " << m_messageCounter << currentMessageCounter;
-#endif
-
- m_messageCounter = currentMessageCounter;
-
- return messageIsLost;
-}
-
-MessageEnvelop ReadMessageBlock::read()
-{
- QDataStream in(m_ioDevice);
-
- MessageEnvelop message;
-
- if (isTheWholeMessageReadable(in)) {
- bool messageIsLost = checkIfMessageIsLost(in);
-
- in >> message;
-
- if (messageIsLost)
- qDebug() << message;
- }
-
- return message;
-}
-
-std::vector<MessageEnvelop> ReadMessageBlock::readAll()
-{
- std::vector<MessageEnvelop> messages;
-
- while (true) {
- MessageEnvelop message = read();
- if (message.isValid())
- messages.push_back(std::move(message));
- else
- return messages;
- }
-
- Q_UNREACHABLE();
-}
-
-void ReadMessageBlock::resetState()
-{
- m_messageCounter = 0;
-}
-
-void ReadMessageBlock::setIoDevice(QIODevice *ioDevice)
-{
- m_ioDevice = ioDevice;
-}
-
-bool ReadMessageBlock::isTheWholeMessageReadable(QDataStream &in)
-{
- if (m_ioDevice->bytesAvailable() < qint64(sizeof(m_blockSize)))
- return false;
-
- if (m_blockSize == 0)
- in >> m_blockSize;
-
- if (m_ioDevice->bytesAvailable() < m_blockSize)
- return false;
-
- m_blockSize = 0;
-
- return true;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/readmessageblock.h b/src/libs/clangsupport/readmessageblock.h
deleted file mode 100644
index b83040d4720..00000000000
--- a/src/libs/clangsupport/readmessageblock.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QtGlobal>
-
-#include <vector>
-
-#include "clangsupport_global.h"
-
-QT_BEGIN_NAMESPACE
-class QDataStream;
-class QIODevice;
-QT_END_NAMESPACE
-
-namespace ClangBackEnd {
-
-class MessageEnvelop;
-
-class CLANGSUPPORT_EXPORT ReadMessageBlock
-{
-public:
- ReadMessageBlock(QIODevice *ioDevice = nullptr);
-
- MessageEnvelop read();
- std::vector<MessageEnvelop> readAll();
-
- void resetState();
-
- void setIoDevice(QIODevice *ioDevice);
-
-private:
- bool isTheWholeMessageReadable(QDataStream &in);
- bool checkIfMessageIsLost(QDataStream &in);
-
-private:
- QIODevice *m_ioDevice;
- qint64 m_messageCounter;
- qint32 m_blockSize;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/referencesmessage.cpp b/src/libs/clangsupport/referencesmessage.cpp
deleted file mode 100644
index 9a288deebaa..00000000000
--- a/src/libs/clangsupport/referencesmessage.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "referencesmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const ReferencesMessage &message)
-{
- debug.nospace() << "ReferencesMessage("
- << message.fileContainer
- << ", " << message.ticketNumber
- << ", " << message.isLocalVariable
- << ", " << message.references;
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/referencesmessage.h b/src/libs/clangsupport/referencesmessage.h
deleted file mode 100644
index a617077f653..00000000000
--- a/src/libs/clangsupport/referencesmessage.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "filecontainer.h"
-#include "sourcerangecontainer.h"
-
-#include <QDataStream>
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class ReferencesMessage
-{
-public:
- ReferencesMessage() = default;
- ReferencesMessage(const FileContainer &fileContainer,
- const QVector<SourceRangeContainer> &references,
- bool isLocalVariable,
- quint64 ticketNumber)
- : fileContainer(fileContainer)
- , references(references)
- , ticketNumber(ticketNumber)
- , isLocalVariable(isLocalVariable)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const ReferencesMessage &message)
- {
- out << message.fileContainer;
- out << message.isLocalVariable;
- out << message.references;
- out << message.ticketNumber;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, ReferencesMessage &message)
- {
- in >> message.fileContainer;
- in >> message.isLocalVariable;
- in >> message.references;
- in >> message.ticketNumber;
-
- return in;
- }
-
- friend bool operator==(const ReferencesMessage &first, const ReferencesMessage &second)
- {
- return first.ticketNumber == second.ticketNumber
- && first.isLocalVariable == second.isLocalVariable
- && first.fileContainer == second.fileContainer
- && first.references == second.references;
- }
-
-public:
- FileContainer fileContainer;
- QVector<SourceRangeContainer> references;
- quint64 ticketNumber = 0;
- bool isLocalVariable = false;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const ReferencesMessage &message);
-
-DECLARE_MESSAGE(ReferencesMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requestannotationsmessage.cpp b/src/libs/clangsupport/requestannotationsmessage.cpp
deleted file mode 100644
index 45392f92677..00000000000
--- a/src/libs/clangsupport/requestannotationsmessage.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "requestannotationsmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const RequestAnnotationsMessage &message)
-{
- debug.nospace() << "RequestAnnotationsMessage("
- << message.fileContainer
- << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requestannotationsmessage.h b/src/libs/clangsupport/requestannotationsmessage.h
deleted file mode 100644
index 24be10d1245..00000000000
--- a/src/libs/clangsupport/requestannotationsmessage.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "filecontainer.h"
-
-namespace ClangBackEnd {
-
-class RequestAnnotationsMessage
-{
-public:
- RequestAnnotationsMessage() = default;
- RequestAnnotationsMessage(const FileContainer &fileContainer)
- : fileContainer(fileContainer)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const RequestAnnotationsMessage &message)
- {
- out << message.fileContainer;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, RequestAnnotationsMessage &message)
- {
- in >> message.fileContainer;
-
- return in;
- }
-
- friend bool operator==(const RequestAnnotationsMessage &first,
- const RequestAnnotationsMessage &second)
- {
- return first.fileContainer == second.fileContainer;
- }
-
-public:
- FileContainer fileContainer;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RequestAnnotationsMessage &message);
-
-DECLARE_MESSAGE(RequestAnnotationsMessage);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requestcompletionsmessage.cpp b/src/libs/clangsupport/requestcompletionsmessage.cpp
deleted file mode 100644
index 156768d0ae2..00000000000
--- a/src/libs/clangsupport/requestcompletionsmessage.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "requestcompletionsmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-quint64 RequestCompletionsMessage::ticketCounter = 0;
-
-QDebug operator<<(QDebug debug, const RequestCompletionsMessage &message)
-{
- debug.nospace() << "RequestCompletionsMessage(";
-
- debug.nospace() << message.filePath << ", ";
- debug.nospace() << message.line << ", ";
- debug.nospace() << message.column << ", ";
- debug.nospace() << message.ticketNumber;
- debug.nospace() << message.funcNameStartLine << ", ";
- debug.nospace() << message.funcNameStartColumn << ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/requestcompletionsmessage.h b/src/libs/clangsupport/requestcompletionsmessage.h
deleted file mode 100644
index 90b492c0f3f..00000000000
--- a/src/libs/clangsupport/requestcompletionsmessage.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "utf8string.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class RequestCompletionsMessage
-{
-public:
- RequestCompletionsMessage() = default;
- RequestCompletionsMessage(const Utf8String &filePath,
- quint32 line,
- quint32 column,
- qint32 funcNameStartLine = -1,
- qint32 funcNameStartColumn = -1)
- : filePath(filePath)
- , ticketNumber(++ticketCounter)
- , line(line)
- , column(column)
- , funcNameStartLine(funcNameStartLine)
- , funcNameStartColumn(funcNameStartColumn)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const RequestCompletionsMessage &message)
- {
- out << message.filePath;
- out << message.ticketNumber;
- out << message.line;
- out << message.column;
- out << message.funcNameStartLine;
- out << message.funcNameStartColumn;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, RequestCompletionsMessage &message)
- {
- in >> message.filePath;
- in >> message.ticketNumber;
- in >> message.line;
- in >> message.column;
- in >> message.funcNameStartLine;
- in >> message.funcNameStartColumn;
-
- return in;
- }
-
- friend bool operator==(const RequestCompletionsMessage &first,
- const RequestCompletionsMessage &second)
- {
- return first.ticketNumber == second.ticketNumber
- && first.filePath == second.filePath
- && first.line == second.line
- && first.column == second.column
- && first.funcNameStartLine == second.funcNameStartLine
- && first.funcNameStartColumn == second.funcNameStartColumn;
- }
-
-public:
- Utf8String filePath;
- static CLANGSUPPORT_EXPORT quint64 ticketCounter;
- quint64 ticketNumber = 0;
- quint32 line = 0;
- quint32 column = 0;
- qint32 funcNameStartLine = -1;
- qint32 funcNameStartColumn = -1;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RequestCompletionsMessage &message);
-
-DECLARE_MESSAGE(RequestCompletionsMessage);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requestfollowsymbolmessage.cpp b/src/libs/clangsupport/requestfollowsymbolmessage.cpp
deleted file mode 100644
index 1caa0cd4540..00000000000
--- a/src/libs/clangsupport/requestfollowsymbolmessage.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "requestfollowsymbolmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-quint64 RequestFollowSymbolMessage::ticketCounter = 0;
-
-QDebug operator<<(QDebug debug, const RequestFollowSymbolMessage &message)
-{
- debug.nospace() << "RequestFollowSymbolMessage(";
-
- debug.nospace() << message.fileContainer << ", ";
- debug.nospace() << message.ticketNumber << ", ";
- debug.nospace() << message.line << ", ";
- debug.nospace() << message.column << ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requestfollowsymbolmessage.h b/src/libs/clangsupport/requestfollowsymbolmessage.h
deleted file mode 100644
index b3eb0209577..00000000000
--- a/src/libs/clangsupport/requestfollowsymbolmessage.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "filecontainer.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class RequestFollowSymbolMessage
-{
-public:
- RequestFollowSymbolMessage() = default;
- RequestFollowSymbolMessage(const FileContainer &fileContainer,
- quint32 line,
- quint32 column)
- : fileContainer(fileContainer)
- , ticketNumber(++ticketCounter)
- , line(line)
- , column(column)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const RequestFollowSymbolMessage &message)
- {
- out << message.fileContainer;
- out << message.ticketNumber;
- out << message.line;
- out << message.column;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, RequestFollowSymbolMessage &message)
- {
- in >> message.fileContainer;
- in >> message.ticketNumber;
- in >> message.line;
- in >> message.column;
-
- return in;
- }
-
- friend bool operator==(const RequestFollowSymbolMessage &first,
- const RequestFollowSymbolMessage &second)
- {
- return first.ticketNumber == second.ticketNumber
- && first.line == second.line
- && first.column == second.column
- && first.fileContainer == second.fileContainer;
- }
-
-public:
- FileContainer fileContainer;
- quint64 ticketNumber = 0;
- quint32 line = 0;
- quint32 column = 0;
- static CLANGSUPPORT_EXPORT quint64 ticketCounter;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RequestFollowSymbolMessage &message);
-
-DECLARE_MESSAGE(RequestFollowSymbolMessage);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requestreferencesmessage.cpp b/src/libs/clangsupport/requestreferencesmessage.cpp
deleted file mode 100644
index ae719e66563..00000000000
--- a/src/libs/clangsupport/requestreferencesmessage.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "requestreferencesmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-quint64 RequestReferencesMessage::ticketCounter = 0;
-
-QDebug operator<<(QDebug debug, const RequestReferencesMessage &message)
-{
- debug.nospace() << "RequestReferencesMessage(";
-
- debug.nospace() << message.fileContainer << ", ";
- debug.nospace() << message.ticketNumber << ", ";
- debug.nospace() << message.line << ", ";
- debug.nospace() << message.column << ", ";
- debug.nospace() << message.local << ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requestreferencesmessage.h b/src/libs/clangsupport/requestreferencesmessage.h
deleted file mode 100644
index 185376c49dd..00000000000
--- a/src/libs/clangsupport/requestreferencesmessage.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "filecontainer.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class RequestReferencesMessage
-{
-public:
- RequestReferencesMessage() = default;
- RequestReferencesMessage(const FileContainer &fileContainer,
- quint32 line,
- quint32 column,
- bool local = false)
- : fileContainer(fileContainer)
- , ticketNumber(++ticketCounter)
- , line(line)
- , column(column)
- , local(local)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const RequestReferencesMessage &message)
- {
- out << message.fileContainer;
- out << message.ticketNumber;
- out << message.line;
- out << message.column;
- out << message.local;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, RequestReferencesMessage &message)
- {
- in >> message.fileContainer;
- in >> message.ticketNumber;
- in >> message.line;
- in >> message.column;
- in >> message.local;
-
- return in;
- }
-
- friend bool operator==(const RequestReferencesMessage &first,
- const RequestReferencesMessage &second)
- {
- return first.ticketNumber == second.ticketNumber
- && first.line == second.line
- && first.column == second.column
- && first.fileContainer == second.fileContainer
- && first.local == second.local;
- }
-
-public:
- FileContainer fileContainer;
- quint64 ticketNumber = 0;
- quint32 line = 0;
- quint32 column = 0;
- bool local = false;
- static CLANGSUPPORT_EXPORT quint64 ticketCounter;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RequestReferencesMessage &message);
-
-DECLARE_MESSAGE(RequestReferencesMessage);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requesttooltipmessage.cpp b/src/libs/clangsupport/requesttooltipmessage.cpp
deleted file mode 100644
index ab5aa3fb82b..00000000000
--- a/src/libs/clangsupport/requesttooltipmessage.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "requesttooltipmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-quint64 RequestToolTipMessage::ticketCounter = 0;
-
-QDebug operator<<(QDebug debug, const RequestToolTipMessage &message)
-{
- debug.nospace() << "RequestToolTipMessage(";
-
- debug.nospace() << message.fileContainer << ", ";
- debug.nospace() << message.ticketNumber << ", ";
- debug.nospace() << message.line << ", ";
- debug.nospace() << message.column << ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requesttooltipmessage.h b/src/libs/clangsupport/requesttooltipmessage.h
deleted file mode 100644
index d05e6a4c929..00000000000
--- a/src/libs/clangsupport/requesttooltipmessage.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "filecontainer.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-// TODO: De-duplicate with RequestReferencesMessage?
-class RequestToolTipMessage
-{
-public:
- RequestToolTipMessage() = default;
- RequestToolTipMessage(const FileContainer &fileContainer, quint32 line, quint32 column)
- : fileContainer(fileContainer)
- , ticketNumber(++ticketCounter)
- , line(line)
- , column(column)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const RequestToolTipMessage &message)
- {
- out << message.fileContainer;
- out << message.ticketNumber;
- out << message.line;
- out << message.column;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, RequestToolTipMessage &message)
- {
- in >> message.fileContainer;
- in >> message.ticketNumber;
- in >> message.line;
- in >> message.column;
-
- return in;
- }
-
- friend bool operator==(const RequestToolTipMessage &first,
- const RequestToolTipMessage &second)
- {
- return first.ticketNumber == second.ticketNumber
- && first.line == second.line
- && first.column == second.column
- && first.fileContainer == second.fileContainer;
- }
-
-public:
- FileContainer fileContainer;
- quint64 ticketNumber = 0;
- quint32 line = 0;
- quint32 column = 0;
- static CLANGSUPPORT_EXPORT quint64 ticketCounter;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RequestToolTipMessage &message);
-
-DECLARE_MESSAGE(RequestToolTipMessage);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/sourcelocationcontainer.cpp b/src/libs/clangsupport/sourcelocationcontainer.cpp
deleted file mode 100644
index 2ec30a25122..00000000000
--- a/src/libs/clangsupport/sourcelocationcontainer.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sourcelocationcontainer.h"
-
-#include <QDataStream>
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDataStream &operator<<(QDataStream &out, const SourceLocationContainer &container)
-{
- out << container.filePath;
- out << container.line;
- out << container.column;
-
- return out;
-}
-
-QDataStream &operator>>(QDataStream &in, SourceLocationContainer &container)
-{
- in >> container.filePath;
- in >> container.line;
- in >> container.column;
-
- return in;
-}
-
-bool operator==(const SourceLocationContainer &first, const SourceLocationContainer &second)
-{
- return !(first != second);
-}
-
-bool operator!=(const SourceLocationContainer &first, const SourceLocationContainer &second)
-{
- return first.line != second.line
- || first.column != second.column
- || first.filePath != second.filePath;
-}
-
-QDebug operator<<(QDebug debug, const SourceLocationContainer &container)
-{
- debug.nospace() << "SourceLocationContainer("
- << container.filePath << ", "
- << container.line << ", "
- << container.column
- << ")";
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/sourcelocationcontainer.h b/src/libs/clangsupport/sourcelocationcontainer.h
deleted file mode 100644
index 4f13488e212..00000000000
--- a/src/libs/clangsupport/sourcelocationcontainer.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "utf8string.h"
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT SourceLocationContainer
-{
-public:
- SourceLocationContainer() = default;
- SourceLocationContainer(const Utf8String &filePath,
- int line,
- int column)
- : filePath(filePath),
- line(line),
- column(column)
- {
- }
-
-public:
- Utf8String filePath;
- int line = 0;
- int column = 0;
-};
-
-CLANGSUPPORT_EXPORT QDataStream &operator<<(QDataStream &out, const SourceLocationContainer &container);
-CLANGSUPPORT_EXPORT QDataStream &operator>>(QDataStream &in, SourceLocationContainer &container);
-CLANGSUPPORT_EXPORT bool operator==(const SourceLocationContainer &first, const SourceLocationContainer &second);
-CLANGSUPPORT_EXPORT bool operator!=(const SourceLocationContainer &first, const SourceLocationContainer &second);
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const SourceLocationContainer &container);
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/sourcelocationscontainer.cpp b/src/libs/clangsupport/sourcelocationscontainer.cpp
deleted file mode 100644
index 19573ddbd1e..00000000000
--- a/src/libs/clangsupport/sourcelocationscontainer.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sourcelocationscontainer.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const SourceLocationsContainer &container)
-{
- debug.nospace() << "SourceLocationsContainer([";
- for (const auto &sourceLocation: container.sourceLocationContainers()) {
- debug.nospace() << "("
- << sourceLocation.filePath << ","
- << sourceLocation.line << ","
- << sourceLocation.column << "), ";
- }
-
- debug.nospace() << "])";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/sourcelocationscontainer.h b/src/libs/clangsupport/sourcelocationscontainer.h
deleted file mode 100644
index 0be15acf900..00000000000
--- a/src/libs/clangsupport/sourcelocationscontainer.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sourcelocationcontainer.h"
-
-#include <utils/smallstringio.h>
-
-namespace ClangBackEnd {
-
-class CLANGSUPPORT_EXPORT SourceLocationsContainer
-{
-public:
- SourceLocationsContainer() = default;
- SourceLocationsContainer(std::vector<SourceLocationContainer> &&sourceLocationContainers)
- : m_sourceLocationContainers(std::move(sourceLocationContainers))
- {}
-
- const std::vector<SourceLocationContainer> &sourceLocationContainers() const
- {
- return m_sourceLocationContainers;
- }
-
- bool hasContent() const
- {
- return !m_sourceLocationContainers.empty();
- }
-
- void insertSourceLocation(const Utf8String &filePath, int line, int column)
- {
- m_sourceLocationContainers.emplace_back(filePath, line, column);
- }
-
- void reserve(std::size_t size)
- {
- m_sourceLocationContainers.reserve(size);
- }
-
- friend QDataStream &operator<<(QDataStream &out, const SourceLocationsContainer &container)
- {
- out << container.m_sourceLocationContainers;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, SourceLocationsContainer &container)
- {
- in >> container.m_sourceLocationContainers;
-
- return in;
- }
-
- friend bool operator==(const SourceLocationsContainer &first, const SourceLocationsContainer &second)
- {
- return first.m_sourceLocationContainers == second.m_sourceLocationContainers;
- }
-
- SourceLocationsContainer clone() const
- {
- return *this;
- }
-
- std::vector<SourceLocationContainer> m_sourceLocationContainers;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const SourceLocationsContainer &container);
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/sourcerangecontainer.cpp b/src/libs/clangsupport/sourcerangecontainer.cpp
deleted file mode 100644
index d9146d0ff33..00000000000
--- a/src/libs/clangsupport/sourcerangecontainer.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sourcerangecontainer.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const SourceRangeContainer &container)
-{
- debug.nospace() << "SourceRangeContainer("
- << container.start << ", "
- << container.end
- << ")";
-
- return debug;
-}
-
-QDebug operator<<(QDebug debug, const QVector<SourceRangeContainer> &containers)
-{
- debug.nospace() << "{";
- for (int i = 0; i < containers.size(); i++) {
- debug.nospace() << containers[i];
- if (i < containers.size() - 1)
- debug.nospace() << ", ";
- }
- debug.nospace() << "}";
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/sourcerangecontainer.h b/src/libs/clangsupport/sourcerangecontainer.h
deleted file mode 100644
index 39a0e6cb210..00000000000
--- a/src/libs/clangsupport/sourcerangecontainer.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sourcelocationcontainer.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class SourceRangeContainer
-{
-public:
- SourceRangeContainer() = default;
- SourceRangeContainer(SourceLocationContainer start,
- SourceLocationContainer end)
- : start(start),
- end(end)
- {
- }
-
- bool contains(int line, int column) const
- {
- if (line < start.line || line > end.line)
- return false;
- if (line == start.line && column < start.column)
- return false;
- if (line == end.line && column > end.column)
- return false;
- return true;
- }
-
- bool contains(const SourceLocationContainer &sourceLocation) const
- {
- return contains(sourceLocation.line, sourceLocation.column);
- }
-
- friend QDataStream &operator<<(QDataStream &out, const SourceRangeContainer &container)
- {
- out << container.start;
- out << container.end;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, SourceRangeContainer &container)
- {
- in >> container.start;
- in >> container.end;
-
- return in;
- }
-
- friend bool operator==(const SourceRangeContainer &first, const SourceRangeContainer &second)
- {
- return first.start == second.start && first.end == second.end;
- }
-
-public:
- SourceLocationContainer start;
- SourceLocationContainer end;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const SourceRangeContainer &container);
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const QVector<SourceRangeContainer> &container);
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tokeninfocontainer.cpp b/src/libs/clangsupport/tokeninfocontainer.cpp
deleted file mode 100644
index 41c0a69f7ee..00000000000
--- a/src/libs/clangsupport/tokeninfocontainer.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "tokeninfocontainer.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-#define RETURN_TEXT_FOR_CASE(enumValue) case HighlightingType::enumValue: return #enumValue
-static const char *highlightingTypeToCStringLiteral(HighlightingType type)
-{
- switch (type) {
- RETURN_TEXT_FOR_CASE(Invalid);
- RETURN_TEXT_FOR_CASE(Comment);
- RETURN_TEXT_FOR_CASE(Keyword);
- RETURN_TEXT_FOR_CASE(StringLiteral);
- RETURN_TEXT_FOR_CASE(NumberLiteral);
- RETURN_TEXT_FOR_CASE(Function);
- RETURN_TEXT_FOR_CASE(VirtualFunction);
- RETURN_TEXT_FOR_CASE(Type);
- RETURN_TEXT_FOR_CASE(LocalVariable);
- RETURN_TEXT_FOR_CASE(GlobalVariable);
- RETURN_TEXT_FOR_CASE(Field);
- RETURN_TEXT_FOR_CASE(Enumeration);
- RETURN_TEXT_FOR_CASE(Operator);
- RETURN_TEXT_FOR_CASE(OverloadedOperator);
- RETURN_TEXT_FOR_CASE(Preprocessor);
- RETURN_TEXT_FOR_CASE(Label);
- RETURN_TEXT_FOR_CASE(FunctionDefinition);
- RETURN_TEXT_FOR_CASE(OutputArgument);
- RETURN_TEXT_FOR_CASE(PreprocessorDefinition);
- RETURN_TEXT_FOR_CASE(PreprocessorExpansion);
- RETURN_TEXT_FOR_CASE(Punctuation);
- RETURN_TEXT_FOR_CASE(Namespace);
- RETURN_TEXT_FOR_CASE(Class);
- RETURN_TEXT_FOR_CASE(Struct);
- RETURN_TEXT_FOR_CASE(Enum);
- RETURN_TEXT_FOR_CASE(Union);
- RETURN_TEXT_FOR_CASE(TypeAlias);
- RETURN_TEXT_FOR_CASE(Typedef);
- RETURN_TEXT_FOR_CASE(QtProperty);
- RETURN_TEXT_FOR_CASE(ObjectiveCClass);
- RETURN_TEXT_FOR_CASE(ObjectiveCCategory);
- RETURN_TEXT_FOR_CASE(ObjectiveCProtocol);
- RETURN_TEXT_FOR_CASE(ObjectiveCInterface);
- RETURN_TEXT_FOR_CASE(ObjectiveCImplementation);
- RETURN_TEXT_FOR_CASE(ObjectiveCProperty);
- RETURN_TEXT_FOR_CASE(ObjectiveCMethod);
- RETURN_TEXT_FOR_CASE(PrimitiveType);
- RETURN_TEXT_FOR_CASE(Declaration);
- RETURN_TEXT_FOR_CASE(TemplateTypeParameter);
- RETURN_TEXT_FOR_CASE(TemplateTemplateParameter);
- default: return "UnhandledHighlightingType";
- }
-}
-#undef RETURN_TEXT_FOR_CASE
-
-QDebug operator<<(QDebug debug, const ExtraInfo &extraInfo)
-{
- debug.nospace() << "ExtraInfo("
- << extraInfo.token << ", "
- << extraInfo.typeSpelling << ", "
- << extraInfo.semanticParentTypeSpelling << ", "
- << extraInfo.cursorRange << ", "
- << extraInfo.lexicalParentIndex << ", "
- << static_cast<uint>(extraInfo.accessSpecifier) << ", "
- << static_cast<uint>(extraInfo.storageClass) << ", "
- << extraInfo.identifier << ", "
- << extraInfo.includeDirectivePath << ", "
- << extraInfo.declaration << ", "
- << extraInfo.definition << ", "
- << extraInfo.signal << ", "
- << extraInfo.slot << ", "
- << ")";
- return debug;
-}
-
-QDebug operator<<(QDebug debug, const TokenInfoContainer &container)
-{
- debug.nospace() << "TokenInfosContainer("
- << container.line << ", "
- << container.column << ", "
- << container.length << ", "
- << highlightingTypeToCStringLiteral(container.types.mainHighlightingType) << ", "
- << container.extraInfo
- << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tokeninfocontainer.h b/src/libs/clangsupport/tokeninfocontainer.h
deleted file mode 100644
index 004bdd3cb9f..00000000000
--- a/src/libs/clangsupport/tokeninfocontainer.h
+++ /dev/null
@@ -1,344 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include "sourcerangecontainer.h"
-
-#include "utf8string.h"
-
-#include <QDataStream>
-
-#include <bitset>
-
-namespace ClangBackEnd {
-
-inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType);
-inline QDataStream &operator<<(QDataStream &out, HighlightingTypes highlightingTypes);
-inline QDataStream &operator>>(QDataStream &in, HighlightingType &highlightingType);
-inline QDataStream &operator>>(QDataStream &in, HighlightingTypes &highlightingTypes);
-inline bool operator==(const MixinHighlightingTypes &first, const MixinHighlightingTypes &second);
-inline bool operator==(const HighlightingTypes &first, const HighlightingTypes &second);
-
-using ByteSizeBitset = std::bitset<8>;
-
-inline QDataStream &operator<<(QDataStream &out, ByteSizeBitset bits);
-inline QDataStream &operator>>(QDataStream &in, ByteSizeBitset &bits);
-
-struct ExtraInfo
-{
- ExtraInfo()
- : identifier(false)
- , includeDirectivePath(false)
- , declaration(false)
- , definition(false)
- , signal(false)
- , slot(false)
- {
- }
- ExtraInfo(Utf8String token, Utf8String typeSpelling,
- Utf8String semanticParentTypeSpelling, SourceRangeContainer cursorRange,
- int lexicalParentIndex, AccessSpecifier accessSpecifier, StorageClass storageClass,
- bool isIdentifier, bool isInclusion, bool isDeclaration, bool isDefinition,
- bool isSignal, bool isSlot)
- : token(token)
- , typeSpelling(typeSpelling)
- , semanticParentTypeSpelling(semanticParentTypeSpelling)
- , cursorRange(cursorRange)
- , lexicalParentIndex(lexicalParentIndex)
- , accessSpecifier(accessSpecifier)
- , storageClass(storageClass)
- , identifier(isIdentifier)
- , includeDirectivePath(isInclusion)
- , declaration(isDeclaration)
- , definition(isDefinition)
- , signal(isSignal)
- , slot(isSlot)
- {
- }
- Utf8String token;
- Utf8String typeSpelling;
- Utf8String semanticParentTypeSpelling;
- SourceRangeContainer cursorRange;
- int lexicalParentIndex = -1;
- AccessSpecifier accessSpecifier = AccessSpecifier::Invalid;
- StorageClass storageClass = StorageClass::Invalid;
- bool identifier : 1;
- bool includeDirectivePath : 1;
- bool declaration : 1;
- bool definition : 1;
- bool signal : 1;
- bool slot : 1;
-};
-
-inline QDataStream &operator<<(QDataStream &out, const ExtraInfo &extraInfo);
-inline QDataStream &operator>>(QDataStream &in, ExtraInfo &extraInfo);
-inline bool operator==(const ExtraInfo &first, const ExtraInfo &second);
-
-class TokenInfoContainer
-{
-public:
- TokenInfoContainer() = default;
- TokenInfoContainer(int line, int column, int length, HighlightingTypes types)
- : line(line)
- , column(column)
- , length(length)
- , types(types)
- {
- }
-
- TokenInfoContainer(int line, int column, int length, HighlightingTypes types,
- const ExtraInfo &extraInfo)
- : line(line)
- , column(column)
- , length(length)
- , types(types)
- , extraInfo(extraInfo)
- , noExtraInfo(false)
- {
- }
-
- bool isInvalid() const
- {
- return line == 0 && column == 0 && length == 0;
- }
-
- bool isGlobalDeclaration() const
- {
- if (types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::TemplateTypeParameter)
- || types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::TemplateTemplateParameter)) {
- return false;
- }
-
- return extraInfo.declaration
- && types.mainHighlightingType != HighlightingType::LocalVariable
- && types.mainHighlightingType != HighlightingType::Parameter
- && (types.mixinHighlightingTypes.contains(HighlightingType::Operator)
- == extraInfo.token.startsWith("operator"));
- }
-
- friend QDataStream &operator<<(QDataStream &out, const TokenInfoContainer &container)
- {
- out << container.line;
- out << container.column;
- out << container.length;
- out << container.types;
- out << container.noExtraInfo;
-
- if (container.noExtraInfo)
- return out;
-
- out << container.extraInfo;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, TokenInfoContainer &container)
- {
- in >> container.line;
- in >> container.column;
- in >> container.length;
- in >> container.types;
- in >> container.noExtraInfo;
-
- if (container.noExtraInfo)
- return in;
-
- in >> container.extraInfo;
-
- return in;
- }
-
- friend bool operator==(const TokenInfoContainer &first, const TokenInfoContainer &second)
- {
- return first.line == second.line
- && first.column == second.column
- && first.length == second.length
- && first.types == second.types
- && first.noExtraInfo == second.noExtraInfo
- && first.extraInfo == second.extraInfo;
- }
-
- int line = 0;
- int column = 0;
- int length = 0;
- HighlightingTypes types;
- ExtraInfo extraInfo;
- bool noExtraInfo = true;
-};
-
-inline QDataStream &operator<<(QDataStream &out, const ExtraInfo &extraInfo)
-{
- out << extraInfo.token;
- out << extraInfo.typeSpelling;
- out << extraInfo.semanticParentTypeSpelling;
- out << extraInfo.cursorRange;
- out << extraInfo.lexicalParentIndex;
- out << static_cast<uint>(extraInfo.accessSpecifier);
- out << static_cast<uint>(extraInfo.storageClass);
- out << extraInfo.identifier;
- out << extraInfo.includeDirectivePath;
- out << extraInfo.declaration;
- out << extraInfo.definition;
- out << extraInfo.signal;
- out << extraInfo.slot;
- return out;
-}
-
-inline QDataStream &operator>>(QDataStream &in, ExtraInfo &extraInfo)
-{
- in >> extraInfo.token;
- in >> extraInfo.typeSpelling;
- in >> extraInfo.semanticParentTypeSpelling;
- in >> extraInfo.cursorRange;
- in >> extraInfo.lexicalParentIndex;
-
- uint accessSpecifier;
- uint storageClass;
- bool isIdentifier;
- bool isInclusion;
- bool isDeclaration;
- bool isDefinition;
- bool isSignal;
- bool isSlot;
-
- in >> accessSpecifier;
- in >> storageClass;
- in >> isIdentifier;
- in >> isInclusion;
- in >> isDeclaration;
- in >> isDefinition;
- in >> isSignal;
- in >> isSlot;
-
- extraInfo.accessSpecifier = static_cast<AccessSpecifier>(accessSpecifier);
- extraInfo.storageClass = static_cast<StorageClass>(storageClass);
- extraInfo.identifier = isIdentifier;
- extraInfo.includeDirectivePath = isInclusion;
- extraInfo.declaration = isDeclaration;
- extraInfo.definition = isDefinition;
- extraInfo.signal = isSignal;
- extraInfo.slot = isSlot;
- return in;
-}
-
-inline bool operator==(const ExtraInfo &first, const ExtraInfo &second)
-{
- return first.token == second.token
- && first.typeSpelling == second.typeSpelling
- && first.semanticParentTypeSpelling == second.semanticParentTypeSpelling
- && first.cursorRange == second.cursorRange
- && first.lexicalParentIndex == second.lexicalParentIndex
- && first.accessSpecifier == second.accessSpecifier
- && first.storageClass == second.storageClass
- && first.identifier == second.identifier
- && first.includeDirectivePath == second.includeDirectivePath
- && first.declaration == second.declaration
- && first.definition == second.definition
- && first.signal == second.signal
- && first.slot == second.slot;
-}
-
-inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType)
-{
- out << static_cast<quint8>(highlightingType);
-
- return out;
-}
-
-inline QDataStream &operator<<(QDataStream &out, HighlightingTypes highlightingTypes)
-{
- out << highlightingTypes.mainHighlightingType;
-
- out << highlightingTypes.mixinHighlightingTypes.size();
-
- for (HighlightingType type : highlightingTypes.mixinHighlightingTypes)
- out << type;
-
- return out;
-}
-
-
-inline QDataStream &operator>>(QDataStream &in, HighlightingType &highlightingType)
-{
- quint8 highlightingTypeInt;
-
- in >> highlightingTypeInt;
-
- highlightingType = static_cast<HighlightingType>(highlightingTypeInt);
-
- return in;
-}
-
-inline QDataStream &operator>>(QDataStream &in, HighlightingTypes &highlightingTypes)
-{
- in >> highlightingTypes.mainHighlightingType ;
-
- quint8 size;
- in >> size;
-
- for (int counter = 0; counter < size; ++counter) {
- HighlightingType type;
- in >> type;
- highlightingTypes.mixinHighlightingTypes.push_back(type);
- }
-
- return in;
-}
-
-inline bool operator==(const MixinHighlightingTypes &first, const MixinHighlightingTypes &second)
-{
- return first.size() == second.size()
- && std::equal(first.begin(), first.end(), second.begin());
-}
-
-inline bool operator==(const HighlightingTypes &first, const HighlightingTypes &second)
-{
- return first.mainHighlightingType == second.mainHighlightingType
- && first.mixinHighlightingTypes == second.mixinHighlightingTypes;
-}
-
-inline QDataStream &operator<<(QDataStream &out, ByteSizeBitset bits)
-{
- // Narrow unsigned long to uint8_t
- out << static_cast<uint8_t>(bits.to_ulong());
- return out;
-}
-
-inline QDataStream &operator>>(QDataStream &in, ByteSizeBitset &bits)
-{
- uint8_t byteValue;
- in >> byteValue;
- bits = ByteSizeBitset(byteValue);
- return in;
-}
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const TokenInfoContainer &container);
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tooltipinfo.cpp b/src/libs/clangsupport/tooltipinfo.cpp
deleted file mode 100644
index 379f53741b9..00000000000
--- a/src/libs/clangsupport/tooltipinfo.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "tooltipinfo.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-#define RETURN_TEXT_FOR_CASE(enumValue) case ToolTipInfo::enumValue: return #enumValue
-const char *qdocCategoryToString(ToolTipInfo::QdocCategory category)
-{
- switch (category) {
- RETURN_TEXT_FOR_CASE(Unknown);
- RETURN_TEXT_FOR_CASE(ClassOrNamespace);
- RETURN_TEXT_FOR_CASE(Enum);
- RETURN_TEXT_FOR_CASE(Typedef);
- RETURN_TEXT_FOR_CASE(Macro);
- RETURN_TEXT_FOR_CASE(Brief);
- RETURN_TEXT_FOR_CASE(Function);
- }
-
- return "UnhandledQdocCategory";
-}
-#undef RETURN_TEXT_FOR_CASE
-
-QDebug operator<<(QDebug debug, const ToolTipInfo &message)
-{
- debug.nospace() << "ToolTipInfo(";
-
- debug.nospace() << message.text << ", ";
- debug.nospace() << message.briefComment << ", ";
- debug.nospace() << message.qdocIdCandidates << ", ";
- debug.nospace() << message.qdocMark << ", ";
- debug.nospace() << qdocCategoryToString(message.qdocCategory) << ", ";
- debug.nospace() << message.sizeInBytes << ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tooltipinfo.h b/src/libs/clangsupport/tooltipinfo.h
deleted file mode 100644
index 3d443c5b640..00000000000
--- a/src/libs/clangsupport/tooltipinfo.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "utf8string.h"
-#include <utf8stringvector.h>
-
-#include <QVariant>
-
-#include "clangsupport_global.h"
-
-namespace ClangBackEnd {
-
-class ToolTipInfo
-{
-public:
- enum QdocCategory : quint8 {
- Unknown,
- ClassOrNamespace,
- Enum,
- Typedef,
- Macro,
- Brief,
- Function,
- };
-
-public:
- ToolTipInfo() = default;
- ToolTipInfo(const Utf8String &text) : text(text) {}
-
- friend QDataStream &operator<<(QDataStream &out, const ToolTipInfo &message)
- {
- out << message.text;
- out << message.briefComment;
- out << message.qdocIdCandidates;
- out << message.qdocMark;
- out << static_cast<quint8>(message.qdocCategory);
- out << message.value;
- out << message.sizeInBytes;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, ToolTipInfo &message)
- {
- quint8 qdocCategory;
-
- in >> message.text;
- in >> message.briefComment;
- in >> message.qdocIdCandidates;
- in >> message.qdocMark;
- in >> qdocCategory;
- in >> message.value;
- in >> message.sizeInBytes;
-
- message.qdocCategory = static_cast<QdocCategory>(qdocCategory);
-
- return in;
- }
-
- friend bool operator==(const ToolTipInfo &first, const ToolTipInfo &second)
- {
- return first.text == second.text
- && first.briefComment == second.briefComment
- && first.qdocIdCandidates == second.qdocIdCandidates
- && first.qdocMark == second.qdocMark
- && first.qdocCategory == second.qdocCategory
- && first.value == second.value
- && first.sizeInBytes == second.sizeInBytes;
- }
-
-public:
- Utf8String text;
- Utf8String briefComment;
-
- Utf8StringVector qdocIdCandidates;
- Utf8String qdocMark;
- QdocCategory qdocCategory = Unknown;
- QVariant value;
-
- // For class definition and for class fields.
- Utf8String sizeInBytes;
-};
-
-QDebug operator<<(QDebug debug, const ToolTipInfo &message);
-std::ostream &operator<<(std::ostream &os, const ToolTipInfo &message);
-
-CLANGSUPPORT_EXPORT const char *qdocCategoryToString(ToolTipInfo::QdocCategory category);
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tooltipmessage.cpp b/src/libs/clangsupport/tooltipmessage.cpp
deleted file mode 100644
index 9cffb42f019..00000000000
--- a/src/libs/clangsupport/tooltipmessage.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "tooltipmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const ToolTipMessage &message)
-{
- debug.nospace() << "ToolTipMessage("
- << message.fileContainer
- << ", " << message.ticketNumber
- << ", " << message.toolTipInfo;
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tooltipmessage.h b/src/libs/clangsupport/tooltipmessage.h
deleted file mode 100644
index 547f8e466ad..00000000000
--- a/src/libs/clangsupport/tooltipmessage.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "filecontainer.h"
-#include "tooltipinfo.h"
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class ToolTipMessage
-{
-public:
- ToolTipMessage() = default;
- ToolTipMessage(const FileContainer &fileContainer,
- const ToolTipInfo &toolTipInfo,
- quint64 ticketNumber)
- : fileContainer(fileContainer)
- , toolTipInfo(toolTipInfo)
- , ticketNumber(ticketNumber)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const ToolTipMessage &message)
- {
- out << message.fileContainer;
- out << message.toolTipInfo;;
- out << message.ticketNumber;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, ToolTipMessage &message)
- {
- in >> message.fileContainer;
- in >> message.toolTipInfo;
- in >> message.ticketNumber;
-
- return in;
- }
-
- friend bool operator==(const ToolTipMessage &first, const ToolTipMessage &second)
- {
- return first.ticketNumber == second.ticketNumber
- && first.fileContainer == second.fileContainer
- && first.toolTipInfo == second.toolTipInfo;
- }
-
-public:
- FileContainer fileContainer;
- ToolTipInfo toolTipInfo;
- quint64 ticketNumber = 0;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const ToolTipMessage &message);
-
-DECLARE_MESSAGE(ToolTipMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/unsavedfilesremovedmessage.cpp b/src/libs/clangsupport/unsavedfilesremovedmessage.cpp
deleted file mode 100644
index 8da5ca1c1b9..00000000000
--- a/src/libs/clangsupport/unsavedfilesremovedmessage.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "unsavedfilesremovedmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const UnsavedFilesRemovedMessage &message)
-{
- debug.nospace() << "UnsavedFilesRemovedMessage(";
-
- for (const FileContainer &fileContainer : message.fileContainers)
- debug.nospace() << fileContainer<< ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/unsavedfilesremovedmessage.h b/src/libs/clangsupport/unsavedfilesremovedmessage.h
deleted file mode 100644
index 58714b407f2..00000000000
--- a/src/libs/clangsupport/unsavedfilesremovedmessage.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "filecontainer.h"
-
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class UnsavedFilesRemovedMessage
-{
-public:
- UnsavedFilesRemovedMessage() = default;
- UnsavedFilesRemovedMessage(const QVector<FileContainer> &fileContainers)
- : fileContainers(fileContainers)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const UnsavedFilesRemovedMessage &message)
- {
- out << message.fileContainers;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, UnsavedFilesRemovedMessage &message)
- {
- in >> message.fileContainers;
-
- return in;
- }
-
- friend bool operator==(const UnsavedFilesRemovedMessage &first,
- const UnsavedFilesRemovedMessage &second)
- {
- return first.fileContainers == second.fileContainers;
- }
-
-public:
- QVector<FileContainer> fileContainers;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const UnsavedFilesRemovedMessage &message);
-
-DECLARE_MESSAGE(UnsavedFilesRemovedMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/unsavedfilesupdatedmessage.cpp b/src/libs/clangsupport/unsavedfilesupdatedmessage.cpp
deleted file mode 100644
index 80000a65664..00000000000
--- a/src/libs/clangsupport/unsavedfilesupdatedmessage.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "unsavedfilesupdatedmessage.h"
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const UnsavedFilesUpdatedMessage &message)
-{
- debug.nospace() << "UnsavedFilesUpdatedMessage(";
-
- for (const FileContainer &fileContainer : message.fileContainers)
- debug.nospace() << fileContainer<< ", ";
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/unsavedfilesupdatedmessage.h b/src/libs/clangsupport/unsavedfilesupdatedmessage.h
deleted file mode 100644
index 5d796f7ae00..00000000000
--- a/src/libs/clangsupport/unsavedfilesupdatedmessage.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "filecontainer.h"
-
-#include <QVector>
-
-namespace ClangBackEnd {
-
-class UnsavedFilesUpdatedMessage
-{
-public:
- UnsavedFilesUpdatedMessage() = default;
- UnsavedFilesUpdatedMessage(const QVector<FileContainer> &fileContainers)
- : fileContainers(fileContainers)
- {
- }
-
- friend QDataStream &operator<<(QDataStream &out, const UnsavedFilesUpdatedMessage &message)
- {
- out << message.fileContainers;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, UnsavedFilesUpdatedMessage &message)
- {
- in >> message.fileContainers;
-
- return in;
- }
-
- friend bool operator==(const UnsavedFilesUpdatedMessage &first,
- const UnsavedFilesUpdatedMessage &second)
- {
- return first.fileContainers == second.fileContainers;
- }
-
-public:
- QVector<FileContainer> fileContainers;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const UnsavedFilesUpdatedMessage &message);
-
-DECLARE_MESSAGE(UnsavedFilesUpdatedMessage);
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/utf8string.cpp b/src/libs/clangsupport/utf8string.cpp
deleted file mode 100644
index ad7748cfa53..00000000000
--- a/src/libs/clangsupport/utf8string.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "utf8string.h"
-
-#include "utf8stringvector.h"
-
-#include <QString>
-#include <QDebug>
-
-#include <ostream>
-
-QDebug operator<<(QDebug debug, const Utf8String &text)
-{
- debug << text.constData();
-
- return debug;
-}
-
-std::ostream& operator<<(std::ostream &os, const Utf8String &utf8String)
-{
- using std::ostream;
- os << utf8String.constData();
-
- return os;
-}
-
-Utf8StringVector Utf8String::split(char separator) const
-{
- Utf8StringVector utf8Vector;
-
- for (const QByteArray &byteArrayPart : byteArray.split(separator))
- utf8Vector.append(Utf8String::fromByteArray(byteArrayPart));
-
- return utf8Vector;
-}
diff --git a/src/libs/clangsupport/utf8string.h b/src/libs/clangsupport/utf8string.h
deleted file mode 100644
index ebd9aba0a6e..00000000000
--- a/src/libs/clangsupport/utf8string.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-
-#include <QByteArray>
-#include <QDataStream>
-#include <QHashFunctions>
-#include <QMetaType>
-#include <QString>
-
-#include <cstring>
-#include <iosfwd>
-
-class Utf8StringVector;
-class Utf8String;
-
-class Utf8String
-{
- friend class Utf8StringVector;
-
-public:
- Utf8String() = default;
-
- explicit Utf8String(const char *utf8Text)
- : byteArray(utf8Text, utf8Text ? static_cast<int>(std::strlen(utf8Text)) : -1)
- {}
-
- explicit Utf8String(const char *utf8Text, int size)
- : byteArray(utf8Text, size)
- {}
-
- Utf8String(const QString &text)
- : byteArray(text.toUtf8())
- {
- }
-
- const char *constData() const
- {
- return byteArray.constData();
- }
-
- int byteSize() const
- {
- return byteArray.size();
- }
-
- static Utf8String fromUtf8(const char *utf8Text)
- {
- return Utf8String(utf8Text, -1);
- }
-
- static Utf8String fromByteArray(const QByteArray &utf8ByteArray)
- {
- return Utf8String(utf8ByteArray);
- }
- const QByteArray &toByteArray() const
- {
- return byteArray;
- }
-
- static Utf8String fromString(const QString &text)
- {
- return Utf8String::fromByteArray(text.toUtf8());
- }
-
- QString toString() const
- {
- return QString::fromUtf8(byteArray, byteArray.size());
- }
-
- Utf8String mid(int position, int length = -1) const
- {
- return Utf8String(byteArray.mid(position, length));
- }
-
- void replace(const Utf8String &before, const Utf8String &after)
- {
- byteArray.replace(before.byteArray, after.byteArray);
- }
-
- void replace(int position, int length, const Utf8String &after)
- {
- byteArray.replace(position, length, after.byteArray);
- }
-
- CLANGSUPPORT_EXPORT Utf8StringVector split(char separator) const;
-
- void clear()
- {
- byteArray.clear();
- }
-
- void append(const Utf8String &textToAppend)
- {
- byteArray.append(textToAppend.byteArray);
- }
-
- void chop(int n)
- {
- byteArray.chop(n);
- }
-
- int indexOf(const Utf8String &text) const
- {
- return byteArray.indexOf(text.byteArray);
- }
-
- int indexOf(const char *text) const
- {
- return byteArray.indexOf(text);
- }
-
- int lastIndexOf(const Utf8String &text) const
- {
- return byteArray.lastIndexOf(text.byteArray);
- }
-
- int lastIndexOf(const char *text) const
- {
- return byteArray.lastIndexOf(text);
- }
-
- int indexOf(char character) const
- {
- return byteArray.indexOf(character);
- }
-
- bool contains(const Utf8String &text) const
- {
- return byteArray.contains(text.byteArray);
- }
-
- bool contains(const char *text) const
- {
- return byteArray.contains(text);
- }
-
- bool contains(char character) const
- {
- return byteArray.contains(character);
- }
-
- bool startsWith(const Utf8String &text) const
- {
- return byteArray.startsWith(text.byteArray);
- }
-
- bool startsWith(const char *text) const
- {
- return byteArray.startsWith(text);
- }
-
- bool startsWith(char character) const
- {
- return byteArray.startsWith(character);
- }
-
- bool endsWith(const Utf8String &text) const
- {
- return byteArray.endsWith(text.byteArray);
- }
-
- bool endsWith(const char *text) const
- {
- return byteArray.endsWith(text);
- }
-
- bool endsWith(char character) const
- {
- return byteArray.endsWith(character);
- }
-
- bool isNull() const
- {
- return byteArray.isNull();
- }
-
- bool isEmpty() const
- {
- return byteArray.isEmpty();
- }
-
- bool hasContent() const
- {
- return !isEmpty();
- }
-
- void reserve(int reserveSize)
- {
- byteArray.reserve(reserveSize);
- }
-
- template<typename T>
- static Utf8String number(T number, int base = 10)
- {
- return Utf8String::fromByteArray(QByteArray::number(number, base));
- }
-
- const Utf8String &operator+=(const Utf8String &text)
- {
- byteArray += text.byteArray;
-
- return *this;
- }
-
- static void registerType()
- {
- qRegisterMetaType<Utf8String>("Utf8String");
- }
-
- operator QString() const
- {
- return toString();
- }
-
- operator const QByteArray &() const
- {
- return byteArray;
- }
-
- friend const Utf8String operator+(const Utf8String &first, const Utf8String &second)
- {
- return Utf8String(first.byteArray + second.byteArray);
- }
-
- friend bool operator!=(const Utf8String &first, const Utf8String &second)
- {
- return first.byteArray != second.byteArray;
- }
-
- friend bool operator==(const Utf8String &first, const Utf8String &second)
- {
- return first.byteArray == second.byteArray;
- }
-
- friend bool operator==(const Utf8String &first, const char *second)
- {
- return first.byteArray == second;
- }
-
- friend bool operator==(const char *first, const Utf8String &second)
- {
- return second == first;
- }
-
- friend bool operator!=(const Utf8String &first, const char *second)
- {
- return first.byteArray != second;
- }
-
- friend bool operator!=(const char *first, const Utf8String &second) { return second != first; }
-
- friend bool operator==(const Utf8String &first, const QString &second)
- {
- return first.byteArray == second.toUtf8();
- }
-
- friend bool operator<(const Utf8String &first, const Utf8String &second)
- {
- if (first.byteSize() == second.byteSize())
- return first.byteArray < second.byteArray;
-
- return first.byteSize() < second.byteSize();
- }
-
- friend QDataStream &operator<<(QDataStream &datastream, const Utf8String &text)
- {
- datastream << text.byteArray;
-
- return datastream;
- }
-
- friend QDataStream &operator>>(QDataStream &datastream, Utf8String &text)
- {
- datastream >> text.byteArray;
-
- return datastream;
- }
-
- friend auto qHash(const Utf8String &utf8String)
- {
- return qHash(utf8String.byteArray);
- }
-
-protected:
- explicit Utf8String(const QByteArray &utf8ByteArray)
- : byteArray(utf8ByteArray)
- {
- }
-
-private:
- QByteArray byteArray;
-};
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const Utf8String &text);
-CLANGSUPPORT_EXPORT std::ostream &operator<<(std::ostream &os, const Utf8String &utf8String);
-
-#define Utf8StringLiteral(str) Utf8String::fromByteArray(QByteArrayLiteral(str))
diff --git a/src/libs/clangsupport/utf8stringvector.cpp b/src/libs/clangsupport/utf8stringvector.cpp
deleted file mode 100644
index f892a173db1..00000000000
--- a/src/libs/clangsupport/utf8stringvector.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "utf8stringvector.h"
-
-#include <QStringList>
-#include <QDebug>
-
-#include <ostream>
-
-Utf8StringVector::Utf8StringVector()
-{
-}
-
-Utf8StringVector::Utf8StringVector(std::initializer_list<Utf8String> initializerList)
- : QVector<Utf8String>(initializerList)
-{
-
-}
-
-Utf8StringVector::Utf8StringVector(const Utf8String &utf8String)
-{
- append(utf8String);
-}
-
-Utf8StringVector::Utf8StringVector(const QVector<Utf8String> &vector)
- : QVector<Utf8String>(vector)
-{
-
-}
-
-Utf8StringVector::Utf8StringVector(const QStringList &stringList)
-{
- reserve(stringList.count());
-
- foreach (const QString &string, stringList)
- append(Utf8String(string));
-}
-
-Utf8StringVector::Utf8StringVector(int size, const Utf8String &text)
- : QVector<Utf8String>(size, text)
-{
-}
-
-Utf8String Utf8StringVector::join(const Utf8String &separator) const
-{
- Utf8String joindedString;
-
- joindedString.reserve(totalByteSize() + separator.byteSize() * count());
-
- for (auto position = begin(); position != end(); ++position) {
- joindedString.append(*position);
- if (std::next(position) != end())
- joindedString.append(separator);
- }
-
- return joindedString;
-}
-
-Utf8StringVector Utf8StringVector::fromIntegerVector(const QVector<int> &integerVector)
-{
- Utf8StringVector utf8StringVector;
- utf8StringVector.reserve(integerVector.count());
-
- foreach (int integer, integerVector)
- utf8StringVector.append(Utf8String::number(integer));
-
- return utf8StringVector;
-}
-
-void Utf8StringVector::registerType()
-{
- qRegisterMetaType<Utf8StringVector>("Utf8StringVector");
-}
-
-int Utf8StringVector::totalByteSize() const
-{
- int totalSize = 0;
-
- for (const Utf8String &utf8String : *this)
- totalSize += utf8String.byteSize();
-
- return totalSize;
-}
-
-QDebug operator<<(QDebug debug, const Utf8StringVector &textVector)
-{
- debug << "Utf8StringVector(" << textVector.join(Utf8StringLiteral(", ")).constData() << ")";
-
- return debug;
-}
diff --git a/src/libs/clangsupport/utf8stringvector.h b/src/libs/clangsupport/utf8stringvector.h
deleted file mode 100644
index 31c681ecb95..00000000000
--- a/src/libs/clangsupport/utf8stringvector.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-#include "utf8string.h"
-
-#include <QDataStream>
-#include <QVector>
-
-#include <ostream>
-
-class CLANGSUPPORT_EXPORT Utf8StringVector : public QVector<Utf8String>
-{
-public:
- Utf8StringVector();
- Utf8StringVector(std::initializer_list<Utf8String> initializerList);
- explicit Utf8StringVector(const Utf8String &utf8String);
- Utf8StringVector(const QVector<Utf8String> &vector);
- explicit Utf8StringVector(const QStringList &stringList);
- explicit Utf8StringVector(int size, const Utf8String &text);
-
- Utf8String join(const Utf8String &separator) const;
-
- static Utf8StringVector fromIntegerVector(const QVector<int> &integerVector);
-
- static void registerType();
-
- inline bool removeFast(const Utf8String &valueToBeRemoved);
-
-protected:
- int totalByteSize() const;
-};
-
-bool Utf8StringVector::removeFast(const Utf8String &valueToBeRemoved)
-{
- auto position = std::remove(begin(), end(), valueToBeRemoved);
-
- bool hasEntry = position != end();
-
- erase(position, end());
-
- return hasEntry;
-}
-
-namespace std { // it has to be in std namespace for lookup
-
-template <typename T>
-ostream &operator<<(ostream &out, const QVector<T> &vector)
-{
- out << "[";
-
- copy(vector.cbegin(), vector.cend(), ostream_iterator<T>(out, ", "));
-
- out << "]";
-
- return out;
-}
-
-inline
-ostream &operator<<(ostream &out, const Utf8StringVector &vector)
-{
- out << "[";
-
- copy(vector.cbegin(), vector.cend(), ostream_iterator<Utf8String>(out, ", "));
-
- out << "]";
-
- return out;
-}
-
-} // namespace std
-
-inline QDataStream &operator<<(QDataStream &s, const Utf8StringVector &v)
-{ return s << static_cast<const QVector<Utf8String> &>(v); }
-
-inline QDataStream &operator>>(QDataStream &s, Utf8StringVector &v)
-{ return s >> static_cast<QVector<Utf8String> &>(v); }
-
-CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const Utf8StringVector &textVector);
-
-Q_DECLARE_METATYPE(Utf8StringVector)
diff --git a/src/libs/clangsupport/writemessageblock.cpp b/src/libs/clangsupport/writemessageblock.cpp
deleted file mode 100644
index b3fe4a51edb..00000000000
--- a/src/libs/clangsupport/writemessageblock.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "writemessageblock.h"
-
-#include "messageenvelop.h"
-
-#include <QDataStream>
-#include <QDebug>
-#include <QLocalSocket>
-#include <QVariant>
-
-namespace ClangBackEnd {
-
-WriteMessageBlock::WriteMessageBlock(QIODevice *ioDevice)
- : m_ioDevice(ioDevice)
-{}
-
-WriteMessageBlock::WriteMessageBlock(QLocalSocket *localSocket)
- : m_ioDevice(localSocket)
- , m_localSocket(localSocket)
-{}
-
-void WriteMessageBlock::write(const MessageEnvelop &message)
-{
- QDataStream out(&m_block, QIODevice::WriteOnly | QIODevice::Append);
-
- int startOffset = m_block.size();
- const qint32 dummyBockSize = 0;
- out << dummyBockSize;
-
- out << m_messageCounter;
-
- out << message;
-
- out.device()->seek(startOffset);
- out << qint32(m_block.size() - startOffset - sizeof(qint32));
-
- ++m_messageCounter;
-
- flushBlock();
-}
-
-qint64 WriteMessageBlock::counter() const
-{
- return m_messageCounter;
-}
-
-void WriteMessageBlock::resetState()
-{
- m_block.clear();
- m_messageCounter = 0;
-}
-
-void WriteMessageBlock::setIoDevice(QIODevice *ioDevice)
-{
- m_ioDevice = ioDevice;
- if (m_localSocket != ioDevice)
- m_localSocket = nullptr;
-
- flushBlock();
-}
-
-void WriteMessageBlock::setLocalSocket(QLocalSocket *localSocket)
-{
- m_localSocket = localSocket;
-
- setIoDevice(localSocket);
-}
-
-void WriteMessageBlock::flushBlock()
-{
- if (m_ioDevice) {
- const qint64 bytesWritten = m_ioDevice->write(m_block);
- m_block.clear();
- if (bytesWritten == -1)
- qWarning() << "Failed to write data:" << m_ioDevice->errorString();
- if (m_localSocket)
- m_localSocket->flush();
- }
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangsupport/writemessageblock.h b/src/libs/clangsupport/writemessageblock.h
deleted file mode 100644
index e8baa978d05..00000000000
--- a/src/libs/clangsupport/writemessageblock.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QByteArray>
-#include <QtGlobal>
-
-#include "clangsupport_global.h"
-
-QT_BEGIN_NAMESPACE
-class QVariant;
-class QDataStream;
-class QIODevice;
-class QLocalSocket;
-QT_END_NAMESPACE
-
-namespace ClangBackEnd {
-
-class MessageEnvelop;
-
-class CLANGSUPPORT_EXPORT WriteMessageBlock
-{
-public:
- WriteMessageBlock(QIODevice *ioDevice = nullptr);
- WriteMessageBlock(QLocalSocket *localSocket);
-
- void write(const MessageEnvelop &message);
-
- qint64 counter() const;
-
- void resetState();
-
- void setIoDevice(QIODevice *ioDevice);
- void setLocalSocket(QLocalSocket *localSocket);
-
- void flushBlock();
-
-private:
- QByteArray m_block;
- qint64 m_messageCounter = 0;
- QIODevice *m_ioDevice = {};
- QLocalSocket *m_localSocket = {};
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/cplusplus/AlreadyConsideredClassContainer.h b/src/libs/cplusplus/AlreadyConsideredClassContainer.h
index 01260c0348c..1f0109d756b 100644
--- a/src/libs/cplusplus/AlreadyConsideredClassContainer.h
+++ b/src/libs/cplusplus/AlreadyConsideredClassContainer.h
@@ -48,7 +48,7 @@ public:
return true;
SafeMatcher matcher;
- foreach (const T *existingItem, _container) {
+ for (const T *existingItem : qAsConst(_container)) {
if (Matcher::match(existingItem, item, &matcher))
return true;
}
diff --git a/src/libs/cplusplus/CMakeLists.txt b/src/libs/cplusplus/CMakeLists.txt
index aa650c11b34..76cbcbde141 100644
--- a/src/libs/cplusplus/CMakeLists.txt
+++ b/src/libs/cplusplus/CMakeLists.txt
@@ -1,10 +1,7 @@
-# TODO: Support static build, currently being done with CPLUSPLUS_BUILD_STATIC_LIB
-# -- if really needed that is.
# TODO: Make Qt5::Gui optional -- if really needed that is.
add_qtc_library(CPlusPlus
DEPENDS Utils Qt5::Concurrent
- DEFINES CPLUSPLUS_BUILD_LIB
PUBLIC_DEPENDS 3rd_cplusplus Qt5::Gui
SOURCES
ASTParent.cpp ASTParent.h
@@ -43,6 +40,12 @@ add_qtc_library(CPlusPlus
SKIP_PCH
)
+set(export_symbol_declaration DEFINES CPLUSPLUS_BUILD_LIB)
+if (QTC_STATIC_BUILD)
+ set(export_symbol_declaration PUBLIC_DEFINES CPLUSPLUS_BUILD_STATIC_LIB)
+endif()
+extend_qtc_target(CPlusPlus ${export_symbol_declaration})
+
if(TARGET CPlusPlus)
qtc_enable_release_for_debug_configuration()
if (BUILD_WITH_PCH)
diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index e33c4708965..4db91090842 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -174,7 +174,7 @@ protected:
bool visit(Template *symbol) override
{
if (Symbol *decl = symbol->declaration()) {
- if (decl->isFunction() || decl->isClass() || decl->isDeclaration())
+ if (decl->asFunction() || decl->asClass() || decl->asDeclaration())
return process(symbol);
}
return true;
@@ -356,7 +356,7 @@ QString Document::fileName() const
QStringList Document::includedFiles() const
{
QStringList files;
- foreach (const Include &i, _resolvedIncludes)
+ for (const Include &i : qAsConst(_resolvedIncludes))
files.append(i.resolvedFileName());
files.removeDuplicates();
return files;
@@ -387,7 +387,7 @@ void Document::addMacroUse(const Macro &macro,
utf16charsOffset, utf16charsOffset + utf16charLength,
beginLine);
- foreach (const MacroArgumentReference &actual, actuals) {
+ for (const MacroArgumentReference &actual : actuals) {
const Block arg(actual.bytesOffset(),
actual.bytesOffset() + actual.bytesLength(),
actual.utf16charsOffset(),
@@ -522,7 +522,7 @@ QString Document::functionAt(int line, int column, int *lineOpeningDeclaratorPar
if (!scope)
scope = symbol->enclosingScope();
- while (scope && !scope->isFunction() )
+ while (scope && !scope->asFunction() )
scope = scope->enclosingScope();
if (!scope)
@@ -555,7 +555,7 @@ Symbol *Document::lastVisibleSymbolAt(int line, int column) const
const Macro *Document::findMacroDefinitionAt(int line) const
{
- foreach (const Macro &macro, _definedMacros) {
+ for (const Macro &macro : qAsConst(_definedMacros)) {
if (macro.line() == line)
return &macro;
}
@@ -564,7 +564,7 @@ const Macro *Document::findMacroDefinitionAt(int line) const
const Document::MacroUse *Document::findMacroUseAt(int utf16charsOffset) const
{
- foreach (const Document::MacroUse &use, _macroUses) {
+ for (const Document::MacroUse &use : qAsConst(_macroUses)) {
if (use.containsUtf16charOffset(utf16charsOffset)
&& (utf16charsOffset < use.utf16charsBegin() + use.macro().nameToQString().size())) {
return &use;
@@ -575,7 +575,7 @@ const Document::MacroUse *Document::findMacroUseAt(int utf16charsOffset) const
const Document::UndefinedMacroUse *Document::findUndefinedMacroUseAt(int utf16charsOffset) const
{
- foreach (const Document::UndefinedMacroUse &use, _undefinedMacroUses) {
+ for (const Document::UndefinedMacroUse &use : qAsConst(_undefinedMacroUses)) {
if (use.containsUtf16charOffset(utf16charsOffset)
&& (utf16charsOffset < use.utf16charsBegin()
+ QString::fromUtf8(use.name(), use.name().size()).length()))
@@ -776,7 +776,7 @@ static QList<Macro> macrosDefinedUntilLine(const QList<Macro> &macros, int line)
{
QList<Macro> filtered;
- foreach (const Macro &macro, macros) {
+ for (const Macro &macro : macros) {
if (macro.line() <= line)
filtered.append(macro);
else
@@ -859,7 +859,8 @@ QList<Snapshot::IncludeLocation> Snapshot::includeLocationsOfDocument(const QStr
QList<IncludeLocation> result;
for (const_iterator cit = begin(), citEnd = end(); cit != citEnd; ++cit) {
const Document::Ptr doc = cit.value();
- foreach (const Document::Include &includeFile, doc->resolvedIncludes()) {
+ const QList<Document::Include> includeFiles = doc->resolvedIncludes();
+ for (const Document::Include &includeFile : includeFiles) {
if (includeFile.resolvedFileName() == fileName)
result.append(qMakePair(doc, includeFile.line()));
}
@@ -901,7 +902,8 @@ Snapshot Snapshot::simplified(Document::Ptr doc) const
if (doc) {
snapshot.insert(doc);
- foreach (const QString &fileName, allIncludesForDocument(doc->fileName()))
+ const QSet<QString> fileNames = allIncludesForDocument(doc->fileName());
+ for (const QString &fileName : fileNames)
if (Document::Ptr inc = document(fileName))
snapshot.insert(inc);
}
diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h
index 1dfa5043b9a..21e1ac7e776 100644
--- a/src/libs/cplusplus/CppDocument.h
+++ b/src/libs/cplusplus/CppDocument.h
@@ -31,7 +31,7 @@
#include <cplusplus/PreprocessorClient.h>
#include <cplusplus/DependencyTable.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <QSharedPointer>
#include <QDateTime>
diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp
index 14d738da791..e10d9aeec23 100644
--- a/src/libs/cplusplus/CppRewriter.cpp
+++ b/src/libs/cplusplus/CppRewriter.cpp
@@ -458,8 +458,8 @@ FullySpecifiedType UseMinimalNames::apply(const Name *name, Rewrite *rewrite) co
SubstitutionEnvironment *env = rewrite->env;
Scope *scope = env->scope();
- if (name->isTemplateNameId() ||
- (name->isQualifiedNameId() && name->asQualifiedNameId()->name()->isTemplateNameId()))
+ if (name->asTemplateNameId() ||
+ (name->asQualifiedNameId() && name->asQualifiedNameId()->name()->asTemplateNameId()))
return FullySpecifiedType();
if (! scope)
diff --git a/src/libs/cplusplus/DependencyTable.cpp b/src/libs/cplusplus/DependencyTable.cpp
index 2f6b4600f8c..6857e7e1c00 100644
--- a/src/libs/cplusplus/DependencyTable.cpp
+++ b/src/libs/cplusplus/DependencyTable.cpp
@@ -79,7 +79,7 @@ void DependencyTable::build(QFutureInterfaceBase &futureInterface, const Snapsho
QList<int> directIncludes;
const QStringList documentIncludes = doc->includedFiles();
- foreach (const QString &includedFile, documentIncludes) {
+ for (const QString &includedFile : documentIncludes) {
int index = fileIndex.value(Utils::FilePath::fromString(includedFile));
if (index == -1)
@@ -108,7 +108,8 @@ void DependencyTable::build(QFutureInterfaceBase &futureInterface, const Snapsho
QBitArray bitmap = includeMap.value(i);
QBitArray previousBitmap = bitmap;
- foreach (int includedFileIndex, includes.value(i)) {
+ const QList<int> includedFileIndexes = includes.value(i);
+ for (const int includedFileIndex : includedFileIndexes) {
bitmap |= includeMap.value(includedFileIndex);
if (futureInterface.isCanceled())
return;
diff --git a/src/libs/cplusplus/FastPreprocessor.cpp b/src/libs/cplusplus/FastPreprocessor.cpp
index be63dea9a29..b90a65c39ee 100644
--- a/src/libs/cplusplus/FastPreprocessor.cpp
+++ b/src/libs/cplusplus/FastPreprocessor.cpp
@@ -57,7 +57,8 @@ QByteArray FastPreprocessor::run(Document::Ptr newDoc,
mergeEnvironment(i.key().toString());
}
- foreach (const Document::Include &i, doc->resolvedIncludes())
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &i : includes)
mergeEnvironment(i.resolvedFileName());
if (mergeDefinedMacrosOfDocument)
@@ -89,7 +90,8 @@ void FastPreprocessor::mergeEnvironment(const QString &fileName)
_merged.insert(fileName);
if (Document::Ptr doc = _snapshot.document(fileName)) {
- foreach (const Document::Include &i, doc->resolvedIncludes())
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &i : includes)
mergeEnvironment(i.resolvedFileName());
_env.addMacros(doc->definedMacros());
diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index f4fbecd0798..8ec65c021a5 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -142,11 +142,30 @@ void FindUsages::reportResult(unsigned tokenIndex, const QList<LookupItem> &cand
const int len = tk.utf16chars();
const Usage u(Utils::FilePath::fromString(_doc->fileName()), lineText,
- getType(line, col, tokenIndex), line, col - 1, len);
+ getContainingFunction(line, col), getType(line, col, tokenIndex),
+ line, col - 1, len);
_usages.append(u);
_references.append(tokenIndex);
}
+QString FindUsages::getContainingFunction(int line, int column)
+{
+ const QList<AST *> astPath = ASTPath(_doc)(line, column);
+ bool hasBlock = false;
+ for (auto it = astPath.crbegin(); it != astPath.crend(); ++it) {
+ if (!hasBlock && (*it)->asCompoundStatement())
+ hasBlock = true;
+ if (const auto func = (*it)->asFunctionDefinition()) {
+ if (!hasBlock)
+ return {};
+ if (!func->symbol)
+ return {};
+ return Overview().prettyName(func->symbol->name());
+ }
+ }
+ return {};
+}
+
class FindUsages::GetUsageType
{
public:
@@ -495,7 +514,7 @@ QString FindUsages::matchingLine(const Token &tk) const
bool FindUsages::isLocalScope(Scope *scope)
{
if (scope) {
- if (scope->isBlock() || scope->isTemplate() || scope->isFunction())
+ if (scope->asBlock() || scope->asTemplate() || scope->asFunction())
return true;
}
@@ -508,7 +527,7 @@ bool FindUsages::checkCandidates(const QList<LookupItem> &candidates) const
const LookupItem &r = candidates.at(i);
if (Symbol *s = r.declaration()) {
- if (_declSymbol->isTypenameArgument()) {
+ if (_declSymbol->asTypenameArgument()) {
if (s != _declSymbol)
return false;
}
@@ -516,8 +535,8 @@ bool FindUsages::checkCandidates(const QList<LookupItem> &candidates) const
Scope *declEnclosingScope = _declSymbol->enclosingScope();
Scope *enclosingScope = s->enclosingScope();
if (isLocalScope(declEnclosingScope) || isLocalScope(enclosingScope)) {
- if (_declSymbol->isClass() && declEnclosingScope->isTemplate()
- && s->isClass() && enclosingScope->isTemplate()) {
+ if (_declSymbol->asClass() && declEnclosingScope->asTemplate()
+ && s->asClass() && enclosingScope->asTemplate()) {
// for definition of functions of class defined outside the class definition
Scope *templEnclosingDeclSymbol = declEnclosingScope;
Scope *scopeOfTemplEnclosingDeclSymbol
@@ -528,9 +547,9 @@ bool FindUsages::checkCandidates(const QList<LookupItem> &candidates) const
if (scopeOfTemplEnclosingCandidateSymbol != scopeOfTemplEnclosingDeclSymbol)
return false;
- } else if (_declSymbol->isClass() && declEnclosingScope->isTemplate()
- && enclosingScope->isClass()
- && enclosingScope->enclosingScope()->isTemplate()) {
+ } else if (_declSymbol->asClass() && declEnclosingScope->asTemplate()
+ && enclosingScope->asClass()
+ && enclosingScope->enclosingScope()->asTemplate()) {
// for declaration inside template class
Scope *templEnclosingDeclSymbol = declEnclosingScope;
Scope *scopeOfTemplEnclosingDeclSymbol
@@ -541,18 +560,18 @@ bool FindUsages::checkCandidates(const QList<LookupItem> &candidates) const
if (scopeOfTemplEnclosingCandidateSymbol != scopeOfTemplEnclosingDeclSymbol)
return false;
- } else if (enclosingScope->isTemplate() && ! _declSymbol->isTypenameArgument()) {
- if (declEnclosingScope->isTemplate()) {
+ } else if (enclosingScope->asTemplate() && ! _declSymbol->asTypenameArgument()) {
+ if (declEnclosingScope->asTemplate()) {
if (enclosingScope->enclosingScope() != declEnclosingScope->enclosingScope())
return false;
} else {
if (enclosingScope->enclosingScope() != declEnclosingScope)
return false;
}
- } else if (declEnclosingScope->isTemplate() && s->isTemplate()) {
+ } else if (declEnclosingScope->asTemplate() && s->asTemplate()) {
if (declEnclosingScope->enclosingScope() != enclosingScope)
return false;
- } else if (! s->isUsingDeclaration()
+ } else if (! s->asUsingDeclaration()
&& enclosingScope != declEnclosingScope) {
return false;
}
@@ -835,11 +854,12 @@ void FindUsages::memInitializer(MemInitializerAST *ast)
if (! ast)
return;
- if (_currentScope->isFunction()) {
+ if (_currentScope->asFunction()) {
Class *classScope = _currentScope->enclosingClass();
if (! classScope) {
if (ClassOrNamespace *binding = _context.lookupType(_currentScope)) {
- foreach (Symbol *s, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols) {
if (Class *k = s->asClass()) {
classScope = k;
break;
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index 87d1cbaef52..1210a745dae 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -42,11 +42,14 @@ public:
enum class Type { Declaration, Initialization, Read, Write, WritableRef, Other };
Usage() = default;
- Usage(const Utils::FilePath &path, const QString &lineText, Type t, int line, int col, int len)
- : path(path), lineText(lineText), type(t), line(line), col(col), len(len) {}
+ Usage(const Utils::FilePath &path, const QString &lineText, const QString &func, Type t,
+ int line, int col, int len)
+ : path(path), lineText(lineText), containingFunction(func), type(t),
+ line(line), col(col), len(len) {}
Utils::FilePath path;
QString lineText;
+ QString containingFunction;
Type type = Type::Other;
int line = 0;
int col = 0;
@@ -75,6 +78,7 @@ protected:
void reportResult(unsigned tokenIndex, const Name *name, Scope *scope = nullptr);
void reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates);
Usage::Type getType(int line, int column, int tokenIndex);
+ QString getContainingFunction(int line, int column);
bool checkCandidates(const QList<LookupItem> &candidates) const;
void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = nullptr);
diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp
index e0d681563bd..aaf258b5577 100644
--- a/src/libs/cplusplus/Icons.cpp
+++ b/src/libs/cplusplus/Icons.cpp
@@ -57,7 +57,7 @@ Utils::CodeModelIcon::Type iconTypeForSymbol(const Symbol *symbol)
}
FullySpecifiedType symbolType = symbol->type();
- if (symbol->isFunction() || (symbol->isDeclaration() && symbolType &&
+ if (symbol->asFunction() || (symbol->asDeclaration() && symbolType &&
symbolType->isFunctionType()))
{
const Function *function = symbol->asFunction();
@@ -80,9 +80,9 @@ Utils::CodeModelIcon::Type iconTypeForSymbol(const Symbol *symbol)
} else if (symbol->isPrivate()) {
return symbol->isStatic() ? FuncPrivateStatic : FuncPrivate;
}
- } else if (symbol->enclosingScope() && symbol->enclosingScope()->isEnum()) {
+ } else if (symbol->enclosingScope() && symbol->enclosingScope()->asEnum()) {
return Enumerator;
- } else if (symbol->isDeclaration() || symbol->isArgument()) {
+ } else if (symbol->asDeclaration() || symbol->asArgument()) {
if (symbol->isPublic()) {
return symbol->isStatic() ? VarPublicStatic : VarPublic;
} else if (symbol->isProtected()) {
@@ -90,26 +90,26 @@ Utils::CodeModelIcon::Type iconTypeForSymbol(const Symbol *symbol)
} else if (symbol->isPrivate()) {
return symbol->isStatic() ? VarPrivateStatic : VarPrivate;
}
- } else if (symbol->isEnum()) {
+ } else if (symbol->asEnum()) {
return Utils::CodeModelIcon::Enum;
- } else if (symbol->isForwardClassDeclaration()) {
+ } else if (symbol->asForwardClassDeclaration()) {
return Utils::CodeModelIcon::Class; // TODO: Store class key in ForwardClassDeclaration
} else if (const Class *klass = symbol->asClass()) {
return klass->isStruct() ? Struct : Utils::CodeModelIcon::Class;
- } else if (symbol->isObjCClass() || symbol->isObjCForwardClassDeclaration()) {
+ } else if (symbol->asObjCClass() || symbol->asObjCForwardClassDeclaration()) {
return Utils::CodeModelIcon::Class;
- } else if (symbol->isObjCProtocol() || symbol->isObjCForwardProtocolDeclaration()) {
+ } else if (symbol->asObjCProtocol() || symbol->asObjCForwardProtocolDeclaration()) {
return Utils::CodeModelIcon::Class;
- } else if (symbol->isObjCMethod()) {
+ } else if (symbol->asObjCMethod()) {
return FuncPublic;
- } else if (symbol->isNamespace()) {
+ } else if (symbol->asNamespace()) {
return Utils::CodeModelIcon::Namespace;
- } else if (symbol->isTypenameArgument()) {
+ } else if (symbol->asTypenameArgument()) {
return Utils::CodeModelIcon::Class;
- } else if (symbol->isQtPropertyDeclaration() || symbol->isObjCPropertyDeclaration()) {
+ } else if (symbol->asQtPropertyDeclaration() || symbol->asObjCPropertyDeclaration()) {
return Property;
- } else if (symbol->isUsingNamespaceDirective() ||
- symbol->isUsingDeclaration()) {
+ } else if (symbol->asUsingNamespaceDirective() ||
+ symbol->asUsingDeclaration()) {
// TODO: Might be nice to have a different icons for these things
return Utils::CodeModelIcon::Namespace;
}
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 7fcb3f4caa2..b3d3882ca07 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -56,7 +56,7 @@ static void addNames(const Name *name, QList<const Name *> *names, bool addAllNa
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
addNames(q->base(), names);
addNames(q->name(), names, addAllNames);
- } else if (addAllNames || name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
+ } else if (addAllNames || name->asNameId() || name->asTemplateNameId() || name->asAnonymousNameId()) {
names->append(name);
}
}
@@ -71,7 +71,7 @@ static void path_helper(Symbol *symbol,
path_helper(symbol->enclosingScope(), names, policy);
if (symbol->name()) {
- if (symbol->isClass() || symbol->isNamespace()) {
+ if (symbol->asClass() || symbol->asNamespace()) {
if (policy == LookupContext::HideInlineNamespaces) {
auto ns = symbol->asNamespace();
if (ns && ns->isInline())
@@ -79,12 +79,12 @@ static void path_helper(Symbol *symbol,
}
addNames(symbol->name(), names);
- } else if (symbol->isObjCClass() || symbol->isObjCBaseClass() || symbol->isObjCProtocol()
- || symbol->isObjCForwardClassDeclaration() || symbol->isObjCForwardProtocolDeclaration()
- || symbol->isForwardClassDeclaration()) {
+ } else if (symbol->asObjCClass() || symbol->asObjCBaseClass() || symbol->asObjCProtocol()
+ || symbol->asObjCForwardClassDeclaration() || symbol->asObjCForwardProtocolDeclaration()
+ || symbol->asForwardClassDeclaration()) {
addNames(symbol->name(), names);
- } else if (symbol->isFunction()) {
+ } else if (symbol->asFunction()) {
if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId())
addNames(q->base(), names);
} else if (Enum *e = symbol->asEnum()) {
@@ -217,7 +217,6 @@ LookupContext &LookupContext::operator=(const LookupContext &other)
QList<const Name *> LookupContext::fullyQualifiedName(Symbol *symbol, InlineNamespacePolicy policy)
{
QList<const Name *> qualifiedName = path(symbol->enclosingScope(), policy);
- QList<const Name *> symbolNames;
addNames(symbol->name(), &qualifiedName, /*add all names*/ true);
return qualifiedName;
}
@@ -317,8 +316,9 @@ QList<LookupItem> LookupContext::lookupByUsing(const Name *name,
{
QList<LookupItem> candidates;
// if it is a nameId there can be a using declaration for it
- if (name->isNameId() || name->isTemplateNameId()) {
- foreach (Symbol *s, bindingScope->symbols()) {
+ if (name->asNameId() || name->asTemplateNameId()) {
+ const QList<Symbol *> symbols = bindingScope->symbols();
+ for (Symbol *s : symbols) {
if (Scope *scope = s->asScope()) {
for (int i = 0, count = scope->memberCount(); i < count; ++i) {
if (UsingDeclaration *u = scope->memberAt(i)->asUsingDeclaration()) {
@@ -345,7 +345,8 @@ QList<LookupItem> LookupContext::lookupByUsing(const Name *name,
}
}
} else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
- foreach (Symbol *s, bindingScope->symbols()) {
+ const QList<Symbol *> symbols = bindingScope->symbols();
+ for (Symbol *s : symbols) {
if (Scope *scope = s->asScope()) {
ClassOrNamespace *base = lookupType(q->base(), scope);
if (base)
@@ -408,7 +409,7 @@ ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope,
}
}
} else if (UsingDeclaration *ud = m->asUsingDeclaration()) {
- if (name->isNameId()) {
+ if (name->asNameId()) {
if (const Name *usingDeclarationName = ud->name()) {
if (const QualifiedNameId *q = usingDeclarationName->asQualifiedNameId()) {
if (q->name() && q->name()->match(name))
@@ -432,7 +433,7 @@ ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope,
} else if (ClassOrNamespace *b = bindings()->lookupType(scope, enclosingBinding)) {
return b->lookupType(name);
} else if (Class *scopeAsClass = scope->asClass()) {
- if (scopeAsClass->enclosingScope()->isBlock()) {
+ if (scopeAsClass->enclosingScope()->asBlock()) {
if (ClassOrNamespace *b = lookupType(scopeAsClass->name(),
scopeAsClass->enclosingScope(),
enclosingBinding,
@@ -459,13 +460,13 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
return candidates;
for (; scope; scope = scope->enclosingScope()) {
- if (name->identifier() != nullptr && scope->isBlock()) {
+ if (name->identifier() != nullptr && scope->asBlock()) {
bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ nullptr, /*binding=*/ nullptr);
if (! candidates.isEmpty()) {
// it's a local.
//for qualified it can be outside of the local scope
- if (name->isQualifiedNameId())
+ if (name->asQualifiedNameId())
continue;
else
break;
@@ -501,13 +502,13 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
if (! candidates.isEmpty()) {
// it's an argument or a template parameter.
//for qualified it can be outside of the local scope
- if (name->isQualifiedNameId())
+ if (name->asQualifiedNameId())
continue;
else
break;
}
- if (fun->name() && fun->name()->isQualifiedNameId()) {
+ if (fun->name() && fun->name()->asQualifiedNameId()) {
if (ClassOrNamespace *binding = bindings()->lookupType(fun)) {
candidates = binding->find(name);
@@ -539,7 +540,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
if (! candidates.isEmpty()) {
// it's a template parameter.
//for qualified it can be outside of the local scope
- if (name->isQualifiedNameId())
+ if (name->asQualifiedNameId())
continue;
else
break;
@@ -571,7 +572,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
if (! candidates.isEmpty())
return candidates;
- } else if (scope->isObjCClass() || scope->isObjCProtocol()) {
+ } else if (scope->asObjCClass() || scope->asObjCProtocol()) {
if (ClassOrNamespace *binding = bindings()->lookupType(scope))
candidates = binding->find(name);
@@ -585,9 +586,9 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const
{
- QList<const Name *> fqName = path(symbol);
+ const QList<const Name *> fqName = path(symbol);
ClassOrNamespace *binding = globalNamespace();
- foreach (const Name *name, fqName) {
+ for (const Name *name : fqName) {
binding = binding->findType(name);
if (!binding)
return nullptr;
@@ -628,7 +629,7 @@ ClassOrNamespace *ClassOrNamespace::parent() const
return _parent;
}
-QList<ClassOrNamespace *> ClassOrNamespace::usings() const
+const QList<ClassOrNamespace *> ClassOrNamespace::usings() const
{
const_cast<ClassOrNamespace *>(this)->flush();
return _usings;
@@ -640,7 +641,7 @@ QList<Enum *> ClassOrNamespace::unscopedEnums() const
return _enums;
}
-QList<Symbol *> ClassOrNamespace::symbols() const
+const QList<Symbol *> ClassOrNamespace::symbols() const
{
const_cast<ClassOrNamespace *>(this)->flush();
return _symbols;
@@ -735,10 +736,11 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
const Identifier *nameId = name->identifier();
- foreach (Symbol *s, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols) {
if (s->isFriend())
continue;
- else if (s->isUsingNamespaceDirective())
+ else if (s->asUsingNamespaceDirective())
continue;
@@ -757,10 +759,12 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
}
}
- foreach (Enum *e, binding->unscopedEnums())
+ const QList<Enum *> enums = binding->unscopedEnums();
+ for (Enum *e : enums)
_factory->lookupInScope(name, e, result, templateId, binding);
- foreach (ClassOrNamespace *u, binding->usings())
+ const QList<ClassOrNamespace *> usings = binding->usings();
+ for (ClassOrNamespace *u : usings)
lookup_helper(name, u, result, processed, binding->_templateId);
Anonymouses::const_iterator cit = binding->_anonymouses.constBegin();
@@ -821,11 +825,11 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
for (Symbol *s = scope->find(id); s; s = s->next()) {
if (s->isFriend())
continue; // skip friends
- else if (s->isUsingNamespaceDirective())
+ else if (s->asUsingNamespaceDirective())
continue; // skip using namespace directives
else if (! id->match(s->identifier()))
continue;
- else if (s->name() && s->name()->isQualifiedNameId())
+ else if (s->name() && s->name()->asQualifiedNameId())
continue; // skip qualified ids.
if (Q_UNLIKELY(debug)) {
@@ -847,7 +851,7 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
}
}
- if (templateId && (s->isDeclaration() || s->isFunction())) {
+ if (templateId && (s->asDeclaration() || s->asFunction())) {
FullySpecifiedType ty = DeprecatedGenTemplateInstance::instantiate(templateId, s, control());
item.setType(ty); // override the type.
}
@@ -987,16 +991,18 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
} else if (! processed->contains(this)) {
processed->insert(this);
- if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
+ if (name->asNameId() || name->asTemplateNameId() || name->asAnonymousNameId()) {
flush();
- foreach (Symbol *s, symbols()) {
+ const QList<Symbol *> symbolList = symbols();
+ for (Symbol *s : symbolList) {
if (Class *klass = s->asClass()) {
if (klass->identifier() && klass->identifier()->match(name->identifier()))
return this;
}
}
- foreach (Enum *e, unscopedEnums()) {
+ const QList<Enum *> enums = unscopedEnums();
+ for (Enum *e : enums) {
if (e->identifier() && e->identifier()->match(name->identifier()))
return this;
}
@@ -1019,7 +1025,8 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
}
}
- foreach (ClassOrNamespace *u, usings()) {
+ const QList<ClassOrNamespace *> usingList = usings();
+ for (ClassOrNamespace *u : usingList) {
if (ClassOrNamespace *r = u->lookupType_helper(name,
processed,
/*searchInEnclosingScope =*/ false,
@@ -1038,7 +1045,8 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
static ClassOrNamespace *findSpecializationWithMatchingTemplateArgument(const Name *argumentName,
ClassOrNamespace *reference)
{
- foreach (Symbol *s, reference->symbols()) {
+ const QList<Symbol *> symbols = reference->symbols();
+ for (Symbol *s : symbols) {
if (Class *clazz = s->asClass()) {
if (Template *templateSpecialization = clazz->enclosingTemplate()) {
const int argumentCountOfSpecialization
@@ -1128,7 +1136,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
ClassOrNamespace *origin)
{
Q_ASSERT(name != nullptr);
- Q_ASSERT(name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId());
+ Q_ASSERT(name->asNameId() || name->asTemplateNameId() || name->asAnonymousNameId());
const_cast<ClassOrNamespace *>(this)->flush();
@@ -1225,7 +1233,8 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
Class *referenceClass = nullptr;
QList<const Name *> allBases;
- foreach (Symbol *s, reference->symbols()) {
+ const QList<Symbol *> symbols = reference->symbols();
+ for (Symbol *s : symbols) {
if (Class *clazz = s->asClass()) {
for (int i = 0; i < clazz->baseClassCount(); ++i) {
BaseClass *baseClass = clazz->baseClassAt(i);
@@ -1246,7 +1255,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
return reference;
}
- if (!name->isTemplateNameId())
+ if (!name->asTemplateNameId())
_alreadyConsideredClasses.insert(referenceClass);
QSet<ClassOrNamespace *> knownUsings = Utils::toSet(reference->usings());
@@ -1261,7 +1270,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
instantiation->_templateId = templId;
QSet<ClassOrNamespace *> otherProcessed;
- while (!origin->_symbols.isEmpty() && origin->_symbols[0]->isBlock()) {
+ while (!origin->_symbols.isEmpty() && origin->_symbols[0]->asBlock()) {
if (otherProcessed.contains(origin))
break;
otherProcessed.insert(origin);
@@ -1339,7 +1348,8 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
subst.bind(cloner.name(name, &subst), ty);
}
- foreach (Symbol *s, reference->symbols()) {
+ const QList<Symbol *> symbols = reference->symbols();
+ for (Symbol *s : symbols) {
Symbol *clone = cloner.symbol(s, &subst);
clone->setEnclosingScope(s->enclosingScope());
instantiation->_symbols.append(clone);
@@ -1370,7 +1380,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
for (int i = 0; i < argumentCountOfSpecialization; ++i)
templParams.insert(templateSpecialization->templateParameterAt(i)->name(), i);
- foreach (const Name *baseName, allBases) {
+ for (const Name *baseName : qAsConst(allBases)) {
ClassOrNamespace *baseBinding = nullptr;
if (const Identifier *nameId = baseName->asNameId()) {
@@ -1448,7 +1458,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
// Find the missing bases for regular (non-template) types.
// Ex.: class A : public B<Some>::Type {};
- foreach (const Name *baseName, allBases) {
+ for (const Name *baseName : qAsConst(allBases)) {
ClassOrNamespace *binding = this;
if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) {
if (const Name *qualification = qBaseName->base())
@@ -1505,7 +1515,8 @@ void ClassOrNamespace::NestedClassInstantiator::instantiate(ClassOrNamespace *en
nestedClassOrNamespaceInstantiation->_usings.append(nestedClassOrNamespace->usings());
nestedClassOrNamespaceInstantiation->_instantiationOrigin = nestedClassOrNamespace;
- foreach (Symbol *s, nestedClassOrNamespace->_symbols) {
+ const QList<Symbol *> symbols = nestedClassOrNamespace->_symbols;
+ for (Symbol *s : symbols) {
Symbol *clone = _cloner.symbol(s, &_subst);
if (!clone->enclosingScope()) // Not from the cache but just cloned.
clone->setEnclosingScope(s->enclosingScope());
@@ -1527,7 +1538,7 @@ void ClassOrNamespace::NestedClassInstantiator::instantiate(ClassOrNamespace *en
bool ClassOrNamespace::NestedClassInstantiator::isInstantiateNestedClassNeeded(const QList<Symbol *> &symbols) const
{
- foreach (Symbol *s, symbols) {
+ for (Symbol *s : symbols) {
if (Class *klass = s->asClass()) {
int memberCount = klass->memberCount();
for (int i = 0; i < memberCount; ++i) {
@@ -1579,7 +1590,7 @@ void ClassOrNamespace::flush()
const QList<Symbol *> todo = _todo;
_todo.clear();
- foreach (Symbol *member, todo)
+ for (Symbol *member : todo)
_factory->process(member, this);
}
}
@@ -1623,7 +1634,7 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNa
return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin, clazz);
- } else if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
+ } else if (name->asNameId() || name->asTemplateNameId() || name->asAnonymousNameId()) {
QSet<ClassOrNamespace *> processed;
ClassOrNamespace *e = nestedType(name, &processed, origin);
@@ -1723,7 +1734,8 @@ void CreateBindings::process(Document::Ptr doc)
if (! _processed.contains(globalNamespace)) {
_processed.insert(globalNamespace);
- foreach (const Document::Include &i, doc->resolvedIncludes()) {
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &i : includes) {
if (Document::Ptr incl = _snapshot.document(i.resolvedFileName()))
process(incl);
}
@@ -1779,7 +1791,7 @@ bool CreateBindings::visit(Class *klass)
ClassOrNamespace *previous = _currentClassOrNamespace;
ClassOrNamespace *binding = nullptr;
- if (klass->name() && klass->name()->isQualifiedNameId())
+ if (klass->name() && klass->name()->asQualifiedNameId())
binding = _currentClassOrNamespace->lookupType(klass->name());
if (! binding)
@@ -1944,7 +1956,7 @@ bool CreateBindings::visit(NamespaceAlias *a)
return false;
} else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) {
- if (a->name()->isNameId() || a->name()->isTemplateNameId() || a->name()->isAnonymousNameId())
+ if (a->name()->asNameId() || a->name()->asTemplateNameId() || a->name()->asAnonymousNameId())
_currentClassOrNamespace->addNestedType(a->name(), e);
} else if (false) {
@@ -2030,12 +2042,12 @@ Symbol *CreateBindings::instantiateTemplateFunction(const Name *instantiationNam
Template *specialization) const
{
if (!specialization || !specialization->declaration()
- || !specialization->declaration()->isFunction())
+ || !specialization->declaration()->asFunction())
return nullptr;
int argumentCountOfInstantiation = 0;
const TemplateNameId *instantiation = nullptr;
- if (instantiationName->isTemplateNameId()) {
+ if (instantiationName->asTemplateNameId()) {
instantiation = instantiationName->asTemplateNameId();
argumentCountOfInstantiation = instantiation->templateArgumentCount();
} else {
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index ce52feec426..cb6fbb3bfa8 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -70,9 +70,9 @@ public:
ClassOrNamespace *instantiationOrigin() const;
ClassOrNamespace *parent() const;
- QList<ClassOrNamespace *> usings() const;
+ const QList<ClassOrNamespace *> usings() const;
QList<Enum *> unscopedEnums() const;
- QList<Symbol *> symbols() const;
+ const QList<Symbol *> symbols() const;
ClassOrNamespace *globalNamespace() const;
diff --git a/src/libs/cplusplus/Macro.cpp b/src/libs/cplusplus/Macro.cpp
index d0c905edf19..c1d23c46de8 100644
--- a/src/libs/cplusplus/Macro.cpp
+++ b/src/libs/cplusplus/Macro.cpp
@@ -69,7 +69,7 @@ QString Macro::decoratedName() const
if (f._functionLike) {
text += QLatin1Char('(');
bool first = true;
- foreach (const QByteArray &formal, _formals) {
+ for (const QByteArray &formal : qAsConst(_formals)) {
if (! first)
text += QLatin1String(", ");
else
diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp
index dafe521dd47..90bdc9b71ef 100644
--- a/src/libs/cplusplus/MatchingText.cpp
+++ b/src/libs/cplusplus/MatchingText.cpp
@@ -543,7 +543,7 @@ QString MatchingText::insertMatchingBrace(const QTextCursor &cursor, const QStri
}
QString result;
- foreach (const QChar &ch, text) {
+ for (const QChar &ch : qAsConst(text)) {
if (ch == QLatin1Char('(')) result += QLatin1Char(')');
else if (ch == QLatin1Char('[')) result += QLatin1Char(']');
else if (ch == QLatin1Char('{')) result += QLatin1Char('}');
diff --git a/src/libs/cplusplus/PreprocessorEnvironment.cpp b/src/libs/cplusplus/PreprocessorEnvironment.cpp
index 4ffc127a19d..a4ad2b20584 100644
--- a/src/libs/cplusplus/PreprocessorEnvironment.cpp
+++ b/src/libs/cplusplus/PreprocessorEnvironment.cpp
@@ -128,7 +128,7 @@ Macro *Environment::bind(const Macro &macro)
void Environment::addMacros(const QList<Macro> &macros)
{
- foreach (const Macro &macro, macros) {
+ for (const Macro &macro : macros) {
bind(macro);
}
}
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 99db8cef9df..6803194ec60 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -59,7 +59,7 @@ static QList<T> removeDuplicates(const QList<T> &results)
{
QList<T> uniqueList;
QSet<T> processed;
- foreach (const T &r, results) {
+ for (const T &r : results) {
if (processed.contains(r))
continue;
@@ -160,7 +160,7 @@ private:
Scope **scope, QSet<Symbol *>& visited)
{
bool foundTypedef = false;
- foreach (const LookupItem &it, namedTypeItems) {
+ for (const LookupItem &it : namedTypeItems) {
Symbol *declaration = it.declaration();
if (declaration && declaration->isTypedef()) {
if (visited.contains(declaration))
@@ -281,7 +281,7 @@ QList<LookupItem> ResolveExpression::switchResults(const QList<LookupItem> &resu
void ResolveExpression::addResults(const QList<Symbol *> &symbols)
{
- foreach (Symbol *symbol, symbols) {
+ for (Symbol *symbol : symbols) {
LookupItem item;
item.setType(symbol->type());
item.setScope(symbol->enclosingScope());
@@ -603,7 +603,8 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast)
} else if (namedTy != nullptr) {
const Name *starOp = control()->operatorNameId(OperatorNameId::StarOp);
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), p.scope(), p.binding())) {
- foreach (const LookupItem &r, b->find(starOp)) {
+ const QList<LookupItem> results = b->find(starOp);
+ for (const LookupItem &r : results) {
Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) {
if (maybeValidPrototype(funTy, 0)) {
@@ -841,7 +842,7 @@ bool ResolveExpression::visit(CallAST *ast)
if (_reference) {
typedef std::multimap<int, LookupItem> LookupMap;
LookupMap sortedResults;
- foreach (const LookupItem &base, baseResults) {
+ for (const LookupItem &base : baseResults) {
if (Function *funTy = base.type()->asFunctionType()) {
if (! maybeValidPrototype(funTy, actualArgumentCount))
continue;
@@ -874,7 +875,7 @@ bool ResolveExpression::visit(CallAST *ast)
const Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp);
- foreach (const LookupItem &result, baseResults) {
+ for (const LookupItem &result : baseResults) {
FullySpecifiedType ty = result.type().simplified();
Scope *scope = result.scope();
@@ -885,7 +886,8 @@ bool ResolveExpression::visit(CallAST *ast)
addResult(ty.simplified(), scope);
} else {
// operator()
- foreach (const LookupItem &r, b->find(functionCallOp)) {
+ const QList<LookupItem> results = b->find(functionCallOp);
+ for (const LookupItem &r : results) {
Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) {
if (maybeValidPrototype(funTy, actualArgumentCount)) {
@@ -931,7 +933,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
- foreach (const LookupItem &result, baseResults) {
+ for (const LookupItem &result : baseResults) {
FullySpecifiedType ty = result.type().simplified();
Scope *scope = result.scope();
@@ -946,7 +948,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
} else if (NamedType *namedTy = ty->asNamedType()) {
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
- foreach (const LookupItem &r, b->find(arrayAccessOp)) {
+ const QList<LookupItem> results = b->find(arrayAccessOp);
+ for (const LookupItem &r : results) {
Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) {
// ### TODO: check the actual arguments
@@ -970,7 +973,7 @@ QList<LookupItem> ResolveExpression::getMembers(ClassOrNamespace *binding, const
#if 0
const QList<LookupItem> originalMembers = binding->find(memberName);
- foreach (const LookupItem &m, originalMembers) {
+ for (const LookupItem &m, originalMembers) {
if (! m.binding() || ! m.binding()->templateId()) {
members.append(m);
continue;
@@ -1042,7 +1045,7 @@ ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &origina
ClassOrNamespace *binding = nullptr;
if (Class *klass = ty->asClassType()) {
- if (scope->isBlock())
+ if (scope->asBlock())
binding = _context.lookupType(klass->name(), scope, enclosingBinding);
if (!binding)
binding = _context.lookupType(klass, enclosingBinding);
@@ -1067,7 +1070,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
Overview oo;
TypedefsResolver typedefsResolver(_context);
- foreach (const LookupItem &r, baseResults) {
+ for (const LookupItem &r : baseResults) {
if (!r.type().type() || !r.scope())
continue;
FullySpecifiedType ty = r.type().simplified();
@@ -1113,7 +1116,8 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
const OperatorNameId *arrowOp
= control()->operatorNameId(OperatorNameId::ArrowOp);
- foreach (const LookupItem &r, binding->find(arrowOp)) {
+ const QList<LookupItem> results = binding->find(arrowOp);
+ for (const LookupItem &r : results) {
Symbol *overload = r.declaration();
if (! overload)
continue;
@@ -1131,7 +1135,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
instantiatedFunction = overloadTy->asFunctionType();
} else if (overloadType->isTemplateType()
&& overloadType->asTemplateType()->declaration()
- && overloadType->asTemplateType()->declaration()->isFunction()) {
+ && overloadType->asTemplateType()->declaration()->asFunction()) {
instantiatedFunction = overloadType->asTemplateType()->declaration()->asFunction();
}
@@ -1157,7 +1161,8 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
}
if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
- foreach (Symbol *originSymbol, origin->symbols()) {
+ const QList<Symbol *> symbols = origin->symbols();
+ for (Symbol *originSymbol : symbols) {
Scope *originScope = originSymbol->asScope();
if (originScope && originScope != scope
&& originScope != functionScope) {
@@ -1204,7 +1209,8 @@ ClassOrNamespace *ResolveExpression::findClassForTemplateParameterInExpressionSc
{
if (resultBinding) {
if (ClassOrNamespace *origin = resultBinding->instantiationOrigin()) {
- foreach (Symbol *originSymbol, origin->symbols()) {
+ const QList<Symbol *> symbols = origin->symbols();
+ for (Symbol *originSymbol : symbols) {
if (Scope *originScope = originSymbol->asScope()) {
if (ClassOrNamespace *retBinding = findClass(ty, originScope))
return retBinding;
@@ -1233,7 +1239,7 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
{
const QList<LookupItem> receiverResults = resolve(ast->receiver_expression, _scope);
- foreach (const LookupItem &result, receiverResults) {
+ for (const LookupItem &result : receiverResults) {
FullySpecifiedType ty = result.type().simplified();
ClassOrNamespace *binding = nullptr;
@@ -1250,7 +1256,8 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
}
if (binding) {
- foreach (const LookupItem &r, binding->lookup(ast->selector->name)) {
+ const QList<LookupItem> results = binding->lookup(ast->selector->name);
+ for (const LookupItem &r : results) {
Symbol *s = r.declaration();
if (ObjCMethod *m = s->asObjCMethod())
addResult(m->returnType(), result.scope());
diff --git a/src/libs/cplusplus/SnapshotSymbolVisitor.cpp b/src/libs/cplusplus/SnapshotSymbolVisitor.cpp
index e28b485173a..478067fc4e3 100644
--- a/src/libs/cplusplus/SnapshotSymbolVisitor.cpp
+++ b/src/libs/cplusplus/SnapshotSymbolVisitor.cpp
@@ -45,7 +45,8 @@ void SnapshotSymbolVisitor::accept(Document::Ptr doc, QSet<QString> *processed)
if (doc && doc->globalNamespace() && ! processed->contains(doc->fileName())) {
processed->insert(doc->fileName());
- foreach (const Document::Include &i, doc->resolvedIncludes()) {
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &i : includes) {
if (Document::Ptr incl = _snapshot.document(i.resolvedFileName()))
accept(incl, processed);
}
diff --git a/src/libs/cplusplus/SymbolNameVisitor.cpp b/src/libs/cplusplus/SymbolNameVisitor.cpp
index b34bf2f42a8..83fe82a9ded 100644
--- a/src/libs/cplusplus/SymbolNameVisitor.cpp
+++ b/src/libs/cplusplus/SymbolNameVisitor.cpp
@@ -41,7 +41,7 @@ void SymbolNameVisitor::accept(Symbol *symbol)
if (Scope *scope = symbol->enclosingScope())
accept(scope);
- if (! symbol->isTemplate()) {
+ if (! symbol->asTemplate()) {
if (const Name *name = symbol->name()) {
std::swap(_symbol, symbol);
accept(name);
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index 02f838542c1..235481ebef7 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -157,10 +157,12 @@ void TypeOfExpression::processEnvironment(Document::Ptr doc, Environment *env,
if (doc && ! processed->contains(doc->fileName())) {
processed->insert(doc->fileName());
- foreach (const Document::Include &incl, doc->resolvedIncludes())
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &incl : includes)
processEnvironment(m_snapshot.document(incl.resolvedFileName()), env, processed);
- foreach (const Macro &macro, doc->definedMacros())
+ const QList<Macro> macros = doc->definedMacros();
+ for (const Macro &macro : macros)
env->bind(macro);
}
}
diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp
index 5e0a7f1b699..57f1cebd471 100644
--- a/src/libs/cplusplus/pp-engine.cpp
+++ b/src/libs/cplusplus/pp-engine.cpp
@@ -1824,7 +1824,8 @@ void Preprocessor::handleDefineDirective(PPToken *tk)
if (macro.isFunctionLike()) {
macroId += '(';
bool fst = true;
- foreach (const QByteArray &formal, macro.formals()) {
+ const QVector<QByteArray> formals = macro.formals();
+ for (const QByteArray &formal : formals) {
if (! fst)
macroId += ", ";
fst = false;
diff --git a/src/libs/extensionsystem/extensionsystem_global.h b/src/libs/extensionsystem/extensionsystem_global.h
index 2cc8add8c59..59dbe629875 100644
--- a/src/libs/extensionsystem/extensionsystem_global.h
+++ b/src/libs/extensionsystem/extensionsystem_global.h
@@ -30,6 +30,8 @@
#if defined(EXTENSIONSYSTEM_LIBRARY)
# define EXTENSIONSYSTEM_EXPORT Q_DECL_EXPORT
+#elif defined(EXTENSIONSYSTEM_STATIC_LIBRARY)
+# define EXTENSIONSYSTEM_EXPORT
#else
# define EXTENSIONSYSTEM_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp
index 46dff4d78a8..16180a9358f 100644
--- a/src/libs/extensionsystem/pluginmanager.cpp
+++ b/src/libs/extensionsystem/pluginmanager.cpp
@@ -53,7 +53,7 @@
#include <utils/executeondestruction.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/qtcsettings.h>
@@ -422,7 +422,7 @@ QString PluginManager::systemInformation()
QtcProcess qtDiagProc;
qtDiagProc.setCommand(qtDiag);
qtDiagProc.runBlocking();
- if (qtDiagProc.result() == QtcProcess::FinishedWithSuccess)
+ if (qtDiagProc.result() == ProcessResult::FinishedWithSuccess)
result += qtDiagProc.allOutput() + "\n";
result += "Plugin information:\n\n";
auto longestSpec = std::max_element(d->pluginSpecs.cbegin(), d->pluginSpecs.cend(),
@@ -1553,12 +1553,14 @@ void PluginManagerPrivate::checkForProblematicPlugins()
? tr("%1 > About Plugins")
.arg(QGuiApplication::applicationDisplayName())
: tr("Help > About Plugins");
- const QString otherPluginsText = tr("The following plugins depend on "
- "%1 and are also disabled: %2.\n\n")
- .arg(spec->name(), dependentsList);
+ const QString otherPluginsText
+ = tr("If you temporarily disable %1, the following plugins that depend on "
+ "it are also disabled: %2.\n\n")
+ .arg(spec->name(), dependentsList);
const QString detailsText = (dependents.isEmpty() ? QString() : otherPluginsText)
+ tr("Disable plugins permanently in %1.").arg(pluginsMenu);
- const QString text = tr("It looks like %1 closed because of a problem with the \"%2\" "
+ const QString text = tr("The last time you started %1, it seems to have closed because "
+ "of a problem with the \"%2\" "
"plugin. Temporarily disable the plugin?")
.arg(QGuiApplication::applicationDisplayName(), spec->name());
QMessageBox dialog;
@@ -1692,11 +1694,20 @@ void PluginManagerPrivate::readPluginPaths()
// default
pluginCategories.insert(QString(), QVector<PluginSpec *>());
+ // from the file system
for (const QString &pluginFile : pluginFiles(pluginPaths)) {
PluginSpec *spec = PluginSpec::read(pluginFile);
- if (!spec) // not a Qt Creator plugin
- continue;
+ if (spec) // Qt Creator plugin
+ pluginSpecs.append(spec);
+ }
+ // static
+ for (const QStaticPlugin &plugin : QPluginLoader::staticPlugins()) {
+ PluginSpec *spec = PluginSpec::read(plugin);
+ if (spec) // Qt Creator plugin
+ pluginSpecs.append(spec);
+ }
+ for (PluginSpec *spec : pluginSpecs) {
// defaultDisabledPlugins and defaultEnabledPlugins from install settings
// is used to override the defaults read from the plugin spec
if (spec->isEnabledByDefault() && defaultDisabledPlugins.contains(spec->name())) {
@@ -1712,7 +1723,6 @@ void PluginManagerPrivate::readPluginPaths()
spec->d->setEnabledBySettings(false);
pluginCategories[spec->category()].append(spec);
- pluginSpecs.append(spec);
}
resolveDependencies();
enableDependenciesIndirectly();
diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp
index 92c7095efd6..311d0d07770 100644
--- a/src/libs/extensionsystem/pluginspec.cpp
+++ b/src/libs/extensionsystem/pluginspec.cpp
@@ -558,6 +558,16 @@ PluginSpec *PluginSpec::read(const QString &filePath)
return spec;
}
+PluginSpec *PluginSpec::read(const QStaticPlugin &plugin)
+{
+ auto spec = new PluginSpec;
+ if (!spec->d->read(plugin)) { // not a Qt Creator plugin
+ delete spec;
+ return nullptr;
+ }
+ return spec;
+}
+
//==========PluginSpecPrivate==================
namespace {
@@ -592,9 +602,28 @@ namespace {
*/
PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec)
: q(spec)
-{
- if (Utils::HostOsInfo::isMacHost())
- loader.setLoadHints(QLibrary::ExportExternalSymbolsHint);
+{}
+
+void PluginSpecPrivate::reset()
+{
+ name.clear();
+ version.clear();
+ compatVersion.clear();
+ vendor.clear();
+ copyright.clear();
+ license.clear();
+ description.clear();
+ url.clear();
+ category.clear();
+ location.clear();
+ filePath.clear();
+ state = PluginSpec::Invalid;
+ hasError = false;
+ errorString.clear();
+ dependencies.clear();
+ metaData = QJsonObject();
+ loader.reset();
+ staticPlugin.reset();
}
/*!
@@ -604,32 +633,32 @@ PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec)
bool PluginSpecPrivate::read(const QString &fileName)
{
qCDebug(pluginLog) << "\nReading meta data of" << fileName;
- name
- = version
- = compatVersion
- = vendor
- = copyright
- = license
- = description
- = url
- = category
- = location
- = QString();
- state = PluginSpec::Invalid;
- hasError = false;
- errorString.clear();
- dependencies.clear();
- metaData = QJsonObject();
+ reset();
QFileInfo fileInfo(fileName);
location = fileInfo.absolutePath();
filePath = fileInfo.absoluteFilePath();
- loader.setFileName(filePath);
- if (loader.fileName().isEmpty()) {
+ loader.emplace();
+ if (Utils::HostOsInfo::isMacHost())
+ loader->setLoadHints(QLibrary::ExportExternalSymbolsHint);
+ loader->setFileName(filePath);
+ if (loader->fileName().isEmpty()) {
qCDebug(pluginLog) << "Cannot open file";
return false;
}
- if (!readMetaData(loader.metaData()))
+ if (!readMetaData(loader->metaData()))
+ return false;
+
+ state = PluginSpec::Read;
+ return true;
+}
+
+bool PluginSpecPrivate::read(const QStaticPlugin &plugin)
+{
+ qCDebug(pluginLog) << "\nReading meta data of static plugin";
+ reset();
+ staticPlugin = plugin;
+ if (!readMetaData(plugin.metaData()))
return false;
state = PluginSpec::Read;
@@ -1050,17 +1079,19 @@ bool PluginSpecPrivate::loadLibrary()
hasError = true;
return false;
}
- if (!loader.load()) {
+ if (loader && !loader->load()) {
hasError = true;
- errorString = QDir::toNativeSeparators(filePath)
- + QString::fromLatin1(": ") + loader.errorString();
+ errorString = QDir::toNativeSeparators(filePath) + QString::fromLatin1(": ")
+ + loader->errorString();
return false;
}
- auto *pluginObject = qobject_cast<IPlugin*>(loader.instance());
+ auto *pluginObject = loader ? qobject_cast<IPlugin *>(loader->instance())
+ : qobject_cast<IPlugin *>(staticPlugin->instance());
if (!pluginObject) {
hasError = true;
errorString = QCoreApplication::translate("PluginSpec", "Plugin is not valid (does not derive from IPlugin)");
- loader.unload();
+ if (loader)
+ loader->unload();
return false;
}
state = PluginSpec::Loaded;
diff --git a/src/libs/extensionsystem/pluginspec.h b/src/libs/extensionsystem/pluginspec.h
index c8737c8abaf..22b06364349 100644
--- a/src/libs/extensionsystem/pluginspec.h
+++ b/src/libs/extensionsystem/pluginspec.h
@@ -29,8 +29,9 @@
#include <utils/porting.h>
-#include <QString>
#include <QHash>
+#include <QStaticPlugin>
+#include <QString>
#include <QVector>
QT_BEGIN_NAMESPACE
@@ -135,6 +136,7 @@ public:
void setEnabledBySettings(bool value);
static PluginSpec *read(const QString &filePath);
+ static PluginSpec *read(const QStaticPlugin &plugin);
private:
PluginSpec();
diff --git a/src/libs/extensionsystem/pluginspec_p.h b/src/libs/extensionsystem/pluginspec_p.h
index 09e410ef63c..4b08c5659f2 100644
--- a/src/libs/extensionsystem/pluginspec_p.h
+++ b/src/libs/extensionsystem/pluginspec_p.h
@@ -28,6 +28,8 @@
#include "pluginspec.h"
#include "iplugin.h"
+#include <utils/optional.h>
+
#include <QJsonObject>
#include <QObject>
#include <QPluginLoader>
@@ -50,7 +52,9 @@ class EXTENSIONSYSTEM_EXPORT PluginSpecPrivate : public QObject
public:
PluginSpecPrivate(PluginSpec *spec);
+ void reset();
bool read(const QString &fileName);
+ bool read(const QStaticPlugin &plugin);
bool provides(const QString &pluginName, const QString &version) const;
bool resolveDependencies(const QVector<PluginSpec *> &specs);
bool loadLibrary();
@@ -65,7 +69,8 @@ public:
void setForceEnabled(bool value);
void setForceDisabled(bool value);
- QPluginLoader loader;
+ Utils::optional<QPluginLoader> loader;
+ Utils::optional<QStaticPlugin> staticPlugin;
QString name;
QString version;
diff --git a/src/libs/glsl/glsl.h b/src/libs/glsl/glsl.h
index fec9a10a83f..895ccc96b49 100644
--- a/src/libs/glsl/glsl.h
+++ b/src/libs/glsl/glsl.h
@@ -31,7 +31,7 @@
#if defined(GLSL_LIBRARY)
# define GLSL_EXPORT Q_DECL_EXPORT
-#elif defined(GLSL_BUILD_STATIC_LIB)
+#elif defined(GLSL_STATIC_LIBRARY)
# define GLSL_EXPORT
#else
# define GLSL_EXPORT Q_DECL_IMPORT
diff --git a/src/libs/languageserverprotocol/CMakeLists.txt b/src/libs/languageserverprotocol/CMakeLists.txt
index 55415e2db7f..9bcbeed3ea8 100644
--- a/src/libs/languageserverprotocol/CMakeLists.txt
+++ b/src/libs/languageserverprotocol/CMakeLists.txt
@@ -6,7 +6,6 @@ add_qtc_library(LanguageServerProtocol
clientcapabilities.cpp clientcapabilities.h
completion.cpp completion.h
diagnostics.cpp diagnostics.h
- icontent.h
initializemessages.cpp initializemessages.h
jsonkeys.h
jsonobject.cpp jsonobject.h
diff --git a/src/libs/languageserverprotocol/basemessage.cpp b/src/libs/languageserverprotocol/basemessage.cpp
index 8c1d4c1a2ff..ee0450010a3 100644
--- a/src/libs/languageserverprotocol/basemessage.cpp
+++ b/src/libs/languageserverprotocol/basemessage.cpp
@@ -27,8 +27,6 @@
#include "jsonrpcmessages.h"
-#include <utils/mimetypes/mimedatabase.h>
-
#include <QBuffer>
#include <QTextCodec>
@@ -39,13 +37,20 @@ namespace LanguageServerProtocol {
Q_LOGGING_CATEGORY(parseLog, "qtc.languageserverprotocol.parse", QtWarningMsg)
+constexpr char headerFieldSeparator[] = ": ";
+constexpr char contentCharsetName[] = "charset";
+constexpr char defaultCharset[] = "utf-8";
+constexpr char contentLengthFieldName[] = "Content-Length";
+constexpr char headerSeparator[] = "\r\n";
+constexpr char contentTypeFieldName[] = "Content-Type";
+
BaseMessage::BaseMessage()
- : mimeType(JsonRpcMessageHandler::jsonRpcMimeType())
+ : mimeType(JsonRpcMessage::jsonRpcMimeType())
{ }
BaseMessage::BaseMessage(const QByteArray &mimeType, const QByteArray &content,
int expectedLength, QTextCodec *codec)
- : mimeType(mimeType.isEmpty() ? JsonRpcMessageHandler::jsonRpcMimeType() : mimeType)
+ : mimeType(mimeType.isEmpty() ? JsonRpcMessage::jsonRpcMimeType() : mimeType)
, content(content)
, contentLength(expectedLength)
, codec(codec)
@@ -174,17 +179,12 @@ bool BaseMessage::isValid() const
return contentLength >= 0;
}
-QByteArray BaseMessage::toData() const
-{
- return header() + content;
-}
-
QByteArray BaseMessage::header() const
{
QByteArray header;
header.append(lengthHeader());
if (codec != defaultCodec()
- || (!mimeType.isEmpty() && mimeType != JsonRpcMessageHandler::jsonRpcMimeType())) {
+ || (!mimeType.isEmpty() && mimeType != JsonRpcMessage::jsonRpcMimeType())) {
header.append(typeHeader());
}
header.append(headerSeparator);
diff --git a/src/libs/languageserverprotocol/basemessage.h b/src/libs/languageserverprotocol/basemessage.h
index b2835aa7d74..dec62b5f227 100644
--- a/src/libs/languageserverprotocol/basemessage.h
+++ b/src/libs/languageserverprotocol/basemessage.h
@@ -27,8 +27,6 @@
#include "languageserverprotocol_global.h"
-#include <utils/mimetypes/mimetype.h>
-
#include <QByteArray>
#include <QCoreApplication>
#include <QLoggingCategory>
@@ -58,7 +56,7 @@ public:
bool isComplete() const;
bool isValid() const;
- QByteArray toData() const;
+ QByteArray header() const;
QByteArray mimeType;
QByteArray content;
@@ -66,7 +64,6 @@ public:
QTextCodec *codec = defaultCodec();
private:
- QByteArray header() const;
QByteArray lengthHeader() const;
QByteArray typeHeader() const;
};
diff --git a/src/libs/languageserverprotocol/clientcapabilities.cpp b/src/libs/languageserverprotocol/clientcapabilities.cpp
index c3665462f81..33c29df9287 100644
--- a/src/libs/languageserverprotocol/clientcapabilities.cpp
+++ b/src/libs/languageserverprotocol/clientcapabilities.cpp
@@ -29,12 +29,12 @@ namespace LanguageServerProtocol {
Utils::optional<QList<SymbolKind> > SymbolCapabilities::SymbolKindCapabilities::valueSet() const
{
- Utils::optional<QList<int>> array = optionalArray<int>(valueSetKey);
- if (!array)
- return Utils::nullopt;
- return Utils::make_optional(Utils::transform(array.value(), [] (int value) {
- return static_cast<SymbolKind>(value);
- }));
+ if (Utils::optional<QList<int>> array = optionalArray<int>(valueSetKey)) {
+ return Utils::make_optional(Utils::transform(*array, [] (int value) {
+ return static_cast<SymbolKind>(value);
+ }));
+ }
+ return Utils::nullopt;
}
void SymbolCapabilities::SymbolKindCapabilities::setValueSet(const QList<SymbolKind> &valueSet)
diff --git a/src/libs/languageserverprotocol/clientcapabilities.h b/src/libs/languageserverprotocol/clientcapabilities.h
index bc6151a1740..93a7181de76 100644
--- a/src/libs/languageserverprotocol/clientcapabilities.h
+++ b/src/libs/languageserverprotocol/clientcapabilities.h
@@ -626,7 +626,7 @@ public:
void clearWorkDoneProgress() { remove(workDoneProgressKey); }
private:
- constexpr static const char workDoneProgressKey[] = "workDoneProgress";
+ constexpr static const char16_t workDoneProgressKey[] = u"workDoneProgress";
};
class LANGUAGESERVERPROTOCOL_EXPORT ClientCapabilities : public JsonObject
diff --git a/src/libs/languageserverprotocol/completion.cpp b/src/libs/languageserverprotocol/completion.cpp
index f4e1295d75d..10d38c71178 100644
--- a/src/libs/languageserverprotocol/completion.cpp
+++ b/src/libs/languageserverprotocol/completion.cpp
@@ -44,13 +44,21 @@ Utils::optional<MarkupOrString> CompletionItem::documentation() const
Utils::optional<CompletionItem::InsertTextFormat> CompletionItem::insertTextFormat() const
{
- Utils::optional<int> value = optionalValue<int>(insertTextFormatKey);
- return value.has_value()
- ? Utils::make_optional(CompletionItem::InsertTextFormat(value.value()))
- : Utils::nullopt;
+ if (Utils::optional<int> value = optionalValue<int>(insertTextFormatKey))
+ return Utils::make_optional(CompletionItem::InsertTextFormat(*value));
+ return Utils::nullopt;
}
-
+Utils::optional<QList<CompletionItem::CompletionItemTag>> CompletionItem::tags() const
+{
+ if (const auto value = optionalValue<QJsonArray>(tagsKey)) {
+ QList<CompletionItemTag> tags;
+ for (auto it = value->cbegin(); it != value->cend(); ++it)
+ tags << static_cast<CompletionItemTag>(it->toInt());
+ return tags;
+ }
+ return {};
+}
CompletionItemResolveRequest::CompletionItemResolveRequest(const CompletionItem &params)
: Request(methodName, params)
diff --git a/src/libs/languageserverprotocol/completion.h b/src/libs/languageserverprotocol/completion.h
index ab5e43ac220..b635e121e42 100644
--- a/src/libs/languageserverprotocol/completion.h
+++ b/src/libs/languageserverprotocol/completion.h
@@ -214,6 +214,27 @@ public:
void setData(const QJsonValue &data) { insert(dataKey, data); }
void clearData() { remove(dataKey); }
+ /**
+ * Completion item tags are extra annotations that tweak the rendering of a
+ * completion item.
+ * @since 3.15.0
+ */
+ enum CompletionItemTag {
+ Deprecated = 1,
+ };
+
+ /**
+ * Tags for this completion item.
+ * @since 3.15.0
+ */
+ Utils::optional<QList<CompletionItemTag>> tags() const;
+
+ /**
+ * Indicates if this item is deprecated.
+ * @deprecated Use `tags` instead if supported.
+ */
+ Utils::optional<bool> deprecated() const { return optionalValue<bool>(deprecatedKey); }
+
bool isValid() const override { return contains(labelKey); }
};
diff --git a/src/libs/languageserverprotocol/icontent.h b/src/libs/languageserverprotocol/icontent.h
deleted file mode 100644
index 35cc84382a1..00000000000
--- a/src/libs/languageserverprotocol/icontent.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "basemessage.h"
-#include "lsputils.h"
-
-#include <utils/mimetypes/mimetype.h>
-#include <utils/qtcassert.h>
-#include <utils/variant.h>
-
-#include <QByteArray>
-#include <QDebug>
-#include <QHash>
-#include <QJsonValue>
-
-#include <functional>
-
-namespace LanguageServerProtocol {
-
-class IContent;
-
-class LANGUAGESERVERPROTOCOL_EXPORT MessageId : public Utils::variant<int, QString>
-{
-public:
- MessageId() = default;
- explicit MessageId(int id) : variant(id) {}
- explicit MessageId(const QString &id) : variant(id) {}
- explicit MessageId(const QJsonValue &value)
- {
- if (value.isDouble())
- *this = MessageId(value.toInt());
- else if (value.isString())
- *this = MessageId(value.toString());
- else
- m_valid = false;
- }
-
- operator QJsonValue() const
- {
- if (auto id = Utils::get_if<int>(this))
- return *id;
- if (auto id = Utils::get_if<QString>(this))
- return *id;
- return QJsonValue();
- }
-
- bool isValid() const { return m_valid; }
-
- QString toString() const
- {
- if (auto id = Utils::get_if<QString>(this))
- return *id;
- if (auto id = Utils::get_if<int>(this))
- return QString::number(*id);
- return {};
- }
-
- friend auto qHash(const MessageId &id)
- {
- if (Utils::holds_alternative<int>(id))
- return QT_PREPEND_NAMESPACE(qHash(Utils::get<int>(id)));
- if (Utils::holds_alternative<QString>(id))
- return QT_PREPEND_NAMESPACE(qHash(Utils::get<QString>(id)));
- return QT_PREPEND_NAMESPACE(qHash(0));
- }
-
-private:
- bool m_valid = true;
-};
-
-struct ResponseHandler
-{
- MessageId id;
- using Callback = std::function<void(const QByteArray &, QTextCodec *)>;
- Callback callback;
-};
-
-using ResponseHandlers = std::function<void(const MessageId &, const QByteArray &, QTextCodec *)>;
-using MethodHandler = std::function<void(const QString &, const MessageId &, const IContent *)>;
-
-template <typename Error>
-inline QDebug operator<<(QDebug stream, const LanguageServerProtocol::MessageId &id)
-{
- if (Utils::holds_alternative<int>(id))
- stream << Utils::get<int>(id);
- else
- stream << Utils::get<QString>(id);
- return stream;
-}
-
-class LANGUAGESERVERPROTOCOL_EXPORT IContent
-{
-public:
- virtual ~IContent() = default;
-
- virtual QByteArray toRawData() const = 0;
- virtual QByteArray mimeType() const = 0;
- virtual bool isValid(QString *errorMessage) const = 0;
-
- virtual Utils::optional<ResponseHandler> responseHandler() const
- { return Utils::nullopt; }
-
- BaseMessage toBaseMessage() const
- { return BaseMessage(mimeType(), toRawData()); }
-};
-
-} // namespace LanguageClient
diff --git a/src/libs/languageserverprotocol/initializemessages.cpp b/src/libs/languageserverprotocol/initializemessages.cpp
index ab09cf1120c..5fcbfa9787a 100644
--- a/src/libs/languageserverprotocol/initializemessages.cpp
+++ b/src/libs/languageserverprotocol/initializemessages.cpp
@@ -85,12 +85,12 @@ Utils::optional<QList<CompletionItemKind::Kind>>
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities::
valueSet() const
{
- Utils::optional<QList<int>> array = optionalArray<int>(valueSetKey);
- if (!array)
- return Utils::nullopt;
- return Utils::make_optional(Utils::transform(array.value(), [] (int value) {
- return static_cast<CompletionItemKind::Kind>(value);
- }));
+ if (Utils::optional<QList<int>> array = optionalArray<int>(valueSetKey)) {
+ return Utils::make_optional(Utils::transform(*array, [] (int value) {
+ return static_cast<CompletionItemKind::Kind>(value);
+ }));
+ }
+ return Utils::nullopt;
}
void
diff --git a/src/libs/languageserverprotocol/initializemessages.h b/src/libs/languageserverprotocol/initializemessages.h
index b8a4bf7da49..04b2fc655f1 100644
--- a/src/libs/languageserverprotocol/initializemessages.h
+++ b/src/libs/languageserverprotocol/initializemessages.h
@@ -53,6 +53,19 @@ private:
Values m_value = off;
};
+class LANGUAGESERVERPROTOCOL_EXPORT ClientInfo : public JsonObject
+{
+public:
+ using JsonObject::JsonObject;
+
+ QString name() const { return typedValue<QString>(nameKey); }
+ void setName(const QString &name) { insert(nameKey, name); }
+
+ Utils::optional<QString> version() const { return optionalValue<QString>(versionKey); }
+ void setVersion(const QString &version) { insert(versionKey, version); }
+ void clearVersion() { remove(versionKey); }
+};
+
class LANGUAGESERVERPROTOCOL_EXPORT InitializeParams : public JsonObject
{
public:
@@ -120,6 +133,10 @@ public:
{ insert(workspaceFoldersKey, folders.toJson()); }
void clearWorkSpaceFolders() { remove(workspaceFoldersKey); }
+ Utils::optional<ClientInfo> clientInfo() const { return optionalValue<ClientInfo>(clientInfoKey); }
+ void setClientInfo(const ClientInfo &clientInfo) { insert(clientInfoKey, clientInfo); }
+ void clearClientInfo() { remove(clientInfoKey); }
+
bool isValid() const override
{ return contains(processIdKey) && contains(rootUriKey) && contains(capabilitiesKey); }
};
diff --git a/src/libs/languageserverprotocol/jsonkeys.h b/src/libs/languageserverprotocol/jsonkeys.h
index 24187d77b07..a8e33ae0575 100644
--- a/src/libs/languageserverprotocol/jsonkeys.h
+++ b/src/libs/languageserverprotocol/jsonkeys.h
@@ -27,217 +27,213 @@
namespace LanguageServerProtocol {
-constexpr char actionsKey[] = "actions";
-constexpr char activeParameterKey[] = "activeParameter";
-constexpr char activeParameterSupportKey[] = "activeParameterSupport";
-constexpr char activeSignatureKey[] = "activeSignature";
-constexpr char addedKey[] = "added";
-constexpr char additionalTextEditsKey[] = "additionalTextEdits";
-constexpr char alphaKey[] = "alpha";
-constexpr char appliedKey[] = "applied";
-constexpr char applyEditKey[] = "applyEdit";
-constexpr char argumentsKey[] = "arguments";
-constexpr char blueKey[] = "blue";
-constexpr char cancellableKey[] = "cancellable";
-constexpr char capabilitiesKey[] = "capabilities";
-constexpr char chKey[] = "ch";
-constexpr char changeKey[] = "change";
-constexpr char changeNotificationsKey[] = "changeNotifications";
-constexpr char changesKey[] = "changes";
-constexpr char characterKey[] = "character";
-constexpr char childrenKey[] = "children";
-constexpr char codeActionKey[] = "codeAction";
-constexpr char codeActionKindKey[] = "codeActionKind";
-constexpr char codeActionKindsKey[] = "codeActionKinds";
-constexpr char codeActionLiteralSupportKey[] = "codeActionLiteralSupport";
-constexpr char codeActionProviderKey[] = "codeActionProvider";
-constexpr char codeKey[] = "code";
-constexpr char codeLensKey[] = "codeLens";
-constexpr char codeLensProviderKey[] = "codeLensProvider";
-constexpr char colorInfoKey[] = "colorInfo";
-constexpr char colorKey[] = "color";
-constexpr char colorProviderKey[] = "colorProvider";
-constexpr char commandKey[] = "command";
-constexpr char commandsKey[] = "commands";
-constexpr char commitCharacterSupportKey[] = "commitCharacterSupport";
-constexpr char commitCharactersKey[] = "commitCharacters";
-constexpr char completionItemKey[] = "completionItem";
-constexpr char completionItemKindKey[] = "completionItemKind";
-constexpr char completionKey[] = "completion";
-constexpr char completionProviderKey[] = "completionProvider";
-constexpr char configurationKey[] = "configuration";
-constexpr char containerNameKey[] = "containerName";
-constexpr char contentChangesKey[] = "contentChanges";
-constexpr char contentCharsetName[] = "charset";
-constexpr char contentFormatKey[] = "contentFormat";
-constexpr char contentKey[] = "value";
-constexpr char contentLengthFieldName[] = "Content-Length";
-constexpr char contentTypeFieldName[] = "Content-Type";
-constexpr char contentsKey[] = "contents";
-constexpr char contextKey[] = "context";
-constexpr char contextSupportKey[] = "contextSupport";
-constexpr char dataKey[] = "data";
-constexpr char defaultCharset[] = "utf-8";
-constexpr char definitionKey[] = "definition";
-constexpr char definitionProviderKey[] = "definitionProvider";
-constexpr char deleteCountKey[] = "deleteCount";
-constexpr char deltaKey[] = "delta";
-constexpr char deprecatedKey[] = "deprecated";
-constexpr char detailKey[] = "detail";
-constexpr char diagnosticsKey[] = "diagnostics";
-constexpr char didChangeConfigurationKey[] = "didChangeConfiguration";
-constexpr char didChangeWatchedFilesKey[] = "didChangeWatchedFiles";
-constexpr char didSaveKey[] = "didSave";
-constexpr char documentChangesKey[] = "documentChanges";
-constexpr char documentFormattingProviderKey[] = "documentFormattingProvider";
-constexpr char documentHighlightKey[] = "documentHighlight";
-constexpr char documentHighlightProviderKey[] = "documentHighlightProvider";
-constexpr char documentLinkKey[] = "documentLink";
-constexpr char documentLinkProviderKey[] = "documentLinkProvider";
-constexpr char documentRangeFormattingProviderKey[] = "documentRangeFormattingProvider";
-constexpr char documentSelectorKey[] = "documentSelector";
-constexpr char documentSymbolKey[] = "documentSymbol";
-constexpr char documentSymbolProviderKey[] = "documentSymbolProvider";
-constexpr char documentationFormatKey[] = "documentationFormat";
-constexpr char documentationKey[] = "documentation";
-constexpr char dynamicRegistrationKey[] = "dynamicRegistration";
-constexpr char editKey[] = "edit";
-constexpr char editsKey[] = "edits";
-constexpr char endKey[] = "end";
-constexpr char errorKey[] = "error";
-constexpr char eventKey[] = "event";
-constexpr char executeCommandKey[] = "executeCommand";
-constexpr char executeCommandProviderKey[] = "executeCommandProvider";
-constexpr char experimentalKey[] = "experimental";
-constexpr char filterTextKey[] = "filterText";
-constexpr char firstTriggerCharacterKey[] = "firstTriggerCharacter";
-constexpr char formatsKey[] = "formats";
-constexpr char formattingKey[] = "formatting";
-constexpr char fullKey[] = "full";
-constexpr char greenKey[] = "green";
-constexpr char headerFieldSeparator[] = ": ";
-constexpr char headerSeparator[] = "\r\n";
-constexpr char hierarchicalDocumentSymbolSupportKey[] = "hierarchicalDocumentSymbolSupport";
-constexpr char hoverKey[] = "hover";
-constexpr char hoverProviderKey[] = "hoverProvider";
-constexpr char idKey[] = "id";
-constexpr char implementationKey[] = "implementation";
-constexpr char implementationProviderKey[] = "implementationProvider";
-constexpr char includeDeclarationKey[] = "includeDeclaration";
-constexpr char includeTextKey[] = "includeText";
-constexpr char initializationOptionsKey[] = "initializationOptions";
-constexpr char insertFinalNewlineKey[] = "insertFinalNewline";
-constexpr char insertSpaceKey[] = "insertSpace";
-constexpr char insertTextFormatKey[] = "insertTextFormat";
-constexpr char insertTextKey[] = "insertText";
-constexpr char isIncompleteKey[] = "isIncomplete";
-constexpr char itemsKey[] = "items";
-constexpr char jsonRpcVersionKey[] = "jsonrpc";
-constexpr char kindKey[] = "kind";
-constexpr char labelKey[] = "label";
-constexpr char languageIdKey[] = "languageId";
-constexpr char languageKey[] = "language";
-constexpr char legendKey[] = "legend";
-constexpr char lineKey[] = "line";
-constexpr char linesKey[] = "lines";
-constexpr char locationKey[] = "location";
-constexpr char messageKey[] = "message";
-constexpr char methodKey[] = "method";
-constexpr char moreTriggerCharacterKey[] = "moreTriggerCharacter";
-constexpr char multiLineTokenSupportKey[] = "multiLineTokenSupport";
-constexpr char nameKey[] = "name";
-constexpr char newNameKey[] = "newName";
-constexpr char newTextKey[] = "newText";
-constexpr char onTypeFormattingKey[] = "onTypeFormatting";
-constexpr char onlyKey[] = "only";
-constexpr char openCloseKey[] = "openClose";
-constexpr char optionsKey[] = "options";
-constexpr char overlappingTokenSupportKey[] = "overlappingTokenSupport";
-constexpr char parametersKey[] = "parameters";
-constexpr char paramsKey[] = "params";
-constexpr char patternKey[] = "pattern";
-constexpr char percentageKey[] = "percentage";
-constexpr char placeHolderKey[] = "placeHolder";
-constexpr char positionKey[] = "position";
-constexpr char prepareProviderKey[] = "prepareProvider";
-constexpr char prepareSupportKey[] = "prepareSupport";
-constexpr char previousResultIdKey[] = "previousResultId";
-constexpr char processIdKey[] = "processId";
-constexpr char queryKey[] = "query";
-constexpr char rangeFormattingKey[] = "rangeFormatting";
-constexpr char rangeKey[] = "range";
-constexpr char rangeLengthKey[] = "rangeLength";
-constexpr char reasonKey[] = "reason";
-constexpr char redKey[] = "red";
-constexpr char referencesKey[] = "references";
-constexpr char referencesProviderKey[] = "referencesProvider";
-constexpr char refreshSupportKey[] = "refreshSupport";
-constexpr char registerOptionsKey[] = "registerOptions";
-constexpr char registrationsKey[] = "registrations";
-constexpr char removedKey[] = "removed";
-constexpr char renameKey[] = "rename";
-constexpr char renameProviderKey[] = "renameProvider";
-constexpr char requestsKey[] = "requests";
-constexpr char resolveProviderKey[] = "resolveProvider";
-constexpr char resultIdKey[] = "resultId";
-constexpr char resultKey[] = "result";
-constexpr char retryKey[] = "retry";
-constexpr char rootPathKey[] = "rootPath";
-constexpr char rootUriKey[] = "rootUri";
-constexpr char saveKey[] = "save";
-constexpr char schemeKey[] = "scheme";
-constexpr char scopeUriKey[] = "scopeUri";
-constexpr char sectionKey[] = "section";
-constexpr char selectionRangeKey[] = "selectionRange";
-constexpr char semanticTokensKey[] = "semanticTokens";
-constexpr char semanticTokensProviderKey[] = "semanticTokensProvider";
-constexpr char serverInfoKey[] = "serverInfo";
-constexpr char settingsKey[] = "settings";
-constexpr char severityKey[] = "severity";
-constexpr char signatureHelpKey[] = "signatureHelp";
-constexpr char signatureHelpProviderKey[] = "signatureHelpProvider";
-constexpr char signatureInformationKey[] = "signatureInformation";
-constexpr char signaturesKey[] = "signatures";
-constexpr char snippetSupportKey[] = "snippetSupport";
-constexpr char sortTextKey[] = "sortText";
-constexpr char sourceKey[] = "source";
-constexpr char startKey[] = "start";
-constexpr char supportedKey[] = "supported";
-constexpr char symbolKey[] = "symbol";
-constexpr char symbolKindKey[] = "symbolKind";
-constexpr char syncKindKey[] = "syncKind";
-constexpr char synchronizationKey[] = "synchronization";
-constexpr char tabSizeKey[] = "tabSize";
-constexpr char targetKey[] = "target";
-constexpr char textDocumentKey[] = "textDocument";
-constexpr char textDocumentSyncKey[] = "textDocumentSync";
-constexpr char textEditKey[] = "textEdit";
-constexpr char textKey[] = "text";
-constexpr char titleKey[] = "title";
-constexpr char tokenKey[] = "token";
-constexpr char tokenModifiersKey[] = "tokenModifiers";
-constexpr char tokenTypesKey[] = "tokenTypes";
-constexpr char traceKey[] = "trace";
-constexpr char triggerCharacterKey[] = "triggerCharacter";
-constexpr char triggerCharactersKey[] = "triggerCharacters";
-constexpr char triggerKindKey[] = "triggerKind";
-constexpr char trimFinalNewlinesKey[] = "trimFinalNewlines";
-constexpr char trimTrailingWhitespaceKey[] = "trimTrailingWhitespace";
-constexpr char typeDefinitionKey[] = "typeDefinition";
-constexpr char typeDefinitionProviderKey[] = "typeDefinitionProvider";
-constexpr char typeKey[] = "type";
-constexpr char unregistrationsKey[] = "unregistrations";
-constexpr char uriKey[] = "uri";
-constexpr char valueKey[] = "value";
-constexpr char valueSetKey[] = "valueSet";
-constexpr char versionKey[] = "version";
-constexpr char willSaveKey[] = "willSave";
-constexpr char willSaveWaitUntilKey[] = "willSaveWaitUntil";
-constexpr char windowKey[] = "window";
-constexpr char workDoneProgressKey[] = "workDoneProgress";
-constexpr char workspaceEditKey[] = "workspaceEdit";
-constexpr char workspaceFoldersKey[] = "workspaceFolders";
-constexpr char workspaceKey[] = "workspace";
-constexpr char workspaceSymbolProviderKey[] = "workspaceSymbolProvider";
+constexpr char16_t actionsKey[] = u"actions";
+constexpr char16_t activeParameterKey[] = u"activeParameter";
+constexpr char16_t activeParameterSupportKey[] = u"activeParameterSupport";
+constexpr char16_t activeSignatureKey[] = u"activeSignature";
+constexpr char16_t addedKey[] = u"added";
+constexpr char16_t additionalTextEditsKey[] = u"additionalTextEdits";
+constexpr char16_t alphaKey[] = u"alpha";
+constexpr char16_t appliedKey[] = u"applied";
+constexpr char16_t applyEditKey[] = u"applyEdit";
+constexpr char16_t argumentsKey[] = u"arguments";
+constexpr char16_t blueKey[] = u"blue";
+constexpr char16_t cancellableKey[] = u"cancellable";
+constexpr char16_t capabilitiesKey[] = u"capabilities";
+constexpr char16_t chKey[] = u"ch";
+constexpr char16_t changeKey[] = u"change";
+constexpr char16_t changeNotificationsKey[] = u"changeNotifications";
+constexpr char16_t changesKey[] = u"changes";
+constexpr char16_t characterKey[] = u"character";
+constexpr char16_t childrenKey[] = u"children";
+constexpr char16_t clientInfoKey[] = u"clientInfo";
+constexpr char16_t codeActionKey[] = u"codeAction";
+constexpr char16_t codeActionKindKey[] = u"codeActionKind";
+constexpr char16_t codeActionKindsKey[] = u"codeActionKinds";
+constexpr char16_t codeActionLiteralSupportKey[] = u"codeActionLiteralSupport";
+constexpr char16_t codeActionProviderKey[] = u"codeActionProvider";
+constexpr char16_t codeKey[] = u"code";
+constexpr char16_t codeLensKey[] = u"codeLens";
+constexpr char16_t codeLensProviderKey[] = u"codeLensProvider";
+constexpr char16_t colorInfoKey[] = u"colorInfo";
+constexpr char16_t colorKey[] = u"color";
+constexpr char16_t colorProviderKey[] = u"colorProvider";
+constexpr char16_t commandKey[] = u"command";
+constexpr char16_t commandsKey[] = u"commands";
+constexpr char16_t commitCharacterSupportKey[] = u"commitCharacterSupport";
+constexpr char16_t commitCharactersKey[] = u"commitCharacters";
+constexpr char16_t completionItemKey[] = u"completionItem";
+constexpr char16_t completionItemKindKey[] = u"completionItemKind";
+constexpr char16_t completionKey[] = u"completion";
+constexpr char16_t completionProviderKey[] = u"completionProvider";
+constexpr char16_t configurationKey[] = u"configuration";
+constexpr char16_t containerNameKey[] = u"containerName";
+constexpr char16_t contentChangesKey[] = u"contentChanges";
+constexpr char16_t contentFormatKey[] = u"contentFormat";
+constexpr char16_t contentKey[] = u"value";
+constexpr char16_t contentsKey[] = u"contents";
+constexpr char16_t contextKey[] = u"context";
+constexpr char16_t contextSupportKey[] = u"contextSupport";
+constexpr char16_t dataKey[] = u"data";
+constexpr char16_t definitionKey[] = u"definition";
+constexpr char16_t definitionProviderKey[] = u"definitionProvider";
+constexpr char16_t deleteCountKey[] = u"deleteCount";
+constexpr char16_t deltaKey[] = u"delta";
+constexpr char16_t deprecatedKey[] = u"deprecated";
+constexpr char16_t detailKey[] = u"detail";
+constexpr char16_t diagnosticsKey[] = u"diagnostics";
+constexpr char16_t didChangeConfigurationKey[] = u"didChangeConfiguration";
+constexpr char16_t didChangeWatchedFilesKey[] = u"didChangeWatchedFiles";
+constexpr char16_t didSaveKey[] = u"didSave";
+constexpr char16_t documentChangesKey[] = u"documentChanges";
+constexpr char16_t documentFormattingProviderKey[] = u"documentFormattingProvider";
+constexpr char16_t documentHighlightKey[] = u"documentHighlight";
+constexpr char16_t documentHighlightProviderKey[] = u"documentHighlightProvider";
+constexpr char16_t documentLinkKey[] = u"documentLink";
+constexpr char16_t documentLinkProviderKey[] = u"documentLinkProvider";
+constexpr char16_t documentRangeFormattingProviderKey[] = u"documentRangeFormattingProvider";
+constexpr char16_t documentSelectorKey[] = u"documentSelector";
+constexpr char16_t documentSymbolKey[] = u"documentSymbol";
+constexpr char16_t documentSymbolProviderKey[] = u"documentSymbolProvider";
+constexpr char16_t documentationFormatKey[] = u"documentationFormat";
+constexpr char16_t documentationKey[] = u"documentation";
+constexpr char16_t dynamicRegistrationKey[] = u"dynamicRegistration";
+constexpr char16_t editKey[] = u"edit";
+constexpr char16_t editsKey[] = u"edits";
+constexpr char16_t endKey[] = u"end";
+constexpr char16_t errorKey[] = u"error";
+constexpr char16_t eventKey[] = u"event";
+constexpr char16_t executeCommandKey[] = u"executeCommand";
+constexpr char16_t executeCommandProviderKey[] = u"executeCommandProvider";
+constexpr char16_t experimentalKey[] = u"experimental";
+constexpr char16_t filterTextKey[] = u"filterText";
+constexpr char16_t firstTriggerCharacterKey[] = u"firstTriggerCharacter";
+constexpr char16_t formatsKey[] = u"formats";
+constexpr char16_t formattingKey[] = u"formatting";
+constexpr char16_t fullKey[] = u"full";
+constexpr char16_t greenKey[] = u"green";
+constexpr char16_t hierarchicalDocumentSymbolSupportKey[] = u"hierarchicalDocumentSymbolSupport";
+constexpr char16_t hoverKey[] = u"hover";
+constexpr char16_t hoverProviderKey[] = u"hoverProvider";
+constexpr char16_t idKey[] = u"id";
+constexpr char16_t implementationKey[] = u"implementation";
+constexpr char16_t implementationProviderKey[] = u"implementationProvider";
+constexpr char16_t includeDeclarationKey[] = u"includeDeclaration";
+constexpr char16_t includeTextKey[] = u"includeText";
+constexpr char16_t initializationOptionsKey[] = u"initializationOptions";
+constexpr char16_t insertFinalNewlineKey[] = u"insertFinalNewline";
+constexpr char16_t insertSpaceKey[] = u"insertSpace";
+constexpr char16_t insertTextFormatKey[] = u"insertTextFormat";
+constexpr char16_t insertTextKey[] = u"insertText";
+constexpr char16_t isIncompleteKey[] = u"isIncomplete";
+constexpr char16_t itemsKey[] = u"items";
+constexpr char16_t jsonRpcVersionKey[] = u"jsonrpc";
+constexpr char16_t kindKey[] = u"kind";
+constexpr char16_t labelKey[] = u"label";
+constexpr char16_t languageIdKey[] = u"languageId";
+constexpr char16_t languageKey[] = u"language";
+constexpr char16_t legendKey[] = u"legend";
+constexpr char16_t lineKey[] = u"line";
+constexpr char16_t linesKey[] = u"lines";
+constexpr char16_t locationKey[] = u"location";
+constexpr char16_t messageKey[] = u"message";
+constexpr char16_t methodKey[] = u"method";
+constexpr char16_t moreTriggerCharacterKey[] = u"moreTriggerCharacter";
+constexpr char16_t multiLineTokenSupportKey[] = u"multiLineTokenSupport";
+constexpr char16_t nameKey[] = u"name";
+constexpr char16_t newNameKey[] = u"newName";
+constexpr char16_t newTextKey[] = u"newText";
+constexpr char16_t onTypeFormattingKey[] = u"onTypeFormatting";
+constexpr char16_t onlyKey[] = u"only";
+constexpr char16_t openCloseKey[] = u"openClose";
+constexpr char16_t optionsKey[] = u"options";
+constexpr char16_t overlappingTokenSupportKey[] = u"overlappingTokenSupport";
+constexpr char16_t parametersKey[] = u"parameters";
+constexpr char16_t paramsKey[] = u"params";
+constexpr char16_t patternKey[] = u"pattern";
+constexpr char16_t percentageKey[] = u"percentage";
+constexpr char16_t placeHolderKey[] = u"placeHolder";
+constexpr char16_t positionKey[] = u"position";
+constexpr char16_t prepareProviderKey[] = u"prepareProvider";
+constexpr char16_t prepareSupportKey[] = u"prepareSupport";
+constexpr char16_t previousResultIdKey[] = u"previousResultId";
+constexpr char16_t processIdKey[] = u"processId";
+constexpr char16_t queryKey[] = u"query";
+constexpr char16_t rangeFormattingKey[] = u"rangeFormatting";
+constexpr char16_t rangeKey[] = u"range";
+constexpr char16_t rangeLengthKey[] = u"rangeLength";
+constexpr char16_t reasonKey[] = u"reason";
+constexpr char16_t redKey[] = u"red";
+constexpr char16_t referencesKey[] = u"references";
+constexpr char16_t referencesProviderKey[] = u"referencesProvider";
+constexpr char16_t refreshSupportKey[] = u"refreshSupport";
+constexpr char16_t registerOptionsKey[] = u"registerOptions";
+constexpr char16_t registrationsKey[] = u"registrations";
+constexpr char16_t removedKey[] = u"removed";
+constexpr char16_t renameKey[] = u"rename";
+constexpr char16_t renameProviderKey[] = u"renameProvider";
+constexpr char16_t requestsKey[] = u"requests";
+constexpr char16_t resolveProviderKey[] = u"resolveProvider";
+constexpr char16_t resultIdKey[] = u"resultId";
+constexpr char16_t resultKey[] = u"result";
+constexpr char16_t retryKey[] = u"retry";
+constexpr char16_t rootPathKey[] = u"rootPath";
+constexpr char16_t rootUriKey[] = u"rootUri";
+constexpr char16_t saveKey[] = u"save";
+constexpr char16_t schemeKey[] = u"scheme";
+constexpr char16_t scopeUriKey[] = u"scopeUri";
+constexpr char16_t sectionKey[] = u"section";
+constexpr char16_t selectionRangeKey[] = u"selectionRange";
+constexpr char16_t semanticTokensKey[] = u"semanticTokens";
+constexpr char16_t semanticTokensProviderKey[] = u"semanticTokensProvider";
+constexpr char16_t serverInfoKey[] = u"serverInfo";
+constexpr char16_t settingsKey[] = u"settings";
+constexpr char16_t severityKey[] = u"severity";
+constexpr char16_t signatureHelpKey[] = u"signatureHelp";
+constexpr char16_t signatureHelpProviderKey[] = u"signatureHelpProvider";
+constexpr char16_t signatureInformationKey[] = u"signatureInformation";
+constexpr char16_t signaturesKey[] = u"signatures";
+constexpr char16_t snippetSupportKey[] = u"snippetSupport";
+constexpr char16_t sortTextKey[] = u"sortText";
+constexpr char16_t sourceKey[] = u"source";
+constexpr char16_t startKey[] = u"start";
+constexpr char16_t supportedKey[] = u"supported";
+constexpr char16_t symbolKey[] = u"symbol";
+constexpr char16_t symbolKindKey[] = u"symbolKind";
+constexpr char16_t syncKindKey[] = u"syncKind";
+constexpr char16_t synchronizationKey[] = u"synchronization";
+constexpr char16_t tabSizeKey[] = u"tabSize";
+constexpr char16_t tagsKey[] = u"tags";
+constexpr char16_t targetKey[] = u"target";
+constexpr char16_t textDocumentKey[] = u"textDocument";
+constexpr char16_t textDocumentSyncKey[] = u"textDocumentSync";
+constexpr char16_t textEditKey[] = u"textEdit";
+constexpr char16_t textKey[] = u"text";
+constexpr char16_t titleKey[] = u"title";
+constexpr char16_t tokenKey[] = u"token";
+constexpr char16_t tokenModifiersKey[] = u"tokenModifiers";
+constexpr char16_t tokenTypesKey[] = u"tokenTypes";
+constexpr char16_t traceKey[] = u"trace";
+constexpr char16_t triggerCharacterKey[] = u"triggerCharacter";
+constexpr char16_t triggerCharactersKey[] = u"triggerCharacters";
+constexpr char16_t triggerKindKey[] = u"triggerKind";
+constexpr char16_t trimFinalNewlinesKey[] = u"trimFinalNewlines";
+constexpr char16_t trimTrailingWhitespaceKey[] = u"trimTrailingWhitespace";
+constexpr char16_t typeDefinitionKey[] = u"typeDefinition";
+constexpr char16_t typeDefinitionProviderKey[] = u"typeDefinitionProvider";
+constexpr char16_t typeKey[] = u"type";
+constexpr char16_t unregistrationsKey[] = u"unregistrations";
+constexpr char16_t uriKey[] = u"uri";
+constexpr char16_t valueKey[] = u"value";
+constexpr char16_t valueSetKey[] = u"valueSet";
+constexpr char16_t versionKey[] = u"version";
+constexpr char16_t willSaveKey[] = u"willSave";
+constexpr char16_t willSaveWaitUntilKey[] = u"willSaveWaitUntil";
+constexpr char16_t windowKey[] = u"window";
+constexpr char16_t workDoneProgressKey[] = u"workDoneProgress";
+constexpr char16_t workspaceEditKey[] = u"workspaceEdit";
+constexpr char16_t workspaceFoldersKey[] = u"workspaceFolders";
+constexpr char16_t workspaceKey[] = u"workspace";
+constexpr char16_t workspaceSymbolProviderKey[] = u"workspaceSymbolProvider";
} // namespace LanguageServerProtocol
diff --git a/src/libs/languageserverprotocol/jsonobject.cpp b/src/libs/languageserverprotocol/jsonobject.cpp
index 75edb76de3b..47d2bb7824c 100644
--- a/src/libs/languageserverprotocol/jsonobject.cpp
+++ b/src/libs/languageserverprotocol/jsonobject.cpp
@@ -37,12 +37,12 @@ JsonObject &JsonObject::operator=(JsonObject &&other)
return *this;
}
-QJsonObject::iterator JsonObject::insert(const QString &key, const JsonObject &object)
+QJsonObject::iterator JsonObject::insert(const QStringView key, const JsonObject &object)
{
return m_jsonObject.insert(key, object.m_jsonObject);
}
-QJsonObject::iterator JsonObject::insert(const QString &key, const QJsonValue &value)
+QJsonObject::iterator JsonObject::insert(const QStringView key, const QJsonValue &value)
{
return m_jsonObject.insert(key, value);
}
diff --git a/src/libs/languageserverprotocol/jsonobject.h b/src/libs/languageserverprotocol/jsonobject.h
index 3b32ed81f58..9dd172bbeff 100644
--- a/src/libs/languageserverprotocol/jsonobject.h
+++ b/src/libs/languageserverprotocol/jsonobject.h
@@ -67,98 +67,97 @@ public:
const_iterator end() const { return m_jsonObject.end(); }
protected:
- iterator insert(const QString &key, const JsonObject &value);
- iterator insert(const QString &key, const QJsonValue &value);
+ iterator insert(const QStringView key, const JsonObject &value);
+ iterator insert(const QStringView key, const QJsonValue &value);
template <typename T, typename V>
- iterator insertVariant(const QString &key, const V &variant);
+ iterator insertVariant(const QStringView key, const V &variant);
template <typename T1, typename T2, typename... Args, typename V>
- iterator insertVariant(const QString &key, const V &variant);
+ iterator insertVariant(const QStringView key, const V &variant);
// QJSonObject redirections
- QJsonValue value(const QString &key) const { return m_jsonObject.value(key); }
- bool contains(const QString &key) const { return m_jsonObject.contains(key); }
- iterator find(const QString &key) { return m_jsonObject.find(key); }
- const_iterator find(const QString &key) const { return m_jsonObject.find(key); }
- void remove(const QString &key) { m_jsonObject.remove(key); }
+ QJsonValue value(const QStringView key) const { return m_jsonObject.value(key); }
+ bool contains(const QStringView key) const { return m_jsonObject.contains(key); }
+ iterator find(const QStringView key) { return m_jsonObject.find(key); }
+ const_iterator find(const QStringView key) const { return m_jsonObject.find(key); }
+ void remove(const QStringView key) { m_jsonObject.remove(key); }
QStringList keys() const { return m_jsonObject.keys(); }
// convenience value access
template<typename T>
- T typedValue(const QString &key) const;
+ T typedValue(const QStringView key) const;
template<typename T>
- Utils::optional<T> optionalValue(const QString &key) const;
+ Utils::optional<T> optionalValue(const QStringView key) const;
template<typename T>
- LanguageClientValue<T> clientValue(const QString &key) const;
+ LanguageClientValue<T> clientValue(const QStringView key) const;
template<typename T>
- Utils::optional<LanguageClientValue<T>> optionalClientValue(const QString &key) const;
+ Utils::optional<LanguageClientValue<T>> optionalClientValue(const QStringView key) const;
template<typename T>
- QList<T> array(const QString &key) const;
+ QList<T> array(const QStringView key) const;
template<typename T>
- Utils::optional<QList<T>> optionalArray(const QString &key) const;
+ Utils::optional<QList<T>> optionalArray(const QStringView key) const;
template<typename T>
- LanguageClientArray<T> clientArray(const QString &key) const;
+ LanguageClientArray<T> clientArray(const QStringView key) const;
template<typename T>
- Utils::optional<LanguageClientArray<T>> optionalClientArray(const QString &key) const;
+ Utils::optional<LanguageClientArray<T>> optionalClientArray(const QStringView key) const;
template<typename T>
- void insertArray(const QString &key, const QList<T> &array);
+ void insertArray(const QStringView key, const QList<T> &array);
template<typename>
- void insertArray(const QString &key, const QList<JsonObject> &array);
+ void insertArray(const QStringView key, const QList<JsonObject> &array);
private:
QJsonObject m_jsonObject;
};
template<typename T, typename V>
-JsonObject::iterator JsonObject::insertVariant(const QString &key, const V &variant)
+JsonObject::iterator JsonObject::insertVariant(const QStringView key, const V &variant)
{
return Utils::holds_alternative<T>(variant) ? insert(key, Utils::get<T>(variant)) : end();
}
template<typename T1, typename T2, typename... Args, typename V>
-JsonObject::iterator JsonObject::insertVariant(const QString &key, const V &variant)
+JsonObject::iterator JsonObject::insertVariant(const QStringView key, const V &variant)
{
auto result = insertVariant<T1>(key, variant);
return result != end() ? result : insertVariant<T2, Args...>(key, variant);
}
template<typename T>
-T JsonObject::typedValue(const QString &key) const
+T JsonObject::typedValue(const QStringView key) const
{
return fromJsonValue<T>(value(key));
}
template<typename T>
-Utils::optional<T> JsonObject::optionalValue(const QString &key) const
+Utils::optional<T> JsonObject::optionalValue(const QStringView key) const
{
const QJsonValue &val = value(key);
return val.isUndefined() ? Utils::nullopt : Utils::make_optional(fromJsonValue<T>(val));
}
template<typename T>
-LanguageClientValue<T> JsonObject::clientValue(const QString &key) const
+LanguageClientValue<T> JsonObject::clientValue(const QStringView key) const
{
return LanguageClientValue<T>(value(key));
}
template<typename T>
-Utils::optional<LanguageClientValue<T>> JsonObject::optionalClientValue(const QString &key) const
+Utils::optional<LanguageClientValue<T>> JsonObject::optionalClientValue(const QStringView key) const
{
return contains(key) ? Utils::make_optional(clientValue<T>(key)) : Utils::nullopt;
}
template<typename T>
-QList<T> JsonObject::array(const QString &key) const
+QList<T> JsonObject::array(const QStringView key) const
{
- const Utils::optional<QList<T>> &array = optionalArray<T>(key);
- if (array.has_value())
- return array.value();
+ if (const Utils::optional<QList<T>> &array = optionalArray<T>(key))
+ return *array;
qCDebug(conversionLog) << QString("Expected array under %1 in:").arg(key) << *this;
return {};
}
template<typename T>
-Utils::optional<QList<T>> JsonObject::optionalArray(const QString &key) const
+Utils::optional<QList<T>> JsonObject::optionalArray(const QStringView key) const
{
const QJsonValue &jsonValue = value(key);
if (jsonValue.isUndefined())
@@ -167,13 +166,13 @@ Utils::optional<QList<T>> JsonObject::optionalArray(const QString &key) const
}
template<typename T>
-LanguageClientArray<T> JsonObject::clientArray(const QString &key) const
+LanguageClientArray<T> JsonObject::clientArray(const QStringView key) const
{
return LanguageClientArray<T>(value(key));
}
template<typename T>
-Utils::optional<LanguageClientArray<T>> JsonObject::optionalClientArray(const QString &key) const
+Utils::optional<LanguageClientArray<T>> JsonObject::optionalClientArray(const QStringView key) const
{
const QJsonValue &val = value(key);
return !val.isUndefined() ? Utils::make_optional(LanguageClientArray<T>(value(key)))
@@ -181,7 +180,7 @@ Utils::optional<LanguageClientArray<T>> JsonObject::optionalClientArray(const QS
}
template<typename T>
-void JsonObject::insertArray(const QString &key, const QList<T> &array)
+void JsonObject::insertArray(const QStringView key, const QList<T> &array)
{
QJsonArray jsonArray;
for (const T &item : array)
@@ -190,7 +189,7 @@ void JsonObject::insertArray(const QString &key, const QList<T> &array)
}
template<typename >
-void JsonObject::insertArray(const QString &key, const QList<JsonObject> &array)
+void JsonObject::insertArray(const QStringView key, const QList<JsonObject> &array)
{
QJsonArray jsonArray;
for (const JsonObject &item : array)
diff --git a/src/libs/languageserverprotocol/jsonrpcmessages.cpp b/src/libs/languageserverprotocol/jsonrpcmessages.cpp
index 2b71d34a754..4f55f121af7 100644
--- a/src/libs/languageserverprotocol/jsonrpcmessages.cpp
+++ b/src/libs/languageserverprotocol/jsonrpcmessages.cpp
@@ -28,7 +28,6 @@
#include "lsputils.h"
#include "initializemessages.h"
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
@@ -41,21 +40,24 @@ Q_LOGGING_CATEGORY(timingLog, "qtc.languageserverprotocol.timing", QtWarningMsg)
constexpr const char CancelRequest::methodName[];
-QHash<QString, JsonRpcMessageHandler::MessageProvider> JsonRpcMessageHandler::m_messageProvider;
-
QByteArray JsonRpcMessage::toRawData() const
{
return QJsonDocument(m_jsonObject).toJson(QJsonDocument::Compact);
}
-QByteArray JsonRpcMessage::mimeType() const
+bool JsonRpcMessage::isValid(QString *errorMessage) const
{
- return JsonRpcMessageHandler::jsonRpcMimeType();
+ if (!m_parseError.isEmpty()) {
+ if (errorMessage)
+ *errorMessage = m_parseError;
+ return false;
+ }
+ return m_jsonObject[jsonRpcVersionKey] == "2.0";
}
-bool JsonRpcMessage::isValid(QString * /*errorMessage*/) const
+const QJsonObject &JsonRpcMessage::toJsonObject() const
{
- return m_jsonObject[jsonRpcVersionKey] == "2.0";
+ return m_jsonObject;
}
JsonRpcMessage::JsonRpcMessage()
@@ -64,47 +66,6 @@ JsonRpcMessage::JsonRpcMessage()
m_jsonObject[jsonRpcVersionKey] = "2.0";
}
-JsonRpcMessage::JsonRpcMessage(const QJsonObject &jsonObject)
- : m_jsonObject(jsonObject)
-{ }
-
-JsonRpcMessage::JsonRpcMessage(QJsonObject &&jsonObject)
- : m_jsonObject(std::move(jsonObject))
-{ }
-
-QByteArray JsonRpcMessageHandler::jsonRpcMimeType()
-{
- return "application/vscode-jsonrpc";
-}
-
-void JsonRpcMessageHandler::registerMessageProvider(
- const QString &method, JsonRpcMessageHandler::MessageProvider provider)
-{
- m_messageProvider.insert(method, provider);
-}
-
-void JsonRpcMessageHandler::parseContent(const QByteArray &content,
- QTextCodec *codec,
- QString &parseError,
- const ResponseHandlers &responseHandlers,
- const MethodHandler &methodHandler)
-{
- const QJsonObject &jsonObject = toJsonObject(content, codec, parseError);
- if (jsonObject.isEmpty())
- return;
-
- const MessageId id(jsonObject.value(idKey));
- const QString &method = jsonObject.value(methodKey).toString();
- if (!method.isEmpty()) {
- if (auto provider = m_messageProvider[method]) {
- methodHandler(method, id, provider(jsonObject));
- return;
- }
- }
-
- responseHandlers(id, content, codec);
-}
-
constexpr int utf8mib = 106;
static QString docTypeName(const QJsonDocument &doc)
@@ -120,29 +81,43 @@ static QString docTypeName(const QJsonDocument &doc)
return {};
}
-QJsonObject JsonRpcMessageHandler::toJsonObject(const QByteArray &_content,
- QTextCodec *codec,
- QString &parseError)
+JsonRpcMessage::JsonRpcMessage(const BaseMessage &message)
{
- if (_content.isEmpty())
- return QJsonObject();
+ if (message.content.isEmpty())
+ return;
QByteArray content;
- if (codec && codec->mibEnum() != utf8mib) {
+ if (message.codec && message.codec->mibEnum() != utf8mib) {
QTextCodec *utf8 = QTextCodec::codecForMib(utf8mib);
if (utf8)
- content = utf8->fromUnicode(codec->toUnicode(_content));
+ content = utf8->fromUnicode(message.codec->toUnicode(message.content));
}
if (content.isEmpty())
- content = _content;
- QJsonParseError error = {0 , QJsonParseError::NoError};
+ content = message.content;
+ QJsonParseError error = {0, QJsonParseError::NoError};
const QJsonDocument doc = QJsonDocument::fromJson(content, &error);
- if (doc.isObject())
- return doc.object();
- if (doc.isNull())
- parseError = tr("Could not parse JSON message \"%1\".").arg(error.errorString());
- else
- parseError = tr("Expected a JSON object, but got a JSON \"%1\" value.").arg(docTypeName(doc));
- return QJsonObject();
+ if (doc.isObject()) {
+ m_jsonObject = doc.object();
+ } else if (doc.isNull()) {
+ m_parseError = tr("LanguageServerProtocol::JsonRpcMessage",
+ "Could not parse JSON message \"%1\".")
+ .arg(error.errorString());
+ } else {
+ m_parseError = tr("Expected a JSON object, but got a JSON \"%1\" value.")
+ .arg(docTypeName(doc));
+ }
+}
+
+JsonRpcMessage::JsonRpcMessage(const QJsonObject &jsonObject)
+ : m_jsonObject(jsonObject)
+{ }
+
+JsonRpcMessage::JsonRpcMessage(QJsonObject &&jsonObject)
+ : m_jsonObject(std::move(jsonObject))
+{ }
+
+QByteArray JsonRpcMessage::jsonRpcMimeType()
+{
+ return "application/vscode-jsonrpc";
}
CancelRequest::CancelRequest(const CancelParameter &params)
diff --git a/src/libs/languageserverprotocol/jsonrpcmessages.h b/src/libs/languageserverprotocol/jsonrpcmessages.h
index 010bc770f8a..3764775eaed 100644
--- a/src/libs/languageserverprotocol/jsonrpcmessages.h
+++ b/src/libs/languageserverprotocol/jsonrpcmessages.h
@@ -25,7 +25,7 @@
#pragma once
-#include "icontent.h"
+#include "basemessage.h"
#include "lsptypes.h"
#include "jsonkeys.h"
@@ -43,46 +43,107 @@
namespace LanguageServerProtocol {
-class LANGUAGESERVERPROTOCOL_EXPORT JsonRpcMessage : public IContent
+class JsonRpcMessage;
+
+class LANGUAGESERVERPROTOCOL_EXPORT MessageId : public Utils::variant<int, QString>
{
public:
- JsonRpcMessage();
- explicit JsonRpcMessage(const QJsonObject &jsonObject);
- explicit JsonRpcMessage(QJsonObject &&jsonObject);
+ MessageId() : variant(QString()) {}
+ explicit MessageId(int id) : variant(id) {}
+ explicit MessageId(const QString &id) : variant(id) {}
+ explicit MessageId(const QJsonValue &value)
+ {
+ if (value.isDouble())
+ emplace<int>(value.toInt());
+ else
+ emplace<QString>(value.toString());
+ }
- QByteArray toRawData() const final;
- QByteArray mimeType() const final;
- bool isValid(QString *errorMessage) const override;
+ operator QJsonValue() const
+ {
+ if (auto id = Utils::get_if<int>(this))
+ return *id;
+ if (auto id = Utils::get_if<QString>(this))
+ return *id;
+ return QJsonValue();
+ }
-protected:
- QJsonObject m_jsonObject;
+ bool isValid() const
+ {
+ if (Utils::holds_alternative<int>(*this))
+ return true;
+ const QString *id = Utils::get_if<QString>(this);
+ QTC_ASSERT(id, return false);
+ return !id->isEmpty();
+ }
-private:
- QString m_parseError;
+ QString toString() const
+ {
+ if (auto id = Utils::get_if<QString>(this))
+ return *id;
+ if (auto id = Utils::get_if<int>(this))
+ return QString::number(*id);
+ return {};
+ }
+
+ friend auto qHash(const MessageId &id)
+ {
+ if (Utils::holds_alternative<int>(id))
+ return QT_PREPEND_NAMESPACE(qHash(Utils::get<int>(id)));
+ if (Utils::holds_alternative<QString>(id))
+ return QT_PREPEND_NAMESPACE(qHash(Utils::get<QString>(id)));
+ return QT_PREPEND_NAMESPACE(qHash(0));
+ }
};
-class LANGUAGESERVERPROTOCOL_EXPORT JsonRpcMessageHandler
+template <typename Error>
+inline QDebug operator<<(QDebug stream, const LanguageServerProtocol::MessageId &id)
{
- Q_DECLARE_TR_FUNCTIONS(JsonRpcMessageHandler)
+ if (Utils::holds_alternative<int>(id))
+ stream << Utils::get<int>(id);
+ else
+ stream << Utils::get<QString>(id);
+ return stream;
+}
+struct ResponseHandler
+{
+ MessageId id;
+ using Callback = std::function<void(const JsonRpcMessage &)>;
+ Callback callback;
+};
+
+class LANGUAGESERVERPROTOCOL_EXPORT JsonRpcMessage
+{
+ Q_DECLARE_TR_FUNCTIONS(JsonRpcMessage)
public:
- using MessageProvider = std::function<IContent *(const QJsonObject &)>;
- static void registerMessageProvider(const QString &method, MessageProvider provider);
- template<typename T>
- static void registerMessageProvider()
- {
- registerMessageProvider(T::methodName, [](const QJsonObject &object){
- return new T(object);
- });
- }
+ JsonRpcMessage();
+ explicit JsonRpcMessage(const BaseMessage &message);
+ explicit JsonRpcMessage(const QJsonObject &jsonObject);
+ explicit JsonRpcMessage(QJsonObject &&jsonObject);
+
+ virtual ~JsonRpcMessage() = default;
+
static QByteArray jsonRpcMimeType();
- static void parseContent(const QByteArray &content, QTextCodec *codec, QString &errorMessage,
- const ResponseHandlers &responseHandlers,
- const MethodHandler &methodHandler);
- static QJsonObject toJsonObject(const QByteArray &content, QTextCodec *codec, QString &parseError);
+
+ QByteArray toRawData() const;
+ virtual bool isValid(QString *errorMessage) const;
+
+ const QJsonObject &toJsonObject() const;
+
+ const QString parseError() { return m_parseError; }
+
+ virtual Utils::optional<ResponseHandler> responseHandler() const
+ { return Utils::nullopt; }
+
+ BaseMessage toBaseMessage() const
+ { return BaseMessage(jsonRpcMimeType(), toRawData()); }
+
+protected:
+ QJsonObject m_jsonObject;
private:
- static QHash<QString, MessageProvider> m_messageProvider;
+ QString m_parseError;
};
template <typename Params>
@@ -122,7 +183,7 @@ public:
virtual bool parametersAreValid(QString *errorMessage) const
{
if (auto parameter = params())
- return parameter.value().isValid();
+ return parameter->isValid();
if (errorMessage)
*errorMessage = QCoreApplication::translate("LanguageServerProtocol::Notification",
"No parameters in \"%1\".").arg(method());
@@ -322,21 +383,12 @@ public:
QElapsedTimer timer;
timer.start();
auto callback = [callback = m_callBack, method = this->method(), t = std::move(timer)]
- (const QByteArray &content, QTextCodec *codec) {
+ (const JsonRpcMessage &message) {
if (!callback)
return;
logElapsedTime(method, t);
- QString parseError;
- const QJsonObject &object = JsonRpcMessageHandler::toJsonObject(content,
- codec,
- parseError);
- Response response(object);
- if (object.isEmpty()) {
- ResponseError<ErrorDataType> error;
- error.setMessage(parseError);
- response.setError(error);
- }
- callback(Response(object));
+
+ callback(Response(message.toJsonObject()));
};
return Utils::make_optional(ResponseHandler{id(), callback});
}
@@ -379,7 +431,7 @@ public:
constexpr static const char methodName[] = "$/cancelRequest";
};
-} // namespace LanguageClient
+} // namespace LanguageServerProtocol
template <typename Error>
inline QDebug operator<<(QDebug stream,
@@ -388,3 +440,5 @@ inline QDebug operator<<(QDebug stream,
stream.nospace() << error.toString();
return stream;
}
+
+Q_DECLARE_METATYPE(LanguageServerProtocol::JsonRpcMessage)
diff --git a/src/libs/languageserverprotocol/languagefeatures.cpp b/src/libs/languageserverprotocol/languagefeatures.cpp
index 08d09cc3b8c..367f22799d8 100644
--- a/src/libs/languageserverprotocol/languagefeatures.cpp
+++ b/src/libs/languageserverprotocol/languagefeatures.cpp
@@ -204,10 +204,9 @@ RenameRequest::RenameRequest(const RenameParams &params)
Utils::optional<DocumentUri> DocumentLink::target() const
{
- Utils::optional<QString> optionalTarget = optionalValue<QString>(targetKey);
- return optionalTarget.has_value()
- ? Utils::make_optional(DocumentUri::fromProtocol(optionalTarget.value()))
- : Utils::nullopt;
+ if (Utils::optional<QString> optionalTarget = optionalValue<QString>(targetKey))
+ return Utils::make_optional(DocumentUri::fromProtocol(*optionalTarget));
+ return Utils::nullopt;
}
Utils::optional<QJsonValue> DocumentLink::data() const
@@ -404,4 +403,19 @@ Utils::optional<QJsonValue> CodeLens::data() const
return contains(dataKey) ? Utils::make_optional(value(dataKey)) : Utils::nullopt;
}
+HoverResult::HoverResult(const QJsonValue &value)
+{
+ if (value.isObject())
+ emplace<Hover>(Hover(value.toObject()));
+ else
+ emplace<std::nullptr_t>(nullptr);
+}
+
+bool HoverResult::isValid() const
+{
+ if (auto hover = Utils::get_if<Hover>(this))
+ return hover->isValid();
+ return true;
+}
+
} // namespace LanguageServerProtocol
diff --git a/src/libs/languageserverprotocol/languagefeatures.h b/src/libs/languageserverprotocol/languagefeatures.h
index b82fccdaf10..36979692ab9 100644
--- a/src/libs/languageserverprotocol/languagefeatures.h
+++ b/src/libs/languageserverprotocol/languagefeatures.h
@@ -101,8 +101,17 @@ public:
bool isValid() const override { return contains(contentsKey); }
};
+class LANGUAGESERVERPROTOCOL_EXPORT HoverResult : public Utils::variant<Hover, std::nullptr_t>
+{
+public:
+ HoverResult() : variant(nullptr) {}
+ explicit HoverResult(const Hover &hover) : variant(hover) {}
+ explicit HoverResult(const QJsonValue &value);
+ bool isValid() const;
+};
+
class LANGUAGESERVERPROTOCOL_EXPORT HoverRequest
- : public Request<Hover, std::nullptr_t, TextDocumentPositionParams>
+ : public Request<HoverResult, std::nullptr_t, TextDocumentPositionParams>
{
public:
explicit HoverRequest(const TextDocumentPositionParams &params);
diff --git a/src/libs/languageserverprotocol/languageserverprotocol.qbs b/src/libs/languageserverprotocol/languageserverprotocol.qbs
index 97e5b5d1c77..5ae12b1d36a 100644
--- a/src/libs/languageserverprotocol/languageserverprotocol.qbs
+++ b/src/libs/languageserverprotocol/languageserverprotocol.qbs
@@ -18,7 +18,6 @@ Project {
"completion.h",
"diagnostics.cpp",
"diagnostics.h",
- "icontent.h",
"initializemessages.cpp",
"initializemessages.h",
"jsonkeys.h",
diff --git a/src/libs/languageserverprotocol/languageserverprotocol_global.h b/src/libs/languageserverprotocol/languageserverprotocol_global.h
index 83e070f8c28..77f22570403 100644
--- a/src/libs/languageserverprotocol/languageserverprotocol_global.h
+++ b/src/libs/languageserverprotocol/languageserverprotocol_global.h
@@ -29,6 +29,8 @@
#if defined(LANGUAGESERVERPROTOCOL_LIBRARY)
# define LANGUAGESERVERPROTOCOL_EXPORT Q_DECL_EXPORT
+#elif defined(LANGUAGESERVERPROTOCOL_STATIC_LIBRARY)
+# define LANGUAGESERVERPROTOCOL_EXPORT
#else
# define LANGUAGESERVERPROTOCOL_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/libs/languageserverprotocol/lsptypes.cpp b/src/libs/languageserverprotocol/lsptypes.cpp
index 65651366a3d..196f4f43753 100644
--- a/src/libs/languageserverprotocol/lsptypes.cpp
+++ b/src/libs/languageserverprotocol/lsptypes.cpp
@@ -26,7 +26,6 @@
#include "lsptypes.h"
#include "lsputils.h"
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/textutils.h>
#include <QFile>
@@ -43,7 +42,7 @@ namespace LanguageServerProtocol {
Utils::optional<DiagnosticSeverity> Diagnostic::severity() const
{
if (auto val = optionalValue<int>(severityKey))
- return Utils::make_optional(static_cast<DiagnosticSeverity>(val.value()));
+ return Utils::make_optional(static_cast<DiagnosticSeverity>(*val));
return Utils::nullopt;
}
@@ -352,13 +351,13 @@ bool DocumentFilter::applies(const Utils::FilePath &fileName, const Utils::MimeT
QRegularExpression::PatternOption option = QRegularExpression::NoPatternOption;
if (fileName.caseSensitivity() == Qt::CaseInsensitive)
option = QRegularExpression::CaseInsensitiveOption;
- const QRegularExpression regexp(expressionForGlob(_pattern.value()), option);
+ const QRegularExpression regexp(expressionForGlob(*_pattern), option);
if (regexp.isValid() && regexp.match(fileName.toString()).hasMatch())
return true;
}
if (Utils::optional<QString> _lang = language()) {
auto match = [&_lang](const Utils::MimeType &mimeType){
- return _lang.value() == TextDocumentItem::mimeTypeToLanguageId(mimeType);
+ return *_lang == TextDocumentItem::mimeTypeToLanguageId(mimeType);
};
if (mimeType.isValid() && match(mimeType))
return true;
diff --git a/src/libs/languageserverprotocol/lsptypes.h b/src/libs/languageserverprotocol/lsptypes.h
index 41e7459e011..21916852c5e 100644
--- a/src/libs/languageserverprotocol/lsptypes.h
+++ b/src/libs/languageserverprotocol/lsptypes.h
@@ -29,8 +29,9 @@
#include "jsonobject.h"
#include "lsputils.h"
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <utils/link.h>
+#include <utils/mimeutils.h>
#include <utils/optional.h>
#include <utils/textutils.h>
#include <utils/variant.h>
diff --git a/src/libs/languageserverprotocol/lsputils.cpp b/src/libs/languageserverprotocol/lsputils.cpp
index fdac50c3d13..2762e60eac9 100644
--- a/src/libs/languageserverprotocol/lsputils.cpp
+++ b/src/libs/languageserverprotocol/lsputils.cpp
@@ -25,8 +25,6 @@
#include "lsputils.h"
-#include <utils/mimetypes/mimedatabase.h>
-
#include <QHash>
#include <QLoggingCategory>
#include <QVector>
diff --git a/src/libs/languageserverprotocol/lsputils.h b/src/libs/languageserverprotocol/lsputils.h
index 08d5e1e3ec5..47352ff6bb7 100644
--- a/src/libs/languageserverprotocol/lsputils.h
+++ b/src/libs/languageserverprotocol/lsputils.h
@@ -28,7 +28,6 @@
#include "languageserverprotocol_global.h"
#include <utils/algorithm.h>
-#include <utils/mimetypes/mimetype.h>
#include <utils/optional.h>
#include <utils/qtcassert.h>
#include <utils/variant.h>
diff --git a/src/libs/languageserverprotocol/messages.cpp b/src/libs/languageserverprotocol/messages.cpp
index 2f658e3afe3..e0d548c87e7 100644
--- a/src/libs/languageserverprotocol/messages.cpp
+++ b/src/libs/languageserverprotocol/messages.cpp
@@ -25,8 +25,6 @@
#include "messages.h"
-#include "icontent.h"
-
namespace LanguageServerProtocol {
constexpr const char ShowMessageNotification::methodName[];
diff --git a/src/libs/languageserverprotocol/servercapabilities.cpp b/src/libs/languageserverprotocol/servercapabilities.cpp
index 125972567d0..dd2b7628eb1 100644
--- a/src/libs/languageserverprotocol/servercapabilities.cpp
+++ b/src/libs/languageserverprotocol/servercapabilities.cpp
@@ -43,13 +43,12 @@ void ServerCapabilities::setTextDocumentSync(const ServerCapabilities::TextDocum
TextDocumentSyncKind ServerCapabilities::textDocumentSyncKindHelper()
{
- Utils::optional<TextDocumentSync> sync = textDocumentSync();
- if (sync.has_value()) {
- if (auto kind = Utils::get_if<int>(&sync.value()))
+ if (Utils::optional<TextDocumentSync> sync = textDocumentSync()) {
+ if (auto kind = Utils::get_if<int>(&*sync))
return static_cast<TextDocumentSyncKind>(*kind);
- if (auto options = Utils::get_if<TextDocumentSyncOptions>(&sync.value())) {
+ if (auto options = Utils::get_if<TextDocumentSyncOptions>(&*sync)) {
if (const Utils::optional<int> &change = options->change())
- return static_cast<TextDocumentSyncKind>(change.value());
+ return static_cast<TextDocumentSyncKind>(*change);
}
}
return TextDocumentSyncKind::None;
diff --git a/src/libs/languageserverprotocol/workspace.cpp b/src/libs/languageserverprotocol/workspace.cpp
index 8b82a70dde4..3244a96bbfb 100644
--- a/src/libs/languageserverprotocol/workspace.cpp
+++ b/src/libs/languageserverprotocol/workspace.cpp
@@ -81,7 +81,7 @@ ExecuteCommandParams::ExecuteCommandParams(const Command &command)
{
setCommand(command.command());
if (command.arguments().has_value())
- setArguments(command.arguments().value());
+ setArguments(*command.arguments());
}
LanguageServerProtocol::WorkSpaceFolderResult::operator const QJsonValue() const
diff --git a/src/libs/languageserverprotocol/workspace.h b/src/libs/languageserverprotocol/workspace.h
index 235ddbe9a59..6179cd70005 100644
--- a/src/libs/languageserverprotocol/workspace.h
+++ b/src/libs/languageserverprotocol/workspace.h
@@ -188,7 +188,7 @@ public:
QString query() const { return typedValue<QString>(queryKey); }
void setQuery(const QString &query) { insert(queryKey, query); }
- void setLimit(int limit) { insert("limit", limit); } // clangd extension
+ void setLimit(int limit) { insert(u"limit", limit); } // clangd extension
bool isValid() const override { return contains(queryKey); }
};
diff --git a/src/libs/languageutils/languageutils_global.h b/src/libs/languageutils/languageutils_global.h
index ddcf53d4941..b2d65f80d42 100644
--- a/src/libs/languageutils/languageutils_global.h
+++ b/src/libs/languageutils/languageutils_global.h
@@ -29,7 +29,7 @@
#if defined(LANGUAGEUTILS_LIBRARY)
# define LANGUAGEUTILS_EXPORT Q_DECL_EXPORT
-#elif defined(LANGUAGEUTILS_BUILD_STATIC_LIB)
+#elif defined(LANGUAGEUTILS_STATIC_LIBRARY)
# define LANGUAGEUTILS_EXPORT
#else
# define LANGUAGEUTILS_EXPORT Q_DECL_IMPORT
diff --git a/src/libs/libs.qbs b/src/libs/libs.qbs
index 99beea8dc65..92f84fe4d19 100644
--- a/src/libs/libs.qbs
+++ b/src/libs/libs.qbs
@@ -8,7 +8,6 @@ Project {
references: [
"advanceddockingsystem/advanceddockingsystem.qbs",
"aggregation/aggregation.qbs",
- "clangsupport/clangsupport.qbs",
"cplusplus/cplusplus.qbs",
"extensionsystem/extensionsystem.qbs",
"glsl/glsl.qbs",
@@ -21,7 +20,6 @@ Project {
"qmldebug/qmldebug.qbs",
"qtcreatorcdbext/qtcreatorcdbext.qbs",
"sqlite/sqlite.qbs",
- "ssh/ssh.qbs",
"tracing/tracing.qbs",
"utils/process_stub.qbs",
"utils/process_ctrlc_stub.qbs",
diff --git a/src/libs/modelinglib/CMakeLists.txt b/src/libs/modelinglib/CMakeLists.txt
index db79b99ee33..64992d8fb48 100644
--- a/src/libs/modelinglib/CMakeLists.txt
+++ b/src/libs/modelinglib/CMakeLists.txt
@@ -1,5 +1,4 @@
add_qtc_library(Modeling
- DEFINES MODELING_LIBRARY
DEPENDS Qt5::Widgets Utils
PUBLIC_DEPENDS OptionalSvg
INCLUDES qtserialization/inc
@@ -138,7 +137,7 @@ add_qtc_library(Modeling
qmt/model_widgets_ui/propertiesviewmview.cpp qmt/model_widgets_ui/propertiesviewmview.h
qmt/project_controller/projectcontroller.cpp qmt/project_controller/projectcontroller.h
qmt/project/project.cpp qmt/project/project.h
- qmt/resources/resources.qrc
+ qmt/resources/resources_modelinglib.qrc
qmt/serializer/diagramserializer.cpp qmt/serializer/diagramserializer.h
qmt/serializer/infrastructureserializer.cpp qmt/serializer/infrastructureserializer.h
qmt/serializer/modelserializer.cpp qmt/serializer/modelserializer.h
diff --git a/src/libs/modelinglib/modelinglib.qbs b/src/libs/modelinglib/modelinglib.qbs
index b9ee382bbdf..f6ccb200971 100644
--- a/src/libs/modelinglib/modelinglib.qbs
+++ b/src/libs/modelinglib/modelinglib.qbs
@@ -354,7 +354,7 @@ QtcLibrary {
name: "Images"
prefix: "./qmt/resources/"
files: [
- "resources.qrc",
+ "resources_modelinglib.qrc",
"25x25/align-bottom.png",
"25x25/align-horizontal.png",
"25x25/align-left.png",
diff --git a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp
index f7d7e702e5b..72eef3ef742 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp
+++ b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp
@@ -557,9 +557,11 @@ void DiagramController::onBeginResetModel()
void DiagramController::onEndResetModel()
{
updateAllDiagramsList();
- foreach (MDiagram *diagram, m_allDiagrams) {
+ for (MDiagram *diagram : qAsConst(m_allDiagrams)) {
+ const QList<DElement *> elements = diagram->diagramElements();
// remove all elements which are not longer part of the model
- foreach (DElement *element, diagram->diagramElements()) {
+ for (int i = elements.size() - 1; i >= 0; --i) {
+ DElement *element = elements.at(i);
if (element->modelUid().isValid()) {
MElement *modelElement = m_modelController->findElement(element->modelUid());
if (!modelElement)
@@ -567,7 +569,7 @@ void DiagramController::onEndResetModel()
}
}
// update all remaining elements from model
- foreach (DElement *element, diagram->diagramElements())
+ for (DElement *element : diagram->diagramElements())
updateElementFromModel(element, diagram, false);
}
emit endResetAllDiagrams();
diff --git a/src/libs/modelinglib/qmt/infrastructure/qmt_global.h b/src/libs/modelinglib/qmt/infrastructure/qmt_global.h
index e01c0b87c63..670deaeac57 100644
--- a/src/libs/modelinglib/qmt/infrastructure/qmt_global.h
+++ b/src/libs/modelinglib/qmt/infrastructure/qmt_global.h
@@ -29,6 +29,8 @@
#if defined(MODELING_LIBRARY)
# define QMT_EXPORT Q_DECL_EXPORT
+#elif defined(MODELING_STATIC_LIBRARY)
+# define QMT_EXPORT
#else
# define QMT_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/libs/modelinglib/qmt/resources/resources.qrc b/src/libs/modelinglib/qmt/resources/resources_modelinglib.qrc
index f6ff6af1198..f6ff6af1198 100644
--- a/src/libs/modelinglib/qmt/resources/resources.qrc
+++ b/src/libs/modelinglib/qmt/resources/resources_modelinglib.qrc
diff --git a/src/libs/qlitehtml b/src/libs/qlitehtml
-Subproject 37c295f4320840b646e84e1cbda8aa07eafc353
+Subproject 076f57c9436b55921a6477bc81660c5564c117a
diff --git a/src/libs/qmldebug/qmldebug_global.h b/src/libs/qmldebug/qmldebug_global.h
index 16199d9f685..d69cd337929 100644
--- a/src/libs/qmldebug/qmldebug_global.h
+++ b/src/libs/qmldebug/qmldebug_global.h
@@ -27,7 +27,7 @@
#if defined(QMLDEBUG_LIBRARY)
# define QMLDEBUG_EXPORT Q_DECL_EXPORT
-#elif defined(QMLDEBUG_STATIC_LIB)
+#elif defined(QMLDEBUG_STATIC_LIBRARY)
# define QMLDEBUG_EXPORT
#else
# define QMLDEBUG_EXPORT Q_DECL_IMPORT
diff --git a/src/libs/qmldebug/qmldebugconnection.cpp b/src/libs/qmldebug/qmldebugconnection.cpp
index ad34bdddab1..cf41b4275ad 100644
--- a/src/libs/qmldebug/qmldebugconnection.cpp
+++ b/src/libs/qmldebug/qmldebugconnection.cpp
@@ -347,11 +347,7 @@ void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
emit logStateChange(socketStateToString(state));
});
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- const auto errorOccurred = QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error);
-#else
const auto errorOccurred = &QAbstractSocket::errorOccurred;
-#endif
connect(socket, errorOccurred, this, [this](QAbstractSocket::SocketError error) {
emit logError(socketErrorToString(error));
socketDisconnected();
@@ -392,14 +388,7 @@ void QmlDebugConnection::newConnection()
connect(socket, &QLocalSocket::disconnected, this, &QmlDebugConnection::socketDisconnected,
Qt::QueuedConnection);
- void (QLocalSocket::*LocalSocketErrorFunction)(QLocalSocket::LocalSocketError)
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- = &QLocalSocket::error;
-#else
- = &QLocalSocket::errorOccurred;
-#endif
-
- connect(socket, LocalSocketErrorFunction, this, [this](QLocalSocket::LocalSocketError error) {
+ connect(socket, &QLocalSocket::errorOccurred, this, [this](QLocalSocket::LocalSocketError error) {
emit logError(socketErrorToString(static_cast<QAbstractSocket::SocketError>(error)));
socketDisconnected();
}, Qt::QueuedConnection);
diff --git a/src/libs/qmleditorwidgets/CMakeLists.txt b/src/libs/qmleditorwidgets/CMakeLists.txt
index b33a7bd075b..e13e8b1a7b0 100644
--- a/src/libs/qmleditorwidgets/CMakeLists.txt
+++ b/src/libs/qmleditorwidgets/CMakeLists.txt
@@ -18,5 +18,5 @@ add_qtc_library(QmlEditorWidgets
gradientline.cpp gradientline.h
huecontrol.cpp huecontrol.h
qmleditorwidgets_global.h
- resources.qrc
+ resources_qmleditorwidgets.qrc
)
diff --git a/src/libs/qmleditorwidgets/qmleditorwidgets.qbs b/src/libs/qmleditorwidgets/qmleditorwidgets.qbs
index e4dd0f773d2..5f15bbc178a 100644
--- a/src/libs/qmleditorwidgets/qmleditorwidgets.qbs
+++ b/src/libs/qmleditorwidgets/qmleditorwidgets.qbs
@@ -29,7 +29,7 @@ QtcLibrary {
"gradientline.cpp", "gradientline.h",
"huecontrol.cpp", "huecontrol.h",
"qmleditorwidgets_global.h",
- "resources.qrc"
+ "resources_qmleditorwidgets.qrc"
]
}
diff --git a/src/libs/qmleditorwidgets/qmleditorwidgets_global.h b/src/libs/qmleditorwidgets/qmleditorwidgets_global.h
index 9c2320afc74..613d582499c 100644
--- a/src/libs/qmleditorwidgets/qmleditorwidgets_global.h
+++ b/src/libs/qmleditorwidgets/qmleditorwidgets_global.h
@@ -29,7 +29,7 @@
# if defined(QMLEDITORWIDGETS_LIBRARY)
# define QMLEDITORWIDGETS_EXPORT Q_DECL_EXPORT
-# elif defined(BUILD_QMLJSDEBUGGER_STATIC_LIB)
+# elif defined(QMLEDITORWIDGETS_STATIC_LIBRARY)
# define QMLEDITORWIDGETS_EXPORT
# else
# define QMLEDITORWIDGETS_EXPORT Q_DECL_IMPORT
diff --git a/src/libs/qmleditorwidgets/resources.qrc b/src/libs/qmleditorwidgets/resources_qmleditorwidgets.qrc
index d8bea3895c6..d8bea3895c6 100644
--- a/src/libs/qmleditorwidgets/resources.qrc
+++ b/src/libs/qmleditorwidgets/resources_qmleditorwidgets.qrc
diff --git a/src/libs/qmljs/parser/qmljsglobal_p.h b/src/libs/qmljs/parser/qmljsglobal_p.h
index f2b0da9d74a..1b6e7181a90 100644
--- a/src/libs/qmljs/parser/qmljsglobal_p.h
+++ b/src/libs/qmljs/parser/qmljsglobal_p.h
@@ -44,7 +44,7 @@
# ifdef QMLJS_LIBRARY
# define QML_PARSER_EXPORT Q_DECL_EXPORT
-# elif QML_BUILD_STATIC_LIB
+# elif QMLJS_STATIC_LIBRARY
# define QML_PARSER_EXPORT
# else
# define QML_PARSER_EXPORT Q_DECL_IMPORT
diff --git a/src/libs/qmljs/qmljs_global.h b/src/libs/qmljs/qmljs_global.h
index 3e5b3617ab1..cf23791649b 100644
--- a/src/libs/qmljs/qmljs_global.h
+++ b/src/libs/qmljs/qmljs_global.h
@@ -29,7 +29,7 @@
#if defined(QMLJS_LIBRARY)
# define QMLJS_EXPORT Q_DECL_EXPORT
-#elif defined(QML_BUILD_STATIC_LIB)
+#elif defined(QMLJS_STATIC_LIBRARY)
# define QMLJS_EXPORT
#else
# define QMLJS_EXPORT Q_DECL_IMPORT
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index d7f96f92a42..dbb0962d0cf 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -612,7 +612,7 @@ class UnsupportedTypesByVisualDesigner : public QStringList
{
public:
UnsupportedTypesByVisualDesigner()
- : QStringList({"Timer", "Package", "Particles", "ApplicationWindow"})
+ : QStringList({"Package", "Particles", "ApplicationWindow"})
{}
};
@@ -1137,6 +1137,44 @@ bool Check::visit(UiPublicMember *ast)
{
if (ast->type == UiPublicMember::Property) {
const QStringView typeName = ast->memberType->name;
+
+ // Check alias properties don't reference root item
+ // Item {
+ // id: root
+ // property alias p1: root
+ // property alias p2: root.child
+ //
+ // Item { id: child }
+ // }
+ // - Show error for alias property p1
+ // - Show warning for alias property p2
+
+ // Check if type and id stack only contain one item as we are only looking for alias
+ // properties in the root item.
+ if (typeName == QLatin1String("alias") && ast->type == AST::UiPublicMember::Property
+ && m_typeStack.count() == 1 && m_idStack.count() == 1 && m_idStack.top().count() == 1) {
+
+ const QString rootId = m_idStack.top().values().first();
+ if (!rootId.isEmpty()) {
+ if (ExpressionStatement *exp = cast<ExpressionStatement *>(ast->statement)) {
+ ExpressionNode *node = exp->expression;
+
+ // Check for case property alias p1: root
+ if (IdentifierExpression *idExp = cast<IdentifierExpression *>(node)) {
+ if (!idExp->name.isEmpty() && idExp->name.toString() == rootId)
+ addMessage(ErrAliasReferRoot, idExp->identifierToken);
+
+ // Check for case property alias p2: root.child
+ } else if (FieldMemberExpression *fmExp = cast<FieldMemberExpression *>(node)) {
+ if (IdentifierExpression *base = cast<IdentifierExpression *>(fmExp->base)) {
+ if (!base->name.isEmpty() && base->name.toString() == rootId)
+ addMessage(WarnAliasReferRootHierarchy, base->identifierToken);
+ }
+ }
+ }
+ }
+ }
+
// warn about dubious use of var/variant
if (typeName == QLatin1String("variant") || typeName == QLatin1String("var")) {
Evaluate evaluator(&_scopeChain);
diff --git a/src/libs/qmljs/qmljsevaluate.cpp b/src/libs/qmljs/qmljsevaluate.cpp
index e848d130b41..53b9dbdbf88 100644
--- a/src/libs/qmljs/qmljsevaluate.cpp
+++ b/src/libs/qmljs/qmljsevaluate.cpp
@@ -213,6 +213,7 @@ bool Evaluate::visit(AST::UiQualifiedId *ast)
bool Evaluate::visit(AST::TemplateLiteral *ast)
{
+ Q_UNUSED(ast)
_result = _valueOwner->stringValue();
return false;
}
diff --git a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
index 40358b6c954..72a4cfad511 100644
--- a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
+++ b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
@@ -334,7 +334,7 @@ protected:
_doc->fileName(),
line, column,
QmlJS::FindExportedCppTypes::tr(
- "The module URI cannot be determined by static analysis. The type will be available\n"
+ "The module URI cannot be determined by static analysis. The type will not be available\n"
"globally in the QML editor. You can add a \"// @uri My.Module.Uri\" annotation to let\n"
"the QML editor know about a likely URI."));
}
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 74526295813..9412406fdc4 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -2378,8 +2378,12 @@ const Value *TypeScope::lookupMember(const QString &name, const Context *context
continue;
if (const Value *v = import->lookupMember(name, context, foundInObject)) {
- i.used = true;
- return v;
+ // FIXME if we have multiple non-aliased imports containing this object we'd have to
+ // disambiguate (and inform the user) about this issue
+ if (info.as().isEmpty()) {
+ i.used = true;
+ return v;
+ }
}
}
if (foundInObject)
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index fe3301db933..df881a09ab4 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -465,7 +465,8 @@ Import LinkPrivate::importNonFile(const Document::Ptr &doc, const ImportInfo &im
"For Qbs projects, declare and set a qmlImportPaths property in your product "
"to add import paths.\n"
"For qmlproject projects, use the importPaths property to add import paths.\n"
- "For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.\n")
+ "For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.\n"
+ "For qmlRegister... calls, make sure that you define the Module URI as a string literal.\n")
.arg(importInfo.name(), m_importPaths.join(QLatin1Char('\n'))));
}
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index 5a2ce801189..444d429a4bc 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
@@ -446,6 +446,20 @@ bool pInfoLessThanImports(const ModelManagerInterface::ProjectInfo &p1,
}
+static QList<Utils::FilePath> generatedQrc(QStringList applicationDirectories)
+{
+ QList<Utils::FilePath> res;
+ for (const QString &pathStr : applicationDirectories) {
+ Utils::FilePath path = Utils::FilePath::fromString(pathStr);
+ Utils::FilePath generatedQrcDir = path.pathAppended(".rcc");
+ if (generatedQrcDir.isReadableDir()) {
+ for (const Utils::FilePath & qrcPath: generatedQrcDir.dirEntries(FileFilter(QStringList({QStringLiteral(u"*.qrc")}), QDir::Files)))
+ res.append(qrcPath.canonicalPath());
+ }
+ }
+ return res;
+}
+
void ModelManagerInterface::iterateQrcFiles(
ProjectExplorer::Project *project, QrcResourceSelector resources,
const std::function<void(QrcParser::ConstPtr)> &callback)
@@ -461,18 +475,21 @@ void ModelManagerInterface::iterateQrcFiles(
Utils::sort(pInfos, &pInfoLessThanAll);
}
- QSet<QString> pathsChecked;
+ QSet<Utils::FilePath> pathsChecked;
for (const ModelManagerInterface::ProjectInfo &pInfo : qAsConst(pInfos)) {
QStringList qrcFilePaths;
if (resources == ActiveQrcResources)
qrcFilePaths = pInfo.activeResourceFiles;
else
qrcFilePaths = pInfo.allResourceFiles;
- for (const QString &qrcFilePath : qAsConst(qrcFilePaths)) {
+ for (const Utils::FilePath &p : generatedQrc(pInfo.applicationDirectories))
+ qrcFilePaths.append(p.toString());
+ for (const QString &qrcFilePathStr : qAsConst(qrcFilePaths)) {
+ auto qrcFilePath = Utils::FilePath::fromString(qrcFilePathStr);
if (pathsChecked.contains(qrcFilePath))
continue;
pathsChecked.insert(qrcFilePath);
- QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath);
+ QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath.toString());
if (qrcFile.isNull())
continue;
callback(qrcFile);
@@ -589,6 +606,8 @@ void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectE
m_qrcContents = pinfo.resourceFileContents;
for (const QString &newQrc : qAsConst(pinfo.allResourceFiles))
m_qrcCache.addPath(newQrc, m_qrcContents.value(newQrc));
+ for (const Utils::FilePath &newQrc : generatedQrc(pinfo.applicationDirectories))
+ m_qrcCache.addPath(newQrc.toString(), m_qrcContents.value(newQrc.toString()));
for (const QString &oldQrc : qAsConst(oldInfo.allResourceFiles))
m_qrcCache.removePath(oldQrc);
@@ -969,7 +988,8 @@ void ModelManagerInterface::parseLoop(QSet<QString> &scannedPaths,
doc->parse();
#ifdef WITH_TESTS
- if (ExtensionSystem::PluginManager::isScenarioRunning("TestModelManagerInterface")) {
+ if (ExtensionSystem::PluginManager::instance() // we might run as an auto-test
+ && ExtensionSystem::PluginManager::isScenarioRunning("TestModelManagerInterface")) {
ExtensionSystem::PluginManager::waitForScenarioFullyInitialized();
if (ExtensionSystem::PluginManager::finishScenario()) {
qDebug() << "Point 1: Shutdown triggered";
@@ -1179,6 +1199,29 @@ void ModelManagerInterface::maybeScan(const PathsAndLanguages &importPaths)
}
}
+static QList<Utils::FilePath> minimalPrefixPaths(const QStringList &paths)
+{
+ QList<Utils::FilePath> sortedPaths;
+ // find minimal prefix, ensure '/' at end
+ for (const QString &pathStr : qAsConst(paths)) {
+ Utils::FilePath path = Utils::FilePath::fromString(pathStr);
+ if (!path.endsWith("/"))
+ path.setPath(path.path() + "/");
+ if (path.path().length() > 1)
+ sortedPaths.append(path);
+ }
+ std::sort(sortedPaths.begin(), sortedPaths.end());
+ QList<Utils::FilePath> res;
+ QString lastPrefix;
+ for (auto it = sortedPaths.begin(); it != sortedPaths.end(); ++it) {
+ if (lastPrefix.isEmpty() || !it->startsWith(lastPrefix)) {
+ lastPrefix = it->path();
+ res.append(*it);
+ }
+ }
+ return res;
+}
+
void ModelManagerInterface::updateImportPaths()
{
if (m_indexerDisabled)
@@ -1242,6 +1285,7 @@ void ModelManagerInterface::updateImportPaths()
m_allImportPaths = allImportPaths;
m_activeBundles = activeBundles;
m_extendedBundles = extendedBundles;
+ m_applicationPaths = minimalPrefixPaths(allApplicationDirectories);
}
@@ -1252,10 +1296,13 @@ void ModelManagerInterface::updateImportPaths()
QSet<QString> newLibraries;
for (const Document::Ptr &doc : qAsConst(snapshot))
findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
- for (const QString &path : qAsConst(allApplicationDirectories)) {
- allImportPaths.maybeInsert(FilePath::fromString(path), Dialect::Qml);
- findNewQmlApplicationInPath(FilePath::fromString(path), snapshot, this, &newLibraries);
+ for (const QString &pathStr : qAsConst(allApplicationDirectories)) {
+ Utils::FilePath path = Utils::FilePath::fromString(pathStr);
+ allImportPaths.maybeInsert(path, Dialect::Qml);
+ findNewQmlApplicationInPath(path, snapshot, this, &newLibraries);
}
+ for (const Utils::FilePath &qrcPath : generatedQrc(allApplicationDirectories))
+ updateQrcFile(qrcPath.toString());
updateSourceFiles(importedFiles, true);
@@ -1667,4 +1714,47 @@ void ModelManagerInterface::resetCodeModel()
updateImportPaths();
}
+Utils::FilePath ModelManagerInterface::fileToSource(const Utils::FilePath &path)
+{
+ if (!path.scheme().isEmpty())
+ return path;
+ for (const Utils::FilePath &p : m_applicationPaths) {
+ if (!p.isEmpty() && path.startsWith(p.path())) {
+ // if it is an applicationPath (i.e. in the build directory)
+ // try to use the path from the build dir as resource path
+ // and recover the path of the corresponding source file
+ QString reducedPath = path.path().mid(p.path().size());
+ QString reversePath(reducedPath);
+ std::reverse(reversePath.begin(), reversePath.end());
+ if (!reversePath.endsWith('/'))
+ reversePath.append('/');
+ QrcParser::MatchResult res;
+ iterateQrcFiles(nullptr,
+ QrcResourceSelector::AllQrcResources,
+ [&](const QrcParser::ConstPtr &qrcFile) {
+ if (!qrcFile)
+ return;
+ QrcParser::MatchResult matchNow = qrcFile->longestReverseMatches(
+ reversePath);
+
+ if (matchNow.matchDepth < res.matchDepth)
+ return;
+ if (matchNow.matchDepth == res.matchDepth) {
+ res.reversedPaths += matchNow.reversedPaths;
+ res.sourceFiles += matchNow.sourceFiles;
+ } else {
+ res = matchNow;
+ }
+ });
+ std::sort(res.sourceFiles.begin(), res.sourceFiles.end());
+ if (!res.sourceFiles.isEmpty()) {
+ return res.sourceFiles.first();
+ }
+ qCWarning(qmljsLog) << "Could not find source file for file" << path
+ << "in application path" << p;
+ }
+ }
+ return path;
+}
+
} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h
index 5a4f711a1be..4ed02c2c96d 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.h
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h
@@ -34,6 +34,7 @@
#include <utils/environment.h>
#include <utils/futuresynchronizer.h>
#include <utils/qrcparser.h>
+#include <utils/filepath.h>
#include <QFuture>
#include <QHash>
@@ -149,6 +150,7 @@ public:
ProjectExplorer::Project *project = nullptr,
bool addDirs = false,
QrcResourceSelector resources = AllQrcResources);
+ Utils::FilePath fileToSource(const Utils::FilePath &file);
QList<ProjectInfo> projectInfos() const;
bool containsProject(ProjectExplorer::Project *project) const;
@@ -254,6 +256,7 @@ private:
QmlJS::Snapshot m_validSnapshot;
QmlJS::Snapshot m_newestSnapshot;
PathsAndLanguages m_allImportPaths;
+ QList<Utils::FilePath> m_applicationPaths;
QStringList m_defaultImportPaths;
QmlJS::QmlLanguageBundles m_activeBundles;
QmlJS::QmlLanguageBundles m_extendedBundles;
diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp
index a51929566ba..56d444f9d9e 100644
--- a/src/libs/qmljs/qmljsplugindumper.cpp
+++ b/src/libs/qmljs/qmljsplugindumper.cpp
@@ -210,7 +210,7 @@ static QString qmldumpFailedMessage(const FilePath &libraryPath, const QString &
"\n"
"%1"
"\n"
- "Check 'General Messages' output pane for details."
+ "Check General Messages for details."
).arg(firstLines);
}
@@ -264,13 +264,20 @@ void PluginDumper::qmlPluginTypeDumpDone(QtcProcess *process)
return;
const Snapshot snapshot = m_modelManager->snapshot();
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
- bool privatePlugin = libraryPath.endsWith(QLatin1String("private"));
+ const bool privatePlugin = libraryPath.endsWith(QLatin1String("private"));
- if (process->exitCode() != 0) {
+ if (process->exitCode() || process->error() != QProcess::UnknownError) {
const QString errorMessages = qmlPluginDumpErrorMessage(process);
if (!privatePlugin)
ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
- libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, qmldumpFailedMessage(libraryPath, errorMessages));
+ libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError,
+ qmldumpFailedMessage(libraryPath, errorMessages));
+
+ if (process->error() != QProcess::UnknownError) {
+ libraryInfo.updateFingerprint();
+ m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
+ return;
+ }
const QByteArray output = process->readAllStandardOutput();
@@ -324,23 +331,6 @@ void PluginDumper::qmlPluginTypeDumpDone(QtcProcess *process)
}
}
-void PluginDumper::qmlPluginTypeDumpError(QtcProcess *process)
-{
- process->deleteLater();
-
- const FilePath libraryPath = m_runningQmldumps.take(process);
- if (libraryPath.isEmpty())
- return;
- const QString errorMessages = qmlPluginDumpErrorMessage(process);
- const Snapshot snapshot = m_modelManager->snapshot();
- LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
- if (!libraryPath.path().endsWith(QLatin1String("private"), Qt::CaseInsensitive))
- ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
- libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, qmldumpFailedMessage(libraryPath, errorMessages));
- libraryInfo.updateFingerprint();
- m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
-}
-
void PluginDumper::pluginChanged(const QString &pluginLibrary)
{
const int pluginIndex = m_libraryToPluginIndex.value(pluginLibrary, -1);
@@ -628,8 +618,7 @@ void PluginDumper::runQmlDump(const ModelManagerInterface::ProjectInfo &info,
process->setEnvironment(info.qmlDumpEnvironment);
process->setWorkingDirectory(importPath);
process->setCommand({info.qmlDumpPath, arguments});
- connect(process, &QtcProcess::finished, this, [this, process] { qmlPluginTypeDumpDone(process); });
- connect(process, &QtcProcess::errorOccurred, this, [this, process] { qmlPluginTypeDumpError(process); });
+ connect(process, &QtcProcess::done, this, [this, process] { qmlPluginTypeDumpDone(process); });
process->start();
m_runningQmldumps.insert(process, importPath);
}
diff --git a/src/libs/qmljs/qmljsplugindumper.h b/src/libs/qmljs/qmljsplugindumper.h
index 3503c046810..7d289a4258f 100644
--- a/src/libs/qmljs/qmljsplugindumper.h
+++ b/src/libs/qmljs/qmljsplugindumper.h
@@ -27,8 +27,6 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
-#include <utils/qtcprocess.h>
-
#include <QObject>
#include <QHash>
@@ -36,7 +34,10 @@ QT_BEGIN_NAMESPACE
class QDir;
QT_END_NAMESPACE
-namespace Utils { class FileSystemWatcher; }
+namespace Utils {
+class FileSystemWatcher;
+class QtcProcess;
+}
namespace QmlJS {
@@ -59,7 +60,6 @@ private:
const QString &importUri, const QString &importVersion);
Q_INVOKABLE void dumpAllPlugins();
void qmlPluginTypeDumpDone(Utils::QtcProcess *process);
- void qmlPluginTypeDumpError(Utils::QtcProcess *process);
void pluginChanged(const QString &pluginLibrary);
private:
diff --git a/src/libs/qmljs/qmljsreformatter.cpp b/src/libs/qmljs/qmljsreformatter.cpp
index 5e57697aa91..98b18c760d2 100644
--- a/src/libs/qmljs/qmljsreformatter.cpp
+++ b/src/libs/qmljs/qmljsreformatter.cpp
@@ -98,6 +98,7 @@ class Rewriter : protected Visitor
bool _hadEmptyLine = false;
int _binaryExpDepth = 0;
bool _hasOpenComment = false;
+ int _lineLength = 80;
public:
Rewriter(Document::Ptr doc)
@@ -107,6 +108,7 @@ public:
void setIndentSize(int size) { _formatter.setIndentSize(size); }
void setTabSize(int size) { _formatter.setTabSize(size); }
+ void setLineLength(int size) { _lineLength = size; }
QString operator()(Node *node)
{
@@ -286,10 +288,10 @@ protected:
QStringList lines;
qreal badnessFromSplits;
- qreal badness()
+ qreal badness(int lineLength)
{
- const int maxLineLength = 80;
- const int strongMaxLineLength = 100;
+ const int maxLineLength = lineLength;
+ const int strongMaxLineLength = lineLength + 20;
const int minContentLength = 10;
qreal result = badnessFromSplits;
@@ -369,7 +371,7 @@ protected:
nested.lines.prepend(newContextLine);
nested.badnessFromSplits += possibleSplits.at(i).badness;
- if (nested.badness() < result.badness())
+ if (nested.badness(_lineLength) < result.badness(_lineLength))
result = nested;
}
@@ -391,13 +393,15 @@ protected:
_indent = tryIndent(_line);
adjustIndent(&_line, &_possibleSplits, _indent);
- // maybe make multi-line?
- BestSplit split = computeBestSplits(QStringList(), _line, _possibleSplits);
- if (!split.lines.isEmpty() && split.lines.size() > 1) {
- for (int i = 0; i < split.lines.size(); ++i) {
- _line = split.lines.at(i);
- if (i != split.lines.size() - 1)
- finishLine();
+ if (_lineLength > 0) {
+ // maybe make multi-line?
+ BestSplit split = computeBestSplits(QStringList(), _line, _possibleSplits);
+ if (!split.lines.isEmpty() && split.lines.size() > 1) {
+ for (int i = 0; i < split.lines.size(); ++i) {
+ _line = split.lines.at(i);
+ if (i != split.lines.size() - 1)
+ finishLine();
+ }
}
}
}
@@ -953,10 +957,10 @@ protected:
accept(ast->left);
// in general, avoid splitting at the operator
- // but && and || are ok
+ // but && || and ?? are ok
qreal splitBadness = 30;
if (ast->op == QSOperator::And
- || ast->op == QSOperator::Or)
+ || ast->op == QSOperator::Or || ast->op == QSOperator::Coalesce)
splitBadness = 0;
addPossibleSplit(splitBadness);
@@ -1414,10 +1418,11 @@ QString QmlJS::reformat(const Document::Ptr &doc)
return rewriter(doc->ast());
}
-QString QmlJS::reformat(const Document::Ptr &doc, int indentSize, int tabSize)
+QString QmlJS::reformat(const Document::Ptr &doc, int indentSize, int tabSize, int lineLength)
{
Rewriter rewriter(doc);
rewriter.setIndentSize(indentSize);
rewriter.setTabSize(tabSize);
+ rewriter.setLineLength(lineLength);
return rewriter(doc->ast());
}
diff --git a/src/libs/qmljs/qmljsreformatter.h b/src/libs/qmljs/qmljsreformatter.h
index 7465a1a17f0..45903062d90 100644
--- a/src/libs/qmljs/qmljsreformatter.h
+++ b/src/libs/qmljs/qmljsreformatter.h
@@ -31,5 +31,5 @@
namespace QmlJS {
QMLJS_EXPORT QString reformat(const Document::Ptr &doc);
-QMLJS_EXPORT QString reformat(const Document::Ptr &doc, int indentSize, int tabSize);
-}
+QMLJS_EXPORT QString reformat(const Document::Ptr &doc, int indentSize, int tabSize, int lineLength);
+} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljsscanner.cpp b/src/libs/qmljs/qmljsscanner.cpp
index 35c616b3bc9..771fb4042fd 100644
--- a/src/libs/qmljs/qmljsscanner.cpp
+++ b/src/libs/qmljs/qmljsscanner.cpp
@@ -306,6 +306,12 @@ QList<Token> Scanner::operator()(const QString &text, int startState)
la = text.at(index + 1);
switch (ch.unicode()) {
+ case '#':
+ if (_scanComments)
+ tokens.append(Token(index, text.length() - index, Token::Comment));
+ index = text.length();
+ break;
+
case '/':
if (la == QLatin1Char('/')) {
if (_scanComments)
@@ -498,6 +504,20 @@ QList<Token> Scanner::operator()(const QString &text, int startState)
setRegexpMayFollow(&_state, true);
break;
+ case '?':
+ switch (la.unicode()) {
+ case '?':
+ case '.':
+ tokens.append(Token(index, 2, Token::Delimiter));
+ index += 2;
+ break;
+ default:
+ tokens.append(Token(index++, 1, Token::Delimiter));
+ break;
+ }
+ setRegexpMayFollow(&_state, true);
+ break;
+
default:
if (ch.isSpace()) {
do {
diff --git a/src/libs/qmljs/qmljsstaticanalysismessage.cpp b/src/libs/qmljs/qmljsstaticanalysismessage.cpp
index 0c026ecb75f..fd9b8bac378 100644
--- a/src/libs/qmljs/qmljsstaticanalysismessage.cpp
+++ b/src/libs/qmljs/qmljsstaticanalysismessage.cpp
@@ -255,6 +255,10 @@ StaticAnalysisMessages::StaticAnalysisMessages()
tr("Components are only allowed to have a single child element."));
newMsg(WarnComponentRequiresChildren, Warning,
tr("Components require a child element."));
+ newMsg(ErrAliasReferRoot, Error,
+ tr("Do not reference the root item as alias."));
+ newMsg(WarnAliasReferRootHierarchy, Warning,
+ tr("Avoid referencing the root item in a hierarchy."));
}
} // anonymous namespace
diff --git a/src/libs/qmljs/qmljsstaticanalysismessage.h b/src/libs/qmljs/qmljsstaticanalysismessage.h
index 51a517d2352..58b1d7cfd5e 100644
--- a/src/libs/qmljs/qmljsstaticanalysismessage.h
+++ b/src/libs/qmljs/qmljsstaticanalysismessage.h
@@ -134,7 +134,9 @@ enum Type {
WarnLogicalValueDoesNotDependOnValues = 325,
ErrToManyComponentChildren = 326,
WarnComponentRequiresChildren = 327,
- WarnDuplicateImport = 400
+ WarnDuplicateImport = 400,
+ ErrAliasReferRoot = 401,
+ WarnAliasReferRootHierarchy = 402
};
class QMLJS_EXPORT PrototypeMessageData {
diff --git a/src/libs/qtcreatorcdbext/CMakeLists.txt b/src/libs/qtcreatorcdbext/CMakeLists.txt
index bf3d1c0989d..ba6508c43e0 100644
--- a/src/libs/qtcreatorcdbext/CMakeLists.txt
+++ b/src/libs/qtcreatorcdbext/CMakeLists.txt
@@ -20,12 +20,16 @@ endif()
find_library(DbgEngLib dbgeng)
-set(ArchSuffix 32)
+set(ArchSuffix "32")
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
- set(ArchSuffix 64)
+ set(ArchSuffix "64")
endif()
-add_qtc_library(qtcreatorcdbext
+if (MSVC_CXX_ARCHITECTURE_ID MATCHES "^ARM")
+ set(ArchSuffix "arm${ArchSuffix}")
+endif()
+
+add_qtc_library(qtcreatorcdbext SHARED
COMPONENT qtcreatorcdbext
DEPENDS ${DbgEngLib}
DESTINATION lib/qtcreatorcdbext${ArchSuffix}/
diff --git a/src/libs/sqlite/CMakeLists.txt b/src/libs/sqlite/CMakeLists.txt
index 236d35b4c96..53ea1636477 100644
--- a/src/libs/sqlite/CMakeLists.txt
+++ b/src/libs/sqlite/CMakeLists.txt
@@ -1,18 +1,21 @@
+set(SQLITE_SOURCES
+ ../3rdparty/sqlite/sqlite3.c
+ ../3rdparty/sqlite/sqlite3.h
+ ../3rdparty/sqlite/carray.c
+ ../3rdparty/sqlite/config.h
+ ../3rdparty/sqlite/sqlite.h
+)
+
add_qtc_library(Sqlite
PROPERTIES AUTOMOC OFF AUTOUIC OFF
PUBLIC_DEFINES
- BUILD_SQLITE_LIBRARY
SQLITE_CORE
DEPENDS Qt5::Core Threads::Threads ${CMAKE_DL_LIBS}
PUBLIC_INCLUDES
"${CMAKE_CURRENT_LIST_DIR}"
../3rdparty/sqlite
SOURCES
- ../3rdparty/sqlite/sqlite3.c
- ../3rdparty/sqlite/sqlite3.h
- ../3rdparty/sqlite/carray.c
- ../3rdparty/sqlite/config.h
- ../3rdparty/sqlite/sqlite.h
+ ${SQLITE_SOURCES}
constraints.h
createtablesqlstatementbuilder.h
lastchangedrowid.h
@@ -42,10 +45,16 @@ add_qtc_library(Sqlite
sqlitelibraryinitializer.cpp sqlitelibraryinitializer.h
)
+set_source_files_properties(
+ ${SQLITE_SOURCES}
+ PROPERTIES
+ QT_COMPILE_OPTIONS_DISABLE_WARNINGS ON
+)
+
extend_qtc_library(Sqlite DEFINES SQLITE_CUSTOM_INCLUDE=config.h)
if (APPLE)
-extend_qtc_library(Sqlite DEFINES _BSD_SOURCE)
+ extend_qtc_library(Sqlite DEFINES _BSD_SOURCE)
elseif (UNIX)
-extend_qtc_library(Sqlite DEFINES _POSIX_C_SOURCE=200809L _GNU_SOURCE _DEFAULT_SOURCE)
+ extend_qtc_library(Sqlite DEFINES _POSIX_C_SOURCE=200809L _GNU_SOURCE _DEFAULT_SOURCE)
endif()
diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h
index 20b06c59af3..d191cefdc26 100644
--- a/src/libs/sqlite/sqlitebasestatement.h
+++ b/src/libs/sqlite/sqlitebasestatement.h
@@ -25,6 +25,10 @@
#pragma once
+#ifdef SQLITE_STATIC_LIBRARY
+#include "config.h"
+#endif
+
#include "sqliteglobal.h"
#include "sqliteblob.h"
diff --git a/src/libs/sqlite/sqlitedatabasebackend.h b/src/libs/sqlite/sqlitedatabasebackend.h
index 997652abc30..530918135d7 100644
--- a/src/libs/sqlite/sqlitedatabasebackend.h
+++ b/src/libs/sqlite/sqlitedatabasebackend.h
@@ -25,6 +25,10 @@
#pragma once
+#ifdef SQLITE_STATIC_LIBRARY
+#include "config.h"
+#endif
+
#include "sqliteglobal.h"
#include <utils/smallstringvector.h>
diff --git a/src/libs/sqlite/sqliteglobal.h b/src/libs/sqlite/sqliteglobal.h
index f8a13e0a972..a2586d671eb 100644
--- a/src/libs/sqlite/sqliteglobal.h
+++ b/src/libs/sqlite/sqliteglobal.h
@@ -29,9 +29,9 @@
#include <QtGlobal>
-#if defined(BUILD_SQLITE_LIBRARY)
+#if defined(SQLITE_LIBRARY)
# define SQLITE_EXPORT Q_DECL_EXPORT
-#elif defined(BUILD_SQLITE_STATIC_LIBRARY)
+#elif defined(SQLITE_STATIC_LIBRARY)
# define SQLITE_EXPORT
#else
# define SQLITE_EXPORT Q_DECL_IMPORT
diff --git a/src/libs/sqlite/sqlitesessionchangeset.h b/src/libs/sqlite/sqlitesessionchangeset.h
index 10c46f64c57..83687470b2f 100644
--- a/src/libs/sqlite/sqlitesessionchangeset.h
+++ b/src/libs/sqlite/sqlitesessionchangeset.h
@@ -25,6 +25,10 @@
#pragma once
+#ifdef SQLITE_STATIC_LIBRARY
+#include "config.h"
+#endif
+
#include "sqliteblob.h"
#include "sqliteglobal.h"
#include "sqlitevalue.h"
diff --git a/src/libs/sqlite/sqlitesessions.h b/src/libs/sqlite/sqlitesessions.h
index 0d1baeec477..0a397868d61 100644
--- a/src/libs/sqlite/sqlitesessions.h
+++ b/src/libs/sqlite/sqlitesessions.h
@@ -25,6 +25,10 @@
#pragma once
+#ifdef SQLITE_STATIC_LIBRARY
+#include "config.h"
+#endif
+
#include "sqlitedatabase.h"
#include "sqlitesessionchangeset.h"
#include "sqlitewritestatement.h"
diff --git a/src/libs/ssh/CMakeLists.txt b/src/libs/ssh/CMakeLists.txt
deleted file mode 100644
index 6f5d1cb7642..00000000000
--- a/src/libs/ssh/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-add_qtc_library(QtcSsh
- DEPENDS Qt5::Core Qt5::Network Qt5::Widgets Utils
- SOURCES
- sftpdefs.cpp sftpdefs.h
- sftpfilesystemmodel.cpp sftpfilesystemmodel.h
- sftpsession.cpp sftpsession.h
- sftptransfer.cpp sftptransfer.h
- ssh.qrc
- ssh_global.h
- sshconnection.cpp sshconnection.h
- sshconnectionmanager.cpp sshconnectionmanager.h
- sshkeycreationdialog.cpp sshkeycreationdialog.h sshkeycreationdialog.ui
- sshlogging.cpp sshlogging_p.h
- sshprocess.cpp sshprocess.h
- sshconnection.cpp sshconnection.h
- sshconnectionmanager.cpp sshconnectionmanager.h
- sshkeycreationdialog.cpp sshkeycreationdialog.h sshkeycreationdialog.ui
- sshlogging.cpp sshlogging_p.h
- sshremoteprocess.cpp sshremoteprocess.h
- sshremoteprocessrunner.cpp sshremoteprocessrunner.h
- sshsettings.cpp sshsettings.h
-)
diff --git a/src/libs/ssh/sftpdefs.cpp b/src/libs/ssh/sftpdefs.cpp
deleted file mode 100644
index 1964e1e1fc2..00000000000
--- a/src/libs/ssh/sftpdefs.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sftpdefs.h"
-
-namespace QSsh { const SftpJobId SftpInvalidJob = 0; }
diff --git a/src/libs/ssh/sftpdefs.h b/src/libs/ssh/sftpdefs.h
deleted file mode 100644
index e3d9be9b974..00000000000
--- a/src/libs/ssh/sftpdefs.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ssh_global.h"
-
-#include <QFile>
-#include <QList>
-#include <QString>
-
-#include <memory>
-
-namespace QSsh {
-
-class SftpTransfer;
-using SftpTransferPtr = std::unique_ptr<SftpTransfer>;
-class SftpSession;
-using SftpSessionPtr = std::unique_ptr<SftpSession>;
-
-enum class FileTransferErrorHandling { Abort, Ignore };
-
-class FileToTransfer
-{
-public:
- FileToTransfer(const QString &source, const QString &target)
- : sourceFile(source), targetFile(target) {}
- QString sourceFile;
- QString targetFile;
-};
-using FilesToTransfer = QList<FileToTransfer>;
-
-namespace Internal { enum class FileTransferType { Upload, Download }; }
-
-typedef quint32 SftpJobId;
-QSSH_EXPORT extern const SftpJobId SftpInvalidJob;
-
-enum SftpOverwriteMode {
- SftpOverwriteExisting, SftpAppendToExisting, SftpSkipExisting
-};
-
-enum SftpFileType { FileTypeRegular, FileTypeDirectory, FileTypeOther, FileTypeUnknown };
-
-class QSSH_EXPORT SftpFileInfo
-{
-public:
- QString name;
- SftpFileType type = FileTypeUnknown;
- quint64 size = 0;
- QFile::Permissions permissions;
-};
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sftpfilesystemmodel.cpp b/src/libs/ssh/sftpfilesystemmodel.cpp
deleted file mode 100644
index 1dedcd3ca47..00000000000
--- a/src/libs/ssh/sftpfilesystemmodel.cpp
+++ /dev/null
@@ -1,384 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sftpfilesystemmodel.h"
-
-#include "sftpsession.h"
-#include "sshconnection.h"
-#include "sshconnectionmanager.h"
-
-#include <utils/qtcassert.h>
-#include <utils/utilsicons.h>
-
-#include <QFileInfo>
-#include <QHash>
-#include <QIcon>
-#include <QList>
-#include <QString>
-
-namespace QSsh {
-namespace Internal {
-namespace {
-
-class SftpDirNode;
-class SftpFileNode
-{
-public:
- SftpFileNode() : parent(nullptr) { }
- virtual ~SftpFileNode() { }
-
- QString path;
- SftpFileInfo fileInfo;
- SftpDirNode *parent;
-};
-
-class SftpDirNode : public SftpFileNode
-{
-public:
- SftpDirNode() : lsState(LsNotYetCalled) { }
- ~SftpDirNode() { qDeleteAll(children); }
-
- enum { LsNotYetCalled, LsRunning, LsFinished } lsState;
- QList<SftpFileNode *> children;
-};
-
-typedef QHash<SftpJobId, SftpDirNode *> DirNodeHash;
-
-SftpFileNode *indexToFileNode(const QModelIndex &index)
-{
- return static_cast<SftpFileNode *>(index.internalPointer());
-}
-
-SftpDirNode *indexToDirNode(const QModelIndex &index)
-{
- SftpFileNode * const fileNode = indexToFileNode(index);
- QTC_CHECK(fileNode);
- return dynamic_cast<SftpDirNode *>(fileNode);
-}
-
-} // anonymous namespace
-
-class SftpFileSystemModelPrivate
-{
-public:
- SshConnection *sshConnection;
- SftpSessionPtr sftpSession;
- QString rootDirectory;
- SftpFileNode *rootNode;
- SftpJobId statJobId;
- DirNodeHash lsOps;
- QList<SftpJobId> externalJobs;
-};
-} // namespace Internal
-
-using namespace Internal;
-
-SftpFileSystemModel::SftpFileSystemModel(QObject *parent)
- : QAbstractItemModel(parent), d(new SftpFileSystemModelPrivate)
-{
- d->sshConnection = nullptr;
- d->rootDirectory = QLatin1Char('/');
- d->rootNode = nullptr;
- d->statJobId = SftpInvalidJob;
-}
-
-SftpFileSystemModel::~SftpFileSystemModel()
-{
- shutDown();
- delete d;
-}
-
-void SftpFileSystemModel::setSshConnection(const SshConnectionParameters &sshParams)
-{
- QTC_ASSERT(!d->sshConnection, return);
- d->sshConnection = SshConnectionManager::acquireConnection(sshParams);
- connect(d->sshConnection, &SshConnection::errorOccurred,
- this, &SftpFileSystemModel::handleSshConnectionFailure);
- if (d->sshConnection->state() == SshConnection::Connected) {
- handleSshConnectionEstablished();
- return;
- }
- connect(d->sshConnection, &SshConnection::connected,
- this, &SftpFileSystemModel::handleSshConnectionEstablished);
- if (d->sshConnection->state() == SshConnection::Unconnected)
- d->sshConnection->connectToHost();
-}
-
-void SftpFileSystemModel::setRootDirectory(const QString &path)
-{
- beginResetModel();
- d->rootDirectory = path;
- delete d->rootNode;
- d->rootNode = nullptr;
- d->lsOps.clear();
- d->statJobId = SftpInvalidJob;
- endResetModel();
- statRootDirectory();
-}
-
-QString SftpFileSystemModel::rootDirectory() const
-{
- return d->rootDirectory;
-}
-
-SftpJobId SftpFileSystemModel::downloadFile(const QModelIndex &index, const QString &targetFilePath)
-{
- QTC_ASSERT(d->rootNode, return SftpInvalidJob);
- const SftpFileNode * const fileNode = indexToFileNode(index);
- QTC_ASSERT(fileNode, return SftpInvalidJob);
- QTC_ASSERT(fileNode->fileInfo.type == FileTypeRegular, return SftpInvalidJob);
- const SftpJobId jobId = d->sftpSession->downloadFile(fileNode->path, targetFilePath);
- if (jobId != SftpInvalidJob)
- d->externalJobs << jobId;
- return jobId;
-}
-
-int SftpFileSystemModel::columnCount(const QModelIndex &parent) const
-{
- Q_UNUSED(parent)
- return 2; // type + name
-}
-
-QVariant SftpFileSystemModel::data(const QModelIndex &index, int role) const
-{
- const SftpFileNode * const node = indexToFileNode(index);
- if (index.column() == 0 && role == Qt::DecorationRole) {
- switch (node->fileInfo.type) {
- case FileTypeRegular:
- case FileTypeOther:
- return Utils::Icons::UNKNOWN_FILE.icon();
- case FileTypeDirectory:
- return Utils::Icons::DIR.icon();
- case FileTypeUnknown:
- return QIcon(":/ssh/images/help.png"); // Shows a question mark.
- }
- }
- if (index.column() == 1) {
- if (role == Qt::DisplayRole)
- return node->fileInfo.name;
- if (role == PathRole)
- return node->path;
- }
- return QVariant();
-}
-
-Qt::ItemFlags SftpFileSystemModel::flags(const QModelIndex &index) const
-{
- if (!index.isValid())
- return Qt::NoItemFlags;
- return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
-}
-
-QVariant SftpFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
- if (orientation != Qt::Horizontal)
- return QVariant();
- if (role != Qt::DisplayRole)
- return QVariant();
- if (section == 0)
- return tr("File Type");
- if (section == 1)
- return tr("File Name");
- return QVariant();
-}
-
-QModelIndex SftpFileSystemModel::index(int row, int column, const QModelIndex &parent) const
-{
- if (row < 0 || row >= rowCount(parent) || column < 0 || column >= columnCount(parent))
- return QModelIndex();
- if (!d->rootNode)
- return QModelIndex();
- if (!parent.isValid())
- return createIndex(row, column, d->rootNode);
- const SftpDirNode * const parentNode = indexToDirNode(parent);
- QTC_ASSERT(parentNode, return QModelIndex());
- QTC_ASSERT(row < parentNode->children.count(), return QModelIndex());
- SftpFileNode * const childNode = parentNode->children.at(row);
- return createIndex(row, column, childNode);
-}
-
-QModelIndex SftpFileSystemModel::parent(const QModelIndex &child) const
-{
- if (!child.isValid()) // Don't assert on this, since the model tester tries it.
- return QModelIndex();
-
- const SftpFileNode * const childNode = indexToFileNode(child);
- QTC_ASSERT(childNode, return QModelIndex());
- if (childNode == d->rootNode)
- return QModelIndex();
- SftpDirNode * const parentNode = childNode->parent;
- if (parentNode == d->rootNode)
- return createIndex(0, 0, d->rootNode);
- const SftpDirNode * const grandParentNode = parentNode->parent;
- QTC_ASSERT(grandParentNode, return QModelIndex());
- return createIndex(grandParentNode->children.indexOf(parentNode), 0, parentNode);
-}
-
-int SftpFileSystemModel::rowCount(const QModelIndex &parent) const
-{
- if (!d->rootNode)
- return 0;
- if (!parent.isValid())
- return 1;
- if (parent.column() != 0)
- return 0;
- SftpDirNode * const dirNode = indexToDirNode(parent);
- if (!dirNode)
- return 0;
- if (dirNode->lsState != SftpDirNode::LsNotYetCalled)
- return dirNode->children.count();
- d->lsOps.insert(d->sftpSession->ls(dirNode->path), dirNode);
- dirNode->lsState = SftpDirNode::LsRunning;
- return 0;
-}
-
-void SftpFileSystemModel::statRootDirectory()
-{
- d->statJobId = d->sftpSession->ls(d->rootDirectory);
-}
-
-void SftpFileSystemModel::shutDown()
-{
- if (d->sftpSession) {
- disconnect(d->sftpSession.get(), nullptr, this, nullptr);
- d->sftpSession->quit();
- d->sftpSession.release()->deleteLater();
- }
- if (d->sshConnection) {
- disconnect(d->sshConnection, nullptr, this, nullptr);
- SshConnectionManager::releaseConnection(d->sshConnection);
- d->sshConnection = nullptr;
- }
- delete d->rootNode;
- d->rootNode = nullptr;
-}
-
-void SftpFileSystemModel::handleSshConnectionFailure()
-{
- emit connectionError(d->sshConnection->errorString());
- beginResetModel();
- shutDown();
- endResetModel();
-}
-
-void SftpFileSystemModel::handleSftpChannelInitialized()
-{
- connect(d->sftpSession.get(), &SftpSession::fileInfoAvailable,
- this, &SftpFileSystemModel::handleFileInfo);
- connect(d->sftpSession.get(), &SftpSession::commandFinished,
- this, &SftpFileSystemModel::handleSftpJobFinished);
- statRootDirectory();
-}
-
-void SftpFileSystemModel::handleSshConnectionEstablished()
-{
- d->sftpSession = d->sshConnection->createSftpSession();
- connect(d->sftpSession.get(), &SftpSession::started,
- this, &SftpFileSystemModel::handleSftpChannelInitialized);
- connect(d->sftpSession.get(), &SftpSession::done,
- this, &SftpFileSystemModel::handleSftpSessionClosed);
- d->sftpSession->start();
-}
-
-void SftpFileSystemModel::handleSftpSessionClosed(const QString &reason)
-{
- emit connectionError(reason);
- beginResetModel();
- shutDown();
- endResetModel();
-}
-
-void SftpFileSystemModel::handleFileInfo(SftpJobId jobId, const QList<SftpFileInfo> &fileInfoList)
-{
- if (jobId == d->statJobId) {
- QTC_ASSERT(!d->rootNode, return);
- beginInsertRows(QModelIndex(), 0, 0);
- d->rootNode = new SftpDirNode;
- d->rootNode->path = d->rootDirectory;
- d->rootNode->fileInfo.type = FileTypeDirectory;
- d->rootNode->fileInfo.name = d->rootDirectory == QLatin1String("/")
- ? d->rootDirectory : QFileInfo(d->rootDirectory).fileName();
- endInsertRows();
- return;
- }
- SftpDirNode * const parentNode = d->lsOps.value(jobId);
- QTC_ASSERT(parentNode, return);
- QList<SftpFileInfo> filteredList;
- foreach (const SftpFileInfo &fi, fileInfoList) {
- if (fi.name != QLatin1String(".") && fi.name != QLatin1String(".."))
- filteredList << fi;
- }
- if (filteredList.isEmpty())
- return;
-
- // In theory beginInsertRows() should suffice, but that fails to have an effect
- // if rowCount() returned 0 earlier.
- emit layoutAboutToBeChanged();
-
- foreach (const SftpFileInfo &fileInfo, filteredList) {
- SftpFileNode *childNode;
- if (fileInfo.type == FileTypeDirectory)
- childNode = new SftpDirNode;
- else
- childNode = new SftpFileNode;
- childNode->path = parentNode->path;
- if (!childNode->path.endsWith(QLatin1Char('/')))
- childNode->path += QLatin1Char('/');
- childNode->path += fileInfo.name;
- childNode->fileInfo = fileInfo;
- childNode->parent = parentNode;
- parentNode->children << childNode;
- }
- emit layoutChanged(); // Should be endInsertRows(), see above.
-}
-
-void SftpFileSystemModel::handleSftpJobFinished(SftpJobId jobId, const QString &errorMessage)
-{
- if (jobId == d->statJobId) {
- d->statJobId = SftpInvalidJob;
- if (!errorMessage.isEmpty())
- emit sftpOperationFailed(tr("Error listing root directory \"%1\": %2")
- .arg(rootDirectory(), errorMessage));
- return;
- }
-
- DirNodeHash::Iterator it = d->lsOps.find(jobId);
- if (it != d->lsOps.end()) {
- QTC_ASSERT(it.value()->lsState == SftpDirNode::LsRunning, return);
- it.value()->lsState = SftpDirNode::LsFinished;
- if (!errorMessage.isEmpty())
- emit sftpOperationFailed(tr("Error listing contents of directory \"%1\": %2")
- .arg(it.value()->path, errorMessage));
- d->lsOps.erase(it);
- return;
- }
-
- const int jobIndex = d->externalJobs.indexOf(jobId);
- QTC_ASSERT(jobIndex != -1, return);
- d->externalJobs.removeAt(jobIndex);
- emit sftpOperationFinished(jobId, errorMessage);
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sftpfilesystemmodel.h b/src/libs/ssh/sftpfilesystemmodel.h
deleted file mode 100644
index ea16568d933..00000000000
--- a/src/libs/ssh/sftpfilesystemmodel.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sftpdefs.h"
-
-#include "ssh_global.h"
-
-#include <QAbstractItemModel>
-
-namespace QSsh {
-class SshConnectionParameters;
-
-namespace Internal { class SftpFileSystemModelPrivate; }
-
-// Very simple read-only model. Symbolic links are not followed.
-class QSSH_EXPORT SftpFileSystemModel : public QAbstractItemModel
-{
- Q_OBJECT
-public:
- explicit SftpFileSystemModel(QObject *parent = nullptr);
- ~SftpFileSystemModel();
-
- /*
- * Once this is called, an SFTP connection is established and the model is populated.
- * The effect of additional calls is undefined.
- */
- void setSshConnection(const SshConnectionParameters &sshParams);
-
- void setRootDirectory(const QString &path); // Default is "/".
- QString rootDirectory() const;
-
- SftpJobId downloadFile(const QModelIndex &index, const QString &targetFilePath);
-
- // Use this to get the full path of a file or directory.
- static const int PathRole = Qt::UserRole;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-
-signals:
- /*
- * E.g. "Permission denied". Note that this can happen without direct user intervention,
- * due to e.g. the view calling rowCount() on a non-readable directory. This signal should
- * therefore not result in a message box or similar, since it might occur very often.
- */
- void sftpOperationFailed(const QString &errorMessage);
-
- /*
- * This error is not recoverable. The model will not have any content after
- * the signal has been emitted.
- */
- void connectionError(const QString &errorMessage);
-
- // Success <=> error.isEmpty().
- void sftpOperationFinished(QSsh::SftpJobId, const QString &error);
-
-private:
- void handleSshConnectionEstablished();
- void handleSshConnectionFailure();
- void handleSftpChannelInitialized();
- void handleSftpSessionClosed(const QString &reason);
- void handleFileInfo(QSsh::SftpJobId jobId, const QList<QSsh::SftpFileInfo> &fileInfoList);
- void handleSftpJobFinished(QSsh::SftpJobId jobId, const QString &errorMessage);
-
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- Qt::ItemFlags flags(const QModelIndex &index) const override;
- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
- QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
- QModelIndex parent(const QModelIndex &child) const override;
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-
- void statRootDirectory();
- void shutDown();
-
- Internal::SftpFileSystemModelPrivate * const d;
-};
-
-} // namespace QSsh;
diff --git a/src/libs/ssh/sftpsession.cpp b/src/libs/ssh/sftpsession.cpp
deleted file mode 100644
index 8ecdfb374f7..00000000000
--- a/src/libs/ssh/sftpsession.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sftpsession.h"
-
-#include "sshlogging_p.h"
-#include "sshprocess.h"
-#include "sshsettings.h"
-
-#include <utils/fileutils.h>
-#include <utils/commandline.h>
-#include <utils/qtcassert.h>
-
-#include <QByteArrayList>
-#include <QFileInfo>
-#include <QQueue>
-#include <QTimer>
-
-using namespace Utils;
-
-namespace QSsh {
-using namespace Internal;
-
-enum class CommandType { Ls, Mkdir, Rmdir, Rm, Rename, Ln, Put, Get, None };
-
-struct Command
-{
- Command() = default;
- Command(CommandType t, const QStringList &p, SftpJobId id) : type(t), paths(p), jobId(id) {}
- bool isValid() const { return type != CommandType::None; }
-
- CommandType type = CommandType::None;
- QStringList paths;
- SftpJobId jobId = SftpInvalidJob;
-};
-
-struct SftpSession::SftpSessionPrivate
-{
- SshProcess sftpProc = {ProcessMode::Writer};
- QStringList connectionArgs;
- QByteArray output;
- QQueue<Command> pendingCommands;
- Command activeCommand;
- SftpJobId nextJobId = 1;
- SftpSession::State state = SftpSession::State::Inactive;
-
- QByteArray commandString(CommandType command) const
- {
- switch (command) {
- case CommandType::Ls: return "ls -n";
- case CommandType::Mkdir: return "mkdir";
- case CommandType::Rmdir: return "rmdir";
- case CommandType::Rm: return "rm";
- case CommandType::Rename: return "rename";
- case CommandType::Ln: return "ln -s";
- case CommandType::Put: return "put";
- case CommandType::Get: return "get";
- default: QTC_ASSERT(false, return QByteArray());
- }
- }
-
- SftpJobId queueCommand(CommandType command, const QStringList &paths)
- {
- qCDebug(sshLog) << "queueing command" << int(command) << paths;
-
- const SftpJobId jobId = nextJobId++;
- pendingCommands.enqueue(Command(command, paths, jobId));
- runNextCommand();
- return jobId;
- }
-
- void runNextCommand()
- {
- if (activeCommand.isValid())
- return;
- if (pendingCommands.empty())
- return;
- QTC_ASSERT(sftpProc.isRunning(), return);
- activeCommand = pendingCommands.dequeue();
-
- // The second newline forces the prompt to appear after the command has finished.
- sftpProc.write(commandString(activeCommand.type) + ' '
- + ProcessArgs::createUnixArgs(activeCommand.paths)
- .toString().toLocal8Bit() + "\n\n");
- }
-};
-
-static QByteArray prompt() { return "sftp> "; }
-
-SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionPrivate)
-{
- d->connectionArgs = connectionArgs;
- connect(&d->sftpProc, &QtcProcess::started, [this] {
- qCDebug(sshLog) << "sftp process started";
- d->sftpProc.write("\n"); // Force initial prompt.
- });
- connect(&d->sftpProc, &QtcProcess::errorOccurred, [this](QProcess::ProcessError error) {
- if (error == QProcess::FailedToStart) {
- d->state = State::Inactive;
- emit done(tr("sftp failed to start: %1").arg(d->sftpProc.errorString()));
- }
- });
- connect(&d->sftpProc, &QtcProcess::finished, [this] {
- qCDebug(sshLog) << "sftp process finished";
-
- d->state = State::Inactive;
- if (d->sftpProc.exitStatus() != QProcess::NormalExit) {
- emit done(tr("sftp crashed."));
- return;
- }
- if (d->sftpProc.exitCode() != 0) {
- emit done(QString::fromLocal8Bit(d->sftpProc.readAllStandardError()));
- return;
- }
- emit done(QString());
- });
- connect(&d->sftpProc, &QtcProcess::readyReadStandardOutput, this, &SftpSession::handleStdout);
-}
-
-void SftpSession::doStart()
-{
- if (d->state != State::Starting)
- return;
- const FilePath sftpBinary = SshSettings::sftpFilePath();
- if (!sftpBinary.exists()) {
- d->state = State::Inactive;
- emit done(tr("Cannot establish SFTP session: sftp binary \"%1\" does not exist.")
- .arg(sftpBinary.toUserOutput()));
- return;
- }
- d->activeCommand = Command();
- const QStringList args = QStringList{"-q"} << d->connectionArgs;
- qCDebug(sshLog) << "starting sftp session:" << sftpBinary.toUserOutput() << args;
- d->sftpProc.setCommand(CommandLine(sftpBinary, args));
- d->sftpProc.start();
-}
-
-void SftpSession::handleStdout()
-{
- if (state() == State::Running && !d->activeCommand.isValid()) {
- qCWarning(sshLog) << "ignoring unexpected sftp output:"
- << d->sftpProc.readAllStandardOutput();
- return;
- }
-
- d->output += d->sftpProc.readAllStandardOutput();
- qCDebug(sshLog) << "accumulated sftp output:" << d->output;
- const int firstPromptOffset = d->output.indexOf(prompt());
- if (firstPromptOffset == -1)
- return;
- if (state() == State::Starting) {
- d->state = State::Running;
- d->output.clear();
- d->sftpProc.readAllStandardError(); // The "connected" message goes to stderr.
- emit started();
- return;
- }
- const int secondPromptOffset = d->output.indexOf(prompt(), firstPromptOffset + prompt().size());
- if (secondPromptOffset == -1)
- return;
- const Command command = d->activeCommand;
- d->activeCommand = Command();
- const QByteArray commandOutput = d->output.mid(
- firstPromptOffset + prompt().size(),
- secondPromptOffset - firstPromptOffset - prompt().size());
- d->output = d->output.mid(secondPromptOffset + prompt().size());
- if (command.type == CommandType::Ls)
- handleLsOutput(command.jobId, commandOutput);
- const QByteArray stdErr = d->sftpProc.readAllStandardError();
- emit commandFinished(command.jobId, QString::fromLocal8Bit(stdErr));
- d->runNextCommand();
-}
-
-static SftpFileType typeFromLsOutput(char c)
-{
- if (c == '-')
- return FileTypeRegular;
- if (c == 'd')
- return FileTypeDirectory;
- return FileTypeOther;
-}
-
-static QFile::Permissions permissionsFromLsOutput(const QByteArray &output)
-{
- QFile::Permissions perms;
- if (output.at(0) == 'r')
- perms |= QFile::ReadOwner;
- if (output.at(1) == 'w')
- perms |= QFile::WriteOwner;
- if (output.at(2) == 'x')
- perms |= QFile::ExeOwner;
- if (output.at(3) == 'r')
- perms |= QFile::ReadGroup;
- if (output.at(4) == 'w')
- perms |= QFile::WriteGroup;
- if (output.at(5) == 'x')
- perms |= QFile::ExeGroup;
- if (output.at(6) == 'r')
- perms |= QFile::ReadOther;
- if (output.at(7) == 'w')
- perms |= QFile::WriteOther;
- if (output.at(8) == 'x')
- perms |= QFile::ExeOther;
- return perms;
-}
-
-void SftpSession::handleLsOutput(SftpJobId jobId, const QByteArray &output)
-{
- QList<SftpFileInfo> allFileInfo;
- for (const QByteArray &line : output.split('\n')) {
- if (line.startsWith("ls") || line.isEmpty())
- continue;
- const QByteArrayList components = line.simplified().split(' ');
- if (components.size() < 9) {
- qCWarning(sshLog) << "Don't know how to parse sftp ls output:" << line;
- continue;
- }
- const QByteArray typeAndPermissions = components.first();
- if (typeAndPermissions.size() != 10) {
- qCWarning(sshLog) << "Don't know how to parse sftp ls output:" << line;
- continue;
- }
- SftpFileInfo fileInfo;
- fileInfo.type = typeFromLsOutput(typeAndPermissions.at(0));
- fileInfo.permissions = permissionsFromLsOutput(QByteArray::fromRawData(
- typeAndPermissions.constData() + 1,
- typeAndPermissions.size() - 1));
- bool isNumber;
- fileInfo.size = components.at(4).toULongLong(&isNumber);
- if (!isNumber) {
- qCWarning(sshLog) << "Don't know how to parse sftp ls output:" << line;
- continue;
- }
- // TODO: This will not work for file names with weird whitespace combinations
- fileInfo.name = QFileInfo(QString::fromUtf8(components.mid(8).join(' '))).fileName();
- allFileInfo << fileInfo;
- }
- emit fileInfoAvailable(jobId, allFileInfo);
-}
-
-SftpSession::~SftpSession()
-{
- quit();
- delete d;
-}
-
-void SftpSession::start()
-{
- QTC_ASSERT(d->state == State::Inactive, return);
- d->state = State::Starting;
- QTimer::singleShot(0, this, &SftpSession::doStart);
-}
-
-void SftpSession::quit()
-{
- qCDebug(sshLog) << "quitting sftp session, current state is" << int(state());
-
- switch (state()) {
- case State::Starting:
- case State::Closing:
- d->state = State::Closing;
- d->sftpProc.kill();
- break;
- case State::Running:
- d->state = State::Closing;
- d->sftpProc.write("bye\n");
- break;
- case State::Inactive:
- break;
- }
-}
-
-SftpJobId SftpSession::ls(const QString &path)
-{
- return d->queueCommand(CommandType::Ls, QStringList(path));
-}
-
-SftpJobId SftpSession::createDirectory(const QString &path)
-{
- return d->queueCommand(CommandType::Mkdir, QStringList(path));
-}
-
-SftpJobId SftpSession::removeDirectory(const QString &path)
-{
- return d->queueCommand(CommandType::Rmdir, QStringList(path));
-}
-
-SftpJobId SftpSession::removeFile(const QString &path)
-{
- return d->queueCommand(CommandType::Rm, QStringList(path));
-}
-
-SftpJobId SftpSession::rename(const QString &oldPath, const QString &newPath)
-{
- return d->queueCommand(CommandType::Rename, QStringList{oldPath, newPath});
-}
-
-SftpJobId SftpSession::createSoftLink(const QString &filePath, const QString &target)
-{
- return d->queueCommand(CommandType::Ln, QStringList{filePath, target});
-}
-
-SftpJobId SftpSession::uploadFile(const QString &localFilePath, const QString &remoteFilePath)
-{
- return d->queueCommand(CommandType::Put, QStringList{localFilePath, remoteFilePath});
-}
-
-SftpJobId SftpSession::downloadFile(const QString &remoteFilePath, const QString &localFilePath)
-{
- return d->queueCommand(CommandType::Get, QStringList{remoteFilePath, localFilePath});
-}
-
-SftpSession::State SftpSession::state() const
-{
- return d->state;
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sftpsession.h b/src/libs/ssh/sftpsession.h
deleted file mode 100644
index 89d0eec145d..00000000000
--- a/src/libs/ssh/sftpsession.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sftpdefs.h"
-#include "ssh_global.h"
-
-#include <QObject>
-
-namespace QSsh {
-class SshConnection;
-
-class QSSH_EXPORT SftpSession : public QObject
-{
- friend class SshConnection;
- Q_OBJECT
-public:
- ~SftpSession() override;
- void start();
- void quit();
-
- SftpJobId ls(const QString &path);
- SftpJobId createDirectory(const QString &path);
- SftpJobId removeDirectory(const QString &path);
- SftpJobId removeFile(const QString &path);
- SftpJobId rename(const QString &oldPath, const QString &newPath);
- SftpJobId createSoftLink(const QString &filePath, const QString &target);
- SftpJobId uploadFile(const QString &localFilePath, const QString &remoteFilePath);
- SftpJobId downloadFile(const QString &remoteFilePath, const QString &localFilePath);
-
- enum class State { Inactive, Starting, Running, Closing };
- State state() const;
-
-signals:
- void started();
- void done(const QString &error);
- void commandFinished(SftpJobId job, const QString &error);
- void fileInfoAvailable(SftpJobId job, const QList<SftpFileInfo> &fileInfoList);
-
-private:
- SftpSession(const QStringList &connectionArgs);
- void doStart();
- void handleStdout();
- void handleLsOutput(SftpJobId jobId, const QByteArray &output);
-
- struct SftpSessionPrivate;
- SftpSessionPrivate * const d;
-};
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sftptransfer.cpp b/src/libs/ssh/sftptransfer.cpp
deleted file mode 100644
index 26d4306f5c7..00000000000
--- a/src/libs/ssh/sftptransfer.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sftptransfer.h"
-
-#include "sshlogging_p.h"
-#include "sshprocess.h"
-#include "sshsettings.h"
-
-#include <QDir>
-#include <QFileInfo>
-#include <QStringList>
-#include <QTemporaryFile>
-#include <QTimer>
-
-#include <utils/algorithm.h>
-#include <utils/commandline.h>
-
-using namespace Utils;
-
-namespace QSsh {
-
-struct SftpTransfer::SftpTransferPrivate
-{
- SshProcess sftpProc;
- FilesToTransfer files;
- Internal::FileTransferType transferType;
- FileTransferErrorHandling errorHandlingMode;
- QStringList connectionArgs;
- QString batchFilePath;
-
- QStringList dirsToCreate() const
- {
- QStringList dirs;
- for (const FileToTransfer &f : qAsConst(files)) {
- QString parentDir = QFileInfo(f.targetFile).path();
- while (true) {
- if (dirs.contains(parentDir) || !parentDir.startsWith('/'))
- break;
- dirs << parentDir;
- parentDir = QFileInfo(parentDir).path();
- }
- }
- sort(dirs, [](const QString &d1, const QString &d2) {
- if (d1 == "/" && d2 != "/")
- return true;
- return d1.count('/') < d2.count('/');
- });
- return dirs;
- }
- QByteArray transferCommand(bool link) const
- {
- QByteArray command;
- switch (transferType) {
- case Internal::FileTransferType::Upload:
- command = link ? "ln -s" : "put";
- break;
- case Internal::FileTransferType::Download:
- command = "get";
- break;
- }
- if (errorHandlingMode == FileTransferErrorHandling::Ignore)
- command.prepend('-');
- return command;
- }
-};
-
-SftpTransfer::~SftpTransfer()
-{
- if (!d->batchFilePath.isEmpty() && !QFile::remove(d->batchFilePath))
- qCWarning(Internal::sshLog) << "failed to remove batch file" << d->batchFilePath;
- delete d;
-}
-
-void SftpTransfer::start()
-{
- QTimer::singleShot(0, this, &SftpTransfer::doStart);
-}
-
-void SftpTransfer::stop()
-{
- d->sftpProc.terminate();
-}
-
-SftpTransfer::SftpTransfer(const FilesToTransfer &files, Internal::FileTransferType type,
- FileTransferErrorHandling errorHandlingMode,
- const QStringList &connectionArgs)
- : d(new SftpTransferPrivate)
-{
- d->files = files;
- d->transferType = type;
- d->errorHandlingMode = errorHandlingMode;
- d->connectionArgs = connectionArgs;
- connect(&d->sftpProc, &QtcProcess::errorOccurred, [this](QProcess::ProcessError error) {
- if (error == QProcess::FailedToStart)
- emitError(tr("sftp failed to start: %1").arg(d->sftpProc.errorString()));
- });
- connect(&d->sftpProc, &QtcProcess::finished, [this] {
- if (d->sftpProc.exitStatus() != QProcess::NormalExit) {
- emitError(tr("sftp crashed."));
- return;
- }
- if (d->sftpProc.exitCode() != 0) {
- emitError(QString::fromLocal8Bit(d->sftpProc.readAllStandardError()));
- return;
- }
- emit done(QString());
- });
- connect(&d->sftpProc, &QtcProcess::readyReadStandardOutput, [this] {
- emit progress(QString::fromLocal8Bit(d->sftpProc.readAllStandardOutput()));
- });
-}
-
-void SftpTransfer::doStart()
-{
- const FilePath sftpBinary = SshSettings::sftpFilePath();
- if (!sftpBinary.exists()) {
- emitError(tr("sftp binary \"%1\" does not exist.").arg(sftpBinary.toUserOutput()));
- return;
- }
- QTemporaryFile batchFile;
- batchFile.setAutoRemove(false);
- if (!batchFile.isOpen() && !batchFile.open()) {
- emitError(tr("Could not create temporary file: %1").arg(batchFile.errorString()));
- return;
- }
- d->batchFilePath = batchFile.fileName();
- batchFile.resize(0);
- for (const QString &dir : d->dirsToCreate()) {
- switch (d->transferType) {
- case Internal::FileTransferType::Upload:
- batchFile.write("-mkdir " + ProcessArgs::quoteArgUnix(dir).toLocal8Bit() + '\n');
- break;
- case Internal::FileTransferType::Download:
- if (!QDir::root().mkpath(dir)) {
- emitError(tr("Failed to create local directory \"%1\".")
- .arg(QDir::toNativeSeparators(dir)));
- return;
- }
- break;
- }
- }
- for (const FileToTransfer &f : qAsConst(d->files)) {
- QString sourceFileOrLinkTarget = f.sourceFile;
- bool link = false;
- if (d->transferType == Internal::FileTransferType::Upload) {
- QFileInfo fi(f.sourceFile);
- if (fi.isSymLink()) {
- link = true;
- batchFile.write("-rm " + ProcessArgs::quoteArgUnix(f.targetFile).toLocal8Bit()
- + '\n');
- sourceFileOrLinkTarget = fi.dir().relativeFilePath(fi.symLinkTarget()); // see QTBUG-5817.
- }
- }
- batchFile.write(d->transferCommand(link) + ' '
- + ProcessArgs::quoteArgUnix(sourceFileOrLinkTarget).toLocal8Bit() + ' '
- + ProcessArgs::quoteArgUnix(f.targetFile).toLocal8Bit() + '\n');
- }
- d->sftpProc.setStandardInputFile(batchFile.fileName());
- d->sftpProc.setCommand(CommandLine(sftpBinary, d->connectionArgs));
- d->sftpProc.start();
- emit started();
-}
-
-void SftpTransfer::emitError(const QString &details)
-{
- emit done(tr("File transfer failed: %1").arg(details));
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sftptransfer.h b/src/libs/ssh/sftptransfer.h
deleted file mode 100644
index 4c1c9cb6364..00000000000
--- a/src/libs/ssh/sftptransfer.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sftpdefs.h"
-#include "ssh_global.h"
-
-#include <QObject>
-
-namespace QSsh {
-class SshConnection;
-
-class QSSH_EXPORT SftpTransfer : public QObject
-{
- friend class SshConnection;
- Q_OBJECT
-public:
- ~SftpTransfer();
-
- void start();
- void stop();
-
-signals:
- void started();
- void done(const QString &error);
- void progress(const QString &output);
-
-private:
- SftpTransfer(const FilesToTransfer &files, Internal::FileTransferType type,
- FileTransferErrorHandling errorHandlingMode,
- const QStringList &connectionArgs);
- void doStart();
- void emitError(const QString &details);
-
- struct SftpTransferPrivate;
- SftpTransferPrivate * const d;
-};
-
-} // namespace QSsh
diff --git a/src/libs/ssh/ssh.qbs b/src/libs/ssh/ssh.qbs
deleted file mode 100644
index cd306d0c4a3..00000000000
--- a/src/libs/ssh/ssh.qbs
+++ /dev/null
@@ -1,50 +0,0 @@
-import qbs 1.0
-
-Project {
- name: "QtcSsh"
-
- QtcLibrary {
- cpp.defines: {
- var defines = base;
- defines.push("QTCSSH_LIBRARY");
- if (project.withAutotests && !defines.contains("WITH_TESTS"))
- defines.push("WITH_TESTS");
- return defines;
- }
- cpp.enableExceptions: true
-
- Depends { name: "Qt"; submodules: ["widgets", "network" ] }
- Depends { name: "Utils" }
-
- files: [
- "sftpdefs.cpp",
- "sftpdefs.h",
- "sftpfilesystemmodel.cpp",
- "sftpfilesystemmodel.h",
- "sftpsession.cpp",
- "sftpsession.h",
- "sftptransfer.cpp",
- "sftptransfer.h",
- "ssh.qrc",
- "sshconnection.h",
- "sshconnection.cpp",
- "sshconnectionmanager.cpp",
- "sshconnectionmanager.h",
- "sshkeycreationdialog.cpp",
- "sshkeycreationdialog.h",
- "sshkeycreationdialog.ui",
- "sshlogging.cpp",
- "sshlogging_p.h",
- "sshprocess.cpp",
- "sshprocess.h",
- "sshremoteprocess.cpp",
- "sshremoteprocess.h",
- "sshremoteprocessrunner.cpp",
- "sshremoteprocessrunner.h",
- "sshsettings.cpp",
- "sshsettings.h",
- ]
-
- Export { Depends { name: "Qt.network" } }
- }
-}
diff --git a/src/libs/ssh/ssh.qrc b/src/libs/ssh/ssh.qrc
deleted file mode 100644
index 9801217093e..00000000000
--- a/src/libs/ssh/ssh.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/ssh">
- <file>images/help.png</file>
- </qresource>
-</RCC>
diff --git a/src/libs/ssh/ssh_global.h b/src/libs/ssh/ssh_global.h
deleted file mode 100644
index 437fb67f148..00000000000
--- a/src/libs/ssh/ssh_global.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QtGlobal>
-
-#if defined(QTCSSH_LIBRARY)
-# define QSSH_EXPORT Q_DECL_EXPORT
-#else
-# define QSSH_EXPORT Q_DECL_IMPORT
-#endif
-
-#ifdef WITH_TESTS
-# define QSSH_AUTOTEST_EXPORT QSSH_EXPORT
-#else
-# define QSSH_AUTOTEST_EXPORT
-#endif
diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp
deleted file mode 100644
index 0e1e62cad1e..00000000000
--- a/src/libs/ssh/sshconnection.cpp
+++ /dev/null
@@ -1,498 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshconnection.h"
-
-#include "sftpsession.h"
-#include "sftptransfer.h"
-#include "sshlogging_p.h"
-#include "sshprocess.h"
-#include "sshremoteprocess.h"
-#include "sshsettings.h"
-
-#include <utils/fileutils.h>
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-
-#include <QByteArrayList>
-#include <QTemporaryDir>
-#include <QTimer>
-
-#include <memory>
-
-/*!
- \class QSsh::SshConnection
-
- \brief The SshConnection class provides an SSH connection via an OpenSSH client
- running in master mode.
-
- It operates asynchronously (non-blocking) and is not thread-safe.
-
- If connection sharing is turned off, the class operates as a simple factory
- for processes etc and "connecting" always succeeds. The actual connection
- is then established later, e.g. when starting the remote process.
-
-*/
-
-namespace QSsh {
-using namespace Internal;
-using namespace Utils;
-
-SshConnectionParameters::SshConnectionParameters()
-{
- url.setPort(0);
-}
-
-QStringList SshConnectionParameters::connectionOptions(const FilePath &binary) const
-{
- QString hostKeyCheckingString;
- switch (hostKeyCheckingMode) {
- case SshHostKeyCheckingNone:
- case SshHostKeyCheckingAllowNoMatch:
- // There is "accept-new" as well, but only since 7.6.
- hostKeyCheckingString = "no";
- break;
- case SshHostKeyCheckingStrict:
- hostKeyCheckingString = "yes";
- break;
- }
-
- QStringList args{"-o", "StrictHostKeyChecking=" + hostKeyCheckingString,
- "-o", "Port=" + QString::number(port())};
-
- if (!userName().isEmpty())
- args.append({"-o", "User=" + userName()});
-
- const bool keyOnly = authenticationType ==
- SshConnectionParameters::AuthenticationTypeSpecificKey;
- if (keyOnly) {
- args << "-o" << "IdentitiesOnly=yes";
- args << "-i" << privateKeyFile.path();
- }
- if (keyOnly || SshSettings::askpassFilePath().isEmpty())
- args << "-o" << "BatchMode=yes";
-
- bool useTimeout = timeout != 0;
- if (useTimeout && HostOsInfo::isWindowsHost()
- && binary.toString().toLower().contains("/system32/")) {
- useTimeout = false;
- }
- if (useTimeout)
- args << "-o" << ("ConnectTimeout=" + QString::number(timeout));
-
- return args;
-}
-
-static inline bool equals(const SshConnectionParameters &p1, const SshConnectionParameters &p2)
-{
- return p1.url == p2.url
- && p1.authenticationType == p2.authenticationType
- && p1.privateKeyFile == p2.privateKeyFile
- && p1.hostKeyCheckingMode == p2.hostKeyCheckingMode
- && p1.x11DisplayName == p2.x11DisplayName
- && p1.timeout == p2.timeout;
-}
-
-bool operator==(const SshConnectionParameters &p1, const SshConnectionParameters &p2)
-{
- return equals(p1, p2);
-}
-
-bool operator!=(const SshConnectionParameters &p1, const SshConnectionParameters &p2)
-{
- return !equals(p1, p2);
-}
-
-struct SshConnection::SshConnectionPrivate
-{
- SshConnectionPrivate(const SshConnectionParameters &sshParameters)
- : connParams(sshParameters) {}
-
- QString fullProcessError()
- {
- QString error;
- if (masterProcess.exitStatus() != QProcess::NormalExit)
- error = masterProcess.errorString();
- const QByteArray stdErr = masterProcess.readAllStandardError();
- if (!stdErr.isEmpty()) {
- if (!error.isEmpty())
- error.append('\n');
- error.append(QString::fromLocal8Bit(stdErr));
- }
- return error;
- }
-
- QString socketFilePath() const
- {
- QTC_ASSERT(masterSocketDir, return QString());
- return masterSocketDir->path() + "/cs";
- }
-
- QStringList connectionOptions(const FilePath &binary) const
- {
- QStringList options = connParams.connectionOptions(binary);
- if (sharingEnabled)
- options << "-o" << ("ControlPath=" + socketFilePath());
- return options;
- }
-
- QStringList connectionArgs(const FilePath &binary) const
- {
- return connectionOptions(binary) << connParams.host();
- }
-
- const SshConnectionParameters connParams;
- SshConnectionInfo connInfo;
- SshProcess masterProcess;
- QString errorString;
- std::unique_ptr<QTemporaryDir> masterSocketDir;
- State state = Unconnected;
- const bool sharingEnabled = SshSettings::connectionSharingEnabled();
-};
-
-
-SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject *parent)
- : QObject(parent), d(new SshConnectionPrivate(serverInfo))
-{
- qRegisterMetaType<QSsh::SftpFileInfo>("QSsh::SftpFileInfo");
- qRegisterMetaType<QList <QSsh::SftpFileInfo> >("QList<QSsh::SftpFileInfo>");
- connect(&d->masterProcess, &QtcProcess::readyReadStandardOutput, [this] {
- const QByteArray reply = d->masterProcess.readAllStandardOutput();
- if (reply == "\n")
- emitConnected();
- });
- connect(&d->masterProcess, &QtcProcess::errorOccurred, [this] (QProcess::ProcessError error) {
- switch (error) {
- case QProcess::FailedToStart:
- emitError(tr("Cannot establish SSH connection: Control process failed to start: %1")
- .arg(d->fullProcessError()));
- break;
- case QProcess::Crashed: // Handled by finished() handler.
- case QProcess::Timedout:
- case QProcess::ReadError:
- case QProcess::WriteError:
- case QProcess::UnknownError:
- break; // Cannot happen.
- }
- });
- connect(&d->masterProcess, &QtcProcess::finished, [this] {
- if (d->state == Disconnecting) {
- emitDisconnected();
- return;
- }
- const QString procError = d->fullProcessError();
- QString errorMsg = tr("SSH connection failure.");
- if (!procError.isEmpty())
- errorMsg.append('\n').append(procError);
- emitError(errorMsg);
- });
- if (!d->connParams.x11DisplayName.isEmpty()) {
- Environment env = d->masterProcess.environment();
- env.set("DISPLAY", d->connParams.x11DisplayName);
- d->masterProcess.setEnvironment(env);
- }
-}
-
-void SshConnection::connectToHost()
-{
- d->state = Connecting;
- QTimer::singleShot(0, this, &SshConnection::doConnectToHost);
-}
-
-void SshConnection::disconnectFromHost()
-{
- switch (d->state) {
- case Connecting:
- case Connected:
- if (!d->sharingEnabled) {
- QTimer::singleShot(0, this, &SshConnection::emitDisconnected);
- return;
- }
- d->state = Disconnecting;
- if (HostOsInfo::isWindowsHost())
- d->masterProcess.kill();
- else
- d->masterProcess.terminate();
- break;
- case Unconnected:
- case Disconnecting:
- break;
- }
-}
-
-SshConnection::State SshConnection::state() const
-{
- return d->state;
-}
-
-QString SshConnection::errorString() const
-{
- return d->errorString;
-}
-
-SshConnectionParameters SshConnection::connectionParameters() const
-{
- return d->connParams;
-}
-
-SshConnectionInfo SshConnection::connectionInfo() const
-{
- QTC_ASSERT(state() == Connected, return SshConnectionInfo());
- if (d->connInfo.isValid())
- return d->connInfo;
- QtcProcess p;
- const FilePath sshFilePath = SshSettings::sshFilePath();
- p.setCommand({sshFilePath, d->connectionArgs(sshFilePath) << "echo" << "-n" << "$SSH_CLIENT"});
- p.start();
- if (!p.waitForStarted() || !p.waitForFinished()) {
- qCWarning(Internal::sshLog) << "failed to retrieve connection info:" << p.errorString();
- return SshConnectionInfo();
- }
- const QByteArrayList data = p.readAllStandardOutput().split(' ');
- if (data.size() != 3) {
- qCWarning(Internal::sshLog) << "failed to retrieve connection info: unexpected output";
- return SshConnectionInfo();
- }
- d->connInfo.localPort = data.at(1).toInt();
- if (d->connInfo.localPort == 0) {
- qCWarning(Internal::sshLog) << "failed to retrieve connection info: unexpected output";
- return SshConnectionInfo();
- }
- if (!d->connInfo.localAddress.setAddress(QString::fromLatin1(data.first()))) {
- qCWarning(Internal::sshLog) << "failed to retrieve connection info: unexpected output";
- return SshConnectionInfo();
- }
- d->connInfo.peerPort = d->connParams.port();
- d->connInfo.peerAddress.setAddress(d->connParams.host());
- return d->connInfo;
-}
-
-QStringList SshConnection::connectionOptions(const FilePath &binary) const
-{
- return d->connectionOptions(binary);
-}
-
-bool SshConnection::sharingEnabled() const
-{
- return d->sharingEnabled;
-}
-
-SshConnection::~SshConnection()
-{
- disconnect();
- disconnectFromHost();
- delete d;
-}
-
-SshRemoteProcessPtr SshConnection::createRemoteProcess(const QString &command, ProcessMode processMode)
-{
- QTC_ASSERT(state() == Connected, return SshRemoteProcessPtr());
- return SshRemoteProcessPtr(new SshRemoteProcess(command,
- d->connectionArgs(SshSettings::sshFilePath()),
- processMode));
-}
-
-SshRemoteProcessPtr SshConnection::createRemoteShell(ProcessMode processMode)
-{
- return createRemoteProcess({}, processMode);
-}
-
-SftpTransferPtr SshConnection::createUpload(const FilesToTransfer &files,
- FileTransferErrorHandling errorHandlingMode)
-{
- return setupTransfer(files, Internal::FileTransferType::Upload, errorHandlingMode);
-}
-
-SftpTransferPtr SshConnection::createDownload(const FilesToTransfer &files,
- FileTransferErrorHandling errorHandlingMode)
-{
- return setupTransfer(files, Internal::FileTransferType::Download, errorHandlingMode);
-}
-
-SftpSessionPtr SshConnection::createSftpSession()
-{
- QTC_ASSERT(state() == Connected, return SftpSessionPtr());
- return SftpSessionPtr(new SftpSession(d->connectionArgs(SshSettings::sftpFilePath())));
-}
-
-void SshConnection::doConnectToHost()
-{
- if (d->state != Connecting)
- return;
- const FilePath sshBinary = SshSettings::sshFilePath();
- if (!sshBinary.exists()) {
- emitError(tr("Cannot establish SSH connection: ssh binary \"%1\" does not exist.")
- .arg(sshBinary.toUserOutput()));
- return;
- }
- if (!d->sharingEnabled) {
- emitConnected();
- return;
- }
- d->masterSocketDir.reset(new QTemporaryDir);
- if (!d->masterSocketDir->isValid()) {
- emitError(tr("Cannot establish SSH connection: Failed to create temporary "
- "directory for control socket: %1")
- .arg(d->masterSocketDir->errorString()));
- return;
- }
- QStringList args = QStringList{"-M", "-N", "-o", "ControlPersist=no",
- "-o", "PermitLocalCommand=yes", // Enable local command
- "-o", "LocalCommand=echo"} // Local command is executed after successfully
- // connecting to the server. "echo" will print "\n"
- // on the process output if everything went fine.
- << d->connectionArgs(sshBinary);
- if (!d->connParams.x11DisplayName.isEmpty())
- args.prepend("-X");
- qCDebug(sshLog) << "establishing connection:" << sshBinary.toUserOutput() << args;
- d->masterProcess.setCommand(CommandLine(sshBinary, args));
- d->masterProcess.start();
-}
-
-void SshConnection::emitError(const QString &reason)
-{
- const State oldState = d->state;
- d->state = Unconnected;
- d->errorString = reason;
- emit errorOccurred();
- if (oldState == Connected)
- emitDisconnected();
-}
-
-void SshConnection::emitConnected()
-{
- d->state = Connected;
- emit connected();
-}
-
-void SshConnection::emitDisconnected()
-{
- d->state = Unconnected;
- emit disconnected();
-}
-
-SftpTransferPtr SshConnection::setupTransfer(
- const FilesToTransfer &files, Internal::FileTransferType type,
- FileTransferErrorHandling errorHandlingMode)
-{
- QTC_ASSERT(state() == Connected, return SftpTransferPtr());
- return SftpTransferPtr(new SftpTransfer(files, type, errorHandlingMode,
- d->connectionArgs(SshSettings::sftpFilePath())));
-}
-
-#ifdef WITH_TESTS
-namespace SshTest {
-const QString getHostFromEnvironment()
-{
- const QString host = QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_HOST"));
- if (host.isEmpty() && qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS"))
- return QString("127.0.0.1");
- return host;
-}
-
-quint16 getPortFromEnvironment()
-{
- const int port = qEnvironmentVariableIntValue("QTC_SSH_TEST_PORT");
- return port != 0 ? quint16(port) : 22;
-}
-
-const QString getUserFromEnvironment()
-{
- return QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_USER"));
-}
-
-const QString getKeyFileFromEnvironment()
-{
- const FilePath defaultKeyFile = FileUtils::homePath() / ".ssh/id_rsa";
- const QString keyFile = QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_KEYFILE"));
- if (keyFile.isEmpty()) {
- if (qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS"))
- return defaultKeyFile.toString();
- }
- return keyFile;
-}
-
-const QString userAtHost()
-{
- QString userMidFix = getUserFromEnvironment();
- if (!userMidFix.isEmpty())
- userMidFix.append('@');
- return userMidFix + getHostFromEnvironment();
-}
-
-SshConnectionParameters getParameters()
-{
- SshConnectionParameters params;
- if (!qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS")) {
- params.setUserName(getUserFromEnvironment());
- params.privateKeyFile = Utils::FilePath::fromUserInput(getKeyFileFromEnvironment());
- }
- params.setHost(getHostFromEnvironment());
- params.setPort(getPortFromEnvironment());
- params.timeout = 10;
- params.authenticationType = !params.privateKeyFile.isEmpty()
- ? QSsh::SshConnectionParameters::AuthenticationTypeSpecificKey
- : QSsh::SshConnectionParameters::AuthenticationTypeAll;
- return params;
-}
-
-bool checkParameters(const QSsh::SshConnectionParameters &params)
-{
- if (qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS"))
- return true;
- if (params.host().isEmpty()) {
- qWarning("No hostname provided. Set QTC_SSH_TEST_HOST.");
- return false;
- }
- if (params.userName().isEmpty())
- qWarning("No user name provided - test may fail with empty default. Set QTC_SSH_TEST_USER.");
- if (params.privateKeyFile.isEmpty()) {
- qWarning("No key file provided. Set QTC_SSH_TEST_KEYFILE.");
- return false;
- }
- return true;
-}
-
-void printSetupHelp()
-{
- qInfo() << "\n\n"
- "In order to run this test properly it requires some setup (example for fedora):\n"
- "1. Run a server on the host to connect to:\n"
- " systemctl start sshd\n"
- "2. Create your own ssh key (needed only once). For fedora it needs ecdsa type:\n"
- " ssh-keygen -t ecdsa\n"
- "3. Make your public key known to the server (needed only once):\n"
- " ssh-copy-id -i [full path to your public key] [user@host]\n"
- "4. Set the env variables before executing test:\n"
- " QTC_SSH_TEST_HOST=127.0.0.1\n"
- " QTC_SSH_TEST_KEYFILE=[full path to your private key]\n"
- " QTC_SSH_TEST_USER=[your user name]\n";
-}
-
-} // namespace SshTest
-#endif
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshconnection.h b/src/libs/ssh/sshconnection.h
deleted file mode 100644
index a559fc13163..00000000000
--- a/src/libs/ssh/sshconnection.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sftpdefs.h"
-#include "ssh_global.h"
-
-#include <utils/filepath.h>
-#include <utils/processutils.h>
-
-#include <QFlags>
-#include <QHostAddress>
-#include <QObject>
-#include <QString>
-#include <QUrl>
-
-#include <memory>
-
-namespace QSsh {
-class SshRemoteProcess;
-
-enum SshHostKeyCheckingMode {
- SshHostKeyCheckingNone,
- SshHostKeyCheckingStrict,
- SshHostKeyCheckingAllowNoMatch,
-};
-
-class QSSH_EXPORT SshConnectionParameters
-{
-public:
- enum AuthenticationType {
- AuthenticationTypeAll,
- AuthenticationTypeSpecificKey,
- };
-
- SshConnectionParameters();
-
- QString host() const { return url.host(); }
- quint16 port() const { return url.port(); }
- QString userName() const { return url.userName(); }
- QString userAtHost() const { return userName().isEmpty() ? host() : userName() + '@' + host(); }
- void setHost(const QString &host) { url.setHost(host); }
- void setPort(int port) { url.setPort(port); }
- void setUserName(const QString &name) { url.setUserName(name); }
-
- QStringList connectionOptions(const Utils::FilePath &binary) const;
-
- QUrl url;
- Utils::FilePath privateKeyFile;
- QString x11DisplayName;
- int timeout = 0; // In seconds.
- AuthenticationType authenticationType = AuthenticationTypeAll;
- SshHostKeyCheckingMode hostKeyCheckingMode = SshHostKeyCheckingAllowNoMatch;
-};
-
-QSSH_EXPORT bool operator==(const SshConnectionParameters &p1, const SshConnectionParameters &p2);
-QSSH_EXPORT bool operator!=(const SshConnectionParameters &p1, const SshConnectionParameters &p2);
-
-class QSSH_EXPORT SshConnectionInfo
-{
-public:
- SshConnectionInfo() = default;
- SshConnectionInfo(const QHostAddress &la, quint16 lp, const QHostAddress &pa, quint16 pp)
- : localAddress(la), localPort(lp), peerAddress(pa), peerPort(pp) {}
-
- bool isValid() const { return peerPort != 0; }
-
- QHostAddress localAddress;
- quint16 localPort = 0;
- QHostAddress peerAddress;
- quint16 peerPort = 0;
-};
-
-using SshRemoteProcessPtr = std::unique_ptr<SshRemoteProcess>;
-
-class QSSH_EXPORT SshConnection : public QObject
-{
- Q_OBJECT
-
-public:
- enum State { Unconnected, Connecting, Connected, Disconnecting };
-
- explicit SshConnection(const SshConnectionParameters &serverInfo, QObject *parent = nullptr);
-
- void connectToHost();
- void disconnectFromHost();
- State state() const;
- QString errorString() const;
- SshConnectionParameters connectionParameters() const;
- SshConnectionInfo connectionInfo() const;
- QStringList connectionOptions(const Utils::FilePath &binary) const;
- bool sharingEnabled() const;
- ~SshConnection();
-
- SshRemoteProcessPtr createRemoteProcess(const QString &command, Utils::ProcessMode processMode
- = Utils::ProcessMode::Reader);
- SshRemoteProcessPtr createRemoteShell(Utils::ProcessMode processMode
- = Utils::ProcessMode::Reader);
- SftpTransferPtr createUpload(const FilesToTransfer &files,
- FileTransferErrorHandling errorHandlingMode);
- SftpTransferPtr createDownload(const FilesToTransfer &files,
- FileTransferErrorHandling errorHandlingMode);
- SftpSessionPtr createSftpSession();
-
-signals:
- void connected();
- void disconnected();
- void errorOccurred();
-
-private:
- void doConnectToHost();
- void emitError(const QString &reason);
- void emitConnected();
- void emitDisconnected();
- SftpTransferPtr setupTransfer(const FilesToTransfer &files, Internal::FileTransferType type,
- FileTransferErrorHandling errorHandlingMode);
-
- struct SshConnectionPrivate;
- SshConnectionPrivate * const d;
-};
-
-#ifdef WITH_TESTS
-namespace SshTest {
-const QString QSSH_EXPORT getHostFromEnvironment();
-quint16 QSSH_EXPORT getPortFromEnvironment();
-const QString QSSH_EXPORT getUserFromEnvironment();
-const QString QSSH_EXPORT getKeyFileFromEnvironment();
-const QSSH_EXPORT QString userAtHost();
-SshConnectionParameters QSSH_EXPORT getParameters();
-bool QSSH_EXPORT checkParameters(const SshConnectionParameters &params);
-void QSSH_EXPORT printSetupHelp();
-} // namespace SshTest
-#endif
-
-} // namespace QSsh
-
-Q_DECLARE_METATYPE(QSsh::SshConnectionParameters::AuthenticationType)
diff --git a/src/libs/ssh/sshconnectionmanager.cpp b/src/libs/ssh/sshconnectionmanager.cpp
deleted file mode 100644
index 800c4f14f19..00000000000
--- a/src/libs/ssh/sshconnectionmanager.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshconnectionmanager.h"
-
-#include "sshconnection.h"
-#include "sshsettings.h"
-
-#include <utils/qtcassert.h>
-
-#include <QCoreApplication>
-#include <QHash>
-#include <QObject>
-#include <QThread>
-#include <QTimer>
-
-namespace QSsh {
-namespace Internal {
-
-class SshConnectionManagerPrivate : public QObject
-{
-public:
- SshConnectionManagerPrivate()
- {
- connect(&m_removalTimer, &QTimer::timeout,
- this, &SshConnectionManagerPrivate::removeInactiveConnections);
- m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2);
- }
-
- ~SshConnectionManagerPrivate() override
- {
- for (auto it = m_connections.cbegin(); it != m_connections.cend(); ++it) {
- SshConnection * const connection = it.key();
- const SshConnectionState &state = it.value();
- QTC_CHECK(state.refCount() == 0);
- QTC_CHECK(!state.isStale());
- disconnect(connection, nullptr, this, nullptr);
- delete connection;
- }
- }
-
- SshConnection *acquireConnection(const SshConnectionParameters &sshParams)
- {
- if (SshSettings::connectionSharingEnabled()) {
- for (auto it = m_connections.begin(); it != m_connections.end(); ++it) {
- SshConnection * const connection = it.key();
- if (connection->connectionParameters() != sshParams)
- continue;
-
- SshConnectionState &state = it.value();
- if (state.isStale())
- continue;
-
- if (state.refCount() == 0 && connection->state() != SshConnection::Connected)
- continue;
-
- state.ref();
- return connection;
- }
- }
-
- SshConnection * const connection = new SshConnection(sshParams);
- if (SshSettings::connectionSharingEnabled()) {
- connect(connection, &SshConnection::disconnected,
- this, [this, connection] { cleanup(connection); });
- m_connections.insert(connection, {});
- }
-
- return connection;
- }
-
- void releaseConnection(SshConnection *connection)
- {
- auto it = m_connections.find(connection);
- bool doDelete = false;
- if (it == m_connections.end()) {
- QTC_ASSERT(!connection->sharingEnabled(), return);
- doDelete = true;
- } else {
- SshConnectionState &state = it.value();
- if (state.deref())
- return;
-
- if (state.isStale() || connection->state() != SshConnection::Connected) {
- doDelete = true;
- m_connections.erase(it);
- }
- }
-
- if (doDelete) {
- disconnect(connection, nullptr, this, nullptr);
- connection->deleteLater();
- }
- }
-
- void forceNewConnection(const SshConnectionParameters &sshParams)
- {
- auto it = m_connections.begin();
- while (it != m_connections.end()) {
- SshConnection * const connection = it.key();
- if (connection->connectionParameters() != sshParams) {
- ++it;
- continue;
- }
-
- SshConnectionState &state = it.value();
- if (state.refCount()) {
- state.makeStale();
- ++it;
- continue;
- }
-
- disconnect(connection, nullptr, this, nullptr);
- delete connection;
- it = m_connections.erase(it);
- }
- }
-
-private:
- void cleanup(SshConnection *connection)
- {
- auto it = m_connections.find(connection);
- if (it == m_connections.end())
- return;
-
- SshConnectionState &state = it.value();
- if (state.refCount())
- return;
-
- disconnect(connection, nullptr, this, nullptr);
- connection->deleteLater();
- m_connections.erase(it);
- }
-
- void removeInactiveConnections()
- {
- auto it = m_connections.begin();
- while (it != m_connections.end()) {
- SshConnection * const connection = it.key();
- SshConnectionState &state = it.value();
- if (state.refCount() == 0 && state.scheduleForRemoval()) {
- disconnect(connection, nullptr, this, nullptr);
- connection->deleteLater();
- it = m_connections.erase(it);
- } else {
- ++it;
- }
- }
- }
-
-private:
- struct SshConnectionState {
- void ref() { ++m_ref; m_scheduledForRemoval = false; }
- bool deref() { QTC_ASSERT(m_ref, return false); return --m_ref; }
- int refCount() const { return m_ref; }
-
- void makeStale() { m_isStale = true; }
- bool isStale() const { return m_isStale; }
-
- bool scheduleForRemoval()
- {
- const bool ret = m_scheduledForRemoval;
- m_scheduledForRemoval = true;
- return ret;
- }
- private:
- int m_ref = 1; // 0 means unacquired connection
- bool m_isStale = false;
- bool m_scheduledForRemoval = false;
- };
-
- QHash<SshConnection *, SshConnectionState> m_connections;
- QTimer m_removalTimer;
-};
-
-} // namespace Internal
-
-SshConnectionManager::SshConnectionManager()
- : d(new Internal::SshConnectionManagerPrivate())
-{
- QTC_CHECK(QThread::currentThread() == qApp->thread());
-}
-
-SshConnectionManager::~SshConnectionManager()
-{
- delete d;
-}
-
-SshConnection *SshConnectionManager::acquireConnection(const SshConnectionParameters &sshParams)
-{
- return instance()->d->acquireConnection(sshParams);
-}
-
-void SshConnectionManager::releaseConnection(SshConnection *connection)
-{
- instance()->d->releaseConnection(connection);
-}
-
-void SshConnectionManager::forceNewConnection(const SshConnectionParameters &sshParams)
-{
- instance()->d->forceNewConnection(sshParams);
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshconnectionmanager.h b/src/libs/ssh/sshconnectionmanager.h
deleted file mode 100644
index d46a8d8b89f..00000000000
--- a/src/libs/ssh/sshconnectionmanager.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ssh_global.h"
-
-#include <utils/launcherinterface.h>
-#include <utils/singleton.h>
-
-namespace QSsh {
-
-class SshConnection;
-class SshConnectionParameters;
-
-namespace Internal { class SshConnectionManagerPrivate; }
-
-class QSSH_EXPORT SshConnectionManager final
- : public Utils::SingletonWithOptionalDependencies<SshConnectionManager,
- Utils::LauncherInterface>
-{
-public:
- static SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
- static void releaseConnection(SshConnection *connection);
- // Make sure the next acquireConnection with the given parameters will return a new connection.
- static void forceNewConnection(const SshConnectionParameters &sshParams);
-
-private:
- SshConnectionManager();
- ~SshConnectionManager();
-
- Internal::SshConnectionManagerPrivate *d;
- friend class Utils::SingletonWithOptionalDependencies<SshConnectionManager, Utils::LauncherInterface>;
-};
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshkeycreationdialog.cpp b/src/libs/ssh/sshkeycreationdialog.cpp
deleted file mode 100644
index cae7a37b664..00000000000
--- a/src/libs/ssh/sshkeycreationdialog.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshkeycreationdialog.h"
-#include "ui_sshkeycreationdialog.h"
-
-#include "sshsettings.h"
-
-#include <utils/fileutils.h>
-#include <utils/pathchooser.h>
-#include <utils/qtcprocess.h>
-
-#include <QApplication>
-#include <QMessageBox>
-#include <QStandardPaths>
-
-using namespace Utils;
-
-namespace QSsh {
-
-SshKeyCreationDialog::SshKeyCreationDialog(QWidget *parent)
- : QDialog(parent), m_ui(new Ui::SshKeyCreationDialog)
-{
- m_ui->setupUi(this);
- m_ui->privateKeyFileButton->setText(Utils::PathChooser::browseButtonLabel());
- const QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
- + QLatin1String("/.ssh/qtc_id");
- setPrivateKeyFile(FilePath::fromString(defaultPath));
-
- connect(m_ui->rsa, &QRadioButton::toggled,
- this, &SshKeyCreationDialog::keyTypeChanged);
- connect(m_ui->privateKeyFileButton, &QPushButton::clicked,
- this, &SshKeyCreationDialog::handleBrowseButtonClicked);
- connect(m_ui->generateButton, &QPushButton::clicked,
- this, &SshKeyCreationDialog::generateKeys);
- keyTypeChanged();
-}
-
-SshKeyCreationDialog::~SshKeyCreationDialog()
-{
- delete m_ui;
-}
-
-void SshKeyCreationDialog::keyTypeChanged()
-{
- m_ui->comboBox->clear();
- QStringList keySizes;
- if (m_ui->rsa->isChecked())
- keySizes << QLatin1String("1024") << QLatin1String("2048") << QLatin1String("4096");
- else if (m_ui->ecdsa->isChecked())
- keySizes << QLatin1String("256") << QLatin1String("384") << QLatin1String("521");
- m_ui->comboBox->addItems(keySizes);
- if (!keySizes.isEmpty())
- m_ui->comboBox->setCurrentIndex(0);
- m_ui->comboBox->setEnabled(!keySizes.isEmpty());
-}
-
-void SshKeyCreationDialog::generateKeys()
-{
- if (SshSettings::keygenFilePath().isEmpty()) {
- showError(tr("The ssh-keygen tool was not found."));
- return;
- }
- if (privateKeyFilePath().exists()) {
- showError(tr("Refusing to overwrite existing private key file \"%1\".")
- .arg(privateKeyFilePath().toUserOutput()));
- return;
- }
- const QString keyTypeString = QLatin1String(m_ui->rsa->isChecked() ? "rsa": "ecdsa");
- QApplication::setOverrideCursor(Qt::BusyCursor);
- QtcProcess keygen;
- const QStringList args{"-t", keyTypeString, "-b", m_ui->comboBox->currentText(),
- "-N", QString(), "-f", privateKeyFilePath().path()};
- QString errorMsg;
- keygen.setCommand({SshSettings::keygenFilePath(), args});
- keygen.start();
- if (!keygen.waitForStarted() || !keygen.waitForFinished())
- errorMsg = keygen.errorString();
- else if (keygen.exitCode() != 0)
- errorMsg = QString::fromLocal8Bit(keygen.readAllStandardError());
- if (!errorMsg.isEmpty()) {
- showError(tr("The ssh-keygen tool at \"%1\" failed: %2")
- .arg(SshSettings::keygenFilePath().toUserOutput(), errorMsg));
- }
- QApplication::restoreOverrideCursor();
- accept();
-}
-
-void SshKeyCreationDialog::handleBrowseButtonClicked()
-{
- const FilePath filePath = FileUtils::getSaveFilePath(this, tr("Choose Private Key File Name"));
- if (!filePath.isEmpty())
- setPrivateKeyFile(filePath);
-}
-
-void SshKeyCreationDialog::setPrivateKeyFile(const FilePath &filePath)
-{
- m_ui->privateKeyFileValueLabel->setText(filePath.toUserOutput());
- m_ui->generateButton->setEnabled(!privateKeyFilePath().isEmpty());
- m_ui->publicKeyFileLabel->setText(filePath.toUserOutput() + ".pub");
-}
-
-void SshKeyCreationDialog::showError(const QString &details)
-{
- QMessageBox::critical(this, tr("Key Generation Failed"), details);
-}
-
-FilePath SshKeyCreationDialog::privateKeyFilePath() const
-{
- return FilePath::fromUserInput(m_ui->privateKeyFileValueLabel->text());
-}
-
-FilePath SshKeyCreationDialog::publicKeyFilePath() const
-{
- return FilePath::fromUserInput(m_ui->publicKeyFileLabel->text());
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshkeycreationdialog.h b/src/libs/ssh/sshkeycreationdialog.h
deleted file mode 100644
index 3999cf93f76..00000000000
--- a/src/libs/ssh/sshkeycreationdialog.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ssh_global.h"
-
-#include <utils/filepath.h>
-
-#include <QDialog>
-
-namespace QSsh {
-
-namespace Ui { class SshKeyCreationDialog; }
-
-class QSSH_EXPORT SshKeyCreationDialog : public QDialog
-{
- Q_OBJECT
-public:
- SshKeyCreationDialog(QWidget *parent = nullptr);
- ~SshKeyCreationDialog();
-
- Utils::FilePath privateKeyFilePath() const;
- Utils::FilePath publicKeyFilePath() const;
-
-private:
- void keyTypeChanged();
- void generateKeys();
- void handleBrowseButtonClicked();
- void setPrivateKeyFile(const Utils::FilePath &filePath);
- void showError(const QString &details);
-
-private:
- Ui::SshKeyCreationDialog *m_ui;
-};
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshkeycreationdialog.ui b/src/libs/ssh/sshkeycreationdialog.ui
deleted file mode 100644
index e5be7c659bf..00000000000
--- a/src/libs/ssh/sshkeycreationdialog.ui
+++ /dev/null
@@ -1,250 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QSsh::SshKeyCreationDialog</class>
- <widget class="QDialog" name="QSsh::SshKeyCreationDialog">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>385</width>
- <height>231</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>SSH Key Configuration</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Options</string>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="keyAlgo">
- <property name="text">
- <string>Key algorithm:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QRadioButton" name="rsa">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>&amp;RSA</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="ecdsa">
- <property name="text">
- <string>ECDSA</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="keySize">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Key &amp;size:</string>
- </property>
- <property name="buddy">
- <cstring>comboBox</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QComboBox" name="comboBox"/>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="privateKeyFileLabel">
- <property name="text">
- <string>Private key file:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="QLabel" name="privateKeyFileValueLabel">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="privateKeyFileButton">
- <property name="text">
- <string>Browse...</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_4">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Public key file:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="publicKeyFileLabel">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="spacing">
- <number>6</number>
- </property>
- <item>
- <widget class="QPushButton" name="generateButton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>&amp;Generate And Save Key Pair</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="closeButton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>&amp;Cancel</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections>
- <connection>
- <sender>closeButton</sender>
- <signal>clicked()</signal>
- <receiver>QSsh::SshKeyCreationDialog</receiver>
- <slot>close()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>195</x>
- <y>184</y>
- </hint>
- <hint type="destinationlabel">
- <x>381</x>
- <y>107</y>
- </hint>
- </hints>
- </connection>
- </connections>
-</ui>
diff --git a/src/libs/ssh/sshlogging.cpp b/src/libs/ssh/sshlogging.cpp
deleted file mode 100644
index d5cfbbca334..00000000000
--- a/src/libs/ssh/sshlogging.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshlogging_p.h"
-
-namespace QSsh {
-namespace Internal {
-Q_LOGGING_CATEGORY(sshLog, "qtc.ssh", QtWarningMsg)
-} // namespace Internal
-} // namespace QSsh
diff --git a/src/libs/ssh/sshlogging_p.h b/src/libs/ssh/sshlogging_p.h
deleted file mode 100644
index 07815313e52..00000000000
--- a/src/libs/ssh/sshlogging_p.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QLoggingCategory>
-
-namespace QSsh {
-namespace Internal {
-Q_DECLARE_LOGGING_CATEGORY(sshLog)
-} // namespace Internal
-} // namespace QSsh
diff --git a/src/libs/ssh/sshprocess.cpp b/src/libs/ssh/sshprocess.cpp
deleted file mode 100644
index 7064deed4b2..00000000000
--- a/src/libs/ssh/sshprocess.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshprocess.h"
-
-#include "sshsettings.h"
-
-#include <utils/environment.h>
-
-namespace QSsh {
-
-SshProcess::SshProcess(Utils::ProcessMode processMode)
- : Utils::QtcProcess(processMode)
-{
- Utils::Environment env = Utils::Environment::systemEnvironment();
- if (SshSettings::askpassFilePath().exists()) {
- env.set("SSH_ASKPASS", SshSettings::askpassFilePath().toUserOutput());
-
- // OpenSSH only uses the askpass program if DISPLAY is set, regardless of the platform.
- if (!env.hasKey("DISPLAY"))
- env.set("DISPLAY", ":0");
- }
- setEnvironment(env);
-
- // Otherwise, ssh will ignore SSH_ASKPASS and read from /dev/tty directly.
- setDisableUnixTerminal();
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshprocess.h b/src/libs/ssh/sshprocess.h
deleted file mode 100644
index 00610bcd69a..00000000000
--- a/src/libs/ssh/sshprocess.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ssh_global.h"
-
-#include <utils/qtcprocess.h>
-
-namespace QSsh {
-
-class QSSH_EXPORT SshProcess : public Utils::QtcProcess
-{
-public:
- SshProcess(Utils::ProcessMode processMode = Utils::ProcessMode::Reader);
-};
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshremoteprocess.cpp b/src/libs/ssh/sshremoteprocess.cpp
deleted file mode 100644
index 0cb916acf13..00000000000
--- a/src/libs/ssh/sshremoteprocess.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshremoteprocess.h"
-
-#include "sshlogging_p.h"
-#include "sshsettings.h"
-
-#include <utils/commandline.h>
-#include <utils/qtcassert.h>
-
-#include <QTimer>
-
-/*!
- \class QSsh::SshRemoteProcess
-
- \brief The SshRemoteProcess class implements an SSH channel for running a
- remote process.
-
- Objects are created via SshConnection::createRemoteProcess.
- The process is started via the start() member function.
- If the process needs a pseudo terminal, you can request one
- via requestTerminal() before calling start().
- */
-
-using namespace QSsh::Internal;
-
-namespace QSsh {
-
-SshRemoteProcess::SshRemoteProcess(const QString &command, const QStringList &connectionArgs,
- Utils::ProcessMode processMode)
- : SshProcess(processMode)
-{
- m_remoteCommand = command;
- m_connectionArgs = connectionArgs;
-
- connect(this, &QtcProcess::finished, this, [this] {
- QString error;
- if (exitStatus() == QProcess::CrashExit)
- error = tr("The ssh process crashed: %1").arg(errorString());
- emit done(error);
- });
- connect(this, &QtcProcess::errorOccurred, [this](QProcess::ProcessError error) {
- if (error == QProcess::FailedToStart)
- emit done(errorString());
- });
-}
-
-void SshRemoteProcess::start()
-{
- QTC_ASSERT(!isRunning(), return);
- const Utils::CommandLine cmd = fullLocalCommandLine();
- if (!m_displayName.isEmpty()) {
- Utils::Environment env = environment();
- env.set("DISPLAY", m_displayName);
- setEnvironment(env);
- }
- qCDebug(sshLog) << "starting remote process:" << cmd.toUserOutput();
- setCommand(cmd);
- QtcProcess::start();
-}
-
-void SshRemoteProcess::requestX11Forwarding(const QString &displayName)
-{
- m_displayName = displayName;
-}
-
-Utils::CommandLine SshRemoteProcess::fullLocalCommandLine(bool inTerminal) const
-{
- Utils::CommandLine cmd{SshSettings::sshFilePath()};
-
- if (!m_displayName.isEmpty())
- cmd.addArg("-X");
- if (inTerminal)
- cmd.addArg("-tt");
-
- cmd.addArg("-q");
- cmd.addArgs(m_connectionArgs);
-
- if (!m_remoteCommand.isEmpty())
- cmd.addArg(m_remoteCommand);
-
- return cmd;
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshremoteprocess.h b/src/libs/ssh/sshremoteprocess.h
deleted file mode 100644
index b5195454b50..00000000000
--- a/src/libs/ssh/sshremoteprocess.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ssh_global.h"
-#include "sshprocess.h"
-
-namespace Utils { class CommandLine; }
-
-namespace QSsh {
-
-class QSSH_EXPORT SshRemoteProcess : public SshProcess
-{
- Q_OBJECT
-
-public:
- SshRemoteProcess(const QString &command, const QStringList &connectionArgs,
- Utils::ProcessMode processMode = Utils::ProcessMode::Reader);
-
- void requestX11Forwarding(const QString &displayName);
- void start();
-
- Utils::CommandLine fullLocalCommandLine(bool inTerminal = false) const;
-
-signals:
- void done(const QString &error);
-
-private:
- QString m_remoteCommand;
- QStringList m_connectionArgs;
- QString m_displayName;
-};
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshremoteprocessrunner.cpp b/src/libs/ssh/sshremoteprocessrunner.cpp
deleted file mode 100644
index edbc7219b17..00000000000
--- a/src/libs/ssh/sshremoteprocessrunner.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshremoteprocessrunner.h"
-
-#include "sshconnectionmanager.h"
-
-#include <utils/qtcassert.h>
-
-/*!
- \class QSsh::SshRemoteProcessRunner
-
- \brief The SshRemoteProcessRunner class is a convenience class for
- running a remote process over an SSH connection.
-*/
-
-namespace QSsh {
-namespace Internal {
-namespace {
-enum State { Inactive, Connecting, Connected, ProcessRunning };
-} // anonymous namespace
-
-class SshRemoteProcessRunnerPrivate
-{
-public:
- SshRemoteProcessRunnerPrivate() : m_state(Inactive) {}
-
- SshRemoteProcessPtr m_process;
- SshConnection *m_connection;
- QString m_command;
- QString m_lastConnectionErrorString;
- QProcess::ExitStatus m_exitStatus;
- QByteArray m_stdout;
- QByteArray m_stderr;
- int m_exitCode;
- QString m_processErrorString;
- State m_state;
-};
-
-} // namespace Internal
-
-using namespace Internal;
-
-SshRemoteProcessRunner::SshRemoteProcessRunner(QObject *parent)
- : QObject(parent), d(new SshRemoteProcessRunnerPrivate)
-{
-}
-
-SshRemoteProcessRunner::~SshRemoteProcessRunner()
-{
- disconnect();
- setState(Inactive);
- delete d;
-}
-
-void SshRemoteProcessRunner::run(const QString &command, const SshConnectionParameters &sshParams)
-{
- QTC_ASSERT(d->m_state == Inactive, return);
-
- runInternal(command, sshParams);
-}
-
-void SshRemoteProcessRunner::runInternal(const QString &command,
- const SshConnectionParameters &sshParams)
-{
- setState(Connecting);
-
- d->m_lastConnectionErrorString.clear();
- d->m_processErrorString.clear();
- d->m_exitCode = -1;
- d->m_command = command;
- d->m_connection = SshConnectionManager::acquireConnection(sshParams);
- connect(d->m_connection, &SshConnection::errorOccurred,
- this, &SshRemoteProcessRunner::handleConnectionError);
- connect(d->m_connection, &SshConnection::disconnected,
- this, &SshRemoteProcessRunner::handleDisconnected);
- if (d->m_connection->state() == SshConnection::Connected) {
- handleConnected();
- } else {
- connect(d->m_connection, &SshConnection::connected, this, &SshRemoteProcessRunner::handleConnected);
- if (d->m_connection->state() == SshConnection::Unconnected)
- d->m_connection->connectToHost();
- }
-}
-
-void SshRemoteProcessRunner::handleConnected()
-{
- QTC_ASSERT(d->m_state == Connecting, return);
- setState(Connected);
-
- d->m_process = d->m_connection->createRemoteProcess(d->m_command);
- connect(d->m_process.get(), &SshRemoteProcess::started,
- this, &SshRemoteProcessRunner::handleProcessStarted);
- connect(d->m_process.get(), &SshRemoteProcess::done,
- this, &SshRemoteProcessRunner::handleProcessFinished);
- connect(d->m_process.get(), &SshRemoteProcess::readyReadStandardOutput,
- this, &SshRemoteProcessRunner::handleStdout);
- connect(d->m_process.get(), &SshRemoteProcess::readyReadStandardError,
- this, &SshRemoteProcessRunner::handleStderr);
- d->m_process->start();
-}
-
-void SshRemoteProcessRunner::handleConnectionError()
-{
- d->m_lastConnectionErrorString = d->m_connection->errorString();
- handleDisconnected();
- emit connectionError();
-}
-
-void SshRemoteProcessRunner::handleDisconnected()
-{
- QTC_ASSERT(d->m_state == Connecting || d->m_state == Connected || d->m_state == ProcessRunning,
- return);
- setState(Inactive);
-}
-
-void SshRemoteProcessRunner::handleProcessStarted()
-{
- QTC_ASSERT(d->m_state == Connected, return);
-
- setState(ProcessRunning);
- emit processStarted();
-}
-
-void SshRemoteProcessRunner::handleProcessFinished(const QString &error)
-{
- d->m_exitStatus = d->m_process->exitStatus();
- d->m_exitCode = d->m_process->exitCode();
- d->m_processErrorString = error;
- setState(Inactive);
- emit processClosed(d->m_processErrorString);
-}
-
-void SshRemoteProcessRunner::handleStdout()
-{
- d->m_stdout += d->m_process->readAllStandardOutput();
- emit readyReadStandardOutput();
-}
-
-void SshRemoteProcessRunner::handleStderr()
-{
- d->m_stderr += d->m_process->readAllStandardError();
- emit readyReadStandardError();
-}
-
-void SshRemoteProcessRunner::setState(int newState)
-{
- if (d->m_state == newState)
- return;
-
- d->m_state = static_cast<State>(newState);
- if (d->m_state == Inactive) {
- if (d->m_process) {
- disconnect(d->m_process.get(), nullptr, this, nullptr);
- d->m_process->terminate();
- d->m_process.reset();
- }
- if (d->m_connection) {
- disconnect(d->m_connection, nullptr, this, nullptr);
- SshConnectionManager::releaseConnection(d->m_connection);
- d->m_connection = nullptr;
- }
- }
-}
-
-QString SshRemoteProcessRunner::lastConnectionErrorString() const {
- return d->m_lastConnectionErrorString;
-}
-
-bool SshRemoteProcessRunner::isProcessRunning() const
-{
- return d->m_process && d->m_process->isRunning();
-}
-
-QProcess::ExitStatus SshRemoteProcessRunner::processExitStatus() const
-{
- QTC_CHECK(!isProcessRunning());
- return d->m_exitStatus;
-}
-
-int SshRemoteProcessRunner::processExitCode() const
-{
- QTC_CHECK(processExitStatus() == QProcess::NormalExit);
- return d->m_exitCode;
-}
-
-QString SshRemoteProcessRunner::processErrorString() const
-{
- return d->m_processErrorString;
-}
-
-QByteArray SshRemoteProcessRunner::readAllStandardOutput()
-{
- const QByteArray data = d->m_stdout;
- d->m_stdout.clear();
- return data;
-}
-
-QByteArray SshRemoteProcessRunner::readAllStandardError()
-{
- const QByteArray data = d->m_stderr;
- d->m_stderr.clear();
- return data;
-}
-
-void SshRemoteProcessRunner::cancel()
-{
- setState(Inactive);
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshremoteprocessrunner.h b/src/libs/ssh/sshremoteprocessrunner.h
deleted file mode 100644
index 5cb188b2e68..00000000000
--- a/src/libs/ssh/sshremoteprocessrunner.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sshconnection.h"
-#include "sshremoteprocess.h"
-
-namespace QSsh {
-namespace Internal { class SshRemoteProcessRunnerPrivate; }
-
-class QSSH_EXPORT SshRemoteProcessRunner : public QObject
-{
- Q_OBJECT
-
-public:
- SshRemoteProcessRunner(QObject *parent = nullptr);
- ~SshRemoteProcessRunner();
-
- void run(const QString &command, const SshConnectionParameters &sshParams);
-
- QString lastConnectionErrorString() const;
-
- bool isProcessRunning() const;
- void cancel();
- QProcess::ExitStatus processExitStatus() const;
- int processExitCode() const;
- QString processErrorString() const;
- QByteArray readAllStandardOutput();
- QByteArray readAllStandardError();
-
-signals:
- void connectionError();
- void processStarted();
- void readyReadStandardOutput();
- void readyReadStandardError();
- void processClosed(const QString &error);
-
-private:
- void handleConnected();
- void handleConnectionError();
- void handleDisconnected();
- void handleProcessStarted();
- void handleProcessFinished(const QString &error);
- void handleStdout();
- void handleStderr();
- void runInternal(const QString &command, const QSsh::SshConnectionParameters &sshParams);
- void setState(int newState);
-
- Internal::SshRemoteProcessRunnerPrivate * const d;
-};
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshsettings.cpp b/src/libs/ssh/sshsettings.cpp
deleted file mode 100644
index 98446b752f1..00000000000
--- a/src/libs/ssh/sshsettings.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshsettings.h"
-
-#include <utils/environment.h>
-#include <utils/hostosinfo.h>
-
-#include <QSettings>
-
-using namespace Utils;
-
-namespace QSsh {
-namespace Internal {
-
-struct SshSettings
-{
- bool useConnectionSharing = !HostOsInfo::isWindowsHost();
- int connectionSharingTimeOutInMinutes = 10;
- FilePath sshFilePath;
- FilePath sftpFilePath;
- FilePath askpassFilePath;
- FilePath keygenFilePath;
- QSsh::SshSettings::SearchPathRetriever searchPathRetriever = [] { return FilePaths(); };
-};
-
-} // namespace Internal
-
-Q_GLOBAL_STATIC(QSsh::Internal::SshSettings, sshSettings)
-
-
-class AccessSettingsGroup
-{
-public:
- AccessSettingsGroup(QSettings *settings) : m_settings(settings)
- {
- settings->beginGroup("SshSettings");
- }
- ~AccessSettingsGroup() { m_settings->endGroup(); }
-private:
- QSettings * const m_settings;
-};
-
-static QString connectionSharingKey() { return QString("UseConnectionSharing"); }
-static QString connectionSharingTimeoutKey() { return QString("ConnectionSharingTimeout"); }
-static QString sshFilePathKey() { return QString("SshFilePath"); }
-static QString sftpFilePathKey() { return QString("SftpFilePath"); }
-static QString askPassFilePathKey() { return QString("AskpassFilePath"); }
-static QString keygenFilePathKey() { return QString("KeygenFilePath"); }
-
-void SshSettings::loadSettings(QSettings *settings)
-{
- AccessSettingsGroup g(settings);
- QVariant value = settings->value(connectionSharingKey());
- if (value.isValid() && !HostOsInfo::isWindowsHost())
- sshSettings->useConnectionSharing = value.toBool();
- value = settings->value(connectionSharingTimeoutKey());
- if (value.isValid())
- sshSettings->connectionSharingTimeOutInMinutes = value.toInt();
- sshSettings->sshFilePath = FilePath::fromString(settings->value(sshFilePathKey()).toString());
- sshSettings->sftpFilePath = FilePath::fromString(settings->value(sftpFilePathKey()).toString());
- sshSettings->askpassFilePath = FilePath::fromString(
- settings->value(askPassFilePathKey()).toString());
- sshSettings->keygenFilePath = FilePath::fromString(
- settings->value(keygenFilePathKey()).toString());
-}
-
-void SshSettings::storeSettings(QSettings *settings)
-{
- AccessSettingsGroup g(settings);
- settings->setValue(connectionSharingKey(), sshSettings->useConnectionSharing);
- settings->setValue(connectionSharingTimeoutKey(),
- sshSettings->connectionSharingTimeOutInMinutes);
- settings->setValue(sshFilePathKey(), sshSettings->sshFilePath.toString());
- settings->setValue(sftpFilePathKey(), sshSettings->sftpFilePath.toString());
- settings->setValue(askPassFilePathKey(), sshSettings->askpassFilePath.toString());
- settings->setValue(keygenFilePathKey(), sshSettings->keygenFilePath.toString());
-}
-
-void SshSettings::setConnectionSharingEnabled(bool share)
-{
- sshSettings->useConnectionSharing = share;
-}
-bool SshSettings::connectionSharingEnabled() { return sshSettings->useConnectionSharing; }
-
-void SshSettings::setConnectionSharingTimeout(int timeInMinutes)
-{
- sshSettings->connectionSharingTimeOutInMinutes = timeInMinutes;
-}
-int SshSettings::connectionSharingTimeout()
-{
- return sshSettings->connectionSharingTimeOutInMinutes;
-}
-
-static FilePath filePathValue(const FilePath &value, const QStringList &candidateFileNames)
-{
- if (!value.isEmpty())
- return value;
- const QList<FilePath> additionalSearchPaths = sshSettings->searchPathRetriever();
- for (const QString &candidate : candidateFileNames) {
- const FilePath filePath = Environment::systemEnvironment()
- .searchInPath(candidate, additionalSearchPaths);
- if (!filePath.isEmpty())
- return filePath;
- }
- return FilePath();
-}
-
-static FilePath filePathValue(const FilePath &value, const QString &candidateFileName)
-{
- return filePathValue(value, QStringList(candidateFileName));
-}
-
-void SshSettings::setSshFilePath(const FilePath &ssh) { sshSettings->sshFilePath = ssh; }
-FilePath SshSettings::sshFilePath() { return filePathValue(sshSettings->sshFilePath, "ssh"); }
-
-void SshSettings::setSftpFilePath(const FilePath &sftp) { sshSettings->sftpFilePath = sftp; }
-FilePath SshSettings::sftpFilePath() { return filePathValue(sshSettings->sftpFilePath, "sftp"); }
-
-void SshSettings::setAskpassFilePath(const FilePath &askPass)
-{
- sshSettings->askpassFilePath = askPass;
-}
-
-FilePath SshSettings::askpassFilePath()
-{
- FilePath candidate;
- candidate = sshSettings->askpassFilePath;
- if (candidate.isEmpty())
- candidate = FilePath::fromString(Environment::systemEnvironment().value("SSH_ASKPASS"));
- return filePathValue(candidate, QStringList{"qtc-askpass", "ssh-askpass"});
-}
-
-void SshSettings::setKeygenFilePath(const FilePath &keygen)
-{
- sshSettings->keygenFilePath = keygen;
-}
-
-FilePath SshSettings::keygenFilePath()
-{
- return filePathValue(sshSettings->keygenFilePath, "ssh-keygen");
-}
-
-void SshSettings::setExtraSearchPathRetriever(const SearchPathRetriever &pathRetriever)
-{
- sshSettings->searchPathRetriever = pathRetriever;
-}
-
-} // namespace QSsh
diff --git a/src/libs/ssh/sshsettings.h b/src/libs/ssh/sshsettings.h
deleted file mode 100644
index 1b7c4584640..00000000000
--- a/src/libs/ssh/sshsettings.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "ssh_global.h"
-
-#include <utils/fileutils.h>
-
-#include <functional>
-
-QT_BEGIN_NAMESPACE
-class QSettings;
-QT_END_NAMESPACE
-
-namespace QSsh {
-
-class QSSH_EXPORT SshSettings
-{
-public:
- static void loadSettings(QSettings *settings);
- static void storeSettings(QSettings *settings);
-
- static void setConnectionSharingEnabled(bool share);
- static bool connectionSharingEnabled();
-
- static void setConnectionSharingTimeout(int timeInMinutes);
- static int connectionSharingTimeout();
-
- static void setSshFilePath(const Utils::FilePath &ssh);
- static Utils::FilePath sshFilePath();
-
- static void setSftpFilePath(const Utils::FilePath &sftp);
- static Utils::FilePath sftpFilePath();
-
- static void setAskpassFilePath(const Utils::FilePath &askPass);
- static Utils::FilePath askpassFilePath();
-
- static void setKeygenFilePath(const Utils::FilePath &keygen);
- static Utils::FilePath keygenFilePath();
-
- using SearchPathRetriever = std::function<Utils::FilePaths()>;
- static void setExtraSearchPathRetriever(const SearchPathRetriever &pathRetriever);
-};
-
-} // namespace QSsh
diff --git a/src/libs/tracing/qml/MainView.qml b/src/libs/tracing/qml/MainView.qml
index 5de435ef12d..c00112dee64 100644
--- a/src/libs/tracing/qml/MainView.qml
+++ b/src/libs/tracing/qml/MainView.qml
@@ -259,19 +259,21 @@ Rectangle {
hoverEnabled: enabled
z: 2
- onReleased: {
- if (selectionRange.creationState === selectionRange.creationSecondLimit) {
- content.interactive = true;
- selectionRange.creationState = selectionRange.creationFinished;
- }
- }
- onPressed: {
+ function handlePress() {
if (selectionRange.creationState === selectionRange.creationFirstLimit) {
content.interactive = false;
selectionRange.setPos(selectionRangeControl.mouseX + content.contentX);
selectionRange.creationState = selectionRange.creationSecondLimit;
}
}
+
+ onReleased: {
+ if (selectionRange.creationState === selectionRange.creationSecondLimit) {
+ content.interactive = true;
+ selectionRange.creationState = selectionRange.creationFinished;
+ }
+ }
+ onPressed: handlePress()
onPositionChanged: {
if (selectionRange.creationState === selectionRange.creationInactive)
selectionRange.creationState = selectionRange.creationFirstLimit;
@@ -280,7 +282,7 @@ Rectangle {
selectionRange.creationState !== selectionRange.creationFinished)
selectionRange.setPos(selectionRangeControl.mouseX + content.contentX);
}
- onCanceled: pressed()
+ onCanceled: handlePress()
}
Flickable {
diff --git a/src/libs/tracing/tracing_global.h b/src/libs/tracing/tracing_global.h
index 4ec75d81ee9..e1fb3472ed7 100644
--- a/src/libs/tracing/tracing_global.h
+++ b/src/libs/tracing/tracing_global.h
@@ -29,6 +29,8 @@
#if defined(TRACING_LIBRARY)
# define TRACING_EXPORT Q_DECL_EXPORT
+#elif defined(TRACING_STATIC_LIBRARY)
+# define TRACING_EXPORT
#else
# define TRACING_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt
index 780f3e2017a..ae1c91364a8 100644
--- a/src/libs/utils/CMakeLists.txt
+++ b/src/libs/utils/CMakeLists.txt
@@ -27,10 +27,10 @@ add_qtc_library(Utils
completingtextedit.cpp completingtextedit.h
cpplanguage_details.h
crumblepath.cpp crumblepath.h
- declarationmacros.h
delegates.cpp delegates.h
detailsbutton.cpp detailsbutton.h
detailswidget.cpp detailswidget.h
+ deviceshell.cpp deviceshell.h
differ.cpp differ.h
displayname.cpp displayname.h
dropsupport.cpp dropsupport.h
@@ -86,13 +86,9 @@ add_qtc_library(Utils
listutils.h
macroexpander.cpp macroexpander.h
mapreduce.h
- mimetypes/mimedatabase.cpp mimetypes/mimedatabase.h mimetypes/mimedatabase_p.h
- mimetypes/mimeglobpattern.cpp mimetypes/mimeglobpattern_p.h
- mimetypes/mimemagicrule.cpp mimetypes/mimemagicrule_p.h
- mimetypes/mimemagicrulematcher.cpp mimetypes/mimemagicrulematcher_p.h
- mimetypes/mimeprovider.cpp mimetypes/mimeprovider_p.h
- mimetypes/mimetype.cpp mimetypes/mimetype.h mimetypes/mimetype_p.h
- mimetypes/mimetypeparser.cpp mimetypes/mimetypeparser_p.h
+ mimeutils.h
+ minimizableinfobars.cpp
+ minimizableinfobars.h
multitextcursor.cpp multitextcursor.h
namevaluedictionary.cpp namevaluedictionary.h
namevaluedictionary.cpp namevaluedictionary.h
@@ -121,7 +117,10 @@ add_qtc_library(Utils
porting.h
portlist.cpp portlist.h
predicates.h
+ processenums.h
processhandle.cpp processhandle.h
+ processinfo.cpp processinfo.h
+ processinterface.cpp processinterface.h
processreaper.cpp processreaper.h
processutils.cpp processutils.h
progressindicator.cpp progressindicator.h
@@ -190,6 +189,37 @@ add_qtc_library(Utils
wizardpage.cpp wizardpage.h
)
+option(QTC_USE_NEW_MIMEDATABASE "Use updated MIME database implementation" YES)
+
+if(QTC_USE_NEW_MIMEDATABASE)
+ set(mime_prefix "mimetypes2")
+else()
+ set(mime_prefix "mimetypes")
+endif()
+
+extend_qtc_library(Utils
+ SOURCES_PREFIX ${mime_prefix}
+ PUBLIC_INCLUDES ${mime_prefix}
+ SOURCES
+ mimedatabase.cpp
+ mimedatabase.h
+ mimedatabase_p.h
+ mimeglobpattern.cpp
+ mimeglobpattern_p.h
+ mimemagicrule.cpp
+ mimemagicrule_p.h
+ mimemagicrulematcher.cpp
+ mimemagicrulematcher_p.h
+ mimeprovider.cpp
+ mimeprovider_p.h
+ mimetype.cpp
+ mimetype.h
+ mimetype_p.h
+ mimetypeparser.cpp
+ mimetypeparser_p.h
+ mimeutils.cpp
+)
+
extend_qtc_library(Utils CONDITION WIN32
SOURCES
touchbar/touchbar.cpp
diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h
index 62bcace8ef9..32ad6d3e46f 100644
--- a/src/libs/utils/algorithm.h
+++ b/src/libs/utils/algorithm.h
@@ -76,6 +76,8 @@ bool allOf(const T &container, F predicate);
/////////////////////////
template<typename T, typename F>
void erase(T &container, F predicate);
+template<typename T, typename F>
+bool eraseOne(T &container, F predicate);
/////////////////////////
// contains
@@ -442,7 +444,15 @@ void erase(T &container, F predicate)
container.erase(std::remove_if(std::begin(container), std::end(container), predicate),
std::end(container));
}
-
+template<typename T, typename F>
+bool eraseOne(T &container, F predicate)
+{
+ const auto it = std::find_if(std::begin(container), std::end(container), predicate);
+ if (it == std::end(container))
+ return false;
+ container.erase(it);
+ return true;
+}
//////////////////
// contains
@@ -1303,11 +1313,7 @@ QList<T> toList(const QSet<T> &set)
template <class Key, class T>
void addToHash(QHash<Key, T> *result, const QHash<Key, T> &additionalContents)
{
-#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
- result->unite(additionalContents);
-#else
result->insert(additionalContents);
-#endif
}
} // namespace Utils
diff --git a/src/libs/utils/ansiescapecodehandler.cpp b/src/libs/utils/ansiescapecodehandler.cpp
index cf0da7c0028..b2c15f6c6dd 100644
--- a/src/libs/utils/ansiescapecodehandler.cpp
+++ b/src/libs/utils/ansiescapecodehandler.cpp
@@ -24,7 +24,8 @@
****************************************************************************/
#include "ansiescapecodehandler.h"
-#include <utils/qtcassert.h>
+
+#include "qtcassert.h"
namespace Utils {
diff --git a/src/libs/utils/appmainwindow.cpp b/src/libs/utils/appmainwindow.cpp
index bdeb3a4cbf9..c297aead7dd 100644
--- a/src/libs/utils/appmainwindow.cpp
+++ b/src/libs/utils/appmainwindow.cpp
@@ -24,9 +24,9 @@
****************************************************************************/
#include "appmainwindow.h"
-#include "theme/theme_p.h"
#ifdef Q_OS_WIN
+#include "theme/theme_p.h"
#include <windows.h>
#endif
diff --git a/src/libs/utils/appmainwindow.h b/src/libs/utils/appmainwindow.h
index 916772a5d12..6626b904a97 100644
--- a/src/libs/utils/appmainwindow.h
+++ b/src/libs/utils/appmainwindow.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include <QMainWindow>
namespace Utils {
diff --git a/src/libs/utils/archive.cpp b/src/libs/utils/archive.cpp
index d05b49eb6f6..7893ba3fc18 100644
--- a/src/libs/utils/archive.cpp
+++ b/src/libs/utils/archive.cpp
@@ -26,16 +26,11 @@
#include "archive.h"
#include "algorithm.h"
-#include "checkablemessagebox.h"
-#include "environment.h"
-#include "mimetypes/mimedatabase.h"
+#include "mimeutils.h"
#include "qtcassert.h"
#include "qtcprocess.h"
-#include <QDir>
-#include <QPushButton>
#include <QSettings>
-#include <QTimer>
namespace Utils {
@@ -113,7 +108,7 @@ static QVector<Tool> toolsForMimeType(const MimeType &mimeType)
static QVector<Tool> toolsForFilePath(const FilePath &fp)
{
- return toolsForMimeType(Utils::mimeTypeForFile(fp));
+ return toolsForMimeType(mimeTypeForFile(fp));
}
static Utils::optional<Tool> resolveTool(const Tool &tool)
@@ -163,99 +158,47 @@ bool Archive::supportsFile(const FilePath &filePath, QString *reason)
return true;
}
-bool Archive::unarchive(const FilePath &src, const FilePath &dest, QWidget *parent)
+Archive::Archive(const FilePath &src, const FilePath &dest)
{
- Archive *archive = unarchive(src, dest);
- QTC_ASSERT(archive, return false);
-
- CheckableMessageBox box(parent);
- box.setIcon(QMessageBox::Information);
- box.setWindowTitle(tr("Unarchiving File"));
- box.setText(tr("Unzipping \"%1\" to \"%2\".").arg(src.toUserOutput(), dest.toUserOutput()));
- box.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
- box.button(QDialogButtonBox::Ok)->setEnabled(false);
- box.setCheckBoxVisible(false);
- QObject::connect(archive, &Archive::outputReceived, &box, [&box](const QString &output) {
- box.setDetailedText(box.detailedText() + output);
- });
- bool success = false;
- QObject::connect(archive, &Archive::finished, [&box, &success](bool ret) {
- box.button(QDialogButtonBox::Ok)->setEnabled(true);
- box.button(QDialogButtonBox::Cancel)->setEnabled(false);
- success = ret;
- });
- QObject::connect(&box, &QMessageBox::rejected, archive, &Archive::cancel);
- box.exec();
- return success;
+ const Utils::optional<Tool> tool = unzipTool(src, dest);
+ if (!tool)
+ return;
+ m_commandLine = tool->command;
+ m_workingDirectory = dest.absoluteFilePath();
}
-Archive *Archive::unarchive(const FilePath &src, const FilePath &dest)
-{
- const Utils::optional<Tool> tool = unzipTool(src, dest);
- QTC_ASSERT(tool, return nullptr);
+Archive::~Archive() = default;
- auto archive = new Archive;
+bool Archive::isValid() const
+{
+ return !m_commandLine.isEmpty();
+}
- const FilePath workingDirectory = dest.absolutePath();
- workingDirectory.ensureWritableDir();
+void Archive::unarchive()
+{
+ QTC_ASSERT(isValid(), return);
+ QTC_ASSERT(!m_process, return);
- archive->m_process = new QtcProcess;
- archive->m_process->setProcessChannelMode(QProcess::MergedChannels);
- QObject::connect(
- archive->m_process,
- &QtcProcess::readyReadStandardOutput,
- archive,
- [archive]() {
- if (!archive->m_process)
- return;
- emit archive->outputReceived(QString::fromUtf8(
- archive->m_process->readAllStandardOutput()));
- },
- Qt::QueuedConnection);
- QObject::connect(
- archive->m_process,
- &QtcProcess::finished,
- archive,
- [archive] {
- if (!archive->m_process)
- return;
- emit archive->finished(archive->m_process->result() == QtcProcess::FinishedWithSuccess);
- archive->m_process->deleteLater();
- archive->m_process = nullptr;
- archive->deleteLater();
- },
- Qt::QueuedConnection);
- QObject::connect(
- archive->m_process,
- &QtcProcess::errorOccurred,
- archive,
- [archive](QProcess::ProcessError) {
- if (!archive->m_process)
- return;
- emit archive->outputReceived(tr("Command failed."));
- emit archive->finished(false);
- archive->m_process->deleteLater();
- archive->m_process = nullptr;
- archive->deleteLater();
- },
- Qt::QueuedConnection);
+ m_workingDirectory.ensureWritableDir();
- QTimer::singleShot(0, archive, [archive, tool, workingDirectory] {
- emit archive->outputReceived(
- tr("Running %1\nin \"%2\".\n\n", "Running <cmd> in <workingdirectory>")
- .arg(tool->command.toUserOutput(), workingDirectory.toUserOutput()));
+ m_process.reset(new QtcProcess);
+ m_process->setProcessChannelMode(QProcess::MergedChannels);
+ QObject::connect(m_process.get(), &QtcProcess::readyReadStandardOutput, this, [this] {
+ emit outputReceived(QString::fromUtf8(m_process->readAllStandardOutput()));
+ });
+ QObject::connect(m_process.get(), &QtcProcess::done, this, [this] {
+ const bool successfulFinish = m_process->result() == ProcessResult::FinishedWithSuccess;
+ if (!successfulFinish)
+ emit outputReceived(tr("Command failed."));
+ emit finished(successfulFinish);
});
- archive->m_process->setCommand(tool->command);
- archive->m_process->setWorkingDirectory(workingDirectory);
- archive->m_process->start();
- return archive;
-}
+ emit outputReceived(tr("Running %1\nin \"%2\".\n\n", "Running <cmd> in <workingdirectory>")
+ .arg(m_commandLine.toUserOutput(), m_workingDirectory.toUserOutput()));
-void Archive::cancel()
-{
- if (m_process)
- m_process->stopProcess();
+ m_process->setCommand(m_commandLine);
+ m_process->setWorkingDirectory(m_workingDirectory);
+ m_process->start();
}
} // namespace Utils
diff --git a/src/libs/utils/archive.h b/src/libs/utils/archive.h
index 217191073a8..b129e69e664 100644
--- a/src/libs/utils/archive.h
+++ b/src/libs/utils/archive.h
@@ -27,32 +27,35 @@
#include "utils_global.h"
-#include "fileutils.h"
+#include "commandline.h"
#include <QObject>
namespace Utils {
+class FilePath;
class QtcProcess;
class QTCREATOR_UTILS_EXPORT Archive : public QObject
{
Q_OBJECT
public:
- static bool supportsFile(const FilePath &filePath, QString *reason = nullptr);
- static bool unarchive(const FilePath &src, const FilePath &dest, QWidget *parent);
- static Archive *unarchive(const FilePath &src, const FilePath &dest);
+ Archive(const FilePath &src, const FilePath &dest);
+ ~Archive();
+
+ bool isValid() const;
+ void unarchive();
- void cancel();
+ static bool supportsFile(const FilePath &filePath, QString *reason = nullptr);
signals:
void outputReceived(const QString &output);
void finished(bool success);
private:
- Archive() = default;
-
- QtcProcess *m_process = nullptr;
+ CommandLine m_commandLine;
+ FilePath m_workingDirectory;
+ std::unique_ptr<QtcProcess> m_process;
};
} // namespace Utils
diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp
index 8159903db57..79f6428a4a2 100644
--- a/src/libs/utils/aspects.cpp
+++ b/src/libs/utils/aspects.cpp
@@ -26,13 +26,12 @@
#include "aspects.h"
#include "algorithm.h"
+#include "environment.h"
#include "fancylineedit.h"
#include "layoutbuilder.h"
#include "pathchooser.h"
#include "qtcassert.h"
-#include "qtcprocess.h"
#include "qtcsettings.h"
-#include "utilsicons.h"
#include "variablechooser.h"
#include <QAction>
@@ -40,7 +39,6 @@
#include <QCheckBox>
#include <QComboBox>
#include <QDebug>
-#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
@@ -51,7 +49,6 @@
#include <QSettings>
#include <QSpinBox>
#include <QTextEdit>
-#include <QToolButton>
namespace Utils {
namespace Internal {
@@ -59,7 +56,7 @@ namespace Internal {
class BaseAspectPrivate
{
public:
- Utils::Id m_id;
+ Id m_id;
QVariant m_value;
QVariant m_defaultValue;
std::function<QVariant(const QVariant &)> m_toSettings;
@@ -82,6 +79,10 @@ public:
int m_spanY = 1;
BaseAspect::ConfigWidgetCreator m_configWidgetCreator;
QList<QPointer<QWidget>> m_subWidgets;
+
+ BaseAspect::DataCreator m_dataCreator;
+ BaseAspect::DataCloner m_dataCloner;
+ QList<BaseAspect::DataExtractor> m_dataExtractors;
};
} // Internal
@@ -110,7 +111,9 @@ public:
*/
BaseAspect::BaseAspect()
: d(new Internal::BaseAspectPrivate)
-{}
+{
+ addDataExtractor(this, &BaseAspect::value, &Data::value);
+}
/*!
Destructs a BaseAspect.
@@ -585,12 +588,6 @@ QVariant BaseAspect::fromSettingsValue(const QVariant &val) const
return d->m_fromSettings ? d->m_fromSettings(val) : val;
}
-/*!
- \internal
-*/
-void BaseAspect::acquaintSiblings(const AspectContainer &)
-{}
-
namespace Internal {
class BoolAspectPrivate
@@ -713,7 +710,7 @@ class TextDisplayPrivate
{
public:
QString m_message;
- Utils::InfoLabel::InfoType m_type;
+ InfoLabel::InfoType m_type;
QPointer<InfoLabel> m_label;
};
@@ -772,6 +769,9 @@ StringAspect::StringAspect()
{
setDefaultValue(QString());
setSpan(2, 1); // Default: Label + something
+
+ addDataExtractor(this, &StringAspect::value, &Data::value);
+ addDataExtractor(this, &StringAspect::filePath, &Data::filePath);
}
/*!
@@ -871,6 +871,11 @@ void StringAspect::setFilePath(const FilePath &value)
setValue(value.toUserOutput());
}
+void StringAspect::setDefaultFilePath(const FilePath &value)
+{
+ setDefaultValue(value.toUserOutput());
+}
+
PathChooser *StringAspect::pathChooser() const
{
return d->m_pathChooserDisplay.data();
@@ -1082,7 +1087,10 @@ void StringAspect::addToLayout(LayoutBuilder &builder)
d->m_pathChooserDisplay->setEnvironmentChange(d->m_environmentChange);
d->m_pathChooserDisplay->setBaseDirectory(d->m_baseFileName);
d->m_pathChooserDisplay->setOpenTerminalHandler(d->m_openTerminal);
- d->m_pathChooserDisplay->setFilePath(FilePath::fromUserInput(displayedString));
+ if (defaultValue() == value())
+ d->m_pathChooserDisplay->setDefaultValue(defaultValue().toString());
+ else
+ d->m_pathChooserDisplay->setFilePath(FilePath::fromUserInput(displayedString));
d->updateWidgetFromCheckStatus(this, d->m_pathChooserDisplay.data());
addLabeledItem(builder, d->m_pathChooserDisplay);
useMacroExpander(d->m_pathChooserDisplay->lineEdit());
@@ -1130,6 +1138,9 @@ void StringAspect::addToLayout(LayoutBuilder &builder)
&FancyLineEdit::textEdited,
this,
&StringAspect::setValue);
+ connect(d->m_lineEditDisplay, &FancyLineEdit::editingFinished, this, [this] {
+ setValue(d->m_lineEditDisplay->text());
+ });
}
}
if (d->m_useResetButton) {
@@ -1295,6 +1306,8 @@ BoolAspect::BoolAspect(const QString &settingsKey)
setDefaultValue(false);
setSettingsKey(settingsKey);
setSpan(2, 1);
+
+ addDataExtractor(this, &BoolAspect::value, &Data::value);
}
/*!
@@ -1749,6 +1762,8 @@ IntegerAspect::IntegerAspect()
{
setDefaultValue(qint64(0));
setSpan(2, 1);
+
+ addDataExtractor(this, &IntegerAspect::value, &Data::value);
}
/*!
@@ -1982,7 +1997,7 @@ TriState TriStateAspect::value() const
void TriStateAspect::setValue(TriState value)
{
- BaseAspect::setValue(value.toVariant());
+ SelectionAspect::setValue(value.toInt());
}
void TriStateAspect::setDefaultValue(TriState value)
@@ -2107,18 +2122,18 @@ void IntegersAspect::emitChangedValue()
QList<int> IntegersAspect::value() const
{
- return Utils::transform(BaseAspect::value().toList(),
+ return transform(BaseAspect::value().toList(),
[](QVariant v) { return v.toInt(); });
}
void IntegersAspect::setValue(const QList<int> &value)
{
- BaseAspect::setValue(Utils::transform(value, &QVariant::fromValue<int>));
+ BaseAspect::setValue(transform(value, &QVariant::fromValue<int>));
}
void IntegersAspect::setDefaultValue(const QList<int> &value)
{
- BaseAspect::setDefaultValue(Utils::transform(value, &QVariant::fromValue<int>));
+ BaseAspect::setDefaultValue(transform(value, &QVariant::fromValue<int>));
}
@@ -2240,7 +2255,7 @@ void AspectContainer::registerAspects(const AspectContainer &aspects)
*/
BaseAspect *AspectContainer::aspect(Id id) const
{
- return Utils::findOrDefault(d->m_items, Utils::equal(&BaseAspect::id, id));
+ return findOrDefault(d->m_items, equal(&BaseAspect::id, id));
}
AspectContainer::const_iterator AspectContainer::begin() const
@@ -2380,4 +2395,66 @@ void AspectContainer::forEachAspect(const std::function<void(BaseAspect *)> &run
}
}
+BaseAspect::Data::Ptr BaseAspect::extractData() const
+{
+ QTC_ASSERT(d->m_dataCreator, return {});
+ Data *data = d->m_dataCreator();
+ data->m_classId = metaObject();
+ data->m_id = id();
+ data->m_cloner = d->m_dataCloner;
+ for (const DataExtractor &extractor : d->m_dataExtractors)
+ extractor(data);
+ return Data::Ptr(data);
+}
+
+void BaseAspect::addDataExtractorHelper(const DataExtractor &extractor) const
+{
+ d->m_dataExtractors.append(extractor);
+}
+
+void BaseAspect::setDataCreatorHelper(const DataCreator &creator) const
+{
+ d->m_dataCreator = creator;
+}
+
+void BaseAspect::setDataClonerHelper(const DataCloner &cloner) const
+{
+ d->m_dataCloner = cloner;
+}
+
+const BaseAspect::Data *AspectContainerData::aspect(Id instanceId) const
+{
+ for (const BaseAspect::Data::Ptr &data : m_data) {
+ if (data.get()->id() == instanceId)
+ return data.get();
+ }
+ return nullptr;
+}
+
+const BaseAspect::Data *AspectContainerData::aspect(BaseAspect::Data::ClassId classId) const
+{
+ for (const BaseAspect::Data::Ptr &data : m_data) {
+ if (data.get()->classId() == classId)
+ return data.get();
+ }
+ return nullptr;
+}
+
+void AspectContainerData::append(const BaseAspect::Data::Ptr &data)
+{
+ m_data.append(data);
+}
+
+// BaseAspect::Data
+
+BaseAspect::Data::~Data() = default;
+
+void BaseAspect::Data::Ptr::operator=(const Ptr &other)
+{
+ if (this == &other)
+ return;
+ delete m_data;
+ m_data = other.m_data->clone();
+}
+
} // namespace Utils
diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h
index d1a0bdfe553..bb39a398cb1 100644
--- a/src/libs/utils/aspects.h
+++ b/src/libs/utils/aspects.h
@@ -25,7 +25,7 @@
#pragma once
-#include "fileutils.h"
+#include "filepath.h"
#include "id.h"
#include "infolabel.h"
#include "macroexpander.h"
@@ -68,8 +68,8 @@ public:
BaseAspect();
~BaseAspect() override;
- Utils::Id id() const;
- void setId(Utils::Id id);
+ Id id() const;
+ void setId(Id id);
QVariant value() const;
void setValue(const QVariant &value);
@@ -117,7 +117,6 @@ public:
virtual void fromMap(const QVariantMap &map);
virtual void toMap(QVariantMap &map) const;
virtual void toActiveMap(QVariantMap &map) const { toMap(map); }
- virtual void acquaintSiblings(const AspectContainer &);
virtual void addToLayout(LayoutBuilder &builder);
@@ -140,6 +139,49 @@ public:
bool isDirty() const;
bool hasAction() const;
+ class QTCREATOR_UTILS_EXPORT Data
+ {
+ public:
+ // The (unique) address of the "owning" aspect's meta object is used as identifier.
+ using ClassId = const void *;
+
+ virtual ~Data();
+
+ Id id() const { return m_id; }
+ ClassId classId() const { return m_classId; }
+ Data *clone() const { return m_cloner(this); }
+
+ QVariant value;
+
+ class Ptr {
+ public:
+ Ptr() = default;
+ explicit Ptr(const Data *data) : m_data(data) {}
+ Ptr(const Ptr &other) { m_data = other.m_data->clone(); }
+ ~Ptr() { delete m_data; }
+
+ void operator=(const Ptr &other);
+ void assign(const Data *other) { delete m_data; m_data = other; }
+
+ const Data *get() const { return m_data; }
+
+ private:
+ const Data *m_data = nullptr;
+ };
+
+ protected:
+ friend class BaseAspect;
+ Id m_id;
+ ClassId m_classId = 0;
+ std::function<Data *(const Data *)> m_cloner;
+ };
+
+ using DataCreator = std::function<Data *()>;
+ using DataCloner = std::function<Data *(const Data *)>;
+ using DataExtractor = std::function<void(Data *data)>;
+
+ Data::Ptr extractData() const;
+
signals:
void changed();
void labelLinkActivated(const QString &link);
@@ -149,6 +191,25 @@ protected:
void setupLabel();
void addLabeledItem(LayoutBuilder &builder, QWidget *widget);
+ void setDataCreatorHelper(const DataCreator &creator) const;
+ void setDataClonerHelper(const DataCloner &cloner) const;
+ void addDataExtractorHelper(const DataExtractor &extractor) const;
+
+ template <typename AspectClass, typename DataClass, typename Type>
+ void addDataExtractor(AspectClass *aspect,
+ Type(AspectClass::*p)() const,
+ Type DataClass::*q) {
+ setDataCreatorHelper([] {
+ return new DataClass;
+ });
+ setDataClonerHelper([](const Data *data) {
+ return new DataClass(*static_cast<const DataClass *>(data));
+ });
+ addDataExtractorHelper([aspect, p, q](Data *data) {
+ static_cast<DataClass *>(data)->*q = (aspect->*p)();
+ });
+ }
+
template <class Widget, typename ...Args>
Widget *createSubWidget(Args && ...args) {
auto w = new Widget(args...);
@@ -172,6 +233,11 @@ public:
explicit BoolAspect(const QString &settingsKey = QString());
~BoolAspect() override;
+ struct Data : BaseAspect::Data
+ {
+ bool value;
+ };
+
void addToLayout(LayoutBuilder &builder) override;
QAction *action() override;
@@ -280,6 +346,12 @@ public:
StringAspect();
~StringAspect() override;
+ struct Data : BaseAspect::Data
+ {
+ QString value;
+ FilePath filePath;
+ };
+
void addToLayout(LayoutBuilder &builder) override;
QVariant volatileValue() const override;
@@ -298,15 +370,15 @@ public:
void setDisplayFilter(const std::function<QString (const QString &)> &displayFilter);
void setPlaceHolderText(const QString &placeHolderText);
void setHistoryCompleter(const QString &historyCompleterKey);
- void setExpectedKind(const Utils::PathChooser::Kind expectedKind);
- void setEnvironmentChange(const Utils::EnvironmentChange &change);
- void setBaseFileName(const Utils::FilePath &baseFileName);
+ void setExpectedKind(const PathChooser::Kind expectedKind);
+ void setEnvironmentChange(const EnvironmentChange &change);
+ void setBaseFileName(const FilePath &baseFileName);
void setUndoRedoEnabled(bool readOnly);
void setAcceptRichText(bool acceptRichText);
- void setMacroExpanderProvider(const Utils::MacroExpanderProvider &expanderProvider);
+ void setMacroExpanderProvider(const MacroExpanderProvider &expanderProvider);
void setUseGlobalMacroExpander();
void setUseResetButton();
- void setValidationFunction(const Utils::FancyLineEdit::ValidationFunction &validator);
+ void setValidationFunction(const FancyLineEdit::ValidationFunction &validator);
void setOpenTerminalHandler(const std::function<void()> &openTerminal);
void setAutoApplyOnEditingFinished(bool applyOnEditingFinished);
void setElideMode(Qt::TextElideMode elideMode);
@@ -332,8 +404,9 @@ public:
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
- Utils::FilePath filePath() const;
- void setFilePath(const Utils::FilePath &value);
+ FilePath filePath() const;
+ void setFilePath(const FilePath &value);
+ void setDefaultFilePath(const FilePath &value);
PathChooser *pathChooser() const; // Avoid to use.
@@ -373,6 +446,8 @@ public:
void setSpecialValueText(const QString &specialText);
void setSingleStep(qint64 step);
+ struct Data : BaseAspect::Data { qint64 value = 0; };
+
private:
std::unique_ptr<Internal::IntegerAspectPrivate> d;
};
@@ -412,6 +487,7 @@ class QTCREATOR_UTILS_EXPORT TriState
public:
TriState() = default;
+ int toInt() const { return int(m_value); }
QVariant toVariant() const { return int(m_value); }
static TriState fromVariant(const QVariant &variant);
@@ -487,18 +563,37 @@ class QTCREATOR_UTILS_EXPORT TextDisplay : public BaseAspect
public:
TextDisplay(const QString &message = {},
- Utils::InfoLabel::InfoType type = Utils::InfoLabel::None);
+ InfoLabel::InfoType type = InfoLabel::None);
~TextDisplay() override;
void addToLayout(LayoutBuilder &builder) override;
- void setIconType(Utils::InfoLabel::InfoType t);
+ void setIconType(InfoLabel::InfoType t);
void setText(const QString &message);
private:
std::unique_ptr<Internal::TextDisplayPrivate> d;
};
+class QTCREATOR_UTILS_EXPORT AspectContainerData
+{
+public:
+ AspectContainerData() = default;
+
+ const BaseAspect::Data *aspect(Id instanceId) const;
+ const BaseAspect::Data *aspect(BaseAspect::Data::ClassId classId) const;
+
+ void append(const BaseAspect::Data::Ptr &data);
+
+ template <typename T> const typename T::Data *aspect() const
+ {
+ return static_cast<const typename T::Data *>(aspect(&T::staticMetaObject));
+ }
+
+private:
+ QList<BaseAspect::Data::Ptr> m_data; // Owned.
+};
+
class QTCREATOR_UTILS_EXPORT AspectContainer : public QObject
{
Q_OBJECT
@@ -549,9 +644,9 @@ public:
return nullptr;
}
- BaseAspect *aspect(Utils::Id id) const;
+ BaseAspect *aspect(Id id) const;
- template <typename T> T *aspect(Utils::Id id) const
+ template <typename T> T *aspect(Id id) const
{
return qobject_cast<T*>(aspect(id));
}
diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp
index 8340f08a375..6f31ec36073 100644
--- a/src/libs/utils/basetreeview.cpp
+++ b/src/libs/utils/basetreeview.cpp
@@ -25,13 +25,12 @@
#include "basetreeview.h"
+#include "algorithm.h"
#include "progressindicator.h"
+#include "qtcassert.h"
#include "qtcsettings.h"
#include "treemodel.h"
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
#include <QDebug>
#include <QFontMetrics>
#include <QHeaderView>
@@ -638,7 +637,7 @@ ItemViewEvent::ItemViewEvent(QEvent *ev, QAbstractItemView *view)
};
m_sourceModelIndex = fixIndex(m_index);
- m_selectedRows = Utils::transform(m_selectedRows, fixIndex);
+ m_selectedRows = transform(m_selectedRows, fixIndex);
}
QModelIndexList ItemViewEvent::currentOrSelectedRows() const
diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp
index f5f5f5d39a4..a23ba678dcb 100644
--- a/src/libs/utils/buildablehelperlibrary.cpp
+++ b/src/libs/utils/buildablehelperlibrary.cpp
@@ -24,10 +24,10 @@
****************************************************************************/
#include "buildablehelperlibrary.h"
+#include "environment.h"
#include "hostosinfo.h"
#include "qtcprocess.h"
-#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QRegularExpression>
@@ -48,9 +48,9 @@ FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser)
proc.setTimeoutS(1);
proc.setCommand({qtChooser, {"-print-env"}});
proc.runBlocking();
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return {};
- const QString output = proc.stdOut();
+ const QString output = proc.cleanedStdOut();
int pos = output.indexOf(toolDir);
if (pos == -1)
return {};
@@ -132,7 +132,7 @@ QString BuildableHelperLibrary::qtVersionForQMake(const FilePath &qmakePath)
qmake.setTimeoutS(5);
qmake.setCommand({qmakePath, {"--version"}});
qmake.runBlocking();
- if (qmake.result() != QtcProcess::FinishedWithSuccess) {
+ if (qmake.result() != ProcessResult::FinishedWithSuccess) {
qWarning() << qmake.exitMessage();
return QString();
}
diff --git a/src/libs/utils/buildablehelperlibrary.h b/src/libs/utils/buildablehelperlibrary.h
index 432ed27de36..8b47bef1012 100644
--- a/src/libs/utils/buildablehelperlibrary.h
+++ b/src/libs/utils/buildablehelperlibrary.h
@@ -25,11 +25,16 @@
#pragma once
-#include "environment.h"
+#include "utils_global.h"
+
#include "filepath.h"
+#include <QCoreApplication>
+
namespace Utils {
+class Environment;
+
class QTCREATOR_UTILS_EXPORT BuildableHelperLibrary
{
Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::DebuggingHelperLibrary)
diff --git a/src/libs/utils/changeset.h b/src/libs/utils/changeset.h
index 84614910db6..e74f340039a 100644
--- a/src/libs/utils/changeset.h
+++ b/src/libs/utils/changeset.h
@@ -30,7 +30,9 @@
#include <QString>
#include <QList>
-QT_FORWARD_DECLARE_CLASS(QTextCursor)
+QT_BEGIN_NAMESPACE
+class QTextCursor;
+QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/checkablemessagebox.cpp b/src/libs/utils/checkablemessagebox.cpp
index 8efb7de6032..6836f61fa37 100644
--- a/src/libs/utils/checkablemessagebox.cpp
+++ b/src/libs/utils/checkablemessagebox.cpp
@@ -26,7 +26,6 @@
#include "checkablemessagebox.h"
#include "qtcassert.h"
-#include "qtcsettings.h"
#include <QApplication>
#include <QCheckBox>
diff --git a/src/libs/utils/classnamevalidatinglineedit.cpp b/src/libs/utils/classnamevalidatinglineedit.cpp
index 86d84601645..a973122294a 100644
--- a/src/libs/utils/classnamevalidatinglineedit.cpp
+++ b/src/libs/utils/classnamevalidatinglineedit.cpp
@@ -25,9 +25,8 @@
#include "classnamevalidatinglineedit.h"
-#include <utils/qtcassert.h>
+#include "qtcassert.h"
-#include <QDebug>
#include <QRegularExpression>
/*!
diff --git a/src/libs/utils/classnamevalidatinglineedit.h b/src/libs/utils/classnamevalidatinglineedit.h
index ecbea82a804..769172b93a3 100644
--- a/src/libs/utils/classnamevalidatinglineedit.h
+++ b/src/libs/utils/classnamevalidatinglineedit.h
@@ -25,6 +25,8 @@
#pragma once
+#include "utils_global.h"
+
#include "fancylineedit.h"
namespace Utils {
diff --git a/src/libs/utils/codegeneration.cpp b/src/libs/utils/codegeneration.cpp
index e08c2d683b5..c401d38e920 100644
--- a/src/libs/utils/codegeneration.cpp
+++ b/src/libs/utils/codegeneration.cpp
@@ -27,10 +27,10 @@
#include "algorithm.h"
-#include <QTextStream>
+#include <QFileInfo>
#include <QSet>
#include <QStringList>
-#include <QFileInfo>
+#include <QTextStream>
namespace Utils {
@@ -85,7 +85,7 @@ QTCREATOR_UTILS_EXPORT void writeBeginQtVersionCheck(QTextStream &str)
static void qtSection(const QStringList &qtIncludes, QTextStream &str)
{
QStringList sorted = qtIncludes;
- Utils::sort(sorted);
+ sort(sorted);
for (const QString &inc : qAsConst(sorted)) {
if (!inc.isEmpty())
str << QStringLiteral("#include <%1>\n").arg(inc);
@@ -105,8 +105,8 @@ void writeQtIncludeSection(const QStringList &qt4,
else
trans = [](const QString &i) { return i.mid(i.indexOf(QLatin1Char('/')) + 1); };
- QSet<QString> qt4Only = Utils::transform<QSet>(qt4, trans);
- QSet<QString> qt5Only = Utils::transform<QSet>(qt5, trans);
+ QSet<QString> qt4Only = transform<QSet>(qt4, trans);
+ QSet<QString> qt5Only = transform<QSet>(qt5, trans);
if (addQtVersionCheck) {
QSet<QString> common = qt4Only;
@@ -121,23 +121,23 @@ void writeQtIncludeSection(const QStringList &qt4,
qt4Only.subtract(common);
qt5Only.subtract(common);
- qtSection(Utils::toList(common), str);
+ qtSection(toList(common), str);
if (!qt4Only.isEmpty() || !qt5Only.isEmpty()) {
if (addQtVersionCheck)
writeBeginQtVersionCheck(str);
- qtSection(Utils::toList(qt5Only), str);
+ qtSection(toList(qt5Only), str);
if (addQtVersionCheck)
str << QLatin1String("#else\n");
- qtSection(Utils::toList(qt4Only), str);
+ qtSection(toList(qt4Only), str);
if (addQtVersionCheck)
str << QLatin1String("#endif\n");
}
} else {
if (!qt5Only.isEmpty()) // default to Qt5
- qtSection(Utils::toList(qt5Only), str);
+ qtSection(toList(qt5Only), str);
else
- qtSection(Utils::toList(qt4Only), str);
+ qtSection(toList(qt4Only), str);
}
}
diff --git a/src/libs/utils/commandline.cpp b/src/libs/utils/commandline.cpp
index df3d12b463b..78f003f1979 100644
--- a/src/libs/utils/commandline.cpp
+++ b/src/libs/utils/commandline.cpp
@@ -658,6 +658,8 @@ bool ProcessArgs::prepareCommand(const CommandLine &cmdLine, QString *outCmd, Pr
const QString arguments = cmdLine.arguments();
if (env && executable.isRelativePath())
executable = env->searchInPath(executable.toString());
+ if (executable.isEmpty())
+ return false;
ProcessArgs::SplitError err;
*outArgs = ProcessArgs::prepareArgs(arguments, &err, executable.osType(), env, pwd);
if (err == ProcessArgs::SplitOk) {
@@ -670,13 +672,7 @@ bool ProcessArgs::prepareCommand(const CommandLine &cmdLine, QString *outCmd, Pr
} else {
if (err != ProcessArgs::FoundMeta)
return false;
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
*outCmd = qEnvironmentVariable("SHELL", "/bin/sh");
-#else
- // for sdktool
- *outCmd = qEnvironmentVariableIsSet("SHELL") ? QString::fromLocal8Bit(qgetenv("SHELL"))
- : QString("/bin/sh");
-#endif
*outArgs = ProcessArgs::createUnixArgs({"-c", quoteArg(executable.toString()) + ' ' + arguments});
}
}
@@ -1478,11 +1474,32 @@ void CommandLine::addCommandLineAsArgs(const CommandLine &cmd)
addArgs(cmd.splitArguments());
}
+void CommandLine::addCommandLineAsArgs(const CommandLine &cmd, RawType)
+{
+ addArg(cmd.executable().path());
+ addArgs(cmd.arguments(), Raw);
+}
+
void CommandLine::addArgs(const QString &inArgs, RawType)
{
ProcessArgs::addArgs(&m_arguments, inArgs);
}
+void CommandLine::prependArgs(const QStringList &inArgs)
+{
+ QString oldArgs = m_arguments;
+ m_arguments.clear();
+ addArgs(inArgs);
+ addArgs(oldArgs, Raw);
+}
+
+void CommandLine::prependArgs(const QString &inArgs, RawType)
+{
+ QString oldArgs = m_arguments;
+ m_arguments = inArgs;
+ addArgs(oldArgs, Raw);
+}
+
QString CommandLine::toUserOutput() const
{
QString res = m_executable.toUserOutput();
@@ -1491,6 +1508,11 @@ QString CommandLine::toUserOutput() const
return res;
}
+QString CommandLine::displayName() const
+{
+ return m_executable.displayName(m_arguments);
+}
+
QStringList CommandLine::splitArguments() const
{
return ProcessArgs::splitArgs(m_arguments, m_executable.osType());
diff --git a/src/libs/utils/commandline.h b/src/libs/utils/commandline.h
index c5408c45b12..c8476ab95ed 100644
--- a/src/libs/utils/commandline.h
+++ b/src/libs/utils/commandline.h
@@ -27,7 +27,7 @@
#include "utils_global.h"
-#include "fileutils.h"
+#include "filepath.h"
#include "hostosinfo.h"
#include <QStringList>
@@ -143,12 +143,16 @@ public:
void addArg(const QString &arg);
void addArgs(const QStringList &inArgs);
+ void addArgs(const QString &inArgs, RawType);
- void addCommandLineAsArgs(const CommandLine &cmd);
+ void prependArgs(const QStringList &inArgs);
+ void prependArgs(const QString &inArgs, RawType);
- void addArgs(const QString &inArgs, RawType);
+ void addCommandLineAsArgs(const CommandLine &cmd);
+ void addCommandLineAsArgs(const CommandLine &cmd, RawType);
QString toUserOutput() const;
+ QString displayName() const;
FilePath executable() const { return m_executable; }
void setExecutable(const FilePath &executable) { m_executable = executable; }
diff --git a/src/libs/utils/completinglineedit.h b/src/libs/utils/completinglineedit.h
index 988e0324c4f..e56ae4e3f2b 100644
--- a/src/libs/utils/completinglineedit.h
+++ b/src/libs/utils/completinglineedit.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include <QLineEdit>
namespace Utils {
diff --git a/src/libs/utils/crumblepath.cpp b/src/libs/utils/crumblepath.cpp
index a49e0c30ac1..fbf7586575d 100644
--- a/src/libs/utils/crumblepath.cpp
+++ b/src/libs/utils/crumblepath.cpp
@@ -27,8 +27,8 @@
#include "qtcassert.h"
#include "stylehelper.h"
-#include <utils/icon.h>
-#include <utils/theme/theme.h>
+#include "icon.h"
+#include "theme/theme.h"
#include <QHBoxLayout>
#include <QMenu>
diff --git a/src/libs/utils/declarationmacros.h b/src/libs/utils/declarationmacros.h
deleted file mode 100644
index 4b7b8945443..00000000000
--- a/src/libs/utils/declarationmacros.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#define UTILS_DELETE_MOVE_AND_COPY(Class) \
- Class(const Class&) = delete; \
- Class &operator=(const Class&) = delete; \
- Class(Class&&) = delete; \
- Class &operator=(Class&&) = delete;
diff --git a/src/libs/utils/delegates.cpp b/src/libs/utils/delegates.cpp
index c5e1985b288..ca42316639a 100644
--- a/src/libs/utils/delegates.cpp
+++ b/src/libs/utils/delegates.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "delegates.h"
+
#include "completinglineedit.h"
#include <QPainter>
diff --git a/src/libs/utils/delegates.h b/src/libs/utils/delegates.h
index eb9819fc7ab..17ab30ea6db 100644
--- a/src/libs/utils/delegates.h
+++ b/src/libs/utils/delegates.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include "pathchooser.h"
#include <QStyledItemDelegate>
diff --git a/src/libs/utils/detailsbutton.cpp b/src/libs/utils/detailsbutton.cpp
index 07c27d3b709..91e45b87cea 100644
--- a/src/libs/utils/detailsbutton.cpp
+++ b/src/libs/utils/detailsbutton.cpp
@@ -24,11 +24,11 @@
****************************************************************************/
#include "detailsbutton.h"
+
#include "hostosinfo.h"
#include "theme/theme.h"
#include <QGraphicsOpacityEffect>
-#include <QGuiApplication>
#include <QPropertyAnimation>
#include <QPaintEvent>
#include <QPainter>
diff --git a/src/libs/utils/detailsbutton.h b/src/libs/utils/detailsbutton.h
index 3c7286e9ee6..72702688137 100644
--- a/src/libs/utils/detailsbutton.h
+++ b/src/libs/utils/detailsbutton.h
@@ -29,7 +29,9 @@
#include <QAbstractButton>
-QT_FORWARD_DECLARE_CLASS(QGraphicsOpacityEffect)
+QT_BEGIN_NAMESPACE
+class QGraphicsOpacityEffect;
+QT_END_NAMESPACE
namespace Utils {
class QTCREATOR_UTILS_EXPORT FadingPanel : public QWidget
diff --git a/src/libs/utils/detailswidget.cpp b/src/libs/utils/detailswidget.cpp
index 1b58919c201..87d51debb29 100644
--- a/src/libs/utils/detailswidget.cpp
+++ b/src/libs/utils/detailswidget.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "detailswidget.h"
+
#include "detailsbutton.h"
#include "hostosinfo.h"
#include "theme/theme.h"
diff --git a/src/libs/utils/deviceshell.cpp b/src/libs/utils/deviceshell.cpp
new file mode 100644
index 00000000000..75a8cbb2604
--- /dev/null
+++ b/src/libs/utils/deviceshell.cpp
@@ -0,0 +1,527 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "deviceshell.h"
+
+#include "processinterface.h"
+#include "qtcassert.h"
+#include "qtcprocess.h"
+
+#include <QLoggingCategory>
+#include <QScopeGuard>
+
+Q_LOGGING_CATEGORY(deviceShellLog, "qtc.utils.deviceshell", QtWarningMsg)
+
+namespace Utils {
+
+namespace {
+
+/*!
+ * The multiplex script waits for input via stdin.
+ *
+ * To start a command, a message is send with the format "<cmd-id> "<base64-encoded-stdin-data>" <commandline>\n"
+ * To stop the script, simply send "exit\n" via stdin
+ *
+ * Once a message is received, two new streams are created that the new process redirects its output to ( $stdoutraw and $stderrraw ).
+ *
+ * These streams are piped through base64 into the two streams stdoutenc and stderrenc.
+ *
+ * Two subshells read from these base64 encoded streams, and prepend the command-id, as well as either "O:" or "E:" depending on whether its the stdout or stderr stream.
+ *
+ * Once the process exits its exit code is send to stdout with the command-id and the type "R".
+ *
+ */
+const QLatin1String r_execScript = QLatin1String(R"SCRIPT(
+#!/bin/sh
+FINAL_OUT=$(mktemp -u)
+mkfifo "$FINAL_OUT"
+
+finalOutput() {
+ local fileInputBuffer
+ while read fileInputBuffer
+ do
+ if test -f "$fileInputBuffer.err"; then
+ cat $fileInputBuffer.err
+ fi
+ cat $fileInputBuffer
+ rm -f $fileInputBuffer.err $fileInputBuffer
+ done
+}
+
+finalOutput < $FINAL_OUT &
+
+readAndMark() {
+ local buffer
+ while read buffer
+ do
+ printf '%s:%s:%s\n' "$1" "$2" "$buffer"
+ done
+}
+
+base64decode()
+{
+ base64 -d 2>/dev/null
+}
+
+base64encode()
+{
+ base64 2>/dev/null
+}
+
+executeAndMark()
+{
+ PID="$1"
+ INDATA="$2"
+ shift
+ shift
+ CMD="$@"
+
+ # LogFile
+ TMPFILE=$(mktemp)
+
+ # Output Streams
+ stdoutenc=$(mktemp -u)
+ stderrenc=$(mktemp -u)
+ mkfifo "$stdoutenc" "$stderrenc"
+
+ # app output streams
+ stdoutraw=$(mktemp -u)
+ stderrraw=$(mktemp -u)
+ mkfifo "$stdoutraw" "$stderrraw"
+
+ # Cleanup
+ trap 'rm -f "$stdoutenc" "$stderrenc" "$stdoutraw" "$stderrraw"' EXIT
+
+ # Pipe all app output through base64, and then into the output streams
+ cat $stdoutraw | base64encode > "$stdoutenc" &
+ cat $stderrraw | base64encode > "$stderrenc" &
+
+ # Mark the app's output streams
+ readAndMark $PID 'O' < "$stdoutenc" >> $TMPFILE &
+ readAndMark $PID 'E' < "$stderrenc" >> $TMPFILE.err &
+
+ # Start the app ...
+ if [ -z "$INDATA" ]
+ then
+ eval $CMD 1> "$stdoutraw" 2> "$stderrraw"
+ else
+ echo $INDATA | base64decode | eval "$CMD" 1> "$stdoutraw" 2> "$stderrraw"
+ fi
+
+ exitcode=$(echo $? | base64encode)
+ wait
+ echo "$PID:R:$exitcode" >> $TMPFILE
+ echo $TMPFILE
+}
+
+execute()
+{
+ PID="$1"
+
+ if [ "$#" -lt "3" ]; then
+ TMPFILE=$(mktemp)
+ echo "$PID:R:MjU1Cg==" > $TMPFILE
+ echo $TMPFILE
+ else
+ INDATA=$(eval echo "$2")
+ shift
+ shift
+ CMD=$@
+ executeAndMark $PID "$INDATA" "$CMD"
+ fi
+}
+
+cleanup()
+{
+ kill -- -$$
+ exit 1
+}
+
+if [ -z "$(which base64)" ]
+then
+ echo "base64 command could not be found" >&2
+ exit 1
+fi
+
+trap cleanup 1 2 3 6
+
+echo SCRIPT_INSTALLED >&2
+
+(while read -r id inData cmd; do
+ if [ "$id" = "exit" ]; then
+ exit
+ fi
+ execute $id $inData $cmd || echo "$id:R:255" &
+done) > $FINAL_OUT
+)SCRIPT");
+
+} // namespace
+
+DeviceShell::DeviceShell()
+{
+ m_thread.setObjectName("Shell Thread");
+ m_thread.start();
+}
+
+DeviceShell::~DeviceShell()
+{
+ m_shellProcess->deleteLater();
+
+ if (m_thread.isRunning()) {
+ m_thread.quit();
+ m_thread.wait();
+ }
+}
+
+/*!
+ * \brief DeviceShell::runInShell
+ * \param cmd The command to run
+ * \param stdInData Data to send to the stdin of the command
+ * \return true if the command finished with EXIT_SUCCESS(0)
+ *
+ * Runs the cmd inside the internal shell process and return whether it exited with EXIT_SUCCESS
+ *
+ * Will automatically defer to the internal thread
+ */
+bool DeviceShell::runInShell(const CommandLine &cmd, const QByteArray &stdInData)
+{
+ QTC_ASSERT(m_shellProcess, return false);
+ Q_ASSERT(QThread::currentThread() != &m_thread);
+
+ const RunResult result = run(cmd, stdInData);
+ return result.exitCode == 0;
+}
+
+/*!
+ * \brief DeviceShell::outputForRunInShell
+ * \param cmd The command to run
+ * \param stdInData Data to send to the stdin of the command
+ * \return The stdout of the command
+ *
+ * Runs a command inside the running shell and returns the stdout that was generated by it.
+ *
+ * Will automatically defer to the internal thread
+ */
+DeviceShell::RunResult DeviceShell::outputForRunInShell(const CommandLine &cmd,
+ const QByteArray &stdInData)
+{
+ QTC_ASSERT(m_shellProcess, return {});
+ Q_ASSERT(QThread::currentThread() != &m_thread);
+
+ return run(cmd, stdInData);
+}
+
+DeviceShell::State DeviceShell::state() const { return m_shellScriptState; }
+
+DeviceShell::RunResult DeviceShell::run(const CommandLine &cmd, const QByteArray &stdInData)
+{
+ const RunResult errorResult{-1, {}, {}};
+ QTC_ASSERT(m_shellProcess, return errorResult);
+ QTC_ASSERT(m_shellScriptState == State::Succeeded, return errorResult);
+
+ QMutexLocker lk(&m_commandMutex);
+
+ QWaitCondition waiter;
+ const int id = ++m_currentId;
+ const auto it = m_commandOutput.insert(id, CommandRun{{-1, {}, {}}, &waiter});
+
+ QMetaObject::invokeMethod(m_shellProcess, [this, id, &cmd, &stdInData]() {
+ const QString command = QString("%1 \"%2\" %3\n")
+ .arg(id)
+ .arg(QString::fromLatin1(stdInData.toBase64()))
+ .arg(cmd.toUserOutput());
+ qCDebug(deviceShellLog) << "Running:" << command;
+ m_shellProcess->writeRaw(command.toUtf8());
+ });
+
+ waiter.wait(&m_commandMutex);
+
+ const RunResult result = *it;
+ m_commandOutput.erase(it);
+
+ return result;
+}
+
+void DeviceShell::close()
+{
+ QTC_ASSERT(QThread::currentThread() == thread(), return );
+ QTC_ASSERT(m_thread.isRunning(), return );
+
+ m_thread.quit();
+ m_thread.wait();
+}
+
+/*!
+ * \brief DeviceShell::setupShellProcess
+ *
+ * Override this function to setup the shell process.
+ * The default implementation just sets the command line to "bash"
+ */
+void DeviceShell::setupShellProcess(QtcProcess *shellProcess)
+{
+ shellProcess->setCommand(CommandLine{"bash"});
+}
+
+/*!
+ * \brief DeviceShell::startupFailed
+ *
+ * Override to display custom error messages
+ */
+void DeviceShell::startupFailed(const CommandLine &cmdLine)
+{
+ qCWarning(deviceShellLog) << "Failed to start shell via:" << cmdLine.toUserOutput();
+}
+
+/*!
+ * \brief DeviceShell::start
+ * \return Returns true if starting the Shell process succeeded
+ *
+ * \note You have to call this function when deriving from DeviceShell. Current implementations call the function from their constructor.
+ */
+bool DeviceShell::start()
+{
+ m_shellProcess = new QtcProcess();
+ connect(m_shellProcess, &QtcProcess::done, m_shellProcess,
+ [this] { emit done(m_shellProcess->resultData()); });
+ connect(m_shellProcess, &QObject::destroyed, this, [this] { m_shellProcess = nullptr; });
+ connect(&m_thread, &QThread::finished, m_shellProcess, [this] { closeShellProcess(); });
+
+ setupShellProcess(m_shellProcess);
+
+ m_shellProcess->setProcessMode(ProcessMode::Writer);
+
+ // Moving the process into its own thread ...
+ m_shellProcess->moveToThread(&m_thread);
+
+ bool result = false;
+ QMetaObject::invokeMethod(
+ m_shellProcess,
+ [this] {
+ m_shellProcess->start();
+
+ if (!m_shellProcess->waitForStarted()) {
+ closeShellProcess();
+ return false;
+ }
+
+ connect(m_shellProcess, &QtcProcess::readyReadStandardOutput, m_shellProcess, [this] {
+ onReadyRead();
+ });
+ connect(m_shellProcess, &QtcProcess::readyReadStandardError, m_shellProcess, [this] {
+ const QByteArray stdErr = m_shellProcess->readAllStandardError();
+
+ if (m_shellScriptState == State::Unknown) {
+ if (stdErr.contains("SCRIPT_INSTALLED")) {
+ m_shellScriptState = State::Succeeded;
+ return;
+ }
+ if (stdErr.contains("ERROR_INSTALL_SCRIPT")) {
+ m_shellScriptState = State::FailedToStart;
+ qCWarning(deviceShellLog) << "Failed installing device shell script";
+ return;
+ }
+ }
+
+ qCWarning(deviceShellLog) << "Received unexpected output on stderr:" << stdErr;
+ });
+
+ connect(m_shellProcess, &QtcProcess::done, m_shellProcess, [this]() {
+ if (m_shellProcess->resultData().m_exitCode != EXIT_SUCCESS
+ || m_shellProcess->resultData().m_exitStatus != QProcess::NormalExit) {
+ qCWarning(deviceShellLog) << "Shell exited with error code:"
+ << m_shellProcess->resultData().m_exitCode << "("
+ << m_shellProcess->exitMessage() << ")";
+ }
+ });
+
+ if (!installShellScript()) {
+ closeShellProcess();
+ return false;
+ }
+
+ return true;
+ },
+ Qt::BlockingQueuedConnection,
+ &result);
+
+ if (!result) {
+ startupFailed(m_shellProcess->commandLine());
+ }
+
+ return result;
+}
+
+bool DeviceShell::installShellScript()
+{
+ const QByteArray runScriptCmd = "scriptData=$(echo "
+ + QByteArray(r_execScript.begin(), r_execScript.size()).toBase64()
+ + " | base64 -d 2>/dev/null ) && /bin/sh -c \"$scriptData\" || echo ERROR_INSTALL_SCRIPT >&2\n";
+
+ qCDebug(deviceShellLog) << "Install shell script command:" << runScriptCmd;
+ m_shellProcess->writeRaw(runScriptCmd);
+
+ while (m_shellScriptState == State::Unknown) {
+ if (!m_shellProcess->waitForReadyRead()) {
+ qCWarning(deviceShellLog) << "Timeout while waiting for device shell script to install";
+ m_shellScriptState = State::FailedToStart;
+ return false;
+ }
+ }
+ return m_shellScriptState == State::Succeeded;
+}
+
+void DeviceShell::closeShellProcess()
+{
+ if (m_shellProcess) {
+ if (m_shellProcess->isRunning()) {
+ m_shellProcess->write("exit\nexit\n");
+ if (!m_shellProcess->waitForFinished(2000))
+ m_shellProcess->terminate();
+ }
+ }
+}
+
+QByteArray::const_iterator next(const QByteArray::const_iterator &bufferEnd,
+ const QByteArray::const_iterator &itCurrent)
+{
+ for (QByteArray::const_iterator it = itCurrent; it != bufferEnd; ++it) {
+ if (*it == '\n')
+ return it;
+ }
+ return bufferEnd;
+}
+
+QByteArray byteArrayFromRange(QByteArray::const_iterator itStart, QByteArray::const_iterator itEnd)
+{
+ return QByteArray(itStart, std::distance(itStart, itEnd));
+}
+
+QList<std::tuple<int, DeviceShell::ParseType, QByteArray>> parseShellOutput(const QByteArray &data)
+{
+ auto itStart = data.cbegin();
+ const auto itEnd = data.cend();
+
+ QList<std::tuple<int, DeviceShell::ParseType, QByteArray>> result;
+
+ for (auto it = next(itEnd, itStart); it != itEnd; ++it, itStart = it, it = next(itEnd, it)) {
+ const QByteArray lineView = byteArrayFromRange(itStart, it);
+ QTC_ASSERT(lineView.size() > 0, continue);
+
+ const auto pidEnd = lineView.indexOf(':');
+ const auto typeEnd = lineView.indexOf(':', pidEnd + 1);
+
+ QTC_ASSERT(pidEnd != -1 && typeEnd != -1, continue);
+
+ bool ok = false;
+ const QLatin1String sId(lineView.begin(), pidEnd);
+ const int id = QString(sId).toInt(&ok);
+ QTC_ASSERT(ok, continue);
+
+ const QByteArray data = byteArrayFromRange(lineView.begin() + typeEnd + 1, lineView.end());
+ const QByteArray decoded = QByteArray::fromBase64(data);
+
+ DeviceShell::ParseType t;
+ char type = lineView.at(typeEnd - 1);
+ switch (type) {
+ case 'O':
+ t = DeviceShell::ParseType::StdOut;
+ break;
+ case 'E':
+ t = DeviceShell::ParseType::StdErr;
+ break;
+ case 'R':
+ t = DeviceShell::ParseType::ExitCode;
+ break;
+ default:
+ QTC_CHECK(false);
+ continue;
+ }
+
+ result.append(std::make_tuple(id, t, decoded));
+ }
+
+ return result;
+}
+
+/*!
+ * \brief DeviceShell::onReadyRead
+ *
+ * Reads lines coming from the multiplex script.
+ *
+ * The format is: "<command-id>:<type>:base64-encoded-text-or-returnvalue"
+ * The possible <type>'s are:
+ * O for stdout
+ * E for stderr
+ * R for exit code
+ *
+ * Multiple O/E messages may be received for a process. Once
+ * a single "R" is received, the exit code is reported back
+ * and no further messages from that process are expected.
+ */
+void DeviceShell::onReadyRead()
+{
+ m_commandBuffer += m_shellProcess->readAllStandardOutput();
+ const qsizetype lastLineEndIndex = m_commandBuffer.lastIndexOf('\n') + 1;
+
+ if (lastLineEndIndex == 0)
+ return;
+
+ const QByteArray input(m_commandBuffer.cbegin(), lastLineEndIndex);
+
+ const auto result = parseShellOutput(input);
+
+ QMutexLocker lk(&m_commandMutex);
+ for (const auto &line : result) {
+ const auto &[cmdId, type, data] = line;
+
+ const auto itCmd = m_commandOutput.find(cmdId);
+ QTC_ASSERT(itCmd != m_commandOutput.end(), continue);
+
+ switch (type) {
+ case Utils::DeviceShell::ParseType::StdOut:
+ itCmd->stdOut.append(data);
+ break;
+ case Utils::DeviceShell::ParseType::StdErr:
+ itCmd->stdErr.append(data);
+ break;
+ case Utils::DeviceShell::ParseType::ExitCode: {
+ bool ok = false;
+ int exitCode;
+ exitCode = QString::fromUtf8(data.begin(), data.size()).toInt(&ok);
+ QTC_ASSERT(ok, exitCode = -1);
+ itCmd->exitCode = exitCode;
+ itCmd->waiter->wakeOne();
+ break;
+ }
+ }
+ };
+
+ if (lastLineEndIndex == m_commandBuffer.size())
+ m_commandBuffer.clear();
+ else
+ m_commandBuffer = m_commandBuffer.mid(lastLineEndIndex);
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/deviceshell.h b/src/libs/utils/deviceshell.h
new file mode 100644
index 00000000000..5f285103c86
--- /dev/null
+++ b/src/libs/utils/deviceshell.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "utils_global.h"
+
+#include <QMap>
+#include <QMutex>
+#include <QProcess>
+#include <QThread>
+#include <QWaitCondition>
+
+#include <memory>
+
+namespace Utils {
+
+class CommandLine;
+class ProcessResultData;
+class QtcProcess;
+
+class DeviceShellImpl;
+
+class QTCREATOR_UTILS_EXPORT DeviceShell : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum class State { FailedToStart = -1, Unknown = 0, Succeeded = 1 };
+
+ struct RunResult
+ {
+ int exitCode = 0;
+ QByteArray stdOut;
+ QByteArray stdErr;
+ };
+
+ enum class ParseType {
+ StdOut,
+ StdErr,
+ ExitCode,
+ };
+
+ DeviceShell();
+ virtual ~DeviceShell();
+
+ bool start();
+
+ bool runInShell(const CommandLine &cmd, const QByteArray &stdInData = {});
+ RunResult outputForRunInShell(const CommandLine &cmd, const QByteArray &stdInData = {});
+
+ State state() const;
+
+signals:
+ void done(const ProcessResultData &resultData);
+
+protected:
+ virtual void startupFailed(const CommandLine &cmdLine);
+ RunResult run(const CommandLine &cmd, const QByteArray &stdInData = {});
+
+ void close();
+
+private:
+ virtual void setupShellProcess(QtcProcess *shellProcess);
+
+ bool installShellScript();
+ void closeShellProcess();
+
+ void onReadyRead();
+
+private:
+ struct CommandRun : public RunResult
+ {
+ QWaitCondition *waiter;
+ };
+
+ QtcProcess *m_shellProcess = nullptr;
+ QThread m_thread;
+ int m_currentId{0};
+
+ QMutex m_commandMutex;
+ // QMap is used here to preserve iterators
+ QMap<quint64, CommandRun> m_commandOutput;
+ QByteArray m_commandBuffer;
+
+ State m_shellScriptState = State::Unknown;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/differ.cpp b/src/libs/utils/differ.cpp
index 8eb04174e87..cd71495aa59 100644
--- a/src/libs/utils/differ.cpp
+++ b/src/libs/utils/differ.cpp
@@ -510,8 +510,8 @@ void Differ::unifiedDiffWithWhitespaceReduced(const QString &leftInput,
*/
static QString encodeExpandedWhitespace(const QString &leftEquality,
const QString &rightEquality,
- QMap<int, QPair<int, QString> > *leftCodeMap,
- QMap<int, QPair<int, QString> > *rightCodeMap,
+ QMap<int, QPair<int, QString>> *leftCodeMap,
+ QMap<int, QPair<int, QString>> *rightCodeMap,
bool *ok)
{
if (ok)
@@ -586,7 +586,7 @@ static QString encodeExpandedWhitespace(const QString &leftEquality,
* the returned value contains decoded diff list.
*/
static QList<Diff> decodeExpandedWhitespace(const QList<Diff> &input,
- const QMap<int, QPair<int, QString> > &codeMap,
+ const QMap<int, QPair<int, QString>> &codeMap,
bool *ok)
{
if (ok)
@@ -651,16 +651,16 @@ static bool diffWithWhitespaceExpandedInEqualities(const QList<Diff> &leftInput,
QString leftText;
QString rightText;
- QMap<int, QPair<int, QString> > commonLeftCodeMap;
- QMap<int, QPair<int, QString> > commonRightCodeMap;
+ QMap<int, QPair<int, QString>> commonLeftCodeMap;
+ QMap<int, QPair<int, QString>> commonRightCodeMap;
while (l <= leftCount && r <= rightCount) {
const Diff leftDiff = l < leftCount ? leftInput.at(l) : Diff(Diff::Equal);
const Diff rightDiff = r < rightCount ? rightInput.at(r) : Diff(Diff::Equal);
if (leftDiff.command == Diff::Equal && rightDiff.command == Diff::Equal) {
- QMap<int, QPair<int, QString> > leftCodeMap;
- QMap<int, QPair<int, QString> > rightCodeMap;
+ QMap<int, QPair<int, QString>> leftCodeMap;
+ QMap<int, QPair<int, QString>> rightCodeMap;
bool ok = false;
const QString &commonEquality = encodeExpandedWhitespace(leftDiff.text,
diff --git a/src/libs/utils/differ.h b/src/libs/utils/differ.h
index 58e56d683f2..a9667c25bf0 100644
--- a/src/libs/utils/differ.h
+++ b/src/libs/utils/differ.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include <QString>
QT_BEGIN_NAMESPACE
diff --git a/src/libs/utils/dropsupport.cpp b/src/libs/utils/dropsupport.cpp
index 7a0a2b4b4e1..a4beda8f4a0 100644
--- a/src/libs/utils/dropsupport.cpp
+++ b/src/libs/utils/dropsupport.cpp
@@ -39,7 +39,7 @@
namespace Utils {
-static bool isFileDrop(const QMimeData *d, QList<DropSupport::FileSpec> *files = nullptr)
+static bool isFileDropMime(const QMimeData *d, QList<DropSupport::FileSpec> *files = nullptr)
{
// internal drop
if (const auto internalData = qobject_cast<const DropMimeData *>(d)) {
@@ -94,7 +94,7 @@ QStringList DropSupport::mimeTypesForFilePaths()
bool DropSupport::isFileDrop(QDropEvent *event)
{
- return Utils::isFileDrop(event->mimeData());
+ return isFileDropMime(event->mimeData());
}
bool DropSupport::isValueDrop(QDropEvent *event)
@@ -125,7 +125,7 @@ bool DropSupport::eventFilter(QObject *obj, QEvent *event)
if (!m_filterFunction || m_filterFunction(de, this)) {
const auto fileDropMimeData = qobject_cast<const DropMimeData *>(de->mimeData());
QList<FileSpec> tempFiles;
- if (Utils::isFileDrop(de->mimeData(), &tempFiles)) {
+ if (isFileDropMime(de->mimeData(), &tempFiles)) {
event->accept();
accepted = true;
if (fileDropMimeData && fileDropMimeData->isOverridingFileDropAction())
diff --git a/src/libs/utils/dropsupport.h b/src/libs/utils/dropsupport.h
index c545045a450..29e5a2cef10 100644
--- a/src/libs/utils/dropsupport.h
+++ b/src/libs/utils/dropsupport.h
@@ -60,7 +60,7 @@ public:
static QStringList mimeTypesForFilePaths();
signals:
- void filesDropped(const QList<Utils::DropSupport::FileSpec> &files, const QPoint &dropPos);
+ void filesDropped(const QList<DropSupport::FileSpec> &files, const QPoint &dropPos);
void valuesDropped(const QList<QVariant> &values, const QPoint &dropPos);
public:
diff --git a/src/libs/utils/elfreader.cpp b/src/libs/utils/elfreader.cpp
index 1883585bc86..c535b46c34f 100644
--- a/src/libs/utils/elfreader.cpp
+++ b/src/libs/utils/elfreader.cpp
@@ -24,10 +24,10 @@
****************************************************************************/
#include "elfreader.h"
+
#include "qtcassert.h"
#include <QDir>
-#include <QDebug>
#include <QtEndian>
#include <new> // std::bad_alloc
diff --git a/src/libs/utils/elfreader.h b/src/libs/utils/elfreader.h
index 2f52938b6f1..8e7d808f237 100644
--- a/src/libs/utils/elfreader.h
+++ b/src/libs/utils/elfreader.h
@@ -83,6 +83,7 @@ enum ElfEndian
enum ElfClass
{
+ Elf_ELFCLASSNONE = 0,
Elf_ELFCLASS32 = 1,
Elf_ELFCLASS64 = 2
};
@@ -98,6 +99,7 @@ enum ElfType
enum ElfMachine
{
+ Elf_EM_NONE = 0,
Elf_EM_386 = 3,
Elf_EM_ARM = 40,
Elf_EM_X86_64 = 62
@@ -142,10 +144,10 @@ public:
int indexOf(const QByteArray &name) const;
public:
- ElfEndian endian;
- ElfType elftype;
- ElfMachine elfmachine;
- ElfClass elfclass;
+ ElfEndian endian = Elf_ELFDATANONE;
+ ElfType elftype = Elf_ET_NONE;
+ ElfMachine elfmachine = Elf_EM_NONE;
+ ElfClass elfclass = Elf_ELFCLASSNONE;
quint64 entryPoint = 0;
QByteArray debugLink;
QByteArray buildId;
diff --git a/src/libs/utils/elidinglabel.cpp b/src/libs/utils/elidinglabel.cpp
index 24299bd8cc3..5f0e1cae0d8 100644
--- a/src/libs/utils/elidinglabel.cpp
+++ b/src/libs/utils/elidinglabel.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "elidinglabel.h"
+
#include <QFontMetrics>
#include <QPainter>
#include <QStyle>
@@ -57,7 +58,7 @@ void ElidingLabel::setElideMode(const Qt::TextElideMode &elideMode)
{
m_elideMode = elideMode;
if (elideMode == Qt::ElideNone)
- setToolTip({});
+ updateToolTip({});
setSizePolicy(QSizePolicy(
m_elideMode == Qt::ElideNone ? QSizePolicy::Preferred : QSizePolicy::Ignored,
@@ -66,10 +67,21 @@ void ElidingLabel::setElideMode(const Qt::TextElideMode &elideMode)
update();
}
+QString ElidingLabel::additionalToolTip()
+{
+ return m_additionalToolTip;
+}
+
+void ElidingLabel::setAdditionalToolTip(const QString &additionalToolTip)
+{
+ m_additionalToolTip = additionalToolTip;
+}
+
void ElidingLabel::paintEvent(QPaintEvent *)
{
if (m_elideMode == Qt::ElideNone) {
QLabel::paintEvent(nullptr);
+ updateToolTip({});
return;
}
@@ -78,10 +90,10 @@ void ElidingLabel::paintEvent(QPaintEvent *)
QFontMetrics fm = fontMetrics();
QString txt = text();
if (txt.length() > 4 && fm.horizontalAdvance(txt) > contents.width()) {
- setToolTip(txt);
+ updateToolTip(txt);
txt = fm.elidedText(txt, m_elideMode, contents.width());
} else {
- setToolTip(QString());
+ updateToolTip(QString());
}
int flags = QStyle::visualAlignment(layoutDirection(), alignment()) | Qt::TextSingleLine;
@@ -90,4 +102,29 @@ void ElidingLabel::paintEvent(QPaintEvent *)
painter.drawText(contents, flags, txt);
}
+void ElidingLabel::updateToolTip(const QString &elidedText)
+{
+ if (m_additionalToolTip.isEmpty()) {
+ setToolTip(elidedText);
+ return;
+ }
+
+ if (elidedText.isEmpty()) {
+ setToolTip(m_additionalToolTip);
+ return;
+ }
+
+ setToolTip(elidedText + m_additionalToolTipSeparator + m_additionalToolTip);
+}
+
+QString ElidingLabel::additionalToolTipSeparator() const
+{
+ return m_additionalToolTipSeparator;
+}
+
+void ElidingLabel::setAdditionalToolTipSeparator(const QString &newAdditionalToolTipSeparator)
+{
+ m_additionalToolTipSeparator = newAdditionalToolTipSeparator;
+}
+
} // namespace Utils
diff --git a/src/libs/utils/elidinglabel.h b/src/libs/utils/elidinglabel.h
index 6a8bd231954..d84487187db 100644
--- a/src/libs/utils/elidinglabel.h
+++ b/src/libs/utils/elidinglabel.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include <QLabel>
namespace Utils {
@@ -34,6 +35,8 @@ class QTCREATOR_UTILS_EXPORT ElidingLabel : public QLabel
{
Q_OBJECT
Q_PROPERTY(Qt::TextElideMode elideMode READ elideMode WRITE setElideMode DESIGNABLE true)
+ Q_PROPERTY(QString additionalToolTip READ additionalToolTip WRITE setAdditionalToolTip DESIGNABLE true)
+ Q_PROPERTY(QString additionalToolTipSeparator READ additionalToolTipSeparator WRITE setAdditionalToolTipSeparator DESIGNABLE true)
public:
explicit ElidingLabel(QWidget *parent = nullptr);
@@ -42,11 +45,20 @@ public:
Qt::TextElideMode elideMode() const;
void setElideMode(const Qt::TextElideMode &elideMode);
+ QString additionalToolTip();
+ void setAdditionalToolTip(const QString& additionalToolTip);
+
+ QString additionalToolTipSeparator() const;
+ void setAdditionalToolTipSeparator(const QString &newAdditionalToolTipSeparator);
+
protected:
void paintEvent(QPaintEvent *event) override;
+ void updateToolTip(const QString& elidedText);
private:
Qt::TextElideMode m_elideMode;
+ QString m_additionalToolTip;
+ QString m_additionalToolTipSeparator{"\n\n"};
};
} // namespace Utils
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index 7b0a48c6a8b..3220fe4a83b 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -26,26 +26,34 @@
#include "environment.h"
#include "algorithm.h"
+#include "fileutils.h"
#include "qtcassert.h"
-#include "stringutils.h"
-#include <QDebug>
#include <QDir>
#include <QProcessEnvironment>
#include <QSet>
-#include <QCoreApplication>
-Q_GLOBAL_STATIC_WITH_ARGS(Utils::Environment, staticSystemEnvironment,
+namespace Utils {
+
+Q_GLOBAL_STATIC_WITH_ARGS(Environment, staticSystemEnvironment,
(QProcessEnvironment::systemEnvironment().toStringList()))
-Q_GLOBAL_STATIC(QVector<Utils::EnvironmentProvider>, environmentProviders)
+Q_GLOBAL_STATIC(QVector<EnvironmentProvider>, environmentProviders)
-namespace Utils {
+NameValueItems Environment::diff(const Environment &other, bool checkAppendPrepend) const
+{
+ return m_dict.diff(other.m_dict, checkAppendPrepend);
+}
+
+int Environment::isValid() const
+{
+ return m_dict.size() != 0;
+}
QProcessEnvironment Environment::toProcessEnvironment() const
{
QProcessEnvironment result;
- for (auto it = m_values.constBegin(); it != m_values.constEnd(); ++it) {
+ for (auto it = m_dict.m_values.constBegin(); it != m_dict.m_values.constEnd(); ++it) {
if (it.value().second)
result.insert(it.key().name, expandedValueForKey(key(it)));
}
@@ -54,28 +62,28 @@ QProcessEnvironment Environment::toProcessEnvironment() const
void Environment::appendOrSetPath(const FilePath &value)
{
- QTC_CHECK(value.osType() == m_osType);
+ QTC_CHECK(value.osType() == osType());
if (value.isEmpty())
return;
appendOrSet("PATH", value.nativePath(),
- QString(OsSpecificAspects::pathListSeparator(m_osType)));
+ QString(OsSpecificAspects::pathListSeparator(osType())));
}
void Environment::prependOrSetPath(const FilePath &value)
{
- QTC_CHECK(value.osType() == m_osType);
+ QTC_CHECK(value.osType() == osType());
if (value.isEmpty())
return;
prependOrSet("PATH", value.nativePath(),
- QString(OsSpecificAspects::pathListSeparator(m_osType)));
+ QString(OsSpecificAspects::pathListSeparator(osType())));
}
void Environment::appendOrSet(const QString &key, const QString &value, const QString &sep)
{
QTC_ASSERT(!key.contains('='), return );
- const auto it = findKey(key);
- if (it == m_values.end()) {
- m_values.insert(DictKey(key, nameCaseSensitivity()), qMakePair(value, true));
+ const auto it = m_dict.findKey(key);
+ if (it == m_dict.m_values.end()) {
+ m_dict.m_values.insert(DictKey(key, m_dict.nameCaseSensitivity()), qMakePair(value, true));
} else {
// Append unless it is already there
const QString toAppend = sep + value;
@@ -87,9 +95,9 @@ void Environment::appendOrSet(const QString &key, const QString &value, const QS
void Environment::prependOrSet(const QString &key, const QString &value, const QString &sep)
{
QTC_ASSERT(!key.contains('='), return );
- const auto it = findKey(key);
- if (it == m_values.end()) {
- m_values.insert(DictKey(key, nameCaseSensitivity()), qMakePair(value, true));
+ const auto it = m_dict.findKey(key);
+ if (it == m_dict.m_values.end()) {
+ m_dict.m_values.insert(DictKey(key, m_dict.nameCaseSensitivity()), qMakePair(value, true));
} else {
// Prepend unless it is already there
const QString toPrepend = value + sep;
@@ -100,8 +108,8 @@ void Environment::prependOrSet(const QString &key, const QString &value, const Q
void Environment::prependOrSetLibrarySearchPath(const FilePath &value)
{
- QTC_CHECK(value.osType() == m_osType);
- switch (m_osType) {
+ QTC_CHECK(value.osType() == osType());
+ switch (osType()) {
case OsTypeWindows: {
const QChar sep = ';';
prependOrSet("PATH", value.nativePath(), QString(sep));
@@ -127,7 +135,7 @@ void Environment::prependOrSetLibrarySearchPath(const FilePath &value)
void Environment::prependOrSetLibrarySearchPaths(const FilePaths &values)
{
- Utils::reverseForeach(values, [this](const FilePath &value) {
+ reverseForeach(values, [this](const FilePath &value) {
prependOrSetLibrarySearchPath(value);
});
}
@@ -139,8 +147,8 @@ Environment Environment::systemEnvironment()
void Environment::setupEnglishOutput()
{
- set("LC_MESSAGES", "en_US.utf8");
- set("LANGUAGE", "en_US:en");
+ m_dict.set("LC_MESSAGES", "en_US.utf8");
+ m_dict.set("LANGUAGE", "en_US:en");
}
static FilePath searchInDirectory(const QStringList &execs,
@@ -168,7 +176,7 @@ QStringList Environment::appendExeExtensions(const QString &executable) const
{
QStringList execs(executable);
const QFileInfo fi(executable);
- if (m_osType == OsTypeWindows) {
+ if (osType() == OsTypeWindows) {
// Check all the executable extensions on windows:
// PATHEXT is only used if the executable has no extension
if (fi.suffix().isEmpty()) {
@@ -204,7 +212,7 @@ bool Environment::isSameExecutable(const QString &exe1, const QString &exe2) con
QString Environment::expandedValueForKey(const QString &key) const
{
- return expandVariables(value(key));
+ return expandVariables(m_dict.value(key));
}
static FilePath searchInDirectoriesHelper(const Environment &env,
@@ -310,7 +318,7 @@ FilePaths Environment::path() const
FilePaths Environment::pathListValue(const QString &varName) const
{
const QStringList pathComponents = expandedValueForKey(varName).split(
- OsSpecificAspects::pathListSeparator(m_osType), SkipEmptyParts);
+ OsSpecificAspects::pathListSeparator(osType()), Qt::SkipEmptyParts);
return transform(pathComponents, &FilePath::fromUserInput);
}
@@ -335,12 +343,12 @@ QString Environment::expandVariables(const QString &input) const
{
QString result = input;
- if (m_osType == OsTypeWindows) {
+ if (osType() == OsTypeWindows) {
for (int vStart = -1, i = 0; i < result.length(); ) {
if (result.at(i++) == '%') {
if (vStart > 0) {
- const auto it = findKey(result.mid(vStart, i - vStart - 1));
- if (it != m_values.constEnd()) {
+ const auto it = m_dict.findKey(result.mid(vStart, i - vStart - 1));
+ if (it != m_dict.m_values.constEnd()) {
result.replace(vStart - 1, i - vStart + 1, it->first);
i = vStart - 1 + it->first.length();
vStart = -1;
@@ -407,7 +415,7 @@ FilePath Environment::expandVariables(const FilePath &variables) const
QStringList Environment::expandVariables(const QStringList &variables) const
{
- return Utils::transform(variables, [this](const QString &i) { return expandVariables(i); });
+ return transform(variables, [this](const QString &i) { return expandVariables(i); });
}
void EnvironmentProvider::addProvider(EnvironmentProvider &&provider)
@@ -430,44 +438,61 @@ optional<EnvironmentProvider> EnvironmentProvider::provider(const QByteArray &id
void EnvironmentChange::addSetValue(const QString &key, const QString &value)
{
- m_changeItems.append([key, value](Environment &env) { env.set(key, value); });
+ m_changeItems.append({Item::SetValue, QVariant::fromValue(QPair<QString, QString>(key, value))});
}
void EnvironmentChange::addUnsetValue(const QString &key)
{
- m_changeItems.append([key](Environment &env) { env.unset(key); });
+ m_changeItems.append({Item::UnsetValue, key});
}
void EnvironmentChange::addPrependToPath(const FilePaths &values)
{
for (int i = values.size(); --i >= 0; ) {
const FilePath value = values.at(i);
- m_changeItems.append([value](Environment &env) { env.prependOrSetPath(value); });
+ m_changeItems.append({Item::PrependToPath, value.toVariant()});
}
}
void EnvironmentChange::addAppendToPath(const FilePaths &values)
{
for (const FilePath &value : values)
- m_changeItems.append([value](Environment &env) { env.appendOrSetPath(value); });
-}
-
-void EnvironmentChange::addModify(const NameValueItems &items)
-{
- m_changeItems.append([items](Environment &env) { env.modify(items); });
+ m_changeItems.append({Item::AppendToPath, value.toVariant()});
}
EnvironmentChange EnvironmentChange::fromFixedEnvironment(const Environment &fixedEnv)
{
EnvironmentChange change;
- change.m_changeItems.append([fixedEnv](Environment &env) { env = fixedEnv; });
+ change.m_changeItems.append({Item::SetFixedEnvironment, QVariant::fromValue(fixedEnv)});
return change;
}
void EnvironmentChange::applyToEnvironment(Environment &env) const
{
- for (const Item &item : m_changeItems)
- item(env);
+ for (const Item &item : m_changeItems) {
+ switch (item.type) {
+ case Item::SetSystemEnvironment:
+ env = Environment::systemEnvironment();
+ break;
+ case Item::SetFixedEnvironment:
+ env = item.data.value<Environment>();
+ break;
+ case Item::SetValue: {
+ auto data = item.data.value<QPair<QString, QString>>();
+ env.set(data.first, data.second);
+ break;
+ }
+ case Item::UnsetValue:
+ env.unset(item.data.toString());
+ break;
+ case Item::PrependToPath:
+ env.prependOrSetPath(FilePath::fromVariant(item.data));
+ break;
+ case Item::AppendToPath:
+ env.appendOrSetPath(FilePath::fromVariant(item.data));
+ break;
+ }
+ }
}
} // namespace Utils
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index 0f150299f32..13fab9605f2 100644
--- a/src/libs/utils/environment.h
+++ b/src/libs/utils/environment.h
@@ -25,37 +25,52 @@
#pragma once
-#include "fileutils.h"
-#include "hostosinfo.h"
+#include "utils_global.h"
+
+#include "environmentfwd.h"
+#include "filepath.h"
#include "namevaluedictionary.h"
-#include "namevalueitem.h"
#include "optional.h"
-#include <QStringList>
-
#include <functional>
-QT_FORWARD_DECLARE_CLASS(QProcessEnvironment)
+QT_BEGIN_NAMESPACE
+class QProcessEnvironment;
+QT_END_NAMESPACE
namespace Utils {
-class QTCREATOR_UTILS_EXPORT Environment final : public NameValueDictionary
+class QTCREATOR_UTILS_EXPORT Environment final
{
public:
- using NameValueDictionary::NameValueDictionary;
+ Environment() : m_dict(HostOsInfo::hostOs()) {}
+ explicit Environment(OsType osType) : m_dict(osType) {}
+ explicit Environment(const QStringList &env, OsType osType = HostOsInfo::hostOs())
+ : m_dict(env, osType) {}
+ explicit Environment(const NameValuePairs &nameValues) : m_dict(nameValues) {}
+ explicit Environment(const NameValueDictionary &dict) : m_dict(dict) {}
- static Environment systemEnvironment();
+ QString value(const QString &key) const { return m_dict.value(key); }
+ bool hasKey(const QString &key) const { return m_dict.hasKey(key); }
+
+ void set(const QString &key, const QString &value, bool enabled = true) { m_dict.set(key, value, enabled); }
+ void unset(const QString &key) { m_dict.unset(key); }
+ void modify(const NameValueItems &items) { m_dict.modify(items); }
+
+ int isValid() const;
+ void clear() { return m_dict.clear(); }
+ QStringList toStringList() const { return m_dict.toStringList(); }
QProcessEnvironment toProcessEnvironment() const;
void appendOrSet(const QString &key, const QString &value, const QString &sep = QString());
void prependOrSet(const QString &key, const QString &value, const QString &sep = QString());
- void appendOrSetPath(const Utils::FilePath &value);
- void prependOrSetPath(const Utils::FilePath &value);
+ void appendOrSetPath(const FilePath &value);
+ void prependOrSetPath(const FilePath &value);
- void prependOrSetLibrarySearchPath(const Utils::FilePath &value);
- void prependOrSetLibrarySearchPaths(const Utils::FilePaths &values);
+ void prependOrSetLibrarySearchPath(const FilePath &value);
+ void prependOrSetLibrarySearchPaths(const FilePaths &values);
void setupEnglishOutput();
@@ -80,27 +95,69 @@ public:
FilePath expandVariables(const FilePath &input) const;
QStringList expandVariables(const QStringList &input) const;
+ OsType osType() const { return m_dict.osType(); }
+ QString userName() const;
+
+ using const_iterator = NameValueMap::const_iterator; // FIXME: avoid
+ NameValueDictionary toDictionary() const { return m_dict; } // FIXME: avoid
+ NameValueItems diff(const Environment &other, bool checkAppendPrepend = false) const; // FIXME: avoid
+
+ QString key(const_iterator it) const { return m_dict.key(it); } // FIXME: avoid
+ QString value(const_iterator it) const { return m_dict.value(it); } // FIXME: avoid
+ bool isEnabled(const_iterator it) const { return m_dict.isEnabled(it); } // FIXME: avoid
+
+ const_iterator constBegin() const { return m_dict.constBegin(); } // FIXME: avoid
+ const_iterator constEnd() const { return m_dict.constEnd(); } // FIXME: avoid
+ const_iterator constFind(const QString &name) const { return m_dict.constFind(name); } // FIXME: avoid
+
+ friend bool operator!=(const Environment &first, const Environment &second)
+ {
+ return first.m_dict != second.m_dict;
+ }
+
+ friend bool operator==(const Environment &first, const Environment &second)
+ {
+ return first.m_dict == second.m_dict;
+ }
+
+ static Environment systemEnvironment();
+
static void modifySystemEnvironment(const EnvironmentItems &list); // use with care!!!
static void setSystemEnvironment(const Environment &environment); // don't use at all!!!
+
+private:
+ NameValueDictionary m_dict;
};
class QTCREATOR_UTILS_EXPORT EnvironmentChange final
{
public:
- using Item = std::function<void(Environment &)>;
-
EnvironmentChange() = default;
+ class Item final
+ {
+ public:
+ enum Type {
+ SetSystemEnvironment,
+ SetFixedEnvironment,
+ SetValue,
+ UnsetValue,
+ PrependToPath,
+ AppendToPath,
+ };
+
+ Type type;
+ QVariant data;
+ };
+
static EnvironmentChange fromFixedEnvironment(const Environment &fixedEnv);
void applyToEnvironment(Environment &) const;
void addSetValue(const QString &key, const QString &value);
void addUnsetValue(const QString &key);
- void addPrependToPath(const Utils::FilePaths &values);
- void addAppendToPath(const Utils::FilePaths &values);
- void addModify(const NameValueItems &items);
- void addChange(const Item &item) { m_changeItems.append(item); }
+ void addPrependToPath(const FilePaths &values);
+ void addAppendToPath(const FilePaths &values);
private:
QList<Item> m_changeItems;
@@ -119,3 +176,5 @@ public:
};
} // namespace Utils
+
+Q_DECLARE_METATYPE(Utils::Environment)
diff --git a/src/libs/utils/environmentdialog.cpp b/src/libs/utils/environmentdialog.cpp
index 7a8b8f588fa..9f70d2364f7 100644
--- a/src/libs/utils/environmentdialog.cpp
+++ b/src/libs/utils/environmentdialog.cpp
@@ -25,13 +25,7 @@
#include "environmentdialog.h"
-#include <utils/environment.h>
-#include <utils/hostosinfo.h>
-
-#include <QVBoxLayout>
-#include <QDialogButtonBox>
-#include <QPlainTextEdit>
-#include <QLabel>
+#include "environment.h"
namespace Utils {
diff --git a/src/libs/utils/environmentdialog.h b/src/libs/utils/environmentdialog.h
index 6dbb38e1917..c6cdc5241aa 100644
--- a/src/libs/utils/environmentdialog.h
+++ b/src/libs/utils/environmentdialog.h
@@ -25,7 +25,9 @@
#pragma once
-#include "environment.h"
+#include "utils_global.h"
+
+#include "environmentfwd.h"
#include "namevaluesdialog.h"
#include <thread>
diff --git a/src/libs/utils/environmentmodel.cpp b/src/libs/utils/environmentmodel.cpp
index c7efcce9300..d7938a4fdae 100644
--- a/src/libs/utils/environmentmodel.cpp
+++ b/src/libs/utils/environmentmodel.cpp
@@ -25,20 +25,18 @@
#include "environmentmodel.h"
-#include <utils/algorithm.h>
-#include <utils/environment.h>
-#include <utils/hostosinfo.h>
-
-#include <QString>
-#include <QFont>
+#include "environment.h"
namespace Utils {
-const Environment &EnvironmentModel::baseEnvironment() const
+
+Environment EnvironmentModel::baseEnvironment() const
{
- return static_cast<const Environment &>(baseNameValueDictionary());
+ return Environment(baseNameValueDictionary());
}
+
void EnvironmentModel::setBaseEnvironment(const Environment &env)
{
- setBaseNameValueDictionary(env);
+ setBaseNameValueDictionary(env.toDictionary());
}
+
} // namespace Utils
diff --git a/src/libs/utils/environmentmodel.h b/src/libs/utils/environmentmodel.h
index ac5f017448c..b64518b6ae9 100644
--- a/src/libs/utils/environmentmodel.h
+++ b/src/libs/utils/environmentmodel.h
@@ -25,6 +25,8 @@
#pragma once
+#include "utils_global.h"
+
#include "namevaluemodel.h"
namespace Utils {
@@ -34,7 +36,7 @@ class QTCREATOR_UTILS_EXPORT EnvironmentModel : public NameValueModel
Q_OBJECT
public:
- const Environment &baseEnvironment() const;
+ Environment baseEnvironment() const;
void setBaseEnvironment(const Environment &env);
};
diff --git a/src/libs/utils/execmenu.cpp b/src/libs/utils/execmenu.cpp
index 02057e8c08d..f5f6465a9dd 100644
--- a/src/libs/utils/execmenu.cpp
+++ b/src/libs/utils/execmenu.cpp
@@ -25,7 +25,6 @@
#include "execmenu.h"
-#include <QApplication>
#include <QMenu>
#include <QPoint>
#include <QRect>
diff --git a/src/libs/utils/fadingindicator.h b/src/libs/utils/fadingindicator.h
index 5f4e96436c4..eed2efdfc55 100644
--- a/src/libs/utils/fadingindicator.h
+++ b/src/libs/utils/fadingindicator.h
@@ -27,8 +27,10 @@
#include "utils_global.h"
-#include <QString>
-#include <QWidget>
+QT_BEGIN_NAMESPACE
+class QString;
+class QWidget;
+QT_END_NAMESPACE
namespace Utils {
namespace FadingIndicator {
diff --git a/src/libs/utils/fancylineedit.cpp b/src/libs/utils/fancylineedit.cpp
index 45d8e3ea109..5ade63e4b0e 100644
--- a/src/libs/utils/fancylineedit.cpp
+++ b/src/libs/utils/fancylineedit.cpp
@@ -23,18 +23,16 @@
**
****************************************************************************/
+#include "fancylineedit.h"
+
#include "camelcasecursor.h"
#include "execmenu.h"
-#include "fancylineedit.h"
#include "historycompleter.h"
#include "hostosinfo.h"
#include "optional.h"
#include "qtcassert.h"
-#include "stylehelper.h"
#include "utilsicons.h"
-#include <QAbstractItemView>
-#include <QDebug>
#include <QKeyEvent>
#include <QKeySequence>
#include <QMenu>
@@ -42,6 +40,8 @@
#include <QStylePainter>
#include <QPropertyAnimation>
#include <QStyle>
+#include <QStyleOptionFocusRect>
+#include <QValidator>
#include <QWindow>
/*!
diff --git a/src/libs/utils/fancylineedit.h b/src/libs/utils/fancylineedit.h
index 13127f08823..1a90a7ce24a 100644
--- a/src/libs/utils/fancylineedit.h
+++ b/src/libs/utils/fancylineedit.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include "completinglineedit.h"
#include <QAbstractButton>
@@ -140,7 +141,7 @@ protected:
void keyPressEvent(QKeyEvent *event) override;
signals:
- void buttonClicked(Utils::FancyLineEdit::Side side);
+ void buttonClicked(FancyLineEdit::Side side);
void leftButtonClicked();
void rightButtonClicked();
diff --git a/src/libs/utils/fancymainwindow.cpp b/src/libs/utils/fancymainwindow.cpp
index a18fa48520f..f975212d868 100644
--- a/src/libs/utils/fancymainwindow.cpp
+++ b/src/libs/utils/fancymainwindow.cpp
@@ -42,7 +42,6 @@
#include <QStyle>
#include <QStyleOption>
#include <QTimer>
-#include <QToolButton>
static const char AutoHideTitleBarsKey[] = "AutoHideTitleBars";
static const char ShowCentralWidgetKey[] = "ShowCentralWidget";
@@ -255,7 +254,7 @@ DockWidget::DockWidget(QWidget *inner, FancyMainWindow *parent, bool immutable)
QString title = inner->windowTitle();
toggleViewAction()->setProperty("original_title", title);
- title = Utils::stripAccelerator(title);
+ title = stripAccelerator(title);
setWindowTitle(title);
QStyleOptionDockWidget opt;
@@ -548,7 +547,7 @@ void FancyMainWindow::addDockActionsToMenu(QMenu *menu)
actions.append(action);
}
}
- Utils::sort(actions, [](const QAction *action1, const QAction *action2) {
+ sort(actions, [](const QAction *action1, const QAction *action2) {
QTC_ASSERT(action1, return true);
QTC_ASSERT(action2, return false);
return stripAccelerator(action1->text()).toLower() < stripAccelerator(action2->text()).toLower();
diff --git a/src/libs/utils/filecrumblabel.cpp b/src/libs/utils/filecrumblabel.cpp
index cf03af553c4..db273bb26db 100644
--- a/src/libs/utils/filecrumblabel.cpp
+++ b/src/libs/utils/filecrumblabel.cpp
@@ -25,7 +25,8 @@
#include "filecrumblabel.h"
-#include <utils/hostosinfo.h>
+#include "filepath.h"
+#include "hostosinfo.h"
#include <QDir>
#include <QUrl>
diff --git a/src/libs/utils/filecrumblabel.h b/src/libs/utils/filecrumblabel.h
index 05dd050812c..fe3cafe996c 100644
--- a/src/libs/utils/filecrumblabel.h
+++ b/src/libs/utils/filecrumblabel.h
@@ -26,12 +26,13 @@
#pragma once
#include "utils_global.h"
-#include "fileutils.h"
#include <QLabel>
namespace Utils {
+class FilePath;
+
class QTCREATOR_UTILS_EXPORT FileCrumbLabel : public QLabel
{
Q_OBJECT
diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp
index af95c47ecdd..1d25e2b2ca9 100644
--- a/src/libs/utils/fileinprojectfinder.cpp
+++ b/src/libs/utils/fileinprojectfinder.cpp
@@ -26,14 +26,11 @@
#include "fileinprojectfinder.h"
#include "algorithm.h"
-#include "fileutils.h"
#include "hostosinfo.h"
#include "qrcparser.h"
#include "qtcassert.h"
-#include "stringutils.h"
#include <QCursor>
-#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QLoggingCategory>
diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h
index dd4771580fc..f4b08596dcc 100644
--- a/src/libs/utils/fileinprojectfinder.h
+++ b/src/libs/utils/fileinprojectfinder.h
@@ -25,14 +25,17 @@
#pragma once
-#include <utils/utils_global.h>
-#include <utils/fileutils.h>
+#include "utils_global.h"
+
+#include "filepath.h"
#include <QHash>
#include <QSharedPointer>
#include <QStringList>
-QT_FORWARD_DECLARE_CLASS(QUrl)
+QT_BEGIN_NAMESPACE
+class QUrl;
+QT_END_NAMESPACE
namespace Utils {
class QrcParser;
diff --git a/src/libs/utils/filenamevalidatinglineedit.cpp b/src/libs/utils/filenamevalidatinglineedit.cpp
index eb850abbfa2..30791d2ffcd 100644
--- a/src/libs/utils/filenamevalidatinglineedit.cpp
+++ b/src/libs/utils/filenamevalidatinglineedit.cpp
@@ -27,7 +27,6 @@
#include "qtcassert.h"
#include <QRegularExpression>
-#include <QDebug>
/*!
\class Utils::FileNameValidatingLineEdit
diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp
index 18fc4be7c46..847c938a019 100644
--- a/src/libs/utils/filepath.cpp
+++ b/src/libs/utils/filepath.cpp
@@ -26,24 +26,19 @@
#include "filepath.h"
#include "algorithm.h"
-#include "commandline.h"
#include "environment.h"
#include "fileutils.h"
#include "hostosinfo.h"
#include "qtcassert.h"
-#include "savefile.h"
#include <QtGlobal>
-#include <QDataStream>
#include <QDateTime>
#include <QDebug>
#include <QDirIterator>
#include <QFileInfo>
-#include <QOperatingSystemVersion>
#include <QRegularExpression>
#include <QStorageInfo>
#include <QUrl>
-#include <qplatformdefs.h>
#ifdef Q_OS_WIN
#ifdef QTCREATOR_PCH_H
@@ -423,9 +418,100 @@ FilePath FileUtils::homePath()
/*! \class Utils::FilePath
- \brief The FilePath class is a light-weight convenience class for filenames.
+ \brief The FilePath class is an abstraction for handles to objects
+ in a (possibly remote) file system, similar to a URL or, in the local
+ case, a path to a file or directory.
- On windows filenames are compared case insensitively.
+ Ideally, all of \QC code should use FilePath for this purpose,
+ but for historic reasons there are still large parts using QString.
+
+ FilePaths are internally stored as triple of strings, with one
+ part ("scheme") identifying an access method, a second part ("host")
+ a file system (e.g. a host) and a third part ("path") identifying
+ a (potential) object on the systems.
+
+ FilePath follows the Unix paradigm of "everything is a file":
+ There is no conceptional difference between FilePaths referring
+ to plain files or directories.
+
+ A FilePath is implicitly associated with an operating system via its
+ host part. The path part of a FilePath is internally stored
+ with forward slashes, independent of the associated OS.
+
+ The path parts of FilePaths associated with Windows (and macOS,
+ unless selected otherwise in the settings) are compared case-insensitively
+ to each other.
+ Note that comparisons for equivalence generally need out-of-band
+ knowledge, as there may be multiple FilePath representations for
+ the same file (e.g. different access methods may lead to the same
+ file).
+
+ There are several conversions between FilePath and other string-like
+ representations:
+
+ \list
+
+ \li FilePath::fromUserInput()
+
+ Convert string-like data from sources originating outside of
+ \QC, e.g. from human input in GUI controls, from environment
+ variables and from command-line parameters to \QC.
+
+ The input can contain both slashes and backslashes and will
+ be parsed and normalized.
+
+ \li FilePath::nativePath()
+
+ Converts the FilePath to the slash convention of the associated
+ OS and drops the scheme and host parts.
+
+ This is useful to interact with the facilities of the associated
+ OS, e.g. when passing this FilePath as an argument to a command
+ executed on the associated OS.
+
+ \note The FilePath passed as executable to a CommandLine is typically
+ not touched by user code. QtcProcess will use it to determine
+ the remote system and apply the necessary conversions internally.
+
+ \li FilePath::toUserOutput()
+
+ Converts the FilePath to the slash convention of the associated
+ OS and retains the scheme and host parts.
+
+ This is rarely useful for remote paths as there is practically
+ no consumer of this style.
+
+ \li FilePath::displayName()
+
+ Converts the FilePath to the slash convention of the associated
+ OS and adds the scheme and host as a " on <device>" suffix.
+
+ This is useful for static user-facing output in he GUI
+
+ \li FilePath::fromVariant(), FilePath::toVariant()
+
+ These are used to interface QVariant-based API, e.g.
+ settings or item model (internal) data.
+
+ \li FilePath::fromString(), FilePath::toString()
+
+ These are used for internal interfaces to code areas that
+ still use QString based file paths.
+
+ \endlist
+
+ Conversion of string-like data should always happen at the outer boundary
+ of \QC code, using \c fromUserInput() for in-bound communication,
+ and depending on the medium \c nativePath() or \c displayName() for out-bound
+ communication.
+
+ Communication with QVariant based Qt API should use \c fromVariant() and
+ \c toVariant().
+
+ Uses of \c fromString() and \c toString() should be phased out by transforming
+ code from QString based file path to FilePath. An exception here are
+ fragments of paths of a FilePath that are later used with \c pathAppended()
+ or similar which should be kept as QString.
*/
FilePath::FilePath()
@@ -532,10 +618,11 @@ QString FilePath::fileNameWithPathComponents(int pathComponents) const
;
}
- // If there are no more slashes before the found one, return the entire string
if (i > 0 && m_data.lastIndexOf(slash, i) != -1)
return m_data.mid(component);
- return m_data;
+
+ // If there are no more slashes before the found one, return the entire string
+ return displayName();
}
/// \returns the base name of the file without the path.
@@ -926,8 +1013,53 @@ FilePath FilePath::normalizedPathName() const
return result;
}
-/// Constructs a FilePath from \a filename
-/// \a filename is not checked for validity.
+QString FilePath::displayName(const QString &args) const
+{
+ QString deviceName;
+ if (needsDevice()) {
+ QTC_ASSERT(s_deviceHooks.deviceDisplayName, return m_data);
+ deviceName = s_deviceHooks.deviceDisplayName(*this);
+ }
+
+ if (args.isEmpty()) {
+ if (deviceName.isEmpty())
+ return m_data;
+
+ return QCoreApplication::translate("Utils::FileUtils", "%1 on %2", "File on device")
+ .arg(m_data, deviceName);
+ }
+
+ if (deviceName.isEmpty())
+ return m_data + ' ' + args;
+
+ return QCoreApplication::translate("Utils::FileUtils", "%1 %2 on %3", "File and args on device")
+ .arg(m_data, args, deviceName);
+}
+
+/*!
+ Constructs a FilePath from \a filepath
+
+ \a filepath is not checked for validity. It can be given in the following forms:
+
+ \list
+ \li /some/absolute/local/path
+ \li some/relative/path
+ \li scheme://host/absolute/path
+ \li scheme://host/./relative/path \note the ./ is verbatim part of the path
+ \endlist
+
+ Some decoding happens when parsing the \a filepath
+ A sequence %25 present in the host part is replaced by % in the host name,
+ a sequence %2f present in the host part is replaced by / in the host name.
+
+ The path part might consist of several parts separated by /, independent
+ of the platform or file system.
+
+ To create FilePath objects from strings possibly containing backslashes as
+ path separator, use \c fromUserInput.
+
+ \sa toString, fromUserInput
+ */
FilePath FilePath::fromString(const QString &filepath)
{
FilePath fn;
@@ -1266,9 +1398,16 @@ FilePath FilePath::searchInDirectories(const FilePaths &dirs) const
return Environment::systemEnvironment().searchInDirectories(path(), dirs);
}
-FilePath FilePath::searchInPath(const QList<FilePath> &additionalDirs) const
+FilePath FilePath::searchInPath(const FilePaths &additionalDirs, PathAmending amending) const
{
- return searchInDirectories(deviceEnvironment().path() + additionalDirs);
+ FilePaths directories = deviceEnvironment().path();
+ if (!additionalDirs.isEmpty()) {
+ if (amending == AppendToPath)
+ directories.append(additionalDirs);
+ else
+ directories = additionalDirs + directories;
+ }
+ return searchInDirectories(directories);
}
Environment FilePath::deviceEnvironment() const
@@ -1282,24 +1421,24 @@ Environment FilePath::deviceEnvironment() const
QString FilePath::formatFilePaths(const QList<FilePath> &files, const QString &separator)
{
- const QStringList nativeFiles = Utils::transform(files, &FilePath::toUserOutput);
+ const QStringList nativeFiles = transform(files, &FilePath::toUserOutput);
return nativeFiles.join(separator);
}
void FilePath::removeDuplicates(QList<FilePath> &files)
{
// FIXME: Improve.
- QStringList list = Utils::transform<QStringList>(files, &FilePath::toString);
+ QStringList list = transform<QStringList>(files, &FilePath::toString);
list.removeDuplicates();
- files = Utils::transform(list, &FilePath::fromString);
+ files = transform(list, &FilePath::fromString);
}
void FilePath::sort(QList<FilePath> &files)
{
// FIXME: Improve.
- QStringList list = Utils::transform<QStringList>(files, &FilePath::toString);
+ QStringList list = transform<QStringList>(files, &FilePath::toString);
list.sort();
- files = Utils::transform(list, &FilePath::fromString);
+ files = transform(list, &FilePath::fromString);
}
FilePath FilePath::pathAppended(const QString &path) const
@@ -1337,8 +1476,8 @@ FilePath FilePath::stringAppended(const QString &str) const
QHashValueType FilePath::hash(uint seed) const
{
- if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive)
- return qHash(m_data.toUpper(), seed);
+ if (HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive)
+ return qHash(m_data.toCaseFolded(), seed);
return qHash(m_data, seed);
}
@@ -1478,6 +1617,6 @@ std::hash<Utils::FilePath>::result_type
std::hash<Utils::FilePath>::operator()(const std::hash<Utils::FilePath>::argument_type &fn) const
{
if (fn.caseSensitivity() == Qt::CaseInsensitive)
- return hash<string>()(fn.toString().toUpper().toStdString());
+ return hash<string>()(fn.toString().toCaseFolded().toStdString());
return hash<string>()(fn.toString().toStdString());
}
diff --git a/src/libs/utils/filepath.h b/src/libs/utils/filepath.h
index b3c035ea870..4b589389b4d 100644
--- a/src/libs/utils/filepath.h
+++ b/src/libs/utils/filepath.h
@@ -26,9 +26,9 @@
#pragma once
#include "utils_global.h"
-#include "porting.h"
-#include "hostosinfo.h"
+#include "osspecificaspects.h"
+#include "porting.h"
#include <QDir>
#include <QDirIterator>
@@ -164,17 +164,21 @@ public:
[[nodiscard]] FilePath relativeChildPath(const FilePath &parent) const;
[[nodiscard]] FilePath relativePath(const FilePath &anchor) const;
[[nodiscard]] FilePath searchInDirectories(const QList<FilePath> &dirs) const;
- [[nodiscard]] FilePath searchInPath(const QList<FilePath> &additionalDirs = {}) const;
[[nodiscard]] Environment deviceEnvironment() const;
[[nodiscard]] FilePath onDevice(const FilePath &deviceTemplate) const;
[[nodiscard]] FilePath withNewPath(const QString &newPath) const;
void iterateDirectory(const std::function<bool(const FilePath &item)> &callBack,
const FileFilter &filter) const;
+ enum PathAmending { AppendToPath, PrependToPath };
+ [[nodiscard]] FilePath searchInPath(const QList<FilePath> &additionalDirs = {},
+ PathAmending = AppendToPath) const;
+
// makes sure that capitalization of directories is canonical
// on Windows and macOS. This is rarely needed.
[[nodiscard]] FilePath normalizedPathName() const;
+ QString displayName(const QString &args = {}) const;
QString nativePath() const;
QString shortNativePath() const;
bool startsWithDriveLetter() const;
diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index 4be8ef209f2..b2016544d2e 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -26,7 +26,7 @@
#include "filesearch.h"
#include "algorithm.h"
-#include "fileutils.h"
+#include "filepath.h"
#include "mapreduce.h"
#include "qtcassert.h"
#include "stringutils.h"
@@ -39,7 +39,7 @@
#include <cctype>
-Q_LOGGING_CATEGORY(log, "qtc.utils.filesearch", QtWarningMsg)
+Q_LOGGING_CATEGORY(searchLog, "qtc.utils.filesearch", QtWarningMsg)
using namespace Utils;
@@ -143,13 +143,13 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
{
if (futureInterface.isCanceled())
return;
- qCDebug(log) << "Searching in" << item.filePath;
+ qCDebug(searchLog) << "Searching in" << item.filePath;
futureInterface.setProgressRange(0, 1);
futureInterface.setProgressValue(0);
FileSearchResultList results;
QString tempString;
if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) {
- qCDebug(log) << "- failed to get content for" << item.filePath;
+ qCDebug(searchLog) << "- failed to get content for" << item.filePath;
futureInterface.cancel(); // failure
return;
}
@@ -159,8 +159,7 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
while (!stream.atEnd()) {
++lineNr;
const QString chunk = stream.readLine();
- const QString resultItemText = clippedText(chunk, MAX_LINE_SIZE);
- int chunkLength = chunk.length();
+ const int chunkLength = chunk.length();
const QChar *chunkPtr = chunk.constData();
const QChar *chunkEnd = chunkPtr + chunkLength - 1;
for (const QChar *regionPtr = chunkPtr; regionPtr + termMaxIndex <= chunkEnd; ++regionPtr) {
@@ -207,12 +206,17 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
&& *regionCursor != termDataUpper[regionIndex])
) {
equal = false;
+ break;
}
}
}
if (equal) {
- results << FileSearchResult(item.filePath, lineNr, resultItemText,
- regionPtr - chunkPtr, termMaxIndex + 1,
+ const QString resultItemText = clippedText(chunk, MAX_LINE_SIZE);
+ results << FileSearchResult(item.filePath,
+ lineNr,
+ resultItemText,
+ regionPtr - chunkPtr,
+ termMaxIndex + 1,
QStringList());
regionPtr += termMaxIndex; // another +1 done by for-loop
}
@@ -227,7 +231,7 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
futureInterface.reportResult(results);
futureInterface.setProgressValue(1);
}
- qCDebug(log) << "- finished searching in" << item.filePath;
+ qCDebug(searchLog) << "- finished searching in" << item.filePath;
}
FileSearchRegExp::FileSearchRegExp(const QString &searchTerm, QTextDocument::FindFlags flags,
@@ -263,13 +267,13 @@ void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &future
}
if (futureInterface.isCanceled())
return;
- qCDebug(log) << "Searching in" << item.filePath;
+ qCDebug(searchLog) << "Searching in" << item.filePath;
futureInterface.setProgressRange(0, 1);
futureInterface.setProgressValue(0);
FileSearchResultList results;
QString tempString;
if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) {
- qCDebug(log) << "- failed to get content for" << item.filePath;
+ qCDebug(searchLog) << "- failed to get content for" << item.filePath;
futureInterface.cancel(); // failure
return;
}
@@ -304,7 +308,7 @@ void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &future
futureInterface.reportResult(results);
futureInterface.setProgressValue(1);
}
- qCDebug(log) << "- finished searching in" << item.filePath;
+ qCDebug(searchLog) << "- finished searching in" << item.filePath;
}
struct SearchState
diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h
index c5f1544c609..1161ff5e3da 100644
--- a/src/libs/utils/filesearch.h
+++ b/src/libs/utils/filesearch.h
@@ -28,14 +28,18 @@
#include "utils_global.h"
#include <QDir>
-#include <QFuture>
#include <QMap>
+#include <QSet>
#include <QStack>
#include <QTextDocument>
#include <functional>
-QT_FORWARD_DECLARE_CLASS(QTextCodec)
+QT_BEGIN_NAMESPACE
+template <typename T>
+class QFuture;
+class QTextCodec;
+QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/filesystemmodel.cpp b/src/libs/utils/filesystemmodel.cpp
index 79f46665664..f26dc517c1c 100644
--- a/src/libs/utils/filesystemmodel.cpp
+++ b/src/libs/utils/filesystemmodel.cpp
@@ -39,12 +39,11 @@
#include "filesystemmodel.h"
-#include "filepath.h"
#include "hostosinfo.h"
#include "qtcassert.h"
#include <QDateTime>
-#include <QDebug>
+#include <QCollator>
#include <QDir>
#include <QDirIterator>
#include <QElapsedTimer>
@@ -58,7 +57,6 @@
#include <QMutex>
#include <QPair>
#include <QStack>
-#include <QCollator>
#include <QRegularExpression>
#include <QThread>
#include <QTimer>
@@ -1180,8 +1178,6 @@ void FileSystemModel::timerEvent(QTimerEvent *event)
if (!node->hasInformation()) {
d->fileInfoGatherer.fetchExtendedInformation(d->toFetch.at(i).dir,
QStringList(d->toFetch.at(i).file));
- } else {
- // qDebug("yah!, you saved a little gerbil soul");
}
}
}
diff --git a/src/libs/utils/filesystemmodel.h b/src/libs/utils/filesystemmodel.h
index 2278238bf18..1a458817d91 100644
--- a/src/libs/utils/filesystemmodel.h
+++ b/src/libs/utils/filesystemmodel.h
@@ -42,7 +42,6 @@
#include "utils_global.h"
#include <QAbstractItemModel>
-#include <QPair>
#include <QDir>
QT_BEGIN_NAMESPACE
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index 60a2d6e62fa..bdd67a6609e 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -27,21 +27,20 @@
#include "savefile.h"
#include "algorithm.h"
-#include "commandline.h"
-#include "environment.h"
-#include "hostosinfo.h"
#include "qtcassert.h"
#include <QDataStream>
-#include <QDateTime>
#include <QDebug>
#include <QOperatingSystemVersion>
-#include <QTimer>
-#include <QUrl>
+#include <QTemporaryFile>
+#include <QTextStream>
+#include <QXmlStreamWriter>
+
#include <qplatformdefs.h>
#ifdef QT_GUI_LIB
#include <QMessageBox>
+#include <QRegularExpression>
#endif
#ifdef Q_OS_WIN
@@ -493,6 +492,43 @@ FilePaths FileUtils::getOpenFilePaths(QWidget *parent,
options);
return transform(result, &FilePath::fromString);
}
+
+// Used on 'ls' output on unix-like systems.
+void FileUtils::iterateLsOutput(const FilePath &base,
+ const QStringList &entries,
+ const FileFilter &filter,
+ const std::function<bool (const FilePath &)> &callBack)
+{
+ QTC_CHECK(filter.iteratorFlags != QDirIterator::NoIteratorFlags); // FIXME: Not supported yet below.
+
+ const QList<QRegularExpression> nameRegexps =
+ transform(filter.nameFilters, [](const QString &filter) {
+ QRegularExpression re;
+ re.setPattern(QRegularExpression::wildcardToRegularExpression(filter));
+ QTC_CHECK(re.isValid());
+ return re;
+ });
+
+ const auto nameMatches = [&nameRegexps](const QString &fileName) {
+ for (const QRegularExpression &re : nameRegexps) {
+ const QRegularExpressionMatch match = re.match(fileName);
+ if (match.hasMatch())
+ return true;
+ }
+ return nameRegexps.isEmpty();
+ };
+
+ // FIXME: Handle filters. For now bark on unsupported options.
+ QTC_CHECK(filter.fileFilters == QDir::NoFilter);
+
+ for (const QString &entry : entries) {
+ if (!nameMatches(entry))
+ continue;
+ if (!callBack(base.pathAppended(entry)))
+ break;
+ }
+}
+
#endif // QT_WIDGETS_LIB
} // namespace Utils
diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h
index 163e762e511..995ebfb78b0 100644
--- a/src/libs/utils/fileutils.h
+++ b/src/libs/utils/fileutils.h
@@ -28,15 +28,9 @@
#include "utils_global.h"
#include "filepath.h"
-#include "hostosinfo.h"
#include <QCoreApplication>
#include <QDir>
-#include <QFileInfo>
-#include <QMetaType>
-#include <QStringList>
-#include <QUrl>
-#include <QXmlStreamWriter> // Mac.
#ifdef QT_WIDGETS_LIB
#include <QFileDialog>
@@ -49,6 +43,7 @@ QT_BEGIN_NAMESPACE
class QDataStream;
class QTextStream;
class QWidget;
+class QXmlStreamWriter;
// for withNtfsPermissions
#ifdef Q_OS_WIN
@@ -78,7 +73,6 @@ public:
std::function<bool(const FilePath &, const FilePath &)> renameFile;
std::function<FilePath(const FilePath &, const QList<FilePath> &)> searchInPath;
std::function<FilePath(const FilePath &)> symLinkTarget;
- std::function<FilePath(const FilePath &)> mapToGlobalPath;
std::function<QString(const FilePath &)> mapToDevicePath;
std::function<void(const FilePath &,
const std::function<bool(const FilePath &)> &, // Abort on 'false' return.
@@ -92,6 +86,7 @@ public:
std::function<Environment(const FilePath &)> environment;
std::function<qint64(const FilePath &)> fileSize;
std::function<qint64(const FilePath &)> bytesAvailable;
+ std::function<QString(const FilePath &)> deviceDisplayName;
template <class ...Args> using Continuation = std::function<void(Args...)>;
std::function<void(const Continuation<bool> &, const FilePath &, const FilePath &)> asyncCopyFile;
@@ -144,6 +139,11 @@ public:
static void setDeviceFileHooks(const DeviceFileHooks &hooks);
+ static void iterateLsOutput(const FilePath &base,
+ const QStringList &entries,
+ const FileFilter &filter,
+ const std::function<bool(const FilePath &)> &callBack);
+
#ifdef QT_WIDGETS_LIB
static void setDialogParentGetter(const std::function<QWidget *()> &getter);
@@ -173,6 +173,7 @@ public:
QString *selectedFilter = nullptr,
QFileDialog::Options options = {});
#endif
+
};
template<typename T>
diff --git a/src/libs/utils/filewizardpage.cpp b/src/libs/utils/filewizardpage.cpp
index 6b5bdf28989..5a6116854fe 100644
--- a/src/libs/utils/filewizardpage.cpp
+++ b/src/libs/utils/filewizardpage.cpp
@@ -26,7 +26,7 @@
#include "filewizardpage.h"
#include "ui_filewizardpage.h"
-#include "wizard.h"
+#include "wizard.h" // TODO: only because of SHORT_TITLE_PROPERTY
/*!
\class Utils::FileWizardPage
diff --git a/src/libs/utils/filewizardpage.h b/src/libs/utils/filewizardpage.h
index b763afa2f85..546009ce451 100644
--- a/src/libs/utils/filewizardpage.h
+++ b/src/libs/utils/filewizardpage.h
@@ -27,11 +27,12 @@
#include "utils_global.h"
-#include "filepath.h"
#include "wizardpage.h"
namespace Utils {
+class FilePath;
+
class FileWizardPagePrivate;
class QTCREATOR_UTILS_EXPORT FileWizardPage : public WizardPage
diff --git a/src/libs/utils/fixedsizeclicklabel.h b/src/libs/utils/fixedsizeclicklabel.h
index 93cf27cc9fb..ac41e6cdd1e 100644
--- a/src/libs/utils/fixedsizeclicklabel.h
+++ b/src/libs/utils/fixedsizeclicklabel.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include <QLabel>
namespace Utils {
diff --git a/src/libs/utils/futuresynchronizer.h b/src/libs/utils/futuresynchronizer.h
index 00f49043a71..80bb0e31e78 100644
--- a/src/libs/utils/futuresynchronizer.h
+++ b/src/libs/utils/futuresynchronizer.h
@@ -26,10 +26,10 @@
#pragma once
#include "utils_global.h"
-#include <QtGlobal>
#include <QFuture>
#include <QList>
+#include <QtGlobal>
namespace Utils {
diff --git a/src/libs/utils/guard.h b/src/libs/utils/guard.h
index 063825650dc..2f986d82b06 100644
--- a/src/libs/utils/guard.h
+++ b/src/libs/utils/guard.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include <QtGlobal>
namespace Utils {
diff --git a/src/libs/utils/headerviewstretcher.cpp b/src/libs/utils/headerviewstretcher.cpp
index 3c21a2d1ba9..2ff70ae9b1e 100644
--- a/src/libs/utils/headerviewstretcher.cpp
+++ b/src/libs/utils/headerviewstretcher.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "headerviewstretcher.h"
+
#include <QHideEvent>
#include <QHeaderView>
diff --git a/src/libs/utils/headerviewstretcher.h b/src/libs/utils/headerviewstretcher.h
index ab874e734a4..fef7302a475 100644
--- a/src/libs/utils/headerviewstretcher.h
+++ b/src/libs/utils/headerviewstretcher.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include <QObject>
QT_BEGIN_NAMESPACE
diff --git a/src/libs/utils/historycompleter.cpp b/src/libs/utils/historycompleter.cpp
index 3a296c37dd7..1c25dfb2be2 100644
--- a/src/libs/utils/historycompleter.cpp
+++ b/src/libs/utils/historycompleter.cpp
@@ -25,15 +25,13 @@
#include "historycompleter.h"
-#include "fancylineedit.h"
#include "qtcassert.h"
#include "qtcsettings.h"
-#include "theme/theme.h"
#include "utilsicons.h"
#include <QItemDelegate>
-#include <QKeyEvent>
#include <QListView>
+#include <QMouseEvent>
#include <QPainter>
#include <QWindow>
diff --git a/src/libs/utils/hostosinfo.cpp b/src/libs/utils/hostosinfo.cpp
index 78ed7f22867..79f042e0f05 100644
--- a/src/libs/utils/hostosinfo.cpp
+++ b/src/libs/utils/hostosinfo.cpp
@@ -31,6 +31,10 @@
#include <QOpenGLContext>
#endif
+#ifdef Q_OS_LINUX
+#include <sys/sysinfo.h>
+#endif
+
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif
@@ -66,6 +70,8 @@ HostOsInfo::HostArchitecture HostOsInfo::hostArchitecture()
return HostOsInfo::HostArchitectureItanium;
case PROCESSOR_ARCHITECTURE_ARM:
return HostOsInfo::HostArchitectureArm;
+ case PROCESSOR_ARCHITECTURE_ARM64:
+ return HostOsInfo::HostArchitectureArm64;
default:
return HostOsInfo::HostArchitectureUnknown;
}
@@ -109,3 +115,27 @@ bool HostOsInfo::canCreateOpenGLContext(QString *errorMessage)
return canCreate;
#endif
}
+
+optional<quint64> HostOsInfo::totalMemoryInstalledInBytes()
+{
+#ifdef Q_OS_LINUX
+ struct sysinfo info;
+ if (sysinfo(&info) == -1)
+ return {};
+ return info.totalram;
+#elif defined(Q_OS_WIN)
+ MEMORYSTATUSEX statex;
+ statex.dwLength = sizeof statex;
+ if (!GlobalMemoryStatusEx(&statex))
+ return {};
+ return statex.ullTotalPhys;
+#elif defined(Q_OS_MACOS)
+ int mib[] = {CTL_HW, HW_MEMSIZE};
+ int64_t ram;
+ size_t length = sizeof(int64_t);
+ if (sysctl(mib, 2, &ram, &length, nullptr, 0) == -1)
+ return {};
+ return ram;
+#endif
+ return {};
+}
diff --git a/src/libs/utils/hostosinfo.h b/src/libs/utils/hostosinfo.h
index db2d77074b4..9823c7e6f23 100644
--- a/src/libs/utils/hostosinfo.h
+++ b/src/libs/utils/hostosinfo.h
@@ -27,9 +27,12 @@
#include "utils_global.h"
+#include "optional.h"
#include "osspecificaspects.h"
-#include <QString>
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
#ifdef Q_OS_WIN
#define QTC_HOST_EXE_SUFFIX QTC_WIN_EXE_SUFFIX
@@ -58,7 +61,7 @@ public:
}
enum HostArchitecture { HostArchitectureX86, HostArchitectureAMD64, HostArchitectureItanium,
- HostArchitectureArm, HostArchitectureUnknown };
+ HostArchitectureArm, HostArchitectureArm64, HostArchitectureUnknown };
static HostArchitecture hostArchitecture();
static constexpr bool isWindowsHost() { return hostOs() == OsTypeWindows; }
@@ -102,6 +105,8 @@ public:
static bool canCreateOpenGLContext(QString *errorMessage);
+ static optional<quint64> totalMemoryInstalledInBytes();
+
private:
static Qt::CaseSensitivity m_overrideFileNameCaseSensitivity;
static bool m_useOverrideFileNameCaseSensitivity;
diff --git a/src/libs/utils/htmldocextractor.cpp b/src/libs/utils/htmldocextractor.cpp
index 7eacb6f237a..eeef38339fe 100644
--- a/src/libs/utils/htmldocextractor.cpp
+++ b/src/libs/utils/htmldocextractor.cpp
@@ -25,7 +25,6 @@
#include "htmldocextractor.h"
-#include <QStringList>
#include <QRegularExpression>
namespace Utils {
diff --git a/src/libs/utils/htmldocextractor.h b/src/libs/utils/htmldocextractor.h
index d4ede7d4eee..0ed9a535359 100644
--- a/src/libs/utils/htmldocextractor.h
+++ b/src/libs/utils/htmldocextractor.h
@@ -27,6 +27,10 @@
#include "utils_global.h"
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
namespace Utils {
class QTCREATOR_UTILS_EXPORT HtmlDocExtractor
diff --git a/src/libs/utils/icon.cpp b/src/libs/utils/icon.cpp
index c778923f22d..a4ae9b81ed2 100644
--- a/src/libs/utils/icon.cpp
+++ b/src/libs/utils/icon.cpp
@@ -30,12 +30,11 @@
#include "stylehelper.h"
#include <QApplication>
+#include <QDebug>
#include <QIcon>
#include <QImage>
#include <QPainter>
-#include <QPaintEngine>
#include <QWidget>
-#include <QDebug>
namespace Utils {
@@ -59,7 +58,7 @@ static QPixmap maskToColorAndAlpha(const QPixmap &mask, const QColor &color)
using MaskAndColor = QPair<QPixmap, QColor>;
using MasksAndColors = QList<MaskAndColor>;
-static MasksAndColors masksAndColors(const Icon &icon, int dpr)
+static MasksAndColors masksAndColors(const QVector<IconMaskAndColor> &icon, int dpr)
{
MasksAndColors result;
for (const IconMaskAndColor &i: icon) {
@@ -158,46 +157,50 @@ static QPixmap masksToIcon(const MasksAndColors &masks, const QPixmap &combinedM
Icon::Icon() = default;
Icon::Icon(std::initializer_list<IconMaskAndColor> args, Icon::IconStyleOptions style)
- : QVector<IconMaskAndColor>(args)
+ : m_iconSourceList(args)
, m_style(style)
{
}
Icon::Icon(const FilePath &imageFileName)
{
- append({imageFileName, Theme::Color(-1)});
+ m_iconSourceList.append({imageFileName, Theme::Color(-1)});
}
QIcon Icon::icon() const
{
- if (isEmpty()) {
+ if (m_iconSourceList.isEmpty())
return QIcon();
- } else if (m_style == None) {
- return QIcon(constFirst().first.toString());
- } else {
- QIcon result;
- const int maxDpr = qRound(qApp->devicePixelRatio());
- for (int dpr = 1; dpr <= maxDpr; dpr++) {
- const MasksAndColors masks = masksAndColors(*this, dpr);
- const QPixmap combinedMask = Utils::combinedMask(masks, m_style);
- result.addPixmap(masksToIcon(masks, combinedMask, m_style));
- const QColor disabledColor = creatorTheme()->color(Theme::IconsDisabledColor);
- result.addPixmap(maskToColorAndAlpha(combinedMask, disabledColor), QIcon::Disabled);
- }
- return result;
+ if (m_style == None)
+ return QIcon(m_iconSourceList.constFirst().first.toString());
+
+ const int maxDpr = qRound(qApp->devicePixelRatio());
+ if (maxDpr == m_lastDevicePixelRatio)
+ return m_lastIcon;
+
+ m_lastDevicePixelRatio = maxDpr;
+ m_lastIcon = QIcon();
+ for (int dpr = 1; dpr <= maxDpr; dpr++) {
+ const MasksAndColors masks = masksAndColors(m_iconSourceList, dpr);
+ const QPixmap combinedMask = Utils::combinedMask(masks, m_style);
+ m_lastIcon.addPixmap(masksToIcon(masks, combinedMask, m_style));
+
+ const QColor disabledColor = creatorTheme()->color(Theme::IconsDisabledColor);
+ m_lastIcon.addPixmap(maskToColorAndAlpha(combinedMask, disabledColor), QIcon::Disabled);
}
+ return m_lastIcon;
}
QPixmap Icon::pixmap(QIcon::Mode iconMode) const
{
- if (isEmpty()) {
+ if (m_iconSourceList.isEmpty()) {
return QPixmap();
} else if (m_style == None) {
- return QPixmap(StyleHelper::dpiSpecificImageFile(constFirst().first.toString()));
+ return QPixmap(StyleHelper::dpiSpecificImageFile(m_iconSourceList.constFirst().first.toString()));
} else {
const MasksAndColors masks =
- masksAndColors(*this, qRound(qApp->devicePixelRatio()));
+ masksAndColors(m_iconSourceList, qRound(qApp->devicePixelRatio()));
const QPixmap combinedMask = Utils::combinedMask(masks, m_style);
return iconMode == QIcon::Disabled
? maskToColorAndAlpha(combinedMask, creatorTheme()->color(Theme::IconsDisabledColor))
@@ -207,8 +210,8 @@ QPixmap Icon::pixmap(QIcon::Mode iconMode) const
FilePath Icon::imageFilePath() const
{
- QTC_ASSERT(length() == 1, return {});
- return first().first;
+ QTC_ASSERT(m_iconSourceList.length() == 1, return {});
+ return m_iconSourceList.first().first;
}
QIcon Icon::sideBarIcon(const Icon &classic, const Icon &flat)
diff --git a/src/libs/utils/icon.h b/src/libs/utils/icon.h
index d784ea5e5e5..286644eb84a 100644
--- a/src/libs/utils/icon.h
+++ b/src/libs/utils/icon.h
@@ -25,17 +25,20 @@
#pragma once
-#include "fileutils.h"
-#include "theme/theme.h"
#include "utils_global.h"
+#include "filepath.h"
+#include "theme/theme.h"
+
#include <QIcon>
#include <QPair>
#include <QVector>
-QT_FORWARD_DECLARE_CLASS(QColor)
-QT_FORWARD_DECLARE_CLASS(QPixmap)
-QT_FORWARD_DECLARE_CLASS(QString)
+QT_BEGIN_NAMESPACE
+class QColor;
+class QPixmap;
+class QString;
+QT_END_NAMESPACE
namespace Utils {
@@ -43,7 +46,7 @@ using IconMaskAndColor = QPair<FilePath, Theme::Color>;
// Returns a recolored icon with shadow and custom disabled state for a
// series of grayscalemask|Theme::Color mask pairs
-class QTCREATOR_UTILS_EXPORT Icon : public QVector<IconMaskAndColor>
+class QTCREATOR_UTILS_EXPORT Icon
{
public:
enum IconStyleOption {
@@ -83,7 +86,10 @@ public:
static QIcon combinedIcon(const QList<Icon> &icons);
private:
+ QVector<IconMaskAndColor> m_iconSourceList;
IconStyleOptions m_style = None;
+ mutable int m_lastDevicePixelRatio = -1;
+ mutable QIcon m_lastIcon;
};
} // namespace Utils
diff --git a/src/libs/utils/id.cpp b/src/libs/utils/id.cpp
index 9757a95250e..0ed64509067 100644
--- a/src/libs/utils/id.cpp
+++ b/src/libs/utils/id.cpp
@@ -34,8 +34,6 @@
#include <QHash>
#include <QVariant>
-#include <string.h>
-
namespace Utils {
/*!
@@ -243,14 +241,14 @@ Id Id::versionedId(const QByteArray &prefix, int major, int minor)
QSet<Id> Id::fromStringList(const QStringList &list)
{
- return Utils::transform<QSet<Id>>(list, &Id::fromString);
+ return transform<QSet<Id>>(list, &Id::fromString);
}
QStringList Id::toStringList(const QSet<Id> &ids)
{
- QList<Id> idList = Utils::toList(ids);
- Utils::sort(idList);
- return Utils::transform(idList, &Id::toString);
+ QList<Id> idList = toList(ids);
+ sort(idList);
+ return transform(idList, &Id::toString);
}
/*!
@@ -338,12 +336,12 @@ QString Id::suffixAfter(Id baseId) const
return n.startsWith(b) ? QString::fromUtf8(n.mid(b.size())) : QString();
}
-QDataStream &operator<<(QDataStream &ds, Utils::Id id)
+QDataStream &operator<<(QDataStream &ds, Id id)
{
return ds << id.name();
}
-QDataStream &operator>>(QDataStream &ds, Utils::Id &id)
+QDataStream &operator>>(QDataStream &ds, Id &id)
{
QByteArray ba;
ds >> ba;
@@ -351,7 +349,7 @@ QDataStream &operator>>(QDataStream &ds, Utils::Id &id)
return ds;
}
-QDebug operator<<(QDebug dbg, const Utils::Id &id)
+QDebug operator<<(QDebug dbg, const Id &id)
{
return dbg << id.name();
}
diff --git a/src/libs/utils/id.h b/src/libs/utils/id.h
index b1b49fe2a8f..963bd46a558 100644
--- a/src/libs/utils/id.h
+++ b/src/libs/utils/id.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include "porting.h"
#include <QList>
@@ -75,9 +76,9 @@ public:
static QStringList toStringList(const QSet<Id> &ids);
friend QHashValueType qHash(Id id) { return static_cast<QHashValueType>(id.uniqueIdentifier()); }
- friend QTCREATOR_UTILS_EXPORT QDataStream &operator<<(QDataStream &ds, Utils::Id id);
- friend QTCREATOR_UTILS_EXPORT QDataStream &operator>>(QDataStream &ds, Utils::Id &id);
- friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::Id &id);
+ friend QTCREATOR_UTILS_EXPORT QDataStream &operator<<(QDataStream &ds, Id id);
+ friend QTCREATOR_UTILS_EXPORT QDataStream &operator>>(QDataStream &ds, Id &id);
+ friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Id &id);
private:
explicit Id(quintptr uid) : m_id(uid) {}
diff --git a/src/libs/ssh/images/help.png b/src/libs/utils/images/help.png
index a12ef281d47..a12ef281d47 100644
--- a/src/libs/ssh/images/help.png
+++ b/src/libs/utils/images/help.png
Binary files differ
diff --git a/src/libs/utils/infobar.cpp b/src/libs/utils/infobar.cpp
index 4e1255956a7..aa8a3fb7736 100644
--- a/src/libs/utils/infobar.cpp
+++ b/src/libs/utils/infobar.cpp
@@ -28,16 +28,15 @@
#include "algorithm.h"
#include "qtcassert.h"
#include "qtcsettings.h"
-#include "theme/theme.h"
#include "utilsicons.h"
+#include <QComboBox>
#include <QHBoxLayout>
-#include <QSettings>
-#include <QVBoxLayout>
#include <QLabel>
-#include <QPaintEngine>
+#include <QPainter>
+#include <QSettings>
#include <QToolButton>
-#include <QComboBox>
+#include <QVBoxLayout>
static const char C_SUPPRESSED_WARNINGS[] = "SuppressedWarnings";
@@ -85,9 +84,21 @@ InfoBarEntry::InfoBarEntry(Id _id, const QString &_infoText, GlobalSuppression _
{
}
-void InfoBarEntry::addCustomButton(const QString &buttonText, CallBack callBack)
+Id InfoBarEntry::id() const
{
- m_buttons.append({buttonText, callBack});
+ return m_id;
+}
+
+QString InfoBarEntry::text() const
+{
+ return m_infoText;
+}
+
+void InfoBarEntry::addCustomButton(const QString &buttonText,
+ CallBack callBack,
+ const QString &tooltip)
+{
+ m_buttons.append({buttonText, callBack, tooltip});
}
void InfoBarEntry::setCancelButtonInfo(CallBack callBack)
@@ -103,10 +114,26 @@ void InfoBarEntry::setCancelButtonInfo(const QString &_cancelButtonText, CallBac
m_cancelButtonCallBack = callBack;
}
-void InfoBarEntry::setComboInfo(const QStringList &list, InfoBarEntry::ComboCallBack callBack)
+void InfoBarEntry::setComboInfo(const QStringList &list,
+ ComboCallBack callBack,
+ const QString &tooltip,
+ int currentIndex)
+{
+ auto comboInfos = transform(list, [](const QString &string) {
+ return ComboInfo{string, string};
+ });
+ setComboInfo(comboInfos, callBack, tooltip, currentIndex);
+}
+
+void InfoBarEntry::setComboInfo(const QList<ComboInfo> &list,
+ ComboCallBack callBack,
+ const QString &tooltip,
+ int currentIndex)
{
- m_comboCallBack = callBack;
- m_comboInfo = list;
+ m_combo.entries = list;
+ m_combo.callback = callBack;
+ m_combo.tooltip = tooltip;
+ m_combo.currentIndex = currentIndex;
}
void InfoBarEntry::removeCancelButton()
@@ -130,14 +157,14 @@ void InfoBar::addInfo(const InfoBarEntry &info)
void InfoBar::removeInfo(Id id)
{
const int size = m_infoBarEntries.size();
- Utils::erase(m_infoBarEntries, Utils::equal(&InfoBarEntry::m_id, id));
+ Utils::erase(m_infoBarEntries, equal(&InfoBarEntry::m_id, id));
if (size != m_infoBarEntries.size())
emit changed();
}
bool InfoBar::containsInfo(Id id) const
{
- return Utils::anyOf(m_infoBarEntries, Utils::equal(&InfoBarEntry::m_id, id));
+ return anyOf(m_infoBarEntries, equal(&InfoBarEntry::m_id, id));
}
// Remove and suppress id
@@ -184,10 +211,15 @@ void InfoBar::initialize(QSettings *settings)
if (QTC_GUARD(m_settings)) {
const QStringList list = m_settings->value(QLatin1String(C_SUPPRESSED_WARNINGS)).toStringList();
- globallySuppressed = Utils::transform<QSet>(list, Id::fromString);
+ globallySuppressed = transform<QSet>(list, Id::fromString);
}
}
+QSettings *InfoBar::settings()
+{
+ return m_settings;
+}
+
void InfoBar::clearGloballySuppressed()
{
globallySuppressed.clear();
@@ -204,7 +236,7 @@ void InfoBar::writeGloballySuppressedToSettings()
{
if (!m_settings)
return;
- const QStringList list = Utils::transform<QList>(globallySuppressed, &Id::toString);
+ const QStringList list = transform<QList>(globallySuppressed, &Id::toString);
QtcSettings::setValueWithDefault(m_settings, C_SUPPRESSED_WARNINGS, list);
}
@@ -306,12 +338,16 @@ void InfoBarDisplay::update()
m_isShowingDetailsWidget = false;
}
- if (!info.m_comboInfo.isEmpty()) {
+ if (!info.m_combo.entries.isEmpty()) {
auto cb = new QComboBox();
- cb->addItems(info.m_comboInfo);
- connect(cb, &QComboBox::currentTextChanged, [info](const QString &text) {
- info.m_comboCallBack(text);
- });
+ cb->setToolTip(info.m_combo.tooltip);
+ for (const InfoBarEntry::ComboInfo &comboInfo : qAsConst(info.m_combo.entries))
+ cb->addItem(comboInfo.displayText, comboInfo.data);
+ if (info.m_combo.currentIndex >= 0 && info.m_combo.currentIndex < cb->count())
+ cb->setCurrentIndex(info.m_combo.currentIndex);
+ connect(cb, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [cb, info]() {
+ info.m_combo.callback({cb->currentText(), cb->currentData()});
+ }, Qt::QueuedConnection);
hbox->addWidget(cb);
}
@@ -319,6 +355,7 @@ void InfoBarDisplay::update()
for (const InfoBarEntry::Button &button : qAsConst(info.m_buttons)) {
auto infoWidgetButton = new QToolButton;
infoWidgetButton->setText(button.text);
+ infoWidgetButton->setToolTip(button.tooltip);
connect(infoWidgetButton, &QAbstractButton::clicked, [button]() { button.callback(); });
hbox->addWidget(infoWidgetButton);
}
@@ -349,7 +386,7 @@ void InfoBarDisplay::update()
if (info.m_cancelButtonText.isEmpty()) {
if (infoWidgetCloseButton) {
infoWidgetCloseButton->setAutoRaise(true);
- infoWidgetCloseButton->setIcon(Utils::Icons::CLOSE_FOREGROUND.icon());
+ infoWidgetCloseButton->setIcon(Icons::CLOSE_FOREGROUND.icon());
infoWidgetCloseButton->setToolTip(tr("Close"));
}
diff --git a/src/libs/utils/infobar.h b/src/libs/utils/infobar.h
index 9ba6e6a6b44..844a007c647 100644
--- a/src/libs/utils/infobar.h
+++ b/src/libs/utils/infobar.h
@@ -25,10 +25,10 @@
#pragma once
-#include "id.h"
#include "utils_global.h"
-#include <QFrame>
+#include "id.h"
+
#include <QObject>
#include <QSet>
@@ -54,14 +54,24 @@ public:
Enabled
};
+ InfoBarEntry() = default;
InfoBarEntry(Id _id, const QString &_infoText, GlobalSuppression _globalSuppression = GlobalSuppression::Disabled);
+ Id id() const;
+ QString text() const;
+
using CallBack = std::function<void()>;
- void addCustomButton(const QString &_buttonText, CallBack callBack);
+ void addCustomButton(const QString &_buttonText, CallBack callBack, const QString &tooltip = {});
void setCancelButtonInfo(CallBack callBack);
void setCancelButtonInfo(const QString &_cancelButtonText, CallBack callBack);
- using ComboCallBack = std::function<void(const QString &)>;
- void setComboInfo(const QStringList &list, ComboCallBack callBack);
+ struct ComboInfo
+ {
+ QString displayText;
+ QVariant data;
+ };
+ using ComboCallBack = std::function<void(const ComboInfo &)>;
+ void setComboInfo(const QStringList &list, ComboCallBack callBack, const QString &tooltip = {}, int currentIndex = -1);
+ void setComboInfo(const QList<ComboInfo> &infos, ComboCallBack callBack, const QString &tooltip = {}, int currentIndex = -1);
void removeCancelButton();
using DetailsWidgetCreator = std::function<QWidget*()>;
@@ -72,6 +82,15 @@ private:
{
QString text;
CallBack callback;
+ QString tooltip;
+ };
+
+ struct Combo
+ {
+ ComboCallBack callback;
+ QList<ComboInfo> entries;
+ QString tooltip;
+ int currentIndex = -1;
};
Id m_id;
@@ -79,11 +98,10 @@ private:
QList<Button> m_buttons;
QString m_cancelButtonText;
CallBack m_cancelButtonCallBack;
- GlobalSuppression m_globalSuppression;
+ GlobalSuppression m_globalSuppression = GlobalSuppression::Disabled;
DetailsWidgetCreator m_detailsWidgetCreator;
bool m_useCancelButton = true;
- ComboCallBack m_comboCallBack;
- QStringList m_comboInfo;
+ Combo m_combo;
friend class InfoBar;
friend class InfoBarDisplay;
};
@@ -106,6 +124,7 @@ public:
static bool anyGloballySuppressed();
static void initialize(QSettings *settings);
+ static QSettings *settings();
signals:
void changed();
diff --git a/src/libs/utils/infolabel.cpp b/src/libs/utils/infolabel.cpp
index 7ae39148617..dfacb4a6bec 100644
--- a/src/libs/utils/infolabel.cpp
+++ b/src/libs/utils/infolabel.cpp
@@ -25,12 +25,11 @@
#include "infolabel.h"
-#include <utils/icon.h>
-#include <utils/utilsicons.h>
+#include "icon.h"
+#include "utilsicons.h"
#include <QPainter>
#include <QPaintEvent>
-#include <QLabel>
namespace Utils {
@@ -76,7 +75,7 @@ QSize InfoLabel::minimumSizeHint() const
return baseHint;
}
-static Utils::Theme::Color fillColorForType(InfoLabel::InfoType type)
+static Theme::Color fillColorForType(InfoLabel::InfoType type)
{
using namespace Utils;
switch (type) {
diff --git a/src/libs/utils/itemviews.h b/src/libs/utils/itemviews.h
index 92122a500dc..d336cce5b1e 100644
--- a/src/libs/utils/itemviews.h
+++ b/src/libs/utils/itemviews.h
@@ -27,15 +27,13 @@
#include "utils_global.h"
-static const char activationModeC[] = "ActivationMode";
-
+#include <QKeyEvent>
#include <QListView>
#include <QListWidget>
#include <QTreeView>
#include <QTreeWidget>
-#include <QKeyEvent>
-
+static const char activationModeC[] = "ActivationMode";
namespace Utils {
diff --git a/src/libs/utils/json.cpp b/src/libs/utils/json.cpp
index 2d8a8ae75f6..e7960afe5e5 100644
--- a/src/libs/utils/json.cpp
+++ b/src/libs/utils/json.cpp
@@ -25,11 +25,10 @@
#include "json.h"
-#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
+#include "fileutils.h"
+#include "qtcassert.h"
#include <QDir>
-#include <QDebug>
#include <QJsonDocument>
using namespace Utils;
diff --git a/src/libs/utils/json.h b/src/libs/utils/json.h
index 1179a0c967c..142150493a8 100644
--- a/src/libs/utils/json.h
+++ b/src/libs/utils/json.h
@@ -27,12 +27,14 @@
#include "utils_global.h"
+#include <QDateTime>
#include <QHash>
-#include <QVector>
#include <QStringList>
-#include <QDateTime>
+#include <QVector>
-QT_FORWARD_DECLARE_CLASS(QVariant)
+QT_BEGIN_NAMESPACE
+class QVariant;
+QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/jsontreeitem.cpp b/src/libs/utils/jsontreeitem.cpp
index 16da8e803e6..899b6839e8f 100644
--- a/src/libs/utils/jsontreeitem.cpp
+++ b/src/libs/utils/jsontreeitem.cpp
@@ -28,7 +28,9 @@
#include <QJsonArray>
#include <QJsonObject>
-Utils::JsonTreeItem::JsonTreeItem(const QString &displayName, const QJsonValue &value)
+namespace Utils {
+
+JsonTreeItem::JsonTreeItem(const QString &displayName, const QJsonValue &value)
: m_name(displayName)
, m_value(value)
{ }
@@ -37,24 +39,24 @@ static QString typeName(QJsonValue::Type type)
{
switch (type) {
case QJsonValue::Null:
- return Utils::JsonTreeItem::tr("Null");
+ return JsonTreeItem::tr("Null");
case QJsonValue::Bool:
- return Utils::JsonTreeItem::tr("Bool");
+ return JsonTreeItem::tr("Bool");
case QJsonValue::Double:
- return Utils::JsonTreeItem::tr("Double");
+ return JsonTreeItem::tr("Double");
case QJsonValue::String:
- return Utils::JsonTreeItem::tr("String");
+ return JsonTreeItem::tr("String");
case QJsonValue::Array:
- return Utils::JsonTreeItem::tr("Array");
+ return JsonTreeItem::tr("Array");
case QJsonValue::Object:
- return Utils::JsonTreeItem::tr("Object");
+ return JsonTreeItem::tr("Object");
case QJsonValue::Undefined:
- return Utils::JsonTreeItem::tr("Undefined");
+ return JsonTreeItem::tr("Undefined");
}
return {};
}
-QVariant Utils::JsonTreeItem::data(int column, int role) const
+QVariant JsonTreeItem::data(int column, int role) const
{
if (role != Qt::DisplayRole)
return {};
@@ -69,12 +71,12 @@ QVariant Utils::JsonTreeItem::data(int column, int role) const
return m_value.toVariant();
}
-bool Utils::JsonTreeItem::canFetchMore() const
+bool JsonTreeItem::canFetchMore() const
{
return canFetchObjectChildren() || canFetchArrayChildren();
}
-void Utils::JsonTreeItem::fetchMore()
+void JsonTreeItem::fetchMore()
{
if (canFetchObjectChildren()) {
const QJsonObject &object = m_value.toObject();
@@ -88,12 +90,14 @@ void Utils::JsonTreeItem::fetchMore()
}
}
-bool Utils::JsonTreeItem::canFetchObjectChildren() const
+bool JsonTreeItem::canFetchObjectChildren() const
{
return m_value.isObject() && m_value.toObject().size() > childCount();
}
-bool Utils::JsonTreeItem::canFetchArrayChildren() const
+bool JsonTreeItem::canFetchArrayChildren() const
{
return m_value.isArray() && m_value.toArray().size() > childCount();
}
+
+} // namespace Utils
diff --git a/src/libs/utils/jsontreeitem.h b/src/libs/utils/jsontreeitem.h
index 57eea36536c..22e31fddcbe 100644
--- a/src/libs/utils/jsontreeitem.h
+++ b/src/libs/utils/jsontreeitem.h
@@ -29,8 +29,8 @@
#include "utils_global.h"
-#include <QJsonValue>
#include <QCoreApplication>
+#include <QJsonValue>
namespace Utils {
diff --git a/src/libs/utils/launcherinterface.cpp b/src/libs/utils/launcherinterface.cpp
index 08c93124657..8e402f51c8a 100644
--- a/src/libs/utils/launcherinterface.cpp
+++ b/src/libs/utils/launcherinterface.cpp
@@ -26,7 +26,6 @@
#include "launcherinterface.h"
#include "filepath.h"
-#include "launcherpackets.h"
#include "launchersocket.h"
#include "qtcassert.h"
#include "temporarydirectory.h"
@@ -73,7 +72,7 @@ private:
static QString launcherSocketName()
{
- return Utils::TemporaryDirectory::masterDirectoryPath()
+ return TemporaryDirectory::masterDirectoryPath()
+ QStringLiteral("/launcher-%1").arg(QString::number(qApp->applicationPid()));
}
@@ -227,23 +226,16 @@ bool LauncherInterface::isStarted()
return s_started;
}
-bool LauncherInterface::isReady()
-{
- QMutexLocker locker(&s_instanceMutex);
- return instance()->m_private->socket()->isReady();
-}
-
void LauncherInterface::sendData(const QByteArray &data)
{
QMutexLocker locker(&s_instanceMutex);
instance()->m_private->socket()->sendData(data);
}
-Utils::Internal::CallerHandle *LauncherInterface::registerHandle(QObject *parent, quintptr token,
- ProcessMode mode)
+Internal::CallerHandle *LauncherInterface::registerHandle(QObject *parent, quintptr token)
{
QMutexLocker locker(&s_instanceMutex);
- return instance()->m_private->socket()->registerHandle(parent, token, mode);
+ return instance()->m_private->socket()->registerHandle(parent, token);
}
void LauncherInterface::unregisterHandle(quintptr token)
diff --git a/src/libs/utils/launcherinterface.h b/src/libs/utils/launcherinterface.h
index 541501efeec..6686f1d3d4e 100644
--- a/src/libs/utils/launcherinterface.h
+++ b/src/libs/utils/launcherinterface.h
@@ -28,7 +28,6 @@
#include "utils_global.h"
#include "processreaper.h"
-#include "processutils.h"
#include "singleton.h"
#include <QThread>
@@ -48,15 +47,13 @@ public:
static void setPathToLauncher(const QString &pathToLauncher);
private:
- friend class Utils::Internal::CallerHandle;
- friend class Utils::Internal::LauncherHandle;
- friend class Utils::Internal::ProcessLauncherImpl;
+ friend class Internal::CallerHandle;
+ friend class Internal::LauncherHandle;
+ friend class Internal::ProcessLauncherImpl;
static bool isStarted();
- static bool isReady();
static void sendData(const QByteArray &data);
- static Utils::Internal::CallerHandle *registerHandle(QObject *parent, quintptr token,
- ProcessMode mode);
+ static Internal::CallerHandle *registerHandle(QObject *parent, quintptr token);
static void unregisterHandle(quintptr token);
LauncherInterface();
diff --git a/src/libs/utils/launcherpackets.cpp b/src/libs/utils/launcherpackets.cpp
index a810fbd7b0e..87a3656306a 100644
--- a/src/libs/utils/launcherpackets.cpp
+++ b/src/libs/utils/launcherpackets.cpp
@@ -26,7 +26,6 @@
#include "launcherpackets.h"
#include <QByteArray>
-#include <QCoreApplication>
namespace Utils {
namespace Internal {
@@ -58,19 +57,42 @@ StartProcessPacket::StartProcessPacket(quintptr token)
void StartProcessPacket::doSerialize(QDataStream &stream) const
{
- stream << command << arguments << workingDir << env << int(processMode) << writeData << int(channelMode)
- << standardInputFile << belowNormalPriority << nativeArguments << lowPriority
- << unixTerminalDisabled;
+ stream << command
+ << arguments
+ << workingDir
+ << env
+ << int(processMode)
+ << writeData
+ << int(processChannelMode)
+ << standardInputFile
+ << belowNormalPriority
+ << nativeArguments
+ << lowPriority
+ << unixTerminalDisabled
+ << useCtrlCStub
+ << reaperTimeout;
}
void StartProcessPacket::doDeserialize(QDataStream &stream)
{
- int cm, pm;
- stream >> command >> arguments >> workingDir >> env >> pm >> writeData >> cm
- >> standardInputFile >> belowNormalPriority >> nativeArguments >> lowPriority
- >> unixTerminalDisabled;
- channelMode = QProcess::ProcessChannelMode(cm);
- processMode = Utils::ProcessMode(pm);
+ int processModeInt;
+ int processChannelModeInt;
+ stream >> command
+ >> arguments
+ >> workingDir
+ >> env
+ >> processModeInt
+ >> writeData
+ >> processChannelModeInt
+ >> standardInputFile
+ >> belowNormalPriority
+ >> nativeArguments
+ >> lowPriority
+ >> unixTerminalDisabled
+ >> useCtrlCStub
+ >> reaperTimeout;
+ processMode = Utils::ProcessMode(processModeInt);
+ processChannelMode = QProcess::ProcessChannelMode(processChannelModeInt);
}
@@ -97,12 +119,14 @@ StopProcessPacket::StopProcessPacket(quintptr token)
void StopProcessPacket::doSerialize(QDataStream &stream) const
{
- Q_UNUSED(stream);
+ stream << int(signalType);
}
void StopProcessPacket::doDeserialize(QDataStream &stream)
{
- Q_UNUSED(stream);
+ int signalTypeInt;
+ stream >> signalTypeInt;
+ signalType = SignalType(signalTypeInt);
}
void WritePacket::doSerialize(QDataStream &stream) const
@@ -115,25 +139,6 @@ void WritePacket::doDeserialize(QDataStream &stream)
stream >> inputData;
}
-ProcessErrorPacket::ProcessErrorPacket(quintptr token)
- : LauncherPacket(LauncherPacketType::ProcessError, token)
-{
-}
-
-void ProcessErrorPacket::doSerialize(QDataStream &stream) const
-{
- stream << static_cast<quint8>(error) << errorString;
-}
-
-void ProcessErrorPacket::doDeserialize(QDataStream &stream)
-{
- quint8 e;
- stream >> e;
- error = static_cast<QProcess::ProcessError>(e);
- stream >> errorString;
-}
-
-
void ReadyReadPacket::doSerialize(QDataStream &stream) const
{
stream << standardChannel;
@@ -145,27 +150,32 @@ void ReadyReadPacket::doDeserialize(QDataStream &stream)
}
-ProcessFinishedPacket::ProcessFinishedPacket(quintptr token)
- : LauncherPacket(LauncherPacketType::ProcessFinished, token)
+ProcessDonePacket::ProcessDonePacket(quintptr token)
+ : LauncherPacket(LauncherPacketType::ProcessDone, token)
{
}
-void ProcessFinishedPacket::doSerialize(QDataStream &stream) const
+void ProcessDonePacket::doSerialize(QDataStream &stream) const
{
- stream << errorString << stdOut << stdErr
- << static_cast<quint8>(exitStatus) << static_cast<quint8>(error)
- << exitCode;
+ stream << exitCode
+ << int(exitStatus)
+ << int(error)
+ << errorString
+ << stdOut
+ << stdErr;
}
-void ProcessFinishedPacket::doDeserialize(QDataStream &stream)
+void ProcessDonePacket::doDeserialize(QDataStream &stream)
{
- stream >> errorString >> stdOut >> stdErr;
- quint8 val;
- stream >> val;
- exitStatus = static_cast<QProcess::ExitStatus>(val);
- stream >> val;
- error = static_cast<QProcess::ProcessError>(val);
- stream >> exitCode;
+ int exitStatusInt, errorInt;
+ stream >> exitCode
+ >> exitStatusInt
+ >> errorInt
+ >> errorString
+ >> stdOut
+ >> stdErr;
+ exitStatus = QProcess::ExitStatus(exitStatusInt);
+ error = QProcess::ProcessError(errorInt);
}
ShutdownPacket::ShutdownPacket() : LauncherPacket(LauncherPacketType::Shutdown, 0) { }
diff --git a/src/libs/utils/launcherpackets.h b/src/libs/utils/launcherpackets.h
index 372290f1ca5..066862ef796 100644
--- a/src/libs/utils/launcherpackets.h
+++ b/src/libs/utils/launcherpackets.h
@@ -25,7 +25,7 @@
#pragma once
-#include "processutils.h"
+#include "processenums.h"
#include <QDataStream>
#include <QProcess>
@@ -45,11 +45,10 @@ enum class LauncherPacketType {
WriteIntoProcess,
StopProcess,
// launcher -> client packets:
- ProcessError,
ProcessStarted,
ReadyReadStandardOutput,
ReadyReadStandardError,
- ProcessFinished
+ ProcessDone
};
class PacketParser
@@ -113,12 +112,14 @@ public:
QStringList env;
ProcessMode processMode = ProcessMode::Reader;
QByteArray writeData;
- QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels;
+ QProcess::ProcessChannelMode processChannelMode = QProcess::SeparateChannels;
QString standardInputFile;
bool belowNormalPriority = false;
QString nativeArguments;
bool lowPriority = false;
bool unixTerminalDisabled = false;
+ bool useCtrlCStub = false;
+ int reaperTimeout = 500;
private:
void doSerialize(QDataStream &stream) const override;
@@ -142,6 +143,14 @@ class StopProcessPacket : public LauncherPacket
public:
StopProcessPacket(quintptr token);
+ enum class SignalType {
+ Kill, // Calls QProcess::kill
+ Terminate, // Calls QProcess::terminate
+ Close // Puts the process into the reaper, no confirmation signal is being sent.
+ };
+
+ SignalType signalType = SignalType::Kill;
+
private:
void doSerialize(QDataStream &stream) const override;
void doDeserialize(QDataStream &stream) override;
@@ -169,19 +178,6 @@ private:
void doDeserialize(QDataStream &stream) override;
};
-class ProcessErrorPacket : public LauncherPacket
-{
-public:
- ProcessErrorPacket(quintptr token);
-
- QProcess::ProcessError error = QProcess::UnknownError;
- QString errorString;
-
-private:
- void doSerialize(QDataStream &stream) const override;
- void doDeserialize(QDataStream &stream) override;
-};
-
class ReadyReadPacket : public LauncherPacket
{
public:
@@ -209,17 +205,18 @@ public:
: ReadyReadPacket(LauncherPacketType::ReadyReadStandardError, token) { }
};
-class ProcessFinishedPacket : public LauncherPacket
+class ProcessDonePacket : public LauncherPacket
{
public:
- ProcessFinishedPacket(quintptr token);
+ ProcessDonePacket(quintptr token);
- QString errorString;
QByteArray stdOut;
QByteArray stdErr;
- QProcess::ExitStatus exitStatus = QProcess::ExitStatus::NormalExit;
- QProcess::ProcessError error = QProcess::ProcessError::UnknownError;
+
int exitCode = 0;
+ QProcess::ExitStatus exitStatus = QProcess::NormalExit;
+ QProcess::ProcessError error = QProcess::UnknownError;
+ QString errorString;
private:
void doSerialize(QDataStream &stream) const override;
diff --git a/src/libs/utils/launchersocket.cpp b/src/libs/utils/launchersocket.cpp
index d2ee1cf19fd..c3d2b8942ab 100644
--- a/src/libs/utils/launchersocket.cpp
+++ b/src/libs/utils/launchersocket.cpp
@@ -33,8 +33,6 @@
#include <QLocalSocket>
#include <QMutexLocker>
-#include <iostream>
-
namespace Utils {
namespace Internal {
@@ -49,24 +47,10 @@ private:
const CallerHandle::SignalType m_signalType;
};
-class ErrorSignal : public LauncherSignal
-{
-public:
- ErrorSignal(QProcess::ProcessError error, const QString &errorString)
- : LauncherSignal(CallerHandle::SignalType::Error)
- , m_error(error)
- , m_errorString(errorString) {}
- QProcess::ProcessError error() const { return m_error; }
- QString errorString() const { return m_errorString; }
-private:
- const QProcess::ProcessError m_error;
- const QString m_errorString;
-};
-
-class StartedSignal : public LauncherSignal
+class LauncherStartedSignal : public LauncherSignal
{
public:
- StartedSignal(int processId)
+ LauncherStartedSignal(int processId)
: LauncherSignal(CallerHandle::SignalType::Started)
, m_processId(processId) {}
int processId() const { return m_processId; }
@@ -74,33 +58,30 @@ private:
const int m_processId;
};
-class ReadyReadSignal : public LauncherSignal
+class LauncherReadyReadSignal : public LauncherSignal
{
public:
- ReadyReadSignal(const QByteArray &stdOut, const QByteArray &stdErr)
+ LauncherReadyReadSignal(const QByteArray &stdOut, const QByteArray &stdErr)
: LauncherSignal(CallerHandle::SignalType::ReadyRead)
, m_stdOut(stdOut)
, m_stdErr(stdErr) {}
QByteArray stdOut() const { return m_stdOut; }
QByteArray stdErr() const { return m_stdErr; }
+
private:
QByteArray m_stdOut;
QByteArray m_stdErr;
};
-class FinishedSignal : public LauncherSignal
+class LauncherDoneSignal : public LauncherSignal
{
public:
- FinishedSignal(QProcess::ExitStatus exitStatus,
- int exitCode)
- : LauncherSignal(CallerHandle::SignalType::Finished)
- , m_exitStatus(exitStatus)
- , m_exitCode(exitCode) {}
- QProcess::ExitStatus exitStatus() const { return m_exitStatus; }
- int exitCode() const { return m_exitCode; }
+ LauncherDoneSignal(const ProcessResultData &resultData)
+ : LauncherSignal(CallerHandle::SignalType::Done)
+ , m_resultData(resultData) {}
+ ProcessResultData resultData() const { return m_resultData; }
private:
- const QProcess::ExitStatus m_exitStatus;
- const int m_exitCode;
+ const ProcessResultData m_resultData;
};
CallerHandle::~CallerHandle()
@@ -108,163 +89,103 @@ CallerHandle::~CallerHandle()
qDeleteAll(m_signals);
}
-bool CallerHandle::waitForStarted(int msecs)
-{
- return waitForSignal(msecs, SignalType::Started);
-}
-
-bool CallerHandle::waitForReadyRead(int msces)
+void CallerHandle::flush()
{
- return waitForSignal(msces, SignalType::ReadyRead);
+ flushFor(SignalType::NoSignal);
}
-bool CallerHandle::waitForFinished(int msecs)
-{
- return waitForSignal(msecs, SignalType::Finished);
-}
-
-QList<CallerHandle::SignalType> CallerHandle::flush()
-{
- return flushFor(CallerHandle::SignalType::NoSignal);
-}
-
-QList<CallerHandle::SignalType> CallerHandle::flushFor(CallerHandle::SignalType signalType)
+bool CallerHandle::flushFor(SignalType signalType)
{
QTC_ASSERT(isCalledFromCallersThread(), return {});
QList<LauncherSignal *> oldSignals;
- QList<CallerHandle::SignalType> flushedSignals;
{
- // 1. If signalType is no signal - flush all
- // 2. Flush all if we have any error
- // 3. If we are flushing for Finished or ReadyRead, flush all, too
- // 4. If we are flushing for Started, flush Started only
-
QMutexLocker locker(&m_mutex);
-
- const QList<CallerHandle::SignalType> storedSignals =
+ const QList<SignalType> storedSignals =
Utils::transform(qAsConst(m_signals), [](const LauncherSignal *launcherSignal) {
return launcherSignal->signalType();
});
- const bool flushAll = (signalType == CallerHandle::SignalType::NoSignal)
- || (signalType == CallerHandle::SignalType::ReadyRead)
- || (signalType == CallerHandle::SignalType::Finished)
- || storedSignals.contains(CallerHandle::SignalType::Error);
+ // If we are flushing for ReadyRead or Done - flush all.
+ // If we are flushing for Started:
+ // - if Started was buffered - flush Started only.
+ // - otherwise if Done signal was buffered - flush all.
+ const bool flushAll = (signalType != SignalType::Started)
+ || (!storedSignals.contains(SignalType::Started)
+ && storedSignals.contains(SignalType::Done));
if (flushAll) {
oldSignals = m_signals;
m_signals = {};
- flushedSignals = storedSignals;
} else {
auto matchingIndex = storedSignals.lastIndexOf(signalType);
- if (matchingIndex < 0 && (signalType == CallerHandle::SignalType::ReadyRead))
- matchingIndex = storedSignals.lastIndexOf(CallerHandle::SignalType::Started);
if (matchingIndex >= 0) {
oldSignals = m_signals.mid(0, matchingIndex + 1);
m_signals = m_signals.mid(matchingIndex + 1);
- flushedSignals = storedSignals.mid(0, matchingIndex + 1);
}
}
}
+ bool signalMatched = false;
for (const LauncherSignal *storedSignal : qAsConst(oldSignals)) {
- const CallerHandle::SignalType storedSignalType = storedSignal->signalType();
+ const SignalType storedSignalType = storedSignal->signalType();
+ if (storedSignalType == signalType)
+ signalMatched = true;
switch (storedSignalType) {
case SignalType::NoSignal:
break;
- case SignalType::Error:
- handleError(static_cast<const ErrorSignal *>(storedSignal));
- break;
case SignalType::Started:
- handleStarted(static_cast<const StartedSignal *>(storedSignal));
+ handleStarted(static_cast<const LauncherStartedSignal *>(storedSignal));
break;
case SignalType::ReadyRead:
- handleReadyRead(static_cast<const ReadyReadSignal *>(storedSignal));
+ handleReadyRead(static_cast<const LauncherReadyReadSignal *>(storedSignal));
break;
- case SignalType::Finished:
- handleFinished(static_cast<const FinishedSignal *>(storedSignal));
+ case SignalType::Done:
+ signalMatched = true;
+ handleDone(static_cast<const LauncherDoneSignal *>(storedSignal));
break;
}
delete storedSignal;
}
- return flushedSignals;
+ return signalMatched;
}
// Called from caller's thread exclusively.
-bool CallerHandle::shouldFlushFor(SignalType signalType) const
+bool CallerHandle::shouldFlush() const
{
QTC_ASSERT(isCalledFromCallersThread(), return false);
- // TODO: Should we always flush when the list isn't empty?
QMutexLocker locker(&m_mutex);
- for (const LauncherSignal *storedSignal : m_signals) {
- const CallerHandle::SignalType storedSignalType = storedSignal->signalType();
- if (storedSignalType == signalType)
- return true;
- if (storedSignalType == SignalType::Error)
- return true;
- if (storedSignalType == SignalType::Finished)
- return true;
- }
- return false;
+ return !m_signals.isEmpty();
}
-void CallerHandle::handleError(const ErrorSignal *launcherSignal)
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_processState = QProcess::NotRunning;
- m_error = launcherSignal->error();
- m_errorString = launcherSignal->errorString();
- if (m_error == QProcess::FailedToStart)
- m_exitCode = 255; // This code is being returned by QProcess when FailedToStart error occurred
- emit errorOccurred(m_error);
-}
-
-void CallerHandle::handleStarted(const StartedSignal *launcherSignal)
+void CallerHandle::handleStarted(const LauncherStartedSignal *launcherSignal)
{
QTC_ASSERT(isCalledFromCallersThread(), return);
m_processState = QProcess::Running;
m_processId = launcherSignal->processId();
- emit started();
+ emit started(m_processId);
}
-void CallerHandle::handleReadyRead(const ReadyReadSignal *launcherSignal)
+void CallerHandle::handleReadyRead(const LauncherReadyReadSignal *launcherSignal)
{
QTC_ASSERT(isCalledFromCallersThread(), return);
- if (m_channelMode == QProcess::ForwardedOutputChannel
- || m_channelMode == QProcess::ForwardedChannels) {
- std::cout << launcherSignal->stdOut().constData();
- } else {
- m_stdout += launcherSignal->stdOut();
- if (!m_stdout.isEmpty())
- emit readyReadStandardOutput();
- }
- if (m_channelMode == QProcess::ForwardedErrorChannel
- || m_channelMode == QProcess::ForwardedChannels) {
- std::cerr << launcherSignal->stdErr().constData();
- } else {
- m_stderr += launcherSignal->stdErr();
- if (!m_stderr.isEmpty())
- emit readyReadStandardError();
- }
+ emit readyRead(launcherSignal->stdOut(), launcherSignal->stdErr());
}
-void CallerHandle::handleFinished(const FinishedSignal *launcherSignal)
+void CallerHandle::handleDone(const LauncherDoneSignal *launcherSignal)
{
QTC_ASSERT(isCalledFromCallersThread(), return);
m_processState = QProcess::NotRunning;
- m_exitStatus = launcherSignal->exitStatus();
- m_exitCode = launcherSignal->exitCode();
- emit finished(m_exitCode, m_exitStatus);
+ emit done(launcherSignal->resultData());
+ m_processId = 0;
}
// Called from launcher's thread exclusively.
-void CallerHandle::appendSignal(LauncherSignal *launcherSignal)
+void CallerHandle::appendSignal(LauncherSignal *newSignal)
{
QTC_ASSERT(!isCalledFromCallersThread(), return);
- if (launcherSignal->signalType() == SignalType::NoSignal)
- return;
+ QTC_ASSERT(newSignal->signalType() != SignalType::NoSignal, delete newSignal; return);
QMutexLocker locker(&m_mutex);
QTC_ASSERT(isCalledFromLaunchersThread(), return);
- m_signals.append(launcherSignal);
+ m_signals.append(newSignal);
}
QProcess::ProcessState CallerHandle::state() const
@@ -272,72 +193,53 @@ QProcess::ProcessState CallerHandle::state() const
return m_processState;
}
-void CallerHandle::cancel()
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- switch (m_processState.exchange(QProcess::NotRunning)) {
- case QProcess::NotRunning:
- break;
- case QProcess::Starting:
- m_errorString = QCoreApplication::translate("Utils::LauncherHandle",
- "Process was canceled before it was started.");
- m_error = QProcess::FailedToStart;
- if (LauncherInterface::isReady()) // TODO: race condition with m_processState???
- sendPacket(StopProcessPacket(m_token));
- else
- emit errorOccurred(m_error);
- break;
- case QProcess::Running:
- sendPacket(StopProcessPacket(m_token));
- break;
- }
-
- if (m_launcherHandle)
- m_launcherHandle->setCanceled();
-}
-
-QByteArray CallerHandle::readAllStandardOutput()
+void CallerHandle::sendStopPacket(StopProcessPacket::SignalType signalType)
{
- QTC_ASSERT(isCalledFromCallersThread(), return {});
- return readAndClear(m_stdout);
-}
+ if (m_processState == QProcess::NotRunning)
+ return;
-QByteArray CallerHandle::readAllStandardError()
-{
- QTC_ASSERT(isCalledFromCallersThread(), return {});
- return readAndClear(m_stderr);
+ // TODO: In case m_processState == QProcess::Starting and the launcher socket isn't ready yet
+ // we might want to remove posted start packet and finish the process immediately.
+ // In addition, we may always try to check if correspodning start packet for the m_token
+ // is still awaiting and do the same (remove the packet from the stack and finish immediately).
+ StopProcessPacket packet(m_token);
+ packet.signalType = signalType;
+ sendPacket(packet);
}
-qint64 CallerHandle::processId() const
+void CallerHandle::terminate()
{
- QTC_ASSERT(isCalledFromCallersThread(), return 0);
- return m_processId;
+ QTC_ASSERT(isCalledFromCallersThread(), return);
+ sendStopPacket(StopProcessPacket::SignalType::Terminate);
}
-int CallerHandle::exitCode() const
+void CallerHandle::kill()
{
- QTC_ASSERT(isCalledFromCallersThread(), return -1);
- return m_exitCode;
+ QTC_ASSERT(isCalledFromCallersThread(), return);
+ sendStopPacket(StopProcessPacket::SignalType::Kill);
}
-QString CallerHandle::errorString() const
+void CallerHandle::close()
{
- QTC_ASSERT(isCalledFromCallersThread(), return {});
- return m_errorString;
+ QTC_ASSERT(isCalledFromCallersThread(), return);
+ sendStopPacket(StopProcessPacket::SignalType::Close);
}
-void CallerHandle::setErrorString(const QString &str)
+qint64 CallerHandle::processId() const
{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_errorString = str;
+ QTC_ASSERT(isCalledFromCallersThread(), return 0);
+ return m_processId;
}
-void CallerHandle::start(const QString &program, const QStringList &arguments, const QByteArray &writeData)
+void CallerHandle::start(const QString &program, const QStringList &arguments)
{
QTC_ASSERT(isCalledFromCallersThread(), return);
if (!m_launcherHandle || m_launcherHandle->isSocketError()) {
- m_error = QProcess::FailedToStart;
- emit errorOccurred(m_error);
+ const QString errorString = QCoreApplication::translate("Utils::LauncherHandle",
+ "Process launcher socket error.");
+ const ProcessResultData result = { 0, QProcess::NormalExit, QProcess::FailedToStart,
+ errorString };
+ emit done(result);
return;
}
@@ -356,44 +258,26 @@ void CallerHandle::start(const QString &program, const QStringList &arguments, c
QMutexLocker locker(&m_mutex);
m_command = program;
m_arguments = arguments;
- m_writeData = writeData;
m_processState = QProcess::Starting;
- StartProcessPacket *p = new StartProcessPacket(m_token);
- p->command = m_command;
- p->arguments = m_arguments;
- p->env = m_environment.toStringList();
- p->workingDir = m_workingDirectory;
- p->processMode = m_processMode;
- p->writeData = m_writeData;
- p->channelMode = m_channelMode;
- p->standardInputFile = m_standardInputFile;
- p->belowNormalPriority = m_belowNormalPriority;
- p->nativeArguments = m_nativeArguments;
- p->lowPriority = m_lowPriority;
- p->unixTerminalDisabled = m_unixTerminalDisabled;
- m_startPacket.reset(p);
- if (LauncherInterface::isReady())
- doStart();
-}
-
-// Called from caller's or launcher's thread.
-void CallerHandle::startIfNeeded()
-{
- QMutexLocker locker(&m_mutex);
- if (m_processState == QProcess::Starting)
- doStart();
-}
-
-// Called from caller's or launcher's thread. Call me with mutex locked.
-void CallerHandle::doStart()
-{
- if (!m_startPacket)
- return;
- sendPacket(*m_startPacket);
- m_startPacket.reset(nullptr);
+ StartProcessPacket p(m_token);
+ p.command = m_command;
+ p.arguments = m_arguments;
+ p.env = m_setup->m_environment.toStringList();
+ p.workingDir = m_setup->m_workingDirectory.path();
+ p.processMode = m_setup->m_processMode;
+ p.writeData = m_setup->m_writeData;
+ p.processChannelMode = m_setup->m_processChannelMode;
+ p.standardInputFile = m_setup->m_standardInputFile;
+ p.belowNormalPriority = m_setup->m_belowNormalPriority;
+ p.nativeArguments = m_setup->m_nativeArguments;
+ p.lowPriority = m_setup->m_lowPriority;
+ p.unixTerminalDisabled = m_setup->m_unixTerminalDisabled;
+ p.useCtrlCStub = m_setup->m_useCtrlCStub;
+ p.reaperTimeout = m_setup->m_reaperTimeout;
+ sendPacket(p);
}
-// Called from caller's or launcher's thread.
+// Called from caller's thread exclusively.
void CallerHandle::sendPacket(const Internal::LauncherPacket &packet)
{
LauncherInterface::sendData(packet.serialize());
@@ -412,12 +296,6 @@ qint64 CallerHandle::write(const QByteArray &data)
return data.size();
}
-QProcess::ProcessError CallerHandle::error() const
-{
- QTC_ASSERT(isCalledFromCallersThread(), return QProcess::UnknownError);
- return m_error;
-}
-
QString CallerHandle::program() const
{
QMutexLocker locker(&m_mutex);
@@ -430,83 +308,17 @@ QStringList CallerHandle::arguments() const
return m_arguments;
}
-void CallerHandle::setStandardInputFile(const QString &fileName)
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_standardInputFile = fileName;
-}
-
-void CallerHandle::setProcessChannelMode(QProcess::ProcessChannelMode mode)
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_channelMode = mode;
-}
-
-void CallerHandle::setProcessEnvironment(const QProcessEnvironment &environment)
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_environment = environment;
-}
-
-void CallerHandle::setWorkingDirectory(const QString &dir)
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_workingDirectory = dir;
-}
-
-QProcess::ExitStatus CallerHandle::exitStatus() const
-{
- QTC_ASSERT(isCalledFromCallersThread(), return QProcess::CrashExit);
- return m_exitStatus;
-}
-
-void CallerHandle::setBelowNormalPriority()
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_belowNormalPriority = true;
-}
-
-void CallerHandle::setNativeArguments(const QString &arguments)
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_nativeArguments = arguments;
-}
-
-void CallerHandle::setLowPriority()
+void CallerHandle::setProcessSetupData(ProcessSetupData *setup)
{
QTC_ASSERT(isCalledFromCallersThread(), return);
- m_lowPriority = true;
-}
-
-void CallerHandle::setUnixTerminalDisabled()
-{
- QTC_ASSERT(isCalledFromCallersThread(), return);
- m_unixTerminalDisabled = true;
-}
-
-bool CallerHandle::waitForSignal(int msecs, CallerHandle::SignalType newSignal)
-{
- QTC_ASSERT(isCalledFromCallersThread(), return false);
- if (!canWaitFor(newSignal))
- return false;
- if (!m_launcherHandle)
- return false;
- return m_launcherHandle->waitForSignal(msecs, newSignal);
+ m_setup = setup;
}
-bool CallerHandle::canWaitFor(SignalType newSignal) const
+bool CallerHandle::waitForSignal(SignalType signalType, int msecs)
{
QTC_ASSERT(isCalledFromCallersThread(), return false);
- switch (newSignal) {
- case SignalType::Started:
- return m_processState == QProcess::Starting;
- case SignalType::ReadyRead:
- case SignalType::Finished:
- return m_processState != QProcess::NotRunning;
- default:
- break;
- }
- return false;
+ QTC_ASSERT(m_launcherHandle, return false);
+ return m_launcherHandle->waitForSignal(signalType, msecs);
}
// Called from caller's or launcher's thread.
@@ -524,77 +336,36 @@ bool CallerHandle::isCalledFromLaunchersThread() const
}
// Called from caller's thread exclusively.
-bool LauncherHandle::waitForSignal(int msecs, CallerHandle::SignalType newSignal)
+bool LauncherHandle::waitForSignal(CallerHandle::SignalType newSignal, int msecs)
{
QTC_ASSERT(!isCalledFromLaunchersThread(), return false);
QDeadlineTimer deadline(msecs);
while (true) {
if (deadline.hasExpired())
break;
- if (!doWaitForSignal(deadline, newSignal))
+ if (!doWaitForSignal(deadline))
break;
- m_awaitingShouldContinue = true; // TODO: make it recursive?
- const QList<CallerHandle::SignalType> flushedSignals = m_callerHandle->flushFor(newSignal);
- const bool wasCanceled = !m_awaitingShouldContinue;
- m_awaitingShouldContinue = false;
- const bool errorOccurred = flushedSignals.contains(CallerHandle::SignalType::Error);
- if (errorOccurred)
- return false; // apparently QProcess behaves like this in case of error
- const bool newSignalFlushed = flushedSignals.contains(newSignal);
- if (newSignalFlushed) // so we don't continue waiting
+ // Matching (or Done) signal was flushed
+ if (m_callerHandle->flushFor(newSignal))
return true;
- if (wasCanceled)
- return true; // or false? is false only in case of timeout?
- const bool finishedSignalFlushed = flushedSignals.contains(CallerHandle::SignalType::Finished);
- if (finishedSignalFlushed)
- return false; // finish has appeared but we were waiting for other signal
+ // Otherwise continue awaiting (e.g. when ReadyRead came while waitForFinished())
}
return false;
}
// Called from caller's thread exclusively.
-bool LauncherHandle::doWaitForSignal(QDeadlineTimer deadline, CallerHandle::SignalType newSignal)
+bool LauncherHandle::doWaitForSignal(QDeadlineTimer deadline)
{
QMutexLocker locker(&m_mutex);
QTC_ASSERT(isCalledFromCallersThread(), return false);
- QTC_ASSERT(m_waitingFor == CallerHandle::SignalType::NoSignal, return false);
- // It may happen, that after calling start() and before calling waitForStarted() we might have
- // reached the Running (or even Finished) state already. In this case we should have
- // collected Started (or even Finished) signal to be flushed - so we return true
- // and we are going to flush pending signals synchronously.
- // It could also happen, that some new readyRead data has appeared, so before we wait for
- // more we flush it, too.
- if (m_callerHandle->shouldFlushFor(newSignal))
+
+ // Flush, if we have any stored signals.
+ // This must be called when holding laucher's mutex locked prior to the call to wait,
+ // so that it's done atomically.
+ if (m_callerHandle->shouldFlush())
return true;
- m_waitingFor = newSignal;
- const bool ret = m_waitCondition.wait(&m_mutex, deadline);
- m_waitingFor = CallerHandle::SignalType::NoSignal;
- return ret;
-}
-
-// Called from launcher's thread exclusively. Call me with mutex locked.
-void LauncherHandle::wakeUpIfWaitingFor(CallerHandle::SignalType newSignal)
-{
- QTC_ASSERT(isCalledFromLaunchersThread(), return);
- // TODO: should we always wake up in case m_waitingFor != NoSignal?
- // The matching signal came
- const bool signalMatched = (m_waitingFor == newSignal);
- // E.g. if we are waiting for ReadyRead and we got Finished or Error signal instead -> wake it, too.
- const bool finishedOrErrorWhileWaiting =
- (m_waitingFor != CallerHandle::SignalType::NoSignal)
- && ((newSignal == CallerHandle::SignalType::Finished) || (newSignal == CallerHandle::SignalType::Error));
- // Wake up, flush and continue waiting.
- // E.g. when being in waitingForFinished() state and Started or ReadyRead signal came.
- const bool continueWaitingAfterFlushing =
- ((m_waitingFor == CallerHandle::SignalType::Finished) && (newSignal != CallerHandle::SignalType::Finished))
- || ((m_waitingFor == CallerHandle::SignalType::ReadyRead) && (newSignal == CallerHandle::SignalType::Started));
- const bool shouldWake = signalMatched
- || finishedOrErrorWhileWaiting
- || continueWaitingAfterFlushing;
-
- if (shouldWake)
- m_waitCondition.wakeOne();
+ return m_waitCondition.wait(&m_mutex, deadline);
}
// Called from launcher's thread exclusively. Call me with mutex locked.
@@ -604,6 +375,8 @@ void LauncherHandle::flushCaller()
if (!m_callerHandle)
return;
+ m_waitCondition.wakeOne();
+
// call in callers thread
QMetaObject::invokeMethod(m_callerHandle, &CallerHandle::flush);
}
@@ -612,9 +385,6 @@ void LauncherHandle::handlePacket(LauncherPacketType type, const QByteArray &pay
{
QTC_ASSERT(isCalledFromLaunchersThread(), return);
switch (type) {
- case LauncherPacketType::ProcessError:
- handleErrorPacket(payload);
- break;
case LauncherPacketType::ProcessStarted:
handleStartedPacket(payload);
break;
@@ -624,37 +394,23 @@ void LauncherHandle::handlePacket(LauncherPacketType type, const QByteArray &pay
case LauncherPacketType::ReadyReadStandardError:
handleReadyReadStandardError(payload);
break;
- case LauncherPacketType::ProcessFinished:
- handleFinishedPacket(payload);
+ case LauncherPacketType::ProcessDone:
+ handleDonePacket(payload);
break;
default:
QTC_ASSERT(false, break);
}
}
-void LauncherHandle::handleErrorPacket(const QByteArray &packetData)
-{
- QTC_ASSERT(isCalledFromLaunchersThread(), return);
- QMutexLocker locker(&m_mutex);
- wakeUpIfWaitingFor(CallerHandle::SignalType::Error);
- if (!m_callerHandle)
- return;
-
- const auto packet = LauncherPacket::extractPacket<ProcessErrorPacket>(m_token, packetData);
- m_callerHandle->appendSignal(new ErrorSignal(packet.error, packet.errorString));
- flushCaller();
-}
-
void LauncherHandle::handleStartedPacket(const QByteArray &packetData)
{
QTC_ASSERT(isCalledFromLaunchersThread(), return);
QMutexLocker locker(&m_mutex);
- wakeUpIfWaitingFor(CallerHandle::SignalType::Started);
if (!m_callerHandle)
return;
const auto packet = LauncherPacket::extractPacket<ProcessStartedPacket>(m_token, packetData);
- m_callerHandle->appendSignal(new StartedSignal(packet.processId));
+ m_callerHandle->appendSignal(new LauncherStartedSignal(packet.processId));
flushCaller();
}
@@ -662,7 +418,6 @@ void LauncherHandle::handleReadyReadStandardOutput(const QByteArray &packetData)
{
QTC_ASSERT(isCalledFromLaunchersThread(), return);
QMutexLocker locker(&m_mutex);
- wakeUpIfWaitingFor(CallerHandle::SignalType::ReadyRead);
if (!m_callerHandle)
return;
@@ -670,7 +425,7 @@ void LauncherHandle::handleReadyReadStandardOutput(const QByteArray &packetData)
if (packet.standardChannel.isEmpty())
return;
- m_callerHandle->appendSignal(new ReadyReadSignal(packet.standardChannel, {}));
+ m_callerHandle->appendSignal(new LauncherReadyReadSignal(packet.standardChannel, {}));
flushCaller();
}
@@ -678,7 +433,6 @@ void LauncherHandle::handleReadyReadStandardError(const QByteArray &packetData)
{
QTC_ASSERT(isCalledFromLaunchersThread(), return);
QMutexLocker locker(&m_mutex);
- wakeUpIfWaitingFor(CallerHandle::SignalType::ReadyRead);
if (!m_callerHandle)
return;
@@ -686,55 +440,43 @@ void LauncherHandle::handleReadyReadStandardError(const QByteArray &packetData)
if (packet.standardChannel.isEmpty())
return;
- m_callerHandle->appendSignal(new ReadyReadSignal({}, packet.standardChannel));
+ m_callerHandle->appendSignal(new LauncherReadyReadSignal({}, packet.standardChannel));
flushCaller();
}
-void LauncherHandle::handleFinishedPacket(const QByteArray &packetData)
+void LauncherHandle::handleDonePacket(const QByteArray &packetData)
{
QTC_ASSERT(isCalledFromLaunchersThread(), return);
QMutexLocker locker(&m_mutex);
- wakeUpIfWaitingFor(CallerHandle::SignalType::Finished);
if (!m_callerHandle)
return;
- const auto packet = LauncherPacket::extractPacket<ProcessFinishedPacket>(m_token, packetData);
+ const auto packet = LauncherPacket::extractPacket<ProcessDonePacket>(m_token, packetData);
const QByteArray stdOut = packet.stdOut;
const QByteArray stdErr = packet.stdErr;
- const QProcess::ProcessError error = packet.error;
- const QString errorString = packet.errorString;
+ const ProcessResultData result = { packet.exitCode, packet.exitStatus,
+ packet.error, packet.errorString };
- // We assume that if error is UnknownError, everything went fine.
- // By default QProcess returns "Unknown error" for errorString()
- if (error != QProcess::UnknownError)
- m_callerHandle->appendSignal(new ErrorSignal(error, errorString));
if (!stdOut.isEmpty() || !stdErr.isEmpty())
- m_callerHandle->appendSignal(new ReadyReadSignal(stdOut, stdErr));
- m_callerHandle->appendSignal(new FinishedSignal(packet.exitStatus, packet.exitCode));
+ m_callerHandle->appendSignal(new LauncherReadyReadSignal(stdOut, stdErr));
+ m_callerHandle->appendSignal(new LauncherDoneSignal(result));
flushCaller();
}
-void LauncherHandle::handleSocketReady()
-{
- QTC_ASSERT(isCalledFromLaunchersThread(), return);
- m_socketError = false;
- QMutexLocker locker(&m_mutex);
- if (m_callerHandle)
- m_callerHandle->startIfNeeded();
-}
-
void LauncherHandle::handleSocketError(const QString &message)
{
QTC_ASSERT(isCalledFromLaunchersThread(), return);
m_socketError = true; // TODO: ???
QMutexLocker locker(&m_mutex);
- wakeUpIfWaitingFor(CallerHandle::SignalType::Error);
if (!m_callerHandle)
return;
+ // TODO: FailedToStart may be wrong in case process has already started
const QString errorString = QCoreApplication::translate("Utils::QtcProcess",
"Internal socket error: %1").arg(message);
- m_callerHandle->appendSignal(new ErrorSignal(QProcess::FailedToStart, errorString));
+ const ProcessResultData result = { 0, QProcess::NormalExit, QProcess::FailedToStart,
+ errorString };
+ m_callerHandle->appendSignal(new LauncherDoneSignal(result));
flushCaller();
}
@@ -778,9 +520,6 @@ LauncherSocket::~LauncherSocket()
void LauncherSocket::sendData(const QByteArray &data)
{
- if (!isReady())
- return;
-
auto storeRequest = [this](const QByteArray &data)
{
QMutexLocker locker(&m_mutex);
@@ -792,23 +531,21 @@ void LauncherSocket::sendData(const QByteArray &data)
QMetaObject::invokeMethod(this, &LauncherSocket::handleRequests);
}
-CallerHandle *LauncherSocket::registerHandle(QObject *parent, quintptr token, ProcessMode mode)
+CallerHandle *LauncherSocket::registerHandle(QObject *parent, quintptr token)
{
QTC_ASSERT(!isCalledFromLaunchersThread(), return nullptr);
QMutexLocker locker(&m_mutex);
if (m_handles.contains(token))
return nullptr; // TODO: issue a warning
- CallerHandle *callerHandle = new CallerHandle(parent, token, mode);
- LauncherHandle *launcherHandle = new LauncherHandle(token, mode);
+ CallerHandle *callerHandle = new CallerHandle(parent, token);
+ LauncherHandle *launcherHandle = new LauncherHandle(token);
callerHandle->setLauncherHandle(launcherHandle);
launcherHandle->setCallerHandle(callerHandle);
launcherHandle->moveToThread(thread());
// Call it after moving LauncherHandle to the launcher's thread.
// Since this method is invoked from caller's thread, CallerHandle will live in caller's thread.
m_handles.insert(token, launcherHandle);
- connect(this, &LauncherSocket::ready,
- launcherHandle, &LauncherHandle::handleSocketReady);
connect(this, &LauncherSocket::errorOccurred,
launcherHandle, &LauncherHandle::handleSocketError);
@@ -845,18 +582,13 @@ void LauncherSocket::setSocket(QLocalSocket *socket)
QTC_ASSERT(!m_socket, return);
m_socket.store(socket);
m_packetParser.setDevice(m_socket);
- connect(m_socket,
-#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
- static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error),
-#else
- &QLocalSocket::errorOccurred,
-#endif
+ connect(m_socket, &QLocalSocket::errorOccurred,
this, &LauncherSocket::handleSocketError);
connect(m_socket, &QLocalSocket::readyRead,
this, &LauncherSocket::handleSocketDataAvailable);
connect(m_socket, &QLocalSocket::disconnected,
this, &LauncherSocket::handleSocketDisconnected);
- emit ready();
+ handleRequests();
}
void LauncherSocket::shutdown()
@@ -894,11 +626,10 @@ void LauncherSocket::handleSocketDataAvailable()
LauncherHandle *handle = handleForToken(m_packetParser.token());
if (handle) {
switch (m_packetParser.type()) {
- case LauncherPacketType::ProcessError:
case LauncherPacketType::ProcessStarted:
case LauncherPacketType::ReadyReadStandardOutput:
case LauncherPacketType::ReadyReadStandardError:
- case LauncherPacketType::ProcessFinished:
+ case LauncherPacketType::ProcessDone:
handle->handlePacket(m_packetParser.type(), m_packetParser.packetData());
break;
default:
@@ -934,11 +665,18 @@ void LauncherSocket::handleRequests()
{
QTC_ASSERT(isCalledFromLaunchersThread(), return);
const auto socket = m_socket.load();
- QTC_ASSERT(socket, return);
- QMutexLocker locker(&m_mutex);
- for (const QByteArray &request : qAsConst(m_requests))
+ if (!socket)
+ return;
+
+ std::vector<QByteArray> requests;
+ {
+ QMutexLocker locker(&m_mutex);
+ requests = m_requests;
+ m_requests.clear();
+ }
+
+ for (const QByteArray &request : qAsConst(requests))
socket->write(request);
- m_requests.clear();
}
bool LauncherSocket::isCalledFromLaunchersThread() const
diff --git a/src/libs/utils/launchersocket.h b/src/libs/utils/launchersocket.h
index 42b5fa757e8..4956bf652bf 100644
--- a/src/libs/utils/launchersocket.h
+++ b/src/libs/utils/launchersocket.h
@@ -26,7 +26,7 @@
#pragma once
#include "launcherpackets.h"
-#include "processutils.h"
+#include "processinterface.h"
#include <QDeadlineTimer>
#include <QHash>
@@ -49,10 +49,9 @@ namespace Internal {
class LauncherInterfacePrivate;
class LauncherHandle;
class LauncherSignal;
-class ErrorSignal;
-class StartedSignal;
-class ReadyReadSignal;
-class FinishedSignal;
+class LauncherStartedSignal;
+class LauncherReadyReadSignal;
+class LauncherDoneSignal;
// All the methods and data fields in this class are called / accessed from the caller's thread.
// Exceptions are explicitly marked.
@@ -62,78 +61,53 @@ class CallerHandle : public QObject
public:
enum class SignalType {
NoSignal,
- Error,
Started,
ReadyRead,
- Finished
+ Done
};
Q_ENUM(SignalType)
- CallerHandle(QObject *parent, quintptr token, ProcessMode mode)
- : QObject(parent), m_token(token), m_processMode(mode) {}
+ CallerHandle(QObject *parent, quintptr token)
+ : QObject(parent), m_token(token) {}
~CallerHandle() override;
LauncherHandle *launcherHandle() const { return m_launcherHandle; }
void setLauncherHandle(LauncherHandle *handle) { QMutexLocker locker(&m_mutex); m_launcherHandle = handle; }
- bool waitForStarted(int msecs);
- bool waitForReadyRead(int msces);
- bool waitForFinished(int msecs);
+ bool waitForSignal(CallerHandle::SignalType signalType, int msecs);
// Returns the list of flushed signals.
- QList<SignalType> flush();
- QList<SignalType> flushFor(SignalType signalType);
- bool shouldFlushFor(SignalType signalType) const;
+ void flush();
+ bool flushFor(SignalType signalType);
+ bool shouldFlush() const;
// Called from launcher's thread exclusively.
void appendSignal(LauncherSignal *launcherSignal);
// Called from caller's or launcher's thread.
QProcess::ProcessState state() const;
- void cancel();
-
- QByteArray readAllStandardOutput();
- QByteArray readAllStandardError();
+ void sendStopPacket(StopProcessPacket::SignalType signalType);
+ void terminate();
+ void kill();
+ void close();
qint64 processId() const;
- int exitCode() const;
- QString errorString() const;
- void setErrorString(const QString &str);
- void start(const QString &program, const QStringList &arguments, const QByteArray &writeData);
- // Called from caller's or launcher's thread.
- void startIfNeeded();
+ void start(const QString &program, const QStringList &arguments);
qint64 write(const QByteArray &data);
- QProcess::ProcessError error() const;
// Called from caller's or launcher's thread.
QString program() const;
// Called from caller's or launcher's thread.
QStringList arguments() const;
- void setStandardInputFile(const QString &fileName);
- void setProcessChannelMode(QProcess::ProcessChannelMode mode);
- void setProcessEnvironment(const QProcessEnvironment &environment);
- void setWorkingDirectory(const QString &dir);
- QProcess::ExitStatus exitStatus() const;
-
- void setBelowNormalPriority();
- void setNativeArguments(const QString &arguments);
- void setLowPriority();
- void setUnixTerminalDisabled();
+ void setProcessSetupData(ProcessSetupData *setup);
signals:
- void errorOccurred(QProcess::ProcessError error);
- void started();
- void finished(int exitCode, QProcess::ExitStatus status);
- void readyReadStandardOutput();
- void readyReadStandardError();
+ void started(qint64 processId, qint64 applicationMainThreadId = 0);
+ void readyRead(const QByteArray &outputData, const QByteArray &errorData);
+ void done(const Utils::ProcessResultData &resultData);
private:
- bool waitForSignal(int msecs, CallerHandle::SignalType newSignal);
- bool canWaitFor(SignalType newSignal) const; // TODO: employ me before calling waitForSignal()
-
- // Called from caller's or launcher's thread. Call me with mutex locked.
- void doStart();
- // Called from caller's or launcher's thread.
+ // Called from caller's thread exclusively.
void sendPacket(const Internal::LauncherPacket &packet);
// Called from caller's or launcher's thread.
bool isCalledFromCallersThread() const;
@@ -147,10 +121,9 @@ private:
return tmp;
}
- void handleError(const ErrorSignal *launcherSignal);
- void handleStarted(const StartedSignal *launcherSignal);
- void handleReadyRead(const ReadyReadSignal *launcherSignal);
- void handleFinished(const FinishedSignal *launcherSignal);
+ void handleStarted(const LauncherStartedSignal *launcherSignal);
+ void handleReadyRead(const LauncherReadyReadSignal *launcherSignal);
+ void handleDone(const LauncherDoneSignal *launcherSignal);
// Lives in launcher's thread. Modified from caller's thread.
LauncherHandle *m_launcherHandle = nullptr;
@@ -160,31 +133,14 @@ private:
QList<LauncherSignal *> m_signals;
const quintptr m_token;
- const ProcessMode m_processMode;
// Modified from caller's thread, read from launcher's thread
std::atomic<QProcess::ProcessState> m_processState = QProcess::NotRunning;
- std::unique_ptr<StartProcessPacket> m_startPacket;
int m_processId = 0;
- int m_exitCode = 0;
- QProcess::ExitStatus m_exitStatus = QProcess::ExitStatus::NormalExit;
- QByteArray m_stdout;
- QByteArray m_stderr;
- QString m_errorString;
- QProcess::ProcessError m_error = QProcess::UnknownError;
QString m_command;
QStringList m_arguments;
- QProcessEnvironment m_environment;
- QString m_workingDirectory;
- QByteArray m_writeData;
- QProcess::ProcessChannelMode m_channelMode = QProcess::SeparateChannels;
- QString m_standardInputFile;
-
- bool m_belowNormalPriority = false;
- QString m_nativeArguments;
- bool m_lowPriority = false;
- bool m_unixTerminalDisabled = false;
+ ProcessSetupData *m_setup = nullptr;
};
// Moved to the launcher thread, returned to caller's thread.
@@ -196,16 +152,13 @@ class LauncherHandle : public QObject
Q_OBJECT
public:
// Called from caller's thread, moved to launcher's thread afterwards.
- LauncherHandle(quintptr token, ProcessMode) : m_token(token) {}
+ LauncherHandle(quintptr token) : m_token(token) {}
// Called from caller's thread exclusively.
- bool waitForSignal(int msecs, CallerHandle::SignalType newSignal);
+ bool waitForSignal(CallerHandle::SignalType newSignal, int msecs);
CallerHandle *callerHandle() const { return m_callerHandle; }
void setCallerHandle(CallerHandle *handle) { QMutexLocker locker(&m_mutex); m_callerHandle = handle; }
- // Called from caller's thread exclusively.
- void setCanceled() { m_awaitingShouldContinue = false; }
// Called from launcher's thread exclusively.
- void handleSocketReady();
void handleSocketError(const QString &message);
void handlePacket(LauncherPacketType type, const QByteArray &payload);
@@ -214,18 +167,14 @@ public:
private:
// Called from caller's thread exclusively.
- bool doWaitForSignal(QDeadlineTimer deadline, CallerHandle::SignalType newSignal);
- // Called from launcher's thread exclusively. Call me with mutex locked.
- void wakeUpIfWaitingFor(CallerHandle::SignalType newSignal);
-
+ bool doWaitForSignal(QDeadlineTimer deadline);
// Called from launcher's thread exclusively. Call me with mutex locked.
void flushCaller();
// Called from launcher's thread exclusively.
- void handleErrorPacket(const QByteArray &packetData);
void handleStartedPacket(const QByteArray &packetData);
void handleReadyReadStandardOutput(const QByteArray &packetData);
void handleReadyReadStandardError(const QByteArray &packetData);
- void handleFinishedPacket(const QByteArray &packetData);
+ void handleDonePacket(const QByteArray &packetData);
// Called from caller's or launcher's thread.
bool isCalledFromLaunchersThread() const;
@@ -234,14 +183,10 @@ private:
// Lives in caller's thread. Modified only in caller's thread. TODO: check usages - all should be with mutex
CallerHandle *m_callerHandle = nullptr;
- // Modified only in caller's thread.
- bool m_awaitingShouldContinue = false;
mutable QMutex m_mutex;
QWaitCondition m_waitCondition;
const quintptr m_token;
std::atomic_bool m_socketError = false;
- // Modified only in caller's thread.
- CallerHandle::SignalType m_waitingFor = CallerHandle::SignalType::NoSignal;
};
class LauncherSocket : public QObject
@@ -249,16 +194,12 @@ class LauncherSocket : public QObject
Q_OBJECT
friend class LauncherInterfacePrivate;
public:
- // Called from caller's or launcher's thread.
- bool isReady() const { return m_socket.load(); }
- void sendData(const QByteArray &data);
-
// Called from caller's thread exclusively.
- CallerHandle *registerHandle(QObject *parent, quintptr token, ProcessMode mode);
+ void sendData(const QByteArray &data);
+ CallerHandle *registerHandle(QObject *parent, quintptr token);
void unregisterHandle(quintptr token);
signals:
- void ready();
void errorOccurred(const QString &error);
private:
diff --git a/src/libs/utils/layoutbuilder.cpp b/src/libs/utils/layoutbuilder.cpp
index 9a2c067cb29..70375e8018a 100644
--- a/src/libs/utils/layoutbuilder.cpp
+++ b/src/libs/utils/layoutbuilder.cpp
@@ -25,9 +25,9 @@
#include "layoutbuilder.h"
-#include <utils/algorithm.h>
-#include <utils/aspects.h>
-#include <utils/qtcassert.h>
+#include "algorithm.h"
+#include "aspects.h"
+#include "qtcassert.h"
#include <QFormLayout>
#include <QGridLayout>
diff --git a/src/libs/utils/link.h b/src/libs/utils/link.h
index 6d9fbb8ac1e..3b126318e23 100644
--- a/src/libs/utils/link.h
+++ b/src/libs/utils/link.h
@@ -25,21 +25,21 @@
#pragma once
-#include "fileutils.h"
-#include "porting.h"
+#include "utils_global.h"
+#include "filepath.h"
+
+#include <QMetaType>
#include <QString>
-#include <qmetatype.h>
#include <functional>
-
namespace Utils {
class QTCREATOR_UTILS_EXPORT Link
{
public:
- Link(const Utils::FilePath &filePath = Utils::FilePath(), int line = 0, int column = 0)
+ Link(const FilePath &filePath = FilePath(), int line = 0, int column = 0)
: targetFilePath(filePath)
, targetLine(line)
, targetColumn(column)
@@ -71,14 +71,15 @@ public:
int linkTextStart = -1;
int linkTextEnd = -1;
- Utils::FilePath targetFilePath;
+ FilePath targetFilePath;
int targetLine;
int targetColumn;
};
QTCREATOR_UTILS_EXPORT QHashValueType qHash(const Link &l);
-using ProcessLinkCallback = std::function<void(const Link &)>;
+using LinkHandler = std::function<void(const Link &)>;
+using Links = QList<Link>;
} // namespace Utils
diff --git a/src/libs/utils/listmodel.h b/src/libs/utils/listmodel.h
index e260b675b62..8eb742e0f12 100644
--- a/src/libs/utils/listmodel.h
+++ b/src/libs/utils/listmodel.h
@@ -25,7 +25,6 @@
#pragma once
-#include "utils_global.h"
#include "treemodel.h"
namespace Utils {
diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp
index 5cf279660ed..d2340a71b08 100644
--- a/src/libs/utils/macroexpander.cpp
+++ b/src/libs/utils/macroexpander.cpp
@@ -26,13 +26,10 @@
#include "macroexpander.h"
#include "algorithm.h"
-#include "fileutils.h"
#include "commandline.h"
#include "qtcassert.h"
#include "stringutils.h"
-#include <QCoreApplication>
-#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QLoggingCategory>
diff --git a/src/libs/utils/macroexpander.h b/src/libs/utils/macroexpander.h
index de24e44c1f2..19e2c02fd0d 100644
--- a/src/libs/utils/macroexpander.h
+++ b/src/libs/utils/macroexpander.h
@@ -27,11 +27,11 @@
#include "utils_global.h"
-#include <functional>
-
+#include <QCoreApplication>
#include <QList>
#include <QVector>
-#include <QCoreApplication>
+
+#include <functional>
namespace Utils {
diff --git a/src/libs/utils/mapreduce.h b/src/libs/utils/mapreduce.h
index 963694a1318..0705229444c 100644
--- a/src/libs/utils/mapreduce.h
+++ b/src/libs/utils/mapreduce.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include "algorithm.h"
#include "runextensions.h"
diff --git a/src/libs/utils/mimetypes/mimedatabase.cpp b/src/libs/utils/mimetypes/mimedatabase.cpp
index 35e0257e5e7..7bf0a4c8fc3 100644
--- a/src/libs/utils/mimetypes/mimedatabase.cpp
+++ b/src/libs/utils/mimetypes/mimedatabase.cpp
@@ -61,12 +61,6 @@
#include <algorithm>
#include <functional>
-#ifdef Q_OS_WIN
-static struct {const char *source; const char *comment; } ALL_FILES_FILTER = QT_TRANSLATE_NOOP3("Core", "All Files (*.*)", "On Windows");
-#else
-static struct {const char *source; const char *comment; } ALL_FILES_FILTER = QT_TRANSLATE_NOOP3("Core", "All Files (*)", "On Linux/macOS");
-#endif
-
using namespace Utils;
using namespace Utils::Internal;
@@ -334,66 +328,6 @@ MimeDatabase::~MimeDatabase()
d = nullptr;
}
-void Utils::addMimeTypes(const QString &fileName, const QByteArray &data)
-{
- auto d = MimeDatabasePrivate::instance();
- QMutexLocker locker(&d->mutex);
-
- if (d->m_startupPhase >= MimeDatabase::PluginsDelayedInitializing)
- qWarning("Adding items from %s to MimeDatabase after initialization time",
- qPrintable(fileName));
-
- auto xmlProvider = static_cast<MimeXMLProvider *>(d->provider());
- xmlProvider->addData(fileName, data);
-}
-
-QString Utils::allFiltersString(QString *allFilesFilter)
-{
- MimeDatabase mdb;
- QSet<QString> uniqueFilters;
- const QList<MimeType> allMimeTypes = mdb.allMimeTypes();
- for (const MimeType &mt : allMimeTypes) {
- const QString &filterString = mt.filterString();
- if (!filterString.isEmpty())
- uniqueFilters.insert(mt.filterString());
- }
- QStringList filters;
- for (const QString &filter : uniqueFilters)
- filters.append(filter);
- filters.sort();
- const QString allFiles = allFilesFilterString();
- if (allFilesFilter)
- *allFilesFilter = allFiles;
-
- // Prepend all files filter
- filters.prepend(allFiles);
-
- return filters.join(QLatin1String(";;"));
-}
-
-QString Utils::allFilesFilterString()
-{
- auto d = MimeDatabasePrivate::instance();
- if (d->m_startupPhase <= MimeDatabase::PluginsInitializing)
- qWarning("Accessing MimeDatabase files filter strings before plugins are initialized");
-
- return QCoreApplication::translate("Core", ALL_FILES_FILTER.source, ALL_FILES_FILTER.comment);
-}
-
-QStringList Utils::allGlobPatterns()
-{
- auto d = MimeDatabasePrivate::instance();
- if (d->m_startupPhase <= MimeDatabase::PluginsInitializing)
- qWarning("Accessing MimeDatabase glob patterns before plugins are initialized");
-
- MimeDatabase mdb;
- QStringList patterns;
- const QList<MimeType> allMimeTypes = mdb.allMimeTypes();
- for (const MimeType &mt : allMimeTypes)
- patterns.append(mt.globPatterns());
- return patterns;
-}
-
/*!
\fn MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const;
Returns a MIME type for \a nameOrAlias or an invalid one if none found.
@@ -686,77 +620,3 @@ QList<MimeType> MimeDatabase::allMimeTypes() const
\value MatchContent The file content is used to look for a match
*/
-
-QMap<int, QList<MimeMagicRule> > Utils::magicRulesForMimeType(const MimeType &mimeType)
-{
- auto d = MimeDatabasePrivate::instance();
- QMutexLocker locker(&d->mutex);
- return d->provider()->magicRulesForMimeType(mimeType);
-}
-
-void Utils::setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns)
-{
- auto d = MimeDatabasePrivate::instance();
- QMutexLocker locker(&d->mutex);
- d->provider()->setGlobPatternsForMimeType(mimeType, patterns);
-}
-
-void Utils::setMagicRulesForMimeType(const MimeType &mimeType, const QMap<int, QList<MimeMagicRule> > &rules)
-{
- auto d = MimeDatabasePrivate::instance();
- QMutexLocker locker(&d->mutex);
- d->provider()->setMagicRulesForMimeType(mimeType, rules);
-}
-
-void Utils::setMimeStartupPhase(MimeStartupPhase phase)
-{
- auto d = MimeDatabasePrivate::instance();
- QMutexLocker locker(&d->mutex);
- if (int(phase) != d->m_startupPhase + 1)
- qWarning("Unexpected jump in MimedDatabase lifetime from %d to %d", d->m_startupPhase, int(phase));
- d->m_startupPhase = int(phase);
-}
-
-MimeType Utils::mimeTypeForName(const QString &nameOrAlias)
-{
- MimeDatabase mdb;
- return mdb.mimeTypeForName(nameOrAlias);
-}
-
-MimeType Utils::mimeTypeForFile(const QString &fileName, MimeMatchMode mode)
-{
- MimeDatabase mdb;
- return mdb.mimeTypeForFile(fileName, MimeDatabase::MatchMode(mode));
-}
-
-MimeType Utils::mimeTypeForFile(const QFileInfo &fileInfo, MimeMatchMode mode)
-{
- MimeDatabase mdb;
- return mdb.mimeTypeForFile(fileInfo, MimeDatabase::MatchMode(mode));
-}
-
-MimeType Utils::mimeTypeForFile(const FilePath &filePath, MimeMatchMode mode)
-{
- MimeDatabase mdb;
- if (filePath.needsDevice())
- return mdb.mimeTypeForUrl(filePath.toUrl());
- return mdb.mimeTypeForFile(filePath.toString(), MimeDatabase::MatchMode(mode));
-}
-
-QList<MimeType> Utils::mimeTypesForFileName(const QString &fileName)
-{
- MimeDatabase mdb;
- return mdb.mimeTypesForFileName(fileName);
-}
-
-MimeType Utils::mimeTypeForData(const QByteArray &data)
-{
- MimeDatabase mdb;
- return mdb.mimeTypeForData(data);
-}
-
-QList<MimeType> Utils::allMimeTypes()
-{
- MimeDatabase mdb;
- return mdb.allMimeTypes();
-}
diff --git a/src/libs/utils/mimetypes/mimedatabase.h b/src/libs/utils/mimetypes/mimedatabase.h
index 9e217245421..4808d96a478 100644
--- a/src/libs/utils/mimetypes/mimedatabase.h
+++ b/src/libs/utils/mimetypes/mimedatabase.h
@@ -40,52 +40,54 @@
#pragma once
#include "mimetype.h"
-#include "mimemagicrule_p.h"
-
-#include <utils/utils_global.h>
QT_BEGIN_NAMESPACE
class QFileInfo;
+class QIODevice;
+class QUrl;
QT_END_NAMESPACE
namespace Utils {
-class FilePath;
+class MimeDatabase
+{
+ Q_DISABLE_COPY(MimeDatabase)
-// Wrapped QMimeDataBase functions
-QTCREATOR_UTILS_EXPORT MimeType mimeTypeForName(const QString &nameOrAlias);
+public:
+ MimeDatabase();
+ ~MimeDatabase();
-enum class MimeMatchMode {
- MatchDefault = 0x0,
- MatchExtension = 0x1,
- MatchContent = 0x2
-};
+ MimeType mimeTypeForName(const QString &nameOrAlias) const;
-QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const QString &fileName, MimeMatchMode mode = MimeMatchMode::MatchDefault);
-QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const QFileInfo &fileInfo, MimeMatchMode mode = MimeMatchMode::MatchDefault);
-QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const FilePath &filePath, MimeMatchMode mode = MimeMatchMode::MatchDefault);
-QTCREATOR_UTILS_EXPORT QList<MimeType> mimeTypesForFileName(const QString &fileName);
-QTCREATOR_UTILS_EXPORT MimeType mimeTypeForData(const QByteArray &data);
-QTCREATOR_UTILS_EXPORT QList<MimeType> allMimeTypes();
-
-// Qt Creator additions
-// For debugging purposes.
-enum class MimeStartupPhase {
- BeforeInitialize,
- PluginsLoading,
- PluginsInitializing, // Register up to here.
- PluginsDelayedInitializing, // Use from here on.
- UpAndRunning
-};
+ enum MatchMode { MatchDefault = 0x0, MatchExtension = 0x1, MatchContent = 0x2 };
+
+ MimeType mimeTypeForFile(const QString &fileName, MatchMode mode = MatchDefault) const;
+ MimeType mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode = MatchDefault) const;
+ QList<MimeType> mimeTypesForFileName(const QString &fileName) const;
+
+ MimeType mimeTypeForData(const QByteArray &data) const;
+ MimeType mimeTypeForData(QIODevice *device) const;
-QTCREATOR_UTILS_EXPORT void setMimeStartupPhase(MimeStartupPhase);
-QTCREATOR_UTILS_EXPORT void addMimeTypes(const QString &id, const QByteArray &data);
-QTCREATOR_UTILS_EXPORT QString allFiltersString(QString *allFilesFilter = nullptr);
-QTCREATOR_UTILS_EXPORT QString allFilesFilterString();
-QTCREATOR_UTILS_EXPORT QStringList allGlobPatterns();
-QTCREATOR_UTILS_EXPORT QMap<int, QList<Internal::MimeMagicRule> > magicRulesForMimeType(const MimeType &mimeType); // priority -> rules
-QTCREATOR_UTILS_EXPORT void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
-QTCREATOR_UTILS_EXPORT void setMagicRulesForMimeType(const MimeType &mimeType,
- const QMap<int, QList<Internal::MimeMagicRule> > &rules); // priority -> rules
+ MimeType mimeTypeForUrl(const QUrl &url) const;
+ MimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const;
+ MimeType mimeTypeForFileNameAndData(const QString &fileName, const QByteArray &data) const;
+
+ QString suffixForFileName(const QString &fileName) const;
+
+ QList<MimeType> allMimeTypes() const;
+
+ // For debugging purposes.
+ enum StartupPhase {
+ BeforeInitialize,
+ PluginsLoading,
+ PluginsInitializing, // Register up to here.
+ PluginsDelayedInitializing, // Use from here on.
+ UpAndRunning
+ };
+ static void setStartupPhase(StartupPhase);
+
+private:
+ Internal::MimeDatabasePrivate *d;
+};
} // Utils
diff --git a/src/libs/utils/mimetypes/mimedatabase_p.h b/src/libs/utils/mimetypes/mimedatabase_p.h
index 6f87b213f34..46211126005 100644
--- a/src/libs/utils/mimetypes/mimedatabase_p.h
+++ b/src/libs/utils/mimetypes/mimedatabase_p.h
@@ -62,9 +62,7 @@
#include <QtCore/qhash.h>
#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
-class QFileInfo;
class QIODevice;
-class QUrl;
QT_END_NAMESPACE
#include "mimetype.h"
@@ -108,50 +106,5 @@ public:
int m_startupPhase = 0;
};
-class MimeDatabase
-{
- Q_DISABLE_COPY(MimeDatabase)
-
-public:
- MimeDatabase();
- ~MimeDatabase();
-
- MimeType mimeTypeForName(const QString &nameOrAlias) const;
-
- enum MatchMode {
- MatchDefault = 0x0,
- MatchExtension = 0x1,
- MatchContent = 0x2
- };
-
- MimeType mimeTypeForFile(const QString &fileName, MatchMode mode = MatchDefault) const;
- MimeType mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode = MatchDefault) const;
- QList<MimeType> mimeTypesForFileName(const QString &fileName) const;
-
- MimeType mimeTypeForData(const QByteArray &data) const;
- MimeType mimeTypeForData(QIODevice *device) const;
-
- MimeType mimeTypeForUrl(const QUrl &url) const;
- MimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const;
- MimeType mimeTypeForFileNameAndData(const QString &fileName, const QByteArray &data) const;
-
- QString suffixForFileName(const QString &fileName) const;
-
- QList<MimeType> allMimeTypes() const;
-
- // For debugging purposes.
- enum StartupPhase {
- BeforeInitialize,
- PluginsLoading,
- PluginsInitializing, // Register up to here.
- PluginsDelayedInitializing, // Use from here on.
- UpAndRunning
- };
- static void setStartupPhase(StartupPhase);
-
-private:
- Internal::MimeDatabasePrivate *d;
-};
-
} // Internal
} // Utils
diff --git a/src/libs/utils/mimetypes/mimemagicrule_p.h b/src/libs/utils/mimetypes/mimemagicrule_p.h
index 1513750a298..14fdbf9b488 100644
--- a/src/libs/utils/mimetypes/mimemagicrule_p.h
+++ b/src/libs/utils/mimetypes/mimemagicrule_p.h
@@ -62,8 +62,8 @@ namespace Utils {
class MimeType;
namespace Internal {
-
class MimeMagicRulePrivate;
+}
class QTCREATOR_UTILS_EXPORT MimeMagicRule
{
@@ -97,12 +97,11 @@ public:
static bool matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength, int valueLength, const char *valueData, const char *mask);
private:
- const QScopedPointer<MimeMagicRulePrivate> d;
+ const QScopedPointer<Internal::MimeMagicRulePrivate> d;
};
-} // Internal
} // Utils
QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(Utils::Internal::MimeMagicRule, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Utils::MimeMagicRule, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
diff --git a/src/libs/utils/mimetypes/mimeutils.cpp b/src/libs/utils/mimetypes/mimeutils.cpp
new file mode 100644
index 00000000000..cd618daeea0
--- /dev/null
+++ b/src/libs/utils/mimetypes/mimeutils.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mimeutils.h"
+
+#include "mimedatabase.h"
+#include "mimedatabase_p.h"
+#include "mimemagicrule_p.h"
+#include "mimeprovider_p.h"
+
+#include "filepath.h"
+
+using namespace Utils;
+using namespace Utils::Internal;
+
+void Utils::addMimeTypes(const QString &fileName, const QByteArray &data)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+
+ if (d->m_startupPhase >= MimeDatabase::PluginsDelayedInitializing)
+ qWarning("Adding items from %s to MimeDatabase after initialization time",
+ qPrintable(fileName));
+
+ auto xmlProvider = static_cast<MimeXMLProvider *>(d->provider());
+ xmlProvider->addData(fileName, data);
+}
+
+QMap<int, QList<MimeMagicRule>> Utils::magicRulesForMimeType(const MimeType &mimeType)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+ return d->provider()->magicRulesForMimeType(mimeType);
+}
+
+void Utils::setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+ d->provider()->setGlobPatternsForMimeType(mimeType, patterns);
+}
+
+void Utils::setMagicRulesForMimeType(const MimeType &mimeType,
+ const QMap<int, QList<MimeMagicRule>> &rules)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+ d->provider()->setMagicRulesForMimeType(mimeType, rules);
+}
+
+void Utils::setMimeStartupPhase(MimeStartupPhase phase)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+ if (int(phase) != d->m_startupPhase + 1)
+ qWarning("Unexpected jump in MimedDatabase lifetime from %d to %d",
+ d->m_startupPhase,
+ int(phase));
+ d->m_startupPhase = int(phase);
+}
+
+MimeType Utils::mimeTypeForName(const QString &nameOrAlias)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypeForName(nameOrAlias);
+}
+
+MimeType Utils::mimeTypeForFile(const QString &fileName, MimeMatchMode mode)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypeForFile(fileName, MimeDatabase::MatchMode(mode));
+}
+
+MimeType Utils::mimeTypeForFile(const QFileInfo &fileInfo, MimeMatchMode mode)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypeForFile(fileInfo, MimeDatabase::MatchMode(mode));
+}
+
+MimeType Utils::mimeTypeForFile(const FilePath &filePath, MimeMatchMode mode)
+{
+ MimeDatabase mdb;
+ if (filePath.needsDevice())
+ return mdb.mimeTypeForUrl(filePath.toUrl());
+ return mdb.mimeTypeForFile(filePath.toString(), MimeDatabase::MatchMode(mode));
+}
+
+QList<MimeType> Utils::mimeTypesForFileName(const QString &fileName)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypesForFileName(fileName);
+}
+
+MimeType Utils::mimeTypeForData(const QByteArray &data)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypeForData(data);
+}
+
+QList<MimeType> Utils::allMimeTypes()
+{
+ MimeDatabase mdb;
+ return mdb.allMimeTypes();
+}
diff --git a/src/libs/utils/mimetypes2/mimedatabase.cpp b/src/libs/utils/mimetypes2/mimedatabase.cpp
new file mode 100644
index 00000000000..5a0ced57d96
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimedatabase.cpp
@@ -0,0 +1,960 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qplatformdefs.h> // always first
+
+#include "mimedatabase.h"
+#include "mimedatabase_p.h"
+
+#include "mimeprovider_p.h"
+#include "mimetype_p.h"
+#include "mimeutils.h"
+
+#include "algorithm.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QStandardPaths>
+#include <QtCore/QBuffer>
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+
+#include <algorithm>
+#include <functional>
+#include <stack>
+
+namespace Utils {
+
+Q_GLOBAL_STATIC(MimeDatabasePrivate, staticMimeDatabase)
+
+MimeDatabasePrivate *MimeDatabasePrivate::instance()
+{
+ return staticMimeDatabase();
+}
+
+MimeDatabasePrivate::MimeDatabasePrivate()
+ : m_defaultMimeType(QLatin1String("application/octet-stream"))
+{
+}
+
+MimeDatabasePrivate::~MimeDatabasePrivate()
+{
+}
+
+#if 0
+#if 0 //def QT_BUILD_INTERNAL
+Q_CORE_EXPORT
+#else
+static const
+#endif
+int mime_secondsBetweenChecks = 5;
+#endif
+
+bool MimeDatabasePrivate::shouldCheck()
+{
+#if 0
+ if (m_lastCheck.isValid() && m_lastCheck.elapsed() < mime_secondsBetweenChecks * 1000)
+ return false;
+ m_lastCheck.start();
+ return true;
+#endif
+ // Qt Creator forces reload manually
+ return m_forceLoad;
+}
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+# define QT_USE_MMAP
+#endif
+
+static void updateOverriddenMimeTypes(std::vector<std::unique_ptr<MimeProviderBase>> &providers)
+{
+ // If a provider earlier in the list already defines a mimetype, it should override the
+ // mimetype definition of following providers. Go through everything once here, telling each
+ // provider which mimetypes are overridden by earlier providers.
+ QList<MimeProviderBase *> handledProviders;
+ for (std::unique_ptr<MimeProviderBase> &provider : providers) {
+ provider->m_overriddenMimeTypes.clear();
+ const QStringList ownMimetypes = provider->allMimeTypeNames();
+ for (MimeProviderBase *other : handledProviders) {
+ const QStringList overridden = Utils::filtered(ownMimetypes,
+ [other](const QString &type) {
+ return other->hasMimeTypeForName(
+ type);
+ });
+ provider->m_overriddenMimeTypes.unite(QSet(overridden.cbegin(), overridden.cend()));
+ }
+ handledProviders.append(provider.get());
+ }
+}
+
+void MimeDatabasePrivate::loadProviders()
+{
+#if 0
+ // We use QStandardPaths every time to check if new files appeared
+ const QStringList mimeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);
+#else
+ // Qt Creator never uses the standard paths, they can conflict with our setup
+ const QStringList mimeDirs;
+#endif
+ const auto fdoIterator = std::find_if(mimeDirs.constBegin(), mimeDirs.constEnd(), [](const QString &mimeDir) -> bool {
+ return QFileInfo::exists(mimeDir + QStringLiteral("/packages/freedesktop.org.xml")); }
+ );
+ const bool needInternalDB = MimeXMLProvider::InternalDatabaseAvailable && fdoIterator == mimeDirs.constEnd();
+ //qDebug() << "mime dirs:" << mimeDirs;
+
+ Providers currentProviders;
+ std::swap(m_providers, currentProviders);
+
+ m_providers.reserve(m_additionalData.size() + mimeDirs.size() + (needInternalDB ? 1 : 0));
+
+ // added for Qt Creator: additional mime data
+ for (auto dataIt = m_additionalData.cbegin(); dataIt != m_additionalData.cend(); ++dataIt) {
+ // Check if we already have a provider for this data
+ const QString id = dataIt.key();
+ const auto it = std::find_if(currentProviders.begin(), currentProviders.end(),
+ [id](const std::unique_ptr<MimeProviderBase> &prov) {
+ return prov && prov->directory() == id;
+ });
+ std::unique_ptr<MimeProviderBase> provider;
+ if (it != currentProviders.end())
+ provider = std::move(*it); // take provider out of the vector
+ provider.reset(new MimeXMLProvider(this, id, dataIt.value()));
+ m_providers.push_back(std::move(provider));
+ }
+
+
+ for (const QString &mimeDir : mimeDirs) {
+ const QString cacheFile = mimeDir + QStringLiteral("/mime.cache");
+ // Check if we already have a provider for this dir
+ const auto predicate = [mimeDir](const std::unique_ptr<MimeProviderBase> &prov)
+ {
+ return prov && prov->directory() == mimeDir;
+ };
+ const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), predicate);
+ if (it == currentProviders.end()) {
+ std::unique_ptr<MimeProviderBase> provider;
+#if defined(QT_USE_MMAP)
+ if (qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE") && QFileInfo::exists(cacheFile)) {
+ provider.reset(new MimeBinaryProvider(this, mimeDir));
+ //qDebug() << "Created binary provider for" << mimeDir;
+ if (!provider->isValid()) {
+ provider.reset();
+ }
+ }
+#endif
+ if (!provider) {
+ provider.reset(new MimeXMLProvider(this, mimeDir));
+ //qDebug() << "Created XML provider for" << mimeDir;
+ }
+ m_providers.push_back(std::move(provider));
+ } else {
+ auto provider = std::move(*it); // take provider out of the vector
+ provider->ensureLoaded();
+ if (!provider->isValid()) {
+ provider.reset(new MimeXMLProvider(this, mimeDir));
+ //qDebug() << "Created XML provider to replace binary provider for" << mimeDir;
+ }
+ m_providers.push_back(std::move(provider));
+ }
+ }
+ // mimeDirs is sorted "most local first, most global last"
+ // so the internal XML DB goes at the end
+ if (needInternalDB) {
+ // Check if we already have a provider for the InternalDatabase
+ const auto isInternal = [](const std::unique_ptr<MimeProviderBase> &prov)
+ {
+ return prov && prov->isInternalDatabase();
+ };
+ const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), isInternal);
+ if (it == currentProviders.end()) {
+ m_providers.push_back(Providers::value_type(new MimeXMLProvider(this, MimeXMLProvider::InternalDatabase)));
+ } else {
+ m_providers.push_back(std::move(*it));
+ }
+ }
+
+ updateOverriddenMimeTypes(m_providers);
+}
+
+const MimeDatabasePrivate::Providers &MimeDatabasePrivate::providers()
+{
+#ifndef Q_OS_WASM // stub implementation always returns true
+ Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex
+#endif
+ if (m_providers.empty()) {
+ loadProviders();
+ // Qt Creator forces reload manually
+ // m_lastCheck.start();
+ } else {
+ if (shouldCheck())
+ loadProviders();
+ }
+ // Qt Creator forces reload manually
+ m_forceLoad = false;
+ return m_providers;
+}
+
+QString MimeDatabasePrivate::resolveAlias(const QString &nameOrAlias)
+{
+ for (const auto &provider : providers()) {
+ const QString ret = provider->resolveAlias(nameOrAlias);
+ if (!ret.isEmpty())
+ return ret;
+ }
+ return nameOrAlias;
+}
+
+/*!
+ \internal
+ Returns a MIME type or an invalid one if none found
+ */
+MimeType MimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)
+{
+ const QString mimeName = resolveAlias(nameOrAlias);
+ for (const auto &provider : providers()) {
+ const MimeType mime = provider->mimeTypeForName(mimeName);
+ if (mime.isValid())
+ return mime;
+ }
+ return {};
+}
+
+QStringList MimeDatabasePrivate::mimeTypeForFileName(const QString &fileName)
+{
+ if (fileName.endsWith(QLatin1Char('/')))
+ return QStringList() << QLatin1String("inode/directory");
+
+ const MimeGlobMatchResult result = findByFileName(fileName);
+ QStringList matchingMimeTypes = result.m_matchingMimeTypes;
+ matchingMimeTypes.sort(); // make it deterministic
+ return matchingMimeTypes;
+}
+
+MimeGlobMatchResult MimeDatabasePrivate::findByFileName(const QString &fileName)
+{
+ MimeGlobMatchResult result;
+ const QString fileNameExcludingPath = QFileInfo(fileName).fileName();
+ for (const auto &provider : providers())
+ provider->addFileNameMatches(fileNameExcludingPath, result);
+ return result;
+}
+
+void MimeDatabasePrivate::loadMimeTypePrivate(MimeTypePrivate &mimePrivate)
+{
+ QMutexLocker locker(&mutex);
+ if (mimePrivate.name.isEmpty())
+ return; // invalid mimetype
+ if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand
+ Q_ASSERT(mimePrivate.fromCache);
+ bool found = false;
+ for (const auto &provider : providers()) {
+ if (provider->loadMimeTypePrivate(mimePrivate)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ const QString file = mimePrivate.name + QLatin1String(".xml");
+ qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.\n"
+ "Either it was just removed, or the directory doesn't have executable permission..."
+ << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);
+ }
+ mimePrivate.loaded = true;
+ }
+}
+
+void MimeDatabasePrivate::loadGenericIcon(MimeTypePrivate &mimePrivate)
+{
+ QMutexLocker locker(&mutex);
+ if (mimePrivate.fromCache) {
+ mimePrivate.genericIconName.clear();
+ for (const auto &provider : providers()) {
+ provider->loadGenericIcon(mimePrivate);
+ if (!mimePrivate.genericIconName.isEmpty())
+ break;
+ }
+ }
+}
+
+void MimeDatabasePrivate::loadIcon(MimeTypePrivate &mimePrivate)
+{
+ QMutexLocker locker(&mutex);
+ if (mimePrivate.fromCache) {
+ mimePrivate.iconName.clear();
+ for (const auto &provider : providers()) {
+ provider->loadIcon(mimePrivate);
+ if (!mimePrivate.iconName.isEmpty())
+ break;
+ }
+ }
+}
+
+static QString fallbackParent(const QString &mimeTypeName)
+{
+ const QStringView myGroup = QStringView{mimeTypeName}.left(mimeTypeName.indexOf(QLatin1Char('/')));
+ // All text/* types are subclasses of text/plain.
+ if (myGroup == QLatin1String("text") && mimeTypeName != QLatin1String("text/plain"))
+ return QLatin1String("text/plain");
+ // All real-file mimetypes implicitly derive from application/octet-stream
+ if (myGroup != QLatin1String("inode") &&
+ // ignore non-file extensions
+ myGroup != QLatin1String("all") && myGroup != QLatin1String("fonts") && myGroup != QLatin1String("print") && myGroup != QLatin1String("uri")
+ && mimeTypeName != QLatin1String("application/octet-stream")) {
+ return QLatin1String("application/octet-stream");
+ }
+ return QString();
+}
+
+QStringList MimeDatabasePrivate::mimeParents(const QString &mimeName)
+{
+ QMutexLocker locker(&mutex);
+ return parents(mimeName);
+}
+
+QStringList MimeDatabasePrivate::parents(const QString &mimeName)
+{
+ Q_ASSERT(!mutex.tryLock());
+ QStringList result;
+ for (const auto &provider : providers()) {
+ if (provider->hasMimeTypeForName(mimeName)) {
+ provider->addParents(mimeName, result);
+ break;
+ }
+ }
+ if (result.isEmpty()) {
+ const QString parent = fallbackParent(mimeName);
+ if (!parent.isEmpty())
+ result.append(parent);
+ }
+ return result;
+}
+
+QStringList MimeDatabasePrivate::listAliases(const QString &mimeName)
+{
+ QMutexLocker locker(&mutex);
+ QStringList result;
+ for (const auto &provider : providers()) {
+ if (provider->hasMimeTypeForName(mimeName)) {
+ provider->addAliases(mimeName, result);
+ return result;
+ }
+ }
+ return result;
+}
+
+bool MimeDatabasePrivate::mimeInherits(const QString &mime, const QString &parent)
+{
+ QMutexLocker locker(&mutex);
+ return inherits(mime, parent);
+}
+
+static inline bool isTextFile(const QByteArray &data)
+{
+ // UTF16 byte order marks
+ static const char bigEndianBOM[] = "\xFE\xFF";
+ static const char littleEndianBOM[] = "\xFF\xFE";
+ if (data.startsWith(bigEndianBOM) || data.startsWith(littleEndianBOM))
+ return true;
+
+ // Check the first 128 bytes (see shared-mime spec)
+ const char *p = data.constData();
+ const char *e = p + qMin(128, data.size());
+ for ( ; p < e; ++p) {
+ if (static_cast<unsigned char>(*p) < 32 && *p != 9 && *p !=10 && *p != 13)
+ return false;
+ }
+
+ return true;
+}
+
+MimeType MimeDatabasePrivate::findByData(const QByteArray &data, int *accuracyPtr)
+{
+#if 0
+ if (data.isEmpty()) {
+ *accuracyPtr = 100;
+ return mimeTypeForName(QLatin1String("application/x-zerosize"));
+ }
+#endif
+
+ *accuracyPtr = 0;
+ MimeType candidate;
+ for (const auto &provider : providers())
+ provider->findByMagic(data, accuracyPtr, candidate);
+
+ if (candidate.isValid())
+ return candidate;
+
+ if (isTextFile(data)) {
+ *accuracyPtr = 5;
+ return mimeTypeForName(QLatin1String("text/plain"));
+ }
+
+ return mimeTypeForName(defaultMimeType());
+}
+
+MimeType MimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *accuracyPtr)
+{
+ // First, glob patterns are evaluated. If there is a match with max weight,
+ // this one is selected and we are done. Otherwise, the file contents are
+ // evaluated and the match with the highest value (either a magic priority or
+ // a glob pattern weight) is selected. Matching starts from max level (most
+ // specific) in both cases, even when there is already a suffix matching candidate.
+ *accuracyPtr = 0;
+
+ // Pass 1) Try to match on the file name
+ MimeGlobMatchResult candidatesByName = findByFileName(fileName);
+ if (candidatesByName.m_allMatchingMimeTypes.count() == 1) {
+ *accuracyPtr = 100;
+ const MimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
+ if (mime.isValid())
+ return mime;
+ candidatesByName = {};
+ }
+
+ // Extension is unknown, or matches multiple mimetypes.
+ // Pass 2) Match on content, if we can read the data
+ const auto matchOnContent = [this, accuracyPtr, &candidatesByName](QIODevice *device) {
+ if (device->isOpen()) {
+ // Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
+ // This is much faster than seeking back and forth into QIODevice.
+ const QByteArray data = device->peek(16384);
+
+ int magicAccuracy = 0;
+ MimeType candidateByData(findByData(data, &magicAccuracy));
+
+ // Disambiguate conflicting extensions (if magic matching found something)
+ if (candidateByData.isValid() && magicAccuracy > 0) {
+ const QString sniffedMime = candidateByData.name();
+ // If the sniffedMime matches a highest-weight glob match, use it
+ if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) {
+ *accuracyPtr = 100;
+ return candidateByData;
+ }
+ for (const QString &m : qAsConst(candidatesByName.m_allMatchingMimeTypes)) {
+ if (inherits(m, sniffedMime)) {
+ // We have magic + pattern pointing to this, so it's a pretty good match
+ *accuracyPtr = 100;
+ return mimeTypeForName(m);
+ }
+ }
+ if (candidatesByName.m_allMatchingMimeTypes.isEmpty()) {
+ // No glob, use magic
+ *accuracyPtr = magicAccuracy;
+ return candidateByData;
+ }
+ }
+ }
+
+ if (candidatesByName.m_allMatchingMimeTypes.count() > 1) {
+ candidatesByName.m_matchingMimeTypes.sort(); // make it deterministic
+ *accuracyPtr = 20;
+ const MimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
+ if (mime.isValid())
+ return mime;
+ }
+
+ return mimeTypeForName(defaultMimeType());
+ };
+
+ if (device)
+ return matchOnContent(device);
+
+ QFile fallbackFile(fileName);
+ fallbackFile.open(QIODevice::ReadOnly); // error handling: matchOnContent() will check isOpen()
+ return matchOnContent(&fallbackFile);
+}
+
+QList<MimeType> MimeDatabasePrivate::allMimeTypes()
+{
+ QList<MimeType> result;
+ for (const auto &provider : providers())
+ provider->addAllMimeTypes(result);
+ return result;
+}
+
+bool MimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
+{
+ const QString resolvedParent = resolveAlias(parent);
+ std::stack<QString, QStringList> toCheck;
+ toCheck.push(mime);
+ while (!toCheck.empty()) {
+ if (toCheck.top() == resolvedParent)
+ return true;
+ const QString mimeName = toCheck.top();
+ toCheck.pop();
+ const auto parentList = parents(mimeName);
+ for (const QString &par : parentList)
+ toCheck.push(resolveAlias(par));
+ }
+ return false;
+}
+
+/*!
+ \class MimeDatabase
+ \inmodule QtCore
+ \brief The MimeDatabase class maintains a database of MIME types.
+
+ \since 5.0
+
+ The MIME type database is provided by the freedesktop.org shared-mime-info
+ project. If the MIME type database cannot be found on the system, as is the case
+ on most Windows, \macos, and iOS systems, Qt will use its own copy of it.
+
+ Applications which want to define custom MIME types need to install an
+ XML file into the locations searched for MIME definitions.
+ These locations can be queried with
+ \snippet code/src_corelib_mimetype_mimedatabase.cpp 1
+ On a typical Unix system, this will be /usr/share/mime/packages/, but it is also
+ possible to extend the list of directories by setting the environment variable
+ \c XDG_DATA_DIRS. For instance adding /opt/myapp/share to \c XDG_DATA_DIRS will result
+ in /opt/myapp/share/mime/packages/ being searched for MIME definitions.
+
+ Here is an example of MIME XML:
+ \snippet code/src_corelib_mimetype_mimedatabase.cpp 2
+
+ For more details about the syntax of XML MIME definitions, including defining
+ "magic" in order to detect MIME types based on data as well, read the
+ Shared Mime Info specification at
+ http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
+
+ On Unix systems, a binary cache is used for more performance. This cache is generated
+ by the command "update-mime-database path", where path would be /opt/myapp/share/mime
+ in the above example. Make sure to run this command when installing the MIME type
+ definition file.
+
+ \threadsafe
+
+ \snippet code/src_corelib_mimetype_mimedatabase.cpp 0
+
+ \sa MimeType, {MIME Type Browser Example}
+ */
+
+/*!
+ \fn MimeDatabase::MimeDatabase();
+ Constructs a MimeDatabase object.
+
+ It is perfectly OK to create an instance of MimeDatabase every time you need to
+ perform a lookup.
+ The parsing of mimetypes is done on demand (when shared-mime-info is installed)
+ or when the very first instance is constructed (when parsing XML files directly).
+ */
+MimeDatabase::MimeDatabase() :
+ d(staticMimeDatabase())
+{
+}
+
+/*!
+ \fn MimeDatabase::~MimeDatabase();
+ Destroys the MimeDatabase object.
+ */
+MimeDatabase::~MimeDatabase()
+{
+ d = nullptr;
+}
+
+/*!
+ \fn MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const;
+ Returns a MIME type for \a nameOrAlias or an invalid one if none found.
+ */
+MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const
+{
+ QMutexLocker locker(&d->mutex);
+
+ if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
+ qWarning("Accessing MimeDatabase for %s before plugins are initialized",
+ qPrintable(nameOrAlias));
+
+ return d->mimeTypeForName(nameOrAlias);
+}
+
+/*!
+ Returns a MIME type for \a fileInfo.
+
+ A valid MIME type is always returned.
+
+ The default matching algorithm looks at both the file name and the file
+ contents, if necessary. The file extension has priority over the contents,
+ but the contents will be used if the file extension is unknown, or
+ matches multiple MIME types.
+ If \a fileInfo is a Unix symbolic link, the file that it refers to
+ will be used instead.
+ If the file doesn't match any known pattern or data, the default MIME type
+ (application/octet-stream) is returned.
+
+ When \a mode is set to MatchExtension, only the file name is used, not
+ the file contents. The file doesn't even have to exist. If the file name
+ doesn't match any known pattern, the default MIME type (application/octet-stream)
+ is returned.
+ If multiple MIME types match this file, the first one (alphabetically) is returned.
+
+ When \a mode is set to MatchContent, and the file is readable, only the
+ file contents are used to determine the MIME type. This is equivalent to
+ calling mimeTypeForData with a QFile as input device.
+
+ \a fileInfo may refer to an absolute or relative path.
+
+ \sa MimeType::isDefault(), mimeTypeForData()
+*/
+MimeType MimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode) const
+{
+ QMutexLocker locker(&d->mutex);
+
+ if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
+ qWarning("Accessing MimeDatabase for %s before plugins are initialized",
+ qPrintable(fileInfo.filePath()));
+
+ if (fileInfo.isDir())
+ return d->mimeTypeForName(QLatin1String("inode/directory"));
+
+ const QString filePath = fileInfo.filePath();
+
+#ifdef Q_OS_UNIX
+ // Cannot access statBuf.st_mode from the filesystem engine, so we have to stat again.
+ // In addition we want to follow symlinks.
+ const QByteArray nativeFilePath = QFile::encodeName(filePath);
+ QT_STATBUF statBuffer;
+ if (QT_STAT(nativeFilePath.constData(), &statBuffer) == 0) {
+ if (S_ISCHR(statBuffer.st_mode))
+ return d->mimeTypeForName(QLatin1String("inode/chardevice"));
+ if (S_ISBLK(statBuffer.st_mode))
+ return d->mimeTypeForName(QLatin1String("inode/blockdevice"));
+ if (S_ISFIFO(statBuffer.st_mode))
+ return d->mimeTypeForName(QLatin1String("inode/fifo"));
+ if (S_ISSOCK(statBuffer.st_mode))
+ return d->mimeTypeForName(QLatin1String("inode/socket"));
+ }
+#endif
+
+ int priority = 0;
+ switch (mode) {
+ case MatchDefault:
+ return d->mimeTypeForFileNameAndData(filePath, nullptr, &priority);
+ case MatchExtension:
+ locker.unlock();
+ return mimeTypeForFile(filePath, mode);
+ case MatchContent: {
+ QFile file(filePath);
+ if (file.open(QIODevice::ReadOnly)) {
+ locker.unlock();
+ return mimeTypeForData(&file);
+ } else {
+ return d->mimeTypeForName(d->defaultMimeType());
+ }
+ }
+ default:
+ Q_ASSERT(false);
+ }
+ return d->mimeTypeForName(d->defaultMimeType());
+}
+
+/*!
+ Returns a MIME type for the file named \a fileName using \a mode.
+
+ \overload
+*/
+MimeType MimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode) const
+{
+ if (mode == MatchExtension) {
+ QMutexLocker locker(&d->mutex);
+
+ if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
+ qWarning("Accessing MimeDatabase for %s before plugins are initialized",
+ qPrintable(fileName));
+
+ const QStringList matches = d->mimeTypeForFileName(fileName);
+ const int matchCount = matches.count();
+ if (matchCount == 0) {
+ return d->mimeTypeForName(d->defaultMimeType());
+ } else if (matchCount == 1) {
+ return d->mimeTypeForName(matches.first());
+ } else {
+ // We have to pick one.
+ return d->mimeTypeForName(matches.first());
+ }
+ } else {
+ // Implemented as a wrapper around mimeTypeForFile(QFileInfo), so no mutex.
+ QFileInfo fileInfo(fileName);
+ return mimeTypeForFile(fileInfo, mode);
+ }
+}
+
+/*!
+ Returns the MIME types for the file name \a fileName.
+
+ If the file name doesn't match any known pattern, an empty list is returned.
+ If multiple MIME types match this file, they are all returned.
+
+ This function does not try to open the file. To also use the content
+ when determining the MIME type, use mimeTypeForFile() or
+ mimeTypeForFileNameAndData() instead.
+
+ \sa mimeTypeForFile()
+*/
+QList<MimeType> MimeDatabase::mimeTypesForFileName(const QString &fileName) const
+{
+ QMutexLocker locker(&d->mutex);
+
+ if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
+ qWarning("Accessing MimeDatabase for %s before plugins are initialized",
+ qPrintable(fileName));
+
+ const QStringList matches = d->mimeTypeForFileName(fileName);
+ QList<MimeType> mimes;
+ mimes.reserve(matches.count());
+ for (const QString &mime : matches)
+ mimes.append(d->mimeTypeForName(mime));
+ return mimes;
+}
+/*!
+ Returns the suffix for the file \a fileName, as known by the MIME database.
+
+ This allows to pre-select "tar.bz2" for foo.tar.bz2, but still only
+ "txt" for my.file.with.dots.txt.
+*/
+QString MimeDatabase::suffixForFileName(const QString &fileName) const
+{
+ QMutexLocker locker(&d->mutex);
+ const int suffixLength = d->findByFileName(fileName).m_knownSuffixLength;
+ return fileName.right(suffixLength);
+}
+
+/*!
+ Returns a MIME type for \a data.
+
+ A valid MIME type is always returned. If \a data doesn't match any
+ known MIME type data, the default MIME type (application/octet-stream)
+ is returned.
+*/
+MimeType MimeDatabase::mimeTypeForData(const QByteArray &data) const
+{
+ QMutexLocker locker(&d->mutex);
+
+ if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
+ qWarning("Accessing MimeDatabase for data before plugins are initialized");
+
+ int accuracy = 0;
+ return d->findByData(data, &accuracy);
+}
+
+/*!
+ Returns a MIME type for the data in \a device.
+
+ A valid MIME type is always returned. If the data in \a device doesn't match any
+ known MIME type data, the default MIME type (application/octet-stream)
+ is returned.
+*/
+MimeType MimeDatabase::mimeTypeForData(QIODevice *device) const
+{
+ QMutexLocker locker(&d->mutex);
+
+ int accuracy = 0;
+ const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
+ if (device->isOpen()) {
+ // Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
+ // This is much faster than seeking back and forth into QIODevice.
+ const QByteArray data = device->peek(16384);
+ const MimeType result = d->findByData(data, &accuracy);
+ if (openedByUs)
+ device->close();
+ return result;
+ }
+ return d->mimeTypeForName(d->defaultMimeType());
+}
+
+/*!
+ Returns a MIME type for \a url.
+
+ If the URL is a local file, this calls mimeTypeForFile.
+
+ Otherwise the matching is done based on the file name only,
+ except for schemes where file names don't mean much, like HTTP.
+ This method always returns the default mimetype for HTTP URLs,
+ use QNetworkAccessManager to handle HTTP URLs properly.
+
+ A valid MIME type is always returned. If \a url doesn't match any
+ known MIME type data, the default MIME type (application/octet-stream)
+ is returned.
+*/
+MimeType MimeDatabase::mimeTypeForUrl(const QUrl &url) const
+{
+ if (url.isLocalFile())
+ return mimeTypeForFile(url.toLocalFile());
+
+ const QString scheme = url.scheme();
+ if (scheme.startsWith(QLatin1String("http")) || scheme == QLatin1String("mailto"))
+ return mimeTypeForName(d->defaultMimeType());
+
+ return mimeTypeForFile(url.path(), MatchExtension);
+}
+
+/*!
+ Returns a MIME type for the given \a fileName and \a device data.
+
+ This overload can be useful when the file is remote, and we started to
+ download some of its data in a device. This allows to do full MIME type
+ matching for remote files as well.
+
+ If the device is not open, it will be opened by this function, and closed
+ after the MIME type detection is completed.
+
+ A valid MIME type is always returned. If \a device data doesn't match any
+ known MIME type data, the default MIME type (application/octet-stream)
+ is returned.
+
+ This method looks at both the file name and the file contents,
+ if necessary. The file extension has priority over the contents,
+ but the contents will be used if the file extension is unknown, or
+ matches multiple MIME types.
+*/
+MimeType MimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const
+{
+ QMutexLocker locker(&d->mutex);
+
+ if (fileName.endsWith(QLatin1Char('/')))
+ return d->mimeTypeForName(QLatin1String("inode/directory"));
+
+ int accuracy = 0;
+ const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
+ const MimeType result = d->mimeTypeForFileNameAndData(fileName, device, &accuracy);
+ if (openedByUs)
+ device->close();
+ return result;
+}
+
+/*!
+ Returns a MIME type for the given \a fileName and device \a data.
+
+ This overload can be useful when the file is remote, and we started to
+ download some of its data. This allows to do full MIME type matching for
+ remote files as well.
+
+ A valid MIME type is always returned. If \a data doesn't match any
+ known MIME type data, the default MIME type (application/octet-stream)
+ is returned.
+
+ This method looks at both the file name and the file contents,
+ if necessary. The file extension has priority over the contents,
+ but the contents will be used if the file extension is unknown, or
+ matches multiple MIME types.
+*/
+MimeType MimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, const QByteArray &data) const
+{
+ QMutexLocker locker(&d->mutex);
+
+ if (fileName.endsWith(QLatin1Char('/')))
+ return d->mimeTypeForName(QLatin1String("inode/directory"));
+
+ QBuffer buffer(const_cast<QByteArray *>(&data));
+ buffer.open(QIODevice::ReadOnly);
+ int accuracy = 0;
+ return d->mimeTypeForFileNameAndData(fileName, &buffer, &accuracy);
+}
+
+/*!
+ Returns the list of all available MIME types.
+
+ This can be useful for showing all MIME types to the user, for instance
+ in a MIME type editor. Do not use unless really necessary in other cases
+ though, prefer using the \l {mimeTypeForData()}{mimeTypeForXxx()} methods for performance reasons.
+*/
+QList<MimeType> MimeDatabase::allMimeTypes() const
+{
+ QMutexLocker locker(&d->mutex);
+
+ if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
+ qWarning("Accessing MimeDatabase for all mime types before plugins are initialized");
+
+ return d->allMimeTypes();
+}
+
+/*!
+ \enum MimeDatabase::MatchMode
+
+ This enum specifies how matching a file to a MIME type is performed.
+
+ \value MatchDefault Both the file name and content are used to look for a match
+
+ \value MatchExtension Only the file name is used to look for a match
+
+ \value MatchContent The file content is used to look for a match
+*/
+
+// added for Qt Creator
+void MimeDatabasePrivate::addMimeData(const QString &id, const QByteArray &data)
+{
+ if (m_additionalData.contains(id))
+ qWarning("Overwriting data in mime database, id '%s'", qPrintable(id));
+
+ m_additionalData.insert(id, data);
+ m_forceLoad = true;
+}
+
+QMap<int, QList<MimeMagicRule>> MimeDatabasePrivate::magicRulesForMimeType(const MimeType &mimeType)
+{
+ for (const auto &provider : providers()) {
+ if (provider->hasMimeTypeForName(mimeType.name()))
+ return provider->magicRulesForMimeType(mimeType);
+ }
+ return {};
+}
+
+void MimeDatabasePrivate::setMagicRulesForMimeType(const MimeType &mimeType,
+ const QMap<int, QList<MimeMagicRule>> &rules)
+{
+ for (const auto &provider : providers()) {
+ if (provider->hasMimeTypeForName(mimeType.name())) {
+ provider->setMagicRulesForMimeType(mimeType, rules);
+ return;
+ }
+ }
+}
+
+void MimeDatabasePrivate::setGlobPatternsForMimeType(const MimeType &mimeType,
+ const QStringList &patterns)
+{
+ for (const auto &provider : providers()) {
+ if (provider->hasMimeTypeForName(mimeType.name())) {
+ provider->setGlobPatternsForMimeType(mimeType, patterns);
+ return;
+ }
+ }
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimedatabase.h b/src/libs/utils/mimetypes2/mimedatabase.h
new file mode 100644
index 00000000000..7516c467ddf
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimedatabase.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "mimetype.h"
+
+#include "mimemagicrule_p.h"
+
+#include <utils/utils_global.h>
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+class QFileInfo;
+class QIODevice;
+class QUrl;
+QT_END_NAMESPACE
+
+namespace Utils {
+
+class MimeDatabasePrivate;
+
+class MimeDatabase
+{
+ Q_DISABLE_COPY(MimeDatabase)
+
+public:
+ MimeDatabase();
+ ~MimeDatabase();
+
+ MimeType mimeTypeForName(const QString &nameOrAlias) const;
+
+ enum MatchMode {
+ MatchDefault = 0x0,
+ MatchExtension = 0x1,
+ MatchContent = 0x2
+ };
+
+ MimeType mimeTypeForFile(const QString &fileName, MatchMode mode = MatchDefault) const;
+ MimeType mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode = MatchDefault) const;
+ QList<MimeType> mimeTypesForFileName(const QString &fileName) const;
+
+ MimeType mimeTypeForData(const QByteArray &data) const;
+ MimeType mimeTypeForData(QIODevice *device) const;
+
+ MimeType mimeTypeForUrl(const QUrl &url) const;
+ MimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const;
+ MimeType mimeTypeForFileNameAndData(const QString &fileName, const QByteArray &data) const;
+
+ QString suffixForFileName(const QString &fileName) const;
+
+ QList<MimeType> allMimeTypes() const;
+
+private:
+ MimeDatabasePrivate *d;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimedatabase_p.h b/src/libs/utils/mimetypes2/mimedatabase_p.h
new file mode 100644
index 00000000000..a85d76af71d
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimedatabase_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "mimetype.h"
+
+#include "mimeglobpattern_p.h"
+#include "mimemagicrule_p.h"
+#include "mimetype_p.h"
+
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qmutex.h>
+
+#include <vector>
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+class QIODevice;
+QT_END_NAMESPACE
+
+namespace Utils {
+
+class MimeDatabase;
+class MimeProviderBase;
+
+class MimeDatabasePrivate
+{
+public:
+ Q_DISABLE_COPY_MOVE(MimeDatabasePrivate)
+
+ MimeDatabasePrivate();
+ ~MimeDatabasePrivate();
+
+ static MimeDatabasePrivate *instance();
+
+ inline QString defaultMimeType() const { return m_defaultMimeType; }
+
+ bool inherits(const QString &mime, const QString &parent);
+
+ QList<MimeType> allMimeTypes();
+
+ QString resolveAlias(const QString &nameOrAlias);
+ QStringList parents(const QString &mimeName);
+ MimeType mimeTypeForName(const QString &nameOrAlias);
+ MimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr);
+ MimeType findByData(const QByteArray &data, int *priorityPtr);
+ QStringList mimeTypeForFileName(const QString &fileName);
+ MimeGlobMatchResult findByFileName(const QString &fileName);
+
+ // API for MimeType. Takes care of locking the mutex.
+ void loadMimeTypePrivate(MimeTypePrivate &mimePrivate);
+ void loadGenericIcon(MimeTypePrivate &mimePrivate);
+ void loadIcon(MimeTypePrivate &mimePrivate);
+ QStringList mimeParents(const QString &mimeName);
+ QStringList listAliases(const QString &mimeName);
+ bool mimeInherits(const QString &mime, const QString &parent);
+
+ // added for Qt Creator
+ void addMimeData(const QString &id, const QByteArray &data);
+ QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(const MimeType &mimeType);
+ void setMagicRulesForMimeType(const MimeType &mimeType,
+ const QMap<int, QList<MimeMagicRule>> &rules);
+ void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
+
+private:
+ using Providers = std::vector<std::unique_ptr<MimeProviderBase>>;
+ const Providers &providers();
+ bool shouldCheck();
+ void loadProviders();
+
+ mutable Providers m_providers;
+ QElapsedTimer m_lastCheck;
+
+ // added for Qt Creator
+ QHash<QString, QByteArray> m_additionalData; // id -> data
+ bool m_forceLoad = true;
+
+public:
+ const QString m_defaultMimeType;
+ QMutex mutex;
+
+ // added for Qt Creator
+ int m_startupPhase = 0;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimeglobpattern.cpp b/src/libs/utils/mimetypes2/mimeglobpattern.cpp
new file mode 100644
index 00000000000..74ccafa3dc6
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimeglobpattern.cpp
@@ -0,0 +1,312 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mimeglobpattern_p.h"
+
+#if QT_CONFIG(regularexpression)
+#include <QRegularExpression>
+#endif
+#include <QStringList>
+#include <QDebug>
+
+namespace Utils {
+
+/*!
+ \internal
+ \class MimeGlobMatchResult
+ \inmodule QtCore
+ \brief The MimeGlobMatchResult class accumulates results from glob matching.
+
+ Handles glob weights, and preferring longer matches over shorter matches.
+*/
+
+void MimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QString &pattern, int knownSuffixLength)
+{
+ if (m_allMatchingMimeTypes.contains(mimeType))
+ return;
+ // Is this a lower-weight pattern than the last match? Skip this match then.
+ if (weight < m_weight) {
+ m_allMatchingMimeTypes.append(mimeType);
+ return;
+ }
+ bool replace = weight > m_weight;
+ if (!replace) {
+ // Compare the length of the match
+ if (pattern.length() < m_matchingPatternLength)
+ return; // too short, ignore
+ else if (pattern.length() > m_matchingPatternLength) {
+ // longer: clear any previous match (like *.bz2, when pattern is *.tar.bz2)
+ replace = true;
+ }
+ }
+ if (replace) {
+ m_matchingMimeTypes.clear();
+ // remember the new "longer" length
+ m_matchingPatternLength = pattern.length();
+ m_weight = weight;
+ }
+ if (!m_matchingMimeTypes.contains(mimeType)) {
+ m_matchingMimeTypes.append(mimeType);
+ if (replace)
+ m_allMatchingMimeTypes.prepend(mimeType); // highest-weight first
+ else
+ m_allMatchingMimeTypes.append(mimeType);
+ m_knownSuffixLength = knownSuffixLength;
+ }
+}
+
+MimeGlobPattern::PatternType MimeGlobPattern::detectPatternType(const QString &pattern) const
+{
+ const int patternLength = pattern.length();
+ if (!patternLength)
+ return OtherPattern;
+
+ const int starCount = pattern.count(QLatin1Char('*'));
+ const bool hasSquareBracket = pattern.indexOf(QLatin1Char('[')) != -1;
+ const bool hasQuestionMark = pattern.indexOf(QLatin1Char('?')) != -1;
+
+ if (!hasSquareBracket && !hasQuestionMark) {
+ if (starCount == 1) {
+ // Patterns like "*~", "*.extension"
+ if (pattern.at(0) == QLatin1Char('*'))
+ return SuffixPattern;
+ // Patterns like "README*" (well this is currently the only one like that...)
+ if (pattern.at(patternLength - 1) == QLatin1Char('*'))
+ return PrefixPattern;
+ } else if (starCount == 0) {
+ // Names without any wildcards like "README"
+ return LiteralPattern;
+ }
+ }
+
+ if (pattern == QLatin1String("[0-9][0-9][0-9].vdr"))
+ return VdrPattern;
+
+ if (pattern == QLatin1String("*.anim[1-9j]"))
+ return AnimPattern;
+
+ return OtherPattern;
+}
+
+
+/*!
+ \internal
+ \class MimeGlobPattern
+ \inmodule QtCore
+ \brief The MimeGlobPattern class contains the glob pattern for file names for MIME type matching.
+
+ \sa MimeType, MimeDatabase, MimeMagicRuleMatcher, MimeMagicRule
+*/
+
+bool MimeGlobPattern::matchFileName(const QString &inputFileName) const
+{
+ // "Applications MUST match globs case-insensitively, except when the case-sensitive
+ // attribute is set to true."
+ // The constructor takes care of putting case-insensitive patterns in lowercase.
+ const QString fileName = m_caseSensitivity == Qt::CaseInsensitive
+ ? inputFileName.toLower() : inputFileName;
+
+ const int patternLength = m_pattern.length();
+ if (!patternLength)
+ return false;
+ const int fileNameLength = fileName.length();
+
+ switch (m_patternType) {
+ case SuffixPattern: {
+ if (fileNameLength + 1 < patternLength)
+ return false;
+
+ const QChar *c1 = m_pattern.unicode() + patternLength - 1;
+ const QChar *c2 = fileName.unicode() + fileNameLength - 1;
+ int cnt = 1;
+ while (cnt < patternLength && *c1-- == *c2--)
+ ++cnt;
+ return cnt == patternLength;
+ }
+ case PrefixPattern: {
+ if (fileNameLength + 1 < patternLength)
+ return false;
+
+ const QChar *c1 = m_pattern.unicode();
+ const QChar *c2 = fileName.unicode();
+ int cnt = 1;
+ while (cnt < patternLength && *c1++ == *c2++)
+ ++cnt;
+ return cnt == patternLength;
+ }
+ case LiteralPattern:
+ return (m_pattern == fileName);
+ case VdrPattern: // "[0-9][0-9][0-9].vdr" case
+ return fileNameLength == 7
+ && fileName.at(0).isDigit() && fileName.at(1).isDigit() && fileName.at(2).isDigit()
+ && QStringView{fileName}.mid(3, 4) == QLatin1String(".vdr");
+ case AnimPattern: { // "*.anim[1-9j]" case
+ if (fileNameLength < 6)
+ return false;
+ const QChar lastChar = fileName.at(fileNameLength - 1);
+ const bool lastCharOK = (lastChar.isDigit() && lastChar != QLatin1Char('0'))
+ || lastChar == QLatin1Char('j');
+ return lastCharOK && QStringView{fileName}.mid(fileNameLength - 6, 5) == QLatin1String(".anim");
+ }
+ case OtherPattern:
+#if QT_CONFIG(regularexpression)
+ // Other fallback patterns: slow but correct method
+ const QRegularExpression rx(QRegularExpression::anchoredPattern(
+ QRegularExpression::wildcardToRegularExpression(m_pattern)));
+ return rx.match(fileName).hasMatch();
+#else
+ return false;
+#endif
+ }
+ return false;
+}
+
+static bool isSimplePattern(const QString &pattern)
+{
+ // starts with "*.", has no other '*'
+ return pattern.lastIndexOf(QLatin1Char('*')) == 0
+ && pattern.length() > 1
+ && pattern.at(1) == QLatin1Char('.') // (other dots are OK, like *.tar.bz2)
+ // and contains no other special character
+ && !pattern.contains(QLatin1Char('?'))
+ && !pattern.contains(QLatin1Char('['))
+ ;
+}
+
+static bool isFastPattern(const QString &pattern)
+{
+ // starts with "*.", has no other '*' and no other '.'
+ return pattern.lastIndexOf(QLatin1Char('*')) == 0
+ && pattern.lastIndexOf(QLatin1Char('.')) == 1
+ // and contains no other special character
+ && !pattern.contains(QLatin1Char('?'))
+ && !pattern.contains(QLatin1Char('['))
+ ;
+}
+
+void MimeAllGlobPatterns::addGlob(const MimeGlobPattern &glob)
+{
+ const QString &pattern = glob.pattern();
+ Q_ASSERT(!pattern.isEmpty());
+
+ // Store each patterns into either m_fastPatternDict (*.txt, *.html etc. with default weight 50)
+ // or for the rest, like core.*, *.tar.bz2, *~, into highWeightPatternOffset (>50)
+ // or lowWeightPatternOffset (<=50)
+
+ if (glob.weight() == 50 && isFastPattern(pattern) && !glob.isCaseSensitive()) {
+ // The bulk of the patterns is *.foo with weight 50 --> those go into the fast patterns hash.
+ const QString extension = pattern.mid(2).toLower();
+ QStringList &patterns = m_fastPatterns[extension]; // find or create
+ if (!patterns.contains(glob.mimeType()))
+ patterns.append(glob.mimeType());
+ } else {
+ if (glob.weight() > 50) {
+ if (!m_highWeightGlobs.hasPattern(glob.mimeType(), glob.pattern()))
+ m_highWeightGlobs.append(glob);
+ } else {
+ if (!m_lowWeightGlobs.hasPattern(glob.mimeType(), glob.pattern()))
+ m_lowWeightGlobs.append(glob);
+ }
+ }
+}
+
+void MimeAllGlobPatterns::removeMimeType(const QString &mimeType)
+{
+ for (auto &x : m_fastPatterns)
+ x.removeAll(mimeType);
+ m_highWeightGlobs.removeMimeType(mimeType);
+ m_lowWeightGlobs.removeMimeType(mimeType);
+}
+
+void MimeGlobPatternList::match(MimeGlobMatchResult &result,
+ const QString &fileName,
+ const QSet<QString> &ignoreMimeTypes) const
+{
+
+ MimeGlobPatternList::const_iterator it = this->constBegin();
+ const MimeGlobPatternList::const_iterator endIt = this->constEnd();
+ for (; it != endIt; ++it) {
+ const MimeGlobPattern &glob = *it;
+ if (ignoreMimeTypes.contains(glob.mimeType()))
+ continue;
+ if (glob.matchFileName(fileName)) {
+ const QString pattern = glob.pattern();
+ const int suffixLen = isSimplePattern(pattern) ? pattern.length() - 2 : 0;
+ result.addMatch(glob.mimeType(), glob.weight(), pattern, suffixLen);
+ }
+ }
+}
+
+void MimeAllGlobPatterns::matchingGlobs(const QString &fileName,
+ MimeGlobMatchResult &result,
+ const QSet<QString> &ignoreMimeTypes) const
+{
+ // First try the high weight matches (>50), if any.
+ m_highWeightGlobs.match(result, fileName, ignoreMimeTypes);
+
+ // Now use the "fast patterns" dict, for simple *.foo patterns with weight 50
+ // (which is most of them, so this optimization is definitely worth it)
+ const int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
+ if (lastDot != -1) { // if no '.', skip the extension lookup
+ const int ext_len = fileName.length() - lastDot - 1;
+ const QString simpleExtension = fileName.right(ext_len).toLower();
+ // (toLower because fast patterns are always case-insensitive and saved as lowercase)
+
+ const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension);
+ const QString simplePattern = QLatin1String("*.") + simpleExtension;
+ for (const QString &mime : matchingMimeTypes) {
+ if (!ignoreMimeTypes.contains(mime))
+ result.addMatch(mime, 50, simplePattern, simpleExtension.size());
+ }
+ // Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway,
+ // at least those with weight 50.
+ }
+
+ // Finally, try the low weight matches (<=50)
+ m_lowWeightGlobs.match(result, fileName, ignoreMimeTypes);
+}
+
+void MimeAllGlobPatterns::clear()
+{
+ m_fastPatterns.clear();
+ m_highWeightGlobs.clear();
+ m_lowWeightGlobs.clear();
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimeglobpattern_p.h b/src/libs/utils/mimetypes2/mimeglobpattern_p.h
new file mode 100644
index 00000000000..8f6c66475e9
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimeglobpattern_p.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qhash.h>
+
+namespace Utils {
+
+struct MimeGlobMatchResult
+{
+ void addMatch(const QString &mimeType, int weight, const QString &pattern, int knownSuffixLength = 0);
+
+ QStringList m_matchingMimeTypes; // only those with highest weight
+ QStringList m_allMatchingMimeTypes;
+ int m_weight = 0;
+ int m_matchingPatternLength = 0;
+ int m_knownSuffixLength = 0;
+};
+
+class MimeGlobPattern
+{
+public:
+ static const unsigned MaxWeight = 100;
+ static const unsigned DefaultWeight = 50;
+ static const unsigned MinWeight = 1;
+
+ explicit MimeGlobPattern(const QString &thePattern, const QString &theMimeType, unsigned theWeight = DefaultWeight, Qt::CaseSensitivity s = Qt::CaseInsensitive) :
+ m_pattern(s == Qt::CaseInsensitive ? thePattern.toLower() : thePattern),
+ m_mimeType(theMimeType),
+ m_weight(theWeight),
+ m_caseSensitivity(s),
+ m_patternType(detectPatternType(m_pattern))
+ {
+ }
+
+ void swap(MimeGlobPattern &other) noexcept
+ {
+ qSwap(m_pattern, other.m_pattern);
+ qSwap(m_mimeType, other.m_mimeType);
+ qSwap(m_weight, other.m_weight);
+ qSwap(m_caseSensitivity, other.m_caseSensitivity);
+ qSwap(m_patternType, other.m_patternType);
+ }
+
+ bool matchFileName(const QString &inputFileName) const;
+
+ inline const QString &pattern() const { return m_pattern; }
+ inline unsigned weight() const { return m_weight; }
+ inline const QString &mimeType() const { return m_mimeType; }
+ inline bool isCaseSensitive() const { return m_caseSensitivity == Qt::CaseSensitive; }
+
+private:
+ enum PatternType {
+ SuffixPattern,
+ PrefixPattern,
+ LiteralPattern,
+ VdrPattern, // special handling for "[0-9][0-9][0-9].vdr" pattern
+ AnimPattern, // special handling for "*.anim[1-9j]" pattern
+ OtherPattern
+ };
+ PatternType detectPatternType(const QString &pattern) const;
+
+ QString m_pattern;
+ QString m_mimeType;
+ int m_weight;
+ Qt::CaseSensitivity m_caseSensitivity;
+ PatternType m_patternType;
+};
+
+class MimeGlobPatternList : public QList<MimeGlobPattern>
+{
+public:
+ bool hasPattern(const QString &mimeType, const QString &pattern) const
+ {
+ const_iterator it = begin();
+ const const_iterator myend = end();
+ for (; it != myend; ++it)
+ if ((*it).pattern() == pattern && (*it).mimeType() == mimeType)
+ return true;
+ return false;
+ }
+
+ /*!
+ "noglobs" is very rare occurrence, so it's ok if it's slow
+ */
+ void removeMimeType(const QString &mimeType)
+ {
+ auto isMimeTypeEqual = [&mimeType](const MimeGlobPattern &pattern) {
+ return pattern.mimeType() == mimeType;
+ };
+ erase(std::remove_if(begin(), end(), isMimeTypeEqual), end());
+ }
+
+ void match(MimeGlobMatchResult &result,
+ const QString &fileName,
+ const QSet<QString> &ignoreMimeTypes) const;
+};
+
+/*!
+ Result of the globs parsing, as data structures ready for efficient MIME type matching.
+ This contains:
+ 1) a map of fast regular patterns (e.g. *.txt is stored as "txt" in a qhash's key)
+ 2) a linear list of high-weight globs
+ 3) a linear list of low-weight globs
+ */
+class MimeAllGlobPatterns
+{
+public:
+ typedef QHash<QString, QStringList> PatternsMap; // MIME type -> patterns
+
+ void addGlob(const MimeGlobPattern &glob);
+ void removeMimeType(const QString &mimeType);
+ void matchingGlobs(const QString &fileName,
+ MimeGlobMatchResult &result,
+ const QSet<QString> &ignoreMimeTypes) const;
+ void clear();
+
+ PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain"
+ MimeGlobPatternList m_highWeightGlobs;
+ MimeGlobPatternList m_lowWeightGlobs; // <= 50, including the non-fast 50 patterns
+};
+
+} // namespace Utils
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_SHARED(Utils::MimeGlobPattern)
+QT_END_NAMESPACE
diff --git a/src/libs/utils/mimetypes2/mimemagicrule.cpp b/src/libs/utils/mimetypes2/mimemagicrule.cpp
new file mode 100644
index 00000000000..5db88c2f717
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimemagicrule.cpp
@@ -0,0 +1,412 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mimemagicrule_p.h"
+
+#include "mimetypeparser_p.h"
+
+#include "porting.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QList>
+#include <qendian.h>
+
+namespace Utils {
+
+// in the same order as Type!
+static const char magicRuleTypes_string[] =
+ "invalid\0"
+ "string\0"
+ "regexp\0"
+ "host16\0"
+ "host32\0"
+ "big16\0"
+ "big32\0"
+ "little16\0"
+ "little32\0"
+ "byte\0"
+ "\0";
+
+static const int magicRuleTypes_indices[] = {
+ 0, 8, 15, 22, 29, 36, 42, 48, 57, 66, 71, 0
+};
+
+MimeMagicRule::Type MimeMagicRule::type(const QByteArray &theTypeName)
+{
+ for (int i = String; i <= Byte; ++i) {
+ if (theTypeName == magicRuleTypes_string + magicRuleTypes_indices[i])
+ return Type(i);
+ }
+ return Invalid;
+}
+
+QByteArray MimeMagicRule::typeName(MimeMagicRule::Type theType)
+{
+ return magicRuleTypes_string + magicRuleTypes_indices[theType];
+}
+
+bool MimeMagicRule::operator==(const MimeMagicRule &other) const
+{
+ return m_type == other.m_type &&
+ m_value == other.m_value &&
+ m_startPos == other.m_startPos &&
+ m_endPos == other.m_endPos &&
+ m_mask == other.m_mask &&
+ m_regexp == other.m_regexp &&
+ m_pattern == other.m_pattern &&
+ m_number == other.m_number &&
+ m_numberMask == other.m_numberMask &&
+ m_matchFunction == other.m_matchFunction;
+}
+
+// Used by both providers
+bool MimeMagicRule::matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength,
+ int valueLength, const char *valueData, const char *mask)
+{
+ // Size of searched data.
+ // Example: value="ABC", rangeLength=3 -> we need 3+3-1=5 bytes (ABCxx,xABCx,xxABC would match)
+ const int dataNeeded = qMin(rangeLength + valueLength - 1, dataSize - rangeStart);
+
+ if (!mask) {
+ // callgrind says QByteArray::indexOf is much slower, since our strings are typically too
+ // short for be worth Boyer-Moore matching (1 to 71 bytes, 11 bytes on average).
+ bool found = false;
+ for (int i = rangeStart; i < rangeStart + rangeLength; ++i) {
+ if (i + valueLength > dataSize)
+ break;
+
+ if (memcmp(valueData, dataPtr + i, valueLength) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
+ } else {
+ bool found = false;
+ const char *readDataBase = dataPtr + rangeStart;
+ // Example (continued from above):
+ // deviceSize is 4, so dataNeeded was max'ed to 4.
+ // maxStartPos = 4 - 3 + 1 = 2, and indeed
+ // we need to check for a match a positions 0 and 1 (ABCx and xABC).
+ const int maxStartPos = dataNeeded - valueLength + 1;
+ for (int i = 0; i < maxStartPos; ++i) {
+ const char *d = readDataBase + i;
+ bool valid = true;
+ for (int idx = 0; idx < valueLength; ++idx) {
+ if (((*d++) & mask[idx]) != (valueData[idx] & mask[idx])) {
+ valid = false;
+ break;
+ }
+ }
+ if (valid)
+ found = true;
+ }
+ if (!found)
+ return false;
+ }
+ //qDebug() << "Found" << value << "in" << searchedData;
+ return true;
+}
+
+bool MimeMagicRule::matchString(const QByteArray &data) const
+{
+ const int rangeLength = m_endPos - m_startPos + 1;
+ return MimeMagicRule::matchSubstring(data.constData(), data.size(), m_startPos, rangeLength, m_pattern.size(), m_pattern.constData(), m_mask.constData());
+}
+
+template <typename T>
+bool MimeMagicRule::matchNumber(const QByteArray &data) const
+{
+ const T value(m_number);
+ const T mask(m_numberMask);
+
+ //qDebug() << "matchNumber" << "0x" << QString::number(m_number, 16) << "size" << sizeof(T);
+ //qDebug() << "mask" << QString::number(m_numberMask, 16);
+
+ const char *p = data.constData() + m_startPos;
+ const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), m_endPos);
+ for ( ; p <= e; ++p) {
+ if ((qFromUnaligned<T>(p) & mask) == (value & mask))
+ return true;
+ }
+
+ return false;
+}
+
+static inline QByteArray makePattern(const QByteArray &value)
+{
+ QByteArray pattern(value.size(), Qt::Uninitialized);
+ char *data = pattern.data();
+
+ const char *p = value.constData();
+ const char *e = p + value.size();
+ for ( ; p < e; ++p) {
+ if (*p == '\\' && ++p < e) {
+ if (*p == 'x') { // hex (\\xff)
+ char c = 0;
+ for (int i = 0; i < 2 && p + 1 < e; ++i) {
+ ++p;
+ if (*p >= '0' && *p <= '9')
+ c = (c << 4) + *p - '0';
+ else if (*p >= 'a' && *p <= 'f')
+ c = (c << 4) + *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'F')
+ c = (c << 4) + *p - 'A' + 10;
+ else
+ continue;
+ }
+ *data++ = c;
+ } else if (*p >= '0' && *p <= '7') { // oct (\\7, or \\77, or \\377)
+ char c = *p - '0';
+ if (p + 1 < e && p[1] >= '0' && p[1] <= '7') {
+ c = (c << 3) + *(++p) - '0';
+ if (p + 1 < e && p[1] >= '0' && p[1] <= '7' && p[-1] <= '3')
+ c = (c << 3) + *(++p) - '0';
+ }
+ *data++ = c;
+ } else if (*p == 'n') {
+ *data++ = '\n';
+ } else if (*p == 'r') {
+ *data++ = '\r';
+ } else if (*p == 't') {
+ *data++ = '\t';
+ } else { // escaped
+ *data++ = *p;
+ }
+ } else {
+ *data++ = *p;
+ }
+ }
+ pattern.truncate(data - pattern.data());
+
+ return pattern;
+}
+
+bool MimeMagicRule::matchRegExp(const QByteArray &data) const
+{
+ const QString str = QString::fromUtf8(data);
+ int length = m_endPos;
+ if (length == m_startPos)
+ length = -1; // from startPos to end of string
+ const QString subStr = str.left(length);
+ return m_regexp.match(subStr, m_startPos).hasMatch();
+}
+
+MimeMagicRule::MimeMagicRule(const Type &type,
+ const QByteArray &value,
+ int startPos,
+ int endPos,
+ const QByteArray &mask,
+ QString *errorString)
+ : m_type(type)
+ , m_value(value)
+ , m_startPos(startPos)
+ , m_endPos(endPos)
+ , m_mask(mask)
+{
+ init(errorString);
+}
+
+// Evaluate a magic match rule like
+// <match value="must be converted with BinHex" type="string" offset="11"/>
+// <match value="0x9501" type="big16" offset="0:64"/>
+
+MimeMagicRule::MimeMagicRule(const QString &type,
+ const QByteArray &value,
+ const QString &offsets,
+ const QByteArray &mask,
+ QString *errorString)
+ : m_type(MimeMagicRule::type(type.toLatin1())),
+ m_value(value),
+ m_mask(mask),
+ m_matchFunction(nullptr)
+{
+ if (Q_UNLIKELY(m_type == Invalid))
+ *errorString = QLatin1String("Type ") + type + QLatin1String(" is not supported");
+
+ // Parse for offset as "1" or "1:10"
+ const int colonIndex = offsets.indexOf(QLatin1Char(':'));
+ const QStringView startPosStr
+ = Utils::midView(offsets, 0, colonIndex); // \ These decay to returning 'offsets'
+ const QStringView endPosStr = Utils::midView(offsets,
+ colonIndex
+ + 1); // / unchanged when colonIndex == -1
+ if (Q_UNLIKELY(!MimeTypeParserBase::parseNumber(startPosStr, &m_startPos, errorString)) ||
+ Q_UNLIKELY(!MimeTypeParserBase::parseNumber(endPosStr, &m_endPos, errorString))) {
+ m_type = Invalid;
+ return;
+ }
+
+ if (Q_UNLIKELY(m_value.isEmpty())) {
+ m_type = Invalid;
+ if (errorString)
+ *errorString = QStringLiteral("Invalid empty magic rule value");
+ return;
+ }
+
+ init(errorString);
+}
+
+void MimeMagicRule::init(QString *errorString)
+{
+ if (m_type >= Host16 && m_type <= Byte) {
+ bool ok;
+ m_number = m_value.toUInt(&ok, 0); // autodetect base
+ if (Q_UNLIKELY(!ok)) {
+ m_type = Invalid;
+ if (errorString)
+ *errorString = QLatin1String("Invalid magic rule value \"") + QLatin1String(m_value) + QLatin1Char('"');
+ return;
+ }
+ m_numberMask = !m_mask.isEmpty() ? m_mask.toUInt(&ok, 0) : 0; // autodetect base
+ }
+
+ switch (m_type) {
+ case String:
+ m_pattern = makePattern(m_value);
+ m_pattern.squeeze();
+ if (!m_mask.isEmpty()) {
+ if (Q_UNLIKELY(m_mask.size() < 4 || !m_mask.startsWith("0x"))) {
+ m_type = Invalid;
+ if (errorString)
+ *errorString = QLatin1String("Invalid magic rule mask \"") + QLatin1String(m_mask) + QLatin1Char('"');
+ return;
+ }
+ const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
+ m_mask.constData() + 2, m_mask.size() - 2));
+ if (Q_UNLIKELY(tempMask.size() != m_pattern.size())) {
+ m_type = Invalid;
+ if (errorString)
+ *errorString = QLatin1String("Invalid magic rule mask size \"") + QLatin1String(m_mask) + QLatin1Char('"');
+ return;
+ }
+ m_mask = tempMask;
+ } else {
+ m_mask.fill(char(-1), m_pattern.size());
+ }
+ m_mask.squeeze();
+ m_matchFunction = &MimeMagicRule::matchString;
+ break;
+ case RegExp:
+ m_regexp.setPatternOptions(QRegularExpression::MultilineOption
+ | QRegularExpression::DotMatchesEverythingOption);
+ m_regexp.setPattern(QString::fromLatin1(m_value));
+ if (!m_regexp.isValid()) {
+ m_type = Invalid;
+ if (errorString)
+ *errorString = QString::fromLatin1("Invalid magic rule regexp value \"%1\"")
+ .arg(QString::fromLatin1(m_value));
+ return;
+ }
+ m_matchFunction = &MimeMagicRule::matchRegExp;
+ break;
+ case Byte:
+ if (m_number <= quint8(-1)) {
+ if (m_numberMask == 0)
+ m_numberMask = quint8(-1);
+ m_matchFunction = &MimeMagicRule::matchNumber<quint8>;
+ }
+ break;
+ case Big16:
+ case Little16:
+ if (m_number <= quint16(-1)) {
+ m_number = m_type == Little16 ? qFromLittleEndian<quint16>(m_number) : qFromBigEndian<quint16>(m_number);
+ if (m_numberMask != 0)
+ m_numberMask = m_type == Little16 ? qFromLittleEndian<quint16>(m_numberMask) : qFromBigEndian<quint16>(m_numberMask);
+ }
+ Q_FALLTHROUGH();
+ case Host16:
+ if (m_number <= quint16(-1)) {
+ if (m_numberMask == 0)
+ m_numberMask = quint16(-1);
+ m_matchFunction = &MimeMagicRule::matchNumber<quint16>;
+ }
+ break;
+ case Big32:
+ case Little32:
+ m_number = m_type == Little32 ? qFromLittleEndian<quint32>(m_number) : qFromBigEndian<quint32>(m_number);
+ if (m_numberMask != 0)
+ m_numberMask = m_type == Little32 ? qFromLittleEndian<quint32>(m_numberMask) : qFromBigEndian<quint32>(m_numberMask);
+ Q_FALLTHROUGH();
+ case Host32:
+ if (m_numberMask == 0)
+ m_numberMask = quint32(-1);
+ m_matchFunction = &MimeMagicRule::matchNumber<quint32>;
+ break;
+ default:
+ break;
+ }
+}
+
+QByteArray MimeMagicRule::mask() const
+{
+ QByteArray result = m_mask;
+ if (m_type == String) {
+ // restore '0x'
+ result = "0x" + result.toHex();
+ }
+ return result;
+}
+
+bool MimeMagicRule::matches(const QByteArray &data) const
+{
+ const bool ok = m_matchFunction && (this->*m_matchFunction)(data);
+ if (!ok)
+ return false;
+
+ // No submatch? Then we are done.
+ if (m_subMatches.isEmpty())
+ return true;
+
+ //qDebug() << "Checking" << m_subMatches.count() << "sub-rules";
+ // Check that one of the submatches matches too
+ for ( QList<MimeMagicRule>::const_iterator it = m_subMatches.begin(), end = m_subMatches.end() ;
+ it != end ; ++it ) {
+ if ((*it).matches(data)) {
+ // One of the hierarchies matched -> mimetype recognized.
+ return true;
+ }
+ }
+ return false;
+
+
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimemagicrule_p.h b/src/libs/utils/mimetypes2/mimemagicrule_p.h
new file mode 100644
index 00000000000..8aa48fd51ee
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimemagicrule_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <utils/utils_global.h>
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qregularexpression.h>
+#include <QtCore/qscopedpointer.h>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT MimeMagicRule
+{
+public:
+ enum Type {
+ Invalid = 0,
+ String,
+ RegExp,
+ Host16,
+ Host32,
+ Big16,
+ Big32,
+ Little16,
+ Little32,
+ Byte
+ };
+
+ MimeMagicRule(const QString &typeStr, const QByteArray &value, const QString &offsets,
+ const QByteArray &mask, QString *errorString);
+ // added for Qt Creator
+ MimeMagicRule(const Type &type, const QByteArray &value, int startPos, int endPos,
+ const QByteArray &mask = {}, QString *errorString = nullptr);
+
+ void swap(MimeMagicRule &other) noexcept
+ {
+ qSwap(m_type, other.m_type);
+ qSwap(m_value, other.m_value);
+ qSwap(m_startPos, other.m_startPos);
+ qSwap(m_endPos, other.m_endPos);
+ qSwap(m_mask, other.m_mask);
+ qSwap(m_pattern, other.m_pattern);
+ qSwap(m_number, other.m_number);
+ qSwap(m_numberMask, other.m_numberMask);
+ qSwap(m_matchFunction, other.m_matchFunction);
+ }
+
+ bool operator==(const MimeMagicRule &other) const;
+
+ Type type() const { return m_type; }
+ QByteArray value() const { return m_value; }
+ int startPos() const { return m_startPos; }
+ int endPos() const { return m_endPos; }
+ QByteArray mask() const;
+
+ bool isValid() const { return m_matchFunction != nullptr; }
+
+ bool matches(const QByteArray &data) const;
+
+ QList<MimeMagicRule> m_subMatches;
+
+ static Type type(const QByteArray &type);
+ static QByteArray typeName(Type type);
+
+ static bool matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength, int valueLength, const char *valueData, const char *mask);
+
+private:
+ // added for Qt Creator
+ void init(QString *errorString);
+
+ Type m_type;
+ QByteArray m_value;
+ int m_startPos;
+ int m_endPos;
+ QByteArray m_mask;
+
+ QRegularExpression m_regexp;
+ QByteArray m_pattern;
+ quint32 m_number;
+ quint32 m_numberMask;
+
+ typedef bool (MimeMagicRule::*MatchFunction)(const QByteArray &data) const;
+ MatchFunction m_matchFunction;
+
+private:
+ // match functions
+ bool matchString(const QByteArray &data) const;
+ template <typename T>
+ bool matchNumber(const QByteArray &data) const;
+ bool matchRegExp(const QByteArray &data) const;
+};
+
+} // namespace Utils
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_SHARED(Utils::MimeMagicRule)
+QT_END_NAMESPACE
diff --git a/src/libs/utils/mimetypes2/mimemagicrulematcher.cpp b/src/libs/utils/mimetypes2/mimemagicrulematcher.cpp
new file mode 100644
index 00000000000..a624efefa2f
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimemagicrulematcher.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mimemagicrulematcher_p.h"
+
+#include "mimetype_p.h"
+
+namespace Utils {
+
+/*!
+ \internal
+ \class MimeMagicRuleMatcher
+ \inmodule QtCore
+
+ \brief The MimeMagicRuleMatcher class checks a number of rules based on operator "or".
+
+ It is used for rules parsed from XML files.
+
+ \sa MimeType, MimeDatabase, MagicRule, MagicStringRule, MagicByteRule, GlobPattern
+ \sa MimeTypeParserBase, MimeTypeParser
+*/
+
+MimeMagicRuleMatcher::MimeMagicRuleMatcher(const QString &mime, unsigned thePriority) :
+ m_list(),
+ m_priority(thePriority),
+ m_mimetype(mime)
+{
+}
+
+bool MimeMagicRuleMatcher::operator==(const MimeMagicRuleMatcher &other) const
+{
+ return m_list == other.m_list &&
+ m_priority == other.m_priority;
+}
+
+void MimeMagicRuleMatcher::addRule(const MimeMagicRule &rule)
+{
+ m_list.append(rule);
+}
+
+void MimeMagicRuleMatcher::addRules(const QList<MimeMagicRule> &rules)
+{
+ m_list.append(rules);
+}
+
+QList<MimeMagicRule> MimeMagicRuleMatcher::magicRules() const
+{
+ return m_list;
+}
+
+// Check for a match on contents of a file
+bool MimeMagicRuleMatcher::matches(const QByteArray &data) const
+{
+ for (const MimeMagicRule &magicRule : m_list) {
+ if (magicRule.matches(data))
+ return true;
+ }
+
+ return false;
+}
+
+// Return a priority value from 1..100
+unsigned MimeMagicRuleMatcher::priority() const
+{
+ return m_priority;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimemagicrulematcher_p.h b/src/libs/utils/mimetypes2/mimemagicrulematcher_p.h
new file mode 100644
index 00000000000..4a4cd1f67f6
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimemagicrulematcher_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "mimemagicrule_p.h"
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qstring.h>
+
+namespace Utils {
+
+class MimeMagicRuleMatcher
+{
+public:
+ explicit MimeMagicRuleMatcher(const QString &mime, unsigned priority = 65535);
+
+ void swap(MimeMagicRuleMatcher &other) noexcept
+ {
+ qSwap(m_list, other.m_list);
+ qSwap(m_priority, other.m_priority);
+ qSwap(m_mimetype, other.m_mimetype);
+ }
+
+ bool operator==(const MimeMagicRuleMatcher &other) const;
+
+ void addRule(const MimeMagicRule &rule);
+ void addRules(const QList<MimeMagicRule> &rules);
+ QList<MimeMagicRule> magicRules() const;
+
+ bool matches(const QByteArray &data) const;
+
+ unsigned priority() const;
+
+ QString mimetype() const { return m_mimetype; }
+
+private:
+ QList<MimeMagicRule> m_list;
+ unsigned m_priority;
+ QString m_mimetype;
+};
+
+} // namespace Utils
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_SHARED(Utils::MimeMagicRuleMatcher)
+QT_END_NAMESPACE
diff --git a/src/libs/utils/mimetypes2/mimeprovider.cpp b/src/libs/utils/mimetypes2/mimeprovider.cpp
new file mode 100644
index 00000000000..8b8b2a353eb
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimeprovider.cpp
@@ -0,0 +1,1011 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Copyright (C) 2019 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mimeprovider_p.h"
+
+#include "mimetypeparser_p.h"
+#include "mimemagicrulematcher_p.h"
+
+#include <qstandardpaths.h>
+#include <QXmlStreamReader>
+#include <QBuffer>
+#include <QDir>
+#include <QFile>
+#include <QByteArrayMatcher>
+#include <QDebug>
+#include <QDateTime>
+#include <QtEndian>
+
+#if 0 // QT_CONFIG(mimetype_database)
+# if defined(Q_CC_MSVC)
+# pragma section(".qtmimedatabase", read, shared)
+__declspec(allocate(".qtmimedatabase")) __declspec(align(4096))
+# elif defined(Q_OS_DARWIN)
+__attribute__((section("__TEXT,.qtmimedatabase"), aligned(4096)))
+# elif (defined(Q_OF_ELF) || defined(Q_OS_WIN)) && defined(Q_CC_GNU)
+__attribute__((section(".qtmimedatabase"), aligned(4096)))
+# endif
+
+# include "qmimeprovider_database.cpp"
+
+# ifdef MIME_DATABASE_IS_ZSTD
+# if !QT_CONFIG(zstd)
+# error "MIME database is zstd but no support compiled in!"
+# endif
+# include <zstd.h>
+# endif
+# ifdef MIME_DATABASE_IS_GZIP
+# ifdef QT_NO_COMPRESS
+# error "MIME database is zlib but no support compiled in!"
+# endif
+# define ZLIB_CONST
+# include <zconf.h>
+# include <zlib.h>
+# endif
+#endif
+
+namespace Utils {
+
+MimeProviderBase::MimeProviderBase(MimeDatabasePrivate *db, const QString &directory)
+ : m_db(db), m_directory(directory)
+{
+}
+
+
+MimeBinaryProvider::MimeBinaryProvider(MimeDatabasePrivate *db, const QString &directory)
+ : MimeProviderBase(db, directory), m_mimetypeListLoaded(false)
+{
+ ensureLoaded();
+}
+
+struct MimeBinaryProvider::CacheFile
+{
+ CacheFile(const QString &fileName);
+ ~CacheFile();
+
+ bool isValid() const { return m_valid; }
+ inline quint16 getUint16(int offset) const
+ {
+ return qFromBigEndian(*reinterpret_cast<quint16 *>(data + offset));
+ }
+ inline quint32 getUint32(int offset) const
+ {
+ return qFromBigEndian(*reinterpret_cast<quint32 *>(data + offset));
+ }
+ inline const char *getCharStar(int offset) const
+ {
+ return reinterpret_cast<const char *>(data + offset);
+ }
+ bool load();
+ bool reload();
+
+ QFile file;
+ uchar *data;
+ QDateTime m_mtime;
+ bool m_valid;
+};
+
+MimeBinaryProvider::CacheFile::CacheFile(const QString &fileName)
+ : file(fileName), m_valid(false)
+{
+ load();
+}
+
+MimeBinaryProvider::CacheFile::~CacheFile()
+{
+}
+
+bool MimeBinaryProvider::CacheFile::load()
+{
+ if (!file.open(QIODevice::ReadOnly))
+ return false;
+ data = file.map(0, file.size());
+ if (data) {
+ const int major = getUint16(0);
+ const int minor = getUint16(2);
+ m_valid = (major == 1 && minor >= 1 && minor <= 2);
+ }
+ m_mtime = QFileInfo(file).lastModified();
+ return m_valid;
+}
+
+bool MimeBinaryProvider::CacheFile::reload()
+{
+ m_valid = false;
+ if (file.isOpen()) {
+ file.close();
+ }
+ data = nullptr;
+ return load();
+}
+
+MimeBinaryProvider::~MimeBinaryProvider()
+{
+ delete m_cacheFile;
+}
+
+bool MimeBinaryProvider::isValid()
+{
+ return m_cacheFile != nullptr;
+}
+
+bool MimeBinaryProvider::isInternalDatabase() const
+{
+ return false;
+}
+
+// Position of the "list offsets" values, at the beginning of the mime.cache file
+enum {
+ PosAliasListOffset = 4,
+ PosParentListOffset = 8,
+ PosLiteralListOffset = 12,
+ PosReverseSuffixTreeOffset = 16,
+ PosGlobListOffset = 20,
+ PosMagicListOffset = 24,
+ // PosNamespaceListOffset = 28,
+ PosIconsListOffset = 32,
+ PosGenericIconsListOffset = 36
+};
+
+bool MimeBinaryProvider::checkCacheChanged()
+{
+ QFileInfo fileInfo(m_cacheFile->file);
+ if (fileInfo.lastModified() > m_cacheFile->m_mtime) {
+ // Deletion can't happen by just running update-mime-database.
+ // But the user could use rm -rf :-)
+ m_cacheFile->reload(); // will mark itself as invalid on failure
+ return true;
+ }
+ return false;
+}
+
+void MimeBinaryProvider::ensureLoaded()
+{
+ if (!m_cacheFile) {
+ const QString cacheFileName = m_directory + QLatin1String("/mime.cache");
+ m_cacheFile = new CacheFile(cacheFileName);
+ m_mimetypeListLoaded = false;
+ m_mimetypeExtra.clear();
+ } else {
+ if (checkCacheChanged()) {
+ m_mimetypeListLoaded = false;
+ m_mimetypeExtra.clear();
+ } else {
+ return; // nothing to do
+ }
+ }
+ if (!m_cacheFile->isValid()) { // verify existence and version
+ delete m_cacheFile;
+ m_cacheFile = nullptr;
+ }
+}
+
+static MimeType mimeTypeForNameUnchecked(const QString &name)
+{
+ MimeTypePrivate data;
+ data.name = name;
+ data.fromCache = true;
+ // The rest is retrieved on demand.
+ // comment and globPatterns: in loadMimeTypePrivate
+ // iconName: in loadIcon
+ // genericIconName: in loadGenericIcon
+ return MimeType(data);
+}
+
+MimeType MimeBinaryProvider::mimeTypeForName(const QString &name)
+{
+ if (!m_mimetypeListLoaded)
+ loadMimeTypeList();
+ if (!m_mimetypeNames.contains(name))
+ return MimeType(); // unknown mimetype
+ return mimeTypeForNameUnchecked(name);
+}
+
+void MimeBinaryProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result)
+{
+ // TODO checkedMimeTypes
+ if (fileName.isEmpty())
+ return;
+ Q_ASSERT(m_cacheFile);
+ const QString lowerFileName = fileName.toLower();
+ // Check literals (e.g. "Makefile")
+ matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), fileName);
+ // Check the very common *.txt cases with the suffix tree
+ if (result.m_matchingMimeTypes.isEmpty()) {
+ const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
+ const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
+ const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
+ matchSuffixTree(result,
+ m_cacheFile,
+ numRoots,
+ firstRootOffset,
+ lowerFileName,
+ lowerFileName.length() - 1,
+ false);
+ if (result.m_matchingMimeTypes.isEmpty())
+ matchSuffixTree(result,
+ m_cacheFile,
+ numRoots,
+ firstRootOffset,
+ fileName,
+ fileName.length() - 1,
+ true);
+ }
+ // Check complex globs (e.g. "callgrind.out[0-9]*" or "README*")
+ if (result.m_matchingMimeTypes.isEmpty())
+ matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName);
+}
+
+void MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result,
+ CacheFile *cacheFile,
+ int off,
+ const QString &fileName)
+{
+ const int numGlobs = cacheFile->getUint32(off);
+ //qDebug() << "Loading" << numGlobs << "globs from" << cacheFile->file.fileName() << "at offset" << cacheFile->globListOffset;
+ for (int i = 0; i < numGlobs; ++i) {
+ const int globOffset = cacheFile->getUint32(off + 4 + 12 * i);
+ const int mimeTypeOffset = cacheFile->getUint32(off + 4 + 12 * i + 4);
+ const int flagsAndWeight = cacheFile->getUint32(off + 4 + 12 * i + 8);
+ const int weight = flagsAndWeight & 0xff;
+ const bool caseSensitive = flagsAndWeight & 0x100;
+ const Qt::CaseSensitivity qtCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ const QString pattern = QLatin1String(cacheFile->getCharStar(globOffset));
+
+ const char *mimeType = cacheFile->getCharStar(mimeTypeOffset);
+ if (m_overriddenMimeTypes.contains(QLatin1String(mimeType)))
+ continue;
+ //qDebug() << pattern << mimeType << weight << caseSensitive;
+ MimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive);
+
+ if (glob.matchFileName(fileName))
+ result.addMatch(QLatin1String(mimeType), weight, pattern);
+ }
+}
+
+bool MimeBinaryProvider::matchSuffixTree(MimeGlobMatchResult &result,
+ MimeBinaryProvider::CacheFile *cacheFile,
+ int numEntries,
+ int firstOffset,
+ const QString &fileName,
+ int charPos,
+ bool caseSensitiveCheck)
+{
+ QChar fileChar = fileName[charPos];
+ int min = 0;
+ int max = numEntries - 1;
+ while (min <= max) {
+ const int mid = (min + max) / 2;
+ const int off = firstOffset + 12 * mid;
+ const QChar ch = char16_t(cacheFile->getUint32(off));
+ if (ch < fileChar)
+ min = mid + 1;
+ else if (ch > fileChar)
+ max = mid - 1;
+ else {
+ --charPos;
+ int numChildren = cacheFile->getUint32(off + 4);
+ int childrenOffset = cacheFile->getUint32(off + 8);
+ bool success = false;
+ if (charPos > 0)
+ success = matchSuffixTree(result,
+ cacheFile,
+ numChildren,
+ childrenOffset,
+ fileName,
+ charPos,
+ caseSensitiveCheck);
+ if (!success) {
+ for (int i = 0; i < numChildren; ++i) {
+ const int childOff = childrenOffset + 12 * i;
+ const int mch = cacheFile->getUint32(childOff);
+ if (mch != 0)
+ break;
+ const int mimeTypeOffset = cacheFile->getUint32(childOff + 4);
+ const char *mimeType = cacheFile->getCharStar(mimeTypeOffset);
+ if (m_overriddenMimeTypes.contains(QLatin1String(mimeType)))
+ continue;
+ const int flagsAndWeight = cacheFile->getUint32(childOff + 8);
+ const int weight = flagsAndWeight & 0xff;
+ const bool caseSensitive = flagsAndWeight & 0x100;
+ if (caseSensitiveCheck || !caseSensitive) {
+ result.addMatch(QLatin1String(mimeType), weight,
+ QLatin1Char('*') + QStringView{fileName}.mid(charPos + 1), fileName.size() - charPos - 2);
+ success = true;
+ }
+ }
+ }
+ return success;
+ }
+ }
+ return false;
+}
+
+bool MimeBinaryProvider::matchMagicRule(MimeBinaryProvider::CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data)
+{
+ const char *dataPtr = data.constData();
+ const int dataSize = data.size();
+ for (int matchlet = 0; matchlet < numMatchlets; ++matchlet) {
+ const int off = firstOffset + matchlet * 32;
+ const int rangeStart = cacheFile->getUint32(off);
+ const int rangeLength = cacheFile->getUint32(off + 4);
+ //const int wordSize = cacheFile->getUint32(off + 8);
+ const int valueLength = cacheFile->getUint32(off + 12);
+ const int valueOffset = cacheFile->getUint32(off + 16);
+ const int maskOffset = cacheFile->getUint32(off + 20);
+ const char *mask = maskOffset ? cacheFile->getCharStar(maskOffset) : nullptr;
+
+ if (!MimeMagicRule::matchSubstring(dataPtr, dataSize, rangeStart, rangeLength, valueLength, cacheFile->getCharStar(valueOffset), mask))
+ continue;
+
+ const int numChildren = cacheFile->getUint32(off + 24);
+ const int firstChildOffset = cacheFile->getUint32(off + 28);
+ if (numChildren == 0) // No submatch? Then we are done.
+ return true;
+ // Check that one of the submatches matches too
+ if (matchMagicRule(cacheFile, numChildren, firstChildOffset, data))
+ return true;
+ }
+ return false;
+}
+
+void MimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate)
+{
+ const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset);
+ const int numMatches = m_cacheFile->getUint32(magicListOffset);
+ //const int maxExtent = cacheFile->getUint32(magicListOffset + 4);
+ const int firstMatchOffset = m_cacheFile->getUint32(magicListOffset + 8);
+
+ for (int i = 0; i < numMatches; ++i) {
+ const int off = firstMatchOffset + i * 16;
+ const int numMatchlets = m_cacheFile->getUint32(off + 8);
+ const int firstMatchletOffset = m_cacheFile->getUint32(off + 12);
+ if (matchMagicRule(m_cacheFile, numMatchlets, firstMatchletOffset, data)) {
+ const int mimeTypeOffset = m_cacheFile->getUint32(off + 4);
+ const char *mimeType = m_cacheFile->getCharStar(mimeTypeOffset);
+ if (m_overriddenMimeTypes.contains(QLatin1String(mimeType)))
+ continue;
+ *accuracyPtr = m_cacheFile->getUint32(off);
+ // Return the first match. We have no rules for conflicting magic data...
+ // (mime.cache itself is sorted, but what about local overrides with a lower prio?)
+ candidate = mimeTypeForNameUnchecked(QLatin1String(mimeType));
+ return;
+ }
+ }
+}
+
+void MimeBinaryProvider::addParents(const QString &mime, QStringList &result)
+{
+ const QByteArray mimeStr = mime.toLatin1();
+ const int parentListOffset = m_cacheFile->getUint32(PosParentListOffset);
+ const int numEntries = m_cacheFile->getUint32(parentListOffset);
+
+ int begin = 0;
+ int end = numEntries - 1;
+ while (begin <= end) {
+ const int medium = (begin + end) / 2;
+ const int off = parentListOffset + 4 + 8 * medium;
+ const int mimeOffset = m_cacheFile->getUint32(off);
+ const char *aMime = m_cacheFile->getCharStar(mimeOffset);
+ const int cmp = qstrcmp(aMime, mimeStr);
+ if (cmp < 0) {
+ begin = medium + 1;
+ } else if (cmp > 0) {
+ end = medium - 1;
+ } else {
+ const int parentsOffset = m_cacheFile->getUint32(off + 4);
+ const int numParents = m_cacheFile->getUint32(parentsOffset);
+ for (int i = 0; i < numParents; ++i) {
+ const int parentOffset = m_cacheFile->getUint32(parentsOffset + 4 + 4 * i);
+ const char *aParent = m_cacheFile->getCharStar(parentOffset);
+ const QString strParent = QString::fromLatin1(aParent);
+ if (!result.contains(strParent))
+ result.append(strParent);
+ }
+ break;
+ }
+ }
+}
+
+QString MimeBinaryProvider::resolveAlias(const QString &name)
+{
+ const QByteArray input = name.toLatin1();
+ const int aliasListOffset = m_cacheFile->getUint32(PosAliasListOffset);
+ const int numEntries = m_cacheFile->getUint32(aliasListOffset);
+ int begin = 0;
+ int end = numEntries - 1;
+ while (begin <= end) {
+ const int medium = (begin + end) / 2;
+ const int off = aliasListOffset + 4 + 8 * medium;
+ const int aliasOffset = m_cacheFile->getUint32(off);
+ const char *alias = m_cacheFile->getCharStar(aliasOffset);
+ const int cmp = qstrcmp(alias, input);
+ if (cmp < 0) {
+ begin = medium + 1;
+ } else if (cmp > 0) {
+ end = medium - 1;
+ } else {
+ const int mimeOffset = m_cacheFile->getUint32(off + 4);
+ const char *mimeType = m_cacheFile->getCharStar(mimeOffset);
+ return QLatin1String(mimeType);
+ }
+ }
+ return QString();
+}
+
+void MimeBinaryProvider::addAliases(const QString &name, QStringList &result)
+{
+ const QByteArray input = name.toLatin1();
+ const int aliasListOffset = m_cacheFile->getUint32(PosAliasListOffset);
+ const int numEntries = m_cacheFile->getUint32(aliasListOffset);
+ for (int pos = 0; pos < numEntries; ++pos) {
+ const int off = aliasListOffset + 4 + 8 * pos;
+ const int mimeOffset = m_cacheFile->getUint32(off + 4);
+ const char *mimeType = m_cacheFile->getCharStar(mimeOffset);
+
+ if (input == mimeType) {
+ const int aliasOffset = m_cacheFile->getUint32(off);
+ const char *alias = m_cacheFile->getCharStar(aliasOffset);
+ const QString strAlias = QString::fromLatin1(alias);
+ if (!result.contains(strAlias))
+ result.append(strAlias);
+ }
+ }
+}
+
+void MimeBinaryProvider::loadMimeTypeList()
+{
+ if (!m_mimetypeListLoaded) {
+ m_mimetypeListLoaded = true;
+ m_mimetypeNames.clear();
+ // Unfortunately mime.cache doesn't have a full list of all mimetypes.
+ // So we have to parse the plain-text files called "types".
+ QFile file(m_directory + QStringLiteral("/types"));
+ if (file.open(QIODevice::ReadOnly)) {
+ while (!file.atEnd()) {
+ QByteArray line = file.readLine();
+ if (line.endsWith('\n'))
+ line.chop(1);
+ m_mimetypeNames.insert(QString::fromLatin1(line));
+ }
+ }
+ }
+}
+
+void MimeBinaryProvider::addAllMimeTypes(QList<MimeType> &result)
+{
+ loadMimeTypeList();
+ if (result.isEmpty()) {
+ result.reserve(m_mimetypeNames.count());
+ for (const QString &name : qAsConst(m_mimetypeNames))
+ result.append(mimeTypeForNameUnchecked(name));
+ } else {
+ for (const QString &name : qAsConst(m_mimetypeNames))
+ if (std::find_if(result.constBegin(), result.constEnd(), [name](const MimeType &mime) -> bool { return mime.name() == name; })
+ == result.constEnd())
+ result.append(mimeTypeForNameUnchecked(name));
+ }
+}
+
+bool MimeBinaryProvider::loadMimeTypePrivate(MimeTypePrivate &data)
+{
+#ifdef QT_NO_XMLSTREAMREADER
+ Q_UNUSED(data);
+ qWarning("Cannot load mime type since QXmlStreamReader is not available.");
+ return false;
+#else
+ if (data.loaded)
+ return true;
+
+ auto it = m_mimetypeExtra.constFind(data.name);
+ if (it == m_mimetypeExtra.constEnd()) {
+ // load comment and globPatterns
+
+ // shared-mime-info since 1.3 lowercases the xml files
+ QString mimeFile = m_directory + QLatin1Char('/') + data.name.toLower() + QLatin1String(".xml");
+ if (!QFile::exists(mimeFile))
+ mimeFile = m_directory + QLatin1Char('/') + data.name + QLatin1String(".xml"); // pre-1.3
+
+ QFile qfile(mimeFile);
+ if (!qfile.open(QFile::ReadOnly))
+ return false;
+
+ auto insertIt = m_mimetypeExtra.insert(data.name, MimeTypeExtra{});
+ it = insertIt;
+ MimeTypeExtra &extra = insertIt.value();
+ QString mainPattern;
+
+ QXmlStreamReader xml(&qfile);
+ if (xml.readNextStartElement()) {
+ if (xml.name() != QLatin1String("mime-type")) {
+ return false;
+ }
+ const auto name = xml.attributes().value(QLatin1String("type"));
+ if (name.isEmpty())
+ return false;
+ if (name.compare(data.name, Qt::CaseInsensitive))
+ qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << data.name;
+
+ while (xml.readNextStartElement()) {
+ const auto tag = xml.name();
+ if (tag == QLatin1String("comment")) {
+ QString lang = xml.attributes().value(QLatin1String("xml:lang")).toString();
+ const QString text = xml.readElementText();
+ if (lang.isEmpty()) {
+ lang = QLatin1String("default"); // no locale attribute provided, treat it as default.
+ }
+ extra.localeComments.insert(lang, text);
+ continue; // we called readElementText, so we're at the EndElement already.
+ } else if (tag == QLatin1String("glob-deleteall")) { // as written out by shared-mime-info >= 0.70
+ extra.globPatterns.clear();
+ mainPattern.clear();
+ } else if (tag == QLatin1String("glob")) { // as written out by shared-mime-info >= 0.70
+ const QString pattern = xml.attributes().value(QLatin1String("pattern")).toString();
+ if (mainPattern.isEmpty() && pattern.startsWith(QLatin1Char('*'))) {
+ mainPattern = pattern;
+ }
+ if (!extra.globPatterns.contains(pattern))
+ extra.globPatterns.append(pattern);
+ }
+ xml.skipCurrentElement();
+ }
+ Q_ASSERT(xml.name() == QLatin1String("mime-type"));
+ }
+
+ // Let's assume that shared-mime-info is at least version 0.70
+ // Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file.
+ if (!mainPattern.isEmpty() &&
+ (extra.globPatterns.isEmpty() || extra.globPatterns.constFirst() != mainPattern)) {
+ // ensure it's first in the list of patterns
+ extra.globPatterns.removeAll(mainPattern);
+ extra.globPatterns.prepend(mainPattern);
+ }
+ }
+ const MimeTypeExtra &e = it.value();
+ data.localeComments = e.localeComments;
+ data.globPatterns = e.globPatterns;
+ return true;
+#endif //QT_NO_XMLSTREAMREADER
+}
+
+// Binary search in the icons or generic-icons list
+QLatin1String MimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime)
+{
+ const int iconsListOffset = cacheFile->getUint32(posListOffset);
+ const int numIcons = cacheFile->getUint32(iconsListOffset);
+ int begin = 0;
+ int end = numIcons - 1;
+ while (begin <= end) {
+ const int medium = (begin + end) / 2;
+ const int off = iconsListOffset + 4 + 8 * medium;
+ const int mimeOffset = cacheFile->getUint32(off);
+ const char *mime = cacheFile->getCharStar(mimeOffset);
+ const int cmp = qstrcmp(mime, inputMime);
+ if (cmp < 0)
+ begin = medium + 1;
+ else if (cmp > 0)
+ end = medium - 1;
+ else {
+ const int iconOffset = cacheFile->getUint32(off + 4);
+ return QLatin1String(cacheFile->getCharStar(iconOffset));
+ }
+ }
+ return QLatin1String();
+}
+
+void MimeBinaryProvider::loadIcon(MimeTypePrivate &data)
+{
+ const QByteArray inputMime = data.name.toLatin1();
+ const QLatin1String icon = iconForMime(m_cacheFile, PosIconsListOffset, inputMime);
+ if (!icon.isEmpty()) {
+ data.iconName = icon;
+ }
+}
+
+void MimeBinaryProvider::loadGenericIcon(MimeTypePrivate &data)
+{
+ const QByteArray inputMime = data.name.toLatin1();
+ const QLatin1String icon = iconForMime(m_cacheFile, PosGenericIconsListOffset, inputMime);
+ if (!icon.isEmpty()) {
+ data.genericIconName = icon;
+ }
+}
+
+////
+
+#if 0
+#if QT_CONFIG(mimetype_database)
+static QString internalMimeFileName()
+{
+ return QStringLiteral("<internal MIME data>");
+}
+
+QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
+ : QMimeProviderBase(db, internalMimeFileName())
+{
+ static_assert(sizeof(mimetype_database), "Bundled MIME database is empty");
+ static_assert(sizeof(mimetype_database) <= MimeTypeDatabaseOriginalSize,
+ "Compressed MIME database is larger than the original size");
+ static_assert(MimeTypeDatabaseOriginalSize <= 16*1024*1024,
+ "Bundled MIME database is too big");
+ const char *data = reinterpret_cast<const char *>(mimetype_database);
+ qsizetype size = MimeTypeDatabaseOriginalSize;
+
+#ifdef MIME_DATABASE_IS_ZSTD
+ // uncompress with libzstd
+ std::unique_ptr<char []> uncompressed(new char[size]);
+ size = ZSTD_decompress(uncompressed.get(), size, mimetype_database, sizeof(mimetype_database));
+ Q_ASSERT(!ZSTD_isError(size));
+ data = uncompressed.get();
+#elif defined(MIME_DATABASE_IS_GZIP)
+ std::unique_ptr<char []> uncompressed(new char[size]);
+ z_stream zs = {};
+ zs.next_in = const_cast<Bytef *>(mimetype_database);
+ zs.avail_in = sizeof(mimetype_database);
+ zs.next_out = reinterpret_cast<Bytef *>(uncompressed.get());
+ zs.avail_out = size;
+
+ int res = inflateInit2(&zs, MAX_WBITS | 32);
+ Q_ASSERT(res == Z_OK);
+ res = inflate(&zs, Z_FINISH);
+ Q_ASSERT(res == Z_STREAM_END);
+ res = inflateEnd(&zs);
+ Q_ASSERT(res == Z_OK);
+
+ data = uncompressed.get();
+ size = zs.total_out;
+#endif
+
+ load(data, size);
+}
+#else // !QT_CONFIG(mimetype_database)
+// never called in release mode, but some debug builds may need
+// this to be defined.
+MimeXMLProvider::MimeXMLProvider(MimeDatabasePrivate *db, InternalDatabaseEnum)
+ : MimeProviderBase(db, QString())
+{
+ Q_UNREACHABLE();
+}
+#endif // QT_CONFIG(mimetype_database)
+#endif
+
+static const char internalMimeFileName[] = ":/utils/mimetypes/freedesktop.org.xml";
+
+// for Qt Creator: internal database from resources
+MimeXMLProvider::MimeXMLProvider(MimeDatabasePrivate *db, InternalDatabaseEnum)
+ : MimeProviderBase(db, internalMimeFileName)
+{
+ load(internalMimeFileName);
+}
+
+MimeXMLProvider::MimeXMLProvider(MimeDatabasePrivate *db, const QString &directory)
+ : MimeProviderBase(db, directory)
+{
+ ensureLoaded();
+}
+
+MimeXMLProvider::~MimeXMLProvider()
+{
+}
+
+bool MimeXMLProvider::isValid()
+{
+ // If you change this method, adjust the logic in MimeDatabasePrivate::loadProviders,
+ // which assumes isValid==false is only possible in MimeBinaryProvider.
+ return true;
+}
+
+bool MimeXMLProvider::isInternalDatabase() const
+{
+#if 1 //QT_CONFIG(mimetype_database)
+ return m_directory == internalMimeFileName;
+#else
+ return false;
+#endif
+}
+
+MimeType MimeXMLProvider::mimeTypeForName(const QString &name)
+{
+ return m_nameMimeTypeMap.value(name);
+}
+
+void MimeXMLProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result)
+{
+ m_mimeTypeGlobs.matchingGlobs(fileName, result, m_overriddenMimeTypes);
+}
+
+void MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate)
+{
+ QString candidateName;
+ bool foundOne = false;
+ for (const MimeMagicRuleMatcher &matcher : qAsConst(m_magicMatchers)) {
+ if (m_overriddenMimeTypes.contains(matcher.mimetype()))
+ continue;
+ if (matcher.matches(data)) {
+ const int priority = matcher.priority();
+ if (priority > *accuracyPtr) {
+ *accuracyPtr = priority;
+ candidateName = matcher.mimetype();
+ foundOne = true;
+ }
+ }
+ }
+ if (foundOne)
+ candidate = mimeTypeForName(candidateName);
+}
+
+void MimeXMLProvider::ensureLoaded()
+{
+ QStringList allFiles;
+ const QString packageDir = m_directory + QStringLiteral("/packages");
+ QDir dir(packageDir);
+ const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
+ allFiles.reserve(files.count());
+ for (const QString &xmlFile : files)
+ allFiles.append(packageDir + QLatin1Char('/') + xmlFile);
+
+ if (m_allFiles == allFiles)
+ return;
+ m_allFiles = allFiles;
+
+ m_nameMimeTypeMap.clear();
+ m_aliases.clear();
+ m_parents.clear();
+ m_mimeTypeGlobs.clear();
+ m_magicMatchers.clear();
+
+ //qDebug() << "Loading" << m_allFiles;
+
+ for (const QString &file : qAsConst(allFiles))
+ load(file);
+}
+
+void MimeXMLProvider::load(const QString &fileName)
+{
+ QString errorMessage;
+ if (!load(fileName, &errorMessage))
+ qWarning("MimeDatabase: Error loading %ls\n%ls", qUtf16Printable(fileName), qUtf16Printable(errorMessage));
+}
+
+bool MimeXMLProvider::load(const QString &fileName, QString *errorMessage)
+{
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ if (errorMessage)
+ *errorMessage = QLatin1String("Cannot open ") + fileName + QLatin1String(": ") + file.errorString();
+ return false;
+ }
+
+ if (errorMessage)
+ errorMessage->clear();
+
+ MimeTypeParser parser(*this);
+ return parser.parse(&file, fileName, errorMessage);
+}
+
+#if 0 //QT_CONFIG(mimetype_database)
+void MimeXMLProvider::load(const char *data, qsizetype len)
+{
+ QBuffer buffer;
+ buffer.setData(QByteArray::fromRawData(data, len));
+ buffer.open(QIODevice::ReadOnly);
+ QString errorMessage;
+ MimeTypeParser parser(*this);
+ if (!parser.parse(&buffer, internalMimeFileName(), &errorMessage))
+ qWarning("MimeDatabase: Error loading internal MIME data\n%s", qPrintable(errorMessage));
+}
+#endif
+
+void MimeXMLProvider::addGlobPattern(const MimeGlobPattern &glob)
+{
+ m_mimeTypeGlobs.addGlob(glob);
+}
+
+void MimeXMLProvider::addMimeType(const MimeType &mt)
+{
+ Q_ASSERT(!mt.d.data()->fromCache);
+ m_nameMimeTypeMap.insert(mt.name(), mt);
+}
+
+void MimeXMLProvider::addParents(const QString &mime, QStringList &result)
+{
+ for (const QString &parent : m_parents.value(mime)) {
+ if (!result.contains(parent))
+ result.append(parent);
+ }
+}
+
+void MimeXMLProvider::addParent(const QString &child, const QString &parent)
+{
+ m_parents[child].append(parent);
+}
+
+void MimeXMLProvider::addAliases(const QString &name, QStringList &result)
+{
+ // Iterate through the whole hash. This method is rarely used.
+ for (auto it = m_aliases.constBegin(), end = m_aliases.constEnd() ; it != end ; ++it) {
+ if (it.value() == name) {
+ if (!result.contains(it.key()))
+ result.append(it.key());
+ }
+ }
+
+}
+
+QString MimeXMLProvider::resolveAlias(const QString &name)
+{
+ return m_aliases.value(name);
+}
+
+void MimeXMLProvider::addAlias(const QString &alias, const QString &name)
+{
+ m_aliases.insert(alias, name);
+}
+
+void MimeXMLProvider::addAllMimeTypes(QList<MimeType> &result)
+{
+ if (result.isEmpty()) { // fast path
+ result = m_nameMimeTypeMap.values();
+ } else {
+ for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd() ; it != end ; ++it) {
+ const QString newMime = it.key();
+ if (std::find_if(result.constBegin(), result.constEnd(), [newMime](const MimeType &mime) -> bool { return mime.name() == newMime; })
+ == result.constEnd())
+ result.append(it.value());
+ }
+ }
+}
+
+void MimeXMLProvider::addMagicMatcher(const MimeMagicRuleMatcher &matcher)
+{
+ m_magicMatchers.append(matcher);
+}
+
+// added for Qt Creator
+MimeXMLProvider::MimeXMLProvider(MimeDatabasePrivate *db,
+ const QString &directory,
+ const QByteArray &data)
+ : MimeProviderBase(db, directory)
+{
+ QString errorMessage;
+ MimeTypeParser parser(*this);
+ QByteArray bufferData(data);
+ QBuffer buffer(&bufferData);
+ if (!buffer.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning("MimeDatabase: Error creating buffer for data with ID %ls.",
+ qUtf16Printable(directory));
+ }
+ if (!parser.parse(&buffer, directory, &errorMessage)) {
+ qWarning("MimeDatabase: Error loading data for ID %ls\n%ls",
+ qUtf16Printable(directory),
+ qUtf16Printable(errorMessage));
+ }
+}
+
+bool MimeBinaryProvider::hasMimeTypeForName(const QString &name)
+{
+ loadMimeTypeList();
+ return m_mimetypeNames.contains(name);
+}
+
+QStringList MimeBinaryProvider::allMimeTypeNames()
+{
+ // similar to addAllMimeTypes
+ loadMimeTypeList();
+ return QList(m_mimetypeNames.cbegin(), m_mimetypeNames.cend());
+}
+
+bool MimeXMLProvider::hasMimeTypeForName(const QString &name)
+{
+ return m_nameMimeTypeMap.contains(name);
+}
+
+QStringList MimeXMLProvider::allMimeTypeNames()
+{
+ // similar to addAllMimeTypes
+ return m_nameMimeTypeMap.keys();
+}
+
+QMap<int, QList<MimeMagicRule>> MimeBinaryProvider::magicRulesForMimeType(const MimeType &mimeType) const
+{
+ Q_UNUSED(mimeType)
+ qWarning("Mimetypes: magicRulesForMimeType not implemented for binary provider");
+ return {};
+}
+
+void MimeBinaryProvider::setMagicRulesForMimeType(const MimeType &mimeType,
+ const QMap<int, QList<MimeMagicRule>> &rules)
+{
+ Q_UNUSED(mimeType)
+ Q_UNUSED(rules)
+ qWarning("Mimetypes: setMagicRulesForMimeType not implemented for binary provider");
+}
+
+void MimeBinaryProvider::setGlobPatternsForMimeType(const MimeType &mimeType,
+ const QStringList &patterns)
+{
+ Q_UNUSED(mimeType)
+ Q_UNUSED(patterns)
+ qWarning("Mimetypes: setGlobPatternsForMimeType not implemented for binary provider");
+}
+
+QMap<int, QList<MimeMagicRule>> MimeXMLProvider::magicRulesForMimeType(const MimeType &mimeType) const
+{
+ QMap<int, QList<MimeMagicRule>> result;
+ for (const MimeMagicRuleMatcher &matcher : m_magicMatchers) {
+ if (mimeType.name() == matcher.mimetype())
+ result[matcher.priority()].append(matcher.magicRules());
+ }
+ return result;
+}
+
+void MimeXMLProvider::setMagicRulesForMimeType(const MimeType &mimeType,
+ const QMap<int, QList<MimeMagicRule>> &rules)
+{
+ // remove previous rules
+ m_magicMatchers.erase(std::remove_if(m_magicMatchers.begin(),
+ m_magicMatchers.end(),
+ [mimeType](const MimeMagicRuleMatcher &matcher) {
+ return mimeType.name() == matcher.mimetype();
+ }),
+ m_magicMatchers.end());
+ // add new rules
+ for (auto it = rules.cbegin(); it != rules.cend(); ++it) {
+ MimeMagicRuleMatcher matcher(mimeType.name(), it.key() /*priority*/);
+ matcher.addRules(it.value());
+ addMagicMatcher(matcher);
+ }
+}
+
+void MimeXMLProvider::setGlobPatternsForMimeType(const MimeType &mimeType,
+ const QStringList &patterns)
+{
+ // remove all previous globs
+ m_mimeTypeGlobs.removeMimeType(mimeType.name());
+ // add new patterns as case-insensitive default-weight patterns
+ for (const QString &pattern : patterns)
+ addGlobPattern(MimeGlobPattern(pattern, mimeType.name()));
+ // the following is safe, because for XML provider mimetype private is always "loaded"
+ // (see comment in MimeDatabasePrivate::loadMimeTypePrivate)
+ mimeType.d->globPatterns = patterns;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimeprovider_p.h b/src/libs/utils/mimetypes2/mimeprovider_p.h
new file mode 100644
index 00000000000..31135fbfd0a
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimeprovider_p.h
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "mimedatabase_p.h"
+
+#include "mimeglobpattern_p.h"
+#include <QtCore/qdatetime.h>
+#include <QtCore/qset.h>
+
+namespace Utils {
+
+class MimeMagicRuleMatcher;
+
+class MimeProviderBase
+{
+public:
+ MimeProviderBase(MimeDatabasePrivate *db, const QString &directory);
+ virtual ~MimeProviderBase() {}
+
+ virtual bool isValid() = 0;
+ virtual bool isInternalDatabase() const = 0;
+ virtual MimeType mimeTypeForName(const QString &name) = 0;
+ virtual void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) = 0;
+ virtual void addParents(const QString &mime, QStringList &result) = 0;
+ virtual QString resolveAlias(const QString &name) = 0;
+ virtual void addAliases(const QString &name, QStringList &result) = 0;
+ virtual void findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate) = 0;
+ virtual void addAllMimeTypes(QList<MimeType> &result) = 0;
+ virtual bool loadMimeTypePrivate(MimeTypePrivate &) { return false; }
+ virtual void loadIcon(MimeTypePrivate &) {}
+ virtual void loadGenericIcon(MimeTypePrivate &) {}
+ virtual void ensureLoaded() {}
+
+ QString directory() const { return m_directory; }
+
+ // added for Qt Creator
+ virtual bool hasMimeTypeForName(const QString &name) = 0;
+ virtual QStringList allMimeTypeNames() = 0;
+ virtual QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(const MimeType &mimeType) const = 0;
+ virtual void setMagicRulesForMimeType(const MimeType &mimeType,
+ const QMap<int, QList<MimeMagicRule>> &rules) = 0;
+ virtual void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns)
+ = 0;
+
+ MimeDatabasePrivate *m_db;
+ QString m_directory;
+ QSet<QString> m_overriddenMimeTypes;
+};
+
+/*
+ Parses the files 'mime.cache' and 'types' on demand
+ */
+class MimeBinaryProvider : public MimeProviderBase
+{
+public:
+ MimeBinaryProvider(MimeDatabasePrivate *db, const QString &directory);
+ virtual ~MimeBinaryProvider();
+
+ bool isValid() override;
+ bool isInternalDatabase() const override;
+ MimeType mimeTypeForName(const QString &name) override;
+ void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) override;
+ void addParents(const QString &mime, QStringList &result) override;
+ QString resolveAlias(const QString &name) override;
+ void addAliases(const QString &name, QStringList &result) override;
+ void findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate) override;
+ void addAllMimeTypes(QList<MimeType> &result) override;
+ bool loadMimeTypePrivate(MimeTypePrivate &) override;
+ void loadIcon(MimeTypePrivate &) override;
+ void loadGenericIcon(MimeTypePrivate &) override;
+ void ensureLoaded() override;
+
+ // added for Qt Creator
+ bool hasMimeTypeForName(const QString &name) override;
+ QStringList allMimeTypeNames() override;
+ QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(const MimeType &mimeType) const override;
+ void setMagicRulesForMimeType(const MimeType &mimeType,
+ const QMap<int, QList<MimeMagicRule>> &rules) override;
+ void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns) override;
+
+private:
+ struct CacheFile;
+
+ void matchGlobList(MimeGlobMatchResult &result,
+ CacheFile *cacheFile,
+ int offset,
+ const QString &fileName);
+ bool matchSuffixTree(MimeGlobMatchResult &result,
+ CacheFile *cacheFile,
+ int numEntries,
+ int firstOffset,
+ const QString &fileName,
+ int charPos,
+ bool caseSensitiveCheck);
+ bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
+ QLatin1String iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
+ void loadMimeTypeList();
+ bool checkCacheChanged();
+
+ CacheFile *m_cacheFile = nullptr;
+ QStringList m_cacheFileNames;
+ QSet<QString> m_mimetypeNames;
+ bool m_mimetypeListLoaded;
+ struct MimeTypeExtra
+ {
+ QHash<QString, QString> localeComments;
+ QStringList globPatterns;
+ };
+ QMap<QString, MimeTypeExtra> m_mimetypeExtra;
+};
+
+/*
+ Parses the raw XML files (slower)
+ */
+class MimeXMLProvider : public MimeProviderBase
+{
+public:
+ enum InternalDatabaseEnum { InternalDatabase };
+#if 1 // QT_CONFIG(mimetype_database)
+ enum : bool { InternalDatabaseAvailable = true };
+#else
+ enum : bool { InternalDatabaseAvailable = false };
+#endif
+ MimeXMLProvider(MimeDatabasePrivate *db, InternalDatabaseEnum);
+ MimeXMLProvider(MimeDatabasePrivate *db, const QString &directory);
+ // added for Qt Creator
+ MimeXMLProvider(MimeDatabasePrivate *db, const QString &directory, const QByteArray &data);
+ ~MimeXMLProvider();
+
+ bool isValid() override;
+ bool isInternalDatabase() const override;
+ MimeType mimeTypeForName(const QString &name) override;
+ void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) override;
+ void addParents(const QString &mime, QStringList &result) override;
+ QString resolveAlias(const QString &name) override;
+ void addAliases(const QString &name, QStringList &result) override;
+ void findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate) override;
+ void addAllMimeTypes(QList<MimeType> &result) override;
+ void ensureLoaded() override;
+
+ bool load(const QString &fileName, QString *errorMessage);
+
+ // Called by the mimetype xml parser
+ void addMimeType(const MimeType &mt);
+ void addGlobPattern(const MimeGlobPattern &glob);
+ void addParent(const QString &child, const QString &parent);
+ void addAlias(const QString &alias, const QString &name);
+ void addMagicMatcher(const MimeMagicRuleMatcher &matcher);
+
+ // added for Qt Creator
+ bool hasMimeTypeForName(const QString &name) override;
+ QStringList allMimeTypeNames() override;
+ QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(const MimeType &mimeType) const override;
+ void setMagicRulesForMimeType(const MimeType &mimeType,
+ const QMap<int, QList<MimeMagicRule>> &rules) override;
+ void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns) override;
+
+private:
+ void load(const QString &fileName);
+ void load(const char *data, qsizetype len);
+
+ typedef QHash<QString, MimeType> NameMimeTypeMap;
+ NameMimeTypeMap m_nameMimeTypeMap;
+
+ typedef QHash<QString, QString> AliasHash;
+ AliasHash m_aliases;
+
+ typedef QHash<QString, QStringList> ParentsHash;
+ ParentsHash m_parents;
+ MimeAllGlobPatterns m_mimeTypeGlobs;
+
+ QList<MimeMagicRuleMatcher> m_magicMatchers;
+ QStringList m_allFiles;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimetype.cpp b/src/libs/utils/mimetypes2/mimetype.cpp
new file mode 100644
index 00000000000..ca1964ed9eb
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimetype.cpp
@@ -0,0 +1,570 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mimetype.h"
+
+#include "mimetype_p.h"
+#include "mimedatabase_p.h"
+#include "mimeprovider_p.h"
+
+#include "mimeglobpattern_p.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QLocale>
+#include <QtCore/QHashFunctions>
+
+#include <memory>
+
+namespace Utils {
+
+static QString suffixFromPattern(const QString &pattern)
+{
+ // Not a simple suffix if it looks like: README or *. or *.* or *.JP*G or *.JP?
+ if (pattern.startsWith(QLatin1String("*.")) &&
+ pattern.length() > 2 &&
+ pattern.indexOf(QLatin1Char('*'), 2) < 0 && pattern.indexOf(QLatin1Char('?'), 2) < 0) {
+ return pattern.mid(2);
+ }
+ return {};
+}
+
+MimeTypePrivate::MimeTypePrivate()
+ : loaded(false), fromCache(false)
+{}
+
+MimeTypePrivate::MimeTypePrivate(const MimeType &other)
+ : loaded(other.d->loaded),
+ name(other.d->name),
+ localeComments(other.d->localeComments),
+ genericIconName(other.d->genericIconName),
+ iconName(other.d->iconName),
+ globPatterns(other.d->globPatterns)
+{}
+
+void MimeTypePrivate::clear()
+{
+ name.clear();
+ localeComments.clear();
+ genericIconName.clear();
+ iconName.clear();
+ globPatterns.clear();
+}
+
+void MimeTypePrivate::addGlobPattern(const QString &pattern)
+{
+ globPatterns.append(pattern);
+}
+
+/*!
+ \class MimeType
+ \inmodule QtCore
+ \ingroup shared
+ \brief The MimeType class describes types of file or data, represented by a MIME type string.
+
+ \since 5.0
+
+ For instance a file named "readme.txt" has the MIME type "text/plain".
+ The MIME type can be determined from the file name, or from the file
+ contents, or from both. MIME type determination can also be done on
+ buffers of data not coming from files.
+
+ Determining the MIME type of a file can be useful to make sure your
+ application supports it. It is also useful in file-manager-like applications
+ or widgets, in order to display an appropriate \l {MimeType::iconName}{icon} for the file, or even
+ the descriptive \l {MimeType::comment()}{comment} in detailed views.
+
+ To check if a file has the expected MIME type, you should use inherits()
+ rather than a simple string comparison based on the name(). This is because
+ MIME types can inherit from each other: for instance a C source file is
+ a specific type of plain text file, so text/x-csrc inherits text/plain.
+
+ \sa MimeDatabase, {MIME Type Browser Example}
+ */
+
+/*!
+ \fn MimeType &MimeType::operator=(MimeType &&other)
+
+ Move-assigns \a other to this MimeType instance.
+
+ \since 5.2
+*/
+
+/*!
+ \fn MimeType::MimeType();
+ Constructs this MimeType object initialized with default property values that indicate an invalid MIME type.
+ */
+MimeType::MimeType() :
+ d(new MimeTypePrivate())
+{
+}
+
+/*!
+ \fn MimeType::MimeType(const MimeType &other);
+ Constructs this MimeType object as a copy of \a other.
+ */
+MimeType::MimeType(const MimeType &other) :
+ d(other.d)
+{
+}
+
+/*!
+ \fn MimeType &MimeType::operator=(const MimeType &other);
+ Assigns the data of \a other to this MimeType object, and returns a reference to this object.
+ */
+MimeType &MimeType::operator=(const MimeType &other)
+{
+ if (d != other.d)
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn MimeType::MimeType(const MimeTypePrivate &dd);
+ Assigns the data of the MimeTypePrivate \a dd to this MimeType object, and returns a reference to this object.
+ \internal
+ */
+MimeType::MimeType(const MimeTypePrivate &dd) :
+ d(new MimeTypePrivate(dd))
+{
+}
+
+/*!
+ \fn void MimeType::swap(MimeType &other);
+ Swaps MimeType \a other with this MimeType object.
+
+ This operation is very fast and never fails.
+
+ The swap() method helps with the implementation of assignment
+ operators in an exception-safe way. For more information consult
+ \l {http://en.wikibooks.org/wiki/More_C++_Idioms/Copy-and-swap}
+ {More C++ Idioms - Copy-and-swap}.
+ */
+
+/*!
+ \fn MimeType::~MimeType();
+ Destroys the MimeType object, and releases the d pointer.
+ */
+MimeType::~MimeType()
+{
+}
+
+/*!
+ \fn bool MimeType::operator==(const MimeType &other) const;
+ Returns \c true if \a other equals this MimeType object, otherwise returns \c false.
+ The name is the unique identifier for a mimetype, so two mimetypes with
+ the same name, are equal.
+ */
+bool MimeType::operator==(const MimeType &other) const
+{
+ return d == other.d || d->name == other.d->name;
+}
+
+/*!
+ \since 5.6
+ \relates MimeType
+
+ Returns the hash value for \a key, using
+ \a seed to seed the calculation.
+ */
+size_t qHash(const MimeType &key, size_t seed) noexcept
+{
+ return qHash(key.d->name, seed);
+}
+
+/*!
+ \fn bool MimeType::operator!=(const MimeType &other) const;
+ Returns \c true if \a other does not equal this MimeType object, otherwise returns \c false.
+ */
+
+/*!
+ \property MimeType::valid
+ \brief \c true if the MimeType object contains valid data, \c false otherwise
+
+ A valid MIME type has a non-empty name().
+ The invalid MIME type is the default-constructed MimeType.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+bool MimeType::isValid() const
+{
+ return !d->name.isEmpty();
+}
+
+/*!
+ \property MimeType::isDefault
+ \brief \c true if this MIME type is the default MIME type which
+ applies to all files: application/octet-stream.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+bool MimeType::isDefault() const
+{
+ return d->name == MimeDatabasePrivate::instance()->defaultMimeType();
+}
+
+/*!
+ \property MimeType::name
+ \brief the name of the MIME type
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+QString MimeType::name() const
+{
+ return d->name;
+}
+
+/*!
+ \property MimeType::comment
+ \brief the description of the MIME type to be displayed on user interfaces
+
+ The default language (QLocale().name()) is used to select the appropriate translation.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+QString MimeType::comment() const
+{
+ MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
+
+ QStringList languageList;
+ languageList << QLocale().name();
+ languageList << QLocale().uiLanguages();
+ languageList << QLatin1String("default"); // use the default locale if possible.
+ for (const QString &language : qAsConst(languageList)) {
+ const QString lang = language == QLatin1String("C") ? QLatin1String("en_US") : language;
+ const QString comm = d->localeComments.value(lang);
+ if (!comm.isEmpty())
+ return comm;
+ const int pos = lang.indexOf(QLatin1Char('_'));
+ if (pos != -1) {
+ // "pt_BR" not found? try just "pt"
+ const QString shortLang = lang.left(pos);
+ const QString commShort = d->localeComments.value(shortLang);
+ if (!commShort.isEmpty())
+ return commShort;
+ }
+ }
+
+ // Use the mimetype name as fallback
+ return d->name;
+}
+
+/*!
+ \property MimeType::genericIconName
+ \brief the file name of a generic icon that represents the MIME type
+
+ This should be used if the icon returned by iconName() cannot be found on
+ the system. It is used for categories of similar types (like spreadsheets
+ or archives) that can use a common icon.
+ The freedesktop.org Icon Naming Specification lists a set of such icon names.
+
+ The icon name can be given to QIcon::fromTheme() in order to load the icon.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+QString MimeType::genericIconName() const
+{
+ MimeDatabasePrivate::instance()->loadGenericIcon(const_cast<MimeTypePrivate&>(*d));
+ if (d->genericIconName.isEmpty()) {
+ // From the spec:
+ // If the generic icon name is empty (not specified by the mimetype definition)
+ // then the mimetype is used to generate the generic icon by using the top-level
+ // media type (e.g. "video" in "video/ogg") and appending "-x-generic"
+ // (i.e. "video-x-generic" in the previous example).
+ const QString group = name();
+ QStringView groupRef(group);
+ const int slashindex = groupRef.indexOf(QLatin1Char('/'));
+ if (slashindex != -1)
+ groupRef = groupRef.left(slashindex);
+ return groupRef + QLatin1String("-x-generic");
+ }
+ return d->genericIconName;
+}
+
+static QString make_default_icon_name_from_mimetype_name(QString iconName)
+{
+ const int slashindex = iconName.indexOf(QLatin1Char('/'));
+ if (slashindex != -1)
+ iconName[slashindex] = QLatin1Char('-');
+ return iconName;
+}
+
+/*!
+ \property MimeType::iconName
+ \brief the file name of an icon image that represents the MIME type
+
+ The icon name can be given to QIcon::fromTheme() in order to load the icon.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+QString MimeType::iconName() const
+{
+ MimeDatabasePrivate::instance()->loadIcon(const_cast<MimeTypePrivate&>(*d));
+ if (d->iconName.isEmpty()) {
+ return make_default_icon_name_from_mimetype_name(name());
+ }
+ return d->iconName;
+}
+
+/*!
+ \property MimeType::globPatterns
+ \brief the list of glob matching patterns
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+QStringList MimeType::globPatterns() const
+{
+ MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
+ return d->globPatterns;
+}
+
+/*!
+ \property MimeType::parentMimeTypes
+ \brief the names of parent MIME types
+
+ A type is a subclass of another type if any instance of the first type is
+ also an instance of the second. For example, all image/svg+xml files are also
+ text/xml, text/plain and application/octet-stream files. Subclassing is about
+ the format, rather than the category of the data (for example, there is no
+ 'generic spreadsheet' class that all spreadsheets inherit from).
+ Conversely, the parent mimetype of image/svg+xml is text/xml.
+
+ A mimetype can have multiple parents. For instance application/x-perl
+ has two parents: application/x-executable and text/plain. This makes
+ it possible to both execute perl scripts, and to open them in text editors.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+*/
+QStringList MimeType::parentMimeTypes() const
+{
+ return MimeDatabasePrivate::instance()->mimeParents(d->name);
+}
+
+static void collectParentMimeTypes(const QString &mime, QStringList &allParents)
+{
+ const QStringList parents = MimeDatabasePrivate::instance()->mimeParents(mime);
+ for (const QString &parent : parents) {
+ // I would use QSet, but since order matters I better not
+ if (!allParents.contains(parent))
+ allParents.append(parent);
+ }
+ // We want a breadth-first search, so that the least-specific parent (octet-stream) is last
+ // This means iterating twice, unfortunately.
+ for (const QString &parent : parents)
+ collectParentMimeTypes(parent, allParents);
+}
+
+/*!
+ \property MimeType::allAncestors
+ \brief the names of direct and indirect parent MIME types
+
+ Return all the parent mimetypes of this mimetype, direct and indirect.
+ This includes the parent(s) of its parent(s), etc.
+
+ For instance, for image/svg+xml the list would be:
+ application/xml, text/plain, application/octet-stream.
+
+ Note that application/octet-stream is the ultimate parent for all types
+ of files (but not directories).
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+*/
+QStringList MimeType::allAncestors() const
+{
+ QStringList allParents;
+ collectParentMimeTypes(d->name, allParents);
+ return allParents;
+}
+
+/*!
+ \property MimeType::aliases
+ \brief the list of aliases of this mimetype
+
+ For instance, for text/csv, the returned list would be:
+ text/x-csv, text/x-comma-separated-values.
+
+ Note that all MimeType instances refer to proper mimetypes,
+ never to aliases directly.
+
+ The order of the aliases in the list is undefined.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+*/
+QStringList MimeType::aliases() const
+{
+ return MimeDatabasePrivate::instance()->listAliases(d->name);
+}
+
+/*!
+ \property MimeType::suffixes
+ \brief the known suffixes for the MIME type
+
+ No leading dot is included, so for instance this would return "jpg", "jpeg" for image/jpeg.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+QStringList MimeType::suffixes() const
+{
+ MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
+
+ QStringList result;
+ for (const QString &pattern : qAsConst(d->globPatterns)) {
+ const QString suffix = suffixFromPattern(pattern);
+ if (!suffix.isEmpty())
+ result.append(suffix);
+ }
+
+ return result;
+}
+
+/*!
+ \property MimeType::preferredSuffix
+ \brief the preferred suffix for the MIME type
+
+ No leading dot is included, so for instance this would return "pdf" for application/pdf.
+ The return value can be empty, for mime types which do not have any suffixes associated.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+ */
+QString MimeType::preferredSuffix() const
+{
+ if (isDefault()) // workaround for unwanted *.bin suffix for octet-stream, https://bugs.freedesktop.org/show_bug.cgi?id=101667, fixed upstream in 1.10
+ return QString();
+ const QStringList suffixList = suffixes();
+ return suffixList.isEmpty() ? QString() : suffixList.at(0);
+}
+
+/*!
+ \property MimeType::filterString
+ \brief a filter string usable for a file dialog
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
+*/
+QString MimeType::filterString() const
+{
+ MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
+ QString filter;
+
+ if (!d->globPatterns.empty()) {
+ filter += comment() + QLatin1String(" (");
+ for (int i = 0; i < d->globPatterns.size(); ++i) {
+ if (i != 0)
+ filter += QLatin1Char(' ');
+ filter += d->globPatterns.at(i);
+ }
+ filter += QLatin1Char(')');
+ }
+
+ return filter;
+}
+
+/*!
+ \fn bool MimeType::inherits(const QString &mimeTypeName) const;
+ Returns \c true if this mimetype is \a mimeTypeName,
+ or inherits \a mimeTypeName (see parentMimeTypes()),
+ or \a mimeTypeName is an alias for this mimetype.
+
+ This method has been made invokable from QML since 5.10.
+ */
+bool MimeType::inherits(const QString &mimeTypeName) const
+{
+ if (d->name == mimeTypeName)
+ return true;
+ return MimeDatabasePrivate::instance()->mimeInherits(d->name, mimeTypeName);
+}
+
+/*!
+ Returns \c true if the name or alias of the MIME type matches
+ \a nameOrAlias.
+*/
+bool MimeType::matchesName(const QString &nameOrAlias) const
+{
+ if (d->name == nameOrAlias)
+ return true;
+ auto dbp = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&dbp->mutex);
+ return MimeDatabasePrivate::instance()->resolveAlias(nameOrAlias) == d->name;
+}
+
+/*!
+ Sets the preferred filename suffix for the MIME type to \a suffix.
+*/
+void MimeType::setPreferredSuffix(const QString &suffix)
+{
+ MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
+
+ auto it = std::find_if(d->globPatterns.begin(),
+ d->globPatterns.end(),
+ [suffix](const QString &pattern) {
+ return suffixFromPattern(pattern) == suffix;
+ });
+ if (it != d->globPatterns.end())
+ d->globPatterns.erase(it);
+ d->globPatterns.prepend(QLatin1String("*.") + suffix);
+}
+
+} // namespace Utils
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const Utils::MimeType &mime)
+{
+ QDebugStateSaver saver(debug);
+ if (!mime.isValid()) {
+ debug.nospace() << "MimeType(invalid)";
+ } else {
+ debug.nospace() << "MimeType(" << mime.name() << ")";
+ }
+ return debug;
+}
+#endif
+
+#include "moc_mimetype.cpp"
diff --git a/src/libs/utils/mimetypes2/mimetype.h b/src/libs/utils/mimetypes2/mimetype.h
new file mode 100644
index 00000000000..b9da254ea8f
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimetype.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/utils_global.h>
+
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+
+namespace Utils {
+
+class MimeTypePrivate;
+class MimeType;
+
+QTCREATOR_UTILS_EXPORT size_t qHash(const MimeType &key, size_t seed = 0) noexcept;
+
+class QTCREATOR_UTILS_EXPORT MimeType
+{
+ Q_GADGET
+ Q_PROPERTY(bool valid READ isValid CONSTANT)
+ Q_PROPERTY(bool isDefault READ isDefault CONSTANT)
+ Q_PROPERTY(QString name READ name CONSTANT)
+ Q_PROPERTY(QString comment READ comment CONSTANT)
+ Q_PROPERTY(QString genericIconName READ genericIconName CONSTANT)
+ Q_PROPERTY(QString iconName READ iconName CONSTANT)
+ Q_PROPERTY(QStringList globPatterns READ globPatterns CONSTANT)
+ Q_PROPERTY(QStringList parentMimeTypes READ parentMimeTypes CONSTANT)
+ Q_PROPERTY(QStringList allAncestors READ allAncestors CONSTANT)
+ Q_PROPERTY(QStringList aliases READ aliases CONSTANT)
+ Q_PROPERTY(QStringList suffixes READ suffixes CONSTANT)
+ Q_PROPERTY(QString preferredSuffix READ preferredSuffix CONSTANT)
+ Q_PROPERTY(QString filterString READ filterString CONSTANT)
+
+public:
+ MimeType();
+ MimeType(const MimeType &other);
+ MimeType &operator=(const MimeType &other);
+ MimeType &operator=(MimeType &&other) noexcept
+ {
+ swap(other);
+ return *this;
+ }
+ void swap(MimeType &other) noexcept
+ {
+ d.swap(other.d);
+ }
+ explicit MimeType(const MimeTypePrivate &dd);
+ ~MimeType();
+
+ bool operator==(const MimeType &other) const;
+
+ inline bool operator!=(const MimeType &other) const
+ {
+ return !operator==(other);
+ }
+
+ bool isValid() const;
+
+ bool isDefault() const;
+
+ QString name() const;
+ QString comment() const;
+ QString genericIconName() const;
+ QString iconName() const;
+ QStringList globPatterns() const;
+ QStringList parentMimeTypes() const;
+ QStringList allAncestors() const;
+ QStringList aliases() const;
+ QStringList suffixes() const;
+ QString preferredSuffix() const;
+
+ Q_INVOKABLE bool inherits(const QString &mimeTypeName) const;
+
+ QString filterString() const;
+
+ // Qt Creator additions
+ bool matchesName(const QString &nameOrAlias) const;
+ void setPreferredSuffix(const QString &suffix);
+
+protected:
+ friend class MimeTypeParserBase;
+ friend class MimeTypeMapEntry;
+ friend class MimeDatabasePrivate;
+ friend class MimeXMLProvider;
+ friend class MimeBinaryProvider;
+ friend class MimeTypePrivate;
+ friend QTCREATOR_UTILS_EXPORT size_t qHash(const MimeType &key, size_t seed) noexcept;
+
+ QExplicitlySharedDataPointer<MimeTypePrivate> d;
+};
+
+
+} // namespace Utils
+
+QT_BEGIN_NAMESPACE
+#ifndef QT_NO_DEBUG_STREAM
+class QDebug;
+QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug debug, const Utils::MimeType &mime);
+#endif
+
+Q_DECLARE_SHARED(Utils::MimeType)
+QT_END_NAMESPACE
diff --git a/src/libs/utils/mimetypes2/mimetype_p.h b/src/libs/utils/mimetypes2/mimetype_p.h
new file mode 100644
index 00000000000..1158333a5c6
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimetype_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "mimetype.h"
+
+#include <QtCore/qhash.h>
+#include <QtCore/qstringlist.h>
+
+namespace Utils {
+
+class MimeTypePrivate : public QSharedData
+{
+public:
+ typedef QHash<QString, QString> LocaleHash;
+
+ MimeTypePrivate();
+ explicit MimeTypePrivate(const MimeType &other);
+
+ void clear();
+
+ void addGlobPattern(const QString &pattern);
+
+ bool loaded; // QSharedData leaves a 4 byte gap, so don't put 8 byte members first
+ bool fromCache; // true if this comes from the binary provider
+ QString name;
+ LocaleHash localeComments;
+ QString genericIconName;
+ QString iconName;
+ QStringList globPatterns;
+};
+
+} // namespace Utils
+
+#if 0
+#define QMIMETYPE_BUILDER_FROM_RVALUE_REFS \
+ QT_BEGIN_NAMESPACE \
+ static QMimeType buildQMimeType ( \
+ QString &&name, \
+ QString &&genericIconName, \
+ QString &&iconName, \
+ QStringList &&globPatterns \
+ ) \
+ { \
+ QMimeTypePrivate qMimeTypeData; \
+ qMimeTypeData.loaded = true; \
+ qMimeTypeData.name = std::move(name); \
+ qMimeTypeData.genericIconName = std::move(genericIconName); \
+ qMimeTypeData.iconName = std::move(iconName); \
+ qMimeTypeData.globPatterns = std::move(globPatterns); \
+ return QMimeType(qMimeTypeData); \
+ } \
+ QT_END_NAMESPACE
+#endif
diff --git a/src/libs/utils/mimetypes2/mimetypeparser.cpp b/src/libs/utils/mimetypes2/mimetypeparser.cpp
new file mode 100644
index 00000000000..40ecfd90400
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimetypeparser.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mimetypeparser_p.h"
+
+#include "mimetype_p.h"
+#include "mimemagicrulematcher_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QXmlStreamWriter>
+#include <QtCore/QStack>
+
+namespace Utils {
+
+// XML tags in MIME files
+static const char mimeInfoTagC[] = "mime-info";
+static const char mimeTypeTagC[] = "mime-type";
+static const char mimeTypeAttributeC[] = "type";
+static const char subClassTagC[] = "sub-class-of";
+static const char commentTagC[] = "comment";
+static const char genericIconTagC[] = "generic-icon";
+static const char iconTagC[] = "icon";
+static const char nameAttributeC[] = "name";
+static const char globTagC[] = "glob";
+static const char globDeleteAllTagC[] = "glob-deleteall";
+static const char aliasTagC[] = "alias";
+static const char patternAttributeC[] = "pattern";
+static const char weightAttributeC[] = "weight";
+static const char caseSensitiveAttributeC[] = "case-sensitive";
+static const char localeAttributeC[] = "xml:lang";
+
+static const char magicTagC[] = "magic";
+static const char priorityAttributeC[] = "priority";
+
+static const char matchTagC[] = "match";
+static const char matchValueAttributeC[] = "value";
+static const char matchTypeAttributeC[] = "type";
+static const char matchOffsetAttributeC[] = "offset";
+static const char matchMaskAttributeC[] = "mask";
+
+/*!
+ \class MimeTypeParser
+ \inmodule QtCore
+ \internal
+ \brief The MimeTypeParser class parses MIME types, and builds a MIME database hierarchy by adding to MimeDatabase.
+
+ Populates MimeDataBase
+
+ \sa MimeDatabase, MimeMagicRuleMatcher, MagicRule, MagicStringRule, MagicByteRule, GlobPattern
+ \sa MimeTypeParser
+*/
+
+/*!
+ \class MimeTypeParserBase
+ \inmodule QtCore
+ \internal
+ \brief The MimeTypeParserBase class parses for a sequence of <mime-type> in a generic way.
+
+ Calls abstract handler function process for MimeType it finds.
+
+ \sa MimeDatabase, MimeMagicRuleMatcher, MagicRule, MagicStringRule, MagicByteRule, GlobPattern
+ \sa MimeTypeParser
+*/
+
+/*!
+ \fn virtual bool MimeTypeParserBase::process(const MimeType &t, QString *errorMessage) = 0;
+ Overwrite to process the sequence of parsed data
+*/
+
+MimeTypeParserBase::ParseState MimeTypeParserBase::nextState(ParseState currentState, QStringView startElement)
+{
+ switch (currentState) {
+ case ParseBeginning:
+ if (startElement == QLatin1String(mimeInfoTagC))
+ return ParseMimeInfo;
+ if (startElement == QLatin1String(mimeTypeTagC))
+ return ParseMimeType;
+ return ParseError;
+ case ParseMimeInfo:
+ return startElement == QLatin1String(mimeTypeTagC) ? ParseMimeType : ParseError;
+ case ParseMimeType:
+ case ParseComment:
+ case ParseGenericIcon:
+ case ParseIcon:
+ case ParseGlobPattern:
+ case ParseGlobDeleteAll:
+ case ParseSubClass:
+ case ParseAlias:
+ case ParseOtherMimeTypeSubTag:
+ case ParseMagicMatchRule:
+ if (startElement == QLatin1String(mimeTypeTagC)) // Sequence of <mime-type>
+ return ParseMimeType;
+ if (startElement == QLatin1String(commentTagC))
+ return ParseComment;
+ if (startElement == QLatin1String(genericIconTagC))
+ return ParseGenericIcon;
+ if (startElement == QLatin1String(iconTagC))
+ return ParseIcon;
+ if (startElement == QLatin1String(globTagC))
+ return ParseGlobPattern;
+ if (startElement == QLatin1String(globDeleteAllTagC))
+ return ParseGlobDeleteAll;
+ if (startElement == QLatin1String(subClassTagC))
+ return ParseSubClass;
+ if (startElement == QLatin1String(aliasTagC))
+ return ParseAlias;
+ if (startElement == QLatin1String(magicTagC))
+ return ParseMagic;
+ if (startElement == QLatin1String(matchTagC))
+ return ParseMagicMatchRule;
+ return ParseOtherMimeTypeSubTag;
+ case ParseMagic:
+ if (startElement == QLatin1String(matchTagC))
+ return ParseMagicMatchRule;
+ break;
+ case ParseError:
+ break;
+ }
+ return ParseError;
+}
+
+// Parse int number from an (attribute) string
+bool MimeTypeParserBase::parseNumber(QStringView n, int *target, QString *errorMessage)
+{
+ bool ok;
+ *target = n.toInt(&ok);
+ if (Q_UNLIKELY(!ok)) {
+ if (errorMessage)
+ *errorMessage = QLatin1String("Not a number '") + n + QLatin1String("'.");
+ return false;
+ }
+ return true;
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+struct CreateMagicMatchRuleResult
+{
+ QString errorMessage; // must be first
+ MimeMagicRule rule;
+
+ CreateMagicMatchRuleResult(QStringView type, QStringView value, QStringView offsets, QStringView mask)
+ : errorMessage(), rule(type.toString(), value.toUtf8(), offsets.toString(), mask.toLatin1(), &errorMessage)
+ {
+
+ }
+};
+
+static CreateMagicMatchRuleResult createMagicMatchRule(const QXmlStreamAttributes &atts)
+{
+ const auto type = atts.value(QLatin1String(matchTypeAttributeC));
+ const auto value = atts.value(QLatin1String(matchValueAttributeC));
+ const auto offsets = atts.value(QLatin1String(matchOffsetAttributeC));
+ const auto mask = atts.value(QLatin1String(matchMaskAttributeC));
+ return CreateMagicMatchRuleResult(type, value, offsets, mask);
+}
+#endif
+
+bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
+{
+#ifdef QT_NO_XMLSTREAMREADER
+ Q_UNUSED(dev);
+ if (errorMessage)
+ *errorMessage = QString::fromLatin1("QXmlStreamReader is not available, cannot parse '%1'.").arg(fileName);
+ return false;
+#else
+ MimeTypePrivate data;
+ data.loaded = true;
+ int priority = 50;
+ QStack<MimeMagicRule *> currentRules; // stack for the nesting of rules
+ QList<MimeMagicRule> rules; // toplevel rules
+ QXmlStreamReader reader(dev);
+ ParseState ps = ParseBeginning;
+ while (!reader.atEnd()) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement: {
+ ps = nextState(ps, reader.name());
+ const QXmlStreamAttributes atts = reader.attributes();
+ switch (ps) {
+ case ParseMimeType: { // start parsing a MIME type name
+ const QString name = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+ if (name.isEmpty()) {
+ reader.raiseError(QStringLiteral("Missing 'type'-attribute"));
+ } else {
+ data.name = name;
+ }
+ }
+ break;
+ case ParseGenericIcon:
+ data.genericIconName = atts.value(QLatin1String(nameAttributeC)).toString();
+ break;
+ case ParseIcon:
+ data.iconName = atts.value(QLatin1String(nameAttributeC)).toString();
+ break;
+ case ParseGlobPattern: {
+ const QString pattern = atts.value(QLatin1String(patternAttributeC)).toString();
+ unsigned weight = atts.value(QLatin1String(weightAttributeC)).toInt();
+ const bool caseSensitive = atts.value(QLatin1String(caseSensitiveAttributeC)) == QLatin1String("true");
+
+ if (weight == 0)
+ weight = MimeGlobPattern::DefaultWeight;
+
+ Q_ASSERT(!data.name.isEmpty());
+ const MimeGlobPattern glob(pattern, data.name, weight, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
+ if (!process(glob, errorMessage)) // for actual glob matching
+ return false;
+ data.addGlobPattern(pattern); // just for MimeType::globPatterns()
+ }
+ break;
+ case ParseGlobDeleteAll:
+ data.globPatterns.clear();
+ break;
+ case ParseSubClass: {
+ const QString inheritsFrom = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+ if (!inheritsFrom.isEmpty())
+ processParent(data.name, inheritsFrom);
+ }
+ break;
+ case ParseComment: {
+ // comments have locale attributes.
+ QString locale = atts.value(QLatin1String(localeAttributeC)).toString();
+ const QString comment = reader.readElementText();
+ if (locale.isEmpty())
+ locale = QString::fromLatin1("default");
+ data.localeComments.insert(locale, comment);
+ }
+ break;
+ case ParseAlias: {
+ const QString alias = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+ if (!alias.isEmpty())
+ processAlias(alias, data.name);
+ }
+ break;
+ case ParseMagic: {
+ priority = 50;
+ const auto priorityS = atts.value(QLatin1String(priorityAttributeC));
+ if (!priorityS.isEmpty()) {
+ if (!parseNumber(priorityS, &priority, errorMessage))
+ return false;
+
+ }
+ currentRules.clear();
+ //qDebug() << "MAGIC start for mimetype" << data.name;
+ }
+ break;
+ case ParseMagicMatchRule: {
+ auto result = createMagicMatchRule(atts);
+ if (Q_UNLIKELY(!result.rule.isValid()))
+ qWarning("MimeDatabase: Error parsing %ls\n%ls",
+ qUtf16Printable(fileName), qUtf16Printable(result.errorMessage));
+ QList<MimeMagicRule> *ruleList;
+ if (currentRules.isEmpty())
+ ruleList = &rules;
+ else // nest this rule into the proper parent
+ ruleList = &currentRules.top()->m_subMatches;
+ ruleList->append(std::move(result.rule));
+ //qDebug() << " MATCH added. Stack size was" << currentRules.size();
+ currentRules.push(&ruleList->last());
+ break;
+ }
+ case ParseError:
+ reader.raiseError(QLatin1String("Unexpected element <") + reader.name() + QLatin1Char('>'));
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ // continue switch QXmlStreamReader::Token...
+ case QXmlStreamReader::EndElement: // Finished element
+ {
+ const auto elementName = reader.name();
+ if (elementName == QLatin1String(mimeTypeTagC)) {
+ if (!process(MimeType(data), errorMessage))
+ return false;
+ data.clear();
+ } else if (elementName == QLatin1String(matchTagC)) {
+ // Closing a <match> tag, pop stack
+ currentRules.pop();
+ //qDebug() << " MATCH closed. Stack size is now" << currentRules.size();
+ } else if (elementName == QLatin1String(magicTagC)) {
+ //qDebug() << "MAGIC ended, we got" << rules.count() << "rules, with prio" << priority;
+ // Finished a <magic> sequence
+ MimeMagicRuleMatcher ruleMatcher(data.name, priority);
+ ruleMatcher.addRules(rules);
+ processMagicMatcher(ruleMatcher);
+ rules.clear();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (Q_UNLIKELY(reader.hasError())) {
+ if (errorMessage) {
+ *errorMessage = QString::asprintf("An error has been encountered at line %lld of %ls: %ls:",
+ reader.lineNumber(),
+ qUtf16Printable(fileName),
+ qUtf16Printable(reader.errorString()));
+ }
+ return false;
+ }
+
+ return true;
+#endif //QT_NO_XMLSTREAMREADER
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimetypeparser_p.h b/src/libs/utils/mimetypes2/mimetypeparser_p.h
new file mode 100644
index 00000000000..87efc19eec7
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimetypeparser_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "mimedatabase_p.h"
+
+#include "mimeprovider_p.h"
+
+QT_BEGIN_NAMESPACE
+class QIODevice;
+QT_END_NAMESPACE
+
+namespace Utils {
+
+class MimeTypeParserBase
+{
+ Q_DISABLE_COPY_MOVE(MimeTypeParserBase)
+
+public:
+ MimeTypeParserBase() {}
+ virtual ~MimeTypeParserBase() {}
+
+ bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage);
+
+ static bool parseNumber(QStringView n, int *target, QString *errorMessage);
+
+protected:
+ virtual bool process(const MimeType &t, QString *errorMessage) = 0;
+ virtual bool process(const MimeGlobPattern &t, QString *errorMessage) = 0;
+ virtual void processParent(const QString &child, const QString &parent) = 0;
+ virtual void processAlias(const QString &alias, const QString &name) = 0;
+ virtual void processMagicMatcher(const MimeMagicRuleMatcher &matcher) = 0;
+
+private:
+ enum ParseState {
+ ParseBeginning,
+ ParseMimeInfo,
+ ParseMimeType,
+ ParseComment,
+ ParseGenericIcon,
+ ParseIcon,
+ ParseGlobPattern,
+ ParseGlobDeleteAll,
+ ParseSubClass,
+ ParseAlias,
+ ParseMagic,
+ ParseMagicMatchRule,
+ ParseOtherMimeTypeSubTag,
+ ParseError
+ };
+
+ static ParseState nextState(ParseState currentState, QStringView startElement);
+};
+
+
+class MimeTypeParser : public MimeTypeParserBase
+{
+public:
+ explicit MimeTypeParser(MimeXMLProvider &provider) : m_provider(provider) {}
+
+protected:
+ inline bool process(const MimeType &t, QString *) override
+ { m_provider.addMimeType(t); return true; }
+
+ inline bool process(const MimeGlobPattern &glob, QString *) override
+ { m_provider.addGlobPattern(glob); return true; }
+
+ inline void processParent(const QString &child, const QString &parent) override
+ { m_provider.addParent(child, parent); }
+
+ inline void processAlias(const QString &alias, const QString &name) override
+ { m_provider.addAlias(alias, name); }
+
+ inline void processMagicMatcher(const MimeMagicRuleMatcher &matcher) override
+ { m_provider.addMagicMatcher(matcher); }
+
+private:
+ MimeXMLProvider &m_provider;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/mimetypes2/mimeutils.cpp b/src/libs/utils/mimetypes2/mimeutils.cpp
new file mode 100644
index 00000000000..676398bb140
--- /dev/null
+++ b/src/libs/utils/mimetypes2/mimeutils.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mimeutils.h"
+
+#include "mimedatabase.h"
+#include "mimedatabase_p.h"
+#include "mimemagicrule_p.h"
+#include "mimeprovider_p.h"
+
+#include "filepath.h"
+
+namespace Utils {
+
+MimeType mimeTypeForName(const QString &nameOrAlias)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypeForName(nameOrAlias);
+}
+
+MimeType mimeTypeForFile(const QString &fileName, MimeMatchMode mode)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypeForFile(fileName, MimeDatabase::MatchMode(mode));
+}
+
+MimeType mimeTypeForFile(const FilePath &filePath, MimeMatchMode mode)
+{
+ MimeDatabase mdb;
+ if (filePath.needsDevice())
+ return mdb.mimeTypeForUrl(filePath.toUrl());
+ return mdb.mimeTypeForFile(filePath.toString(), MimeDatabase::MatchMode(mode));
+}
+
+QList<MimeType> mimeTypesForFileName(const QString &fileName)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypesForFileName(fileName);
+}
+
+MimeType mimeTypeForData(const QByteArray &data)
+{
+ MimeDatabase mdb;
+ return mdb.mimeTypeForData(data);
+}
+
+QList<MimeType> allMimeTypes()
+{
+ MimeDatabase mdb;
+ return mdb.allMimeTypes();
+}
+
+void setMimeStartupPhase(MimeStartupPhase phase)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+ if (int(phase) != d->m_startupPhase + 1) {
+ qWarning("Unexpected jump in MimedDatabase lifetime from %d to %d",
+ d->m_startupPhase,
+ int(phase));
+ }
+ d->m_startupPhase = int(phase);
+}
+
+void addMimeTypes(const QString &id, const QByteArray &data)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+
+ if (d->m_startupPhase >= int(MimeStartupPhase::PluginsDelayedInitializing)) {
+ qWarning("Adding items for ID \"%s\" to MimeDatabase after initialization time",
+ qPrintable(id));
+ }
+
+ d->addMimeData(id, data);
+}
+
+QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(const MimeType &mimeType)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+ return d->magicRulesForMimeType(mimeType);
+}
+
+void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+ d->setGlobPatternsForMimeType(mimeType, patterns);
+}
+
+void setMagicRulesForMimeType(const MimeType &mimeType, const QMap<int, QList<MimeMagicRule>> &rules)
+{
+ auto d = MimeDatabasePrivate::instance();
+ QMutexLocker locker(&d->mutex);
+ d->setMagicRulesForMimeType(mimeType, rules);
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/mimeutils.h b/src/libs/utils/mimeutils.h
new file mode 100644
index 00000000000..7b3071ff609
--- /dev/null
+++ b/src/libs/utils/mimeutils.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "utils_global.h"
+
+#include <mimemagicrule_p.h>
+#include <mimetype.h>
+
+namespace Utils {
+
+class FilePath;
+
+// Wrapped QMimeDataBase functions
+QTCREATOR_UTILS_EXPORT MimeType mimeTypeForName(const QString &nameOrAlias);
+
+enum class MimeMatchMode { MatchDefault = 0x0, MatchExtension = 0x1, MatchContent = 0x2 };
+
+QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const QString &fileName,
+ MimeMatchMode mode = MimeMatchMode::MatchDefault);
+QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const FilePath &filePath,
+ MimeMatchMode mode = MimeMatchMode::MatchDefault);
+QTCREATOR_UTILS_EXPORT QList<MimeType> mimeTypesForFileName(const QString &fileName);
+QTCREATOR_UTILS_EXPORT MimeType mimeTypeForData(const QByteArray &data);
+QTCREATOR_UTILS_EXPORT QList<MimeType> allMimeTypes();
+
+// Qt Creator additions
+// For debugging purposes.
+enum class MimeStartupPhase {
+ BeforeInitialize,
+ PluginsLoading,
+ PluginsInitializing, // Register up to here.
+ PluginsDelayedInitializing, // Use from here on.
+ UpAndRunning
+};
+
+QTCREATOR_UTILS_EXPORT void setMimeStartupPhase(MimeStartupPhase);
+QTCREATOR_UTILS_EXPORT void addMimeTypes(const QString &id, const QByteArray &data);
+QTCREATOR_UTILS_EXPORT QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(
+ const MimeType &mimeType); // priority -> rules
+QTCREATOR_UTILS_EXPORT void setGlobPatternsForMimeType(const MimeType &mimeType,
+ const QStringList &patterns);
+QTCREATOR_UTILS_EXPORT void setMagicRulesForMimeType(
+ const MimeType &mimeType, const QMap<int, QList<MimeMagicRule>> &rules); // priority -> rules
+
+} // namespace Utils
diff --git a/src/libs/utils/minimizableinfobars.cpp b/src/libs/utils/minimizableinfobars.cpp
new file mode 100644
index 00000000000..3848c458705
--- /dev/null
+++ b/src/libs/utils/minimizableinfobars.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "minimizableinfobars.h"
+
+#include "qtcassert.h"
+#include "qtcsettings.h"
+#include "utilsicons.h"
+
+#include <QAction>
+#include <QToolButton>
+
+const char SETTINGS_PREFIX[] = "ShowInfoBarFor";
+const bool kShowInInfoBarDefault = true;
+
+namespace Utils {
+
+MinimizableInfoBars::MinimizableInfoBars(InfoBar &infoBar)
+ : m_infoBar(infoBar)
+{
+}
+
+void MinimizableInfoBars::setPossibleInfoBarEntries(const QList<Utils::InfoBarEntry> &entries)
+{
+ QTC_CHECK(m_actions.isEmpty());
+ m_infoEntries.clear();
+ m_isInfoVisible.clear();
+ for (const Utils::InfoBarEntry &entry : entries) {
+ m_infoEntries.insert(entry.id(), entry);
+ m_isInfoVisible.insert(entry.id(), false);
+ }
+ createActions();
+}
+
+void MinimizableInfoBars::setSettingsGroup(const QString &settingsGroup)
+{
+ m_settingsGroup = settingsGroup;
+}
+
+void MinimizableInfoBars::createActions()
+{
+ QTC_CHECK(m_actions.isEmpty());
+ for (const Utils::InfoBarEntry &entry : qAsConst(m_infoEntries)) {
+ const Id id = entry.id();
+ auto action = new QAction(this);
+ action->setToolTip(entry.text());
+ action->setIcon(Icons::WARNING_TOOLBAR.pixmap());
+ connect(action, &QAction::triggered, this, [this, id]() {
+ setShowInInfoBar(id, true);
+ updateInfo(id);
+ });
+ action->setVisible(!showInInfoBar(id));
+ m_actions.insert(id, action);
+ }
+}
+
+QString MinimizableInfoBars::settingsKey(const Id &id) const
+{
+ QTC_CHECK(!m_settingsGroup.isEmpty());
+ return m_settingsGroup + '/' + SETTINGS_PREFIX + id.toString();
+}
+
+void MinimizableInfoBars::createShowInfoBarActions(const ActionCreator &actionCreator) const
+{
+ QTC_ASSERT(actionCreator, return );
+
+ for (QAction *action : m_actions) {
+ auto *button = new QToolButton();
+ button->setDefaultAction(action);
+ QAction *toolbarAction = actionCreator(button);
+ connect(action, &QAction::changed, toolbarAction, [action, toolbarAction] {
+ toolbarAction->setVisible(action->isVisible());
+ });
+ toolbarAction->setVisible(action->isVisible());
+ }
+}
+
+void MinimizableInfoBars::setInfoVisible(const Id &id, bool visible)
+{
+ QTC_CHECK(m_isInfoVisible.contains(id));
+ m_isInfoVisible.insert(id, visible);
+ updateInfo(id);
+}
+
+void MinimizableInfoBars::updateInfo(const Id &id)
+{
+ m_infoBar.removeInfo(id);
+
+ bool show = false;
+ if (m_isInfoVisible.value(id)) {
+ if (showInInfoBar(id))
+ showInfoBar(id);
+ else
+ show = true;
+ }
+
+ QAction *action = m_actions.value(id);
+ if (QTC_GUARD(action))
+ action->setVisible(show);
+}
+
+void MinimizableInfoBars::showInfoBar(const Id &id)
+{
+ const InfoBarEntry entry = m_infoEntries.value(id);
+ InfoBarEntry info(entry);
+ info.removeCancelButton();
+ // The minimizer() might delete the "Minimize" button immediately and as
+ // result invalid reads will happen in QToolButton::mouseReleaseEvent().
+ // Avoid this by running the minimizer in the next event loop iteration.
+ info.addCustomButton(MinimizableInfoBars::tr("Minimize"), [this, id] {
+ QMetaObject::invokeMethod(
+ this,
+ [id, this] {
+ setShowInInfoBar(id, false);
+ updateInfo(id);
+ },
+ Qt::QueuedConnection);
+ });
+ m_infoBar.addInfo(info);
+}
+
+bool MinimizableInfoBars::showInInfoBar(const Id &id) const
+{
+ return InfoBar::settings()->value(settingsKey(id), kShowInInfoBarDefault).toBool();
+}
+
+void MinimizableInfoBars::setShowInInfoBar(const Id &id, bool show)
+{
+ QtcSettings::setValueWithDefault(InfoBar::settings(),
+ settingsKey(id),
+ show,
+ kShowInInfoBarDefault);
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/minimizableinfobars.h b/src/libs/utils/minimizableinfobars.h
new file mode 100644
index 00000000000..bb658f9cf63
--- /dev/null
+++ b/src/libs/utils/minimizableinfobars.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "utils_global.h"
+
+#include "id.h"
+#include "infobar.h"
+
+#include <QHash>
+#include <QObject>
+
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+QT_END_NAMESPACE
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT MinimizableInfoBars : public QObject
+{
+ Q_OBJECT
+
+public:
+ using ActionCreator = std::function<QAction *(QWidget *widget)>;
+
+public:
+ explicit MinimizableInfoBars(InfoBar &infoBar);
+
+ void setSettingsGroup(const QString &settingsGroup);
+ void setPossibleInfoBarEntries(const QList<InfoBarEntry> &entries);
+
+ void createShowInfoBarActions(const ActionCreator &actionCreator) const;
+
+ void setInfoVisible(const Id &id, bool visible);
+
+private:
+ void createActions();
+
+ QString settingsKey(const Id &id) const;
+ bool showInInfoBar(const Id &id) const;
+ void setShowInInfoBar(const Id &id, bool show);
+
+ void updateInfo(const Id &id);
+
+ void showInfoBar(const Id &id);
+
+private:
+ InfoBar &m_infoBar;
+ QString m_settingsGroup;
+ QHash<Id, QAction *> m_actions;
+ QHash<Id, bool> m_isInfoVisible;
+ QHash<Id, InfoBarEntry> m_infoEntries;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/multitextcursor.cpp b/src/libs/utils/multitextcursor.cpp
index f22490eb7db..c5d8feac0ab 100644
--- a/src/libs/utils/multitextcursor.cpp
+++ b/src/libs/utils/multitextcursor.cpp
@@ -50,6 +50,12 @@ void MultiTextCursor::addCursor(const QTextCursor &cursor)
mergeCursors();
}
+void MultiTextCursor::addCursors(const QList<QTextCursor> &cursors)
+{
+ m_cursors.append(cursors);
+ mergeCursors();
+}
+
void MultiTextCursor::setCursors(const QList<QTextCursor> &cursors)
{
m_cursors = cursors;
diff --git a/src/libs/utils/multitextcursor.h b/src/libs/utils/multitextcursor.h
index 8fdf041faa0..4aaaee933ee 100644
--- a/src/libs/utils/multitextcursor.h
+++ b/src/libs/utils/multitextcursor.h
@@ -57,6 +57,7 @@ public:
/// the \param cursor that is appended by added by \brief addCursor
/// will be interpreted as the new main cursor
void addCursor(const QTextCursor &cursor);
+ void addCursors(const QList<QTextCursor> &cursors);
/// convenience function that removes the old main cursor and appends
/// \param cursor as the new main cursor
void replaceMainCursor(const QTextCursor &cursor);
diff --git a/src/libs/utils/namevaluedictionary.cpp b/src/libs/utils/namevaluedictionary.cpp
index 57eb2ffe995..364b6dc4003 100644
--- a/src/libs/utils/namevaluedictionary.cpp
+++ b/src/libs/utils/namevaluedictionary.cpp
@@ -25,10 +25,9 @@
#include "algorithm.h"
#include "namevaluedictionary.h"
+#include "namevalueitem.h"
#include "qtcassert.h"
-#include <QDir>
-
namespace Utils {
NameValueDictionary::NameValueDictionary(const QStringList &env, OsType osType)
diff --git a/src/libs/utils/namevaluedictionary.h b/src/libs/utils/namevaluedictionary.h
index 8023c97dfd1..7e302796705 100644
--- a/src/libs/utils/namevaluedictionary.h
+++ b/src/libs/utils/namevaluedictionary.h
@@ -25,7 +25,8 @@
#pragma once
-#include "fileutils.h"
+#include "utils_global.h"
+
#include "hostosinfo.h"
#include "namevalueitem.h"
@@ -100,6 +101,7 @@ public:
}
protected:
+ friend class Environment;
NameValueMap::iterator findKey(const QString &key);
const_iterator findKey(const QString &key) const;
diff --git a/src/libs/utils/namevalueitem.h b/src/libs/utils/namevalueitem.h
index 654b4be5bf8..e6c669c373f 100644
--- a/src/libs/utils/namevalueitem.h
+++ b/src/libs/utils/namevalueitem.h
@@ -25,6 +25,8 @@
#pragma once
+#include "utils_global.h"
+
#include "environmentfwd.h"
#include "utils_global.h"
diff --git a/src/libs/utils/namevaluemodel.cpp b/src/libs/utils/namevaluemodel.cpp
index 697a6b58117..d05f2f5b4af 100644
--- a/src/libs/utils/namevaluemodel.cpp
+++ b/src/libs/utils/namevaluemodel.cpp
@@ -25,11 +25,13 @@
#include "namevaluemodel.h"
-#include <utils/algorithm.h>
-#include <utils/hostosinfo.h>
-#include <utils/namevaluedictionary.h>
-#include <utils/qtcassert.h>
+#include "algorithm.h"
+#include "hostosinfo.h"
+#include "namevaluedictionary.h"
+#include "namevalueitem.h"
+#include "qtcassert.h"
+#include <QFileInfo>
#include <QFont>
#include <QGuiApplication>
#include <QPalette>
diff --git a/src/libs/utils/namevaluemodel.h b/src/libs/utils/namevaluemodel.h
index 6e6ddfc1773..9efe30f243e 100644
--- a/src/libs/utils/namevaluemodel.h
+++ b/src/libs/utils/namevaluemodel.h
@@ -25,9 +25,10 @@
#pragma once
-#include "environmentfwd.h"
#include "utils_global.h"
+#include "environmentfwd.h"
+
#include <QAbstractTableModel>
#include <memory>
diff --git a/src/libs/utils/namevaluesdialog.cpp b/src/libs/utils/namevaluesdialog.cpp
index 54c7a4577ea..0b8de22e6c8 100644
--- a/src/libs/utils/namevaluesdialog.cpp
+++ b/src/libs/utils/namevaluesdialog.cpp
@@ -25,8 +25,8 @@
#include "namevaluesdialog.h"
-#include <utils/environment.h>
-#include <utils/hostosinfo.h>
+#include "environment.h"
+#include "hostosinfo.h"
#include <QDialogButtonBox>
#include <QLabel>
diff --git a/src/libs/utils/namevaluesdialog.h b/src/libs/utils/namevaluesdialog.h
index e690c717d70..3b6132b2c24 100644
--- a/src/libs/utils/namevaluesdialog.h
+++ b/src/libs/utils/namevaluesdialog.h
@@ -25,10 +25,10 @@
#pragma once
-#include "environmentfwd.h"
+#include "utils_global.h"
+
#include "namevalueitem.h"
#include "optional.h"
-#include "utils_global.h"
#include <QDialog>
diff --git a/src/libs/utils/namevaluevalidator.cpp b/src/libs/utils/namevaluevalidator.cpp
index be4506b28df..57f3f569abb 100644
--- a/src/libs/utils/namevaluevalidator.cpp
+++ b/src/libs/utils/namevaluevalidator.cpp
@@ -32,7 +32,7 @@
namespace Utils {
NameValueValidator::NameValueValidator(QWidget *parent,
- Utils::NameValueModel *model,
+ NameValueModel *model,
QTreeView *view,
const QModelIndex &index,
const QString &toolTipText)
@@ -44,7 +44,7 @@ NameValueValidator::NameValueValidator(QWidget *parent,
{
m_hideTipTimer.setInterval(2000);
m_hideTipTimer.setSingleShot(true);
- connect(&m_hideTipTimer, &QTimer::timeout, this, []() { Utils::ToolTip::hide(); });
+ connect(&m_hideTipTimer, &QTimer::timeout, this, []() { ToolTip::hide(); });
}
QValidator::State NameValueValidator::validate(QString &in, int &pos) const
@@ -53,7 +53,7 @@ QValidator::State NameValueValidator::validate(QString &in, int &pos) const
QModelIndex idx = m_model->variableToIndex(in);
if (idx.isValid() && idx != m_index)
return QValidator::Intermediate;
- Utils::ToolTip::hide();
+ ToolTip::hide();
m_hideTipTimer.stop();
return QValidator::Acceptable;
}
@@ -65,8 +65,8 @@ void NameValueValidator::fixup(QString &input) const
if (!m_index.isValid())
return;
QPoint pos = m_view->mapToGlobal(m_view->visualRect(m_index).topLeft());
- pos -= Utils::ToolTip::offsetFromPosition();
- Utils::ToolTip::show(pos, m_toolTipText);
+ pos -= ToolTip::offsetFromPosition();
+ ToolTip::show(pos, m_toolTipText);
m_hideTipTimer.start();
// do nothing
}
diff --git a/src/libs/utils/namevaluevalidator.h b/src/libs/utils/namevaluevalidator.h
index c81dbe2e5bd..0d18e3385cc 100644
--- a/src/libs/utils/namevaluevalidator.h
+++ b/src/libs/utils/namevaluevalidator.h
@@ -25,22 +25,28 @@
#pragma once
-#include "environmentfwd.h"
#include "utils_global.h"
-#include <QModelIndex>
+#include "environmentfwd.h"
+
#include <QPersistentModelIndex>
#include <QTimer>
#include <QValidator>
+QT_BEGIN_NAMESPACE
+class QModelIndex;
+QT_END_NAMESPACE
+
namespace Utils {
+class NameValueModel;
+
class QTCREATOR_UTILS_EXPORT NameValueValidator : public QValidator
{
Q_OBJECT
public:
NameValueValidator(QWidget *parent,
- Utils::NameValueModel *model,
+ NameValueModel *model,
QTreeView *view,
const QModelIndex &index,
const QString &toolTipText);
@@ -51,7 +57,7 @@ public:
private:
const QString m_toolTipText;
- Utils::NameValueModel *m_model;
+ NameValueModel *m_model;
QTreeView *m_view;
QPersistentModelIndex m_index;
mutable QTimer m_hideTipTimer;
diff --git a/src/libs/utils/networkaccessmanager.h b/src/libs/utils/networkaccessmanager.h
index 4f09123aab2..91d23c84600 100644
--- a/src/libs/utils/networkaccessmanager.h
+++ b/src/libs/utils/networkaccessmanager.h
@@ -29,7 +29,9 @@
#include <QNetworkAccessManager>
-QT_FORWARD_DECLARE_CLASS(QUrl)
+QT_BEGIN_NAMESPACE
+class QUrl;
+QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp
index 8ae568204d2..d81ba32b935 100644
--- a/src/libs/utils/outputformatter.cpp
+++ b/src/libs/utils/outputformatter.cpp
@@ -34,7 +34,6 @@
#include "theme/theme.h"
#include <QDir>
-#include <QFileInfo>
#include <QPair>
#include <QPlainTextEdit>
#include <QPointer>
@@ -185,6 +184,15 @@ void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpec
match.capturedLength(capName));
}
+bool Utils::OutputLineParser::fileExists(const FilePath &fp) const
+{
+#ifdef WITH_TESTS
+ if (d->skipFileExistsCheck)
+ return !fp.isEmpty();
+#endif
+ return fp.exists();
+}
+
QString OutputLineParser::rightTrimmed(const QString &in)
{
int pos = in.length();
diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h
index f34b984ce8c..256e45bf4c3 100644
--- a/src/libs/utils/outputformatter.h
+++ b/src/libs/utils/outputformatter.h
@@ -26,7 +26,8 @@
#pragma once
#include "utils_global.h"
-#include "fileutils.h"
+
+#include "filepath.h"
#include "optional.h"
#include "outputformat.h"
@@ -115,6 +116,7 @@ protected:
static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath,
int lineNo, const QRegularExpressionMatch &match,
const QString &capName);
+ bool fileExists(const Utils::FilePath &fp) const;
signals:
void newSearchDirFound(const Utils::FilePath &dir);
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index e1bb3c4eb50..7a31cf8318d 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -27,13 +27,12 @@
#include "commandline.h"
#include "environment.h"
+#include "fileutils.h"
#include "hostosinfo.h"
#include "macroexpander.h"
#include "qtcassert.h"
#include "qtcprocess.h"
-#include "theme/theme.h"
-#include <QDebug>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QMenu>
@@ -153,7 +152,7 @@ QString BinaryVersionToolTipEventFilter::toolVersion(const CommandLine &cmd)
proc.setTimeoutS(1);
proc.setCommand(cmd);
proc.runBlocking();
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return QString();
return proc.allOutput();
}
@@ -179,7 +178,7 @@ class PathChooserPrivate
public:
PathChooserPrivate();
- FilePath expandedPath(const QString &path) const;
+ FilePath expandedPath(const FilePath &path) const;
QHBoxLayout *m_hLayout = nullptr;
FancyLineEdit *m_lineEdit = nullptr;
@@ -193,7 +192,7 @@ public:
EnvironmentChange m_environmentChange;
BinaryVersionToolTipEventFilter *m_binaryVersionToolTipEventFilter = nullptr;
QList<QAbstractButton *> m_buttons;
- MacroExpander *m_macroExpander = globalMacroExpander();
+ const MacroExpander *m_macroExpander = globalMacroExpander();
std::function<void()> m_openTerminal;
};
@@ -203,12 +202,12 @@ PathChooserPrivate::PathChooserPrivate()
{
}
-FilePath PathChooserPrivate::expandedPath(const QString &input) const
+FilePath PathChooserPrivate::expandedPath(const FilePath &input) const
{
if (input.isEmpty())
return {};
- FilePath path = FilePath::fromUserInput(input);
+ FilePath path = input;
Environment env = path.deviceEnvironment();
m_environmentChange.applyToEnvironment(env);
@@ -233,7 +232,7 @@ FilePath PathChooserPrivate::expandedPath(const QString &input) const
case PathChooser::File:
case PathChooser::SaveFile:
if (!m_baseDirectory.isEmpty()) {
- Utils::FilePath fp = m_baseDirectory.resolvePath(path.path()).absoluteFilePath();
+ FilePath fp = m_baseDirectory.resolvePath(path.path()).absoluteFilePath();
// FIXME bad hotfix for manually editing PathChooser (invalid paths, jumping cursor)
// examples: have an absolute path and try to change the device letter by typing the new
// letter and removing the original afterwards ends up in
@@ -354,7 +353,7 @@ FilePath PathChooser::rawFilePath() const
FilePath PathChooser::filePath() const
{
- return d->expandedPath(rawFilePath().toString());
+ return d->expandedPath(rawFilePath());
}
FilePath PathChooser::absoluteFilePath() const
@@ -530,11 +529,11 @@ FancyLineEdit::ValidationFunction PathChooser::defaultValidationFunction() const
bool PathChooser::validatePath(FancyLineEdit *edit, QString *errorMessage) const
{
- QString path = edit->text();
+ QString input = edit->text();
- if (path.isEmpty()) {
+ if (input.isEmpty()) {
if (!d->m_defaultValue.isEmpty()) {
- path = d->m_defaultValue;
+ input = d->m_defaultValue;
} else {
if (errorMessage)
*errorMessage = tr("The path must not be empty.");
@@ -542,10 +541,10 @@ bool PathChooser::validatePath(FancyLineEdit *edit, QString *errorMessage) const
}
}
- const FilePath filePath = d->expandedPath(path);
+ const FilePath filePath = d->expandedPath(FilePath::fromUserInput(input));
if (filePath.isEmpty()) {
if (errorMessage)
- *errorMessage = tr("The path \"%1\" expanded to an empty string.").arg(QDir::toNativeSeparators(path));
+ *errorMessage = tr("The path \"%1\" expanded to an empty string.").arg(input);
return false;
}
@@ -733,7 +732,7 @@ void PathChooser::setHistoryCompleter(const QString &historyKey, bool restoreLas
d->m_lineEdit->setHistoryCompleter(historyKey, restoreLastItemFromHistory);
}
-void PathChooser::setMacroExpander(MacroExpander *macroExpander)
+void PathChooser::setMacroExpander(const MacroExpander *macroExpander)
{
d->m_macroExpander = macroExpander;
}
diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h
index ddc68b227e5..698dc48951a 100644
--- a/src/libs/utils/pathchooser.h
+++ b/src/libs/utils/pathchooser.h
@@ -25,8 +25,10 @@
#pragma once
+#include "utils_global.h"
+
#include "fancylineedit.h"
-#include "fileutils.h"
+#include "filepath.h"
#include <QWidget>
@@ -35,11 +37,9 @@ class QAbstractButton;
class QLineEdit;
QT_END_NAMESPACE
-
namespace Utils {
class CommandLine;
-class FancyLineEdit;
class MacroExpander;
class Environment;
class EnvironmentChange;
@@ -126,7 +126,7 @@ public:
void setCommandVersionArguments(const QStringList &arguments);
// Utility to run a tool and return its stdout.
- static QString toolVersion(const Utils::CommandLine &cmd);
+ static QString toolVersion(const CommandLine &cmd);
// Install a tooltip on lineedits used for binaries showing the version.
static void installLineEditVersionToolTip(QLineEdit *le, const QStringList &arguments);
@@ -136,7 +136,7 @@ public:
// Sets a macro expander that is used when producing path and fileName.
// By default, the global expander is used.
// nullptr can be passed to disable macro expansion.
- void setMacroExpander(MacroExpander *macroExpander);
+ void setMacroExpander(const MacroExpander *macroExpander);
bool isReadOnly() const;
void setReadOnly(bool b);
diff --git a/src/libs/utils/pathlisteditor.cpp b/src/libs/utils/pathlisteditor.cpp
index d24be4995b5..9915a0db1f7 100644
--- a/src/libs/utils/pathlisteditor.cpp
+++ b/src/libs/utils/pathlisteditor.cpp
@@ -25,13 +25,9 @@
#include "pathlisteditor.h"
-#include "hostosinfo.h"
-#include "stringutils.h"
#include "fileutils.h"
+#include "hostosinfo.h"
-#include <QDebug>
-#include <QFileDialog>
-#include <QMenu>
#include <QMimeData>
#include <QPlainTextEdit>
#include <QPushButton>
@@ -196,6 +192,11 @@ void PathListEditor::setFileDialogTitle(const QString &l)
d->fileDialogTitle = l;
}
+void PathListEditor::setPlaceholderText(const QString &placeholder)
+{
+ d->edit->setPlaceholderText(placeholder);
+}
+
void PathListEditor::clear()
{
d->edit->clear();
diff --git a/src/libs/utils/pathlisteditor.h b/src/libs/utils/pathlisteditor.h
index edd70336c09..a7c61448d18 100644
--- a/src/libs/utils/pathlisteditor.h
+++ b/src/libs/utils/pathlisteditor.h
@@ -57,6 +57,7 @@ public:
void setPathList(const QStringList &l);
void setPathList(const QString &pathString);
void setFileDialogTitle(const QString &l);
+ void setPlaceholderText(const QString &placeholder);
signals:
void changed();
diff --git a/src/libs/utils/persistentsettings.cpp b/src/libs/utils/persistentsettings.cpp
index 491d2874d00..7d3fdc697b6 100644
--- a/src/libs/utils/persistentsettings.cpp
+++ b/src/libs/utils/persistentsettings.cpp
@@ -25,24 +25,25 @@
#include "persistentsettings.h"
+#include "fileutils.h"
+#include "qtcassert.h"
+
+#include <QCoreApplication>
+#include <QDateTime>
#include <QDebug>
#include <QDir>
+#include <QRect>
+#include <QRegularExpression>
#include <QStack>
+#include <QTextStream>
#include <QXmlStreamAttributes>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
-#include <QDateTime>
-#include <QTextStream>
-#include <QRegularExpression>
-#include <QRect>
#ifdef QT_GUI_LIB
#include <QMessageBox>
#endif
-#include <utils/porting.h>
-#include <utils/qtcassert.h>
-
// Read and write rectangle in X11 resource syntax "12x12+4+3"
static QString rectangleToString(const QRect &r)
{
diff --git a/src/libs/utils/persistentsettings.h b/src/libs/utils/persistentsettings.h
index 20802ea2630..9ffb8191552 100644
--- a/src/libs/utils/persistentsettings.h
+++ b/src/libs/utils/persistentsettings.h
@@ -25,9 +25,10 @@
#pragma once
-#include "fileutils.h"
#include "utils_global.h"
+#include "filepath.h"
+
#include <QVariant>
QT_BEGIN_NAMESPACE
diff --git a/src/libs/utils/port.cpp b/src/libs/utils/port.cpp
index c4f3af18888..15a45f84244 100644
--- a/src/libs/utils/port.cpp
+++ b/src/libs/utils/port.cpp
@@ -25,8 +25,46 @@
#include "port.h"
+#include "stringutils.h"
+
/*! \class Utils::Port
\brief The Port class implements a wrapper around a 16 bit port number
to be used in conjunction with IP addresses.
*/
+
+namespace Utils {
+
+QList<Port> Port::parseFromSedOutput(const QByteArray &output)
+{
+ QList<Port> ports;
+ const QList<QByteArray> portStrings = output.split('\n');
+ for (const QByteArray &portString : portStrings) {
+ if (portString.size() != 4)
+ continue;
+ bool ok;
+ const Port port(portString.toInt(&ok, 16));
+ if (ok) {
+ if (!ports.contains(port))
+ ports << port;
+ } else {
+ qWarning("%s: Unexpected string '%s' is not a port.",
+ Q_FUNC_INFO, portString.data());
+ }
+ }
+ return ports;
+}
+
+QList<Port> Port::parseFromNetstatOutput(const QByteArray &output)
+{
+ QList<Port> ports;
+ const QList<QByteArray> lines = output.split('\n');
+ for (const QByteArray &line : lines) {
+ const Port port(parseUsedPortFromNetstatOutput(line));
+ if (port.isValid() && !ports.contains(port))
+ ports.append(port);
+ }
+ return ports;
+}
+
+} // Utils
diff --git a/src/libs/utils/port.h b/src/libs/utils/port.h
index 56d0b646dc0..3d88d99328d 100644
--- a/src/libs/utils/port.h
+++ b/src/libs/utils/port.h
@@ -26,9 +26,11 @@
#pragma once
#include "utils_global.h"
+
#include "qtcassert.h"
#include <QMetaType>
+#include <QList>
#include <QString>
#include <limits>
@@ -55,6 +57,9 @@ public:
QString toString() const { return QString::number(m_port); }
+ static QList<Port> parseFromSedOutput(const QByteArray &output);
+ static QList<Port> parseFromNetstatOutput(const QByteArray &output);
+
private:
int m_port = -1;
};
diff --git a/src/libs/utils/porting.h b/src/libs/utils/porting.h
index f8d945a0c41..8b13e366180 100644
--- a/src/libs/utils/porting.h
+++ b/src/libs/utils/porting.h
@@ -34,13 +34,6 @@
namespace Utils {
-#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
-// Keep the support code for lower Qt versions for sdktool
-constexpr QString::SplitBehavior SkipEmptyParts = QString::SkipEmptyParts;
-#else
-constexpr Qt::SplitBehaviorFlags SkipEmptyParts = Qt::SkipEmptyParts;
-#endif
-
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
using QHashValueType = uint;
#else
@@ -71,9 +64,8 @@ inline StringView make_stringview(const QString &s)
#endif
}
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
// QStringView::mid in Qt5 does not do bounds checking, in Qt6 it does
-inline QStringView midView(const QString &s, int offset, int length)
+inline QStringView midView(const QString &s, int offset, int length = -1)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
const int size = s.size();
@@ -85,14 +77,13 @@ inline QStringView midView(const QString &s, int offset, int length)
if (length + offset <= 0)
return {};
return QStringView(s).left(length + offset);
- } else if (length > size - offset)
+ } else if (length < 0 || length > size - offset)
return QStringView(s).mid(offset);
return QStringView(s).mid(offset, length);
#else
return QStringView(s).mid(offset, length);
#endif
}
-#endif
#ifdef QT_GUI_LIB
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
diff --git a/src/libs/utils/portlist.cpp b/src/libs/utils/portlist.cpp
index 3abc4d8b05c..f57137ccf59 100644
--- a/src/libs/utils/portlist.cpp
+++ b/src/libs/utils/portlist.cpp
@@ -27,7 +27,6 @@
#include <QPair>
#include <QString>
-#include <QStringList>
#include <cctype>
diff --git a/src/libs/utils/portlist.h b/src/libs/utils/portlist.h
index 49adf3ae0ba..3b0bbf7958a 100644
--- a/src/libs/utils/portlist.h
+++ b/src/libs/utils/portlist.h
@@ -26,9 +26,12 @@
#pragma once
#include "utils_global.h"
+
#include "port.h"
-QT_FORWARD_DECLARE_CLASS(QString)
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
namespace Utils {
namespace Internal { class PortListPrivate; }
diff --git a/src/libs/utils/process_ctrlc_stub.cpp b/src/libs/utils/process_ctrlc_stub.cpp
index 33694d64487..8abd3bca206 100644
--- a/src/libs/utils/process_ctrlc_stub.cpp
+++ b/src/libs/utils/process_ctrlc_stub.cpp
@@ -167,13 +167,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == uiShutDownWindowMessage) {
SetConsoleCtrlHandler(interruptHandler, FALSE);
- SetConsoleCtrlHandler(shutdownHandler, TRUE);
- GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
PostQuitMessage(0);
return 0;
} else if (message == uiInterruptMessage) {
SetConsoleCtrlHandler(interruptHandler, TRUE);
- SetConsoleCtrlHandler(shutdownHandler, FALSE);
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
return 0;
}
@@ -194,12 +191,6 @@ bool isSpaceOrTab(const wchar_t c)
return c == L' ' || c == L'\t';
}
-BOOL WINAPI shutdownHandler(DWORD /*dwCtrlType*/)
-{
- PostMessage(hwndMain, WM_DESTROY, 0, 0);
- return TRUE;
-}
-
BOOL WINAPI interruptHandler(DWORD /*dwCtrlType*/)
{
return TRUE;
diff --git a/src/libs/utils/processenums.h b/src/libs/utils/processenums.h
new file mode 100644
index 00000000000..f755a812eaa
--- /dev/null
+++ b/src/libs/utils/processenums.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QMetaType>
+
+#include <functional>
+
+namespace Utils {
+
+enum class ProcessMode {
+ Reader, // This opens in ReadOnly mode if no write data or in ReadWrite mode otherwise,
+ // closes the write channel afterwards.
+ Writer // This opens in ReadWrite mode and doesn't close the write channel
+};
+
+enum class ProcessImpl {
+ QProcess,
+ ProcessLauncher,
+ Default // Defaults to ProcessLauncherImpl, if QTC_USE_QPROCESS env var is set
+ // it equals to QProcessImpl.
+};
+
+enum class TerminalMode {
+ Off,
+ Run,
+ Debug,
+ Suspend,
+ On = Run // Default mode for terminal set to on
+};
+
+// Miscellaneous, not process core
+
+enum class EventLoopMode {
+ Off,
+ On // Avoid
+};
+
+enum class ProcessResult {
+ // Finished successfully. Unless an ExitCodeInterpreter is set
+ // this corresponds to a return code 0.
+ FinishedWithSuccess,
+ // Finished unsuccessfully. Unless an ExitCodeInterpreter is set
+ // this corresponds to a return code different from 0.
+ FinishedWithError,
+ // Process terminated abnormally (kill)
+ TerminatedAbnormally,
+ // Executable could not be started
+ StartFailed,
+ // Hang, no output after time out
+ Hang
+};
+
+using ExitCodeInterpreter = std::function<ProcessResult(int /*exitCode*/)>;
+
+} // namespace Utils
+
+Q_DECLARE_METATYPE(Utils::ProcessMode);
diff --git a/src/libs/utils/processhandle.h b/src/libs/utils/processhandle.h
index 7b5bb639238..f1d2299bdc3 100644
--- a/src/libs/utils/processhandle.h
+++ b/src/libs/utils/processhandle.h
@@ -41,17 +41,17 @@ public:
void setPid(qint64 pid);
qint64 pid() const;
- bool equals(const ProcessHandle &) const;
-
bool activate();
private:
+ bool equals(const ProcessHandle &) const;
+
+ friend bool operator==(const ProcessHandle &p, const ProcessHandle &q) { return p.equals(q); }
+ friend bool operator!=(const ProcessHandle &p, const ProcessHandle &q) { return !p.equals(q); }
+
qint64 m_pid;
};
-inline bool operator==(const ProcessHandle &p1, const ProcessHandle &p2) { return p1.equals(p2); }
-inline bool operator!=(const ProcessHandle &p1, const ProcessHandle &p2) { return !p1.equals(p2); }
-
} // Utils
Q_DECLARE_METATYPE(Utils::ProcessHandle)
diff --git a/src/libs/utils/processinfo.cpp b/src/libs/utils/processinfo.cpp
new file mode 100644
index 00000000000..8508e85197b
--- /dev/null
+++ b/src/libs/utils/processinfo.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "processinfo.h"
+
+#include "qtcprocess.h"
+
+#if defined(Q_OS_UNIX)
+#include <QDir>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#elif defined(Q_OS_WIN)
+#include "winutils.h"
+#include <windows.h>
+#include <tlhelp32.h>
+#include <psapi.h>
+#endif
+
+namespace Utils {
+
+bool ProcessInfo::operator<(const ProcessInfo &other) const
+{
+ if (processId != other.processId)
+ return processId < other.processId;
+ if (executable != other.executable)
+ return executable < other.executable;
+ return commandLine < other.commandLine;
+}
+
+#if defined(Q_OS_UNIX)
+
+static bool isUnixProcessId(const QString &procname)
+{
+ for (int i = 0; i != procname.size(); ++i)
+ if (!procname.at(i).isDigit())
+ return false;
+ return true;
+}
+
+// Determine UNIX processes by reading "/proc". Default to ps if
+// it does not exist
+
+static const char procDirC[] = "/proc/";
+
+static QList<ProcessInfo> getLocalProcessesUsingProc()
+{
+ QList<ProcessInfo> processes;
+ const QString procDirPath = QLatin1String(procDirC);
+ const QDir procDir = QDir(QLatin1String(procDirC));
+ const QStringList procIds = procDir.entryList();
+ for (const QString &procId : procIds) {
+ if (!isUnixProcessId(procId))
+ continue;
+ ProcessInfo proc;
+ proc.processId = procId.toInt();
+ const QString root = procDirPath + procId;
+
+ const QFile exeFile(root + QLatin1String("/exe"));
+ proc.executable = exeFile.symLinkTarget();
+
+ QFile cmdLineFile(root + QLatin1String("/cmdline"));
+ if (cmdLineFile.open(QIODevice::ReadOnly)) { // process may have exited
+ const QList<QByteArray> tokens = cmdLineFile.readAll().split('\0');
+ if (!tokens.isEmpty()) {
+ if (proc.executable.isEmpty())
+ proc.executable = QString::fromLocal8Bit(tokens.front());
+ for (const QByteArray &t : tokens) {
+ if (!proc.commandLine.isEmpty())
+ proc.commandLine.append(QLatin1Char(' '));
+ proc.commandLine.append(QString::fromLocal8Bit(t));
+ }
+ }
+ }
+
+ if (proc.executable.isEmpty()) {
+ QFile statFile(root + QLatin1String("/stat"));
+ if (statFile.open(QIODevice::ReadOnly)) {
+ const QStringList data = QString::fromLocal8Bit(statFile.readAll()).split(QLatin1Char(' '));
+ if (data.size() < 2)
+ continue;
+ proc.executable = data.at(1);
+ proc.commandLine = data.at(1); // PPID is element 3
+ if (proc.executable.startsWith(QLatin1Char('(')) && proc.executable.endsWith(QLatin1Char(')'))) {
+ proc.executable.truncate(proc.executable.size() - 1);
+ proc.executable.remove(0, 1);
+ }
+ }
+ }
+ if (!proc.executable.isEmpty())
+ processes.push_back(proc);
+ }
+ return processes;
+}
+
+// Determine UNIX processes by running ps
+static QMap<qint64, QString> getLocalProcessDataUsingPs(const QString &column)
+{
+ QMap<qint64, QString> result;
+ Utils::QtcProcess psProcess;
+ psProcess.setCommand({"ps", {"-e", "-o", "pid," + column}});
+ psProcess.start();
+ if (psProcess.waitForStarted()) {
+ QByteArray output;
+ if (psProcess.readDataFromProcess(30, &output, nullptr, false)) {
+ // Split "457 /Users/foo.app arg1 arg2"
+ const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
+ const int lineCount = lines.size();
+ const QChar blank = QLatin1Char(' ');
+ for (int l = 1; l < lineCount; l++) { // Skip header
+ const QString line = lines.at(l).trimmed();
+ const int pidSep = line.indexOf(blank);
+ const qint64 pid = line.left(pidSep).toLongLong();
+ result[pid] = line.mid(pidSep + 1);
+ }
+ }
+ }
+ return result;
+}
+
+static QList<ProcessInfo> getLocalProcessesUsingPs()
+{
+ QList<ProcessInfo> processes;
+
+ // cmdLines are full command lines, usually with absolute path,
+ // exeNames only the file part of the executable's path.
+ const QMap<qint64, QString> exeNames = getLocalProcessDataUsingPs("comm");
+ const QMap<qint64, QString> cmdLines = getLocalProcessDataUsingPs("args");
+
+ for (auto it = exeNames.begin(), end = exeNames.end(); it != end; ++it) {
+ const qint64 pid = it.key();
+ if (pid <= 0)
+ continue;
+ const QString cmdLine = cmdLines.value(pid);
+ if (cmdLines.isEmpty())
+ continue;
+ const QString exeName = it.value();
+ if (exeName.isEmpty())
+ continue;
+ const int pos = cmdLine.indexOf(exeName);
+ if (pos == -1)
+ continue;
+ processes.append({pid, cmdLine.left(pos + exeName.size()), cmdLine});
+ }
+
+ return processes;
+}
+
+QList<ProcessInfo> ProcessInfo::processInfoList()
+{
+ const QDir procDir = QDir(QLatin1String(procDirC));
+ return procDir.exists() ? getLocalProcessesUsingProc() : getLocalProcessesUsingPs();
+}
+
+#elif defined(Q_OS_WIN)
+
+QList<ProcessInfo> ProcessInfo::processInfoList()
+{
+ QList<ProcessInfo> processes;
+
+ PROCESSENTRY32 pe;
+ pe.dwSize = sizeof(PROCESSENTRY32);
+ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snapshot == INVALID_HANDLE_VALUE)
+ return processes;
+
+ for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) {
+ ProcessInfo p;
+ p.processId = pe.th32ProcessID;
+ // Image has the absolute path, but can fail.
+ const QString image = imageName(pe.th32ProcessID);
+ p.executable = p.commandLine = image.isEmpty() ?
+ QString::fromWCharArray(pe.szExeFile) : image;
+ processes << p;
+ }
+ CloseHandle(snapshot);
+ return processes;
+}
+
+#endif //Q_OS_WIN
+
+} // namespace Utils
diff --git a/src/libs/utils/processinfo.h b/src/libs/utils/processinfo.h
new file mode 100644
index 00000000000..807adcefaa8
--- /dev/null
+++ b/src/libs/utils/processinfo.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "utils_global.h"
+
+#include <QList>
+#include <QString>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT ProcessInfo
+{
+public:
+ qint64 processId = 0;
+ QString executable;
+ QString commandLine;
+
+ bool operator<(const ProcessInfo &other) const;
+
+ static QList<ProcessInfo> processInfoList();
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/processinterface.cpp b/src/libs/utils/processinterface.cpp
new file mode 100644
index 00000000000..60c3676d2f5
--- /dev/null
+++ b/src/libs/utils/processinterface.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "processinterface.h"
+
+#include "qtcassert.h"
+
+namespace Utils {
+
+/*!
+ * \brief controlSignalToInt
+ * \param controlSignal
+ * \return Converts the ControlSignal enum to the corresponding unix signal
+ */
+int ProcessInterface::controlSignalToInt(ControlSignal controlSignal)
+{
+ switch (controlSignal) {
+ case ControlSignal::Terminate: return 15;
+ case ControlSignal::Kill: return 9;
+ case ControlSignal::Interrupt: return 2;
+ case ControlSignal::KickOff: QTC_CHECK(false); return 0;
+ }
+ return 0;
+}
+
+} // Utils
diff --git a/src/libs/utils/processinterface.h b/src/libs/utils/processinterface.h
new file mode 100644
index 00000000000..0ca1cc1f15d
--- /dev/null
+++ b/src/libs/utils/processinterface.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "utils_global.h"
+
+#include "environment.h"
+#include "commandline.h"
+#include "processenums.h"
+
+#include <QProcess>
+
+namespace Utils {
+
+namespace Internal { class QtcProcessPrivate; }
+
+class QTCREATOR_UTILS_EXPORT ProcessSetupData
+{
+public:
+ ProcessImpl m_processImpl = ProcessImpl::Default;
+ ProcessMode m_processMode = ProcessMode::Reader;
+ TerminalMode m_terminalMode = TerminalMode::Off;
+
+ CommandLine m_commandLine;
+ FilePath m_workingDirectory;
+ Environment m_environment;
+ Environment m_controlEnvironment;
+ QByteArray m_writeData;
+ QProcess::ProcessChannelMode m_processChannelMode = QProcess::SeparateChannels;
+ QVariantHash m_extraData;
+ QString m_standardInputFile;
+ QString m_nativeArguments; // internal, dependent on specific code path
+
+ int m_reaperTimeout = 500; // in ms
+ bool m_abortOnMetaChars = true;
+ bool m_runAsRoot = false;
+ bool m_lowPriority = false;
+ bool m_unixTerminalDisabled = false;
+ bool m_useCtrlCStub = false;
+ bool m_belowNormalPriority = false; // internal, dependent on other fields and specific code path
+};
+
+class QTCREATOR_UTILS_EXPORT ProcessResultData
+{
+public:
+ int m_exitCode = 0;
+ QProcess::ExitStatus m_exitStatus = QProcess::NormalExit;
+ QProcess::ProcessError m_error = QProcess::UnknownError;
+ QString m_errorString;
+};
+
+enum class ControlSignal {
+ Terminate,
+ Kill,
+ Interrupt,
+ KickOff
+};
+
+enum class ProcessSignalType {
+ Started,
+ ReadyRead,
+ Done
+};
+
+class QTCREATOR_UTILS_EXPORT ProcessBlockingInterface : public QObject
+{
+private:
+ // Wait for:
+ // - Started is being called only in Starting state.
+ // - ReadyRead is being called in Starting or Running state.
+ // - Done is being called in Starting or Running state.
+ virtual bool waitForSignal(ProcessSignalType signalType, int msecs) = 0;
+
+ friend class Internal::QtcProcessPrivate;
+};
+
+class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject
+{
+ Q_OBJECT
+
+signals:
+ // This should be emitted when being in Starting state only.
+ // After emitting this signal the process enters Running state.
+ void started(qint64 processId, qint64 applicationMainThreadId = 0);
+
+ // This should be emitted when being in Running state only.
+ void readyRead(const QByteArray &outputData, const QByteArray &errorData);
+
+ // This should be emitted when being in Starting or Running state.
+ // When being in Starting state, the resultData should set error to FailedToStart.
+ // After emitting this signal the process enters NotRunning state.
+ void done(const ProcessResultData &resultData);
+
+protected:
+ static int controlSignalToInt(ControlSignal controlSignal);
+
+ ProcessSetupData m_setup;
+
+private:
+ // It's being called only in Starting state. Just before this method is being called,
+ // the process transitions from NotRunning into Starting state.
+ virtual void start() = 0;
+
+ // It's being called only in Running state.
+ virtual qint64 write(const QByteArray &data) = 0;
+
+ // It's being called in Starting or Running state.
+ virtual void sendControlSignal(ControlSignal controlSignal) = 0;
+
+ virtual ProcessBlockingInterface *processBlockingInterface() const { return nullptr; }
+
+ friend class QtcProcess;
+ friend class Internal::QtcProcessPrivate;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/processreaper.cpp b/src/libs/utils/processreaper.cpp
index 3ff060be548..783644c4132 100644
--- a/src/libs/utils/processreaper.cpp
+++ b/src/libs/utils/processreaper.cpp
@@ -24,152 +24,238 @@
****************************************************************************/
#include "processreaper.h"
+#include "processutils.h"
#include "qtcassert.h"
#include <QCoreApplication>
+#include <QDebug>
+#include <QElapsedTimer>
#include <QProcess>
-#include <QThread>
#include <QTimer>
-
-#ifdef Q_OS_WIN
-#ifdef QTCREATOR_PCH_H
-#define CALLBACK WINAPI
-#endif
-#include <qt_windows.h>
-#endif
+#include <QWaitCondition>
using namespace Utils;
namespace Utils {
namespace Internal {
-class Reaper final : public QObject
-{
-public:
- Reaper(QProcess *p, int timeoutMs);
- ~Reaper() final;
+/*
- int timeoutMs() const;
- bool isFinished() const;
- void nextIteration();
+Observations on how QProcess::terminate() behaves on different platforms when called for
+never ending running process:
-private:
- mutable QTimer m_iterationTimer;
- QProcess *m_process = nullptr;
- int m_emergencyCounter = 0;
- QProcess::ProcessState m_lastState = QProcess::NotRunning;
-};
+1. Windows:
-static QList<Reaper *> g_reapers;
+ The issue in QTCREATORBUG-27118 with adb.exe is most probably a special
+ Windows only case described in docs of QProcess::terminate():
-Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p)
-{
- g_reapers.append(this);
+ "Console applications on Windows that do not run an event loop, or whose event loop does
+ not handle the WM_CLOSE message, can only be terminated by calling kill()."
- m_iterationTimer.setInterval(timeoutMs);
- m_iterationTimer.setSingleShot(true);
- connect(&m_iterationTimer, &QTimer::timeout, this, &Reaper::nextIteration);
+ It looks like when you call terminate() for the adb.exe, it won't stop, never, even after
+ default 30 seconds timeout. The same happens for blocking processes tested in
+ tst_QtcProcess::killBlockingProcess(). It's hard to say whether any process on Windows can
+ be finished by a call to terminate(). Until now, no such a process has been found.
- QMetaObject::invokeMethod(this, &Reaper::nextIteration, Qt::QueuedConnection);
-}
+ Further call to kill() (after a call to terminate()) finishes the process quickly.
-Reaper::~Reaper()
-{
- g_reapers.removeOne(this);
-}
+2. Linux:
-int Reaper::timeoutMs() const
-{
- const int remaining = m_iterationTimer.remainingTime();
- if (remaining < 0)
- return m_iterationTimer.interval();
- m_iterationTimer.stop();
- return remaining;
-}
+ It looks like a call to terminate() finishes the running process after a long wait
+ (between 10-15 seconds). After calling terminate(), further calls to kill() doesn't
+ make the process to finish soon (are no-op). On the other hand, when we start reaping the
+ running process from a call to kill() without a prior call to terminate(), the process
+ finishes quickly.
+
+3. Mac:
+
+ It looks like the process finishes quickly after a call to terminate().
-bool Reaper::isFinished() const
+*/
+
+static const int s_timeoutThreshold = 10000; // 10 seconds
+
+static QString execWithArguments(QProcess *process)
{
- return !m_process;
+ QStringList commandLine;
+ commandLine.append(process->program());
+ commandLine.append(process->arguments());
+ return commandLine.join(QChar::Space);
}
-#ifdef Q_OS_WIN
-static BOOL sendMessage(UINT message, HWND hwnd, LPARAM lParam)
+struct ReaperSetup
{
- DWORD dwProcessID;
- GetWindowThreadProcessId(hwnd, &dwProcessID);
- if ((DWORD)lParam == dwProcessID) {
- SendNotifyMessage(hwnd, message, 0, 0);
- return FALSE;
- }
- return TRUE;
-}
+ QProcess *m_process = nullptr;
+ int m_timeoutMs;
+};
-BOOL CALLBACK sendShutDownMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARAM lParam)
+class Reaper : public QObject
{
- static UINT uiShutDownMessage = RegisterWindowMessage(L"qtcctrlcstub_shutdown");
- return sendMessage(uiShutDownMessage, hwnd, lParam);
-}
+ Q_OBJECT
-#endif
+public:
+ Reaper(const ReaperSetup &reaperSetup) : m_reaperSetup(reaperSetup) {}
-void Reaper::nextIteration()
-{
- QProcess::ProcessState state = m_process ? m_process->state() : QProcess::NotRunning;
- if (state == QProcess::NotRunning || m_emergencyCounter > 5) {
- delete m_process;
- m_process = nullptr;
- return;
+ void reap()
+ {
+ m_timer.start();
+
+ connect(m_reaperSetup.m_process,
+ QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ this, &Reaper::handleFinished);
+
+ if (emitFinished())
+ return;
+
+ terminate();
}
- if (state == QProcess::Starting) {
- if (m_lastState == QProcess::Starting)
- m_process->kill();
- } else if (state == QProcess::Running) {
- if (m_lastState == QProcess::Running) {
- m_process->kill();
- } else if (m_process->program().endsWith(QLatin1String("qtcreator_ctrlc_stub.exe"))) {
-#ifdef Q_OS_WIN
- EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, m_process->processId());
-#endif
- } else {
- m_process->terminate();
+signals:
+ void finished();
+
+private:
+ void terminate()
+ {
+ ProcessHelper::terminateProcess(m_reaperSetup.m_process);
+ QTimer::singleShot(m_reaperSetup.m_timeoutMs, this, &Reaper::handleTerminateTimeout);
+ }
+
+ void kill() { m_reaperSetup.m_process->kill(); }
+
+ bool emitFinished()
+ {
+ if (m_reaperSetup.m_process->state() != QProcess::NotRunning)
+ return false;
+
+ if (!m_finished) {
+ const int timeout = m_timer.elapsed();
+ if (timeout > s_timeoutThreshold) {
+ qWarning() << "Finished parallel reaping of" << execWithArguments(m_reaperSetup.m_process)
+ << "in" << (timeout / 1000.0) << "seconds.";
+ }
+
+ m_finished = true;
+ emit finished();
}
+ return true;
}
- m_lastState = state;
- m_iterationTimer.start();
+ void handleFinished()
+ {
+ // In case the process is still running - wait until it has finished
+ QTC_ASSERT(emitFinished(), QTimer::singleShot(m_reaperSetup.m_timeoutMs,
+ this, &Reaper::handleFinished));
+ }
- ++m_emergencyCounter;
-}
+ void handleTerminateTimeout()
+ {
+ if (emitFinished())
+ return;
-} // namespace Internal
+ kill();
+ }
-ProcessReaper::~ProcessReaper()
+ bool m_finished = false;
+ QElapsedTimer m_timer;
+ const ReaperSetup m_reaperSetup;
+};
+
+class ProcessReaperPrivate : public QObject
{
- while (!Internal::g_reapers.isEmpty()) {
- int alreadyWaited = 0;
- QList<Internal::Reaper *> toDelete;
-
- // push reapers along:
- for (Internal::Reaper *pr : qAsConst(Internal::g_reapers)) {
- const int timeoutMs = pr->timeoutMs();
- if (alreadyWaited < timeoutMs) {
- const unsigned long toSleep = static_cast<unsigned long>(timeoutMs - alreadyWaited);
- QThread::msleep(toSleep);
- QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
- alreadyWaited += toSleep;
- }
+ Q_OBJECT
- pr->nextIteration();
+public:
+ // Called from non-reaper's thread
+ void scheduleReap(const ReaperSetup &reaperSetup)
+ {
+ QTC_CHECK(QThread::currentThread() != thread());
+ QMutexLocker locker(&m_mutex);
+ m_reaperSetupList.append(reaperSetup);
+ QMetaObject::invokeMethod(this, &ProcessReaperPrivate::flush);
+ }
+
+ // Called from non-reaper's thread
+ void waitForFinished()
+ {
+ QTC_CHECK(QThread::currentThread() != thread());
+ QMetaObject::invokeMethod(this, &ProcessReaperPrivate::flush,
+ Qt::BlockingQueuedConnection);
+ QMutexLocker locker(&m_mutex);
+ if (m_reaperList.isEmpty())
+ return;
+
+ m_waitCondition.wait(&m_mutex);
+ }
+
+private:
+ // All the private methods are called from the reaper's thread
+ QList<ReaperSetup> takeReaperSetupList()
+ {
+ QMutexLocker locker(&m_mutex);
+ const QList<ReaperSetup> reaperSetupList = m_reaperSetupList;
+ m_reaperSetupList.clear();
+ return reaperSetupList;
+ }
+
+ void flush()
+ {
+ while (true) {
+ const QList<ReaperSetup> reaperSetupList = takeReaperSetupList();
+ if (reaperSetupList.isEmpty())
+ return;
+ for (const ReaperSetup &reaperSetup : reaperSetupList)
+ reap(reaperSetup);
+ }
+ }
- if (pr->isFinished())
- toDelete.append(pr);
+ void reap(const ReaperSetup &reaperSetup)
+ {
+ Reaper *reaper = new Reaper(reaperSetup);
+ connect(reaper, &Reaper::finished, this, [this, reaper, process = reaperSetup.m_process] {
+ QMutexLocker locker(&m_mutex);
+ QTC_CHECK(m_reaperList.removeOne(reaper));
+ delete reaper;
+ delete process;
+ if (m_reaperList.isEmpty())
+ m_waitCondition.wakeOne();
+ }, Qt::QueuedConnection);
+
+ {
+ QMutexLocker locker(&m_mutex);
+ m_reaperList.append(reaper);
}
- // Clean out reapers that finished in the meantime
- qDeleteAll(toDelete);
- toDelete.clear();
+ reaper->reap();
}
+
+ QMutex m_mutex;
+ QWaitCondition m_waitCondition;
+ QList<ReaperSetup> m_reaperSetupList;
+ QList<Reaper *> m_reaperList;
+};
+
+} // namespace Internal
+
+using namespace Utils::Internal;
+
+static QMutex s_instanceMutex;
+
+ProcessReaper::ProcessReaper()
+ : m_private(new ProcessReaperPrivate())
+{
+ m_private->moveToThread(&m_thread);
+ QObject::connect(&m_thread, &QThread::finished, m_private, &QObject::deleteLater);
+ m_thread.start();
+ m_thread.moveToThread(qApp->thread());
+}
+
+ProcessReaper::~ProcessReaper()
+{
+ QTC_CHECK(QThread::currentThread() == qApp->thread());
+ QMutexLocker locker(&s_instanceMutex);
+ instance()->m_private->waitForFinished();
+ m_thread.quit();
+ m_thread.wait();
}
void ProcessReaper::reap(QProcess *process, int timeoutMs)
@@ -177,27 +263,26 @@ void ProcessReaper::reap(QProcess *process, int timeoutMs)
if (!process)
return;
- QTC_ASSERT(QThread::currentThread() == process->thread(), return );
+ QTC_ASSERT(QThread::currentThread() == process->thread(), return);
process->disconnect();
if (process->state() == QProcess::NotRunning) {
process->deleteLater();
return;
}
+
// Neither can move object with a parent into a different thread
// nor reaping the process with a parent makes any sense.
process->setParent(nullptr);
- if (process->thread() != QCoreApplication::instance()->thread()) {
- process->moveToThread(QCoreApplication::instance()->thread());
- QMetaObject::invokeMethod(process, [process, timeoutMs] {
- reap(process, timeoutMs);
- }); // will be queued
- return;
- }
- ProcessReaper::instance();
- new Internal::Reaper(process, timeoutMs);
+ QMutexLocker locker(&s_instanceMutex);
+ ProcessReaperPrivate *priv = instance()->m_private;
+
+ process->moveToThread(priv->thread());
+ ReaperSetup reaperSetup {process, timeoutMs};
+ priv->scheduleReap(reaperSetup);
}
} // namespace Utils
+#include "processreaper.moc"
diff --git a/src/libs/utils/processreaper.h b/src/libs/utils/processreaper.h
index 64886312990..f56de5f155b 100644
--- a/src/libs/utils/processreaper.h
+++ b/src/libs/utils/processreaper.h
@@ -29,11 +29,14 @@
#include "singleton.h"
+#include <QThread>
+
QT_BEGIN_NAMESPACE
class QProcess;
QT_END_NAMESPACE
namespace Utils {
+namespace Internal { class ProcessReaperPrivate; }
class QTCREATOR_UTILS_EXPORT ProcessReaper final
: public SingletonWithOptionalDependencies<ProcessReaper>
@@ -42,8 +45,11 @@ public:
static void reap(QProcess *process, int timeoutMs = 500);
private:
- ProcessReaper() = default;
+ ProcessReaper();
~ProcessReaper();
+
+ QThread m_thread;
+ Internal::ProcessReaperPrivate *m_private;
friend class SingletonWithOptionalDependencies<ProcessReaper>;
};
diff --git a/src/libs/utils/processutils.cpp b/src/libs/utils/processutils.cpp
index 1f57fc15d1f..3019bcd2c82 100644
--- a/src/libs/utils/processutils.cpp
+++ b/src/libs/utils/processutils.cpp
@@ -26,6 +26,9 @@
#include "processutils.h"
#ifdef Q_OS_WIN
+#ifdef QTCREATOR_PCH_H
+#define CALLBACK WINAPI
+#endif
#include <qt_windows.h>
#else
#include <errno.h>
@@ -82,6 +85,72 @@ void ProcessStartHandler::setNativeArguments(const QString &arguments)
#endif // Q_OS_WIN
}
+#ifdef Q_OS_WIN
+static BOOL sendMessage(UINT message, HWND hwnd, LPARAM lParam)
+{
+ DWORD dwProcessID;
+ GetWindowThreadProcessId(hwnd, &dwProcessID);
+ if ((DWORD)lParam == dwProcessID) {
+ SendNotifyMessage(hwnd, message, 0, 0);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL CALLBACK sendShutDownMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARAM lParam)
+{
+ static UINT uiShutDownMessage = RegisterWindowMessage(L"qtcctrlcstub_shutdown");
+ return sendMessage(uiShutDownMessage, hwnd, lParam);
+}
+
+BOOL CALLBACK sendInterruptMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARAM lParam)
+{
+ static UINT uiInterruptMessage = RegisterWindowMessage(L"qtcctrlcstub_interrupt");
+ return sendMessage(uiInterruptMessage, hwnd, lParam);
+}
+#endif
+
+void ProcessHelper::setUseCtrlCStub(bool enabled)
+{
+ m_useCtrlCStub = enabled;
+}
+
+void ProcessHelper::terminateProcess()
+{
+#ifdef Q_OS_WIN
+ if (m_useCtrlCStub)
+ EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId());
+ else
+ terminate();
+#else
+ terminate();
+#endif
+}
+
+void ProcessHelper::terminateProcess(QProcess *process)
+{
+ ProcessHelper *helper = qobject_cast<ProcessHelper *>(process);
+ if (helper)
+ helper->terminateProcess();
+ else
+ process->terminate();
+}
+
+void ProcessHelper::interruptPid(qint64 pid)
+{
+#ifdef Q_OS_WIN
+ EnumWindows(sendInterruptMessageToAllWindowsOfProcess_enumWnd, pid);
+#else
+ Q_UNUSED(pid)
+#endif
+}
+
+void ProcessHelper::interruptProcess(QProcess *process)
+{
+ ProcessHelper *helper = qobject_cast<ProcessHelper *>(process);
+ if (helper && helper->m_useCtrlCStub)
+ ProcessHelper::interruptPid(process->processId());
+}
void ProcessHelper::setupChildProcess_impl()
{
diff --git a/src/libs/utils/processutils.h b/src/libs/utils/processutils.h
index 74f3c1c8e20..141de2d4fde 100644
--- a/src/libs/utils/processutils.h
+++ b/src/libs/utils/processutils.h
@@ -25,17 +25,13 @@
#pragma once
+#include "processenums.h"
+
#include <QIODevice>
#include <QProcess>
namespace Utils {
-enum class ProcessMode {
- Reader, // This opens in ReadOnly mode if no write data or in ReadWrite mode otherwise,
- // closes the write channel afterwards
- Writer // This opens in ReadWrite mode and doesn't close the write channel
-};
-
class ProcessStartHandler {
public:
ProcessStartHandler(QProcess *process) : m_process(process) {}
@@ -56,6 +52,8 @@ private:
class ProcessHelper : public QProcess
{
+ Q_OBJECT
+
public:
ProcessHelper(QObject *parent) : QProcess(parent), m_processStartHandler(this)
{
@@ -74,14 +72,20 @@ public:
void setLowPriority() { m_lowPriority = true; }
void setUnixTerminalDisabled() { m_unixTerminalDisabled = true; }
+ void setUseCtrlCStub(bool enabled); // release only
+
+ static void terminateProcess(QProcess *process);
+ static void interruptProcess(QProcess *process);
+ static void interruptPid(qint64 pid);
private:
+ void terminateProcess();
void setupChildProcess_impl();
+
bool m_lowPriority = false;
bool m_unixTerminalDisabled = false;
+ bool m_useCtrlCStub = false;
ProcessStartHandler m_processStartHandler;
};
} // namespace Utils
-
-Q_DECLARE_METATYPE(Utils::ProcessMode);
diff --git a/src/libs/utils/progressindicator.cpp b/src/libs/utils/progressindicator.cpp
index 2ecfb578fe5..a14fcbbd2bc 100644
--- a/src/libs/utils/progressindicator.cpp
+++ b/src/libs/utils/progressindicator.cpp
@@ -27,11 +27,8 @@
#include "icon.h"
#include "qtcassert.h"
-#include "stylehelper.h"
-#include <QEvent>
#include <QPainter>
-#include <QPixmap>
/*!
\class Utils::ProgressIndicator
diff --git a/src/libs/utils/progressindicator.h b/src/libs/utils/progressindicator.h
index 1cf41806c87..9ec6d40b9e7 100644
--- a/src/libs/utils/progressindicator.h
+++ b/src/libs/utils/progressindicator.h
@@ -25,11 +25,11 @@
#pragma once
-#include "overlaywidget.h"
#include "utils_global.h"
+#include "overlaywidget.h"
+
#include <QTimer>
-#include <QWidget>
#include <functional>
#include <memory>
diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp
index e5189759b03..6a347919625 100644
--- a/src/libs/utils/projectintropage.cpp
+++ b/src/libs/utils/projectintropage.cpp
@@ -27,6 +27,7 @@
#include "ui_projectintropage.h"
#include "filenamevalidatinglineedit.h"
+#include "fileutils.h"
#include "wizard.h"
#include <QDir>
diff --git a/src/libs/utils/projectintropage.h b/src/libs/utils/projectintropage.h
index ea755d671ed..4508039b06c 100644
--- a/src/libs/utils/projectintropage.h
+++ b/src/libs/utils/projectintropage.h
@@ -39,7 +39,7 @@ class QTCREATOR_UTILS_EXPORT ProjectIntroPage : public WizardPage
{
Q_OBJECT
Q_PROPERTY(QString description READ description WRITE setDescription DESIGNABLE true)
- Q_PROPERTY(FilePath filePath READ filePath WRITE setFilePath DESIGNABLE true)
+ Q_PROPERTY(Utils::FilePath filePath READ filePath WRITE setFilePath DESIGNABLE true)
Q_PROPERTY(QString projectName READ projectName WRITE setProjectName DESIGNABLE true)
Q_PROPERTY(bool useAsDefaultPath READ useAsDefaultPath WRITE setUseAsDefaultPath DESIGNABLE true)
Q_PROPERTY(bool forceSubProject READ forceSubProject WRITE setForceSubProject DESIGNABLE true)
@@ -61,7 +61,7 @@ public:
bool forceSubProject() const;
void setForceSubProject(bool force);
void setProjectList(const QStringList &projectList);
- void setProjectDirectories(const Utils::FilePaths &directoryList);
+ void setProjectDirectories(const FilePaths &directoryList);
int projectIndex() const;
bool validateProjectName(const QString &name, QString *errorMessage);
diff --git a/src/libs/utils/proxyaction.cpp b/src/libs/utils/proxyaction.cpp
index d8d9cf86971..b0360f5c355 100644
--- a/src/libs/utils/proxyaction.cpp
+++ b/src/libs/utils/proxyaction.cpp
@@ -173,7 +173,8 @@ void ProxyAction::updateToolTipWithKeySequence()
QString ProxyAction::stringWithAppendedShortcut(const QString &str, const QKeySequence &shortcut)
{
const QString s = stripAccelerator(str);
- return QString::fromLatin1("%1 <span style=\"color: gray; font-size: small\">%2</span>")
+ return QString::fromLatin1("<div style=\"white-space:pre\">%1 "
+ "<span style=\"color: gray; font-size: small\">%2</span></div>")
.arg(s, shortcut.toString(QKeySequence::NativeText));
}
diff --git a/src/libs/utils/proxycredentialsdialog.cpp b/src/libs/utils/proxycredentialsdialog.cpp
index c1888153599..71222014f95 100644
--- a/src/libs/utils/proxycredentialsdialog.cpp
+++ b/src/libs/utils/proxycredentialsdialog.cpp
@@ -26,7 +26,6 @@
#include "proxycredentialsdialog.h"
#include "ui_proxycredentialsdialog.h"
-#include <utils/networkaccessmanager.h>
#include <QNetworkProxy>
using namespace Utils;
diff --git a/src/libs/utils/proxycredentialsdialog.h b/src/libs/utils/proxycredentialsdialog.h
index 13f380a15cf..03ea87363b7 100644
--- a/src/libs/utils/proxycredentialsdialog.h
+++ b/src/libs/utils/proxycredentialsdialog.h
@@ -26,9 +26,12 @@
#pragma once
#include "utils_global.h"
+
#include <QDialog>
-QT_FORWARD_DECLARE_CLASS(QNetworkProxy)
+QT_BEGIN_NAMESPACE
+class QNetworkProxy;
+QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/qrcparser.cpp b/src/libs/utils/qrcparser.cpp
index 5fcb4aa20f9..58935f12100 100644
--- a/src/libs/utils/qrcparser.cpp
+++ b/src/libs/utils/qrcparser.cpp
@@ -25,7 +25,7 @@
#include "qrcparser.h"
-#include <utils/qtcassert.h>
+#include "qtcassert.h"
#include <QCoreApplication>
#include <QDir>
@@ -34,11 +34,8 @@
#include <QFileInfo>
#include <QLocale>
#include <QLoggingCategory>
-#include <QMultiHash>
#include <QMutex>
#include <QMutexLocker>
-#include <QSet>
-#include <QStringList>
static Q_LOGGING_CATEGORY(qrcParserLog, "qtc.qrcParser", QtWarningMsg)
@@ -60,6 +57,7 @@ public:
const QLocale *locale = nullptr) const;
void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
const QLocale *locale = nullptr) const;
+ QrcParser::MatchResult longestReverseMatches(const QString &) const;
QStringList errorMessages() const;
QStringList languages() const;
@@ -68,6 +66,7 @@ private:
const QStringList allUiLanguages(const QLocale *locale) const;
SMap m_resources;
+ SMap m_reverseResources;
SMap m_files;
QStringList m_languages;
QStringList m_errorMessages;
@@ -210,6 +209,11 @@ void QrcParser::collectFilesAtPath(const QString &path, QStringList *res, const
d->collectFilesAtPath(path, res, locale);
}
+QrcParser::MatchResult QrcParser::longestReverseMatches(const QString &p) const
+{
+ return d->longestReverseMatches(p);
+}
+
/*!
Returns \c true if \a path is a non-empty directory and matches \a locale.
@@ -417,8 +421,14 @@ bool QrcParserPrivate::parseFile(const QString &path, const QString &contents)
else
accessPath = language + prefix + fileName;
QStringList &resources = m_resources[accessPath];
- if (!resources.contains(filePath))
+ if (!resources.contains(filePath)) {
resources.append(filePath);
+ QString reversePath(accessPath);
+ std::reverse(reversePath.begin(), reversePath.end());
+ if (!reversePath.endsWith('/'))
+ reversePath.append('/');
+ m_reverseResources[reversePath].append(filePath);
+ }
QStringList &files = m_files[filePath];
if (!files.contains(accessPath))
files.append(accessPath);
@@ -520,6 +530,37 @@ void QrcParserPrivate::collectResourceFilesForSourceFile(const QString &sourceFi
}
}
+QrcParser::MatchResult QrcParserPrivate::longestReverseMatches(const QString &reversePath) const
+{
+ QrcParser::MatchResult res;
+ if (reversePath.length() == 1)
+ return res;
+ auto lastMatch = m_reverseResources.end();
+ qsizetype matchedUntil = 0;
+ for (qsizetype i = 1, j = 0; i < reversePath.size(); i = j + 1) {
+ j = reversePath.indexOf(u'/', i);
+ if (j == -1)
+ j = reversePath.size() - 1;
+ auto match = m_reverseResources.lowerBound(reversePath.mid(0, j + 1));
+ QString pNow = reversePath.left(j + 1);
+ if (match == m_reverseResources.end() || match.key().left(j + 1) != pNow)
+ break;
+ ++res.matchDepth;
+ matchedUntil = j + 1;
+ lastMatch = match;
+ }
+ res.reversedPaths.clear();
+ res.sourceFiles.clear();
+ for (auto it = lastMatch; it != m_reverseResources.end()
+ && it.key().left(matchedUntil) == reversePath.left(matchedUntil);
+ ++it) {
+ res.reversedPaths.append(it.key());
+ for (const QString &filePath : it.value())
+ res.sourceFiles.append(Utils::FilePath::fromString(filePath));
+ }
+ return res;
+}
+
QStringList QrcParserPrivate::errorMessages() const
{
return m_errorMessages;
diff --git a/src/libs/utils/qrcparser.h b/src/libs/utils/qrcparser.h
index 49e1f9e9249..3027076a97e 100644
--- a/src/libs/utils/qrcparser.h
+++ b/src/libs/utils/qrcparser.h
@@ -24,14 +24,19 @@
****************************************************************************/
#pragma once
+
#include "utils_global.h"
+#include "utils/filepath.h"
-#include <QMap>
#include <QSharedPointer>
#include <QString>
#include <QStringList>
-QT_FORWARD_DECLARE_CLASS(QLocale)
+QT_BEGIN_NAMESPACE
+class QLocale;
+template <typename K, typename V>
+class QMap;
+QT_END_NAMESPACE
namespace Utils {
@@ -43,14 +48,22 @@ class QrcCachePrivate;
class QTCREATOR_UTILS_EXPORT QrcParser
{
public:
+ struct MatchResult
+ {
+ int matchDepth = {};
+ QStringList reversedPaths;
+ QList<Utils::FilePath> sourceFiles;
+ };
+
typedef QSharedPointer<QrcParser> Ptr;
typedef QSharedPointer<const QrcParser> ConstPtr;
~QrcParser();
bool parseFile(const QString &path, const QString &contents);
QString firstFileAtPath(const QString &path, const QLocale &locale) const;
void collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale = nullptr) const;
+ MatchResult longestReverseMatches(const QString &) const;
bool hasDirAtPath(const QString &path, const QLocale *locale = nullptr) const;
- void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false,
+ void collectFilesInPath(const QString &path, QMap<QString, QStringList> *res, bool addDirs = false,
const QLocale *locale = nullptr) const;
void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *results,
const QLocale *locale = nullptr) const;
diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp
index 63af544cf26..62a2435cd1b 100644
--- a/src/libs/utils/qtcprocess.cpp
+++ b/src/libs/utils/qtcprocess.cpp
@@ -25,15 +25,13 @@
#include "qtcprocess.h"
-#include "commandline.h"
-#include "executeondestruction.h"
+#include "algorithm.h"
+#include "guard.h"
#include "hostosinfo.h"
#include "launcherinterface.h"
-#include "launcherpackets.h"
#include "launchersocket.h"
#include "processreaper.h"
-#include "qtcassert.h"
-#include "stringutils.h"
+#include "processutils.h"
#include "terminalprocess_p.h"
#include <QCoreApplication>
@@ -54,22 +52,21 @@
#include <algorithm>
#include <atomic>
+#include <chrono>
#include <functional>
+#include <iostream>
#include <limits>
#include <memory>
-#ifdef Q_OS_WIN
-#ifdef QTCREATOR_PCH_H
-#define CALLBACK WINAPI
-#endif
-#include <qt_windows.h>
-#endif
-
using namespace Utils::Internal;
namespace Utils {
namespace Internal {
+const char QTC_PROCESS_BLOCKING_TYPE[] = "__BLOCKING_TYPE__";
+const char QTC_PROCESS_NUMBER[] = "__NUMBER__";
+const char QTC_PROCESS_STARTTIME[] = "__STARTTIME__";
+
class MeasureAndRun
{
public:
@@ -190,6 +187,8 @@ enum { syncDebug = 0 };
enum { defaultMaxHangTimerCount = 10 };
static Q_LOGGING_CATEGORY(processLog, "qtc.utils.qtcprocess", QtWarningMsg)
+static Q_LOGGING_CATEGORY(processStdoutLog, "qtc.utils.qtcprocess.stdout", QtWarningMsg)
+static Q_LOGGING_CATEGORY(processStderrLog, "qtc.utils.qtcprocess.stderr", QtWarningMsg)
static DeviceProcessHooks s_deviceHooks;
@@ -202,6 +201,8 @@ public:
void handleRest();
void append(const QByteArray &text);
+ QByteArray readAllData() { return std::exchange(rawData, {}); }
+
QByteArray rawData;
QString incompleteLineBuffer; // lines not yet signaled
QTextCodec *codec = nullptr; // Not owner
@@ -212,243 +213,230 @@ public:
bool keepRawData = true;
};
-class ProcessInterface : public QObject
+class DefaultImpl : public ProcessInterface
{
- Q_OBJECT
-public:
- ProcessInterface(QObject *parent, ProcessMode processMode)
- : QObject(parent)
- , m_processMode(processMode) {}
-
- virtual QByteArray readAllStandardOutput() = 0;
- virtual QByteArray readAllStandardError() = 0;
-
- virtual void setProcessEnvironment(const QProcessEnvironment &environment) = 0;
- virtual void setWorkingDirectory(const QString &dir) = 0;
- virtual void start(const QString &program, const QStringList &arguments,
- const QByteArray &writeData) = 0;
- virtual void customStart(const CommandLine &, const FilePath &workingDirectory,
- const Environment &) { Q_UNUSED(workingDirectory); QTC_CHECK(false); }
- virtual bool isCustomStart() const { return false; }
- virtual void terminate() = 0;
- virtual void kill() = 0;
- virtual void close() = 0;
- virtual qint64 write(const QByteArray &data) = 0;
-
- virtual void setStandardInputFile(const QString &fileName) = 0;
- virtual void setProcessChannelMode(QProcess::ProcessChannelMode mode) = 0;
-
- virtual QString program() const = 0;
- virtual QProcess::ProcessError error() const = 0;
- virtual QProcess::ProcessState state() const = 0;
- virtual qint64 processId() const = 0;
- virtual int exitCode() const = 0;
- virtual QProcess::ExitStatus exitStatus() const = 0;
- virtual QString errorString() const = 0;
- virtual void setErrorString(const QString &str) = 0;
-
- virtual bool waitForStarted(int msecs) = 0;
- virtual bool waitForReadyRead(int msecs) = 0;
- virtual bool waitForFinished(int msecs) = 0;
-
- virtual void kickoffProcess() { QTC_CHECK(false); }
- virtual void interruptProcess() { QTC_CHECK(false); }
- virtual qint64 applicationMainThreadID() const { QTC_CHECK(false); return -1; }
-
- void setLowPriority() { m_lowPriority = true; }
- bool isLowPriority() const { return m_lowPriority; }
- void setUnixTerminalDisabled() { m_unixTerminalDisabled = true; }
- bool isUnixTerminalDisabled() const { return m_unixTerminalDisabled; }
-
- void setAbortOnMetaChars(bool abort) { m_abortOnMetaChars = abort; }
- bool isAbortOnMetaChars() const { return m_abortOnMetaChars; }
-
- void setBelowNormalPriority() { m_belowNormalPriority = true; }
- bool isBelowNormalPriority() const { return m_belowNormalPriority; }
- void setNativeArguments(const QString &arguments) { m_nativeArguments = arguments; }
- QString nativeArguments() const { return m_nativeArguments; }
-
-signals:
- void started();
- void finished(int exitCode, QProcess::ExitStatus status);
- void errorOccurred(QProcess::ProcessError error);
- void readyReadStandardOutput();
- void readyReadStandardError();
-
-protected:
- ProcessMode processMode() const { return m_processMode; }
private:
- const ProcessMode m_processMode;
- bool m_belowNormalPriority = false;
- QString m_nativeArguments;
- bool m_lowPriority = false;
- bool m_unixTerminalDisabled = false;
- bool m_abortOnMetaChars = true;
+ virtual void start() final;
+ virtual void doDefaultStart(const QString &program, const QStringList &arguments) = 0;
+ bool dissolveCommand(QString *program, QStringList *arguments);
+ bool ensureProgramExists(const QString &program);
};
-class TerminalImpl : public ProcessInterface
+static QString blockingMessage(const QVariant &variant)
{
-public:
- TerminalImpl(QObject *parent, QtcProcess::ProcessImpl processImpl,
- QtcProcess::TerminalMode terminalMode)
- : ProcessInterface(parent, ProcessMode::Reader)
- , m_terminal(this, processImpl, terminalMode)
- {
- connect(&m_terminal, &Internal::TerminalProcess::started,
- this, &ProcessInterface::started);
- connect(&m_terminal, &Internal::TerminalProcess::finished,
- this, &ProcessInterface::finished);
- connect(&m_terminal, &Internal::TerminalProcess::errorOccurred,
- this, &ProcessInterface::errorOccurred);
+ if (!variant.isValid())
+ return "non blocking";
+ if (variant.toInt() == int(EventLoopMode::On))
+ return "blocking with event loop";
+ return "blocking without event loop";
+}
+
+void DefaultImpl::start()
+{
+ if (processLog().isDebugEnabled()) {
+ using namespace std::chrono;
+ const quint64 msSinceEpoc =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ setProperty(QTC_PROCESS_STARTTIME, msSinceEpoc);
+
+ static std::atomic_int startCounter = 0;
+ const int currentNumber = startCounter.fetch_add(1);
+ qCDebug(processLog).nospace().noquote()
+ << "Process " << currentNumber << " starting ("
+ << qPrintable(blockingMessage(property(QTC_PROCESS_BLOCKING_TYPE)))
+ << "): "
+ << m_setup.m_commandLine.toUserOutput();
+ setProperty(QTC_PROCESS_NUMBER, currentNumber);
}
- ~TerminalImpl() override
- {
+
+ QString program;
+ QStringList arguments;
+ if (!dissolveCommand(&program, &arguments))
+ return;
+ if (!ensureProgramExists(program))
+ return;
+ s_start.measureAndRun(&DefaultImpl::doDefaultStart, this, program, arguments);
+}
+
+bool DefaultImpl::dissolveCommand(QString *program, QStringList *arguments)
+{
+ const CommandLine &commandLine = m_setup.m_commandLine;
+ QString commandString;
+ ProcessArgs processArgs;
+ const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &processArgs,
+ &m_setup.m_environment,
+ &m_setup.m_workingDirectory);
+
+ if (commandLine.executable().osType() == OsTypeWindows) {
+ QString args;
+ if (m_setup.m_useCtrlCStub) {
+ if (m_setup.m_lowPriority)
+ ProcessArgs::addArg(&args, "-nice");
+ ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString));
+ commandString = QCoreApplication::applicationDirPath()
+ + QLatin1String("/qtcreator_ctrlc_stub.exe");
+ } else if (m_setup.m_lowPriority) {
+ m_setup.m_belowNormalPriority = true;
+ }
+ ProcessArgs::addArgs(&args, processArgs.toWindowsArgs());
+ m_setup.m_nativeArguments = args;
+ // Note: Arguments set with setNativeArgs will be appended to the ones
+ // passed with start() below.
+ *arguments = QStringList();
+ } else {
+ if (!success) {
+ const ProcessResultData result = {0,
+ QProcess::NormalExit,
+ QProcess::FailedToStart,
+ QtcProcess::tr("Error in command line.")};
+ emit done(result);
+ return false;
+ }
+ *arguments = processArgs.toUnixArgs();
}
+ *program = commandString;
+ return true;
+}
- QByteArray readAllStandardOutput() override { QTC_CHECK(false); return {}; }
- QByteArray readAllStandardError() override { QTC_CHECK(false); return {}; }
+static FilePath resolve(const FilePath &workingDir, const FilePath &filePath)
+{
+ if (filePath.isAbsolutePath())
+ return filePath;
- void setProcessEnvironment(const QProcessEnvironment &) override { QTC_CHECK(false); }
- void setWorkingDirectory(const QString &) override { QTC_CHECK(false); }
- void start(const QString &, const QStringList &, const QByteArray &) override
- { QTC_CHECK(false); }
- void customStart(const CommandLine &command, const FilePath &workingDirectory,
- const Environment &environment) override
+ const FilePath fromWorkingDir = workingDir.resolvePath(filePath);
+ if (fromWorkingDir.exists() && fromWorkingDir.isExecutableFile())
+ return fromWorkingDir;
+ return filePath.searchInPath();
+}
+
+bool DefaultImpl::ensureProgramExists(const QString &program)
+{
+ const FilePath programFilePath = resolve(m_setup.m_workingDirectory,
+ FilePath::fromString(program));
+ if (programFilePath.exists() && programFilePath.isExecutableFile())
+ return true;
+
+ const QString errorString
+ = QtcProcess::tr("The program \"%1\" does not exist or is not executable.").arg(program);
+ const ProcessResultData result = { 0, QProcess::NormalExit, QProcess::FailedToStart,
+ errorString };
+ emit done(result);
+ return false;
+}
+
+class QProcessBlockingImpl : public ProcessBlockingInterface
+{
+public:
+ QProcessBlockingImpl(QProcess *process) : m_process(process) {}
+
+private:
+ bool waitForSignal(ProcessSignalType signalType, int msecs) final
{
- m_terminal.setAbortOnMetaChars(isAbortOnMetaChars());
- m_terminal.setCommand(command);
- m_terminal.setWorkingDirectory(workingDirectory);
- m_terminal.setEnvironment(environment);
- m_terminal.start();
+ switch (signalType) {
+ case ProcessSignalType::Started:
+ return m_process->waitForStarted(msecs);
+ case ProcessSignalType::ReadyRead:
+ return m_process->waitForReadyRead(msecs);
+ case ProcessSignalType::Done:
+ return m_process->waitForFinished(msecs);
+ }
+ return false;
}
- bool isCustomStart() const override { return true; }
- void terminate() override { m_terminal.stopProcess(); }
- void kill() override { m_terminal.stopProcess(); }
- void close() override { m_terminal.stopProcess(); }
- qint64 write(const QByteArray &) override { QTC_CHECK(false); return -1; }
-
- void setStandardInputFile(const QString &fileName) override { Q_UNUSED(fileName) QTC_CHECK(false); }
- // intentionally no-op without an assert
- void setProcessChannelMode(QProcess::ProcessChannelMode mode) override { Q_UNUSED(mode) }
-
- QString program() const override { QTC_CHECK(false); return {}; }
- QProcess::ProcessError error() const override { return m_terminal.error(); }
- QProcess::ProcessState state() const override { return m_terminal.state(); }
- qint64 processId() const override { return m_terminal.processId(); }
- int exitCode() const override { return m_terminal.exitCode(); }
- QProcess::ExitStatus exitStatus() const override { return m_terminal.exitStatus(); }
- QString errorString() const override { return m_terminal.errorString(); }
- void setErrorString(const QString &) override { QTC_CHECK(false); }
-
- // intentionally no-op without an assert
- bool waitForStarted(int) override { return false; }
- bool waitForReadyRead(int) override { QTC_CHECK(false); return false; }
- // intentionally no-op without an assert
- bool waitForFinished(int) override { return false; }
-
- void kickoffProcess() override { m_terminal.kickoffProcess(); }
- void interruptProcess() override { m_terminal.interruptProcess(); }
- qint64 applicationMainThreadID() const override { return m_terminal.applicationMainThreadID(); }
-private:
- Internal::TerminalProcess m_terminal;
+ QProcess *m_process = nullptr;
};
-class QProcessImpl : public ProcessInterface
+class QProcessImpl final : public DefaultImpl
{
public:
- QProcessImpl(QObject *parent, ProcessMode processMode)
- : ProcessInterface(parent, processMode)
- , m_process(new ProcessHelper(parent))
+ QProcessImpl()
+ : m_process(new ProcessHelper(this))
+ , m_blockingImpl(new QProcessBlockingImpl(m_process))
{
connect(m_process, &QProcess::started,
this, &QProcessImpl::handleStarted);
connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- this, &ProcessInterface::finished);
+ this, &QProcessImpl::handleFinished);
connect(m_process, &QProcess::errorOccurred,
- this, &ProcessInterface::errorOccurred);
- connect(m_process, &QProcess::readyReadStandardOutput,
- this, &ProcessInterface::readyReadStandardOutput);
- connect(m_process, &QProcess::readyReadStandardError,
- this, &ProcessInterface::readyReadStandardError);
- }
- ~QProcessImpl() override
- {
- ProcessReaper::reap(m_process);
+ this, &QProcessImpl::handleError);
+ connect(m_process, &QProcess::readyReadStandardOutput, this, [this] {
+ emit readyRead(m_process->readAllStandardOutput(), {});
+ });
+ connect(m_process, &QProcess::readyReadStandardError, this, [this] {
+ emit readyRead({}, m_process->readAllStandardError());
+ });
}
+ ~QProcessImpl() final { ProcessReaper::reap(m_process, m_setup.m_reaperTimeout); }
- QByteArray readAllStandardOutput() override { return m_process->readAllStandardOutput(); }
- QByteArray readAllStandardError() override
- {
- if (m_process->processChannelMode() == QProcess::MergedChannels)
- return {};
- return m_process->readAllStandardError();
+private:
+ qint64 write(const QByteArray &data) final { return m_process->write(data); }
+ void sendControlSignal(ControlSignal controlSignal) final {
+ switch (controlSignal) {
+ case ControlSignal::Terminate:
+ ProcessHelper::terminateProcess(m_process);
+ break;
+ case ControlSignal::Kill:
+ m_process->kill();
+ break;
+ case ControlSignal::Interrupt:
+ ProcessHelper::interruptProcess(m_process);
+ break;
+ case ControlSignal::KickOff:
+ QTC_CHECK(false);
+ break;
+ }
}
- void setProcessEnvironment(const QProcessEnvironment &environment) override
- { m_process->setProcessEnvironment(environment); }
- void setWorkingDirectory(const QString &dir) override
- { m_process->setWorkingDirectory(dir); }
- void start(const QString &program, const QStringList &arguments, const QByteArray &writeData) override
+ virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; }
+
+ void doDefaultStart(const QString &program, const QStringList &arguments) final
{
+ QTC_ASSERT(QThread::currentThread()->eventDispatcher(),
+ qWarning("QtcProcess::start(): Starting a process in a non QThread thread "
+ "may cause infinite hang when destroying the running process."));
ProcessStartHandler *handler = m_process->processStartHandler();
- handler->setProcessMode(processMode());
- handler->setWriteData(writeData);
- if (isBelowNormalPriority())
+ handler->setProcessMode(m_setup.m_processMode);
+ handler->setWriteData(m_setup.m_writeData);
+ if (m_setup.m_belowNormalPriority)
handler->setBelowNormalPriority();
- handler->setNativeArguments(nativeArguments());
- if (isLowPriority())
+ handler->setNativeArguments(m_setup.m_nativeArguments);
+ m_process->setProcessEnvironment(m_setup.m_environment.toProcessEnvironment());
+ m_process->setWorkingDirectory(m_setup.m_workingDirectory.path());
+ m_process->setStandardInputFile(m_setup.m_standardInputFile);
+ m_process->setProcessChannelMode(m_setup.m_processChannelMode);
+ if (m_setup.m_lowPriority)
m_process->setLowPriority();
- if (isUnixTerminalDisabled())
+ if (m_setup.m_unixTerminalDisabled)
m_process->setUnixTerminalDisabled();
+ m_process->setUseCtrlCStub(m_setup.m_useCtrlCStub);
m_process->start(program, arguments, handler->openMode());
handler->handleProcessStart();
}
- void terminate() override
- { m_process->terminate(); }
- void kill() override
- { m_process->kill(); }
- void close() override
- { m_process->close(); }
- qint64 write(const QByteArray &data) override
- { return m_process->write(data); }
-
- void setStandardInputFile(const QString &fileName) override
- { m_process->setStandardInputFile(fileName); }
- void setProcessChannelMode(QProcess::ProcessChannelMode mode) override
- { m_process->setProcessChannelMode(mode); }
-
- QString program() const override
- { return m_process->program(); }
- QProcess::ProcessError error() const override
- { return m_process->error(); }
- QProcess::ProcessState state() const override
- { return m_process->state(); }
- qint64 processId() const override
- { return m_process->processId(); }
- int exitCode() const override
- { return m_process->exitCode(); }
- QProcess::ExitStatus exitStatus() const override
- { return m_process->exitStatus(); }
- QString errorString() const override
- { return m_process->errorString(); }
- void setErrorString(const QString &str) override
- { m_process->setErrorString(str); }
-
- bool waitForStarted(int msecs) override
- { return m_process->waitForStarted(msecs); }
- bool waitForReadyRead(int msecs) override
- { return m_process->waitForReadyRead(msecs); }
- bool waitForFinished(int msecs) override
- { return m_process->waitForFinished(msecs); }
-private:
void handleStarted()
{
m_process->processStartHandler()->handleProcessStarted();
- emit started();
+ emit started(m_process->processId());
}
- ProcessHelper *m_process;
+
+ void handleError(QProcess::ProcessError error)
+ {
+ if (error != QProcess::FailedToStart)
+ return;
+ const ProcessResultData result = { m_process->exitCode(), m_process->exitStatus(),
+ error, m_process->errorString() };
+ emit done(result);
+ }
+
+ void handleFinished(int exitCode, QProcess::ExitStatus exitStatus)
+ {
+ const ProcessResultData result = { exitCode, exitStatus,
+ m_process->error(), m_process->errorString() };
+ emit done(result);
+ }
+
+ ProcessHelper *m_process = nullptr;
+ QProcessBlockingImpl *m_blockingImpl = nullptr;
};
static uint uniqueToken()
@@ -457,275 +445,549 @@ static uint uniqueToken()
return ++globalUniqueToken;
}
-class ProcessLauncherImpl : public ProcessInterface
+class ProcessLauncherBlockingImpl : public ProcessBlockingInterface
+{
+public:
+ ProcessLauncherBlockingImpl(CallerHandle *caller) : m_caller(caller) {}
+
+private:
+ bool waitForSignal(ProcessSignalType signalType, int msecs) final
+ {
+ // TODO: Remove CallerHandle::SignalType
+ const CallerHandle::SignalType type = [signalType] {
+ switch (signalType) {
+ case ProcessSignalType::Started:
+ return CallerHandle::SignalType::Started;
+ case ProcessSignalType::ReadyRead:
+ return CallerHandle::SignalType::ReadyRead;
+ case ProcessSignalType::Done:
+ return CallerHandle::SignalType::Done;
+ }
+ QTC_CHECK(false);
+ return CallerHandle::SignalType::NoSignal;
+ }();
+ return m_caller->waitForSignal(type, msecs);
+ }
+
+ CallerHandle *m_caller = nullptr;
+};
+
+class ProcessLauncherImpl final : public DefaultImpl
{
Q_OBJECT
public:
- ProcessLauncherImpl(QObject *parent, ProcessMode processMode)
- : ProcessInterface(parent, processMode), m_token(uniqueToken())
+ ProcessLauncherImpl() : m_token(uniqueToken())
{
- m_handle = LauncherInterface::registerHandle(parent, token(), processMode);
- connect(m_handle, &CallerHandle::errorOccurred,
- this, &ProcessInterface::errorOccurred);
+ m_handle = LauncherInterface::registerHandle(this, token());
+ m_handle->setProcessSetupData(&m_setup);
connect(m_handle, &CallerHandle::started,
this, &ProcessInterface::started);
- connect(m_handle, &CallerHandle::finished,
- this, &ProcessInterface::finished);
- connect(m_handle, &CallerHandle::readyReadStandardOutput,
- this, &ProcessInterface::readyReadStandardOutput);
- connect(m_handle, &CallerHandle::readyReadStandardError,
- this, &ProcessInterface::readyReadStandardError);
+ connect(m_handle, &CallerHandle::readyRead,
+ this, &ProcessInterface::readyRead);
+ connect(m_handle, &CallerHandle::done,
+ this, &ProcessInterface::done);
+ m_blockingImpl = new ProcessLauncherBlockingImpl(m_handle);
}
- ~ProcessLauncherImpl() override
+ ~ProcessLauncherImpl() final
{
- cancel();
+ m_handle->close();
LauncherInterface::unregisterHandle(token());
m_handle = nullptr;
}
- QByteArray readAllStandardOutput() override { return m_handle->readAllStandardOutput(); }
- QByteArray readAllStandardError() override { return m_handle->readAllStandardError(); }
-
- void setProcessEnvironment(const QProcessEnvironment &environment) override
- { m_handle->setProcessEnvironment(environment); }
- void setWorkingDirectory(const QString &dir) override { m_handle->setWorkingDirectory(dir); }
- void start(const QString &program, const QStringList &arguments, const QByteArray &writeData) override
- {
- if (isBelowNormalPriority())
- m_handle->setBelowNormalPriority();
- m_handle->setNativeArguments(nativeArguments());
- if (isLowPriority())
- m_handle->setLowPriority();
- if (isUnixTerminalDisabled())
- m_handle->setUnixTerminalDisabled();
- m_handle->start(program, arguments, writeData);
- }
- void terminate() override { cancel(); } // TODO: what are differences among terminate, kill and close?
- void kill() override { cancel(); } // TODO: see above
- void close() override { cancel(); } // TODO: see above
- qint64 write(const QByteArray &data) override { return m_handle->write(data); }
-
- void setStandardInputFile(const QString &fileName) override { m_handle->setStandardInputFile(fileName); }
- void setProcessChannelMode(QProcess::ProcessChannelMode mode) override { m_handle->setProcessChannelMode(mode); }
-
- QString program() const override { return m_handle->program(); }
- QProcess::ProcessError error() const override { return m_handle->error(); }
- QProcess::ProcessState state() const override { return m_handle->state(); }
- qint64 processId() const override { return m_handle->processId(); }
- int exitCode() const override { return m_handle->exitCode(); }
- QProcess::ExitStatus exitStatus() const override { return m_handle->exitStatus(); }
- QString errorString() const override { return m_handle->errorString(); }
- void setErrorString(const QString &str) override { m_handle->setErrorString(str); }
-
- bool waitForStarted(int msecs) override { return m_handle->waitForStarted(msecs); }
- bool waitForReadyRead(int msecs) override { return m_handle->waitForReadyRead(msecs); }
- bool waitForFinished(int msecs) override { return m_handle->waitForFinished(msecs); }
-
private:
- typedef void (ProcessLauncherImpl::*PreSignal)(void);
+ qint64 write(const QByteArray &data) final { return m_handle->write(data); }
+ void sendControlSignal(ControlSignal controlSignal) final {
+ switch (controlSignal) {
+ case ControlSignal::Terminate:
+ m_handle->terminate();
+ break;
+ case ControlSignal::Kill:
+ m_handle->kill();
+ break;
+ case ControlSignal::Interrupt:
+ if (m_setup.m_useCtrlCStub) // bypass launcher and interrupt directly
+ ProcessHelper::interruptPid(m_handle->processId());
+ break;
+ case ControlSignal::KickOff:
+ QTC_CHECK(false);
+ break;
+ }
+ }
- void cancel();
+ virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; }
- void handleSocketError(const QString &message);
- void handleSocketReady();
+ void doDefaultStart(const QString &program, const QStringList &arguments) final
+ {
+ m_handle->start(program, arguments);
+ }
quintptr token() const { return m_token; }
const uint m_token = 0;
// Lives in caller's thread.
CallerHandle *m_handle = nullptr;
+ ProcessLauncherBlockingImpl *m_blockingImpl = nullptr;
};
-void ProcessLauncherImpl::cancel()
+static ProcessImpl defaultProcessImpl()
{
- m_handle->cancel();
+ if (qEnvironmentVariableIsSet("QTC_USE_QPROCESS"))
+ return ProcessImpl::QProcess;
+ return ProcessImpl::ProcessLauncher;
}
-static ProcessInterface *newProcessInstance(QObject *parent, QtcProcess::ProcessImpl processImpl,
- ProcessMode mode, QtcProcess::TerminalMode terminalMode)
+class ProcessInterfaceSignal
{
- if (terminalMode != QtcProcess::TerminalOff)
- return new TerminalImpl(parent, processImpl, terminalMode);
- if (processImpl == QtcProcess::QProcessImpl)
- return new QProcessImpl(parent, mode);
- return new ProcessLauncherImpl(parent, mode);
-}
+public:
+ ProcessSignalType signalType() const { return m_signalType; }
+ virtual ~ProcessInterfaceSignal() = default;
+protected:
+ ProcessInterfaceSignal(ProcessSignalType signalType) : m_signalType(signalType) {}
+private:
+ const ProcessSignalType m_signalType;
+};
-class QtcProcessPrivate : public QObject
+class StartedSignal : public ProcessInterfaceSignal
{
public:
- enum StartFailure {
- NoFailure,
- WrongFileNameFailure,
- OtherFailure
- };
-
- explicit QtcProcessPrivate(QtcProcess *parent,
- QtcProcess::ProcessImpl processImpl,
- ProcessMode processMode,
- QtcProcess::TerminalMode terminalMode)
- : QObject(parent)
- , q(parent)
- , m_process(newProcessInstance(parent, processImpl, processMode, terminalMode))
- , m_processMode(processMode)
- , m_terminalMode(terminalMode)
- {
- connect(m_process, &ProcessInterface::started,
- q, &QtcProcess::started);
- connect(m_process, &ProcessInterface::finished,
- this, &QtcProcessPrivate::slotFinished);
- connect(m_process, &ProcessInterface::errorOccurred,
- this, [this](QProcess::ProcessError error) { handleError(error, OtherFailure); });
- connect(m_process, &ProcessInterface::readyReadStandardOutput,
- this, &QtcProcessPrivate::handleReadyReadStandardOutput);
- connect(m_process, &ProcessInterface::readyReadStandardError,
- this, &QtcProcessPrivate::handleReadyReadStandardError);
- }
+ StartedSignal(qint64 processId, qint64 applicationMainThreadId)
+ : ProcessInterfaceSignal(ProcessSignalType::Started)
+ , m_processId(processId)
+ , m_applicationMainThreadId(applicationMainThreadId) {}
+ qint64 processId() const { return m_processId; }
+ qint64 applicationMainThreadId() const { return m_applicationMainThreadId; }
+private:
+ const qint64 m_processId;
+ const qint64 m_applicationMainThreadId;
+};
- void handleReadyReadStandardOutput()
- {
- m_stdOut.append(m_process->readAllStandardOutput());
- m_hangTimerCount = 0;
- emit q->readyReadStandardOutput();
- }
+class ReadyReadSignal : public ProcessInterfaceSignal
+{
+public:
+ ReadyReadSignal(const QByteArray &stdOut, const QByteArray &stdErr)
+ : ProcessInterfaceSignal(ProcessSignalType::ReadyRead)
+ , m_stdOut(stdOut)
+ , m_stdErr(stdErr) {}
+ QByteArray stdOut() const { return m_stdOut; }
+ QByteArray stdErr() const { return m_stdErr; }
+private:
+ const QByteArray m_stdOut;
+ const QByteArray m_stdErr;
+};
- void handleReadyReadStandardError()
- {
- m_stdErr.append(m_process->readAllStandardError());
- m_hangTimerCount = 0;
- emit q->readyReadStandardError();
- }
+class DoneSignal : public ProcessInterfaceSignal
+{
+public:
+ DoneSignal(const ProcessResultData &resultData)
+ : ProcessInterfaceSignal(ProcessSignalType::Done)
+ , m_resultData(resultData) {}
+ ProcessResultData resultData() const { return m_resultData; }
+private:
+ const ProcessResultData m_resultData;
+};
- FilePath resolve(const FilePath &workingDir, const FilePath &filePath) const
- {
- if (filePath.isAbsolutePath())
- return filePath;
+class GeneralProcessBlockingImpl;
+
+class ProcessInterfaceHandler : public QObject
+{
+public:
+ ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller, ProcessInterface *process);
+
+ // Called from caller's thread exclusively.
+ bool waitForSignal(ProcessSignalType newSignal, int msecs);
+ void moveToCallerThread();
- const FilePath fromWorkingDir = workingDir.resolvePath(filePath);
- if (fromWorkingDir.exists() && fromWorkingDir.isExecutableFile())
- return fromWorkingDir;
- return filePath.searchInPath();
+private:
+ // Called from caller's thread exclusively.
+ bool doWaitForSignal(QDeadlineTimer deadline);
+
+ // Called from caller's thread when not waiting for signal,
+ // otherwise called from temporary thread.
+ void handleStarted(qint64 processId, qint64 applicationMainThreadId);
+ void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData);
+ void handleDone(const ProcessResultData &data);
+ void appendSignal(ProcessInterfaceSignal *newSignal);
+
+ GeneralProcessBlockingImpl *m_caller = nullptr;
+ QMutex m_mutex;
+ QWaitCondition m_waitCondition;
+};
+
+class GeneralProcessBlockingImpl : public ProcessBlockingInterface
+{
+public:
+ GeneralProcessBlockingImpl(QtcProcessPrivate *parent);
+
+ void flush() { flushSignals(takeAllSignals()); }
+ bool flushFor(ProcessSignalType signalType) {
+ return flushSignals(takeSignalsFor(signalType), &signalType);
}
- void defaultStart(const CommandLine &commandLine, const FilePath &workingDirectory,
- const Environment &environment)
+ bool shouldFlush() const { QMutexLocker locker(&m_mutex); return !m_signals.isEmpty(); }
+ // Called from ProcessInterfaceHandler thread exclusively.
+ void appendSignal(ProcessInterfaceSignal *launcherSignal);
+
+private:
+ // Called from caller's thread exclusively
+ bool waitForSignal(ProcessSignalType newSignal, int msecs) final;
+
+ QList<ProcessInterfaceSignal *> takeAllSignals();
+ QList<ProcessInterfaceSignal *> takeSignalsFor(ProcessSignalType signalType);
+ bool flushSignals(const QList<ProcessInterfaceSignal *> &signalList,
+ ProcessSignalType *signalType = nullptr);
+
+ void handleStartedSignal(const StartedSignal *launcherSignal);
+ void handleReadyReadSignal(const ReadyReadSignal *launcherSignal);
+ void handleDoneSignal(const DoneSignal *launcherSignal);
+
+ QtcProcessPrivate *m_caller = nullptr;
+ std::unique_ptr<ProcessInterfaceHandler> m_processHandler;
+ mutable QMutex m_mutex;
+ QList<ProcessInterfaceSignal *> m_signals;
+};
+
+class QtcProcessPrivate : public QObject
+{
+public:
+ explicit QtcProcessPrivate(QtcProcess *parent)
+ : QObject(parent)
+ , q(parent)
+ , m_killTimer(this)
{
- if (processLog().isDebugEnabled()) {
- static int n = 0;
- qCDebug(processLog) << "STARTING PROCESS: " << ++n << " " << commandLine.toUserOutput();
- }
+ m_setup.m_controlEnvironment = Environment::systemEnvironment();
+ m_killTimer.setSingleShot(true);
+ connect(&m_killTimer, &QTimer::timeout, this, [this] {
+ m_killTimer.stop();
+ sendControlSignal(ControlSignal::Kill);
+ });
+ }
- m_process->setProcessEnvironment(environment.toProcessEnvironment());
- m_process->setWorkingDirectory(workingDirectory.path());
-
- QString commandString;
- ProcessArgs arguments;
- const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &arguments,
- &environment, &workingDirectory);
-
- if (commandLine.executable().osType() == OsTypeWindows) {
- QString args;
- if (m_useCtrlCStub) {
- if (m_process->isLowPriority())
- ProcessArgs::addArg(&args, "-nice");
- ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString));
- commandString = QCoreApplication::applicationDirPath()
- + QLatin1String("/qtcreator_ctrlc_stub.exe");
- } else if (m_process->isLowPriority()) {
- m_process->setBelowNormalPriority();
- }
- ProcessArgs::addArgs(&args, arguments.toWindowsArgs());
-#ifdef Q_OS_WIN
- m_process->setNativeArguments(args);
-#endif
- // Note: Arguments set with setNativeArgs will be appended to the ones
- // passed with start() below.
- start(commandString, QStringList(), workingDirectory, m_writeData);
- } else {
- if (!success) {
- q->setErrorString(QtcProcess::tr("Error in command line."));
- // Should be FailedToStart, but we cannot set the process error from the outside,
- // so it would be inconsistent.
- emit q->errorOccurred(QProcess::UnknownError);
- return;
- }
- start(commandString, arguments.toUnixArgs(), workingDirectory, m_writeData);
- }
+ ProcessInterface *createProcessInterface()
+ {
+ if (m_setup.m_terminalMode != TerminalMode::Off)
+ return new TerminalImpl();
+
+ const ProcessImpl impl = m_setup.m_processImpl == ProcessImpl::Default
+ ? defaultProcessImpl() : m_setup.m_processImpl;
+ if (impl == ProcessImpl::QProcess)
+ return new QProcessImpl();
+ return new ProcessLauncherImpl();
}
- void start(const QString &program, const QStringList &arguments,
- const FilePath &workingDirectory, const QByteArray &writeData)
+ void setProcessInterface(ProcessInterface *process)
{
- const FilePath programFilePath = resolve(workingDirectory, FilePath::fromString(program));
- if (programFilePath.exists() && programFilePath.isExecutableFile()) {
- s_start.measureAndRun(&ProcessInterface::start, m_process, program, arguments, writeData);
- } else {
- m_process->setErrorString(QLatin1String(
- "The program \"%1\" does not exist or is not executable.").arg(program));
- handleError(QProcess::FailedToStart, WrongFileNameFailure);
- }
+ m_process.reset(process);
+ m_process->setParent(this);
+ connect(m_process.get(), &ProcessInterface::started,
+ this, &QtcProcessPrivate::handleStarted);
+ connect(m_process.get(), &ProcessInterface::readyRead,
+ this, &QtcProcessPrivate::handleReadyRead);
+ connect(m_process.get(), &ProcessInterface::done,
+ this, &QtcProcessPrivate::handleDone);
+
+ m_blockingInterface.reset(process->processBlockingInterface());
+ if (!m_blockingInterface)
+ m_blockingInterface.reset(new GeneralProcessBlockingImpl(this));
+ m_blockingInterface->setParent(this);
}
CommandLine fullCommandLine() const
{
- if (!m_runAsRoot || HostOsInfo::isWindowsHost())
- return m_commandLine;
+ if (!m_setup.m_runAsRoot || HostOsInfo::isWindowsHost())
+ return m_setup.m_commandLine;
CommandLine rootCommand("sudo", {"-A"});
- rootCommand.addCommandLineAsArgs(m_commandLine);
+ rootCommand.addCommandLineAsArgs(m_setup.m_commandLine);
return rootCommand;
}
Environment fullEnvironment() const
{
- Environment env;
- if (m_haveEnv) {
- if (m_environment.size() == 0)
- qWarning("QtcProcess::start: Empty environment set when running '%s'.",
- qPrintable(m_commandLine.executable().toString()));
- env = m_environment;
- } else {
- env = Environment::systemEnvironment();
+ Environment env = m_setup.m_environment;
+ if (!env.isValid()) {
+// FIXME: Either switch to using EnvironmentChange instead of full Environments, or
+// feed the full environment into the QtcProcess instead of fixing it up here.
+// qWarning("QtcProcess::start: Empty environment set when running '%s'.",
+// qPrintable(m_setup.m_commandLine.executable().toString()));
+ env = m_setup.m_commandLine.executable().deviceEnvironment();
}
-
-// TODO: needs SshSettings
-// if (m_runAsRoot)
-// RunControl::provideAskPassEntry(env);
+ // TODO: needs SshSettings
+ // if (m_runAsRoot)
+ // RunControl::provideAskPassEntry(env);
return env;
}
QtcProcess *q;
- ProcessInterface *m_process;
- const ProcessMode m_processMode;
- const QtcProcess::TerminalMode m_terminalMode;
- CommandLine m_commandLine;
- FilePath m_workingDirectory;
- Environment m_environment;
- QByteArray m_writeData;
- bool m_runAsRoot = false;
- bool m_haveEnv = false;
- bool m_useCtrlCStub = false;
+ std::unique_ptr<ProcessBlockingInterface> m_blockingInterface;
+ std::unique_ptr<ProcessInterface> m_process;
+ ProcessSetupData m_setup;
void slotTimeout();
- void slotFinished(int exitCode, QProcess::ExitStatus e);
- void handleError(QProcess::ProcessError error, StartFailure startFailure);
+ void handleStarted(qint64 processId, qint64 applicationMainThreadId);
+ void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData);
+ void handleDone(const ProcessResultData &data);
void clearForRun();
- QtcProcess::Result interpretExitCode(int exitCode);
+ void emitStarted();
+ void emitDone();
+ void emitReadyReadStandardOutput();
+ void emitReadyReadStandardError();
+
+ ProcessResult interpretExitCode(int exitCode);
+
+ bool waitForSignal(ProcessSignalType signalType, int msecs);
+ Qt::ConnectionType connectionType() const;
+ void sendControlSignal(ControlSignal controlSignal);
+
+ QTimer m_killTimer;
+ QProcess::ProcessState m_state = QProcess::NotRunning;
+ qint64 m_processId = 0;
+ qint64 m_applicationMainThreadId = 0;
+ ProcessResultData m_resultData;
QTextCodec *m_codec = QTextCodec::codecForLocale();
QEventLoop *m_eventLoop = nullptr;
- QtcProcess::Result m_result = QtcProcess::StartFailed;
+ ProcessResult m_result = ProcessResult::StartFailed;
ChannelBuffer m_stdOut;
ChannelBuffer m_stdErr;
ExitCodeInterpreter m_exitCodeInterpreter;
int m_hangTimerCount = 0;
int m_maxHangTimerCount = defaultMaxHangTimerCount;
- StartFailure m_startFailure = NoFailure;
bool m_timeOutMessageBoxEnabled = false;
bool m_waitingForUser = false;
+
+ Guard m_guard;
};
+ProcessInterfaceHandler::ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller,
+ ProcessInterface *process)
+ : m_caller(caller)
+{
+ process->disconnect();
+ connect(process, &ProcessInterface::started,
+ this, &ProcessInterfaceHandler::handleStarted);
+ connect(process, &ProcessInterface::readyRead,
+ this, &ProcessInterfaceHandler::handleReadyRead);
+ connect(process, &ProcessInterface::done,
+ this, &ProcessInterfaceHandler::handleDone);
+}
+
+// Called from caller's thread exclusively.
+bool ProcessInterfaceHandler::waitForSignal(ProcessSignalType newSignal, int msecs)
+{
+ QDeadlineTimer deadline(msecs);
+ while (true) {
+ if (deadline.hasExpired())
+ break;
+ if (!doWaitForSignal(deadline))
+ break;
+ // Matching (or Done) signal was flushed
+ if (m_caller->flushFor(newSignal))
+ return true;
+ // Otherwise continue awaiting (e.g. when ReadyRead came while waitForFinished())
+ }
+ return false;
+}
+
+// Called from caller's thread exclusively.
+void ProcessInterfaceHandler::moveToCallerThread()
+{
+ QMetaObject::invokeMethod(this, [this] {
+ moveToThread(m_caller->thread());
+ }, Qt::BlockingQueuedConnection);
+}
+
+// Called from caller's thread exclusively.
+bool ProcessInterfaceHandler::doWaitForSignal(QDeadlineTimer deadline)
+{
+ QMutexLocker locker(&m_mutex);
+
+ // Flush, if we have any stored signals.
+ // This must be called when holding laucher's mutex locked prior to the call to wait,
+ // so that it's done atomically.
+ if (m_caller->shouldFlush())
+ return true;
+
+ return m_waitCondition.wait(&m_mutex, deadline);
+}
+
+// Called from ProcessInterfaceHandler thread exclusively
+void ProcessInterfaceHandler::handleStarted(qint64 processId, qint64 applicationMainThreadId)
+{
+ appendSignal(new StartedSignal(processId, applicationMainThreadId));
+}
+
+// Called from ProcessInterfaceHandler thread exclusively
+void ProcessInterfaceHandler::handleReadyRead(const QByteArray &outputData, const QByteArray &errorData)
+{
+ appendSignal(new ReadyReadSignal(outputData, errorData));
+}
+
+// Called from ProcessInterfaceHandler thread exclusively
+void ProcessInterfaceHandler::handleDone(const ProcessResultData &data)
+{
+ appendSignal(new DoneSignal(data));
+}
+
+void ProcessInterfaceHandler::appendSignal(ProcessInterfaceSignal *newSignal)
+{
+ {
+ QMutexLocker locker(&m_mutex);
+ m_caller->appendSignal(newSignal);
+ }
+ m_waitCondition.wakeOne();
+ // call in callers thread
+ QMetaObject::invokeMethod(m_caller, &GeneralProcessBlockingImpl::flush);
+}
+
+GeneralProcessBlockingImpl::GeneralProcessBlockingImpl(QtcProcessPrivate *parent)
+ : m_caller(parent)
+ , m_processHandler(new ProcessInterfaceHandler(this, parent->m_process.get()))
+{
+ // In order to move the process interface into another thread together with handle
+ parent->m_process.get()->setParent(m_processHandler.get());
+ m_processHandler->setParent(this);
+}
+
+bool GeneralProcessBlockingImpl::waitForSignal(ProcessSignalType newSignal, int msecs)
+{
+ m_processHandler->setParent(nullptr);
+
+ QThread thread;
+ thread.start();
+ // Note: the thread may have started before and it's appending new signals before
+ // waitForSignal() is called. However, in this case they won't be flushed since
+ // the caller here is blocked, so all signals should be buffered and we are going
+ // to flush them from inside waitForSignal().
+ m_processHandler->moveToThread(&thread);
+ const bool result = m_processHandler->waitForSignal(newSignal, msecs);
+ m_processHandler->moveToCallerThread();
+ m_processHandler->setParent(this);
+ thread.quit();
+ thread.wait();
+ return result;
+}
+
+// Called from caller's thread exclusively
+QList<ProcessInterfaceSignal *> GeneralProcessBlockingImpl::takeAllSignals()
+{
+ QMutexLocker locker(&m_mutex);
+ return std::exchange(m_signals, {});
+}
+
+// Called from caller's thread exclusively
+QList<ProcessInterfaceSignal *> GeneralProcessBlockingImpl::takeSignalsFor(ProcessSignalType signalType)
+{
+ // If we are flushing for ReadyRead or Done - flush all.
+ if (signalType != ProcessSignalType::Started)
+ return takeAllSignals();
+
+ QMutexLocker locker(&m_mutex);
+ const QList<ProcessSignalType> storedSignals = transform(qAsConst(m_signals),
+ [](const ProcessInterfaceSignal *aSignal) {
+ return aSignal->signalType();
+ });
+
+ // If we are flushing for Started:
+ // - if Started was buffered - flush Started only (even when Done was buffered)
+ // - otherwise if Done signal was buffered - flush all.
+ if (!storedSignals.contains(ProcessSignalType::Started)
+ && storedSignals.contains(ProcessSignalType::Done)) {
+ return std::exchange(m_signals, {}); // avoid takeAllSignals() because of mutex locked
+ }
+
+ QList<ProcessInterfaceSignal *> oldSignals;
+ const auto matchingIndex = storedSignals.lastIndexOf(signalType);
+ if (matchingIndex >= 0) {
+ oldSignals = m_signals.mid(0, matchingIndex + 1);
+ m_signals = m_signals.mid(matchingIndex + 1);
+ }
+ return oldSignals;
+}
+
+// Called from caller's thread exclusively
+bool GeneralProcessBlockingImpl::flushSignals(const QList<ProcessInterfaceSignal *> &signalList,
+ ProcessSignalType *signalType)
+{
+ bool signalMatched = false;
+ for (const ProcessInterfaceSignal *storedSignal : qAsConst(signalList)) {
+ const ProcessSignalType storedSignalType = storedSignal->signalType();
+ if (signalType && storedSignalType == *signalType)
+ signalMatched = true;
+ switch (storedSignalType) {
+ case ProcessSignalType::Started:
+ handleStartedSignal(static_cast<const StartedSignal *>(storedSignal));
+ break;
+ case ProcessSignalType::ReadyRead:
+ handleReadyReadSignal(static_cast<const ReadyReadSignal *>(storedSignal));
+ break;
+ case ProcessSignalType::Done:
+ if (signalType)
+ signalMatched = true;
+ handleDoneSignal(static_cast<const DoneSignal *>(storedSignal));
+ break;
+ }
+ delete storedSignal;
+ }
+ return signalMatched;
+}
+
+void GeneralProcessBlockingImpl::handleStartedSignal(const StartedSignal *aSignal)
+{
+ m_caller->handleStarted(aSignal->processId(), aSignal->applicationMainThreadId());
+}
+
+void GeneralProcessBlockingImpl::handleReadyReadSignal(const ReadyReadSignal *aSignal)
+{
+ m_caller->handleReadyRead(aSignal->stdOut(), aSignal->stdErr());
+}
+
+void GeneralProcessBlockingImpl::handleDoneSignal(const DoneSignal *aSignal)
+{
+ m_caller->handleDone(aSignal->resultData());
+}
+
+// Called from ProcessInterfaceHandler thread exclusively.
+void GeneralProcessBlockingImpl::appendSignal(ProcessInterfaceSignal *newSignal)
+{
+ QMutexLocker locker(&m_mutex);
+ m_signals.append(newSignal);
+}
+
+bool QtcProcessPrivate::waitForSignal(ProcessSignalType newSignal, int msecs)
+{
+ const QDeadlineTimer timeout(msecs);
+ const QDeadlineTimer currentKillTimeout(m_killTimer.remainingTime());
+ const bool needsSplit = m_killTimer.isActive() ? timeout > currentKillTimeout : false;
+ const QDeadlineTimer mainTimeout = needsSplit ? currentKillTimeout : timeout;
+
+ bool result = m_blockingInterface->waitForSignal(newSignal, mainTimeout.remainingTime());
+ if (!result && needsSplit) {
+ m_killTimer.stop();
+ sendControlSignal(ControlSignal::Kill);
+ result = m_blockingInterface->waitForSignal(newSignal, timeout.remainingTime());
+ }
+ return result;
+}
+
+Qt::ConnectionType QtcProcessPrivate::connectionType() const
+{
+ return (m_process->thread() == thread()) ? Qt::DirectConnection
+ : Qt::BlockingQueuedConnection;
+}
+
+void QtcProcessPrivate::sendControlSignal(ControlSignal controlSignal)
+{
+ QTC_ASSERT(QThread::currentThread() == thread(), return);
+ if (!m_process || (m_state == QProcess::NotRunning))
+ return;
+
+ QMetaObject::invokeMethod(m_process.get(), [this, controlSignal] {
+ m_process->sendControlSignal(controlSignal);
+ }, connectionType());
+}
+
void QtcProcessPrivate::clearForRun()
{
m_hangTimerCount = 0;
@@ -733,17 +995,22 @@ void QtcProcessPrivate::clearForRun()
m_stdOut.codec = m_codec;
m_stdErr.clearForRun();
m_stdErr.codec = m_codec;
- m_result = QtcProcess::StartFailed;
- m_startFailure = NoFailure;
+ m_result = ProcessResult::StartFailed;
+
+ m_killTimer.stop();
+ m_state = QProcess::NotRunning;
+ m_processId = 0;
+ m_applicationMainThreadId = 0;
+ m_resultData = {};
}
-QtcProcess::Result QtcProcessPrivate::interpretExitCode(int exitCode)
+ProcessResult QtcProcessPrivate::interpretExitCode(int exitCode)
{
if (m_exitCodeInterpreter)
return m_exitCodeInterpreter(exitCode);
// default:
- return exitCode ? QtcProcess::FinishedWithError : QtcProcess::FinishedWithSuccess;
+ return exitCode ? ProcessResult::FinishedWithError : ProcessResult::FinishedWithSuccess;
}
} // Internal
@@ -756,161 +1023,173 @@ QtcProcess::Result QtcProcessPrivate::interpretExitCode(int exitCode)
\sa Utils::ProcessArgs
*/
-static QtcProcess::ProcessImpl defaultProcessImpl()
-{
- if (qEnvironmentVariableIsSet("QTC_USE_QPROCESS"))
- return QtcProcess::QProcessImpl;
- return QtcProcess::ProcessLauncherImpl;
-}
-
-QtcProcess::QtcProcess(const Setup &setup, QObject *parent)
+QtcProcess::QtcProcess(QObject *parent)
: QObject(parent),
- d(new QtcProcessPrivate(this,
- setup.processImpl == DefaultImpl ? defaultProcessImpl() : setup.processImpl,
- setup.processMode, setup.terminalMode))
+ d(new QtcProcessPrivate(this))
{
static int qProcessExitStatusMeta = qRegisterMetaType<QProcess::ExitStatus>();
static int qProcessProcessErrorMeta = qRegisterMetaType<QProcess::ProcessError>();
Q_UNUSED(qProcessExitStatusMeta)
Q_UNUSED(qProcessProcessErrorMeta)
-}
-QtcProcess::QtcProcess(QObject *parent)
- : QtcProcess({}, parent)
-{}
+ if (processLog().isDebugEnabled()) {
+ connect(this, &QtcProcess::done, [this] {
+ if (!d->m_process.get())
+ return;
+ const QVariant n = d->m_process.get()->property(QTC_PROCESS_NUMBER);
+ if (!n.isValid())
+ return;
+ using namespace std::chrono;
+ const quint64 msSinceEpoc =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ const quint64 msStarted =
+ d->m_process.get()->property(QTC_PROCESS_STARTTIME).toULongLong();
+ const quint64 msElapsed = msSinceEpoc - msStarted;
+
+ const int number = n.toInt();
+ qCDebug(processLog).nospace() << "Process " << number << " finished: "
+ << "result=" << int(result())
+ << ", ex=" << exitCode()
+ << ", " << cleanedStdOut().size() << " bytes stdout: "
+ << cleanedStdOut().left(20)
+ << ", " << cleanedStdErr().size() << " bytes stderr: "
+ << cleanedStdErr().left(1000)
+ << ", " << msElapsed << " ms elapsed";
+ if (processStdoutLog().isDebugEnabled() && !cleanedStdOut().isEmpty())
+ qCDebug(processStdoutLog).nospace()
+ << "Process " << number << " sdout: " << cleanedStdOut();
+ if (processStderrLog().isDebugEnabled() && !cleanedStdErr().isEmpty())
+ qCDebug(processStderrLog).nospace()
+ << "Process " << number << " stderr: " << cleanedStdErr();
+ });
+ }
+}
QtcProcess::~QtcProcess()
{
+ QTC_ASSERT(!d->m_guard.isLocked(), qWarning("Deleting QtcProcess instance directly from "
+ "one of its signal handlers will lead to crash!"));
delete d;
}
+void QtcProcess::setProcessImpl(ProcessImpl processImpl)
+{
+ d->m_setup.m_processImpl = processImpl;
+}
+
ProcessMode QtcProcess::processMode() const
{
- return d->m_processMode;
+ return d->m_setup.m_processMode;
}
-QtcProcess::TerminalMode QtcProcess::terminalMode() const
+void QtcProcess::setTerminalMode(TerminalMode mode)
{
- return d->m_terminalMode;
+ d->m_setup.m_terminalMode = mode;
}
-void QtcProcess::setEnvironment(const Environment &env)
+TerminalMode QtcProcess::terminalMode() const
+{
+ return d->m_setup.m_terminalMode;
+}
+
+void QtcProcess::setProcessMode(ProcessMode processMode)
{
- d->m_environment = env;
- d->m_haveEnv = true;
+ d->m_setup.m_processMode = processMode;
}
-void QtcProcess::unsetEnvironment()
+void QtcProcess::setEnvironment(const Environment &env)
{
- d->m_environment = Environment();
- d->m_haveEnv = false;
+ d->m_setup.m_environment = env;
}
const Environment &QtcProcess::environment() const
{
- return d->m_environment;
+ return d->m_setup.m_environment;
}
-bool QtcProcess::hasEnvironment() const
+void QtcProcess::setControlEnvironment(const Environment &environment)
{
- return d->m_haveEnv;
+ d->m_setup.m_controlEnvironment = environment;
+}
+
+const Environment &QtcProcess::controlEnvironment() const
+{
+ return d->m_setup.m_controlEnvironment;
}
void QtcProcess::setCommand(const CommandLine &cmdLine)
{
- if (d->m_workingDirectory.needsDevice() && cmdLine.executable().needsDevice()) {
- QTC_CHECK(d->m_workingDirectory.host() == cmdLine.executable().host());
+ if (d->m_setup.m_workingDirectory.needsDevice() && cmdLine.executable().needsDevice()) {
+ QTC_CHECK(d->m_setup.m_workingDirectory.host() == cmdLine.executable().host());
}
- d->m_commandLine = cmdLine;
+ d->m_setup.m_commandLine = cmdLine;
}
const CommandLine &QtcProcess::commandLine() const
{
- return d->m_commandLine;
+ return d->m_setup.m_commandLine;
}
FilePath QtcProcess::workingDirectory() const
{
- return d->m_workingDirectory;
+ return d->m_setup.m_workingDirectory;
}
void QtcProcess::setWorkingDirectory(const FilePath &dir)
{
- if (dir.needsDevice() && d->m_commandLine.executable().needsDevice()) {
- QTC_CHECK(dir.host() == d->m_commandLine.executable().host());
+ if (dir.needsDevice() && d->m_setup.m_commandLine.executable().needsDevice()) {
+ QTC_CHECK(dir.host() == d->m_setup.m_commandLine.executable().host());
}
- d->m_workingDirectory = dir;
+ d->m_setup.m_workingDirectory = dir;
}
void QtcProcess::setUseCtrlCStub(bool enabled)
{
- // Do not use the stub in debug mode. Activating the stub will shut down
- // Qt Creator otherwise, because they share the same Windows console.
- // See QTCREATORBUG-11995 for details.
-#ifndef QT_DEBUG
- d->m_useCtrlCStub = enabled;
-#else
- Q_UNUSED(enabled)
-#endif
+ d->m_setup.m_useCtrlCStub = enabled;
}
void QtcProcess::start()
{
- if (d->m_commandLine.executable().needsDevice()) {
- QTC_ASSERT(s_deviceHooks.startProcessHook, return);
- s_deviceHooks.startProcessHook(*this);
- return;
- }
+ QTC_ASSERT(state() == QProcess::NotRunning, return);
d->clearForRun();
- const CommandLine cmd = d->fullCommandLine();
- const Environment env = d->fullEnvironment();
- if (d->m_process->isCustomStart())
- d->m_process->customStart(cmd, d->m_workingDirectory, env);
- else
- d->defaultStart(cmd, d->m_workingDirectory, env);
-}
-
-#ifdef Q_OS_WIN
-static BOOL sendMessage(UINT message, HWND hwnd, LPARAM lParam)
-{
- DWORD dwProcessID;
- GetWindowThreadProcessId(hwnd, &dwProcessID);
- if ((DWORD)lParam == dwProcessID) {
- SendNotifyMessage(hwnd, message, 0, 0);
- return FALSE;
+ d->m_state = QProcess::Starting;
+ ProcessInterface *processImpl = nullptr;
+ if (d->m_setup.m_commandLine.executable().needsDevice()) {
+ QTC_ASSERT(s_deviceHooks.processImplHook, d->m_state = QProcess::NotRunning; return);
+ processImpl = s_deviceHooks.processImplHook(commandLine().executable());
+ } else {
+ processImpl = d->createProcessInterface();
+ }
+ QTC_ASSERT(processImpl, d->m_state = QProcess::NotRunning; return);
+ d->setProcessInterface(processImpl);
+ d->m_process->m_setup = d->m_setup;
+ d->m_process->m_setup.m_commandLine = d->fullCommandLine();
+ d->m_process->m_setup.m_environment = d->fullEnvironment();
+ if (processLog().isDebugEnabled()) {
+ // Pass a dynamic property with info about blocking type
+ d->m_process->setProperty(QTC_PROCESS_BLOCKING_TYPE, property(QTC_PROCESS_BLOCKING_TYPE));
}
- return TRUE;
+ d->m_process->start();
}
-BOOL CALLBACK sendShutDownMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARAM lParam)
+void QtcProcess::terminate()
{
- static UINT uiShutDownMessage = RegisterWindowMessage(L"qtcctrlcstub_shutdown");
- return sendMessage(uiShutDownMessage, hwnd, lParam);
+ d->sendControlSignal(ControlSignal::Terminate);
}
-BOOL CALLBACK sendInterruptMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARAM lParam)
+void QtcProcess::kill()
{
- static UINT uiInterruptMessage = RegisterWindowMessage(L"qtcctrlcstub_interrupt");
- return sendMessage(uiInterruptMessage, hwnd, lParam);
+ d->sendControlSignal(ControlSignal::Kill);
}
-#endif
-void QtcProcess::terminate()
+void QtcProcess::interrupt()
{
-#ifdef Q_OS_WIN
- if (d->m_useCtrlCStub)
- EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId());
- else
-#endif
- d->m_process->terminate();
+ d->sendControlSignal(ControlSignal::Interrupt);
}
-void QtcProcess::interrupt()
+void QtcProcess::kickoffProcess()
{
-#ifdef Q_OS_WIN
- QTC_ASSERT(d->m_useCtrlCStub, return);
- EnumWindows(sendInterruptMessageToAllWindowsOfProcess_enumWnd, processId());
-#endif
+ d->sendControlSignal(ControlSignal::KickOff);
}
bool QtcProcess::startDetached(const CommandLine &cmd, const FilePath &workingDirectory, qint64 *pid)
@@ -923,67 +1202,86 @@ bool QtcProcess::startDetached(const CommandLine &cmd, const FilePath &workingDi
void QtcProcess::setLowPriority()
{
- d->m_process->setLowPriority();
+ d->m_setup.m_lowPriority = true;
}
void QtcProcess::setDisableUnixTerminal()
{
- d->m_process->setUnixTerminalDisabled();
+ d->m_setup.m_unixTerminalDisabled = true;
}
void QtcProcess::setAbortOnMetaChars(bool abort)
{
- d->m_process->setAbortOnMetaChars(abort);
+ d->m_setup.m_abortOnMetaChars = abort;
}
void QtcProcess::setRunAsRoot(bool on)
{
- d->m_runAsRoot = on;
+ d->m_setup.m_runAsRoot = on;
}
bool QtcProcess::isRunAsRoot() const
{
- return d->m_runAsRoot;
+ return d->m_setup.m_runAsRoot;
}
void QtcProcess::setStandardInputFile(const QString &inputFile)
{
- d->m_process->setStandardInputFile(inputFile);
+ d->m_setup.m_standardInputFile = inputFile;
}
QString QtcProcess::toStandaloneCommandLine() const
{
QStringList parts;
parts.append("/usr/bin/env");
- if (!d->m_workingDirectory.isEmpty()) {
+ if (!d->m_setup.m_workingDirectory.isEmpty()) {
parts.append("-C");
- d->m_workingDirectory.path();
+ d->m_setup.m_workingDirectory.path();
}
parts.append("-i");
- if (d->m_environment.size() > 0) {
- const QStringList envVars = d->m_environment.toStringList();
+ if (d->m_setup.m_environment.isValid()) {
+ const QStringList envVars = d->m_setup.m_environment.toStringList();
std::transform(envVars.cbegin(), envVars.cend(),
std::back_inserter(parts), ProcessArgs::quoteArgUnix);
}
- parts.append(d->m_commandLine.executable().path());
- parts.append(d->m_commandLine.splitArguments());
+ parts.append(d->m_setup.m_commandLine.executable().path());
+ parts.append(d->m_setup.m_commandLine.splitArguments());
return parts.join(" ");
}
-void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks)
+void QtcProcess::setExtraData(const QString &key, const QVariant &value)
{
- s_deviceHooks = hooks;
+ d->m_setup.m_extraData.insert(key, value);
}
-bool QtcProcess::stopProcess()
+QVariant QtcProcess::extraData(const QString &key) const
{
- if (state() == QProcess::NotRunning)
- return true;
- terminate();
- if (waitForFinished(300))
- return true;
- kill();
- return waitForFinished(300);
+ return d->m_setup.m_extraData.value(key);
+}
+
+void QtcProcess::setExtraData(const QVariantHash &extraData)
+{
+ d->m_setup.m_extraData = extraData;
+}
+
+QVariantHash QtcProcess::extraData() const
+{
+ return d->m_setup.m_extraData;
+}
+
+void QtcProcess::setReaperTimeout(int msecs)
+{
+ d->m_setup.m_reaperTimeout = msecs;
+}
+
+int QtcProcess::reaperTimeout() const
+{
+ return d->m_setup.m_reaperTimeout;
+}
+
+void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks)
+{
+ s_deviceHooks = hooks;
}
static bool askToKill(const QString &command)
@@ -1052,7 +1350,7 @@ bool QtcProcess::readDataFromProcess(int timeoutS,
}
// Prompt user, pretend we have data if says 'No'.
const bool hang = !hasData && !finished;
- hasData = hang && showTimeOutMessageBox && !askToKill(d->m_process->program());
+ hasData = hang && showTimeOutMessageBox && !askToKill(d->m_setup.m_commandLine.executable().path());
} while (hasData && !finished);
if (syncDebug)
qDebug() << "<readDataFromProcess" << finished;
@@ -1062,7 +1360,7 @@ bool QtcProcess::readDataFromProcess(int timeoutS,
QString QtcProcess::normalizeNewlines(const QString &text)
{
QString res = text;
- const auto newEnd = std::unique(res.begin(), res.end(), [](const QChar &c1, const QChar &c2) {
+ const auto newEnd = std::unique(res.begin(), res.end(), [](const QChar c1, const QChar c2) {
return c1 == '\r' && c2 == '\r'; // QTCREATORBUG-24556
});
res.chop(std::distance(newEnd, res.end()));
@@ -1070,23 +1368,40 @@ QString QtcProcess::normalizeNewlines(const QString &text)
return res;
}
-QtcProcess::Result QtcProcess::result() const
+ProcessResult QtcProcess::result() const
{
return d->m_result;
}
-void QtcProcess::setResult(Result result)
+void QtcProcess::setResult(const ProcessResult &result)
{
d->m_result = result;
}
+ProcessResultData QtcProcess::resultData() const
+{
+ return d->m_resultData;
+}
+
int QtcProcess::exitCode() const
{
- if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure)
- return 255; // This code is being returned by QProcess when FailedToStart error occurred
- return d->m_process->exitCode();
+ return resultData().m_exitCode;
+}
+
+QProcess::ExitStatus QtcProcess::exitStatus() const
+{
+ return resultData().m_exitStatus;
}
+QProcess::ProcessError QtcProcess::error() const
+{
+ return resultData().m_error;
+}
+
+QString QtcProcess::errorString() const
+{
+ return resultData().m_errorString;
+}
// Path utilities
@@ -1177,36 +1492,24 @@ Environment QtcProcess::systemEnvironmentForBinary(const FilePath &filePath)
return Environment::systemEnvironment();
}
-void QtcProcess::kickoffProcess()
-{
- d->m_process->kickoffProcess();
-}
-
-void QtcProcess::interruptProcess()
+qint64 QtcProcess::applicationMainThreadId() const
{
- d->m_process->interruptProcess();
+ return d->m_applicationMainThreadId;
}
-qint64 QtcProcess::applicationMainThreadID() const
+QProcess::ProcessChannelMode QtcProcess::processChannelMode() const
{
- return d->m_process->applicationMainThreadID();
+ return d->m_setup.m_processChannelMode;
}
void QtcProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode)
{
- d->m_process->setProcessChannelMode(mode);
-}
-
-QProcess::ProcessError QtcProcess::error() const
-{
- if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure)
- return QProcess::FailedToStart;
- return d->m_process->error();
+ d->m_setup.m_processChannelMode = mode;
}
QProcess::ProcessState QtcProcess::state() const
{
- return d->m_process->state();
+ return d->m_state;
}
bool QtcProcess::isRunning() const
@@ -1214,95 +1517,105 @@ bool QtcProcess::isRunning() const
return state() == QProcess::Running;
}
-QString QtcProcess::errorString() const
-{
- return d->m_process->errorString();
-}
-
-void QtcProcess::setErrorString(const QString &str)
-{
- d->m_process->setErrorString(str);
-}
-
qint64 QtcProcess::processId() const
{
- return d->m_process->processId();
+ return d->m_processId;
}
bool QtcProcess::waitForStarted(int msecs)
{
- return s_waitForStarted.measureAndRun(&ProcessInterface::waitForStarted, d->m_process, msecs);
+ QTC_ASSERT(d->m_process, return false);
+ if (d->m_state == QProcess::Running)
+ return true;
+ if (d->m_state == QProcess::NotRunning)
+ return false;
+ return s_waitForStarted.measureAndRun(&QtcProcessPrivate::waitForSignal, d,
+ ProcessSignalType::Started, msecs);
}
bool QtcProcess::waitForReadyRead(int msecs)
{
- return d->m_process->waitForReadyRead(msecs);
+ QTC_ASSERT(d->m_process, return false);
+ if (d->m_state == QProcess::NotRunning)
+ return false;
+ return d->waitForSignal(ProcessSignalType::ReadyRead, msecs);
}
bool QtcProcess::waitForFinished(int msecs)
{
- return d->m_process->waitForFinished(msecs);
+ QTC_ASSERT(d->m_process, return false);
+ if (d->m_state == QProcess::NotRunning)
+ return false;
+ return d->waitForSignal(ProcessSignalType::Done, msecs);
}
QByteArray QtcProcess::readAllStandardOutput()
{
- QByteArray buf = d->m_stdOut.rawData;
- d->m_stdOut.rawData.clear();
- return buf;
+ return d->m_stdOut.readAllData();
}
QByteArray QtcProcess::readAllStandardError()
{
- QByteArray buf = d->m_stdErr.rawData;
- d->m_stdErr.rawData.clear();
- return buf;
+ return d->m_stdErr.readAllData();
}
-QProcess::ExitStatus QtcProcess::exitStatus() const
+qint64 QtcProcess::write(const QString &input)
{
- return d->m_process->exitStatus();
-}
+ // Non-windows is assumed to be UTF-8
+ if (commandLine().executable().osType() != OsTypeWindows)
+ return writeRaw(input.toUtf8());
-void QtcProcess::kill()
-{
- d->m_process->kill();
+ if (HostOsInfo::hostOs() == OsTypeWindows)
+ return writeRaw(input.toLocal8Bit());
+
+ // "remote" Windows target on non-Windows host is unlikely,
+ // but the true encoding is not accessible. Use UTF8 as best guess.
+ QTC_CHECK(false);
+ return writeRaw(input.toUtf8());
}
-qint64 QtcProcess::write(const QByteArray &input)
+qint64 QtcProcess::writeRaw(const QByteArray &input)
{
QTC_ASSERT(processMode() == ProcessMode::Writer, return -1);
- return d->m_process->write(input);
+ QTC_ASSERT(d->m_process, return -1);
+ QTC_ASSERT(state() == QProcess::Running, return -1);
+ QTC_ASSERT(QThread::currentThread() == thread(), return -1);
+ qint64 result = -1;
+ QMetaObject::invokeMethod(d->m_process.get(), [this, input] {
+ d->m_process->write(input);
+ }, d->connectionType(), &result);
+ return result;
}
void QtcProcess::close()
{
- d->m_process->close();
-}
-
-void QtcProcess::beginFeed()
-{
+ QTC_ASSERT(QThread::currentThread() == thread(), return);
+ if (d->m_process) {
+ // Note: the m_process may be inside ProcessInterfaceHandler's thread.
+ QTC_ASSERT(d->m_process->thread() == thread(), return);
+ d->m_process->disconnect();
+ d->m_process.release()->deleteLater();
+ }
+ if (d->m_blockingInterface) {
+ d->m_blockingInterface->disconnect();
+ d->m_blockingInterface.release()->deleteLater();
+ }
d->clearForRun();
}
-void QtcProcess::endFeed()
-{
- d->slotFinished(0, QProcess::NormalExit);
-}
-
-void QtcProcess::feedStdOut(const QByteArray &data)
+/*
+ Calls terminate() directly and after a delay of reaperTimeout() it calls kill()
+ if the process is still running.
+*/
+void QtcProcess::stop()
{
- d->m_stdOut.append(data);
- d->m_hangTimerCount = 0;
- emit readyReadStandardOutput();
-}
+ if (state() == QProcess::NotRunning)
+ return;
-QString QtcProcess::locateBinary(const QString &binary)
-{
- const QByteArray path = qgetenv("PATH");
- return locateBinary(QString::fromLocal8Bit(path), binary);
+ d->sendControlSignal(ControlSignal::Terminate);
+ d->m_killTimer.start(d->m_process->m_setup.m_reaperTimeout);
}
-
/*!
\class Utils::SynchronousProcess
@@ -1333,20 +1646,20 @@ QString QtcProcess::locateBinary(const QString &binary)
as this will cause event loop problems.
*/
-QString QtcProcess::exitMessage()
+QString QtcProcess::exitMessage() const
{
const QString fullCmd = commandLine().toUserOutput();
switch (result()) {
- case FinishedWithSuccess:
+ case ProcessResult::FinishedWithSuccess:
return QtcProcess::tr("The command \"%1\" finished successfully.").arg(fullCmd);
- case FinishedWithError:
+ case ProcessResult::FinishedWithError:
return QtcProcess::tr("The command \"%1\" terminated with exit code %2.")
.arg(fullCmd).arg(exitCode());
- case TerminatedAbnormally:
+ case ProcessResult::TerminatedAbnormally:
return QtcProcess::tr("The command \"%1\" terminated abnormally.").arg(fullCmd);
- case StartFailed:
+ case ProcessResult::StartFailed:
return QtcProcess::tr("The command \"%1\" could not be started.").arg(fullCmd);
- case Hang:
+ case ProcessResult::Hang:
return QtcProcess::tr("The command \"%1\" did not respond within the timeout limit (%2 s).")
.arg(fullCmd).arg(d->m_maxHangTimerCount);
}
@@ -1371,8 +1684,8 @@ QString QtcProcess::allOutput() const
{
QTC_CHECK(d->m_stdOut.keepRawData);
QTC_CHECK(d->m_stdErr.keepRawData);
- const QString out = stdOut();
- const QString err = stdErr();
+ const QString out = cleanedStdOut();
+ const QString err = cleanedStdErr();
if (!out.isEmpty() && !err.isEmpty()) {
QString result = out;
@@ -1384,10 +1697,16 @@ QString QtcProcess::allOutput() const
return !out.isEmpty() ? out : err;
}
+QByteArray QtcProcess::rawStdOut() const
+{
+ QTC_CHECK(d->m_stdOut.keepRawData);
+ return d->m_stdOut.rawData;
+}
+
QString QtcProcess::stdOut() const
{
QTC_CHECK(d->m_stdOut.keepRawData);
- return normalizeNewlines(d->m_codec->toUnicode(d->m_stdOut.rawData));
+ return d->m_codec->toUnicode(d->m_stdOut.rawData);
}
QString QtcProcess::stdErr() const
@@ -1397,20 +1716,44 @@ QString QtcProcess::stdErr() const
// is not trivial. So weaken it a bit for now.
//QTC_CHECK(d->m_stdErr.keepRawData);
QTC_CHECK(d->m_stdErr.keepRawData || d->m_stdErr.rawData.isEmpty());
- return normalizeNewlines(d->m_codec->toUnicode(d->m_stdErr.rawData));
+ return d->m_codec->toUnicode(d->m_stdErr.rawData);
}
-QByteArray QtcProcess::rawStdOut() const
+QString QtcProcess::cleanedStdOut() const
{
- QTC_CHECK(d->m_stdOut.keepRawData);
- return d->m_stdOut.rawData;
+ return normalizeNewlines(stdOut());
+}
+
+QString QtcProcess::cleanedStdErr() const
+{
+ return normalizeNewlines(stdErr());
+}
+
+static QStringList splitLines(const QString &text)
+{
+ QStringList result = text.split('\n');
+ for (QString &line : result) {
+ if (line.endsWith('\r'))
+ line.chop(1);
+ }
+ return result;
+}
+
+const QStringList QtcProcess::stdOutLines() const
+{
+ return splitLines(cleanedStdOut());
+}
+
+const QStringList QtcProcess::stdErrLines() const
+{
+ return splitLines(cleanedStdErr());
}
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r)
{
QDebug nsp = str.nospace();
nsp << "QtcProcess: result="
- << r.d->m_result << " ex=" << r.exitCode() << '\n'
+ << int(r.d->m_result) << " ex=" << r.exitCode() << '\n'
<< r.d->m_stdOut.rawData.size() << " bytes stdout, stderr=" << r.d->m_stdErr.rawData << '\n';
return str;
}
@@ -1511,7 +1854,7 @@ void QtcProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter)
void QtcProcess::setWriteData(const QByteArray &writeData)
{
- d->m_writeData = writeData;
+ d->m_setup.m_writeData = writeData;
}
#ifdef QT_GUI_LIB
@@ -1521,27 +1864,23 @@ static bool isGuiThread()
}
#endif
-void QtcProcess::runBlocking(QtcProcess::EventLoopMode eventLoopMode)
+void QtcProcess::runBlocking(EventLoopMode eventLoopMode)
{
- // FIXME: Implement properly
-
- if (d->m_commandLine.executable().needsDevice()) {
- QtcProcess::start();
- waitForFinished();
- return;
- };
-
- qCDebug(processLog).noquote() << "Starting blocking:" << d->m_commandLine.toUserOutput()
- << " process user events: " << (eventLoopMode == QtcProcess::WithEventLoop);
- ExecuteOnDestruction logResult([this] { qCDebug(processLog) << *this; });
-
- if (eventLoopMode == QtcProcess::WithEventLoop) {
- QtcProcess::start();
+ if (processLog().isDebugEnabled()) {
+ // Attach a dynamic property with info about blocking type
+ setProperty(QTC_PROCESS_BLOCKING_TYPE, int(eventLoopMode));
+ }
- // On Windows, start failure is triggered immediately if the
- // executable cannot be found in the path. Do not start the
- // event loop in that case.
- if (d->m_startFailure == QtcProcessPrivate::NoFailure) {
+ QtcProcess::start();
+ if (processLog().isDebugEnabled()) {
+ // Remove the dynamic property so that it's not reused in subseqent start()
+ setProperty(QTC_PROCESS_BLOCKING_TYPE, QVariant());
+ }
+ if (eventLoopMode == EventLoopMode::On) {
+ // Start failure is triggered immediately if the executable cannot be found in the path.
+ // In this case the process is left in NotRunning state.
+ // Do not start the event loop in that case.
+ if (state() == QProcess::Starting) {
QTimer timer(this);
connect(&timer, &QTimer::timeout, d, &QtcProcessPrivate::slotTimeout);
timer.setInterval(1000);
@@ -1555,9 +1894,6 @@ void QtcProcess::runBlocking(QtcProcess::EventLoopMode eventLoopMode)
d->m_eventLoop = &eventLoop;
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
d->m_eventLoop = nullptr;
- d->m_stdOut.append(d->m_process->readAllStandardOutput());
- d->m_stdErr.append(d->m_process->readAllStandardError());
-
timer.stop();
#ifdef QT_GUI_LIB
if (isGuiThread())
@@ -1565,25 +1901,18 @@ void QtcProcess::runBlocking(QtcProcess::EventLoopMode eventLoopMode)
#endif
}
} else {
- QtcProcess::start();
if (!waitForStarted(d->m_maxHangTimerCount * 1000)) {
- d->m_result = QtcProcess::StartFailed;
+ d->m_result = ProcessResult::StartFailed;
return;
}
if (!waitForFinished(d->m_maxHangTimerCount * 1000)) {
- d->m_result = QtcProcess::Hang;
+ d->m_result = ProcessResult::Hang;
terminate();
if (!waitForFinished(1000)) {
kill();
waitForFinished(1000);
}
}
-
- if (state() != QProcess::NotRunning)
- return;
-
- d->m_stdOut.append(d->m_process->readAllStandardOutput());
- d->m_stdErr.append(d->m_process->readAllStandardError());
}
}
@@ -1620,11 +1949,12 @@ void QtcProcessPrivate::slotTimeout()
qDebug() << Q_FUNC_INFO << "HANG detected, killing";
m_waitingForUser = true;
const bool terminate = !m_timeOutMessageBoxEnabled
- || askToKill(m_commandLine.executable().toString());
+ || askToKill(m_setup.m_commandLine.executable().toString());
m_waitingForUser = false;
if (terminate) {
- q->stopProcess();
- m_result = QtcProcess::Hang;
+ q->stop();
+ q->waitForFinished();
+ m_result = ProcessResult::Hang;
} else {
m_hangTimerCount = 0;
}
@@ -1634,44 +1964,122 @@ void QtcProcessPrivate::slotTimeout()
}
}
-void QtcProcessPrivate::slotFinished(int exitCode, QProcess::ExitStatus status)
+void QtcProcessPrivate::handleStarted(qint64 processId, qint64 applicationMainThreadId)
{
- if (debug)
- qDebug() << Q_FUNC_INFO << exitCode << status;
+ QTC_CHECK(m_state == QProcess::Starting);
+ m_state = QProcess::Running;
+
+ m_processId = processId;
+ m_applicationMainThreadId = applicationMainThreadId;
+ emitStarted();
+}
+
+void QtcProcessPrivate::handleReadyRead(const QByteArray &outputData, const QByteArray &errorData)
+{
+ QTC_CHECK(m_state == QProcess::Running);
+
+ // TODO: check why we need this timer?
m_hangTimerCount = 0;
+ // TODO: store a copy of m_processChannelMode on start()? Currently we assert that state
+ // is NotRunning when setting the process channel mode.
+
+ if (!outputData.isEmpty()) {
+ if (m_process->m_setup.m_processChannelMode == QProcess::ForwardedOutputChannel
+ || m_process->m_setup.m_processChannelMode == QProcess::ForwardedChannels) {
+ std::cout << outputData.constData() << std::flush;
+ } else {
+ m_stdOut.append(outputData);
+ emitReadyReadStandardOutput();
+ }
+ }
+ if (!errorData.isEmpty()) {
+ if (m_process->m_setup.m_processChannelMode == QProcess::ForwardedErrorChannel
+ || m_process->m_setup.m_processChannelMode == QProcess::ForwardedChannels) {
+ std::cerr << errorData.constData() << std::flush;
+ } else {
+ m_stdErr.append(errorData);
+ emitReadyReadStandardError();
+ }
+ }
+}
+
+void QtcProcessPrivate::handleDone(const ProcessResultData &data)
+{
+ m_killTimer.stop();
+ m_resultData = data;
- switch (status) {
- case QProcess::NormalExit:
- m_result = interpretExitCode(exitCode);
+ switch (m_state) {
+ case QProcess::NotRunning:
+ QTC_CHECK(false); // Can't happen
+ break;
+ case QProcess::Starting:
+ QTC_CHECK(m_resultData.m_error == QProcess::FailedToStart);
break;
- case QProcess::CrashExit:
- // Was hang detected before and killed?
- if (m_result != QtcProcess::Hang)
- m_result = QtcProcess::TerminatedAbnormally;
+ case QProcess::Running:
+ QTC_CHECK(m_resultData.m_error != QProcess::FailedToStart);
break;
}
+ m_state = QProcess::NotRunning;
+
+ // This code (255) is being returned by QProcess when FailedToStart error occurred
+ if (m_resultData.m_error == QProcess::FailedToStart)
+ m_resultData.m_exitCode = 0xFF;
+
+ // HACK: See QIODevice::errorString() implementation.
+ if (m_resultData.m_error == QProcess::UnknownError)
+ m_resultData.m_errorString.clear();
+ else if (m_result != ProcessResult::Hang)
+ m_result = ProcessResult::StartFailed;
+
+ if (debug)
+ qDebug() << Q_FUNC_INFO << m_resultData.m_exitCode << m_resultData.m_exitStatus;
+ m_hangTimerCount = 0;
+
+ if (m_resultData.m_error != QProcess::FailedToStart) {
+ switch (m_resultData.m_exitStatus) {
+ case QProcess::NormalExit:
+ m_result = interpretExitCode(m_resultData.m_exitCode);
+ break;
+ case QProcess::CrashExit:
+ // Was hang detected before and killed?
+ if (m_result != ProcessResult::Hang)
+ m_result = ProcessResult::TerminatedAbnormally;
+ break;
+ }
+ }
if (m_eventLoop)
m_eventLoop->quit();
m_stdOut.handleRest();
m_stdErr.handleRest();
- emit q->finished();
+ emitDone();
+ m_processId = 0;
+ m_applicationMainThreadId = 0;
}
-void QtcProcessPrivate::handleError(QProcess::ProcessError error, StartFailure startFailure)
+void QtcProcessPrivate::emitStarted()
{
- m_hangTimerCount = 0;
- if (debug)
- qDebug() << Q_FUNC_INFO << error;
- // Was hang detected before and killed?
- if (m_result != QtcProcess::Hang)
- m_result = QtcProcess::StartFailed;
- m_startFailure = startFailure;
- if (m_eventLoop)
- m_eventLoop->quit();
+ GuardLocker locker(m_guard);
+ emit q->started();
+}
- emit q->errorOccurred(error);
+void QtcProcessPrivate::emitDone()
+{
+ GuardLocker locker(m_guard);
+ emit q->done();
+}
+
+void QtcProcessPrivate::emitReadyReadStandardOutput()
+{
+ GuardLocker locker(m_guard);
+ emit q->readyReadStandardOutput();
+}
+
+void QtcProcessPrivate::emitReadyReadStandardError()
+{
+ GuardLocker locker(m_guard);
+ emit q->readyReadStandardError();
}
} // namespace Utils
diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h
index fa844d18955..5dc24ee0046 100644
--- a/src/libs/utils/qtcprocess.h
+++ b/src/libs/utils/qtcprocess.h
@@ -27,221 +27,196 @@
#include "utils_global.h"
-#include "environment.h"
#include "commandline.h"
-#include "processutils.h"
+#include "processenums.h"
#include <QProcess>
-#include <functional>
-
-QT_FORWARD_DECLARE_CLASS(QDebug)
-QT_FORWARD_DECLARE_CLASS(QTextCodec)
+QT_BEGIN_NAMESPACE
+class QDebug;
+class QTextCodec;
+QT_END_NAMESPACE
class tst_QtcProcess;
namespace Utils {
-class CommandLine;
-class Environment;
-class QtcProcess;
-
namespace Internal { class QtcProcessPrivate; }
-class DeviceProcessHooks
-{
-public:
- std::function<void(QtcProcess &)> startProcessHook;
- std::function<Environment(const FilePath &)> systemEnvironmentForBinary;
-};
+class Environment;
+class DeviceProcessHooks;
+class ProcessInterface;
+class ProcessResultData;
-class QTCREATOR_UTILS_EXPORT QtcProcess : public QObject
+class QTCREATOR_UTILS_EXPORT QtcProcess final : public QObject
{
Q_OBJECT
public:
- enum ProcessImpl {
- QProcessImpl,
- ProcessLauncherImpl,
- DefaultImpl,
- };
-
- enum TerminalMode {
- TerminalOff,
- TerminalRun,
- TerminalDebug,
- TerminalSuspend,
- TerminalOn = TerminalRun // default mode for ON
- };
-
- struct Setup {
- Setup() {}
- Setup(ProcessImpl processImpl) : processImpl(processImpl) {}
- Setup(ProcessMode processMode) : processMode(processMode) {}
- Setup(TerminalMode terminalMode) : terminalMode(terminalMode) {}
-
- ProcessImpl processImpl = DefaultImpl;
- ProcessMode processMode = ProcessMode::Reader;
- TerminalMode terminalMode = TerminalOff;
- };
-
- QtcProcess(const Setup &setup = {}, QObject *parent = nullptr);
- QtcProcess(QObject *parent);
+ QtcProcess(QObject *parent = nullptr);
~QtcProcess();
- ProcessMode processMode() const;
+ // ProcessInterface related
+
+ void start();
+
+ void terminate();
+ void kill();
+ void interrupt();
+ void kickoffProcess();
+ void close();
+ void stop();
+
+ QByteArray readAllStandardOutput();
+ QByteArray readAllStandardError();
+
+ qint64 write(const QString &input);
+ qint64 writeRaw(const QByteArray &input);
+
+ qint64 processId() const;
+ qint64 applicationMainThreadId() const;
+
+ QProcess::ProcessState state() const;
+ virtual ProcessResultData resultData() const;
+
+ int exitCode() const;
+ QProcess::ExitStatus exitStatus() const;
+
+ QProcess::ProcessError error() const;
+ QString errorString() const;
+
+ bool waitForStarted(int msecs = 30000);
+ bool waitForReadyRead(int msecs = 30000);
+ bool waitForFinished(int msecs = 30000);
+
+ // ProcessSetupData related
+
+ void setProcessImpl(ProcessImpl processImpl);
+
+ void setTerminalMode(TerminalMode mode);
TerminalMode terminalMode() const;
+ bool usesTerminal() const { return terminalMode() != TerminalMode::Off; }
- enum Result {
- // Finished successfully. Unless an ExitCodeInterpreter is set
- // this corresponds to a return code 0.
- FinishedWithSuccess,
- Finished = FinishedWithSuccess, // FIXME: Kept to ease downstream transition
- // Finished unsuccessfully. Unless an ExitCodeInterpreter is set
- // this corresponds to a return code different from 0.
- FinishedWithError,
- FinishedError = FinishedWithError, // FIXME: Kept to ease downstream transition
- // Process terminated abnormally (kill)
- TerminatedAbnormally,
- // Executable could not be started
- StartFailed,
- // Hang, no output after time out
- Hang
- };
-
- void setEnvironment(const Environment &env);
- void unsetEnvironment();
+ void setProcessMode(ProcessMode processMode);
+ ProcessMode processMode() const;
+
+ void setEnvironment(const Environment &env); // Main process
const Environment &environment() const;
- bool hasEnvironment() const;
+
+ void setControlEnvironment(const Environment &env); // Possible helper process (ssh on host etc)
+ const Environment &controlEnvironment() const;
void setCommand(const CommandLine &cmdLine);
const CommandLine &commandLine() const;
- FilePath workingDirectory() const;
void setWorkingDirectory(const FilePath &dir);
+ FilePath workingDirectory() const;
+
+ void setWriteData(const QByteArray &writeData);
- void setUseCtrlCStub(bool enabled);
+ void setUseCtrlCStub(bool enabled); // release only
void setLowPriority();
void setDisableUnixTerminal();
void setRunAsRoot(bool on);
bool isRunAsRoot() const;
-
void setAbortOnMetaChars(bool abort);
- void start();
- virtual void terminate();
- virtual void interrupt();
+ QProcess::ProcessChannelMode processChannelMode() const;
+ void setProcessChannelMode(QProcess::ProcessChannelMode mode);
+ void setStandardInputFile(const QString &inputFile);
+
+ void setExtraData(const QString &key, const QVariant &value);
+ QVariant extraData(const QString &key) const;
+
+ void setExtraData(const QVariantHash &extraData);
+ QVariantHash extraData() const;
+
+ void setReaperTimeout(int msecs);
+ int reaperTimeout() const;
+
+ static void setRemoteProcessHooks(const DeviceProcessHooks &hooks);
+
+ // TODO: Some usages of this method assume that Starting phase is also a running state
+ // i.e. if isRunning() returns false, they assume NotRunning state, what may be an error.
+ bool isRunning() const; // Short for state() == QProcess::Running.
+
+ // Other enhancements.
+ // These (or some of them) may be potentially moved outside of the class.
+ // For some we may aggregate in another public utils class (or subclass of QtcProcess)?
+
+ // TODO: How below 2 methods relate to QtcProcess?
+ // Action: move/merge them somewhere else, FilePath::searchInPath() ?
+ // Helpers to find binaries. Do not use it for other path variables
+ // and file types.
+ static QString locateBinary(const QString &path, const QString &binary);
+ static QString normalizeNewlines(const QString &text);
+
+ // TODO: Unused currently? Should it serve as a compartment for contrary of remoteEnvironment?
+ static Environment systemEnvironmentForBinary(const FilePath &filePath);
static bool startDetached(const CommandLine &cmd, const FilePath &workingDirectory = {},
qint64 *pid = nullptr);
- enum EventLoopMode {
- NoEventLoop,
- WithEventLoop // Avoid
- };
-
// Starts the command and waits for finish.
- // User input processing is enabled when WithEventLoop was passed.
- void runBlocking(EventLoopMode eventLoopMode = NoEventLoop);
+ // User input processing is enabled when EventLoopMode::On was passed.
+ void runBlocking(EventLoopMode eventLoopMode = EventLoopMode::Off);
/* Timeout for hanging processes (triggers after no more output
* occurs on stderr/stdout). */
void setTimeoutS(int timeoutS);
+ // TODO: We should specify the purpose of the codec, e.g. setCodecForStandardChannel()
void setCodec(QTextCodec *c);
void setTimeOutMessageBoxEnabled(bool);
- void setExitCodeInterpreter(const std::function<QtcProcess::Result(int)> &interpreter);
-
- void setWriteData(const QByteArray &writeData);
+ void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter);
void setStdOutCallback(const std::function<void(const QString &)> &callback);
void setStdOutLineCallback(const std::function<void(const QString &)> &callback);
void setStdErrCallback(const std::function<void(const QString &)> &callback);
void setStdErrLineCallback(const std::function<void(const QString &)> &callback);
- static void setRemoteProcessHooks(const DeviceProcessHooks &hooks);
-
- bool stopProcess();
bool readDataFromProcess(int timeoutS, QByteArray *stdOut, QByteArray *stdErr,
bool showTimeOutMessageBox);
- static QString normalizeNewlines(const QString &text);
-
- Result result() const;
- void setResult(Result result);
+ ProcessResult result() const;
+ void setResult(const ProcessResult &result);
QByteArray allRawOutput() const;
QString allOutput() const;
- QString stdOut() const;
- QString stdErr() const;
-
QByteArray rawStdOut() const;
- virtual int exitCode() const;
-
- QString exitMessage();
-
- // Helpers to find binaries. Do not use it for other path variables
- // and file types.
- static QString locateBinary(const QString &binary);
- static QString locateBinary(const QString &path, const QString &binary);
-
- static Environment systemEnvironmentForBinary(const FilePath &filePath);
-
- void kickoffProcess();
- void interruptProcess();
- qint64 applicationMainThreadID() const;
-
- // FIXME: Cut down the following bits inherited from QProcess and QIODevice.
-
- void setProcessChannelMode(QProcess::ProcessChannelMode mode);
-
- QProcess::ProcessError error() const;
- virtual QProcess::ProcessState state() const;
- bool isRunning() const; // Short for state() == QProcess::Running.
-
- virtual QString errorString() const;
- void setErrorString(const QString &str);
-
- qint64 processId() const;
-
- bool waitForStarted(int msecs = 30000);
- bool waitForReadyRead(int msecs = 30000);
- bool waitForFinished(int msecs = 30000);
-
- virtual QByteArray readAllStandardOutput();
- virtual QByteArray readAllStandardError();
+ QString stdOut() const; // possibly with CR
+ QString stdErr() const; // possibly with CR
- virtual QProcess::ExitStatus exitStatus() const;
+ QString cleanedStdOut() const; // with sequences of CR squashed and CR LF replaced by LF
+ QString cleanedStdErr() const; // with sequences of CR squashed and CR LF replaced by LF
- virtual void kill();
+ const QStringList stdOutLines() const; // split, CR removed
+ const QStringList stdErrLines() const; // split, CR removed
- virtual qint64 write(const QByteArray &input);
- void close();
-
- void setStandardInputFile(const QString &inputFile);
+ QString exitMessage() const;
QString toStandaloneCommandLine() const;
signals:
void started();
- void finished();
- void errorOccurred(QProcess::ProcessError error);
+ void done();
void readyReadStandardOutput();
void readyReadStandardError();
private:
friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r);
+ friend class Internal::QtcProcessPrivate;
Internal::QtcProcessPrivate *d = nullptr;
-
- friend tst_QtcProcess;
- void beginFeed();
- void feedStdOut(const QByteArray &data);
- void endFeed();
};
-using ExitCodeInterpreter = std::function<QtcProcess::Result(int /*exitCode*/)>;
+class DeviceProcessHooks
+{
+public:
+ std::function<ProcessInterface *(const FilePath &)> processImplHook;
+ std::function<Environment(const FilePath &)> systemEnvironmentForBinary;
+};
} // namespace Utils
diff --git a/src/libs/utils/reloadpromptutils.cpp b/src/libs/utils/reloadpromptutils.cpp
index 210791157c6..276c272dbc8 100644
--- a/src/libs/utils/reloadpromptutils.cpp
+++ b/src/libs/utils/reloadpromptutils.cpp
@@ -23,9 +23,10 @@
**
****************************************************************************/
-#include "fileutils.h"
#include "reloadpromptutils.h"
+#include "fileutils.h"
+
#include <QCoreApplication>
#include <QDir>
#include <QMessageBox>
@@ -50,10 +51,11 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FilePath &fileName,
msg = QCoreApplication::translate("Utils::reloadPrompt",
"The file <i>%1</i> has been changed on disk. Do you want to reload it?");
}
- msg = "<p>" + msg.arg(fileName.fileName()) + "</p><p>" +
- QCoreApplication::translate("Utils::reloadPrompt",
- "The default behavior can be set in Tools > Options > Environment > System.")
- + "</p>";
+ msg = "<p>" + msg.arg(fileName.fileName()) + "</p><p>"
+ + QCoreApplication::translate(
+ "Utils::reloadPrompt",
+ "The default behavior can be set in Edit > Preferences > Environment > System.")
+ + "</p>";
return reloadPrompt(title, msg, fileName.toUserOutput(), enableDiffOption, parent);
}
diff --git a/src/libs/utils/removefiledialog.cpp b/src/libs/utils/removefiledialog.cpp
index 4bc4fa24dad..edc9f57dbf3 100644
--- a/src/libs/utils/removefiledialog.cpp
+++ b/src/libs/utils/removefiledialog.cpp
@@ -26,7 +26,7 @@
#include "removefiledialog.h"
#include "ui_removefiledialog.h"
-#include <utils/filepath.h>
+#include "filepath.h"
namespace Utils {
diff --git a/src/libs/utils/runextensions.h b/src/libs/utils/runextensions.h
index e7b9dd6c939..6fed1cbae05 100644
--- a/src/libs/utils/runextensions.h
+++ b/src/libs/utils/runextensions.h
@@ -25,9 +25,10 @@
#pragma once
+#include "utils_global.h"
+
#include "functiontraits.h"
#include "optional.h"
-#include "utils_global.h"
#include <QCoreApplication>
#include <QFuture>
@@ -481,7 +482,7 @@ runAsync(QThread::Priority priority, Function &&function, Args&&... args)
template<typename Function,
typename... Args,
typename ResultType = typename Internal::resultType<Function>::type>
-QFuture<ResultType> runAsync(Utils::StackSizeInBytes stackSize, Function &&function, Args &&... args)
+QFuture<ResultType> runAsync(StackSizeInBytes stackSize, Function &&function, Args &&... args)
{
return Internal::runAsync_internal(static_cast<QThreadPool *>(nullptr),
stackSize,
@@ -500,7 +501,7 @@ QFuture<ResultType> runAsync(Utils::StackSizeInBytes stackSize, Function &&funct
template<typename Function,
typename... Args,
typename ResultType = typename Internal::resultType<Function>::type>
-QFuture<ResultType> runAsync(Utils::StackSizeInBytes stackSize,
+QFuture<ResultType> runAsync(StackSizeInBytes stackSize,
QThread::Priority priority,
Function &&function,
Args &&... args)
diff --git a/src/libs/utils/savefile.cpp b/src/libs/utils/savefile.cpp
index 721a87217ea..859085ea09f 100644
--- a/src/libs/utils/savefile.cpp
+++ b/src/libs/utils/savefile.cpp
@@ -24,8 +24,12 @@
****************************************************************************/
#include "savefile.h"
+
+#include "filepath.h"
#include "qtcassert.h"
-#include "fileutils.h"
+
+#include <QTemporaryFile>
+
#ifdef Q_OS_WIN
# include <windows.h>
# include <io.h>
diff --git a/src/libs/utils/savefile.h b/src/libs/utils/savefile.h
index 4978de08e1d..336c6999e79 100644
--- a/src/libs/utils/savefile.h
+++ b/src/libs/utils/savefile.h
@@ -27,7 +27,11 @@
#include "utils_global.h"
-#include <QTemporaryFile>
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+class QTemporaryFile;
+QT_END_NAMESPACE
#include <memory>
diff --git a/src/libs/utils/settingsaccessor.cpp b/src/libs/utils/settingsaccessor.cpp
index 7c847446f95..784e685812e 100644
--- a/src/libs/utils/settingsaccessor.cpp
+++ b/src/libs/utils/settingsaccessor.cpp
@@ -27,9 +27,9 @@
#include "algorithm.h"
#include "qtcassert.h"
+#include "persistentsettings.h"
#include <QApplication>
-#include <QDebug>
#include <QDir>
namespace {
@@ -73,6 +73,8 @@ applicationDisplayName(applicationDisplayName)
QTC_CHECK(!applicationDisplayName.isEmpty());
}
+SettingsAccessor::~SettingsAccessor() = default;
+
/*!
* Restore settings from disk and report any issues in a message box centered on \a parent.
*/
@@ -300,7 +302,7 @@ BackingUpSettingsAccessor::writeData(const FilePath &path, const QVariantMap &da
FilePaths BackingUpSettingsAccessor::readFileCandidates(const FilePath &path) const
{
- FilePaths result = Utils::filteredUnique(m_strategy->readFileCandidates(path));
+ FilePaths result = filteredUnique(m_strategy->readFileCandidates(path));
if (result.removeOne(baseFilePath()))
result.prepend(baseFilePath());
@@ -747,7 +749,7 @@ static QVariant mergeQVariantMapsRecursion(const QVariantMap &mainTree, const QV
const SettingsMergeFunction &merge)
{
QVariantMap result;
- const QList<QString> allKeys = Utils::filteredUnique(mainSubtree.keys() + secondarySubtree.keys());
+ const QList<QString> allKeys = filteredUnique(mainSubtree.keys() + secondarySubtree.keys());
MergingSettingsAccessor::SettingsMergeData global = {mainTree, secondaryTree, QString()};
MergingSettingsAccessor::SettingsMergeData local = {mainSubtree, secondarySubtree, QString()};
diff --git a/src/libs/utils/settingsaccessor.h b/src/libs/utils/settingsaccessor.h
index 4edfd5393fc..f52b528fa30 100644
--- a/src/libs/utils/settingsaccessor.h
+++ b/src/libs/utils/settingsaccessor.h
@@ -27,9 +27,8 @@
#include "utils_global.h"
-#include "fileutils.h"
+#include "filepath.h"
#include "optional.h"
-#include "persistentsettings.h"
#include <QHash>
#include <QMessageBox>
@@ -63,6 +62,7 @@ QTCREATOR_UTILS_EXPORT void setVersionInMap(QVariantMap &data, int version);
QTCREATOR_UTILS_EXPORT void setOriginalVersionInMap(QVariantMap &data, int version);
QTCREATOR_UTILS_EXPORT void setSettingsIdInMap(QVariantMap &data, const QByteArray &id);
+class PersistentSettingsWriter;
using SettingsMergeResult = optional<QPair<QString, QVariant>>;
// --------------------------------------------------------------------
@@ -75,7 +75,7 @@ class QTCREATOR_UTILS_EXPORT SettingsAccessor
public:
SettingsAccessor(const QString &docType, const QString &displayName,
const QString &applicationDisplayName);
- virtual ~SettingsAccessor() = default;
+ virtual ~SettingsAccessor();
enum ProceedInfo { Continue, DiscardAndContinue };
using ButtonMap = QHash<QMessageBox::StandardButton, ProceedInfo>;
diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp
index e5527c127b4..81c293c8d99 100644
--- a/src/libs/utils/shellcommand.cpp
+++ b/src/libs/utils/shellcommand.cpp
@@ -26,19 +26,13 @@
#include "shellcommand.h"
#include "environment.h"
-#include "fileutils.h"
#include "qtcassert.h"
+#include "qtcprocess.h"
#include "runextensions.h"
-#include <QFileInfo>
#include <QFuture>
#include <QFutureWatcher>
#include <QMutex>
-#include <QProcess>
-#include <QProcessEnvironment>
-#include <QScopedPointer>
-#include <QSharedPointer>
-#include <QStringList>
#include <QTextCodec>
#include <QThread>
#include <QVariant>
@@ -208,7 +202,7 @@ void ShellCommand::execute()
if (d->m_jobs.empty())
return;
- QFuture<void> task = Utils::runAsync(&ShellCommand::run, this);
+ QFuture<void> task = runAsync(&ShellCommand::run, this);
d->m_watcher.setFuture(task);
if (!(d->m_flags & SuppressCommandLogging))
addTask(task);
@@ -277,10 +271,10 @@ void ShellCommand::run(QFutureInterface<void> &future)
proc.setExitCodeInterpreter(job.exitCodeInterpreter);
proc.setTimeoutS(job.timeoutS);
runCommand(proc, job.command, job.workingDirectory);
- stdOut += proc.stdOut();
- stdErr += proc.stdErr();
+ stdOut += proc.cleanedStdOut();
+ stdErr += proc.cleanedStdErr();
d->m_lastExecExitCode = proc.exitCode();
- d->m_lastExecSuccess = proc.result() == QtcProcess::FinishedWithSuccess;
+ d->m_lastExecSuccess = proc.result() == ProcessResult::FinishedWithSuccess;
if (!d->m_lastExecSuccess)
break;
}
@@ -314,7 +308,7 @@ void ShellCommand::runCommand(QtcProcess &proc,
const FilePath dir = workDirectory(workingDirectory);
if (command.executable().isEmpty()) {
- proc.setResult(QtcProcess::StartFailed);
+ proc.setResult(ProcessResult::StartFailed);
return;
}
@@ -332,7 +326,7 @@ void ShellCommand::runCommand(QtcProcess &proc,
if (!d->m_aborted) {
// Success/Fail message in appropriate window?
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
if (d->m_flags & ShowSuccessMessage)
emit appendMessage(proc.exitMessage());
} else if (!(d->m_flags & SuppressFailMessage)) {
@@ -358,11 +352,11 @@ void ShellCommand::runFullySynchronous(QtcProcess &process, const FilePath &work
process.runBlocking();
if (!d->m_aborted) {
- const QString stdErr = process.stdErr();
+ const QString stdErr = process.cleanedStdErr();
if (!stdErr.isEmpty() && !(d->m_flags & SuppressStdErr))
emit append(stdErr);
- const QString stdOut = process.stdOut();
+ const QString stdOut = process.cleanedStdOut();
if (!stdOut.isEmpty() && d->m_flags & ShowStdOut) {
if (d->m_flags & SilentOutput)
emit appendSilently(stdOut);
@@ -374,7 +368,10 @@ void ShellCommand::runFullySynchronous(QtcProcess &process, const FilePath &work
void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDirectory)
{
- connect(this, &ShellCommand::terminate, &process, &QtcProcess::stopProcess);
+ connect(this, &ShellCommand::terminate, &process, [&process] {
+ process.stop();
+ process.waitForFinished();
+ });
process.setEnvironment(processEnvironment());
if (d->m_codec)
process.setCodec(d->m_codec);
@@ -416,7 +413,7 @@ void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDi
if (d->m_codec)
process.setCodec(d->m_codec);
- process.runBlocking(QtcProcess::WithEventLoop);
+ process.runBlocking(EventLoopMode::On);
}
const QVariant &ShellCommand::cookie() const
diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h
index dcdd0795f1a..f4ab789079b 100644
--- a/src/libs/utils/shellcommand.h
+++ b/src/libs/utils/shellcommand.h
@@ -27,7 +27,10 @@
#include "utils_global.h"
-#include "qtcprocess.h"
+#include "filepath.h"
+#include "processenums.h"
+
+#include <QObject>
QT_BEGIN_NAMESPACE
class QMutex;
@@ -36,10 +39,15 @@ template <typename T>
class QFutureInterface;
template <typename T>
class QFuture;
+class QTextCodec;
QT_END_NAMESPACE
namespace Utils {
+class CommandLine;
+class Environment;
+class QtcProcess;
+
namespace Internal { class ShellCommandPrivate; }
class QTCREATOR_UTILS_EXPORT ProgressParser
@@ -141,6 +149,7 @@ signals:
void append(const QString &text);
void appendSilently(const QString &text);
void appendError(const QString &text);
+ // TODO: remove Utils:: scope when support for Qt5 is dropped (Creator 9.0)
void appendCommand(const Utils::FilePath &workingDirectory, const Utils::CommandLine &command);
void appendMessage(const QString &text);
diff --git a/src/libs/utils/singleton.cpp b/src/libs/utils/singleton.cpp
index 6bd79ca36f6..6e56695283c 100644
--- a/src/libs/utils/singleton.cpp
+++ b/src/libs/utils/singleton.cpp
@@ -63,8 +63,8 @@ SingletonStaticData &Singleton::staticData(std::type_index index)
// Note: it's caller responsibility to ensure that this function is being called when all other
// threads don't use any singleton. As a good practice: finish all other threads that were using
// singletons before this function is called.
-// Some singletons (currently e.g. SshConnectionManager) can work only in main thread,
-// so this method should be called from main thread only.
+// Some singletons may work only in main thread, so this method should be called from main thread
+// only.
void Singleton::deleteAll()
{
QTC_ASSERT(QThread::currentThread() == qApp->thread(), return);
diff --git a/src/libs/utils/statuslabel.h b/src/libs/utils/statuslabel.h
index 054330b0853..57a89c5212f 100644
--- a/src/libs/utils/statuslabel.h
+++ b/src/libs/utils/statuslabel.h
@@ -27,7 +27,9 @@
#include "utils_global.h"
-QT_FORWARD_DECLARE_CLASS(QTimer)
+QT_BEGIN_NAMESPACE
+class QTimer;
+QT_END_NAMESPACE
#include <QLabel>
diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp
index ba664b1b700..30f5c805aa8 100644
--- a/src/libs/utils/stringutils.cpp
+++ b/src/libs/utils/stringutils.cpp
@@ -25,10 +25,14 @@
#include "stringutils.h"
+#include "algorithm.h"
#include "hostosinfo.h"
+#include "qtcassert.h"
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
+#ifdef QT_WIDGETS_LIB
+#include <QApplication>
+#include <QClipboard>
+#endif
#include <QCoreApplication>
#include <QDir>
@@ -92,7 +96,7 @@ QTCREATOR_UTILS_EXPORT QString commonPrefix(const QStringList &strings)
QTCREATOR_UTILS_EXPORT QString commonPath(const QStringList &files)
{
- QStringList appendedSlashes = Utils::transform(files, [](const QString &file) -> QString {
+ QStringList appendedSlashes = transform(files, [](const QString &file) -> QString {
if (!file.endsWith('/'))
return QString(file + '/');
return file;
@@ -400,9 +404,6 @@ QString formatElapsedTime(qint64 elapsed)
*/
QString wildcardToRegularExpression(const QString &original)
{
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- using qsizetype = int;
-#endif
const qsizetype wclen = original.size();
QString rx;
rx.reserve(wclen + wclen / 16);
@@ -459,11 +460,7 @@ QString wildcardToRegularExpression(const QString &original)
}
}
-#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
return QRegularExpression::anchoredPattern(rx);
-#else
- return "\\A" + rx + "\\z";
-#endif
}
QTCREATOR_UTILS_EXPORT QString languageNameFromLanguageCode(const QString &languageCode)
@@ -477,4 +474,16 @@ QTCREATOR_UTILS_EXPORT QString languageNameFromLanguageCode(const QString &langu
return languageName;
}
+#ifdef QT_WIDGETS_LIB
+
+QTCREATOR_UTILS_EXPORT void setClipboardAndSelection(const QString &text)
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setText(text);
+ if (clipboard->supportsSelection())
+ clipboard->setText(text, QClipboard::Selection);
+}
+
+#endif
+
} // namespace Utils
diff --git a/src/libs/utils/stringutils.h b/src/libs/utils/stringutils.h
index 9a8cf8f964c..fd29223967b 100644
--- a/src/libs/utils/stringutils.h
+++ b/src/libs/utils/stringutils.h
@@ -27,8 +27,6 @@
#include "utils_global.h"
-#include "porting.h"
-
#include <QList>
#include <QString>
@@ -124,4 +122,12 @@ QTCREATOR_UTILS_EXPORT QString wildcardToRegularExpression(const QString &origin
QTCREATOR_UTILS_EXPORT QString languageNameFromLanguageCode(const QString &languageCode);
+
+#ifdef QT_WIDGETS_LIB
+
+// Feeds the global clipboard and, when present, the primary selection
+QTCREATOR_UTILS_EXPORT void setClipboardAndSelection(const QString &text);
+
+#endif
+
} // namespace Utils
diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp
index e89183d5981..fae47a5653b 100644
--- a/src/libs/utils/stylehelper.cpp
+++ b/src/libs/utils/stylehelper.cpp
@@ -27,17 +27,17 @@
#include "theme/theme.h"
#include "hostosinfo.h"
+#include "qtcassert.h"
-#include <utils/qtcassert.h>
-
-#include <QPixmapCache>
-#include <QPainter>
#include <QApplication>
-#include <QFileInfo>
#include <QCommonStyle>
+#include <QFileInfo>
+#include <QFontDatabase>
+#include <QPainter>
+#include <QPixmapCache>
#include <QStyleOption>
#include <QWindow>
-#include <QFontDatabase>
+
#include <qmath.h>
// Clamps float color values within (0, 255)
diff --git a/src/libs/utils/templateengine.cpp b/src/libs/utils/templateengine.cpp
index 2030e62237a..1f59c81d9e6 100644
--- a/src/libs/utils/templateengine.cpp
+++ b/src/libs/utils/templateengine.cpp
@@ -25,6 +25,7 @@
#include "templateengine.h"
+#include "macroexpander.h"
#include "qtcassert.h"
#include <QJSEngine>
diff --git a/src/libs/utils/templateengine.h b/src/libs/utils/templateengine.h
index 5073992347d..f6e92c6fa93 100644
--- a/src/libs/utils/templateengine.h
+++ b/src/libs/utils/templateengine.h
@@ -27,14 +27,15 @@
#include "utils_global.h"
-#include "macroexpander.h"
-
-#include <QString>
-
-QT_FORWARD_DECLARE_CLASS(QJSEngine);
+QT_BEGIN_NAMESPACE
+class QJSEngine;
+class QString;
+QT_END_NAMESPACE
namespace Utils {
+class MacroExpander;
+
class QTCREATOR_UTILS_EXPORT TemplateEngine {
public:
static bool preprocessText(const QString &input, QString *output, QString *errorMessage);
diff --git a/src/libs/utils/temporarydirectory.cpp b/src/libs/utils/temporarydirectory.cpp
index 9ffbf45a017..071efc9c4b8 100644
--- a/src/libs/utils/temporarydirectory.cpp
+++ b/src/libs/utils/temporarydirectory.cpp
@@ -25,12 +25,11 @@
#include "temporarydirectory.h"
-#include "fileutils.h"
-
-#include <QtCore/QCoreApplication>
-
+#include "filepath.h"
#include "qtcassert.h"
+#include <QCoreApplication>
+
namespace Utils {
static QTemporaryDir* m_masterTemporaryDir = nullptr;
diff --git a/src/libs/utils/temporaryfile.cpp b/src/libs/utils/temporaryfile.cpp
index 2ee6a3a40a7..06a4ba00200 100644
--- a/src/libs/utils/temporaryfile.cpp
+++ b/src/libs/utils/temporaryfile.cpp
@@ -36,4 +36,6 @@ TemporaryFile::TemporaryFile(const QString &pattern) :
QTC_CHECK(!QFileInfo(pattern).isAbsolute());
}
+TemporaryFile::~TemporaryFile() = default;
+
} // namespace Utils
diff --git a/src/libs/utils/temporaryfile.h b/src/libs/utils/temporaryfile.h
index 2cb38e39289..a9b02adf429 100644
--- a/src/libs/utils/temporaryfile.h
+++ b/src/libs/utils/temporaryfile.h
@@ -35,6 +35,7 @@ class QTCREATOR_UTILS_EXPORT TemporaryFile : public QTemporaryFile
{
public:
explicit TemporaryFile(const QString &pattern);
+ ~TemporaryFile();
};
} // namespace Utils
diff --git a/src/libs/utils/terminalcommand.cpp b/src/libs/utils/terminalcommand.cpp
index 41c0604868c..a1dfebd08f6 100644
--- a/src/libs/utils/terminalcommand.cpp
+++ b/src/libs/utils/terminalcommand.cpp
@@ -25,11 +25,11 @@
#include "terminalcommand.h"
-#include <utils/algorithm.h>
-#include <utils/commandline.h>
-#include <utils/environment.h>
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
+#include "algorithm.h"
+#include "commandline.h"
+#include "environment.h"
+#include "hostosinfo.h"
+#include "qtcassert.h"
#include <QCoreApplication>
#include <QFileInfo>
@@ -155,8 +155,8 @@ TerminalCommand TerminalCommand::terminalEmulator()
const QStringList splitCommand = ProcessArgs::splitArgs(value);
if (QTC_GUARD(!splitCommand.isEmpty())) {
const QString command = splitCommand.first();
- const QStringList quotedArgs = Utils::transform(splitCommand.mid(1),
- &ProcessArgs::quoteArgUnix);
+ const QStringList quotedArgs = transform(splitCommand.mid(1),
+ &ProcessArgs::quoteArgUnix);
const QString options = quotedArgs.join(' ');
return {command, "", options};
}
diff --git a/src/libs/utils/terminalprocess.cpp b/src/libs/utils/terminalprocess.cpp
index f24b6aaf952..17a15adc4a1 100644
--- a/src/libs/utils/terminalprocess.cpp
+++ b/src/libs/utils/terminalprocess.cpp
@@ -25,17 +25,15 @@
#include "terminalprocess_p.h"
-#include <utils/environment.h>
-#include <utils/hostosinfo.h>
-#include <utils/commandline.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-#include <utils/terminalcommand.h>
-#include <utils/winutils.h>
-
-#include <QAbstractEventDispatcher>
+#include "commandline.h"
+#include "environment.h"
+#include "hostosinfo.h"
+#include "qtcassert.h"
+#include "qtcprocess.h"
+#include "terminalcommand.h"
+#include "winutils.h"
+
#include <QCoreApplication>
-#include <QDir>
#include <QLocalServer>
#include <QLocalSocket>
#include <QRegularExpression>
@@ -63,16 +61,16 @@
namespace Utils {
namespace Internal {
-static QString modeOption(QtcProcess::TerminalMode m)
+static QString modeOption(TerminalMode m)
{
switch (m) {
- case QtcProcess::TerminalRun:
+ case TerminalMode::Run:
return QLatin1String("run");
- case QtcProcess::TerminalDebug:
+ case TerminalMode::Debug:
return QLatin1String("debug");
- case QtcProcess::TerminalSuspend:
+ case TerminalMode::Suspend:
return QLatin1String("suspend");
- case QtcProcess::TerminalOff:
+ case TerminalMode::Off:
QTC_CHECK(false);
break;
}
@@ -81,67 +79,58 @@ static QString modeOption(QtcProcess::TerminalMode m)
static QString msgCommChannelFailed(const QString &error)
{
- return TerminalProcess::tr("Cannot set up communication channel: %1").arg(error);
+ return QtcProcess::tr("Cannot set up communication channel: %1").arg(error);
}
static QString msgPromptToClose()
{
// Shown in a terminal which might have a different character set on Windows.
- return TerminalProcess::tr("Press <RETURN> to close this window...");
+ return QtcProcess::tr("Press <RETURN> to close this window...");
}
static QString msgCannotCreateTempFile(const QString &why)
{
- return TerminalProcess::tr("Cannot create temporary file: %1").arg(why);
+ return QtcProcess::tr("Cannot create temporary file: %1").arg(why);
}
static QString msgCannotWriteTempFile()
{
- return TerminalProcess::tr("Cannot write temporary file. Disk full?");
+ return QtcProcess::tr("Cannot write temporary file. Disk full?");
}
static QString msgCannotCreateTempDir(const QString & dir, const QString &why)
{
- return TerminalProcess::tr("Cannot create temporary directory \"%1\": %2").arg(dir, why);
+ return QtcProcess::tr("Cannot create temporary directory \"%1\": %2").arg(dir, why);
}
static QString msgUnexpectedOutput(const QByteArray &what)
{
- return TerminalProcess::tr("Unexpected output from helper program (%1).").arg(QString::fromLatin1(what));
+ return QtcProcess::tr("Unexpected output from helper program (%1).")
+ .arg(QString::fromLatin1(what));
}
static QString msgCannotChangeToWorkDir(const FilePath &dir, const QString &why)
{
- return TerminalProcess::tr("Cannot change to working directory \"%1\": %2").arg(dir.toString(), why);
+ return QtcProcess::tr("Cannot change to working directory \"%1\": %2").arg(dir.toString(), why);
}
static QString msgCannotExecute(const QString & p, const QString &why)
{
- return TerminalProcess::tr("Cannot execute \"%1\": %2").arg(p, why);
+ return QtcProcess::tr("Cannot execute \"%1\": %2").arg(p, why);
}
class TerminalProcessPrivate
{
public:
- TerminalProcessPrivate(QObject *parent, QtcProcess::ProcessImpl processImpl,
- QtcProcess::TerminalMode terminalMode)
- : m_terminalMode(terminalMode)
- , m_process(processImpl, parent)
- {}
-
- const QtcProcess::TerminalMode m_terminalMode;
- FilePath m_workingDir;
- Environment m_environment;
+ TerminalProcessPrivate(QObject *parent)
+ : m_stubServer(parent)
+ , m_process(parent) {}
+
qint64 m_processId = 0;
- int m_exitCode = 0;
- CommandLine m_commandLine;
- QProcess::ExitStatus m_appStatus = QProcess::NormalExit;
+ ProcessResultData m_result;
QLocalServer m_stubServer;
QLocalSocket *m_stubSocket = nullptr;
QTemporaryFile *m_tempFile = nullptr;
- QProcess::ProcessError m_error = QProcess::UnknownError;
- QString m_errorString;
- bool m_abortOnMetaChars = true;
// Used on Unix only
QtcProcess m_process;
@@ -159,63 +148,39 @@ public:
#endif
};
-TerminalProcess::TerminalProcess(QObject *parent, QtcProcess::ProcessImpl processImpl,
- QtcProcess::TerminalMode terminalMode) :
- QObject(parent), d(new TerminalProcessPrivate(this, processImpl, terminalMode))
+TerminalImpl::TerminalImpl()
+ : d(new TerminalProcessPrivate(this))
{
connect(&d->m_stubServer, &QLocalServer::newConnection,
- this, &TerminalProcess::stubConnectionAvailable);
+ this, &TerminalImpl::stubConnectionAvailable);
d->m_process.setProcessChannelMode(QProcess::ForwardedChannels);
}
-TerminalProcess::~TerminalProcess()
+TerminalImpl::~TerminalImpl()
{
stopProcess();
delete d;
}
-void TerminalProcess::setCommand(const CommandLine &command)
-{
- d->m_commandLine = command;
-}
-
-const CommandLine &TerminalProcess::commandLine() const
-{
- return d->m_commandLine;
-}
-
-void TerminalProcess::setAbortOnMetaChars(bool abort)
-{
- d->m_abortOnMetaChars = abort;
-}
-
-qint64 TerminalProcess::applicationMainThreadID() const
-{
- if (HostOsInfo::isWindowsHost())
- return d->m_appMainThreadId;
- return -1;
-}
-
-void TerminalProcess::start()
+void TerminalImpl::start()
{
if (isRunning())
return;
- d->m_errorString.clear();
- d->m_error = QProcess::UnknownError;
+ d->m_result = {};
#ifdef Q_OS_WIN
QString pcmd;
QString pargs;
- if (d->m_terminalMode != QtcProcess::TerminalRun) { // The debugger engines already pre-process the arguments.
- pcmd = d->m_commandLine.executable().toString();
- pargs = d->m_commandLine.arguments();
+ if (m_setup.m_terminalMode != TerminalMode::Run) { // The debugger engines already pre-process the arguments.
+ pcmd = m_setup.m_commandLine.executable().toString();
+ pargs = m_setup.m_commandLine.arguments();
} else {
ProcessArgs outArgs;
- ProcessArgs::prepareCommand(d->m_commandLine, &pcmd, &outArgs,
- &d->m_environment, &d->m_workingDir);
+ ProcessArgs::prepareCommand(m_setup.m_commandLine, &pcmd, &outArgs,
+ &m_setup.m_environment, &m_setup.m_workingDirectory);
pargs = outArgs.toWindowsArgs();
}
@@ -225,7 +190,7 @@ void TerminalProcess::start()
return;
}
- QStringList env = d->m_environment.toStringList();
+ QStringList env = m_setup.m_environment.toStringList();
if (!env.isEmpty()) {
d->m_tempFile = new QTemporaryFile();
if (!d->m_tempFile->open()) {
@@ -272,7 +237,7 @@ void TerminalProcess::start()
d->m_pid = new PROCESS_INFORMATION;
ZeroMemory(d->m_pid, sizeof(PROCESS_INFORMATION));
- QString workDir = workingDirectory().toUserOutput();
+ QString workDir = m_setup.m_workingDirectory.toUserOutput();
if (!workDir.isEmpty() && !workDir.endsWith(QLatin1Char('\\')))
workDir.append(QLatin1Char('\\'));
@@ -328,7 +293,7 @@ void TerminalProcess::start()
};
QStringList stubArgs;
- stubArgs << modeOption(d->m_terminalMode)
+ stubArgs << modeOption(m_setup.m_terminalMode)
<< d->m_stubServer.fullServerName()
<< workDir
<< (d->m_tempFile ? d->m_tempFile->fileName() : QString())
@@ -346,44 +311,45 @@ void TerminalProcess::start()
if (!success) {
delete d->m_pid;
d->m_pid = nullptr;
- const QString msg = tr("The process \"%1\" could not be started: %2")
- .arg(cmdLine, winErrorMessage(GetLastError()));
+ const QString msg = QtcProcess::tr("The process \"%1\" could not be started: %2")
+ .arg(cmdLine, winErrorMessage(GetLastError()));
cleanupAfterStartFailure(msg);
return;
}
d->processFinishedNotifier = new QWinEventNotifier(d->m_pid->hProcess, this);
connect(d->processFinishedNotifier, &QWinEventNotifier::activated,
- this, &TerminalProcess::stubExited);
+ this, &TerminalImpl::stubExited);
#else
ProcessArgs::SplitError perr;
- ProcessArgs pargs = ProcessArgs::prepareArgs(d->m_commandLine.arguments(),
+ ProcessArgs pargs = ProcessArgs::prepareArgs(m_setup.m_commandLine.arguments(),
&perr,
HostOsInfo::hostOs(),
- &d->m_environment,
- &d->m_workingDir,
- d->m_abortOnMetaChars);
+ &m_setup.m_environment,
+ &m_setup.m_workingDirectory,
+ m_setup.m_abortOnMetaChars);
QString pcmd;
if (perr == ProcessArgs::SplitOk) {
- pcmd = d->m_commandLine.executable().toString();
+ pcmd = m_setup.m_commandLine.executable().toString();
} else {
if (perr != ProcessArgs::FoundMeta) {
- emitError(QProcess::FailedToStart, tr("Quoting error in command."));
+ emitError(QProcess::FailedToStart, QtcProcess::tr("Quoting error in command."));
return;
}
- if (d->m_terminalMode == QtcProcess::TerminalDebug) {
+ if (m_setup.m_terminalMode == TerminalMode::Debug) {
// FIXME: QTCREATORBUG-2809
- emitError(QProcess::FailedToStart, tr("Debugging complex shell commands in a terminal"
- " is currently not supported."));
+ emitError(QProcess::FailedToStart,
+ QtcProcess::tr("Debugging complex shell commands in a terminal"
+ " is currently not supported."));
return;
}
pcmd = qEnvironmentVariable("SHELL", "/bin/sh");
pargs = ProcessArgs::createUnixArgs(
- {"-c", (ProcessArgs::quoteArg(d->m_commandLine.executable().toString())
- + ' ' + d->m_commandLine.arguments())});
+ {"-c", (ProcessArgs::quoteArg(m_setup.m_commandLine.executable().toString())
+ + ' ' + m_setup.m_commandLine.arguments())});
}
ProcessArgs::SplitError qerr;
@@ -391,12 +357,13 @@ void TerminalProcess::start()
const ProcessArgs terminalArgs = ProcessArgs::prepareArgs(terminal.executeArgs,
&qerr,
HostOsInfo::hostOs(),
- &d->m_environment,
- &d->m_workingDir);
+ &m_setup.m_environment,
+ &m_setup.m_workingDirectory);
if (qerr != ProcessArgs::SplitOk) {
- emitError(QProcess::FailedToStart, qerr == ProcessArgs::BadQuoting
- ? tr("Quoting error in terminal command.")
- : tr("Terminal command may not be a shell command."));
+ emitError(QProcess::FailedToStart,
+ qerr == ProcessArgs::BadQuoting
+ ? QtcProcess::tr("Quoting error in terminal command.")
+ : QtcProcess::tr("Terminal command may not be a shell command."));
return;
}
@@ -406,11 +373,11 @@ void TerminalProcess::start()
return;
}
- d->m_environment.unset(QLatin1String("TERM"));
+ m_setup.m_environment.unset(QLatin1String("TERM"));
- const QStringList env = d->m_environment.toStringList();
+ const QStringList env = m_setup.m_environment.toStringList();
if (!env.isEmpty()) {
- d->m_tempFile = new QTemporaryFile();
+ d->m_tempFile = new QTemporaryFile(this);
if (!d->m_tempFile->open()) {
cleanupAfterStartFailure(msgCannotCreateTempFile(d->m_tempFile->errorString()));
return;
@@ -432,10 +399,10 @@ void TerminalProcess::start()
QStringList allArgs = terminalArgs.toUnixArgs();
allArgs << stubPath
- << modeOption(d->m_terminalMode)
+ << modeOption(m_setup.m_terminalMode)
<< d->m_stubServer.fullServerName()
<< msgPromptToClose()
- << workingDirectory().path()
+ << m_setup.m_workingDirectory.path()
<< (d->m_tempFile ? d->m_tempFile->fileName() : QString())
<< QString::number(getpid())
<< pcmd
@@ -444,24 +411,28 @@ void TerminalProcess::start()
if (terminal.needsQuotes)
allArgs = QStringList { ProcessArgs::joinArgs(allArgs) };
- d->m_process.setEnvironment(d->m_environment);
+ d->m_process.setEnvironment(m_setup.m_environment);
d->m_process.setCommand({FilePath::fromString(terminal.command), allArgs});
+ d->m_process.setProcessImpl(m_setup.m_processImpl);
+ d->m_process.setReaperTimeout(m_setup.m_reaperTimeout);
d->m_process.start();
if (!d->m_process.waitForStarted()) {
- const QString msg = tr("Cannot start the terminal emulator \"%1\", change the setting in the "
- "Environment options.").arg(terminal.command);
+ const QString msg
+ = QtcProcess::tr("Cannot start the terminal emulator \"%1\", change the setting in the "
+ "Environment options.")
+ .arg(terminal.command);
cleanupAfterStartFailure(msg);
return;
}
d->m_stubConnectTimer = new QTimer(this);
- connect(d->m_stubConnectTimer, &QTimer::timeout, this, &TerminalProcess::stopProcess);
+ connect(d->m_stubConnectTimer, &QTimer::timeout, this, &TerminalImpl::stopProcess);
d->m_stubConnectTimer->setSingleShot(true);
d->m_stubConnectTimer->start(10000);
#endif
}
-void TerminalProcess::cleanupAfterStartFailure(const QString &errorMessage)
+void TerminalImpl::cleanupAfterStartFailure(const QString &errorMessage)
{
stubServerShutdown();
emitError(QProcess::FailedToStart, errorMessage);
@@ -469,39 +440,35 @@ void TerminalProcess::cleanupAfterStartFailure(const QString &errorMessage)
d->m_tempFile = nullptr;
}
-void TerminalProcess::finish(int exitCode, QProcess::ExitStatus exitStatus)
-{
- d->m_processId = 0;
- d->m_exitCode = exitCode;
- d->m_appStatus = exitStatus;
- emit finished(exitCode, exitStatus);
-}
-
-void TerminalProcess::kickoffProcess()
+void TerminalImpl::sendControlSignal(ControlSignal controlSignal)
{
-#ifdef Q_OS_WIN
- // Not used.
-#else
- if (d->m_stubSocket && d->m_stubSocket->isWritable()) {
- d->m_stubSocket->write("c", 1);
- d->m_stubSocket->flush();
+ switch (controlSignal) {
+ case ControlSignal::Terminate:
+ case ControlSignal::Kill:
+ stopProcess();
+ break;
+ case ControlSignal::Interrupt:
+ sendCommand('i');
+ break;
+ case ControlSignal::KickOff:
+ sendCommand('c');
+ break;
}
-#endif
}
-void TerminalProcess::interruptProcess()
+void TerminalImpl::sendCommand(char c)
{
#ifdef Q_OS_WIN
- // Not used.
+ Q_UNUSED(c)
#else
if (d->m_stubSocket && d->m_stubSocket->isWritable()) {
- d->m_stubSocket->write("i", 1);
+ d->m_stubSocket->write(&c, 1);
d->m_stubSocket->flush();
}
#endif
}
-void TerminalProcess::killProcess()
+void TerminalImpl::killProcess()
{
#ifdef Q_OS_WIN
if (d->m_hInferior != NULL) {
@@ -509,45 +476,36 @@ void TerminalProcess::killProcess()
cleanupInferior();
}
#else
- if (d->m_stubSocket && d->m_stubSocket->isWritable()) {
- d->m_stubSocket->write("k", 1);
- d->m_stubSocket->flush();
- }
+ sendCommand('k');
#endif
d->m_processId = 0;
}
-void TerminalProcess::killStub()
+void TerminalImpl::killStub()
{
+ if (!isRunning())
+ return;
+
#ifdef Q_OS_WIN
- if (d->m_pid) {
- TerminateProcess(d->m_pid->hProcess, (unsigned)-1);
- WaitForSingleObject(d->m_pid->hProcess, INFINITE);
- cleanupStub();
- }
+ TerminateProcess(d->m_pid->hProcess, (unsigned)-1);
+ WaitForSingleObject(d->m_pid->hProcess, INFINITE);
+ cleanupStub();
#else
- if (d->m_stubSocket && d->m_stubSocket->isWritable()) {
- d->m_stubSocket->write("s", 1);
- d->m_stubSocket->flush();
- }
+ sendCommand('s');
stubServerShutdown();
+ d->m_process.waitForFinished();
#endif
+
+ emitFinished(-1, QProcess::CrashExit);
}
-void TerminalProcess::stopProcess()
+void TerminalImpl::stopProcess()
{
killProcess();
killStub();
- if (isRunning() && HostOsInfo::isAnyUnixHost()) {
- d->m_process.terminate();
- if (!d->m_process.waitForFinished(1000) && d->m_process.state() == QProcess::Running) {
- d->m_process.kill();
- d->m_process.waitForFinished();
- }
- }
}
-bool TerminalProcess::isRunning() const
+bool TerminalImpl::isRunning() const
{
#ifdef Q_OS_WIN
return d->m_pid != nullptr;
@@ -557,17 +515,7 @@ bool TerminalProcess::isRunning() const
#endif
}
-QProcess::ProcessState TerminalProcess::state() const
-{
-#ifdef Q_OS_WIN
- return (d->m_pid != nullptr) ? QProcess::Running : QProcess::NotRunning;
-#else
- return (d->m_stubSocket && d->m_stubSocket->isOpen())
- ? QProcess::Running : d->m_process.state();
-#endif
-}
-
-QString TerminalProcess::stubServerListen()
+QString TerminalImpl::stubServerListen()
{
#ifdef Q_OS_WIN
if (d->m_stubServer.listen(QString::fromLatin1("creator-%1-%2")
@@ -596,13 +544,14 @@ QString TerminalProcess::stubServerListen()
const QString stubServer = stubFifoDir + QLatin1String("/stub-socket");
if (!d->m_stubServer.listen(stubServer)) {
::rmdir(d->m_stubServerDir.constData());
- return tr("Cannot create socket \"%1\": %2").arg(stubServer, d->m_stubServer.errorString());
+ return QtcProcess::tr("Cannot create socket \"%1\": %2")
+ .arg(stubServer, d->m_stubServer.errorString());
}
return QString();
#endif
}
-void TerminalProcess::stubServerShutdown()
+void TerminalImpl::stubServerShutdown()
{
#ifdef Q_OS_WIN
delete d->m_stubSocket;
@@ -623,7 +572,7 @@ void TerminalProcess::stubServerShutdown()
#endif
}
-void TerminalProcess::stubConnectionAvailable()
+void TerminalImpl::stubConnectionAvailable()
{
if (d->m_stubConnectTimer) {
delete d->m_stubConnectTimer;
@@ -631,10 +580,10 @@ void TerminalProcess::stubConnectionAvailable()
}
d->m_stubSocket = d->m_stubServer.nextPendingConnection();
- connect(d->m_stubSocket, &QIODevice::readyRead, this, &TerminalProcess::readStubOutput);
+ connect(d->m_stubSocket, &QIODevice::readyRead, this, &TerminalImpl::readStubOutput);
if (HostOsInfo::isAnyUnixHost())
- connect(d->m_stubSocket, &QLocalSocket::disconnected, this, &TerminalProcess::stubExited);
+ connect(d->m_stubSocket, &QLocalSocket::disconnected, this, &TerminalImpl::stubExited);
}
static QString errorMsg(int code)
@@ -642,17 +591,20 @@ static QString errorMsg(int code)
return QString::fromLocal8Bit(strerror(code));
}
-void TerminalProcess::readStubOutput()
+void TerminalImpl::readStubOutput()
{
while (d->m_stubSocket->canReadLine()) {
QByteArray out = d->m_stubSocket->readLine();
#ifdef Q_OS_WIN
out.chop(2); // \r\n
if (out.startsWith("err:chdir ")) {
- emitError(QProcess::FailedToStart, msgCannotChangeToWorkDir(workingDirectory(), winErrorMessage(out.mid(10).toInt())));
+ emitError(QProcess::FailedToStart,
+ msgCannotChangeToWorkDir(m_setup.m_workingDirectory, winErrorMessage(out.mid(10).toInt())));
} else if (out.startsWith("err:exec ")) {
- emitError(QProcess::FailedToStart, msgCannotExecute(d->m_commandLine.executable().toUserOutput(), winErrorMessage(out.mid(9).toInt())));
+ emitError(QProcess::FailedToStart,
+ msgCannotExecute(m_setup.m_commandLine.executable().toUserOutput(), winErrorMessage(out.mid(9).toInt())));
} else if (out.startsWith("thread ")) { // Windows only
+ // TODO: ensure that it comes before "pid " comes
d->m_appMainThreadId = out.mid(7).toLongLong();
} else if (out.startsWith("pid ")) {
// Will not need it any more
@@ -664,8 +616,9 @@ void TerminalProcess::readStubOutput()
SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE,
FALSE, d->m_processId);
if (d->m_hInferior == NULL) {
- emitError(QProcess::FailedToStart, tr("Cannot obtain a handle to the inferior: %1")
- .arg(winErrorMessage(GetLastError())));
+ emitError(QProcess::FailedToStart,
+ QtcProcess::tr("Cannot obtain a handle to the inferior: %1")
+ .arg(winErrorMessage(GetLastError())));
// Uhm, and now what?
continue;
}
@@ -674,13 +627,14 @@ void TerminalProcess::readStubOutput()
DWORD chldStatus;
if (!GetExitCodeProcess(d->m_hInferior, &chldStatus))
- emitError(QProcess::UnknownError, tr("Cannot obtain exit status from inferior: %1")
- .arg(winErrorMessage(GetLastError())));
+ emitError(QProcess::UnknownError,
+ QtcProcess::tr("Cannot obtain exit status from inferior: %1")
+ .arg(winErrorMessage(GetLastError())));
cleanupInferior();
- finish(chldStatus, QProcess::NormalExit);
+ emitFinished(chldStatus, QProcess::NormalExit);
});
- emit started();
+ emit started(d->m_processId, d->m_appMainThreadId);
} else {
emitError(QProcess::UnknownError, msgUnexpectedOutput(out));
TerminateProcess(d->m_pid->hProcess, (unsigned)-1);
@@ -689,19 +643,21 @@ void TerminalProcess::readStubOutput()
#else
out.chop(1); // \n
if (out.startsWith("err:chdir ")) {
- emitError(QProcess::FailedToStart, msgCannotChangeToWorkDir(workingDirectory(), errorMsg(out.mid(10).toInt())));
+ emitError(QProcess::FailedToStart,
+ msgCannotChangeToWorkDir(m_setup.m_workingDirectory, errorMsg(out.mid(10).toInt())));
} else if (out.startsWith("err:exec ")) {
- emitError(QProcess::FailedToStart, msgCannotExecute(d->m_commandLine.executable().toString(), errorMsg(out.mid(9).toInt())));
+ emitError(QProcess::FailedToStart,
+ msgCannotExecute(m_setup.m_commandLine.executable().toString(), errorMsg(out.mid(9).toInt())));
} else if (out.startsWith("spid ")) {
delete d->m_tempFile;
d->m_tempFile = nullptr;
} else if (out.startsWith("pid ")) {
d->m_processId = out.mid(4).toInt();
- emit started();
+ emit started(d->m_processId);
} else if (out.startsWith("exit ")) {
- finish(out.mid(5).toInt(), QProcess::NormalExit);
+ emitFinished(out.mid(5).toInt(), QProcess::NormalExit);
} else if (out.startsWith("crash ")) {
- finish(out.mid(6).toInt(), QProcess::CrashExit);
+ emitFinished(out.mid(6).toInt(), QProcess::CrashExit);
} else {
emitError(QProcess::UnknownError, msgUnexpectedOutput(out));
d->m_process.terminate();
@@ -711,7 +667,7 @@ void TerminalProcess::readStubOutput()
} // while
}
-void TerminalProcess::stubExited()
+void TerminalImpl::stubExited()
{
// The stub exit might get noticed before we read the pid for the kill on Windows
// or the error status elsewhere.
@@ -723,18 +679,18 @@ void TerminalProcess::stubExited()
if (d->m_hInferior != NULL) {
TerminateProcess(d->m_hInferior, (unsigned)-1);
cleanupInferior();
- finish(-1, QProcess::CrashExit);
+ emitFinished(-1, QProcess::CrashExit);
}
#else
stubServerShutdown();
delete d->m_tempFile;
d->m_tempFile = nullptr;
if (d->m_processId)
- finish(-1, QProcess::CrashExit);
+ emitFinished(-1, QProcess::CrashExit);
#endif
}
-void TerminalProcess::cleanupInferior()
+void TerminalImpl::cleanupInferior()
{
#ifdef Q_OS_WIN
delete d->inferiorFinishedNotifier;
@@ -744,7 +700,7 @@ void TerminalProcess::cleanupInferior()
#endif
}
-void TerminalProcess::cleanupStub()
+void TerminalImpl::cleanupStub()
{
#ifdef Q_OS_WIN
stubServerShutdown();
@@ -759,57 +715,22 @@ void TerminalProcess::cleanupStub()
#endif
}
-qint64 TerminalProcess::processId() const
+void TerminalImpl::emitError(QProcess::ProcessError error, const QString &errorString)
{
- return d->m_processId;
+ d->m_result.m_error = error;
+ d->m_result.m_errorString = errorString;
+ if (error == QProcess::FailedToStart)
+ emit done(d->m_result);
}
-int TerminalProcess::exitCode() const
-{
- return d->m_exitCode;
-} // This will be the signal number if exitStatus == CrashExit
-
-QProcess::ExitStatus TerminalProcess::exitStatus() const
+void TerminalImpl::emitFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
- return d->m_appStatus;
-}
-
-void TerminalProcess::setWorkingDirectory(const FilePath &dir)
-{
- d->m_workingDir = dir;
-}
-
-FilePath TerminalProcess::workingDirectory() const
-{
- return d->m_workingDir;
-}
-
-void TerminalProcess::setEnvironment(const Environment &env)
-{
- d->m_environment = env;
-}
-
-const Environment &TerminalProcess::environment() const
-{
- return d->m_environment;
-}
-
-QProcess::ProcessError TerminalProcess::error() const
-{
- return d->m_error;
-}
-
-QString TerminalProcess::errorString() const
-{
- return d->m_errorString;
+ d->m_processId = 0;
+ d->m_result.m_exitCode = exitCode;
+ d->m_result.m_exitStatus = exitStatus;
+ emit done(d->m_result);
}
-void TerminalProcess::emitError(QProcess::ProcessError err, const QString &errorString)
-{
- d->m_error = err;
- d->m_errorString = errorString;
- emit errorOccurred(err);
-}
} // Internal
} // Utils
diff --git a/src/libs/utils/terminalprocess_p.h b/src/libs/utils/terminalprocess_p.h
index 0fb2006049e..32be83f0206 100644
--- a/src/libs/utils/terminalprocess_p.h
+++ b/src/libs/utils/terminalprocess_p.h
@@ -25,7 +25,11 @@
#pragma once
-#include "qtcprocess.h"
+#include "processenums.h"
+#include "processinterface.h"
+#include "qtcassert.h"
+
+#include <QProcess>
namespace Utils {
@@ -35,61 +39,35 @@ class FilePath;
namespace Internal {
-class TerminalProcess : public QObject
+class TerminalImpl final : public ProcessInterface
{
- Q_OBJECT
public:
- explicit TerminalProcess(QObject *parent, QtcProcess::ProcessImpl processImpl,
- QtcProcess::TerminalMode terminalMode);
- ~TerminalProcess() override;
-
- void setCommand(const CommandLine &command);
- const CommandLine &commandLine() const;
-
- void setWorkingDirectory(const FilePath &dir);
- FilePath workingDirectory() const;
+ TerminalImpl();
+ ~TerminalImpl() final;
- void setEnvironment(const Environment &env);
- const Environment &environment() const;
-
- QProcess::ProcessError error() const;
- QString errorString() const;
-
- void start();
- void stopProcess();
+private:
+ void start() final;
+ qint64 write(const QByteArray &) final { QTC_CHECK(false); return -1; }
+ void sendControlSignal(ControlSignal controlSignal) final;
// OK, however, impl looks a bit different (!= NotRunning vs == Running).
// Most probably changing it into (== Running) should be OK.
bool isRunning() const;
- QProcess::ProcessState state() const;
- qint64 processId() const;
- int exitCode() const;
- QProcess::ExitStatus exitStatus() const;
-
- void setAbortOnMetaChars(bool abort); // used only in sshDeviceProcess
- void kickoffProcess(); // only debugger terminal, only non-windows
- void interruptProcess(); // only debugger terminal, only non-windows
- qint64 applicationMainThreadID() const; // only debugger terminal, only windows (-1 otherwise)
-
-signals:
- void started();
- void finished(int exitCode, QProcess::ExitStatus status);
- void errorOccurred(QProcess::ProcessError error);
-
-private:
+ void stopProcess();
void stubConnectionAvailable();
void readStubOutput();
void stubExited();
void cleanupAfterStartFailure(const QString &errorMessage);
- void finish(int exitCode, QProcess::ExitStatus exitStatus);
void killProcess();
void killStub();
- void emitError(QProcess::ProcessError err, const QString &errorString);
+ void emitError(QProcess::ProcessError error, const QString &errorString);
+ void emitFinished(int exitCode, QProcess::ExitStatus exitStatus);
QString stubServerListen();
void stubServerShutdown();
void cleanupStub();
void cleanupInferior();
+ void sendCommand(char c);
class TerminalProcessPrivate *d;
};
diff --git a/src/libs/utils/textfieldcheckbox.h b/src/libs/utils/textfieldcheckbox.h
index 3fea4f1ec32..99292ea8db4 100644
--- a/src/libs/utils/textfieldcheckbox.h
+++ b/src/libs/utils/textfieldcheckbox.h
@@ -32,11 +32,13 @@
namespace Utils {
// Documentation inside.
-class QTCREATOR_UTILS_EXPORT TextFieldCheckBox : public QCheckBox {
+class QTCREATOR_UTILS_EXPORT TextFieldCheckBox : public QCheckBox
+{
Q_PROPERTY(QString compareText READ text WRITE setText)
Q_PROPERTY(QString trueText READ trueText WRITE setTrueText)
Q_PROPERTY(QString falseText READ falseText WRITE setFalseText)
Q_OBJECT
+
public:
explicit TextFieldCheckBox(const QString &text, QWidget *parent = nullptr);
diff --git a/src/libs/utils/textfieldcombobox.h b/src/libs/utils/textfieldcombobox.h
index a10906bcbc9..119ccfa6d3b 100644
--- a/src/libs/utils/textfieldcombobox.h
+++ b/src/libs/utils/textfieldcombobox.h
@@ -32,9 +32,11 @@
namespace Utils {
// Documentation inside.
-class QTCREATOR_UTILS_EXPORT TextFieldComboBox : public QComboBox {
+class QTCREATOR_UTILS_EXPORT TextFieldComboBox : public QComboBox
+{
Q_PROPERTY(QString indexText READ text WRITE setText)
Q_OBJECT
+
public:
explicit TextFieldComboBox(QWidget *parent = nullptr);
diff --git a/src/libs/utils/textfileformat.cpp b/src/libs/utils/textfileformat.cpp
index c06bf5dc383..95c74d7cfe5 100644
--- a/src/libs/utils/textfileformat.cpp
+++ b/src/libs/utils/textfileformat.cpp
@@ -24,12 +24,12 @@
****************************************************************************/
#include "textfileformat.h"
+
#include "fileutils.h"
#include "qtcassert.h"
-#include <QTextCodec>
-#include <QStringList>
#include <QDebug>
+#include <QTextCodec>
enum { debug = 0 };
diff --git a/src/libs/utils/textutils.cpp b/src/libs/utils/textutils.cpp
index 4e0764fffb7..6075b71fa33 100644
--- a/src/libs/utils/textutils.cpp
+++ b/src/libs/utils/textutils.cpp
@@ -165,7 +165,7 @@ int utf8NthLineOffset(const QTextDocument *textDocument, const QByteArray &buffe
LineColumn utf16LineColumn(const QByteArray &utf8Buffer, int utf8Offset)
{
- Utils::LineColumn lineColumn;
+ LineColumn lineColumn;
lineColumn.line = static_cast<int>(
std::count(utf8Buffer.begin(), utf8Buffer.begin() + utf8Offset, '\n'))
+ 1;
@@ -221,7 +221,7 @@ void applyReplacements(QTextDocument *doc, const Replacements &replacements)
int fullOffsetShift = 0;
QTextCursor editCursor(doc);
editCursor.beginEditBlock();
- for (const Utils::Text::Replacement &replacement : replacements) {
+ for (const Text::Replacement &replacement : replacements) {
editCursor.setPosition(replacement.offset + fullOffsetShift);
editCursor.movePosition(QTextCursor::NextCharacter,
QTextCursor::KeepAnchor,
diff --git a/src/libs/utils/textutils.h b/src/libs/utils/textutils.h
index 272e4911b37..7f68fb47aae 100644
--- a/src/libs/utils/textutils.h
+++ b/src/libs/utils/textutils.h
@@ -25,13 +25,16 @@
#pragma once
-#include "linecolumn.h"
#include "utils_global.h"
+#include "linecolumn.h"
+
#include <QString>
-QT_FORWARD_DECLARE_CLASS(QTextDocument)
-QT_FORWARD_DECLARE_CLASS(QTextCursor)
+QT_BEGIN_NAMESPACE
+class QTextCursor;
+class QTextDocument;
+QT_END_NAMESPACE
namespace Utils {
namespace Text {
diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h
index b3d54497455..cbcf3658577 100644
--- a/src/libs/utils/theme/theme.h
+++ b/src/libs/utils/theme/theme.h
@@ -30,8 +30,10 @@
#include <QBrush> // QGradientStops
#include <QObject>
-QT_FORWARD_DECLARE_CLASS(QSettings)
-QT_FORWARD_DECLARE_CLASS(QPalette)
+QT_BEGIN_NAMESPACE
+class QPalette;
+class QSettings;
+QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/theme/theme_p.h b/src/libs/utils/theme/theme_p.h
index 1feeeda4e25..3f300de136e 100644
--- a/src/libs/utils/theme/theme_p.h
+++ b/src/libs/utils/theme/theme_p.h
@@ -25,9 +25,10 @@
#pragma once
-#include "theme.h"
#include "../utils_global.h"
+#include "theme.h"
+
#include <QColor>
#include <QMap>
diff --git a/src/libs/utils/tooltip/tips.cpp b/src/libs/utils/tooltip/tips.cpp
index e8c3cae6df6..b53a586e884 100644
--- a/src/libs/utils/tooltip/tips.cpp
+++ b/src/libs/utils/tooltip/tips.cpp
@@ -26,12 +26,11 @@
#include "tips.h"
#include "tooltip.h"
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
+#include "../qtcassert.h"
-#include <QApplication>
#include <QColor>
#include <QFontMetrics>
+#include <QGuiApplication>
#include <QPaintEvent>
#include <QPainter>
#include <QPen>
@@ -43,6 +42,7 @@
#include <QStyleOptionFrame>
#include <QTextDocument>
#include <QScreen>
+#include <QVBoxLayout>
#include <QWidget>
#include <memory>
diff --git a/src/libs/utils/tooltip/tips.h b/src/libs/utils/tooltip/tips.h
index ba5f4151013..cc43cb25e82 100644
--- a/src/libs/utils/tooltip/tips.h
+++ b/src/libs/utils/tooltip/tips.h
@@ -29,9 +29,11 @@
#include <QLabel>
#include <QPixmap>
-#include <QSharedPointer>
#include <QVariant>
-#include <QVBoxLayout>
+
+QT_BEGIN_NAMESPACE
+class QVBoxLayout;
+QT_END_NAMESPACE
namespace Utils {
namespace Internal {
diff --git a/src/libs/utils/tooltip/tooltip.cpp b/src/libs/utils/tooltip/tooltip.cpp
index 60f10f5d71a..f7d22c20298 100644
--- a/src/libs/utils/tooltip/tooltip.cpp
+++ b/src/libs/utils/tooltip/tooltip.cpp
@@ -27,9 +27,9 @@
#include "tips.h"
#include "effects.h"
-#include <utils/faketooltip.h>
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
+#include "faketooltip.h"
+#include "hostosinfo.h"
+#include "qtcassert.h"
#include <QApplication>
#include <QColor>
diff --git a/src/libs/utils/tooltip/tooltip.h b/src/libs/utils/tooltip/tooltip.h
index 4c0c3de84f8..b8899a46507 100644
--- a/src/libs/utils/tooltip/tooltip.h
+++ b/src/libs/utils/tooltip/tooltip.h
@@ -27,7 +27,6 @@
#include "../utils_global.h"
-#include <QSharedPointer>
#include <QObject>
#include <QPointer>
#include <QTimer>
diff --git a/src/libs/utils/touchbar/touchbar.cpp b/src/libs/utils/touchbar/touchbar.cpp
index 191fae385f6..b1bdeb05149 100644
--- a/src/libs/utils/touchbar/touchbar.cpp
+++ b/src/libs/utils/touchbar/touchbar.cpp
@@ -25,6 +25,11 @@
#include "touchbar.h"
+#include <QAction>
+#include <QByteArray>
+#include <QIcon>
+#include <QString>
+
namespace Utils {
namespace Internal {
diff --git a/src/libs/utils/touchbar/touchbar.h b/src/libs/utils/touchbar/touchbar.h
index d00a33c4c99..55893172ba1 100644
--- a/src/libs/utils/touchbar/touchbar.h
+++ b/src/libs/utils/touchbar/touchbar.h
@@ -25,12 +25,14 @@
#pragma once
-#include <utils/utils_global.h>
+#include "../utils_global.h"
-#include <QAction>
-#include <QByteArray>
-#include <QIcon>
-#include <QString>
+QT_BEGIN_NAMESPACE
+class QAction;
+class QByteArray;
+class QIcon;
+class QString;
+QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/treemodel.cpp b/src/libs/utils/treemodel.cpp
index 22e59b488fc..cc216afab58 100644
--- a/src/libs/utils/treemodel.cpp
+++ b/src/libs/utils/treemodel.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "treemodel.h"
+
#include "qtcassert.h"
#include <QStack>
diff --git a/src/libs/utils/treemodel.h b/src/libs/utils/treemodel.h
index 7240d8d6b6b..570f39fd75e 100644
--- a/src/libs/utils/treemodel.h
+++ b/src/libs/utils/treemodel.h
@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
+
#include "indexedcontainerproxyconstiterator.h"
#include <QAbstractItemModel>
diff --git a/src/libs/utils/uncommentselection.cpp b/src/libs/utils/uncommentselection.cpp
index 612b34b3590..9b7e62be63b 100644
--- a/src/libs/utils/uncommentselection.cpp
+++ b/src/libs/utils/uncommentselection.cpp
@@ -26,10 +26,11 @@
#include "uncommentselection.h"
#include "qtcassert.h"
-#include "utils/multitextcursor.h"
+#include "multitextcursor.h"
-#include <QPlainTextEdit>
#include <QTextBlock>
+#include <QTextCursor>
+#include <QTextDocument>
namespace Utils {
diff --git a/src/libs/utils/uncommentselection.h b/src/libs/utils/uncommentselection.h
index 40895cbb9ea..ae09b63796e 100644
--- a/src/libs/utils/uncommentselection.h
+++ b/src/libs/utils/uncommentselection.h
@@ -28,10 +28,10 @@
#include "utils_global.h"
#include <QString>
-#include <QTextCursor>
QT_BEGIN_NAMESPACE
class QPlainTextEdit;
+class QTextCursor;
QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/unixutils.cpp b/src/libs/utils/unixutils.cpp
index 535bfa2a041..02d02676a68 100644
--- a/src/libs/utils/unixutils.cpp
+++ b/src/libs/utils/unixutils.cpp
@@ -25,12 +25,12 @@
#include "unixutils.h"
-#include "fileutils.h"
+#include "filepath.h"
#include "qtcsettings.h"
-#include <QSettings>
-#include <QFileInfo>
#include <QCoreApplication>
+#include <QFileInfo>
+#include <QSettings>
using namespace Utils;
diff --git a/src/libs/utils/unixutils.h b/src/libs/utils/unixutils.h
index b43cb091427..32c4c40f0ca 100644
--- a/src/libs/utils/unixutils.h
+++ b/src/libs/utils/unixutils.h
@@ -29,6 +29,7 @@
QT_BEGIN_NAMESPACE
class QSettings;
+class QString;
QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/url.cpp b/src/libs/utils/url.cpp
index e325615bb2d..00f4996cc13 100644
--- a/src/libs/utils/url.cpp
+++ b/src/libs/utils/url.cpp
@@ -24,10 +24,12 @@
****************************************************************************/
#include "url.h"
+
#include "temporaryfile.h"
#include <QHostAddress>
#include <QTcpServer>
+#include <QUrl>
namespace Utils {
diff --git a/src/libs/utils/url.h b/src/libs/utils/url.h
index 91ced4d4446..3d3400366ab 100644
--- a/src/libs/utils/url.h
+++ b/src/libs/utils/url.h
@@ -26,7 +26,11 @@
#pragma once
#include "utils_global.h"
-#include <QUrl>
+
+QT_BEGIN_NAMESPACE
+class QString;
+class QUrl;
+QT_END_NAMESPACE
namespace Utils {
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index 318e7bcbef1..71fadc6bcf3 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -5,7 +5,9 @@ Project {
name: "Utils"
QtcLibrary {
+ property bool useNewMimeDatabase: true
+ cpp.includePaths: base.concat((useNewMimeDatabase ? "mimetypes2" : "mimetypes"), ".")
cpp.defines: base.concat([
"UTILS_LIBRARY"
])
@@ -32,7 +34,7 @@ Project {
}
Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets", "xml"] }
- Depends { name: "Qt.macextras"; condition: qbs.targetOS.contains("macos") }
+ Depends { name: "Qt.macextras"; condition: Qt.core.versionMajor < 6 && qbs.targetOS.contains("macos") }
Depends { name: "app_version_header" }
files: [
@@ -73,13 +75,14 @@ Project {
"cpplanguage_details.h",
"crumblepath.cpp",
"crumblepath.h",
- "declarationmacros.h",
"delegates.cpp",
"delegates.h",
"detailsbutton.cpp",
"detailsbutton.h",
"detailswidget.cpp",
"detailswidget.h",
+ "deviceshell.cpp",
+ "deviceshell.h",
"differ.cpp",
"differ.h",
"displayname.cpp",
@@ -179,6 +182,9 @@ Project {
"macroexpander.cpp",
"macroexpander.h",
"mapreduce.h",
+ "mimeutils.h",
+ "minimizableinfobars.cpp",
+ "minimizableinfobars.h",
"multitextcursor.cpp",
"multitextcursor.h",
"namevaluedictionary.cpp",
@@ -220,8 +226,13 @@ Project {
"porting.h",
"portlist.cpp",
"portlist.h",
+ "processenums.h",
"processhandle.cpp",
"processhandle.h",
+ "processinfo.cpp",
+ "processinfo.h",
+ "processinterface.cpp",
+ "processinterface.h",
"processreaper.cpp",
"processreaper.h",
"processutils.cpp",
@@ -384,7 +395,7 @@ Project {
Group {
name: "MimeTypes"
- prefix: "mimetypes/"
+ prefix: useNewMimeDatabase ? "mimetypes2/" : "mimetypes/"
files: [
"mimedatabase.cpp",
"mimedatabase.h",
@@ -402,6 +413,7 @@ Project {
"mimetype_p.h",
"mimetypeparser.cpp",
"mimetypeparser_p.h",
+ "mimeutils.cpp"
]
}
@@ -428,6 +440,8 @@ Project {
Export {
Depends { name: "Qt"; submodules: ["concurrent", "widgets" ] }
+ cpp.includePaths: base.concat(exportingProduct.useNewMimeDatabase ? "mimetypes2"
+ : "mimetypes")
}
}
}
diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc
index fc5ec2adfae..8685c9be9f2 100644
--- a/src/libs/utils/utils.qrc
+++ b/src/libs/utils/utils.qrc
@@ -237,6 +237,7 @@
<file>images/download@2x.png</file>
<file>images/message.png</file>
<file>images/message@2x.png</file>
+ <file>images/help.png</file>
<file alias="mimetypes/freedesktop.org.xml" compression-algorithm="best">../3rdparty/xdg/freedesktop.org.xml</file>
</qresource>
<qresource prefix="/codemodel">
diff --git a/src/libs/utils/utils_global.h b/src/libs/utils/utils_global.h
index ae30640217d..4bd21326568 100644
--- a/src/libs/utils/utils_global.h
+++ b/src/libs/utils/utils_global.h
@@ -29,7 +29,7 @@
#if defined(UTILS_LIBRARY)
# define QTCREATOR_UTILS_EXPORT Q_DECL_EXPORT
-#elif defined(QTCREATOR_UTILS_STATIC_LIB) // Abuse single files for manual tests
+#elif defined(UTILS_STATIC_LIBRARY) // Abuse single files for manual tests
# define QTCREATOR_UTILS_EXPORT
#else
# define QTCREATOR_UTILS_EXPORT Q_DECL_IMPORT
diff --git a/src/libs/utils/utilsicons.cpp b/src/libs/utils/utilsicons.cpp
index 8bec380a23f..abb8c5e8e1c 100644
--- a/src/libs/utils/utilsicons.cpp
+++ b/src/libs/utils/utilsicons.cpp
@@ -107,10 +107,12 @@ const Icon EXPORTFILE_TOOLBAR({
const Icon MULTIEXPORTFILE_TOOLBAR({
{":/utils/images/filemultiexport.png", Theme::IconsBaseColor}});
-const Icon UNKNOWN_FILE({
- {":/utils/images/unknownfile.png", Theme::IconsBaseColor}});
const Icon DIR({
{":/utils/images/dir.png", Theme::IconsBaseColor}});
+const Icon HELP({
+ {":/utils/images/help.png", Theme::IconsBaseColor}});
+const Icon UNKNOWN_FILE({
+ {":/utils/images/unknownfile.png", Theme::IconsBaseColor}});
const Icon UNDO({
{":/utils/images/undo.png", Theme::PanelTextColorMid}}, Icon::Tint);
diff --git a/src/libs/utils/utilsicons.h b/src/libs/utils/utilsicons.h
index 9e70d8b88c0..0c57bce95cd 100644
--- a/src/libs/utils/utilsicons.h
+++ b/src/libs/utils/utilsicons.h
@@ -25,9 +25,10 @@
#pragma once
-#include "icon.h"
#include "utils_global.h"
+#include "icon.h"
+
namespace Utils {
namespace Icons {
@@ -69,8 +70,9 @@ QTCREATOR_UTILS_EXPORT extern const Icon SAVEFILE_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon EXPORTFILE_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon MULTIEXPORTFILE_TOOLBAR;
-QTCREATOR_UTILS_EXPORT extern const Icon UNKNOWN_FILE;
QTCREATOR_UTILS_EXPORT extern const Icon DIR;
+QTCREATOR_UTILS_EXPORT extern const Icon HELP;
+QTCREATOR_UTILS_EXPORT extern const Icon UNKNOWN_FILE;
QTCREATOR_UTILS_EXPORT extern const Icon UNDO;
QTCREATOR_UTILS_EXPORT extern const Icon UNDO_TOOLBAR;
diff --git a/src/libs/utils/variablechooser.cpp b/src/libs/utils/variablechooser.cpp
index 51ad12f524f..32a7c1026de 100644
--- a/src/libs/utils/variablechooser.cpp
+++ b/src/libs/utils/variablechooser.cpp
@@ -33,11 +33,9 @@
#include "utilsicons.h"
#include <QApplication>
-#include <QAbstractItemModel>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
-#include <QListWidgetItem>
#include <QMenu>
#include <QPlainTextEdit>
#include <QPointer>
@@ -47,14 +45,14 @@
#include <QTimer>
#include <QTreeView>
#include <QVBoxLayout>
-#include <QVector>
namespace Utils {
namespace Internal {
enum {
UnexpandedTextRole = Qt::UserRole,
- ExpandedTextRole
+ ExpandedTextRole,
+ CurrentValueDisplayRole
};
class VariableTreeView : public QTreeView
@@ -105,7 +103,7 @@ public:
void createIconButton()
{
m_iconButton = new IconButton;
- m_iconButton->setIcon(Utils::Icons::REPLACE.icon());
+ m_iconButton->setIcon(Icons::REPLACE.icon());
m_iconButton->setToolTip(VariableChooser::tr("Insert Variable"));
m_iconButton->hide();
connect(m_iconButton.data(), static_cast<void(QAbstractButton::*)(bool)>(&QAbstractButton::clicked),
@@ -133,7 +131,7 @@ public:
QPointer<QPlainTextEdit> m_plainTextEdit;
QPointer<IconButton> m_iconButton;
- Utils::FancyLineEdit *m_variableFilter;
+ FancyLineEdit *m_variableFilter;
VariableTreeView *m_variableTree;
QLabel *m_variableDescription;
QSortFilterProxyModel *m_sortModel;
@@ -197,11 +195,8 @@ public:
}
if (role == Qt::ToolTipRole) {
- QString description = m_expander->variableDescription(m_variable);
- const QString value = m_expander->value(m_variable).toHtmlEscaped();
- if (!value.isEmpty())
- description += QLatin1String("<p>") + VariableChooser::tr("Current Value: %1").arg(value);
- return description;
+ return QString::fromLatin1("<div style=\"white-space:pre\">%1</div>")
+ .arg(data(column, CurrentValueDisplayRole).toString());
}
if (role == UnexpandedTextRole)
@@ -210,6 +205,15 @@ public:
if (role == ExpandedTextRole)
return m_expander->expand(QString::fromUtf8("%{" + m_variable + '}'));
+ if (role == CurrentValueDisplayRole) {
+ QString description = m_expander->variableDescription(m_variable);
+ const QString value = m_expander->value(m_variable).toHtmlEscaped();
+ if (!value.isEmpty())
+ description += QLatin1String("<p>")
+ + VariableChooser::tr("Current Value: %1").arg(value);
+ return description;
+ }
+
return QVariant();
}
@@ -270,7 +274,7 @@ VariableChooserPrivate::VariableChooserPrivate(VariableChooser *parent)
{
m_defaultDescription = VariableChooser::tr("Select a variable to insert.");
- m_variableFilter = new Utils::FancyLineEdit(q);
+ m_variableFilter = new FancyLineEdit(q);
m_variableTree = new VariableTreeView(q, this);
m_variableDescription = new QLabel(q);
@@ -309,15 +313,16 @@ void VariableGroupItem::populateGroup(MacroExpander *expander)
{
if (!expander)
return;
-
- foreach (const QByteArray &variable, expander->visibleVariables()) {
+ const QList<QByteArray> variables = expander->visibleVariables();
+ for (const QByteArray &variable : variables) {
auto item = new VariableItem;
item->m_variable = variable;
item->m_expander = expander;
appendChild(item);
}
- foreach (const MacroExpanderProvider &subProvider, expander->subProviders()) {
+ const MacroExpanderProviders subProviders = expander->subProviders();
+ for (const MacroExpanderProvider &subProvider : subProviders) {
if (!subProvider)
continue;
if (expander->isAccumulating()) {
@@ -434,7 +439,8 @@ void VariableChooser::addSupportForChildWidgets(QWidget *parent, MacroExpander *
{
auto chooser = new VariableChooser(parent);
chooser->addMacroExpanderProvider([expander] { return expander; });
- foreach (QWidget *child, parent->findChildren<QWidget *>()) {
+ const QList<QWidget *> children = parent->findChildren<QWidget *>();
+ for (QWidget *child : children) {
if (qobject_cast<QLineEdit *>(child)
|| qobject_cast<QTextEdit *>(child)
|| qobject_cast<QPlainTextEdit *>(child))
@@ -449,7 +455,7 @@ void VariableChooserPrivate::updateDescription(const QModelIndex &index)
{
if (m_variableDescription)
m_variableDescription->setText(m_model.data(m_sortModel->mapToSource(index),
- Qt::ToolTipRole).toString());
+ CurrentValueDisplayRole).toString());
}
/*!
diff --git a/src/libs/utils/variablechooser.h b/src/libs/utils/variablechooser.h
index 69b95141f6c..23cb56facf1 100644
--- a/src/libs/utils/variablechooser.h
+++ b/src/libs/utils/variablechooser.h
@@ -26,7 +26,6 @@
#pragma once
#include "utils_global.h"
-#include "macroexpander.h"
#include <QWidget>
@@ -34,6 +33,8 @@
namespace Utils {
+class MacroExpander;
+
namespace Internal { class VariableChooserPrivate; }
class QTCREATOR_UTILS_EXPORT VariableChooser : public QWidget
@@ -44,10 +45,10 @@ public:
explicit VariableChooser(QWidget *parent = nullptr);
~VariableChooser() override;
- void addMacroExpanderProvider(const Utils::MacroExpanderProvider &provider);
+ void addMacroExpanderProvider(const std::function<MacroExpander *()> &provider);
void addSupportedWidget(QWidget *textcontrol, const QByteArray &ownName = QByteArray());
- static void addSupportForChildWidgets(QWidget *parent, Utils::MacroExpander *expander);
+ static void addSupportForChildWidgets(QWidget *parent, MacroExpander *expander);
protected:
bool event(QEvent *ev) override;
diff --git a/src/libs/utils/winutils.cpp b/src/libs/utils/winutils.cpp
index 0724100dff3..bda4c197336 100644
--- a/src/libs/utils/winutils.cpp
+++ b/src/libs/utils/winutils.cpp
@@ -32,12 +32,9 @@
#include <windows.h>
#endif
-#include <QString>
-#include <QVector>
-#include <QDebug>
#include <QLibrary>
+#include <QString>
#include <QTextStream>
-#include <QDir>
namespace Utils {
@@ -148,7 +145,8 @@ QTCREATOR_UTILS_EXPORT bool is64BitWindowsSystem()
SYSTEM_INFO systemInfo;
GetNativeSystemInfo(&systemInfo);
return systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64
- || systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64;
+ || systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64
+ || systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64;
#else
return false;
#endif
diff --git a/src/libs/utils/wizard.cpp b/src/libs/utils/wizard.cpp
index 68ae59129c9..beffac23a0e 100644
--- a/src/libs/utils/wizard.cpp
+++ b/src/libs/utils/wizard.cpp
@@ -28,10 +28,9 @@
#include "algorithm.h"
#include "hostosinfo.h"
#include "qtcassert.h"
+#include "theme/theme.h"
#include "wizardpage.h"
-#include <utils/theme/theme.h>
-
#include <QDebug>
#include <QDialog>
#include <QDialogButtonBox>
@@ -41,8 +40,8 @@
#include <QLabel>
#include <QMap>
#include <QScrollArea>
-#include <QVBoxLayout>
#include <QVariant>
+#include <QVBoxLayout>
/*! \class Utils::Wizard
@@ -319,7 +318,7 @@ Wizard::Wizard(QWidget *parent, Qt::WindowFlags flags) :
setOption(QWizard::NoCancelButton, false);
setOption(QWizard::NoDefaultButton, false);
setOption(QWizard::NoBackButtonOnStartPage, true);
- if (!Utils::creatorTheme()->preferredStyles().isEmpty())
+ if (!creatorTheme()->preferredStyles().isEmpty())
setWizardStyle(QWizard::ModernStyle);
if (HostOsInfo::isMacHost()) {
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
index 800cd3b775d..13a985613e6 100644
--- a/src/plugins/CMakeLists.txt
+++ b/src/plugins/CMakeLists.txt
@@ -61,6 +61,8 @@ add_subdirectory(languageclient)
# Level 6:
add_subdirectory(cmakeprojectmanager)
add_subdirectory(debugger)
+add_subdirectory(coco)
+add_subdirectory(gitlab)
# Level 7:
add_subdirectory(android)
@@ -78,7 +80,6 @@ add_subdirectory(qmlpreview)
add_subdirectory(qmlprofiler)
add_subdirectory(remotelinux)
add_subdirectory(valgrind)
-add_subdirectory(winrt)
add_subdirectory(perfprofiler)
add_subdirectory(qbsprojectmanager)
add_subdirectory(ctfvisualizer)
diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt
index 2f4b06f634a..5ac673bd4f4 100644
--- a/src/plugins/android/CMakeLists.txt
+++ b/src/plugins/android/CMakeLists.txt
@@ -1,5 +1,5 @@
add_qtc_plugin(Android
- DEPENDS QtcSsh QmlDebug Qt5::Xml LanguageServerProtocol
+ DEPENDS QmlDebug Qt5::Xml LanguageServerProtocol
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport LanguageClient
SOURCES
addnewavddialog.ui
diff --git a/src/plugins/android/android_global.h b/src/plugins/android/android_global.h
index 1f79d86ebc1..eaf24f88076 100644
--- a/src/plugins/android/android_global.h
+++ b/src/plugins/android/android_global.h
@@ -29,6 +29,8 @@
#if defined(ANDROID_LIBRARY)
# define ANDROID_EXPORT Q_DECL_EXPORT
+#elif defined(ANDROID_STATIC_LIBRARY)
+# define ANDROID_EXPORT
#else
# define ANDROID_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/android/androidavdmanager.cpp b/src/plugins/android/androidavdmanager.cpp
index 3944e30ed6b..429e7183df7 100644
--- a/src/plugins/android/androidavdmanager.cpp
+++ b/src/plugins/android/androidavdmanager.cpp
@@ -66,13 +66,13 @@ const int avdCreateTimeoutMs = 30000;
bool AndroidAvdManager::avdManagerCommand(const AndroidConfig &config, const QStringList &args, QString *output)
{
CommandLine cmd(config.avdManagerToolPath(), args);
- Utils::QtcProcess proc;
+ QtcProcess proc;
Environment env = AndroidConfigurations::toolsEnvironment(config);
proc.setEnvironment(env);
qCDebug(avdManagerLog) << "Running AVD Manager command:" << cmd.toUserOutput();
proc.setCommand(cmd);
proc.runBlocking();
- if (proc.result() == Utils::QtcProcess::FinishedWithSuccess) {
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
if (output)
*output = proc.allOutput();
return true;
@@ -118,7 +118,8 @@ static CreateAvdInfo createAvdCommand(const AndroidConfig &config, const CreateA
const FilePath avdManagerTool = config.avdManagerToolPath();
qCDebug(avdManagerLog)
<< "Running AVD Manager command:" << CommandLine(avdManagerTool, arguments).toUserOutput();
- QtcProcess proc(ProcessMode::Writer);
+ QtcProcess proc;
+ proc.setProcessMode(ProcessMode::Writer);
proc.setEnvironment(AndroidConfigurations::toolsEnvironment(config));
proc.setCommand({avdManagerTool, arguments});
proc.start();
@@ -129,7 +130,7 @@ static CreateAvdInfo createAvdCommand(const AndroidConfig &config, const CreateA
return result;
}
QTC_CHECK(proc.isRunning());
- proc.write(QByteArray("yes\n")); // yes to "Do you wish to create a custom hardware profile"
+ proc.write("yes\n"); // yes to "Do you wish to create a custom hardware profile"
auto start = chrono::steady_clock::now();
QString errorOutput;
@@ -143,9 +144,9 @@ static CreateAvdInfo createAvdCommand(const AndroidConfig &config, const CreateA
if (index != -1)
question = question.mid(index);
if (question.contains("hw.gpu.enabled"))
- proc.write(QByteArray("yes\n"));
+ proc.write("yes\n");
else
- proc.write(QByteArray("\n"));
+ proc.write("\n");
question.clear();
}
// The exit code is always 0, so we need to check stderr
@@ -161,30 +162,10 @@ static CreateAvdInfo createAvdCommand(const AndroidConfig &config, const CreateA
}
}
- // Kill the running process.
- if (proc.state() != QProcess::NotRunning) {
- proc.terminate();
- if (!proc.waitForFinished(3000))
- proc.kill();
- }
-
- QTC_CHECK(proc.state() == QProcess::NotRunning);
result.error = errorOutput;
return result;
}
-static void avdProcessFinished(int exitCode, QtcProcess *p)
-{
- QTC_ASSERT(p, return);
- if (exitCode) {
- QString title = QCoreApplication::translate("Android::Internal::AndroidAvdManager",
- "AVD Start Error");
- QMessageBox::critical(Core::ICore::dialogParent(), title,
- QString::fromLatin1(p->readAllStandardOutput()));
- }
- p->deleteLater();
-}
-
AndroidAvdManager::AndroidAvdManager(const AndroidConfig &config)
: m_config(config)
{
@@ -195,7 +176,7 @@ AndroidAvdManager::~AndroidAvdManager() = default;
QFuture<CreateAvdInfo> AndroidAvdManager::createAvd(CreateAvdInfo info) const
{
- return Utils::runAsync(&createAvdCommand, m_config, info);
+ return runAsync(&createAvdCommand, m_config, info);
}
bool AndroidAvdManager::removeAvd(const QString &name) const
@@ -207,12 +188,12 @@ bool AndroidAvdManager::removeAvd(const QString &name) const
proc.setEnvironment(AndroidConfigurations::toolsEnvironment(m_config));
proc.setCommand(command);
proc.runBlocking();
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
static void avdConfigEditManufacturerTag(const QString &avdPathStr, bool recoverMode = false)
{
- const Utils::FilePath avdPath = Utils::FilePath::fromString(avdPathStr);
+ const FilePath avdPath = FilePath::fromString(avdPathStr);
if (avdPath.exists()) {
const QString configFilePath = avdPath.pathAppended("config.ini").toString();
QFile configFile(configFilePath);
@@ -272,7 +253,7 @@ static AndroidDeviceInfoList listVirtualDevices(const AndroidConfig &config)
QFuture<AndroidDeviceInfoList> AndroidAvdManager::avdList() const
{
- return Utils::runAsync(listVirtualDevices, m_config);
+ return runAsync(listVirtualDevices, m_config);
}
QString AndroidAvdManager::startAvd(const QString &name) const
@@ -286,42 +267,57 @@ bool AndroidAvdManager::startAvdAsync(const QString &avdName) const
{
QFileInfo info(m_config.emulatorToolPath().toString());
if (!info.exists()) {
- QMessageBox::critical(Core::ICore::dialogParent(),
- tr("Emulator Tool Is Missing"),
- tr("Install the missing emulator tool (%1) to the"
- " installed Android SDK.")
- .arg(m_config.emulatorToolPath().toString()));
+ const QString emulatorToolPath = m_config.emulatorToolPath().toUserOutput();
+ QMetaObject::invokeMethod(Core::ICore::mainWindow(), [emulatorToolPath] {
+ QMessageBox::critical(Core::ICore::dialogParent(),
+ AndroidAvdManager::tr("Emulator Tool Is Missing"),
+ AndroidAvdManager::tr(
+ "Install the missing emulator tool (%1) to the"
+ " installed Android SDK.")
+ .arg(emulatorToolPath));
+ });
return false;
}
- auto avdProcess = new QtcProcess();
+
+ // TODO: Here we are potentially leaking QtcProcess instance in case when shutdown happens
+ // after the avdProcess has started and before it has finished. Giving a parent object here
+ // should solve the issue. However, AndroidAvdManager is not a QObject, so no clue what parent
+ // would be the most appropriate. Preferably some object taken form android plugin...
+ QtcProcess *avdProcess = new QtcProcess;
avdProcess->setProcessChannelMode(QProcess::MergedChannels);
- QObject::connect(avdProcess, &QtcProcess::finished, avdProcess,
- [avdProcess] { avdProcessFinished(avdProcess->exitCode(), avdProcess); });
+ QObject::connect(avdProcess, &QtcProcess::done, avdProcess, [avdProcess] {
+ if (avdProcess->exitCode()) {
+ const QString errorOutput = QString::fromLatin1(avdProcess->readAllStandardOutput());
+ QMetaObject::invokeMethod(Core::ICore::mainWindow(), [errorOutput] {
+ const QString title
+ = QCoreApplication::translate("Android::Internal::AndroidAvdManager",
+ "AVD Start Error");
+ QMessageBox::critical(Core::ICore::dialogParent(), title, errorOutput);
+ });
+ }
+ avdProcess->deleteLater();
+ });
// start the emulator
- QStringList arguments;
+ CommandLine cmd(m_config.emulatorToolPath());
if (AndroidConfigurations::force32bitEmulator())
- arguments << "-force-32bit";
+ cmd.addArg("-force-32bit");
- arguments << m_config.emulatorArgs() << "-avd" << avdName;
- qCDebug(avdManagerLog) << "Running command (startAvdAsync):"
- << CommandLine(m_config.emulatorToolPath(), arguments).toUserOutput();
- avdProcess->setCommand({m_config.emulatorToolPath(), arguments});
+ cmd.addArgs(m_config.emulatorArgs(), CommandLine::Raw);
+ cmd.addArgs({"-avd", avdName});
+ qCDebug(avdManagerLog) << "Running command (startAvdAsync):" << cmd.toUserOutput();
+ avdProcess->setCommand(cmd);
avdProcess->start();
- if (!avdProcess->waitForStarted(-1)) {
- delete avdProcess;
- return false;
- }
- return true;
+ return avdProcess->waitForStarted(-1);
}
QString AndroidAvdManager::findAvd(const QString &avdName) const
{
- QVector<AndroidDeviceInfo> devices = m_config.connectedDevices();
- foreach (AndroidDeviceInfo device, devices) {
+ const QVector<AndroidDeviceInfo> devices = m_config.connectedDevices();
+ for (const AndroidDeviceInfo &device : devices) {
if (device.type != ProjectExplorer::IDevice::Emulator)
continue;
- if (device.avdname == avdName)
+ if (device.avdName == avdName)
return device.serialNumber;
}
return QString();
@@ -355,7 +351,7 @@ bool AndroidAvdManager::isAvdBooted(const QString &device) const
adbProc.setTimeoutS(10);
adbProc.setCommand(command);
adbProc.runBlocking();
- if (adbProc.result() != QtcProcess::FinishedWithSuccess)
+ if (adbProc.result() != ProcessResult::FinishedWithSuccess)
return false;
QString value = adbProc.allOutput().trimmed();
return value == "stopped";
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index c97a337c231..868e7e4129d 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -385,7 +385,7 @@ QWidget *AndroidBuildApkWidget::createAdditionalLibrariesGroup()
m_openSslCheckBox = new QCheckBox(tr("Include prebuilt OpenSSL libraries"));
m_openSslCheckBox->setToolTip(tr("This is useful for apps that use SSL operations. The path "
- "can be defined in Tools > Options > Devices > Android."));
+ "can be defined in Edit > Preferences > Devices > Android."));
connect(m_openSslCheckBox, &QAbstractButton::clicked, this,
&AndroidBuildApkWidget::onOpenSslCheckBoxChanged);
@@ -535,7 +535,7 @@ bool AndroidBuildApkStep::init()
const QVersionNumber sdkToolsVersion = AndroidConfigurations::currentConfig().sdkToolsVersion();
if (sdkToolsVersion >= QVersionNumber(25, 3, 0)
- || AndroidConfigurations::currentConfig().isCmdlineSdkToolsInstalled()) {
+ && AndroidConfigurations::currentConfig().preCmdlineSdkToolsInstalled()) {
if (!version->sourcePath().pathAppended("src/3rdparty/gradle").exists()) {
const QString error
= tr("The installed SDK tools version (%1) does not include Gradle "
@@ -611,9 +611,11 @@ bool AndroidBuildApkStep::init()
QStringList argumentsPasswordConcealed = arguments;
if (m_signPackage) {
- arguments << "--sign" << m_keystorePath.toString() << m_certificateAlias
+ arguments << "--release"
+ << "--sign" << m_keystorePath.toString() << m_certificateAlias
<< "--storepass" << m_keystorePasswd;
- argumentsPasswordConcealed << "--sign" << "******"
+ argumentsPasswordConcealed << "--release"
+ << "--sign" << "******"
<< "--storepass" << "******";
if (!m_certificatePasswd.isEmpty()) {
arguments << "--keypass" << m_certificatePasswd;
@@ -1061,11 +1063,11 @@ QAbstractItemModel *AndroidBuildApkStep::keystoreCertificates()
QtcProcess keytoolProc;
keytoolProc.setTimeoutS(30);
keytoolProc.setCommand({AndroidConfigurations::currentConfig().keytoolPath(), params});
- keytoolProc.runBlocking(QtcProcess::WithEventLoop);
- if (keytoolProc.result() > QtcProcess::FinishedWithError)
+ keytoolProc.runBlocking(EventLoopMode::On);
+ if (keytoolProc.result() > ProcessResult::FinishedWithError)
QMessageBox::critical(nullptr, tr("Error"), tr("Failed to run keytool."));
else
- model = new CertificatesModel(keytoolProc.stdOut(), this);
+ model = new CertificatesModel(keytoolProc.cleanedStdOut(), this);
return model;
}
diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h
index 2b439faf8af..4aec88641e2 100644
--- a/src/plugins/android/androidbuildapkstep.h
+++ b/src/plugins/android/androidbuildapkstep.h
@@ -30,8 +30,6 @@
#include <projectexplorer/abstractprocessstep.h>
-#include <utils/fileutils.h>
-
QT_BEGIN_NAMESPACE
class QAbstractItemModel;
QT_END_NAMESPACE
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 7400020bbb9..642cef0b085 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -165,7 +165,7 @@ namespace {
proc.setTimeoutS(30);
proc.setCommand({executable, {shell}});
proc.runBlocking();
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return true;
return !proc.allOutput().contains("x86-64");
}
@@ -229,8 +229,10 @@ QLatin1String AndroidConfig::displayName(const Abi &abi)
void AndroidConfig::load(const QSettings &settings)
{
// user settings
- m_emulatorArgs = settings.value(EmulatorArgsKey,
- QStringList({"-netdelay", "none", "-netspeed", "full"})).toStringList();
+ QVariant emulatorArgs = settings.value(EmulatorArgsKey, QString("-netdelay none -netspeed full"));
+ if (emulatorArgs.type() == QVariant::StringList) // Changed in 8.0 from QStringList to QString.
+ emulatorArgs = ProcessArgs::joinArgs(emulatorArgs.toStringList());
+ m_emulatorArgs = emulatorArgs.toString();
m_sdkLocation = FilePath::fromUserInput(settings.value(SDKLocationKey).toString()).cleanPath();
m_customNdkList = settings.value(CustomNdkLocationsKey).toStringList();
m_defaultNdk =
@@ -334,7 +336,7 @@ void AndroidConfig::parseDependenciesJson()
if (HostOsInfo::isWindowsHost())
appendEssentialsFromArray(commonEssentials[WindowsOsKey].toArray());
- if (HostOsInfo::isMacHost())
+ else if (HostOsInfo::isMacHost())
appendEssentialsFromArray(commonEssentials[macOsKey].toArray());
else
appendEssentialsFromArray(commonEssentials[LinuxOsKey].toArray());
@@ -342,13 +344,13 @@ void AndroidConfig::parseDependenciesJson()
auto fillQtVersionsRange = [](const QString &shortVersion) {
QList<QtVersionNumber> versions;
- QRegularExpression re("([0-9]\\.[0-9]*\\.)\\[([0-9])\\-([0-9])\\]");
+ const QRegularExpression re(R"(([0-9]\.[0-9]+\.)\[([0-9]+)\-([0-9]+)\])");
QRegularExpressionMatch match = re.match(shortVersion);
if (match.hasMatch() && match.lastCapturedIndex() == 3)
for (int i = match.captured(2).toInt(); i <= match.captured(3).toInt(); ++i)
versions.append(QtVersionNumber(match.captured(1) + QString::number(i)));
else
- versions.append(QtVersionNumber(shortVersion));
+ versions.append(QtVersionNumber(shortVersion + ".-1"));
return versions;
};
@@ -474,9 +476,12 @@ QString AndroidConfig::apiLevelNameFor(const SdkPlatform *platform)
QString("android-%1").arg(platform->apiLevel()) : "";
}
-bool AndroidConfig::isCmdlineSdkToolsInstalled() const
+// This is checking for the SDK tools [*] that were deprecated in favor of
+// the command-line tools.
+// See https://developer.android.com/studio/releases/sdk-tools
+bool AndroidConfig::preCmdlineSdkToolsInstalled() const
{
- QString toolPath("cmdline-tools/latest/bin/sdkmanager");
+ QString toolPath("tools/bin/sdkmanager");
if (HostOsInfo::isWindowsHost())
toolPath += ANDROID_BAT_SUFFIX;
@@ -491,38 +496,51 @@ FilePath AndroidConfig::adbToolPath() const
FilePath AndroidConfig::emulatorToolPath() const
{
QString relativePath = "emulator/emulator";
- if (sdkToolsVersion() < QVersionNumber(25, 3, 0) && !isCmdlineSdkToolsInstalled())
+ if (sdkToolsVersion() < QVersionNumber(25, 3, 0) && preCmdlineSdkToolsInstalled())
relativePath = "tools/emulator";
return m_sdkLocation / (relativePath + QTC_HOST_EXE_SUFFIX);
}
FilePath AndroidConfig::sdkManagerToolPath() const
{
- QStringList sdkmanagerPaths = {"cmdline-tools/latest/bin/sdkmanager",
- "tools/bin/sdkmanager"};
+ const QStringList sdkmanagerPaths = {
+ QString(Constants::cmdlineToolsName).append("/latest/bin/sdkmanager"),
+ "tools/bin/sdkmanager"};
- for (QString &toolPath : sdkmanagerPaths) {
+ for (const QString &toolPath : sdkmanagerPaths) {
+ QString toolPathWithSuffix = toolPath;
if (HostOsInfo::isWindowsHost())
- toolPath += ANDROID_BAT_SUFFIX;
-
- const FilePath sdkmanagerPath = m_sdkLocation / toolPath;
+ toolPathWithSuffix += ANDROID_BAT_SUFFIX;
+ const FilePath sdkmanagerPath = m_sdkLocation / toolPathWithSuffix;
if (sdkmanagerPath.exists())
return sdkmanagerPath;
}
+ // If it's a first time install use the path of Constants::cmdlineToolsName temporary download
+ const FilePath tmpSdkPath = m_temporarySdkToolsPath;
+ if (!tmpSdkPath.isEmpty()) {
+ QString suffix = "bin/sdkmanager";
+ if (HostOsInfo::isWindowsHost())
+ suffix += ANDROID_BAT_SUFFIX;
+ const FilePath tmpsdkManagerPath = tmpSdkPath.pathAppended(suffix);
+ if (tmpsdkManagerPath.exists())
+ return tmpsdkManagerPath;
+ }
+
return FilePath();
}
FilePath AndroidConfig::avdManagerToolPath() const
{
- QStringList sdkmanagerPaths = {"cmdline-tools/latest/bin/avdmanager",
- "tools/bin/avdmanager"};
+ const QStringList sdkmanagerPaths = {
+ QString(Constants::cmdlineToolsName).append("/latest/bin/avdmanager"),
+ "tools/bin/avdmanager"};
- for (QString &toolPath : sdkmanagerPaths) {
+ for (const QString &toolPath : sdkmanagerPaths) {
+ QString toolPathWithSuffix = toolPath;
if (HostOsInfo::isWindowsHost())
- toolPath += ANDROID_BAT_SUFFIX;
-
- const FilePath sdkmanagerPath = m_sdkLocation / toolPath;
+ toolPathWithSuffix += ANDROID_BAT_SUFFIX;
+ const FilePath sdkmanagerPath = m_sdkLocation / toolPathWithSuffix;
if (sdkmanagerPath.exists())
return sdkmanagerPath;
}
@@ -530,6 +548,34 @@ FilePath AndroidConfig::avdManagerToolPath() const
return FilePath();
}
+void AndroidConfig::setTemporarySdkToolsPath(const Utils::FilePath &path)
+{
+ m_temporarySdkToolsPath = path;
+}
+
+FilePath AndroidConfig::sdkToolsVersionPath() const
+{
+ const QStringList sdkVersionPaths = {
+ QString(Constants::cmdlineToolsName).append("/latest/source.properties"),
+ "tools/source.properties"};
+
+ for (const QString &versionPath : sdkVersionPaths) {
+ const FilePath sdkVersionPath = m_sdkLocation / versionPath;
+ if (sdkVersionPath.exists())
+ return sdkVersionPath;
+ }
+
+ // If it's a first time install use the path of Constants::cmdlineToolsName temporary download
+ const FilePath tmpSdkPath = m_temporarySdkToolsPath;
+ if (!tmpSdkPath.isEmpty()) {
+ const FilePath sdkVersionPath = tmpSdkPath.pathAppended("source.properties");
+ if (sdkVersionPath.exists())
+ return sdkVersionPath;
+ }
+
+ return FilePath();
+}
+
FilePath AndroidConfig::toolchainPathFromNdk(const FilePath &ndkLocation, OsType hostOs)
{
const FilePath tcPath = ndkLocation / "toolchains/";
@@ -635,7 +681,7 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
CommandLine cmd{adbToolPath(), {"devices"}};
adbProc.setCommand(cmd);
adbProc.runBlocking();
- if (adbProc.result() != QtcProcess::FinishedWithSuccess) {
+ if (adbProc.result() != ProcessResult::FinishedWithSuccess) {
if (error)
*error = QApplication::translate("AndroidConfiguration", "Could not run: %1")
.arg(cmd.toUserOutput());
@@ -652,7 +698,7 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
// workaround for '????????????' serial numbers:
// can use "adb -d" when only one usb device attached
- foreach (const QString &device, adbDevs) {
+ for (const QString &device : qAsConst(adbDevs)) {
const QString serialNo = device.left(device.indexOf('\t')).trimmed();
const QString deviceType = device.mid(device.indexOf('\t')).trimmed();
AndroidDeviceInfo dev;
@@ -669,9 +715,9 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
dev.state = IDevice::DeviceReadyToUse;
if (dev.type == IDevice::Emulator) {
- dev.avdname = getAvdName(dev.serialNumber);
- if (dev.avdname.isEmpty())
- dev.avdname = serialNo;
+ dev.avdName = getAvdName(dev.serialNumber);
+ if (dev.avdName.isEmpty())
+ dev.avdName = serialNo;
}
devices.push_back(dev);
@@ -687,8 +733,8 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
bool AndroidConfig::isConnected(const QString &serialNumber) const
{
- QVector<AndroidDeviceInfo> devices = connectedDevices();
- foreach (AndroidDeviceInfo device, devices) {
+ const QVector<AndroidDeviceInfo> devices = connectedDevices();
+ for (const AndroidDeviceInfo &device : devices) {
if (device.serialNumber == serialNumber)
return true;
}
@@ -706,7 +752,7 @@ QString AndroidConfig::getDeviceProperty(const QString &device, const QString &p
adbProc.setTimeoutS(10);
adbProc.setCommand(cmd);
adbProc.runBlocking();
- if (adbProc.result() != QtcProcess::FinishedWithSuccess)
+ if (adbProc.result() != ProcessResult::FinishedWithSuccess)
return QString();
return adbProc.allOutput();
@@ -753,28 +799,6 @@ QString AndroidConfig::getAvdName(const QString &serialnumber)
return QString::fromLatin1(name).trimmed();
}
-AndroidConfig::OpenGl AndroidConfig::getOpenGLEnabled(const QString &emulator) const
-{
- QDir dir = QDir::home();
- if (!dir.cd(QLatin1String(".android")))
- return OpenGl::Unknown;
- if (!dir.cd(QLatin1String("avd")))
- return OpenGl::Unknown;
- if (!dir.cd(emulator + QLatin1String(".avd")))
- return OpenGl::Unknown;
- QFile file(dir.filePath(QLatin1String("config.ini")));
- if (!file.exists())
- return OpenGl::Unknown;
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
- return OpenGl::Unknown;
- while (!file.atEnd()) {
- QByteArray line = file.readLine();
- if (line.contains("hw.gpu.enabled") && line.contains("yes"))
- return OpenGl::Enabled;
- }
- return OpenGl::Disabled;
-}
-
//!
//! \brief AndroidConfigurations::getProductModel
//! \param device serial number
@@ -805,7 +829,7 @@ QStringList AndroidConfig::getAbis(const QString &device)
adbProc.setTimeoutS(10);
adbProc.setCommand({adbTool, arguments});
adbProc.runBlocking();
- if (adbProc.result() != QtcProcess::FinishedWithSuccess)
+ if (adbProc.result() != ProcessResult::FinishedWithSuccess)
return result;
QString output = adbProc.allOutput().trimmed();
@@ -828,7 +852,7 @@ QStringList AndroidConfig::getAbis(const QString &device)
abiProc.setTimeoutS(10);
abiProc.setCommand({adbTool, arguments});
abiProc.runBlocking();
- if (abiProc.result() != QtcProcess::FinishedWithSuccess)
+ if (abiProc.result() != ProcessResult::FinishedWithSuccess)
return result;
QString abi = abiProc.allOutput().trimmed();
@@ -864,7 +888,8 @@ bool AndroidConfig::isValidNdk(const QString &ndkLocation) const
QString AndroidConfig::bestNdkPlatformMatch(int target, const QtVersion *qtVersion) const
{
target = std::max(AndroidManager::defaultMinimumSDK(qtVersion), target);
- foreach (int apiLevel, availableNdkPlatforms(qtVersion)) {
+ const QList<int> platforms = availableNdkPlatforms(qtVersion);
+ for (const int apiLevel : platforms) {
if (apiLevel <= target)
return QString::fromLatin1("android-%1").arg(apiLevel);
}
@@ -883,18 +908,12 @@ void AndroidConfig::setSdkLocation(const FilePath &sdkLocation)
QVersionNumber AndroidConfig::sdkToolsVersion() const
{
- QVersionNumber version;
- if (m_sdkLocation.exists()) {
- FilePath sdkToolsPropertiesPath;
- if (isCmdlineSdkToolsInstalled())
- sdkToolsPropertiesPath = m_sdkLocation / "cmdline-tools/latest/source.properties";
- else
- sdkToolsPropertiesPath = m_sdkLocation / "tools/source.properties";
- QSettings settings(sdkToolsPropertiesPath.toString(), QSettings::IniFormat);
- auto versionStr = settings.value(sdkToolsVersionKey).toString();
- version = QVersionNumber::fromString(versionStr);
- }
- return version;
+ if (!m_sdkLocation.exists())
+ return {};
+
+ const FilePath sdkToolsPropertiesPath = sdkToolsVersionPath();
+ const QSettings settings(sdkToolsPropertiesPath.toString(), QSettings::IniFormat);
+ return QVersionNumber::fromString(settings.value(sdkToolsVersionKey).toString());
}
QVersionNumber AndroidConfig::buildToolsVersion() const
@@ -1090,12 +1109,12 @@ QString AndroidConfig::toolchainHostFromNdk(const FilePath &ndkPath)
return toolchainHost;
}
-QStringList AndroidConfig::emulatorArgs() const
+QString AndroidConfig::emulatorArgs() const
{
return m_emulatorArgs;
}
-void AndroidConfig::setEmulatorArgs(const QStringList &args)
+void AndroidConfig::setEmulatorArgs(const QString &args)
{
m_emulatorArgs = args;
}
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
index 5338845d0d2..0578b3f5783 100644
--- a/src/plugins/android/androidconfigurations.h
+++ b/src/plugins/android/androidconfigurations.h
@@ -96,6 +96,7 @@ public:
Utils::FilePath sdkLocation() const;
void setSdkLocation(const Utils::FilePath &sdkLocation);
QVersionNumber sdkToolsVersion() const;
+ Utils::FilePath sdkToolsVersionPath() const;
QVersionNumber buildToolsVersion() const;
QStringList sdkManagerToolArgs() const;
void setSdkManagerToolArgs(const QStringList &args);
@@ -122,8 +123,8 @@ public:
QString toolchainHost(const QtSupport::QtVersion *qtVersion) const;
static QString toolchainHostFromNdk(const Utils::FilePath &ndkPath);
- QStringList emulatorArgs() const;
- void setEmulatorArgs(const QStringList &args);
+ QString emulatorArgs() const;
+ void setEmulatorArgs(const QString &args);
bool automaticKitCreation() const;
void setAutomaticKitCreation(bool b);
@@ -134,6 +135,8 @@ public:
Utils::FilePath sdkManagerToolPath() const;
Utils::FilePath avdManagerToolPath() const;
+ void setTemporarySdkToolsPath(const Utils::FilePath &path);
+
Utils::FilePath toolchainPath(const QtSupport::QtVersion *qtVersion) const;
static Utils::FilePath toolchainPathFromNdk(const Utils::FilePath &ndkLocation,
Utils::OsType hostOs = Utils::HostOsInfo::hostOs());
@@ -156,11 +159,9 @@ public:
static QLatin1String displayName(const ProjectExplorer::Abi &abi);
QString getProductModel(const QString &device) const;
- enum class OpenGl { Enabled, Disabled, Unknown };
- OpenGl getOpenGLEnabled(const QString &emulator) const;
bool isConnected(const QString &serialNumber) const;
- bool isCmdlineSdkToolsInstalled() const;
+ bool preCmdlineSdkToolsInstalled() const;
bool sdkFullyConfigured() const { return m_sdkFullyConfigured; }
void setSdkFullyConfigured(bool allEssentialsInstalled) { m_sdkFullyConfigured = allEssentialsInstalled; }
@@ -190,11 +191,12 @@ private:
QList<int> availableNdkPlatforms(const QtSupport::QtVersion *qtVersion) const;
Utils::FilePath m_sdkLocation;
+ Utils::FilePath m_temporarySdkToolsPath;
QStringList m_sdkManagerToolArgs;
Utils::FilePath m_openJDKLocation;
Utils::FilePath m_keystoreLocation;
Utils::FilePath m_openSslLocation;
- QStringList m_emulatorArgs;
+ QString m_emulatorArgs;
bool m_automaticKitCreation = true;
QUrl m_sdkToolsUrl;
QByteArray m_sdkToolsSha256;
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h
index 02bb50b348e..83012d8073e 100644
--- a/src/plugins/android/androidconstants.h
+++ b/src/plugins/android/androidconstants.h
@@ -99,11 +99,11 @@ const char SdkLocation[] = "SdkLocation"; // FileName
const Utils::Id AndroidSerialNumber = "AndroidSerialNumber";
const Utils::Id AndroidAvdName = "AndroidAvdName";
const Utils::Id AndroidCpuAbi = "AndroidCpuAbi";
-const Utils::Id AndroidAvdTarget = "AndroidAvdTarget";
-const Utils::Id AndroidAvdDevice = "AndroidAvdDevice";
-const Utils::Id AndroidAvdSkin = "AndroidAvdSkin";
-const Utils::Id AndroidAvdSdcard = "AndroidAvdSdcard";
const Utils::Id AndroidSdk = "AndroidSdk";
+const Utils::Id AndroidAvdPath = "AndroidAvdPath";
+
+// SDK Tools
+const char cmdlineToolsName[] = "cmdline-tools";
} // namespace Constants;
} // namespace Android
diff --git a/src/plugins/android/androidcreatekeystorecertificate.cpp b/src/plugins/android/androidcreatekeystorecertificate.cpp
index 48c91c6bae8..b17ac11993b 100644
--- a/src/plugins/android/androidcreatekeystorecertificate.cpp
+++ b/src/plugins/android/androidcreatekeystorecertificate.cpp
@@ -208,9 +208,9 @@ void AndroidCreateKeystoreCertificate::buttonBoxAccepted()
QtcProcess genKeyCertProc;
genKeyCertProc.setTimeoutS(15);
genKeyCertProc.setCommand(command);
- genKeyCertProc.runBlocking(QtcProcess::WithEventLoop);
+ genKeyCertProc.runBlocking(EventLoopMode::On);
- if (genKeyCertProc.result() != QtcProcess::FinishedWithSuccess) {
+ if (genKeyCertProc.result() != ProcessResult::FinishedWithSuccess) {
QMessageBox::critical(this, tr("Error"),
genKeyCertProc.exitMessage() + '\n' + genKeyCertProc.allOutput());
return;
diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp
index c92ec6af462..2cc37d7e931 100644
--- a/src/plugins/android/androiddebugsupport.cpp
+++ b/src/plugins/android/androiddebugsupport.cpp
@@ -140,11 +140,16 @@ void AndroidDebugSupport::start()
solibSearchPath.append(qtVersion->qtSoPaths());
solibSearchPath.append(uniquePaths(extraLibs));
+ FilePath buildDir = AndroidManager::buildDirectory(target);
const RunConfiguration *activeRunConfig = target->activeRunConfiguration();
- FilePath buildDir;
if (activeRunConfig)
- buildDir = activeRunConfig->buildTargetInfo().workingDirectory;
+ solibSearchPath.append(activeRunConfig->buildTargetInfo().workingDirectory.toString());
solibSearchPath.append(buildDir.toString());
+ const auto androidLibsPath = AndroidManager::androidBuildDirectory(target)
+ .pathAppended("libs")
+ .pathAppended(AndroidManager::apkDevicePreferredAbi(target))
+ .toString();
+ solibSearchPath.append(androidLibsPath);
solibSearchPath.removeDuplicates();
setSolibSearchPath(solibSearchPath);
qCDebug(androidDebugSupportLog) << "SoLibSearchPath: "<<solibSearchPath;
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index 89ea6de806a..e5bde4a30b7 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -209,16 +209,16 @@ bool AndroidDeployQtStep::init()
.arg(info.cpuAbi.first())));
}
- m_avdName = info.avdname;
+ m_avdName = info.avdName;
m_serialNumber = info.serialNumber;
qCDebug(deployStepLog) << "Selected device info:" << info;
- gatherFilesToPull();
-
AndroidManager::setDeviceSerialNumber(target(), m_serialNumber);
AndroidManager::setDeviceApiLevel(target(), info.sdk);
AndroidManager::setDeviceAbis(target(), info.cpuAbi);
+ gatherFilesToPull();
+
emit addOutput(tr("Deploying to %1").arg(m_serialNumber), OutputFormat::NormalMessage);
m_uninstallPreviousPackageRun = m_uninstallPreviousPackage->value();
@@ -324,53 +324,39 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
cmd.addArgs({"install", "-r", m_apkPath.toString()});
}
- m_process = new QtcProcess;
- m_process->setCommand(cmd);
- m_process->setWorkingDirectory(m_workingDirectory);
- m_process->setEnvironment(m_environment);
- m_process->setUseCtrlCStub(true);
+ QtcProcess process;
+ process.setCommand(cmd);
+ process.setWorkingDirectory(m_workingDirectory);
+ process.setEnvironment(m_environment);
+ process.setUseCtrlCStub(true);
DeployErrorCode deployError = NoError;
- m_process->setStdOutLineCallback([this, &deployError](const QString &line) {
+ process.setStdOutLineCallback([this, &deployError](const QString &line) {
deployError |= parseDeployErrors(line);
stdOutput(line);
});
- m_process->setStdErrLineCallback([this, &deployError](const QString &line) {
+ process.setStdErrLineCallback([this, &deployError](const QString &line) {
deployError |= parseDeployErrors(line);
stdError(line);
});
- m_process->start();
+ process.start();
emit addOutput(tr("Starting: \"%1\"").arg(cmd.toUserOutput()), OutputFormat::NormalMessage);
- while (!m_process->waitForFinished(200)) {
- if (m_process->state() == QProcess::NotRunning)
+ while (!process.waitForFinished(200)) {
+ if (process.state() == QProcess::NotRunning)
break;
if (isCanceled()) {
- m_process->kill();
- m_process->waitForFinished();
+ process.kill();
+ process.waitForFinished();
}
}
- QString line = QString::fromLocal8Bit(m_process->readAllStandardError());
- if (!line.isEmpty()) {
- deployError |= parseDeployErrors(line);
- stdError(line);
- }
-
- line = QString::fromLocal8Bit(m_process->readAllStandardOutput());
- if (!line.isEmpty()) {
- deployError |= parseDeployErrors(line);
- stdOutput(line);
- }
-
- QProcess::ExitStatus exitStatus = m_process->exitStatus();
- int exitCode = m_process->exitCode();
- delete m_process;
- m_process = nullptr;
+ const QProcess::ExitStatus exitStatus = process.exitStatus();
+ const int exitCode = process.exitCode();
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
emit addOutput(tr("The process \"%1\" exited normally.").arg(m_command.toUserOutput()),
@@ -528,8 +514,8 @@ void AndroidDeployQtStep::runCommand(const CommandLine &command)
OutputFormat::NormalMessage);
buildProc.setCommand(command);
- buildProc.runBlocking(QtcProcess::WithEventLoop);
- if (buildProc.result() != QtcProcess::FinishedWithSuccess)
+ buildProc.runBlocking(EventLoopMode::On);
+ if (buildProc.result() != ProcessResult::FinishedWithSuccess)
reportWarningOrError(buildProc.exitMessage(), Task::Error);
}
@@ -600,7 +586,7 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::parseDeployErrors(
void AndroidDeployQtStep::reportWarningOrError(const QString &message, Task::TaskType type)
{
- qCDebug(deployStepLog) << message;
+ qCDebug(deployStepLog).noquote() << message;
emit addOutput(message, OutputFormat::ErrorMessage);
TaskHub::addTask(DeploymentTask(type, message));
}
diff --git a/src/plugins/android/androiddeployqtstep.h b/src/plugins/android/androiddeployqtstep.h
index 0e0f1c3054e..26c6af58aae 100644
--- a/src/plugins/android/androiddeployqtstep.h
+++ b/src/plugins/android/androiddeployqtstep.h
@@ -32,8 +32,10 @@
#include <projectexplorer/abstractprocessstep.h>
#include <qtsupport/baseqtversion.h>
+#include <utils/commandline.h>
#include <utils/environment.h>
-#include <utils/qtcprocess.h>
+
+namespace Utils { class QtcProcess; }
namespace Android {
namespace Internal {
@@ -110,7 +112,6 @@ private:
Utils::FilePath m_command;
Utils::FilePath m_workingDirectory;
Utils::Environment m_environment;
- Utils::QtcProcess *m_process = nullptr;
AndroidDeviceInfo m_deviceInfo;
};
diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp
index 1839d16f562..037049a95a8 100644
--- a/src/plugins/android/androiddevice.cpp
+++ b/src/plugins/android/androiddevice.cpp
@@ -38,6 +38,7 @@
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/devicesupport/idevicewidget.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -58,6 +59,7 @@
#include <utils/qtcprocess.h>
using namespace ProjectExplorer;
+using namespace Utils;
namespace {
static Q_LOGGING_CATEGORY(androidDeviceLog, "qtc.android.androiddevice", QtWarningMsg)
@@ -66,6 +68,10 @@ static Q_LOGGING_CATEGORY(androidDeviceLog, "qtc.android.androiddevice", QtWarni
namespace Android {
namespace Internal {
+static constexpr char ipRegexStr[] = "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})";
+static const QRegularExpression ipRegex = QRegularExpression(ipRegexStr);
+static constexpr char wifiDevicePort[] = "5555";
+
class AndroidDeviceWidget : public IDeviceWidget
{
public:
@@ -73,7 +79,9 @@ public:
void updateDeviceFromUi() final {}
static QString dialogTitle();
+ static bool messageDialog(const QString &msg, QMessageBox::Icon icon, QWidget *parent = nullptr);
static bool criticalDialog(const QString &error, QWidget *parent = nullptr);
+ static bool infoDialog(const QString &msg, QWidget *parent = nullptr);
static bool questionDialog(const QString &question, QWidget *parent = nullptr);
};
@@ -116,7 +124,7 @@ AndroidDeviceWidget::AndroidDeviceWidget(const IDevice::Ptr &device)
formLayout->addRow(AndroidDevice::tr("Android target flavor:"), new QLabel(targetName));
formLayout->addRow(AndroidDevice::tr("SD card size:"), new QLabel(dev->sdcardSize()));
formLayout->addRow(AndroidDevice::tr("Skin type:"), new QLabel(dev->skinName()));
- const QString openGlStatus = dev->openGlStatusString();
+ const QString openGlStatus = dev->openGLStatus();
formLayout->addRow(AndroidDevice::tr("OpenGL status:"), new QLabel(openGlStatus));
}
}
@@ -126,17 +134,27 @@ QString AndroidDeviceWidget::dialogTitle()
return AndroidDevice::tr("Android Device Manager");
}
-bool AndroidDeviceWidget::criticalDialog(const QString &error, QWidget *parent)
+bool AndroidDeviceWidget::messageDialog(const QString &msg, QMessageBox::Icon icon, QWidget *parent)
{
- qCDebug(androidDeviceLog) << error;
+ qCDebug(androidDeviceLog) << msg;
QMessageBox box(parent ? parent : Core::ICore::dialogParent());
box.QDialog::setWindowTitle(dialogTitle());
- box.setText(error);
- box.setIcon(QMessageBox::Critical);
+ box.setText(msg);
+ box.setIcon(icon);
box.setWindowFlag(Qt::WindowTitleHint);
return box.exec();
}
+bool AndroidDeviceWidget::criticalDialog(const QString &error, QWidget *parent)
+{
+ return messageDialog(error, QMessageBox::Critical, parent);
+}
+
+bool AndroidDeviceWidget::infoDialog(const QString &message, QWidget *parent)
+{
+ return messageDialog(message, QMessageBox::Information, parent);
+}
+
bool AndroidDeviceWidget::questionDialog(const QString &question, QWidget *parent)
{
QMessageBox box(parent ? parent : Core::ICore::dialogParent());
@@ -160,26 +178,26 @@ AndroidDevice::AndroidDevice()
setDefaultDisplayName(tr("Run on Android"));
setDisplayType(tr("Android"));
setMachineType(IDevice::Hardware);
- setOsType(Utils::OsTypeOtherUnix);
- setDeviceState(DeviceConnected);
+ setOsType(OsType::OsTypeOtherUnix);
+ setDeviceState(DeviceDisconnected);
addDeviceAction({tr("Refresh"), [](const IDevice::Ptr &device, QWidget *parent) {
Q_UNUSED(parent)
AndroidDeviceManager::instance()->updateDeviceState(device);
}});
-
- addEmulatorActionsIfNotFound();
}
-void AndroidDevice::addEmulatorActionsIfNotFound()
+void AndroidDevice::addActionsIfNotFound()
{
static const QString startAvdAction = tr("Start AVD");
static const QString eraseAvdAction = tr("Erase AVD");
static const QString avdArgumentsAction = tr("AVD Arguments");
+ static const QString setupWifi = tr("Setup Wi-Fi");
bool hasStartAction = false;
bool hasEraseAction = false;
bool hasAvdArgumentsAction = false;
+ bool hasSetupWifi = false;
for (const DeviceAction &item : deviceActions()) {
if (item.display == startAvdAction)
@@ -188,6 +206,8 @@ void AndroidDevice::addEmulatorActionsIfNotFound()
hasEraseAction = true;
else if (item.display == avdArgumentsAction)
hasAvdArgumentsAction = true;
+ else if (item.display == setupWifi)
+ hasSetupWifi = true;
}
if (machineType() == Emulator) {
@@ -209,15 +229,22 @@ void AndroidDevice::addEmulatorActionsIfNotFound()
AndroidDeviceManager::instance()->setEmulatorArguments(parent);
}});
}
+ } else if (machineType() == Hardware && !ipRegex.match(id().toString()).hasMatch()) {
+ if (!hasSetupWifi) {
+ addDeviceAction({setupWifi, [](const IDevice::Ptr &device, QWidget *parent) {
+ AndroidDeviceManager::instance()->setupWifiForDevice(device, parent);
+ }});
+ }
}
}
void AndroidDevice::fromMap(const QVariantMap &map)
{
IDevice::fromMap(map);
- // Add Actions for Emulator is not added already.
+ initAvdSettings();
+ // Add Actions for Emulator and hardware if not added already.
// This is needed because actions for Emulators and physical devices are not the same.
- addEmulatorActionsIfNotFound();
+ addActionsIfNotFound();
}
IDevice::Ptr AndroidDevice::create()
@@ -229,47 +256,33 @@ AndroidDeviceInfo AndroidDevice::androidDeviceInfoFromIDevice(const IDevice *dev
{
AndroidDeviceInfo info;
info.state = dev->deviceState();
- info.avdname = dev->extraData(Constants::AndroidAvdName).toString();
+ info.avdName = dev->extraData(Constants::AndroidAvdName).toString();
info.serialNumber = dev->extraData(Constants::AndroidSerialNumber).toString();
info.cpuAbi = dev->extraData(Constants::AndroidCpuAbi).toStringList();
- info.avdTarget = dev->extraData(Constants::AndroidAvdTarget).toString();
- info.avdDevice = dev->extraData(Constants::AndroidAvdDevice).toString();
- info.avdSkin = dev->extraData(Constants::AndroidAvdSkin).toString();
- info.avdSdcardSize = dev->extraData(Constants::AndroidAvdSdcard).toString();
+ const QString avdPath = dev->extraData(Constants::AndroidAvdPath).toString();
+ info.avdPath = FilePath::fromUserInput(avdPath);
info.sdk = dev->extraData(Constants::AndroidSdk).toInt();
info.type = dev->machineType();
return info;
}
-void AndroidDevice::setAndroidDeviceInfoExtras(IDevice *dev, const AndroidDeviceInfo &info)
-{
- dev->setExtraData(Constants::AndroidAvdName, info.avdname);
- dev->setExtraData(Constants::AndroidSerialNumber, info.serialNumber);
- dev->setExtraData(Constants::AndroidCpuAbi, info.cpuAbi);
- dev->setExtraData(Constants::AndroidAvdTarget, info.avdTarget);
- dev->setExtraData(Constants::AndroidAvdDevice, info.avdDevice);
- dev->setExtraData(Constants::AndroidAvdSkin, info.avdSkin);
- dev->setExtraData(Constants::AndroidAvdSdcard, info.avdSdcardSize);
- dev->setExtraData(Constants::AndroidSdk, info.sdk);
-}
-
QString AndroidDevice::displayNameFromInfo(const AndroidDeviceInfo &info)
{
return info.type == IDevice::Hardware
? AndroidConfigurations::currentConfig().getProductModel(info.serialNumber)
- : info.avdname;
+ : info.avdName;
}
-Utils::Id AndroidDevice::idFromDeviceInfo(const AndroidDeviceInfo &info)
+Id AndroidDevice::idFromDeviceInfo(const AndroidDeviceInfo &info)
{
- const QString id = (info.type == IDevice::Hardware ? info.serialNumber : info.avdname);
- return Utils::Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + id);
+ const QString id = (info.type == IDevice::Hardware ? info.serialNumber : info.avdName);
+ return Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + id);
}
-Utils::Id AndroidDevice::idFromAvdInfo(const CreateAvdInfo &info)
+Id AndroidDevice::idFromAvdInfo(const CreateAvdInfo &info)
{
- return Utils::Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + info.name);
+ return Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + info.name);
}
QStringList AndroidDevice::supportedAbis() const
@@ -342,6 +355,17 @@ int AndroidDevice::sdkLevel() const
return extraData(Constants::AndroidSdk).toInt();
}
+FilePath AndroidDevice::avdPath() const
+{
+ return FilePath::fromUserInput(extraData(Constants::AndroidAvdPath).toString());
+}
+
+void AndroidDevice::setAvdPath(const FilePath &path)
+{
+ setExtraData(Constants::AndroidAvdPath, path.toUserOutput());
+ initAvdSettings();
+}
+
QString AndroidDevice::androidVersion() const
{
return AndroidManager::androidNameForApiLevel(sdkLevel());
@@ -350,46 +374,32 @@ QString AndroidDevice::androidVersion() const
QString AndroidDevice::deviceTypeName() const
{
if (machineType() == Emulator)
- return tr("Emulator for ") + extraData(Constants::AndroidAvdDevice).toString();
+ return tr("Emulator for \"%1\"").arg(avdSettings()->value("hw.device.name").toString());
return tr("Physical device");
}
QString AndroidDevice::skinName() const
{
- const QString skin = extraData(Constants::AndroidAvdSkin).toString();
+ const QString skin = avdSettings()->value("skin.name").toString();
return skin.isEmpty() ? tr("None") : skin;
}
QString AndroidDevice::androidTargetName() const
{
- const QString target = extraData(Constants::AndroidAvdTarget).toString();
+ const QString target = avdSettings()->value("tag.display").toString();
return target.isEmpty() ? tr("Unknown") : target;
}
QString AndroidDevice::sdcardSize() const
{
- const QString size = extraData(Constants::AndroidAvdSdcard).toString();
+ const QString size = avdSettings()->value("sdcard.size").toString();
return size.isEmpty() ? tr("Unknown") : size;
}
-AndroidConfig::OpenGl AndroidDevice::openGlStatus() const
+QString AndroidDevice::openGLStatus() const
{
- return AndroidConfigurations::currentConfig().getOpenGLEnabled(displayName());
-}
-
-QString AndroidDevice::openGlStatusString() const
-{
- const AndroidConfig::OpenGl glStatus = AndroidConfigurations::currentConfig()
- .getOpenGLEnabled(displayName());
- switch (glStatus) {
- case (AndroidConfig::OpenGl::Enabled):
- return tr("Enabled");
- case (AndroidConfig::OpenGl::Disabled):
- return tr("Disabled");
- case (AndroidConfig::OpenGl::Unknown):
- return tr("Unknown");
- }
- return tr("Unknown");
+ const QString openGL = avdSettings()->value("hw.gpu.enabled").toString();
+ return openGL.isEmpty() ? tr("Unknown") : openGL;
}
IDevice::DeviceInfo AndroidDevice::deviceInformation() const
@@ -415,11 +425,22 @@ DeviceProcessSignalOperation::Ptr AndroidDevice::signalOperation() const
QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
{
QUrl url;
- url.setScheme(Utils::urlTcpScheme());
+ url.setScheme(urlTcpScheme());
url.setHost("localhost");
return url;
}
+QSettings *AndroidDevice::avdSettings() const
+{
+ return m_avdSettings.get();
+}
+
+void AndroidDevice::initAvdSettings()
+{
+ const FilePath configPath = avdPath().resolvePath(QStringLiteral("config.ini"));
+ m_avdSettings.reset(new QSettings(configPath.toUserOutput(), QSettings::IniFormat));
+}
+
void AndroidDeviceManager::updateAvdsList()
{
if (!m_avdsFutureWatcher.isRunning() && m_androidConfig.adbToolPath().exists())
@@ -444,13 +465,11 @@ void AndroidDeviceManager::updateDeviceState(const ProjectExplorer::IDevice::Con
const AndroidDevice *dev = static_cast<const AndroidDevice *>(device.data());
const QString serial = dev->serialNumber();
DeviceManager *const devMgr = DeviceManager::instance();
- const Utils::Id id = dev->id();
- if (serial.isEmpty() && dev->machineType() == IDevice::Emulator) {
+ const Id id = dev->id();
+ if (!serial.isEmpty())
+ devMgr->setDeviceState(id, getDeviceState(serial, dev->machineType()));
+ else if (dev->machineType() == IDevice::Emulator)
devMgr->setDeviceState(id, IDevice::DeviceConnected);
- return;
- }
-
- devMgr->setDeviceState(id, getDeviceState(serial, dev->machineType()));
}
void AndroidDeviceManager::startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent)
@@ -459,7 +478,7 @@ void AndroidDeviceManager::startAvd(const ProjectExplorer::IDevice::Ptr &device,
const AndroidDevice *androidDev = static_cast<const AndroidDevice *>(device.data());
const QString name = androidDev->avdName();
qCDebug(androidDeviceLog, "Starting Android AVD id \"%s\".", qPrintable(name));
- Utils::runAsync([this, name, device]() {
+ runAsync([this, name, device]() {
const QString serialNumber = m_avdManager.startAvd(name);
// Mark the AVD as ReadyToUse once we know it's started
if (!serialNumber.isEmpty()) {
@@ -484,7 +503,7 @@ void AndroidDeviceManager::eraseAvd(const IDevice::Ptr &device, QWidget *parent)
return;
qCDebug(androidDeviceLog) << QString("Erasing Android AVD \"%1\" from the system.").arg(name);
- m_removeAvdFutureWatcher.setFuture(Utils::runAsync([this, name, device]() {
+ m_removeAvdFutureWatcher.setFuture(runAsync([this, name, device]() {
QPair<IDevice::ConstPtr, bool> pair;
pair.first = device;
pair.second = false;
@@ -494,6 +513,66 @@ void AndroidDeviceManager::eraseAvd(const IDevice::Ptr &device, QWidget *parent)
}));
}
+void AndroidDeviceManager::setupWifiForDevice(const IDevice::Ptr &device, QWidget *parent)
+{
+ if (device->deviceState() != IDevice::DeviceReadyToUse) {
+ AndroidDeviceWidget::infoDialog(
+ AndroidDevice::tr("The device has to be connected with ADB debugging "
+ "enabled to use this feature."), parent);
+ return;
+ }
+
+ const auto androidDev = static_cast<const AndroidDevice *>(device.data());
+ const QStringList adbSelector = AndroidDeviceInfo::adbSelector(androidDev->serialNumber());
+ // prepare port
+ QStringList args = adbSelector;
+ args.append({"tcpip", wifiDevicePort});
+ const SdkToolResult result = AndroidManager::runAdbCommand(args);
+ if (!result.success()) {
+ AndroidDeviceWidget::criticalDialog(
+ AndroidDevice::tr("Opening connection port %1 failed.").arg(wifiDevicePort),
+ parent);
+ return;
+ }
+
+ QTimer::singleShot(2000, parent, [adbSelector, &parent]() {
+ // Get device IP address
+ QStringList args = adbSelector;
+ args.append({"shell", "ip", "route"});
+ const SdkToolResult ipRes = AndroidManager::runAdbCommand(args);
+ if (!ipRes.success()) {
+ AndroidDeviceWidget::criticalDialog(
+ AndroidDevice::tr("Retrieving the device IP address failed."), parent);
+ return;
+ }
+
+ // Expected output from "ip route" is:
+ // 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.190
+ // where the ip of interest is at the end of the line
+ const QStringList ipParts = ipRes.stdOut().split(" ");
+ QString ip;
+ if (!ipParts.isEmpty()) {
+ ip = ipParts.last();
+ }
+ if (!ipRegex.match(ipParts.last()).hasMatch()) {
+ AndroidDeviceWidget::criticalDialog(
+ AndroidDevice::tr("The retrieved IP address is invalid."), parent);
+ return;
+ }
+
+ // Connect to device
+ args = adbSelector;
+ args.append({"connect", QString("%1:%2").arg(ip).arg(wifiDevicePort)});
+ const SdkToolResult connectRes = AndroidManager::runAdbCommand(args);
+ if (!connectRes.success()) {
+ AndroidDeviceWidget::criticalDialog(
+ AndroidDevice::tr("Connecting to to the device IP \"%1\" failed.").arg(ip),
+ parent);
+ return;
+ }
+ });
+}
+
void AndroidDeviceManager::handleAvdRemoved()
{
const QPair<IDevice::ConstPtr, bool> result = m_removeAvdFutureWatcher.result();
@@ -525,7 +604,7 @@ void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
dialog.setLabelText(AndroidDevice::tr("Emulator command-line startup options "
"(<a href=\"%1\">Help Web Page</a>):")
.arg(helpUrl));
- dialog.setTextValue(m_androidConfig.emulatorArgs().join(' '));
+ dialog.setTextValue(m_androidConfig.emulatorArgs());
if (auto label = dialog.findChild<QLabel*>()) {
label->setOpenExternalLinks(true);
@@ -535,7 +614,7 @@ void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
if (dialog.exec() != QDialog::Accepted)
return;
- m_androidConfig.setEmulatorArgs(Utils::ProcessArgs::splitArgs(dialog.textValue()));
+ m_androidConfig.setEmulatorArgs(dialog.textValue());
}
QString AndroidDeviceManager::getRunningAvdsSerialNumber(const QString &name) const
@@ -563,24 +642,23 @@ void AndroidDeviceManager::setupDevicesWatcher()
}
if (!m_adbDeviceWatcherProcess)
- m_adbDeviceWatcherProcess.reset(new Utils::QtcProcess(this));
+ m_adbDeviceWatcherProcess.reset(new QtcProcess(this));
if (m_adbDeviceWatcherProcess->isRunning()) {
qCDebug(androidDeviceLog) << "ADB device watcher is already running.";
return;
}
- connect(m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::finished, this,
- []() { qCDebug(androidDeviceLog) << "ADB device watcher finished."; });
-
- connect(m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::errorOccurred, this,
- [this](QProcess::ProcessError) {
- qCDebug(androidDeviceLog) << "ADB device watcher encountered an error:"
- << m_adbDeviceWatcherProcess->errorString();
- if (!m_adbDeviceWatcherProcess->isRunning()) {
- qCDebug(androidDeviceLog) << "Restarting the ADB device watcher now.";
- QTimer::singleShot(0, m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::start);
+ connect(m_adbDeviceWatcherProcess.get(), &QtcProcess::done, this, [this] {
+ if (m_adbDeviceWatcherProcess->error() != QProcess::UnknownError) {
+ qCDebug(androidDeviceLog) << "ADB device watcher encountered an error:"
+ << m_adbDeviceWatcherProcess->errorString();
+ if (!m_adbDeviceWatcherProcess->isRunning()) {
+ qCDebug(androidDeviceLog) << "Restarting the ADB device watcher now.";
+ QTimer::singleShot(0, m_adbDeviceWatcherProcess.get(), &QtcProcess::start);
+ }
}
+ qCDebug(androidDeviceLog) << "ADB device watcher finished.";
});
m_adbDeviceWatcherProcess->setStdErrLineCallback([](const QString &error) {
@@ -589,13 +667,10 @@ void AndroidDeviceManager::setupDevicesWatcher()
HandleDevicesListChange(output);
});
- const Utils::CommandLine command = Utils::CommandLine(m_androidConfig.adbToolPath(),
- {"track-devices"});
+ const CommandLine command = CommandLine(m_androidConfig.adbToolPath(), {"track-devices"});
m_adbDeviceWatcherProcess->setCommand(command);
m_adbDeviceWatcherProcess->setEnvironment(AndroidConfigurations::toolsEnvironment(m_androidConfig));
m_adbDeviceWatcherProcess->start();
- qCDebug(androidDeviceLog).noquote() << "ADB device watcher started:"
- << command.toUserOutput();
// Setup AVD filesystem watcher to listen for changes when an avd is created/deleted,
// or started/stopped
@@ -606,7 +681,7 @@ void AndroidDeviceManager::setupDevicesWatcher()
avdEnvVar = qEnvironmentVariable("HOME");
avdEnvVar.append("/.android/avd");
}
- const Utils::FilePath avdPath = Utils::FilePath::fromUserInput(avdEnvVar);
+ const FilePath avdPath = FilePath::fromUserInput(avdEnvVar);
m_avdFileSystemWatcher.addPath(avdPath.toString());
connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
this, &AndroidDeviceManager::HandleAvdsListChange);
@@ -623,38 +698,41 @@ void AndroidDeviceManager::HandleAvdsListChange()
{
DeviceManager *const devMgr = DeviceManager::instance();
- QVector<IDevice::ConstPtr> existingAvds;
+ QVector<Id> existingAvds;
for (int i = 0; i < devMgr->deviceCount(); ++i) {
const IDevice::ConstPtr dev = devMgr->deviceAt(i);
const bool isEmulator = dev->machineType() == IDevice::Emulator;
if (isEmulator && dev->type() == Constants::ANDROID_DEVICE_TYPE)
- existingAvds.append(dev);
+ existingAvds.append(dev->id());
}
- QVector<IDevice::ConstPtr> connectedDevs;
+ QVector<Id> connectedDevs;
for (const AndroidDeviceInfo &item : m_avdsFutureWatcher.result()) {
- const Utils::Id deviceId = AndroidDevice::idFromDeviceInfo(item);
+ const Id deviceId = AndroidDevice::idFromDeviceInfo(item);
const QString displayName = AndroidDevice::displayNameFromInfo(item);
IDevice::ConstPtr dev = devMgr->find(deviceId);
if (!dev.isNull()) {
const auto androidDev = static_cast<const AndroidDevice *>(dev.data());
- // DeviceManager doens't seem to hav a way to directly update the name, if the name
+ // DeviceManager doens't seem to have a way to directly update the name, if the name
// of the device has changed, remove it and register it again with the new name.
// Also account for the case of an AVD registered through old QC which might have
- // invalid data by checking the sdcard size value.
- if (dev->displayName() != displayName
- || androidDev->sdcardSize() == AndroidDevice::tr("Unknown")) {
+ // invalid data by checking if the avdPath is not empty.
+ if (dev->displayName() != displayName || androidDev->avdPath().toString().isEmpty()) {
devMgr->removeDevice(dev->id());
} else {
// Find the state of the AVD retrieved from the AVD watcher
- const QString serial = getRunningAvdsSerialNumber(item.avdname);
- const IDevice::DeviceState state = getDeviceState(serial, IDevice::Emulator);
- if (dev->deviceState() != state) {
- devMgr->setDeviceState(dev->id(), state);
- qCDebug(androidDeviceLog, "Device id \"%s\" changed its state.",
- dev->id().toString().toUtf8().data());
+ const QString serial = getRunningAvdsSerialNumber(item.avdName);
+ if (!serial.isEmpty()) {
+ const IDevice::DeviceState state = getDeviceState(serial, IDevice::Emulator);
+ if (dev->deviceState() != state) {
+ devMgr->setDeviceState(dev->id(), state);
+ qCDebug(androidDeviceLog, "Device id \"%s\" changed its state.",
+ dev->id().toString().toUtf8().data());
+ }
+ } else {
+ devMgr->setDeviceState(dev->id(), IDevice::DeviceConnected);
}
- connectedDevs.append(dev);
+ connectedDevs.append(dev->id());
continue;
}
}
@@ -664,31 +742,30 @@ void AndroidDeviceManager::HandleAvdsListChange()
newDev->setDisplayName(displayName);
newDev->setMachineType(item.type);
newDev->setDeviceState(item.state);
- AndroidDevice::setAndroidDeviceInfoExtras(newDev, item);
+
+ newDev->setExtraData(Constants::AndroidAvdName, item.avdName);
+ newDev->setExtraData(Constants::AndroidSerialNumber, item.serialNumber);
+ newDev->setExtraData(Constants::AndroidCpuAbi, item.cpuAbi);
+ newDev->setExtraData(Constants::AndroidSdk, item.sdk);
+ newDev->setAvdPath(item.avdPath);
+
qCDebug(androidDeviceLog, "Registering new Android device id \"%s\".",
newDev->id().toString().toUtf8().data());
const IDevice::ConstPtr constNewDev = IDevice::ConstPtr(newDev);
devMgr->addDevice(IDevice::ConstPtr(constNewDev));
- connectedDevs.append(constNewDev);
+ connectedDevs.append(constNewDev->id());
+ }
- // Set devices no longer connected to disconnected state.
- for (const IDevice::ConstPtr &dev : existingAvds) {
- if (!connectedDevs.contains(dev)) {
+ // Set devices no longer connected to disconnected state.
+ for (const Id &id : existingAvds) {
+ if (!connectedDevs.contains(id)) {
qCDebug(androidDeviceLog, "Removing AVD id \"%s\" because it no longer exists.",
- dev->id().toString().toUtf8().data());
- devMgr->removeDevice(dev->id());
- }
+ id.toString().toUtf8().data());
+ devMgr->removeDevice(id);
}
}
}
-void AndroidDeviceManager::shutdownDevicesWatcher()
-{
- m_avdsFutureWatcher.waitForFinished();
- m_removeAvdFutureWatcher.waitForFinished();
- m_adbDeviceWatcherProcess.reset();
-}
-
void AndroidDeviceManager::HandleDevicesListChange(const QString &serialNumber)
{
DeviceManager *const devMgr = DeviceManager::instance();
@@ -722,16 +799,15 @@ void AndroidDeviceManager::HandleDevicesListChange(const QString &serialNumber)
if (isEmulator) {
const QString avdName = emulatorName(serial);
- const Utils::Id avdId = Utils::Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + avdName);
+ const Id avdId = Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + avdName);
devMgr->setDeviceState(avdId, state);
} else {
- const Utils::Id id = Utils::Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + serial);
+ const Id id = Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + serial);
QString displayName = AndroidConfigurations::currentConfig().getProductModel(serial);
// Check if the device is connected via WiFi. A sample serial of such devices can be
// like: "192.168.1.190:5555"
- const QRegularExpression wifiSerialRegExp(
- QLatin1String("(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}):(\\d{1,5})"));
- if (wifiSerialRegExp.match(serial).hasMatch())
+ static const auto ipRegex = QRegularExpression(ipRegexStr + QStringLiteral(":(\\d{1,5})"));
+ if (ipRegex.match(serial).hasMatch())
displayName += QLatin1String(" (WiFi)");
if (IDevice::ConstPtr dev = devMgr->find(id)) {
@@ -759,10 +835,11 @@ void AndroidDeviceManager::HandleDevicesListChange(const QString &serialNumber)
}
}
+static AndroidDeviceManager *s_instance = nullptr;
+
AndroidDeviceManager *AndroidDeviceManager::instance()
{
- static AndroidDeviceManager obj;
- return &obj;
+ return s_instance;
}
AndroidDeviceManager::AndroidDeviceManager(QObject *parent)
@@ -772,6 +849,16 @@ AndroidDeviceManager::AndroidDeviceManager(QObject *parent)
{
connect(&m_removeAvdFutureWatcher, &QFutureWatcherBase::finished,
this, &AndroidDeviceManager::handleAvdRemoved);
+ QTC_ASSERT(!s_instance, return);
+ s_instance = this;
+}
+
+AndroidDeviceManager::~AndroidDeviceManager()
+{
+ m_avdsFutureWatcher.waitForFinished();
+ m_removeAvdFutureWatcher.waitForFinished();
+ QTC_ASSERT(s_instance == this, return);
+ s_instance = nullptr;
}
// Factory
diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h
index 9800098fb16..b3390a9d65e 100644
--- a/src/plugins/android/androiddevice.h
+++ b/src/plugins/android/androiddevice.h
@@ -33,10 +33,11 @@
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/idevicefactory.h>
-#include <utils/qtcprocess.h>
-
#include <QFutureWatcher>
#include <QFileSystemWatcher>
+#include <QSettings>
+
+namespace Utils { class QtcProcess; }
namespace Android {
namespace Internal {
@@ -50,7 +51,6 @@ public:
static IDevice::Ptr create();
static AndroidDeviceInfo androidDeviceInfoFromIDevice(const IDevice *dev);
- static void setAndroidDeviceInfoExtras(IDevice *dev, const AndroidDeviceInfo &info);
static QString displayNameFromInfo(const AndroidDeviceInfo &info);
static Utils::Id idFromDeviceInfo(const AndroidDeviceInfo &info);
@@ -66,25 +66,33 @@ public:
QString avdName() const;
int sdkLevel() const;
+ Utils::FilePath avdPath() const;
+ void setAvdPath(const Utils::FilePath &path);
+
QString deviceTypeName() const;
QString androidVersion() const;
+
+ // AVD specific
QString skinName() const;
QString androidTargetName() const;
QString sdcardSize() const;
- QString openGlStatusString() const;
- // TODO: remove not used
- AndroidConfig::OpenGl openGlStatus() const;
+ QString openGLStatus() const;
protected:
void fromMap(const QVariantMap &map) final;
private:
- void addEmulatorActionsIfNotFound();
+ void addActionsIfNotFound();
ProjectExplorer::IDevice::DeviceInfo deviceInformation() const override;
ProjectExplorer::IDeviceWidget *createWidget() override;
bool canAutoDetectPorts() const override;
ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override;
QUrl toolControlChannel(const ControlChannelHint &) const override;
+
+ QSettings *avdSettings() const;
+ void initAvdSettings();
+
+ std::unique_ptr<QSettings> m_avdSettings;
};
class AndroidDeviceFactory final : public ProjectExplorer::IDeviceFactory
@@ -98,19 +106,16 @@ private:
class AndroidDeviceManager : public QObject
{
- Q_OBJECT
-
public:
static AndroidDeviceManager *instance();
void setupDevicesWatcher();
- void shutdownDevicesWatcher();
-
void updateAvdsList();
IDevice::DeviceState getDeviceState(const QString &serial, IDevice::MachineType type) const;
void updateDeviceState(const ProjectExplorer::IDevice::ConstPtr &device);
void startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr);
void eraseAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr);
+ void setupWifiForDevice(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr);
void setEmulatorArguments(QWidget *parent = nullptr);
@@ -118,6 +123,7 @@ public:
private:
AndroidDeviceManager(QObject *parent = nullptr);
+ ~AndroidDeviceManager();
void HandleDevicesListChange(const QString &serialNumber);
void HandleAvdsListChange();
void handleAvdRemoved();
@@ -130,6 +136,8 @@ private:
std::unique_ptr<Utils::QtcProcess> m_adbDeviceWatcherProcess;
AndroidConfig &m_androidConfig;
AndroidAvdManager m_avdManager;
+
+ friend class AndroidPluginPrivate;
};
} // namespace Internal
diff --git a/src/plugins/android/androiddeviceinfo.cpp b/src/plugins/android/androiddeviceinfo.cpp
index 752a710c14d..fb2223c0675 100644
--- a/src/plugins/android/androiddeviceinfo.cpp
+++ b/src/plugins/android/androiddeviceinfo.cpp
@@ -46,25 +46,25 @@ bool AndroidDeviceInfo::operator<(const AndroidDeviceInfo &other) const
return type == ProjectExplorer::IDevice::Hardware;
if (sdk != other.sdk)
return sdk < other.sdk;
- if (avdname != other.avdname)
- return avdname < other.avdname;
+ if (avdName != other.avdName)
+ return avdName < other.avdName;
return serialNumber < other.serialNumber;
}
bool AndroidDeviceInfo::operator==(const AndroidDeviceInfo &other) const
{
- return serialNumber == other.serialNumber && avdname == other.avdname && cpuAbi == other.cpuAbi
- && avdTarget == other.avdTarget && avdDevice == other.avdDevice
- && avdSkin == other.avdSkin && avdSdcardSize == other.avdSdcardSize && sdk == other.sdk
- && state == other.state && type == other.type;
+ return serialNumber == other.serialNumber && avdName == other.avdName
+ && avdPath == other.avdPath && cpuAbi == other.cpuAbi
+ && sdk == other.sdk && state == other.state && type == other.type;
}
QDebug &operator<<(QDebug &stream, const AndroidDeviceInfo &device)
{
- stream << "Type:" << (device.type == ProjectExplorer::IDevice::Emulator ? "Emulator" : "Device")
+ stream.nospace()
+ << "Type:" << (device.type == ProjectExplorer::IDevice::Emulator ? "Emulator" : "Device")
<< ", ABI:" << device.cpuAbi << ", Serial:" << device.serialNumber
- << ", Name:" << device.avdname << ", API:" << device.sdk
+ << ", Name:" << device.avdName << ", API:" << device.sdk
<< ", Authorised:" << (device.state == IDevice::DeviceReadyToUse);
return stream;
}
diff --git a/src/plugins/android/androiddeviceinfo.h b/src/plugins/android/androiddeviceinfo.h
index b43cbc63426..8b6e4c0e921 100644
--- a/src/plugins/android/androiddeviceinfo.h
+++ b/src/plugins/android/androiddeviceinfo.h
@@ -40,19 +40,16 @@ class AndroidDeviceInfo
{
public:
QString serialNumber;
- QString avdname;
+ QString avdName;
QStringList cpuAbi;
- QString avdTarget;
- QString avdDevice;
- QString avdSkin;
- QString avdSdcardSize;
int sdk = -1;
IDevice::DeviceState state = IDevice::DeviceDisconnected;
IDevice::MachineType type = IDevice::Emulator;
+ Utils::FilePath avdPath;
static QStringList adbSelector(const QString &serialNumber);
- bool isValid() const { return !serialNumber.isEmpty() || !avdname.isEmpty(); }
+ bool isValid() const { return !serialNumber.isEmpty() || !avdName.isEmpty(); }
bool operator<(const AndroidDeviceInfo &other) const;
bool operator==(const AndroidDeviceInfo &other) const; // should be = default with C++20
bool operator!=(const AndroidDeviceInfo &other) const { return !(*this == other); }
diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp
index 3fadbf6f9be..c31b996ecb6 100644
--- a/src/plugins/android/androidmanager.cpp
+++ b/src/plugins/android/androidmanager.cpp
@@ -416,9 +416,12 @@ QString AndroidManager::apkDevicePreferredAbi(const Target *target)
{
const FilePath libsPath = androidBuildDirectory(target).pathAppended("libs");
if (!libsPath.exists()) {
- if (const ProjectNode *node = currentProjectNode(target))
- return preferredAbi(node->data(Android::Constants::AndroidAbis).toStringList(),
- target);
+ if (const ProjectNode *node = currentProjectNode(target)) {
+ const QString abi = preferredAbi(
+ node->data(Android::Constants::AndroidAbis).toStringList(), target);
+ if (abi.isEmpty())
+ return node->data(Android::Constants::AndroidAbi).toString();
+ }
}
QStringList apkAbis;
const FilePaths libsPaths = libsPath.dirEntries(QDir::Dirs | QDir::NoDotAndDotDot);
@@ -459,66 +462,70 @@ int AndroidManager::defaultMinimumSDK(const QtSupport::QtVersion *qtVersion)
QString AndroidManager::androidNameForApiLevel(int x)
{
switch (x) {
+ case 2:
+ return QLatin1String("Android 1.1");
+ case 3:
+ return QLatin1String("Android 1.5 (Cupcake)");
case 4:
- return QLatin1String("Android 1.6");
+ return QLatin1String("Android 1.6 (Donut)");
case 5:
- return QLatin1String("Android 2.0");
+ return QLatin1String("Android 2.0 (Eclair)");
case 6:
- return QLatin1String("Android 2.0.1");
+ return QLatin1String("Android 2.0.1 (Eclair)");
case 7:
- return QLatin1String("Android 2.1.x");
+ return QLatin1String("Android 2.1 (Eclair)");
case 8:
- return QLatin1String("Android 2.2.x");
+ return QLatin1String("Android 2.2 (Froyo)");
case 9:
- return QLatin1String("Android 2.3, 2.3.1, 2.3.2");
+ return QLatin1String("Android 2.3 (Gingerbread)");
case 10:
- return QLatin1String("Android 2.3.3, 2.3.4");
+ return QLatin1String("Android 2.3.3 (Gingerbread)");
case 11:
- return QLatin1String("Android 3.0.x");
+ return QLatin1String("Android 3.0 (Honeycomb)");
case 12:
- return QLatin1String("Android 3.1.x");
+ return QLatin1String("Android 3.1 (Honeycomb)");
case 13:
- return QLatin1String("Android 3.2");
+ return QLatin1String("Android 3.2 (Honeycomb)");
case 14:
- return QLatin1String("Android 4.0, 4.0.1, 4.0.2");
+ return QLatin1String("Android 4.0 (IceCreamSandwich)");
case 15:
- return QLatin1String("Android 4.0.3, 4.0.4");
+ return QLatin1String("Android 4.0.3 (IceCreamSandwich)");
case 16:
- return QLatin1String("Android 4.1, 4.1.1");
+ return QLatin1String("Android 4.1 (Jelly Bean)");
case 17:
- return QLatin1String("Android 4.2, 4.2.2");
+ return QLatin1String("Android 4.2 (Jelly Bean)");
case 18:
- return QLatin1String("Android 4.3");
+ return QLatin1String("Android 4.3 (Jelly Bean)");
case 19:
- return QLatin1String("Android 4.4");
+ return QLatin1String("Android 4.4 (KitKat)");
case 20:
- return QLatin1String("Android 4.4W");
+ return QLatin1String("Android 4.4W (KitKat Wear)");
case 21:
- return QLatin1String("Android 5.0");
+ return QLatin1String("Android 5.0 (Lollipop)");
case 22:
- return QLatin1String("Android 5.1");
+ return QLatin1String("Android 5.1 (Lollipop)");
case 23:
- return QLatin1String("Android 6.0");
+ return QLatin1String("Android 6.0 (Marshmallow)");
case 24:
- return QLatin1String("Android 7.0");
+ return QLatin1String("Android 7.0 (Nougat)");
case 25:
- return QLatin1String("Android 7.1");
+ return QLatin1String("Android 7.1.1 (Nougat)");
case 26:
- return QLatin1String("Android 8.0");
+ return QLatin1String("Android 8.0 (Oreo)");
case 27:
- return QLatin1String("Android 8.1");
+ return QLatin1String("Android 8.1 (Oreo)");
case 28:
- return QLatin1String("Android 9");
+ return QLatin1String("Android 9.0 (Pie)");
case 29:
- return QLatin1String("Android 10");
+ return QLatin1String("Android 10.0 (Q)");
case 30:
- return QLatin1String("Android 11");
+ return QLatin1String("Android 11.0 (R)");
case 31:
- return QLatin1String("Android 12");
+ return QLatin1String("Android 12.0 (S)");
case 32:
- return QLatin1String("Android 12L");
+ return QLatin1String("Android 12L (API 32)");
case 33:
- return QLatin1String("Android 13");
+ return QLatin1String("Android Tiramisu");
default:
return tr("Unknown Android version. API Level: %1").arg(x);
}
@@ -573,7 +580,7 @@ void AndroidManager::installQASIPackage(Target *target, const FilePath &packageP
QString deviceSerialNumber = info.serialNumber;
if (info.type == IDevice::Emulator) {
- deviceSerialNumber = AndroidAvdManager().startAvd(info.avdname);
+ deviceSerialNumber = AndroidAvdManager().startAvd(info.avdName);
if (deviceSerialNumber.isEmpty())
Core::MessageManager::writeDisrupting(tr("Starting Android virtual device failed."));
}
@@ -595,8 +602,8 @@ bool AndroidManager::checkKeystorePassword(const QString &keystorePath, const QS
QtcProcess proc;
proc.setTimeoutS(10);
proc.setCommand(cmd);
- proc.runBlocking(QtcProcess::WithEventLoop);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ proc.runBlocking(EventLoopMode::On);
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool AndroidManager::checkCertificatePassword(const QString &keystorePath, const QString &keystorePasswd, const QString &alias, const QString &certificatePasswd)
@@ -612,8 +619,8 @@ bool AndroidManager::checkCertificatePassword(const QString &keystorePath, const
QtcProcess proc;
proc.setTimeoutS(10);
proc.setCommand({AndroidConfigurations::currentConfig().keytoolPath(), arguments});
- proc.runBlocking(QtcProcess::WithEventLoop);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ proc.runBlocking(EventLoopMode::On);
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool AndroidManager::checkCertificateExists(const QString &keystorePath,
@@ -626,8 +633,8 @@ bool AndroidManager::checkCertificateExists(const QString &keystorePath,
QtcProcess proc;
proc.setTimeoutS(10);
proc.setCommand({AndroidConfigurations::currentConfig().keytoolPath(), arguments});
- proc.runBlocking(QtcProcess::WithEventLoop);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ proc.runBlocking(EventLoopMode::On);
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
using GradleProperties = QMap<QByteArray, QByteArray>;
@@ -639,7 +646,8 @@ static GradleProperties readGradleProperties(const QString &path)
if (!file.open(QIODevice::ReadOnly))
return properties;
- foreach (const QByteArray &line, file.readAll().split('\n')) {
+ const QList<QByteArray> lines = file.readAll().split('\n');
+ for (const QByteArray &line : lines) {
if (line.trimmed().startsWith('#'))
continue;
@@ -781,10 +789,10 @@ SdkToolResult AndroidManager::runCommand(const CommandLine &command,
cmdProc.setWriteData(writeData);
qCDebug(androidManagerLog) << "Running command (sync):" << command.toUserOutput();
cmdProc.setCommand(command);
- cmdProc.runBlocking(QtcProcess::WithEventLoop);
- cmdResult.m_stdOut = cmdProc.stdOut().trimmed();
- cmdResult.m_stdErr = cmdProc.stdErr().trimmed();
- cmdResult.m_success = cmdProc.result() == QtcProcess::FinishedWithSuccess;
+ cmdProc.runBlocking(EventLoopMode::On);
+ cmdResult.m_stdOut = cmdProc.cleanedStdOut().trimmed();
+ cmdResult.m_stdErr = cmdProc.cleanedStdErr().trimmed();
+ cmdResult.m_success = cmdProc.result() == ProcessResult::FinishedWithSuccess;
qCDebug(androidManagerLog) << "Command finshed (sync):" << command.toUserOutput()
<< "Success:" << cmdResult.m_success
<< "Output:" << cmdProc.allRawOutput();
diff --git a/src/plugins/android/androidmanifesteditor.cpp b/src/plugins/android/androidmanifesteditor.cpp
index 5565001eadf..5146c972908 100644
--- a/src/plugins/android/androidmanifesteditor.cpp
+++ b/src/plugins/android/androidmanifesteditor.cpp
@@ -99,7 +99,8 @@ void AndroidManifestEditor::gotoLine(int line, int column, bool centerLine)
void AndroidManifestEditor::changeEditorPage(QAction *action)
{
if (!widget()->setActivePage(static_cast<AndroidManifestEditorWidget::EditorPage>(action->data().toInt()))) {
- foreach (QAction *action, m_actionGroup->actions()) {
+ const QList<QAction *> actions = m_actionGroup->actions();
+ for (QAction *action : actions) {
if (action->data().toInt() == widget()->activePage()) {
action->setChecked(true);
break;
diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp
index 58868778158..b04ce6de5e5 100644
--- a/src/plugins/android/androidmanifesteditorwidget.cpp
+++ b/src/plugins/android/androidmanifesteditorwidget.cpp
@@ -76,6 +76,8 @@
#include <QSpinBox>
#include <QTimer>
#include <QToolButton>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
#include <algorithm>
#include <limits>
@@ -1006,7 +1008,7 @@ QXmlStreamAttributes modifyXmlStreamAttributes(const QXmlStreamAttributes &input
Q_ASSERT(keys.size() == values.size());
QXmlStreamAttributes result;
result.reserve(input.size());
- foreach (const QXmlStreamAttribute &attribute, input) {
+ for (const QXmlStreamAttribute &attribute : input) {
const QString &name = attribute.qualifiedName().toString();
if (remove.contains(name))
continue;
@@ -1082,7 +1084,7 @@ void AndroidManifestEditorWidget::parseManifest(QXmlStreamReader &reader, QXmlSt
writer.writeComment(QLatin1String(" %%INSERT_FEATURES "));
if (!permissions.isEmpty()) {
- foreach (const QString &permission, permissions) {
+ for (const QString &permission : qAsConst(permissions)) {
writer.writeEmptyElement(QLatin1String("uses-permission"));
writer.writeAttribute(QLatin1String("android:name"), permission);
}
diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/android/androidpackageinstallationstep.cpp
index cd45495550e..aa43c81c5a7 100644
--- a/src/plugins/android/androidpackageinstallationstep.cpp
+++ b/src/plugins/android/androidpackageinstallationstep.cpp
@@ -147,7 +147,7 @@ void AndroidPackageInstallationStep::setupOutputFormatter(OutputFormatter *forma
void AndroidPackageInstallationStep::doRun()
{
QString error;
- foreach (const QString &dir, m_androidDirsToClean) {
+ for (const QString &dir : qAsConst(m_androidDirsToClean)) {
FilePath androidDir = FilePath::fromString(dir);
if (!dir.isEmpty() && androidDir.exists()) {
emit addOutput(tr("Removing directory %1").arg(dir), OutputFormat::NormalMessage);
diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp
index 7eb8e8c0d23..b5d19c12e7f 100644
--- a/src/plugins/android/androidplugin.cpp
+++ b/src/plugins/android/androidplugin.cpp
@@ -136,6 +136,7 @@ public:
};
AndroidBuildApkStepFactory buildApkStepFactory;
+ AndroidDeviceManager deviceManager;
};
AndroidPlugin::~AndroidPlugin()
@@ -160,12 +161,6 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa
return true;
}
-ExtensionSystem::IPlugin::ShutdownFlag AndroidPlugin::aboutToShutdown()
-{
- AndroidDeviceManager::instance()->shutdownDevicesWatcher();
- return ExtensionSystem::IPlugin::SynchronousShutdown;
-}
-
void AndroidPlugin::kitsRestored()
{
const bool qtForAndroidInstalled
@@ -199,7 +194,7 @@ void AndroidPlugin::askUserAboutAndroidSetup()
info(kSetupAndroidSetting,
tr("Would you like to configure Android options? This will ensure "
"Android kits can be usable and all essential packages are installed. "
- "To do it later, select Options > Devices > Android."),
+ "To do it later, select Edit > Preferences > Devices > Android."),
Utils::InfoBarEntry::GlobalSuppression::Enabled);
info.addCustomButton(tr("Configure Android"), [this] {
Core::ICore::infoBar()->removeInfo(kSetupAndroidSetting);
diff --git a/src/plugins/android/androidplugin.h b/src/plugins/android/androidplugin.h
index e98a5a32cd9..d4ad726cf05 100644
--- a/src/plugins/android/androidplugin.h
+++ b/src/plugins/android/androidplugin.h
@@ -44,7 +44,6 @@ class AndroidPlugin final : public ExtensionSystem::IPlugin
class AndroidPluginPrivate *d = nullptr;
- ShutdownFlag aboutToShutdown() final;
#ifdef WITH_TESTS
private slots:
void testAndroidSdkManagerProgressParser_data();
diff --git a/src/plugins/android/androidpotentialkit.cpp b/src/plugins/android/androidpotentialkit.cpp
index 325ee7c2bb7..f0eba970535 100644
--- a/src/plugins/android/androidpotentialkit.cpp
+++ b/src/plugins/android/androidpotentialkit.cpp
@@ -66,15 +66,15 @@ QWidget *AndroidPotentialKit::createWidget(QWidget *parent) const
bool AndroidPotentialKit::isEnabled() const
{
- QList<ProjectExplorer::Kit *> kits = ProjectExplorer::KitManager::kits();
- foreach (ProjectExplorer::Kit *kit, kits) {
+ const QList<ProjectExplorer::Kit *> kits = ProjectExplorer::KitManager::kits();
+ for (const ProjectExplorer::Kit *kit : kits) {
if (kit->isAutoDetected() && !kit->isSdkProvided()) {
return false;
}
}
return QtSupport::QtVersionManager::version([](const QtSupport::QtVersion *v) {
- return v->isValid() && v->type() == QString::fromLatin1(Constants::ANDROID_QT_TYPE);
+ return v->type() == QString::fromLatin1(Constants::ANDROID_QT_TYPE);
});
}
@@ -115,8 +115,8 @@ void AndroidPotentialKitWidget::openOptions()
void AndroidPotentialKitWidget::recheck()
{
- QList<ProjectExplorer::Kit *> kits = ProjectExplorer::KitManager::kits();
- foreach (ProjectExplorer::Kit *kit, kits) {
+ const QList<ProjectExplorer::Kit *> kits = ProjectExplorer::KitManager::kits();
+ for (const ProjectExplorer::Kit *kit : kits) {
if (kit->isAutoDetected() && !kit->isSdkProvided()) {
setVisible(false);
return;
diff --git a/src/plugins/android/androidqmlpreviewworker.cpp b/src/plugins/android/androidqmlpreviewworker.cpp
index cb809454015..e43654d4c8d 100644
--- a/src/plugins/android/androidqmlpreviewworker.cpp
+++ b/src/plugins/android/androidqmlpreviewworker.cpp
@@ -28,7 +28,6 @@
#include "androidavdmanager.h"
#include "androiddevice.h"
#include "androiddeviceinfo.h"
-#include "androidglobal.h"
#include "androidmanager.h"
#include <coreplugin/icore.h>
@@ -38,6 +37,7 @@
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <qmlprojectmanager/qmlprojectconstants.h>
@@ -127,7 +127,7 @@ bool AndroidQmlPreviewWorker::isPreviewRunning(int lastKnownPid) const
void AndroidQmlPreviewWorker::startPidWatcher()
{
- m_pidFutureWatcher.setFuture(Utils::runAsync([this]() {
+ m_pidFutureWatcher.setFuture(runAsync([this]() {
// wait for started
const int sleepTimeMs = 2000;
QDeadlineTimer deadline(20000);
@@ -157,7 +157,7 @@ void AndroidQmlPreviewWorker::startLogcat()
QString args = QString("logcat --pid=%1").arg(m_viewerPid);
if (!m_logcatStartTimeStamp.isEmpty())
args += QString(" -T '%1'").arg(m_logcatStartTimeStamp);
- Utils::CommandLine cmd(AndroidConfigurations::currentConfig().adbToolPath());
+ CommandLine cmd(AndroidConfigurations::currentConfig().adbToolPath());
cmd.setArguments(args);
m_logcatProcess.setCommand(cmd);
m_logcatProcess.setUseCtrlCStub(true);
@@ -190,7 +190,7 @@ AndroidQmlPreviewWorker::AndroidQmlPreviewWorker(ProjectExplorer::RunControl *ru
connect(this, &AndroidQmlPreviewWorker::previewPidChanged,
this, &AndroidQmlPreviewWorker::startLogcat);
- connect(this, &RunWorker::stopped, &m_logcatProcess, &Utils::QtcProcess::stopProcess);
+ connect(this, &RunWorker::stopped, &m_logcatProcess, &QtcProcess::stop);
m_logcatProcess.setStdOutCallback([this](const QString &stdOut) {
filterLogcatAndAppendMessage(stdOut);
});
@@ -250,7 +250,7 @@ bool AndroidQmlPreviewWorker::ensureAvdIsRunning()
if (devInfoLocal.isValid()) {
if (dev->machineType() == IDevice::Emulator) {
appendMessage(tr("Launching AVD."), NormalMessageFormat);
- devInfoLocal.serialNumber = avdMananager.startAvd(devInfoLocal.avdname);
+ devInfoLocal.serialNumber = avdMananager.startAvd(devInfoLocal.avdName);
}
if (devInfoLocal.serialNumber.isEmpty()) {
appendMessage(tr("Could not start AVD."), ErrorMessageFormat);
@@ -314,7 +314,7 @@ bool AndroidQmlPreviewWorker::preparePreviewArtefacts()
}
} else {
const FilePaths allFiles = m_rc->project()->files(m_rc->project()->SourceFiles);
- const FilePaths filesToExport = Utils::filtered(allFiles,[](const FilePath &path) {
+ const FilePaths filesToExport = filtered(allFiles, [](const FilePath &path) {
return path.suffix() == "qmlproject";
});
@@ -363,7 +363,8 @@ FilePath AndroidQmlPreviewWorker::createQmlrcFile(const FilePath &workFolder,
QByteArray stdOut;
QByteArray stdErr;
if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
- rccProcess.stopProcess();
+ rccProcess.stop();
+ rccProcess.waitForFinished();
appendMessage(tr("A timeout occurred running \"%1\"").
arg(rccProcess.commandLine().toUserOutput()), StdErrFormat);
qrcPath.removeFile();
@@ -425,7 +426,7 @@ bool AndroidQmlPreviewWorker::startPreviewApp()
const QDir destDir(apkInfo()->uploadDir);
const QString qmlrcPath = destDir.filePath(m_uploadInfo.uploadPackage.baseName()
+ packageSuffix);
- const QStringList envVars = m_rc->aspect<EnvironmentAspect>()->environment().toStringList();
+ const QStringList envVars = m_rc->aspect<EnvironmentAspect>()->environment.toStringList();
const QStringList command {
"am", "start",
diff --git a/src/plugins/android/androidqmlpreviewworker.h b/src/plugins/android/androidqmlpreviewworker.h
index 68e541a8ec8..b1605b3992a 100644
--- a/src/plugins/android/androidqmlpreviewworker.h
+++ b/src/plugins/android/androidqmlpreviewworker.h
@@ -24,10 +24,12 @@
****************************************************************************/
#pragma once
+
#include "androidconfigurations.h"
#include <projectexplorer/runcontrol.h>
-#include <utils/environment.h>
+
+#include <utils/qtcprocess.h>
#include <QFutureWatcher>
diff --git a/src/plugins/android/androidqtversion.cpp b/src/plugins/android/androidqtversion.cpp
index fc8dd9f41ca..7376f10a737 100644
--- a/src/plugins/android/androidqtversion.cpp
+++ b/src/plugins/android/androidqtversion.cpp
@@ -28,6 +28,7 @@
#include "androidconfigurations.h"
#include "androidmanager.h"
+#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
@@ -95,43 +96,8 @@ bool AndroidQtVersion::supportsMultipleQtAbis() const
Abis AndroidQtVersion::detectQtAbis() const
{
- auto androidAbi2Abi = [](const QString &androidAbi) {
- if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A) {
- return Abi{Abi::Architecture::ArmArchitecture,
- Abi::OS::LinuxOS,
- Abi::OSFlavor::AndroidLinuxFlavor,
- Abi::BinaryFormat::ElfFormat,
- 64, androidAbi};
- } else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A) {
- return Abi{Abi::Architecture::ArmArchitecture,
- Abi::OS::LinuxOS,
- Abi::OSFlavor::AndroidLinuxFlavor,
- Abi::BinaryFormat::ElfFormat,
- 32, androidAbi};
- } else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_X86_64) {
- return Abi{Abi::Architecture::X86Architecture,
- Abi::OS::LinuxOS,
- Abi::OSFlavor::AndroidLinuxFlavor,
- Abi::BinaryFormat::ElfFormat,
- 64, androidAbi};
- } else if (androidAbi == ProjectExplorer::Constants::ANDROID_ABI_X86) {
- return Abi{Abi::Architecture::X86Architecture,
- Abi::OS::LinuxOS,
- Abi::OSFlavor::AndroidLinuxFlavor,
- Abi::BinaryFormat::ElfFormat,
- 32, androidAbi};
- } else {
- return Abi{Abi::Architecture::UnknownArchitecture,
- Abi::OS::LinuxOS,
- Abi::OSFlavor::AndroidLinuxFlavor,
- Abi::BinaryFormat::ElfFormat,
- 0, androidAbi};
- }
- };
- Abis abis;
- for (const auto &abi : androidAbis())
- abis << androidAbi2Abi(abi);
- return abis;
+ const bool conf = AndroidConfigurations::currentConfig().sdkFullyConfigured();
+ return conf ? Utils::transform<Abis>(androidAbis(), &AndroidManager::androidAbi2Abi) : Abis();
}
void AndroidQtVersion::addToEnvironment(const Kit *k, Utils::Environment &env) const
diff --git a/src/plugins/android/androidrunconfiguration.cpp b/src/plugins/android/androidrunconfiguration.cpp
index b0b3c58f998..e02ac0de1ab 100644
--- a/src/plugins/android/androidrunconfiguration.cpp
+++ b/src/plugins/android/androidrunconfiguration.cpp
@@ -75,15 +75,14 @@ AndroidRunConfiguration::AndroidRunConfiguration(Target *target, Utils::Id id)
auto envAspect = addAspect<EnvironmentAspect>();
envAspect->addSupportedBaseEnvironment(tr("Clean Environment"), {});
- auto extraAppArgsAspect = addAspect<ArgumentsAspect>();
+ auto extraAppArgsAspect = addAspect<ArgumentsAspect>(macroExpander());
- connect(extraAppArgsAspect, &BaseAspect::changed,
- this, [target, extraAppArgsAspect]() {
+ connect(extraAppArgsAspect, &BaseAspect::changed, this, [target, extraAppArgsAspect] {
if (target->buildConfigurations().first()->buildType() == BuildConfiguration::BuildType::Release) {
const QString buildKey = target->activeBuildKey();
target->buildSystem()->setExtraData(buildKey,
Android::Constants::AndroidApplicationArgs,
- extraAppArgsAspect->arguments(target->macroExpander()));
+ extraAppArgsAspect->arguments());
}
});
diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
index b8be01ae808..3156ecda5c3 100644
--- a/src/plugins/android/androidrunner.cpp
+++ b/src/plugins/android/androidrunner.cpp
@@ -193,9 +193,9 @@ void AndroidRunner::launchAVD()
emit androidDeviceInfoChanged(info);
if (info.isValid()) {
AndroidAvdManager avdManager;
- if (!info.avdname.isEmpty() && avdManager.findAvd(info.avdname).isEmpty()) {
- bool launched = avdManager.startAvdAsync(info.avdname);
- m_launchedAVDName = launched ? info.avdname:"";
+ if (!info.avdName.isEmpty() && avdManager.findAvd(info.avdName).isEmpty()) {
+ bool launched = avdManager.startAvdAsync(info.avdName);
+ m_launchedAVDName = launched ? info.avdName:"";
} else {
m_launchedAVDName.clear();
}
diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp
index 2bf8d60570f..4734ec50244 100644
--- a/src/plugins/android/androidrunnerworker.cpp
+++ b/src/plugins/android/androidrunnerworker.cpp
@@ -28,11 +28,11 @@
#include "androidconfigurations.h"
#include "androidconstants.h"
#include "androidmanager.h"
-#include "androidrunconfiguration.h"
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerrunconfigurationaspect.h>
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/runconfigurationaspects.h>
@@ -242,8 +242,8 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
auto aspect = runControl->aspect<Debugger::DebuggerRunConfigurationAspect>();
Utils::Id runMode = runControl->runMode();
const bool debuggingMode = runMode == ProjectExplorer::Constants::DEBUG_RUN_MODE;
- m_useCppDebugger = debuggingMode && aspect->useCppDebugger();
- if (debuggingMode && aspect->useQmlDebugger())
+ m_useCppDebugger = debuggingMode && aspect->useCppDebugger;
+ if (debuggingMode && aspect->useQmlDebugger)
m_qmlDebugServices = QmlDebug::QmlDebuggerServices;
else if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE)
m_qmlDebugServices = QmlDebug::QmlProfilerServices;
@@ -270,23 +270,22 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
m_deviceSerialNumber = AndroidManager::deviceSerialNumber(target);
m_apiLevel = AndroidManager::deviceApiLevel(target);
- m_extraEnvVars = runControl->aspect<EnvironmentAspect>()->environment();
+ m_extraEnvVars = runControl->aspect<EnvironmentAspect>()->environment;
qCDebug(androidRunWorkerLog) << "Environment variables for the app"
<< m_extraEnvVars.toStringList();
- if (target->buildConfigurations().first()->buildType() != BuildConfiguration::BuildType::Release) {
- m_extraAppParams = runControl->runnable().command.arguments();
- }
+ if (target->buildConfigurations().first()->buildType() != BuildConfiguration::BuildType::Release)
+ m_extraAppParams = runControl->commandLine().arguments();
if (auto aspect = runControl->aspect(Constants::ANDROID_AM_START_ARGS)) {
- QTC_CHECK(aspect->value().type() == QVariant::String);
- const QString startArgs = aspect->value().toString();
+ QTC_CHECK(aspect->value.type() == QVariant::String);
+ const QString startArgs = aspect->value.toString();
m_amStartExtraArgs = ProcessArgs::splitArgs(startArgs, OsTypeOtherUnix);
}
if (auto aspect = runControl->aspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) {
- QTC_CHECK(aspect->value().type() == QVariant::String);
- const QStringList commands = aspect->value().toString().split('\n', Qt::SkipEmptyParts);
+ QTC_CHECK(aspect->value.type() == QVariant::String);
+ const QStringList commands = aspect->value.toString().split('\n', Qt::SkipEmptyParts);
for (const QString &shellCmd : commands)
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
}
@@ -295,8 +294,8 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
if (auto aspect = runControl->aspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) {
- QTC_CHECK(aspect->value().type() == QVariant::String);
- const QStringList commands = aspect->value().toString().split('\n', Qt::SkipEmptyParts);
+ QTC_CHECK(aspect->value.type() == QVariant::String);
+ const QStringList commands = aspect->value.toString().split('\n', Qt::SkipEmptyParts);
for (const QString &shellCmd : commands)
m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
}
@@ -439,7 +438,7 @@ void AndroidRunnerWorker::logcatProcess(const QByteArray &text, QByteArray &buff
}
QString pidString = QString::number(m_processPID);
- foreach (const QByteArray &msg, lines) {
+ for (const QByteArray &msg : qAsConst(lines)) {
const QString line = QString::fromUtf8(msg).trimmed() + QLatin1Char('\n');
if (!line.contains(pidString))
continue;
@@ -646,7 +645,7 @@ void AndroidRunnerWorker::asyncStartHelper()
<< QString::fromLatin1(appArgs.join(' ').toUtf8().toBase64());
}
- if (m_extraEnvVars.size() > 0) {
+ if (m_extraEnvVars.isValid()) {
args << "-e" << "extraenvvars"
<< QString::fromLatin1(m_extraEnvVars.toStringList().join('\t')
.toUtf8().toBase64());
diff --git a/src/plugins/android/androidsdkdownloader.cpp b/src/plugins/android/androidsdkdownloader.cpp
index c9512b464a9..6e0b66c555d 100644
--- a/src/plugins/android/androidsdkdownloader.cpp
+++ b/src/plugins/android/androidsdkdownloader.cpp
@@ -25,6 +25,8 @@
#include "androidsdkdownloader.h"
+#include "androidconstants.h"
+
#include <utils/archive.h>
#include <utils/filepath.h>
@@ -52,6 +54,8 @@ AndroidSdkDownloader::AndroidSdkDownloader()
connect(&m_manager, &QNetworkAccessManager::finished, this, &AndroidSdkDownloader::downloadFinished);
}
+AndroidSdkDownloader::~AndroidSdkDownloader() = default;
+
#if QT_CONFIG(ssl)
void AndroidSdkDownloader::sslErrors(const QList<QSslError> &sslErrors)
{
@@ -61,7 +65,7 @@ void AndroidSdkDownloader::sslErrors(const QList<QSslError> &sslErrors)
}
#endif
-void AndroidSdkDownloader::downloadAndExtractSdk(const FilePath &sdkExtractPath)
+void AndroidSdkDownloader::downloadAndExtractSdk()
{
if (m_androidConfig.sdkToolsUrl().isEmpty()) {
logError(tr("The SDK Tools download URL is empty."));
@@ -88,12 +92,23 @@ void AndroidSdkDownloader::downloadAndExtractSdk(const FilePath &sdkExtractPath)
connect(m_progressDialog, &QProgressDialog::canceled, this, &AndroidSdkDownloader::cancel);
- connect(this, &AndroidSdkDownloader::sdkPackageWriteFinished, this, [this, sdkExtractPath]() {
- if (Archive *archive = Archive::unarchive(m_sdkFilename, sdkExtractPath)) {
- connect(archive, &Archive::finished, [this, sdkExtractPath](bool success){
- if (success)
+ connect(this, &AndroidSdkDownloader::sdkPackageWriteFinished, this, [this]() {
+ if (!Archive::supportsFile(m_sdkFilename))
+ return;
+ const FilePath extractDir = m_sdkFilename.parentDir();
+ m_archive.reset(new Archive(m_sdkFilename, extractDir));
+ if (m_archive->isValid()) {
+ connect(m_archive.get(), &Archive::finished, this, [this, extractDir](bool success) {
+ if (success) {
+ // Save the extraction path temporarily which can be used by sdkmanager
+ // to install essential packages at firt time setup.
+ m_androidConfig.setTemporarySdkToolsPath(
+ extractDir.pathAppended(Constants::cmdlineToolsName));
emit sdkExtracted();
+ }
+ m_archive.release()->deleteLater();
});
+ m_archive->unarchive();
}
});
}
@@ -153,7 +168,7 @@ FilePath AndroidSdkDownloader::getSaveFilename(const QUrl &url)
basename += QString::number(i);
}
- return FilePath::fromString(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))
+ return FilePath::fromString(QStandardPaths::writableLocation(QStandardPaths::TempLocation))
/ basename;
}
diff --git a/src/plugins/android/androidsdkdownloader.h b/src/plugins/android/androidsdkdownloader.h
index 76375132397..c18f4c51000 100644
--- a/src/plugins/android/androidsdkdownloader.h
+++ b/src/plugins/android/androidsdkdownloader.h
@@ -32,7 +32,10 @@
#include <QObject>
#include <QProgressDialog>
-namespace Utils { class FilePath; }
+namespace Utils {
+class Archive;
+class FilePath;
+}
namespace Android {
namespace Internal {
@@ -43,7 +46,8 @@ class AndroidSdkDownloader : public QObject
public:
AndroidSdkDownloader();
- void downloadAndExtractSdk(const Utils::FilePath &sdkExtractPath);
+ ~AndroidSdkDownloader();
+ void downloadAndExtractSdk();
static QString dialogTitle();
void cancel();
@@ -71,7 +75,8 @@ private:
QNetworkReply *m_reply = nullptr;
Utils::FilePath m_sdkFilename;
QProgressDialog *m_progressDialog = nullptr;
- const AndroidConfig &m_androidConfig;
+ AndroidConfig &m_androidConfig;
+ std::unique_ptr<Utils::Archive> m_archive;
};
} // Internal
diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp
index 15636de0789..960509e827c 100644
--- a/src/plugins/android/androidsdkmanager.cpp
+++ b/src/plugins/android/androidsdkmanager.cpp
@@ -138,10 +138,10 @@ static bool sdkManagerCommand(const AndroidConfig &config, const QStringList &ar
proc.setTimeoutS(timeout);
proc.setTimeOutMessageBoxEnabled(true);
proc.setCommand({config.sdkManagerToolPath(), newArgs});
- proc.runBlocking(QtcProcess::WithEventLoop);
+ proc.runBlocking(EventLoopMode::On);
if (output)
*output = proc.allOutput();
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
/*!
@@ -166,8 +166,10 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar
proc.setTimeoutS(timeout);
proc.setStdOutCallback([offset, progressQuota, &proc, &assertionFound, &fi](const QString &out) {
int progressPercent = parseProgress(out, assertionFound);
- if (assertionFound)
- proc.stopProcess();
+ if (assertionFound) {
+ proc.stop();
+ proc.waitForFinished();
+ }
if (progressPercent != -1)
fi.setProgressValue(offset + qRound((progressPercent / 100.0) * progressQuota));
});
@@ -175,19 +177,21 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar
output.stdError = err;
});
if (interruptible) {
- QObject::connect(&sdkManager, &AndroidSdkManager::cancelActiveOperations,
- &proc, &QtcProcess::stopProcess);
+ QObject::connect(&sdkManager, &AndroidSdkManager::cancelActiveOperations, &proc, [&proc] {
+ proc.stop();
+ proc.waitForFinished();
+ });
}
proc.setCommand({config.sdkManagerToolPath(), newArgs});
- proc.runBlocking(QtcProcess::WithEventLoop);
+ proc.runBlocking(EventLoopMode::On);
if (assertionFound) {
output.success = false;
- output.stdOutput = proc.stdOut();
+ output.stdOutput = proc.cleanedStdOut();
output.stdError = QCoreApplication::translate("Android::Internal::AndroidSdkManager",
"The operation requires user interaction. "
"Use the \"sdkmanager\" command-line tool.");
} else {
- output.success = proc.result() == QtcProcess::FinishedWithSuccess;
+ output.success = proc.result() == ProcessResult::FinishedWithSuccess;
}
}
@@ -303,18 +307,18 @@ private:
using MarkerTagsType = std::map<SdkManagerOutputParser::MarkerTag, const char *>;
Q_GLOBAL_STATIC_WITH_ARGS(MarkerTagsType, markerTags, ({
- {SdkManagerOutputParser::MarkerTag::InstalledPackagesMarker, "Installed packages:"},
- {SdkManagerOutputParser::MarkerTag::AvailablePackagesMarkers, "Available Packages:"},
- {SdkManagerOutputParser::MarkerTag::AvailableUpdatesMarker, "Available Updates:"},
- {SdkManagerOutputParser::MarkerTag::PlatformMarker, "platforms"},
- {SdkManagerOutputParser::MarkerTag::SystemImageMarker, "system-images"},
- {SdkManagerOutputParser::MarkerTag::BuildToolsMarker, "build-tools"},
- {SdkManagerOutputParser::MarkerTag::SdkToolsMarker, "tools"},
- {SdkManagerOutputParser::MarkerTag::CmdlineSdkToolsMarker, "cmdline-tools"},
- {SdkManagerOutputParser::MarkerTag::PlatformToolsMarker, "platform-tools"},
- {SdkManagerOutputParser::MarkerTag::EmulatorToolsMarker, "emulator"},
- {SdkManagerOutputParser::MarkerTag::NdkMarker, "ndk"},
- {SdkManagerOutputParser::MarkerTag::ExtrasMarker, "extras"}
+ {SdkManagerOutputParser::MarkerTag::InstalledPackagesMarker, "Installed packages:"},
+ {SdkManagerOutputParser::MarkerTag::AvailablePackagesMarkers, "Available Packages:"},
+ {SdkManagerOutputParser::MarkerTag::AvailableUpdatesMarker, "Available Updates:"},
+ {SdkManagerOutputParser::MarkerTag::PlatformMarker, "platforms"},
+ {SdkManagerOutputParser::MarkerTag::SystemImageMarker, "system-images"},
+ {SdkManagerOutputParser::MarkerTag::BuildToolsMarker, "build-tools"},
+ {SdkManagerOutputParser::MarkerTag::SdkToolsMarker, "tools"},
+ {SdkManagerOutputParser::MarkerTag::CmdlineSdkToolsMarker, Constants::cmdlineToolsName},
+ {SdkManagerOutputParser::MarkerTag::PlatformToolsMarker, "platform-tools"},
+ {SdkManagerOutputParser::MarkerTag::EmulatorToolsMarker, "emulator"},
+ {SdkManagerOutputParser::MarkerTag::NdkMarker, "ndk"},
+ {SdkManagerOutputParser::MarkerTag::ExtrasMarker, "extras"}
}));
AndroidSdkManager::AndroidSdkManager(const AndroidConfig &config):
@@ -1017,9 +1021,12 @@ void AndroidSdkManagerPrivate::getPendingLicense(SdkCmdFutureInterface &fi)
{
fi.setProgressRange(0, 100);
fi.setProgressValue(0);
+
AndroidSdkManager::OperationOutput result;
result.type = AndroidSdkManager::LicenseWorkflow;
- QtcProcess licenseCommand(ProcessMode::Writer);
+
+ QtcProcess licenseCommand;
+ licenseCommand.setProcessMode(ProcessMode::Writer);
licenseCommand.setEnvironment(AndroidConfigurations::toolsEnvironment(m_config));
bool reviewingLicenses = false;
licenseCommand.setCommand(CommandLine(m_config.sdkManagerToolPath(), {"--licenses", sdkRootArg(m_config)}));
@@ -1038,7 +1045,7 @@ void AndroidSdkManagerPrivate::getPendingLicense(SdkCmdFutureInterface &fi)
QByteArray userInput = getUserInput();
if (!userInput.isEmpty()) {
clearUserInput();
- licenseCommand.write(userInput);
+ licenseCommand.writeRaw(userInput);
++inputCounter;
if (steps != -1)
fi.setProgressValue(qRound((inputCounter / (double)steps) * 100));
diff --git a/src/plugins/android/androidsdkmanagerwidget.cpp b/src/plugins/android/androidsdkmanagerwidget.cpp
index be93c03f609..5539f36143b 100644
--- a/src/plugins/android/androidsdkmanagerwidget.cpp
+++ b/src/plugins/android/androidsdkmanagerwidget.cpp
@@ -68,7 +68,7 @@ private:
AndroidSdkManagerWidget::AndroidSdkManagerWidget(AndroidConfig &config,
AndroidSdkManager *sdkManager, QWidget *parent) :
- QWidget(parent),
+ QDialog(parent),
m_androidConfig(config),
m_sdkManager(sdkManager),
m_sdkModel(new AndroidSdkModel(m_androidConfig, m_sdkManager, this)),
@@ -79,6 +79,7 @@ AndroidSdkManagerWidget::AndroidSdkManagerWidget(AndroidConfig &config,
m_ui->sdkLicensebuttonBox->hide();
m_ui->sdkLicenseLabel->hide();
m_ui->viewStack->setCurrentWidget(m_ui->packagesStack);
+ setModal(true);
m_formatter = new Utils::OutputFormatter;
m_formatter->setPlainTextEdit(m_ui->outputEdit);
@@ -136,6 +137,7 @@ AndroidSdkManagerWidget::AndroidSdkManagerWidget(AndroidConfig &config,
m_ui->expandCheck->setChecked(!text.isEmpty());
});
+ connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &AndroidSdkManagerWidget::close);
connect(m_ui->applySelectionButton, &QPushButton::clicked,
this, [this]() { onApplyButton(); });
connect(m_ui->cancelButton, &QPushButton::clicked, this,
@@ -268,6 +270,9 @@ void AndroidSdkManagerWidget::onApplyButton(const QString &extraMessage)
if (messageDlg.exec() == QMessageBox::Cancel)
return;
+ // Open the SDK Manager dialog after accepting to continue with the installation
+ show();
+
switchView(Operations);
m_pendingCommand = AndroidSdkManager::UpdatePackage;
// User agreed with the selection. Check for licenses.
@@ -401,6 +406,8 @@ void AndroidSdkManagerWidget::notifyOperationFinished()
QMessageBox::information(this, tr("Android SDK Changes"),
tr("Android SDK operations finished."), QMessageBox::Ok);
m_ui->operationProgress->setValue(0);
+ // Once the update/install is done, let's hide the dialog.
+ hide();
}
}
@@ -464,10 +471,15 @@ void AndroidSdkManagerWidget::switchView(AndroidSdkManagerWidget::View view)
if (m_currentView == PackageListing)
m_formatter->clear();
m_currentView = view;
- if (m_currentView == PackageListing)
+ if (m_currentView == PackageListing) {
+ // We need the buttonBox only in the main listing view, as the license and update
+ // views already have a cancel button.
+ m_ui->buttonBox->button(QDialogButtonBox::Ok)->setVisible(true);
emit updatingSdkFinished();
- else
+ } else {
+ m_ui->buttonBox->button(QDialogButtonBox::Ok)->setVisible(false);
emit updatingSdk();
+ }
if (m_currentView == LicenseWorkflow)
emit licenseWorkflowStarted();
diff --git a/src/plugins/android/androidsdkmanagerwidget.h b/src/plugins/android/androidsdkmanagerwidget.h
index 5266290b109..f154d2a3a57 100644
--- a/src/plugins/android/androidsdkmanagerwidget.h
+++ b/src/plugins/android/androidsdkmanagerwidget.h
@@ -65,7 +65,7 @@ private:
QFuture<QString> m_optionsFuture;
};
-class AndroidSdkManagerWidget : public QWidget
+class AndroidSdkManagerWidget : public QDialog
{
Q_OBJECT
diff --git a/src/plugins/android/androidsdkmanagerwidget.ui b/src/plugins/android/androidsdkmanagerwidget.ui
index ea35571896e..06203ce2a41 100644
--- a/src/plugins/android/androidsdkmanagerwidget.ui
+++ b/src/plugins/android/androidsdkmanagerwidget.ui
@@ -18,16 +18,16 @@
<number>-1</number>
</property>
<property name="leftMargin">
- <number>0</number>
+ <number>9</number>
</property>
<property name="topMargin">
- <number>0</number>
+ <number>9</number>
</property>
<property name="rightMargin">
- <number>0</number>
+ <number>9</number>
</property>
<property name="bottomMargin">
- <number>0</number>
+ <number>9</number>
</property>
<item>
<widget class="QStackedWidget" name="viewStack">
@@ -297,6 +297,13 @@
</widget>
</widget>
</item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<customwidgets>
diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp
index e928023937a..2b0a5864f82 100644
--- a/src/plugins/android/androidsettingswidget.cpp
+++ b/src/plugins/android/androidsettingswidget.cpp
@@ -32,14 +32,11 @@
#include "androidsdkdownloader.h"
#include "androidsdkmanager.h"
#include "androidsdkmanagerwidget.h"
-#include "androidtoolchain.h"
#include <projectexplorer/projectexplorerconstants.h>
-#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/infolabel.h>
-#include <utils/listmodel.h>
#include <utils/pathchooser.h>
#include <utils/progressindicator.h>
#include <utils/qtcassert.h>
@@ -49,16 +46,10 @@
#include <QDesktopServices>
#include <QDir>
#include <QFileDialog>
-#include <QFutureWatcher>
-#include <QInputDialog>
#include <QList>
#include <QLoggingCategory>
#include <QMessageBox>
-#include <QModelIndex>
-#include <QScrollArea>
-#include <QSettings>
#include <QStandardPaths>
-#include <QString>
#include <QTimer>
#include <QUrl>
#include <QWidget>
@@ -304,34 +295,7 @@ bool AndroidSettingsWidget::isDefaultNdkSelected() const
AndroidSettingsWidget::AndroidSettingsWidget()
{
m_ui.setupUi(this);
- m_sdkManagerWidget = new AndroidSdkManagerWidget(m_androidConfig, &m_sdkManager,
- m_ui.sdkManagerGroupBox);
- auto sdkMangerLayout = new QVBoxLayout(m_ui.sdkManagerGroupBox);
- sdkMangerLayout->addWidget(m_sdkManagerWidget);
- connect(m_sdkManagerWidget, &AndroidSdkManagerWidget::updatingSdk, [this] {
- // Disable the top level UI to keep the user from unintentionally interrupting operations
- m_ui.androidSettingsGroupBox->setEnabled(false);
- m_ui.androidOpenSSLSettingsGroupBox->setEnabled(false);
- m_ui.CreateKitCheckBox->setEnabled(false);
- m_androidSummary->setState(DetailsWidget::Collapsed);
- m_androidProgress->hide();
- });
- connect(m_sdkManagerWidget, &AndroidSdkManagerWidget::updatingSdkFinished, [this] {
- m_ui.androidSettingsGroupBox->setEnabled(true);
- m_ui.androidOpenSSLSettingsGroupBox->setEnabled(true);
- m_ui.CreateKitCheckBox->setEnabled(true);
- });
- connect(m_sdkManagerWidget, &AndroidSdkManagerWidget::licenseWorkflowStarted, [this] {
- QObject *parentWidget = parent();
- while (parentWidget) {
- if (auto scrollArea = qobject_cast<QScrollArea *>(parentWidget)) {
- scrollArea->ensureWidgetVisible(m_ui.sdkManagerGroupBox);
- break;
- }
- parentWidget = parentWidget->parent();
- };
- });
-
+ m_sdkManagerWidget = new AndroidSdkManagerWidget(m_androidConfig, &m_sdkManager, this);
QMap<int, QString> androidValidationPoints;
androidValidationPoints[SdkPathExistsAndWritableRow] =
tr("Android SDK path exists and is writable.");
@@ -347,7 +311,7 @@ AndroidSettingsWidget::AndroidSettingsWidget()
m_androidSummary = new SummaryWidget(androidValidationPoints, tr("Android settings are OK."),
tr("Android settings have errors."),
m_ui.androidDetailsWidget);
- m_androidProgress = new Utils::ProgressIndicator(ProgressIndicatorSize::Medium, this);
+ m_androidProgress = new ProgressIndicator(ProgressIndicatorSize::Medium, this);
m_androidProgress->attachToWidget(m_ui.androidDetailsWidget);
m_androidProgress->hide();
@@ -446,12 +410,21 @@ AndroidSettingsWidget::AndroidSettingsWidget()
m_androidSummary->setInProgressText("Retrieving packages information");
m_androidProgress->show();
});
+ connect(m_ui.sdkManagerToolButton, &QAbstractButton::clicked,
+ this, [this]() { m_sdkManagerWidget->exec(); });
connect(m_ui.sdkToolsAutoDownloadButton, &QAbstractButton::clicked,
this, &AndroidSettingsWidget::downloadSdk);
connect(&m_sdkDownloader, &AndroidSdkDownloader::sdkDownloaderError, this, [this](const QString &error) {
QMessageBox::warning(this, AndroidSdkDownloader::dialogTitle(), error);
});
connect(&m_sdkDownloader, &AndroidSdkDownloader::sdkExtracted, this, [this] {
+ // Make sure the sdk path is created before installing packages
+ const FilePath sdkPath = m_androidConfig.sdkLocation();
+ if (!sdkPath.createDir()) {
+ QMessageBox::warning(this, AndroidSdkDownloader::dialogTitle(),
+ tr("Failed to create the SDK Tools path %1.")
+ .arg("\n\"" + sdkPath.toUserOutput() + "\""));
+ }
m_sdkManager.reloadPackages(true);
updateUI();
apply();
@@ -584,13 +557,6 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent)
return;
}
- const QString openSslRepo("https://github.com/KDAB/android_openssl.git");
- QtcProcess *gitCloner = new QtcProcess(this);
- CommandLine gitCloneCommand("git", {"clone", "--depth=1", openSslRepo, openSslPath.toString()});
- gitCloner->setCommand(gitCloneCommand);
-
- qCDebug(androidsettingswidget) << "Cloning OpenSSL repo: " << gitCloneCommand.toUserOutput();
-
QDir openSslDir(openSslPath.toString());
const bool isEmptyDir = openSslDir.isEmpty(QDir::AllEntries | QDir::NoDotAndDotDot
| QDir::Hidden | QDir::System);
@@ -611,7 +577,14 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent)
openSslProgressDialog->setWindowTitle(openSslCloneTitle);
openSslProgressDialog->setFixedSize(openSslProgressDialog->sizeHint());
- connect(openSslProgressDialog, &QProgressDialog::canceled, gitCloner, &QtcProcess::kill);
+ const QString openSslRepo("https://github.com/KDAB/android_openssl.git");
+ QtcProcess *gitCloner = new QtcProcess(this);
+ CommandLine gitCloneCommand("git", {"clone", "--depth=1", openSslRepo, openSslPath.toString()});
+ gitCloner->setCommand(gitCloneCommand);
+
+ qCDebug(androidsettingswidget) << "Cloning OpenSSL repo: " << gitCloneCommand.toUserOutput();
+
+ connect(openSslProgressDialog, &QProgressDialog::canceled, gitCloner, &QObject::deleteLater);
auto failDialog = [=](const QString &msgSuffix = {}) {
QStringList sl;
@@ -630,22 +603,21 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent)
openButton->deleteLater();
};
- connect(gitCloner, &QtcProcess::finished, [=] {
- openSslProgressDialog->close();
- validateOpenSsl();
- m_ui.openSslPathChooser->triggerChanged(); // After cloning, the path exists
-
- if (!openSslProgressDialog->wasCanceled()
- || gitCloner->result() == QtcProcess::FinishedWithError) {
- failDialog();
- }
- });
-
- connect(gitCloner, &QtcProcess::errorOccurred, this, [=](QProcess::ProcessError error) {
+ connect(gitCloner, &QtcProcess::done, this, [=] {
openSslProgressDialog->close();
- if (error == QProcess::FailedToStart) {
- failDialog(tr("The Git tool might not be installed properly on your system."));
- } else {
+ if (gitCloner->error() != QProcess::UnknownError) {
+ if (gitCloner->error() == QProcess::FailedToStart) {
+ failDialog(tr("The Git tool might not be installed properly on your system."));
+ return;
+ } else {
+ failDialog();
+ }
+ }
+ validateOpenSsl();
+ m_ui.openSslPathChooser->triggerChanged(); // After cloning, the path exists
+
+ if (!openSslProgressDialog->wasCanceled()
+ || gitCloner->result() == ProcessResult::FinishedWithError) {
failDialog();
}
});
@@ -661,12 +633,9 @@ void AndroidSettingsWidget::createKitToggled()
void AndroidSettingsWidget::updateUI()
{
- const bool sdkToolsOk = m_androidSummary->rowsOk({SdkPathExistsAndWritableRow, SdkToolsInstalledRow});
const bool androidSetupOk = m_androidSummary->allRowsOk();
const bool openSslOk = m_openSslSummary->allRowsOk();
- m_ui.sdkManagerGroupBox->setEnabled(sdkToolsOk);
-
const QListWidgetItem *currentItem = m_ui.ndkListWidget->currentItem();
const FilePath currentNdk = FilePath::fromString(currentItem ? currentItem->text() : "");
const QString infoText = tr("(SDK Version: %1, NDK Version: %2)")
@@ -703,12 +672,13 @@ void AndroidSettingsWidget::downloadSdk()
return;
}
- const QString message = tr("Download and install Android SDK Tools to: %1?")
- .arg(m_ui.SDKLocationPathChooser->filePath().cleanPath().toUserOutput());
+ const QString message = tr("Download and install Android SDK Tools to %1?")
+ .arg("\n\"" + m_ui.SDKLocationPathChooser->filePath().cleanPath().toUserOutput()
+ + "\"");
auto userInput = QMessageBox::information(this, AndroidSdkDownloader::dialogTitle(),
message, QMessageBox::Yes | QMessageBox::No);
if (userInput == QMessageBox::Yes)
- m_sdkDownloader.downloadAndExtractSdk(m_ui.SDKLocationPathChooser->filePath().cleanPath());
+ m_sdkDownloader.downloadAndExtractSdk();
}
// AndroidSettingsPage
diff --git a/src/plugins/android/androidsettingswidget.ui b/src/plugins/android/androidsettingswidget.ui
index fcfdc63a1d2..a4d3df36453 100644
--- a/src/plugins/android/androidsettingswidget.ui
+++ b/src/plugins/android/androidsettingswidget.ui
@@ -158,6 +158,13 @@
</property>
</widget>
</item>
+ <item row="2" column="2" colspan="4">
+ <widget class="QPushButton" name="sdkManagerToolButton">
+ <property name="text">
+ <string>SDK Manager</string>
+ </property>
+ </widget>
+ </item>
<item row="3" column="0">
<widget class="QLabel" name="ndkComboBoxLabel">
<property name="text">
@@ -234,11 +241,11 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="sdkManagerGroupBox">
- <property name="title">
- <string>SDK Manager</string>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
</property>
- </widget>
+ </spacer>
</item>
</layout>
</widget>
diff --git a/src/plugins/android/androidsignaloperation.cpp b/src/plugins/android/androidsignaloperation.cpp
index cfd3f6c94af..f437888bcee 100644
--- a/src/plugins/android/androidsignaloperation.cpp
+++ b/src/plugins/android/androidsignaloperation.cpp
@@ -36,40 +36,42 @@ namespace Internal {
AndroidSignalOperation::AndroidSignalOperation()
: m_adbPath(AndroidConfigurations::currentConfig().adbToolPath())
- , m_adbProcess(new QtcProcess(this))
, m_timeout(new QTimer(this))
{
m_timeout->setInterval(5000);
connect(m_timeout, &QTimer::timeout, this, &AndroidSignalOperation::handleTimeout);
}
+AndroidSignalOperation::~AndroidSignalOperation() = default;
+
+bool AndroidSignalOperation::handleCrashMessage()
+{
+ if (m_adbProcess->exitStatus() == QProcess::NormalExit)
+ return false;
+ m_errorMessage = QLatin1String(" adb process exit code: ") + QString::number(m_adbProcess->exitCode());
+ const QString adbError = m_adbProcess->errorString();
+ if (!adbError.isEmpty())
+ m_errorMessage += QLatin1String(" adb process error: ") + adbError;
+ return true;
+}
+
void AndroidSignalOperation::adbFindRunAsFinished()
{
QTC_ASSERT(m_state == RunAs, return);
m_timeout->stop();
- m_adbProcess->disconnect(this);
-
- QString runAs = QString::fromLatin1(m_adbProcess->readAllStandardOutput());
- if (m_adbProcess->exitStatus() != QProcess::NormalExit) {
- m_errorMessage = QLatin1String(" adb Exit code: ") + QString::number(m_adbProcess->exitCode());
- QString adbError = m_adbProcess->errorString();
- if (!adbError.isEmpty())
- m_errorMessage += QLatin1String(" adb process error: ") + adbError;
- }
+
+ handleCrashMessage();
+ const QString runAs = QString::fromLatin1(m_adbProcess->readAllStandardOutput());
+ m_adbProcess.release()->deleteLater();
if (runAs.isEmpty() || !m_errorMessage.isEmpty()) {
- m_errorMessage = QLatin1String("Cannot find User for process: ")
- + QString::number(m_pid)
- + m_errorMessage;
+ m_errorMessage.prepend(QLatin1String("Cannot find User for process: ")
+ + QString::number(m_pid));
m_state = Idle;
emit finished(m_errorMessage);
} else {
- connect(m_adbProcess, &QtcProcess::finished,
- this, &AndroidSignalOperation::adbKillFinished);
- m_state = Kill;
- m_timeout->start();
- m_adbProcess->setCommand({m_adbPath, {"shell", "run-as", runAs,
- "kill", QString("-%1").arg(m_signal), QString::number(m_pid)}});
- m_adbProcess->start();
+ startAdbProcess(Kill, {m_adbPath, {"shell", "run-as", runAs, "kill",
+ QString("-%1").arg(m_signal), QString::number(m_pid)}},
+ [this] { adbKillFinished(); });
}
}
@@ -77,28 +79,19 @@ void AndroidSignalOperation::adbKillFinished()
{
QTC_ASSERT(m_state == Kill, return);
m_timeout->stop();
- m_adbProcess->disconnect(this);
- if (m_adbProcess->exitStatus() != QProcess::NormalExit) {
- m_errorMessage = QLatin1String(" adb process exit code: ") + QString::number(m_adbProcess->exitCode());
- QString adbError = m_adbProcess->errorString();
- if (!adbError.isEmpty())
- m_errorMessage += QLatin1String(" adb process error: ") + adbError;
- } else {
+ if (!handleCrashMessage())
m_errorMessage = QString::fromLatin1(m_adbProcess->readAllStandardError());
- }
- if (!m_errorMessage.isEmpty()) {
- m_errorMessage = QLatin1String("Cannot kill process: ") + QString::number(m_pid)
- + m_errorMessage;
- }
+ m_adbProcess.release()->deleteLater();
+ if (!m_errorMessage.isEmpty())
+ m_errorMessage.prepend(QLatin1String("Cannot kill process: ") + QString::number(m_pid));
m_state = Idle;
emit finished(m_errorMessage);
}
void AndroidSignalOperation::handleTimeout()
{
- m_adbProcess->disconnect(this);
- m_adbProcess->kill();
+ m_adbProcess.reset();
m_timeout->stop();
m_state = Idle;
m_errorMessage = QLatin1String("adb process timed out");
@@ -108,14 +101,20 @@ void AndroidSignalOperation::handleTimeout()
void AndroidSignalOperation::signalOperationViaADB(qint64 pid, int signal)
{
QTC_ASSERT(m_state == Idle, return);
- m_adbProcess->disconnect(this);
m_pid = pid;
m_signal = signal;
- connect(m_adbProcess, &QtcProcess::finished,
- this, &AndroidSignalOperation::adbFindRunAsFinished);
- m_state = RunAs;
+ startAdbProcess(RunAs, {m_adbPath, {"shell", "cat", QString("/proc/%1/cmdline").arg(m_pid)}},
+ [this] { adbFindRunAsFinished(); });
+}
+
+void AndroidSignalOperation::startAdbProcess(State state, const Utils::CommandLine &commandLine,
+ FinishHandler handler)
+{
+ m_state = state;
m_timeout->start();
- m_adbProcess->setCommand({m_adbPath, {"shell", "cat", QString("/proc/%1/cmdline").arg(m_pid)}});
+ m_adbProcess.reset(new QtcProcess);
+ connect(m_adbProcess.get(), &QtcProcess::done, this, handler);
+ m_adbProcess->setCommand(commandLine);
m_adbProcess->start();
}
diff --git a/src/plugins/android/androidsignaloperation.h b/src/plugins/android/androidsignaloperation.h
index 2427eaf9f76..2992462c00a 100644
--- a/src/plugins/android/androidsignaloperation.h
+++ b/src/plugins/android/androidsignaloperation.h
@@ -37,7 +37,7 @@ class AndroidSignalOperation : public ProjectExplorer::DeviceProcessSignalOperat
{
Q_OBJECT
public:
- ~AndroidSignalOperation() override = default;
+ ~AndroidSignalOperation() override;
void killProcess(qint64 pid) override;
void killProcess(const QString &filePath) override;
void interruptProcess(qint64 pid) override;
@@ -47,22 +47,27 @@ protected:
explicit AndroidSignalOperation();
private:
+ enum State {
+ Idle,
+ RunAs,
+ Kill
+ };
+
+ using FinishHandler = std::function<void()>;
+
+ bool handleCrashMessage();
void adbFindRunAsFinished();
void adbKillFinished();
void handleTimeout();
void signalOperationViaADB(qint64 pid, int signal);
+ void startAdbProcess(State state, const Utils::CommandLine &commandLine, FinishHandler handler);
Utils::FilePath m_adbPath;
- Utils::QtcProcess *m_adbProcess;
+ std::unique_ptr<Utils::QtcProcess> m_adbProcess;
QTimer *m_timeout;
- enum State {
- Idle,
- RunAs,
- Kill
- } m_state = Idle;
-
+ State m_state = Idle;
qint64 m_pid = 0;
int m_signal = 0;
diff --git a/src/plugins/android/avddialog.cpp b/src/plugins/android/avddialog.cpp
index b44af13720b..f9f9dce9147 100644
--- a/src/plugins/android/avddialog.cpp
+++ b/src/plugins/android/avddialog.cpp
@@ -107,18 +107,20 @@ int AvdDialog::exec()
const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig);
QFutureWatcher<CreateAvdInfo> createAvdFutureWatcher;
- createAvdFutureWatcher.setFuture(avdManager.createAvd(result));
QEventLoop loop;
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::finished,
&loop, &QEventLoop::quit);
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::canceled,
&loop, &QEventLoop::quit);
+ createAvdFutureWatcher.setFuture(avdManager.createAvd(result));
loop.exec(QEventLoop::ExcludeUserInputEvents);
const QFuture<CreateAvdInfo> future = createAvdFutureWatcher.future();
- if (future.isResultReadyAt(0))
+ if (future.isResultReadyAt(0)) {
m_createdAvdInfo = future.result();
+ AndroidDeviceManager::instance()->updateAvdsList();
+ }
}
return execResult;
@@ -145,10 +147,6 @@ ProjectExplorer::IDevice::Ptr AvdDialog::device() const
dev->setExtraData(Constants::AndroidAvdName, m_createdAvdInfo.name);
dev->setExtraData(Constants::AndroidCpuAbi, {m_createdAvdInfo.abi});
dev->setExtraData(Constants::AndroidSdk, m_createdAvdInfo.systemImage->apiLevel());
- dev->setExtraData(Constants::AndroidAvdSdcard, QString("%1 MB")
- .arg(m_createdAvdInfo.sdcardSize));
- dev->setExtraData(Constants::AndroidAvdDevice, m_createdAvdInfo.deviceDefinition);
-
return IDevice::Ptr(dev);
}
diff --git a/src/plugins/android/avdmanageroutputparser.cpp b/src/plugins/android/avdmanageroutputparser.cpp
index 892405c33e4..49652143348 100644
--- a/src/plugins/android/avdmanageroutputparser.cpp
+++ b/src/plugins/android/avdmanageroutputparser.cpp
@@ -46,10 +46,6 @@ const char avdInfoPathKey[] = "Path:";
const char avdInfoAbiKey[] = "abi.type";
const char avdInfoTargetKey[] = "target";
const char avdInfoErrorKey[] = "Error:";
-const char avdInfoSdcardKey[] = "Sdcard";
-const char avdInfoTargetTypeKey[] = "Target";
-const char avdInfoDeviceKey[] = "Device";
-const char avdInfoSkinKey[] = "Skin";
namespace Android {
namespace Internal {
@@ -78,9 +74,10 @@ static Utils::optional<AndroidDeviceInfo> parseAvd(const QStringList &deviceInfo
qCDebug(avdOutputParserLog) << "Avd Parsing: Skip avd device. Error key found:" << line;
return {};
} else if (valueForKey(avdInfoNameKey, line, &value)) {
- avd.avdname = value;
+ avd.avdName = value;
} else if (valueForKey(avdInfoPathKey, line, &value)) {
const Utils::FilePath avdPath = Utils::FilePath::fromUserInput(value);
+ avd.avdPath = avdPath;
if (avdPath.exists()) {
// Get ABI.
const Utils::FilePath configFile = avdPath.pathAppended("config.ini");
@@ -92,7 +89,7 @@ static Utils::optional<AndroidDeviceInfo> parseAvd(const QStringList &deviceInfo
qCDebug(avdOutputParserLog) << "Avd Parsing: Cannot find ABI:" << configFile;
// Get Target
- const QString avdInfoFileName = avd.avdname + ".ini";
+ const QString avdInfoFileName = avd.avdName + ".ini";
const Utils::FilePath avdInfoFile = avdPath.parentDir().pathAppended(
avdInfoFileName);
QSettings avdInfo(avdInfoFile.toString(), QSettings::IniFormat);
@@ -103,14 +100,6 @@ static Utils::optional<AndroidDeviceInfo> parseAvd(const QStringList &deviceInfo
qCDebug(avdOutputParserLog)
<< "Avd Parsing: Cannot find sdk API:" << avdInfoFile.toString();
}
- } else if (valueForKey(avdInfoDeviceKey, line, &value)) {
- avd.avdDevice = value.remove(0, 2);
- } else if (valueForKey(avdInfoTargetTypeKey, line, &value)) {
- avd.avdTarget = value.remove(0, 2);
- } else if (valueForKey(avdInfoSkinKey, line, &value)) {
- avd.avdSkin = value.remove(0, 2);
- } else if (valueForKey(avdInfoSdcardKey, line, &value)) {
- avd.avdSdcardSize = value.remove(0, 2);
}
}
if (avd != AndroidDeviceInfo())
diff --git a/src/plugins/android/javalanguageserver.cpp b/src/plugins/android/javalanguageserver.cpp
index 4c06b296ebd..ca77497c17e 100644
--- a/src/plugins/android/javalanguageserver.cpp
+++ b/src/plugins/android/javalanguageserver.cpp
@@ -44,6 +44,7 @@
#include <QGridLayout>
#include <QLineEdit>
+#include <QXmlStreamWriter>
using namespace ProjectExplorer;
using namespace Utils;
@@ -187,7 +188,7 @@ private:
TemporaryDirectory m_workspaceDir = TemporaryDirectory("QtCreator-jls-XXXXXX");
};
-LanguageClient::BaseClientInterface *JLSSettings::createInterface() const
+LanguageClient::BaseClientInterface *JLSSettings::createInterface(ProjectExplorer::Project *) const
{
auto interface = new JLSInterface();
CommandLine cmd{m_executable, arguments(), CommandLine::Raw};
diff --git a/src/plugins/android/javalanguageserver.h b/src/plugins/android/javalanguageserver.h
index 1727da74a41..c2ef687cd64 100644
--- a/src/plugins/android/javalanguageserver.h
+++ b/src/plugins/android/javalanguageserver.h
@@ -42,7 +42,8 @@ public:
void fromMap(const QVariantMap &map) final;
LanguageClient::BaseSettings *copy() const final;
LanguageClient::Client *createClient(LanguageClient::BaseClientInterface *interface) const final;
- LanguageClient::BaseClientInterface *createInterface() const final;
+ LanguageClient::BaseClientInterface *createInterface(
+ ProjectExplorer::Project *project) const final;
Utils::FilePath m_languageServer;
diff --git a/src/plugins/android/splashscreencontainerwidget.cpp b/src/plugins/android/splashscreencontainerwidget.cpp
index a738b0ed127..261c0d56746 100644
--- a/src/plugins/android/splashscreencontainerwidget.cpp
+++ b/src/plugins/android/splashscreencontainerwidget.cpp
@@ -43,6 +43,8 @@
#include <QTabWidget>
#include <QToolButton>
#include <QVBoxLayout>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
using namespace Utils;
diff --git a/src/plugins/autotest/CMakeLists.txt b/src/plugins/autotest/CMakeLists.txt
index 881b5d2bc85..f2e468f177c 100644
--- a/src/plugins/autotest/CMakeLists.txt
+++ b/src/plugins/autotest/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(AutoTest
+ PLUGIN_CLASS AutotestPlugin
PLUGIN_DEPENDS Core CppEditor Debugger ProjectExplorer QmlJSTools TextEditor
PLUGIN_TEST_DEPENDS QmakeProjectManager QtSupport QbsProjectManager
SOURCES
diff --git a/src/plugins/autotest/autotest_global.h b/src/plugins/autotest/autotest_global.h
index c485ad21851..dfa0e6292d4 100644
--- a/src/plugins/autotest/autotest_global.h
+++ b/src/plugins/autotest/autotest_global.h
@@ -29,6 +29,8 @@
#if defined(AUTOTEST_LIBRARY)
# define AUTOTESTSHARED_EXPORT Q_DECL_EXPORT
+#elif defined(AUTOTEST_STATIC_LIBRARY)
+# define AUTOTESTSHARED_EXPORT
#else
# define AUTOTESTSHARED_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/autotest/autotestconstants.h b/src/plugins/autotest/autotestconstants.h
index 2021f8e9776..6782ab2101b 100644
--- a/src/plugins/autotest/autotestconstants.h
+++ b/src/plugins/autotest/autotestconstants.h
@@ -47,6 +47,7 @@ const char AUTOTEST_CONTEXT[] = "Auto Tests";
const char TASK_INDEX[] = "AutoTest.Task.Index";
const char TASK_PARSE[] = "AutoTest.Task.Parse";
const char AUTOTEST_SETTINGS_CATEGORY[] = "ZY.Tests";
+const char AUTOTEST_SETTINGS_ID[] = "A.AutoTest.0.General";
const char AUTOTEST_SETTINGS_TR[] = QT_TRANSLATE_NOOP("AutoTest", "Testing");
const char FRAMEWORK_PREFIX[] = "AutoTest.Framework.";
const char SETTINGSPAGE_PREFIX[] = "A.AutoTest.";
diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp
index 82fb07a982c..7ac67a7780a 100644
--- a/src/plugins/autotest/autotestplugin.cpp
+++ b/src/plugins/autotest/autotestplugin.cpp
@@ -38,7 +38,6 @@
#include "testsettingspage.h"
#include "testtreeitem.h"
#include "testtreemodel.h"
-#include "testtreeview.h"
#include "boost/boosttestframework.h"
#include "catch/catchframework.h"
@@ -66,6 +65,7 @@
#include <projectexplorer/target.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
+#include <utils/algorithm.h>
#include <utils/textutils.h>
#include <utils/utilsicons.h>
diff --git a/src/plugins/autotest/boost/boosttestconfiguration.cpp b/src/plugins/autotest/boost/boosttestconfiguration.cpp
index ba306e55c8c..556228bd653 100644
--- a/src/plugins/autotest/boost/boosttestconfiguration.cpp
+++ b/src/plugins/autotest/boost/boosttestconfiguration.cpp
@@ -32,13 +32,14 @@
#include "../itestframework.h"
#include "../testsettings.h"
+#include <utils/algorithm.h>
#include <utils/stringutils.h>
namespace Autotest {
namespace Internal {
TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const
+ Utils::QtcProcess *app) const
{
auto settings = static_cast<BoostTestSettings *>(framework()->testSettings());
return new BoostTestOutputReader(fi, app, buildDirectory(), projectFile(),
diff --git a/src/plugins/autotest/boost/boosttestconfiguration.h b/src/plugins/autotest/boost/boosttestconfiguration.h
index 2259eca5137..d3d4b851df4 100644
--- a/src/plugins/autotest/boost/boosttestconfiguration.h
+++ b/src/plugins/autotest/boost/boosttestconfiguration.h
@@ -36,7 +36,7 @@ public:
explicit BoostTestConfiguration(ITestFramework *framework)
: DebuggableTestConfiguration(framework) {}
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const override;
+ Utils::QtcProcess *app) const override;
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
};
diff --git a/src/plugins/autotest/boost/boosttestframework.cpp b/src/plugins/autotest/boost/boosttestframework.cpp
index 74a7880c988..2b9b4837b80 100644
--- a/src/plugins/autotest/boost/boosttestframework.cpp
+++ b/src/plugins/autotest/boost/boosttestframework.cpp
@@ -41,8 +41,7 @@ ITestTreeItem *BoostTestFramework::createRootNode()
{
return new BoostTestTreeItem(
this,
- QCoreApplication::translate("BoostTestFramework",
- BoostTest::Constants::FRAMEWORK_SETTINGS_CATEGORY),
+ displayName(),
Utils::FilePath(), ITestTreeItem::Root);
}
@@ -51,6 +50,12 @@ const char *BoostTestFramework::name() const
return BoostTest::Constants::FRAMEWORK_NAME;
}
+QString BoostTestFramework::displayName() const
+{
+ return QCoreApplication::translate("BoostTestFramework",
+ BoostTest::Constants::FRAMEWORK_SETTINGS_CATEGORY);
+}
+
unsigned BoostTestFramework::priority() const
{
return BoostTest::Constants::FRAMEWORK_PRIORITY;
diff --git a/src/plugins/autotest/boost/boosttestframework.h b/src/plugins/autotest/boost/boosttestframework.h
index 2ca7b608699..91f2bdac0f6 100644
--- a/src/plugins/autotest/boost/boosttestframework.h
+++ b/src/plugins/autotest/boost/boosttestframework.h
@@ -39,6 +39,7 @@ public:
private:
const char *name() const override;
+ QString displayName() const override;
unsigned priority() const override;
ITestSettings *testSettings() override { return &m_settings; }
ITestParser *createTestParser() override;
diff --git a/src/plugins/autotest/boost/boosttestoutputreader.cpp b/src/plugins/autotest/boost/boosttestoutputreader.cpp
index 5036a683ff3..b87f9ab764b 100644
--- a/src/plugins/autotest/boost/boosttestoutputreader.cpp
+++ b/src/plugins/autotest/boost/boosttestoutputreader.cpp
@@ -29,6 +29,7 @@
#include "boosttesttreeitem.h"
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QDir>
#include <QFileInfo>
@@ -41,7 +42,7 @@ namespace Internal {
static Q_LOGGING_CATEGORY(orLog, "qtc.autotest.boost.outputreader", QtWarningMsg)
BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication,
+ Utils::QtcProcess *testApplication,
const Utils::FilePath &buildDirectory,
const Utils::FilePath &projectFile,
LogLevel log, ReportLevel report)
@@ -50,10 +51,8 @@ BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPt
, m_logLevel(log)
, m_reportLevel(report)
{
- if (m_testApplication) {
- connect(m_testApplication, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- this, &BoostTestOutputReader::onFinished);
- }
+ if (m_testApplication)
+ connect(m_testApplication, &Utils::QtcProcess::done, this, &BoostTestOutputReader::onDone);
}
// content of "error:..." / "info:..." / ... messages
@@ -405,7 +404,8 @@ TestResultPtr BoostTestOutputReader::createDefaultResult() const
return TestResultPtr(result);
}
-void BoostTestOutputReader::onFinished(int exitCode, QProcess::ExitStatus /*exitState*/) {
+void BoostTestOutputReader::onDone() {
+ int exitCode = m_testApplication->exitCode();
if (m_reportLevel == ReportLevel::No && m_testCaseCount != -1) {
int reportedFailsAndSkips = m_summary[ResultType::Fail] + m_summary[ResultType::Skip];
m_summary.insert(ResultType::Pass, m_testCaseCount - reportedFailsAndSkips);
diff --git a/src/plugins/autotest/boost/boosttestoutputreader.h b/src/plugins/autotest/boost/boosttestoutputreader.h
index 56527fa6271..2bfd9af3f94 100644
--- a/src/plugins/autotest/boost/boosttestoutputreader.h
+++ b/src/plugins/autotest/boost/boosttestoutputreader.h
@@ -39,7 +39,7 @@ class BoostTestOutputReader : public TestOutputReader
Q_OBJECT
public:
BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication, const Utils::FilePath &buildDirectory,
+ Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
const Utils::FilePath &projectFile, LogLevel log, ReportLevel report);
protected:
void processOutputLine(const QByteArray &outputLine) override;
@@ -47,7 +47,7 @@ protected:
TestResultPtr createDefaultResult() const override;
private:
- void onFinished(int exitCode, QProcess::ExitStatus /*exitState*/);
+ void onDone();
void sendCompleteInformation();
void handleMessageMatch(const QRegularExpressionMatch &match);
void reportNoOutputFinish(const QString &description, ResultType type);
diff --git a/src/plugins/autotest/catch/catchcodeparser.cpp b/src/plugins/autotest/catch/catchcodeparser.cpp
index c1368c1aa72..350b34f5dc6 100644
--- a/src/plugins/autotest/catch/catchcodeparser.cpp
+++ b/src/plugins/autotest/catch/catchcodeparser.cpp
@@ -90,22 +90,24 @@ void CatchCodeParser::handleIdentifier()
QTC_ASSERT(m_currentIndex < m_tokens.size(), return);
const Token &token = m_tokens.at(m_currentIndex);
const QByteArray &identifier = m_source.mid(int(token.bytesBegin()), int(token.bytes()));
- if (identifier == "TEST_CASE") {
+ const QByteArray unprefixed = identifier.startsWith("CATCH_") ? identifier.mid(6) : identifier;
+
+ if (unprefixed == "TEST_CASE") {
handleTestCase(false);
- } else if (identifier == "SCENARIO") {
+ } else if (unprefixed == "SCENARIO") {
handleTestCase(true);
- } else if (identifier == "TEMPLATE_TEST_CASE" || identifier == "TEMPLATE_PRODUCT_TEST_CASE"
- || identifier == "TEMPLATE_LIST_TEST_CASE" || identifier == "TEMPLATE_TEST_CASE_SIG"
- || identifier == "TEMPLATE_PRODUCT_TEST_CASE_SIG") {
+ } else if (unprefixed == "TEMPLATE_TEST_CASE" || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE"
+ || unprefixed == "TEMPLATE_LIST_TEST_CASE" || unprefixed == "TEMPLATE_TEST_CASE_SIG"
+ || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE_SIG") {
handleParameterizedTestCase(false);
- } else if (identifier == "TEST_CASE_METHOD") {
+ } else if (unprefixed == "TEST_CASE_METHOD") {
handleFixtureOrRegisteredTestCase(true);
- } else if (identifier == "TEMPLATE_TEST_CASE_METHOD_SIG"
- || identifier == "TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG"
- || identifier == "TEMPLATE_TEST_CASE_METHOD"
- || identifier == "TEMPLATE_LIST_TEST_CASE_METHOD") {
+ } else if (unprefixed == "TEMPLATE_TEST_CASE_METHOD_SIG"
+ || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG"
+ || unprefixed == "TEMPLATE_TEST_CASE_METHOD"
+ || unprefixed == "TEMPLATE_LIST_TEST_CASE_METHOD") {
handleParameterizedTestCase(true);
- } else if (identifier == "METHOD_AS_TEST_CASE" || identifier == "REGISTER_TEST_CASE") {
+ } else if (unprefixed == "METHOD_AS_TEST_CASE" || unprefixed == "REGISTER_TEST_CASE") {
handleFixtureOrRegisteredTestCase(false);
}
}
diff --git a/src/plugins/autotest/catch/catchconfiguration.cpp b/src/plugins/autotest/catch/catchconfiguration.cpp
index bb1353ff4a9..7d374413a51 100644
--- a/src/plugins/autotest/catch/catchconfiguration.cpp
+++ b/src/plugins/autotest/catch/catchconfiguration.cpp
@@ -35,7 +35,8 @@
namespace Autotest {
namespace Internal {
-TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi, QProcess *app) const
+TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
+ Utils::QtcProcess *app) const
{
return new CatchOutputReader(fi, app, buildDirectory(), projectFile());
}
@@ -97,7 +98,7 @@ QStringList CatchConfiguration::argumentsForTestRunner(QStringList *omitted) con
{
QStringList arguments;
if (testCaseCount())
- arguments << "\"" + testCases().join("\",\"") + "\"";
+ arguments << "\"" + testCases().join("\", \"") + "\"";
arguments << "--reporter" << "xml";
if (AutotestPlugin::settings()->processArgs) {
diff --git a/src/plugins/autotest/catch/catchconfiguration.h b/src/plugins/autotest/catch/catchconfiguration.h
index 2a198558098..ef3549514b5 100644
--- a/src/plugins/autotest/catch/catchconfiguration.h
+++ b/src/plugins/autotest/catch/catchconfiguration.h
@@ -34,7 +34,7 @@ class CatchConfiguration : public DebuggableTestConfiguration
public:
CatchConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {}
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const override;
+ Utils::QtcProcess *app) const override;
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
};
diff --git a/src/plugins/autotest/catch/catchframework.cpp b/src/plugins/autotest/catch/catchframework.cpp
index 754703bf711..defa59b10d3 100644
--- a/src/plugins/autotest/catch/catchframework.cpp
+++ b/src/plugins/autotest/catch/catchframework.cpp
@@ -35,6 +35,11 @@ const char *CatchFramework::name() const
return "Catch";
}
+QString CatchFramework::displayName() const
+{
+ return QCoreApplication::translate("CatchFramework", "Catch Test");
+}
+
unsigned CatchFramework::priority() const
{
return 12;
@@ -48,7 +53,7 @@ ITestParser *CatchFramework::createTestParser()
ITestTreeItem *CatchFramework::createRootNode()
{
return new CatchTreeItem(this,
- QCoreApplication::translate("CatchFramework", "Catch Test"),
+ displayName(),
Utils::FilePath(), ITestTreeItem::Root);
}
diff --git a/src/plugins/autotest/catch/catchframework.h b/src/plugins/autotest/catch/catchframework.h
index c49e79c9293..38de904f29a 100644
--- a/src/plugins/autotest/catch/catchframework.h
+++ b/src/plugins/autotest/catch/catchframework.h
@@ -37,6 +37,7 @@ public:
CatchFramework() : ITestFramework(true) {}
const char *name() const override;
+ QString displayName() const override;
unsigned priority() const override;
protected:
diff --git a/src/plugins/autotest/catch/catchoutputreader.cpp b/src/plugins/autotest/catch/catchoutputreader.cpp
index f7ae4d3bc8f..f788aea017c 100644
--- a/src/plugins/autotest/catch/catchoutputreader.cpp
+++ b/src/plugins/autotest/catch/catchoutputreader.cpp
@@ -49,7 +49,8 @@ namespace CatchXml {
}
CatchOutputReader::CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication, const Utils::FilePath &buildDirectory,
+ Utils::QtcProcess *testApplication,
+ const Utils::FilePath &buildDirectory,
const Utils::FilePath &projectFile)
: TestOutputReader (futureInterface, testApplication, buildDirectory)
, m_projectFile(projectFile)
diff --git a/src/plugins/autotest/catch/catchoutputreader.h b/src/plugins/autotest/catch/catchoutputreader.h
index 70158309617..86c3acbb034 100644
--- a/src/plugins/autotest/catch/catchoutputreader.h
+++ b/src/plugins/autotest/catch/catchoutputreader.h
@@ -39,7 +39,7 @@ class CatchOutputReader : public TestOutputReader
public:
CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication, const Utils::FilePath &buildDirectory,
+ Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
const Utils::FilePath &projectFile);
protected:
diff --git a/src/plugins/autotest/catch/catchtestparser.cpp b/src/plugins/autotest/catch/catchtestparser.cpp
index da6f6ca423a..c878da135e3 100644
--- a/src/plugins/autotest/catch/catchtestparser.cpp
+++ b/src/plugins/autotest/catch/catchtestparser.cpp
@@ -57,10 +57,11 @@ static bool isCatchTestCaseMacro(const QString &macroName)
static bool isCatchMacro(const QString &macroName)
{
+ QString unprefixed = macroName.startsWith("CATCH_") ? macroName.mid(6) : macroName;
const QStringList validSectionMacros = {
QStringLiteral("SECTION"), QStringLiteral("WHEN")
};
- return isCatchTestCaseMacro(macroName) || validSectionMacros.contains(macroName);
+ return isCatchTestCaseMacro(unprefixed) || validSectionMacros.contains(unprefixed);
}
static bool includesCatchHeader(const CPlusPlus::Document::Ptr &doc,
@@ -123,7 +124,8 @@ bool CatchTestParser::processDocument(QFutureInterface<TestParseResultPtr> &futu
const QByteArray &fileContent = getFileContent(fileName);
if (!hasCatchNames(doc)) {
- const QRegularExpression regex("\\b(SCENARIO|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|"
+ const QRegularExpression regex("\\b(CATCH_)?"
+ "(SCENARIO|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|"
"TEMPLATE_TEST_CASE(_METHOD)?_SIG|"
"TEMPLATE_PRODUCT_TEST_CASE(_METHOD)?_SIG|"
"TEMPLATE_LIST_TEST_CASE_METHOD|METHOD_AS_TEST_CASE|"
diff --git a/src/plugins/autotest/catch/catchtreeitem.cpp b/src/plugins/autotest/catch/catchtreeitem.cpp
index 0108811008c..462f03dba84 100644
--- a/src/plugins/autotest/catch/catchtreeitem.cpp
+++ b/src/plugins/autotest/catch/catchtreeitem.cpp
@@ -37,7 +37,9 @@ namespace Internal {
QString CatchTreeItem::testCasesString() const
{
- return m_state & CatchTreeItem::Parameterized ? QString(name() + " -*") : name();
+ QString testcase = m_state & CatchTreeItem::Parameterized ? QString(name() + " -*") : name();
+ // mask comma if it is part of the test case name
+ return testcase.replace(',', "\\,");
}
static QString nonRootDisplayName(const CatchTreeItem *it)
diff --git a/src/plugins/autotest/ctest/ctestconfiguration.cpp b/src/plugins/autotest/ctest/ctestconfiguration.cpp
index de2a94061e1..2a1d18389fb 100644
--- a/src/plugins/autotest/ctest/ctestconfiguration.cpp
+++ b/src/plugins/autotest/ctest/ctestconfiguration.cpp
@@ -36,7 +36,7 @@ CTestConfiguration::CTestConfiguration(ITestBase *testBase)
}
TestOutputReader *CTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const
+ Utils::QtcProcess *app) const
{
return new CTestOutputReader(fi, app, workingDirectory());
}
diff --git a/src/plugins/autotest/ctest/ctestconfiguration.h b/src/plugins/autotest/ctest/ctestconfiguration.h
index 77f7904ab31..3c62c7ea843 100644
--- a/src/plugins/autotest/ctest/ctestconfiguration.h
+++ b/src/plugins/autotest/ctest/ctestconfiguration.h
@@ -36,7 +36,7 @@ public:
explicit CTestConfiguration(ITestBase *testBase);
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const final;
+ Utils::QtcProcess *app) const final;
};
} // namespace Internal
diff --git a/src/plugins/autotest/ctest/ctestoutputreader.cpp b/src/plugins/autotest/ctest/ctestoutputreader.cpp
index 93315c0bea6..e9bd1f465d3 100644
--- a/src/plugins/autotest/ctest/ctestoutputreader.cpp
+++ b/src/plugins/autotest/ctest/ctestoutputreader.cpp
@@ -71,7 +71,7 @@ private:
};
CTestOutputReader::CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication,
+ Utils::QtcProcess *testApplication,
const Utils::FilePath &buildDirectory)
: TestOutputReader(futureInterface, testApplication, buildDirectory)
{
diff --git a/src/plugins/autotest/ctest/ctestoutputreader.h b/src/plugins/autotest/ctest/ctestoutputreader.h
index bbec3f70c77..205325fe1f7 100644
--- a/src/plugins/autotest/ctest/ctestoutputreader.h
+++ b/src/plugins/autotest/ctest/ctestoutputreader.h
@@ -28,6 +28,8 @@
#include <QCoreApplication>
+namespace Utils { class QtcProcess; }
+
namespace Autotest {
namespace Internal {
@@ -36,7 +38,7 @@ class CTestOutputReader final : public Autotest::TestOutputReader
Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::CTestOutputReader)
public:
CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication, const Utils::FilePath &buildDirectory);
+ Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory);
protected:
void processOutputLine(const QByteArray &outputLineWithNewLine) final;
diff --git a/src/plugins/autotest/ctest/ctesttool.cpp b/src/plugins/autotest/ctest/ctesttool.cpp
index 4db818581eb..0f9bd8eecaf 100644
--- a/src/plugins/autotest/ctest/ctesttool.cpp
+++ b/src/plugins/autotest/ctest/ctesttool.cpp
@@ -50,10 +50,15 @@ const char *CTestTool::name() const
return "CTest";
}
+QString CTestTool::displayName() const
+{
+ return QCoreApplication::translate("CTestTool", "CTest");
+}
+
ITestTreeItem *CTestTool::createRootNode()
{
return new CTestTreeItem(this,
- QCoreApplication::translate("CTestTool", "CTest"),
+ displayName(),
Utils::FilePath(), ITestTreeItem::Root);
}
diff --git a/src/plugins/autotest/ctest/ctesttool.h b/src/plugins/autotest/ctest/ctesttool.h
index ff0d3b75221..232a3a0f12d 100644
--- a/src/plugins/autotest/ctest/ctesttool.h
+++ b/src/plugins/autotest/ctest/ctesttool.h
@@ -42,6 +42,7 @@ public:
protected:
const char *name() const final;
+ QString displayName() const final;
ITestTreeItem *createRootNode() final;
private:
diff --git a/src/plugins/autotest/ctest/ctesttreeitem.cpp b/src/plugins/autotest/ctest/ctesttreeitem.cpp
index 5e08d62c488..c374754d652 100644
--- a/src/plugins/autotest/ctest/ctesttreeitem.cpp
+++ b/src/plugins/autotest/ctest/ctesttreeitem.cpp
@@ -32,6 +32,7 @@
#include "../itestframework.h"
#include "../testsettings.h"
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/project.h>
diff --git a/src/plugins/autotest/gtest/gtestconfiguration.cpp b/src/plugins/autotest/gtest/gtestconfiguration.cpp
index ff60f32171c..025040f54c8 100644
--- a/src/plugins/autotest/gtest/gtestconfiguration.cpp
+++ b/src/plugins/autotest/gtest/gtestconfiguration.cpp
@@ -38,7 +38,7 @@ namespace Autotest {
namespace Internal {
TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const
+ Utils::QtcProcess *app) const
{
return new GTestOutputReader(fi, app, buildDirectory(), projectFile());
}
diff --git a/src/plugins/autotest/gtest/gtestconfiguration.h b/src/plugins/autotest/gtest/gtestconfiguration.h
index 822ad99fd1b..3844869a4b9 100644
--- a/src/plugins/autotest/gtest/gtestconfiguration.h
+++ b/src/plugins/autotest/gtest/gtestconfiguration.h
@@ -37,7 +37,7 @@ public:
: DebuggableTestConfiguration(framework) {}
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const override;
+ Utils::QtcProcess *app) const override;
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
};
diff --git a/src/plugins/autotest/gtest/gtestframework.cpp b/src/plugins/autotest/gtest/gtestframework.cpp
index b093417324b..ec84108d68b 100644
--- a/src/plugins/autotest/gtest/gtestframework.cpp
+++ b/src/plugins/autotest/gtest/gtestframework.cpp
@@ -48,8 +48,7 @@ ITestTreeItem *GTestFramework::createRootNode()
{
return new GTestTreeItem(
this,
- QCoreApplication::translate("GTestFramework",
- GTest::Constants::FRAMEWORK_SETTINGS_CATEGORY),
+ displayName(),
Utils::FilePath(), ITestTreeItem::Root);
}
@@ -58,6 +57,12 @@ const char *GTestFramework::name() const
return GTest::Constants::FRAMEWORK_NAME;
}
+QString GTestFramework:: displayName() const
+{
+ return QCoreApplication::translate("GTestFramework",
+ GTest::Constants::FRAMEWORK_SETTINGS_CATEGORY);
+}
+
unsigned GTestFramework::priority() const
{
return GTest::Constants::FRAMEWORK_PRIORITY;
diff --git a/src/plugins/autotest/gtest/gtestframework.h b/src/plugins/autotest/gtest/gtestframework.h
index c7504d28e36..185b37ec98e 100644
--- a/src/plugins/autotest/gtest/gtestframework.h
+++ b/src/plugins/autotest/gtest/gtestframework.h
@@ -42,6 +42,7 @@ public:
private:
const char *name() const override;
+ QString displayName() const override;
unsigned priority() const override;
QString groupingToolTip() const override;
ITestSettings *testSettings() override { return &m_settings; }
diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp
index 997e7d2ddc2..4935b6599b3 100644
--- a/src/plugins/autotest/gtest/gtestoutputreader.cpp
+++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp
@@ -28,6 +28,7 @@
#include "../testtreemodel.h"
#include "../testtreeitem.h"
#include <utils/hostosinfo.h>
+#include <utils/qtcprocess.h>
#include <QDir>
#include <QFileInfo>
@@ -37,18 +38,18 @@ namespace Autotest {
namespace Internal {
GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication,
+ Utils::QtcProcess *testApplication,
const Utils::FilePath &buildDirectory,
const Utils::FilePath &projectFile)
: TestOutputReader(futureInterface, testApplication, buildDirectory)
, m_projectFile(projectFile)
{
if (m_testApplication) {
- connect(m_testApplication, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- this, [this] (int exitCode, QProcess::ExitStatus /*exitStatus*/) {
+ connect(m_testApplication, &Utils::QtcProcess::done, this, [this] {
+ const int exitCode = m_testApplication->exitCode();
if (exitCode == 1 && !m_description.isEmpty()) {
createAndReportResult(tr("Running tests failed.\n %1\nExecutable: %2")
- .arg(m_description).arg(id()), ResultType::MessageFatal);
+ .arg(m_description).arg(id()), ResultType::MessageFatal);
}
// on Windows abort() will result in normal termination, but exit code will be set to 3
if (Utils::HostOsInfo::isWindowsHost() && exitCode == 3)
diff --git a/src/plugins/autotest/gtest/gtestoutputreader.h b/src/plugins/autotest/gtest/gtestoutputreader.h
index 05688a4fa2b..f6d499dbed5 100644
--- a/src/plugins/autotest/gtest/gtestoutputreader.h
+++ b/src/plugins/autotest/gtest/gtestoutputreader.h
@@ -38,7 +38,7 @@ class GTestOutputReader : public TestOutputReader
public:
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication, const Utils::FilePath &buildDirectory,
+ Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
const Utils::FilePath &projectFile);
protected:
void processOutputLine(const QByteArray &outputLine) override;
diff --git a/src/plugins/autotest/itestframework.h b/src/plugins/autotest/itestframework.h
index 6b30c70dd0e..acfd9592b9b 100644
--- a/src/plugins/autotest/itestframework.h
+++ b/src/plugins/autotest/itestframework.h
@@ -53,6 +53,7 @@ public:
virtual ~ITestBase() = default;
virtual const char *name() const = 0;
+ virtual QString displayName() const = 0;
virtual unsigned priority() const = 0; // should this be modifyable?
TestBaseType type() const { return m_type; }
diff --git a/src/plugins/autotest/loadprojectscenario.cpp b/src/plugins/autotest/loadprojectscenario.cpp
index 2fa5c74636b..1150e47dc44 100644
--- a/src/plugins/autotest/loadprojectscenario.cpp
+++ b/src/plugins/autotest/loadprojectscenario.cpp
@@ -32,6 +32,8 @@
#include <utils/algorithm.h>
+#include <QDebug>
+
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;
diff --git a/src/plugins/autotest/projectsettingswidget.cpp b/src/plugins/autotest/projectsettingswidget.cpp
index f4ede604fcf..11841f56c27 100644
--- a/src/plugins/autotest/projectsettingswidget.cpp
+++ b/src/plugins/autotest/projectsettingswidget.cpp
@@ -25,6 +25,7 @@
#include "projectsettingswidget.h"
+#include "autotestconstants.h"
#include "autotestplugin.h"
#include "testframeworkmanager.h"
#include "testprojectsettings.h"
@@ -53,14 +54,12 @@ static QSpacerItem *createSpacer(QSizePolicy::Policy horizontal, QSizePolicy::Po
ProjectTestSettingsWidget::ProjectTestSettingsWidget(ProjectExplorer::Project *project,
QWidget *parent)
- : QWidget(parent)
+ : ProjectExplorer::ProjectSettingsWidget(parent)
, m_projectSettings(AutotestPlugin::projectSettings(project))
{
+ setGlobalSettingsId(Constants::AUTOTEST_SETTINGS_ID);
auto verticalLayout = new QVBoxLayout(this);
verticalLayout->setContentsMargins(0, 0, 0, 0);
- m_useGlobalSettings = new QComboBox;
- m_useGlobalSettings->addItem(tr("Global"));
- m_useGlobalSettings->addItem(tr("Custom"));
auto generalWidget = new QWidget;
auto groupBoxLayout = new QVBoxLayout;
@@ -83,29 +82,26 @@ ProjectTestSettingsWidget::ProjectTestSettingsWidget(ProjectExplorer::Project *p
generalWidget->setLayout(groupBoxLayout);
horizontalLayout = new QHBoxLayout;
- horizontalLayout->addWidget(m_useGlobalSettings);
- horizontalLayout->addItem(createSpacer(QSizePolicy::Expanding, QSizePolicy::Minimum));
- verticalLayout->addLayout(horizontalLayout);
- horizontalLayout = new QHBoxLayout;
verticalLayout->addItem(createSpacer(QSizePolicy::Minimum, QSizePolicy::Fixed));
horizontalLayout->addWidget(generalWidget);
horizontalLayout->addItem(createSpacer(QSizePolicy::Expanding, QSizePolicy::Minimum));
verticalLayout->addLayout(horizontalLayout);
verticalLayout->addItem(createSpacer(QSizePolicy::Minimum, QSizePolicy::Expanding));
- m_useGlobalSettings->setCurrentIndex(m_projectSettings->useGlobalSettings() ? 0 : 1);
generalWidget->setDisabled(m_projectSettings->useGlobalSettings());
populateFrameworks(m_projectSettings->activeFrameworks(),
m_projectSettings->activeTestTools());
- connect(m_useGlobalSettings, QOverload<int>::of(&QComboBox::currentIndexChanged),
- this, [this, generalWidget](int index) {
- generalWidget->setEnabled(index != 0);
- m_projectSettings->setUseGlobalSettings(index == 0);
- m_syncTimer.start(3000);
- m_syncType = ITestBase::Framework | ITestBase::Tool;
- });
+ setUseGlobalSettings(m_projectSettings->useGlobalSettings());
+ connect(this, &ProjectSettingsWidget::useGlobalSettingsChanged,
+ this, [this, generalWidget](bool useGlobalSettings) {
+ generalWidget->setEnabled(!useGlobalSettings);
+ m_projectSettings->setUseGlobalSettings(useGlobalSettings);
+ m_syncTimer.start(3000);
+ m_syncType = ITestBase::Framework | ITestBase::Tool;
+ });
+
connect(m_activeFrameworks, &QTreeWidget::itemChanged,
this, &ProjectTestSettingsWidget::onActiveFrameworkChanged);
connect(m_runAfterBuild, QOverload<int>::of(&QComboBox::currentIndexChanged),
@@ -131,7 +127,7 @@ void ProjectTestSettingsWidget::populateFrameworks(const QHash<ITestFramework *,
Utils::sort(sortedFrameworks, &ITestFramework::priority);
auto generateItem = [this](ITestBase *frameworkOrTestTool, bool checked) {
- auto item = new QTreeWidgetItem(m_activeFrameworks, {QLatin1String(frameworkOrTestTool->name())});
+ auto item = new QTreeWidgetItem(m_activeFrameworks, {frameworkOrTestTool->displayName()});
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
item->setData(0, BaseIdRole, frameworkOrTestTool->id().toSetting());
diff --git a/src/plugins/autotest/projectsettingswidget.h b/src/plugins/autotest/projectsettingswidget.h
index b11429e9675..c6119048600 100644
--- a/src/plugins/autotest/projectsettingswidget.h
+++ b/src/plugins/autotest/projectsettingswidget.h
@@ -25,6 +25,8 @@
#pragma once
+#include <projectexplorer/projectsettingswidget.h>
+
#include <QTimer>
#include <QWidget>
@@ -45,12 +47,13 @@ namespace Internal {
class TestProjectSettings;
-class ProjectTestSettingsWidget : public QWidget
+class ProjectTestSettingsWidget : public ProjectExplorer::ProjectSettingsWidget
{
Q_OBJECT
public:
explicit ProjectTestSettingsWidget(ProjectExplorer::Project *project,
QWidget *parent = nullptr);
+
private:
void populateFrameworks(const QHash<Autotest::ITestFramework *, bool> &frameworks,
const QHash<Autotest::ITestTool *, bool> &testTools);
diff --git a/src/plugins/autotest/qtest/qttestconfiguration.cpp b/src/plugins/autotest/qtest/qttestconfiguration.cpp
index 7f613702137..4ca1326ba52 100644
--- a/src/plugins/autotest/qtest/qttestconfiguration.cpp
+++ b/src/plugins/autotest/qtest/qttestconfiguration.cpp
@@ -38,7 +38,7 @@ namespace Autotest {
namespace Internal {
TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const
+ Utils::QtcProcess *app) const
{
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
diff --git a/src/plugins/autotest/qtest/qttestconfiguration.h b/src/plugins/autotest/qtest/qttestconfiguration.h
index 8196665679c..83ac6d79a53 100644
--- a/src/plugins/autotest/qtest/qttestconfiguration.h
+++ b/src/plugins/autotest/qtest/qttestconfiguration.h
@@ -36,7 +36,7 @@ public:
explicit QtTestConfiguration(ITestFramework *framework)
: DebuggableTestConfiguration(framework) {}
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const override;
+ Utils::QtcProcess *app) const override;
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
};
diff --git a/src/plugins/autotest/qtest/qttestframework.cpp b/src/plugins/autotest/qtest/qttestframework.cpp
index 23646e43d93..15686c57c96 100644
--- a/src/plugins/autotest/qtest/qttestframework.cpp
+++ b/src/plugins/autotest/qtest/qttestframework.cpp
@@ -40,8 +40,7 @@ ITestTreeItem *QtTestFramework::createRootNode()
{
return new QtTestTreeItem(
this,
- QCoreApplication::translate("QtTestFramework",
- QtTest::Constants::FRAMEWORK_SETTINGS_CATEGORY),
+ displayName(),
Utils::FilePath(), ITestTreeItem::Root);
}
@@ -50,6 +49,12 @@ const char *QtTestFramework::name() const
return QtTest::Constants::FRAMEWORK_NAME;
}
+QString QtTestFramework::displayName() const
+{
+ return QCoreApplication::translate("QtTestFramework",
+ QtTest::Constants::FRAMEWORK_SETTINGS_CATEGORY);
+}
+
unsigned QtTestFramework::priority() const
{
return QtTest::Constants::FRAMEWORK_PRIORITY;
diff --git a/src/plugins/autotest/qtest/qttestframework.h b/src/plugins/autotest/qtest/qttestframework.h
index d75e07044be..e02f3c16dd6 100644
--- a/src/plugins/autotest/qtest/qttestframework.h
+++ b/src/plugins/autotest/qtest/qttestframework.h
@@ -39,6 +39,7 @@ public:
private:
const char *name() const override;
+ QString displayName() const override;
unsigned priority() const override;
ITestParser *createTestParser() override;
ITestTreeItem *createRootNode() override;
diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp
index a6be21019d9..fc762bbe0a4 100644
--- a/src/plugins/autotest/qtest/qttestoutputreader.cpp
+++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp
@@ -126,7 +126,7 @@ static QString constructBenchmarkInformation(const QString &metric, double value
}
QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication,
+ Utils::QtcProcess *testApplication,
const Utils::FilePath &buildDirectory,
const Utils::FilePath &projectFile,
OutputMode mode, TestType type)
diff --git a/src/plugins/autotest/qtest/qttestoutputreader.h b/src/plugins/autotest/qtest/qttestoutputreader.h
index eff84dd4642..6ceabd508b5 100644
--- a/src/plugins/autotest/qtest/qttestoutputreader.h
+++ b/src/plugins/autotest/qtest/qttestoutputreader.h
@@ -48,7 +48,7 @@ public:
};
QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication, const Utils::FilePath &buildDirectory,
+ Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
const Utils::FilePath &projectFile, OutputMode mode, TestType type);
protected:
void processOutputLine(const QByteArray &outputLine) override;
diff --git a/src/plugins/autotest/qtest/qttestresult.cpp b/src/plugins/autotest/qtest/qttestresult.cpp
index aa16f601963..eee2697ff71 100644
--- a/src/plugins/autotest/qtest/qttestresult.cpp
+++ b/src/plugins/autotest/qtest/qttestresult.cpp
@@ -52,7 +52,9 @@ const QString QtTestResult::outputString(bool selected) const
case ResultType::UnexpectedPass:
case ResultType::BlacklistedFail:
case ResultType::BlacklistedPass:
- output = className + "::" + m_function;
+ output = className;
+ if (!m_function.isEmpty())
+ output.append("::" + m_function);
if (!m_dataTag.isEmpty())
output.append(QString(" (%1)").arg(m_dataTag));
if (selected && !desc.isEmpty()) {
@@ -60,7 +62,9 @@ const QString QtTestResult::outputString(bool selected) const
}
break;
case ResultType::Benchmark:
- output = className + "::" + m_function;
+ output = className;
+ if (!m_function.isEmpty())
+ output.append("::" + m_function);
if (!m_dataTag.isEmpty())
output.append(QString(" (%1)").arg(m_dataTag));
if (!desc.isEmpty()) {
diff --git a/src/plugins/autotest/qtest/qttestsettings.cpp b/src/plugins/autotest/qtest/qttestsettings.cpp
index a8d5626aa1a..486b831766d 100644
--- a/src/plugins/autotest/qtest/qttestsettings.cpp
+++ b/src/plugins/autotest/qtest/qttestsettings.cpp
@@ -28,6 +28,7 @@
#include "../autotestconstants.h"
#include "qttestconstants.h"
+#include <utils/hostosinfo.h>
#include <utils/layoutbuilder.h>
using namespace Utils;
diff --git a/src/plugins/autotest/quick/quicktest_utils.cpp b/src/plugins/autotest/quick/quicktest_utils.cpp
index c25009a1ff7..68147dbb3f1 100644
--- a/src/plugins/autotest/quick/quicktest_utils.cpp
+++ b/src/plugins/autotest/quick/quicktest_utils.cpp
@@ -35,11 +35,10 @@ namespace Autotest {
namespace Internal {
namespace QuickTestUtils {
-static const QByteArrayList valid = {"QUICK_TEST_MAIN", "QUICK_TEST_OPENGL_MAIN",
- "QUICK_TEST_MAIN_WITH_SETUP"};
-
bool isQuickTestMacro(const QByteArray &macro)
{
+ static const QByteArrayList valid = {"QUICK_TEST_MAIN", "QUICK_TEST_OPENGL_MAIN",
+ "QUICK_TEST_MAIN_WITH_SETUP"};
return valid.contains(macro);
}
diff --git a/src/plugins/autotest/quick/quicktestconfiguration.cpp b/src/plugins/autotest/quick/quicktestconfiguration.cpp
index 8ede65e66bc..9cb1abb680e 100644
--- a/src/plugins/autotest/quick/quicktestconfiguration.cpp
+++ b/src/plugins/autotest/quick/quicktestconfiguration.cpp
@@ -44,7 +44,7 @@ QuickTestConfiguration::QuickTestConfiguration(ITestFramework *framework)
}
TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const
+ Utils::QtcProcess *app) const
{
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
diff --git a/src/plugins/autotest/quick/quicktestconfiguration.h b/src/plugins/autotest/quick/quicktestconfiguration.h
index 88f94c96df9..ca74633a912 100644
--- a/src/plugins/autotest/quick/quicktestconfiguration.h
+++ b/src/plugins/autotest/quick/quicktestconfiguration.h
@@ -35,7 +35,7 @@ class QuickTestConfiguration : public DebuggableTestConfiguration
public:
explicit QuickTestConfiguration(ITestFramework *framework);
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const override;
+ Utils::QtcProcess *app) const override;
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
};
diff --git a/src/plugins/autotest/quick/quicktestframework.cpp b/src/plugins/autotest/quick/quicktestframework.cpp
index e4fecb1daf0..1a72669ae88 100644
--- a/src/plugins/autotest/quick/quicktestframework.cpp
+++ b/src/plugins/autotest/quick/quicktestframework.cpp
@@ -41,7 +41,7 @@ ITestParser *QuickTestFramework::createTestParser()
ITestTreeItem *QuickTestFramework::createRootNode()
{
- return new QuickTestTreeItem(this, QCoreApplication::translate("QuickTestFramework", "Quick Test"),
+ return new QuickTestTreeItem(this, displayName(),
Utils::FilePath(), ITestTreeItem::Root);
}
@@ -50,6 +50,11 @@ const char *QuickTestFramework::name() const
return QuickTest::Constants::FRAMEWORK_NAME;
}
+QString QuickTestFramework::displayName() const
+{
+ return QCoreApplication::translate("QuickTestFramework", "Quick Test");
+}
+
unsigned QuickTestFramework::priority() const
{
return 5;
diff --git a/src/plugins/autotest/quick/quicktestframework.h b/src/plugins/autotest/quick/quicktestframework.h
index 316a5a9f380..1600e03f34d 100644
--- a/src/plugins/autotest/quick/quicktestframework.h
+++ b/src/plugins/autotest/quick/quicktestframework.h
@@ -43,6 +43,7 @@ class QuickTestFramework : public ITestFramework
public:
QuickTestFramework() : ITestFramework(true) {}
const char *name() const override;
+ QString displayName() const override;
unsigned priority() const override;
ITestSettings *testSettings() override;
diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp
index 2cbb7868724..fbb497cbaa2 100644
--- a/src/plugins/autotest/quick/quicktestparser.cpp
+++ b/src/plugins/autotest/quick/quicktestparser.cpp
@@ -126,7 +126,7 @@ QString QuickTestParser::quickTestName(const CPlusPlus::Document::Ptr &doc) cons
const Utils::FilePath filePath = Utils::FilePath::fromString(doc->fileName());
for (const CPlusPlus::Document::MacroUse &macro : macros) {
- if (!macro.isFunctionLike())
+ if (!macro.isFunctionLike() || macro.arguments().isEmpty())
continue;
const QByteArray name = macro.macro().name();
if (QuickTestUtils::isQuickTestMacro(name)) {
@@ -137,7 +137,7 @@ QString QuickTestParser::quickTestName(const CPlusPlus::Document::Ptr &doc) cons
}
- const QByteArray &fileContent = getFileContent(filePath);
+ const QByteArray fileContent = getFileContent(filePath);
// check for using quick_test_main() directly
CPlusPlus::Document::Ptr document = m_cppSnapshot.preprocessedDocument(fileContent, filePath);
if (document.isNull())
diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp
index 4599fc7606b..e00c2bf2fcf 100644
--- a/src/plugins/autotest/testconfiguration.cpp
+++ b/src/plugins/autotest/testconfiguration.cpp
@@ -83,8 +83,8 @@ FilePath ITestConfiguration::executableFilePath() const
if (!hasExecutable())
return {};
- const Environment env = m_runnable.environment.size() == 0 ? Environment::systemEnvironment()
- : m_runnable.environment;
+ const Environment env = m_runnable.environment.isValid()
+ ? m_runnable.environment : Environment::systemEnvironment();
return env.searchInPath(m_runnable.command.executable().path());
}
diff --git a/src/plugins/autotest/testconfiguration.h b/src/plugins/autotest/testconfiguration.h
index a1a4240f3dd..e338280a954 100644
--- a/src/plugins/autotest/testconfiguration.h
+++ b/src/plugins/autotest/testconfiguration.h
@@ -35,9 +35,7 @@
#include <QPointer>
#include <QStringList>
-QT_BEGIN_NAMESPACE
-class QProcess;
-QT_END_NAMESPACE
+namespace Utils { class QtcProcess; }
namespace Autotest {
namespace Internal {
@@ -66,7 +64,7 @@ public:
Utils::FilePath executableFilePath() const;
virtual TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
- QProcess *app) const = 0;
+ Utils::QtcProcess *app) const = 0;
virtual Utils::Environment filteredEnvironment(const Utils::Environment &original) const;
ITestBase *testBase() const { return m_testBase; }
diff --git a/src/plugins/autotest/testframeworkmanager.cpp b/src/plugins/autotest/testframeworkmanager.cpp
index 0352a3dd61b..2d3b7508834 100644
--- a/src/plugins/autotest/testframeworkmanager.cpp
+++ b/src/plugins/autotest/testframeworkmanager.cpp
@@ -49,6 +49,7 @@ TestFrameworkManager::TestFrameworkManager()
TestFrameworkManager::~TestFrameworkManager()
{
qDeleteAll(m_registeredFrameworks);
+ qDeleteAll(m_registeredTestTools);
s_instance = nullptr;
}
diff --git a/src/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp
index f2ad3bff054..fcd0ace2300 100644
--- a/src/plugins/autotest/testoutputreader.cpp
+++ b/src/plugins/autotest/testoutputreader.cpp
@@ -30,6 +30,7 @@
#include "testtreeitem.h"
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QDebug>
#include <QDir>
@@ -46,11 +47,12 @@ Utils::FilePath TestOutputReader::constructSourceFilePath(const Utils::FilePath
}
TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication, const Utils::FilePath &buildDirectory)
+ Utils::QtcProcess *testApplication,
+ const Utils::FilePath &buildDirectory)
: m_futureInterface(futureInterface)
, m_testApplication(testApplication)
, m_buildDir(buildDirectory)
- , m_id(testApplication ? testApplication->program() : QString())
+ , m_id(testApplication ? testApplication->commandLine().executable().toUserOutput() : QString())
{
auto chopLineBreak = [](QByteArray line) {
if (line.endsWith('\n'))
@@ -61,17 +63,11 @@ TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &future
};
if (m_testApplication) {
- connect(m_testApplication, &QProcess::readyReadStandardOutput,
- this, [chopLineBreak, this] () {
- m_testApplication->setReadChannel(QProcess::StandardOutput);
- while (m_testApplication->canReadLine())
- processStdOutput(chopLineBreak(m_testApplication->readLine()));
+ m_testApplication->setStdOutLineCallback([this, &chopLineBreak](const QString &line) {
+ processStdOutput(chopLineBreak(line.toUtf8()));
});
- connect(m_testApplication, &QProcess::readyReadStandardError,
- this, [chopLineBreak, this] () {
- m_testApplication->setReadChannel(QProcess::StandardError);
- while (m_testApplication->canReadLine())
- processStdError(chopLineBreak(m_testApplication->readLine()));
+ m_testApplication->setStdErrLineCallback([this, &chopLineBreak](const QString &line) {
+ processStdError(chopLineBreak(line.toUtf8()));
});
}
}
diff --git a/src/plugins/autotest/testoutputreader.h b/src/plugins/autotest/testoutputreader.h
index b3d7cc3476d..4f5d75b471c 100644
--- a/src/plugins/autotest/testoutputreader.h
+++ b/src/plugins/autotest/testoutputreader.h
@@ -29,9 +29,10 @@
#include <QFutureInterface>
#include <QObject>
-#include <QProcess>
#include <QString>
+namespace Utils { class QtcProcess; }
+
namespace Autotest {
class TestOutputReader : public QObject
@@ -39,7 +40,7 @@ class TestOutputReader : public QObject
Q_OBJECT
public:
TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
- QProcess *testApplication, const Utils::FilePath &buildDirectory);
+ Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory);
virtual ~TestOutputReader();
void processStdOutput(const QByteArray &outputLine);
virtual void processStdError(const QByteArray &outputLine);
@@ -67,7 +68,7 @@ protected:
void reportResult(const TestResultPtr &result);
QFutureInterface<TestResultPtr> m_futureInterface;
- QProcess *m_testApplication; // not owned
+ Utils::QtcProcess *m_testApplication; // not owned
Utils::FilePath m_buildDir;
QString m_id;
QHash<ResultType, int> m_summary;
diff --git a/src/plugins/autotest/testrunconfiguration.h b/src/plugins/autotest/testrunconfiguration.h
index 451add1fa2b..ccb6282059b 100644
--- a/src/plugins/autotest/testrunconfiguration.h
+++ b/src/plugins/autotest/testrunconfiguration.h
@@ -66,7 +66,7 @@ public:
ProjectExplorer::Runnable r;
QTC_ASSERT(m_testConfig, return r);
r.command.setExecutable(m_testConfig->executableFilePath());
- r.command.setArguments(m_testConfig->argumentsForTestRunner().join(' '));
+ r.command.addArgs(m_testConfig->argumentsForTestRunner().join(' '), Utils::CommandLine::Raw);
r.workingDirectory = m_testConfig->workingDirectory();
r.environment = m_testConfig->environment();
return r;
diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp
index 8dac62a4ed8..90c4f72a1d0 100644
--- a/src/plugins/autotest/testrunner.cpp
+++ b/src/plugins/autotest/testrunner.cpp
@@ -90,6 +90,8 @@ TestRunner::TestRunner()
{
s_instance = this;
+ m_cancelTimer.setSingleShot(true);
+ connect(&m_cancelTimer, &QTimer::timeout, this, [this]() { cancelCurrent(Timeout); });
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::resultReadyAt,
this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); });
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::finished,
@@ -131,16 +133,17 @@ void TestRunner::runTest(TestRunMode mode, const ITestTreeItem *item)
}
}
-static QString processInformation(const QProcess *proc)
+static QString processInformation(const QtcProcess *proc)
{
QTC_ASSERT(proc, return QString());
- QString information("\nCommand line: " + proc->program() + ' ' + proc->arguments().join(' '));
+ const Utils::CommandLine command = proc->commandLine();
+ QString information("\nCommand line: " + command.executable().toUserOutput() + ' ' + command.arguments());
QStringList important = { "PATH" };
if (Utils::HostOsInfo::isLinuxHost())
important.append("LD_LIBRARY_PATH");
else if (Utils::HostOsInfo::isMacHost())
important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" });
- const QProcessEnvironment &environment = proc->processEnvironment();
+ const Utils::Environment &environment = proc->environment();
for (const QString &var : important)
information.append('\n' + var + ": " + environment.value(var));
return information;
@@ -194,7 +197,7 @@ bool TestRunner::currentConfigValid()
m_fakeFutureInterface->reportFinished();
onFinished();
} else {
- onProcessFinished();
+ onProcessDone();
}
return false;
}
@@ -204,34 +207,35 @@ bool TestRunner::currentConfigValid()
void TestRunner::setUpProcess()
{
QTC_ASSERT(m_currentConfig, return);
- m_currentProcess = new QProcess;
- m_currentProcess->setReadChannel(QProcess::StandardOutput);
+ m_currentProcess = new QtcProcess;
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
- m_currentProcess->setProgram(current->executableFilePath().toString());
+ m_currentProcess->setCommand({current->executableFilePath(), {}});
} else {
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
- m_currentProcess->setProgram(current->commandLine().executable().toString());
+ m_currentProcess->setCommand({current->commandLine().executable(), {}});
}
}
void TestRunner::setUpProcessEnv()
{
+ Utils::CommandLine command = m_currentProcess->commandLine();
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
QStringList omitted;
- m_currentProcess->setArguments(current->argumentsForTestRunner(&omitted));
+ command.addArgs(current->argumentsForTestRunner(&omitted).join(' '), Utils::CommandLine::Raw);
if (!omitted.isEmpty()) {
const QString &details = constructOmittedDetailsString(omitted);
reportResult(ResultType::MessageWarn, details.arg(current->displayName()));
}
} else {
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
- m_currentProcess->setArguments(current->commandLine().splitArguments());
+ command.setArguments(current->commandLine().arguments());
}
+ m_currentProcess->setCommand(command);
- m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory().toString());
+ m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory());
const Utils::Environment &original = m_currentConfig->environment();
Utils::Environment environment = m_currentConfig->filteredEnvironment(original);
const Utils::EnvironmentItems removedVariables = Utils::filtered(
@@ -243,7 +247,7 @@ void TestRunner::setUpProcessEnv()
.arg(m_currentConfig->displayName());
reportResult(ResultType::MessageWarn, details);
}
- m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment());
+ m_currentProcess->setEnvironment(environment);
}
void TestRunner::scheduleNext()
@@ -259,35 +263,35 @@ void TestRunner::scheduleNext()
return;
if (!m_currentConfig->project())
- onProcessFinished();
+ onProcessDone();
setUpProcess();
- QTC_ASSERT(m_currentProcess, onProcessFinished(); return);
+ QTC_ASSERT(m_currentProcess, onProcessDone(); return);
QTC_ASSERT(!m_currentOutputReader, delete m_currentOutputReader);
m_currentOutputReader = m_currentConfig->outputReader(*m_fakeFutureInterface, m_currentProcess);
- QTC_ASSERT(m_currentOutputReader, onProcessFinished();return);
+ QTC_ASSERT(m_currentOutputReader, onProcessDone();return);
connect(m_currentOutputReader, &TestOutputReader::newOutputLineAvailable,
TestResultsPane::instance(), &TestResultsPane::addOutputLine);
setUpProcessEnv();
- connect(m_currentProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- this, &TestRunner::onProcessFinished);
+ connect(m_currentProcess, &Utils::QtcProcess::done, this, &TestRunner::onProcessDone);
const int timeout = AutotestPlugin::settings()->timeout;
- QTimer::singleShot(timeout, m_currentProcess, [this]() { cancelCurrent(Timeout); });
+ m_cancelTimer.setInterval(timeout);
+ m_cancelTimer.start();
- qCInfo(runnerLog) << "Command:" << m_currentProcess->program();
- qCInfo(runnerLog) << "Arguments:" << m_currentProcess->arguments();
+ qCInfo(runnerLog) << "Command:" << m_currentProcess->commandLine().executable();
+ qCInfo(runnerLog) << "Arguments:" << m_currentProcess->commandLine().arguments();
qCInfo(runnerLog) << "Working directory:" << m_currentProcess->workingDirectory();
- qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment();
+ qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment().toStringList();
m_currentProcess->start();
if (!m_currentProcess->waitForStarted()) {
reportResult(ResultType::MessageFatal,
tr("Failed to start test for project \"%1\".").arg(m_currentConfig->displayName())
+ processInformation(m_currentProcess) + rcInfo(m_currentConfig));
- onProcessFinished();
+ onProcessDone();
}
}
@@ -310,7 +314,7 @@ void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
}
}
-void TestRunner::onProcessFinished()
+void TestRunner::onProcessDone()
{
if (m_executingTests && m_currentConfig) {
QTC_CHECK(m_fakeFutureInterface);
@@ -355,7 +359,8 @@ void TestRunner::onProcessFinished()
void TestRunner::resetInternalPointers()
{
delete m_currentOutputReader;
- delete m_currentProcess;
+ if (m_currentProcess)
+ m_currentProcess->deleteLater();
delete m_currentConfig;
m_currentOutputReader = nullptr;
m_currentProcess = nullptr;
@@ -635,7 +640,7 @@ void TestRunner::debugTests()
}
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
- runControl->setRunConfiguration(config->runConfiguration());
+ runControl->copyDataFromRunConfiguration(config->runConfiguration());
QStringList omitted;
Runnable inferior = config->runnable();
@@ -812,6 +817,7 @@ void TestRunner::onBuildQueueFinished(bool success)
void TestRunner::onFinished()
{
+ m_cancelTimer.stop();
// if we've been canceled and we still have test configurations queued just throw them away
qDeleteAll(m_selectedTests);
m_selectedTests.clear();
diff --git a/src/plugins/autotest/testrunner.h b/src/plugins/autotest/testrunner.h
index a95a78ab9d5..0d41f7d161c 100644
--- a/src/plugins/autotest/testrunner.h
+++ b/src/plugins/autotest/testrunner.h
@@ -32,16 +32,17 @@
#include <QFutureWatcher>
#include <QObject>
#include <QQueue>
+#include <QTimer>
QT_BEGIN_NAMESPACE
class QCheckBox;
class QComboBox;
class QDialogButtonBox;
class QLabel;
-class QProcess;
QT_END_NAMESPACE
namespace ProjectExplorer { class Project; }
+namespace Utils { class QtcProcess; }
namespace Autotest {
@@ -89,7 +90,7 @@ private:
void setUpProcessEnv();
void scheduleNext();
void cancelCurrent(CancelReason reason);
- void onProcessFinished();
+ void onProcessDone();
void resetInternalPointers();
void runTests();
@@ -105,7 +106,7 @@ private:
bool m_executingTests = false;
bool m_canceled = false;
ITestConfiguration *m_currentConfig = nullptr;
- QProcess *m_currentProcess = nullptr;
+ Utils::QtcProcess *m_currentProcess = nullptr;
TestOutputReader *m_currentOutputReader = nullptr;
TestRunMode m_runMode = TestRunMode::None;
@@ -116,6 +117,7 @@ private:
QMetaObject::Connection m_finishDebugConnect;
// temporarily used for handling of switching the current target
QMetaObject::Connection m_targetConnect;
+ QTimer m_cancelTimer;
bool m_skipTargetsCheck = false;
};
diff --git a/src/plugins/autotest/testsettingspage.cpp b/src/plugins/autotest/testsettingspage.cpp
index 5e1e0f6c6d8..437355a40fa 100644
--- a/src/plugins/autotest/testsettingspage.cpp
+++ b/src/plugins/autotest/testsettingspage.cpp
@@ -115,7 +115,7 @@ void TestSettingsWidget::populateFrameworksListWidget(const QHash<Utils::Id, boo
m_ui.frameworkTreeWidget->clear();
for (const ITestFramework *framework : registered) {
const Utils::Id id = framework->id();
- auto item = new QTreeWidgetItem(m_ui.frameworkTreeWidget, QStringList(QLatin1String(framework->name())));
+ auto item = new QTreeWidgetItem(m_ui.frameworkTreeWidget, {framework->displayName()});
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
item->setCheckState(0, frameworks.value(id) ? Qt::Checked : Qt::Unchecked);
item->setData(0, BaseId, id.toSetting());
@@ -132,7 +132,7 @@ void TestSettingsWidget::populateFrameworksListWidget(const QHash<Utils::Id, boo
const TestTools &registeredTools = TestFrameworkManager::registeredTestTools();
for (const ITestTool *testTool : registeredTools) {
const Utils::Id id = testTool->id();
- auto item = new QTreeWidgetItem(m_ui.frameworkTreeWidget, {QLatin1String(testTool->name())});
+ auto item = new QTreeWidgetItem(m_ui.frameworkTreeWidget, {testTool->displayName()});
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
item->setCheckState(0, testTools.value(id) ? Qt::Checked : Qt::Unchecked);
item->setData(0, BaseId, id.toSetting());
@@ -203,7 +203,7 @@ void TestSettingsWidget::onFrameworkItemChanged()
TestSettingsPage::TestSettingsPage(TestSettings *settings)
: m_settings(settings)
{
- setId("A.AutoTest.0.General");
+ setId(Constants::AUTOTEST_SETTINGS_ID);
setDisplayName(tr("General"));
setCategory(Constants::AUTOTEST_SETTINGS_CATEGORY);
setDisplayCategory(QCoreApplication::translate("AutoTest", Constants::AUTOTEST_SETTINGS_TR));
diff --git a/src/plugins/autotest/testsettingspage.ui b/src/plugins/autotest/testsettingspage.ui
index 0ea7404370d..326a02966d7 100644
--- a/src/plugins/autotest/testsettingspage.ui
+++ b/src/plugins/autotest/testsettingspage.ui
@@ -106,20 +106,20 @@
<item>
<widget class="QCheckBox" name="openResultsOnStartCB">
<property name="toolTip">
- <string>Opens the test results pane automatically when tests are started.</string>
+ <string>Displays test results automatically when tests are started.</string>
</property>
<property name="text">
- <string>Open results pane when tests start</string>
+ <string>Open results when tests start</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="openResultsOnFinishCB">
<property name="toolTip">
- <string>Opens the test result pane automatically when tests are finished.</string>
+ <string>Displays test results automatically when tests are finished.</string>
</property>
<property name="text">
- <string>Open results pane when tests finish</string>
+ <string>Open results when tests finish</string>
</property>
<property name="checked">
<bool>true</bool>
@@ -147,7 +147,7 @@
<item>
<widget class="QCheckBox" name="openResultsOnFailCB">
<property name="toolTip">
- <string>Opens the test result pane only if the test run contains failed, fatal or unexpectedly passed tests.</string>
+ <string>Displays test results only if the test run contains failed, fatal or unexpectedly passed tests.</string>
</property>
<property name="text">
<string>Only for unsuccessful test runs</string>
diff --git a/src/plugins/autotoolsprojectmanager/CMakeLists.txt b/src/plugins/autotoolsprojectmanager/CMakeLists.txt
index 9567ec861a0..64446adc3a2 100644
--- a/src/plugins/autotoolsprojectmanager/CMakeLists.txt
+++ b/src/plugins/autotoolsprojectmanager/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(AutotoolsProjectManager
+ PLUGIN_CLASS AutotoolsProjectPlugin
PLUGIN_DEPENDS Core CppEditor ProjectExplorer QtSupport
SOURCES
autogenstep.cpp autogenstep.h
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp
index 2415f567893..f7e27b8b60d 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp
+++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp
@@ -116,13 +116,13 @@ void AutotoolsBuildSystem::makefileParsingFinished()
const QFileInfo fileInfo = projectFilePath().toFileInfo();
const QDir dir = fileInfo.absoluteDir();
const QStringList files = m_makefileParserThread->sources();
- foreach (const QString& file, files)
+ for (const QString& file : files)
m_files.append(dir.absoluteFilePath(file));
// Watch for changes of Makefile.am files. If a Makefile.am file
// has been changed, the project tree must be reparsed.
const QStringList makefiles = m_makefileParserThread->makefiles();
- foreach (const QString &makefile, makefiles) {
+ for (const QString &makefile : makefiles) {
const QString absMakefile = dir.absoluteFilePath(makefile);
m_files.append(absMakefile);
@@ -161,7 +161,7 @@ static QStringList filterIncludes(const QString &absSrc, const QString &absBuild
const QStringList &in)
{
QStringList result;
- foreach (const QString i, in) {
+ for (const QString &i : in) {
QString out = i;
out.replace(QLatin1String("$(top_srcdir)"), absSrc);
out.replace(QLatin1String("$(abs_top_srcdir)"), absSrc);
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp b/src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp
index 351484ee67e..bf40ece8150 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp
@@ -30,7 +30,7 @@
#include "debugserverproviderchooser.h"
#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <QFormLayout>
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwidget.h b/src/plugins/baremetal/baremetaldeviceconfigurationwidget.h
index b94ced03abd..472c3734b3e 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwidget.h
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwidget.h
@@ -41,7 +41,7 @@ class BareMetalDeviceConfigurationWidget final
Q_OBJECT
public:
- explicit BareMetalDeviceConfigurationWidget(const ProjectExplorer::IDevice::Ptr &deviceConfig);
+ explicit BareMetalDeviceConfigurationWidget(const ProjectExplorer::IDevicePtr &deviceConfig);
private:
void debugServerProviderChanged();
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwizard.h b/src/plugins/baremetal/baremetaldeviceconfigurationwizard.h
index 79ada6a0a8b..083c4c2ab0c 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwizard.h
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwizard.h
@@ -25,7 +25,7 @@
#pragma once
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
#include <utils/wizard.h>
namespace BareMetal {
@@ -42,7 +42,7 @@ class BareMetalDeviceConfigurationWizard final : public Utils::Wizard
public:
explicit BareMetalDeviceConfigurationWizard(QWidget *parent = nullptr);
- ProjectExplorer::IDevice::Ptr device() const;
+ ProjectExplorer::IDevicePtr device() const;
private:
BareMetalDeviceConfigurationWizardSetupPage *m_setupPage = nullptr;
diff --git a/src/plugins/baremetal/baremetalplugin.cpp b/src/plugins/baremetal/baremetalplugin.cpp
index 9f9f09c6b8b..239a169b088 100644
--- a/src/plugins/baremetal/baremetalplugin.cpp
+++ b/src/plugins/baremetal/baremetalplugin.cpp
@@ -45,6 +45,7 @@
#include <coreplugin/icore.h>
#include <projectexplorer/deployconfiguration.h>
+#include <projectexplorer/projectexplorerconstants.h>
using namespace ProjectExplorer;
diff --git a/src/plugins/baremetal/baremetalrunconfiguration.cpp b/src/plugins/baremetal/baremetalrunconfiguration.cpp
index 913f1f3448f..b8961d9476d 100644
--- a/src/plugins/baremetal/baremetalrunconfiguration.cpp
+++ b/src/plugins/baremetal/baremetalrunconfiguration.cpp
@@ -45,15 +45,15 @@ class BareMetalRunConfiguration final : public RunConfiguration
Q_DECLARE_TR_FUNCTIONS(BareMetal::Internal::BareMetalRunConfiguration)
public:
- explicit BareMetalRunConfiguration(Target *target, Utils::Id id)
+ explicit BareMetalRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- const auto exeAspect = addAspect<ExecutableAspect>();
+ const auto exeAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
exeAspect->setDisplayStyle(StringAspect::LabelDisplay);
exeAspect->setPlaceHolderText(tr("Unknown"));
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), nullptr);
setUpdater([this, exeAspect] {
const BuildTargetInfo bti = buildTargetInfo();
@@ -69,18 +69,18 @@ class BareMetalCustomRunConfiguration final : public RunConfiguration
Q_DECLARE_TR_FUNCTIONS(BareMetal::Internal::BareMetalCustomRunConfiguration)
public:
- explicit BareMetalCustomRunConfiguration(Target *target, Utils::Id id)
+ explicit BareMetalCustomRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- const auto exeAspect = addAspect<ExecutableAspect>();
+ const auto exeAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
exeAspect->setSettingsKey("BareMetal.CustomRunConfig.Executable");
exeAspect->setPlaceHolderText(tr("Unknown"));
exeAspect->setDisplayStyle(StringAspect::PathChooserDisplay);
exeAspect->setHistoryCompleter("BareMetal.CustomRunConfig.History");
exeAspect->setExpectedKind(PathChooser::Any);
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), nullptr);
setDefaultDisplayName(RunConfigurationFactory::decoratedTargetName(tr("Custom Executable"), target));
}
diff --git a/src/plugins/baremetal/debugservers/gdb/gdbserverprovider.cpp b/src/plugins/baremetal/debugservers/gdb/gdbserverprovider.cpp
index 90b3dbd2b93..f363a3631c5 100644
--- a/src/plugins/baremetal/debugservers/gdb/gdbserverprovider.cpp
+++ b/src/plugins/baremetal/debugservers/gdb/gdbserverprovider.cpp
@@ -35,8 +35,6 @@
#include <utils/qtcassert.h>
#include <utils/pathchooser.h>
-#include <ssh/sshconnection.h>
-
#include <QComboBox>
#include <QFormLayout>
#include <QLineEdit>
@@ -166,7 +164,7 @@ bool GdbServerProvider::aboutToRun(DebuggerRunTool *runTool,
const auto exeAspect = runControl->aspect<ExecutableAspect>();
QTC_ASSERT(exeAspect, return false);
- const FilePath bin = exeAspect->executable();
+ const FilePath bin = FilePath::fromString(exeAspect->executable.path());
if (bin.isEmpty()) {
errorMessage = BareMetalDebugSupport::tr(
"Cannot debug: Local executable is not set.");
@@ -181,10 +179,8 @@ bool GdbServerProvider::aboutToRun(DebuggerRunTool *runTool,
Runnable inferior;
inferior.command.setExecutable(bin);
- inferior.extraData.insert(Debugger::Constants::kPeripheralDescriptionFile,
- m_peripheralDescriptionFile.toVariant());
if (const auto argAspect = runControl->aspect<ArgumentsAspect>())
- inferior.command.setArguments(argAspect->arguments(runControl->macroExpander()));
+ inferior.command.setArguments(argAspect->arguments);
runTool->setInferior(inferior);
runTool->setSymbolFile(bin);
runTool->setStartMode(AttachToRemoteServer);
@@ -193,6 +189,7 @@ bool GdbServerProvider::aboutToRun(DebuggerRunTool *runTool,
runTool->setRemoteChannel(channelString());
runTool->setUseContinueInsteadOfRun(true);
runTool->setUseExtendedRemote(useExtendedRemote());
+ runTool->runParameters().peripheralDescriptionFile = m_peripheralDescriptionFile;
return true;
}
@@ -201,11 +198,9 @@ RunWorker *GdbServerProvider::targetRunner(RunControl *runControl) const
if (m_startupMode != GdbServerProvider::StartupOnNetwork)
return nullptr;
- Runnable r;
- r.command = command();
// Command arguments are in host OS style as the bare metal's GDB servers are launched
// on the host, not on that target.
- return new GdbServerProviderRunner(runControl, r);
+ return new GdbServerProviderRunner(runControl, command());
}
bool GdbServerProvider::fromMap(const QVariantMap &data)
@@ -343,12 +338,15 @@ QString GdbServerProviderConfigWidget::defaultResetCommandsTooltip()
// GdbServerProviderRunner
GdbServerProviderRunner::GdbServerProviderRunner(ProjectExplorer::RunControl *runControl,
- const ProjectExplorer::Runnable &runnable)
+ const Utils::CommandLine &commandLine)
: SimpleTargetRunner(runControl)
{
setId("BareMetalGdbServer");
// Baremetal's GDB servers are launched on the host, not on the target.
- setStarter([this, runnable] { doStart(runnable, {}); });
+ setStartModifier([this, commandLine] {
+ setCommandLine(commandLine);
+ forceRunOnHost();
+ });
}
} // namespace Internal
diff --git a/src/plugins/baremetal/debugservers/gdb/gdbserverprovider.h b/src/plugins/baremetal/debugservers/gdb/gdbserverprovider.h
index a8351939210..7ed3301d175 100644
--- a/src/plugins/baremetal/debugservers/gdb/gdbserverprovider.h
+++ b/src/plugins/baremetal/debugservers/gdb/gdbserverprovider.h
@@ -126,7 +126,7 @@ class GdbServerProviderRunner final : public ProjectExplorer::SimpleTargetRunner
{
public:
explicit GdbServerProviderRunner(ProjectExplorer::RunControl *runControl,
- const ProjectExplorer::Runnable &runnable);
+ const Utils::CommandLine &commandLine);
};
} // namespace Internal
diff --git a/src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp b/src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp
index 42f8973d650..481a8959572 100644
--- a/src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp
+++ b/src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp
@@ -175,6 +175,11 @@ bool JLinkGdbServerProvider::operator==(const IDebugServerProvider &other) const
const auto p = static_cast<const JLinkGdbServerProvider *>(&other);
return m_executableFile == p->m_executableFile
+ && m_jlinkDevice == p->m_jlinkDevice
+ && m_jlinkHost == p->m_jlinkHost
+ && m_jlinkHostAddr == p->m_jlinkHostAddr
+ && m_jlinkTargetIface == p->m_jlinkTargetIface
+ && m_jlinkTargetIfaceSpeed == p->m_jlinkTargetIfaceSpeed
&& m_additionalArguments == p->m_additionalArguments;
}
diff --git a/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp b/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp
index 75d0cc12442..1fddaada16c 100644
--- a/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp
+++ b/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp
@@ -91,12 +91,12 @@ UvscServerProvider::UvscServerProvider(const UvscServerProvider &other)
setEngineType(UvscEngineType);
}
-void UvscServerProvider::setToolsIniFile(const Utils::FilePath &toolsIniFile)
+void UvscServerProvider::setToolsIniFile(const FilePath &toolsIniFile)
{
m_toolsIniFile = toolsIniFile;
}
-Utils::FilePath UvscServerProvider::toolsIniFile() const
+FilePath UvscServerProvider::toolsIniFile() const
{
return m_toolsIniFile;
}
@@ -194,7 +194,7 @@ bool UvscServerProvider::aboutToRun(DebuggerRunTool *runTool, QString &errorMess
const auto exeAspect = runControl->aspect<ExecutableAspect>();
QTC_ASSERT(exeAspect, return false);
- const FilePath bin = exeAspect->executable();
+ const FilePath bin = exeAspect->executable;
if (bin.isEmpty()) {
errorMessage = BareMetalDebugSupport::tr("Cannot debug: Local executable is not set.");
return false;
@@ -216,11 +216,10 @@ bool UvscServerProvider::aboutToRun(DebuggerRunTool *runTool, QString &errorMess
Runnable inferior;
inferior.command.setExecutable(bin);
- inferior.extraData.insert(Debugger::Constants::kPeripheralDescriptionFile,
- peripheralDescriptionFile.toVariant());
- inferior.extraData.insert(Debugger::Constants::kUVisionProjectFilePath, projFilePath.toString());
- inferior.extraData.insert(Debugger::Constants::kUVisionOptionsFilePath, optFilePath.toString());
- inferior.extraData.insert(Debugger::Constants::kUVisionSimulator, isSimulator());
+ runTool->runParameters().peripheralDescriptionFile = peripheralDescriptionFile;
+ runTool->runParameters().uVisionProjectFilePath = projFilePath;
+ runTool->runParameters().uVisionOptionsFilePath = optFilePath;
+ runTool->runParameters().uVisionSimulator = isSimulator();
runTool->setInferior(inferior);
runTool->setSymbolFile(bin);
runTool->setStartMode(AttachToRemoteServer);
@@ -252,8 +251,7 @@ bool UvscServerProvider::fromMap(const QVariantMap &data)
return true;
}
-Utils::FilePath UvscServerProvider::projectFilePath(DebuggerRunTool *runTool,
- QString &errorMessage) const
+FilePath UvscServerProvider::projectFilePath(DebuggerRunTool *runTool, QString &errorMessage) const
{
const FilePath projectPath = buildProjectFilePath(runTool);
std::ofstream ofs(projectPath.toString().toStdString(), std::ofstream::out);
@@ -333,12 +331,12 @@ void UvscServerProviderConfigWidget::discard()
IDebugServerProviderConfigWidget::discard();
}
-void UvscServerProviderConfigWidget::setToolsIniFile(const Utils::FilePath &toolsIniFile)
+void UvscServerProviderConfigWidget::setToolsIniFile(const FilePath &toolsIniFile)
{
m_toolsIniChooser->setFilePath(toolsIniFile);
}
-Utils::FilePath UvscServerProviderConfigWidget::toolsIniFile() const
+FilePath UvscServerProviderConfigWidget::toolsIniFile() const
{
return m_toolsIniChooser->filePath();
}
@@ -387,25 +385,16 @@ UvscServerProviderRunner::UvscServerProviderRunner(ProjectExplorer::RunControl *
this->runControl()->setApplicationProcessHandle(pid);
reportStarted();
});
- connect(&m_process, &QtcProcess::finished, this, [this] {
+ connect(&m_process, &QtcProcess::done, this, [this] {
appendMessage(m_process.exitMessage(), NormalMessageFormat);
reportStopped();
});
- connect(&m_process, &QtcProcess::errorOccurred, this, [this] (QProcess::ProcessError error) {
- if (error == QProcess::Timedout)
- return; // No actual change on the process side.
- const QString msg = userMessageForProcessError(
- error, m_process.commandLine().executable());
- appendMessage(msg, Utils::NormalMessageFormat);
- reportStopped();
- });
}
void UvscServerProviderRunner::start()
{
- const QString msg = RunControl::tr("Starting %1 ...")
- .arg(m_process.commandLine().toUserOutput());
- appendMessage(msg, Utils::NormalMessageFormat);
+ const QString msg = RunControl::tr("Starting %1 ...").arg(m_process.commandLine().displayName());
+ appendMessage(msg, NormalMessageFormat);
m_process.start();
}
diff --git a/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.h b/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.h
index fb877760c35..3a4cf31e474 100644
--- a/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.h
+++ b/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.h
@@ -28,7 +28,7 @@
#include "uvtargetdeviceselection.h"
#include <utils/basetreeview.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <utils/treemodel.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/baremetal/iarewtoolchain.cpp b/src/plugins/baremetal/iarewtoolchain.cpp
index a79a6380081..101a80f5317 100644
--- a/src/plugins/baremetal/iarewtoolchain.cpp
+++ b/src/plugins/baremetal/iarewtoolchain.cpp
@@ -113,7 +113,7 @@ static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &
cpp.setCommand(cmd);
cpp.runBlocking();
- if (cpp.result() != QtcProcess::FinishedWithSuccess) {
+ if (cpp.result() != ProcessResult::FinishedWithSuccess) {
qWarning() << cpp.exitMessage();
return {};
}
@@ -347,10 +347,10 @@ ToolChain::BuiltInHeaderPathsRunner IarToolChain::createBuiltInHeaderPathsRunner
HeaderPathsCache headerPaths = headerPathsCache();
return [env, compiler, headerPaths, languageId](const QStringList &flags,
- const QString &fileName,
+ const FilePath &sysRoot,
const QString &) {
Q_UNUSED(flags)
- Q_UNUSED(fileName)
+ Q_UNUSED(sysRoot)
const HeaderPaths paths = dumpHeaderPaths(compiler, languageId, env);
headerPaths->insert({}, paths);
diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp
index 39cac8a2ca9..44e8737ac32 100644
--- a/src/plugins/baremetal/keiltoolchain.cpp
+++ b/src/plugins/baremetal/keiltoolchain.cpp
@@ -287,7 +287,7 @@ static Macros dumpArmPredefinedMacros(const FilePath &compiler, const QStringLis
cpp.setCommand({compiler, args});
cpp.runBlocking();
- if (cpp.result() != QtcProcess::FinishedWithSuccess) {
+ if (cpp.result() != ProcessResult::FinishedWithSuccess) {
qWarning() << cpp.exitMessage();
return {};
}
@@ -473,9 +473,9 @@ ToolChain::BuiltInHeaderPathsRunner KeilToolChain::createBuiltInHeaderPathsRunne
const HeaderPathsCache headerPaths = headerPathsCache();
return [compiler,
- headerPaths](const QStringList &flags, const QString &fileName, const QString &) {
+ headerPaths](const QStringList &flags, const FilePath &sysRoot, const QString &) {
Q_UNUSED(flags)
- Q_UNUSED(fileName)
+ Q_UNUSED(sysRoot)
const HeaderPaths paths = dumpHeaderPaths(compiler);
headerPaths->insert({}, paths);
diff --git a/src/plugins/baremetal/sdcctoolchain.cpp b/src/plugins/baremetal/sdcctoolchain.cpp
index f793d93de6e..9ed380f5c80 100644
--- a/src/plugins/baremetal/sdcctoolchain.cpp
+++ b/src/plugins/baremetal/sdcctoolchain.cpp
@@ -93,7 +93,7 @@ static Macros dumpPredefinedMacros(const FilePath &compiler, const Environment &
cpp.setCommand({compiler, {compilerTargetFlag(abi), "-dM", "-E", fakeIn.fileName()}});
cpp.runBlocking();
- if (cpp.result() != QtcProcess::FinishedWithSuccess) {
+ if (cpp.result() != ProcessResult::FinishedWithSuccess) {
qWarning() << cpp.exitMessage();
return {};
}
@@ -114,7 +114,7 @@ static HeaderPaths dumpHeaderPaths(const FilePath &compiler, const Environment &
cpp.setCommand({compiler, {compilerTargetFlag(abi), "--print-search-dirs"}});
cpp.runBlocking();
- if (cpp.result() != QtcProcess::FinishedWithSuccess) {
+ if (cpp.result() != ProcessResult::FinishedWithSuccess) {
qWarning() << cpp.exitMessage();
return {};
}
@@ -258,7 +258,7 @@ ToolChain::BuiltInHeaderPathsRunner SdccToolChain::createBuiltInHeaderPathsRunne
const FilePath compiler = compilerCommand();
const Abi abi = targetAbi();
- return [env, compiler, abi](const QStringList &, const QString &, const QString &) {
+ return [env, compiler, abi](const QStringList &, const FilePath &, const QString &) {
return dumpHeaderPaths(compiler, env, abi);
};
}
diff --git a/src/plugins/bazaar/bazaarclient.cpp b/src/plugins/bazaar/bazaarclient.cpp
index c0804930b7e..ccd91a236f2 100644
--- a/src/plugins/bazaar/bazaarclient.cpp
+++ b/src/plugins/bazaar/bazaarclient.cpp
@@ -31,6 +31,7 @@
#include <vcsbase/vcsbaseeditorconfig.h>
#include <utils/hostosinfo.h>
+#include <utils/qtcprocess.h>
#include <QDir>
#include <QFileInfo>
@@ -152,8 +153,8 @@ bool BazaarClient::synchronousUncommit(const FilePath &workingDir,
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDir, args);
- VcsOutputWindow::append(proc.stdOut());
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ VcsOutputWindow::append(proc.cleanedStdOut());
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
void BazaarClient::commit(const FilePath &repositoryRoot, const QStringList &files,
@@ -191,7 +192,7 @@ bool BazaarClient::managesFile(const FilePath &workingDirectory, const QString &
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, args);
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return false;
return proc.rawStdOut().startsWith("unknown");
}
@@ -231,8 +232,8 @@ ExitCodeInterpreter BazaarClient::exitCodeInterpreter(VcsCommandTag cmd) const
{
if (cmd == DiffCommand) {
return [](int code) {
- return (code < 0 || code > 2) ? QtcProcess::FinishedWithError
- : QtcProcess::FinishedWithSuccess;
+ return (code < 0 || code > 2) ? ProcessResult::FinishedWithError
+ : ProcessResult::FinishedWithSuccess;
};
}
return {};
diff --git a/src/plugins/bazaar/bazaarplugin.cpp b/src/plugins/bazaar/bazaarplugin.cpp
index 74202d90413..185f0e7191a 100644
--- a/src/plugins/bazaar/bazaarplugin.cpp
+++ b/src/plugins/bazaar/bazaarplugin.cpp
@@ -50,6 +50,8 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/locator/commandlocator.h>
+#include <utils/commandline.h>
+#include <utils/environment.h>
#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
diff --git a/src/plugins/beautifier/abstractsettings.cpp b/src/plugins/beautifier/abstractsettings.cpp
index 28d8ac6b049..e9768041452 100644
--- a/src/plugins/beautifier/abstractsettings.cpp
+++ b/src/plugins/beautifier/abstractsettings.cpp
@@ -33,12 +33,17 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/genericconstants.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
+#include <utils/qtcprocess.h>
#include <QFile>
#include <QFileInfo>
+#include <QRegularExpression>
+#include <QVersionNumber>
#include <QXmlStreamReader>
+using namespace Utils;
+
namespace Beautifier {
namespace Internal {
@@ -47,12 +52,65 @@ const char COMMAND[] = "command";
const char SUPPORTED_MIME[] = "supportedMime";
}
+class VersionUpdater
+{
+public:
+ VersionUpdater()
+ {
+ QObject::connect(&m_process, &QtcProcess::done, [this] {
+ if (m_process.result() != ProcessResult::FinishedWithSuccess)
+ return;
+
+ m_versionNumber = parseVersion(m_process.cleanedStdOut());
+ if (m_versionNumber.isNull())
+ m_versionNumber = parseVersion(m_process.cleanedStdErr());
+ });
+ }
+
+ void setVersionRegExp(const QRegularExpression &versionRegExp)
+ {
+ m_versionRegExp = versionRegExp;
+ }
+
+ void update(const FilePath &executable)
+ {
+ m_versionNumber = {};
+ if (m_versionRegExp.pattern().isEmpty())
+ return;
+ m_process.close();
+ m_process.setCommand({executable, {"--version"}});
+ m_process.start();
+ }
+
+ QVersionNumber version() const
+ {
+ if (m_process.state() != QProcess::NotRunning)
+ m_process.waitForFinished(-1);
+ return m_versionNumber;
+ }
+
+private:
+ QVersionNumber parseVersion(const QString &text) const
+ {
+ const QRegularExpressionMatch match = m_versionRegExp.match(text);
+ if (!match.hasMatch())
+ return {};
+
+ return {match.captured(1).toInt(), match.captured(2).toInt()};
+ }
+
+ QRegularExpression m_versionRegExp;
+ mutable QtcProcess m_process;
+ QVersionNumber m_versionNumber;
+};
+
AbstractSettings::AbstractSettings(const QString &name, const QString &ending)
: m_ending(ending)
, m_styleDir(Core::ICore::userResourcePath(Beautifier::Constants::SETTINGS_DIRNAME)
.pathAppended(name)
.toString())
, m_name(name)
+ , m_versionUpdater(new VersionUpdater)
{
}
@@ -122,29 +180,28 @@ QString AbstractSettings::styleFileName(const QString &key) const
return m_styleDir.absoluteFilePath(key + m_ending);
}
-Utils::FilePath AbstractSettings::command() const
+FilePath AbstractSettings::command() const
{
- return Utils::FilePath::fromString(m_command);
+ return FilePath::fromString(m_command);
}
-void AbstractSettings::setCommand(const QString &command)
+void AbstractSettings::setCommand(const QString &cmd)
{
- if (command == m_command)
+ if (cmd == m_command)
return;
- m_command = command;
- updateVersion();
+ m_command = cmd;
+ m_versionUpdater->update(command());
}
-int AbstractSettings::version() const
+QVersionNumber AbstractSettings::version() const
{
- return m_version;
+ return m_versionUpdater->version();
}
-void AbstractSettings::updateVersion()
+void AbstractSettings::setVersionRegExp(const QRegularExpression &versionRegExp)
{
- // If a beautifier needs to know the current tool's version, reimplement and store the version
- // in m_version.
+ m_versionUpdater->setVersionRegExp(versionRegExp);
}
QString AbstractSettings::supportedMimeTypesAsString() const
@@ -157,7 +214,7 @@ void AbstractSettings::setSupportedMimeTypes(const QString &mimes)
const QStringList stringTypes = mimes.split(';');
QStringList types;
for (const QString &type : stringTypes) {
- const Utils::MimeType mime = Utils::mimeTypeForName(type.trimmed());
+ const MimeType mime = mimeTypeForName(type.trimmed());
if (!mime.isValid())
continue;
const QString canonicalName = mime.name();
@@ -179,8 +236,8 @@ bool AbstractSettings::isApplicable(const Core::IDocument *document) const
if (m_supportedMimeTypes.isEmpty())
return true;
- const Utils::MimeType documentMimeType = Utils::mimeTypeForName(document->mimeType());
- return Utils::anyOf(m_supportedMimeTypes, [&documentMimeType](const QString &mime) {
+ const MimeType documentMimeType = mimeTypeForName(document->mimeType());
+ return anyOf(m_supportedMimeTypes, [&documentMimeType](const QString &mime) {
return documentMimeType.inherits(mime);
});
}
@@ -246,7 +303,7 @@ void AbstractSettings::save()
continue;
}
- Utils::FileSaver saver(Utils::FilePath::fromUserInput(fi.absoluteFilePath()));
+ FileSaver saver(FilePath::fromUserInput(fi.absoluteFilePath()));
if (saver.hasError()) {
BeautifierPlugin::showError(tr("Cannot open file \"%1\": %2.")
.arg(saver.filePath().toUserOutput())
diff --git a/src/plugins/beautifier/abstractsettings.h b/src/plugins/beautifier/abstractsettings.h
index ae61bde2676..ae39c6ce690 100644
--- a/src/plugins/beautifier/abstractsettings.h
+++ b/src/plugins/beautifier/abstractsettings.h
@@ -35,12 +35,21 @@
#include <QStringList>
#include <QVector>
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+class QRegularExpression;
+class QVersionNumber;
+QT_END_NAMESPACE
+
namespace Core { class IDocument; }
namespace Utils { class FilePath; }
namespace Beautifier {
namespace Internal {
+class VersionUpdater;
+
class AbstractSettings : public QObject
{
Q_OBJECT
@@ -66,9 +75,8 @@ public:
virtual QString styleFileName(const QString &key) const;
Utils::FilePath command() const;
- void setCommand(const QString &command);
- int version() const;
- virtual void updateVersion();
+ void setCommand(const QString &cmd);
+ QVersionNumber version() const;
QString supportedMimeTypesAsString() const;
void setSupportedMimeTypes(const QString &mimes);
@@ -81,9 +89,10 @@ signals:
void supportedMimeTypesChanged();
protected:
+ void setVersionRegExp(const QRegularExpression &versionRegExp);
+
QMap<QString, QString> m_styles;
QMap<QString, QVariant> m_settings;
- int m_version = 0;
QString m_ending;
QDir m_styleDir;
@@ -92,6 +101,7 @@ protected:
private:
QString m_name;
+ std::unique_ptr<VersionUpdater> m_versionUpdater;
QStringList m_stylesToRemove;
QSet<QString> m_changedStyles;
QString m_command;
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
index a8851b43cc5..04fda15a819 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
+++ b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
@@ -53,6 +53,7 @@
#include <QAction>
#include <QMenu>
+#include <QVersionNumber>
using namespace TextEditor;
@@ -150,10 +151,10 @@ Command ArtisticStyle::command(const QString &cfgFile) const
command.addOption("-q");
command.addOption("--options=" + cfgFile);
- const int version = m_settings.version();
- if (version > ArtisticStyleSettings::Version_2_03) {
+ const QVersionNumber version = m_settings.version();
+ if (version > QVersionNumber(2, 3)) {
command.setProcessing(Command::PipeProcessing);
- if (version == ArtisticStyleSettings::Version_2_04)
+ if (version == QVersionNumber(2, 4))
command.setPipeAddsNewline(true);
command.setReturnsCRLF(Utils::HostOsInfo::isWindowsHost());
command.addOption("-z2");
diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
index 429fc80ada2..5e7f8425cb9 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
+++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
@@ -41,6 +41,8 @@
#include <QRegularExpression>
#include <QXmlStreamWriter>
+using namespace Utils;
+
namespace Beautifier {
namespace Internal {
@@ -55,9 +57,7 @@ const char SETTINGS_NAME[] = "artisticstyle";
ArtisticStyleSettings::ArtisticStyleSettings() :
AbstractSettings(SETTINGS_NAME, ".astyle")
{
- connect(&m_versionWatcher, &QFutureWatcherBase::finished,
- this, &ArtisticStyleSettings::helperSetVersion);
-
+ setVersionRegExp(QRegularExpression("([2-9]{1})\\.([0-9]{1,2})(\\.[1-9]{1})?$"));
setCommand("astyle");
m_settings.insert(USE_OTHER_FILES, QVariant(true));
m_settings.insert(USE_SPECIFIC_CONFIG_FILE, QVariant(false));
@@ -68,48 +68,6 @@ ArtisticStyleSettings::ArtisticStyleSettings() :
read();
}
-static int parseVersion(const QString &text)
-{
- // The version in Artistic Style is printed like "Artistic Style Version 2.04"
- const QRegularExpression rx("([2-9]{1})\\.([0-9]{1,2})(\\.[1-9]{1})?$");
- const QRegularExpressionMatch match = rx.match(text);
- if (match.hasMatch()) {
- const int major = match.captured(1).toInt() * 100;
- const int minor = match.captured(2).toInt();
- return major + minor;
- }
- return 0;
-}
-
-static int updateVersionHelper(const Utils::FilePath &command)
-{
- Utils::QtcProcess process;
- process.setCommand({command, {"--version"}});
- process.runBlocking();
- if (process.result() != Utils::QtcProcess::FinishedWithSuccess)
- return 0;
-
- // Astyle prints the version on stdout or stderr, depending on platform
- const int version = parseVersion(process.stdOut().trimmed());
- if (version != 0)
- return version;
- return parseVersion(process.stdErr().trimmed());
-}
-
-void ArtisticStyleSettings::updateVersion()
-{
- if (m_versionFuture.isRunning())
- m_versionFuture.cancel();
-
- m_versionFuture = Utils::runAsync(updateVersionHelper, command());
- m_versionWatcher.setFuture(m_versionFuture);
-}
-
-void ArtisticStyleSettings::helperSetVersion()
-{
- m_version = m_versionWatcher.result();
-}
-
bool ArtisticStyleSettings::useOtherFiles() const
{
return m_settings.value(USE_OTHER_FILES).toBool();
@@ -130,12 +88,12 @@ void ArtisticStyleSettings::setUseSpecificConfigFile(bool useSpecificConfigFile)
m_settings.insert(USE_SPECIFIC_CONFIG_FILE, QVariant(useSpecificConfigFile));
}
-Utils::FilePath ArtisticStyleSettings::specificConfigFile() const
+FilePath ArtisticStyleSettings::specificConfigFile() const
{
- return Utils::FilePath::fromString(m_settings.value(SPECIFIC_CONFIG_FILE).toString());
+ return FilePath::fromString(m_settings.value(SPECIFIC_CONFIG_FILE).toString());
}
-void ArtisticStyleSettings::setSpecificConfigFile(const Utils::FilePath &specificConfigFile)
+void ArtisticStyleSettings::setSpecificConfigFile(const FilePath &specificConfigFile)
{
m_settings.insert(SPECIFIC_CONFIG_FILE, QVariant(specificConfigFile.toString()));
}
@@ -180,11 +138,11 @@ QString ArtisticStyleSettings::documentationFilePath() const
void ArtisticStyleSettings::createDocumentationFile() const
{
- Utils::QtcProcess process;
+ QtcProcess process;
process.setTimeoutS(2);
process.setCommand({command(), {"-h"}});
process.runBlocking();
- if (process.result() != Utils::QtcProcess::FinishedWithSuccess)
+ if (process.result() != ProcessResult::FinishedWithSuccess)
return;
QFile file(documentationFilePath());
@@ -202,7 +160,7 @@ void ArtisticStyleSettings::createDocumentationFile() const
stream.writeStartElement(Constants::DOCUMENTATION_XMLROOT);
// astyle writes its output to 'error'...
- const QStringList lines = process.stdErr().split(QLatin1Char('\n'));
+ const QStringList lines = process.cleanedStdErr().split(QLatin1Char('\n'));
QStringList keys;
QStringList docu;
for (QString line : lines) {
diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.h b/src/plugins/beautifier/artisticstyle/artisticstylesettings.h
index e0fa1b8866e..cf125810317 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.h
+++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.h
@@ -29,9 +29,6 @@
#include <utils/fileutils.h>
-#include <QFuture>
-#include <QFutureWatcher>
-
namespace Beautifier {
namespace Internal {
@@ -40,15 +37,8 @@ class ArtisticStyleSettings : public AbstractSettings
Q_OBJECT
public:
- enum ArtisticStyleVersion {
- Version_2_03 = 203,
- Version_2_04 = 204
- };
-
ArtisticStyleSettings();
- void updateVersion() override;
-
bool useOtherFiles() const;
void setUseOtherFiles(bool useOtherFiles);
@@ -69,11 +59,6 @@ public:
QString documentationFilePath() const override;
void createDocumentationFile() const override;
-
-private:
- void helperSetVersion();
- QFuture<int> m_versionFuture;
- QFutureWatcher<int> m_versionWatcher;
};
} // namespace Internal
diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp
index aa2f8e4532e..c1abcdd7bcf 100644
--- a/src/plugins/beautifier/beautifierplugin.cpp
+++ b/src/plugins/beautifier/beautifierplugin.cpp
@@ -51,7 +51,7 @@
#include <texteditor/texteditorconstants.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
diff --git a/src/plugins/beautifier/generalsettings.cpp b/src/plugins/beautifier/generalsettings.cpp
index df16001aa0a..b90ab0a1337 100644
--- a/src/plugins/beautifier/generalsettings.cpp
+++ b/src/plugins/beautifier/generalsettings.cpp
@@ -30,7 +30,7 @@
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
#include <utils/genericconstants.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
namespace Beautifier {
namespace Internal {
diff --git a/src/plugins/beautifier/generalsettings.h b/src/plugins/beautifier/generalsettings.h
index 254a13c7c2a..ae3d49734d2 100644
--- a/src/plugins/beautifier/generalsettings.h
+++ b/src/plugins/beautifier/generalsettings.h
@@ -25,7 +25,7 @@
#pragma once
-#include <utils/mimetypes/mimetype.h>
+#include <utils/mimeutils.h>
#include <QList>
diff --git a/src/plugins/beautifier/uncrustify/uncrustify.cpp b/src/plugins/beautifier/uncrustify/uncrustify.cpp
index 689ef3714a0..370a7f37a00 100644
--- a/src/plugins/beautifier/uncrustify/uncrustify.cpp
+++ b/src/plugins/beautifier/uncrustify/uncrustify.cpp
@@ -49,6 +49,7 @@
#include <QAction>
#include <QMenu>
+#include <QVersionNumber>
using namespace TextEditor;
@@ -180,7 +181,7 @@ Command Uncrustify::command(const QString &cfgFile, bool fragment) const
Command command;
command.setExecutable(m_settings.command().toString());
command.setProcessing(Command::PipeProcessing);
- if (m_settings.version() >= 62) {
+ if (m_settings.version() >= QVersionNumber(0, 62)) {
command.addOption("--assume");
command.addOption("%file");
} else {
diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
index bb5b234bfbb..fbc8bfe079b 100644
--- a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
+++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
@@ -30,7 +30,6 @@
#include "../beautifierconstants.h"
#include <coreplugin/icore.h>
-
#include <utils/qtcprocess.h>
#include <QDateTime>
@@ -39,6 +38,8 @@
#include <QRegularExpression>
#include <QXmlStreamWriter>
+using namespace Utils;
+
namespace Beautifier {
namespace Internal {
@@ -54,9 +55,7 @@ const char SETTINGS_NAME[] = "uncrustify";
UncrustifySettings::UncrustifySettings() :
AbstractSettings(SETTINGS_NAME, ".cfg")
{
- connect(&m_versionProcess, &Utils::QtcProcess::finished,
- this, &UncrustifySettings::parseVersionProcessResult);
-
+ setVersionRegExp(QRegularExpression("([0-9]{1})\\.([0-9]{2})"));
setCommand("uncrustify");
m_settings.insert(USE_OTHER_FILES, QVariant(true));
m_settings.insert(USE_HOME_FILE, QVariant(false));
@@ -68,6 +67,8 @@ UncrustifySettings::UncrustifySettings() :
read();
}
+UncrustifySettings::~UncrustifySettings() = default;
+
bool UncrustifySettings::useOtherFiles() const
{
return m_settings.value(USE_OTHER_FILES).toBool();
@@ -88,12 +89,12 @@ void UncrustifySettings::setUseHomeFile(bool useHomeFile)
m_settings.insert(USE_HOME_FILE, QVariant(useHomeFile));
}
-Utils::FilePath UncrustifySettings::specificConfigFile() const
+FilePath UncrustifySettings::specificConfigFile() const
{
- return Utils::FilePath::fromString(m_settings.value(SPECIFIC_CONFIG_FILE_PATH).toString());
+ return FilePath::fromString(m_settings.value(SPECIFIC_CONFIG_FILE_PATH).toString());
}
-void UncrustifySettings::setSpecificConfigFile(const Utils::FilePath &filePath)
+void UncrustifySettings::setSpecificConfigFile(const FilePath &filePath)
{
m_settings.insert(SPECIFIC_CONFIG_FILE_PATH, QVariant(filePath.toString()));
}
@@ -148,11 +149,11 @@ QString UncrustifySettings::documentationFilePath() const
void UncrustifySettings::createDocumentationFile() const
{
- Utils::QtcProcess process;
+ QtcProcess process;
process.setTimeoutS(2);
process.setCommand({command(), {"--show-config"}});
process.runBlocking();
- if (process.result() != Utils::QtcProcess::FinishedWithSuccess)
+ if (process.result() != ProcessResult::FinishedWithSuccess)
return;
QFile file(documentationFilePath());
@@ -209,38 +210,5 @@ void UncrustifySettings::createDocumentationFile() const
}
}
-static bool parseVersion(const QString &text, int &version)
-{
- // The version in Uncrustify is printed like "uncrustify 0.62"
- const QRegularExpression rx("([0-9]{1})\\.([0-9]{2})");
- const QRegularExpressionMatch match = rx.match(text);
- if (!match.hasMatch())
- return false;
-
- const int major = match.captured(1).toInt() * 100;
- const int minor = match.captured(2).toInt();
- version = major + minor;
- return true;
-}
-
-void UncrustifySettings::updateVersion()
-{
- if (m_versionProcess.state() != QProcess::NotRunning) {
- m_versionProcess.kill();
- m_versionProcess.waitForFinished();
- }
- m_versionProcess.setCommand({ command(), { "--version" } });
- m_versionProcess.start();
-}
-
-void UncrustifySettings::parseVersionProcessResult()
-{
- if (m_versionProcess.exitStatus() != QProcess::NormalExit)
- return;
-
- if (!parseVersion(QString::fromUtf8(m_versionProcess.readAllStandardOutput()), m_version))
- parseVersion(QString::fromUtf8(m_versionProcess.readAllStandardError()), m_version);
-}
-
} // namespace Internal
} // namespace Beautifier
diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.h b/src/plugins/beautifier/uncrustify/uncrustifysettings.h
index 7c6e0a7e327..e2cd9e99ec2 100644
--- a/src/plugins/beautifier/uncrustify/uncrustifysettings.h
+++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.h
@@ -26,8 +26,6 @@
#pragma once
#include "../abstractsettings.h"
-#include <utils/fileutils.h>
-#include <utils/qtcprocess.h>
namespace Beautifier {
namespace Internal {
@@ -38,6 +36,7 @@ class UncrustifySettings : public AbstractSettings
public:
UncrustifySettings();
+ ~UncrustifySettings() override;
bool useOtherFiles() const;
void setUseOtherFiles(bool useOtherFiles);
@@ -57,17 +56,11 @@ public:
QString documentationFilePath() const override;
void createDocumentationFile() const override;
- void updateVersion() override;
-
Utils::FilePath specificConfigFile() const;
void setSpecificConfigFile(const Utils::FilePath &filePath);
bool useSpecificConfigFile() const;
void setUseSpecificConfigFile(bool useConfigFile);
-
-private:
- Utils::QtcProcess m_versionProcess;
- void parseVersionProcessResult();
};
} // namespace Internal
diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp
index 2856f44c252..1d3163cd4ca 100644
--- a/src/plugins/bineditor/bineditorplugin.cpp
+++ b/src/plugins/bineditor/bineditorplugin.cpp
@@ -455,7 +455,7 @@ BinEditorFactory::BinEditorFactory()
setDisplayName(QCoreApplication::translate("OpenWith::Editors", Constants::C_BINEDITOR_DISPLAY_NAME));
addMimeType(Constants::C_BINEDITOR_MIMETYPE);
- setEditorCreator([this] {
+ setEditorCreator([] {
auto widget = new BinEditorWidget();
auto editor = new BinEditor(widget);
diff --git a/src/plugins/bineditor/bineditorwidget.cpp b/src/plugins/bineditor/bineditorwidget.cpp
index d2ea7b28c49..2ae54122494 100644
--- a/src/plugins/bineditor/bineditorwidget.cpp
+++ b/src/plugins/bineditor/bineditorwidget.cpp
@@ -905,7 +905,7 @@ void BinEditorWidget::paintEvent(QPaintEvent *e)
int item_x = -xoffset + m_margin + c * m_columnWidth + m_labelWidth;
QColor color;
- foreach (const Markup &m, m_markup) {
+ for (const Markup &m : qAsConst(m_markup)) {
if (m.covers(lineAddress + c)) {
color = m.color;
break;
@@ -1236,7 +1236,7 @@ QString BinEditorWidget::toolTip(const QHelpEvent *helpEvent) const
str << "<html><head/><body><p align=\"center\"><b>"
<< tr("Memory at 0x%1").arg(address, 0, 16) << "</b></p>";
- foreach (const Markup &m, m_markup) {
+ for (const Markup &m : qAsConst(m_markup)) {
if (m.covers(address) && !m.toolTip.isEmpty()) {
str << "<p>" << m.toolTip << "</p><br>";
break;
diff --git a/src/plugins/boot2qt/CMakeLists.txt b/src/plugins/boot2qt/CMakeLists.txt
index d11cd580f9e..9713dc5b7ec 100644
--- a/src/plugins/boot2qt/CMakeLists.txt
+++ b/src/plugins/boot2qt/CMakeLists.txt
@@ -1,5 +1,6 @@
add_qtc_plugin(Boot2Qt
- DEPENDS Qt5::Network QtcSsh
+ PLUGIN_CLASS QdbPlugin
+ DEPENDS Qt5::Network
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport RemoteLinux
SOURCES
qdb.qrc
@@ -8,12 +9,10 @@ add_qtc_plugin(Boot2Qt
qdbdeployconfigurationfactory.cpp qdbdeployconfigurationfactory.h
qdbdevice.cpp qdbdevice.h
qdbdevicedebugsupport.cpp qdbdevicedebugsupport.h
- qdbmakedefaultappservice.cpp qdbmakedefaultappservice.h
qdbmakedefaultappstep.cpp qdbmakedefaultappstep.h
qdbplugin.cpp qdbplugin.h
qdbqtversion.cpp qdbqtversion.h
qdbrunconfiguration.cpp qdbrunconfiguration.h
- qdbstopapplicationservice.cpp qdbstopapplicationservice.h
qdbstopapplicationstep.cpp qdbstopapplicationstep.h
qdbutils.cpp qdbutils.h
)
diff --git a/src/plugins/boot2qt/boot2qt.qbs b/src/plugins/boot2qt/boot2qt.qbs
index 3487e3eb946..448659b47b3 100644
--- a/src/plugins/boot2qt/boot2qt.qbs
+++ b/src/plugins/boot2qt/boot2qt.qbs
@@ -27,14 +27,10 @@ QtcPlugin {
"qdbdevice.h",
"qdbdevicedebugsupport.cpp",
"qdbdevicedebugsupport.h",
- "qdbmakedefaultappservice.cpp",
- "qdbmakedefaultappservice.h",
"qdbmakedefaultappstep.cpp",
"qdbmakedefaultappstep.h",
"qdbplugin.cpp",
"qdbplugin.h",
- "qdbstopapplicationservice.cpp",
- "qdbstopapplicationservice.h",
"qdbstopapplicationstep.cpp",
"qdbstopapplicationstep.h",
"qdbqtversion.cpp",
diff --git a/src/plugins/boot2qt/device-detection/qdbwatcher.cpp b/src/plugins/boot2qt/device-detection/qdbwatcher.cpp
index 3d54227a514..7a782e09472 100644
--- a/src/plugins/boot2qt/device-detection/qdbwatcher.cpp
+++ b/src/plugins/boot2qt/device-detection/qdbwatcher.cpp
@@ -62,17 +62,10 @@ void QdbWatcher::start(RequestType requestType)
void QdbWatcher::startPrivate()
{
- void (QLocalSocket::*LocalSocketErrorFunction)(QLocalSocket::LocalSocketError)
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- = &QLocalSocket::error;
-#else
- = &QLocalSocket::errorOccurred;
-#endif
-
m_socket = std::unique_ptr<QLocalSocket>(new QLocalSocket());
connect(m_socket.get(), &QLocalSocket::connected,
this, &QdbWatcher::handleWatchConnection);
- connect(m_socket.get(), LocalSocketErrorFunction,
+ connect(m_socket.get(), &QLocalSocket::errorOccurred,
this, &QdbWatcher::handleWatchError);
m_socket->connectToServer(qdbSocketName);
}
diff --git a/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp b/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp
index a8b86a87ffd..535658f0f17 100644
--- a/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp
+++ b/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp
@@ -52,7 +52,6 @@ QdbDeployConfigurationFactory::QdbDeployConfigurationFactory()
return prj->deploymentKnowledge() == DeploymentKnowledge::Bad
&& prj->hasMakeInstallEquivalent();
});
- addInitialStep(RemoteLinux::Constants::CheckForFreeDiskSpaceId);
addInitialStep(Qdb::Constants::QdbStopApplicationStepId);
addInitialStep(RemoteLinux::Constants::DirectUploadStepId);
}
diff --git a/src/plugins/boot2qt/qdbdevice.cpp b/src/plugins/boot2qt/qdbdevice.cpp
index 7b858747e50..2a7a3e42e3d 100644
--- a/src/plugins/boot2qt/qdbdevice.cpp
+++ b/src/plugins/boot2qt/qdbdevice.cpp
@@ -31,13 +31,11 @@
#include <coreplugin/icore.h>
-#include <projectexplorer/applicationlauncher.h>
#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <projectexplorer/runcontrol.h>
-#include <remotelinux/linuxdeviceprocess.h>
-
-#include <ssh/sshconnection.h>
+#include <remotelinux/linuxprocessinterface.h>
#include <utils/portlist.h>
#include <utils/qtcassert.h>
@@ -49,80 +47,70 @@
#include <QWizard>
using namespace ProjectExplorer;
+using namespace RemoteLinux;
using namespace Utils;
namespace Qdb {
namespace Internal {
-class QdbDeviceProcess : public RemoteLinux::LinuxDeviceProcess
+class QdbProcessImpl : public LinuxProcessInterface
{
public:
- QdbDeviceProcess(const QSharedPointer<const IDevice> &device, QObject *parent)
- : RemoteLinux::LinuxDeviceProcess(device, parent)
- {
- }
+ QdbProcessImpl(const LinuxDevice *linuxDevice)
+ : LinuxProcessInterface(linuxDevice) {}
+ ~QdbProcessImpl() { killIfRunning(); }
- void terminate() override
+private:
+ void sendControlSignal(ControlSignal controlSignal) final
{
- ProjectExplorer::Runnable r;
- r.command = {Constants::AppcontrollerFilepath, {"--stop"}};
-
- (new ApplicationLauncher(this))->start(r, device());
+ QTC_ASSERT(controlSignal != ControlSignal::Interrupt, return);
+ QTC_ASSERT(controlSignal != ControlSignal::KickOff, return);
+ runInShell({Constants::AppcontrollerFilepath, {"--stop"}});
}
};
-
-class DeviceApplicationObserver : public ApplicationLauncher
+class DeviceApplicationObserver : public QObject
{
public:
DeviceApplicationObserver(const IDevice::ConstPtr &device, const CommandLine &command)
{
- connect(&m_appRunner, &ApplicationLauncher::appendMessage, this,
- &DeviceApplicationObserver::handleAppendMessage);
- connect(&m_appRunner, &ApplicationLauncher::error, this,
- [this] { m_error = m_appRunner.errorString(); });
- connect(&m_appRunner, &ApplicationLauncher::processExited, this,
- &DeviceApplicationObserver::handleFinished);
+ connect(&m_appRunner, &QtcProcess::done, this, &DeviceApplicationObserver::handleDone);
QTC_ASSERT(device, return);
m_deviceName = device->displayName();
- Runnable r;
- r.command = command;
- m_appRunner.start(r, device);
+ m_appRunner.setCommand(command);
+ m_appRunner.start();
showMessage(QdbDevice::tr("Starting command \"%1\" on device \"%2\".")
.arg(command.toUserOutput(), m_deviceName));
}
private:
- void handleAppendMessage(const QString &data, Utils::OutputFormat format)
+ void handleDone()
{
- if (format == Utils::StdOutFormat)
- m_stdout += data;
- else if (format == Utils::StdErrFormat)
- m_stderr += data;
- }
+ const QString stdOut = m_appRunner.cleanedStdOut();
+ const QString stdErr = m_appRunner.cleanedStdErr();
- void handleFinished(int exitCode, QProcess::ExitStatus exitStatus)
- {
- Q_UNUSED(exitCode)
// FIXME: Needed in a post-adb world?
// adb does not forward exit codes and all stderr goes to stdout.
- const bool failure = exitStatus == QProcess::CrashExit || m_stdout.contains("fail")
- || m_stdout.contains("error") || m_stdout.contains("not found");
+ const bool failure = m_appRunner.result() != ProcessResult::FinishedWithSuccess
+ || stdOut.contains("fail")
+ || stdOut.contains("error")
+ || stdOut.contains("not found");
+
if (failure) {
QString errorString;
- if (!m_error.isEmpty()) {
+ if (!m_appRunner.errorString().isEmpty()) {
errorString = QdbDevice::tr("Command failed on device \"%1\": %2")
- .arg(m_deviceName, m_error);
+ .arg(m_deviceName, m_appRunner.errorString());
} else {
errorString = QdbDevice::tr("Command failed on device \"%1\".").arg(m_deviceName);
}
showMessage(errorString, true);
- if (!m_stdout.isEmpty())
- showMessage(QdbDevice::tr("stdout was: \"%1\"").arg(m_stdout));
- if (!m_stderr.isEmpty())
- showMessage(QdbDevice::tr("stderr was: \"%1\"").arg(m_stderr));
+ if (!stdOut.isEmpty())
+ showMessage(QdbDevice::tr("stdout was: \"%1\"").arg(stdOut));
+ if (!stdErr.isEmpty())
+ showMessage(QdbDevice::tr("stderr was: \"%1\"").arg(stdErr));
} else {
showMessage(QdbDevice::tr("Commands on device \"%1\" finished successfully.")
.arg(m_deviceName));
@@ -130,11 +118,8 @@ private:
deleteLater();
}
- QString m_stdout;
- QString m_stderr;
- ProjectExplorer::ApplicationLauncher m_appRunner;
+ QtcProcess m_appRunner;
QString m_deviceName;
- QString m_error;
};
@@ -145,11 +130,11 @@ QdbDevice::QdbDevice()
setDisplayType(tr("Boot2Qt Device"));
addDeviceAction({tr("Reboot Device"), [](const IDevice::Ptr &device, QWidget *) {
- (void) new DeviceApplicationObserver(device, CommandLine{"reboot"});
+ (void) new DeviceApplicationObserver(device, {device->filePath("reboot"), {}});
}});
addDeviceAction({tr("Restore Default App"), [](const IDevice::Ptr &device, QWidget *) {
- (void) new DeviceApplicationObserver(device, CommandLine{"appcontroller", {"--remove-default"}});
+ (void) new DeviceApplicationObserver(device, {device->filePath("appcontroller"), {"--remove-default"}});
}});
}
@@ -160,9 +145,9 @@ ProjectExplorer::IDeviceWidget *QdbDevice::createWidget()
return w;
}
-ProjectExplorer::DeviceProcess *QdbDevice::createProcess(QObject *parent) const
+ProcessInterface *QdbDevice::createProcessInterface() const
{
- return new QdbDeviceProcess(sharedFromThis(), parent);
+ return new QdbProcessImpl(this);
}
void QdbDevice::setSerialNumber(const QString &serial)
@@ -192,12 +177,12 @@ void QdbDevice::setupDefaultNetworkSettings(const QString &host)
{
setFreePorts(Utils::PortList::fromString("10000-10100"));
- QSsh::SshConnectionParameters parameters = sshParameters();
+ SshParameters parameters = sshParameters();
parameters.setHost(host);
parameters.setUserName("root");
parameters.setPort(22);
parameters.timeout = 10;
- parameters.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypeAll;
+ parameters.authenticationType = SshParameters::AuthenticationTypeAll;
setSshParameters(parameters);
}
diff --git a/src/plugins/boot2qt/qdbdevice.h b/src/plugins/boot2qt/qdbdevice.h
index 191a410633d..fce5d79f0bd 100644
--- a/src/plugins/boot2qt/qdbdevice.h
+++ b/src/plugins/boot2qt/qdbdevice.h
@@ -44,7 +44,7 @@ public:
ProjectExplorer::IDeviceWidget *createWidget() final;
- ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const final;
+ Utils::ProcessInterface *createProcessInterface() const override;
void setSerialNumber(const QString &serial);
QString serialNumber() const;
diff --git a/src/plugins/boot2qt/qdbdevicedebugsupport.cpp b/src/plugins/boot2qt/qdbdevicedebugsupport.cpp
index 153c21be453..e09b134e74f 100644
--- a/src/plugins/boot2qt/qdbdevicedebugsupport.cpp
+++ b/src/plugins/boot2qt/qdbdevicedebugsupport.cpp
@@ -31,9 +31,8 @@
#include <debugger/debuggerruncontrol.h>
-#include <ssh/sshconnection.h>
-
#include <utils/algorithm.h>
+#include <utils/qtcprocess.h>
#include <utils/url.h>
using namespace Debugger;
@@ -55,12 +54,16 @@ public:
{
setId("QdbDebuggeeRunner");
- connect(&m_launcher, &ApplicationLauncher::processStarted,
- this, &RunWorker::reportStarted);
- connect(&m_launcher, &ApplicationLauncher::processExited,
- this, &RunWorker::reportStopped);
- connect(&m_launcher, &ApplicationLauncher::appendMessage,
- this, &RunWorker::appendMessage);
+ connect(&m_launcher, &QtcProcess::started, this, &RunWorker::reportStarted);
+ connect(&m_launcher, &QtcProcess::done, this, &RunWorker::reportStopped);
+
+ connect(&m_launcher, &QtcProcess::readyReadStandardOutput, [this] {
+ appendMessage(QString::fromUtf8(m_launcher.readAllStandardOutput()), StdOutFormat);
+ });
+ connect(&m_launcher, &QtcProcess::readyReadStandardError, [this] {
+ appendMessage(QString::fromUtf8(m_launcher.readAllStandardError()), StdErrFormat);
+ });
+
m_portsGatherer = new DebugServerPortsGatherer(runControl);
m_portsGatherer->setUseGdbServer(useGdbServer || usePerf);
m_portsGatherer->setUseQmlServer(useQmlServer);
@@ -80,16 +83,17 @@ public:
int lowerPort = 0;
int upperPort = 0;
- Runnable r = runnable();
+ CommandLine cmd;
+ cmd.setExecutable(device()->filePath(Constants::AppcontrollerFilepath));
- QString args;
if (m_useGdbServer) {
- args.append(" --debug-gdb");
+ cmd.addArg("--debug-gdb");
lowerPort = upperPort = gdbServerPort;
}
if (m_useQmlServer) {
- args.append(" --debug-qml --qml-debug-services ");
- args.append(QmlDebug::qmlDebugServices(m_qmlServices));
+ cmd.addArg("--debug-qml");
+ cmd.addArg("--qml-debug-services");
+ cmd.addArg(QmlDebug::qmlDebugServices(m_qmlServices));
lowerPort = upperPort = qmlServerPort;
}
if (m_useGdbServer && m_useQmlServer) {
@@ -106,22 +110,21 @@ public:
QString args = Utils::transform(perfRecordArgs.toStringList(), [](QString arg) {
return arg.replace(',', ",,");
}).join(',');
- args.append(QString(" --profile-perf %1").arg(args));
+ cmd.addArg("--profile-perf");
+ cmd.addArg(args);
lowerPort = upperPort = perfPort;
}
- args.append(QString(" --port-range %1-%2 ").arg(lowerPort).arg(upperPort));
- // FIXME: Breaks with spaces!
- args.append(r.command.executable().toString());
- args.append(" ");
- args.append(r.command.arguments());
-
- r.command.setArguments(args);
- r.command.setExecutable(FilePath::fromString(Constants::AppcontrollerFilepath));
-
- m_launcher.start(r, device());
+ cmd.addArg("--port-range");
+ cmd.addArg(QString("%1-%2").arg(lowerPort).arg(upperPort));
+ cmd.addCommandLineAsArgs(runControl()->commandLine());
+
+ m_launcher.setCommand(cmd);
+ m_launcher.setWorkingDirectory(runControl()->workingDirectory());
+ m_launcher.setEnvironment(runControl()->environment());
+ m_launcher.start();
}
- void stop() override { m_launcher.stop(); }
+ void stop() override { m_launcher.close(); }
private:
Debugger::DebugServerPortsGatherer *m_portsGatherer = nullptr;
@@ -129,7 +132,7 @@ private:
bool m_useGdbServer;
bool m_useQmlServer;
QmlDebug::QmlDebugServicesPreset m_qmlServices;
- ApplicationLauncher m_launcher;
+ QtcProcess m_launcher;
};
diff --git a/src/plugins/boot2qt/qdbmakedefaultappservice.cpp b/src/plugins/boot2qt/qdbmakedefaultappservice.cpp
deleted file mode 100644
index 20192d6aad6..00000000000
--- a/src/plugins/boot2qt/qdbmakedefaultappservice.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "qdbmakedefaultappservice.h"
-
-#include "qdbconstants.h"
-#include "qdbrunconfiguration.h"
-
-#include <ssh/sshremoteprocessrunner.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/runconfigurationaspects.h>
-
-namespace Qdb {
-namespace Internal {
-
-class QdbMakeDefaultAppServicePrivate
-{
-public:
- bool makeDefault;
- QSsh::SshRemoteProcessRunner *processRunner;
-};
-
-QdbMakeDefaultAppService::QdbMakeDefaultAppService(QObject *parent)
- : AbstractRemoteLinuxDeployService(parent),
- d(new QdbMakeDefaultAppServicePrivate)
-{
- d->processRunner = 0;
- d->makeDefault = true;
-}
-
-QdbMakeDefaultAppService::~QdbMakeDefaultAppService()
-{
- cleanup();
- delete d;
-}
-
-void QdbMakeDefaultAppService::setMakeDefault(bool makeDefault)
-{
- d->makeDefault = makeDefault;
-}
-
-void QdbMakeDefaultAppService::handleStdErr()
-{
- emit stdErrData(QString::fromUtf8(d->processRunner->readAllStandardError()));
-}
-
-void QdbMakeDefaultAppService::handleProcessFinished(const QString &error)
-{
- if (!error.isEmpty()) {
- emit errorMessage(tr("Remote process failed: %1").arg(error));
- stopDeployment();
- return;
- }
-
- // FIXME: Check that ignoring is fine
- QByteArray processOutput = d->processRunner->readAllStandardOutput();
-
- if (d->makeDefault)
- emit progressMessage(tr("Application set as the default one."));
- else
- emit progressMessage(tr("Reset the default application."));
-
- stopDeployment();
-}
-
-void QdbMakeDefaultAppService::doDeploy()
-{
- d->processRunner = new QSsh::SshRemoteProcessRunner;
- connect(d->processRunner, &QSsh::SshRemoteProcessRunner::processClosed,
- this, &QdbMakeDefaultAppService::handleProcessFinished);
- connect(d->processRunner, &QSsh::SshRemoteProcessRunner::readyReadStandardError,
- this, &QdbMakeDefaultAppService::handleStdErr);
-
- QString remoteExe;
-
- if (ProjectExplorer::RunConfiguration *rc = target()->activeRunConfiguration()) {
- if (auto exeAspect = rc->aspect<ProjectExplorer::ExecutableAspect>())
- remoteExe = exeAspect->executable().toString();
- }
-
- QString command = Constants::AppcontrollerFilepath;
- command += d->makeDefault && !remoteExe.isEmpty() ? QStringLiteral(" --make-default ") + remoteExe
- : QStringLiteral(" --remove-default");
-
- d->processRunner->run(command, deviceConfiguration()->sshParameters());
-}
-
-void QdbMakeDefaultAppService::stopDeployment()
-{
- cleanup();
- handleDeploymentDone();
-}
-
-void QdbMakeDefaultAppService::cleanup()
-{
- if (d->processRunner) {
- disconnect(d->processRunner, 0, this, 0);
- d->processRunner->cancel();
- delete d->processRunner;
- d->processRunner = 0;
- }
-}
-
-} // namespace Internal
-} // namespace Qdb
diff --git a/src/plugins/boot2qt/qdbmakedefaultappservice.h b/src/plugins/boot2qt/qdbmakedefaultappservice.h
deleted file mode 100644
index cab4b4cb331..00000000000
--- a/src/plugins/boot2qt/qdbmakedefaultappservice.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <remotelinux/abstractremotelinuxdeployservice.h>
-
-namespace Qdb {
-namespace Internal {
-
-class QdbMakeDefaultAppServicePrivate;
-
-class QdbMakeDefaultAppService : public RemoteLinux::AbstractRemoteLinuxDeployService
-{
- Q_OBJECT
-public:
- QdbMakeDefaultAppService(QObject *parent = 0);
- ~QdbMakeDefaultAppService();
- void setMakeDefault(bool makeDefault);
-
-private:
- void handleStdErr();
- void handleProcessFinished(const QString &error);
-
- bool isDeploymentNecessary() const final { return true; }
-
- void doDeploy() final;
- void stopDeployment() final;
-
- void cleanup();
-
- QdbMakeDefaultAppServicePrivate * const d;
-};
-
-} // namespace Internal
-} // namespace Qdb
diff --git a/src/plugins/boot2qt/qdbmakedefaultappstep.cpp b/src/plugins/boot2qt/qdbmakedefaultappstep.cpp
index a88a6391f83..2e42a77fa51 100644
--- a/src/plugins/boot2qt/qdbmakedefaultappstep.cpp
+++ b/src/plugins/boot2qt/qdbmakedefaultappstep.cpp
@@ -26,41 +26,108 @@
#include "qdbmakedefaultappstep.h"
#include "qdbconstants.h"
-#include "qdbmakedefaultappservice.h"
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/target.h>
+#include <remotelinux/abstractremotelinuxdeployservice.h>
#include <remotelinux/abstractremotelinuxdeploystep.h>
+#include <utils/commandline.h>
+#include <utils/qtcprocess.h>
+
using namespace ProjectExplorer;
using namespace Utils;
namespace Qdb {
namespace Internal {
-class QdbMakeDefaultAppStep final : public RemoteLinux::AbstractRemoteLinuxDeployStep
+// QdbMakeDefaultAppService
+
+class QdbMakeDefaultAppService : public RemoteLinux::AbstractRemoteLinuxDeployService
{
- Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbMakeDefaultAppStep)
+ Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbMakeDefaultAppService)
public:
- QdbMakeDefaultAppStep(BuildStepList *bsl, Utils::Id id);
+ QdbMakeDefaultAppService()
+ {
+ connect(&m_process, &QtcProcess::done, this, [this] {
+ if (m_process.error() != QProcess::UnknownError)
+ emit errorMessage(tr("Remote process failed: %1").arg(m_process.errorString()));
+ else if (m_makeDefault)
+ emit progressMessage(tr("Application set as the default one."));
+ else
+ emit progressMessage(tr("Reset the default application."));
+
+ stopDeployment();
+ });
+ connect(&m_process, &QtcProcess::readyReadStandardError, this, [this] {
+ emit stdErrData(QString::fromUtf8(m_process.readAllStandardError()));
+ });
+ }
+
+ void setMakeDefault(bool makeDefault)
+ {
+ m_makeDefault = makeDefault;
+ }
+
+private:
+ bool isDeploymentNecessary() const final { return true; }
+
+ void doDeploy() final
+ {
+ QString remoteExe;
+
+ if (RunConfiguration *rc = target()->activeRunConfiguration()) {
+ if (auto exeAspect = rc->aspect<ExecutableAspect>())
+ remoteExe = exeAspect->executable().toString();
+ }
+
+ const QString args = m_makeDefault && !remoteExe.isEmpty()
+ ? QStringLiteral("--make-default ") + remoteExe
+ : QStringLiteral("--remove-default");
+ m_process.setCommand(
+ {deviceConfiguration()->filePath(Constants::AppcontrollerFilepath), {args}});
+ m_process.start();
+ }
+
+ void stopDeployment() final
+ {
+ m_process.close();
+ handleDeploymentDone();
+ }
+
+ bool m_makeDefault = true;
+ QtcProcess m_process;
};
-QdbMakeDefaultAppStep::QdbMakeDefaultAppStep(BuildStepList *bsl, Utils::Id id)
- : AbstractRemoteLinuxDeployStep(bsl, id)
+
+// QdbMakeDefaultAppStep
+
+class QdbMakeDefaultAppStep final : public RemoteLinux::AbstractRemoteLinuxDeployStep
{
- auto service = createDeployService<QdbMakeDefaultAppService>();
+ Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbMakeDefaultAppStep)
- auto selection = addAspect<SelectionAspect>();
- selection->setSettingsKey("QdbMakeDefaultDeployStep.MakeDefault");
- selection->addOption(tr("Set this application to start by default"));
- selection->addOption(tr("Reset default application"));
+public:
+ QdbMakeDefaultAppStep(BuildStepList *bsl, Id id)
+ : AbstractRemoteLinuxDeployStep(bsl, id)
+ {
+ auto service = createDeployService<QdbMakeDefaultAppService>();
+
+ auto selection = addAspect<SelectionAspect>();
+ selection->setSettingsKey("QdbMakeDefaultDeployStep.MakeDefault");
+ selection->addOption(tr("Set this application to start by default"));
+ selection->addOption(tr("Reset default application"));
+
+ setInternalInitializer([service, selection] {
+ service->setMakeDefault(selection->value() == 0);
+ return service->isDeploymentPossible();
+ });
+ }
+};
- setInternalInitializer([service, selection] {
- service->setMakeDefault(selection->value() == 0);
- return service->isDeploymentPossible();
- });
-}
// QdbMakeDefaultAppStepFactory
diff --git a/src/plugins/boot2qt/qdbplugin.cpp b/src/plugins/boot2qt/qdbplugin.cpp
index b9b8aa237d7..711cdb50099 100644
--- a/src/plugins/boot2qt/qdbplugin.cpp
+++ b/src/plugins/boot2qt/qdbplugin.cpp
@@ -47,7 +47,6 @@
#include <remotelinux/genericdirectuploadstep.h>
#include <remotelinux/makeinstallstep.h>
-#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
#include <remotelinux/remotelinux_constants.h>
#include <utils/hostosinfo.h>
@@ -142,12 +141,12 @@ public:
QdbDeviceRunSupport(RunControl *runControl)
: SimpleTargetRunner(runControl)
{
- setStarter([this, runControl] {
- Runnable r = runControl->runnable();
- // FIXME: Spaces!
- r.command.setArguments(r.command.executable().toString() + ' ' + r.command.arguments());
- r.command.setExecutable(FilePath::fromString(Constants::AppcontrollerFilepath));
- doStart(r, runControl->device());
+ setStartModifier([this] {
+ CommandLine plain = commandLine();
+ CommandLine cmd;
+ cmd.setExecutable(plain.executable().withNewPath(Constants::AppcontrollerFilepath));
+ cmd.addCommandLineAsArgs(plain);
+ setCommandLine(cmd);
});
}
};
@@ -177,8 +176,6 @@ public:
QdbStopApplicationStepFactory m_stopApplicationStepFactory;
QdbMakeDefaultAppStepFactory m_makeDefaultAppStepFactory;
- QdbDeployStepFactory<RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep>
- m_checkForFreeDiskSpaceStepFactory{RemoteLinux::Constants::CheckForFreeDiskSpaceId};
QdbDeployStepFactory<RemoteLinux::GenericDirectUploadStep>
m_directUploadStepFactory{RemoteLinux::Constants::DirectUploadStepId};
QdbDeployStepFactory<RemoteLinux::MakeInstallStep>
diff --git a/src/plugins/boot2qt/qdbrunconfiguration.cpp b/src/plugins/boot2qt/qdbrunconfiguration.cpp
index 56dc0af8d62..4c09f3c2086 100644
--- a/src/plugins/boot2qt/qdbrunconfiguration.cpp
+++ b/src/plugins/boot2qt/qdbrunconfiguration.cpp
@@ -36,6 +36,8 @@
#include <remotelinux/remotelinuxenvironmentaspect.h>
+#include <utils/commandline.h>
+
using namespace ProjectExplorer;
using namespace Utils;
@@ -56,11 +58,12 @@ public:
auto exeAspect = rc->aspect<ExecutableAspect>();
auto argumentsAspect = rc->aspect<ArgumentsAspect>();
- auto updateCommandLine = [this, rc, exeAspect, argumentsAspect] {
- const QString usedExecutable = exeAspect->executable().toString();
- const QString args = argumentsAspect->arguments(rc->macroExpander());
- setValue(QString(Constants::AppcontrollerFilepath)
- + ' ' + usedExecutable + ' ' + args);
+ auto updateCommandLine = [this, exeAspect, argumentsAspect] {
+ CommandLine plain{exeAspect->executable(), argumentsAspect->arguments(), CommandLine::Raw};
+ CommandLine cmd;
+ cmd.setExecutable(plain.executable().withNewPath(Constants::AppcontrollerFilepath));
+ cmd.addCommandLineAsArgs(plain);
+ setValue(cmd.toUserOutput());
};
connect(argumentsAspect, &ArgumentsAspect::changed, this, updateCommandLine);
@@ -84,13 +87,12 @@ private:
QString defaultDisplayName() const;
};
-QdbRunConfiguration::QdbRunConfiguration(Target *target, Utils::Id id)
+QdbRunConfiguration::QdbRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- auto exeAspect = addAspect<ExecutableAspect>();
+ auto exeAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
exeAspect->setSettingsKey("QdbRunConfig.RemoteExecutable");
exeAspect->setLabelText(tr("Executable on device:"));
- exeAspect->setExecutablePathStyle(OsTypeLinux);
exeAspect->setPlaceHolderText(tr("Remote path not set"));
exeAspect->makeOverridable("QdbRunConfig.AlternateRemoteExecutable",
"QdbRunCofig.UseAlternateRemoteExecutable");
@@ -100,9 +102,10 @@ QdbRunConfiguration::QdbRunConfiguration(Target *target, Utils::Id id)
symbolsAspect->setLabelText(tr("Executable on host:"));
symbolsAspect->setDisplayStyle(SymbolFileAspect::LabelDisplay);
- addAspect<RemoteLinux::RemoteLinuxEnvironmentAspect>(target);
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ auto envAspect = addAspect<RemoteLinux::RemoteLinuxEnvironmentAspect>(target);
+
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
addAspect<FullCommandLineAspect>(this);
setUpdater([this, target, exeAspect, symbolsAspect] {
diff --git a/src/plugins/boot2qt/qdbstopapplicationservice.cpp b/src/plugins/boot2qt/qdbstopapplicationservice.cpp
deleted file mode 100644
index 018e6bdbb70..00000000000
--- a/src/plugins/boot2qt/qdbstopapplicationservice.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "qdbstopapplicationservice.h"
-
-#include "qdbconstants.h"
-
-#include <projectexplorer/applicationlauncher.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/runcontrol.h>
-#include <projectexplorer/target.h>
-
-using namespace Utils;
-
-namespace Qdb {
-namespace Internal {
-
-class QdbStopApplicationServicePrivate
-{
-public:
- ProjectExplorer::ApplicationLauncher applicationLauncher;
- QString errorOutput;
-};
-
-QdbStopApplicationService::QdbStopApplicationService(QObject *parent)
- : AbstractRemoteLinuxDeployService(parent),
- d(new QdbStopApplicationServicePrivate)
-{
-
-}
-
-QdbStopApplicationService::~QdbStopApplicationService()
-{
- cleanup();
- delete d;
-}
-
-void QdbStopApplicationService::handleProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
-{
- Q_UNUSED(exitCode)
- const auto failureMessage = tr("Could not check and possibly stop running application.");
- if (exitStatus == QProcess::CrashExit) {
- emit errorMessage(failureMessage);
- stopDeployment();
- return;
- }
-
- if (d->errorOutput.contains("Could not connect: Connection refused")) {
- emit progressMessage(tr("Checked that there is no running application."));
- } else if (!d->errorOutput.isEmpty()) {
- emit stdErrData(d->errorOutput);
- emit errorMessage(failureMessage);
- } else {
- emit progressMessage(tr("Stopped the running application."));
- }
-
- stopDeployment();
-}
-
-void QdbStopApplicationService::handleAppendMessage(const QString &message, Utils::OutputFormat format)
-{
- if (format == Utils::StdErrFormat)
- d->errorOutput.append(message);
- else
- emit stdOutData(message);
-}
-
-void QdbStopApplicationService::doDeploy()
-{
- connect(&d->applicationLauncher, &ProjectExplorer::ApplicationLauncher::error,
- this, [this] { emit stdErrData(d->applicationLauncher.errorString()); });
- connect(&d->applicationLauncher, &ProjectExplorer::ApplicationLauncher::processExited,
- this, &QdbStopApplicationService::handleProcessFinished);
- connect(&d->applicationLauncher, &ProjectExplorer::ApplicationLauncher::appendMessage,
- this, &QdbStopApplicationService::handleAppendMessage);
-
- ProjectExplorer::Runnable runnable;
- runnable.command = {Constants::AppcontrollerFilepath, {"--stop"}};
- runnable.workingDirectory = "/usr/bin";
-
- d->applicationLauncher.start(runnable,
- ProjectExplorer::DeviceKitAspect::device(target()->kit()));
-}
-
-void QdbStopApplicationService::stopDeployment()
-{
- cleanup();
- handleDeploymentDone();
-}
-
-void QdbStopApplicationService::cleanup()
-{
- d->applicationLauncher.disconnect(this);
-}
-
-} // namespace Internal
-} // namespace Qdb
diff --git a/src/plugins/boot2qt/qdbstopapplicationservice.h b/src/plugins/boot2qt/qdbstopapplicationservice.h
deleted file mode 100644
index f9b35681823..00000000000
--- a/src/plugins/boot2qt/qdbstopapplicationservice.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <remotelinux/abstractremotelinuxdeployservice.h>
-#include <utils/outputformat.h>
-
-#include <QProcess>
-
-namespace Qdb {
-namespace Internal {
-
-class QdbStopApplicationServicePrivate;
-
-class QdbStopApplicationService : public RemoteLinux::AbstractRemoteLinuxDeployService
-{
- Q_OBJECT
-public:
- QdbStopApplicationService(QObject *parent = 0);
- ~QdbStopApplicationService();
-
-private:
- void handleProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
- void handleAppendMessage(const QString &message, Utils::OutputFormat format);
-
- bool isDeploymentNecessary() const final { return true; }
-
- void doDeploy() final;
- void stopDeployment() final;
-
- void cleanup();
-
- QdbStopApplicationServicePrivate * const d;
-};
-
-} // namespace Internal
-} // namespace Qdb
diff --git a/src/plugins/boot2qt/qdbstopapplicationstep.cpp b/src/plugins/boot2qt/qdbstopapplicationstep.cpp
index c5a847c1195..106685b4268 100644
--- a/src/plugins/boot2qt/qdbstopapplicationstep.cpp
+++ b/src/plugins/boot2qt/qdbstopapplicationstep.cpp
@@ -26,35 +26,126 @@
#include "qdbstopapplicationstep.h"
#include "qdbconstants.h"
-#include "qdbstopapplicationservice.h"
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/runcontrol.h>
+#include <projectexplorer/target.h>
+#include <remotelinux/abstractremotelinuxdeployservice.h>
#include <remotelinux/abstractremotelinuxdeploystep.h>
+#include <utils/qtcprocess.h>
+
using namespace ProjectExplorer;
+using namespace Utils;
namespace Qdb {
namespace Internal {
-class QdbStopApplicationStep final : public RemoteLinux::AbstractRemoteLinuxDeployStep
+// QdbStopApplicationService
+
+class QdbStopApplicationService : public RemoteLinux::AbstractRemoteLinuxDeployService
{
- Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbStopApplicationStep)
+ Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbStopApplicationService)
public:
- QdbStopApplicationStep(BuildStepList *bsl, Utils::Id id);
+ QdbStopApplicationService() {}
+ ~QdbStopApplicationService() { cleanup(); }
+
+private:
+ void handleProcessDone();
+
+ bool isDeploymentNecessary() const final { return true; }
+
+ void doDeploy() final;
+ void stopDeployment() final;
+
+ void cleanup();
+
+ QtcProcess m_process;
+ QString m_errorOutput;
};
-QdbStopApplicationStep::QdbStopApplicationStep(BuildStepList *bsl, Utils::Id id)
- : AbstractRemoteLinuxDeployStep(bsl, id)
+void QdbStopApplicationService::handleProcessDone()
{
- auto service = createDeployService<QdbStopApplicationService>();
+ const QString failureMessage = tr("Could not check and possibly stop running application.");
- setWidgetExpandedByDefault(false);
+ if (m_process.exitStatus() == QProcess::CrashExit) {
+ emit errorMessage(failureMessage);
+ stopDeployment();
+ return;
+ }
- setInternalInitializer([service] { return service->isDeploymentPossible(); });
+ if (m_process.result() != ProcessResult::FinishedWithSuccess) {
+ emit stdErrData(m_process.errorString());
+ return;
+ }
+
+ if (m_errorOutput.contains("Could not connect: Connection refused")) {
+ emit progressMessage(tr("Checked that there is no running application."));
+ } else if (!m_errorOutput.isEmpty()) {
+ emit stdErrData(m_errorOutput);
+ emit errorMessage(failureMessage);
+ } else {
+ emit progressMessage(tr("Stopped the running application."));
+ }
+
+ stopDeployment();
}
+void QdbStopApplicationService::doDeploy()
+{
+ auto device = DeviceKitAspect::device(target()->kit());
+ QTC_ASSERT(device, return);
+
+ connect(&m_process, &QtcProcess::done,
+ this, &QdbStopApplicationService::handleProcessDone);
+
+ connect(&m_process, &QtcProcess::readyReadStandardError, this, [this] {
+ m_errorOutput.append(QString::fromUtf8(m_process.readAllStandardError()));
+ });
+ connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
+ emit stdOutData(QString::fromUtf8(m_process.readAllStandardOutput()));
+ });
+
+ m_process.setCommand({device->filePath(Constants::AppcontrollerFilepath), {"--stop"}});
+ m_process.setWorkingDirectory("/usr/bin");
+ m_process.start();
+}
+
+void QdbStopApplicationService::stopDeployment()
+{
+ cleanup();
+ handleDeploymentDone();
+}
+
+void QdbStopApplicationService::cleanup()
+{
+ m_process.close();
+}
+
+
+// QdbStopApplicationStep
+
+class QdbStopApplicationStep final : public RemoteLinux::AbstractRemoteLinuxDeployStep
+{
+ Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbStopApplicationStep)
+
+public:
+ QdbStopApplicationStep(BuildStepList *bsl, Id id)
+ : AbstractRemoteLinuxDeployStep(bsl, id)
+ {
+ auto service = createDeployService<QdbStopApplicationService>();
+
+ setWidgetExpandedByDefault(false);
+
+ setInternalInitializer([service] { return service->isDeploymentPossible(); });
+ }
+};
+
+
// QdbStopApplicationStepFactory
QdbStopApplicationStepFactory::QdbStopApplicationStepFactory()
diff --git a/src/plugins/clangcodemodel/CMakeLists.txt b/src/plugins/clangcodemodel/CMakeLists.txt
index 1e8b9a53e95..9205ba340bf 100644
--- a/src/plugins/clangcodemodel/CMakeLists.txt
+++ b/src/plugins/clangcodemodel/CMakeLists.txt
@@ -4,52 +4,33 @@ if(WITH_TESTS)
endif()
add_qtc_plugin(ClangCodeModel
- CONDITION TARGET libclang
- DEPENDS ClangSupport CPlusPlus
+ DEPENDS CPlusPlus
PLUGIN_DEPENDS Core CppEditor LanguageClient ${TEST_LINK_DEPENDS} TextEditor
PLUGIN_TEST_DEPENDS QmakeProjectManager
+ DEFINES
+ CLANG_BINDIR="${LLVM_TOOLS_BINARY_DIR}"
SOURCES
clangactivationsequencecontextprocessor.cpp clangactivationsequencecontextprocessor.h
clangactivationsequenceprocessor.cpp clangactivationsequenceprocessor.h
- clangassistproposalitem.cpp clangassistproposalitem.h
- clangassistproposalmodel.cpp clangassistproposalmodel.h
- clangbackendcommunicator.cpp clangbackendcommunicator.h
- clangbackendlogging.cpp clangbackendlogging.h
- clangbackendreceiver.cpp clangbackendreceiver.h
- clangbackendsender.cpp clangbackendsender.h
clangcodemodelplugin.cpp clangcodemodelplugin.h
- clangcompletionassistinterface.cpp clangcompletionassistinterface.h
- clangcompletionassistprocessor.cpp clangcompletionassistprocessor.h
- clangcompletionassistprovider.cpp clangcompletionassistprovider.h
- clangcompletionchunkstotextconverter.cpp clangcompletionchunkstotextconverter.h
clangcompletioncontextanalyzer.cpp clangcompletioncontextanalyzer.h
clangconstants.h
- clangcurrentdocumentfilter.cpp clangcurrentdocumentfilter.h
+ clangdast.cpp clangdast.h
clangdclient.cpp clangdclient.h
- clangdiagnosticfilter.cpp clangdiagnosticfilter.h
- clangdiagnosticmanager.cpp clangdiagnosticmanager.h
+ clangdfollowsymbol.cpp clangdfollowsymbol.h
clangdiagnostictooltipwidget.cpp clangdiagnostictooltipwidget.h
clangdquickfixfactory.cpp clangdquickfixfactory.h
clangdqpropertyhighlighter.cpp clangdqpropertyhighlighter.h
- clangeditordocumentparser.cpp clangeditordocumentparser.h
+ clangdsemantichighlighting.cpp clangdsemantichighlighting.h
+ clangdswitchdecldef.cpp clangdswitchdecldef.h
clangeditordocumentprocessor.cpp clangeditordocumentprocessor.h
clangfixitoperation.cpp clangfixitoperation.h
- clangfixitoperationsextractor.cpp clangfixitoperationsextractor.h
- clangfollowsymbol.cpp clangfollowsymbol.h
- clangfunctionhintmodel.cpp clangfunctionhintmodel.h
clangdlocatorfilters.cpp clangdlocatorfilters.h
- clanghighlightingresultreporter.cpp clanghighlightingresultreporter.h
- clanghoverhandler.cpp clanghoverhandler.h
- clangisdiagnosticrelatedtolocation.h
clangmodelmanagersupport.cpp clangmodelmanagersupport.h
- clangoverviewmodel.cpp clangoverviewmodel.h
clangpreprocessorassistproposalitem.cpp clangpreprocessorassistproposalitem.h
- clangprojectsettings.cpp clangprojectsettings.h
- clangprojectsettingswidget.cpp clangprojectsettingswidget.h clangprojectsettingswidget.ui
- clangrefactoringengine.cpp clangrefactoringengine.h
clangtextmark.cpp clangtextmark.h
- clanguiheaderondiskmanager.cpp clanguiheaderondiskmanager.h
clangutils.cpp clangutils.h
+ tasktimers.cpp tasktimers.h
EXPLICIT_MOC clangcodemodelplugin.h
)
@@ -65,10 +46,10 @@ extend_qtc_plugin(ClangCodeModel
extend_qtc_plugin(ClangCodeModel
CONDITION WITH_TESTS
SOURCES
- test/clangautomationutils.cpp test/clangautomationutils.h
+ test/activationsequenceprocessortest.cpp test/activationsequenceprocessortest.h
test/clangbatchfileprocessor.cpp test/clangbatchfileprocessor.h
- test/clangcodecompletion_test.cpp test/clangcodecompletion_test.h
test/clangdtests.cpp test/clangdtests.h
+ test/clangfixittest.cpp test/clangfixittest.h
test/data/clangtestdata.qrc
)
diff --git a/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp
index 0eaffa3f724..db5e71bde43 100644
--- a/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp
@@ -52,13 +52,6 @@ ActivationSequenceContextProcessor::ActivationSequenceContextProcessor(
process();
}
-ActivationSequenceContextProcessor::ActivationSequenceContextProcessor(
- const ClangCompletionAssistInterface *interface)
- : ActivationSequenceContextProcessor(interface->textDocument(), interface->position(),
- interface->languageFeatures())
-{
-}
-
CPlusPlus::Kind ActivationSequenceContextProcessor::completionKind() const
{
return m_completionKind;
diff --git a/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.h b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.h
index c735ce419ef..aa457dfeb92 100644
--- a/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.h
+++ b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.h
@@ -25,8 +25,6 @@
#pragma once
-#include <clangcodemodel/clangcompletionassistinterface.h>
-
#include <cplusplus/Token.h>
#include <QTextCursor>
@@ -43,7 +41,6 @@ class ActivationSequenceContextProcessor
public:
ActivationSequenceContextProcessor(QTextDocument *document, int position,
CPlusPlus::LanguageFeatures languageFeatures);
- ActivationSequenceContextProcessor(const ClangCompletionAssistInterface *interface);
CPlusPlus::Kind completionKind() const;
int startOfNamePosition() const; // e.g. points to 'b' in "foo.bar<CURSOR>"
diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.cpp b/src/plugins/clangcodemodel/clangassistproposalitem.cpp
deleted file mode 100644
index 068355ef911..00000000000
--- a/src/plugins/clangcodemodel/clangassistproposalitem.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangassistproposalitem.h"
-
-#include "clangcompletionchunkstotextconverter.h"
-#include "clangfixitoperation.h"
-#include "clangutils.h"
-
-#include <cplusplus/Icons.h>
-#include <cplusplus/MatchingText.h>
-#include <cplusplus/SimpleLexer.h>
-#include <cplusplus/Token.h>
-
-#include <texteditor/completionsettings.h>
-#include <texteditor/texteditor.h>
-#include <texteditor/texteditorsettings.h>
-
-#include <QCoreApplication>
-#include <QTextBlock>
-#include <QTextCursor>
-#include <QTextDocument>
-
-#include <utils/algorithm.h>
-#include <utils/textutils.h>
-#include <utils/qtcassert.h>
-
-using namespace CPlusPlus;
-using namespace ClangBackEnd;
-using namespace TextEditor;
-using namespace Utils;
-
-namespace ClangCodeModel {
-namespace Internal {
-
-bool ClangAssistProposalItem::prematurelyApplies(const QChar &typedCharacter) const
-{
- bool applies = false;
-
- if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT)
- applies = QString::fromLatin1("(,").contains(typedCharacter);
- else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL)
- applies = (typedCharacter == QLatin1Char('/')) && text().endsWith(QLatin1Char('/'));
- else if (firstCodeCompletion().completionKind == CodeCompletion::ObjCMessageCompletionKind)
- applies = QString::fromLatin1(";.,").contains(typedCharacter);
- else
- applies = QString::fromLatin1(";.,:(").contains(typedCharacter);
-
- if (applies)
- m_typedCharacter = typedCharacter;
-
- return applies;
-}
-
-bool ClangAssistProposalItem::implicitlyApplies() const
-{
- return true;
-}
-
-static QString methodDefinitionParameters(const CodeCompletionChunks &chunks)
-{
- QString result;
-
- auto typedTextChunkIt = std::find_if(chunks.cbegin(), chunks.cend(),
- [](const CodeCompletionChunk &chunk) {
- return chunk.kind == CodeCompletionChunk::TypedText;
- });
- if (typedTextChunkIt == chunks.cend())
- return result;
-
- std::for_each(++typedTextChunkIt, chunks.cend(), [&result](const CodeCompletionChunk &chunk) {
- if (chunk.kind == CodeCompletionChunk::Placeholder && chunk.text.contains('=')) {
- Utf8String text = chunk.text.mid(0, chunk.text.indexOf('='));
- if (text.endsWith(' '))
- text.chop(1);
- result += text;
- } else {
- result += chunk.text;
- }
- });
-
- return result;
-}
-
-static bool skipParenForFunctionLikeSnippet(const std::vector<int> &placeholderPositions,
- const QString &text,
- int position)
-{
- return placeholderPositions.size() == 1
- && position > 0
- && text[position - 1] == '('
- && text[position] == ')'
- && position + 1 == text.size();
-}
-
-static bool isFuncDeclAsSingleTypedText(const CodeCompletion &completion)
-{
- // There is no libclang API to tell function call items from declaration items apart.
- // However, the chunks differ for these items (c-index-test -code-completion-at=...):
- // An (override) declaration (available in derived class scope):
- // CXXMethod:{TypedText void hello() override} (40)
- // A function call:
- // CXXMethod:{ResultType void}{TypedText hello}{LeftParen (}{RightParen )} (36)
- return completion.completionKind == CodeCompletion::FunctionDefinitionCompletionKind
- && completion.chunks.size() == 1
- && completion.chunks[0].kind == CodeCompletionChunk::TypedText;
-}
-
-void ClangAssistProposalItem::apply(TextDocumentManipulatorInterface &manipulator,
- int basePosition) const
-{
- const CodeCompletion ccr = firstCodeCompletion();
-
- if (!ccr.requiredFixIts.empty()) {
- // Important: Calculate shift before changing the document.
- basePosition += fixItsShift(manipulator);
-
- ClangFixItOperation fixItOperation(Utf8String(), ccr.requiredFixIts);
- fixItOperation.perform();
- }
-
- QString textToBeInserted = m_text;
- QString extraCharacters;
- int extraLength = 0;
- int cursorOffset = 0;
- bool setAutoCompleteSkipPos = false;
- int currentPosition = manipulator.currentPosition();
-
- if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) {
- extraCharacters += QLatin1Char(')');
- if (m_typedCharacter == QLatin1Char('(')) // Eat the opening parenthesis
- m_typedCharacter = QChar();
- } else if (ccr.completionKind == CodeCompletion::KeywordCompletionKind) {
- CompletionChunksToTextConverter converter;
- converter.setupForKeywords();
- converter.parseChunks(ccr.chunks);
-
- textToBeInserted = converter.text();
-
- if (converter.hasPlaceholderPositions()) {
- const std::vector<int> &placeholderPositions = converter.placeholderPositions();
- const int position = placeholderPositions[0];
- cursorOffset = position - converter.text().size();
- // If the snippet looks like a function call, e.g. "sizeof(<PLACEHOLDER>)",
- // ensure that we can "overtype" ')' after inserting it.
- setAutoCompleteSkipPos = skipParenForFunctionLikeSnippet(placeholderPositions,
- textToBeInserted,
- position);
- }
- } else if (ccr.completionKind == CodeCompletion::NamespaceCompletionKind) {
- CompletionChunksToTextConverter converter;
- converter.parseChunks(ccr.chunks); // Appends "::" after name space name
- textToBeInserted = converter.text();
-
- // Clang does not provide the "::" chunk consistently for namespaces, e.g.
- //
- // namespace a { namespace b { namespace c {} } }
- // <CURSOR> // complete "a" ==> "a::"
- // a::<CURSOR> // complete "b" ==> "b", not "b::"
- //
- // Remove "::" to avoid any confusion for now.
- if (textToBeInserted.endsWith("::"))
- textToBeInserted.chop(2);
- } else if (!ccr.text.isEmpty()) {
- const CompletionSettings &completionSettings =
- TextEditorSettings::completionSettings();
- const bool autoInsertBrackets = completionSettings.m_autoInsertBrackets;
-
- if (autoInsertBrackets &&
- (ccr.completionKind == CodeCompletion::FunctionCompletionKind
- || ccr.completionKind == CodeCompletion::FunctionDefinitionCompletionKind
- || ccr.completionKind == CodeCompletion::DestructorCompletionKind
- || ccr.completionKind == CodeCompletion::ConstructorCompletionKind
- || ccr.completionKind == CodeCompletion::SignalCompletionKind
- || ccr.completionKind == CodeCompletion::SlotCompletionKind)) {
- // When the user typed the opening parenthesis, he'll likely also type the closing one,
- // in which case it would be annoying if we put the cursor after the already automatically
- // inserted closing parenthesis.
- const bool skipClosingParenthesis = m_typedCharacter != QLatin1Char('(');
- QTextCursor cursor = manipulator.textCursorAt(basePosition);
-
- bool abandonParen = false;
- if (matchPreviousWord(manipulator, cursor, "&")) {
- moveToPreviousWord(manipulator, cursor);
- moveToPreviousChar(manipulator, cursor);
- const QChar prevChar = manipulator.characterAt(cursor.position());
- cursor.setPosition(basePosition);
- abandonParen = QString("(;,{}").contains(prevChar);
- }
- if (!abandonParen) {
- const bool isFullDecl = isFuncDeclAsSingleTypedText(ccr);
- if (isFullDecl)
- extraCharacters += QLatin1Char(';');
- abandonParen = isAtUsingDeclaration(manipulator, basePosition) || isFullDecl;
- }
-
- if (!abandonParen && ccr.completionKind == CodeCompletion::FunctionDefinitionCompletionKind) {
- const CodeCompletionChunk resultType = ccr.chunks.first();
- if (resultType.kind == CodeCompletionChunk::ResultType) {
- if (matchPreviousWord(manipulator, cursor, resultType.text.toString())) {
- extraCharacters += methodDefinitionParameters(ccr.chunks);
- // To skip the next block.
- abandonParen = true;
- }
- } else {
- // Do nothing becasue it's not a function definition.
-
- // It's a clang bug that the function might miss a ResultType chunk
- // when the base class method is called from the overriding method
- // of the derived class. For example:
- // void Derived::foo() override { Base::<complete here> }
- }
- }
- if (!abandonParen) {
- if (completionSettings.m_spaceAfterFunctionName)
- extraCharacters += QLatin1Char(' ');
- extraCharacters += QLatin1Char('(');
- if (m_typedCharacter == QLatin1Char('('))
- m_typedCharacter = QChar();
-
- // If the function doesn't return anything, automatically place the semicolon,
- // unless we're doing a scope completion (then it might be function definition).
- const QChar characterAtCursor = manipulator.characterAt(currentPosition);
- bool endWithSemicolon = m_typedCharacter == QLatin1Char(';')/*
- || (function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON)*/; //###
- const QChar semicolon = m_typedCharacter.isNull() ? QLatin1Char(';') : m_typedCharacter;
-
- if (endWithSemicolon && characterAtCursor == semicolon) {
- endWithSemicolon = false;
- m_typedCharacter = QChar();
- }
-
- // If the function takes no arguments, automatically place the closing parenthesis
- if (!hasOverloadsWithParameters() && !ccr.hasParameters && skipClosingParenthesis) {
- extraCharacters += QLatin1Char(')');
- if (endWithSemicolon) {
- extraCharacters += semicolon;
- m_typedCharacter = QChar();
- }
- } else {
- const QChar lookAhead = manipulator.characterAt(manipulator.currentPosition() + 1);
- if (MatchingText::shouldInsertMatchingText(lookAhead)) {
- extraCharacters += QLatin1Char(')');
- --cursorOffset;
- setAutoCompleteSkipPos = true;
- if (endWithSemicolon) {
- extraCharacters += semicolon;
- --cursorOffset;
- m_typedCharacter = QChar();
- }
- }
- }
- }
- }
- }
-
- // Append an unhandled typed character, adjusting cursor offset when it had been adjusted before
- if (!m_typedCharacter.isNull()) {
- extraCharacters += m_typedCharacter;
- if (cursorOffset != 0)
- --cursorOffset;
- }
-
- // Avoid inserting characters that are already there
- QTextCursor cursor = manipulator.textCursorAt(basePosition);
- cursor.movePosition(QTextCursor::EndOfWord);
- const QString textAfterCursor = manipulator.textAt(currentPosition,
- cursor.position() - currentPosition);
-
- if (textToBeInserted != textAfterCursor
- && textToBeInserted.indexOf(textAfterCursor, currentPosition - basePosition) >= 0) {
- currentPosition = cursor.position();
- }
-
- for (int i = 0; i < extraCharacters.length(); ++i) {
- const QChar a = extraCharacters.at(i);
- const QChar b = manipulator.characterAt(currentPosition + i);
- if (a == b)
- ++extraLength;
- else
- break;
- }
-
- textToBeInserted += extraCharacters;
-
- const int length = currentPosition - basePosition + extraLength;
-
- const bool isReplaced = manipulator.replace(basePosition, length, textToBeInserted);
- manipulator.setCursorPosition(basePosition + textToBeInserted.length());
- if (isReplaced) {
- if (cursorOffset)
- manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset);
- if (setAutoCompleteSkipPos)
- manipulator.setAutoCompleteSkipPosition(manipulator.currentPosition());
-
- if (ccr.completionKind == CodeCompletion::KeywordCompletionKind)
- manipulator.autoIndent(basePosition, textToBeInserted.size());
- }
-}
-
-void ClangAssistProposalItem::setText(const QString &text)
-{
- m_text = text;
-}
-
-QString ClangAssistProposalItem::text() const
-{
- return m_text;
-}
-
-const QVector<ClangBackEnd::FixItContainer> &ClangAssistProposalItem::firstCompletionFixIts() const
-{
- return firstCodeCompletion().requiredFixIts;
-}
-
-std::pair<int, int> fixItPositionsRange(const FixItContainer &fixIt, const QTextCursor &cursor)
-{
- const QTextBlock startLine = cursor.document()->findBlockByNumber(fixIt.range.start.line - 1);
- const QTextBlock endLine = cursor.document()->findBlockByNumber(fixIt.range.end.line - 1);
-
- const int fixItStartPos = Text::positionInText(
- cursor.document(),
- fixIt.range.start.line,
- cppEditorColumn(startLine, fixIt.range.start.column));
- const int fixItEndPos = Text::positionInText(
- cursor.document(),
- fixIt.range.end.line,
- cppEditorColumn(endLine, fixIt.range.end.column));
- return std::make_pair(fixItStartPos, fixItEndPos);
-}
-
-static QString textReplacedByFixit(const FixItContainer &fixIt)
-{
- TextEditorWidget *textEditorWidget = TextEditorWidget::currentTextEditorWidget();
- if (!textEditorWidget)
- return QString();
- const std::pair<int, int> fixItPosRange = fixItPositionsRange(fixIt,
- textEditorWidget->textCursor());
- return textEditorWidget->textAt(fixItPosRange.first,
- fixItPosRange.second - fixItPosRange.first);
-}
-
-QString ClangAssistProposalItem::fixItText() const
-{
- const FixItContainer &fixIt = firstCompletionFixIts().first();
- return QCoreApplication::translate("ClangCodeModel::ClangAssistProposalItem",
- "Requires changing \"%1\" to \"%2\"")
- .arg(textReplacedByFixit(fixIt), fixIt.text.toString());
-}
-
-int ClangAssistProposalItem::fixItsShift(const TextDocumentManipulatorInterface &manipulator) const
-{
- const QVector<ClangBackEnd::FixItContainer> &requiredFixIts = firstCompletionFixIts();
- if (requiredFixIts.empty())
- return 0;
-
- int shift = 0;
- const QTextCursor cursor = manipulator.textCursorAt(0);
- for (const FixItContainer &fixIt : requiredFixIts) {
- const std::pair<int, int> fixItPosRange = fixItPositionsRange(fixIt, cursor);
- shift += fixIt.text.toString().length() - (fixItPosRange.second - fixItPosRange.first);
- }
- return shift;
-}
-
-QIcon ClangAssistProposalItem::icon() const
-{
- using namespace CPlusPlus::Icons;
- static const char SNIPPET_ICON_PATH[] = ":/texteditor/images/snippet.png";
- static const QIcon snippetIcon = QIcon(QLatin1String(SNIPPET_ICON_PATH));
-
- const ClangBackEnd::CodeCompletion &completion = firstCodeCompletion();
- switch (completion.completionKind) {
- case CodeCompletion::ClassCompletionKind:
- case CodeCompletion::TemplateClassCompletionKind:
- case CodeCompletion::TypeAliasCompletionKind:
- return CodeModelIcon::iconForType(CodeModelIcon::Class);
- case CodeCompletion::EnumerationCompletionKind:
- return CodeModelIcon::iconForType(CodeModelIcon::Enum);
- case CodeCompletion::EnumeratorCompletionKind:
- return CodeModelIcon::iconForType(CodeModelIcon::Enumerator);
- case CodeCompletion::ConstructorCompletionKind:
- case CodeCompletion::DestructorCompletionKind:
- case CodeCompletion::FunctionCompletionKind:
- case CodeCompletion::FunctionDefinitionCompletionKind:
- case CodeCompletion::TemplateFunctionCompletionKind:
- case CodeCompletion::ObjCMessageCompletionKind:
- switch (completion.availability) {
- case CodeCompletion::Available:
- case CodeCompletion::Deprecated:
- return CodeModelIcon::iconForType(CodeModelIcon::FuncPublic);
- default:
- return CodeModelIcon::iconForType(CodeModelIcon::FuncPrivate);
- }
- case CodeCompletion::SignalCompletionKind:
- return CodeModelIcon::iconForType(CodeModelIcon::Signal);
- case CodeCompletion::SlotCompletionKind:
- switch (completion.availability) {
- case CodeCompletion::Available:
- case CodeCompletion::Deprecated:
- return CodeModelIcon::iconForType(CodeModelIcon::SlotPublic);
- case CodeCompletion::NotAccessible:
- case CodeCompletion::NotAvailable:
- return CodeModelIcon::iconForType(CodeModelIcon::SlotPrivate);
- }
- break;
- case CodeCompletion::NamespaceCompletionKind:
- return CodeModelIcon::iconForType(CodeModelIcon::Namespace);
- case CodeCompletion::PreProcessorCompletionKind:
- return CodeModelIcon::iconForType(CodeModelIcon::Macro);
- case CodeCompletion::VariableCompletionKind:
- switch (completion.availability) {
- case CodeCompletion::Available:
- case CodeCompletion::Deprecated:
- return CodeModelIcon::iconForType(CodeModelIcon::VarPublic);
- default:
- return CodeModelIcon::iconForType(CodeModelIcon::VarPrivate);
- }
- case CodeCompletion::KeywordCompletionKind:
- return CodeModelIcon::iconForType(CodeModelIcon::Keyword);
- case CodeCompletion::ClangSnippetKind:
- return snippetIcon;
- case CodeCompletion::Other:
- return CodeModelIcon::iconForType(CodeModelIcon::Unknown);
- default:
- break;
- }
-
- return QIcon();
-}
-
-QString ClangAssistProposalItem::detail() const
-{
- QString detail;
- for (const ClangBackEnd::CodeCompletion &codeCompletion : m_codeCompletions) {
- if (!detail.isEmpty())
- detail += "<br>";
- detail += CompletionChunksToTextConverter::convertToToolTipWithHtml(
- codeCompletion.chunks, codeCompletion.completionKind);
-
- if (!codeCompletion.briefComment.isEmpty())
- detail += "<br>" + codeCompletion.briefComment.toString();
- }
-
- if (requiresFixIts())
- detail += "<br><br><b>" + fixItText() + "</b>";
-
- return detail;
-}
-
-bool ClangAssistProposalItem::isKeyword() const
-{
- // KeywordCompletionKind includes real keywords but also "code patterns"/snippets.
- return m_codeCompletions[0].completionKind == CodeCompletion::KeywordCompletionKind;
-}
-
-Qt::TextFormat ClangAssistProposalItem::detailFormat() const
-{
- return Qt::RichText;
-}
-
-bool ClangAssistProposalItem::isSnippet() const
-{
- return false;
-}
-
-bool ClangAssistProposalItem::isValid() const
-{
- return true;
-}
-
-quint64 ClangAssistProposalItem::hash() const
-{
- return 0;
-}
-
-bool ClangAssistProposalItem::requiresFixIts() const
-{
- return !firstCompletionFixIts().empty();
-}
-
-bool ClangAssistProposalItem::hasOverloadsWithParameters() const
-{
- return m_hasOverloadsWithParameters;
-}
-
-void ClangAssistProposalItem::setHasOverloadsWithParameters(bool hasOverloadsWithParameters)
-{
- m_hasOverloadsWithParameters = hasOverloadsWithParameters;
-}
-
-void ClangAssistProposalItem::keepCompletionOperator(unsigned compOp)
-{
- m_completionOperator = compOp;
-}
-
-void ClangAssistProposalItem::appendCodeCompletion(const CodeCompletion &codeCompletion)
-{
- m_codeCompletions.push_back(codeCompletion);
-}
-
-const ClangBackEnd::CodeCompletion &ClangAssistProposalItem::firstCodeCompletion() const
-{
- return m_codeCompletions.at(0);
-}
-
-void ClangAssistProposalItem::removeFirstCodeCompletion()
-{
- QTC_ASSERT(!m_codeCompletions.empty(), return;);
- m_codeCompletions.erase(m_codeCompletions.begin());
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.h b/src/plugins/clangcodemodel/clangassistproposalitem.h
deleted file mode 100644
index 64eb8789b34..00000000000
--- a/src/plugins/clangcodemodel/clangassistproposalitem.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <codecompletion.h>
-
-#include <texteditor/codeassist/assistproposaliteminterface.h>
-
-#include <QString>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangAssistProposalItem final : public TextEditor::AssistProposalItemInterface
-{
- friend bool operator<(const ClangAssistProposalItem &first, const ClangAssistProposalItem &second);
-public:
- ~ClangAssistProposalItem() noexcept override = default;
- bool prematurelyApplies(const QChar &typedCharacter) const final;
- bool implicitlyApplies() const final;
- void apply(TextEditor::TextDocumentManipulatorInterface &manipulator, int basePosition) const final;
-
- void setText(const QString &text);
- QString text() const final;
- QIcon icon() const final;
- QString detail() const final;
- bool isKeyword() const final;
- Qt::TextFormat detailFormat() const final;
- bool isSnippet() const final;
- bool isValid() const final;
- quint64 hash() const final;
- bool requiresFixIts() const final;
-
- void keepCompletionOperator(unsigned compOp);
-
- bool hasOverloadsWithParameters() const;
- void setHasOverloadsWithParameters(bool hasOverloadsWithParameters);
-
- void appendCodeCompletion(const ClangBackEnd::CodeCompletion &firstCodeCompletion);
- const ClangBackEnd::CodeCompletion &firstCodeCompletion() const;
- void removeFirstCodeCompletion();
-
-private:
- const QVector<ClangBackEnd::FixItContainer> &firstCompletionFixIts() const;
- QString fixItText() const;
- int fixItsShift(const TextEditor::TextDocumentManipulatorInterface &manipulator) const;
-
- std::vector<ClangBackEnd::CodeCompletion> m_codeCompletions;
- QList<ClangBackEnd::CodeCompletion> m_overloads;
- bool m_hasOverloadsWithParameters = false;
- QString m_text;
- unsigned m_completionOperator;
- mutable QChar m_typedCharacter;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp
deleted file mode 100644
index 9f682ff6eb3..00000000000
--- a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangassistproposalitem.h"
-
-#include "clangassistproposalmodel.h"
-
-#include <texteditor/codeassist/assistproposaliteminterface.h>
-
-#include <algorithm>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-constexpr int SORT_LIMIT = 30000;
-
-bool ClangAssistProposalModel::containsDuplicates() const
-{
- return false;
-}
-
-bool ClangAssistProposalModel::isSortable(const QString &/*prefix*/) const
-{
- return m_currentItems.size() <= SORT_LIMIT;
-}
-
-void ClangAssistProposalModel::sort(const QString &/*prefix*/)
-{
- using TextEditor::AssistProposalItemInterface;
-
- auto currentItemsCompare = [](AssistProposalItemInterface *first,
- AssistProposalItemInterface *second) {
- if (first->proposalMatch() != second->proposalMatch()) {
- return static_cast<int>(first->proposalMatch())
- < static_cast<int>(second->proposalMatch());
- }
- return false;
- };
-
- // Keep the order for the items with the same priority and name.
- std::stable_sort(m_currentItems.begin(), m_currentItems.end(), currentItemsCompare);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
-
diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.h b/src/plugins/clangcodemodel/clangassistproposalmodel.h
deleted file mode 100644
index cb2cb7edd36..00000000000
--- a/src/plugins/clangcodemodel/clangassistproposalmodel.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <cplusplus/Token.h>
-
-#include <texteditor/codeassist/genericproposalmodel.h>
-
-#include <clangsupport/clangsupport_global.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangAssistProposalModel : public TextEditor::GenericProposalModel
-{
-public:
- ClangAssistProposalModel() = default;
-
- bool containsDuplicates() const override;
-
- bool isSortable(const QString &prefix) const override;
- void sort(const QString &prefix) override;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
deleted file mode 100644
index 679b47677c4..00000000000
--- a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
+++ /dev/null
@@ -1,517 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangbackendcommunicator.h"
-
-#include "clangbackendlogging.h"
-#include "clangcompletionassistprocessor.h"
-#include "clangmodelmanagersupport.h"
-#include "clangutils.h"
-
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/messagemanager.h>
-
-#include <cppeditor/abstracteditorsupport.h>
-#include <cppeditor/baseeditordocumentprocessor.h>
-#include <cppeditor/cppmodelmanager.h>
-#include <cppeditor/editordocumenthandle.h>
-#include <cppeditor/projectinfo.h>
-
-#include <texteditor/codeassist/functionhintproposal.h>
-#include <texteditor/codeassist/iassistprocessor.h>
-#include <texteditor/texteditor.h>
-
-#include <clangsupport/filecontainer.h>
-#include <clangsupport/clangcodemodelservermessages.h>
-
-#include <utils/globalfilechangeblocker.h>
-#include <utils/qtcassert.h>
-
-#include <QDateTime>
-#include <QDir>
-#include <QTextBlock>
-
-using namespace CPlusPlus;
-using namespace ClangBackEnd;
-using namespace TextEditor;
-using namespace Utils;
-
-enum { backEndStartTimeOutInMs = 10000 };
-
-static QString backendProcessPath()
-{
- return Core::ICore::libexecPath("clangbackend" QTC_HOST_EXE_SUFFIX).toString();
-}
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class DummyBackendSender : public ClangBackEnd::ClangCodeModelServerInterface
-{
-public:
- void end() override {}
-
- void documentsOpened(const DocumentsOpenedMessage &) override {}
- void documentsChanged(const DocumentsChangedMessage &) override {}
- void documentsClosed(const DocumentsClosedMessage &) override {}
- void documentVisibilityChanged(const DocumentVisibilityChangedMessage &) override {}
-
- void unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &) override {}
- void unsavedFilesRemoved(const UnsavedFilesRemovedMessage &) override {}
-
- void requestCompletions(const RequestCompletionsMessage &) override {}
- void requestAnnotations(const RequestAnnotationsMessage &) override {}
- void requestReferences(const RequestReferencesMessage &) override {}
- void requestFollowSymbol(const RequestFollowSymbolMessage &) override {}
- void requestToolTip(const RequestToolTipMessage &) override {}
-};
-
-BackendCommunicator::BackendCommunicator()
- : m_connection(&m_receiver)
- , m_sender(new DummyBackendSender())
-{
- m_backendStartTimeOut.setSingleShot(true);
- connect(&m_backendStartTimeOut, &QTimer::timeout,
- this, &BackendCommunicator::logStartTimeOut);
-
- m_receiver.setAliveHandler([this]() { m_connection.resetProcessAliveTimer(); });
-
- connect(Core::EditorManager::instance(), &Core::EditorManager::editorAboutToClose,
- this, &BackendCommunicator::onEditorAboutToClose);
- connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose,
- this, &BackendCommunicator::setupDummySender);
- auto globalFCB = GlobalFileChangeBlocker::instance();
- m_postponeBackendJobs = globalFCB->isBlocked();
- connect(globalFCB, &GlobalFileChangeBlocker::stateChanged,
- this, &BackendCommunicator::setBackendJobsPostponed);
-
- initializeBackend();
-}
-
-BackendCommunicator::~BackendCommunicator()
-{
- disconnect(&m_connection, nullptr, this, nullptr);
-}
-
-void BackendCommunicator::initializeBackend()
-{
- const QString clangBackEndProcessPath = backendProcessPath();
- if (!QFileInfo::exists(clangBackEndProcessPath)) {
- logExecutableDoesNotExist();
- return;
- }
- qCDebug(ipcLog) << "Starting" << clangBackEndProcessPath;
-
- m_connection.setProcessAliveTimerInterval(30 * 1000);
- m_connection.setProcessPath(clangBackEndProcessPath);
-
- connect(&m_connection, &ConnectionClient::connectedToLocalSocket,
- this, &BackendCommunicator::onConnectedToBackend);
- connect(&m_connection, &ConnectionClient::disconnectedFromLocalSocket,
- this, &BackendCommunicator::setupDummySender);
-
- m_connection.startProcessAndConnectToServerAsynchronously();
- m_backendStartTimeOut.start(backEndStartTimeOutInMs);
-}
-
-namespace {
-void removeDuplicates(Utf8StringVector &visibleEditorDocumentsFilePaths)
-{
- std::sort(visibleEditorDocumentsFilePaths.begin(),
- visibleEditorDocumentsFilePaths.end());
- const auto end = std::unique(visibleEditorDocumentsFilePaths.begin(),
- visibleEditorDocumentsFilePaths.end());
- visibleEditorDocumentsFilePaths.erase(end,
- visibleEditorDocumentsFilePaths.end());
-}
-
-void removeNonCppEditors(QList<Core::IEditor*> &visibleEditors)
-{
- const auto isNotCppEditor = [] (Core::IEditor *editor) {
- return !CppEditor::CppModelManager::isCppEditor(editor);
- };
-
- const auto end = std::remove_if(visibleEditors.begin(),
- visibleEditors.end(),
- isNotCppEditor);
-
- visibleEditors.erase(end, visibleEditors.end());
-}
-
-Utf8StringVector visibleCppEditorDocumentsFilePaths()
-{
- auto visibleEditors = Core::EditorManager::visibleEditors();
-
- removeNonCppEditors(visibleEditors);
-
- Utf8StringVector visibleCppEditorDocumentsFilePaths;
- visibleCppEditorDocumentsFilePaths.reserve(visibleEditors.size());
-
- const auto editorFilePaths = [] (Core::IEditor *editor) {
- return Utf8String(editor->document()->filePath().toString());
- };
-
- std::transform(visibleEditors.begin(),
- visibleEditors.end(),
- std::back_inserter(visibleCppEditorDocumentsFilePaths),
- editorFilePaths);
-
- removeDuplicates(visibleCppEditorDocumentsFilePaths);
-
- return visibleCppEditorDocumentsFilePaths;
-}
-
-}
-
-void BackendCommunicator::documentVisibilityChanged()
-{
- documentVisibilityChanged(currentCppEditorDocumentFilePath(),
- visibleCppEditorDocumentsFilePaths());
-}
-
-bool BackendCommunicator::isNotWaitingForCompletion() const
-{
- return !m_receiver.isExpectingCompletionsMessage();
-}
-
-void BackendCommunicator::setBackendJobsPostponed(bool postponed)
-{
- if (postponed) {
- documentVisibilityChanged(Utf8String(), {});
- m_postponeBackendJobs = postponed;
- } else {
- m_postponeBackendJobs = postponed;
- documentVisibilityChanged();
- }
-}
-
-void BackendCommunicator::documentVisibilityChanged(const Utf8String &currentEditorFilePath,
- const Utf8StringVector &visibleEditorsFilePaths)
-{
- if (m_postponeBackendJobs)
- return;
-
- const DocumentVisibilityChangedMessage message(currentEditorFilePath, visibleEditorsFilePaths);
- m_sender->documentVisibilityChanged(message);
-}
-
-void BackendCommunicator::restoreCppEditorDocuments()
-{
- resetCppEditorDocumentProcessors();
- CppEditor::CppModelManager::instance()->updateCppEditorDocuments();
-}
-
-void BackendCommunicator::resetCppEditorDocumentProcessors()
-{
- using namespace CppEditor;
-
- const auto cppEditorDocuments = CppModelManager::instance()->cppEditorDocuments();
- foreach (CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments)
- cppEditorDocument->resetProcessor();
-}
-
-void BackendCommunicator::unsavedFilesUpdatedForUiHeaders()
-{
- using namespace CppEditor;
-
- const auto editorSupports = CppModelManager::instance()->abstractEditorSupports();
- foreach (const AbstractEditorSupport *es, editorSupports) {
- const QString mappedPath
- = ClangModelManagerSupport::instance()->dummyUiHeaderOnDiskPath(es->fileName());
- unsavedFilesUpdated(mappedPath, es->contents(), es->revision());
- }
-}
-
-void BackendCommunicator::documentsChangedFromCppEditorDocument(const QString &filePath)
-{
- const CppEditor::CppEditorDocumentHandle *document = cppDocument(filePath);
- QTC_ASSERT(document, return);
- documentsChanged(filePath, document->contents(), document->revision());
-}
-
-void BackendCommunicator::unsavedFilesUpdatedFromCppEditorDocument(const QString &filePath)
-{
- const CppEditor::CppEditorDocumentHandle *document = cppDocument(filePath);
- QTC_ASSERT(document, return);
- unsavedFilesUpdated(filePath, document->contents(), document->revision());
-}
-
-void BackendCommunicator::documentsChanged(const QString &filePath,
- const QByteArray &contents,
- uint documentRevision)
-{
- const bool hasUnsavedContent = true;
-
- documentsChanged({{filePath,
- Utf8String::fromByteArray(contents),
- hasUnsavedContent,
- documentRevision}});
-}
-
-void BackendCommunicator::unsavedFilesUpdated(const QString &filePath,
- const QByteArray &contents,
- uint documentRevision)
-{
- const bool hasUnsavedContent = true;
-
- // TODO: Send new only if changed
- unsavedFilesUpdated({{filePath,
- Utf8String::fromByteArray(contents),
- hasUnsavedContent,
- documentRevision}});
-}
-
-static bool documentHasChanged(const QString &filePath, uint revision)
-{
- if (CppEditor::CppEditorDocumentHandle *document = cppDocument(filePath))
- return document->sendTracker().shouldSendRevision(revision);
-
- return true;
-}
-
-void BackendCommunicator::documentsChangedWithRevisionCheck(const FileContainer &fileContainer)
-{
- if (documentHasChanged(fileContainer.filePath, fileContainer.documentRevision)) {
- documentsChanged({fileContainer});
- setLastSentDocumentRevision(fileContainer.filePath,
- fileContainer.documentRevision);
- }
-}
-
-void BackendCommunicator::requestAnnotations(const FileContainer &fileContainer)
-{
- const RequestAnnotationsMessage message(fileContainer);
- m_sender->requestAnnotations(message);
-}
-
-QFuture<CppEditor::CursorInfo> BackendCommunicator::requestReferences(
- const FileContainer &fileContainer,
- quint32 line,
- quint32 column,
- const CppEditor::SemanticInfo::LocalUseMap &localUses)
-{
- const RequestReferencesMessage message(fileContainer, line, column);
- m_sender->requestReferences(message);
-
- return m_receiver.addExpectedReferencesMessage(message.ticketNumber, localUses);
-}
-
-QFuture<CppEditor::CursorInfo> BackendCommunicator::requestLocalReferences(
- const FileContainer &fileContainer,
- quint32 line,
- quint32 column)
-{
- const RequestReferencesMessage message(fileContainer, line, column, true);
- m_sender->requestReferences(message);
-
- return m_receiver.addExpectedReferencesMessage(message.ticketNumber);
-}
-
-QFuture<CppEditor::ToolTipInfo> BackendCommunicator::requestToolTip(
- const FileContainer &fileContainer, quint32 line, quint32 column)
-{
- const RequestToolTipMessage message(fileContainer, line, column);
- m_sender->requestToolTip(message);
-
- return m_receiver.addExpectedToolTipMessage(message.ticketNumber);
-}
-
-QFuture<CppEditor::SymbolInfo> BackendCommunicator::requestFollowSymbol(
- const FileContainer &curFileContainer,
- quint32 line,
- quint32 column)
-{
- const RequestFollowSymbolMessage message(curFileContainer, line, column);
- m_sender->requestFollowSymbol(message);
-
- return m_receiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber);
-}
-
-void BackendCommunicator::documentsChangedWithRevisionCheck(Core::IDocument *document)
-{
- const auto textDocument = qobject_cast<TextDocument*>(document);
- const auto filePath = textDocument->filePath().toString();
-
- documentsChangedWithRevisionCheck(
- FileContainer(filePath, {}, {}, textDocument->document()->revision()));
-}
-
-void BackendCommunicator::updateChangeContentStartPosition(const QString &filePath, int position)
-{
- if (CppEditor::CppEditorDocumentHandle *document = cppDocument(filePath))
- document->sendTracker().applyContentChange(position);
-}
-
-void BackendCommunicator::documentsChangedIfNotCurrentDocument(Core::IDocument *document)
-{
- QTC_ASSERT(document, return);
- if (Core::EditorManager::currentDocument() != document)
- documentsChanged(document);
-}
-
-void BackendCommunicator::documentsChanged(Core::IDocument *document)
-{
- documentsChangedFromCppEditorDocument(document->filePath().toString());
-}
-
-void BackendCommunicator::unsavedFilesUpdated(Core::IDocument *document)
-{
- QTC_ASSERT(document, return);
-
- unsavedFilesUpdatedFromCppEditorDocument(document->filePath().toString());
-}
-
-void BackendCommunicator::onConnectedToBackend()
-{
- m_backendStartTimeOut.stop();
-
- ++m_connectedCount;
- if (m_connectedCount > 1)
- logRestartedDueToUnexpectedFinish();
-
- m_receiver.reset();
- m_sender.reset(new BackendSender(&m_connection));
-
- initializeBackendWithCurrentData();
-}
-
-void BackendCommunicator::onEditorAboutToClose(Core::IEditor *editor)
-{
- if (auto *textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor))
- m_receiver.deleteProcessorsOfEditorWidget(textEditor->editorWidget());
-}
-
-void BackendCommunicator::setupDummySender()
-{
- m_sender.reset(new DummyBackendSender);
-}
-
-void BackendCommunicator::logExecutableDoesNotExist()
-{
- const QString msg
- = tr("Clang Code Model: Error: "
- "The clangbackend executable \"%1\" does not exist.")
- .arg(QDir::toNativeSeparators(backendProcessPath()));
-
- logError(msg);
-}
-
-void BackendCommunicator::logStartTimeOut()
-{
- const QString msg
- = tr("Clang Code Model: Error: "
- "The clangbackend executable \"%1\" could not be started (timeout after %2ms).")
- .arg(QDir::toNativeSeparators(backendProcessPath()))
- .arg(backEndStartTimeOutInMs);
-
- logError(msg);
-}
-
-void BackendCommunicator::logRestartedDueToUnexpectedFinish()
-{
- const QString msg
- = tr("Clang Code Model: Error: "
- "The clangbackend process has finished unexpectedly and was restarted.");
-
- logError(msg);
-}
-
-void BackendCommunicator::logError(const QString &text)
-{
- const QString textWithTimestamp = QDateTime::currentDateTime().toString(Qt::ISODate)
- + ' ' + text;
- Core::MessageManager::writeFlashing(textWithTimestamp);
- qWarning("%s", qPrintable(textWithTimestamp));
-}
-
-void BackendCommunicator::initializeBackendWithCurrentData()
-{
- unsavedFilesUpdatedForUiHeaders();
- restoreCppEditorDocuments();
- documentVisibilityChanged();
-}
-
-void BackendCommunicator::documentsOpened(const FileContainers &fileContainers)
-{
- Utf8String currentDocument;
- Utf8StringVector visibleDocuments;
- if (!m_postponeBackendJobs) {
- currentDocument = currentCppEditorDocumentFilePath();
- visibleDocuments = visibleCppEditorDocumentsFilePaths();
- }
-
- const DocumentsOpenedMessage message(fileContainers, currentDocument, visibleDocuments);
- m_sender->documentsOpened(message);
-}
-
-void BackendCommunicator::documentsChanged(const FileContainers &fileContainers)
-{
- const DocumentsChangedMessage message(fileContainers);
- m_sender->documentsChanged(message);
-}
-
-void BackendCommunicator::documentsClosed(const FileContainers &fileContainers)
-{
- const DocumentsClosedMessage message(fileContainers);
- m_sender->documentsClosed(message);
- documentVisibilityChanged(); // QTCREATORBUG-25193
-}
-
-void BackendCommunicator::unsavedFilesUpdated(const FileContainers &fileContainers)
-{
- const UnsavedFilesUpdatedMessage message(fileContainers);
- m_sender->unsavedFilesUpdated(message);
-}
-
-void BackendCommunicator::unsavedFilesRemoved(const FileContainers &fileContainers)
-{
- const UnsavedFilesRemovedMessage message(fileContainers);
- m_sender->unsavedFilesRemoved(message);
-}
-
-void BackendCommunicator::requestCompletions(ClangCompletionAssistProcessor *assistProcessor,
- const QString &filePath,
- quint32 line,
- quint32 column,
- qint32 funcNameStartLine,
- qint32 funcNameStartColumn)
-{
- const RequestCompletionsMessage message(filePath,
- line,
- column,
- funcNameStartLine,
- funcNameStartColumn);
- m_sender->requestCompletions(message);
- m_receiver.addExpectedCompletionsMessage(message.ticketNumber, assistProcessor);
-}
-
-void BackendCommunicator::cancelCompletions(TextEditor::IAssistProcessor *processor)
-{
- m_receiver.cancelProcessor(processor);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.h b/src/plugins/clangcodemodel/clangbackendcommunicator.h
deleted file mode 100644
index 7c12d43a884..00000000000
--- a/src/plugins/clangcodemodel/clangbackendcommunicator.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangbackendreceiver.h"
-#include "clangbackendsender.h"
-
-#include <cppeditor/projectpart.h>
-
-#include <clangsupport/clangcodemodelconnectionclient.h>
-#include <clangsupport/filecontainer.h>
-
-#include <QFuture>
-#include <QObject>
-#include <QVector>
-#include <QTimer>
-
-namespace Core {
-class IEditor;
-class IDocument;
-}
-
-namespace TextEditor { class IAssistProcessor; }
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangCompletionAssistProcessor;
-
-class BackendCommunicator : public QObject
-{
- Q_OBJECT
-
-public:
- using FileContainer = ClangBackEnd::FileContainer;
- using FileContainers = QVector<ClangBackEnd::FileContainer>;
- using LocalUseMap = CppEditor::SemanticInfo::LocalUseMap;
-
-public:
- BackendCommunicator();
- ~BackendCommunicator() override;
-
- void documentsOpened(const FileContainers &fileContainers);
- void documentsChanged(Core::IDocument *document);
- void documentsChanged(const QString &filePath,
- const QByteArray &contents,
- uint documentRevision);
- void documentsChanged(const FileContainers &fileContainers);
- void documentsChangedFromCppEditorDocument(const QString &filePath);
- void documentsChangedIfNotCurrentDocument(Core::IDocument *document);
- void documentsChangedWithRevisionCheck(const ClangBackEnd::FileContainer &fileContainer);
- void documentsChangedWithRevisionCheck(Core::IDocument *document);
- void documentsClosed(const FileContainers &fileContainers);
- void documentVisibilityChanged();
-
- void unsavedFilesUpdated(Core::IDocument *document);
- void unsavedFilesUpdated(const QString &filePath,
- const QByteArray &contents,
- uint documentRevision);
- void unsavedFilesUpdated(const FileContainers &fileContainers);
- void unsavedFilesUpdatedFromCppEditorDocument(const QString &filePath);
- void unsavedFilesRemoved(const FileContainers &fileContainers);
-
- void requestCompletions(ClangCompletionAssistProcessor *assistProcessor,
- const QString &filePath,
- quint32 line,
- quint32 column,
- qint32 funcNameStartLine = -1,
- qint32 funcNameStartColumn = -1);
- void cancelCompletions(TextEditor::IAssistProcessor *processor);
- void requestAnnotations(const ClangBackEnd::FileContainer &fileContainer);
- QFuture<CppEditor::CursorInfo> requestReferences(
- const FileContainer &fileContainer,
- quint32 line,
- quint32 column,
- const LocalUseMap &localUses);
- QFuture<CppEditor::CursorInfo> requestLocalReferences(
- const FileContainer &fileContainer,
- quint32 line,
- quint32 column);
- QFuture<CppEditor::ToolTipInfo> requestToolTip(const FileContainer &fileContainer,
- quint32 line,
- quint32 column);
- QFuture<CppEditor::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
- quint32 line,
- quint32 column);
-
- void updateChangeContentStartPosition(const QString &filePath, int position);
- bool isNotWaitingForCompletion() const;
-
- void setBackendJobsPostponed(bool postponed);
-
-private:
- void initializeBackend();
- void initializeBackendWithCurrentData();
- void restoreCppEditorDocuments();
- void resetCppEditorDocumentProcessors();
- void unsavedFilesUpdatedForUiHeaders();
-
- void setupDummySender();
-
- void onConnectedToBackend();
- void onEditorAboutToClose(Core::IEditor *editor);
-
- void logExecutableDoesNotExist();
- void logRestartedDueToUnexpectedFinish();
- void logStartTimeOut();
- void logError(const QString &text);
-
- void documentVisibilityChanged(const Utf8String &currentEditorFilePath,
- const Utf8StringVector &visibleEditorsFilePaths);
-
-private:
- BackendReceiver m_receiver;
- ClangBackEnd::ClangCodeModelConnectionClient m_connection;
- QTimer m_backendStartTimeOut;
- QScopedPointer<ClangBackEnd::ClangCodeModelServerInterface> m_sender;
- int m_connectedCount = 0;
- bool m_postponeBackendJobs = false;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendlogging.cpp b/src/plugins/clangcodemodel/clangbackendlogging.cpp
deleted file mode 100644
index e7074fe0415..00000000000
--- a/src/plugins/clangcodemodel/clangbackendlogging.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangbackendlogging.h"
-
-namespace ClangCodeModel {
-namespace Internal {
-
-Q_LOGGING_CATEGORY(ipcLog, "qtc.clangcodemodel.ipc", QtWarningMsg)
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendlogging.h b/src/plugins/clangcodemodel/clangbackendlogging.h
deleted file mode 100644
index 6e2e3ec6893..00000000000
--- a/src/plugins/clangcodemodel/clangbackendlogging.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QLoggingCategory>
-
-namespace ClangCodeModel { namespace Internal {
-
-Q_DECLARE_LOGGING_CATEGORY(ipcLog)
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
deleted file mode 100644
index 1346fbe8d0e..00000000000
--- a/src/plugins/clangcodemodel/clangbackendreceiver.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangbackendreceiver.h"
-
-#include "clangbackendlogging.h"
-
-#include "clangcompletionassistprocessor.h"
-#include "clangeditordocumentprocessor.h"
-
-#include <clangsupport/clangcodemodelclientmessages.h>
-
-#include <QLoggingCategory>
-#include <QTextBlock>
-
-#include <utils/qtcassert.h>
-
-#define qCDebugIpc() qCDebug(ipcLog) << "<===="
-
-namespace ClangCodeModel {
-namespace Internal {
-
-static bool printAliveMessageHelper()
-{
- const bool print = qEnvironmentVariableIntValue("QTC_CLANG_FORCE_VERBOSE_ALIVE");
- if (!print) {
- qCDebug(ipcLog) << "Hint: AliveMessage will not be printed. "
- "Force it by setting QTC_CLANG_FORCE_VERBOSE_ALIVE=1.";
- }
-
- return print;
-}
-
-static bool printAliveMessage()
-{
- static bool print = ipcLog().isDebugEnabled() ? printAliveMessageHelper() : false;
- return print;
-}
-
-BackendReceiver::BackendReceiver() = default;
-
-BackendReceiver::~BackendReceiver()
-{
- reset();
-}
-
-void BackendReceiver::setAliveHandler(const BackendReceiver::AliveHandler &handler)
-{
- m_aliveHandler = handler;
-}
-
-void BackendReceiver::addExpectedCompletionsMessage(
- quint64 ticket,
- ClangCompletionAssistProcessor *processor)
-{
- QTC_ASSERT(processor, return);
- QTC_CHECK(!m_assistProcessorsTable.contains(ticket));
- m_assistProcessorsTable.insert(ticket, processor);
-}
-
-void BackendReceiver::cancelProcessor(TextEditor::IAssistProcessor *processor)
-{
- for (auto it = m_assistProcessorsTable.cbegin(), end = m_assistProcessorsTable.cend();
- it != end; ++it)
- {
- if (it.value() == processor) {
- m_assistProcessorsTable.erase(it);
- return;
- }
- }
-}
-
-void BackendReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget)
-{
- QList<quint64> toRemove;
- for (auto it = m_assistProcessorsTable.cbegin(), end = m_assistProcessorsTable.cend();
- it != end; ++it)
- {
- ClangCompletionAssistProcessor *assistProcessor = it.value();
- if (assistProcessor->textEditorWidget() == textEditorWidget) {
- delete assistProcessor;
- toRemove.append(it.key());
- }
- }
- for (quint64 item : toRemove)
- m_assistProcessorsTable.remove(item);
-}
-
-QFuture<CppEditor::CursorInfo> BackendReceiver::addExpectedReferencesMessage(
- quint64 ticket,
- const CppEditor::SemanticInfo::LocalUseMap &localUses)
-{
- QTC_CHECK(!m_referencesTable.contains(ticket));
-
- QFutureInterface<CppEditor::CursorInfo> futureInterface;
- futureInterface.reportStarted();
-
- const ReferencesEntry entry{futureInterface, localUses};
- m_referencesTable.insert(ticket, entry);
-
- return futureInterface.future();
-}
-
-QFuture<CppEditor::SymbolInfo> BackendReceiver::addExpectedRequestFollowSymbolMessage(quint64 ticket)
-{
- QTC_CHECK(!m_followTable.contains(ticket));
-
- QFutureInterface<CppEditor::SymbolInfo> futureInterface;
- futureInterface.reportStarted();
-
- m_followTable.insert(ticket, futureInterface);
-
- return futureInterface.future();
-}
-
-QFuture<CppEditor::ToolTipInfo> BackendReceiver::addExpectedToolTipMessage(quint64 ticket)
-{
- QTC_CHECK(!m_toolTipsTable.contains(ticket));
-
- QFutureInterface<CppEditor::ToolTipInfo> futureInterface;
- futureInterface.reportStarted();
-
- m_toolTipsTable.insert(ticket, futureInterface);
-
- return futureInterface.future();
-}
-
-bool BackendReceiver::isExpectingCompletionsMessage() const
-{
- return !m_assistProcessorsTable.isEmpty();
-}
-
-void BackendReceiver::reset()
-{
- // Clean up waiting assist processors
- for (ClangCompletionAssistProcessor *processor : m_assistProcessorsTable)
- processor->setAsyncProposalAvailable(nullptr);
- m_assistProcessorsTable.clear();
-
- // Clean up futures for references; TODO: Remove duplication
- for (ReferencesEntry &entry : m_referencesTable) {
- entry.futureInterface.cancel();
- entry.futureInterface.reportFinished();
- }
- m_referencesTable.clear();
- for (QFutureInterface<CppEditor::SymbolInfo> &futureInterface : m_followTable) {
- futureInterface.cancel();
- futureInterface.reportFinished();
- }
- m_followTable.clear();
- for (QFutureInterface<CppEditor::ToolTipInfo> &futureInterface : m_toolTipsTable) {
- futureInterface.cancel();
- futureInterface.reportFinished();
- }
- m_toolTipsTable.clear();
-}
-
-void BackendReceiver::alive()
-{
- if (printAliveMessage())
- qCDebugIpc() << "AliveMessage";
- QTC_ASSERT(m_aliveHandler, return);
- m_aliveHandler();
-}
-
-void BackendReceiver::echo(const ClangBackEnd::EchoMessage &message)
-{
- qCDebugIpc() << message;
-}
-
-void BackendReceiver::completions(const ClangBackEnd::CompletionsMessage &message)
-{
- qCDebugIpc() << "CompletionsMessage with" << message.codeCompletions.size()
- << "items";
-
- const quint64 ticket = message.ticketNumber;
- if (ClangCompletionAssistProcessor *processor = m_assistProcessorsTable.take(ticket))
- processor->handleAvailableCompletions(message.codeCompletions);
-}
-
-void BackendReceiver::annotations(const ClangBackEnd::AnnotationsMessage &message)
-{
- qCDebugIpc() << "AnnotationsMessage"
- << "for" << QFileInfo(message.fileContainer.filePath).fileName() << "with"
- << message.diagnostics.size() << "diagnostics" << message.tokenInfos.size()
- << "token infos" << message.skippedPreprocessorRanges.size()
- << "skipped preprocessor ranges";
-
- auto processor = ClangEditorDocumentProcessor::get(message.fileContainer.filePath);
- if (!processor)
- return;
-
- const quint32 documentRevision = message.fileContainer.documentRevision;
- if (message.onlyTokenInfos) {
- processor->updateTokenInfos(message.tokenInfos, documentRevision);
- return;
- }
- processor->updateCodeWarnings(message.diagnostics,
- message.firstHeaderErrorDiagnostic,
- documentRevision);
- processor->updateHighlighting(message.tokenInfos,
- message.skippedPreprocessorRanges,
- documentRevision);
-}
-
-static
-CppEditor::CursorInfo::Range toCursorInfoRange(const ClangBackEnd::SourceRangeContainer &sourceRange)
-{
- const ClangBackEnd::SourceLocationContainer &start = sourceRange.start;
- const ClangBackEnd::SourceLocationContainer &end = sourceRange.end;
- const int length = end.column - start.column;
-
- return {start.line, start.column, length};
-}
-
-static
-CppEditor::CursorInfo toCursorInfo(const CppEditor::SemanticInfo::LocalUseMap &localUses,
- const ClangBackEnd::ReferencesMessage &message)
-{
- CppEditor::CursorInfo result;
- const QVector<ClangBackEnd::SourceRangeContainer> &references = message.references;
-
- result.areUseRangesForLocalVariable = message.isLocalVariable;
- for (const ClangBackEnd::SourceRangeContainer &reference : references)
- result.useRanges.append(toCursorInfoRange(reference));
-
- result.useRanges.reserve(references.size());
- result.localUses = localUses;
-
- return result;
-}
-
-static
-CppEditor::SymbolInfo toSymbolInfo(const ClangBackEnd::FollowSymbolMessage &message)
-{
- CppEditor::SymbolInfo result;
- const ClangBackEnd::SourceRangeContainer &range = message.result.range;
-
- const ClangBackEnd::SourceLocationContainer &start = range.start;
- const ClangBackEnd::SourceLocationContainer &end = range.end;
- result.startLine = start.line;
- result.startColumn = start.column;
- result.endLine = end.line;
- result.endColumn = end.column;
- result.fileName = start.filePath;
-
- result.isResultOnlyForFallBack = message.result.isResultOnlyForFallBack;
-
- return result;
-}
-
-void BackendReceiver::references(const ClangBackEnd::ReferencesMessage &message)
-{
- qCDebugIpc() << "ReferencesMessage with"
- << message.references.size() << "references";
-
- const quint64 ticket = message.ticketNumber;
- const ReferencesEntry entry = m_referencesTable.take(ticket);
- QFutureInterface<CppEditor::CursorInfo> futureInterface = entry.futureInterface;
- QTC_CHECK(futureInterface != QFutureInterface<CppEditor::CursorInfo>());
-
- if (futureInterface.isCanceled())
- return; // Editor document closed or a new request was issued making this result outdated.
-
- futureInterface.reportResult(toCursorInfo(entry.localUses, message));
- futureInterface.reportFinished();
-}
-
-static Core::HelpItem::Category toHelpItemCategory(ClangBackEnd::ToolTipInfo::QdocCategory category)
-{
- switch (category) {
- case ClangBackEnd::ToolTipInfo::Unknown:
- return Core::HelpItem::Unknown;
- case ClangBackEnd::ToolTipInfo::ClassOrNamespace:
- return Core::HelpItem::ClassOrNamespace;
- case ClangBackEnd::ToolTipInfo::Enum:
- return Core::HelpItem::Enum;
- case ClangBackEnd::ToolTipInfo::Typedef:
- return Core::HelpItem::Typedef;
- case ClangBackEnd::ToolTipInfo::Macro:
- return Core::HelpItem::Macro;
- case ClangBackEnd::ToolTipInfo::Brief:
- return Core::HelpItem::Brief;
- case ClangBackEnd::ToolTipInfo::Function:
- return Core::HelpItem::Function;
- }
-
- return Core::HelpItem::Unknown;
-}
-
-static QStringList toStringList(const Utf8StringVector &utf8StringVector)
-{
- QStringList list;
- list.reserve(utf8StringVector.size());
-
- for (const Utf8String &utf8String : utf8StringVector)
- list << utf8String.toString();
-
- return list;
-}
-
-static CppEditor::ToolTipInfo toToolTipInfo(const ClangBackEnd::ToolTipMessage &message)
-{
- CppEditor::ToolTipInfo info;
-
- const ClangBackEnd::ToolTipInfo &backendInfo = message.toolTipInfo;
-
- info.text = backendInfo.text;
- info.briefComment = backendInfo.briefComment;
-
- info.qDocIdCandidates = toStringList(backendInfo.qdocIdCandidates);
- info.qDocMark = backendInfo.qdocMark;
- info.qDocCategory = toHelpItemCategory(backendInfo.qdocCategory);
- info.value = backendInfo.value;
- info.sizeInBytes = backendInfo.sizeInBytes;
-
- return info;
-}
-
-void BackendReceiver::tooltip(const ClangBackEnd::ToolTipMessage &message)
-{
- qCDebugIpc() << "ToolTipMessage" << message.toolTipInfo.text;
-
- const quint64 ticket = message.ticketNumber;
- QFutureInterface<CppEditor::ToolTipInfo> futureInterface = m_toolTipsTable.take(ticket);
- QTC_CHECK(futureInterface != QFutureInterface<CppEditor::ToolTipInfo>());
-
- if (futureInterface.isCanceled())
- return; // A new request was issued making this one outdated.
-
- futureInterface.reportResult(toToolTipInfo(message));
- futureInterface.reportFinished();
-}
-
-void BackendReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
-{
- qCDebugIpc() << "FollowSymbolMessage with"
- << message.result;
-
- const quint64 ticket = message.ticketNumber;
- QFutureInterface<CppEditor::SymbolInfo> futureInterface = m_followTable.take(ticket);
- QTC_CHECK(futureInterface != QFutureInterface<CppEditor::SymbolInfo>());
-
- if (futureInterface.isCanceled())
- return; // Editor document closed or a new request was issued making this result outdated.
-
- futureInterface.reportResult(toSymbolInfo(message));
- futureInterface.reportFinished();
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.h b/src/plugins/clangcodemodel/clangbackendreceiver.h
deleted file mode 100644
index 253a0ff52c3..00000000000
--- a/src/plugins/clangcodemodel/clangbackendreceiver.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <cppeditor/cppcursorinfo.h>
-#include <cppeditor/cpptoolsreuse.h>
-#include <cppeditor/baseeditordocumentprocessor.h>
-
-#include <clangsupport/clangcodemodelclientinterface.h>
-
-#include <QFuture>
-#include <QPointer>
-#include <QTextDocument>
-
-namespace TextEditor {
-class IAssistProcessor;
-class TextEditorWidget;
-} // namespace TextEditor
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangCompletionAssistProcessor;
-
-class BackendReceiver : public ClangBackEnd::ClangCodeModelClientInterface
-{
-public:
- BackendReceiver();
- ~BackendReceiver() override;
-
- using AliveHandler = std::function<void ()>;
- void setAliveHandler(const AliveHandler &handler);
-
- void addExpectedCompletionsMessage(quint64 ticket, ClangCompletionAssistProcessor *processor);
- void cancelProcessor(TextEditor::IAssistProcessor *processor);
- void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget);
-
- QFuture<CppEditor::CursorInfo>
- addExpectedReferencesMessage(quint64 ticket,
- const CppEditor::SemanticInfo::LocalUseMap &localUses
- = CppEditor::SemanticInfo::LocalUseMap());
- QFuture<CppEditor::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
- QFuture<CppEditor::ToolTipInfo> addExpectedToolTipMessage(quint64 ticket);
- bool isExpectingCompletionsMessage() const;
-
- void reset();
-
-private:
- void alive() override;
- void echo(const ClangBackEnd::EchoMessage &message) override;
- void completions(const ClangBackEnd::CompletionsMessage &message) override;
-
- void annotations(const ClangBackEnd::AnnotationsMessage &message) override;
- void references(const ClangBackEnd::ReferencesMessage &message) override;
- void tooltip(const ClangBackEnd::ToolTipMessage &message) override;
- void followSymbol(const ClangBackEnd::FollowSymbolMessage &message) override;
-
-private:
- AliveHandler m_aliveHandler;
- QHash<quint64, ClangCompletionAssistProcessor *> m_assistProcessorsTable;
-
- struct ReferencesEntry {
- ReferencesEntry() = default;
- ReferencesEntry(QFutureInterface<CppEditor::CursorInfo> futureInterface,
- const CppEditor::SemanticInfo::LocalUseMap &localUses)
- : futureInterface(futureInterface)
- , localUses(localUses) {}
- QFutureInterface<CppEditor::CursorInfo> futureInterface;
- CppEditor::SemanticInfo::LocalUseMap localUses;
- };
- QHash<quint64, ReferencesEntry> m_referencesTable;
- QHash<quint64, QFutureInterface<CppEditor::ToolTipInfo>> m_toolTipsTable;
- QHash<quint64, QFutureInterface<CppEditor::SymbolInfo>> m_followTable;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendsender.cpp b/src/plugins/clangcodemodel/clangbackendsender.cpp
deleted file mode 100644
index 17f68ae1d73..00000000000
--- a/src/plugins/clangcodemodel/clangbackendsender.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangbackendsender.h"
-
-#include "clangbackendlogging.h"
-
-#include <clangsupport/clangcodemodelconnectionclient.h>
-#include <clangsupport/clangcodemodelservermessages.h>
-
-#include <utils/qtcassert.h>
-
-#define qCDebugIpc() qCDebug(ipcLog) << "====>"
-
-using namespace ClangBackEnd;
-
-namespace ClangCodeModel {
-namespace Internal {
-
-BackendSender::BackendSender(ClangCodeModelConnectionClient *connectionClient)
- : m_connection(connectionClient)
-{}
-
-void BackendSender::end()
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << ClangBackEnd::EndMessage();
- m_connection->sendEndMessage();
-}
-
-void BackendSender::documentsOpened(const DocumentsOpenedMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().documentsOpened(message);
-}
-
-void BackendSender::documentsChanged(const DocumentsChangedMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().documentsChanged(message);
-}
-
-void BackendSender::documentsClosed(const DocumentsClosedMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().documentsClosed(message);
-}
-
-void BackendSender::unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().unsavedFilesUpdated(message);
-}
-
-void BackendSender::unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().unsavedFilesRemoved(message);
-}
-
-void BackendSender::requestCompletions(const RequestCompletionsMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().requestCompletions(message);
-}
-
-void BackendSender::requestAnnotations(const RequestAnnotationsMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().requestAnnotations(message);
-}
-
-void BackendSender::requestReferences(const RequestReferencesMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().requestReferences(message);
-}
-
-void BackendSender::requestToolTip(const RequestToolTipMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebug(ipcLog) << ">>>" << message;
- m_connection->serverProxy().requestToolTip(message);
-}
-
-void BackendSender::requestFollowSymbol(const RequestFollowSymbolMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().requestFollowSymbol(message);
-}
-
-void BackendSender::documentVisibilityChanged(const DocumentVisibilityChangedMessage &message)
-{
- QTC_CHECK(m_connection->isConnected());
- qCDebugIpc() << message;
- m_connection->serverProxy().documentVisibilityChanged(message);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendsender.h b/src/plugins/clangcodemodel/clangbackendsender.h
deleted file mode 100644
index 5e4f14f9379..00000000000
--- a/src/plugins/clangcodemodel/clangbackendsender.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport/clangcodemodelserverinterface.h>
-
-namespace ClangBackEnd { class ClangCodeModelConnectionClient; }
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class BackendSender : public ClangBackEnd::ClangCodeModelServerInterface
-{
-public:
- BackendSender(ClangBackEnd::ClangCodeModelConnectionClient *connectionClient);
-
- void end() override;
-
- void documentsOpened(const ClangBackEnd::DocumentsOpenedMessage &message) override;
- void documentsChanged(const ClangBackEnd::DocumentsChangedMessage &message) override;
- void documentsClosed(const ClangBackEnd::DocumentsClosedMessage &message) override;
- void documentVisibilityChanged(const ClangBackEnd::DocumentVisibilityChangedMessage &message) override;
-
- void unsavedFilesUpdated(const ClangBackEnd::UnsavedFilesUpdatedMessage &message) override;
- void unsavedFilesRemoved(const ClangBackEnd::UnsavedFilesRemovedMessage &message) override;
-
- void requestCompletions(const ClangBackEnd::RequestCompletionsMessage &message) override;
- void requestAnnotations(const ClangBackEnd::RequestAnnotationsMessage &message) override;
- void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
- void requestToolTip(const ClangBackEnd::RequestToolTipMessage &message) override;
- void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override;
-
-private:
- ClangBackEnd::ClangCodeModelConnectionClient *m_connection = nullptr;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs
index 75a7f6bc90f..dc85b9d96d4 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.qbs
+++ b/src/plugins/clangcodemodel/clangcodemodel.qbs
@@ -6,7 +6,6 @@ QtcPlugin {
Depends { name: "Qt"; submodules: ["concurrent", "widgets"] }
- Depends { name: "ClangSupport" }
Depends { name: "Core" }
Depends { name: "CppEditor" }
Depends { name: "LanguageClient" }
@@ -15,53 +14,28 @@ QtcPlugin {
Depends { name: "TextEditor" }
Depends { name: "Utils" }
- Depends { name: "libclang"; required: false }
Depends { name: "clang_defines" }
pluginTestDepends: [
"QmakeProjectManager",
]
- condition: libclang.present
-
files: [
"clangactivationsequencecontextprocessor.cpp",
"clangactivationsequencecontextprocessor.h",
"clangactivationsequenceprocessor.cpp",
"clangactivationsequenceprocessor.h",
- "clangassistproposalitem.cpp",
- "clangassistproposalitem.h",
- "clangassistproposalmodel.cpp",
- "clangassistproposalmodel.h",
- "clangbackendcommunicator.cpp",
- "clangbackendcommunicator.h",
- "clangbackendlogging.cpp",
- "clangbackendlogging.h",
- "clangbackendreceiver.cpp",
- "clangbackendreceiver.h",
- "clangbackendsender.cpp",
- "clangbackendsender.h",
"clangcodemodelplugin.cpp",
"clangcodemodelplugin.h",
- "clangcompletionassistinterface.cpp",
- "clangcompletionassistinterface.h",
- "clangcompletionassistprocessor.cpp",
- "clangcompletionassistprocessor.h",
- "clangcompletionassistprovider.cpp",
- "clangcompletionassistprovider.h",
- "clangcompletionchunkstotextconverter.cpp",
- "clangcompletionchunkstotextconverter.h",
"clangcompletioncontextanalyzer.cpp",
"clangcompletioncontextanalyzer.h",
"clangconstants.h",
- "clangcurrentdocumentfilter.cpp",
- "clangcurrentdocumentfilter.h",
+ "clangdast.cpp",
+ "clangdast.h",
"clangdclient.cpp",
"clangdclient.h",
- "clangdiagnosticfilter.cpp",
- "clangdiagnosticfilter.h",
- "clangdiagnosticmanager.cpp",
- "clangdiagnosticmanager.h",
+ "clangdfollowsymbol.cpp",
+ "clangdfollowsymbol.h",
"clangdiagnostictooltipwidget.cpp",
"clangdiagnostictooltipwidget.h",
"clangdlocatorfilters.cpp",
@@ -70,42 +44,24 @@ QtcPlugin {
"clangdqpropertyhighlighter.h",
"clangdquickfixfactory.cpp",
"clangdquickfixfactory.h",
- "clangeditordocumentparser.cpp",
- "clangeditordocumentparser.h",
+ "clangdsemantichighlighting.cpp",
+ "clangdsemantichighlighting.h",
+ "clangdswitchdecldef.cpp",
+ "clangdswitchdecldef.h",
"clangeditordocumentprocessor.cpp",
"clangeditordocumentprocessor.h",
"clangfixitoperation.cpp",
"clangfixitoperation.h",
- "clangfixitoperationsextractor.cpp",
- "clangfixitoperationsextractor.h",
- "clangfollowsymbol.cpp",
- "clangfollowsymbol.h",
- "clangfunctionhintmodel.cpp",
- "clangfunctionhintmodel.h",
- "clanghighlightingresultreporter.cpp",
- "clanghighlightingresultreporter.h",
- "clanghoverhandler.cpp",
- "clanghoverhandler.h",
- "clangisdiagnosticrelatedtolocation.h",
"clangmodelmanagersupport.cpp",
"clangmodelmanagersupport.h",
- "clangoverviewmodel.cpp",
- "clangoverviewmodel.h",
"clangpreprocessorassistproposalitem.cpp",
"clangpreprocessorassistproposalitem.h",
- "clangprojectsettings.cpp",
- "clangprojectsettings.h",
- "clangprojectsettingswidget.cpp",
- "clangprojectsettingswidget.h",
- "clangprojectsettingswidget.ui",
- "clangrefactoringengine.cpp",
- "clangrefactoringengine.h",
"clangtextmark.cpp",
"clangtextmark.h",
- "clanguiheaderondiskmanager.cpp",
- "clanguiheaderondiskmanager.h",
"clangutils.cpp",
"clangutils.h",
+ "tasktimers.cpp",
+ "tasktimers.h",
]
Group {
@@ -136,14 +92,14 @@ QtcPlugin {
condition: qtc.testsEnabled
prefix: "test/"
files: [
- "clangautomationutils.cpp",
- "clangautomationutils.h",
+ "activationsequenceprocessortest.cpp",
+ "activationsequenceprocessortest.h",
"clangbatchfileprocessor.cpp",
"clangbatchfileprocessor.h",
- "clangcodecompletion_test.cpp",
- "clangcodecompletion_test.h",
"clangdtests.cpp",
"clangdtests.h",
+ "clangfixittest.cpp",
+ "clangfixittest.h",
"data/clangtestdata.qrc",
]
}
diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
index 3a13c4542db..c92de68c04c 100644
--- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
+++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
@@ -26,13 +26,13 @@
#include "clangcodemodelplugin.h"
#include "clangconstants.h"
-#include "clangprojectsettingswidget.h"
#include "clangutils.h"
#ifdef WITH_TESTS
+# include "test/activationsequenceprocessortest.h"
# include "test/clangbatchfileprocessor.h"
-# include "test/clangcodecompletion_test.h"
# include "test/clangdtests.h"
+# include "test/clangfixittest.h"
#endif
#include <coreplugin/actionmanager/actioncontainer.h>
@@ -40,34 +40,28 @@
#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
+#include <cppeditor/clangdiagnosticconfig.h>
#include <cppeditor/cppmodelmanager.h>
#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/project.h>
#include <projectexplorer/projectpanelfactory.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
#include <texteditor/textmark.h>
-#include <QtConcurrent>
+#include <utils/temporarydirectory.h>
+#include <utils/runextensions.h>
using namespace Utils;
namespace ClangCodeModel {
namespace Internal {
-static void addProjectPanelWidget()
-{
- auto panelFactory = new ProjectExplorer::ProjectPanelFactory();
- panelFactory->setPriority(60);
- panelFactory->setDisplayName(ClangProjectSettingsWidget::tr("Clang Code Model"));
- panelFactory->setCreateWidgetFunction(
- [&](ProjectExplorer::Project *project) { return new ClangProjectSettingsWidget(project); });
- ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
-}
-
void ClangCodeModelPlugin::generateCompilationDB()
{
using namespace CppEditor;
@@ -79,12 +73,16 @@ void ClangCodeModelPlugin::generateCompilationDB()
const auto projectInfo = CppModelManager::instance()->projectInfo(target->project());
if (!projectInfo)
return;
+ FilePath baseDir = projectInfo->buildRoot();
+ if (baseDir == target->project()->projectDirectory())
+ baseDir = TemporaryDirectory::masterDirectoryFilePath();
QFuture<GenerateCompilationDbResult> task
- = QtConcurrent::run(&Internal::generateCompilationDB, projectInfo,
- projectInfo->buildRoot(), CompilationDbPurpose::Project,
- warningsConfigForProject(target->project()),
- optionsForProject(target->project()));
+ = Utils::runAsync(&Internal::generateCompilationDB, projectInfo,
+ baseDir, CompilationDbPurpose::Project,
+ warningsConfigForProject(target->project()),
+ globalClangOptions(),
+ FilePath());
Core::ProgressManager::addTask(task, tr("Generating Compilation DB"), "generate compilation db");
m_generatorWatcher.setFuture(task);
}
@@ -118,8 +116,6 @@ bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *err
CppEditor::CppModelManager::instance()->activateClangCodeModel(&m_modelManagerSupportProvider);
- addProjectPanelWidget();
-
createCompilationDBButton();
return true;
@@ -209,7 +205,7 @@ void ClangCodeModelPlugin::maybeHandleBatchFileAndExit() const
QVector<QObject *> ClangCodeModelPlugin::createTestObjects() const
{
return {
- new Tests::ClangCodeCompletionTest,
+ new Tests::ActivationSequenceProcessorTest,
new Tests::ClangdTestCompletion,
new Tests::ClangdTestExternalChanges,
new Tests::ClangdTestFindReferences,
@@ -217,10 +213,10 @@ QVector<QObject *> ClangCodeModelPlugin::createTestObjects() const
new Tests::ClangdTestHighlighting,
new Tests::ClangdTestLocalReferences,
new Tests::ClangdTestTooltips,
+ new Tests::ClangFixItTest,
};
}
#endif
-
} // namespace Internal
} // namespace Clang
diff --git a/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp b/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp
deleted file mode 100644
index 8f2b5a9ffb8..00000000000
--- a/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcompletionassistinterface.h"
-
-#include <texteditor/texteditor.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-ClangCompletionAssistInterface::ClangCompletionAssistInterface(BackendCommunicator &communicator, CompletionType type,
- const TextEditor::TextEditorWidget *textEditorWidget,
- int position,
- const Utils::FilePath &fileName,
- TextEditor::AssistReason reason,
- const ProjectExplorer::HeaderPaths &headerPaths,
- const CPlusPlus::LanguageFeatures &features)
- : AssistInterface(textEditorWidget->document(), position, fileName, reason)
- , m_communicator(communicator)
- , m_type(type)
- , m_headerPaths(headerPaths)
- , m_languageFeatures(features)
- , m_textEditorWidget(textEditorWidget)
-{
-}
-
-bool ClangCompletionAssistInterface::objcEnabled() const
-{
- return true; // TODO:
-}
-
-const ProjectExplorer::HeaderPaths &ClangCompletionAssistInterface::headerPaths() const
-{
- return m_headerPaths;
-}
-
-CPlusPlus::LanguageFeatures ClangCompletionAssistInterface::languageFeatures() const
-{
- return m_languageFeatures;
-}
-
-void ClangCompletionAssistInterface::setHeaderPaths(const ProjectExplorer::HeaderPaths &headerPaths)
-{
- m_headerPaths = headerPaths;
-}
-
-const TextEditor::TextEditorWidget *ClangCompletionAssistInterface::textEditorWidget() const
-{
- return m_textEditorWidget;
-}
-
-BackendCommunicator &ClangCompletionAssistInterface::communicator() const
-{
- return m_communicator;
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
-
diff --git a/src/plugins/clangcodemodel/clangcompletionassistinterface.h b/src/plugins/clangcodemodel/clangcompletionassistinterface.h
deleted file mode 100644
index ce3f0921c8f..00000000000
--- a/src/plugins/clangcodemodel/clangcompletionassistinterface.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangbackendcommunicator.h"
-#include "clangutils.h"
-
-#include <texteditor/codeassist/assistinterface.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-enum class CompletionType { FunctionHint, Other };
-
-class ClangCompletionAssistInterface: public TextEditor::AssistInterface
-{
-public:
- ClangCompletionAssistInterface(BackendCommunicator &communicator,
- CompletionType type,
- const TextEditor::TextEditorWidget *textEditorWidget,
- int position,
- const Utils::FilePath &fileName,
- TextEditor::AssistReason reason,
- const ProjectExplorer::HeaderPaths &headerPaths,
- const CPlusPlus::LanguageFeatures &features);
-
- BackendCommunicator &communicator() const;
- CompletionType type() const { return m_type; }
- bool objcEnabled() const;
- const ProjectExplorer::HeaderPaths &headerPaths() const;
- CPlusPlus::LanguageFeatures languageFeatures() const;
- const TextEditor::TextEditorWidget *textEditorWidget() const;
-
- void setHeaderPaths(const ProjectExplorer::HeaderPaths &headerPaths); // For tests
-
-private:
- BackendCommunicator &m_communicator;
- const CompletionType m_type;
- QStringList m_options;
- ProjectExplorer::HeaderPaths m_headerPaths;
- CPlusPlus::LanguageFeatures m_languageFeatures;
- const TextEditor::TextEditorWidget *m_textEditorWidget;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
deleted file mode 100644
index ac8f686910a..00000000000
--- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
+++ /dev/null
@@ -1,718 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangassistproposalitem.h"
-
-#include "clangactivationsequenceprocessor.h"
-#include "clangassistproposalmodel.h"
-#include "clangcompletionassistprocessor.h"
-#include "clangcompletioncontextanalyzer.h"
-#include "clangfixitoperation.h"
-#include "clangfunctionhintmodel.h"
-#include "clangcompletionchunkstotextconverter.h"
-#include "clangpreprocessorassistproposalitem.h"
-
-#include <cppeditor/cppdoxygen.h>
-#include <cppeditor/cppmodelmanager.h>
-#include <cppeditor/cpptoolsreuse.h>
-#include <cppeditor/editordocumenthandle.h>
-
-#include <texteditor/codeassist/assistproposalitem.h>
-#include <texteditor/codeassist/functionhintproposal.h>
-#include <texteditor/codeassist/genericproposal.h>
-#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
-#include <texteditor/texteditorsettings.h>
-
-#include <cplusplus/Icons.h>
-
-#include <clangsupport/filecontainer.h>
-
-#include <utils/algorithm.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/optional.h>
-#include <utils/porting.h>
-#include <utils/qtcassert.h>
-#include <utils/textutils.h>
-
-#include <QDirIterator>
-#include <QPair>
-#include <QTextDocument>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-using ClangBackEnd::CodeCompletion;
-using TextEditor::AssistProposalItemInterface;
-
-static void addAssistProposalItem(QList<AssistProposalItemInterface *> &items,
- const CodeCompletion &codeCompletion,
- const QString &name)
-{
- auto item = new ClangAssistProposalItem;
- items.push_back(item);
-
- item->setText(name);
- item->setOrder(int(codeCompletion.priority));
- item->appendCodeCompletion(codeCompletion);
-}
-
-// Add the next CXXMethod or CXXConstructor which is the overload for another existing item.
-static void addFunctionOverloadAssistProposalItem(QList<AssistProposalItemInterface *> &items,
- AssistProposalItemInterface *sameItem,
- const ClangCompletionAssistInterface *interface,
- const CodeCompletion &codeCompletion,
- const QString &name)
-{
- auto *item = static_cast<ClangAssistProposalItem *>(sameItem);
- item->setHasOverloadsWithParameters(codeCompletion.hasParameters);
- if (codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind) {
- // It's the constructor, currently constructor definitions do not lead here.
- // CLANG-UPGRADE-CHECK: Can we get here with constructor definition?
- item->appendCodeCompletion(codeCompletion);
- return;
- }
-
- QTextCursor cursor = interface->textEditorWidget()->textCursor();
- cursor.setPosition(interface->position());
- cursor.movePosition(QTextCursor::StartOfWord);
-
- const ClangBackEnd::CodeCompletionChunk resultType = codeCompletion.chunks.first();
- if (matchPreviousWord(*interface->textEditorWidget(), cursor, resultType.text.toString())) {
- // Function definition completion - do not merge completions together.
- addAssistProposalItem(items, codeCompletion, name);
- } else {
- item->appendCodeCompletion(codeCompletion);
- }
-}
-
-// Check if they are both CXXMethod or CXXConstructor.
-static bool isTheSameFunctionOverload(const CodeCompletion &completion,
- const QString &name,
- ClangAssistProposalItem *lastItem)
-{
- return completion.completionKind == lastItem->firstCodeCompletion().completionKind
- && lastItem->text() == name;
-}
-
-QList<AssistProposalItemInterface *> ClangCompletionAssistProcessor::toAssistProposalItems(
- const CodeCompletions &completions) const
-{
- // TODO: Handle Qt4's SIGNAL/SLOT
- // Possibly check for m_completionOperator == T_SIGNAL
- // Possibly check for codeCompletion.completionKind == CodeCompletion::SignalCompletionKind
-
- QList<AssistProposalItemInterface *> items;
- items.reserve(completions.size());
-
- // If there are signals among the candidates, we employ the built-in code model to find out
- // whether the cursor was on the second argument of a (dis)connect() call.
- // If so, we offer only signals, as nothing else makes sense in that context.
- bool considerOnlySignals = false;
- if (m_position != -1 && Utils::anyOf(completions, [](const CodeCompletion &c) {
- return c.completionKind == CodeCompletion::SignalCompletionKind;
- })) {
- considerOnlySignals = CppEditor::CppModelManager::instance()
- ->positionRequiresSignal(m_interface->filePath().toString(), m_content, m_position);
- }
- for (const CodeCompletion &codeCompletion : completions) {
- if (codeCompletion.text.isEmpty())
- continue; // It's an OverloadCandidate which has text but no typedText.
-
- if (considerOnlySignals
- && codeCompletion.completionKind != CodeCompletion::ClassCompletionKind
- && codeCompletion.completionKind != CodeCompletion::NamespaceCompletionKind
- && codeCompletion.completionKind != CodeCompletion::SignalCompletionKind) {
- continue;
- }
-
- // Don't offer symbols that are not accessible here.
- if (codeCompletion.availability == CodeCompletion::NotAvailable
- || codeCompletion.availability == CodeCompletion::NotAccessible) {
- continue;
- }
-
- const QString name = codeCompletion.completionKind == CodeCompletion::KeywordCompletionKind
- ? CompletionChunksToTextConverter::convertToName(codeCompletion.chunks)
- : codeCompletion.text.toString();
-
- if (items.empty()) {
- addAssistProposalItem(items, codeCompletion, name);
- } else {
- auto *lastItem = static_cast<ClangAssistProposalItem *>(items.last());
- if (isTheSameFunctionOverload(codeCompletion, name, lastItem)) {
- addFunctionOverloadAssistProposalItem(items, items.back(), m_interface.data(),
- codeCompletion, name);
- } else {
- addAssistProposalItem(items, codeCompletion, name);
- }
- }
- }
-
- return items;
-}
-
-using namespace CPlusPlus;
-using namespace TextEditor;
-
-ClangCompletionAssistProcessor::ClangCompletionAssistProcessor()
- : CppCompletionAssistProcessor(100)
- , m_completionOperator(T_EOF_SYMBOL)
-{
-}
-
-ClangCompletionAssistProcessor::~ClangCompletionAssistProcessor() = default;
-
-IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface *interface)
-{
- m_interface.reset(static_cast<const ClangCompletionAssistInterface *>(interface));
-
- if (interface->reason() != ExplicitlyInvoked && !accepts()) {
- m_requestSent = false;
- return nullptr;
- }
-
- return startCompletionHelper(); // == 0 if results are calculated asynchronously
-}
-
-// All completions require fix-it, apply this fix-it now.
-CodeCompletions ClangCompletionAssistProcessor::applyCompletionFixIt(const CodeCompletions &completions)
-{
- // CLANG-UPGRADE-CHECK: Currently we rely on fact that there are only 2 possible fix-it types:
- // 'dot to arrow' and 'arrow to dot' and they can't appear for the same item.
- // However if we get multiple options which trigger for the same code we need to improve this
- // algorithm. Check comments to FixIts field of CodeCompletionResult and which fix-its are used
- // to construct results in SemaCodeComplete.cpp.
- const CodeCompletion &completion = completions.front();
- const ClangBackEnd::FixItContainer &fixIt = completion.requiredFixIts.front();
-
- ClangFixItOperation fixItOperation(Utf8String(), completion.requiredFixIts);
- fixItOperation.perform();
-
- const int fixItLength = fixIt.range.end.column - fixIt.range.start.column;
- const QString fixItText = fixIt.text.toString();
- m_positionForProposal += fixItText.length() - fixItLength;
-
- CodeCompletions completionsWithoutFixIts;
- completionsWithoutFixIts.reserve(completions.size());
- for (const CodeCompletion &completion : completions) {
- CodeCompletion completionCopy = completion;
- completionCopy.requiredFixIts.clear();
- completionsWithoutFixIts.push_back(completionCopy);
- }
-
- return completionsWithoutFixIts;
-}
-
-void ClangCompletionAssistProcessor::handleAvailableCompletions(const CodeCompletions &completions)
-{
- QTC_CHECK(m_completions.isEmpty());
-
- if (m_sentRequestType == FunctionHintCompletion && !completions.isEmpty()) {
- const CodeCompletion &firstCompletion = completions.front();
- if (firstCompletion.completionKind == CodeCompletion::FunctionOverloadCompletionKind) {
- setAsyncProposalAvailable(createFunctionHintProposal(completions));
- return;
- }
-
- if (!m_fallbackToNormalCompletion) {
- // We must report back to the code assistant under all circumstances
- setAsyncProposalAvailable(nullptr);
- return;
- }
- // else: Proceed with a normal completion in case:
- // 1) it was not a function call, but e.g. a function declaration like "void f("
- // 2) '{' meant not a constructor call.
- }
-
- //m_sentRequestType == NormalCompletion or function signatures were empty
-
- // Completions are sorted the way that all items with fix-its come after all items without them
- // therefore it's enough to check only the first one.
- if (!completions.isEmpty() && !completions.front().requiredFixIts.isEmpty())
- m_completions = toAssistProposalItems(applyCompletionFixIt(completions));
- else
- m_completions = toAssistProposalItems(completions);
-
- if (m_addSnippets && !m_completions.isEmpty())
- addSnippets();
-
- setAsyncProposalAvailable(createProposal());
-}
-
-const TextEditorWidget *ClangCompletionAssistProcessor::textEditorWidget() const
-{
- return m_interface->textEditorWidget();
-}
-
-/// Seach backwards in the document starting from pos to find the first opening
-/// parenthesis. Nested parenthesis are skipped.
-static int findOpenParen(QTextDocument *document, int start)
-{
- unsigned parenCount = 1;
- for (int position = start; position >= 0; --position) {
- const QChar ch = document->characterAt(position);
- if (ch == QLatin1Char('(')) {
- --parenCount;
- if (parenCount == 0)
- return position;
- } else if (ch == QLatin1Char(')')) {
- ++parenCount;
- }
- }
- return -1;
-}
-
-static QByteArray modifyInput(QTextDocument *doc, int endOfExpression) {
- int comma = endOfExpression;
- while (comma > 0) {
- const QChar ch = doc->characterAt(comma);
- if (ch == QLatin1Char(','))
- break;
- if (ch == QLatin1Char(';') || ch == QLatin1Char('{') || ch == QLatin1Char('}')) {
- // Safety net: we don't seem to have "connect(pointer, SIGNAL(" as
- // input, so stop searching.
- comma = -1;
- break;
- }
- --comma;
- }
- if (comma < 0)
- return QByteArray();
- const int openBrace = findOpenParen(doc, comma);
- if (openBrace < 0)
- return QByteArray();
-
- QByteArray modifiedInput = doc->toPlainText().toUtf8();
- const int len = endOfExpression - comma;
- QByteArray replacement(len - 4, ' ');
- replacement.append(")->");
- modifiedInput.replace(comma, len, replacement);
- modifiedInput.insert(openBrace, '(');
- return modifiedInput;
-}
-
-static QChar lastPrecedingNonWhitespaceChar(const ClangCompletionAssistInterface *interface)
-{
- int pos = interface->position();
- while (pos >= 0 && interface->characterAt(pos).isSpace())
- --pos;
- return pos >= 0 ? interface->characterAt(pos) : QChar::Null;
-}
-
-IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
-{
- ClangCompletionContextAnalyzer analyzer(m_interface.data(), m_interface->languageFeatures());
- analyzer.analyze();
- m_completionOperator = analyzer.completionOperator();
- m_positionForProposal = analyzer.positionForProposal();
- m_addSnippets = analyzer.addSnippets();
-
- QByteArray modifiedFileContent;
-
- const ClangCompletionContextAnalyzer::CompletionAction action = analyzer.completionAction();
- switch (action) {
- case ClangCompletionContextAnalyzer::CompleteDoxygenKeyword:
- if (completeDoxygenKeywords())
- return createProposal();
- break;
- case ClangCompletionContextAnalyzer::CompleteIncludePath:
- m_completions = completeInclude(analyzer.positionEndOfExpression(), m_completionOperator,
- m_interface.data(), m_interface->headerPaths());
- if (!m_completions.isEmpty())
- return createProposal();
- break;
- case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
- if (completePreprocessorDirectives())
- return createProposal();
- break;
- case ClangCompletionContextAnalyzer::CompleteSignal:
- case ClangCompletionContextAnalyzer::CompleteSlot:
- modifiedFileContent = modifyInput(m_interface->textDocument(),
- analyzer.positionEndOfExpression());
- Q_FALLTHROUGH();
- case ClangCompletionContextAnalyzer::PassThroughToLibClang: {
- m_sentRequestType = NormalCompletion;
- m_requestSent = sendCompletionRequest(analyzer.positionForClang(),
- modifiedFileContent);
- break;
- }
- case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: {
- m_sentRequestType = FunctionHintCompletion;
- if (lastPrecedingNonWhitespaceChar(m_interface.data()) == ',')
- m_fallbackToNormalCompletion = false;
- m_requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray(),
- analyzer.functionNameStart());
- break;
- }
- case ClangCompletionContextAnalyzer::CompleteNone:
- default:
- break;
- }
-
- return nullptr;
-}
-
-int ClangCompletionAssistProcessor::startOfOperator(int positionInDocument,
- unsigned *kind,
- bool wantFunctionCall) const
-{
- auto activationSequence = m_interface->textAt(positionInDocument - 3, 3);
- ActivationSequenceProcessor activationSequenceProcessor(activationSequence,
- positionInDocument,
- wantFunctionCall);
-
- *kind = activationSequenceProcessor.completionKind();
- int start = activationSequenceProcessor.operatorStartPosition();
-
- CppCompletionAssistProcessor::startOfOperator(m_interface->textDocument(),
- positionInDocument,
- kind,
- start,
- m_interface->languageFeatures());
-
- return start;
-}
-
-int ClangCompletionAssistProcessor::findStartOfName(int pos) const
-{
- if (pos == -1)
- pos = m_interface->position();
- QChar chr;
-
- // Skip to the start of a name
- do {
- chr = m_interface->characterAt(--pos);
- } while (chr.isLetterOrNumber() || chr == QLatin1Char('_'));
-
- return pos + 1;
-}
-
-bool ClangCompletionAssistProcessor::accepts() const
-{
- const int pos = m_interface->position();
- unsigned token = T_EOF_SYMBOL;
-
- const int start = startOfOperator(pos, &token, /*want function call=*/ true);
- if (start != pos) {
- if (token == T_POUND) {
- const int column = pos - m_interface->textDocument()->findBlock(start).position();
- if (column != 1)
- return false;
- }
-
- return true;
- } else {
- // Trigger completion after n characters of a name have been typed, when not editing an existing name
- QChar characterUnderCursor = m_interface->characterAt(pos);
- if (!characterUnderCursor.isLetterOrNumber() && characterUnderCursor != QLatin1Char('_')) {
- const int startOfName = findStartOfName(pos);
- if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) {
- const QChar firstCharacter = m_interface->characterAt(startOfName);
- if (firstCharacter.isLetter() || firstCharacter == QLatin1Char('_')) {
- return !CppEditor::isInCommentOrString(m_interface.data(),
- m_interface->languageFeatures());
- }
- }
- }
- }
-
- return false;
-}
-
-/**
- * @brief Creates completion proposals for #include and given cursor
- * @param position - cursor placed after opening bracked or quote
- * @param completionOperator - the type of token
- * @param interface - relevant document data
- * @param headerPaths - the include paths
- * @return the list of completion items
- */
-QList<AssistProposalItemInterface *> ClangCompletionAssistProcessor::completeInclude(
- int position, unsigned completionOperator, const TextEditor::AssistInterface *interface,
- const ProjectExplorer::HeaderPaths &headerPaths)
-{
- QTextCursor cursor(interface->textDocument());
- cursor.setPosition(position);
- QString directoryPrefix;
- if (completionOperator == T_SLASH) {
- QTextCursor c = cursor;
- c.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
- QString sel = c.selectedText();
- int startCharPos = sel.indexOf(QLatin1Char('"'));
- if (startCharPos == -1) {
- startCharPos = sel.indexOf(QLatin1Char('<'));
- completionOperator = T_ANGLE_STRING_LITERAL;
- } else {
- completionOperator = T_STRING_LITERAL;
- }
- if (startCharPos != -1)
- directoryPrefix = sel.mid(startCharPos + 1, sel.length() - 1);
- }
-
- // Make completion for all relevant includes
- ProjectExplorer::HeaderPaths allHeaderPaths = headerPaths;
- const auto currentFilePath = ProjectExplorer::HeaderPath::makeUser(
- interface->filePath().toFileInfo().path());
- if (!allHeaderPaths.contains(currentFilePath))
- allHeaderPaths.append(currentFilePath);
-
- const ::Utils::MimeType mimeType = ::Utils::mimeTypeForName("text/x-c++hdr");
- const QStringList suffixes = mimeType.suffixes();
-
- QList<AssistProposalItemInterface *> completions;
- foreach (const ProjectExplorer::HeaderPath &headerPath, allHeaderPaths) {
- QString realPath = headerPath.path;
- if (!directoryPrefix.isEmpty()) {
- realPath += QLatin1Char('/');
- realPath += directoryPrefix;
- if (headerPath.type == ProjectExplorer::HeaderPathType::Framework)
- realPath += QLatin1String(".framework/Headers");
- }
- completions << completeIncludePath(realPath, suffixes, completionOperator);
- }
-
- QList<QPair<AssistProposalItemInterface *, QString>> completionsForSorting;
- for (AssistProposalItemInterface * const item : qAsConst(completions)) {
- QString s = item->text();
- s.replace('/', QChar(0)); // The dir separator should compare less than anything else.
- completionsForSorting << qMakePair(item, s);
- }
- Utils::sort(completionsForSorting, [](const auto &left, const auto &right) {
- return left.second < right.second;
- });
- for (int i = 0; i < completionsForSorting.count(); ++i)
- completions[i] = completionsForSorting[i].first;
-
- return completions;
-}
-
-/**
- * @brief Finds #include completion proposals using given include path
- * @param realPath - one of directories where compiler searches includes
- * @param suffixes - file suffixes for C/C++ header files
- * @return a list of matching completion items
- */
-QList<AssistProposalItemInterface *> ClangCompletionAssistProcessor::completeIncludePath(
- const QString &realPath, const QStringList &suffixes, unsigned completionOperator)
-{
- QList<AssistProposalItemInterface *> completions;
- QDirIterator i(realPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
- //: Parent folder for proposed #include completion
- const QString hint = tr("Location: %1").arg(QDir::toNativeSeparators(QDir::cleanPath(realPath)));
- while (i.hasNext()) {
- const QString fileName = i.next();
- const QFileInfo fileInfo = i.fileInfo();
- const QString suffix = fileInfo.suffix();
- if (suffix.isEmpty() || suffixes.contains(suffix)) {
- QString text = fileName.mid(realPath.length() + 1);
- if (fileInfo.isDir())
- text += QLatin1Char('/');
-
- auto *item = new ClangPreprocessorAssistProposalItem;
- item->setText(text);
- item->setDetail(hint);
- item->setIcon(CPlusPlus::Icons::keywordIcon());
- item->setCompletionOperator(completionOperator);
- completions.append(item);
- }
- }
- return completions;
-}
-
-bool ClangCompletionAssistProcessor::completePreprocessorDirectives()
-{
- foreach (const QString &preprocessorCompletion, preprocessorCompletions())
- addCompletionItem(preprocessorCompletion,
- Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro));
-
- if (m_interface->objcEnabled())
- addCompletionItem(QLatin1String("import"),
- Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro));
-
- return !m_completions.isEmpty();
-}
-
-bool ClangCompletionAssistProcessor::completeDoxygenKeywords()
-{
- for (int i = 1; i < CppEditor::T_DOXY_LAST_TAG; ++i)
- addCompletionItem(QString::fromLatin1(CppEditor::doxygenTagSpell(i)), CPlusPlus::Icons::keywordIcon());
- return !m_completions.isEmpty();
-}
-
-void ClangCompletionAssistProcessor::addCompletionItem(const QString &text,
- const QIcon &icon,
- int order)
-{
- auto *item = new ClangPreprocessorAssistProposalItem;
- item->setText(text);
- item->setIcon(icon);
- item->setOrder(order);
- item->setCompletionOperator(m_completionOperator);
- m_completions.append(item);
-}
-
-ClangCompletionAssistProcessor::UnsavedFileContentInfo
-ClangCompletionAssistProcessor::unsavedFileContent(const QByteArray &customFileContent) const
-{
- const bool hasCustomModification = !customFileContent.isEmpty();
-
- UnsavedFileContentInfo info;
- info.isDocumentModified = hasCustomModification || m_interface->textDocument()->isModified();
- info.unsavedContent = hasCustomModification
- ? customFileContent
- : m_interface->textDocument()->toPlainText().toUtf8();
- return info;
-}
-
-void ClangCompletionAssistProcessor::sendFileContent(const QByteArray &customFileContent)
-{
- // TODO: Revert custom modification after the completions
- const UnsavedFileContentInfo info = unsavedFileContent(customFileContent);
-
- BackendCommunicator &communicator = m_interface->communicator();
- communicator.documentsChanged({{m_interface->filePath().toString(),
- Utf8String::fromByteArray(info.unsavedContent),
- info.isDocumentModified,
- uint(m_interface->textDocument()->revision())}});
-}
-namespace {
-bool shouldSendDocumentForCompletion(const QString &filePath,
- int completionPosition)
-{
- CppEditor::CppEditorDocumentHandle *document = cppDocument(filePath);
-
- if (document) {
- auto &sendTracker = document->sendTracker();
- return sendTracker.shouldSendRevisionWithCompletionPosition(int(document->revision()),
- completionPosition);
- }
-
- return true;
-}
-
-bool shouldSendCodeCompletion(const QString &filePath,
- int completionPosition)
-{
- CppEditor::CppEditorDocumentHandle *document = cppDocument(filePath);
-
- if (document) {
- auto &sendTracker = document->sendTracker();
- return sendTracker.shouldSendCompletion(completionPosition);
- }
-
- return true;
-}
-
-void setLastDocumentRevision(const QString &filePath)
-{
- CppEditor::CppEditorDocumentHandle *document = cppDocument(filePath);
-
- if (document)
- document->sendTracker().setLastSentRevision(int(document->revision()));
-}
-
-void setLastCompletionPosition(const QString &filePath,
- int completionPosition)
-{
- CppEditor::CppEditorDocumentHandle *document = cppDocument(filePath);
-
- if (document)
- document->sendTracker().setLastCompletionPosition(completionPosition);
-}
-
-}
-
-ClangCompletionAssistProcessor::Position
-ClangCompletionAssistProcessor::extractLineColumn(int position)
-{
- if (position < 0)
- return {-1, -1};
-
- int line = -1, column = -1;
- Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column);
-
- column = clangColumn(m_interface->textDocument()->findBlock(position), column);
- return {line, column};
-}
-
-bool ClangCompletionAssistProcessor::sendCompletionRequest(int position,
- const QByteArray &customFileContent,
- int functionNameStartPosition)
-{
- const QString filePath = m_interface->filePath().toString();
-
- auto &communicator = m_interface->communicator();
-
- if (shouldSendCodeCompletion(filePath, position) || communicator.isNotWaitingForCompletion()) {
- if (shouldSendDocumentForCompletion(filePath, position)) {
- sendFileContent(customFileContent);
- setLastDocumentRevision(filePath);
- }
-
- const Position cursorPosition = extractLineColumn(position);
- const Position functionNameStart = extractLineColumn(functionNameStartPosition);
- communicator.requestCompletions(this,
- filePath,
- uint(cursorPosition.line),
- uint(cursorPosition.column),
- functionNameStart.line,
- functionNameStart.column);
- setLastCompletionPosition(filePath, position);
- if (m_sentRequestType == NormalCompletion) {
- if (!customFileContent.isEmpty())
- m_content = customFileContent;
- else if (const CppEditor::CppEditorDocumentHandle * const doc = cppDocument(filePath))
- m_content = doc->contents();
- m_position = position;
- }
- return true;
- }
-
- return false;
-}
-
-TextEditor::IAssistProposal *ClangCompletionAssistProcessor::createProposal()
-{
- m_requestSent = false;
- TextEditor::GenericProposalModelPtr model(new ClangAssistProposalModel());
- model->loadContent(m_completions);
- return new GenericProposal(m_positionForProposal, model);
-}
-
-IAssistProposal *ClangCompletionAssistProcessor::createFunctionHintProposal(
- const ClangBackEnd::CodeCompletions &completions)
-{
- m_requestSent = false;
- TextEditor::FunctionHintProposalModelPtr model(new ClangFunctionHintModel(completions));
- return new FunctionHintProposal(m_positionForProposal, model);
-}
-
-void ClangCompletionAssistProcessor::cancel()
-{
- m_interface->communicator().cancelCompletions(this);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h
deleted file mode 100644
index 1d67344cc86..00000000000
--- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangcompletionassistinterface.h"
-
-#include <cppeditor/cppcompletionassistprocessor.h>
-
-#include <clangsupport/codecompletion.h>
-
-#include <QCoreApplication>
-#include <QTextCursor>
-
-namespace TextEditor {
-class AssistInterface;
-class AssistProposalItemInterface;
-}
-
-namespace ClangCodeModel {
-namespace Internal {
-
-using ClangBackEnd::CodeCompletions;
-using ClangBackEnd::CompletionCorrection;
-
-class ClangCompletionAssistProcessor : public CppEditor::CppCompletionAssistProcessor
-{
- Q_DECLARE_TR_FUNCTIONS(ClangCodeModel::Internal::ClangCompletionAssistProcessor)
-
-public:
- ClangCompletionAssistProcessor();
- ~ClangCompletionAssistProcessor() override;
-
- static QList<TextEditor::AssistProposalItemInterface *> completeInclude(
- int position, unsigned completionOperator,
- const TextEditor::AssistInterface *interface,
- const ProjectExplorer::HeaderPaths &headerPaths);
-
- TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override;
-
- void handleAvailableCompletions(const CodeCompletions &completions);
- bool running() final { return m_requestSent; }
-
- const TextEditor::TextEditorWidget *textEditorWidget() const;
-
-private:
- void cancel() override;
- TextEditor::IAssistProposal *startCompletionHelper();
- int startOfOperator(int pos, unsigned *kind, bool wantFunctionCall) const;
- int findStartOfName(int pos = -1) const;
- bool accepts() const;
-
- TextEditor::IAssistProposal *createProposal();
- TextEditor::IAssistProposal *createFunctionHintProposal(
- const CodeCompletions &completions);
- QList<TextEditor::AssistProposalItemInterface *> toAssistProposalItems(
- const CodeCompletions &completions) const;
- static QList<TextEditor::AssistProposalItemInterface *> completeIncludePath(
- const QString &realPath, const QStringList &suffixes, unsigned completionOperator);
- bool completePreprocessorDirectives();
- bool completeDoxygenKeywords();
- void addCompletionItem(const QString &text,
- const QIcon &icon = QIcon(),
- int order = 0);
-
- struct UnsavedFileContentInfo {
- QByteArray unsavedContent;
- bool isDocumentModified = false;
- };
- UnsavedFileContentInfo unsavedFileContent(const QByteArray &customFileContent) const;
-
- void sendFileContent(const QByteArray &customFileContent);
- bool sendCompletionRequest(int position,
- const QByteArray &customFileContent,
- int functionNameStartPosition = -1);
-
- CodeCompletions applyCompletionFixIt(const CodeCompletions &completions);
-
-private:
- struct Position { int line; int column; };
- Position extractLineColumn(int position);
-
- QScopedPointer<const ClangCompletionAssistInterface> m_interface;
- unsigned m_completionOperator;
- enum CompletionRequestType { NormalCompletion, FunctionHintCompletion };
- CompletionRequestType m_sentRequestType = NormalCompletion;
- int m_position = -1;
- QByteArray m_content;
- bool m_requestSent = false;
- bool m_addSnippets = false; // For type == Type::NormalCompletion
- bool m_fallbackToNormalCompletion = true;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp b/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp
deleted file mode 100644
index c3c752f9569..00000000000
--- a/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcompletionassistprovider.h"
-
-#include "clangcompletionassistprocessor.h"
-#include "clangeditordocumentprocessor.h"
-#include "clangutils.h"
-
-#include <cplusplus/Token.h>
-#include <cppeditor/cppcompletionassistprocessor.h>
-#include <cppeditor/projectpart.h>
-
-#include <texteditor/codeassist/assistinterface.h>
-#include <texteditor/codeassist/iassistprocessor.h>
-#include <texteditor/codeassist/iassistprovider.h>
-#include <texteditor/texteditor.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-ClangCompletionAssistProvider::ClangCompletionAssistProvider(BackendCommunicator &communicator,
- CompletionType type)
- : m_communicator(communicator), m_type(type)
-{
-}
-
-TextEditor::IAssistProvider::RunType ClangCompletionAssistProvider::runType() const
-{
- return Asynchronous;
-}
-
-TextEditor::IAssistProcessor *ClangCompletionAssistProvider::createProcessor(
- const TextEditor::AssistInterface *) const
-{
- return new ClangCompletionAssistProcessor;
-}
-
-TextEditor::AssistInterface *ClangCompletionAssistProvider::createAssistInterface(
- const Utils::FilePath &filePath,
- const TextEditor::TextEditorWidget *textEditorWidget,
- const CPlusPlus::LanguageFeatures & /*languageFeatures*/,
- int position,
- TextEditor::AssistReason reason) const
-{
- const CppEditor::ProjectPart::ConstPtr projectPart = projectPartForFileBasedOnProcessor(
- filePath.toString());
- if (projectPart) {
- return new ClangCompletionAssistInterface(m_communicator,
- m_type,
- textEditorWidget,
- position,
- filePath,
- reason,
- projectPart->headerPaths,
- projectPart->languageFeatures);
- }
-
- return nullptr;
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprovider.h b/src/plugins/clangcodemodel/clangcompletionassistprovider.h
deleted file mode 100644
index c1bb5b6b87c..00000000000
--- a/src/plugins/clangcodemodel/clangcompletionassistprovider.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangbackendcommunicator.h"
-#include "clangcompletionassistinterface.h"
-
-#include <cppeditor/cppcompletionassistprovider.h>
-
-#include <texteditor/codeassist/assistinterface.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangCompletionAssistProvider : public CppEditor::CppCompletionAssistProvider
-{
- Q_OBJECT
-
-public:
- ClangCompletionAssistProvider(BackendCommunicator &communicator, CompletionType type);
-
- IAssistProvider::RunType runType() const override;
-
- TextEditor::IAssistProcessor *createProcessor(const TextEditor::AssistInterface *) const override;
- TextEditor::AssistInterface *createAssistInterface(
- const Utils::FilePath &filePath,
- const TextEditor::TextEditorWidget *textEditorWidget,
- const CPlusPlus::LanguageFeatures &languageFeatures,
- int position,
- TextEditor::AssistReason reason) const override;
-
-private:
- BackendCommunicator &m_communicator;
- CompletionType m_type;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
deleted file mode 100644
index ad5ee50476f..00000000000
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcompletionchunkstotextconverter.h"
-
-#include <QtGlobal>
-
-#include <algorithm>
-#include <functional>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-void CompletionChunksToTextConverter::parseChunks(
- const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks)
-{
- m_text.clear();
- m_placeholderPositions.clear();
-
- m_codeCompletionChunks = codeCompletionChunks;
-
- addExtraVerticalSpaceBetweenBraces();
-
- std::for_each(m_codeCompletionChunks.cbegin(),
- m_codeCompletionChunks.cend(),
- [this] (const ClangBackEnd::CodeCompletionChunk &chunk)
- {
- parseDependentOnTheOptionalState(chunk);
- m_previousCodeCompletionChunk = chunk;
- });
-}
-
-void CompletionChunksToTextConverter::setAddPlaceHolderText(bool addPlaceHolderText)
-{
- m_addPlaceHolderText = addPlaceHolderText;
-}
-
-void CompletionChunksToTextConverter::setAddPlaceHolderPositions(bool addPlaceHolderPositions)
-{
- m_addPlaceHolderPositions = addPlaceHolderPositions;
-}
-
-void CompletionChunksToTextConverter::setAddResultType(bool addResultType)
-{
- m_addResultType = addResultType;
-}
-
-void CompletionChunksToTextConverter::setAddSpaces(bool addSpaces)
-{
- m_addSpaces = addSpaces;
-}
-
-void CompletionChunksToTextConverter::setHonorVerticalSpace(bool honor)
-{
- m_honorVerticalSpace = honor;
-}
-
-void CompletionChunksToTextConverter::setAddExtraVerticalSpaceBetweenBraces(
- bool addExtraVerticalSpaceBetweenBraces)
-{
- m_addExtraVerticalSpaceBetweenBraces = addExtraVerticalSpaceBetweenBraces;
-}
-
-void CompletionChunksToTextConverter::setEmphasizeOptional(bool emphasizeOptional)
-{
- m_emphasizeOptional = emphasizeOptional;
-}
-
-void CompletionChunksToTextConverter::setAddOptional(bool addOptional)
-{
- m_addOptional = addOptional;
-}
-
-void CompletionChunksToTextConverter::setPlaceHolderToEmphasize(int placeHolderNumber)
-{
- m_placeHolderPositionToEmphasize = placeHolderNumber;
-}
-
-void CompletionChunksToTextConverter::setCompletionKind(const ClangBackEnd::CodeCompletion::Kind kind)
-{
- m_codeCompletionKind = kind;
-}
-
-void CompletionChunksToTextConverter::setupForKeywords()
-{
- setAddPlaceHolderPositions(true);
- setAddSpaces(true);
- setAddExtraVerticalSpaceBetweenBraces(true);
-}
-
-const QString &CompletionChunksToTextConverter::text() const
-{
- return m_text;
-}
-
-const std::vector<int> &CompletionChunksToTextConverter::placeholderPositions() const
-{
- return m_placeholderPositions;
-}
-
-bool CompletionChunksToTextConverter::hasPlaceholderPositions() const
-{
- return m_placeholderPositions.size() > 0;
-}
-
-QString CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(
- const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks,
- ClangBackEnd::CodeCompletion::Kind codeCompletionKind,
- int parameterToEmphasize)
-{
- CompletionChunksToTextConverter converter;
- converter.setAddPlaceHolderText(true);
- converter.setAddResultType(true);
-
- converter.setTextFormat(TextFormat::Html);
- converter.setAddOptional(true);
- converter.setEmphasizeOptional(true);
-
- converter.setAddPlaceHolderPositions(true);
- converter.setPlaceHolderToEmphasize(parameterToEmphasize);
- converter.setCompletionKind(codeCompletionKind);
-
- converter.parseChunks(codeCompletionChunks);
-
- return converter.text();
-}
-
-QString CompletionChunksToTextConverter::convertToName(
- const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks)
-{
- CompletionChunksToTextConverter converter;
-
- converter.setHonorVerticalSpace(false);
-
- converter.parseChunks(codeCompletionChunks);
-
- return converter.text();
-}
-
-QString CompletionChunksToTextConverter::convertToToolTipWithHtml(
- const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks,
- ClangBackEnd::CodeCompletion::Kind codeCompletionKind)
-{
- CompletionChunksToTextConverter converter;
- converter.setAddPlaceHolderText(true);
- converter.setAddSpaces(true);
- converter.setAddExtraVerticalSpaceBetweenBraces(true);
- converter.setAddOptional(true);
- converter.setTextFormat(TextFormat::Html);
- converter.setEmphasizeOptional(true);
- converter.setAddResultType(true);
- converter.setCompletionKind(codeCompletionKind);
-
- converter.parseChunks(codeCompletionChunks);
-
- return converter.text();
-}
-
-void CompletionChunksToTextConverter::parse(
- const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
-{
- using ClangBackEnd::CodeCompletionChunk;
-
- switch (codeCompletionChunk.kind) {
- case CodeCompletionChunk::ResultType: parseResultType(codeCompletionChunk.text); break;
- // Do not rely on CurrentParameter because it might be wrong for
- // invalid code. Instead, handle it as PlaceHolder.
- case CodeCompletionChunk::CurrentParameter:
- case CodeCompletionChunk::Placeholder:
- parsePlaceHolder(codeCompletionChunk); break;
- case CodeCompletionChunk::LeftParen: parseLeftParen(codeCompletionChunk); break;
- case CodeCompletionChunk::LeftBrace: parseLeftBrace(codeCompletionChunk); break;
- case CodeCompletionChunk::VerticalSpace:
- if (!m_honorVerticalSpace)
- break;
- Q_FALLTHROUGH();
- default: parseText(codeCompletionChunk.text); break;
- }
-}
-
-void CompletionChunksToTextConverter::parseDependentOnTheOptionalState(
- const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
-{
- wrapInCursiveTagIfOptional(codeCompletionChunk);
-
- if (isNotOptionalOrAddOptionals(codeCompletionChunk))
- parse(codeCompletionChunk);
-}
-
-void CompletionChunksToTextConverter::parseResultType(const Utf8String &resultTypeText)
-{
- if (m_addResultType)
- m_text += inDesiredTextFormat(resultTypeText) + QChar(QChar::Space);
-}
-
-void CompletionChunksToTextConverter::parseText(const Utf8String &text)
-{
- if (canAddSpace()
- && m_previousCodeCompletionChunk.kind == ClangBackEnd::CodeCompletionChunk::RightBrace) {
- m_text += QChar(QChar::Space);
- }
-
- m_text += inDesiredTextFormat(text);
-}
-
-void CompletionChunksToTextConverter::wrapInCursiveTagIfOptional(
- const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
-{
- if (m_addOptional) {
- if (m_emphasizeOptional && m_textFormat == TextFormat::Html) {
- if (!m_previousCodeCompletionChunk.isOptional && codeCompletionChunk.isOptional)
- m_text += QStringLiteral("<i>");
- else if (m_previousCodeCompletionChunk.isOptional && !codeCompletionChunk.isOptional)
- m_text += QStringLiteral("</i>");
- }
- }
-}
-
-void CompletionChunksToTextConverter::parsePlaceHolder(
- const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
-{
- if (m_addPlaceHolderText) {
- appendText(inDesiredTextFormat(codeCompletionChunk.text),
- emphasizeCurrentPlaceHolder());
- }
-
- if (m_addPlaceHolderPositions)
- m_placeholderPositions.push_back(m_text.size());
-}
-
-void CompletionChunksToTextConverter::parseLeftParen(
- const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
-{
- if (canAddSpace())
- m_text += QChar(QChar::Space);
- m_text += codeCompletionChunk.text.toString();
-}
-
-void CompletionChunksToTextConverter::parseLeftBrace(
- const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
-{
- if (canAddSpace())
- m_text += QChar(QChar::Space);
-
- m_text += codeCompletionChunk.text.toString();
-}
-
-void CompletionChunksToTextConverter::addExtraVerticalSpaceBetweenBraces()
-{
- if (m_addExtraVerticalSpaceBetweenBraces)
- addExtraVerticalSpaceBetweenBraces(m_codeCompletionChunks.begin());
-}
-
-void CompletionChunksToTextConverter::addExtraVerticalSpaceBetweenBraces(
- const ClangBackEnd::CodeCompletionChunks::iterator &begin)
-{
- using ClangBackEnd::CodeCompletionChunk;
-
- const auto leftBraceCompare = [] (const CodeCompletionChunk &chunk) {
- return chunk.kind == CodeCompletionChunk::LeftBrace;
- };
-
- const auto rightBraceCompare = [] (const CodeCompletionChunk &chunk) {
- return chunk.kind == CodeCompletionChunk::RightBrace;
- };
-
- const auto verticalSpaceCompare = [] (const CodeCompletionChunk &chunk) {
- return chunk.kind == CodeCompletionChunk::VerticalSpace;
- };
-
- auto leftBrace = std::find_if(begin, m_codeCompletionChunks.end(), leftBraceCompare);
-
- if (leftBrace != m_codeCompletionChunks.end()) {
- auto rightBrace = std::find_if(leftBrace, m_codeCompletionChunks.end(), rightBraceCompare);
-
- if (rightBrace != m_codeCompletionChunks.end()) {
- auto verticalSpaceCount = std::count_if(leftBrace, rightBrace, verticalSpaceCompare);
-
- if (verticalSpaceCount <= 1) {
- auto distance = std::distance(leftBrace, rightBrace);
- CodeCompletionChunk verticalSpaceChunck(CodeCompletionChunk::VerticalSpace,
- Utf8StringLiteral("\n"));
- auto verticalSpace = m_codeCompletionChunks.insert(std::next(leftBrace),
- verticalSpaceChunck);
- std::advance(verticalSpace, distance);
- rightBrace = verticalSpace;
- }
-
- auto begin = std::next(rightBrace);
-
- if (begin != m_codeCompletionChunks.end())
- addExtraVerticalSpaceBetweenBraces(begin);
- }
- }
-}
-
-QString CompletionChunksToTextConverter::inDesiredTextFormat(const Utf8String &text) const
-{
- if (m_textFormat == TextFormat::Html)
- return text.toString().toHtmlEscaped();
- else
- return text.toString();
-}
-
-bool CompletionChunksToTextConverter::emphasizeCurrentPlaceHolder() const
-{
- if (m_addPlaceHolderPositions) {
- const uint currentPlaceHolderPosition = uint(m_placeholderPositions.size() + 1);
- return uint(m_placeHolderPositionToEmphasize) == currentPlaceHolderPosition;
- }
-
- return false;
-}
-
-void CompletionChunksToTextConverter::setTextFormat(TextFormat textFormat)
-{
- m_textFormat = textFormat;
-}
-
-void CompletionChunksToTextConverter::appendText(const QString &text, bool boldFormat)
-{
- if (boldFormat && m_textFormat == TextFormat::Html)
- m_text += QStringLiteral("<b>") + text + QStringLiteral("</b>");
- else
- m_text += text;
-}
-
-bool CompletionChunksToTextConverter::canAddSpace() const
-{
- return m_addSpaces
- && m_previousCodeCompletionChunk.kind != ClangBackEnd::CodeCompletionChunk::HorizontalSpace
- && m_previousCodeCompletionChunk.kind != ClangBackEnd::CodeCompletionChunk::RightAngle
- && m_codeCompletionKind != ClangBackEnd::CodeCompletion::FunctionCompletionKind;
-}
-
-bool CompletionChunksToTextConverter::isNotOptionalOrAddOptionals(
- const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk) const
-{
- return !codeCompletionChunk.isOptional || m_addOptional;
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
-
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
deleted file mode 100644
index abb5609b0d3..00000000000
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport/codecompletion.h>
-
-#include <clangsupport/utf8string.h>
-
-#include <QString>
-
-#include <vector>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class CompletionChunksToTextConverter
-{
-public:
- void parseChunks(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks);
-
- enum class TextFormat {
- Plain,
- Html
- };
- void setTextFormat(TextFormat textFormat);
- void setAddPlaceHolderText(bool addPlaceHolderText);
- void setAddPlaceHolderPositions(bool addPlaceHolderPositions);
- void setAddResultType(bool addResultType);
- void setAddSpaces(bool addSpaces);
- void setHonorVerticalSpace(bool honor);
- void setAddExtraVerticalSpaceBetweenBraces(bool addExtraVerticalSpaceBetweenBraces);
- void setEmphasizeOptional(bool emphasizeOptional); // Only for Html format
- void setAddOptional(bool addOptional);
- void setPlaceHolderToEmphasize(int placeHolderNumber);
- void setCompletionKind(const ClangBackEnd::CodeCompletion::Kind kind);
-
- void setupForKeywords();
-
- const QString &text() const;
- const std::vector<int> &placeholderPositions() const;
- bool hasPlaceholderPositions() const;
-
- static QString convertToName(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks);
- static QString convertToKeywords(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks);
- static QString convertToToolTipWithHtml(
- const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks,
- ClangBackEnd::CodeCompletion::Kind codeCompletionKind);
- static QString convertToFunctionSignatureWithHtml(
- const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks,
- ClangBackEnd::CodeCompletion::Kind codeCompletionKind,
- int parameterToEmphasize = -1);
-
-private:
- void parse(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
- void parseDependentOnTheOptionalState(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
- void parseResultType(const Utf8String &text);
- void parseText(const Utf8String &text);
- void wrapInCursiveTagIfOptional(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
- void parsePlaceHolder(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
- void parseLeftParen(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
- void parseLeftBrace(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
- void addExtraVerticalSpaceBetweenBraces();
- void addExtraVerticalSpaceBetweenBraces(const ClangBackEnd::CodeCompletionChunks::iterator &);
-
- QString inDesiredTextFormat(const Utf8String &text) const;
- void appendText(const QString &text, bool boldFormat = false); // Boldness only in Html format
- bool canAddSpace() const;
- bool isNotOptionalOrAddOptionals(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk) const;
-
- bool emphasizeCurrentPlaceHolder() const;
-
-private:
- std::vector<int> m_placeholderPositions;
- ClangBackEnd::CodeCompletionChunks m_codeCompletionChunks;
- ClangBackEnd::CodeCompletionChunk m_previousCodeCompletionChunk;
- QString m_text;
- int m_placeHolderPositionToEmphasize = -1;
- TextFormat m_textFormat = TextFormat::Plain;
- ClangBackEnd::CodeCompletion::Kind m_codeCompletionKind = ClangBackEnd::CodeCompletion::Other;
- bool m_addPlaceHolderText = false;
- bool m_addPlaceHolderPositions = false;
- bool m_addResultType = false;
- bool m_addSpaces = false;
- bool m_honorVerticalSpace = true;
- bool m_addExtraVerticalSpaceBetweenBraces = false;
- bool m_emphasizeOptional = false;
- bool m_addOptional = false;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp
index 1cb2fcdf482..b0fe3c4fc5d 100644
--- a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp
+++ b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp
@@ -39,6 +39,7 @@
#include <QDebug>
#include <QTextBlock>
#include <QTextCursor>
+#include <QTextDocument>
using namespace CPlusPlus;
@@ -66,15 +67,6 @@ namespace ClangCodeModel {
namespace Internal {
ClangCompletionContextAnalyzer::ClangCompletionContextAnalyzer(
- const ClangCompletionAssistInterface *assistInterface,
- CPlusPlus::LanguageFeatures languageFeatures)
- : ClangCompletionContextAnalyzer(assistInterface->textDocument(), assistInterface->position(),
- assistInterface->type() == CompletionType::FunctionHint,
- languageFeatures)
-{
-}
-
-ClangCompletionContextAnalyzer::ClangCompletionContextAnalyzer(
QTextDocument *document, int position, bool isFunctionHint,
CPlusPlus::LanguageFeatures languageFeatures)
: m_document(document), m_position(position), m_isFunctionHint(isFunctionHint),
diff --git a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h
index 18cebdb36f3..53dbe8093e0 100644
--- a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h
+++ b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h
@@ -38,14 +38,9 @@ namespace TextEditor { class AssistInterface; }
namespace ClangCodeModel {
namespace Internal {
-class ClangCompletionAssistInterface;
-
class ClangCompletionContextAnalyzer
{
public:
- ClangCompletionContextAnalyzer() = delete;
- ClangCompletionContextAnalyzer(const ClangCompletionAssistInterface *assistInterface,
- CPlusPlus::LanguageFeatures languageFeatures);
ClangCompletionContextAnalyzer(QTextDocument *document, int position, bool isFunctionHint,
CPlusPlus::LanguageFeatures languageFeatures);
void analyze();
diff --git a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp b/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp
deleted file mode 100644
index 47b4803f894..00000000000
--- a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcurrentdocumentfilter.h"
-
-#include "clangeditordocumentprocessor.h"
-#include "clangutils.h"
-
-#include <clangsupport/tokeninfocontainer.h>
-
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/editormanager/ieditor.h>
-
-#include <cplusplus/Icons.h>
-
-#include <cppeditor/cppeditorconstants.h>
-
-#include <texteditor/textdocument.h>
-
-#include <utils/algorithm.h>
-#include <utils/fuzzymatcher.h>
-#include <utils/linecolumn.h>
-#include <utils/textutils.h>
-#include <utils/qtcassert.h>
-
-#include <QRegularExpression>
-
-using namespace Utils;
-
-namespace ClangCodeModel {
-namespace Internal {
-
-ClangCurrentDocumentFilter::ClangCurrentDocumentFilter()
-{
- setId(CppEditor::Constants::CURRENT_DOCUMENT_FILTER_ID);
- setDisplayName(CppEditor::Constants::CURRENT_DOCUMENT_FILTER_DISPLAY_NAME);
- setDefaultShortcutString(".");
- setPriority(High);
- setDefaultIncludedByDefault(false);
-
- Core::EditorManager *editorManager = Core::EditorManager::instance();
- connect(editorManager, &Core::EditorManager::currentEditorChanged,
- this, &ClangCurrentDocumentFilter::onCurrentEditorChanged);
- connect(editorManager, &Core::EditorManager::editorAboutToClose,
- this, &ClangCurrentDocumentFilter::onEditorAboutToClose);
-}
-
-static QString addType(const QString &signature, const ClangBackEnd::ExtraInfo &extraInfo)
-{
- return signature + QLatin1String(" -> ", 4) + extraInfo.typeSpelling.toString();
-}
-
-static Core::LocatorFilterEntry makeEntry(Core::ILocatorFilter *filter,
- const ClangBackEnd::TokenInfoContainer &info)
-{
- const ClangBackEnd::ExtraInfo &extraInfo = info.extraInfo;
- QString displayName = extraInfo.token;
- LineColumn lineColumn(info.line, info.column);
- Core::LocatorFilterEntry entry(filter, displayName, QVariant::fromValue(lineColumn));
- QString extra;
- ClangBackEnd::HighlightingType mainType = info.types.mainHighlightingType;
- if (mainType == ClangBackEnd::HighlightingType::VirtualFunction
- || mainType == ClangBackEnd::HighlightingType::Function
- || mainType == ClangBackEnd::HighlightingType::GlobalVariable
- || mainType == ClangBackEnd::HighlightingType::Field
- || mainType == ClangBackEnd::HighlightingType::QtProperty) {
- displayName = addType(displayName, extraInfo);
- extra = extraInfo.semanticParentTypeSpelling.toString();
- } else {
- extra = extraInfo.typeSpelling.toString();
- }
- entry.displayName = displayName;
- entry.extraInfo = extra;
- entry.displayIcon = CodeModelIcon::iconForType(iconTypeForToken(info));
- return entry;
-}
-
-void ClangCurrentDocumentFilter::prepareSearch(const QString &entry)
-{
- Q_UNUSED(entry)
- m_preparedPath = m_currentPath;
-}
-
-QList<Core::LocatorFilterEntry> ClangCurrentDocumentFilter::matchesFor(
- QFutureInterface<Core::LocatorFilterEntry> &, const QString &entry)
-{
- QList<Core::LocatorFilterEntry> goodEntries;
- if (m_preparedPath.isEmpty())
- return goodEntries;
-
- FuzzyMatcher::CaseSensitivity caseSesitivity = caseSensitivity(entry) == Qt::CaseSensitive
- ? FuzzyMatcher::CaseSensitivity::CaseSensitive
- : FuzzyMatcher::CaseSensitivity::CaseInsensitive;
- const QRegularExpression regexp = FuzzyMatcher::createRegExp(entry, caseSesitivity);
- if (!regexp.isValid())
- return goodEntries;
-
- ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(m_preparedPath);
- if (!processor)
- return goodEntries;
-
- using TokInfoContainer = ClangBackEnd::TokenInfoContainer;
- const QVector<TokInfoContainer> &infos = processor->tokenInfos();
-
- for (const TokInfoContainer &info : infos) {
- if (!info.isGlobalDeclaration())
- continue;
- QRegularExpressionMatch match = regexp.match(info.extraInfo.token);
- if (match.hasMatch())
- goodEntries.push_back(makeEntry(this, info));
- }
-
- return goodEntries;
-}
-
-void ClangCurrentDocumentFilter::accept(const Core::LocatorFilterEntry &selection,
- QString *, int *, int *) const
-{
- if (!m_currentEditor)
- return;
- auto lineColumn = qvariant_cast<LineColumn>(selection.internalData);
- Core::EditorManager::openEditorAt(
- {FilePath::fromString(m_currentPath), lineColumn.line, lineColumn.column - 1});
-}
-
-void ClangCurrentDocumentFilter::reset(Core::IEditor *newCurrent, const QString &path)
-{
- m_currentEditor = newCurrent;
- m_currentPath = path;
-}
-
-void ClangCurrentDocumentFilter::onEditorAboutToClose(Core::IEditor *editorAboutToClose)
-{
- if (!editorAboutToClose)
- return;
-
- if (m_currentEditor == editorAboutToClose)
- reset();
-}
-
-void ClangCurrentDocumentFilter::onCurrentEditorChanged(Core::IEditor *newCurrent)
-{
- if (newCurrent) {
- Core::IDocument *document = newCurrent->document();
- QTC_ASSERT(document, reset(); return);
- if (auto *textDocument = qobject_cast<TextEditor::TextDocument *>(document)) {
- reset(newCurrent, textDocument->filePath().toString());
- return;
- }
- }
- reset();
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.h b/src/plugins/clangcodemodel/clangcurrentdocumentfilter.h
deleted file mode 100644
index c60d20630f8..00000000000
--- a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <coreplugin/locator/ilocatorfilter.h>
-
-namespace Core { class IEditor; }
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangCurrentDocumentFilter : public Core::ILocatorFilter
-{
- Q_OBJECT
-
-public:
- explicit ClangCurrentDocumentFilter();
-
- void prepareSearch(const QString &entry) override;
- QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
- const QString &entry) override;
- void accept(const Core::LocatorFilterEntry &selection,
- QString *newText, int *selectionStart, int *selectionLength) const override;
-
-private:
- void onEditorAboutToClose(Core::IEditor *editors);
- void onCurrentEditorChanged(Core::IEditor *newCurrent);
-
- void reset(Core::IEditor *newCurrent = nullptr, const QString &path = QString());
-
- Core::IEditor *m_currentEditor = nullptr;
- QString m_currentPath;
- QString m_preparedPath;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangdast.cpp b/src/plugins/clangcodemodel/clangdast.cpp
new file mode 100644
index 00000000000..cc4f9708985
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdast.cpp
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangdast.h"
+
+#include <languageclient/client.h>
+#include <languageserverprotocol/jsonkeys.h>
+#include <languageserverprotocol/lsptypes.h>
+#include <utils/hostosinfo.h>
+#include <utils/filepath.h>
+
+#include <QStringView>
+
+using namespace Core;
+using namespace LanguageClient;
+using namespace LanguageServerProtocol;
+using namespace Utils;
+
+namespace ClangCodeModel::Internal {
+
+static constexpr char16_t roleKey[] = u"role";
+static constexpr char16_t arcanaKey[] = u"arcana";
+
+QString ClangdAstNode::role() const { return typedValue<QString>(roleKey); }
+QString ClangdAstNode::kind() const { return typedValue<QString>(kindKey); }
+optional<QString> ClangdAstNode::detail() const { return optionalValue<QString>(detailKey); }
+optional<QString> ClangdAstNode::arcana() const { return optionalValue<QString>(arcanaKey); }
+Range ClangdAstNode::range() const { return typedValue<Range>(rangeKey); }
+bool ClangdAstNode::hasRange() const { return contains(rangeKey); }
+bool ClangdAstNode::isValid() const { return contains(roleKey) && contains(kindKey); }
+
+optional<QList<ClangdAstNode> > ClangdAstNode::children() const
+{
+ return optionalArray<ClangdAstNode>(childrenKey);
+}
+
+bool ClangdAstNode::arcanaContains(const QString &s) const
+{
+ const optional<QString> arcanaString = arcana();
+ return arcanaString && arcanaString->contains(s);
+}
+
+bool ClangdAstNode::isFunction() const
+{
+ return role() == "declaration"
+ && (kind() == "Function" || kind() == "FunctionProto" || kind() == "CXXMethod");
+}
+
+bool ClangdAstNode::isMemberFunctionCall() const
+{
+ return role() == "expression" && (kind() == "CXXMemberCall"
+ || (kind() == "Member" && arcanaContains("member function")));
+}
+
+bool ClangdAstNode::isPureVirtualDeclaration() const
+{
+ return role() == "declaration" && kind() == "CXXMethod" && arcanaContains("virtual pure");
+}
+
+bool ClangdAstNode::isPureVirtualDefinition() const
+{
+ return role() == "declaration" && kind() == "CXXMethod" && arcanaContains("' pure");
+}
+
+bool ClangdAstNode::mightBeAmbiguousVirtualCall() const
+{
+ if (!isMemberFunctionCall())
+ return false;
+ bool hasBaseCast = false;
+ bool hasRecordType = false;
+ const QList<ClangdAstNode> childList = children().value_or(QList<ClangdAstNode>());
+ for (const ClangdAstNode &c : childList) {
+ if (!hasBaseCast && c.detailIs("UncheckedDerivedToBase"))
+ hasBaseCast = true;
+ if (!hasRecordType && c.role() == "specifier" && c.kind() == "TypeSpec")
+ hasRecordType = true;
+ if (hasBaseCast && hasRecordType)
+ return false;
+ }
+ return true;
+}
+
+bool ClangdAstNode::isTemplateParameterDeclaration() const
+{
+ return role() == "declaration" && (kind() == "TemplateTypeParm"
+ || kind() == "NonTypeTemplateParm");
+}
+
+QString ClangCodeModel::Internal::ClangdAstNode::type() const
+{
+ const optional<QString> arcanaString = arcana();
+ if (!arcanaString)
+ return {};
+ return typeFromPos(*arcanaString, 0);
+}
+
+QString ClangdAstNode::typeFromPos(const QString &s, int pos) const
+{
+ const int quote1Offset = s.indexOf('\'', pos);
+ if (quote1Offset == -1)
+ return {};
+ const int quote2Offset = s.indexOf('\'', quote1Offset + 1);
+ if (quote2Offset == -1)
+ return {};
+ if (s.mid(quote2Offset + 1, 2) == ":'")
+ return typeFromPos(s, quote2Offset + 2);
+ return s.mid(quote1Offset + 1, quote2Offset - quote1Offset - 1);
+}
+
+HelpItem::Category ClangdAstNode::qdocCategoryForDeclaration(HelpItem::Category fallback)
+{
+ const auto childList = children();
+ if (!childList || childList->size() < 2)
+ return fallback;
+ const ClangdAstNode c1 = childList->first();
+ if (c1.role() != "type" || c1.kind() != "Auto")
+ return fallback;
+ QList<ClangdAstNode> typeCandidates = {childList->at(1)};
+ while (!typeCandidates.isEmpty()) {
+ const ClangdAstNode n = typeCandidates.takeFirst();
+ if (n.role() == "type") {
+ if (n.kind() == "Enum")
+ return HelpItem::Enum;
+ if (n.kind() == "Record")
+ return HelpItem::ClassOrNamespace;
+ return fallback;
+ }
+ typeCandidates << n.children().value_or(QList<ClangdAstNode>());
+ }
+ return fallback;
+}
+
+bool ClangdAstNode::hasConstType() const
+{
+ QString theType = type();
+ if (theType.endsWith("const"))
+ theType.chop(5);
+
+ // We don't care about the "inner" type of templates.
+ const int openAngleBracketPos = theType.indexOf('<');
+ if (openAngleBracketPos != -1) {
+ const int closingAngleBracketPos = theType.lastIndexOf('>');
+ if (closingAngleBracketPos > openAngleBracketPos) {
+ theType = theType.left(openAngleBracketPos)
+ + theType.mid(closingAngleBracketPos + 1);
+ }
+ }
+ const int xrefCount = theType.count("&&");
+ const int refCount = theType.count('&') - 2 * xrefCount;
+ const int ptrRefCount = theType.count('*') + refCount;
+ const int constCount = theType.count("const");
+ if (ptrRefCount == 0)
+ return constCount > 0 || detailIs("LValueToRValue") || arcanaContains("xvalue");
+ return ptrRefCount <= constCount;
+}
+
+bool ClangdAstNode::childContainsRange(int index, const LanguageServerProtocol::Range &range) const
+{
+ const optional<QList<ClangdAstNode>> childList = children();
+ return childList && childList->size() > index && childList->at(index).range().contains(range);
+}
+
+bool ClangdAstNode::hasChildWithRole(const QString &role) const
+{
+ return Utils::contains(children().value_or(QList<ClangdAstNode>()),
+ [&role](const ClangdAstNode &c) { return c.role() == role; });
+}
+
+QString ClangdAstNode::operatorString() const
+{
+ if (kind() == "BinaryOperator")
+ return detail().value_or(QString());
+ QTC_ASSERT(kind() == "CXXOperatorCall", return {});
+ const optional<QString> arcanaString = arcana();
+ if (!arcanaString)
+ return {};
+ const int closingQuoteOffset = arcanaString->lastIndexOf('\'');
+ if (closingQuoteOffset <= 0)
+ return {};
+ const int openingQuoteOffset = arcanaString->lastIndexOf('\'', closingQuoteOffset - 1);
+ if (openingQuoteOffset == -1)
+ return {};
+ return arcanaString->mid(openingQuoteOffset + 1, closingQuoteOffset
+ - openingQuoteOffset - 1);
+}
+
+ClangdAstNode::FileStatus ClangdAstNode::fileStatus(const FilePath &thisFile) const
+{
+ const optional<QString> arcanaString = arcana();
+ if (!arcanaString)
+ return FileStatus::Unknown;
+
+ // Example arcanas:
+ // "FunctionDecl 0x7fffb5d0dbd0 </tmp/test.cpp:1:1, line:5:1> line:1:6 func 'void ()'"
+ // "VarDecl 0x7fffb5d0dcf0 </tmp/test.cpp:2:5, /tmp/test.h:1:1> /tmp/test.cpp:2:10 b 'bool' cinit"
+ // The second one is for a particularly silly construction where the RHS of an
+ // initialization comes from an included header.
+ const int openPos = arcanaString->indexOf('<');
+ if (openPos == -1)
+ return FileStatus::Unknown;
+ const int closePos = arcanaString->indexOf('>', openPos + 1);
+ if (closePos == -1)
+ return FileStatus::Unknown;
+ bool hasOurs = false;
+ bool hasOther = false;
+ for (int startPos = openPos + 1; startPos < closePos;) {
+ int colon1Pos = arcanaString->indexOf(':', startPos);
+ if (colon1Pos == -1 || colon1Pos > closePos)
+ break;
+ if (HostOsInfo::isWindowsHost())
+ colon1Pos = arcanaString->indexOf(':', colon1Pos + 1);
+ if (colon1Pos == -1 || colon1Pos > closePos)
+ break;
+ const int colon2Pos = arcanaString->indexOf(':', colon1Pos + 2);
+ if (colon2Pos == -1 || colon2Pos > closePos)
+ break;
+ const int line = subViewEnd(*arcanaString, colon1Pos + 1, colon2Pos).toInt();
+ if (line == 0)
+ break;
+ const QStringView fileOrLineString = subViewEnd(*arcanaString, startPos, colon1Pos);
+ if (fileOrLineString != QLatin1String("line")) {
+ if (FilePath::fromUserInput(fileOrLineString.toString()) == thisFile)
+ hasOurs = true;
+ else
+ hasOther = true;
+ }
+ const int commaPos = arcanaString->indexOf(',', colon2Pos + 2);
+ if (commaPos != -1)
+ startPos = commaPos + 2;
+ else
+ break;
+ }
+ if (hasOurs)
+ return hasOther ? FileStatus::Mixed : FileStatus::Ours;
+ return hasOther ? FileStatus::Foreign : FileStatus::Unknown;
+}
+
+void ClangdAstNode::print(int indent) const
+{
+ (qDebug().noquote() << QByteArray(indent, ' ')).quote() << role() << kind()
+ << detail().value_or(QString()) << arcana().value_or(QString()) << range();
+ for (const ClangdAstNode &c : children().value_or(QList<ClangdAstNode>()))
+ c.print(indent + 2);
+}
+
+QStringView subViewLen(const QString &s, qsizetype start, qsizetype length)
+{
+ if (start < 0 || length < 0 || start + length > s.length())
+ return {};
+ return QStringView(s).mid(start, length);
+}
+
+QStringView subViewEnd(const QString &s, qsizetype start, qsizetype end)
+{
+ return subViewLen(s, start, end - start);
+}
+
+class AstPathCollector
+{
+public:
+ AstPathCollector(const ClangdAstNode &root, const Range &range)
+ : m_root(root), m_range(range) {}
+
+ ClangdAstPath collectPath()
+ {
+ if (!m_root.isValid())
+ return {};
+ visitNode(m_root, true);
+ return m_done ? m_path : m_longestSubPath;
+ }
+
+private:
+ void visitNode(const ClangdAstNode &node, bool isRoot = false)
+ {
+ if (!isRoot && (!node.hasRange() || !node.range().contains(m_range)))
+ return;
+ m_path << node;
+
+ class PathDropper {
+ public:
+ PathDropper(AstPathCollector &collector) : m_collector(collector) {};
+ ~PathDropper() {
+ if (m_collector.m_done)
+ return;
+ if (m_collector.m_path.size() > m_collector.m_longestSubPath.size())
+ m_collector.m_longestSubPath = m_collector.m_path;
+ m_collector.m_path.removeLast();
+ }
+ private:
+ AstPathCollector &m_collector;
+ } pathDropper(*this);
+
+ // Still traverse the children, because they could have the same range.
+ if (node.range() == m_range)
+ m_done = true;
+
+ const auto children = node.children();
+ if (!children)
+ return;
+
+ QList<ClangdAstNode> childrenToCheck;
+ if (node.kind() == "Function" || node.role() == "expression") {
+ // Functions and expressions can contain implicit nodes that make the list unsorted.
+ // They cannot be ignored, as we need to consider them in certain contexts.
+ // Therefore, the binary search cannot be used here.
+ childrenToCheck = *children;
+ } else {
+ for (auto it = std::lower_bound(children->cbegin(), children->cend(), m_range,
+ leftOfRange);
+ it != children->cend() && !m_range.isLeftOf(it->range()); ++it) {
+ childrenToCheck << *it;
+ }
+ }
+
+ const bool wasDone = m_done;
+ for (const ClangdAstNode &child : qAsConst(childrenToCheck)) {
+ visitNode(child);
+ if (m_done && !wasDone)
+ break;
+ }
+ }
+
+ static bool leftOfRange(const ClangdAstNode &node, const Range &range)
+ {
+ // Class and struct nodes can contain implicit constructors, destructors and
+ // operators, which appear at the end of the list, but whose range is the same
+ // as the class name. Therefore, we must force them not to compare less to
+ // anything else.
+ return node.range().isLeftOf(range) && !node.arcanaContains(" implicit ");
+ };
+
+ const ClangdAstNode &m_root;
+ const Range &m_range;
+ ClangdAstPath m_path;
+ ClangdAstPath m_longestSubPath;
+ bool m_done = false;
+};
+
+ClangdAstPath getAstPath(const ClangdAstNode &root, const Range &range)
+{
+ return AstPathCollector(root, range).collectPath();
+}
+
+ClangdAstPath getAstPath(const ClangdAstNode &root, const Position &pos)
+{
+ return getAstPath(root, Range(pos, pos));
+}
+
+MessageId requestAst(Client *client, const FilePath &filePath, const Range range,
+ const AstHandler &handler)
+{
+ class AstParams : public JsonObject
+ {
+ public:
+ AstParams(const TextDocumentIdentifier &document, const Range &range = {})
+ {
+ setTextDocument(document);
+ if (range.isValid())
+ setRange(range);
+ }
+
+ using JsonObject::JsonObject;
+
+ // The open file to inspect.
+ TextDocumentIdentifier textDocument() const
+ { return typedValue<TextDocumentIdentifier>(textDocumentKey); }
+ void setTextDocument(const TextDocumentIdentifier &id) { insert(textDocumentKey, id); }
+
+ // The region of the source code whose AST is fetched. The highest-level node that entirely
+ // contains the range is returned.
+ optional<Range> range() const { return optionalValue<Range>(rangeKey); }
+ void setRange(const Range &range) { insert(rangeKey, range); }
+
+ bool isValid() const override { return contains(textDocumentKey); }
+ };
+
+ class AstRequest : public Request<ClangdAstNode, std::nullptr_t, AstParams>
+ {
+ public:
+ using Request::Request;
+ explicit AstRequest(const AstParams &params) : Request("textDocument/ast", params) {}
+ };
+
+ AstRequest request(AstParams(TextDocumentIdentifier(DocumentUri::fromFilePath(filePath)),
+ range));
+ request.setResponseCallback([handler, reqId = request.id()](AstRequest::Response response) {
+ const auto result = response.result();
+ handler(result ? *result : ClangdAstNode(), reqId);
+ });
+ client->sendMessage(request, Client::SendDocUpdates::Ignore);
+ return request.id();
+}
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/clangdast.h b/src/plugins/clangcodemodel/clangdast.h
new file mode 100644
index 00000000000..bd8d3a6f270
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdast.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <coreplugin/helpitem.h>
+#include <languageserverprotocol/jsonobject.h>
+
+#include <functional>
+
+namespace LanguageClient { class Client; }
+namespace LanguageServerProtocol {
+class MessageId;
+class Position;
+class Range;
+}
+namespace Utils { class FilePath; }
+
+QT_BEGIN_NAMESPACE
+class QStringView;
+QT_END_NAMESPACE
+
+namespace ClangCodeModel::Internal {
+
+// string view helpers
+QStringView subViewLen(const QString &s, qsizetype start, qsizetype length);
+QStringView subViewEnd(const QString &s, qsizetype start, qsizetype end);
+
+class ClangdAstNode : public LanguageServerProtocol::JsonObject
+{
+public:
+ using JsonObject::JsonObject;
+
+ // The general kind of node, such as “expressionâ€. Corresponds to clang’s base AST node type,
+ // such as Expr. The most common are “expressionâ€, “statementâ€, “type†and “declarationâ€.
+ QString role() const;
+
+ // The specific kind of node, such as “BinaryOperatorâ€. Corresponds to clang’s concrete
+ // node class, with Expr etc suffix dropped.
+ QString kind() const;
+
+ // Brief additional details, such as ‘||’. Information present here depends on the node kind.
+ Utils::optional<QString> detail() const;
+
+ // One line dump of information, similar to that printed by clang -Xclang -ast-dump.
+ // Only available for certain types of nodes.
+ Utils::optional<QString> arcana() const;
+
+ // The part of the code that produced this node. Missing for implicit nodes, nodes produced
+ // by macro expansion, etc.
+ LanguageServerProtocol::Range range() const;
+
+ // Descendants describing the internal structure. The tree of nodes is similar to that printed
+ // by clang -Xclang -ast-dump, or that traversed by clang::RecursiveASTVisitor.
+ Utils::optional<QList<ClangdAstNode>> children() const;
+
+ bool hasRange() const;
+ bool arcanaContains(const QString &s) const;
+ bool detailIs(const QString &s) const { return detail() && *detail() == s; }
+ bool isFunction() const;
+ bool isMemberFunctionCall() const;
+ bool isPureVirtualDeclaration() const;
+ bool isPureVirtualDefinition() const;
+ bool mightBeAmbiguousVirtualCall() const;
+ bool isNamespace() const { return role() == "declaration" && kind() == "Namespace"; }
+ bool isTemplateParameterDeclaration() const;;
+ QString type() const;
+ QString typeFromPos(const QString &s, int pos) const;
+ Core::HelpItem::Category qdocCategoryForDeclaration(Core::HelpItem::Category fallback);
+
+ // Returns true <=> the type is "recursively const".
+ // E.g. returns true for "const int &", "const int *" and "const int * const *",
+ // and false for "int &" and "const int **".
+ // For non-pointer types such as "int", we check whether they are used as lvalues
+ // or rvalues.
+ bool hasConstType() const;
+
+ bool childContainsRange(int index, const LanguageServerProtocol::Range &range) const;
+ bool hasChildWithRole(const QString &role) const;
+ QString operatorString() const;
+
+ enum class FileStatus { Ours, Foreign, Mixed, Unknown };
+ FileStatus fileStatus(const Utils::FilePath &thisFile) const;
+
+ // For debugging.
+ void print(int indent = 0) const;
+
+ bool isValid() const override;
+};
+using ClangdAstPath = QList<ClangdAstNode>;
+
+ClangdAstPath getAstPath(const ClangdAstNode &root, const LanguageServerProtocol::Range &range);
+ClangdAstPath getAstPath(const ClangdAstNode &root, const LanguageServerProtocol::Position &pos);
+
+using AstHandler = std::function<void(const ClangdAstNode &node,
+ const LanguageServerProtocol::MessageId &requestId)>;
+LanguageServerProtocol::MessageId requestAst(LanguageClient::Client *client,
+ const Utils::FilePath &filePath, const LanguageServerProtocol::Range range,
+ const AstHandler &handler);
+
+} // namespace ClangCodeModel::Internal
+
diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp
index b12c63c8591..9e828900a7c 100644
--- a/src/plugins/clangcodemodel/clangdclient.cpp
+++ b/src/plugins/clangcodemodel/clangdclient.cpp
@@ -25,16 +25,18 @@
#include "clangdclient.h"
-#include "clangcompletionassistprocessor.h"
#include "clangcompletioncontextanalyzer.h"
-#include "clangdiagnosticmanager.h"
-#include "clangdqpropertyhighlighter.h"
-#include "clangmodelmanagersupport.h"
+#include "clangconstants.h"
+#include "clangdast.h"
+#include "clangdfollowsymbol.h"
+#include "clangdlocatorfilters.h"
+#include "clangdswitchdecldef.h"
#include "clangpreprocessorassistproposalitem.h"
#include "clangtextmark.h"
#include "clangutils.h"
+#include "clangdsemantichighlighting.h"
+#include "tasktimers.h"
-#include <clangsupport/sourcelocationscontainer.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/searchresultitem.h>
#include <coreplugin/find/searchresultwindow.h>
@@ -51,16 +53,27 @@
#include <cppeditor/cppeditorwidget.h>
#include <cppeditor/cppfindreferences.h>
#include <cppeditor/cppmodelmanager.h>
+#include <cppeditor/cpprefactoringchanges.h>
#include <cppeditor/cpptoolsreuse.h>
#include <cppeditor/cppvirtualfunctionassistprovider.h>
#include <cppeditor/cppvirtualfunctionproposalitem.h>
#include <cppeditor/semantichighlighter.h>
+#include <cppeditor/cppsemanticinfo.h>
+#include <languageclient/diagnosticmanager.h>
+#include <languageclient/languageclientcompletionassist.h>
+#include <languageclient/languageclientfunctionhint.h>
+#include <languageclient/languageclienthoverhandler.h>
#include <languageclient/languageclientinterface.h>
#include <languageclient/languageclientmanager.h>
+#include <languageclient/languageclientquickfix.h>
+#include <languageclient/languageclientsymbolsupport.h>
#include <languageclient/languageclientutils.h>
+#include <languageserverprotocol/clientcapabilities.h>
+#include <languageserverprotocol/progresssupport.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/session.h>
+#include <projectexplorer/taskhub.h>
#include <texteditor/basefilefind.h>
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/iassistprocessor.h>
@@ -69,6 +82,7 @@
#include <texteditor/texteditorsettings.h>
#include <texteditor/texteditor.h>
#include <utils/algorithm.h>
+#include <utils/fileutils.h>
#include <utils/itemviews.h>
#include <utils/runextensions.h>
#include <utils/treemodel.h>
@@ -76,7 +90,6 @@
#include <QAction>
#include <QCheckBox>
-#include <QDateTime>
#include <QElapsedTimer>
#include <QFile>
#include <QHash>
@@ -87,7 +100,6 @@
#include <QRegularExpression>
#include <QVBoxLayout>
#include <QWidget>
-#include <QtConcurrent>
#include <cmath>
#include <set>
@@ -104,377 +116,14 @@ using namespace TextEditor;
namespace ClangCodeModel {
namespace Internal {
-static Q_LOGGING_CATEGORY(clangdLog, "qtc.clangcodemodel.clangd", QtWarningMsg);
+Q_LOGGING_CATEGORY(clangdLog, "qtc.clangcodemodel.clangd", QtWarningMsg);
+Q_LOGGING_CATEGORY(clangdLogAst, "qtc.clangcodemodel.clangd.ast", QtWarningMsg);
static Q_LOGGING_CATEGORY(clangdLogServer, "qtc.clangcodemodel.clangd.server", QtWarningMsg);
-static Q_LOGGING_CATEGORY(clangdLogAst, "qtc.clangcodemodel.clangd.ast", QtWarningMsg);
-static Q_LOGGING_CATEGORY(clangdLogHighlight, "qtc.clangcodemodel.clangd.highlight", QtWarningMsg);
-static Q_LOGGING_CATEGORY(clangdLogTiming, "qtc.clangcodemodel.clangd.timing", QtWarningMsg);
static Q_LOGGING_CATEGORY(clangdLogCompletion, "qtc.clangcodemodel.clangd.completion",
QtWarningMsg);
static QString indexingToken() { return "backgroundIndexProgress"; }
-static QStringView subViewLen(const QString &s, qsizetype start, qsizetype length)
-{
- if (start < 0 || length < 0 || start + length > s.length())
- return {};
- return QStringView(s).mid(start, length);
-}
-
-static QStringView subViewEnd(const QString &s, qsizetype start, qsizetype end)
-{
- return subViewLen(s, start, end - start);
-}
-
-class AstNode : public JsonObject
-{
-public:
- using JsonObject::JsonObject;
-
- static constexpr char roleKey[] = "role";
- static constexpr char arcanaKey[] = "arcana";
-
- // The general kind of node, such as “expressionâ€. Corresponds to clang’s base AST node type,
- // such as Expr. The most common are “expressionâ€, “statementâ€, “type†and “declarationâ€.
- QString role() const { return typedValue<QString>(roleKey); }
-
- // The specific kind of node, such as “BinaryOperatorâ€. Corresponds to clang’s concrete
- // node class, with Expr etc suffix dropped.
- QString kind() const { return typedValue<QString>(kindKey); }
-
- // Brief additional details, such as ‘||’. Information present here depends on the node kind.
- Utils::optional<QString> detail() const { return optionalValue<QString>(detailKey); }
-
- // One line dump of information, similar to that printed by clang -Xclang -ast-dump.
- // Only available for certain types of nodes.
- Utils::optional<QString> arcana() const { return optionalValue<QString>(arcanaKey); }
-
- // The part of the code that produced this node. Missing for implicit nodes, nodes produced
- // by macro expansion, etc.
- Range range() const { return typedValue<Range>(rangeKey); }
-
- // Descendants describing the internal structure. The tree of nodes is similar to that printed
- // by clang -Xclang -ast-dump, or that traversed by clang::RecursiveASTVisitor.
- Utils::optional<QList<AstNode>> children() const { return optionalArray<AstNode>(childrenKey); }
-
- bool hasRange() const { return contains(rangeKey); }
-
- bool arcanaContains(const QString &s) const
- {
- const Utils::optional<QString> arcanaString = arcana();
- return arcanaString && arcanaString->contains(s);
- }
-
- bool detailIs(const QString &s) const
- {
- return detail() && detail().value() == s;
- }
-
- bool isMemberFunctionCall() const
- {
- return role() == "expression" && (kind() == "CXXMemberCall"
- || (kind() == "Member" && arcanaContains("member function")));
- }
-
- bool isPureVirtualDeclaration() const
- {
- return role() == "declaration" && kind() == "CXXMethod" && arcanaContains("virtual pure");
- }
-
- bool isPureVirtualDefinition() const
- {
- return role() == "declaration" && kind() == "CXXMethod" && arcanaContains("' pure");
- }
-
- bool mightBeAmbiguousVirtualCall() const
- {
- if (!isMemberFunctionCall())
- return false;
- bool hasBaseCast = false;
- bool hasRecordType = false;
- const QList<AstNode> childList = children().value_or(QList<AstNode>());
- for (const AstNode &c : childList) {
- if (!hasBaseCast && c.detailIs("UncheckedDerivedToBase"))
- hasBaseCast = true;
- if (!hasRecordType && c.role() == "specifier" && c.kind() == "TypeSpec")
- hasRecordType = true;
- if (hasBaseCast && hasRecordType)
- return false;
- }
- return true;
- }
-
- bool isNamespace() const { return role() == "declaration" && kind() == "Namespace"; }
-
- bool isTemplateParameterDeclaration() const
- {
- return role() == "declaration" && (kind() == "TemplateTypeParm"
- || kind() == "NonTypeTemplateParm");
- };
-
- QString type() const
- {
- const Utils::optional<QString> arcanaString = arcana();
- if (!arcanaString)
- return {};
- return typeFromPos(*arcanaString, 0);
- }
-
- QString typeFromPos(const QString &s, int pos) const
- {
- const int quote1Offset = s.indexOf('\'', pos);
- if (quote1Offset == -1)
- return {};
- const int quote2Offset = s.indexOf('\'', quote1Offset + 1);
- if (quote2Offset == -1)
- return {};
- if (s.mid(quote2Offset + 1, 2) == ":'")
- return typeFromPos(s, quote2Offset + 2);
- return s.mid(quote1Offset + 1, quote2Offset - quote1Offset - 1);
- }
-
- HelpItem::Category qdocCategoryForDeclaration(HelpItem::Category fallback)
- {
- const auto childList = children();
- if (!childList || childList->size() < 2)
- return fallback;
- const AstNode c1 = childList->first();
- if (c1.role() != "type" || c1.kind() != "Auto")
- return fallback;
- QList<AstNode> typeCandidates = {childList->at(1)};
- while (!typeCandidates.isEmpty()) {
- const AstNode n = typeCandidates.takeFirst();
- if (n.role() == "type") {
- if (n.kind() == "Enum")
- return HelpItem::Enum;
- if (n.kind() == "Record")
- return HelpItem::ClassOrNamespace;
- return fallback;
- }
- typeCandidates << n.children().value_or(QList<AstNode>());
- }
- return fallback;
- }
-
- // Returns true <=> the type is "recursively const".
- // E.g. returns true for "const int &", "const int *" and "const int * const *",
- // and false for "int &" and "const int **".
- // For non-pointer types such as "int", we check whether they are uses as lvalues
- // or rvalues.
- bool hasConstType() const
- {
- QString theType = type();
- if (theType.endsWith("const"))
- theType.chop(5);
-
- // We don't care about the "inner" type of templates.
- const int openAngleBracketPos = theType.indexOf('<');
- if (openAngleBracketPos != -1) {
- const int closingAngleBracketPos = theType.lastIndexOf('>');
- if (closingAngleBracketPos > openAngleBracketPos) {
- theType = theType.left(openAngleBracketPos)
- + theType.mid(closingAngleBracketPos + 1);
- }
- }
- const int xrefCount = theType.count("&&");
- const int refCount = theType.count('&') - 2 * xrefCount;
- const int ptrRefCount = theType.count('*') + refCount;
- const int constCount = theType.count("const");
- if (ptrRefCount == 0)
- return constCount > 0 || detailIs("LValueToRValue") || arcanaContains("xvalue");
- return ptrRefCount <= constCount;
- }
-
- bool childContainsRange(int index, const Range &range) const
- {
- const Utils::optional<QList<AstNode>> childList = children();
- return childList && childList->size() > index
- && childList->at(index).range().contains(range);
- }
-
- bool hasChildWithRole(const QString &role) const
- {
- return Utils::contains(children().value_or(QList<AstNode>()), [&role](const AstNode &c) {
- return c.role() == role;
- });
- }
-
- QString operatorString() const
- {
- if (kind() == "BinaryOperator")
- return detail().value_or(QString());
- QTC_ASSERT(kind() == "CXXOperatorCall", return {});
- const Utils::optional<QString> arcanaString = arcana();
- if (!arcanaString)
- return {};
- const int closingQuoteOffset = arcanaString->lastIndexOf('\'');
- if (closingQuoteOffset <= 0)
- return {};
- const int openingQuoteOffset = arcanaString->lastIndexOf('\'', closingQuoteOffset - 1);
- if (openingQuoteOffset == -1)
- return {};
- return arcanaString->mid(openingQuoteOffset + 1, closingQuoteOffset
- - openingQuoteOffset - 1);
- }
-
- enum class FileStatus { Ours, Foreign, Mixed, Unknown };
- FileStatus fileStatus(const Utils::FilePath &thisFile) const
- {
- const Utils::optional<QString> arcanaString = arcana();
- if (!arcanaString)
- return FileStatus::Unknown;
-
- // Example arcanas:
- // "FunctionDecl 0x7fffb5d0dbd0 </tmp/test.cpp:1:1, line:5:1> line:1:6 func 'void ()'"
- // "VarDecl 0x7fffb5d0dcf0 </tmp/test.cpp:2:5, /tmp/test.h:1:1> /tmp/test.cpp:2:10 b 'bool' cinit"
- // The second one is for a particularly silly construction where the RHS of an
- // initialization comes from an included header.
- const int openPos = arcanaString->indexOf('<');
- if (openPos == -1)
- return FileStatus::Unknown;
- const int closePos = arcanaString->indexOf('>', openPos + 1);
- if (closePos == -1)
- return FileStatus::Unknown;
- bool hasOurs = false;
- bool hasOther = false;
- for (int startPos = openPos + 1; startPos < closePos;) {
- int colon1Pos = arcanaString->indexOf(':', startPos);
- if (colon1Pos == -1 || colon1Pos > closePos)
- break;
- if (Utils::HostOsInfo::isWindowsHost())
- colon1Pos = arcanaString->indexOf(':', colon1Pos + 1);
- if (colon1Pos == -1 || colon1Pos > closePos)
- break;
- const int colon2Pos = arcanaString->indexOf(':', colon1Pos + 2);
- if (colon2Pos == -1 || colon2Pos > closePos)
- break;
- const int line = subViewEnd(*arcanaString, colon1Pos + 1, colon2Pos).toString().toInt(); // TODO: Drop toString() once we require >= Qt 5.15
- if (line == 0)
- break;
- const QStringView fileOrLineString = subViewEnd(*arcanaString, startPos, colon1Pos);
- if (fileOrLineString != QLatin1String("line")) {
- if (Utils::FilePath::fromUserInput(fileOrLineString.toString()) == thisFile)
- hasOurs = true;
- else
- hasOther = true;
- }
- const int commaPos = arcanaString->indexOf(',', colon2Pos + 2);
- if (commaPos != -1)
- startPos = commaPos + 2;
- else
- break;
- }
- if (hasOurs)
- return hasOther ? FileStatus::Mixed : FileStatus::Ours;
- return hasOther ? FileStatus::Foreign : FileStatus::Unknown;
- }
-
- // For debugging.
- void print(int indent = 0) const
- {
- (qDebug().noquote() << QByteArray(indent, ' ')).quote() << role() << kind()
- << detail().value_or(QString()) << arcana().value_or(QString())
- << range();
- for (const AstNode &c : children().value_or(QList<AstNode>()))
- c.print(indent + 2);
- }
-
- bool isValid() const override
- {
- return contains(roleKey) && contains(kindKey);
- }
-};
-
-class AstPathCollector
-{
-public:
- AstPathCollector(const AstNode &root, const Range &range) : m_root(root), m_range(range) {}
-
- QList<AstNode> collectPath()
- {
- if (!m_root.isValid())
- return {};
- visitNode(m_root, true);
- return m_done ? m_path : m_longestSubPath;
- }
-
-private:
- void visitNode(const AstNode &node, bool isRoot = false)
- {
- if (!isRoot && (!node.hasRange() || !node.range().contains(m_range)))
- return;
- m_path << node;
-
- class PathDropper {
- public:
- PathDropper(AstPathCollector &collector) : m_collector(collector) {};
- ~PathDropper() {
- if (m_collector.m_done)
- return;
- if (m_collector.m_path.size() > m_collector.m_longestSubPath.size())
- m_collector.m_longestSubPath = m_collector.m_path;
- m_collector.m_path.removeLast();
- }
- private:
- AstPathCollector &m_collector;
- } pathDropper(*this);
-
- // Still traverse the children, because they could have the same range.
- if (node.range() == m_range)
- m_done = true;
-
- const auto children = node.children();
- if (!children)
- return;
-
- QList<AstNode> childrenToCheck;
- if (node.kind() == "Function" || node.role() == "expression") {
- // Functions and expressions can contain implicit nodes that make the list unsorted.
- // They cannot be ignored, as we need to consider them in certain contexts.
- // Therefore, the binary search cannot be used here.
- childrenToCheck = *children;
- } else {
- for (auto it = std::lower_bound(children->cbegin(), children->cend(), m_range,
- leftOfRange);
- it != children->cend() && !m_range.isLeftOf(it->range()); ++it) {
- childrenToCheck << *it;
- }
- }
-
- const bool wasDone = m_done;
- for (const AstNode &child : qAsConst(childrenToCheck)) {
- visitNode(child);
- if (m_done && !wasDone)
- break;
- }
- }
-
- static bool leftOfRange(const AstNode &node, const Range &range)
- {
- // Class and struct nodes can contain implicit constructors, destructors and
- // operators, which appear at the end of the list, but whose range is the same
- // as the class name. Therefore, we must force them not to compare less to
- // anything else.
- return node.range().isLeftOf(range) && !node.arcanaContains(" implicit ");
- };
-
- const AstNode &m_root;
- const Range &m_range;
- QList<AstNode> m_path;
- QList<AstNode> m_longestSubPath;
- bool m_done = false;
-};
-
-static QList<AstNode> getAstPath(const AstNode &root, const Range &range)
-{
- return AstPathCollector(root, range).collectPath();
-}
-
-static QList<AstNode> getAstPath(const AstNode &root, const Position &pos)
-{
- return getAstPath(root, Range(pos, pos));
-}
-
-static Usage::Type getUsageType(const QList<AstNode> &path)
+static Usage::Type getUsageType(const ClangdAstPath &path)
{
bool potentialWrite = false;
bool isFunction = false;
@@ -568,7 +217,7 @@ class SymbolDetails : public JsonObject
public:
using JsonObject::JsonObject;
- static constexpr char usrKey[] = "usr";
+ static constexpr char16_t usrKey[] = u"usr";
// the unqualified name of the symbol
QString name() const { return typedValue<QString>(nameKey); }
@@ -597,6 +246,25 @@ public:
: Request("textDocument/symbolInfo", params) {}
};
+void setupClangdConfigFile()
+{
+ const Utils::FilePath targetConfigFile = CppEditor::ClangdSettings::clangdUserConfigFilePath();
+ const Utils::FilePath baseDir = targetConfigFile.parentDir();
+ baseDir.ensureWritableDir();
+ Utils::FileReader configReader;
+ const QByteArray firstLine = "# This file was generated by Qt Creator and will be overwritten "
+ "unless you remove this line.";
+ if (!configReader.fetch(targetConfigFile) || configReader.data().startsWith(firstLine)) {
+ Utils::FileSaver saver(targetConfigFile);
+ saver.write(firstLine + '\n');
+ saver.write("Hover:\n");
+ saver.write(" ShowAKA: Yes\n");
+ saver.write("Diagnostics:\n");
+ saver.write(" UnusedIncludes: Strict\n");
+ QTC_CHECK(saver.finalize());
+ }
+}
+
static BaseClientInterface *clientInterface(Project *project, const Utils::FilePath &jsonDbDir)
{
QString indexingOption = "--background-index";
@@ -605,16 +273,20 @@ static BaseClientInterface *clientInterface(Project *project, const Utils::FileP
indexingOption += "=0";
const QString headerInsertionOption = QString("--header-insertion=")
+ (settings.autoIncludeHeaders() ? "iwyu" : "never");
+
+ bool ok = false;
+ const int userValue = qEnvironmentVariableIntValue("QTC_CLANGD_COMPLETION_RESULTS", &ok);
+ const QString limitResults = QString("--limit-results=%1").arg(ok ? userValue : 0);
+
Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, headerInsertionOption,
- "--limit-results=0", "--limit-references=0", "--clang-tidy=0"}};
+ limitResults, "--limit-references=0", "--clang-tidy=0"}};
if (settings.workerThreadLimit() != 0)
cmd.addArg("-j=" + QString::number(settings.workerThreadLimit()));
if (!jsonDbDir.isEmpty())
cmd.addArg("--compile-commands-dir=" + jsonDbDir.toString());
if (clangdLogServer().isDebugEnabled())
cmd.addArgs({"--log=verbose", "--pretty"});
- if (settings.clangdVersion() >= QVersionNumber(14))
- cmd.addArg("--use-dirty-headers");
+ cmd.addArg("--use-dirty-headers");
const auto interface = new StdIOClientInterface;
interface->setCommandLine(cmd);
return interface;
@@ -624,7 +296,7 @@ class ReferencesFileData {
public:
QList<QPair<Range, QString>> rangesAndLineText;
QString fileContent;
- AstNode ast;
+ ClangdAstNode ast;
};
class ReplacementData {
public:
@@ -643,167 +315,10 @@ public:
bool categorize = CppEditor::codeModelSettings()->categorizeFindReferences();
};
-using SymbolData = QPair<QString, Utils::Link>;
-using SymbolDataList = QList<SymbolData>;
-
-class ClangdClient::VirtualFunctionAssistProcessor : public IAssistProcessor
-{
-public:
- VirtualFunctionAssistProcessor(ClangdClient::Private *data) : m_data(data) {}
-
- void cancel() override;
- bool running() override { return m_data; }
-
- void update();
- void finalize();
- void resetData(bool resetFollowSymbolData);
-
-private:
- IAssistProposal *perform(const AssistInterface *) override
- {
- return nullptr;
- }
-
- IAssistProposal *immediateProposal(const AssistInterface *) override
- {
- return createProposal(false);
- }
-
- IAssistProposal *immediateProposalImpl() const;
- IAssistProposal *createProposal(bool final) const;
- CppEditor::VirtualFunctionProposalItem *createEntry(const QString &name,
- const Utils::Link &link) const;
-
- ClangdClient::Private *m_data = nullptr;
-};
-
-class ClangdClient::VirtualFunctionAssistProvider : public IAssistProvider
-{
-public:
- VirtualFunctionAssistProvider(ClangdClient::Private *data) : m_data(data) {}
-
-private:
- RunType runType() const override { return Asynchronous; }
- IAssistProcessor *createProcessor(const AssistInterface *) const override;
-
- ClangdClient::Private * const m_data;
-};
-
-class ClangdClient::FollowSymbolData {
-public:
- FollowSymbolData(ClangdClient *q, quint64 id, const QTextCursor &cursor,
- CppEditor::CppEditorWidget *editorWidget,
- const DocumentUri &uri, Utils::ProcessLinkCallback &&callback,
- bool openInSplit)
- : q(q), id(id), cursor(cursor), editorWidget(editorWidget), uri(uri),
- callback(std::move(callback)), virtualFuncAssistProvider(q->d),
- docRevision(editorWidget ? editorWidget->textDocument()->document()->revision() : -1),
- openInSplit(openInSplit) {}
-
- ~FollowSymbolData()
- {
- closeTempDocuments();
- if (virtualFuncAssistProcessor)
- virtualFuncAssistProcessor->resetData(false);
- for (const MessageId &id : qAsConst(pendingSymbolInfoRequests))
- q->cancelRequest(id);
- for (const MessageId &id : qAsConst(pendingGotoImplRequests))
- q->cancelRequest(id);
- for (const MessageId &id : qAsConst(pendingGotoDefRequests))
- q->cancelRequest(id);
- }
-
- void closeTempDocuments()
- {
- for (const Utils::FilePath &fp : qAsConst(openedFiles)) {
- if (!q->documentForFilePath(fp))
- q->closeExtraFile(fp);
- }
- openedFiles.clear();
- }
-
- bool defLinkIsAmbiguous() const;
-
- ClangdClient * const q;
- const quint64 id;
- const QTextCursor cursor;
- const QPointer<CppEditor::CppEditorWidget> editorWidget;
- const DocumentUri uri;
- const Utils::ProcessLinkCallback callback;
- VirtualFunctionAssistProvider virtualFuncAssistProvider;
- QList<MessageId> pendingSymbolInfoRequests;
- QList<MessageId> pendingGotoImplRequests;
- QList<MessageId> pendingGotoDefRequests;
- const int docRevision;
- const bool openInSplit;
-
- Utils::Link defLink;
- QList<Utils::Link> allLinks;
- QHash<Utils::Link, Utils::Link> declDefMap;
- Utils::optional<AstNode> cursorNode;
- AstNode defLinkNode;
- SymbolDataList symbolsToDisplay;
- std::set<Utils::FilePath> openedFiles;
- VirtualFunctionAssistProcessor *virtualFuncAssistProcessor = nullptr;
- bool finished = false;
-};
-
-class SwitchDeclDefData {
-public:
- SwitchDeclDefData(quint64 id, TextDocument *doc, const QTextCursor &cursor,
- CppEditor::CppEditorWidget *editorWidget,
- Utils::ProcessLinkCallback &&callback)
- : id(id), document(doc), uri(DocumentUri::fromFilePath(doc->filePath())),
- cursor(cursor), editorWidget(editorWidget), callback(std::move(callback)) {}
-
- Utils::optional<AstNode> getFunctionNode() const
- {
- QTC_ASSERT(ast, return {});
-
- const QList<AstNode> path = getAstPath(*ast, Range(cursor));
- for (auto it = path.rbegin(); it != path.rend(); ++it) {
- if (it->role() == "declaration"
- && (it->kind() == "CXXMethod" || it->kind() == "CXXConversion"
- || it->kind() == "CXXConstructor" || it->kind() == "CXXDestructor")) {
- return *it;
- }
- }
- return {};
- }
-
- QTextCursor cursorForFunctionName(const AstNode &functionNode) const
- {
- QTC_ASSERT(docSymbols, return {});
-
- const auto symbolList = Utils::get_if<QList<DocumentSymbol>>(&*docSymbols);
- if (!symbolList)
- return {};
- const Range &astRange = functionNode.range();
- QList symbolsToCheck = *symbolList;
- while (!symbolsToCheck.isEmpty()) {
- const DocumentSymbol symbol = symbolsToCheck.takeFirst();
- if (symbol.range() == astRange)
- return symbol.selectionRange().start().toTextCursor(document->document());
- if (symbol.range().contains(astRange))
- symbolsToCheck << symbol.children().value_or(QList<DocumentSymbol>());
- }
- return {};
- }
-
- const quint64 id;
- const QPointer<TextDocument> document;
- const DocumentUri uri;
- const QTextCursor cursor;
- const QPointer<CppEditor::CppEditorWidget> editorWidget;
- Utils::ProcessLinkCallback callback;
- Utils::optional<DocumentSymbolsResult> docSymbols;
- Utils::optional<AstNode> ast;
-};
-
class LocalRefsData {
public:
LocalRefsData(quint64 id, TextDocument *doc, const QTextCursor &cursor,
- CppEditor::RefactoringEngineInterface::RenameCallback &&callback)
+ CppEditor::RenameCallback &&callback)
: id(id), document(doc), cursor(cursor), callback(std::move(callback)),
uri(DocumentUri::fromFilePath(doc->filePath())), revision(doc->document()->revision())
{}
@@ -817,7 +332,7 @@ public:
const quint64 id;
const QPointer<TextDocument> document;
const QTextCursor cursor;
- CppEditor::RefactoringEngineInterface::RenameCallback callback;
+ CppEditor::RenameCallback callback;
const DocumentUri uri;
const int revision;
};
@@ -826,8 +341,8 @@ class DiagnosticsCapabilities : public JsonObject
{
public:
using JsonObject::JsonObject;
- void enableCategorySupport() { insert("categorySupport", true); }
- void enableCodeActionsInline() {insert("codeActionsInline", true);}
+ void enableCategorySupport() { insert(u"categorySupport", true); }
+ void enableCodeActionsInline() {insert(u"codeActionsInline", true);}
};
class ClangdTextDocumentClientCapabilities : public TextDocumentClientCapabilities
@@ -837,7 +352,7 @@ public:
void setPublishDiagnostics(const DiagnosticsCapabilities &caps)
- { insert("publishDiagnostics", caps); }
+ { insert(u"publishDiagnostics", caps); }
};
@@ -881,8 +396,7 @@ private:
= projectPartForFile(interface->filePath().toString());
if (projectPart)
headerPaths = projectPart->headerPaths;
- completions = ClangCompletionAssistProcessor::completeInclude(
- m_endPos, m_completionOperator, interface, headerPaths);
+ completions = completeInclude(m_endPos, m_completionOperator, interface, headerPaths);
break;
}
}
@@ -905,6 +419,107 @@ private:
return item;
}
+ /**
+ * @brief Creates completion proposals for #include and given cursor
+ * @param position - cursor placed after opening bracked or quote
+ * @param completionOperator - the type of token
+ * @param interface - relevant document data
+ * @param headerPaths - the include paths
+ * @return the list of completion items
+ */
+ static QList<AssistProposalItemInterface *> completeInclude(
+ int position, unsigned completionOperator, const TextEditor::AssistInterface *interface,
+ const ProjectExplorer::HeaderPaths &headerPaths)
+ {
+ QTextCursor cursor(interface->textDocument());
+ cursor.setPosition(position);
+ QString directoryPrefix;
+ if (completionOperator == T_SLASH) {
+ QTextCursor c = cursor;
+ c.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
+ QString sel = c.selectedText();
+ int startCharPos = sel.indexOf(QLatin1Char('"'));
+ if (startCharPos == -1) {
+ startCharPos = sel.indexOf(QLatin1Char('<'));
+ completionOperator = T_ANGLE_STRING_LITERAL;
+ } else {
+ completionOperator = T_STRING_LITERAL;
+ }
+ if (startCharPos != -1)
+ directoryPrefix = sel.mid(startCharPos + 1, sel.length() - 1);
+ }
+
+ // Make completion for all relevant includes
+ ProjectExplorer::HeaderPaths allHeaderPaths = headerPaths;
+ const auto currentFilePath = ProjectExplorer::HeaderPath::makeUser(
+ interface->filePath().toFileInfo().path());
+ if (!allHeaderPaths.contains(currentFilePath))
+ allHeaderPaths.append(currentFilePath);
+
+ const ::Utils::MimeType mimeType = ::Utils::mimeTypeForName("text/x-c++hdr");
+ const QStringList suffixes = mimeType.suffixes();
+
+ QList<AssistProposalItemInterface *> completions;
+ for (const ProjectExplorer::HeaderPath &headerPath : qAsConst(allHeaderPaths)) {
+ QString realPath = headerPath.path;
+ if (!directoryPrefix.isEmpty()) {
+ realPath += QLatin1Char('/');
+ realPath += directoryPrefix;
+ if (headerPath.type == ProjectExplorer::HeaderPathType::Framework)
+ realPath += QLatin1String(".framework/Headers");
+ }
+ completions << completeIncludePath(realPath, suffixes, completionOperator);
+ }
+
+ QList<QPair<AssistProposalItemInterface *, QString>> completionsForSorting;
+ for (AssistProposalItemInterface * const item : qAsConst(completions)) {
+ QString s = item->text();
+ s.replace('/', QChar(0)); // The dir separator should compare less than anything else.
+ completionsForSorting << qMakePair(item, s);
+ }
+ Utils::sort(completionsForSorting, [](const auto &left, const auto &right) {
+ return left.second < right.second;
+ });
+ for (int i = 0; i < completionsForSorting.count(); ++i)
+ completions[i] = completionsForSorting[i].first;
+
+ return completions;
+ }
+
+ /**
+ * @brief Finds #include completion proposals using given include path
+ * @param realPath - one of directories where compiler searches includes
+ * @param suffixes - file suffixes for C/C++ header files
+ * @return a list of matching completion items
+ */
+ static QList<AssistProposalItemInterface *> completeIncludePath(
+ const QString &realPath, const QStringList &suffixes, unsigned completionOperator)
+ {
+ QList<AssistProposalItemInterface *> completions;
+ QDirIterator i(realPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+ //: Parent folder for proposed #include completion
+ const QString hint = ClangdClient::tr("Location: %1")
+ .arg(QDir::toNativeSeparators(QDir::cleanPath(realPath)));
+ while (i.hasNext()) {
+ const QString fileName = i.next();
+ const QFileInfo fileInfo = i.fileInfo();
+ const QString suffix = fileInfo.suffix();
+ if (suffix.isEmpty() || suffixes.contains(suffix)) {
+ QString text = fileName.mid(realPath.length() + 1);
+ if (fileInfo.isDir())
+ text += QLatin1Char('/');
+
+ auto *item = new ClangPreprocessorAssistProposalItem;
+ item->setText(text);
+ item->setDetail(hint);
+ item->setIcon(CPlusPlus::Icons::keywordIcon());
+ item->setCompletionOperator(completionOperator);
+ completions.append(item);
+ }
+ }
+ return completions;
+ }
+
ClangdClient * const m_client;
const int m_position;
const int m_endPos;
@@ -963,121 +578,6 @@ private:
std::unordered_map<DocType, VersionedDocData<DocType, DataType>> m_data;
};
-class TaskTimer
-{
-public:
- TaskTimer(const QString &task) : m_task(task) {}
-
- void stopTask()
- {
- // This can happen due to the RAII mechanism employed with SubtaskTimer.
- // The subtask timers will expire immediately after, so this does not distort
- // the timing data.
- if (m_subtasks > 0) {
- QTC_CHECK(m_timer.isValid());
- m_elapsedMs += m_timer.elapsed();
- m_timer.invalidate();
- m_subtasks = 0;
- }
- m_started = false;
- qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": took " << m_elapsedMs
- << " ms in UI thread";
- m_elapsedMs = 0;
- }
- void startSubtask()
- {
- // We have some callbacks that are either synchronous or asynchronous, depending on
- // dynamic conditions. In the sync case, we will have nested subtasks, in which case
- // the inner ones must not collect timing data, as their code blocks are already covered.
- if (++m_subtasks > 1)
- return;
- if (!m_started) {
- QTC_ASSERT(m_elapsedMs == 0, m_elapsedMs = 0);
- m_started = true;
- m_finalized = false;
- qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": starting";
-
- // Used by ThreadedSubtaskTimer to mark the end of the whole highlighting operation
- m_startTimer.restart();
- }
- qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": subtask started at "
- << QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz");
- QTC_CHECK(!m_timer.isValid());
- m_timer.start();
- }
- void stopSubtask(bool isFinalizing)
- {
- if (m_subtasks == 0) // See stopTask().
- return;
- if (isFinalizing)
- m_finalized = true;
- if (--m_subtasks > 0) // See startSubtask().
- return;
- qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": subtask stopped at "
- << QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz");
- QTC_CHECK(m_timer.isValid());
- m_elapsedMs += m_timer.elapsed();
- m_timer.invalidate();
- if (m_finalized)
- stopTask();
- }
-
- QElapsedTimer startTimer() const { return m_startTimer; }
-
-private:
- const QString m_task;
- QElapsedTimer m_timer;
- QElapsedTimer m_startTimer;
- qint64 m_elapsedMs = 0;
- int m_subtasks = 0;
- bool m_started = false;
- bool m_finalized = false;
-};
-
-class SubtaskTimer
-{
-public:
- SubtaskTimer(TaskTimer &timer) : m_timer(timer) { m_timer.startSubtask(); }
- ~SubtaskTimer() { m_timer.stopSubtask(m_isFinalizing); }
-
-protected:
- void makeFinalizing() { m_isFinalizing = true; }
-
-private:
- TaskTimer &m_timer;
- bool m_isFinalizing = false;
-};
-
-class FinalizingSubtaskTimer : public SubtaskTimer
-{
-public:
- FinalizingSubtaskTimer(TaskTimer &timer) : SubtaskTimer(timer) { makeFinalizing(); }
-};
-
-class ThreadedSubtaskTimer
-{
-public:
- ThreadedSubtaskTimer(const QString &task, const TaskTimer &taskTimer) : m_task(task), m_taskTimer(taskTimer)
- {
- qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": starting thread";
- m_timer.start();
- }
-
- ~ThreadedSubtaskTimer()
- {
- qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": took " << m_timer.elapsed()
- << " ms in dedicated thread";
-
- qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": Start to end: "
- << m_taskTimer.startTimer().elapsed() << " ms";
- }
-
-private:
- const QString m_task;
- QElapsedTimer m_timer;
- const TaskTimer &m_taskTimer;
-};
-
class MemoryTreeModel;
class MemoryUsageWidget : public QWidget
{
@@ -1096,6 +596,20 @@ private:
Utils::optional<MessageId> m_currentRequest;
};
+class HighlightingData
+{
+public:
+ // For all QPairs, the int member is the corresponding document version.
+ QPair<QList<ExpandedSemanticToken>, int> previousTokens;
+
+ // The ranges of symbols referring to virtual functions,
+ // as extracted by the highlighting procedure.
+ QPair<QList<Range>, int> virtualRanges;
+
+ // The highlighter is owned by its document.
+ CppEditor::SemanticHighlighter *highlighter = nullptr;
+};
+
class ClangdClient::Private
{
public:
@@ -1116,13 +630,10 @@ public:
void reportAllSearchResultsAndFinish(ReferencesData &data);
void finishSearch(const ReferencesData &refData, bool canceled);
- void handleGotoDefinitionResult();
- void sendGotoImplementationRequest(const Utils::Link &link);
- void handleGotoImplementationResult(const GotoImplementationRequest::Response &response);
- void handleDocumentInfoResults();
-
void handleDeclDefSwitchReplies();
+ Utils::optional<QString> getContainingFunctionName(const ClangdAstPath &astPath, const Range& range);
+
static CppEditor::CppEditorWidget *widgetFromDocument(const TextDocument *doc);
QString searchTermFromCursor(const QTextCursor &cursor) const;
QTextCursor adjustedCursor(const QTextCursor &cursor, const TextDocument *doc);
@@ -1134,32 +645,23 @@ public:
void handleSemanticTokens(TextDocument *doc, const QList<ExpandedSemanticToken> &tokens,
int version, bool force);
- enum class AstCallbackMode { SyncIfPossible, AlwaysAsync };
- using TextDocOrFile = const Utils::variant<const TextDocument *, Utils::FilePath>;
- using AstHandler = const std::function<void(const AstNode &ast, const MessageId &)>;
- MessageId getAndHandleAst(TextDocOrFile &doc, AstHandler &astHandler,
+ MessageId getAndHandleAst(const TextDocOrFile &doc, const AstHandler &astHandler,
AstCallbackMode callbackMode, const Range &range = {});
ClangdClient * const q;
const CppEditor::ClangdSettings::Data settings;
QHash<quint64, ReferencesData> runningFindUsages;
- Utils::optional<FollowSymbolData> followSymbolData;
- Utils::optional<SwitchDeclDefData> switchDeclDefData;
+ ClangdFollowSymbol *followSymbol = nullptr;
+ ClangdSwitchDeclDef *switchDeclDef = nullptr;
Utils::optional<LocalRefsData> localRefsData;
Utils::optional<QVersionNumber> versionNumber;
- // The highlighters are owned by their respective documents.
- std::unordered_map<TextDocument *, CppEditor::SemanticHighlighter *> highlighters;
-
- QHash<TextDocument *, QPair<QList<ExpandedSemanticToken>, int>> previousTokens;
+ QHash<TextDocument *, HighlightingData> highlightingData;
QHash<Utils::FilePath, CppEditor::BaseEditorDocumentParser::Configuration> parserConfigs;
+ QHash<Utils::FilePath, Tasks> issuePaneEntries;
- // The ranges of symbols referring to virtual functions, with document version,
- // as extracted by the highlighting procedure.
- QHash<TextDocument *, QPair<QList<Range>, int>> virtualRanges;
-
- VersionedDataCache<const TextDocument *, AstNode> astCache;
- VersionedDataCache<Utils::FilePath, AstNode> externalAstCache;
+ VersionedDataCache<const TextDocument *, ClangdAstNode> astCache;
+ VersionedDataCache<Utils::FilePath, ClangdAstNode> externalAstCache;
TaskTimer highlightingTimer{"highlighting"};
quint64 nextJobId = 0;
bool isFullyIndexed = false;
@@ -1172,7 +674,7 @@ public:
explicit ClangdCompletionCapabilities(const JsonObject &object)
: TextDocumentClientCapabilities::CompletionCapabilities(object)
{
- insert("editsNearCursor", true); // For dot-to-arrow correction.
+ insert(u"editsNearCursor", true); // For dot-to-arrow correction.
if (Utils::optional<CompletionItemCapbilities> completionItemCaps = completionItem()) {
completionItemCaps->setSnippetSupport(false);
setCompletionItem(*completionItemCaps);
@@ -1192,6 +694,7 @@ public:
private:
QIcon icon() const override;
+ QString text() const override;
};
class ClangdClient::ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor
@@ -1253,9 +756,8 @@ ClangdClient::ClangdCompletionAssistProcessor::generateCompletionItems(
return itemGenerator(items);
const QString content = doc->toPlainText();
const bool requiresSignal = CppEditor::CppModelManager::instance()
- ->positionRequiresSignal(filePath().toString(),
- content.toUtf8(),
- pos);
+ ->getSignalSlotType(filePath().toString(), content.toUtf8(), pos)
+ == CppEditor::SignalSlotType::NewStyleSignal;
if (requiresSignal)
return itemGenerator(Utils::filtered(items, criterion));
return itemGenerator(items);
@@ -1278,6 +780,99 @@ private:
ClangdClient * const m_client;
};
+class ClangdQuickFixProcessor : public LanguageClientQuickFixAssistProcessor
+{
+public:
+ ClangdQuickFixProcessor(LanguageClient::Client *client)
+ : LanguageClientQuickFixAssistProcessor(client)
+ {
+ }
+
+private:
+ IAssistProposal *perform(const AssistInterface *interface) override
+ {
+ m_interface = interface;
+
+ // Step 1: Collect clangd code actions asynchronously
+ LanguageClientQuickFixAssistProcessor::perform(interface);
+
+ // Step 2: Collect built-in quickfixes synchronously
+ m_builtinOps = CppEditor::quickFixOperations(interface);
+
+ return nullptr;
+ }
+
+ TextEditor::GenericProposal *handleCodeActionResult(const CodeActionResult &result) override
+ {
+ auto toOperation =
+ [=](const Utils::variant<Command, CodeAction> &item) -> QuickFixOperation * {
+ if (auto action = Utils::get_if<CodeAction>(&item)) {
+ const Utils::optional<QList<Diagnostic>> diagnostics = action->diagnostics();
+ if (!diagnostics.has_value() || diagnostics->isEmpty())
+ return new CodeActionQuickFixOperation(*action, client());
+ }
+ if (auto command = Utils::get_if<Command>(&item))
+ return new CommandQuickFixOperation(*command, client());
+ return nullptr;
+ };
+
+ if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&result)) {
+ QuickFixOperations ops;
+ for (const Utils::variant<Command, CodeAction> &item : *list) {
+ if (QuickFixOperation *op = toOperation(item)) {
+ op->setDescription("clangd: " + op->description());
+ ops << op;
+ }
+ }
+ return GenericProposal::createProposal(m_interface, ops + m_builtinOps);
+ }
+ return nullptr;
+ }
+
+ QuickFixOperations m_builtinOps;
+ const AssistInterface *m_interface = nullptr;
+};
+
+class ClangdQuickFixProvider : public LanguageClientQuickFixProvider
+{
+public:
+ ClangdQuickFixProvider(ClangdClient *client) : LanguageClientQuickFixProvider(client) {};
+
+private:
+ IAssistProcessor *createProcessor(const TextEditor::AssistInterface *) const override
+ {
+ return new ClangdQuickFixProcessor(client());
+ }
+};
+
+static void addToCompilationDb(QJsonObject &cdb,
+ const CppEditor::ProjectPart &projectPart,
+ CppEditor::UsePrecompiledHeaders usePch,
+ const QJsonArray &projectPartOptions,
+ const Utils::FilePath &workingDir,
+ const CppEditor::ProjectFile &sourceFile,
+ bool clStyle)
+{
+ QJsonArray args = clangOptionsForFile(sourceFile, projectPart, projectPartOptions, usePch,
+ clStyle);
+
+ // TODO: clangd seems to apply some heuristics depending on what we put here.
+ // Should we make use of them or keep using our own?
+ args.prepend("clang");
+
+ const QString fileString = Utils::FilePath::fromString(sourceFile.path).toUserOutput();
+ args.append(fileString);
+ QJsonObject value;
+ value.insert("workingDirectory", workingDir.toString());
+ value.insert("compilationCommand", args);
+ cdb.insert(fileString, value);
+}
+
+static void addCompilationDb(QJsonObject &parentObject, const QJsonObject &cdb)
+{
+ parentObject.insert("compilationDatabaseChanges", cdb);
+}
+
ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
: Client(clientInterface(project, jsonDbDir)), d(new Private(this, project))
{
@@ -1289,12 +884,21 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
setActivateDocumentAutomatically(true);
setLogTarget(LogTarget::Console);
setCompletionAssistProvider(new ClangdCompletionAssistProvider(this));
+ setQuickFixAssistProvider(new ClangdQuickFixProvider(this));
if (!project) {
QJsonObject initOptions;
- const QStringList clangOptions = createClangOptions(
- *CppEditor::CppModelManager::instance()->fallbackProjectPart(), {},
- warningsConfigForProject(nullptr), optionsForProject(nullptr));
- initOptions.insert("fallbackFlags", QJsonArray::fromStringList(clangOptions));
+ const Utils::FilePath includeDir
+ = CppEditor::ClangdSettings(d->settings).clangdIncludePath();
+ CppEditor::CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder(
+ *CppEditor::CppModelManager::instance()->fallbackProjectPart(),
+ warningsConfigForProject(nullptr), includeDir);
+ const CppEditor::UsePrecompiledHeaders usePch = CppEditor::getPchUsage();
+ const QJsonArray projectPartOptions = fullProjectPartOptions(
+ optionsBuilder, globalClangOptions());
+ const QJsonArray clangOptions = clangOptionsForFile({}, optionsBuilder.projectPart(),
+ projectPartOptions, usePch,
+ optionsBuilder.isClStyle());
+ initOptions.insert("fallbackFlags", clangOptions);
setInitializationOptions(initOptions);
}
auto isRunningClangdClient = [](const LanguageClient::Client *c) {
@@ -1331,20 +935,6 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
}
setCurrentProject(project);
setDocumentChangeUpdateThreshold(d->settings.documentUpdateThreshold);
-
- const auto textMarkCreator = [this](const Utils::FilePath &filePath,
- const Diagnostic &diag, bool isProjectFile) {
- if (d->isTesting)
- emit textMarkCreated(filePath);
- return new ClangdTextMark(filePath, diag, isProjectFile, this);
- };
- const auto hideDiagsHandler = []{ ClangDiagnosticManager::clearTaskHubIssues(); };
- static const auto diagsFilter = [](const Diagnostic &diag) {
- const Diagnostic::Code code = diag.code().value_or(Diagnostic::Code());
- const QString * const codeString = Utils::get_if<QString>(&code);
- return !codeString || *codeString != "drv_unknown_argument";
- };
- setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler, diagsFilter);
setSymbolStringifier(displayNameFromDocumentSymbol);
setSemanticTokensHandler([this](TextDocument *doc, const QList<ExpandedSemanticToken> &tokens,
int version, bool force) {
@@ -1369,6 +959,9 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
});
connect(this, &Client::initialized, this, [this] {
+ auto currentDocumentFilter = static_cast<ClangdCurrentDocumentFilter *>(
+ CppEditor::CppModelManager::instance()->currentDocumentFilter());
+ currentDocumentFilter->updateCurrentClient();
// If we get this signal while there are pending searches, it means that
// the client was re-initialized, i.e. clangd crashed.
@@ -1378,26 +971,13 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
QTC_CHECK(d->runningFindUsages.isEmpty());
});
- connect(documentSymbolCache(), &DocumentSymbolCache::gotSymbols, this,
- [this](const DocumentUri &uri, const DocumentSymbolsResult &symbols) {
- if (!d->switchDeclDefData || d->switchDeclDefData->uri != uri)
- return;
- d->switchDeclDefData->docSymbols = symbols;
- if (d->switchDeclDefData->ast)
- d->handleDeclDefSwitchReplies();
- });
-
start();
}
ClangdClient::~ClangdClient()
{
- if (d->followSymbolData) {
- d->followSymbolData->openedFiles.clear();
- d->followSymbolData->pendingSymbolInfoRequests.clear();
- d->followSymbolData->pendingGotoImplRequests.clear();
- d->followSymbolData->pendingGotoDefRequests.clear();
- }
+ if (d->followSymbol)
+ d->followSymbol->clear();
delete d;
}
@@ -1413,13 +993,13 @@ void ClangdClient::openExtraFile(const Utils::FilePath &filePath, const QString
item.setUri(DocumentUri::fromFilePath(filePath));
item.setText(!content.isEmpty() ? content : QString::fromUtf8(cxxFile.readAll()));
item.setVersion(0);
- sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item)),
+ sendMessage(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item)),
SendDocUpdates::Ignore);
}
void ClangdClient::closeExtraFile(const Utils::FilePath &filePath)
{
- sendContent(DidCloseTextDocumentNotification(DidCloseTextDocumentParams(
+ sendMessage(DidCloseTextDocumentNotification(DidCloseTextDocumentParams(
TextDocumentIdentifier{DocumentUri::fromFilePath(filePath)})),
SendDocUpdates::Ignore);
}
@@ -1428,11 +1008,11 @@ void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor,
const Utils::optional<QString> &replacement)
{
// Quick check: Are we even on anything searchable?
- const QString searchTerm = d->searchTermFromCursor(cursor);
+ const QTextCursor adjustedCursor = d->adjustedCursor(cursor, document);
+ const QString searchTerm = d->searchTermFromCursor(adjustedCursor);
if (searchTerm.isEmpty())
return;
- const QTextCursor adjustedCursor = d->adjustedCursor(cursor, document);
const bool categorize = CppEditor::codeModelSettings()->categorizeFindReferences();
// If it's a "normal" symbol, go right ahead.
@@ -1445,25 +1025,15 @@ void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor,
// Otherwise get the proper spelling of the search term from clang, so we can put it into the
// search widget.
- const TextDocumentIdentifier docId(DocumentUri::fromFilePath(document->filePath()));
- const TextDocumentPositionParams params(docId, Range(adjustedCursor).start());
- SymbolInfoRequest symReq(params);
- symReq.setResponseCallback([this, doc = QPointer(document), adjustedCursor, replacement, categorize]
- (const SymbolInfoRequest::Response &response) {
+ const auto symbolInfoHandler = [this, doc = QPointer(document), adjustedCursor, replacement, categorize]
+ (const QString &name, const QString &, const MessageId &) {
if (!doc)
return;
- const auto result = response.result();
- if (!result)
- return;
- const auto list = Utils::get_if<QList<SymbolDetails>>(&result.value());
- if (!list || list->isEmpty())
+ if (name.isEmpty())
return;
- const SymbolDetails &sd = list->first();
- if (sd.name().isEmpty())
- return;
- d->findUsages(doc.data(), adjustedCursor, sd.name(), replacement, categorize);
- });
- sendContent(symReq);
+ d->findUsages(doc.data(), adjustedCursor, name, replacement, categorize);
+ };
+ requestSymbolInfo(document->filePath(), Range(adjustedCursor).start(), symbolInfoHandler);
}
void ClangdClient::handleDiagnostics(const PublishDiagnosticsParams &params)
@@ -1475,8 +1045,19 @@ void ClangdClient::handleDiagnostics(const PublishDiagnosticsParams &params)
return;
for (const Diagnostic &diagnostic : params.diagnostics()) {
const ClangdDiagnostic clangdDiagnostic(diagnostic);
- for (const CodeAction &action : clangdDiagnostic.codeActions().value_or(QList<CodeAction>{}))
- LanguageClient::updateCodeActionRefactoringMarker(this, action, uri);
+ auto codeActions = clangdDiagnostic.codeActions();
+ if (codeActions && !codeActions->isEmpty()) {
+ for (CodeAction &action : *codeActions)
+ action.setDiagnostics({diagnostic});
+ LanguageClient::updateCodeActionRefactoringMarker(this, *codeActions, uri);
+ } else {
+ // We know that there's only one kind of diagnostic for which clangd has
+ // a quickfix tweak, so let's not be wasteful.
+ const Diagnostic::Code code = diagnostic.code().value_or(Diagnostic::Code());
+ const QString * const codeString = Utils::get_if<QString>(&code);
+ if (codeString && *codeString == "-Wswitch")
+ requestCodeActions(uri, diagnostic);
+ }
}
}
@@ -1491,10 +1072,8 @@ void ClangdClient::handleDocumentOpened(TextDocument *doc)
void ClangdClient::handleDocumentClosed(TextDocument *doc)
{
- d->highlighters.erase(doc);
+ d->highlightingData.remove(doc);
d->astCache.remove(doc);
- d->previousTokens.remove(doc);
- d->virtualRanges.remove(doc);
d->parserConfigs.remove(doc->filePath());
}
@@ -1509,6 +1088,75 @@ const LanguageClient::Client::CustomInspectorTabs ClangdClient::createCustomInsp
return {std::make_pair(new MemoryUsageWidget(this), tr("Memory Usage"))};
}
+class ClangdDiagnosticManager : public LanguageClient::DiagnosticManager
+{
+ using LanguageClient::DiagnosticManager::DiagnosticManager;
+
+ ClangdClient *getClient() const { return qobject_cast<ClangdClient *>(client()); }
+
+ bool isCurrentDocument(const Utils::FilePath &filePath) const
+ {
+ const IDocument * const doc = EditorManager::currentDocument();
+ return doc && doc->filePath() == filePath;
+ }
+
+ void showDiagnostics(const DocumentUri &uri, int version) override
+ {
+ const Utils::FilePath filePath = uri.toFilePath();
+ getClient()->clearTasks(filePath);
+ DiagnosticManager::showDiagnostics(uri, version);
+ if (isCurrentDocument(filePath))
+ getClient()->switchIssuePaneEntries(filePath);
+ }
+
+ void hideDiagnostics(const Utils::FilePath &filePath) override
+ {
+ DiagnosticManager::hideDiagnostics(filePath);
+ if (isCurrentDocument(filePath))
+ TaskHub::clearTasks(Constants::TASK_CATEGORY_DIAGNOSTICS);
+ }
+
+ QList<Diagnostic> filteredDiagnostics(const QList<Diagnostic> &diagnostics) const override
+ {
+ return Utils::filtered(diagnostics, [](const Diagnostic &diag){
+ const Diagnostic::Code code = diag.code().value_or(Diagnostic::Code());
+ const QString * const codeString = Utils::get_if<QString>(&code);
+ return !codeString || *codeString != "drv_unknown_argument";
+ });
+ }
+
+ TextMark *createTextMark(const Utils::FilePath &filePath,
+ const Diagnostic &diagnostic,
+ bool isProjectFile) const override
+ {
+ return new ClangdTextMark(filePath, diagnostic, isProjectFile, getClient());
+ }
+};
+
+DiagnosticManager *ClangdClient::createDiagnosticManager()
+{
+ auto diagnosticManager = new ClangdDiagnosticManager(this);
+ if (d->isTesting) {
+ connect(diagnosticManager, &DiagnosticManager::textMarkCreated,
+ this, &ClangdClient::textMarkCreated);
+ }
+ return diagnosticManager;
+}
+
+bool ClangdClient::referencesShadowFile(const TextEditor::TextDocument *doc,
+ const Utils::FilePath &candidate)
+{
+ const QRegularExpression includeRex("#include.*" + candidate.fileName() + R"([>"])");
+ const QTextCursor includePos = doc->document()->find(includeRex);
+ return !includePos.isNull();
+}
+
+RefactoringChangesData *ClangdClient::createRefactoringChangesBackend() const
+{
+ return new CppEditor::CppRefactoringChangesData(
+ CppEditor::CppModelManager::instance()->snapshot());
+}
+
QVersionNumber ClangdClient::versionNumber() const
{
if (d->versionNumber)
@@ -1612,11 +1260,29 @@ QString ClangdClient::displayNameFromDocumentSymbol(SymbolKind kind, const QStri
case SymbolKind::Constructor:
return name + detail;
case SymbolKind::Method:
- case LanguageServerProtocol::SymbolKind::Function: {
- const int parenOffset = detail.indexOf(" (");
- if (parenOffset == -1)
+ case SymbolKind::Function: {
+ const int lastParenOffset = detail.lastIndexOf(')');
+ if (lastParenOffset == -1)
+ return name;
+ int leftParensNeeded = 1;
+ int i = -1;
+ for (i = lastParenOffset - 1; i >= 0; --i) {
+ switch (detail.at(i).toLatin1()) {
+ case ')':
+ ++leftParensNeeded;
+ break;
+ case '(':
+ --leftParensNeeded;
+ break;
+ default:
+ break;
+ }
+ if (leftParensNeeded == 0)
+ break;
+ }
+ if (leftParensNeeded > 0)
return name;
- return name + detail.mid(parenOffset + 1) + " -> " + detail.mid(0, parenOffset);
+ return name + detail.mid(i) + " -> " + detail.left(i);
}
case SymbolKind::Variable:
case SymbolKind::Field:
@@ -1634,7 +1300,7 @@ QString ClangdClient::displayNameFromDocumentSymbol(SymbolKind kind, const QStri
void ClangdClient::handleUiHeaderChange(const QString &fileName)
{
const QRegularExpression includeRex("#include.*" + fileName + R"([>"])");
- const QVector<Client *> &allClients = LanguageClientManager::clients();
+ const QList<Client *> &allClients = LanguageClientManager::clients();
for (Client * const client : allClients) {
if (!client->reachable() || !qobject_cast<ClangdClient *>(client))
continue;
@@ -1669,21 +1335,87 @@ void ClangdClient::updateParserConfig(const Utils::FilePath &filePath,
->projectPartForId(config.preferredProjectPartId);
if (!projectPart)
return;
- const CppEditor::ClangDiagnosticConfig projectWarnings = warningsConfigForProject(project());
- const QStringList projectOptions = optionsForProject(project());
QJsonObject cdbChanges;
- QStringList args = createClangOptions(*projectPart, filePath.toString(), projectWarnings,
- projectOptions);
- args.prepend("clang");
- args.append(filePath.toString());
- QJsonObject value;
- value.insert("workingDirectory", filePath.parentDir().toString());
- value.insert("compilationCommand", QJsonArray::fromStringList(args));
- cdbChanges.insert(filePath.toUserOutput(), value);
- const QJsonObject settings({qMakePair(QString("compilationDatabaseChanges"), cdbChanges)});
+ const Utils::FilePath includeDir = CppEditor::ClangdSettings(d->settings).clangdIncludePath();
+ CppEditor::CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder(
+ *projectPart, warningsConfigForProject(project()), includeDir);
+ const CppEditor::ProjectFile file(filePath.toString(),
+ CppEditor::ProjectFile::classify(filePath.toString()));
+ const QJsonArray projectPartOptions = fullProjectPartOptions(
+ optionsBuilder, globalClangOptions());
+ addToCompilationDb(cdbChanges, *projectPart, CppEditor::getPchUsage(), projectPartOptions,
+ filePath.parentDir(), file, optionsBuilder.isClStyle());
+ QJsonObject settings;
+ addCompilationDb(settings, cdbChanges);
DidChangeConfigurationParams configChangeParams;
configChangeParams.setSettings(settings);
- sendContent(DidChangeConfigurationNotification(configChangeParams));
+ sendMessage(DidChangeConfigurationNotification(configChangeParams));
+}
+
+void ClangdClient::switchIssuePaneEntries(const Utils::FilePath &filePath)
+{
+ TaskHub::clearTasks(Constants::TASK_CATEGORY_DIAGNOSTICS);
+ const Tasks tasks = d->issuePaneEntries.value(filePath);
+ for (const Task &t : tasks)
+ TaskHub::addTask(t);
+}
+
+void ClangdClient::addTask(const ProjectExplorer::Task &task)
+{
+ d->issuePaneEntries[task.file] << task;
+}
+
+void ClangdClient::clearTasks(const Utils::FilePath &filePath)
+{
+ d->issuePaneEntries[filePath].clear();
+}
+
+Utils::optional<bool> ClangdClient::hasVirtualFunctionAt(TextDocument *doc, int revision,
+ const Range &range)
+{
+ const auto highlightingData = d->highlightingData.constFind(doc);
+ if (highlightingData == d->highlightingData.constEnd()
+ || highlightingData->virtualRanges.second != revision) {
+ return {};
+ }
+ const auto matcher = [range](const Range &r) { return range.overlaps(r); };
+ return Utils::contains(highlightingData->virtualRanges.first, matcher);
+}
+
+MessageId ClangdClient::getAndHandleAst(const TextDocOrFile &doc, const AstHandler &astHandler,
+ AstCallbackMode callbackMode, const Range &range)
+{
+ return d->getAndHandleAst(doc, astHandler, callbackMode, range);
+}
+
+MessageId ClangdClient::requestSymbolInfo(const Utils::FilePath &filePath, const Position &position,
+ const SymbolInfoHandler &handler)
+{
+ const TextDocumentIdentifier docId(DocumentUri::fromFilePath(filePath));
+ const TextDocumentPositionParams params(docId, position);
+ SymbolInfoRequest symReq(params);
+ symReq.setResponseCallback([handler, reqId = symReq.id()]
+ (const SymbolInfoRequest::Response &response) {
+ const auto result = response.result();
+ if (!result) {
+ handler({}, {}, reqId);
+ return;
+ }
+
+ // According to the documentation, we should receive a single
+ // object here, but it's a list. No idea what it means if there's
+ // more than one entry. We choose the first one.
+ const auto list = Utils::get_if<QList<SymbolDetails>>(&result.value());
+ if (!list || list->isEmpty()) {
+ handler({}, {}, reqId);
+ return;
+ }
+
+ const SymbolDetails &sd = list->first();
+ handler(sd.name(), sd.containerName(), reqId);
+ });
+ sendMessage(symReq);
+ return symReq.id();
}
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
@@ -1746,7 +1478,7 @@ void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Loca
q->openExtraFile(it.key().toFilePath(), it->fileContent);
it->fileContent.clear();
const auto docVariant = doc ? TextDocOrFile(doc) : TextDocOrFile(it.key().toFilePath());
- const auto astHandler = [this, key, loc = it.key()](const AstNode &ast,
+ const auto astHandler = [this, key, loc = it.key()](const ClangdAstNode &ast,
const MessageId &reqId) {
qCDebug(clangdLog) << "AST for" << loc.toFilePath();
const auto refData = runningFindUsages.find(key);
@@ -1808,9 +1540,10 @@ void ClangdClient::Private::addSearchResultsForFile(ReferencesData &refData,
qCDebug(clangdLog) << file << "has valid AST:" << fileData.ast.isValid();
for (const auto &rangeWithText : fileData.rangesAndLineText) {
const Range &range = rangeWithText.first;
- const Usage::Type usageType = fileData.ast.isValid()
- ? getUsageType(getAstPath(fileData.ast, qAsConst(range)))
- : Usage::Type::Other;
+ const ClangdAstPath astPath = getAstPath(fileData.ast, range);
+ const Usage::Type usageType = fileData.ast.isValid() ? getUsageType(astPath)
+ : Usage::Type::Other;
+
SearchResultItem item;
item.setUserData(int(usageType));
item.setStyle(CppEditor::colorStyleForUsageType(usageType));
@@ -1818,6 +1551,8 @@ void ClangdClient::Private::addSearchResultsForFile(ReferencesData &refData,
item.setMainRange(SymbolSupport::convertRange(range));
item.setUseTextEditorFont(true);
item.setLineText(rangeWithText.second);
+ item.setContainingFunctionName(getContainingFunctionName(astPath, range));
+
if (refData.search->supportsReplace()) {
const bool fileInSession = SessionManager::projectForFile(file);
item.setSelectForReplacement(fileInSession);
@@ -1868,88 +1603,73 @@ void ClangdClient::Private::finishSearch(const ReferencesData &refData, bool can
void ClangdClient::followSymbol(TextDocument *document,
const QTextCursor &cursor,
CppEditor::CppEditorWidget *editorWidget,
- Utils::ProcessLinkCallback &&callback,
+ const Utils::LinkHandler &callback,
bool resolveTarget,
bool openInSplit
)
{
QTC_ASSERT(documentOpen(document), openDocument(document));
+
+ delete d->followSymbol;
+ d->followSymbol = nullptr;
+
const QTextCursor adjustedCursor = d->adjustedCursor(cursor, document);
if (!resolveTarget) {
- d->followSymbolData.reset();
- symbolSupport().findLinkAt(document, adjustedCursor, std::move(callback), false);
+ symbolSupport().findLinkAt(document, adjustedCursor, callback, false);
return;
}
qCDebug(clangdLog) << "follow symbol requested" << document->filePath()
<< adjustedCursor.blockNumber() << adjustedCursor.positionInBlock();
- d->followSymbolData.emplace(this, ++d->nextJobId, adjustedCursor, editorWidget,
- DocumentUri::fromFilePath(document->filePath()),
- std::move(callback), openInSplit);
-
- // Step 1: Follow the symbol via "Go to Definition". At the same time, request the
- // AST node corresponding to the cursor position, so we can find out whether
- // we have to look for overrides.
- const auto gotoDefCallback = [this, id = d->followSymbolData->id](const Utils::Link &link) {
- qCDebug(clangdLog) << "received go to definition response";
- if (!link.hasValidTarget()) {
- d->followSymbolData.reset();
- return;
- }
- if (!d->followSymbolData || id != d->followSymbolData->id)
- return;
- d->followSymbolData->defLink = link;
- if (d->followSymbolData->cursorNode)
- d->handleGotoDefinitionResult();
- };
- symbolSupport().findLinkAt(document, adjustedCursor, std::move(gotoDefCallback), true);
-
- const auto astHandler = [this, id = d->followSymbolData->id]
- (const AstNode &ast, const MessageId &) {
- qCDebug(clangdLog) << "received ast response for cursor";
- if (!d->followSymbolData || d->followSymbolData->id != id)
- return;
- d->followSymbolData->cursorNode = ast;
- if (d->followSymbolData->defLink.hasValidTarget())
- d->handleGotoDefinitionResult();
- };
- d->getAndHandleAst(document, astHandler, Private::AstCallbackMode::AlwaysAsync,
- Range(adjustedCursor));
+ d->followSymbol = new ClangdFollowSymbol(this, adjustedCursor, editorWidget, document, callback,
+ openInSplit);
+ connect(d->followSymbol, &ClangdFollowSymbol::done, this, [this] {
+ d->followSymbol->deleteLater();
+ d->followSymbol = nullptr;
+ });
}
void ClangdClient::switchDeclDef(TextDocument *document, const QTextCursor &cursor,
CppEditor::CppEditorWidget *editorWidget,
- Utils::ProcessLinkCallback &&callback)
+ const Utils::LinkHandler &callback)
{
QTC_ASSERT(documentOpen(document), openDocument(document));
qCDebug(clangdLog) << "switch decl/dev requested" << document->filePath()
<< cursor.blockNumber() << cursor.positionInBlock();
- d->switchDeclDefData.emplace(++d->nextJobId, document, cursor, editorWidget,
- std::move(callback));
-
- // Retrieve AST and document symbols.
- const auto astHandler = [this, id = d->switchDeclDefData->id](const AstNode &ast,
- const MessageId &) {
- qCDebug(clangdLog) << "received ast for decl/def switch";
- if (!d->switchDeclDefData || d->switchDeclDefData->id != id
- || !d->switchDeclDefData->document)
- return;
- if (!ast.isValid()) {
- d->switchDeclDefData.reset();
- return;
- }
- d->switchDeclDefData->ast = ast;
- if (d->switchDeclDefData->docSymbols)
- d->handleDeclDefSwitchReplies();
+ if (d->switchDeclDef)
+ delete d->switchDeclDef;
+ d->switchDeclDef = new ClangdSwitchDeclDef(this, document, cursor, editorWidget, callback);
+ connect(d->switchDeclDef, &ClangdSwitchDeclDef::done, this, [this] {
+ d->switchDeclDef->deleteLater();
+ d->switchDeclDef = nullptr;
+ });
+}
+void ClangdClient::switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit)
+{
+ class SwitchSourceHeaderRequest : public Request<QJsonValue, std::nullptr_t, TextDocumentIdentifier>
+ {
+ public:
+ using Request::Request;
+ explicit SwitchSourceHeaderRequest(const Utils::FilePath &filePath)
+ : Request("textDocument/switchSourceHeader",
+ TextDocumentIdentifier(DocumentUri::fromFilePath(filePath))) {}
};
- d->getAndHandleAst(document, astHandler, Private::AstCallbackMode::SyncIfPossible);
- documentSymbolCache()->requestSymbols(d->switchDeclDefData->uri, Schedule::Now);
+ SwitchSourceHeaderRequest req(filePath);
+ req.setResponseCallback([inNextSplit](const SwitchSourceHeaderRequest::Response &response) {
+ if (const Utils::optional<QJsonValue> result = response.result()) {
+ const DocumentUri uri = DocumentUri::fromProtocol(result->toString());
+ const Utils::FilePath filePath = uri.toFilePath();
+ if (!filePath.isEmpty())
+ CppEditor::openEditor(filePath, inNextSplit);
+ }
+ });
+ sendMessage(req);
}
void ClangdClient::findLocalUsages(TextDocument *document, const QTextCursor &cursor,
- CppEditor::RefactoringEngineInterface::RenameCallback &&callback)
+ CppEditor::RenameCallback &&callback)
{
QTC_ASSERT(documentOpen(document), openDocument(document));
@@ -1975,7 +1695,7 @@ void ClangdClient::findLocalUsages(TextDocument *document, const QTextCursor &cu
}
// Step 2: Get AST and check whether it's a local variable.
- const auto astHandler = [this, link, id](const AstNode &ast, const MessageId &) {
+ const auto astHandler = [this, link, id](const ClangdAstNode &ast, const MessageId &) {
qCDebug(clangdLog) << "received ast response";
if (!d->localRefsData || id != d->localRefsData->id)
return;
@@ -1985,7 +1705,7 @@ void ClangdClient::findLocalUsages(TextDocument *document, const QTextCursor &cu
}
const Position linkPos(link.targetLine - 1, link.targetColumn);
- const QList<AstNode> astPath = getAstPath(ast, linkPos);
+ const ClangdAstPath astPath = getAstPath(ast, linkPos);
bool isVar = false;
for (auto it = astPath.rbegin(); it != astPath.rend(); ++it) {
if (it->role() == "declaration"
@@ -2003,11 +1723,7 @@ void ClangdClient::findLocalUsages(TextDocument *document, const QTextCursor &cu
qCDebug(clangdLog) << "found" << locations.size() << "local references";
if (!d->localRefsData || id != d->localRefsData->id)
return;
- ClangBackEnd::SourceLocationsContainer container;
- for (const Location &loc : locations) {
- container.insertSourceLocation({}, loc.range().start().line() + 1,
- loc.range().start().character() + 1);
- }
+ const Utils::Links links = Utils::transform(locations, &Location::toLink);
// The callback only uses the symbol length, so we just create a dummy.
// Note that the calculation will be wrong for identifiers with
@@ -2017,7 +1733,7 @@ void ClangdClient::findLocalUsages(TextDocument *document, const QTextCursor &cu
const Range r = locations.first().range();
symbol = QString(r.end().character() - r.start().character(), 'x');
}
- d->localRefsData->callback(symbol, container, d->localRefsData->revision);
+ d->localRefsData->callback(symbol, links, d->localRefsData->revision);
d->localRefsData->callback = {};
d->localRefsData.reset();
});
@@ -2032,7 +1748,7 @@ void ClangdClient::findLocalUsages(TextDocument *document, const QTextCursor &cu
};
qCDebug(clangdLog) << "sending ast request for link";
d->getAndHandleAst(d->localRefsData->document, astHandler,
- Private::AstCallbackMode::SyncIfPossible);
+ AstCallbackMode::SyncIfPossible);
};
symbolSupport().findLinkAt(document, cursor, std::move(gotoDefCallback), true);
}
@@ -2040,35 +1756,38 @@ void ClangdClient::findLocalUsages(TextDocument *document, const QTextCursor &cu
void ClangdClient::gatherHelpItemForTooltip(const HoverRequest::Response &hoverResponse,
const DocumentUri &uri)
{
- if (const Utils::optional<Hover> result = hoverResponse.result()) {
- const HoverContent content = result->content();
- const MarkupContent * const markup = Utils::get_if<MarkupContent>(&content);
- if (markup) {
- const QString markupString = markup->content();
-
- // Macros aren't locatable via the AST, so parse the formatted string.
- static const QString magicMacroPrefix = "### macro `";
- if (markupString.startsWith(magicMacroPrefix)) {
- const int nameStart = magicMacroPrefix.length();
- const int closingQuoteIndex = markupString.indexOf('`', nameStart);
- if (closingQuoteIndex != -1) {
- const QString macroName = markupString.mid(nameStart,
- closingQuoteIndex - nameStart);
- d->setHelpItemForTooltip(hoverResponse.id(), macroName, HelpItem::Macro);
- return;
+ if (const Utils::optional<HoverResult> result = hoverResponse.result()) {
+ if (auto hover = Utils::get_if<Hover>(&(*result))) {
+ const HoverContent content = hover->content();
+ const MarkupContent *const markup = Utils::get_if<MarkupContent>(&content);
+ if (markup) {
+ const QString markupString = markup->content();
+
+ // Macros aren't locatable via the AST, so parse the formatted string.
+ static const QString magicMacroPrefix = "### macro `";
+ if (markupString.startsWith(magicMacroPrefix)) {
+ const int nameStart = magicMacroPrefix.length();
+ const int closingQuoteIndex = markupString.indexOf('`', nameStart);
+ if (closingQuoteIndex != -1) {
+ const QString macroName = markupString.mid(nameStart,
+ closingQuoteIndex - nameStart);
+ d->setHelpItemForTooltip(hoverResponse.id(), macroName, HelpItem::Macro);
+ return;
+ }
}
- }
- // Is it the file path for an include directive?
- QString cleanString = markupString;
- cleanString.remove('`');
- const QStringList lines = cleanString.trimmed().split('\n');
- if (!lines.isEmpty()) {
- const auto filePath = Utils::FilePath::fromUserInput(lines.last().simplified());
- if (filePath.exists()) {
- d->setHelpItemForTooltip(hoverResponse.id(), filePath.fileName(),
- HelpItem::Brief);
- return;
+ // Is it the file path for an include directive?
+ QString cleanString = markupString;
+ cleanString.remove('`');
+ const QStringList lines = cleanString.trimmed().split('\n');
+ if (!lines.isEmpty()) {
+ const auto filePath = Utils::FilePath::fromUserInput(lines.last().simplified());
+ if (filePath.exists()) {
+ d->setHelpItemForTooltip(hoverResponse.id(),
+ filePath.fileName(),
+ HelpItem::Brief);
+ return;
+ }
}
}
}
@@ -2076,22 +1795,26 @@ void ClangdClient::gatherHelpItemForTooltip(const HoverRequest::Response &hoverR
const TextDocument * const doc = documentForFilePath(uri.toFilePath());
QTC_ASSERT(doc, return);
- const auto astHandler = [this, uri, hoverResponse](const AstNode &ast, const MessageId &) {
+ const auto astHandler = [this, uri, hoverResponse](const ClangdAstNode &ast, const MessageId &) {
const MessageId id = hoverResponse.id();
- const Range range = hoverResponse.result()->range().value_or(Range());
- const QList<AstNode> path = getAstPath(ast, range);
+ Range range;
+ if (const Utils::optional<HoverResult> result = hoverResponse.result()) {
+ if (auto hover = Utils::get_if<Hover>(&(*result)))
+ range = hover->range().value_or(Range());
+ }
+ const ClangdAstPath path = getAstPath(ast, range);
if (path.isEmpty()) {
d->setHelpItemForTooltip(id);
return;
}
- AstNode node = path.last();
+ ClangdAstNode node = path.last();
if (node.role() == "expression" && node.kind() == "ImplicitCast") {
- const Utils::optional<QList<AstNode>> children = node.children();
+ const Utils::optional<QList<ClangdAstNode>> children = node.children();
if (children && !children->isEmpty())
node = children->first();
}
while (node.kind() == "Qualified") {
- const Utils::optional<QList<AstNode>> children = node.children();
+ const Utils::optional<QList<ClangdAstNode>> children = node.children();
if (children && !children->isEmpty())
node = children->first();
}
@@ -2110,28 +1833,19 @@ void ClangdClient::gatherHelpItemForTooltip(const HoverRequest::Response &hoverR
const bool isFunction = node.role() == "expression" && node.kind() == "DeclRef"
&& type.contains('(');
if (isMemberFunction || isFunction) {
- const TextDocumentPositionParams params(TextDocumentIdentifier(uri), range.start());
- SymbolInfoRequest symReq(params);
- symReq.setResponseCallback([this, id, type, isFunction]
- (const SymbolInfoRequest::Response &response) {
+ const auto symbolInfoHandler = [this, id, type, isFunction]
+ (const QString &name, const QString &prefix, const MessageId &) {
qCDebug(clangdLog) << "handling symbol info reply";
- QString fqn;
- if (const auto result = response.result()) {
- if (const auto list = Utils::get_if<QList<SymbolDetails>>(&result.value())) {
- if (!list->isEmpty()) {
- const SymbolDetails &sd = list->first();
- fqn = sd.containerName() + sd.name();
- }
- }
- }
+ const QString fqn = prefix + name;
// Unfortunately, the arcana string contains the signature only for
// free functions, so we can't distinguish member function overloads.
// But since HtmlDocExtractor::getFunctionDescription() is always called
// with mainOverload = true, such information would get ignored anyway.
- d->setHelpItemForTooltip(id, fqn, HelpItem::Function, isFunction ? type : "()");
- });
- sendContent(symReq, SendDocUpdates::Ignore);
+ if (!fqn.isEmpty())
+ d->setHelpItemForTooltip(id, fqn, HelpItem::Function, isFunction ? type : "()");
+ };
+ requestSymbolInfo(uri.toFilePath(), range.start(), symbolInfoHandler);
return;
}
if ((node.role() == "expression" && node.kind() == "DeclRef")
@@ -2196,7 +1910,7 @@ void ClangdClient::gatherHelpItemForTooltip(const HoverRequest::Response &hoverR
}
d->setHelpItemForTooltip(id);
};
- d->getAndHandleAst(doc, astHandler, Private::AstCallbackMode::SyncIfPossible);
+ d->getAndHandleAst(doc, astHandler, AstCallbackMode::SyncIfPossible);
}
void ClangdClient::setVirtualRanges(const Utils::FilePath &filePath, const QList<Range> &ranges,
@@ -2204,239 +1918,32 @@ void ClangdClient::setVirtualRanges(const Utils::FilePath &filePath, const QList
{
TextDocument * const doc = documentForFilePath(filePath);
if (doc && doc->document()->revision() == revision)
- d->virtualRanges.insert(doc, {ranges, revision});
+ d->highlightingData[doc].virtualRanges = {ranges, revision};
}
-void ClangdClient::Private::handleGotoDefinitionResult()
+Utils::optional<QString> ClangdClient::Private::getContainingFunctionName(
+ const ClangdAstPath &astPath, const Range& range)
{
- QTC_ASSERT(followSymbolData->defLink.hasValidTarget(), return);
+ const ClangdAstNode* containingFuncNode{nullptr};
+ const ClangdAstNode* lastCompoundStmtNode{nullptr};
- qCDebug(clangdLog) << "handling go to definition result";
+ for (auto it = astPath.crbegin(); it != astPath.crend(); ++it) {
+ if (it->arcanaContains("CompoundStmt"))
+ lastCompoundStmtNode = &*it;
- // No dis-ambiguation necessary. Call back with the link and finish.
- if (!followSymbolData->defLinkIsAmbiguous()) {
- followSymbolData->callback(followSymbolData->defLink);
- followSymbolData.reset();
- return;
- }
-
- // Step 2: Get all possible overrides via "Go to Implementation".
- // Note that we have to do this for all member function calls, because
- // we cannot tell here whether the member function is virtual.
- followSymbolData->allLinks << followSymbolData->defLink;
- sendGotoImplementationRequest(followSymbolData->defLink);
-}
-
-void ClangdClient::Private::sendGotoImplementationRequest(const Utils::Link &link)
-{
- if (!q->documentForFilePath(link.targetFilePath)
- && followSymbolData->openedFiles.insert(link.targetFilePath).second) {
- q->openExtraFile(link.targetFilePath);
- }
- const Position position(link.targetLine - 1, link.targetColumn);
- const TextDocumentIdentifier documentId(DocumentUri::fromFilePath(link.targetFilePath));
- GotoImplementationRequest req(TextDocumentPositionParams(documentId, position));
- req.setResponseCallback([this, id = followSymbolData->id, reqId = req.id()](
- const GotoImplementationRequest::Response &response) {
- qCDebug(clangdLog) << "received go to implementation reply";
- if (!followSymbolData || id != followSymbolData->id)
- return;
- followSymbolData->pendingGotoImplRequests.removeOne(reqId);
- handleGotoImplementationResult(response);
- });
- q->sendContent(req, SendDocUpdates::Ignore);
- followSymbolData->pendingGotoImplRequests << req.id();
- qCDebug(clangdLog) << "sending go to implementation request" << link.targetLine;
-}
-
-void ClangdClient::Private::handleGotoImplementationResult(
- const GotoImplementationRequest::Response &response)
-{
- if (const Utils::optional<GotoResult> &result = response.result()) {
- QList<Utils::Link> newLinks;
- if (const auto ploc = Utils::get_if<Location>(&*result))
- newLinks = {ploc->toLink()};
- if (const auto plloc = Utils::get_if<QList<Location>>(&*result))
- newLinks = Utils::transform(*plloc, &Location::toLink);
- for (const Utils::Link &link : qAsConst(newLinks)) {
- if (!followSymbolData->allLinks.contains(link)) {
- followSymbolData->allLinks << link;
-
- // We must do this recursively, because clangd reports only the first
- // level of overrides.
- sendGotoImplementationRequest(link);
+ if (it->isFunction()) {
+ if (lastCompoundStmtNode && lastCompoundStmtNode->hasRange()
+ && lastCompoundStmtNode->range().contains(range)) {
+ containingFuncNode = &*it;
+ break;
}
}
}
- // We didn't find any further candidates, so jump to the original definition link.
- if (followSymbolData->allLinks.size() == 1
- && followSymbolData->pendingGotoImplRequests.isEmpty()) {
- followSymbolData->callback(followSymbolData->allLinks.first());
- followSymbolData.reset();
- return;
- }
-
- // As soon as we know that there is more than one candidate, we start the code assist
- // procedure, to let the user know that things are happening.
- if (followSymbolData->allLinks.size() > 1 && !followSymbolData->virtualFuncAssistProcessor
- && followSymbolData->editorWidget) {
- followSymbolData->editorWidget->invokeTextEditorWidgetAssist(FollowSymbol,
- &followSymbolData->virtualFuncAssistProvider);
- }
-
- if (!followSymbolData->pendingGotoImplRequests.isEmpty())
- return;
-
- // Step 3: We are done looking for overrides, and we found at least one.
- // Make a symbol info request for each link to get the class names.
- // Also get the AST for the base declaration, so we can find out whether it's
- // pure virtual and mark it accordingly.
- // In addition, we need to follow all override links, because for these, clangd
- // gives us the declaration instead of the definition.
- for (const Utils::Link &link : qAsConst(followSymbolData->allLinks)) {
- if (!q->documentForFilePath(link.targetFilePath)
- && followSymbolData->openedFiles.insert(link.targetFilePath).second) {
- q->openExtraFile(link.targetFilePath);
- }
- const TextDocumentIdentifier doc(DocumentUri::fromFilePath(link.targetFilePath));
- const Position pos(link.targetLine - 1, link.targetColumn);
- const TextDocumentPositionParams params(doc, pos);
- SymbolInfoRequest symReq(params);
- symReq.setResponseCallback([this, link, id = followSymbolData->id, reqId = symReq.id()](
- const SymbolInfoRequest::Response &response) {
- qCDebug(clangdLog) << "handling symbol info reply"
- << link.targetFilePath.toUserOutput() << link.targetLine;
- if (!followSymbolData || id != followSymbolData->id)
- return;
- if (const auto result = response.result()) {
- if (const auto list = Utils::get_if<QList<SymbolDetails>>(&result.value())) {
- if (!list->isEmpty()) {
- // According to the documentation, we should receive a single
- // object here, but it's a list. No idea what it means if there's
- // more than one entry. We choose the first one.
- const SymbolDetails &sd = list->first();
- followSymbolData->symbolsToDisplay << qMakePair(sd.containerName()
- + sd.name(), link);
- }
- }
- }
- followSymbolData->pendingSymbolInfoRequests.removeOne(reqId);
- followSymbolData->virtualFuncAssistProcessor->update();
- if (followSymbolData->pendingSymbolInfoRequests.isEmpty()
- && followSymbolData->pendingGotoDefRequests.isEmpty()
- && followSymbolData->defLinkNode.isValid()) {
- handleDocumentInfoResults();
- }
- });
- followSymbolData->pendingSymbolInfoRequests << symReq.id();
- qCDebug(clangdLog) << "sending symbol info request";
- q->sendContent(symReq, SendDocUpdates::Ignore);
-
- if (link == followSymbolData->defLink)
- continue;
-
- GotoDefinitionRequest defReq(params);
- defReq.setResponseCallback([this, link, id = followSymbolData->id, reqId = defReq.id()]
- (const GotoDefinitionRequest::Response &response) {
- qCDebug(clangdLog) << "handling additional go to definition reply for"
- << link.targetFilePath << link.targetLine;
- if (!followSymbolData || id != followSymbolData->id)
- return;
- Utils::Link newLink;
- if (Utils::optional<GotoResult> _result = response.result()) {
- const GotoResult result = _result.value();
- if (const auto ploc = Utils::get_if<Location>(&result)) {
- newLink = ploc->toLink();
- } else if (const auto plloc = Utils::get_if<QList<Location>>(&result)) {
- if (!plloc->isEmpty())
- newLink = plloc->value(0).toLink();
- }
- }
- qCDebug(clangdLog) << "def link is" << newLink.targetFilePath << newLink.targetLine;
- followSymbolData->declDefMap.insert(link, newLink);
- followSymbolData->pendingGotoDefRequests.removeOne(reqId);
- if (followSymbolData->pendingSymbolInfoRequests.isEmpty()
- && followSymbolData->pendingGotoDefRequests.isEmpty()
- && followSymbolData->defLinkNode.isValid()) {
- handleDocumentInfoResults();
- }
- });
- followSymbolData->pendingGotoDefRequests << defReq.id();
- qCDebug(clangdLog) << "sending additional go to definition request"
- << link.targetFilePath << link.targetLine;
- q->sendContent(defReq, SendDocUpdates::Ignore);
- }
-
- const Utils::FilePath defLinkFilePath = followSymbolData->defLink.targetFilePath;
- const TextDocument * const defLinkDoc = q->documentForFilePath(defLinkFilePath);
- const auto defLinkDocVariant = defLinkDoc ? TextDocOrFile(defLinkDoc)
- : TextDocOrFile(defLinkFilePath);
- const Position defLinkPos(followSymbolData->defLink.targetLine - 1,
- followSymbolData->defLink.targetColumn);
- const auto astHandler = [this, id = followSymbolData->id]
- (const AstNode &ast, const MessageId &) {
- qCDebug(clangdLog) << "received ast response for def link";
- if (!followSymbolData || followSymbolData->id != id)
- return;
- followSymbolData->defLinkNode = ast;
- if (followSymbolData->pendingSymbolInfoRequests.isEmpty()
- && followSymbolData->pendingGotoDefRequests.isEmpty()) {
- handleDocumentInfoResults();
- }
- };
- getAndHandleAst(defLinkDocVariant, astHandler, AstCallbackMode::AlwaysAsync,
- Range(defLinkPos, defLinkPos));
-}
+ if (!containingFuncNode || !containingFuncNode->isValid())
+ return Utils::nullopt;
-void ClangdClient::Private::handleDocumentInfoResults()
-{
- followSymbolData->closeTempDocuments();
-
- // If something went wrong, we just follow the original link.
- if (followSymbolData->symbolsToDisplay.isEmpty()) {
- followSymbolData->callback(followSymbolData->defLink);
- followSymbolData.reset();
- return;
- }
- if (followSymbolData->symbolsToDisplay.size() == 1) {
- followSymbolData->callback(followSymbolData->symbolsToDisplay.first().second);
- followSymbolData.reset();
- return;
- }
- QTC_ASSERT(followSymbolData->virtualFuncAssistProcessor
- && followSymbolData->virtualFuncAssistProcessor->running(),
- followSymbolData.reset(); return);
- followSymbolData->virtualFuncAssistProcessor->finalize();
-}
-
-void ClangdClient::Private::handleDeclDefSwitchReplies()
-{
- if (!switchDeclDefData->document) {
- switchDeclDefData.reset();
- return;
- }
-
- // Find the function declaration or definition associated with the cursor.
- // For instance, the cursor could be somwehere inside a function body or
- // on a function return type, or ...
- if (clangdLogAst().isDebugEnabled())
- switchDeclDefData->ast->print(0);
- const Utils::optional<AstNode> functionNode = switchDeclDefData->getFunctionNode();
- if (!functionNode) {
- switchDeclDefData.reset();
- return;
- }
-
- // Unfortunately, the AST does not contain the location of the actual function name symbol,
- // so we have to look for it in the document symbols.
- const QTextCursor funcNameCursor = switchDeclDefData->cursorForFunctionName(*functionNode);
- if (!funcNameCursor.isNull()) {
- q->followSymbol(switchDeclDefData->document.data(), funcNameCursor,
- switchDeclDefData->editorWidget, std::move(switchDeclDefData->callback),
- true, false);
- }
- switchDeclDefData.reset();
+ return containingFuncNode->detail();
}
CppEditor::CppEditorWidget *ClangdClient::Private::widgetFromDocument(const TextDocument *doc)
@@ -2464,17 +1971,32 @@ QTextCursor ClangdClient::Private::adjustedCursor(const QTextCursor &cursor,
if (!cppDoc)
return cursor;
const QList<AST *> builtinAstPath = ASTPath(cppDoc)(cursor);
+ if (builtinAstPath.isEmpty())
+ return cursor;
const TranslationUnit * const tu = cppDoc->translationUnit();
const auto posForToken = [doc, tu](int tok) {
int line, column;
tu->getTokenPosition(tok, &line, &column);
return Utils::Text::positionInText(doc->document(), line, column);
};
+ const auto endPosForToken = [doc, tu](int tok) {
+ int line, column;
+ tu->getTokenEndPosition(tok, &line, &column);
+ return Utils::Text::positionInText(doc->document(), line, column);
+ };
const auto leftMovedCursor = [cursor] {
QTextCursor c = cursor;
c.setPosition(cursor.position() - 1);
return c;
};
+
+ // enum E { v1|, v2 };
+ if (const EnumeratorAST * const enumAst = builtinAstPath.last()->asEnumerator()) {
+ if (endPosForToken(enumAst->identifier_token) == cursor.position())
+ return leftMovedCursor();
+ return cursor;
+ }
+
for (auto it = builtinAstPath.rbegin(); it != builtinAstPath.rend(); ++it) {
// s|.x or s|->x
@@ -2483,10 +2005,10 @@ QTextCursor ClangdClient::Private::adjustedCursor(const QTextCursor &cursor,
case T_DOT:
break;
case T_ARROW: {
- const Utils::optional<AstNode> clangdAst = astCache.get(doc);
+ const Utils::optional<ClangdAstNode> clangdAst = astCache.get(doc);
if (!clangdAst)
return cursor;
- const QList<AstNode> clangdAstPath = getAstPath(*clangdAst, Range(cursor));
+ const ClangdAstPath clangdAstPath = getAstPath(*clangdAst, Range(cursor));
for (auto it = clangdAstPath.rbegin(); it != clangdAstPath.rend(); ++it) {
if (it->detailIs("operator->") && it->arcanaContains("CXXMethod"))
return cursor;
@@ -2525,6 +2047,13 @@ QTextCursor ClangdClient::Private::adjustedCursor(const QTextCursor &cursor,
c.setPosition(posForToken(destrAst->tilde_token));
return c;
}
+
+ // QVector<QString|>
+ if (const TemplateIdAST * const templAst = (*it)->asTemplateId()) {
+ if (posForToken(templAst->greater_token) == cursor.position())
+ return leftMovedCursor();
+ return cursor;
+ }
}
return cursor;
}
@@ -2559,349 +2088,6 @@ void ClangdClient::Private::setHelpItemForTooltip(const MessageId &token, const
q->hoverHandler()->setHelpItem(token, helpItem);
}
-class ExtraHighlightingResultsCollector
-{
-public:
- ExtraHighlightingResultsCollector(QFutureInterface<HighlightingResult> &future,
- HighlightingResults &results,
- const Utils::FilePath &filePath, const AstNode &ast,
- const QTextDocument *doc, const QString &docContent);
-
- void collect();
-private:
- static bool lessThan(const HighlightingResult &r1, const HighlightingResult &r2);
- static int onlyIndexOf(const QStringView &text, const QStringView &subString, int from = 0);
- int posForNodeStart(const AstNode &node) const;
- int posForNodeEnd(const AstNode &node) const;
- void insertResult(const HighlightingResult &result);
- void insertResult(const AstNode &node, TextStyle style);
- void insertAngleBracketInfo(int searchStart1, int searchEnd1, int searchStart2, int searchEnd2);
- void setResultPosFromRange(HighlightingResult &result, const Range &range);
- void collectFromNode(const AstNode &node);
- void visitNode(const AstNode&node);
-
- QFutureInterface<HighlightingResult> &m_future;
- HighlightingResults &m_results;
- const Utils::FilePath m_filePath;
- const AstNode &m_ast;
- const QTextDocument * const m_doc;
- const QString &m_docContent;
- AstNode::FileStatus m_currentFileStatus = AstNode::FileStatus::Unknown;
-};
-
-// clangd reports also the #ifs, #elses and #endifs around the disabled code as disabled,
-// and not even in a consistent manner. We don't want this, so we have to clean up here.
-// But note that we require this behavior, as otherwise we would not be able to grey out
-// e.g. empty lines after an #ifdef, due to the lack of symbols.
-static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const QTextDocument *doc,
- const QString &docContent)
-{
- QList<BlockRange> ifdefedOutRanges;
- int rangeStartPos = -1;
- for (auto it = results.begin(); it != results.end();) {
- const bool wasIfdefedOut = rangeStartPos != -1;
- const bool isIfDefedOut = it->textStyles.mainStyle == C_DISABLED_CODE;
- if (!isIfDefedOut) {
- if (wasIfdefedOut) {
- const QTextBlock block = doc->findBlockByNumber(it->line - 1);
- ifdefedOutRanges << BlockRange(rangeStartPos, block.position());
- rangeStartPos = -1;
- }
- ++it;
- continue;
- }
-
- if (!wasIfdefedOut)
- rangeStartPos = doc->findBlockByNumber(it->line - 1).position();
-
- // Does the current line contain a potential "ifdefed-out switcher"?
- // If not, no state change is possible and we continue with the next line.
- const auto isPreprocessorControlStatement = [&] {
- const int pos = Utils::Text::positionInText(doc, it->line, it->column);
- const QStringView content = subViewLen(docContent, pos, it->length).trimmed();
- if (content.isEmpty() || content.first() != '#')
- return false;
- int offset = 1;
- while (offset < content.size() && content.at(offset).isSpace())
- ++offset;
- if (offset == content.size())
- return false;
- const QStringView ppDirective = content.mid(offset);
- return ppDirective.startsWith(QLatin1String("if"))
- || ppDirective.startsWith(QLatin1String("elif"))
- || ppDirective.startsWith(QLatin1String("else"))
- || ppDirective.startsWith(QLatin1String("endif"));
- };
- if (!isPreprocessorControlStatement()) {
- ++it;
- continue;
- }
-
- if (!wasIfdefedOut) {
- // The #if or #else that starts disabled code should not be disabled.
- const QTextBlock nextBlock = doc->findBlockByNumber(it->line);
- rangeStartPos = nextBlock.isValid() ? nextBlock.position() : -1;
- it = results.erase(it);
- continue;
- }
-
- if (wasIfdefedOut && (it + 1 == results.end()
- || (it + 1)->textStyles.mainStyle != C_DISABLED_CODE
- || (it + 1)->line != it->line + 1)) {
- // The #else or #endif that ends disabled code should not be disabled.
- const QTextBlock block = doc->findBlockByNumber(it->line - 1);
- ifdefedOutRanges << BlockRange(rangeStartPos, block.position());
- rangeStartPos = -1;
- it = results.erase(it);
- continue;
- }
- ++it;
- }
-
- if (rangeStartPos != -1)
- ifdefedOutRanges << BlockRange(rangeStartPos, doc->characterCount());
-
- qCDebug(clangdLogHighlight) << "found" << ifdefedOutRanges.size() << "ifdefed-out ranges";
- if (clangdLogHighlight().isDebugEnabled()) {
- for (const BlockRange &r : qAsConst(ifdefedOutRanges))
- qCDebug(clangdLogHighlight) << r.first() << r.last();
- }
-
- return ifdefedOutRanges;
-}
-
-static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
- const Utils::FilePath &filePath,
- const QList<ExpandedSemanticToken> &tokens,
- const QString &docContents, const AstNode &ast,
- const QPointer<TextDocument> &textDocument,
- int docRevision, const QVersionNumber &clangdVersion,
- const TaskTimer &taskTimer)
-{
- ThreadedSubtaskTimer t("highlighting", taskTimer);
- if (future.isCanceled()) {
- future.reportFinished();
- return;
- }
-
- const QTextDocument doc(docContents);
- const auto tokenRange = [&doc](const ExpandedSemanticToken &token) {
- const Position startPos(token.line - 1, token.column - 1);
- const Position endPos = startPos.withOffset(token.length, &doc);
- return Range(startPos, endPos);
- };
- const auto isOutputParameter = [&ast, &tokenRange](const ExpandedSemanticToken &token) {
- if (token.modifiers.contains(QLatin1String("usedAsMutableReference")))
- return true;
- if (token.type != "variable" && token.type != "property" && token.type != "parameter")
- return false;
- const Range range = tokenRange(token);
- const QList<AstNode> path = getAstPath(ast, range);
- if (path.size() < 2)
- return false;
- if (token.type == "property"
- && (path.rbegin()->kind() == "MemberInitializer"
- || path.rbegin()->kind() == "CXXConstruct")) {
- return false;
- }
- if (path.rbegin()->hasConstType())
- return false;
- for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
- if (it->kind() == "CXXConstruct" || it->kind() == "MemberInitializer")
- return true;
-
- if (it->kind() == "Call") {
- // The first child is e.g. a called lambda or an object on which
- // the call happens, and should not be highlighted as an output argument.
- // If the call is not fully resolved (as in templates), we don't
- // know whether the argument is passed as const or not.
- if (it->arcanaContains("dependent type"))
- return false;
- const QList<AstNode> children = it->children().value_or(QList<AstNode>());
- return children.isEmpty()
- || (children.first().range() != (it - 1)->range()
- && children.first().kind() != "UnresolvedLookup");
- }
-
- // The token should get marked for e.g. lambdas, but not for assignment operators,
- // where the user sees that it's being written.
- if (it->kind() == "CXXOperatorCall") {
- const QList<AstNode> children = it->children().value_or(QList<AstNode>());
-
- // Child 1 is the call itself, Child 2 is the named entity on which the call happens
- // (a lambda or a class instance), after that follow the actual call arguments.
- if (children.size() < 2)
- return false;
-
- // The call itself is never modifiable.
- if (children.first().range() == range)
- return false;
-
- // The callable is never displayed as an output parameter.
- // TODO: A good argument can be made to display objects on which a non-const
- // operator or function is called as output parameters.
- if (children.at(1).range().contains(range))
- return false;
-
- QList<AstNode> firstChildTree{children.first()};
- while (!firstChildTree.isEmpty()) {
- const AstNode n = firstChildTree.takeFirst();
- const QString detail = n.detail().value_or(QString());
- if (detail.startsWith("operator")) {
- return !detail.contains('=')
- && !detail.contains("++") && !detail.contains("--")
- && !detail.contains("<<") && !detail.contains(">>")
- && !detail.contains("*");
- }
- firstChildTree << n.children().value_or(QList<AstNode>());
- }
- return true;
- }
-
- if (it->kind() == "Lambda")
- return false;
- if (it->kind() == "BinaryOperator")
- return false;
- if (it->hasConstType())
- return false;
-
- if (it->kind() == "CXXMemberCall") {
- if (it == path.rbegin())
- return false;
- const QList<AstNode> children = it->children().value_or(QList<AstNode>());
- QTC_ASSERT(!children.isEmpty(), return false);
-
- // The called object is never displayed as an output parameter.
- // TODO: A good argument can be made to display objects on which a non-const
- // operator or function is called as output parameters.
- return (it - 1)->range() != children.first().range();
- }
-
- if (it->kind() == "Member" && it->arcanaContains("(")
- && !it->arcanaContains("bound member function type")) {
- return false;
- }
- }
- return false;
- };
-
- const std::function<HighlightingResult(const ExpandedSemanticToken &)> toResult
- = [&ast, &isOutputParameter, &clangdVersion, &tokenRange]
- (const ExpandedSemanticToken &token) {
- TextStyles styles;
- if (token.type == "variable") {
- if (token.modifiers.contains(QLatin1String("functionScope"))) {
- styles.mainStyle = C_LOCAL;
- } else if (token.modifiers.contains(QLatin1String("classScope"))) {
- styles.mainStyle = C_FIELD;
- } else if (token.modifiers.contains(QLatin1String("fileScope"))
- || token.modifiers.contains(QLatin1String("globalScope"))) {
- styles.mainStyle = C_GLOBAL;
- }
- } else if (token.type == "function" || token.type == "method") {
- styles.mainStyle = token.modifiers.contains(QLatin1String("virtual"))
- ? C_VIRTUAL_METHOD : C_FUNCTION;
- if (ast.isValid()) {
- const QList<AstNode> path = getAstPath(ast, tokenRange(token));
- if (path.length() > 1) {
- const AstNode declNode = path.at(path.length() - 2);
- if (declNode.kind() == "Function" || declNode.kind() == "CXXMethod") {
- if (clangdVersion < QVersionNumber(14)
- && declNode.arcanaContains("' virtual")) {
- styles.mainStyle = C_VIRTUAL_METHOD;
- }
- if (declNode.hasChildWithRole("statement"))
- styles.mixinStyles.push_back(C_FUNCTION_DEFINITION);
- }
- }
- }
- } else if (token.type == "class") {
- styles.mainStyle = C_TYPE;
-
- // clang hardly ever differentiates between constructors and the associated class,
- // whereas we highlight constructors as functions.
- if (ast.isValid()) {
- const QList<AstNode> path = getAstPath(ast, tokenRange(token));
- if (!path.isEmpty()) {
- if (path.last().kind() == "CXXConstructor") {
- if (!path.last().arcanaContains("implicit"))
- styles.mainStyle = C_FUNCTION;
- } else if (path.last().kind() == "Record" && path.length() > 1) {
- const AstNode node = path.at(path.length() - 2);
- if (node.kind() == "CXXDestructor" && !node.arcanaContains("implicit")) {
- styles.mainStyle = C_FUNCTION;
-
- // https://github.com/clangd/clangd/issues/872
- if (node.role() == "declaration")
- styles.mixinStyles.push_back(C_DECLARATION);
- }
- }
- }
- }
- } else if (token.type == "comment") { // "comment" means code disabled via the preprocessor
- styles.mainStyle = C_DISABLED_CODE;
- } else if (token.type == "namespace") {
- styles.mainStyle = C_NAMESPACE;
- } else if (token.type == "property") {
- styles.mainStyle = C_FIELD;
- } else if (token.type == "enum") {
- styles.mainStyle = C_TYPE;
- } else if (token.type == "enumMember") {
- styles.mainStyle = C_ENUMERATION;
- } else if (token.type == "parameter") {
- styles.mainStyle = C_PARAMETER;
- } else if (token.type == "macro") {
- styles.mainStyle = C_PREPROCESSOR;
- } else if (token.type == "type") {
- styles.mainStyle = C_TYPE;
- } else if (token.type == "typeParameter") {
- // clangd reports both type and non-type template parameters as type parameters,
- // but the latter can be distinguished by the readonly modifier.
- styles.mainStyle = token.modifiers.contains(QLatin1String("readonly"))
- ? C_PARAMETER : C_TYPE;
- }
- if (token.modifiers.contains(QLatin1String("declaration")))
- styles.mixinStyles.push_back(C_DECLARATION);
- if (token.modifiers.contains(QLatin1String("static"))) {
- if (styles.mainStyle != C_FIELD && styles.mainStyle != C_TEXT)
- styles.mixinStyles.push_back(styles.mainStyle);
- styles.mainStyle = C_STATIC_MEMBER;
- }
- if (isOutputParameter(token))
- styles.mixinStyles.push_back(C_OUTPUT_ARGUMENT);
- qCDebug(clangdLogHighlight) << "adding highlighting result"
- << token.line << token.column << token.length << int(styles.mainStyle);
- return HighlightingResult(token.line, token.column, token.length, styles);
- };
-
- auto results = QtConcurrent::blockingMapped<HighlightingResults>(tokens, toResult);
- const QList<BlockRange> ifdefedOutBlocks = cleanupDisabledCode(results, &doc, docContents);
- ExtraHighlightingResultsCollector(future, results, filePath, ast, &doc, docContents).collect();
- if (!future.isCanceled()) {
- qCDebug(clangdLog) << "reporting" << results.size() << "highlighting results";
- QMetaObject::invokeMethod(textDocument, [textDocument, ifdefedOutBlocks, docRevision] {
- if (textDocument && textDocument->document()->revision() == docRevision)
- textDocument->setIfdefedOutBlocks(ifdefedOutBlocks);
- }, Qt::QueuedConnection);
- QList<Range> virtualRanges;
- for (const HighlightingResult &r : results) {
- if (r.textStyles.mainStyle != C_VIRTUAL_METHOD)
- continue;
- const Position startPos(r.line - 1, r.column - 1);
- virtualRanges << Range(startPos, startPos.withOffset(r.length, &doc));
- }
- QMetaObject::invokeMethod(ClangModelManagerSupport::instance(),
- [filePath, virtualRanges, docRevision] {
- if (ClangdClient * const client
- = ClangModelManagerSupport::instance()->clientForFile(filePath)) {
- client->setVirtualRanges(filePath, virtualRanges, docRevision);
- }
- }, Qt::QueuedConnection);
- future.reportResults(QVector<HighlightingResult>(results.cbegin(), results.cend()));
- }
- future.reportFinished();
-}
-
// Unfortunately, clangd ignores almost everything except symbols when sending
// semantic token info, so we need to consult the AST for additional information.
// In particular, we inspect the following constructs:
@@ -2927,22 +2113,25 @@ void ClangdClient::Private::handleSemanticTokens(TextDocument *doc,
return;
}
force = force || isTesting;
- const auto previous = previousTokens.find(doc);
- if (previous != previousTokens.end()) {
- if (!force && previous->first == tokens && previous->second == version) {
+ const auto data = highlightingData.find(doc);
+ if (data != highlightingData.end()) {
+ if (!force && data->previousTokens.first == tokens
+ && data->previousTokens.second == version) {
qCInfo(clangdLogHighlight) << "tokens and version same as last time; nothing to do";
return;
}
- previous->first = tokens;
- previous->second = version;
+ data->previousTokens.first = tokens;
+ data->previousTokens.second = version;
} else {
- previousTokens.insert(doc, qMakePair(tokens, version));
+ HighlightingData data;
+ data.previousTokens = qMakePair(tokens, version);
+ highlightingData.insert(doc, data);
}
for (const ExpandedSemanticToken &t : tokens)
qCDebug(clangdLogHighlight()) << '\t' << t.line << t.column << t.length << t.type
<< t.modifiers;
- const auto astHandler = [this, tokens, doc, version](const AstNode &ast, const MessageId &) {
+ const auto astHandler = [this, tokens, doc, version](const ClangdAstNode &ast, const MessageId &) {
FinalizingSubtaskTimer t(highlightingTimer);
if (!q->documentOpen(doc))
return;
@@ -2959,7 +2148,7 @@ void ClangdClient::Private::handleSemanticTokens(TextDocument *doc,
doc = QPointer(doc), rev = doc->document()->revision(),
clangdVersion = q->versionNumber(),
this] {
- return Utils::runAsync(semanticHighlighter, filePath, tokens, text, ast, doc, rev,
+ return Utils::runAsync(doSemanticHighlighting, filePath, tokens, text, ast, doc, rev,
clangdVersion, highlightingTimer);
};
@@ -2974,125 +2163,37 @@ void ClangdClient::Private::handleSemanticTokens(TextDocument *doc,
return;
}
- auto it = highlighters.find(doc);
- if (it == highlighters.end()) {
- it = highlighters.insert(std::make_pair(doc, new CppEditor::SemanticHighlighter(doc)))
- .first;
- } else {
- it->second->updateFormatMapFromFontSettings();
- }
- it->second->setHighlightingRunner(runner);
- it->second->run();
+ auto &data = highlightingData[doc];
+ if (!data.highlighter)
+ data.highlighter = new CppEditor::SemanticHighlighter(doc);
+ else
+ data.highlighter->updateFormatMapFromFontSettings();
+ data.highlighter->setHighlightingRunner(runner);
+ data.highlighter->run();
};
getAndHandleAst(doc, astHandler, AstCallbackMode::SyncIfPossible);
}
-void ClangdClient::VirtualFunctionAssistProcessor::cancel()
-{
- resetData(true);
-}
-
-void ClangdClient::VirtualFunctionAssistProcessor::update()
-{
- if (!m_data->followSymbolData->editorWidget)
- return;
- setAsyncProposalAvailable(createProposal(false));
-}
-
-void ClangdClient::VirtualFunctionAssistProcessor::finalize()
-{
- if (!m_data->followSymbolData->editorWidget)
- return;
- const auto proposal = createProposal(true);
- if (m_data->followSymbolData->editorWidget->isInTestMode()) {
- m_data->followSymbolData->symbolsToDisplay.clear();
- const auto immediateProposal = createProposal(false);
- m_data->followSymbolData->editorWidget->setProposals(immediateProposal, proposal);
- } else {
- setAsyncProposalAvailable(proposal);
- }
- resetData(true);
-}
-
-void ClangdClient::VirtualFunctionAssistProcessor::resetData(bool resetFollowSymbolData)
-{
- if (!m_data)
- return;
- m_data->followSymbolData->virtualFuncAssistProcessor = nullptr;
- if (resetFollowSymbolData)
- m_data->followSymbolData.reset();
- m_data = nullptr;
-}
-
-IAssistProposal *ClangdClient::VirtualFunctionAssistProcessor::createProposal(bool final) const
-{
- QTC_ASSERT(m_data && m_data->followSymbolData, return nullptr);
-
- QList<AssistProposalItemInterface *> items;
- bool needsBaseDeclEntry = !m_data->followSymbolData->defLinkNode.range()
- .contains(Position(m_data->followSymbolData->cursor));
- for (const SymbolData &symbol : qAsConst(m_data->followSymbolData->symbolsToDisplay)) {
- Utils::Link link = symbol.second;
- if (m_data->followSymbolData->defLink == link) {
- if (!needsBaseDeclEntry)
- continue;
- needsBaseDeclEntry = false;
- } else {
- const Utils::Link defLink = m_data->followSymbolData->declDefMap.value(symbol.second);
- if (defLink.hasValidTarget())
- link = defLink;
- }
- items << createEntry(symbol.first, link);
- }
- if (needsBaseDeclEntry)
- items << createEntry({}, m_data->followSymbolData->defLink);
- if (!final) {
- const auto infoItem = new CppEditor::VirtualFunctionProposalItem({}, false);
- infoItem->setText(ClangdClient::tr("collecting overrides ..."));
- infoItem->setOrder(-1);
- items << infoItem;
- }
-
- return new CppEditor::VirtualFunctionProposal(
- m_data->followSymbolData->cursor.position(),
- items, m_data->followSymbolData->openInSplit);
-}
-
-CppEditor::VirtualFunctionProposalItem *
-ClangdClient::VirtualFunctionAssistProcessor::createEntry(const QString &name,
- const Utils::Link &link) const
-{
- const auto item = new CppEditor::VirtualFunctionProposalItem(
- link, m_data->followSymbolData->openInSplit);
- QString text = name;
- if (link == m_data->followSymbolData->defLink) {
- item->setOrder(1000); // Ensure base declaration is on top.
- if (text.isEmpty()) {
- text = ClangdClient::tr("<base declaration>");
- } else if (m_data->followSymbolData->defLinkNode.isPureVirtualDeclaration()
- || m_data->followSymbolData->defLinkNode.isPureVirtualDefinition()) {
- text += " = 0";
- }
- }
- item->setText(text);
- return item;
-}
-
-IAssistProcessor *ClangdClient::VirtualFunctionAssistProvider::createProcessor(
- const AssistInterface *) const
-{
- return m_data->followSymbolData->virtualFuncAssistProcessor
- = new VirtualFunctionAssistProcessor(m_data);
-}
-
Utils::optional<QList<CodeAction> > ClangdDiagnostic::codeActions() const
{
- return optionalArray<LanguageServerProtocol::CodeAction>("codeActions");
+ auto actions = optionalArray<LanguageServerProtocol::CodeAction>(u"codeActions");
+ if (!actions)
+ return actions;
+ static const QStringList badCodeActions{
+ "remove constant to silence this warning", // QTCREATORBUG-18593
+ };
+ for (auto it = actions->begin(); it != actions->end();) {
+ if (badCodeActions.contains(it->title()))
+ it = actions->erase(it);
+ else
+ ++it;
+ }
+ return actions;
}
QString ClangdDiagnostic::category() const
{
- return typedValue<QString>("category");
+ return typedValue<QString>(u"category");
}
class ClangdClient::ClangdFunctionHintProcessor : public FunctionHintProcessor
@@ -3151,16 +2252,10 @@ IAssistProcessor *ClangdClient::ClangdCompletionAssistProvider::createProcessor(
contextAnalyzer.positionEndOfExpression(),
contextAnalyzer.completionOperator(),
CustomAssistMode::Preprocessor);
- case ClangCompletionContextAnalyzer::CompleteIncludePath:
- if (m_client->versionNumber() < QVersionNumber(14)) { // https://reviews.llvm.org/D112996
- qCDebug(clangdLogCompletion) << "creating include processor";
- return new CustomAssistProcessor(m_client,
- contextAnalyzer.positionForProposal(),
- contextAnalyzer.positionEndOfExpression(),
- contextAnalyzer.completionOperator(),
- CustomAssistMode::IncludePath);
- }
- [[fallthrough]];
+ case ClangCompletionContextAnalyzer::CompleteSignal:
+ case ClangCompletionContextAnalyzer::CompleteSlot:
+ if (!interface->isBaseObject())
+ return CppEditor::getCppCompletionAssistProcessor();
default:
break;
}
@@ -3373,6 +2468,8 @@ ClangdCompletionItem::SpecialQtType ClangdCompletionItem::getQtType(const Comple
QIcon ClangdCompletionItem::icon() const
{
+ if (isDeprecated())
+ return Utils::Icons::WARNING.icon();
const SpecialQtType qtType = getQtType(item());
switch (qtType) {
case SpecialQtType::Signal:
@@ -3388,6 +2485,14 @@ QIcon ClangdCompletionItem::icon() const
return LanguageClientCompletionItem::icon();
}
+QString ClangdCompletionItem::text() const
+{
+ const QString clangdValue = LanguageClientCompletionItem::text();
+ if (isDeprecated())
+ return "[[deprecated]]" + clangdValue;
+ return clangdValue;
+}
+
MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
const AstHandler &astHandler,
AstCallbackMode callbackMode, const Range &range)
@@ -3417,48 +2522,10 @@ MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
}
// Otherwise retrieve the AST from clangd.
-
- class AstParams : public JsonObject
- {
- public:
- AstParams(const TextDocumentIdentifier &document, const Range &range = {})
- {
- setTextDocument(document);
- if (range.isValid())
- setRange(range);
- }
-
- using JsonObject::JsonObject;
-
- // The open file to inspect.
- TextDocumentIdentifier textDocument() const
- { return typedValue<TextDocumentIdentifier>(textDocumentKey); }
- void setTextDocument(const TextDocumentIdentifier &id) { insert(textDocumentKey, id); }
-
- // The region of the source code whose AST is fetched. The highest-level node that entirely
- // contains the range is returned.
- Utils::optional<Range> range() const { return optionalValue<Range>(rangeKey); }
- void setRange(const Range &range) { insert(rangeKey, range); }
-
- bool isValid() const override { return contains(textDocumentKey); }
- };
-
- class AstRequest : public Request<AstNode, std::nullptr_t, AstParams>
- {
- public:
- using Request::Request;
- explicit AstRequest(const AstParams &params) : Request("textDocument/ast", params) {}
- };
-
- AstRequest request(AstParams(TextDocumentIdentifier(DocumentUri::fromFilePath(filePath)),
- range));
- request.setResponseCallback([this, filePath, guardedTextDoc = QPointer(textDoc), astHandler,
- fullAstRequested, docRev = textDoc ? getRevision(textDoc) : -1,
- fileRev = getRevision(filePath), reqId = request.id()]
- (AstRequest::Response response) {
+ const auto wrapperHandler = [this, filePath, guardedTextDoc = QPointer(textDoc), astHandler,
+ fullAstRequested, docRev = textDoc ? getRevision(textDoc) : -1,
+ fileRev = getRevision(filePath)](const ClangdAstNode &ast, const MessageId &reqId) {
qCDebug(clangdLog) << "retrieved AST from clangd";
- const auto result = response.result();
- const AstNode ast = result ? *result : AstNode();
if (fullAstRequested) {
if (guardedTextDoc) {
if (docRev == getRevision(guardedTextDoc))
@@ -3468,555 +2535,9 @@ MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
}
}
astHandler(ast, reqId);
- });
- qCDebug(clangdLog) << "requesting AST for" << filePath;
- q->sendContent(request, SendDocUpdates::Ignore);
- return request.id();
-}
-
-ExtraHighlightingResultsCollector::ExtraHighlightingResultsCollector(
- QFutureInterface<HighlightingResult> &future, HighlightingResults &results,
- const Utils::FilePath &filePath, const AstNode &ast, const QTextDocument *doc,
- const QString &docContent)
- : m_future(future), m_results(results), m_filePath(filePath), m_ast(ast), m_doc(doc),
- m_docContent(docContent)
-{
-}
-
-void ExtraHighlightingResultsCollector::collect()
-{
- for (int i = 0; i < m_results.length(); ++i) {
- const HighlightingResult res = m_results.at(i);
- if (res.textStyles.mainStyle != C_PREPROCESSOR || res.length != 10)
- continue;
- const int pos = Utils::Text::positionInText(m_doc, res.line, res.column);
- if (subViewLen(m_docContent, pos, 10) != QLatin1String("Q_PROPERTY"))
- continue;
- int endPos;
- if (i < m_results.length() - 1) {
- const HighlightingResult nextRes = m_results.at(i + 1);
- endPos = Utils::Text::positionInText(m_doc, nextRes.line, nextRes.column);
- } else {
- endPos = m_docContent.length();
- }
- const QString qPropertyString = m_docContent.mid(pos, endPos - pos);
- QPropertyHighlighter propHighlighter(m_doc, qPropertyString, pos);
- for (const HighlightingResult &newRes : propHighlighter.highlight())
- m_results.insert(++i, newRes);
- }
-
- if (!m_ast.isValid())
- return;
- visitNode(m_ast);
-}
-
-bool ExtraHighlightingResultsCollector::lessThan(const HighlightingResult &r1,
- const HighlightingResult &r2)
-{
- return r1.line < r2.line || (r1.line == r2.line && r1.column < r2.column)
- || (r1.line == r2.line && r1.column == r2.column && r1.length < r2.length);
-}
-
-int ExtraHighlightingResultsCollector::onlyIndexOf(const QStringView &text,
- const QStringView &subString, int from)
-{
- const int firstIndex = text.indexOf(subString, from);
- if (firstIndex == -1)
- return -1;
- const int nextIndex = text.indexOf(subString, firstIndex + 1);
-
- // The second condion deals with the off-by-one error in TemplateSpecialization nodes;
- // see collectFromNode().
- return nextIndex == -1 || nextIndex == firstIndex + 1 ? firstIndex : -1;
-}
-
-// Unfortunately, the exact position of a specific token is usually not
-// recorded in the AST, so if we need that, we have to search for it textually.
-// In corner cases, this might get sabotaged by e.g. comments, in which case we give up.
-int ExtraHighlightingResultsCollector::posForNodeStart(const AstNode &node) const
-{
- return Utils::Text::positionInText(m_doc, node.range().start().line() + 1,
- node.range().start().character() + 1);
-}
-
-int ExtraHighlightingResultsCollector::posForNodeEnd(const AstNode &node) const
-{
- return Utils::Text::positionInText(m_doc, node.range().end().line() + 1,
- node.range().end().character() + 1);
-}
-
-void ExtraHighlightingResultsCollector::insertResult(const HighlightingResult &result)
-{
- if (!result.isValid()) // Some nodes don't have a range.
- return;
- const auto it = std::lower_bound(m_results.begin(), m_results.end(), result, lessThan);
- if (it == m_results.end() || *it != result) {
-
- // Prevent inserting expansions for function-like macros. For instance:
- // #define TEST() "blubb"
- // const char *s = TEST();
- // The macro name is always shorter than the expansion and starts at the same
- // location, so it should occur right before the insertion position.
- if (it > m_results.begin() && (it - 1)->line == result.line
- && (it - 1)->column == result.column
- && (it - 1)->textStyles.mainStyle == C_PREPROCESSOR) {
- return;
- }
-
- qCDebug(clangdLogHighlight) << "adding additional highlighting result"
- << result.line << result.column << result.length;
- m_results.insert(it, result);
- return;
- }
-
- // This is for conversion operators, whose type part is only reported as a type by clangd.
- if ((it->textStyles.mainStyle == C_TYPE
- || it->textStyles.mainStyle == C_PRIMITIVE_TYPE)
- && !result.textStyles.mixinStyles.empty()
- && result.textStyles.mixinStyles.at(0) == C_OPERATOR) {
- it->textStyles.mixinStyles = result.textStyles.mixinStyles;
- }
-}
-
-void ExtraHighlightingResultsCollector::insertResult(const AstNode &node, TextStyle style)
-{
- HighlightingResult result;
- result.useTextSyles = true;
- result.textStyles.mainStyle = style;
- setResultPosFromRange(result, node.range());
- insertResult(result);
- return;
-}
-
-// For matching the "<" and ">" brackets of template declarations, specializations
-// and instantiations.
-void ExtraHighlightingResultsCollector::insertAngleBracketInfo(int searchStart1, int searchEnd1,
- int searchStart2, int searchEnd2)
-{
- const int openingAngleBracketPos = onlyIndexOf(
- subViewEnd(m_docContent, searchStart1, searchEnd1),
- QStringView(QStringLiteral("<")));
- if (openingAngleBracketPos == -1)
- return;
- const int absOpeningAngleBracketPos = searchStart1 + openingAngleBracketPos;
- if (absOpeningAngleBracketPos > searchStart2)
- searchStart2 = absOpeningAngleBracketPos + 1;
- if (searchStart2 >= searchEnd2)
- return;
- const int closingAngleBracketPos = onlyIndexOf(
- subViewEnd(m_docContent, searchStart2, searchEnd2),
- QStringView(QStringLiteral(">")));
- if (closingAngleBracketPos == -1)
- return;
-
- const int absClosingAngleBracketPos = searchStart2 + closingAngleBracketPos;
- if (absOpeningAngleBracketPos > absClosingAngleBracketPos)
- return;
-
- HighlightingResult result;
- result.useTextSyles = true;
- result.textStyles.mainStyle = C_PUNCTUATION;
- Utils::Text::convertPosition(m_doc, absOpeningAngleBracketPos, &result.line, &result.column);
- result.length = 1;
- result.kind = CppEditor::SemanticHighlighter::AngleBracketOpen;
- insertResult(result);
- Utils::Text::convertPosition(m_doc, absClosingAngleBracketPos, &result.line, &result.column);
- result.kind = CppEditor::SemanticHighlighter::AngleBracketClose;
- insertResult(result);
-}
-
-void ExtraHighlightingResultsCollector::setResultPosFromRange(HighlightingResult &result,
- const Range &range)
-{
- if (!range.isValid())
- return;
- const Position startPos = range.start();
- const Position endPos = range.end();
- result.line = startPos.line() + 1;
- result.column = startPos.character() + 1;
- result.length = endPos.toPositionInDocument(m_doc) - startPos.toPositionInDocument(m_doc);
-}
-
-void ExtraHighlightingResultsCollector::collectFromNode(const AstNode &node)
-{
- if (node.kind() == "UserDefinedLiteral")
- return;
- if (node.kind().endsWith("Literal")) {
- const bool isKeyword = node.kind() == "CXXBoolLiteral"
- || node.kind() == "CXXNullPtrLiteral";
- const bool isStringLike = !isKeyword && (node.kind().startsWith("String")
- || node.kind().startsWith("Character"));
- const TextStyle style = isKeyword ? C_KEYWORD : isStringLike ? C_STRING : C_NUMBER;
- insertResult(node, style);
- return;
- }
- if (node.role() == "type" && node.kind() == "Builtin") {
- insertResult(node, C_PRIMITIVE_TYPE);
- return;
- }
- if (node.role() == "attribute" && (node.kind() == "Override" || node.kind() == "Final")) {
- insertResult(node, C_KEYWORD);
- return;
- }
-
- const bool isExpression = node.role() == "expression";
- if (isExpression && node.kind() == "Predefined") {
- insertResult(node, C_PREPROCESSOR);
- return;
- }
-
- const bool isDeclaration = node.role() == "declaration";
- const int nodeStartPos = posForNodeStart(node);
- const int nodeEndPos = posForNodeEnd(node);
- const QList<AstNode> children = node.children().value_or(QList<AstNode>());
-
- // Match question mark and colon in ternary operators.
- if (isExpression && node.kind() == "ConditionalOperator") {
- if (children.size() != 3)
- return;
-
- // The question mark is between sub-expressions 1 and 2, the colon is between
- // sub-expressions 2 and 3.
- const int searchStartPosQuestionMark = posForNodeEnd(children.first());
- const int searchEndPosQuestionMark = posForNodeStart(children.at(1));
- QStringView content = subViewEnd(m_docContent, searchStartPosQuestionMark,
- searchEndPosQuestionMark);
- const int questionMarkPos = onlyIndexOf(content, QStringView(QStringLiteral("?")));
- if (questionMarkPos == -1)
- return;
- const int searchStartPosColon = posForNodeEnd(children.at(1));
- const int searchEndPosColon = posForNodeStart(children.at(2));
- content = subViewEnd(m_docContent, searchStartPosColon, searchEndPosColon);
- const int colonPos = onlyIndexOf(content, QStringView(QStringLiteral(":")));
- if (colonPos == -1)
- return;
-
- const int absQuestionMarkPos = searchStartPosQuestionMark + questionMarkPos;
- const int absColonPos = searchStartPosColon + colonPos;
- if (absQuestionMarkPos > absColonPos)
- return;
-
- HighlightingResult result;
- result.useTextSyles = true;
- result.textStyles.mainStyle = C_PUNCTUATION;
- result.textStyles.mixinStyles.push_back(C_OPERATOR);
- Utils::Text::convertPosition(m_doc, absQuestionMarkPos, &result.line, &result.column);
- result.length = 1;
- result.kind = CppEditor::SemanticHighlighter::TernaryIf;
- insertResult(result);
- Utils::Text::convertPosition(m_doc, absColonPos, &result.line, &result.column);
- result.kind = CppEditor::SemanticHighlighter::TernaryElse;
- insertResult(result);
- return;
- }
-
- if (isDeclaration && (node.kind() == "FunctionTemplate"
- || node.kind() == "ClassTemplate")) {
- // The child nodes are the template parameters and and the function or class.
- // The opening angle bracket is before the first child node, the closing angle
- // bracket is before the function child node and after the last param node.
- const QString classOrFunctionKind = QLatin1String(node.kind() == "FunctionTemplate"
- ? "Function" : "CXXRecord");
- const auto functionOrClassIt = std::find_if(children.begin(), children.end(),
- [&classOrFunctionKind](const AstNode &n) {
- return n.role() == "declaration" && n.kind() == classOrFunctionKind;
- });
- if (functionOrClassIt == children.end() || functionOrClassIt == children.begin())
- return;
- const int firstTemplateParamStartPos = posForNodeStart(children.first());
- const int lastTemplateParamEndPos = posForNodeEnd(*(functionOrClassIt - 1));
- const int functionOrClassStartPos = posForNodeStart(*functionOrClassIt);
- insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
- lastTemplateParamEndPos, functionOrClassStartPos);
- return;
- }
-
- const auto isTemplateParamDecl = [](const AstNode &node) {
- return node.isTemplateParameterDeclaration();
- };
- if (isDeclaration && node.kind() == "TypeAliasTemplate") {
- // Children are one node of type TypeAlias and the template parameters.
- // The opening angle bracket is before the first parameter and the closing
- // angle bracket is after the last parameter.
- // The TypeAlias node seems to appear first in the AST, even though lexically
- // is comes after the parameters. We don't rely on the order here.
- // Note that there is a second pair of angle brackets. That one is part of
- // a TemplateSpecialization, which is handled further below.
- const auto firstTemplateParam = std::find_if(children.begin(), children.end(),
- isTemplateParamDecl);
- if (firstTemplateParam == children.end())
- return;
- const auto lastTemplateParam = std::find_if(children.rbegin(), children.rend(),
- isTemplateParamDecl);
- QTC_ASSERT(lastTemplateParam != children.rend(), return);
- const auto typeAlias = std::find_if(children.begin(), children.end(),
- [](const AstNode &n) { return n.kind() == "TypeAlias"; });
- if (typeAlias == children.end())
- return;
-
- const int firstTemplateParamStartPos = posForNodeStart(*firstTemplateParam);
- const int lastTemplateParamEndPos = posForNodeEnd(*lastTemplateParam);
- const int searchEndPos = posForNodeStart(*typeAlias);
- insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
- lastTemplateParamEndPos, searchEndPos);
- return;
- }
-
- if (isDeclaration && node.kind() == "ClassTemplateSpecialization") {
- // There is one child of kind TemplateSpecialization. The first pair
- // of angle brackets comes before that.
- if (children.size() == 1) {
- const int childNodePos = posForNodeStart(children.first());
- insertAngleBracketInfo(nodeStartPos, childNodePos, nodeStartPos, childNodePos);
- }
- return;
- }
-
- if (isDeclaration && node.kind() == "TemplateTemplateParm") {
- // The child nodes are template arguments and template parameters.
- // Arguments seem to appear before parameters in the AST, even though they
- // come after them in the source code. We don't rely on the order here.
- const auto firstTemplateParam = std::find_if(children.begin(), children.end(),
- isTemplateParamDecl);
- if (firstTemplateParam == children.end())
- return;
- const auto lastTemplateParam = std::find_if(children.rbegin(), children.rend(),
- isTemplateParamDecl);
- QTC_ASSERT(lastTemplateParam != children.rend(), return);
- const auto templateArg = std::find_if(children.begin(), children.end(),
- [](const AstNode &n) { return n.role() == "template argument"; });
-
- const int firstTemplateParamStartPos = posForNodeStart(*firstTemplateParam);
- const int lastTemplateParamEndPos = posForNodeEnd(*lastTemplateParam);
- const int searchEndPos = templateArg == children.end()
- ? nodeEndPos : posForNodeStart(*templateArg);
- insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
- lastTemplateParamEndPos, searchEndPos);
- return;
- }
-
- // {static,dynamic,reinterpret}_cast<>().
- if (isExpression && node.kind().startsWith("CXX") && node.kind().endsWith("Cast")) {
- // First child is type, second child is expression.
- // The opening angle bracket is before the first child, the closing angle bracket
- // is between the two children.
- if (children.size() == 2) {
- insertAngleBracketInfo(nodeStartPos, posForNodeStart(children.first()),
- posForNodeEnd(children.first()),
- posForNodeStart(children.last()));
- }
- return;
- }
-
- if (node.kind() == "TemplateSpecialization") {
- // First comes the template type, then the template arguments.
- // The opening angle bracket is before the first template argument,
- // the closing angle bracket is after the last template argument.
- // The first child node has no range, so we start searching at the parent node.
- if (children.size() >= 2) {
- int searchStart2 = posForNodeEnd(children.last());
- int searchEnd2 = nodeEndPos;
-
- // There is a weird off-by-one error on the clang side: If there is a
- // nested template instantiation *and* there is no space between
- // the closing angle brackets, then the inner TemplateSpecialization node's range
- // will extend one character too far, covering the outer's closing angle bracket.
- // This is what we are correcting for here.
- // This issue is tracked at https://github.com/clangd/clangd/issues/871.
- if (searchStart2 == searchEnd2)
- --searchStart2;
- insertAngleBracketInfo(nodeStartPos, posForNodeStart(children.at(1)),
- searchStart2, searchEnd2);
- }
- return;
- }
-
- if (!isExpression && !isDeclaration)
- return;
-
- // Operators, overloaded ones in particular.
- static const QString operatorPrefix = "operator";
- QString detail = node.detail().value_or(QString());
- const bool isCallToNew = node.kind() == "CXXNew";
- const bool isCallToDelete = node.kind() == "CXXDelete";
- const auto isProperOperator = [&] {
- if (isCallToNew || isCallToDelete)
- return true;
- if (!detail.startsWith(operatorPrefix))
- return false;
- if (detail == operatorPrefix)
- return false;
- const QChar nextChar = detail.at(operatorPrefix.length());
- return !nextChar.isLetterOrNumber() && nextChar != '_';
};
- if (!isProperOperator())
- return;
-
- if (!isCallToNew && !isCallToDelete)
- detail.remove(0, operatorPrefix.length());
-
- HighlightingResult result;
- result.useTextSyles = true;
- const bool isConversionOp = node.kind() == "CXXConversion";
- const bool isOverloaded = !isConversionOp
- && (isDeclaration || ((!isCallToNew && !isCallToDelete)
- || node.arcanaContains("CXXMethod")));
- result.textStyles.mainStyle = isConversionOp
- ? C_PRIMITIVE_TYPE
- : isCallToNew || isCallToDelete || detail.at(0).isSpace()
- ? C_KEYWORD : C_PUNCTUATION;
- result.textStyles.mixinStyles.push_back(C_OPERATOR);
- if (isOverloaded)
- result.textStyles.mixinStyles.push_back(C_OVERLOADED_OPERATOR);
- if (isDeclaration)
- result.textStyles.mixinStyles.push_back(C_DECLARATION);
-
- const QStringView nodeText = subViewEnd(m_docContent, nodeStartPos, nodeEndPos);
-
- if (isCallToNew || isCallToDelete) {
- result.line = node.range().start().line() + 1;
- result.column = node.range().start().character() + 1;
- result.length = isCallToNew ? 3 : 6;
- insertResult(result);
- if (node.arcanaContains("array")) {
- const int openingBracketOffset = nodeText.indexOf('[');
- if (openingBracketOffset == -1)
- return;
- const int closingBracketOffset = nodeText.lastIndexOf(']');
- if (closingBracketOffset == -1 || closingBracketOffset < openingBracketOffset)
- return;
-
- result.textStyles.mainStyle = C_PUNCTUATION;
- result.length = 1;
- Utils::Text::convertPosition(m_doc,
- nodeStartPos + openingBracketOffset,
- &result.line, &result.column);
- insertResult(result);
- Utils::Text::convertPosition(m_doc,
- nodeStartPos + closingBracketOffset,
- &result.line, &result.column);
- insertResult(result);
- }
- return;
- }
-
- if (isExpression && (detail == QLatin1String("()") || detail == QLatin1String("[]"))) {
- result.line = node.range().start().line() + 1;
- result.column = node.range().start().character() + 1;
- result.length = 1;
- insertResult(result);
- result.line = node.range().end().line() + 1;
- result.column = node.range().end().character();
- insertResult(result);
- return;
- }
-
- const int opStringLen = detail.at(0).isSpace() ? detail.length() - 1 : detail.length();
-
- // The simple case: Call to operator+, +=, * etc.
- if (nodeEndPos - nodeStartPos == opStringLen) {
- setResultPosFromRange(result, node.range());
- insertResult(result);
- return;
- }
-
- const int prefixOffset = nodeText.indexOf(operatorPrefix);
- if (prefixOffset == -1)
- return;
-
- const bool isArray = detail == "[]";
- const bool isCall = detail == "()";
- const bool isArrayNew = detail == " new[]";
- const bool isArrayDelete = detail == " delete[]";
- const QStringView searchTerm = isArray || isCall
- ? QStringView(detail).chopped(1) : isArrayNew || isArrayDelete
- ? QStringView(detail).chopped(2) : detail;
- const int opStringOffset = nodeText.indexOf(searchTerm, prefixOffset
- + operatorPrefix.length());
- if (opStringOffset == -1 || nodeText.indexOf(operatorPrefix, opStringOffset) != -1)
- return;
-
- const int opStringOffsetInDoc = nodeStartPos + opStringOffset
- + detail.length() - opStringLen;
- Utils::Text::convertPosition(m_doc, opStringOffsetInDoc, &result.line, &result.column);
- result.length = opStringLen;
- if (isArray || isCall)
- result.length = 1;
- else if (isArrayNew || isArrayDelete)
- result.length -= 2;
- if (!isArray && !isCall)
- insertResult(result);
- if (!isArray && !isCall && !isArrayNew && !isArrayDelete)
- return;
-
- result.textStyles.mainStyle = C_PUNCTUATION;
- result.length = 1;
- const int openingParenOffset = nodeText.indexOf(
- isCall ? '(' : '[', prefixOffset + operatorPrefix.length());
- if (openingParenOffset == -1)
- return;
- const int closingParenOffset = nodeText.indexOf(isCall ? ')' : ']', openingParenOffset + 1);
- if (closingParenOffset == -1 || closingParenOffset < openingParenOffset)
- return;
- Utils::Text::convertPosition(m_doc, nodeStartPos + openingParenOffset,
- &result.line, &result.column);
- insertResult(result);
- Utils::Text::convertPosition(m_doc, nodeStartPos + closingParenOffset,
- &result.line, &result.column);
- insertResult(result);
-}
-
-void ExtraHighlightingResultsCollector::visitNode(const AstNode &node)
-{
- if (m_future.isCanceled())
- return;
- const AstNode::FileStatus prevFileStatus = m_currentFileStatus;
- m_currentFileStatus = node.fileStatus(m_filePath);
- if (m_currentFileStatus == AstNode::FileStatus::Unknown
- && prevFileStatus != AstNode::FileStatus::Ours) {
- m_currentFileStatus = prevFileStatus;
- }
- switch (m_currentFileStatus) {
- case AstNode::FileStatus::Ours:
- case AstNode::FileStatus::Unknown:
- collectFromNode(node);
- [[fallthrough]];
- case AstNode::FileStatus::Foreign:
- case ClangCodeModel::Internal::AstNode::FileStatus::Mixed: {
- const auto children = node.children();
- if (!children)
- return;
- for (const AstNode &childNode : *children)
- visitNode(childNode);
- break;
- }
- }
- m_currentFileStatus = prevFileStatus;
-}
-
-bool ClangdClient::FollowSymbolData::defLinkIsAmbiguous() const
-{
- // Even if the call is to a virtual function, it might not be ambiguous:
- // class A { virtual void f(); }; class B : public A { void f() override { A::f(); } };
- if (!cursorNode->mightBeAmbiguousVirtualCall() && !cursorNode->isPureVirtualDeclaration())
- return false;
-
- // If we have up-to-date highlighting info, we know whether we are dealing with
- // a virtual call.
- if (editorWidget) {
- const auto virtualRanges = q->d->virtualRanges.constFind(editorWidget->textDocument());
- if (virtualRanges != q->d->virtualRanges.constEnd()
- && virtualRanges->second == docRevision) {
- const auto matcher = [cursorRange = cursorNode->range()](const Range &r) {
- return cursorRange.overlaps(r);
- };
- return Utils::contains(virtualRanges->first, matcher);
- }
- }
-
- // Otherwise, we accept potentially doing more work than needed rather than not catching
- // possible overrides.
- return true;
+ qCDebug(clangdLog) << "requesting AST for" << filePath;
+ return requestAst(q, filePath, range, wrapperHandler);
}
class MemoryTree : public JsonObject
@@ -4150,7 +2671,7 @@ void MemoryUsageWidget::getMemoryTree()
});
qCDebug(clangdLog) << "sending memory usage request";
m_currentRequest = request.id();
- m_client->sendContent(request, ClangdClient::SendDocUpdates::Ignore);
+ m_client->sendMessage(request, ClangdClient::SendDocUpdates::Ignore);
}
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h
index cc4b6aa71e9..850d6b41285 100644
--- a/src/plugins/clangcodemodel/clangdclient.h
+++ b/src/plugins/clangcodemodel/clangdclient.h
@@ -25,23 +25,35 @@
#pragma once
+#include <coreplugin/find/searchresultitem.h>
#include <cppeditor/baseeditordocumentparser.h>
#include <cppeditor/cppcodemodelsettings.h>
-#include <cppeditor/refactoringengineinterface.h>
+#include <cppeditor/cursorineditor.h>
#include <languageclient/client.h>
#include <utils/link.h>
#include <utils/optional.h>
#include <QVersionNumber>
-namespace Core { class SearchResultItem; }
namespace CppEditor { class CppEditorWidget; }
namespace LanguageServerProtocol { class Range; }
-namespace ProjectExplorer { class Project; }
-namespace TextEditor { class BaseTextEditor; }
+namespace ProjectExplorer {
+class Project;
+class Task;
+}
+namespace TextEditor {
+class BaseTextEditor;
+class IAssistProposal;
+}
namespace ClangCodeModel {
namespace Internal {
+class ClangdAstNode;
+
+Q_DECLARE_LOGGING_CATEGORY(clangdLog);
+Q_DECLARE_LOGGING_CATEGORY(clangdLogAst);
+
+void setupClangdConfigFile();
class ClangdClient : public LanguageClient::Client
{
@@ -62,17 +74,18 @@ public:
void followSymbol(TextEditor::TextDocument *document,
const QTextCursor &cursor,
CppEditor::CppEditorWidget *editorWidget,
- Utils::ProcessLinkCallback &&callback,
+ const Utils::LinkHandler &callback,
bool resolveTarget,
bool openInSplit);
void switchDeclDef(TextEditor::TextDocument *document,
const QTextCursor &cursor,
CppEditor::CppEditorWidget *editorWidget,
- Utils::ProcessLinkCallback &&callback);
+ const Utils::LinkHandler &callback);
+ void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit);
void findLocalUsages(TextEditor::TextDocument *document, const QTextCursor &cursor,
- CppEditor::RefactoringEngineInterface::RenameCallback &&callback);
+ CppEditor::RenameCallback &&callback);
void gatherHelpItemForTooltip(
const LanguageServerProtocol::HoverRequest::Response &hoverResponse,
@@ -91,6 +104,27 @@ public:
void updateParserConfig(const Utils::FilePath &filePath,
const CppEditor::BaseEditorDocumentParser::Configuration &config);
+ void switchIssuePaneEntries(const Utils::FilePath &filePath);
+ void addTask(const ProjectExplorer::Task &task);
+ void clearTasks(const Utils::FilePath &filePath);
+ Utils::optional<bool> hasVirtualFunctionAt(TextEditor::TextDocument *doc, int revision,
+ const LanguageServerProtocol::Range &range);
+
+ using TextDocOrFile = Utils::variant<const TextEditor::TextDocument *, Utils::FilePath>;
+ using AstHandler = std::function<void(const ClangdAstNode &ast,
+ const LanguageServerProtocol::MessageId &)>;
+ enum class AstCallbackMode { SyncIfPossible, AlwaysAsync };
+ LanguageServerProtocol::MessageId getAndHandleAst(const TextDocOrFile &doc,
+ const AstHandler &astHandler,
+ AstCallbackMode callbackMode,
+ const LanguageServerProtocol::Range &range);
+
+ using SymbolInfoHandler = std::function<void(const QString &name, const QString &prefix,
+ const LanguageServerProtocol::MessageId &)>;
+ LanguageServerProtocol::MessageId requestSymbolInfo(
+ const Utils::FilePath &filePath,
+ const LanguageServerProtocol::Position &position,
+ const SymbolInfoHandler &handler);
signals:
void indexingFinished();
@@ -109,9 +143,12 @@ private:
QTextCursor adjustedCursorForHighlighting(const QTextCursor &cursor,
TextEditor::TextDocument *doc) override;
const CustomInspectorTabs createCustomInspectorTabs() override;
+ TextEditor::RefactoringChangesData *createRefactoringChangesBackend() const override;
+ LanguageClient::DiagnosticManager *createDiagnosticManager() override;
+ bool referencesShadowFile(const TextEditor::TextDocument *doc,
+ const Utils::FilePath &candidate) override;
class Private;
- class FollowSymbolData;
class VirtualFunctionAssistProcessor;
class VirtualFunctionAssistProvider;
class ClangdFunctionHintProcessor;
diff --git a/src/plugins/clangcodemodel/clangdfollowsymbol.cpp b/src/plugins/clangcodemodel/clangdfollowsymbol.cpp
new file mode 100644
index 00000000000..a0e6aae6108
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdfollowsymbol.cpp
@@ -0,0 +1,527 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangdfollowsymbol.h"
+
+#include "clangdast.h"
+#include "clangdclient.h"
+
+#include <cppeditor/cppeditorwidget.h>
+#include <cppeditor/cppvirtualfunctionassistprovider.h>
+#include <cppeditor/cppvirtualfunctionproposalitem.h>
+#include <languageclient/languageclientsymbolsupport.h>
+#include <languageserverprotocol/lsptypes.h>
+#include <languageserverprotocol/jsonrpcmessages.h>
+#include <texteditor/codeassist/iassistprocessor.h>
+#include <texteditor/codeassist/iassistprovider.h>
+#include <texteditor/textdocument.h>
+
+#include <QApplication>
+#include <QPointer>
+
+using namespace CppEditor;
+using namespace LanguageServerProtocol;
+using namespace TextEditor;
+using namespace Utils;
+
+namespace ClangCodeModel::Internal {
+using SymbolData = QPair<QString, Link>;
+using SymbolDataList = QList<SymbolData>;
+
+class ClangdFollowSymbol::VirtualFunctionAssistProcessor : public IAssistProcessor
+{
+public:
+ VirtualFunctionAssistProcessor(ClangdFollowSymbol *followSymbol)
+ : m_followSymbol(followSymbol) {}
+
+ void cancel() override { resetData(true); }
+ bool running() override { return m_followSymbol; }
+ void update();
+ void finalize();
+ void resetData(bool resetFollowSymbolData);
+
+private:
+ IAssistProposal *perform(const AssistInterface *) override
+ {
+ return nullptr;
+ }
+
+ IAssistProposal *immediateProposal(const AssistInterface *) override
+ {
+ return createProposal(false);
+ }
+
+ IAssistProposal *immediateProposalImpl() const;
+ IAssistProposal *createProposal(bool final) const;
+ VirtualFunctionProposalItem *createEntry(const QString &name, const Link &link) const;
+
+ QPointer<ClangdFollowSymbol> m_followSymbol;
+};
+
+class ClangdFollowSymbol::VirtualFunctionAssistProvider : public IAssistProvider
+{
+public:
+ VirtualFunctionAssistProvider(ClangdFollowSymbol *followSymbol)
+ : m_followSymbol(followSymbol) {}
+
+private:
+ RunType runType() const override { return Asynchronous; }
+ IAssistProcessor *createProcessor(const AssistInterface *) const override;
+
+ const QPointer<ClangdFollowSymbol> m_followSymbol;
+};
+
+class ClangdFollowSymbol::Private
+{
+public:
+ Private(ClangdFollowSymbol *q, ClangdClient *client, const QTextCursor &cursor,
+ CppEditorWidget *editorWidget, const FilePath &filePath, const LinkHandler &callback,
+ bool openInSplit)
+ : q(q), client(client), cursor(cursor), editorWidget(editorWidget),
+ uri(DocumentUri::fromFilePath(filePath)), callback(callback),
+ virtualFuncAssistProvider(q),
+ docRevision(editorWidget ? editorWidget->textDocument()->document()->revision() : -1),
+ openInSplit(openInSplit) {}
+
+ void handleGotoDefinitionResult();
+ void sendGotoImplementationRequest(const Utils::Link &link);
+ void handleGotoImplementationResult(const GotoImplementationRequest::Response &response);
+ void handleDocumentInfoResults();
+ void closeTempDocuments();
+ bool addOpenFile(const FilePath &filePath);
+ bool defLinkIsAmbiguous() const;
+
+ ClangdFollowSymbol * const q;
+ ClangdClient * const client;
+ const QTextCursor cursor;
+ const QPointer<CppEditor::CppEditorWidget> editorWidget;
+ const DocumentUri uri;
+ const LinkHandler callback;
+ VirtualFunctionAssistProvider virtualFuncAssistProvider;
+ QList<MessageId> pendingSymbolInfoRequests;
+ QList<MessageId> pendingGotoImplRequests;
+ QList<MessageId> pendingGotoDefRequests;
+ const int docRevision;
+ const bool openInSplit;
+
+ Link defLink;
+ Links allLinks;
+ QHash<Link, Link> declDefMap;
+ optional<ClangdAstNode> cursorNode;
+ ClangdAstNode defLinkNode;
+ SymbolDataList symbolsToDisplay;
+ std::set<FilePath> openedFiles;
+ VirtualFunctionAssistProcessor *virtualFuncAssistProcessor = nullptr;
+ QMetaObject::Connection focusChangedConnection;
+ bool done = false;
+};
+
+ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, const QTextCursor &cursor,
+ CppEditorWidget *editorWidget, TextDocument *document, const LinkHandler &callback,
+ bool openInSplit)
+ : QObject(client),
+ d(new Private(this, client, cursor, editorWidget, document->filePath(), callback,
+ openInSplit))
+{
+ // Abort if the user does something else with the document in the meantime.
+ connect(document, &TextDocument::contentsChanged, this, [this] { emitDone(); },
+ Qt::QueuedConnection);
+ if (editorWidget) {
+ connect(editorWidget, &CppEditorWidget::cursorPositionChanged,
+ this, [this] { emitDone(); }, Qt::QueuedConnection);
+ }
+ d->focusChangedConnection = connect(qApp, &QApplication::focusChanged,
+ this, [this] { emitDone(); }, Qt::QueuedConnection);
+
+ // Step 1: Follow the symbol via "Go to Definition". At the same time, request the
+ // AST node corresponding to the cursor position, so we can find out whether
+ // we have to look for overrides.
+ const auto gotoDefCallback = [self = QPointer(this)](const Utils::Link &link) {
+ qCDebug(clangdLog) << "received go to definition response";
+ if (!self)
+ return;
+ if (!link.hasValidTarget()) {
+ self->emitDone();
+ return;
+ }
+ self->d->defLink = link;
+ if (self->d->cursorNode)
+ self->d->handleGotoDefinitionResult();
+ };
+ client->symbolSupport().findLinkAt(document, cursor, std::move(gotoDefCallback), true);
+
+ const auto astHandler = [self = QPointer(this)](const ClangdAstNode &ast, const MessageId &) {
+ qCDebug(clangdLog) << "received ast response for cursor";
+ if (!self)
+ return;
+ self->d->cursorNode = ast;
+ if (self->d->defLink.hasValidTarget())
+ self->d->handleGotoDefinitionResult();
+ };
+ client->getAndHandleAst(document, astHandler, ClangdClient::AstCallbackMode::AlwaysAsync,
+ Range(cursor));
+}
+
+ClangdFollowSymbol::~ClangdFollowSymbol()
+{
+ d->closeTempDocuments();
+ if (d->virtualFuncAssistProcessor)
+ d->virtualFuncAssistProcessor->resetData(false);
+ for (const MessageId &id : qAsConst(d->pendingSymbolInfoRequests))
+ d->client->cancelRequest(id);
+ for (const MessageId &id : qAsConst(d->pendingGotoImplRequests))
+ d->client->cancelRequest(id);
+ for (const MessageId &id : qAsConst(d->pendingGotoDefRequests))
+ d->client->cancelRequest(id);
+ delete d;
+}
+
+void ClangdFollowSymbol::clear()
+{
+ d->openedFiles.clear();
+ d->pendingSymbolInfoRequests.clear();
+ d->pendingGotoImplRequests.clear();
+ d->pendingGotoDefRequests.clear();
+}
+
+void ClangdFollowSymbol::emitDone(const Link &link)
+{
+ if (d->done)
+ return;
+
+ d->done = true;
+ if (link.hasValidTarget())
+ d->callback(link);
+ emit done();
+}
+
+bool ClangdFollowSymbol::Private::defLinkIsAmbiguous() const
+{
+ // Even if the call is to a virtual function, it might not be ambiguous:
+ // class A { virtual void f(); }; class B : public A { void f() override { A::f(); } };
+ if (!cursorNode->mightBeAmbiguousVirtualCall() && !cursorNode->isPureVirtualDeclaration())
+ return false;
+
+ // If we have up-to-date highlighting info, we know whether we are dealing with
+ // a virtual call.
+ if (editorWidget) {
+ const auto result = client->hasVirtualFunctionAt(editorWidget->textDocument(),
+ docRevision, cursorNode->range());
+ if (result.has_value())
+ return *result;
+ }
+
+ // Otherwise, we accept potentially doing more work than needed rather than not catching
+ // possible overrides.
+ return true;
+}
+
+bool ClangdFollowSymbol::Private::addOpenFile(const FilePath &filePath)
+{
+ return openedFiles.insert(filePath).second;
+}
+
+void ClangdFollowSymbol::Private::handleDocumentInfoResults()
+{
+ closeTempDocuments();
+
+ // If something went wrong, we just follow the original link.
+ if (symbolsToDisplay.isEmpty()) {
+ q->emitDone(defLink);
+ return;
+ }
+
+ if (symbolsToDisplay.size() == 1) {
+ q->emitDone(symbolsToDisplay.first().second);
+ return;
+ }
+
+ QTC_ASSERT(virtualFuncAssistProcessor && virtualFuncAssistProcessor->running(),
+ q->emitDone(); return);
+ virtualFuncAssistProcessor->finalize();
+}
+
+void ClangdFollowSymbol::Private::sendGotoImplementationRequest(const Link &link)
+{
+ if (!client->documentForFilePath(link.targetFilePath) && addOpenFile(link.targetFilePath))
+ client->openExtraFile(link.targetFilePath);
+ const Position position(link.targetLine - 1, link.targetColumn);
+ const TextDocumentIdentifier documentId(DocumentUri::fromFilePath(link.targetFilePath));
+ GotoImplementationRequest req(TextDocumentPositionParams(documentId, position));
+ req.setResponseCallback([sentinel = QPointer(q), this, reqId = req.id()]
+ (const GotoImplementationRequest::Response &response) {
+ qCDebug(clangdLog) << "received go to implementation reply";
+ if (!sentinel)
+ return;
+ pendingGotoImplRequests.removeOne(reqId);
+ handleGotoImplementationResult(response);
+ });
+ client->sendMessage(req, ClangdClient::SendDocUpdates::Ignore);
+ pendingGotoImplRequests << req.id();
+ qCDebug(clangdLog) << "sending go to implementation request" << link.targetLine;
+}
+
+void ClangdFollowSymbol::VirtualFunctionAssistProcessor::update()
+{
+ if (!m_followSymbol->d->editorWidget)
+ return;
+ setAsyncProposalAvailable(createProposal(false));
+}
+
+void ClangdFollowSymbol::VirtualFunctionAssistProcessor::finalize()
+{
+ if (!m_followSymbol->d->editorWidget)
+ return;
+ const auto proposal = createProposal(true);
+ if (m_followSymbol->d->editorWidget->isInTestMode()) {
+ m_followSymbol->d->symbolsToDisplay.clear();
+ const auto immediateProposal = createProposal(false);
+ m_followSymbol->d->editorWidget->setProposals(immediateProposal, proposal);
+ } else {
+ setAsyncProposalAvailable(proposal);
+ }
+ resetData(true);
+}
+
+void ClangdFollowSymbol::VirtualFunctionAssistProcessor::resetData(bool resetFollowSymbolData)
+{
+ if (!m_followSymbol)
+ return;
+ m_followSymbol->d->virtualFuncAssistProcessor = nullptr;
+ if (resetFollowSymbolData)
+ m_followSymbol->emitDone();
+ m_followSymbol = nullptr;
+}
+
+IAssistProposal *
+ClangdFollowSymbol::VirtualFunctionAssistProcessor::createProposal(bool final) const
+{
+ QTC_ASSERT(m_followSymbol, return nullptr);
+
+ QList<AssistProposalItemInterface *> items;
+ bool needsBaseDeclEntry = !m_followSymbol->d->defLinkNode.range()
+ .contains(Position(m_followSymbol->d->cursor));
+ for (const SymbolData &symbol : qAsConst(m_followSymbol->d->symbolsToDisplay)) {
+ Link link = symbol.second;
+ if (m_followSymbol->d->defLink == link) {
+ if (!needsBaseDeclEntry)
+ continue;
+ needsBaseDeclEntry = false;
+ } else {
+ const Link defLink = m_followSymbol->d->declDefMap.value(symbol.second);
+ if (defLink.hasValidTarget())
+ link = defLink;
+ }
+ items << createEntry(symbol.first, link);
+ }
+ if (needsBaseDeclEntry)
+ items << createEntry({}, m_followSymbol->d->defLink);
+ if (!final) {
+ const auto infoItem = new VirtualFunctionProposalItem({}, false);
+ infoItem->setText(ClangdClient::tr("collecting overrides ..."));
+ infoItem->setOrder(-1);
+ items << infoItem;
+ }
+
+ return new VirtualFunctionProposal(m_followSymbol->d->cursor.position(), items,
+ m_followSymbol->d->openInSplit);
+}
+
+CppEditor::VirtualFunctionProposalItem *
+ClangdFollowSymbol::VirtualFunctionAssistProcessor::createEntry(const QString &name,
+ const Link &link) const
+{
+ const auto item = new VirtualFunctionProposalItem(link, m_followSymbol->d->openInSplit);
+ QString text = name;
+ if (link == m_followSymbol->d->defLink) {
+ item->setOrder(1000); // Ensure base declaration is on top.
+ if (text.isEmpty()) {
+ text = ClangdClient::tr("<base declaration>");
+ } else if (m_followSymbol->d->defLinkNode.isPureVirtualDeclaration()
+ || m_followSymbol->d->defLinkNode.isPureVirtualDefinition()) {
+ text += " = 0";
+ }
+ }
+ item->setText(text);
+ return item;
+}
+
+IAssistProcessor *
+ClangdFollowSymbol::VirtualFunctionAssistProvider::createProcessor(const AssistInterface *) const
+{
+ return m_followSymbol->d->virtualFuncAssistProcessor
+ = new VirtualFunctionAssistProcessor(m_followSymbol);
+}
+
+void ClangdFollowSymbol::Private::handleGotoDefinitionResult()
+{
+ QTC_ASSERT(defLink.hasValidTarget(), return);
+
+ qCDebug(clangdLog) << "handling go to definition result";
+
+ // No dis-ambiguation necessary. Call back with the link and finish.
+ if (!defLinkIsAmbiguous()) {
+ q->emitDone(defLink);
+ return;
+ }
+
+ // Step 2: Get all possible overrides via "Go to Implementation".
+ // Note that we have to do this for all member function calls, because
+ // we cannot tell here whether the member function is virtual.
+ allLinks << defLink;
+ sendGotoImplementationRequest(defLink);
+}
+
+void ClangdFollowSymbol::Private::handleGotoImplementationResult(
+ const GotoImplementationRequest::Response &response)
+{
+ if (const optional<GotoResult> &result = response.result()) {
+ QList<Link> newLinks;
+ if (const auto ploc = get_if<Location>(&*result))
+ newLinks = {ploc->toLink()};
+ if (const auto plloc = get_if<QList<Location>>(&*result))
+ newLinks = transform(*plloc, &Location::toLink);
+ for (const Link &link : qAsConst(newLinks)) {
+ if (!allLinks.contains(link)) {
+ allLinks << link;
+
+ // We must do this recursively, because clangd reports only the first
+ // level of overrides.
+ sendGotoImplementationRequest(link);
+ }
+ }
+ }
+
+ // We didn't find any further candidates, so jump to the original definition link.
+ if (allLinks.size() == 1 && pendingGotoImplRequests.isEmpty()) {
+ q->emitDone(allLinks.first());
+ return;
+ }
+
+ // As soon as we know that there is more than one candidate, we start the code assist
+ // procedure, to let the user know that things are happening.
+ if (allLinks.size() > 1 && !virtualFuncAssistProcessor && editorWidget) {
+ QObject::disconnect(focusChangedConnection);
+ editorWidget->invokeTextEditorWidgetAssist(FollowSymbol, &virtualFuncAssistProvider);
+ }
+
+ if (!pendingGotoImplRequests.isEmpty())
+ return;
+
+ // Step 3: We are done looking for overrides, and we found at least one.
+ // Make a symbol info request for each link to get the class names.
+ // Also get the AST for the base declaration, so we can find out whether it's
+ // pure virtual and mark it accordingly.
+ // In addition, we need to follow all override links, because for these, clangd
+ // gives us the declaration instead of the definition.
+ for (const Link &link : qAsConst(allLinks)) {
+ if (!client->documentForFilePath(link.targetFilePath) && addOpenFile(link.targetFilePath))
+ client->openExtraFile(link.targetFilePath);
+ const auto symbolInfoHandler = [sentinel = QPointer(q), this, link](
+ const QString &name, const QString &prefix, const MessageId &reqId) {
+ qCDebug(clangdLog) << "handling symbol info reply"
+ << link.targetFilePath.toUserOutput() << link.targetLine;
+ if (!sentinel)
+ return;
+ if (!name.isEmpty())
+ symbolsToDisplay << qMakePair(prefix + name, link);
+ pendingSymbolInfoRequests.removeOne(reqId);
+ virtualFuncAssistProcessor->update();
+ if (pendingSymbolInfoRequests.isEmpty() && pendingGotoDefRequests.isEmpty()
+ && defLinkNode.isValid()) {
+ handleDocumentInfoResults();
+ }
+ };
+ const Position pos(link.targetLine - 1, link.targetColumn);
+ const MessageId reqId = client->requestSymbolInfo(link.targetFilePath, pos,
+ symbolInfoHandler);
+ pendingSymbolInfoRequests << reqId;
+ qCDebug(clangdLog) << "sending symbol info request";
+
+ if (link == defLink)
+ continue;
+
+ const TextDocumentIdentifier doc(DocumentUri::fromFilePath(link.targetFilePath));
+ const TextDocumentPositionParams params(doc, pos);
+ GotoDefinitionRequest defReq(params);
+ defReq.setResponseCallback([this, link, sentinel = QPointer(q), reqId = defReq.id()]
+ (const GotoDefinitionRequest::Response &response) {
+ qCDebug(clangdLog) << "handling additional go to definition reply for"
+ << link.targetFilePath << link.targetLine;
+ if (!sentinel)
+ return;
+ Link newLink;
+ if (optional<GotoResult> _result = response.result()) {
+ const GotoResult result = _result.value();
+ if (const auto ploc = get_if<Location>(&result)) {
+ newLink = ploc->toLink();
+ } else if (const auto plloc = get_if<QList<Location>>(&result)) {
+ if (!plloc->isEmpty())
+ newLink = plloc->value(0).toLink();
+ }
+ }
+ qCDebug(clangdLog) << "def link is" << newLink.targetFilePath << newLink.targetLine;
+ declDefMap.insert(link, newLink);
+ pendingGotoDefRequests.removeOne(reqId);
+ if (pendingSymbolInfoRequests.isEmpty() && pendingGotoDefRequests.isEmpty()
+ && defLinkNode.isValid()) {
+ handleDocumentInfoResults();
+ }
+ });
+ pendingGotoDefRequests << defReq.id();
+ qCDebug(clangdLog) << "sending additional go to definition request"
+ << link.targetFilePath << link.targetLine;
+ client->sendMessage(defReq, ClangdClient::SendDocUpdates::Ignore);
+ }
+
+ const FilePath defLinkFilePath = defLink.targetFilePath;
+ const TextDocument * const defLinkDoc = client->documentForFilePath(defLinkFilePath);
+ const auto defLinkDocVariant = defLinkDoc ? ClangdClient::TextDocOrFile(defLinkDoc)
+ : ClangdClient::TextDocOrFile(defLinkFilePath);
+ const Position defLinkPos(defLink.targetLine - 1, defLink.targetColumn);
+ const auto astHandler = [this, sentinel = QPointer(q)]
+ (const ClangdAstNode &ast, const MessageId &) {
+ qCDebug(clangdLog) << "received ast response for def link";
+ if (!sentinel)
+ return;
+ defLinkNode = ast;
+ if (pendingSymbolInfoRequests.isEmpty() && pendingGotoDefRequests.isEmpty())
+ handleDocumentInfoResults();
+ };
+ client->getAndHandleAst(defLinkDocVariant, astHandler,
+ ClangdClient::AstCallbackMode::AlwaysAsync,
+ Range(defLinkPos, defLinkPos));
+}
+
+void ClangdFollowSymbol::Private::closeTempDocuments()
+{
+ for (const FilePath &fp : qAsConst(openedFiles)) {
+ if (!client->documentForFilePath(fp))
+ client->closeExtraFile(fp);
+ }
+ openedFiles.clear();
+}
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/clangdfollowsymbol.h b/src/plugins/clangcodemodel/clangdfollowsymbol.h
new file mode 100644
index 00000000000..09094bbed5e
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdfollowsymbol.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/link.h>
+
+#include <QObject>
+
+namespace CppEditor { class CppEditorWidget; }
+namespace TextEditor { class TextDocument; }
+
+QT_BEGIN_NAMESPACE
+class QTextCursor;
+QT_END_NAMESPACE
+
+namespace ClangCodeModel::Internal {
+class ClangdAstNode;
+class ClangdClient;
+
+class ClangdFollowSymbol : public QObject
+{
+ Q_OBJECT
+public:
+ ClangdFollowSymbol(ClangdClient *client, const QTextCursor &cursor,
+ CppEditor::CppEditorWidget *editorWidget,
+ TextEditor::TextDocument *document, const Utils::LinkHandler &callback,
+ bool openInSplit);
+ ~ClangdFollowSymbol();
+ void clear();
+
+signals:
+ void done();
+
+private:
+ void emitDone(const Utils::Link &link = {});
+ class VirtualFunctionAssistProcessor;
+ class VirtualFunctionAssistProvider;
+
+ class Private;
+ Private * const d;
+};
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/clangdiagnosticfilter.cpp b/src/plugins/clangcodemodel/clangdiagnosticfilter.cpp
deleted file mode 100644
index fea6075e00b..00000000000
--- a/src/plugins/clangcodemodel/clangdiagnosticfilter.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangdiagnosticfilter.h"
-
-#include <cppeditor/cppprojectfile.h>
-
-#include <utf8stringvector.h>
-
-namespace {
-
-bool isWarningOrNote(ClangBackEnd::DiagnosticSeverity severity)
-{
- using ClangBackEnd::DiagnosticSeverity;
- switch (severity) {
- case DiagnosticSeverity::Ignored:
- case DiagnosticSeverity::Note:
- case DiagnosticSeverity::Warning: return true;
- case DiagnosticSeverity::Error:
- case DiagnosticSeverity::Fatal: return false;
- }
-
- Q_UNREACHABLE();
-}
-
-bool isBlackListedHeaderDiagnostic(const ClangBackEnd::DiagnosticContainer &diagnostic,
- bool isHeaderFile)
-{
- static const Utf8StringVector blackList{
- Utf8StringLiteral("warning: #pragma once in main file"),
- Utf8StringLiteral("warning: #include_next in primary source file")
- };
-
- return isHeaderFile && blackList.contains(diagnostic.text);
-}
-
-bool isBlackListedQtDiagnostic(const ClangBackEnd::DiagnosticContainer &diagnostic)
-{
- static const Utf8StringVector blackList{
- // From Q_OBJECT:
- Utf8StringLiteral("warning: "
- "'metaObject' overrides a member function but is not marked 'override'"),
- Utf8StringLiteral("warning: "
- "'qt_metacast' overrides a member function but is not marked 'override'"),
- Utf8StringLiteral("warning: "
- "'qt_metacall' overrides a member function but is not marked 'override'"),
- };
-
- return blackList.contains(diagnostic.text);
-}
-
-template <class Condition>
-QVector<ClangBackEnd::DiagnosticContainer>
-filterDiagnostics(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- const Condition &condition)
-{
- QVector<ClangBackEnd::DiagnosticContainer> filteredDiagnostics;
-
- std::copy_if(diagnostics.cbegin(),
- diagnostics.cend(),
- std::back_inserter(filteredDiagnostics),
- condition);
-
- return filteredDiagnostics;
-}
-
-template <class Condition>
-void
-filterDiagnostics(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- const Condition &condition,
- QVector<ClangBackEnd::DiagnosticContainer> &filteredDiagnostic)
-{
- std::copy_if(diagnostics.cbegin(),
- diagnostics.cend(),
- std::back_inserter(filteredDiagnostic),
- condition);
-}
-
-} // anonymous namespace
-
-namespace ClangCodeModel {
-namespace Internal {
-
-void ClangDiagnosticFilter::filterDocumentRelatedWarnings(
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
-{
- using namespace CppEditor;
- const bool isHeaderFile = ProjectFile::isHeader(ProjectFile::classify(m_filePath));
-
- const auto isLocalWarning = [this, isHeaderFile]
- (const ClangBackEnd::DiagnosticContainer &diagnostic) {
- return isWarningOrNote(diagnostic.severity)
- && !isBlackListedHeaderDiagnostic(diagnostic, isHeaderFile)
- && !isBlackListedQtDiagnostic(diagnostic)
- && diagnostic.location.filePath == m_filePath;
- };
-
- m_warningDiagnostics = filterDiagnostics(diagnostics, isLocalWarning);
-}
-
-void ClangDiagnosticFilter::filterDocumentRelatedErrors(
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
-{
- const auto isLocalWarning = [this] (const ClangBackEnd::DiagnosticContainer &diagnostic) {
- return !isWarningOrNote(diagnostic.severity)
- && diagnostic.location.filePath == m_filePath;
- };
-
- m_errorDiagnostics = filterDiagnostics(diagnostics, isLocalWarning);
-}
-
-void ClangDiagnosticFilter::filterFixits()
-{
- const auto hasFixIts = [] (const ClangBackEnd::DiagnosticContainer &diagnostic) {
- return diagnostic.fixIts.size() > 0;
- };
-
- m_fixItdiagnostics.clear();
- filterDiagnostics(m_warningDiagnostics, hasFixIts, m_fixItdiagnostics);
- filterDiagnostics(m_errorDiagnostics, hasFixIts, m_fixItdiagnostics);
-
- for (const auto &warningDiagnostic : m_warningDiagnostics)
- filterDiagnostics(warningDiagnostic.children, hasFixIts, m_fixItdiagnostics);
- for (const auto &warningDiagnostic : m_errorDiagnostics)
- filterDiagnostics(warningDiagnostic.children, hasFixIts, m_fixItdiagnostics);
-}
-
-ClangDiagnosticFilter::ClangDiagnosticFilter(const QString &filePath)
- : m_filePath(filePath)
-{
-}
-
-void ClangDiagnosticFilter::filter(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
-{
- filterDocumentRelatedWarnings(diagnostics);
- filterDocumentRelatedErrors(diagnostics);
- filterFixits();
-}
-
-QVector<ClangBackEnd::DiagnosticContainer> ClangDiagnosticFilter::takeWarnings()
-{
- auto diagnostics = m_warningDiagnostics;
- m_warningDiagnostics.clear();
-
- return diagnostics;
-}
-
-QVector<ClangBackEnd::DiagnosticContainer> ClangDiagnosticFilter::takeErrors()
-{
- auto diagnostics = m_errorDiagnostics;
- m_errorDiagnostics.clear();
-
- return diagnostics;
-}
-
-QVector<ClangBackEnd::DiagnosticContainer> ClangDiagnosticFilter::takeFixIts()
-{
- auto diagnostics = m_fixItdiagnostics;
- m_fixItdiagnostics.clear();
-
- return diagnostics;
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
-
diff --git a/src/plugins/clangcodemodel/clangdiagnosticfilter.h b/src/plugins/clangcodemodel/clangdiagnosticfilter.h
deleted file mode 100644
index a61734718ea..00000000000
--- a/src/plugins/clangcodemodel/clangdiagnosticfilter.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport/diagnosticcontainer.h>
-
-#include <QVector>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangDiagnosticFilter
-{
-public:
- ClangDiagnosticFilter(const QString &filePath);
-
- void filter(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
-
- QVector<ClangBackEnd::DiagnosticContainer> takeWarnings();
- QVector<ClangBackEnd::DiagnosticContainer> takeErrors();
- QVector<ClangBackEnd::DiagnosticContainer> takeFixIts();
-
-private:
- void filterDocumentRelatedWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
- void filterDocumentRelatedErrors(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
- void filterFixits();
-
-private:
- const QString m_filePath;
-
- QVector<ClangBackEnd::DiagnosticContainer> m_warningDiagnostics;
- QVector<ClangBackEnd::DiagnosticContainer> m_errorDiagnostics;
- QVector<ClangBackEnd::DiagnosticContainer> m_fixItdiagnostics;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
deleted file mode 100644
index 5ba64e95773..00000000000
--- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
+++ /dev/null
@@ -1,505 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangconstants.h"
-#include "clangdiagnosticfilter.h"
-#include "clangdiagnosticmanager.h"
-#include "clangisdiagnosticrelatedtolocation.h"
-#include "clangutils.h"
-
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/command.h>
-
-#include <cppeditor/cppeditorconstants.h>
-
-#include <projectexplorer/taskhub.h>
-
-#include <texteditor/fontsettings.h>
-#include <texteditor/textdocument.h>
-#include <texteditor/texteditor.h>
-#include <texteditor/texteditorsettings.h>
-
-#include <utils/textutils.h>
-#include <utils/fileutils.h>
-#include <utils/proxyaction.h>
-#include <utils/qtcassert.h>
-#include <utils/theme/theme.h>
-#include <utils/utilsicons.h>
-
-#include <QFileInfo>
-#include <QTextBlock>
-
-namespace {
-
-QTextEdit::ExtraSelection createExtraSelections(const QTextCharFormat &mainformat,
- const QTextCursor &cursor)
-{
- QTextEdit::ExtraSelection extraSelection;
-
- extraSelection.format = mainformat;
- extraSelection.cursor = cursor;
-
- return extraSelection;
-}
-
-void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
- QTextDocument *textDocument,
- const QTextCharFormat &contextFormat,
- QList<QTextEdit::ExtraSelection> &extraSelections)
-{
- for (auto &&range : diagnostic.ranges) {
- QTextCursor cursor(textDocument);
- cursor.setPosition(::Utils::Text::positionInText(textDocument,
- range.start.line,
- range.start.column));
- cursor.setPosition(::Utils::Text::positionInText(textDocument,
- range.end.line,
- range.end.column),
- QTextCursor::KeepAnchor);
-
- auto extraSelection = createExtraSelections(contextFormat, cursor);
-
- extraSelections.push_back(std::move(extraSelection));
- }
-}
-
-QChar selectionEndChar(const QChar startSymbol)
-{
- if (startSymbol == '"')
- return QLatin1Char('"');
- if (startSymbol == '<')
- return QLatin1Char('>');
- return {};
-}
-
-void selectToLocationEnd(QTextCursor &cursor)
-{
- const QTextBlock textBlock = cursor.document()->findBlock(cursor.position());
- const QString simplifiedStr = textBlock.text().simplified();
- if (!simplifiedStr.startsWith("#include") && !simplifiedStr.startsWith("# include")) {
- // General case, not the line with #include
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- return;
- }
-
- const QChar endChar = selectionEndChar(cursor.document()->characterAt(cursor.position()));
- if (endChar.isNull()) {
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- } else {
- const int endPosition = textBlock.text().indexOf(endChar, cursor.position()
- - textBlock.position() + 1);
- if (endPosition >= 0)
- cursor.setPosition(textBlock.position() + endPosition + 1, QTextCursor::KeepAnchor);
- else
- cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
- }
-}
-
-QTextCursor createSelectionCursor(QTextDocument *textDocument,
- const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
-{
- QTextCursor cursor(textDocument);
- cursor.setPosition(::Utils::Text::positionInText(textDocument,
- sourceLocationContainer.line,
- sourceLocationContainer.column));
- selectToLocationEnd(cursor);
-
- if (!cursor.hasSelection()) {
- cursor.setPosition(::Utils::Text::positionInText(textDocument,
- sourceLocationContainer.line,
- sourceLocationContainer.column) - 1);
- cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2);
- }
-
- return cursor;
-}
-
-void addSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- QTextDocument *textDocument,
- const QTextCharFormat &mainFormat,
- const QTextCharFormat &contextFormat,
- QList<QTextEdit::ExtraSelection> &extraSelections)
-{
- for (auto &&diagnostic : diagnostics) {
- auto cursor = createSelectionCursor(textDocument, diagnostic.location);
- auto extraSelection = createExtraSelections(mainFormat, cursor);
-
- addRangeSelections(diagnostic, textDocument, contextFormat, extraSelections);
-
- extraSelections.push_back(std::move(extraSelection));
- }
-}
-
-void addWarningSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- QTextDocument *textDocument,
- QList<QTextEdit::ExtraSelection> &extraSelections)
-{
- const auto fontSettings = TextEditor::TextEditorSettings::fontSettings();
-
- QTextCharFormat warningFormat = fontSettings.toTextCharFormat(TextEditor::C_WARNING);
-
- QTextCharFormat warningContextFormat = fontSettings.toTextCharFormat(TextEditor::C_WARNING_CONTEXT);
-
- addSelections(diagnostics, textDocument, warningFormat, warningContextFormat, extraSelections);
-}
-
-void addErrorSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- QTextDocument *textDocument,
- QList<QTextEdit::ExtraSelection> &extraSelections)
-{
- const auto fontSettings = TextEditor::TextEditorSettings::fontSettings();
-
- QTextCharFormat errorFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR);
- QTextCharFormat errorContextFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR_CONTEXT);
-
- addSelections(diagnostics, textDocument, errorFormat, errorContextFormat, extraSelections);
-}
-
-ClangBackEnd::SourceLocationContainer toSourceLocation(QTextDocument *textDocument, int position)
-{
- int line, column;
- if (Utils::Text::convertPosition(textDocument, position, &line, &column))
- return ClangBackEnd::SourceLocationContainer(Utf8String(), line, column);
-
- return ClangBackEnd::SourceLocationContainer();
-}
-
-ClangBackEnd::SourceRangeContainer toSourceRange(const QTextCursor &cursor)
-{
- using namespace ClangBackEnd;
-
- QTextDocument *textDocument = cursor.document();
-
- return SourceRangeContainer(toSourceLocation(textDocument, cursor.anchor()),
- toSourceLocation(textDocument, cursor.position()));
-}
-
-bool isDiagnosticAtLocation(const ClangBackEnd::DiagnosticContainer &diagnostic,
- uint line,
- uint column,
- QTextDocument *textDocument)
-{
- using namespace ClangCodeModel::Internal;
-
- const ClangBackEnd::SourceLocationContainer &location = diagnostic.location;
- const QTextCursor cursor = createSelectionCursor(textDocument, location);
- const ClangBackEnd::SourceRangeContainer cursorRange = toSourceRange(cursor);
-
- return isDiagnosticRelatedToLocation(diagnostic, {cursorRange}, line, column);
-}
-
-QTextCursor cursorAtLastPositionOfLine(QTextDocument *textDocument, int lineNumber)
-{
- const QTextBlock textBlock = textDocument->findBlockByNumber(lineNumber - 1);
- QTC_ASSERT(textBlock.isValid(), return QTextCursor());
-
- const int lastPositionOfLine = textBlock.position() + textBlock.length() - 1;
-
- QTextCursor textCursor(textDocument);
- textCursor.setPosition(lastPositionOfLine);
-
- return textCursor;
-}
-
-QString tooltipForFixItAvailableMarker()
-{
- QString text = QCoreApplication::translate("ClangCodeModel::Internal::ClangDiagnosticManager", "Inspect available fixits");
-
- Core::Command *command = Core::ActionManager::command(TextEditor::Constants::QUICKFIX_THIS);
- if (command)
- text = Utils::ProxyAction::stringWithAppendedShortcut(text, command->keySequence());
-
- return text;
-}
-
-TextEditor::RefactorMarker createFixItAvailableMarker(QTextDocument *textDocument, int lineNumber)
-{
- TextEditor::RefactorMarker marker;
- marker.tooltip = tooltipForFixItAvailableMarker();
- marker.cursor = cursorAtLastPositionOfLine(textDocument, lineNumber);
- marker.callback = [marker](TextEditor::TextEditorWidget *editor) {
- int line, column;
- if (Utils::Text::convertPosition(marker.cursor.document(),
- marker.cursor.position(), &line, &column)) {
- editor->setTextCursor(marker.cursor);
- editor->invokeAssist(TextEditor::QuickFix);
- }
- };
- marker.type = CppEditor::Constants::CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID;
-
- return marker;
-}
-
-} // anonymous
-
-namespace ClangCodeModel {
-namespace Internal {
-
-ClangDiagnosticManager::ClangDiagnosticManager(TextEditor::TextDocument *textDocument)
- : m_textDocument(textDocument)
-{
- m_textMarkDelay.setInterval(1500);
- m_textMarkDelay.setSingleShot(true);
-}
-
-ClangDiagnosticManager::~ClangDiagnosticManager()
-{
- cleanMarks();
-}
-
-void ClangDiagnosticManager::cleanMarks()
-{
- for (ClangTextMark *textMark : m_clangTextMarks) {
- m_textDocument->removeMark(textMark);
- delete textMark;
- }
- m_clangTextMarks.clear();
-}
-void ClangDiagnosticManager::generateTextMarks()
-{
- QObject::disconnect(&m_textMarkDelay, &QTimer::timeout, nullptr, nullptr);
- cleanMarks();
- m_clangTextMarks.reserve(m_warningDiagnostics.size() + m_errorDiagnostics.size());
- addClangTextMarks(m_warningDiagnostics);
- addClangTextMarks(m_errorDiagnostics);
-}
-
-void ClangDiagnosticManager::generateFixItAvailableMarkers()
-{
- m_fixItAvailableMarkers.clear();
-
- if (!m_fullVisualization)
- return;
-
- QSet<int> lineNumbersWithFixItMarker;
- addFixItAvailableMarker(m_warningDiagnostics, lineNumbersWithFixItMarker);
- addFixItAvailableMarker(m_errorDiagnostics, lineNumbersWithFixItMarker);
-}
-
-void ClangDiagnosticManager::addTask(const ClangBackEnd::DiagnosticContainer &diagnostic,
- bool isChild)
-{
- using namespace ProjectExplorer;
- using ::Utils::FilePath;
-
- Task::TaskType taskType = ProjectExplorer::Task::TaskType::Unknown;
- FilePath iconPath;
- QIcon icon;
-
- if (!isChild) {
- switch (diagnostic.severity) {
- case ClangBackEnd::DiagnosticSeverity::Fatal:
- case ClangBackEnd::DiagnosticSeverity::Error:
- taskType = Task::TaskType::Error;
- icon = ::Utils::Icons::CODEMODEL_ERROR.icon();
- break;
- case ClangBackEnd::DiagnosticSeverity::Warning:
- taskType = Task::TaskType::Warning;
- icon = ::Utils::Icons::CODEMODEL_WARNING.icon();
- break;
- default:
- break;
- }
- }
-
- TaskHub::addTask(Task(taskType,
- diagnosticCategoryPrefixRemoved(diagnostic.text.toString()),
- FilePath::fromString(diagnostic.location.filePath.toString()),
- diagnostic.location.line,
- Constants::TASK_CATEGORY_DIAGNOSTICS,
- icon,
- Task::NoOptions));
-}
-
-void ClangDiagnosticManager::clearTaskHubIssues()
-{
- ProjectExplorer::TaskHub::clearTasks(Constants::TASK_CATEGORY_DIAGNOSTICS);
-}
-
-void ClangDiagnosticManager::generateTaskHubIssues()
-{
- if (!m_fullVisualization)
- return;
-
- const QVector<ClangBackEnd::DiagnosticContainer> diagnostics = m_errorDiagnostics
- + m_warningDiagnostics;
- for (const ClangBackEnd::DiagnosticContainer &diagnostic : diagnostics) {
- addTask(diagnostic);
- for (const ClangBackEnd::DiagnosticContainer &child : diagnostic.children)
- addTask(child, /*isChild = */ true);
- }
-}
-
-QList<QTextEdit::ExtraSelection> ClangDiagnosticManager::takeExtraSelections()
-{
- auto extraSelections = m_extraSelections;
-
- m_extraSelections.clear();
-
- return extraSelections;
-}
-
-TextEditor::RefactorMarkers ClangDiagnosticManager::takeFixItAvailableMarkers()
-{
- TextEditor::RefactorMarkers fixItAvailableMarkers = m_fixItAvailableMarkers;
-
- m_fixItAvailableMarkers.clear();
-
- return fixItAvailableMarkers;
-}
-
-TextEditor::TextMarks ClangDiagnosticManager::diagnosticTextMarksAt(uint line, uint column) const
-{
- QList<TextEditor::TextMark *> textMarks;
-
- for (ClangTextMark *textMark : m_clangTextMarks) {
- if (isDiagnosticAtLocation(textMark->diagnostic(), line, column, m_textDocument->document()))
- textMarks << textMark;
- }
-
- return textMarks;
-}
-
-void ClangDiagnosticManager::invalidateDiagnostics()
-{
- m_textMarkDelay.start();
- if (m_diagnosticsInvalidated)
- return;
-
- m_diagnosticsInvalidated = true;
- for (ClangTextMark *textMark : m_clangTextMarks) {
- textMark->setColor(::Utils::Theme::Color::IconsDisabledColor);
- textMark->updateIcon(/*valid=*/ false);
- textMark->updateMarker();
- }
-}
-
-void ClangDiagnosticManager::clearDiagnosticsWithFixIts()
-{
- m_fixItdiagnostics.clear();
-}
-
-void ClangDiagnosticManager::generateEditorSelections()
-{
- m_extraSelections.clear();
- m_extraSelections.reserve(int(m_warningDiagnostics.size() + m_errorDiagnostics.size()));
-
- if (!m_fullVisualization)
- return;
-
- addWarningSelections(m_warningDiagnostics, m_textDocument->document(), m_extraSelections);
- addErrorSelections(m_errorDiagnostics, m_textDocument->document(), m_extraSelections);
-}
-
-void ClangDiagnosticManager::processNewDiagnostics(
- const QVector<ClangBackEnd::DiagnosticContainer> &allDiagnostics,
- bool fullVisualization)
-{
- m_diagnosticsInvalidated = false;
- m_fullVisualization = fullVisualization;
- filterDiagnostics(allDiagnostics);
-
- generateEditorSelections();
- generateFixItAvailableMarkers();
- if (m_firstDiagnostics) {
- m_firstDiagnostics = false;
- generateTextMarks();
- } else if (!m_textMarkDelay.isActive()) {
- generateTextMarks();
- } else {
- QObject::connect(&m_textMarkDelay, &QTimer::timeout, [this]() {
- generateTextMarks();
- });
- }
-
- clearTaskHubIssues();
- generateTaskHubIssues();
-}
-
-const QVector<ClangBackEnd::DiagnosticContainer> &
-ClangDiagnosticManager::diagnosticsWithFixIts() const
-{
- return m_fixItdiagnostics;
-}
-
-void ClangDiagnosticManager::addClangTextMarks(
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
-{
- for (const ClangBackEnd::DiagnosticContainer &diagnostic : diagnostics) {
- const auto onMarkRemoved = [this](const ClangTextMark *mark) {
- const auto it = std::remove(m_clangTextMarks.begin(), m_clangTextMarks.end(), mark);
- m_clangTextMarks.erase(it, m_clangTextMarks.end());
- delete mark;
- };
- auto textMark = new ClangTextMark(::Utils::FilePath::fromString(filePath()),
- diagnostic,
- onMarkRemoved,
- m_fullVisualization,
- this);
- m_clangTextMarks.push_back(textMark);
- m_textDocument->addMark(textMark);
- }
-}
-
-void ClangDiagnosticManager::addFixItAvailableMarker(
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- QSet<int> &lineNumbersWithFixItMarker)
-{
- for (auto &&diagnostic : diagnostics) {
- for (auto &&fixit : diagnostic.fixIts) {
- const ClangBackEnd::SourceLocationContainer &location = fixit.range.start;
- const int line = int(location.line);
-
- if (location.filePath == filePath() && !lineNumbersWithFixItMarker.contains(line)) {
- const TextEditor::RefactorMarker marker
- = createFixItAvailableMarker(m_textDocument->document(), line);
-
- lineNumbersWithFixItMarker.insert(line);
- m_fixItAvailableMarkers.append(marker);
- }
- }
-
- addFixItAvailableMarker(diagnostic.children, lineNumbersWithFixItMarker);
- }
-}
-
-QString ClangDiagnosticManager::filePath() const
-{
- return m_textDocument->filePath().toString();
-}
-
-void ClangDiagnosticManager::filterDiagnostics(
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
-{
- ClangDiagnosticFilter filter(filePath());
- filter.filter(diagnostics);
-
- m_warningDiagnostics = filter.takeWarnings();
- m_errorDiagnostics = filter.takeErrors();
- m_fixItdiagnostics = filter.takeFixIts();
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.h b/src/plugins/clangcodemodel/clangdiagnosticmanager.h
deleted file mode 100644
index e3b8537e6a7..00000000000
--- a/src/plugins/clangcodemodel/clangdiagnosticmanager.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangtextmark.h"
-
-#include <texteditor/refactoroverlay.h>
-
-#include <clangsupport/diagnosticcontainer.h>
-
-#include <QList>
-#include <QSet>
-#include <QTextEdit>
-#include <QTimer>
-#include <QVector>
-
-#include <vector>
-
-namespace TextEditor { class TextDocument; }
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangDiagnosticManager
-{
-public:
- ClangDiagnosticManager(TextEditor::TextDocument *textDocument);
- ~ClangDiagnosticManager();
-
- void processNewDiagnostics(const QVector<ClangBackEnd::DiagnosticContainer> &allDiagnostics,
- bool fullVisualization);
-
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnosticsWithFixIts() const;
- QList<QTextEdit::ExtraSelection> takeExtraSelections();
- TextEditor::RefactorMarkers takeFixItAvailableMarkers();
-
- QList<TextEditor::TextMark *> diagnosticTextMarksAt(uint line, uint column) const;
- bool diagnosticsInvalidated() const { return m_diagnosticsInvalidated; }
-
- void invalidateDiagnostics();
- void clearDiagnosticsWithFixIts();
-
- static void clearTaskHubIssues();
- void generateTaskHubIssues();
- void cleanMarks();
-
- static void addTask(const ClangBackEnd::DiagnosticContainer &diagnostic, bool isChild = false);
-
-private:
- QString filePath() const;
- void filterDiagnostics(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
- void generateEditorSelections();
- void generateTextMarks();
- void generateFixItAvailableMarkers();
- void addClangTextMarks(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
- void addFixItAvailableMarker(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- QSet<int> &lineNumbersWithFixItMarker);
-
-private:
- TextEditor::TextDocument *m_textDocument;
-
- QVector<ClangBackEnd::DiagnosticContainer> m_warningDiagnostics;
- QVector<ClangBackEnd::DiagnosticContainer> m_errorDiagnostics;
- QVector<ClangBackEnd::DiagnosticContainer> m_fixItdiagnostics;
- QList<QTextEdit::ExtraSelection> m_extraSelections;
- TextEditor::RefactorMarkers m_fixItAvailableMarkers;
- std::vector<ClangTextMark *> m_clangTextMarks;
- bool m_firstDiagnostics = true;
- bool m_diagnosticsInvalidated = false;
- bool m_fullVisualization = false;
- QTimer m_textMarkDelay;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
index ddef8f6f6c8..d506f6a23ec 100644
--- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
+++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
@@ -25,7 +25,6 @@
#include "clangdiagnostictooltipwidget.h"
-#include "clangdiagnosticmanager.h"
#include "clangfixitoperation.h"
#include "clangutils.h"
@@ -53,36 +52,27 @@ namespace {
const char LINK_ACTION_GOTO_LOCATION[] = "#gotoLocation";
const char LINK_ACTION_APPLY_FIX[] = "#applyFix";
-QString fileNamePrefix(const QString &mainFilePath,
- const ClangBackEnd::SourceLocationContainer &location)
+QString fileNamePrefix(const QString &mainFilePath, const Utils::Link &location)
{
- const QString filePath = location.filePath.toString();
- if (filePath != mainFilePath)
+ const QString filePath = location.targetFilePath.toString();
+ if (!filePath.isEmpty() && filePath != mainFilePath)
return QFileInfo(filePath).fileName() + QLatin1Char(':');
return QString();
}
-QString locationToString(const ClangBackEnd::SourceLocationContainer &location)
+QString locationToString(const Utils::Link &location)
{
- return QString::number(location.line)
+ if (location.targetLine <= 0 || location.targetColumn <= 0)
+ return {};
+ return QString::number(location.targetLine)
+ QStringLiteral(":")
- + QString::number(location.column);
+ + QString::number(location.targetColumn + 1);
}
-void openEditorAt(const ClangBackEnd::DiagnosticContainer &diagnostic)
+void applyFixit(const ClangDiagnostic &diagnostic)
{
- const ClangBackEnd::SourceLocationContainer &location = diagnostic.location;
-
- Core::EditorManager::openEditorAt({Utils::FilePath::fromString(location.filePath.toString()),
- int(location.line),
- int(location.column - 1)});
-}
-
-void applyFixit(const ClangBackEnd::DiagnosticContainer &diagnostic)
-{
- ClangFixItOperation operation(Utf8String(), diagnostic.fixIts);
-
+ ClangFixItOperation operation({}, diagnostic.fixIts);
operation.perform();
}
@@ -103,7 +93,7 @@ public:
{
}
- QWidget *createWidget(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
+ QWidget *createWidget(const QList<ClangDiagnostic> &diagnostics,
const std::function<bool()> &canApplyFixIt, const QString &source)
{
const QString text = htmlText(diagnostics, source);
@@ -134,12 +124,12 @@ public:
const bool hideToolTipAfterLinkActivation = m_displayHints.hideTooltipAfterLinkActivation;
QObject::connect(label, &QLabel::linkActivated, [table, hideToolTipAfterLinkActivation,
canApplyFixIt](const QString &action) {
- const ClangBackEnd::DiagnosticContainer diagnostic = table.value(action);
+ const ClangDiagnostic diagnostic = table.value(action);
- if (diagnostic == ClangBackEnd::DiagnosticContainer())
+ if (diagnostic == ClangDiagnostic())
QDesktopServices::openUrl(QUrl(action));
else if (action.startsWith(LINK_ACTION_GOTO_LOCATION)) {
- openEditorAt(diagnostic);
+ Core::EditorManager::openEditorAt(diagnostic.location);
} else if (action.startsWith(LINK_ACTION_APPLY_FIX)) {
if (canApplyFixIt && canApplyFixIt())
applyFixit(diagnostic);
@@ -154,13 +144,12 @@ public:
return label;
}
- QString htmlText(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- const QString &source)
+ QString htmlText(const QList<ClangDiagnostic> &diagnostics, const QString &source)
{
// For debugging, add: style='border-width:1px;border-color:black'
QString text = "<table cellspacing='0' cellpadding='0' width='100%'>";
- foreach (const ClangBackEnd::DiagnosticContainer &diagnostic, diagnostics)
+ for (const ClangDiagnostic &diagnostic : diagnostics)
text.append(tableRows(diagnostic));
if (!source.isEmpty()) {
text.append(QString::fromUtf8("<tr><td colspan='2' align='left'>"
@@ -187,13 +176,12 @@ private:
// For clazy/tidy diagnostics, we expect something like "some text [some option]", e.g.:
// * clazy: "Use the static QFileInfo::exists() instead. It's documented to be faster. [-Wclazy-qfileinfo-exists]"
// * tidy: "use emplace_back instead of push_back [modernize-use-emplace]"
- static ClangBackEnd::DiagnosticContainer supplementedDiagnostic(
- const ClangBackEnd::DiagnosticContainer &diagnostic)
+ static ClangDiagnostic supplementedDiagnostic(const ClangDiagnostic &diagnostic)
{
if (!diagnostic.category.isEmpty())
return diagnostic; // OK, diagnostics from clang itself have this set.
- ClangBackEnd::DiagnosticContainer supplementedDiagnostic = diagnostic;
+ ClangDiagnostic supplementedDiagnostic = diagnostic;
DiagnosticTextInfo info(diagnostic.text);
supplementedDiagnostic.enableOption = info.option();
@@ -201,18 +189,18 @@ private:
supplementedDiagnostic.text = info.textWithoutOption();
for (auto &child : supplementedDiagnostic.children)
- child.text = DiagnosticTextInfo(diagnostic.text.toString()).textWithoutOption();
+ child.text = DiagnosticTextInfo(diagnostic.text).textWithoutOption();
return supplementedDiagnostic;
}
- QString tableRows(const ClangBackEnd::DiagnosticContainer &diagnostic)
+ QString tableRows(const ClangDiagnostic &diagnostic)
{
m_mainFilePath = m_displayHints.showFileNameInMainDiagnostic
- ? Utf8String()
- : diagnostic.location.filePath;
+ ? QString()
+ : diagnostic.location.targetFilePath.toString();
- const ClangBackEnd::DiagnosticContainer diag = supplementedDiagnostic(diagnostic);
+ const ClangDiagnostic diag = supplementedDiagnostic(diagnostic);
QString text;
if (m_displayHints.showCategoryAndEnableOption)
@@ -223,8 +211,7 @@ private:
return text;
}
- static QString diagnosticCategoryAndEnableOptionRow(
- const ClangBackEnd::DiagnosticContainer &diagnostic)
+ static QString diagnosticCategoryAndEnableOptionRow(const ClangDiagnostic &diagnostic)
{
const QString text = QString::fromLatin1(
" <tr>"
@@ -236,20 +223,19 @@ private:
return text;
}
- QString diagnosticText(const ClangBackEnd::DiagnosticContainer &diagnostic)
+ QString diagnosticText(const ClangDiagnostic &diagnostic)
{
const bool hasFixit = m_displayHints.enableClickableFixits
&& !diagnostic.fixIts.isEmpty();
- const QString diagnosticText = diagnostic.text.toString().toHtmlEscaped();
- const QString text = QString::fromLatin1("%1: %2")
- .arg(clickableLocation(diagnostic, m_mainFilePath),
- clickableFixIt(diagnostic, diagnosticText, hasFixit));
-
- return text;
+ const QString diagnosticText = diagnostic.text.toHtmlEscaped();
+ bool hasLocation = false;
+ QString text = clickableLocation(diagnostic, m_mainFilePath, hasLocation);
+ if (hasLocation)
+ text += ": ";
+ return text += clickableFixIt(diagnostic, diagnosticText, hasFixit);
}
- QString diagnosticRow(const ClangBackEnd::DiagnosticContainer &diagnostic,
- IndentMode indentMode)
+ QString diagnosticRow(const ClangDiagnostic &diagnostic, IndentMode indentMode)
{
const QString text = QString::fromLatin1(
" <tr>"
@@ -261,9 +247,9 @@ private:
return text;
}
- QString diagnosticRowsForChildren(const ClangBackEnd::DiagnosticContainer &diagnostic)
+ QString diagnosticRowsForChildren(const ClangDiagnostic &diagnostic)
{
- const QVector<ClangBackEnd::DiagnosticContainer> &children = diagnostic.children;
+ const QList<ClangDiagnostic> &children = diagnostic.children;
QString text;
if (children.size() <= 10) {
@@ -278,8 +264,8 @@ private:
}
QString diagnosticRowsForChildren(
- const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator first,
- const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator last)
+ const QList<ClangDiagnostic>::const_iterator first,
+ const QList<ClangDiagnostic>::const_iterator last)
{
QString text;
@@ -289,22 +275,21 @@ private:
return text;
}
- QString clickableLocation(const ClangBackEnd::DiagnosticContainer &diagnostic,
- const QString &mainFilePath)
+ QString clickableLocation(const ClangDiagnostic &diagnostic, const QString &mainFilePath,
+ bool &hasContent)
{
- const ClangBackEnd::SourceLocationContainer &location = diagnostic.location;
+ const Utils::Link &location = diagnostic.location;
const QString filePrefix = fileNamePrefix(mainFilePath, location);
const QString lineColumn = locationToString(location);
const QString linkText = filePrefix + lineColumn;
const QString targetId = generateTargetId(LINK_ACTION_GOTO_LOCATION, diagnostic);
+ hasContent = !linkText.isEmpty();
return wrapInLink(linkText, targetId);
}
- QString clickableFixIt(const ClangBackEnd::DiagnosticContainer &diagnostic,
- const QString &text,
- bool hasFixIt)
+ QString clickableFixIt(const ClangDiagnostic &diagnostic, const QString &text, bool hasFixIt)
{
if (!hasFixIt)
return text;
@@ -323,8 +308,7 @@ private:
return nonClickableCategory + wrapInLink(clickableText, targetId);
}
- QString generateTargetId(const QString &targetPrefix,
- const ClangBackEnd::DiagnosticContainer &diagnostic)
+ QString generateTargetId(const QString &targetPrefix, const ClangDiagnostic &diagnostic)
{
const QString idAsString = QString::number(++m_targetIdCounter);
const QString targetId = targetPrefix + idAsString;
@@ -365,7 +349,7 @@ private:
private:
const DisplayHints m_displayHints;
- using TargetIdToDiagnosticTable = QHash<QString, ClangBackEnd::DiagnosticContainer>;
+ using TargetIdToDiagnosticTable = QHash<QString, ClangDiagnostic>;
TargetIdToDiagnosticTable m_targetIdsToDiagnostics;
unsigned m_targetIdCounter = 0;
@@ -400,7 +384,7 @@ WidgetFromDiagnostics::DisplayHints toHints(const ClangDiagnosticWidget::Destina
} // anonymous namespace
QString ClangDiagnosticWidget::createText(
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
+ const QList<ClangDiagnostic> &diagnostics,
const ClangDiagnosticWidget::Destination &destination)
{
const QString htmlText = WidgetFromDiagnostics(toHints(destination, {}))
@@ -419,7 +403,7 @@ QString ClangDiagnosticWidget::createText(
}
QWidget *ClangDiagnosticWidget::createWidget(
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
+ const QList<ClangDiagnostic> &diagnostics,
const Destination &destination, const std::function<bool()> &canApplyFixIt,
const QString &source)
{
diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
index 92f98a59cae..555842efd89 100644
--- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
+++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangsupport/diagnosticcontainer.h>
+#include <QtGlobal>
#include <functional>
@@ -36,17 +36,17 @@ QT_END_NAMESPACE
namespace ClangCodeModel {
namespace Internal {
-class ClangDiagnosticManager;
+class ClangDiagnostic;
class ClangDiagnosticWidget {
public:
enum Destination { ToolTip, InfoBar };
- static QString createText(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
+ static QString createText(const QList<ClangDiagnostic> &diagnostics,
const Destination &destination);
- static QWidget *createWidget(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
+ static QWidget *createWidget(const QList<ClangDiagnostic> &diagnostics,
const Destination &destination,
const std::function<bool()> &canApplyFixIt,
const QString &source);
diff --git a/src/plugins/clangcodemodel/clangdlocatorfilters.cpp b/src/plugins/clangcodemodel/clangdlocatorfilters.cpp
index 6aa5d1e9703..425025ae54b 100644
--- a/src/plugins/clangcodemodel/clangdlocatorfilters.cpp
+++ b/src/plugins/clangcodemodel/clangdlocatorfilters.cpp
@@ -27,7 +27,6 @@
#include "clangdclient.h"
#include "clangmodelmanagersupport.h"
-#include "clangcurrentdocumentfilter.h"
#include <cppeditor/cppeditorconstants.h>
#include <cppeditor/cpplocatorfilter.h>
@@ -157,7 +156,7 @@ ClangGlobalSymbolFilter::~ClangGlobalSymbolFilter()
void ClangGlobalSymbolFilter::prepareSearch(const QString &entry)
{
m_cppFilter->prepareSearch(entry);
- QVector<LanguageClient::Client *> clients;
+ QList<LanguageClient::Client *> clients;
for (ProjectExplorer::Project * const project : ProjectExplorer::SessionManager::projects()) {
LanguageClient::Client * const client
= ClangModelManagerSupport::instance()->clientForProject(project);
@@ -226,19 +225,6 @@ ClangFunctionsFilter::ClangFunctionsFilter()
setDefaultIncludedByDefault(false);
}
-class CppCurrentDocumentFilter : public ClangCurrentDocumentFilter
-{
-public:
- CppCurrentDocumentFilter()
- {
- setId({});
- setDisplayName({});
- setDefaultShortcutString({});
- setEnabled(false);
- setHidden(true);
- }
-};
-
class LspCurrentDocumentFilter : public LanguageClient::DocumentLocatorFilter
{
public:
@@ -278,7 +264,10 @@ private:
class ClangdCurrentDocumentFilter::Private
{
public:
- CppCurrentDocumentFilter cppFilter;
+ ~Private() { delete cppFilter; }
+
+ Core::ILocatorFilter * const cppFilter
+ = CppEditor::CppModelManager::createAuxiliaryCurrentDocumentFilter();
LspCurrentDocumentFilter lspFilter;
Core::ILocatorFilter *activeFilter = nullptr;
};
@@ -298,6 +287,11 @@ ClangdCurrentDocumentFilter::ClangdCurrentDocumentFilter() : d(new Private)
ClangdCurrentDocumentFilter::~ClangdCurrentDocumentFilter() { delete d; }
+void ClangdCurrentDocumentFilter::updateCurrentClient()
+{
+ d->lspFilter.updateCurrentClient();
+}
+
void ClangdCurrentDocumentFilter::prepareSearch(const QString &entry)
{
const auto doc = TextEditor::TextDocument::currentTextDocument();
@@ -306,7 +300,7 @@ void ClangdCurrentDocumentFilter::prepareSearch(const QString &entry)
->clientForFile(doc->filePath()); client && client->reachable()) {
d->activeFilter = &d->lspFilter;
} else {
- d->activeFilter = &d->cppFilter;
+ d->activeFilter = d->cppFilter;
}
d->activeFilter->prepareSearch(entry);
}
diff --git a/src/plugins/clangcodemodel/clangdlocatorfilters.h b/src/plugins/clangcodemodel/clangdlocatorfilters.h
index bf3f6792820..2f695a4c97c 100644
--- a/src/plugins/clangcodemodel/clangdlocatorfilters.h
+++ b/src/plugins/clangcodemodel/clangdlocatorfilters.h
@@ -66,6 +66,8 @@ public:
ClangdCurrentDocumentFilter();
~ClangdCurrentDocumentFilter() override;
+ void updateCurrentClient();
+
private:
void prepareSearch(const QString &entry) override;
QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
diff --git a/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp b/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp
new file mode 100644
index 00000000000..ae7495fb944
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp
@@ -0,0 +1,925 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangdsemantichighlighting.h"
+
+#include "clangdast.h"
+#include "clangdclient.h"
+#include "clangdqpropertyhighlighter.h"
+#include "clangmodelmanagersupport.h"
+#include "tasktimers.h"
+
+#include <cppeditor/semantichighlighter.h>
+#include <languageclient/semantichighlightsupport.h>
+#include <languageserverprotocol/lsptypes.h>
+#include <texteditor/blockrange.h>
+#include <texteditor/textstyles.h>
+
+#include <QtConcurrent>
+#include <QTextDocument>
+
+using namespace LanguageClient;
+using namespace LanguageServerProtocol;
+using namespace TextEditor;
+
+namespace ClangCodeModel::Internal {
+Q_LOGGING_CATEGORY(clangdLogHighlight, "qtc.clangcodemodel.clangd.highlight", QtWarningMsg);
+
+// clangd reports also the #ifs, #elses and #endifs around the disabled code as disabled,
+// and not even in a consistent manner. We don't want this, so we have to clean up here.
+// But note that we require this behavior, as otherwise we would not be able to grey out
+// e.g. empty lines after an #ifdef, due to the lack of symbols.
+static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const QTextDocument *doc,
+ const QString &docContent)
+{
+ QList<BlockRange> ifdefedOutRanges;
+ int rangeStartPos = -1;
+ for (auto it = results.begin(); it != results.end();) {
+ const bool wasIfdefedOut = rangeStartPos != -1;
+ const bool isIfDefedOut = it->textStyles.mainStyle == C_DISABLED_CODE;
+ if (!isIfDefedOut) {
+ if (wasIfdefedOut) {
+ const QTextBlock block = doc->findBlockByNumber(it->line - 1);
+ ifdefedOutRanges << BlockRange(rangeStartPos, block.position());
+ rangeStartPos = -1;
+ }
+ ++it;
+ continue;
+ }
+
+ if (!wasIfdefedOut)
+ rangeStartPos = doc->findBlockByNumber(it->line - 1).position();
+
+ // Does the current line contain a potential "ifdefed-out switcher"?
+ // If not, no state change is possible and we continue with the next line.
+ const auto isPreprocessorControlStatement = [&] {
+ const int pos = Utils::Text::positionInText(doc, it->line, it->column);
+ const QStringView content = subViewLen(docContent, pos, it->length).trimmed();
+ if (content.isEmpty() || content.first() != '#')
+ return false;
+ int offset = 1;
+ while (offset < content.size() && content.at(offset).isSpace())
+ ++offset;
+ if (offset == content.size())
+ return false;
+ const QStringView ppDirective = content.mid(offset);
+ return ppDirective.startsWith(QLatin1String("if"))
+ || ppDirective.startsWith(QLatin1String("elif"))
+ || ppDirective.startsWith(QLatin1String("else"))
+ || ppDirective.startsWith(QLatin1String("endif"));
+ };
+ if (!isPreprocessorControlStatement()) {
+ ++it;
+ continue;
+ }
+
+ if (!wasIfdefedOut) {
+ // The #if or #else that starts disabled code should not be disabled.
+ const QTextBlock nextBlock = doc->findBlockByNumber(it->line);
+ rangeStartPos = nextBlock.isValid() ? nextBlock.position() : -1;
+ it = results.erase(it);
+ continue;
+ }
+
+ if (wasIfdefedOut && (it + 1 == results.end()
+ || (it + 1)->textStyles.mainStyle != C_DISABLED_CODE
+ || (it + 1)->line != it->line + 1)) {
+ // The #else or #endif that ends disabled code should not be disabled.
+ const QTextBlock block = doc->findBlockByNumber(it->line - 1);
+ ifdefedOutRanges << BlockRange(rangeStartPos, block.position());
+ rangeStartPos = -1;
+ it = results.erase(it);
+ continue;
+ }
+ ++it;
+ }
+
+ if (rangeStartPos != -1)
+ ifdefedOutRanges << BlockRange(rangeStartPos, doc->characterCount());
+
+ qCDebug(clangdLogHighlight) << "found" << ifdefedOutRanges.size() << "ifdefed-out ranges";
+ if (clangdLogHighlight().isDebugEnabled()) {
+ for (const BlockRange &r : qAsConst(ifdefedOutRanges))
+ qCDebug(clangdLogHighlight) << r.first() << r.last();
+ }
+
+ return ifdefedOutRanges;
+}
+
+class ExtraHighlightingResultsCollector
+{
+public:
+ ExtraHighlightingResultsCollector(QFutureInterface<HighlightingResult> &future,
+ HighlightingResults &results,
+ const Utils::FilePath &filePath, const ClangdAstNode &ast,
+ const QTextDocument *doc, const QString &docContent);
+
+ void collect();
+private:
+ static bool lessThan(const HighlightingResult &r1, const HighlightingResult &r2);
+ static int onlyIndexOf(const QStringView &text, const QStringView &subString, int from = 0);
+ int posForNodeStart(const ClangdAstNode &node) const;
+ int posForNodeEnd(const ClangdAstNode &node) const;
+ void insertResult(const HighlightingResult &result);
+ void insertResult(const ClangdAstNode &node, TextStyle style);
+ void insertAngleBracketInfo(int searchStart1, int searchEnd1, int searchStart2, int searchEnd2);
+ void setResultPosFromRange(HighlightingResult &result, const Range &range);
+ void collectFromNode(const ClangdAstNode &node);
+ void visitNode(const ClangdAstNode&node);
+
+ QFutureInterface<HighlightingResult> &m_future;
+ HighlightingResults &m_results;
+ const Utils::FilePath m_filePath;
+ const ClangdAstNode &m_ast;
+ const QTextDocument * const m_doc;
+ const QString &m_docContent;
+ ClangdAstNode::FileStatus m_currentFileStatus = ClangdAstNode::FileStatus::Unknown;
+};
+
+void doSemanticHighlighting(
+ QFutureInterface<HighlightingResult> &future,
+ const Utils::FilePath &filePath,
+ const QList<ExpandedSemanticToken> &tokens,
+ const QString &docContents,
+ const ClangdAstNode &ast,
+ const QPointer<TextDocument> &textDocument,
+ int docRevision,
+ const QVersionNumber &clangdVersion,
+ const TaskTimer &taskTimer)
+{
+ ThreadedSubtaskTimer t("highlighting", taskTimer);
+ if (future.isCanceled()) {
+ future.reportFinished();
+ return;
+ }
+
+ const QTextDocument doc(docContents);
+ const auto tokenRange = [&doc](const ExpandedSemanticToken &token) {
+ const Position startPos(token.line - 1, token.column - 1);
+ const Position endPos = startPos.withOffset(token.length, &doc);
+ return Range(startPos, endPos);
+ };
+ const auto isOutputParameter = [&ast, &tokenRange](const ExpandedSemanticToken &token) {
+ if (token.modifiers.contains(QLatin1String("usedAsMutableReference")))
+ return true;
+ if (token.type != "variable" && token.type != "property" && token.type != "parameter")
+ return false;
+ const Range range = tokenRange(token);
+ const ClangdAstPath path = getAstPath(ast, range);
+ if (path.size() < 2)
+ return false;
+ if (token.type == "property"
+ && (path.rbegin()->kind() == "MemberInitializer"
+ || path.rbegin()->kind() == "CXXConstruct")) {
+ return false;
+ }
+ if (path.rbegin()->hasConstType())
+ return false;
+ for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
+ if (it->kind() == "CXXConstruct" || it->kind() == "MemberInitializer")
+ return true;
+
+ if (it->kind() == "Call") {
+ // The first child is e.g. a called lambda or an object on which
+ // the call happens, and should not be highlighted as an output argument.
+ // If the call is not fully resolved (as in templates), we don't
+ // know whether the argument is passed as const or not.
+ if (it->arcanaContains("dependent type"))
+ return false;
+ const QList<ClangdAstNode> children = it->children().value_or(QList<ClangdAstNode>());
+ return children.isEmpty()
+ || (children.first().range() != (it - 1)->range()
+ && children.first().kind() != "UnresolvedLookup");
+ }
+
+ // The token should get marked for e.g. lambdas, but not for assignment operators,
+ // where the user sees that it's being written.
+ if (it->kind() == "CXXOperatorCall") {
+ const QList<ClangdAstNode> children = it->children().value_or(QList<ClangdAstNode>());
+
+ // Child 1 is the call itself, Child 2 is the named entity on which the call happens
+ // (a lambda or a class instance), after that follow the actual call arguments.
+ if (children.size() < 2)
+ return false;
+
+ // The call itself is never modifiable.
+ if (children.first().range() == range)
+ return false;
+
+ // The callable is never displayed as an output parameter.
+ // TODO: A good argument can be made to display objects on which a non-const
+ // operator or function is called as output parameters.
+ if (children.at(1).range().contains(range))
+ return false;
+
+ QList<ClangdAstNode> firstChildTree{children.first()};
+ while (!firstChildTree.isEmpty()) {
+ const ClangdAstNode n = firstChildTree.takeFirst();
+ const QString detail = n.detail().value_or(QString());
+ if (detail.startsWith("operator")) {
+ return !detail.contains('=')
+ && !detail.contains("++") && !detail.contains("--")
+ && !detail.contains("<<") && !detail.contains(">>")
+ && !detail.contains("*");
+ }
+ firstChildTree << n.children().value_or(QList<ClangdAstNode>());
+ }
+ return true;
+ }
+
+ if (it->kind() == "Lambda")
+ return false;
+ if (it->kind() == "BinaryOperator")
+ return false;
+ if (it->hasConstType())
+ return false;
+
+ if (it->kind() == "CXXMemberCall") {
+ if (it == path.rbegin())
+ return false;
+ const QList<ClangdAstNode> children = it->children().value_or(QList<ClangdAstNode>());
+ QTC_ASSERT(!children.isEmpty(), return false);
+
+ // The called object is never displayed as an output parameter.
+ // TODO: A good argument can be made to display objects on which a non-const
+ // operator or function is called as output parameters.
+ return (it - 1)->range() != children.first().range();
+ }
+
+ if (it->kind() == "Member" && it->arcanaContains("(")
+ && !it->arcanaContains("bound member function type")) {
+ return false;
+ }
+ }
+ return false;
+ };
+
+ const std::function<HighlightingResult(const ExpandedSemanticToken &)> toResult
+ = [&ast, &isOutputParameter, &clangdVersion, &tokenRange]
+ (const ExpandedSemanticToken &token) {
+ TextStyles styles;
+ if (token.type == "variable") {
+ if (token.modifiers.contains(QLatin1String("functionScope"))) {
+ styles.mainStyle = C_LOCAL;
+ } else if (token.modifiers.contains(QLatin1String("classScope"))) {
+ styles.mainStyle = C_FIELD;
+ } else if (token.modifiers.contains(QLatin1String("fileScope"))
+ || token.modifiers.contains(QLatin1String("globalScope"))) {
+ styles.mainStyle = C_GLOBAL;
+ }
+ } else if (token.type == "function" || token.type == "method") {
+ styles.mainStyle = token.modifiers.contains(QLatin1String("virtual"))
+ ? C_VIRTUAL_METHOD : C_FUNCTION;
+ if (ast.isValid()) {
+ const ClangdAstPath path = getAstPath(ast, tokenRange(token));
+ if (path.length() > 1) {
+ const ClangdAstNode declNode = path.at(path.length() - 2);
+ if (declNode.kind() == "Function" || declNode.kind() == "CXXMethod") {
+ if (clangdVersion < QVersionNumber(14)
+ && declNode.arcanaContains("' virtual")) {
+ styles.mainStyle = C_VIRTUAL_METHOD;
+ }
+ if (declNode.hasChildWithRole("statement"))
+ styles.mixinStyles.push_back(C_FUNCTION_DEFINITION);
+ }
+ }
+ }
+ } else if (token.type == "class") {
+ styles.mainStyle = C_TYPE;
+
+ // clang hardly ever differentiates between constructors and the associated class,
+ // whereas we highlight constructors as functions.
+ if (ast.isValid()) {
+ const ClangdAstPath path = getAstPath(ast, tokenRange(token));
+ if (!path.isEmpty()) {
+ if (path.last().kind() == "CXXConstructor") {
+ if (!path.last().arcanaContains("implicit"))
+ styles.mainStyle = C_FUNCTION;
+ } else if (path.last().kind() == "Record" && path.length() > 1) {
+ const ClangdAstNode node = path.at(path.length() - 2);
+ if (node.kind() == "CXXDestructor" && !node.arcanaContains("implicit")) {
+ styles.mainStyle = C_FUNCTION;
+
+ // https://github.com/clangd/clangd/issues/872
+ if (node.role() == "declaration")
+ styles.mixinStyles.push_back(C_DECLARATION);
+ }
+ }
+ }
+ }
+ } else if (token.type == "comment") { // "comment" means code disabled via the preprocessor
+ styles.mainStyle = C_DISABLED_CODE;
+ } else if (token.type == "namespace") {
+ styles.mainStyle = C_NAMESPACE;
+ } else if (token.type == "property") {
+ styles.mainStyle = C_FIELD;
+ } else if (token.type == "enum") {
+ styles.mainStyle = C_TYPE;
+ } else if (token.type == "enumMember") {
+ styles.mainStyle = C_ENUMERATION;
+ } else if (token.type == "parameter") {
+ styles.mainStyle = C_PARAMETER;
+ } else if (token.type == "macro") {
+ styles.mainStyle = C_MACRO;
+ } else if (token.type == "type") {
+ styles.mainStyle = C_TYPE;
+ } else if (token.type == "typeParameter") {
+ // clangd reports both type and non-type template parameters as type parameters,
+ // but the latter can be distinguished by the readonly modifier.
+ styles.mainStyle = token.modifiers.contains(QLatin1String("readonly"))
+ ? C_PARAMETER : C_TYPE;
+ }
+ if (token.modifiers.contains(QLatin1String("declaration")))
+ styles.mixinStyles.push_back(C_DECLARATION);
+ if (token.modifiers.contains(QLatin1String("static"))) {
+ if (styles.mainStyle != C_FIELD && styles.mainStyle != C_TEXT)
+ styles.mixinStyles.push_back(styles.mainStyle);
+ styles.mainStyle = C_STATIC_MEMBER;
+ }
+ if (isOutputParameter(token))
+ styles.mixinStyles.push_back(C_OUTPUT_ARGUMENT);
+ qCDebug(clangdLogHighlight) << "adding highlighting result"
+ << token.line << token.column << token.length << int(styles.mainStyle);
+ return HighlightingResult(token.line, token.column, token.length, styles);
+ };
+
+ auto results = QtConcurrent::blockingMapped<HighlightingResults>(tokens, toResult);
+ const QList<BlockRange> ifdefedOutBlocks = cleanupDisabledCode(results, &doc, docContents);
+ ExtraHighlightingResultsCollector(future, results, filePath, ast, &doc, docContents).collect();
+ if (!future.isCanceled()) {
+ qCInfo(clangdLogHighlight) << "reporting" << results.size() << "highlighting results";
+ QMetaObject::invokeMethod(textDocument, [textDocument, ifdefedOutBlocks, docRevision] {
+ if (textDocument && textDocument->document()->revision() == docRevision)
+ textDocument->setIfdefedOutBlocks(ifdefedOutBlocks);
+ }, Qt::QueuedConnection);
+ QList<Range> virtualRanges;
+ for (const HighlightingResult &r : results) {
+ if (r.textStyles.mainStyle != C_VIRTUAL_METHOD)
+ continue;
+ const Position startPos(r.line - 1, r.column - 1);
+ virtualRanges << Range(startPos, startPos.withOffset(r.length, &doc));
+ }
+ QMetaObject::invokeMethod(ClangModelManagerSupport::instance(),
+ [filePath, virtualRanges, docRevision] {
+ if (ClangdClient * const client
+ = ClangModelManagerSupport::instance()->clientForFile(filePath)) {
+ client->setVirtualRanges(filePath, virtualRanges, docRevision);
+ }
+ }, Qt::QueuedConnection);
+ future.reportResults(QVector<HighlightingResult>(results.cbegin(), results.cend()));
+ }
+ future.reportFinished();
+}
+
+ExtraHighlightingResultsCollector::ExtraHighlightingResultsCollector(
+ QFutureInterface<HighlightingResult> &future, HighlightingResults &results,
+ const Utils::FilePath &filePath, const ClangdAstNode &ast, const QTextDocument *doc,
+ const QString &docContent)
+ : m_future(future), m_results(results), m_filePath(filePath), m_ast(ast), m_doc(doc),
+ m_docContent(docContent)
+{
+}
+
+void ExtraHighlightingResultsCollector::collect()
+{
+ for (int i = 0; i < m_results.length(); ++i) {
+ const HighlightingResult res = m_results.at(i);
+ if (res.textStyles.mainStyle != TextEditor::C_MACRO || res.length != 10)
+ continue;
+ const int pos = Utils::Text::positionInText(m_doc, res.line, res.column);
+ if (subViewLen(m_docContent, pos, 10) != QLatin1String("Q_PROPERTY"))
+ continue;
+ int endPos;
+ if (i < m_results.length() - 1) {
+ const HighlightingResult nextRes = m_results.at(i + 1);
+ endPos = Utils::Text::positionInText(m_doc, nextRes.line, nextRes.column);
+ } else {
+ endPos = m_docContent.length();
+ }
+ const QString qPropertyString = m_docContent.mid(pos, endPos - pos);
+ QPropertyHighlighter propHighlighter(m_doc, qPropertyString, pos);
+ for (const HighlightingResult &newRes : propHighlighter.highlight())
+ m_results.insert(++i, newRes);
+ }
+
+ if (!m_ast.isValid())
+ return;
+ visitNode(m_ast);
+}
+
+bool ExtraHighlightingResultsCollector::lessThan(const HighlightingResult &r1,
+ const HighlightingResult &r2)
+{
+ return r1.line < r2.line || (r1.line == r2.line && r1.column < r2.column)
+ || (r1.line == r2.line && r1.column == r2.column && r1.length < r2.length);
+}
+
+int ExtraHighlightingResultsCollector::onlyIndexOf(const QStringView &text,
+ const QStringView &subString, int from)
+{
+ const int firstIndex = text.indexOf(subString, from);
+ if (firstIndex == -1)
+ return -1;
+ const int nextIndex = text.indexOf(subString, firstIndex + 1);
+
+ // The second condion deals with the off-by-one error in TemplateSpecialization nodes;
+ // see collectFromNode().
+ return nextIndex == -1 || nextIndex == firstIndex + 1 ? firstIndex : -1;
+}
+
+// Unfortunately, the exact position of a specific token is usually not
+// recorded in the AST, so if we need that, we have to search for it textually.
+// In corner cases, this might get sabotaged by e.g. comments, in which case we give up.
+int ExtraHighlightingResultsCollector::posForNodeStart(const ClangdAstNode &node) const
+{
+ return Utils::Text::positionInText(m_doc, node.range().start().line() + 1,
+ node.range().start().character() + 1);
+}
+
+int ExtraHighlightingResultsCollector::posForNodeEnd(const ClangdAstNode &node) const
+{
+ return Utils::Text::positionInText(m_doc, node.range().end().line() + 1,
+ node.range().end().character() + 1);
+}
+
+void ExtraHighlightingResultsCollector::insertResult(const HighlightingResult &result)
+{
+ if (!result.isValid()) // Some nodes don't have a range.
+ return;
+ const auto it = std::lower_bound(m_results.begin(), m_results.end(), result, lessThan);
+ if (it == m_results.end() || *it != result) {
+
+ // Prevent inserting expansions for function-like macros. For instance:
+ // #define TEST() "blubb"
+ // const char *s = TEST();
+ // The macro name is always shorter than the expansion and starts at the same
+ // location, so it should occur right before the insertion position.
+ if (it > m_results.begin() && (it - 1)->line == result.line
+ && (it - 1)->column == result.column
+ && (it - 1)->textStyles.mainStyle == C_MACRO) {
+ return;
+ }
+
+ // Bogus ranges; e.g. QTCREATORBUG-27601
+ if (it != m_results.end()) {
+ const int nextStartPos = Utils::Text::positionInText(m_doc, it->line, it->column);
+ const int resultEndPos = Utils::Text::positionInText(m_doc, result.line, result.column)
+ + result.length;
+ if (resultEndPos > nextStartPos)
+ return;
+ }
+
+ qCDebug(clangdLogHighlight) << "adding additional highlighting result"
+ << result.line << result.column << result.length;
+ m_results.insert(it, result);
+ return;
+ }
+
+ // This is for conversion operators, whose type part is only reported as a type by clangd.
+ if ((it->textStyles.mainStyle == C_TYPE
+ || it->textStyles.mainStyle == C_PRIMITIVE_TYPE)
+ && !result.textStyles.mixinStyles.empty()
+ && result.textStyles.mixinStyles.at(0) == C_OPERATOR) {
+ it->textStyles.mixinStyles = result.textStyles.mixinStyles;
+ }
+}
+
+void ExtraHighlightingResultsCollector::insertResult(const ClangdAstNode &node, TextStyle style)
+{
+ HighlightingResult result;
+ result.useTextSyles = true;
+ result.textStyles.mainStyle = style;
+ setResultPosFromRange(result, node.range());
+ insertResult(result);
+ return;
+}
+
+// For matching the "<" and ">" brackets of template declarations, specializations
+// and instantiations.
+void ExtraHighlightingResultsCollector::insertAngleBracketInfo(int searchStart1, int searchEnd1,
+ int searchStart2, int searchEnd2)
+{
+ const int openingAngleBracketPos = onlyIndexOf(
+ subViewEnd(m_docContent, searchStart1, searchEnd1),
+ QStringView(QStringLiteral("<")));
+ if (openingAngleBracketPos == -1)
+ return;
+ const int absOpeningAngleBracketPos = searchStart1 + openingAngleBracketPos;
+ if (absOpeningAngleBracketPos > searchStart2)
+ searchStart2 = absOpeningAngleBracketPos + 1;
+ if (searchStart2 >= searchEnd2)
+ return;
+ const int closingAngleBracketPos = onlyIndexOf(
+ subViewEnd(m_docContent, searchStart2, searchEnd2),
+ QStringView(QStringLiteral(">")));
+ if (closingAngleBracketPos == -1)
+ return;
+
+ const int absClosingAngleBracketPos = searchStart2 + closingAngleBracketPos;
+ if (absOpeningAngleBracketPos > absClosingAngleBracketPos)
+ return;
+
+ HighlightingResult result;
+ result.useTextSyles = true;
+ result.textStyles.mainStyle = C_PUNCTUATION;
+ Utils::Text::convertPosition(m_doc, absOpeningAngleBracketPos, &result.line, &result.column);
+ result.length = 1;
+ result.kind = CppEditor::SemanticHighlighter::AngleBracketOpen;
+ insertResult(result);
+ Utils::Text::convertPosition(m_doc, absClosingAngleBracketPos, &result.line, &result.column);
+ result.kind = CppEditor::SemanticHighlighter::AngleBracketClose;
+ insertResult(result);
+}
+
+void ExtraHighlightingResultsCollector::setResultPosFromRange(HighlightingResult &result,
+ const Range &range)
+{
+ if (!range.isValid())
+ return;
+ const Position startPos = range.start();
+ const Position endPos = range.end();
+ result.line = startPos.line() + 1;
+ result.column = startPos.character() + 1;
+ result.length = endPos.toPositionInDocument(m_doc) - startPos.toPositionInDocument(m_doc);
+}
+
+void ExtraHighlightingResultsCollector::collectFromNode(const ClangdAstNode &node)
+{
+ if (node.kind() == "UserDefinedLiteral")
+ return;
+ if (node.kind().endsWith("Literal")) {
+ const bool isKeyword = node.kind() == "CXXBoolLiteral"
+ || node.kind() == "CXXNullPtrLiteral";
+ const bool isStringLike = !isKeyword && (node.kind().startsWith("String")
+ || node.kind().startsWith("Character"));
+ const TextStyle style = isKeyword ? C_KEYWORD : isStringLike ? C_STRING : C_NUMBER;
+ insertResult(node, style);
+ return;
+ }
+ if (node.role() == "type" && node.kind() == "Builtin") {
+ insertResult(node, C_PRIMITIVE_TYPE);
+ return;
+ }
+ if (node.role() == "attribute" && (node.kind() == "Override" || node.kind() == "Final")) {
+ insertResult(node, C_KEYWORD);
+ return;
+ }
+
+ const bool isExpression = node.role() == "expression";
+ if (isExpression && node.kind() == "Predefined") {
+ insertResult(node, C_MACRO);
+ return;
+ }
+
+ const bool isDeclaration = node.role() == "declaration";
+ const int nodeStartPos = posForNodeStart(node);
+ const int nodeEndPos = posForNodeEnd(node);
+ const QList<ClangdAstNode> children = node.children().value_or(QList<ClangdAstNode>());
+
+ // Match question mark and colon in ternary operators.
+ if (isExpression && node.kind() == "ConditionalOperator") {
+ if (children.size() != 3)
+ return;
+
+ // The question mark is between sub-expressions 1 and 2, the colon is between
+ // sub-expressions 2 and 3.
+ const int searchStartPosQuestionMark = posForNodeEnd(children.first());
+ const int searchEndPosQuestionMark = posForNodeStart(children.at(1));
+ QStringView content = subViewEnd(m_docContent, searchStartPosQuestionMark,
+ searchEndPosQuestionMark);
+ const int questionMarkPos = onlyIndexOf(content, QStringView(QStringLiteral("?")));
+ if (questionMarkPos == -1)
+ return;
+ const int searchStartPosColon = posForNodeEnd(children.at(1));
+ const int searchEndPosColon = posForNodeStart(children.at(2));
+ content = subViewEnd(m_docContent, searchStartPosColon, searchEndPosColon);
+ const int colonPos = onlyIndexOf(content, QStringView(QStringLiteral(":")));
+ if (colonPos == -1)
+ return;
+
+ const int absQuestionMarkPos = searchStartPosQuestionMark + questionMarkPos;
+ const int absColonPos = searchStartPosColon + colonPos;
+ if (absQuestionMarkPos > absColonPos)
+ return;
+
+ HighlightingResult result;
+ result.useTextSyles = true;
+ result.textStyles.mainStyle = C_PUNCTUATION;
+ result.textStyles.mixinStyles.push_back(C_OPERATOR);
+ Utils::Text::convertPosition(m_doc, absQuestionMarkPos, &result.line, &result.column);
+ result.length = 1;
+ result.kind = CppEditor::SemanticHighlighter::TernaryIf;
+ insertResult(result);
+ Utils::Text::convertPosition(m_doc, absColonPos, &result.line, &result.column);
+ result.kind = CppEditor::SemanticHighlighter::TernaryElse;
+ insertResult(result);
+ return;
+ }
+
+ if (isDeclaration && (node.kind() == "FunctionTemplate"
+ || node.kind() == "ClassTemplate")) {
+ // The child nodes are the template parameters and and the function or class.
+ // The opening angle bracket is before the first child node, the closing angle
+ // bracket is before the function child node and after the last param node.
+ const QString classOrFunctionKind = QLatin1String(node.kind() == "FunctionTemplate"
+ ? "Function" : "CXXRecord");
+ const auto functionOrClassIt = std::find_if(children.begin(), children.end(),
+ [&classOrFunctionKind](const ClangdAstNode &n) {
+ return n.role() == "declaration" && n.kind() == classOrFunctionKind;
+ });
+ if (functionOrClassIt == children.end() || functionOrClassIt == children.begin())
+ return;
+ const int firstTemplateParamStartPos = posForNodeStart(children.first());
+ const int lastTemplateParamEndPos = posForNodeEnd(*(functionOrClassIt - 1));
+ const int functionOrClassStartPos = posForNodeStart(*functionOrClassIt);
+ insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
+ lastTemplateParamEndPos, functionOrClassStartPos);
+ return;
+ }
+
+ const auto isTemplateParamDecl = [](const ClangdAstNode &node) {
+ return node.isTemplateParameterDeclaration();
+ };
+ if (isDeclaration && node.kind() == "TypeAliasTemplate") {
+ // Children are one node of type TypeAlias and the template parameters.
+ // The opening angle bracket is before the first parameter and the closing
+ // angle bracket is after the last parameter.
+ // The TypeAlias node seems to appear first in the AST, even though lexically
+ // is comes after the parameters. We don't rely on the order here.
+ // Note that there is a second pair of angle brackets. That one is part of
+ // a TemplateSpecialization, which is handled further below.
+ const auto firstTemplateParam = std::find_if(children.begin(), children.end(),
+ isTemplateParamDecl);
+ if (firstTemplateParam == children.end())
+ return;
+ const auto lastTemplateParam = std::find_if(children.rbegin(), children.rend(),
+ isTemplateParamDecl);
+ QTC_ASSERT(lastTemplateParam != children.rend(), return);
+ const auto typeAlias = std::find_if(children.begin(), children.end(),
+ [](const ClangdAstNode &n) { return n.kind() == "TypeAlias"; });
+ if (typeAlias == children.end())
+ return;
+
+ const int firstTemplateParamStartPos = posForNodeStart(*firstTemplateParam);
+ const int lastTemplateParamEndPos = posForNodeEnd(*lastTemplateParam);
+ const int searchEndPos = posForNodeStart(*typeAlias);
+ insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
+ lastTemplateParamEndPos, searchEndPos);
+ return;
+ }
+
+ if (isDeclaration && node.kind() == "ClassTemplateSpecialization") {
+ // There is one child of kind TemplateSpecialization. The first pair
+ // of angle brackets comes before that.
+ if (children.size() == 1) {
+ const int childNodePos = posForNodeStart(children.first());
+ insertAngleBracketInfo(nodeStartPos, childNodePos, nodeStartPos, childNodePos);
+ }
+ return;
+ }
+
+ if (isDeclaration && node.kind() == "TemplateTemplateParm") {
+ // The child nodes are template arguments and template parameters.
+ // Arguments seem to appear before parameters in the AST, even though they
+ // come after them in the source code. We don't rely on the order here.
+ const auto firstTemplateParam = std::find_if(children.begin(), children.end(),
+ isTemplateParamDecl);
+ if (firstTemplateParam == children.end())
+ return;
+ const auto lastTemplateParam = std::find_if(children.rbegin(), children.rend(),
+ isTemplateParamDecl);
+ QTC_ASSERT(lastTemplateParam != children.rend(), return);
+ const auto templateArg = std::find_if(children.begin(), children.end(),
+ [](const ClangdAstNode &n) { return n.role() == "template argument"; });
+
+ const int firstTemplateParamStartPos = posForNodeStart(*firstTemplateParam);
+ const int lastTemplateParamEndPos = posForNodeEnd(*lastTemplateParam);
+ const int searchEndPos = templateArg == children.end()
+ ? nodeEndPos : posForNodeStart(*templateArg);
+ insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
+ lastTemplateParamEndPos, searchEndPos);
+ return;
+ }
+
+ // {static,dynamic,reinterpret}_cast<>().
+ if (isExpression && node.kind().startsWith("CXX") && node.kind().endsWith("Cast")) {
+ // First child is type, second child is expression.
+ // The opening angle bracket is before the first child, the closing angle bracket
+ // is between the two children.
+ if (children.size() == 2) {
+ insertAngleBracketInfo(nodeStartPos, posForNodeStart(children.first()),
+ posForNodeEnd(children.first()),
+ posForNodeStart(children.last()));
+ }
+ return;
+ }
+
+ if (node.kind() == "TemplateSpecialization") {
+ // First comes the template type, then the template arguments.
+ // The opening angle bracket is before the first template argument,
+ // the closing angle bracket is after the last template argument.
+ // The first child node has no range, so we start searching at the parent node.
+ if (children.size() >= 2) {
+ int searchStart2 = posForNodeEnd(children.last());
+ int searchEnd2 = nodeEndPos;
+
+ // There is a weird off-by-one error on the clang side: If there is a
+ // nested template instantiation *and* there is no space between
+ // the closing angle brackets, then the inner TemplateSpecialization node's range
+ // will extend one character too far, covering the outer's closing angle bracket.
+ // This is what we are correcting for here.
+ // This issue is tracked at https://github.com/clangd/clangd/issues/871.
+ if (searchStart2 == searchEnd2)
+ --searchStart2;
+ insertAngleBracketInfo(nodeStartPos, posForNodeStart(children.at(1)),
+ searchStart2, searchEnd2);
+ }
+ return;
+ }
+
+ if (!isExpression && !isDeclaration)
+ return;
+
+ // Operators, overloaded ones in particular.
+ static const QString operatorPrefix = "operator";
+ QString detail = node.detail().value_or(QString());
+ const bool isCallToNew = node.kind() == "CXXNew";
+ const bool isCallToDelete = node.kind() == "CXXDelete";
+ const auto isProperOperator = [&] {
+ if (isCallToNew || isCallToDelete)
+ return true;
+ if (!detail.startsWith(operatorPrefix))
+ return false;
+ if (detail == operatorPrefix)
+ return false;
+ const QChar nextChar = detail.at(operatorPrefix.length());
+ return !nextChar.isLetterOrNumber() && nextChar != '_';
+ };
+ if (!isProperOperator())
+ return;
+
+ if (!isCallToNew && !isCallToDelete)
+ detail.remove(0, operatorPrefix.length());
+
+ HighlightingResult result;
+ result.useTextSyles = true;
+ const bool isConversionOp = node.kind() == "CXXConversion";
+ const bool isOverloaded = !isConversionOp
+ && (isDeclaration || ((!isCallToNew && !isCallToDelete)
+ || node.arcanaContains("CXXMethod")));
+ result.textStyles.mainStyle = isConversionOp
+ ? C_PRIMITIVE_TYPE
+ : isCallToNew || isCallToDelete || detail.at(0).isSpace()
+ ? C_KEYWORD : C_PUNCTUATION;
+ result.textStyles.mixinStyles.push_back(C_OPERATOR);
+ if (isOverloaded)
+ result.textStyles.mixinStyles.push_back(C_OVERLOADED_OPERATOR);
+ if (isDeclaration)
+ result.textStyles.mixinStyles.push_back(C_DECLARATION);
+
+ const QStringView nodeText = subViewEnd(m_docContent, nodeStartPos, nodeEndPos);
+
+ if (isCallToNew || isCallToDelete) {
+ result.line = node.range().start().line() + 1;
+ result.column = node.range().start().character() + 1;
+ result.length = isCallToNew ? 3 : 6;
+ insertResult(result);
+ if (node.arcanaContains("array")) {
+ const int openingBracketOffset = nodeText.indexOf('[');
+ if (openingBracketOffset == -1)
+ return;
+ const int closingBracketOffset = nodeText.lastIndexOf(']');
+ if (closingBracketOffset == -1 || closingBracketOffset < openingBracketOffset)
+ return;
+
+ result.textStyles.mainStyle = C_PUNCTUATION;
+ result.length = 1;
+ Utils::Text::convertPosition(m_doc,
+ nodeStartPos + openingBracketOffset,
+ &result.line, &result.column);
+ insertResult(result);
+ Utils::Text::convertPosition(m_doc,
+ nodeStartPos + closingBracketOffset,
+ &result.line, &result.column);
+ insertResult(result);
+ }
+ return;
+ }
+
+ if (isExpression && (detail == QLatin1String("()") || detail == QLatin1String("[]"))) {
+ result.line = node.range().start().line() + 1;
+ result.column = node.range().start().character() + 1;
+ result.length = 1;
+ insertResult(result);
+ result.line = node.range().end().line() + 1;
+ result.column = node.range().end().character();
+ insertResult(result);
+ return;
+ }
+
+ const int opStringLen = detail.at(0).isSpace() ? detail.length() - 1 : detail.length();
+
+ // The simple case: Call to operator+, +=, * etc.
+ if (nodeEndPos - nodeStartPos == opStringLen) {
+ setResultPosFromRange(result, node.range());
+ insertResult(result);
+ return;
+ }
+
+ const int prefixOffset = nodeText.indexOf(operatorPrefix);
+ if (prefixOffset == -1)
+ return;
+
+ const bool isArray = detail == "[]";
+ const bool isCall = detail == "()";
+ const bool isArrayNew = detail == " new[]";
+ const bool isArrayDelete = detail == " delete[]";
+ const QStringView searchTerm = isArray || isCall
+ ? QStringView(detail).chopped(1) : isArrayNew || isArrayDelete
+ ? QStringView(detail).chopped(2) : detail;
+ const int opStringOffset = nodeText.indexOf(searchTerm, prefixOffset
+ + operatorPrefix.length());
+ if (opStringOffset == -1 || nodeText.indexOf(operatorPrefix, opStringOffset) != -1)
+ return;
+
+ const int opStringOffsetInDoc = nodeStartPos + opStringOffset
+ + detail.length() - opStringLen;
+ Utils::Text::convertPosition(m_doc, opStringOffsetInDoc, &result.line, &result.column);
+ result.length = opStringLen;
+ if (isArray || isCall)
+ result.length = 1;
+ else if (isArrayNew || isArrayDelete)
+ result.length -= 2;
+ if (!isArray && !isCall)
+ insertResult(result);
+ if (!isArray && !isCall && !isArrayNew && !isArrayDelete)
+ return;
+
+ result.textStyles.mainStyle = C_PUNCTUATION;
+ result.length = 1;
+ const int openingParenOffset = nodeText.indexOf(
+ isCall ? '(' : '[', prefixOffset + operatorPrefix.length());
+ if (openingParenOffset == -1)
+ return;
+ const int closingParenOffset = nodeText.indexOf(isCall ? ')' : ']', openingParenOffset + 1);
+ if (closingParenOffset == -1 || closingParenOffset < openingParenOffset)
+ return;
+ Utils::Text::convertPosition(m_doc, nodeStartPos + openingParenOffset,
+ &result.line, &result.column);
+ insertResult(result);
+ Utils::Text::convertPosition(m_doc, nodeStartPos + closingParenOffset,
+ &result.line, &result.column);
+ insertResult(result);
+}
+
+void ExtraHighlightingResultsCollector::visitNode(const ClangdAstNode &node)
+{
+ if (m_future.isCanceled())
+ return;
+ const ClangdAstNode::FileStatus prevFileStatus = m_currentFileStatus;
+ m_currentFileStatus = node.fileStatus(m_filePath);
+ if (m_currentFileStatus == ClangdAstNode::FileStatus::Unknown
+ && prevFileStatus != ClangdAstNode::FileStatus::Ours) {
+ m_currentFileStatus = prevFileStatus;
+ }
+ switch (m_currentFileStatus) {
+ case ClangdAstNode::FileStatus::Ours:
+ case ClangdAstNode::FileStatus::Unknown:
+ collectFromNode(node);
+ [[fallthrough]];
+ case ClangdAstNode::FileStatus::Foreign:
+ case ClangCodeModel::Internal::ClangdAstNode::FileStatus::Mixed: {
+ const auto children = node.children();
+ if (!children)
+ return;
+ for (const ClangdAstNode &childNode : *children)
+ visitNode(childNode);
+ break;
+ }
+ }
+ m_currentFileStatus = prevFileStatus;
+}
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/clangdsemantichighlighting.h b/src/plugins/clangcodemodel/clangdsemantichighlighting.h
new file mode 100644
index 00000000000..29a4446e9e1
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdsemantichighlighting.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QFutureInterface>
+#include <QLoggingCategory>
+#include <QPointer>
+#include <QVersionNumber>
+
+namespace LanguageClient { class ExpandedSemanticToken; }
+namespace TextEditor {
+class HighlightingResult;
+class TextDocument;
+}
+namespace Utils { class FilePath; }
+
+namespace ClangCodeModel::Internal {
+class ClangdAstNode;
+class TaskTimer;
+Q_DECLARE_LOGGING_CATEGORY(clangdLogHighlight);
+
+void doSemanticHighlighting(
+ QFutureInterface<TextEditor::HighlightingResult> &future,
+ const Utils::FilePath &filePath,
+ const QList<LanguageClient::ExpandedSemanticToken> &tokens,
+ const QString &docContents,
+ const ClangdAstNode &ast,
+ const QPointer<TextEditor::TextDocument> &textDocument,
+ int docRevision,
+ const QVersionNumber &clangdVersion,
+ const TaskTimer &taskTimer
+ );
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/clangdswitchdecldef.cpp b/src/plugins/clangcodemodel/clangdswitchdecldef.cpp
new file mode 100644
index 00000000000..28c27034f48
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdswitchdecldef.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangdswitchdecldef.h"
+
+#include "clangdast.h"
+#include "clangdclient.h"
+
+#include <cppeditor/cppeditorwidget.h>
+#include <languageclient/documentsymbolcache.h>
+#include <languageserverprotocol/lsptypes.h>
+#include <texteditor/textdocument.h>
+#include <utils/optional.h>
+#include <utils/qtcassert.h>
+
+#include <QApplication>
+#include <QTextCursor>
+
+using namespace CppEditor;
+using namespace LanguageClient;
+using namespace LanguageServerProtocol;
+using namespace TextEditor;
+using namespace Utils;
+
+namespace ClangCodeModel::Internal {
+
+class ClangdSwitchDeclDef::Private
+{
+public:
+ Private(ClangdSwitchDeclDef * q, ClangdClient *client, TextDocument *doc,
+ const QTextCursor &cursor, CppEditorWidget *editorWidget, const LinkHandler &callback)
+ : q(q), client(client), document(doc), uri(DocumentUri::fromFilePath(doc->filePath())),
+ cursor(cursor), editorWidget(editorWidget), callback(callback)
+ {}
+
+ optional<ClangdAstNode> getFunctionNode() const;
+ QTextCursor cursorForFunctionName(const ClangdAstNode &functionNode) const;
+ void handleDeclDefSwitchReplies();
+
+ ClangdSwitchDeclDef * const q;
+ ClangdClient * const client;
+ const QPointer<TextDocument> document;
+ const DocumentUri uri;
+ const QTextCursor cursor;
+ const QPointer<CppEditorWidget> editorWidget;
+ const LinkHandler callback;
+ optional<ClangdAstNode> ast;
+ optional<DocumentSymbolsResult> docSymbols;
+ bool done = false;
+};
+
+ClangdSwitchDeclDef::ClangdSwitchDeclDef(ClangdClient *client, TextDocument *doc,
+ const QTextCursor &cursor, CppEditorWidget *editorWidget, const LinkHandler &callback)
+ : QObject(client), d(new Private(this, client, doc, cursor, editorWidget, callback))
+{
+ // Abort if the user does something else with the document in the meantime.
+ connect(doc, &TextDocument::contentsChanged, this, &ClangdSwitchDeclDef::emitDone,
+ Qt::QueuedConnection);
+ if (editorWidget) {
+ connect(editorWidget, &CppEditorWidget::cursorPositionChanged,
+ this, &ClangdSwitchDeclDef::emitDone, Qt::QueuedConnection);
+ }
+ connect(qApp, &QApplication::focusChanged,
+ this, &ClangdSwitchDeclDef::emitDone, Qt::QueuedConnection);
+
+ connect(client->documentSymbolCache(), &DocumentSymbolCache::gotSymbols, this,
+ [this](const DocumentUri &uri, const DocumentSymbolsResult &symbols) {
+ if (uri != d->uri)
+ return;
+ d->docSymbols = symbols;
+ if (d->ast)
+ d->handleDeclDefSwitchReplies();
+ });
+
+
+ // Retrieve AST and document symbols.
+ const auto astHandler = [this, self = QPointer(this)]
+ (const ClangdAstNode &ast, const MessageId &) {
+ qCDebug(clangdLog) << "received ast for decl/def switch";
+ if (!self)
+ return;
+ if (!d->document) {
+ emitDone();
+ return;
+ }
+ if (!ast.isValid()) {
+ emitDone();
+ return;
+ }
+ d->ast = ast;
+ if (d->docSymbols)
+ d->handleDeclDefSwitchReplies();
+
+ };
+ client->getAndHandleAst(doc, astHandler, ClangdClient::AstCallbackMode::SyncIfPossible, {});
+ client->documentSymbolCache()->requestSymbols(d->uri, Schedule::Now);
+}
+
+ClangdSwitchDeclDef::~ClangdSwitchDeclDef()
+{
+ delete d;
+}
+
+void ClangdSwitchDeclDef::emitDone()
+{
+ if (d->done)
+ return;
+
+ d->done = true;
+ emit done();
+}
+
+optional<ClangdAstNode> ClangdSwitchDeclDef::Private::getFunctionNode() const
+{
+ QTC_ASSERT(ast, return {});
+
+ const ClangdAstPath path = getAstPath(*ast, Range(cursor));
+ for (auto it = path.rbegin(); it != path.rend(); ++it) {
+ if (it->role() == "declaration"
+ && (it->kind() == "CXXMethod" || it->kind() == "CXXConversion"
+ || it->kind() == "CXXConstructor" || it->kind() == "CXXDestructor"
+ || it->kind() == "Function")) {
+ return *it;
+ }
+ }
+ return {};
+}
+
+QTextCursor ClangdSwitchDeclDef::Private::cursorForFunctionName(const ClangdAstNode &functionNode) const
+{
+ QTC_ASSERT(docSymbols, return {});
+
+ const auto symbolList = Utils::get_if<QList<DocumentSymbol>>(&*docSymbols);
+ if (!symbolList)
+ return {};
+ const Range &astRange = functionNode.range();
+ QList symbolsToCheck = *symbolList;
+ while (!symbolsToCheck.isEmpty()) {
+ const DocumentSymbol symbol = symbolsToCheck.takeFirst();
+ if (symbol.range() == astRange)
+ return symbol.selectionRange().start().toTextCursor(document->document());
+ if (symbol.range().contains(astRange))
+ symbolsToCheck << symbol.children().value_or(QList<DocumentSymbol>());
+ }
+ return {};
+}
+
+void ClangdSwitchDeclDef::Private::handleDeclDefSwitchReplies()
+{
+ if (!document) {
+ q->emitDone();
+ return;
+ }
+
+ // Find the function declaration or definition associated with the cursor.
+ // For instance, the cursor could be somwehere inside a function body or
+ // on a function return type, or ...
+ if (clangdLogAst().isDebugEnabled())
+ ast->print(0);
+ const Utils::optional<ClangdAstNode> functionNode = getFunctionNode();
+ if (!functionNode) {
+ q->emitDone();
+ return;
+ }
+
+ // Unfortunately, the AST does not contain the location of the actual function name symbol,
+ // so we have to look for it in the document symbols.
+ const QTextCursor funcNameCursor = cursorForFunctionName(*functionNode);
+ if (!funcNameCursor.isNull()) {
+ client->followSymbol(document.data(), funcNameCursor, editorWidget, callback,
+ true, false);
+ }
+ q->emitDone();
+}
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/clangdswitchdecldef.h b/src/plugins/clangcodemodel/clangdswitchdecldef.h
new file mode 100644
index 00000000000..44e296686db
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdswitchdecldef.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/link.h>
+
+#include <QObject>
+
+namespace CppEditor { class CppEditorWidget; }
+namespace TextEditor { class TextDocument; }
+
+QT_BEGIN_NAMESPACE
+class QTextCursor;
+QT_END_NAMESPACE
+
+namespace ClangCodeModel::Internal {
+class ClangdClient;
+
+class ClangdSwitchDeclDef : public QObject
+{
+ Q_OBJECT
+public:
+ ClangdSwitchDeclDef(ClangdClient *client, TextEditor::TextDocument *doc,
+ const QTextCursor &cursor, CppEditor::CppEditorWidget *editorWidget,
+ const Utils::LinkHandler &callback);
+ ~ClangdSwitchDeclDef();
+
+signals:
+ void done();
+
+private:
+ void emitDone();
+ class Private;
+ Private * const d;
+};
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp
deleted file mode 100644
index b892f393648..00000000000
--- a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangeditordocumentparser.h"
-
-namespace ClangCodeModel {
-namespace Internal {
-
-ClangEditorDocumentParser::ClangEditorDocumentParser(const QString &filePath)
- : BaseEditorDocumentParser(filePath)
-{
-}
-
-void ClangEditorDocumentParser::updateImpl(const QFutureInterface<void> &,
- const UpdateParams &updateParams)
-{
- State state_ = state();
- state_.projectPartInfo = determineProjectPart(filePath(),
- configuration().preferredProjectPartId,
- state_.projectPartInfo,
- updateParams.activeProject,
- updateParams.languagePreference,
- updateParams.projectsUpdated);
- emit projectPartInfoUpdated(state_.projectPartInfo);
- setState(state_);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangeditordocumentparser.h b/src/plugins/clangcodemodel/clangeditordocumentparser.h
deleted file mode 100644
index e917ff9e360..00000000000
--- a/src/plugins/clangcodemodel/clangeditordocumentparser.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <cppeditor/baseeditordocumentparser.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangEditorDocumentParser : public CppEditor::BaseEditorDocumentParser
-{
- Q_OBJECT
-
-public:
- ClangEditorDocumentParser(const QString &filePath);
-
-private:
- void updateImpl(const QFutureInterface<void> &future,
- const UpdateParams &updateParams) override;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
index 1b2027139f1..bff5b85e236 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
@@ -25,20 +25,11 @@
#include "clangeditordocumentprocessor.h"
-#include "clangbackendcommunicator.h"
-#include "clangprojectsettings.h"
#include "clangdiagnostictooltipwidget.h"
#include "clangfixitoperation.h"
-#include "clangfixitoperationsextractor.h"
#include "clangmodelmanagersupport.h"
-#include "clanghighlightingresultreporter.h"
#include "clangutils.h"
-#include <diagnosticcontainer.h>
-#include <sourcelocationcontainer.h>
-
-#include <clangsupport/tokeninfocontainer.h>
-
#include <cppeditor/builtincursorinfo.h>
#include <cppeditor/clangdiagnosticconfigsmodel.h>
#include <cppeditor/compileroptionsbuilder.h>
@@ -67,69 +58,14 @@
namespace ClangCodeModel {
namespace Internal {
-ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
- BackendCommunicator &communicator,
- TextEditor::TextDocument *document)
- : BaseEditorDocumentProcessor(document->document(), document->filePath().toString())
- , m_document(*document)
- , m_diagnosticManager(document)
- , m_communicator(communicator)
- , m_parser(new ClangEditorDocumentParser(document->filePath().toString()))
- , m_parserRevision(0)
- , m_semanticHighlighter(document)
- , m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false)
+ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(TextEditor::TextDocument *document)
+ : BuiltinEditorDocumentProcessor(document), m_document(*document)
{
- m_updateBackendDocumentTimer.setSingleShot(true);
- m_updateBackendDocumentTimer.setInterval(350);
- connect(&m_updateBackendDocumentTimer, &QTimer::timeout,
- this, &ClangEditorDocumentProcessor::updateBackendDocumentIfProjectPartExists);
-
- connect(m_parser.data(), &ClangEditorDocumentParser::projectPartInfoUpdated,
+ connect(parser().data(), &CppEditor::BaseEditorDocumentParser::projectPartInfoUpdated,
this, &BaseEditorDocumentProcessor::projectPartInfoUpdated);
-
- // Forwarding the semantic info from the builtin processor enables us to provide all
- // editor (widget) related features that are not yet implemented by the clang plugin.
- connect(&m_builtinProcessor, &CppEditor::BuiltinEditorDocumentProcessor::cppDocumentUpdated,
- this, &ClangEditorDocumentProcessor::cppDocumentUpdated);
- connect(&m_builtinProcessor, &CppEditor::BuiltinEditorDocumentProcessor::semanticInfoUpdated,
- this, &ClangEditorDocumentProcessor::semanticInfoUpdated);
-
- m_parserSynchronizer.setCancelOnWait(true);
-}
-
-ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
-{
- m_updateBackendDocumentTimer.stop();
-
- if (m_projectPart)
- closeBackendDocument();
-}
-
-void ClangEditorDocumentProcessor::runImpl(
- const CppEditor::BaseEditorDocumentParser::UpdateParams &updateParams)
-{
- m_updateBackendDocumentTimer.start();
-
- // Run clang parser
- disconnect(&m_parserWatcher, &QFutureWatcher<void>::finished,
- this, &ClangEditorDocumentProcessor::onParserFinished);
- m_parserWatcher.cancel();
- m_parserWatcher.setFuture(QFuture<void>());
-
- m_parserRevision = revision();
- connect(&m_parserWatcher, &QFutureWatcher<void>::finished,
- this, &ClangEditorDocumentProcessor::onParserFinished);
- const QFuture<void> future = ::Utils::runAsync(&runParser, parser(), updateParams);
- m_parserWatcher.setFuture(future);
- m_parserSynchronizer.addFuture(future);
-
- // Run builtin processor
- m_builtinProcessor.runImpl(updateParams);
-}
-
-void ClangEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force)
-{
- m_builtinProcessor.recalculateSemanticInfoDetached(force);
+ setSemanticHighlightingChecker([this] {
+ return !ClangModelManagerSupport::instance()->clientForFile(m_document.filePath());
+ });
}
void ClangEditorDocumentProcessor::semanticRehighlight()
@@ -141,30 +77,7 @@ void ClangEditorDocumentProcessor::semanticRehighlight()
return;
if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
return;
-
- m_semanticHighlighter.updateFormatMapFromFontSettings();
- if (m_projectPart)
- requestAnnotationsFromBackend();
-}
-
-CppEditor::SemanticInfo ClangEditorDocumentProcessor::recalculateSemanticInfo()
-{
- return m_builtinProcessor.recalculateSemanticInfo();
-}
-
-CppEditor::BaseEditorDocumentParser::Ptr ClangEditorDocumentProcessor::parser()
-{
- return m_parser;
-}
-
-CPlusPlus::Snapshot ClangEditorDocumentProcessor::snapshot()
-{
- return m_builtinProcessor.snapshot();
-}
-
-bool ClangEditorDocumentProcessor::isParserRunning() const
-{
- return m_parserWatcher.isRunning();
+ BuiltinEditorDocumentProcessor::semanticRehighlight();
}
bool ClangEditorDocumentProcessor::hasProjectPart() const
@@ -187,235 +100,16 @@ void ClangEditorDocumentProcessor::clearProjectPart()
return m_diagnosticConfigId;
}
-void ClangEditorDocumentProcessor::updateCodeWarnings(
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
- uint documentRevision)
-{
- if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
- return;
-
- if (documentRevision == revision()) {
- if (m_invalidationState == InvalidationState::Scheduled)
- m_invalidationState = InvalidationState::Canceled;
- m_diagnosticManager.processNewDiagnostics(diagnostics, m_isProjectFile);
- const auto codeWarnings = m_diagnosticManager.takeExtraSelections();
- const auto fixitAvailableMarkers = m_diagnosticManager.takeFixItAvailableMarkers();
- const auto creator = creatorForHeaderErrorDiagnosticWidget(firstHeaderErrorDiagnostic);
-
- emit codeWarningsUpdated(revision(),
- codeWarnings,
- creator,
- fixitAvailableMarkers);
- }
-}
-namespace {
-
-TextEditor::BlockRange
-toTextEditorBlock(QTextDocument *textDocument,
- const ClangBackEnd::SourceRangeContainer &sourceRangeContainer)
-{
- return {::Utils::Text::positionInText(textDocument,
- sourceRangeContainer.start.line,
- sourceRangeContainer.start.column),
- ::Utils::Text::positionInText(textDocument,
- sourceRangeContainer.end.line,
- sourceRangeContainer.end.column)};
-}
-
-QList<TextEditor::BlockRange>
-toTextEditorBlocks(QTextDocument *textDocument,
- const QVector<ClangBackEnd::SourceRangeContainer> &ifdefedOutRanges)
-{
- QList<TextEditor::BlockRange> blockRanges;
- blockRanges.reserve(ifdefedOutRanges.size());
-
- for (const auto &range : ifdefedOutRanges)
- blockRanges.append(toTextEditorBlock(textDocument, range));
-
- return blockRanges;
-}
-}
-
-const QVector<ClangBackEnd::TokenInfoContainer>
-&ClangEditorDocumentProcessor::tokenInfos() const
-{
- return m_tokenInfos;
-}
-
-void ClangEditorDocumentProcessor::clearTaskHubIssues()
-{
- ClangDiagnosticManager::clearTaskHubIssues();
-}
-
-void ClangEditorDocumentProcessor::generateTaskHubIssues()
-{
- m_diagnosticManager.generateTaskHubIssues();
-}
-
-void ClangEditorDocumentProcessor::clearTextMarks(const Utils::FilePath &filePath)
-{
- if (ClangEditorDocumentProcessor * const proc = get(filePath.toString())) {
- proc->m_diagnosticManager.cleanMarks();
- emit proc->codeWarningsUpdated(proc->revision(), {}, {}, {});
- }
-}
-
-void ClangEditorDocumentProcessor::updateHighlighting(
- const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
- const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
- uint documentRevision)
-{
- if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
- return;
- if (documentRevision == revision()) {
- const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges);
- emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
-
- m_semanticHighlighter.setHighlightingRunner(
- [tokenInfos]() { return highlightResults(tokenInfos); });
- m_semanticHighlighter.run();
- }
-}
-
-void ClangEditorDocumentProcessor::updateTokenInfos(
- const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
- uint documentRevision)
-{
- if (documentRevision != revision())
- return;
- m_tokenInfos = tokenInfos;
- emit tokenInfosUpdated();
-}
-
-static int currentLine(const TextEditor::AssistInterface &assistInterface)
-{
- int line, column;
- ::Utils::Text::convertPosition(assistInterface.textDocument(), assistInterface.position(),
- &line, &column);
- return line;
-}
-
-TextEditor::QuickFixOperations ClangEditorDocumentProcessor::extraRefactoringOperations(
- const TextEditor::AssistInterface &assistInterface)
-{
- ClangFixItOperationsExtractor extractor(m_diagnosticManager.diagnosticsWithFixIts());
-
- return extractor.extract(assistInterface.filePath().toString(), currentLine(assistInterface));
-}
-
-void ClangEditorDocumentProcessor::editorDocumentTimerRestarted()
-{
- m_updateBackendDocumentTimer.stop(); // Wait for the next call to run().
- m_invalidationState = InvalidationState::Scheduled;
-}
-
-void ClangEditorDocumentProcessor::invalidateDiagnostics()
-{
- if (m_invalidationState != InvalidationState::Canceled)
- m_diagnosticManager.invalidateDiagnostics();
- m_invalidationState = InvalidationState::Off;
-}
-
-TextEditor::TextMarks ClangEditorDocumentProcessor::diagnosticTextMarksAt(uint line,
- uint column) const
-{
- return m_diagnosticManager.diagnosticTextMarksAt(line, column);
-}
-
void ClangEditorDocumentProcessor::setParserConfig(
const CppEditor::BaseEditorDocumentParser::Configuration &config)
{
- m_parser->setConfiguration(config);
- m_builtinProcessor.parser()->setConfiguration(config);
+ CppEditor::BuiltinEditorDocumentProcessor::setParserConfig(config);
emit parserConfigChanged(Utils::FilePath::fromString(filePath()), config);
}
-CppEditor::BaseEditorDocumentParser::Configuration ClangEditorDocumentProcessor::parserConfig() const
+CppEditor::BaseEditorDocumentParser::Configuration ClangEditorDocumentProcessor::parserConfig()
{
- return m_parser->configuration();
-}
-
-static bool isCursorOnIdentifier(const QTextCursor &textCursor)
-{
- QTextDocument *document = textCursor.document();
- return CppEditor::isValidIdentifierChar(document->characterAt(textCursor.position()));
-}
-
-static QFuture<CppEditor::CursorInfo> defaultCursorInfoFuture()
-{
- QFutureInterface<CppEditor::CursorInfo> futureInterface;
- futureInterface.reportResult(CppEditor::CursorInfo());
- futureInterface.reportFinished();
-
- return futureInterface.future();
-}
-
-static bool convertPosition(const QTextCursor &textCursor, int *line, int *column)
-{
- const bool converted = ::Utils::Text::convertPosition(textCursor.document(),
- textCursor.position(),
- line,
- column);
- QTC_CHECK(converted);
- return converted;
-}
-
-QFuture<CppEditor::CursorInfo>
-ClangEditorDocumentProcessor::cursorInfo(const CppEditor::CursorInfoParams &params)
-{
- int line, column;
- convertPosition(params.textCursor, &line, &column);
-
- if (!isCursorOnIdentifier(params.textCursor))
- return defaultCursorInfoFuture();
-
- column = clangColumn(params.textCursor.document()->findBlockByNumber(line - 1), column);
- const CppEditor::SemanticInfo::LocalUseMap localUses
- = CppEditor::BuiltinCursorInfo::findLocalUses(params.semanticInfo.doc, line, column);
-
- return m_communicator.requestReferences(simpleFileContainer(),
- static_cast<quint32>(line),
- static_cast<quint32>(column),
- localUses);
-}
-
-QFuture<CppEditor::CursorInfo> ClangEditorDocumentProcessor::requestLocalReferences(
- const QTextCursor &cursor)
-{
- int line, column;
- convertPosition(cursor, &line, &column);
- ++column; // for 1-based columns
-
- // TODO: check that by highlighting items
- if (!isCursorOnIdentifier(cursor))
- return defaultCursorInfoFuture();
-
- return m_communicator.requestLocalReferences(simpleFileContainer(),
- static_cast<quint32>(line),
- static_cast<quint32>(column));
-}
-
-QFuture<CppEditor::SymbolInfo>
-ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column)
-{
- return m_communicator.requestFollowSymbol(simpleFileContainer(),
- static_cast<quint32>(line),
- static_cast<quint32>(column));
-}
-
-QFuture<CppEditor::ToolTipInfo> ClangEditorDocumentProcessor::toolTipInfo(const QByteArray &codecName,
- int line,
- int column)
-{
- return m_communicator.requestToolTip(simpleFileContainer(codecName),
- static_cast<quint32>(line),
- static_cast<quint32>(column));
-}
-
-void ClangEditorDocumentProcessor::clearDiagnosticsWithFixIts()
-{
- m_diagnosticManager.clearDiagnosticsWithFixIts();
+ return parser()->configuration();
}
ClangEditorDocumentProcessor *ClangEditorDocumentProcessor::get(const QString &filePath)
@@ -424,139 +118,5 @@ ClangEditorDocumentProcessor *ClangEditorDocumentProcessor::get(const QString &f
CppEditor::CppModelManager::cppEditorDocumentProcessor(filePath));
}
-static bool isProjectPartLoadedOrIsFallback(CppEditor::ProjectPart::ConstPtr projectPart)
-{
- return projectPart
- && (projectPart->id().isEmpty() || isProjectPartLoaded(projectPart));
-}
-
-void ClangEditorDocumentProcessor::updateBackendProjectPartAndDocument()
-{
- const CppEditor::ProjectPart::ConstPtr projectPart = m_parser->projectPartInfo().projectPart;
-
- if (isProjectPartLoadedOrIsFallback(projectPart)) {
- updateBackendDocument(*projectPart.data());
-
- m_projectPart = projectPart;
- m_isProjectFile = m_parser->projectPartInfo().hints
- & CppEditor::ProjectPartInfo::IsFromProjectMatch;
- }
-}
-
-void ClangEditorDocumentProcessor::onParserFinished()
-{
- if (revision() != m_parserRevision)
- return;
-
- updateBackendProjectPartAndDocument();
-}
-
-void ClangEditorDocumentProcessor::updateBackendDocument(const CppEditor::ProjectPart &projectPart)
-{
- // On registration we send the document content immediately as an unsaved
- // file, because
- // (1) a refactoring action might have opened and already modified
- // this document.
- // (2) it prevents an extra preamble generation on first user
- // modification of the document in case the line endings on disk
- // differ from the ones returned by textDocument()->toPlainText(),
- // like on Windows.
-
- if (m_projectPart) {
- if (projectPart.id() == m_projectPart->id())
- return;
- }
-
- ProjectExplorer::Project * const project = CppEditor::projectForProjectPart(projectPart);
- const CppEditor::ClangDiagnosticConfig config = warningsConfigForProject(project);
- const QStringList clangOptions = createClangOptions(projectPart, filePath(), config,
- optionsForProject(project));
- m_diagnosticConfigId = config.id();
-
- m_communicator.documentsOpened(
- {fileContainerWithOptionsAndDocumentContent(clangOptions, projectPart.headerPaths)});
- setLastSentDocumentRevision(filePath(), revision());
-}
-
-void ClangEditorDocumentProcessor::closeBackendDocument()
-{
- QTC_ASSERT(m_projectPart, return);
- m_communicator.documentsClosed({ClangBackEnd::FileContainer(filePath(), m_projectPart->id())});
-}
-
-void ClangEditorDocumentProcessor::updateBackendDocumentIfProjectPartExists()
-{
- if (m_projectPart) {
- const ClangBackEnd::FileContainer fileContainer = fileContainerWithDocumentContent();
- m_communicator.documentsChangedWithRevisionCheck(fileContainer);
- }
-}
-
-void ClangEditorDocumentProcessor::requestAnnotationsFromBackend()
-{
- const auto fileContainer = fileContainerWithDocumentContent();
- m_communicator.requestAnnotations(fileContainer);
-}
-
-CppEditor::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator
-ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget(
- const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic)
-{
- if (firstHeaderErrorDiagnostic.text.isEmpty())
- return CppEditor::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator();
-
- return [firstHeaderErrorDiagnostic]() {
- auto vbox = new QVBoxLayout;
- vbox->setContentsMargins(10, 0, 0, 2);
- vbox->setSpacing(2);
-
- vbox->addWidget(ClangDiagnosticWidget::createWidget({firstHeaderErrorDiagnostic},
- ClangDiagnosticWidget::InfoBar, {},
- "libclang"));
-
- auto widget = new QWidget;
- widget->setLayout(vbox);
-
- return widget;
- };
-}
-
-ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer(
- const QByteArray &codecName) const
-{
- return ClangBackEnd::FileContainer(filePath(),
- Utf8String(),
- false,
- revision(),
- Utf8String::fromByteArray(codecName));
-}
-
-ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithOptionsAndDocumentContent(
- const QStringList &compilationArguments, const ProjectExplorer::HeaderPaths headerPaths) const
-{
- auto theHeaderPaths
- = ::Utils::transform<QVector>(headerPaths, [](const ProjectExplorer::HeaderPath path) {
- return Utf8String(QDir::toNativeSeparators(path.path));
- });
- theHeaderPaths << QDir::toNativeSeparators(
- ClangModelManagerSupport::instance()->dummyUiHeaderOnDiskDirPath());
-
- return ClangBackEnd::FileContainer(filePath(),
- Utf8StringVector(compilationArguments),
- theHeaderPaths,
- textDocument()->toPlainText(),
- true,
- revision());
-}
-
-ClangBackEnd::FileContainer
-ClangEditorDocumentProcessor::fileContainerWithDocumentContent() const
-{
- return ClangBackEnd::FileContainer(filePath(),
- textDocument()->toPlainText(),
- true,
- revision());
-}
-
} // namespace Internal
} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
index 7111eee4c80..59939177532 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
@@ -25,46 +25,21 @@
#pragma once
-#include "clangdiagnosticmanager.h"
-#include "clangeditordocumentparser.h"
-
#include <cppeditor/builtineditordocumentprocessor.h>
-#include <cppeditor/semantichighlighter.h>
-#include <utils/futuresynchronizer.h>
#include <utils/id.h>
-#include <QFutureWatcher>
-#include <QTimer>
-
-namespace ClangBackEnd {
-class DiagnosticContainer;
-class TokenInfoContainer;
-class FileContainer;
-}
-
namespace ClangCodeModel {
namespace Internal {
-class BackendCommunicator;
-
-class ClangEditorDocumentProcessor : public CppEditor::BaseEditorDocumentProcessor
+class ClangEditorDocumentProcessor : public CppEditor::BuiltinEditorDocumentProcessor
{
Q_OBJECT
public:
- ClangEditorDocumentProcessor(BackendCommunicator &communicator,
- TextEditor::TextDocument *document);
- ~ClangEditorDocumentProcessor() override;
+ ClangEditorDocumentProcessor(TextEditor::TextDocument *document);
- // BaseEditorDocumentProcessor interface
- void runImpl(const CppEditor::BaseEditorDocumentParser::UpdateParams &updateParams) override;
void semanticRehighlight() override;
- void recalculateSemanticInfoDetached(bool force) override;
- CppEditor::SemanticInfo recalculateSemanticInfo() override;
- CppEditor::BaseEditorDocumentParser::Ptr parser() override;
- CPlusPlus::Snapshot snapshot() override;
- bool isParserRunning() const override;
bool hasProjectPart() const;
CppEditor::ProjectPart::ConstPtr projectPart() const;
@@ -72,86 +47,20 @@ public:
::Utils::Id diagnosticConfigId() const;
- void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
- const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
- uint documentRevision);
- void updateHighlighting(const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
- const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
- uint documentRevision);
- void updateTokenInfos(const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
- uint documentRevision);
-
- TextEditor::QuickFixOperations
- extraRefactoringOperations(const TextEditor::AssistInterface &assistInterface) override;
-
- void invalidateDiagnostics() override;
-
- TextEditor::TextMarks diagnosticTextMarksAt(uint line, uint column) const;
-
- void editorDocumentTimerRestarted() override;
-
void setParserConfig(const CppEditor::BaseEditorDocumentParser::Configuration &config) override;
- CppEditor::BaseEditorDocumentParser::Configuration parserConfig() const;
-
- QFuture<CppEditor::CursorInfo> cursorInfo(const CppEditor::CursorInfoParams &params) override;
- QFuture<CppEditor::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override;
- QFuture<CppEditor::SymbolInfo> requestFollowSymbol(int line, int column) override;
- QFuture<CppEditor::ToolTipInfo> toolTipInfo(const QByteArray &codecName,
- int line,
- int column) override;
-
- void closeBackendDocument();
-
- void clearDiagnosticsWithFixIts();
-
- const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos() const;
-
- static void clearTaskHubIssues();
- void generateTaskHubIssues();
-
- static void clearTextMarks(const Utils::FilePath &filePath);
+ CppEditor::BaseEditorDocumentParser::Configuration parserConfig();
public:
static ClangEditorDocumentProcessor *get(const QString &filePath);
signals:
- void tokenInfosUpdated();
void parserConfigChanged(const Utils::FilePath &filePath,
const CppEditor::BaseEditorDocumentParser::Configuration &config);
private:
- void onParserFinished();
-
- void updateBackendProjectPartAndDocument();
- void updateBackendDocument(const CppEditor::ProjectPart &projectPart);
- void updateBackendDocumentIfProjectPartExists();
- void requestAnnotationsFromBackend();
-
- HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
- const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic);
- ClangBackEnd::FileContainer simpleFileContainer(const QByteArray &codecName = QByteArray()) const;
- ClangBackEnd::FileContainer fileContainerWithOptionsAndDocumentContent(
- const QStringList &compilationArguments,
- const ProjectExplorer::HeaderPaths headerPaths) const;
- ClangBackEnd::FileContainer fileContainerWithDocumentContent() const;
-
-private:
TextEditor::TextDocument &m_document;
- ClangDiagnosticManager m_diagnosticManager;
- BackendCommunicator &m_communicator;
- QSharedPointer<ClangEditorDocumentParser> m_parser;
CppEditor::ProjectPart::ConstPtr m_projectPart;
::Utils::Id m_diagnosticConfigId;
- bool m_isProjectFile = false;
- QFutureWatcher<void> m_parserWatcher;
- QTimer m_updateBackendDocumentTimer;
- unsigned m_parserRevision;
- enum class InvalidationState { Off, Scheduled, Canceled } m_invalidationState;
-
- QVector<ClangBackEnd::TokenInfoContainer> m_tokenInfos;
- CppEditor::SemanticHighlighter m_semanticHighlighter;
- CppEditor::BuiltinEditorDocumentProcessor m_builtinProcessor;
- Utils::FutureSynchronizer m_parserSynchronizer;
};
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangfixitoperation.cpp b/src/plugins/clangcodemodel/clangfixitoperation.cpp
index 112fe7ef969..5d8f4929c6b 100644
--- a/src/plugins/clangcodemodel/clangfixitoperation.cpp
+++ b/src/plugins/clangcodemodel/clangfixitoperation.cpp
@@ -34,14 +34,11 @@
namespace ClangCodeModel {
namespace Internal {
-using FileToFixits = QMap<QString, QVector<ClangBackEnd::FixItContainer>>;
+using FileToFixits = QMap<QString, QList<ClangFixIt>>;
using RefactoringFilePtr = QSharedPointer<TextEditor::RefactoringFile>;
-ClangFixItOperation::ClangFixItOperation(
- const Utf8String &fixItText,
- const QVector<ClangBackEnd::FixItContainer> &fixItContainers)
- : fixItText(fixItText)
- , fixItContainers(fixItContainers)
+ClangFixItOperation::ClangFixItOperation(const QString &fixItText, const QList<ClangFixIt> &fixIts)
+ : fixItText(fixItText), fixIts(fixIts)
{
}
@@ -52,16 +49,16 @@ int ClangFixItOperation::priority() const
QString ClangFixItOperation::description() const
{
- return QStringLiteral("Apply Fix: ") + fixItText.toString();
+ return QStringLiteral("Apply Fix: ") + fixItText;
}
-static FileToFixits fixitsPerFile(const QVector<ClangBackEnd::FixItContainer> &fixItContainers)
+static FileToFixits fixitsPerFile(const QList<ClangFixIt> &fixIts)
{
FileToFixits mapping;
- for (const auto &fixItContainer : fixItContainers) {
- const QString rangeStartFilePath = fixItContainer.range.start.filePath.toString();
- const QString rangeEndFilePath = fixItContainer.range.end.filePath.toString();
+ for (const auto &fixItContainer : fixIts) {
+ const QString rangeStartFilePath = fixItContainer.range.start.targetFilePath.toString();
+ const QString rangeEndFilePath = fixItContainer.range.end.targetFilePath.toString();
QTC_CHECK(rangeStartFilePath == rangeEndFilePath);
mapping[rangeStartFilePath].append(fixItContainer);
}
@@ -72,11 +69,11 @@ static FileToFixits fixitsPerFile(const QVector<ClangBackEnd::FixItContainer> &f
void ClangFixItOperation::perform()
{
const TextEditor::RefactoringChanges refactoringChanges;
- const FileToFixits fileToFixIts = fixitsPerFile(fixItContainers);
+ const FileToFixits fileToFixIts = fixitsPerFile(fixIts);
for (auto i = fileToFixIts.cbegin(), end = fileToFixIts.cend(); i != end; ++i) {
const QString filePath = i.key();
- const QVector<ClangBackEnd::FixItContainer> fixits = i.value();
+ const QList<ClangFixIt> fixits = i.value();
RefactoringFilePtr refactoringFile = refactoringChanges.file(
Utils::FilePath::fromString(filePath));
@@ -91,11 +88,10 @@ QString ClangFixItOperation::firstRefactoringFileContent_forTestOnly() const
return refactoringFiles.first()->document()->toPlainText();
}
-void ClangFixItOperation::applyFixitsToFile(
- TextEditor::RefactoringFile &refactoringFile,
- const QVector<ClangBackEnd::FixItContainer> fixItContainers)
+void ClangFixItOperation::applyFixitsToFile(TextEditor::RefactoringFile &refactoringFile,
+ const QList<ClangFixIt> fixIts)
{
- const Utils::ChangeSet changeSet = toChangeSet(refactoringFile, fixItContainers);
+ const Utils::ChangeSet changeSet = toChangeSet(refactoringFile, fixIts);
refactoringFile.setChangeSet(changeSet);
refactoringFile.apply();
@@ -103,16 +99,16 @@ void ClangFixItOperation::applyFixitsToFile(
Utils::ChangeSet ClangFixItOperation::toChangeSet(
TextEditor::RefactoringFile &refactoringFile,
- const QVector<ClangBackEnd::FixItContainer> fixItContainers) const
+ const QList<ClangFixIt> fixIts) const
{
Utils::ChangeSet changeSet;
- for (const auto &fixItContainer : fixItContainers) {
+ for (const auto &fixItContainer : fixIts) {
const auto &range = fixItContainer.range;
const auto &start = range.start;
const auto &end = range.end;
- changeSet.replace(refactoringFile.position(start.line, start.column),
- refactoringFile.position(end.line, end.column),
+ changeSet.replace(refactoringFile.position(start.targetLine, start.targetColumn + 1),
+ refactoringFile.position(end.targetLine, end.targetColumn + 1),
fixItContainer.text);
}
diff --git a/src/plugins/clangcodemodel/clangfixitoperation.h b/src/plugins/clangcodemodel/clangfixitoperation.h
index 7caf0cf6523..49606983176 100644
--- a/src/plugins/clangcodemodel/clangfixitoperation.h
+++ b/src/plugins/clangcodemodel/clangfixitoperation.h
@@ -25,9 +25,9 @@
#pragma once
-#include <texteditor/quickfix.h>
+#include "clangutils.h"
-#include <clangsupport/fixitcontainer.h>
+#include <texteditor/quickfix.h>
#include <utils/changeset.h>
@@ -45,8 +45,7 @@ namespace Internal {
class ClangFixItOperation : public TextEditor::QuickFixOperation
{
public:
- ClangFixItOperation(const Utf8String &fixItText,
- const QVector<ClangBackEnd::FixItContainer> &fixItContainers);
+ ClangFixItOperation(const QString &fixItText, const QList<ClangFixIt> &fixIts);
int priority() const override;
QString description() const override;
@@ -56,15 +55,14 @@ public:
private:
void applyFixitsToFile(TextEditor::RefactoringFile &refactoringFile,
- const QVector<ClangBackEnd::FixItContainer> fixItContainers);
- ::Utils::ChangeSet toChangeSet(
- TextEditor::RefactoringFile &refactoringFile,
- const QVector<ClangBackEnd::FixItContainer> fixItContainers) const;
+ const QList<ClangFixIt> fixIts);
+ Utils::ChangeSet toChangeSet(TextEditor::RefactoringFile &refactoringFile,
+ const QList<ClangFixIt> fixIts) const;
private:
- Utf8String fixItText;
+ QString fixItText;
QVector<QSharedPointer<TextEditor::RefactoringFile>> refactoringFiles;
- QVector<ClangBackEnd::FixItContainer> fixItContainers;
+ QList<ClangFixIt> fixIts;
};
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangfixitoperationsextractor.cpp b/src/plugins/clangcodemodel/clangfixitoperationsextractor.cpp
deleted file mode 100644
index 0fc4d02effd..00000000000
--- a/src/plugins/clangcodemodel/clangfixitoperationsextractor.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangfixitoperationsextractor.h"
-
-#include "clangfixitoperation.h"
-#include "clangutils.h"
-
-#include <utils/algorithm.h>
-
-#include <QDebug>
-
-using ClangBackEnd::DiagnosticContainer;
-
-namespace ClangCodeModel {
-namespace Internal {
-
-namespace {
-
-void capitalizeText(QString &text)
-{
- text[0] = text[0].toUpper();
-}
-
-QString tweakedDiagnosticText(const QString &diagnosticText)
-{
- // Examples:
- // "note: use '==' to turn this assignment into an equality comparison"
- // "error: expected ';' at end of declaration"
-
- QString tweakedText = diagnosticText;
-
- if (!tweakedText.isEmpty()) {
- tweakedText = diagnosticCategoryPrefixRemoved(tweakedText);
- capitalizeText(tweakedText);
- }
-
- return tweakedText;
-}
-
-bool hasFixItAt(const QVector<ClangBackEnd::FixItContainer> &fixits,
- const Utf8String &filePath,
- int line)
-{
- const auto isFixitForLocation = [filePath, line] (const ClangBackEnd::FixItContainer &fixit) {
- const ClangBackEnd::SourceLocationContainer &location = fixit.range.start;
- return location.filePath == filePath && location.line == line;
- };
-
- return Utils::anyOf(fixits, isFixitForLocation);
-}
-
-} // anonymous namespace
-
-ClangFixItOperationsExtractor::ClangFixItOperationsExtractor(
- const QVector<DiagnosticContainer> &diagnosticContainers)
- : diagnosticContainers(diagnosticContainers)
-{
-}
-
-TextEditor::QuickFixOperations
-ClangFixItOperationsExtractor::extract(const QString &filePath, int line)
-{
- foreach (const DiagnosticContainer &diagnosticContainer, diagnosticContainers)
- extractFromDiagnostic(diagnosticContainer, filePath, line);
-
- return operations;
-}
-
-void ClangFixItOperationsExtractor::appendFixitOperation(
- const QString &diagnosticText,
- const QVector<ClangBackEnd::FixItContainer> &fixits)
-{
- if (!fixits.isEmpty()) {
- const QString diagnosticTextTweaked = tweakedDiagnosticText(diagnosticText);
- TextEditor::QuickFixOperation::Ptr operation(
- new ClangFixItOperation(diagnosticTextTweaked, fixits));
- operations.append(operation);
- }
-}
-
-void ClangFixItOperationsExtractor::extractFromDiagnostic(
- const DiagnosticContainer &diagnosticContainer,
- const QString &filePath,
- int line)
-{
- const QVector<ClangBackEnd::FixItContainer> &fixIts = diagnosticContainer.fixIts;
- if (hasFixItAt(fixIts, filePath, line)) {
- appendFixitOperation(diagnosticContainer.text.toString(), fixIts);
-
- for (const auto &child : diagnosticContainer.children)
- extractFromDiagnostic(child, filePath, line);
- }
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangfixitoperationsextractor.h b/src/plugins/clangcodemodel/clangfixitoperationsextractor.h
deleted file mode 100644
index 77b5643f8b3..00000000000
--- a/src/plugins/clangcodemodel/clangfixitoperationsextractor.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <texteditor/quickfix.h>
-
-#include <clangsupport/diagnosticcontainer.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangFixItOperationsExtractor
-{
-public:
- ClangFixItOperationsExtractor(const QVector<ClangBackEnd::DiagnosticContainer> &diagnosticContainers);
-
- TextEditor::QuickFixOperations extract(const QString &filePath, int line);
-
-private:
- void extractFromDiagnostic(const ClangBackEnd::DiagnosticContainer &diagnosticContainer,
- const QString &filePath,
- int line);
- void appendFixitOperation(const QString &diagnosticText,
- const QVector<ClangBackEnd::FixItContainer> &fixits);
-
-private:
- const QVector<ClangBackEnd::DiagnosticContainer> &diagnosticContainers;
- TextEditor::QuickFixOperations operations;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.cpp b/src/plugins/clangcodemodel/clangfollowsymbol.cpp
deleted file mode 100644
index c81bbe12688..00000000000
--- a/src/plugins/clangcodemodel/clangfollowsymbol.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangfollowsymbol.h"
-
-#include "clangdclient.h"
-#include "clangeditordocumentprocessor.h"
-#include "clangmodelmanagersupport.h"
-
-#include <coreplugin/editormanager/editormanager.h>
-#include <cppeditor/cppmodelmanager.h>
-#include <cppeditor/cppfollowsymbolundercursor.h>
-#include <texteditor/texteditor.h>
-
-#include <clangsupport/tokeninfocontainer.h>
-
-#include <utils/textutils.h>
-#include <utils/algorithm.h>
-
-#include <memory>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-// Returns invalid Mark if it is not found at (line, column)
-static bool findMark(const QVector<ClangBackEnd::TokenInfoContainer> &marks,
- int line,
- int column,
- ClangBackEnd::TokenInfoContainer &mark)
-{
- mark = Utils::findOrDefault(marks,
- [line, column](const ClangBackEnd::TokenInfoContainer &curMark) {
- if (curMark.line != line)
- return false;
- if (curMark.column == column)
- return true;
- if (curMark.column < column && curMark.column + curMark.length > column)
- return true;
- return false;
- });
- if (mark.isInvalid())
- return false;
- return true;
-}
-
-static int getMarkPos(QTextCursor cursor, const ClangBackEnd::TokenInfoContainer &mark)
-{
- cursor.setPosition(0);
- cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, mark.line - 1);
- cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, mark.column - 1);
- return cursor.position();
-}
-
-static bool isValidIncludePathToken(const ClangBackEnd::TokenInfoContainer &token)
-{
- if (!token.extraInfo.includeDirectivePath)
- return false;
- const Utf8String &tokenName = token.extraInfo.token;
- return !tokenName.startsWith("include") && tokenName != Utf8String("<")
- && tokenName != Utf8String(">") && tokenName != Utf8String("#");
-}
-
-static int includePathStartIndex(const QVector<ClangBackEnd::TokenInfoContainer> &marks,
- int currentIndex)
-{
- int startIndex = currentIndex - 1;
- while (startIndex >= 0 && isValidIncludePathToken(marks[startIndex]))
- --startIndex;
- return startIndex + 1;
-}
-
-static int includePathEndIndex(const QVector<ClangBackEnd::TokenInfoContainer> &marks,
- int currentIndex)
-{
- int endIndex = currentIndex + 1;
- while (endIndex < marks.size() && isValidIncludePathToken(marks[endIndex]))
- ++endIndex;
- return endIndex - 1;
-}
-
-static Utils::Link linkAtCursor(const QTextCursor &cursor,
- const QString &filePath,
- uint line,
- uint column,
- ClangEditorDocumentProcessor *processor)
-{
- using Link = Utils::Link;
-
- const QVector<ClangBackEnd::TokenInfoContainer> &marks
- = processor->tokenInfos();
- ClangBackEnd::TokenInfoContainer mark;
- if (!findMark(marks, line, column, mark))
- return Link();
-
- if (mark.extraInfo.includeDirectivePath && !isValidIncludePathToken(mark))
- return Link();
-
- Link token(Utils::FilePath::fromString(filePath), mark.line, mark.column);
- token.linkTextStart = getMarkPos(cursor, mark);
- token.linkTextEnd = token.linkTextStart + mark.length;
-
- if (mark.extraInfo.includeDirectivePath) {
- // Tweak include paths to cover everything between "" or <>.
- if (mark.extraInfo.token.startsWith("\"")) {
- token.linkTextStart++;
- token.linkTextEnd--;
- } else {
- // '#include <path/file.h>' case. Clang gives us a separate token for each part of
- // the path. We want to have the full range instead therefore we search for < and >
- // tokens around the current token.
- const int index = marks.indexOf(mark);
- const int startIndex = includePathStartIndex(marks, index);
- const int endIndex = includePathEndIndex(marks, index);
-
- if (startIndex != index)
- token.linkTextStart = getMarkPos(cursor, marks[startIndex]);
- if (endIndex != index)
- token.linkTextEnd = getMarkPos(cursor, marks[endIndex]) + marks[endIndex].length;
- }
- return token;
- }
-
- if (mark.extraInfo.identifier || mark.extraInfo.token == "operator"
- || mark.extraInfo.token == "auto") {
- return token;
- }
- return Link();
-}
-
-static ::Utils::ProcessLinkCallback extendedCallback(::Utils::ProcessLinkCallback &&callback,
- const CppEditor::SymbolInfo &result)
-{
- // If globalFollowSymbol finds nothing follow to the declaration.
- return [original_callback = std::move(callback), result](const ::Utils::Link &link) {
- if (link.linkTextStart < 0 && result.isResultOnlyForFallBack) {
- return original_callback(Utils::Link(
- Utils::FilePath::fromString(result.fileName).cleanPath(),
- result.startLine,
- result.startColumn - 1));
- }
- return original_callback(link);
- };
-}
-
-static bool isSameInvocationContext(const Utils::FilePath &filePath)
-{
- return TextEditor::BaseTextEditor::currentTextEditor()->editorWidget()->isVisible()
- && Core::EditorManager::currentDocument()->filePath() == filePath;
-}
-
-void ClangFollowSymbol::findLink(const CppEditor::CursorInEditor &data,
- ::Utils::ProcessLinkCallback &&processLinkCallback,
- bool resolveTarget,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- CppEditor::SymbolFinder *symbolFinder,
- bool inNextSplit)
-{
- ClangdClient * const client
- = ClangModelManagerSupport::instance()->clientForFile(data.filePath());
- if (client && client->isFullyIndexed()) {
- client->followSymbol(data.textDocument(), data.cursor(), data.editorWidget(),
- std::move(processLinkCallback), resolveTarget, inNextSplit);
- return;
- }
-
- int line = 0;
- int column = 0;
- QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor());
- Utils::Text::convertPosition(cursor.document(), cursor.position(), &line, &column);
-
- ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(
- data.filePath().toString());
- if (!processor)
- return processLinkCallback(Utils::Link());
-
- if (!resolveTarget) {
- Utils::Link link = linkAtCursor(cursor,
- data.filePath().toString(),
- static_cast<uint>(line),
- static_cast<uint>(column),
- processor);
- if (link == Utils::Link()) {
- CppEditor::FollowSymbolUnderCursor followSymbol;
- return followSymbol.findLink(data,
- std::move(processLinkCallback),
- false,
- snapshot,
- documentFromSemanticInfo,
- symbolFinder,
- inNextSplit);
- }
- return processLinkCallback(link);
- }
-
- QFuture<CppEditor::SymbolInfo> infoFuture
- = processor->requestFollowSymbol(static_cast<int>(line),
- static_cast<int>(column));
-
- if (infoFuture.isCanceled())
- return processLinkCallback(Utils::Link());
-
- if (m_watcher)
- m_watcher->cancel();
-
- m_watcher = std::make_unique<FutureSymbolWatcher>();
-
- QObject::connect(m_watcher.get(), &FutureSymbolWatcher::finished, [=, filePath=data.filePath(),
- callback=std::move(processLinkCallback)]() mutable {
- if (m_watcher->isCanceled() || !isSameInvocationContext(filePath))
- return callback(Utils::Link());
- CppEditor::SymbolInfo result = m_watcher->result();
- // We did not fail but the result is empty
- if (result.fileName.isEmpty() || result.isResultOnlyForFallBack) {
- const CppEditor::RefactoringEngineInterface &refactoringEngine
- = *CppEditor::CppModelManager::instance();
- refactoringEngine.globalFollowSymbol(data,
- extendedCallback(std::move(callback), result),
- snapshot,
- documentFromSemanticInfo,
- symbolFinder,
- inNextSplit);
- } else {
- callback(Link(Utils::FilePath::fromString(result.fileName).cleanPath(),
- result.startLine,
- result.startColumn - 1));
- }
- });
-
- m_watcher->setFuture(infoFuture);
-}
-
-void ClangFollowSymbol::switchDeclDef(const CppEditor::CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- CppEditor::SymbolFinder *symbolFinder)
-{
- ClangdClient * const client
- = ClangModelManagerSupport::instance()->clientForFile(data.filePath());
- if (client && client->isFullyIndexed()) {
- client->switchDeclDef(data.textDocument(), data.cursor(), data.editorWidget(),
- std::move(processLinkCallback));
- return;
- }
- CppEditor::CppModelManager::builtinFollowSymbol().switchDeclDef(
- data, std::move(processLinkCallback), snapshot, documentFromSemanticInfo,
- symbolFinder);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.h b/src/plugins/clangcodemodel/clangfollowsymbol.h
deleted file mode 100644
index 0ae10035b40..00000000000
--- a/src/plugins/clangcodemodel/clangfollowsymbol.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <cppeditor/cpptoolsreuse.h>
-#include <cppeditor/followsymbolinterface.h>
-
-#include <QFutureWatcher>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangFollowSymbol : public CppEditor::FollowSymbolInterface
-{
-public:
- void findLink(const CppEditor::CursorInEditor &data,
- ::Utils::ProcessLinkCallback &&processLinkCallback,
- bool resolveTarget,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- CppEditor::SymbolFinder *symbolFinder,
- bool inNextSplit) override;
-
- void switchDeclDef(const CppEditor::CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- CppEditor::SymbolFinder *symbolFinder) override;
-
-private:
- using FutureSymbolWatcher = QFutureWatcher<CppEditor::SymbolInfo>;
- std::unique_ptr<FutureSymbolWatcher> m_watcher;
-
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp
deleted file mode 100644
index 6e33c649d3f..00000000000
--- a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangfunctionhintmodel.h"
-
-#include "clangcompletionchunkstotextconverter.h"
-
-#include <cplusplus/SimpleLexer.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-using namespace CPlusPlus;
-
-ClangFunctionHintModel::ClangFunctionHintModel(const ClangBackEnd::CodeCompletions &functionSymbols)
- : m_functionSymbols(functionSymbols)
- , m_currentArgument(-1)
-{
-}
-
-void ClangFunctionHintModel::reset()
-{
-}
-
-int ClangFunctionHintModel::size() const
-{
- return m_functionSymbols.size();
-}
-
-QString ClangFunctionHintModel::text(int index) const
-{
- const ClangBackEnd::CodeCompletionChunks &chunks = m_functionSymbols.at(index).chunks;
- const QString signatureWithEmphasizedCurrentParameter
- = CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(
- chunks,
- m_functionSymbols.at(index).completionKind,
- m_currentArgument + 1);
-
- return signatureWithEmphasizedCurrentParameter;
-}
-
-QString ClangFunctionHintModel::id(int index) const
-{
- QString chunks;
- for (const ClangBackEnd::CodeCompletionChunk &chunk : m_functionSymbols.at(index).chunks)
- chunks += chunk.text;
-
- return chunks;
-}
-
-int ClangFunctionHintModel::activeArgument(const QString &prefix) const
-{
- int activeArgumentNumber = 0;
-
- int unbalancedParens = 0; // expressions
- int unbalancedBraces = 0; // initializer lists
- int unbalancedBrackets = 0; // lambda-capture
- int unbalancedLessGreater = 0; // template arguments
-
- SimpleLexer tokenize;
- const Tokens tokens = tokenize(prefix);
- for (const Token &token : tokens) {
- if (token.is(T_LPAREN)) {
- ++unbalancedParens;
- } else if (token.is(T_RPAREN)) {
- --unbalancedParens;
- } else if (token.is(T_LBRACE)) {
- ++unbalancedBraces;
- } else if (token.is(T_RBRACE)) {
- --unbalancedBraces;
- } else if (token.is(T_LBRACKET)) {
- ++unbalancedBrackets;
- } else if (token.is(T_RBRACKET)) {
- --unbalancedBrackets;
- } else if (token.is(T_LESS)) {
- ++unbalancedLessGreater;
- } else if (token.is(T_GREATER)) {
- --unbalancedLessGreater;
- } else if (!unbalancedParens
- && !unbalancedBraces
- && !unbalancedBrackets
- && !unbalancedLessGreater
- && token.is(T_COMMA)) {
- ++activeArgumentNumber;
- }
- }
-
- if (unbalancedParens < 0
- || unbalancedBraces < 0
- || unbalancedBrackets < 0
- || unbalancedLessGreater < 0) {
- return -1;
- }
-
- if (activeArgumentNumber != m_currentArgument)
- m_currentArgument = activeArgumentNumber;
-
- return activeArgumentNumber;
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
-
diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.h b/src/plugins/clangcodemodel/clangfunctionhintmodel.h
deleted file mode 100644
index 9a848025a4d..00000000000
--- a/src/plugins/clangcodemodel/clangfunctionhintmodel.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <codecompletion.h>
-
-#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangFunctionHintModel : public TextEditor::IFunctionHintProposalModel
-{
-public:
- ClangFunctionHintModel(const ClangBackEnd::CodeCompletions &functionSymbols);
-
- void reset() override;
- int size() const override;
- QString text(int index) const override;
- QString id(int index) const override;
- int activeArgument(const QString &prefix) const override;
-
-private:
- ClangBackEnd::CodeCompletions m_functionSymbols;
- mutable int m_currentArgument;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanghighlightingresultreporter.cpp b/src/plugins/clangcodemodel/clanghighlightingresultreporter.cpp
deleted file mode 100644
index 149fb30c8b7..00000000000
--- a/src/plugins/clangcodemodel/clanghighlightingresultreporter.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clanghighlightingresultreporter.h"
-
-#include <clangsupport/tokeninfocontainer.h>
-#include <cppeditor/semantichighlighter.h>
-#include <texteditor/semantichighlighter.h>
-#include <texteditor/textstyles.h>
-#include <utils/runextensions.h>
-#include <utils/qtcassert.h>
-
-namespace {
-
-TextEditor::TextStyle toTextStyle(ClangBackEnd::HighlightingType type)
-{
- using ClangBackEnd::HighlightingType;
-
- switch (type) {
- case HighlightingType::Keyword:
- return TextEditor::C_KEYWORD;
- case HighlightingType::Function:
- return TextEditor::C_FUNCTION;
- case HighlightingType::VirtualFunction:
- return TextEditor::C_VIRTUAL_METHOD;
- case HighlightingType::Type:
- return TextEditor::C_TYPE;
- case HighlightingType::PrimitiveType:
- return TextEditor::C_PRIMITIVE_TYPE;
- case HighlightingType::LocalVariable:
- return TextEditor::C_LOCAL;
- case HighlightingType::Parameter:
- return TextEditor::C_PARAMETER;
- case HighlightingType::Field:
- case HighlightingType::QtProperty:
- return TextEditor::C_FIELD;
- case HighlightingType::GlobalVariable:
- return TextEditor::C_GLOBAL;
- case HighlightingType::Enumeration:
- return TextEditor::C_ENUMERATION;
- case HighlightingType::Label:
- return TextEditor::C_LABEL;
- case HighlightingType::Preprocessor:
- case HighlightingType::PreprocessorDefinition:
- case HighlightingType::PreprocessorExpansion:
- return TextEditor::C_PREPROCESSOR;
- case HighlightingType::Punctuation:
- return TextEditor::C_PUNCTUATION;
- case HighlightingType::Declaration:
- return TextEditor::C_DECLARATION;
- case HighlightingType::FunctionDefinition:
- return TextEditor::C_FUNCTION_DEFINITION;
- case HighlightingType::OutputArgument:
- return TextEditor::C_OUTPUT_ARGUMENT;
- case HighlightingType::Operator:
- return TextEditor::C_OPERATOR;
- case HighlightingType::OverloadedOperator:
- return TextEditor::C_OVERLOADED_OPERATOR;
- case HighlightingType::Comment:
- return TextEditor::C_COMMENT;
- case HighlightingType::StringLiteral:
- return TextEditor::C_STRING;
- case HighlightingType::NumberLiteral:
- return TextEditor::C_NUMBER;
- case HighlightingType::Invalid:
- QTC_CHECK(false); // never called
- return TextEditor::C_TEXT;
- default:
- break;
- }
- Q_UNREACHABLE();
-}
-
-bool ignore(ClangBackEnd::HighlightingType type)
-{
- using ClangBackEnd::HighlightingType;
-
- switch (type) {
- default:
- break;
- case HighlightingType::Namespace:
- case HighlightingType::Class:
- case HighlightingType::Struct:
- case HighlightingType::Enum:
- case HighlightingType::Union:
- case HighlightingType::TypeAlias:
- case HighlightingType::Typedef:
- case HighlightingType::ObjectiveCClass:
- case HighlightingType::ObjectiveCCategory:
- case HighlightingType::ObjectiveCProtocol:
- case HighlightingType::ObjectiveCInterface:
- case HighlightingType::ObjectiveCImplementation:
- case HighlightingType::ObjectiveCProperty:
- case HighlightingType::ObjectiveCMethod:
- case HighlightingType::TemplateTypeParameter:
- case HighlightingType::TemplateTemplateParameter:
- case HighlightingType::AngleBracketOpen:
- case HighlightingType::AngleBracketClose:
- case HighlightingType::DoubleAngleBracketClose:
- case HighlightingType::TernaryIf:
- case HighlightingType::TernaryElse:
- return true;
- }
-
- return false;
-}
-
-TextEditor::TextStyles toTextStyles(ClangBackEnd::HighlightingTypes types)
-{
- TextEditor::TextStyles textStyles;
- textStyles.mixinStyles.initializeElements();
-
- textStyles.mainStyle = toTextStyle(types.mainHighlightingType);
-
- for (ClangBackEnd::HighlightingType type : types.mixinHighlightingTypes) {
- if (!ignore(type))
- textStyles.mixinStyles.push_back(toTextStyle(type));
- }
-
- return textStyles;
-}
-
-TextEditor::HighlightingResult toHighlightingResult(
- const ClangBackEnd::TokenInfoContainer &tokenInfo)
-{
- using ClangBackEnd::HighlightingType;
- const auto textStyles = toTextStyles(tokenInfo.types);
- TextEditor::HighlightingResult result(tokenInfo.line, tokenInfo.column, tokenInfo.length,
- textStyles);
- if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::AngleBracketOpen))
- result.kind = CppEditor::SemanticHighlighter::AngleBracketOpen;
- else if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::AngleBracketClose))
- result.kind = CppEditor::SemanticHighlighter::AngleBracketClose;
- else if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::DoubleAngleBracketClose))
- result.kind = CppEditor::SemanticHighlighter::DoubleAngleBracketClose;
- else if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::TernaryIf))
- result.kind = CppEditor::SemanticHighlighter::TernaryIf;
- else if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::TernaryElse))
- result.kind = CppEditor::SemanticHighlighter::TernaryElse;
- return result;
-}
-
-void highlightResultsImpl(QFutureInterface<TextEditor::HighlightingResult> &fi,
- const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
- int chunkSize)
-{
- if (fi.isCanceled())
- return;
-
- QVector<TextEditor::HighlightingResult> chunksToReport;
- chunksToReport.reserve(chunkSize + 1);
-
- using ClangBackEnd::HighlightingType;
- bool flushRequested = false;
- int flushLine = 0;
-
- auto reportAndClearCurrentChunks = [&] {
- flushRequested = false;
- flushLine = 0;
-
- if (!chunksToReport.isEmpty()) {
- fi.reportResults(chunksToReport);
- chunksToReport.erase(chunksToReport.begin(), chunksToReport.end());
- }
- };
-
- auto reportChunkWise = [&](const TextEditor::HighlightingResult &highlightingResult) {
- if (chunksToReport.size() >= chunkSize) {
- if (flushRequested && highlightingResult.line != flushLine) {
- reportAndClearCurrentChunks();
- } else if (!flushRequested) {
- flushRequested = true;
- flushLine = highlightingResult.line;
- }
- }
-
- chunksToReport.append(highlightingResult);
- };
-
- for (const auto &tokenInfo : tokenInfos)
- reportChunkWise(toHighlightingResult(tokenInfo));
-
- if (fi.isCanceled())
- return;
-
- reportAndClearCurrentChunks();
-}
-
-} // anonymous
-
-namespace ClangCodeModel {
-namespace Internal {
-
-QFuture<TextEditor::HighlightingResult> highlightResults(
- const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
- int chunkSize)
-{
- return Utils::runAsync(highlightResultsImpl, tokenInfos, chunkSize);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanghighlightingresultreporter.h b/src/plugins/clangcodemodel/clanghighlightingresultreporter.h
deleted file mode 100644
index 4999a7d77f1..00000000000
--- a/src/plugins/clangcodemodel/clanghighlightingresultreporter.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QFuture>
-#include <QVector>
-
-namespace TextEditor { class HighlightingResult; }
-namespace ClangBackEnd { class TokenInfoContainer; }
-
-namespace ClangCodeModel {
-namespace Internal {
-
-QFuture<TextEditor::HighlightingResult> highlightResults(
- const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
- int chunkSize = 100);
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp
deleted file mode 100644
index 10e3524db41..00000000000
--- a/src/plugins/clangcodemodel/clanghoverhandler.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clanghoverhandler.h"
-
-#include "clangeditordocumentprocessor.h"
-#include "clangmodelmanagersupport.h"
-
-#include <coreplugin/helpmanager.h>
-#include <cppeditor/cppmodelmanager.h>
-#include <cppeditor/cpptoolsreuse.h>
-#include <cppeditor/editordocumenthandle.h>
-#include <texteditor/texteditor.h>
-
-#include <utils/qtcassert.h>
-#include <utils/textutils.h>
-#include <utils/tooltip/tooltip.h>
-
-#include <QFutureWatcher>
-#include <QLoggingCategory>
-#include <QRegularExpression>
-#include <QTextCodec>
-#include <QVBoxLayout>
-
-static Q_LOGGING_CATEGORY(hoverLog, "qtc.clangcodemodel.hover", QtWarningMsg);
-
-using namespace TextEditor;
-
-namespace ClangCodeModel {
-namespace Internal {
-
-static CppEditor::BaseEditorDocumentProcessor *editorDocumentProcessor(TextEditorWidget *editorWidget)
-{
- const QString filePath = editorWidget->textDocument()->filePath().toString();
- auto cppModelManager = CppEditor::CppModelManager::instance();
- CppEditor::CppEditorDocumentHandle *editorHandle = cppModelManager->cppEditorDocument(filePath);
-
- if (editorHandle)
- return editorHandle->processor();
-
- return nullptr;
-}
-
-static TextMarks diagnosticTextMarksAt(TextEditorWidget *editorWidget, int position)
-{
- const auto processor = qobject_cast<ClangEditorDocumentProcessor *>(
- editorDocumentProcessor(editorWidget));
- QTC_ASSERT(processor, return TextMarks());
-
- int line, column;
- const bool ok = Utils::Text::convertPosition(editorWidget->document(), position, &line, &column);
- QTC_ASSERT(ok, return TextMarks());
-
- return processor->diagnosticTextMarksAt(line, column);
-}
-
-static QFuture<CppEditor::ToolTipInfo> editorDocumentHandlesToolTipInfo(
- TextEditorWidget *editorWidget, int pos)
-{
- const QByteArray textCodecName = editorWidget->textDocument()->codec()->name();
- if (CppEditor::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
- int line, column;
- if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column))
- return processor->toolTipInfo(textCodecName, line, column + 1);
- }
-
- return QFuture<CppEditor::ToolTipInfo>();
-}
-
-ClangHoverHandler::~ClangHoverHandler()
-{
- abort();
-}
-
-void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
- int pos,
- BaseHoverHandler::ReportPriority report)
-{
- if (ClangModelManagerSupport::instance()
- ->clientForFile(editorWidget->textDocument()->filePath())) {
- report(Priority_None);
- return;
- }
-
- // Reset
- m_futureWatcher.reset();
- m_cursorPosition = -1;
-
- // Check for diagnostics (sync)
- if (!isContextHelpRequest() && !diagnosticTextMarksAt(editorWidget, pos).isEmpty()) {
- qCDebug(hoverLog) << "Checking for diagnostic at" << pos;
- setPriority(Priority_Diagnostic);
- m_cursorPosition = pos;
- }
-
- // Check for tooltips (async)
- QFuture<CppEditor::ToolTipInfo> future = editorDocumentHandlesToolTipInfo(editorWidget, pos);
- if (QTC_GUARD(future.isRunning())) {
- qCDebug(hoverLog) << "Requesting tooltip info at" << pos;
- m_reportPriority = report;
- m_futureWatcher.reset(new QFutureWatcher<CppEditor::ToolTipInfo>());
- QTextCursor tc(editorWidget->document());
- tc.setPosition(pos);
- const QStringList fallback = CppEditor::identifierWordsUnderCursor(tc);
- QObject::connect(m_futureWatcher.data(),
- &QFutureWatcherBase::finished,
- [this, fallback]() {
- if (m_futureWatcher->isCanceled()) {
- m_reportPriority(Priority_None);
- } else {
- CppEditor::ToolTipInfo info = m_futureWatcher->result();
- qCDebug(hoverLog)
- << "Appending word-based fallback lookup" << fallback;
- info.qDocIdCandidates += fallback;
- processToolTipInfo(info);
- }
- });
- m_futureWatcher->setFuture(future);
- return;
- }
-
- report(priority()); // Ops, something went wrong.
-}
-
-void ClangHoverHandler::abort()
-{
- if (m_futureWatcher) {
- m_futureWatcher->cancel();
- m_futureWatcher.reset();
- }
-}
-
-#define RETURN_TEXT_FOR_CASE(enumValue) case Core::HelpItem::enumValue: return #enumValue
-static const char *helpItemCategoryAsString(Core::HelpItem::Category category)
-{
- switch (category) {
- RETURN_TEXT_FOR_CASE(Unknown);
- RETURN_TEXT_FOR_CASE(ClassOrNamespace);
- RETURN_TEXT_FOR_CASE(Enum);
- RETURN_TEXT_FOR_CASE(Typedef);
- RETURN_TEXT_FOR_CASE(Macro);
- RETURN_TEXT_FOR_CASE(Brief);
- RETURN_TEXT_FOR_CASE(Function);
- RETURN_TEXT_FOR_CASE(QmlComponent);
- RETURN_TEXT_FOR_CASE(QmlProperty);
- RETURN_TEXT_FOR_CASE(QMakeVariableOfFunction);
- }
-
- return "UnhandledHelpItemCategory";
-}
-#undef RETURN_TEXT_FOR_CASE
-
-void ClangHoverHandler::processToolTipInfo(const CppEditor::ToolTipInfo &info)
-{
- qCDebug(hoverLog) << "Processing tooltip info" << info.text;
-
- QString text = info.text;
- if (!info.briefComment.isEmpty())
- text.append("\n\n" + info.briefComment);
-
- qCDebug(hoverLog) << "Querying help manager with"
- << info.qDocIdCandidates
- << info.qDocMark
- << helpItemCategoryAsString(info.qDocCategory);
- setLastHelpItemIdentified({info.qDocIdCandidates, info.qDocMark, info.qDocCategory});
-
- if (!info.sizeInBytes.isEmpty())
- text.append("\n\n" + tr("%1 bytes").arg(info.sizeInBytes));
- if (info.value.isValid()) {
- QString value;
- switch (info.value.type()) {
- case static_cast<QVariant::Type>(QMetaType::LongLong):
- value = QString::number(info.value.toLongLong());
- break;
- case static_cast<QVariant::Type>(QMetaType::ULongLong):
- value = QString::number(info.value.toULongLong());
- break;
- case static_cast<QVariant::Type>(QMetaType::Double):
- value = QString::number(info.value.toDouble());
- break;
- default:
- QTC_CHECK(false);
- }
- text.append("\n\n" + tr("Value: %1").arg(value));
- }
-
- setToolTip(text);
- m_reportPriority(priority());
-}
-
-void ClangHoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget,
- const QPoint &point)
-{
- if (priority() == Priority_Diagnostic) {
- const TextMarks textMarks = diagnosticTextMarksAt(editorWidget, m_cursorPosition);
- editorWidget->showTextMarksToolTip(point, textMarks);
- return;
- }
-
- // Priority_Tooltip / Priority_Help
- BaseHoverHandler::operateTooltip(editorWidget, point);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.h b/src/plugins/clangcodemodel/clanghoverhandler.h
deleted file mode 100644
index 90ae5f05955..00000000000
--- a/src/plugins/clangcodemodel/clanghoverhandler.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <cppeditor/baseeditordocumentprocessor.h>
-#include <texteditor/basehoverhandler.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangHoverHandler final : public TextEditor::BaseHoverHandler
-{
- Q_DECLARE_TR_FUNCTIONS(ClangHoverHandler)
-
-public:
- ~ClangHoverHandler() override;
-
- void identifyMatch(TextEditor::TextEditorWidget *editorWidget,
- int pos,
- ReportPriority report) override;
- void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
-
-private:
- void abort() override;
- void processToolTipInfo(const CppEditor::ToolTipInfo &info);
-
-private:
- int m_cursorPosition = -1;
- QScopedPointer<QFutureWatcher<CppEditor::ToolTipInfo>> m_futureWatcher;
- ReportPriority m_reportPriority;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h b/src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h
deleted file mode 100644
index c8de24a0d03..00000000000
--- a/src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport/diagnosticcontainer.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-static bool isWithinRange(const ClangBackEnd::SourceRangeContainer &range,
- int line,
- int column)
-{
- const ClangBackEnd::SourceLocationContainer &startLocation = range.start;
- const ClangBackEnd::SourceLocationContainer &endLocation = range.end;
-
- return startLocation.line <= line
- && startLocation.column <= column
- && line <= endLocation.line
- && column <= endLocation.column;
-}
-
-static bool isWithinOneRange(const QVector<ClangBackEnd::SourceRangeContainer> &ranges,
- int line,
- int column)
-{
- for (const ClangBackEnd::SourceRangeContainer &range : ranges) {
- if (isWithinRange(range, line, column))
- return true;
- }
-
- return false;
-}
-
-bool isDiagnosticRelatedToLocation(const ClangBackEnd::DiagnosticContainer &diagnostic,
- const QVector<ClangBackEnd::SourceRangeContainer> &additionalRanges,
- int line,
- int column)
-{
- const ClangBackEnd::SourceLocationContainer &location = diagnostic.location;
-
- if (location.line == line && location.column == column)
- return true;
-
- if (isWithinOneRange(additionalRanges, line, column))
- return true;
-
- if (isWithinOneRange(diagnostic.ranges, line, column))
- return true;
-
- return false;
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index 94902075e91..7375cc9c685 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -29,12 +29,7 @@
#include "clangdclient.h"
#include "clangdquickfixfactory.h"
#include "clangeditordocumentprocessor.h"
-#include "clangfollowsymbol.h"
#include "clangdlocatorfilters.h"
-#include "clanghoverhandler.h"
-#include "clangoverviewmodel.h"
-#include "clangprojectsettings.h"
-#include "clangrefactoringengine.h"
#include "clangutils.h"
#include <coreplugin/documentmanager.h>
@@ -43,8 +38,10 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
+#include <cppeditor/abstractoverviewmodel.h>
#include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/cppeditorconstants.h>
+#include <cppeditor/cppeditorwidget.h>
#include <cppeditor/cppfollowsymbolundercursor.h>
#include <cppeditor/cppmodelmanager.h>
#include <cppeditor/cppprojectfile.h>
@@ -62,13 +59,15 @@
#include <projectexplorer/projecttree.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
+#include <projectexplorer/taskhub.h>
-#include <clangsupport/filecontainer.h>
#include <utils/algorithm.h>
+#include <utils/infobar.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QApplication>
+#include <QLabel>
#include <QMenu>
#include <QTextBlock>
#include <QTimer>
@@ -103,17 +102,87 @@ static const QList<TextEditor::TextDocument *> allCppDocuments()
return Utils::qobject_container_cast<TextEditor::TextDocument *>(documents);
}
+static bool fileIsProjectBuildArtifact(const Client *client, const Utils::FilePath &filePath)
+{
+ if (const auto p = client->project()) {
+ if (const auto t = p->activeTarget()) {
+ if (const auto bc = t->activeBuildConfiguration()) {
+ if (filePath.isChildOf(bc->buildDirectory()))
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static Client *clientForGeneratedFile(const Utils::FilePath &filePath)
+{
+ for (Client * const client : LanguageClientManager::clients()) {
+ if (qobject_cast<ClangdClient *>(client) && client->reachable()
+ && fileIsProjectBuildArtifact(client, filePath)) {
+ return client;
+ }
+ }
+ return nullptr;
+}
+
+static void checkSystemForClangdSuitability()
+{
+ if (ClangdSettings::haveCheckedHardwareRequirements())
+ return;
+ if (ClangdSettings::hardwareFulfillsRequirements())
+ return;
+
+ ClangdSettings::setUseClangd(false);
+ const QString warnStr = ClangModelManagerSupport::tr("The use of clangd for the C/C++ "
+ "code model was disabled, because it is likely that its memory requirements "
+ "would be higher than what your system can handle.");
+ const Utils::Id clangdWarningSetting("WarnAboutClangd");
+ Utils::InfoBarEntry info(clangdWarningSetting, warnStr);
+ info.setDetailsWidgetCreator([] {
+ const auto label = new QLabel(ClangModelManagerSupport::tr(
+ "With clangd enabled, Qt Creator fully supports modern C++ "
+ "when highlighting code, completing symbols and so on.<br>"
+ "This comes at a higher cost in terms of CPU load and memory usage compared "
+ "to the built-in code model, which therefore might be the better choice "
+ "on older machines and/or with legacy code.<br>"
+ "You can enable/disable and fine-tune clangd <a href=\"dummy\">here</a>."));
+ label->setWordWrap(true);
+ QObject::connect(label, &QLabel::linkActivated, [] {
+ Core::ICore::showOptionsDialog(CppEditor::Constants::CPP_CLANGD_SETTINGS_ID);
+ });
+ return label;
+ });
+ info.addCustomButton(ClangModelManagerSupport::tr("Enable Anyway"), [clangdWarningSetting] {
+ ClangdSettings::setUseClangd(true);
+ Core::ICore::infoBar()->removeInfo(clangdWarningSetting);
+ });
+ Core::ICore::infoBar()->addInfo(info);
+}
+
+static void updateParserConfig(ClangdClient *client)
+{
+ if (!client->reachable())
+ return;
+ if (const auto editor = TextEditor::BaseTextEditor::currentTextEditor()) {
+ if (!client->documentOpen(editor->textDocument()))
+ return;
+ const Utils::FilePath filePath = editor->textDocument()->filePath();
+ if (const auto processor = ClangEditorDocumentProcessor::get(filePath.toString()))
+ client->updateParserConfig(filePath, processor->parserConfig());
+ }
+}
+
+
ClangModelManagerSupport::ClangModelManagerSupport()
- : m_completionAssistProvider(m_communicator, CompletionType::Other)
- , m_functionHintAssistProvider(m_communicator, CompletionType::FunctionHint)
- , m_followSymbol(new ClangFollowSymbol)
- , m_refactoringEngine(new RefactoringEngine)
{
QTC_CHECK(!m_instance);
m_instance = this;
watchForExternalChanges();
watchForInternalChanges();
+ setupClangdConfigFile();
+ checkSystemForClangdSuitability();
cppModelManager()->setCurrentDocumentFilter(std::make_unique<ClangdCurrentDocumentFilter>());
cppModelManager()->setLocatorFilter(std::make_unique<ClangGlobalSymbolFilter>());
cppModelManager()->setClassesFilter(std::make_unique<ClangClassesFilter>());
@@ -124,8 +193,6 @@ ClangModelManagerSupport::ClangModelManagerSupport()
this, &ClangModelManagerSupport::onEditorOpened);
connect(editorManager, &Core::EditorManager::currentEditorChanged,
this, &ClangModelManagerSupport::onCurrentEditorChanged);
- connect(editorManager, &Core::EditorManager::editorsClosed,
- this, &ClangModelManagerSupport::onEditorClosed);
CppEditor::CppModelManager *modelManager = cppModelManager();
connect(modelManager, &CppEditor::CppModelManager::abstractEditorSupportContentsUpdated,
@@ -144,19 +211,12 @@ ClangModelManagerSupport::ClangModelManagerSupport()
});
auto *sessionManager = ProjectExplorer::SessionManager::instance();
- connect(sessionManager, &ProjectExplorer::SessionManager::projectAdded,
- this, &ClangModelManagerSupport::onProjectAdded);
- connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
- this, &ClangModelManagerSupport::onAboutToRemoveProject);
connect(sessionManager, &ProjectExplorer::SessionManager::projectRemoved,
this, [this] { claimNonProjectSources(clientForProject(fallbackProject())); });
CppEditor::ClangdSettings::setDefaultClangdPath(Core::ICore::clangdExecutable(CLANG_BINDIR));
connect(&CppEditor::ClangdSettings::instance(), &CppEditor::ClangdSettings::changed,
this, &ClangModelManagerSupport::onClangdSettingsChanged);
- CppEditor::CppCodeModelSettings *settings = CppEditor::codeModelSettings();
- connect(settings, &CppEditor::CppCodeModelSettings::clangDiagnosticConfigsInvalidated,
- this, &ClangModelManagerSupport::onDiagnosticConfigsInvalidated);
if (CppEditor::ClangdSettings::instance().useClangd())
createClient(nullptr, {});
@@ -167,55 +227,113 @@ ClangModelManagerSupport::ClangModelManagerSupport()
ClangModelManagerSupport::~ClangModelManagerSupport()
{
- QTC_CHECK(m_projectSettings.isEmpty());
m_generatorSynchronizer.waitForFinished();
m_instance = nullptr;
}
CppEditor::CppCompletionAssistProvider *ClangModelManagerSupport::completionAssistProvider()
{
- return &m_completionAssistProvider;
+ return nullptr;
}
-CppEditor::CppCompletionAssistProvider *ClangModelManagerSupport::functionHintAssistProvider()
+void ClangModelManagerSupport::followSymbol(const CppEditor::CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback, bool resolveTarget,
+ bool inNextSplit)
{
- return &m_functionHintAssistProvider;
+ if (ClangdClient * const client = clientForFile(data.filePath());
+ client && client->isFullyIndexed()) {
+ client->followSymbol(data.textDocument(), data.cursor(), data.editorWidget(),
+ processLinkCallback, resolveTarget, inNextSplit);
+ return;
+ }
+
+ CppModelManager::followSymbol(data, processLinkCallback, resolveTarget, inNextSplit,
+ CppModelManager::Backend::Builtin);
+}
+
+void ClangModelManagerSupport::switchDeclDef(const CppEditor::CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback)
+{
+ if (ClangdClient * const client = clientForFile(data.filePath());
+ client && client->isFullyIndexed()) {
+ client->switchDeclDef(data.textDocument(), data.cursor(), data.editorWidget(),
+ processLinkCallback);
+ return;
+ }
+
+ CppModelManager::switchDeclDef(data, processLinkCallback, CppModelManager::Backend::Builtin);
}
-TextEditor::BaseHoverHandler *ClangModelManagerSupport::createHoverHandler()
+void ClangModelManagerSupport::startLocalRenaming(const CppEditor::CursorInEditor &data,
+ const CppEditor::ProjectPart *projectPart,
+ RenameCallback &&renameSymbolsCallback)
{
- return new Internal::ClangHoverHandler;
+ if (ClangdClient * const client = clientForFile(data.filePath());
+ client && client->reachable()) {
+ client->findLocalUsages(data.textDocument(), data.cursor(),
+ std::move(renameSymbolsCallback));
+ return;
+ }
+
+ CppModelManager::startLocalRenaming(data, projectPart,
+ std::move(renameSymbolsCallback), CppModelManager::Backend::Builtin);
}
-CppEditor::FollowSymbolInterface &ClangModelManagerSupport::followSymbolInterface()
+void ClangModelManagerSupport::globalRename(const CppEditor::CursorInEditor &cursor,
+ const QString &replacement)
{
- return *m_followSymbol;
+ if (ClangdClient * const client = clientForFile(cursor.filePath());
+ client && client->isFullyIndexed()) {
+ QTC_ASSERT(client->documentOpen(cursor.textDocument()),
+ client->openDocument(cursor.textDocument()));
+ client->findUsages(cursor.textDocument(), cursor.cursor(), replacement);
+ return;
+ }
+ CppModelManager::globalRename(cursor, replacement, CppModelManager::Backend::Builtin);
}
-CppEditor::RefactoringEngineInterface &ClangModelManagerSupport::refactoringEngineInterface()
+void ClangModelManagerSupport::findUsages(const CppEditor::CursorInEditor &cursor) const
{
- return *m_refactoringEngine;
+ if (ClangdClient * const client = clientForFile(cursor.filePath());
+ client && client->isFullyIndexed()) {
+ QTC_ASSERT(client->documentOpen(cursor.textDocument()),
+ client->openDocument(cursor.textDocument()));
+ client->findUsages(cursor.textDocument(), cursor.cursor(), {});
+
+ return;
+ }
+ CppModelManager::findUsages(cursor, CppModelManager::Backend::Builtin);
}
-std::unique_ptr<CppEditor::AbstractOverviewModel> ClangModelManagerSupport::createOverviewModel()
+void ClangModelManagerSupport::switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit)
{
- return std::make_unique<OverviewModel>();
+ if (ClangdClient * const client = clientForFile(filePath)) {
+ // The fast, synchronous approach works most of the time, so let's try that one first.
+ const auto otherFile = Utils::FilePath::fromString(
+ correspondingHeaderOrSource(filePath.toString()));
+ if (!otherFile.isEmpty())
+ openEditor(otherFile, inNextSplit);
+ else
+ client->switchHeaderSource(filePath, inNextSplit);
+ return;
+ }
+ CppModelManager::switchHeaderSource(inNextSplit, CppModelManager::Backend::Builtin);
}
-bool ClangModelManagerSupport::supportsOutline(const TextEditor::TextDocument *document) const
+std::unique_ptr<CppEditor::AbstractOverviewModel> ClangModelManagerSupport::createOverviewModel()
{
- return !clientForFile(document->filePath());
+ return {};
}
-bool ClangModelManagerSupport::supportsLocalUses(const TextEditor::TextDocument *document) const
+bool ClangModelManagerSupport::usesClangd(const TextEditor::TextDocument *document) const
{
- return !clientForFile(document->filePath());
+ return clientForFile(document->filePath());
}
CppEditor::BaseEditorDocumentProcessor *ClangModelManagerSupport::createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument)
{
- const auto processor = new ClangEditorDocumentProcessor(m_communicator, baseTextDocument);
+ const auto processor = new ClangEditorDocumentProcessor(baseTextDocument);
const auto handleConfigChange = [this](const Utils::FilePath &fp,
const BaseEditorDocumentParser::Configuration &config) {
if (const auto client = clientForFile(fp))
@@ -228,66 +346,21 @@ CppEditor::BaseEditorDocumentProcessor *ClangModelManagerSupport::createEditorDo
void ClangModelManagerSupport::onCurrentEditorChanged(Core::IEditor *editor)
{
- m_communicator.documentVisibilityChanged();
-
// Update task hub issues for current CppEditorDocument
- ClangEditorDocumentProcessor::clearTaskHubIssues();
+ ProjectExplorer::TaskHub::clearTasks(Constants::TASK_CATEGORY_DIAGNOSTICS);
if (!editor || !editor->document() || !cppModelManager()->isCppEditor(editor))
return;
const ::Utils::FilePath filePath = editor->document()->filePath();
if (auto processor = ClangEditorDocumentProcessor::get(filePath.toString())) {
processor->semanticRehighlight();
- processor->generateTaskHubIssues();
- if (const auto client = clientForFile(filePath))
+ if (const auto client = clientForFile(filePath)) {
client->updateParserConfig(filePath, processor->parserConfig());
+ client->switchIssuePaneEntries(filePath);
+ }
}
}
-void ClangModelManagerSupport::connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument)
-{
- // Handle externally changed documents
- connect(textDocument, &Core::IDocument::aboutToReload,
- this, &ClangModelManagerSupport::onCppDocumentAboutToReloadOnTranslationUnit,
- Qt::UniqueConnection);
- connect(textDocument, &Core::IDocument::reloadFinished,
- this, &ClangModelManagerSupport::onCppDocumentReloadFinishedOnTranslationUnit,
- Qt::UniqueConnection);
-
- // Handle changes from e.g. refactoring actions
- connectToTextDocumentContentsChangedForTranslationUnit(textDocument);
-}
-
-void ClangModelManagerSupport::connectTextDocumentToUnsavedFiles(TextEditor::TextDocument *textDocument)
-{
- // Handle externally changed documents
- connect(textDocument, &Core::IDocument::aboutToReload,
- this, &ClangModelManagerSupport::onCppDocumentAboutToReloadOnUnsavedFile,
- Qt::UniqueConnection);
- connect(textDocument, &Core::IDocument::reloadFinished,
- this, &ClangModelManagerSupport::onCppDocumentReloadFinishedOnUnsavedFile,
- Qt::UniqueConnection);
-
- // Handle changes from e.g. refactoring actions
- connectToTextDocumentContentsChangedForUnsavedFile(textDocument);
-}
-
-void ClangModelManagerSupport::connectToTextDocumentContentsChangedForTranslationUnit(
- TextEditor::TextDocument *textDocument)
-{
- connect(textDocument, &TextEditor::TextDocument::contentsChangedWithPosition,
- this, &ClangModelManagerSupport::onCppDocumentContentsChangedOnTranslationUnit,
- Qt::UniqueConnection);
-}
-
-void ClangModelManagerSupport::connectToTextDocumentContentsChangedForUnsavedFile(
- TextEditor::TextDocument *textDocument)
-{
- connect(textDocument, &TextEditor::TextDocument::contentsChangedWithPosition,
- this, &ClangModelManagerSupport::onCppDocumentContentsChangedOnUnsavedFile,
- Qt::UniqueConnection);
-}
-
void ClangModelManagerSupport::connectToWidgetsMarkContextMenuRequested(QWidget *editorWidget)
{
const auto widget = qobject_cast<TextEditor::TextEditorWidget *>(editorWidget);
@@ -300,7 +373,8 @@ void ClangModelManagerSupport::connectToWidgetsMarkContextMenuRequested(QWidget
void ClangModelManagerSupport::updateLanguageClient(
ProjectExplorer::Project *project, const CppEditor::ProjectInfo::ConstPtr &projectInfo)
{
- if (!CppEditor::ClangdProjectSettings(project).settings().useClangd)
+ const ClangdSettings settings(ClangdProjectSettings(project).settings());
+ if (!settings.useClangd())
return;
const auto getJsonDbDir = [project] {
if (const ProjectExplorer::Target * const target = project->activeTarget()) {
@@ -321,7 +395,7 @@ void ClangModelManagerSupport::updateLanguageClient(
generatorWatcher->deleteLater();
if (!ProjectExplorer::SessionManager::hasProject(project))
return;
- if (!CppEditor::ClangdProjectSettings(project).settings().useClangd)
+ if (!ClangdSettings(ClangdProjectSettings(project).settings()).useClangd())
return;
const CppEditor::ProjectInfo::ConstPtr newProjectInfo
= cppModelManager()->projectInfo(project);
@@ -339,7 +413,13 @@ void ClangModelManagerSupport::updateLanguageClient(
if (Client * const oldClient = clientForProject(project))
LanguageClientManager::shutdownClient(oldClient);
ClangdClient * const client = createClient(project, jsonDbDir);
- connect(client, &Client::initialized, this, [client, project, projectInfo, jsonDbDir] {
+ connect(client, &Client::shadowDocumentSwitched, this,
+ [](const Utils::FilePath &fp) {
+ ClangdClient::handleUiHeaderChange(fp.fileName());
+ });
+ connect(CppModelManager::instance(), &CppModelManager::projectPartsUpdated,
+ client, [client] { updateParserConfig(client); });
+ connect(client, &Client::initialized, this, [this, client, project, projectInfo, jsonDbDir] {
using namespace ProjectExplorer;
if (!SessionManager::hasProject(project))
return;
@@ -350,39 +430,45 @@ void ClangModelManagerSupport::updateLanguageClient(
if (!newProjectInfo || *newProjectInfo != *projectInfo)
return;
- const auto updateParserConfig = [client] {
- if (const auto editor = TextEditor::BaseTextEditor::currentTextEditor()) {
- if (!client->documentOpen(editor->textDocument()))
- return;
- const Utils::FilePath filePath = editor->textDocument()->filePath();
- if (const auto processor = ClangEditorDocumentProcessor::get(
- filePath.toString())) {
- const CppEditor::BaseEditorDocumentParser::Configuration config
- = processor->parserConfig();
- client->updateParserConfig(filePath, config);
- }
- }
- };
-
// Acquaint the client with all open C++ documents for this project.
bool hasDocuments = false;
+ const ClangdSettings settings(ClangdProjectSettings(project).settings());
for (TextEditor::TextDocument * const doc : allCppDocuments()) {
- const Client * const currentClient = LanguageClientManager::clientForDocument(doc);
- if (!currentClient || !currentClient->project()
- || currentClient->state() != Client::Initialized
- || project->isKnownFile(doc->filePath())) {
+ Client * const currentClient = LanguageClientManager::clientForDocument(doc);
+ if (currentClient == client) {
+ hasDocuments = true;
+ continue;
+ }
+ if (!settings.sizeIsOkay(doc->filePath()))
+ continue;
+ const Project * const docProject = SessionManager::projectForFile(doc->filePath());
+ if (currentClient && currentClient->project()
+ && currentClient->project() != project
+ && currentClient->project() == docProject) {
+ continue;
+ }
+ if (!docProject || docProject == project) {
+ if (currentClient)
+ currentClient->closeDocument(doc);
LanguageClientManager::openDocumentWithClient(doc, client);
- ClangEditorDocumentProcessor::clearTextMarks(doc->filePath());
hasDocuments = true;
}
}
- if (client->state() == Client::Initialized)
- updateParserConfig();
- else
- connect(client, &Client::initialized, client, updateParserConfig);
- connect(CppModelManager::instance(), &CppModelManager::projectPartsUpdated,
- client, updateParserConfig);
+ for (auto it = m_queuedShadowDocuments.begin(); it != m_queuedShadowDocuments.end();) {
+ if (fileIsProjectBuildArtifact(client, it.key())) {
+ if (it.value().isEmpty())
+ client->removeShadowDocument(it.key());
+ else
+ client->setShadowDocument(it.key(), it.value());
+ ClangdClient::handleUiHeaderChange(it.key().fileName());
+ it = m_queuedShadowDocuments.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ updateParserConfig(client);
if (hasDocuments)
return;
@@ -407,10 +493,11 @@ void ClangModelManagerSupport::updateLanguageClient(
});
});
+ const Utils::FilePath includeDir = settings.clangdIncludePath();
auto future = Utils::runAsync(&Internal::generateCompilationDB, projectInfo, jsonDbDir,
CompilationDbPurpose::CodeModel,
warningsConfigForProject(project),
- optionsForProject(project));
+ globalClangOptions(), includeDir);
generatorWatcher->setFuture(future);
m_generatorSynchronizer.addFuture(future);
}
@@ -459,13 +546,18 @@ void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *client)
if (!client)
return;
for (TextEditor::TextDocument * const doc : allCppDocuments()) {
- if (Client * const currentClient = LanguageClientManager::clientForDocument(doc);
- currentClient && currentClient->state() == Client::Initialized
+ Client * const currentClient = LanguageClientManager::clientForDocument(doc);
+ if (currentClient && currentClient->state() == Client::Initialized
&& (currentClient == client || currentClient->project())) {
continue;
}
- ClangEditorDocumentProcessor::clearTextMarks(doc->filePath());
- client->openDocument(doc);
+ if (!ClangdSettings::instance().sizeIsOkay(doc->filePath()))
+ continue;
+ if (!ProjectExplorer::SessionManager::projectForFile(doc->filePath())) {
+ if (currentClient)
+ currentClient->closeDocument(doc);
+ LanguageClientManager::openDocumentWithClient(doc, client);
+ }
}
}
@@ -560,13 +652,15 @@ void ClangModelManagerSupport::onEditorOpened(Core::IEditor *editor)
auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
if (textDocument && cppModelManager()->isCppEditor(editor)) {
- connectTextDocumentToTranslationUnit(textDocument);
connectToWidgetsMarkContextMenuRequested(editor->widget());
// TODO: Ensure that not fully loaded documents are updated?
ProjectExplorer::Project * project
= ProjectExplorer::SessionManager::projectForFile(document->filePath());
+ const ClangdSettings settings(ClangdProjectSettings(project).settings());
+ if (!settings.sizeIsOkay(textDocument->filePath()))
+ return;
if (!project)
project = fallbackProject();
if (ClangdClient * const client = clientForProject(project))
@@ -574,71 +668,6 @@ void ClangModelManagerSupport::onEditorOpened(Core::IEditor *editor)
}
}
-void ClangModelManagerSupport::onEditorClosed(const QList<Core::IEditor *> &)
-{
- m_communicator.documentVisibilityChanged();
-}
-
-void ClangModelManagerSupport::onCppDocumentAboutToReloadOnTranslationUnit()
-{
- auto textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
- disconnect(textDocument, &TextEditor::TextDocument::contentsChangedWithPosition,
- this, &ClangModelManagerSupport::onCppDocumentContentsChangedOnTranslationUnit);
-}
-
-void ClangModelManagerSupport::onCppDocumentReloadFinishedOnTranslationUnit(bool success)
-{
- if (success) {
- auto textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
- connectToTextDocumentContentsChangedForTranslationUnit(textDocument);
- m_communicator.documentsChangedWithRevisionCheck(textDocument);
- }
-}
-
-namespace {
-void clearDiagnosticFixIts(const QString &filePath)
-{
- auto processor = ClangEditorDocumentProcessor::get(filePath);
- if (processor)
- processor->clearDiagnosticsWithFixIts();
-}
-}
-
-void ClangModelManagerSupport::onCppDocumentContentsChangedOnTranslationUnit(int position,
- int /*charsRemoved*/,
- int /*charsAdded*/)
-{
- auto document = qobject_cast<Core::IDocument *>(sender());
-
- m_communicator.updateChangeContentStartPosition(document->filePath().toString(),
- position);
- m_communicator.documentsChangedIfNotCurrentDocument(document);
-
- clearDiagnosticFixIts(document->filePath().toString());
-}
-
-void ClangModelManagerSupport::onCppDocumentAboutToReloadOnUnsavedFile()
-{
- auto textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
- disconnect(textDocument, &TextEditor::TextDocument::contentsChangedWithPosition,
- this, &ClangModelManagerSupport::onCppDocumentContentsChangedOnUnsavedFile);
-}
-
-void ClangModelManagerSupport::onCppDocumentReloadFinishedOnUnsavedFile(bool success)
-{
- if (success) {
- auto textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
- connectToTextDocumentContentsChangedForUnsavedFile(textDocument);
- m_communicator.unsavedFilesUpdated(textDocument);
- }
-}
-
-void ClangModelManagerSupport::onCppDocumentContentsChangedOnUnsavedFile()
-{
- auto document = qobject_cast<Core::IDocument *>(sender());
- m_communicator.unsavedFilesUpdated(document);
-}
-
void ClangModelManagerSupport::onAbstractEditorSupportContentsUpdated(const QString &filePath,
const QString &,
const QByteArray &content)
@@ -647,27 +676,34 @@ void ClangModelManagerSupport::onAbstractEditorSupportContentsUpdated(const QStr
if (content.size() == 0)
return; // Generation not yet finished.
-
- const QString mappedPath = m_uiHeaderOnDiskManager.write(filePath, content);
- m_communicator.unsavedFilesUpdated(mappedPath, content, 0);
- ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName());
+ const auto fp = Utils::FilePath::fromString(filePath);
+ const QString stringContent = QString::fromUtf8(content);
+ if (Client * const client = clientForGeneratedFile(fp)) {
+ client->setShadowDocument(fp, stringContent);
+ ClangdClient::handleUiHeaderChange(fp.fileName());
+ QTC_CHECK(m_queuedShadowDocuments.remove(fp) == 0);
+ } else {
+ m_queuedShadowDocuments.insert(fp, stringContent);
+ }
}
void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &filePath)
{
QTC_ASSERT(!filePath.isEmpty(), return);
- if (!cppModelManager()->cppEditorDocument(filePath)) {
- const QString mappedPath = m_uiHeaderOnDiskManager.remove(filePath);
- const QString projectPartId = projectPartIdForFile(filePath);
- m_communicator.unsavedFilesRemoved({{mappedPath, projectPartId}});
- ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName());
+ const auto fp = Utils::FilePath::fromString(filePath);
+ if (Client * const client = clientForGeneratedFile(fp)) {
+ client->removeShadowDocument(fp);
+ ClangdClient::handleUiHeaderChange(fp.fileName());
+ QTC_CHECK(m_queuedShadowDocuments.remove(fp) == 0);
+ } else {
+ m_queuedShadowDocuments.insert(fp, {});
}
}
void addFixItsActionsToMenu(QMenu *menu, const TextEditor::QuickFixOperations &fixItOperations)
{
- foreach (const auto &fixItOperation, fixItOperations) {
+ for (const TextEditor::QuickFixOperation::Ptr &fixItOperation : fixItOperations) {
QAction *action = menu->addAction(fixItOperation->description());
QObject::connect(action, &QAction::triggered, [fixItOperation]() {
fixItOperation->perform();
@@ -675,18 +711,13 @@ void addFixItsActionsToMenu(QMenu *menu, const TextEditor::QuickFixOperations &f
}
}
-static int lineToPosition(const QTextDocument *textDocument, int lineNumber)
-{
- QTC_ASSERT(textDocument, return 0);
- const QTextBlock textBlock = textDocument->findBlockByLineNumber(lineNumber);
- return textBlock.isValid() ? textBlock.position() - 1 : 0;
-}
-
static TextEditor::AssistInterface createAssistInterface(TextEditor::TextEditorWidget *widget,
int lineNumber)
{
- return TextEditor::AssistInterface(widget->document(),
- lineToPosition(widget->document(), lineNumber),
+ QTextCursor cursor(widget->document()->findBlockByLineNumber(lineNumber));
+ if (!cursor.atStart())
+ cursor.movePosition(QTextCursor::PreviousCharacter);
+ return TextEditor::AssistInterface(cursor,
widget->textDocument()->filePath(),
TextEditor::IdleEditor);
}
@@ -713,48 +744,12 @@ using ClangEditorDocumentProcessors = QVector<ClangEditorDocumentProcessor *>;
static ClangEditorDocumentProcessors clangProcessors()
{
ClangEditorDocumentProcessors result;
- foreach (auto *editorDocument, cppModelManager()->cppEditorDocuments())
+ for (const CppEditorDocumentHandle *editorDocument : cppModelManager()->cppEditorDocuments())
result.append(qobject_cast<ClangEditorDocumentProcessor *>(editorDocument->processor()));
return result;
}
-static ClangEditorDocumentProcessors
-clangProcessorsWithProject(const ProjectExplorer::Project *project)
-{
- return ::Utils::filtered(clangProcessors(), [project](ClangEditorDocumentProcessor *p) {
- return p->hasProjectPart() && p->projectPart()->belongsToProject(project);
- });
-}
-
-static void updateProcessors(const ClangEditorDocumentProcessors &processors)
-{
- CppEditor::CppModelManager *modelManager = cppModelManager();
- for (ClangEditorDocumentProcessor *processor : processors)
- modelManager->cppEditorDocument(processor->filePath())->resetProcessor();
- modelManager->updateCppEditorDocuments(/*projectsUpdated=*/ false);
-}
-
-void ClangModelManagerSupport::onProjectAdded(ProjectExplorer::Project *project)
-{
- QTC_ASSERT(!m_projectSettings.value(project), return);
-
- auto *settings = new Internal::ClangProjectSettings(project);
- connect(settings, &Internal::ClangProjectSettings::changed, [project]() {
- updateProcessors(clangProcessorsWithProject(project));
- });
-
- m_projectSettings.insert(project, settings);
-}
-
-void ClangModelManagerSupport::onAboutToRemoveProject(ProjectExplorer::Project *project)
-{
- ClangProjectSettings * const settings = m_projectSettings.value(project);
- QTC_ASSERT(settings, return);
- m_projectSettings.remove(project);
- delete settings;
-}
-
void ClangModelManagerSupport::onProjectPartsUpdated(ProjectExplorer::Project *project)
{
QTC_ASSERT(project, return);
@@ -814,19 +809,6 @@ void ClangModelManagerSupport::onClangdSettingsChanged()
}
}
-static ClangEditorDocumentProcessors clangProcessorsWithDiagnosticConfig(
- const QVector<::Utils::Id> &configIds)
-{
- return ::Utils::filtered(clangProcessors(), [configIds](ClangEditorDocumentProcessor *p) {
- return configIds.contains(p->diagnosticConfigId());
- });
-}
-
-void ClangModelManagerSupport::onDiagnosticConfigsInvalidated(const QVector<::Utils::Id> &configIds)
-{
- updateProcessors(clangProcessorsWithDiagnosticConfig(configIds));
-}
-
static ClangEditorDocumentProcessors
clangProcessorsWithProjectParts(const QStringList &projectPartIds)
{
@@ -837,9 +819,8 @@ clangProcessorsWithProjectParts(const QStringList &projectPartIds)
void ClangModelManagerSupport::reinitializeBackendDocuments(const QStringList &projectPartIds)
{
- const auto processors = clangProcessorsWithProjectParts(projectPartIds);
- foreach (ClangEditorDocumentProcessor *processor, processors) {
- processor->closeBackendDocument();
+ const ClangEditorDocumentProcessors processors = clangProcessorsWithProjectParts(projectPartIds);
+ for (ClangEditorDocumentProcessor *processor : processors) {
processor->clearProjectPart();
processor->run();
}
@@ -850,27 +831,6 @@ ClangModelManagerSupport *ClangModelManagerSupport::instance()
return m_instance;
}
-BackendCommunicator &ClangModelManagerSupport::communicator()
-{
- return m_communicator;
-}
-
-QString ClangModelManagerSupport::dummyUiHeaderOnDiskPath(const QString &filePath) const
-{
- return m_uiHeaderOnDiskManager.mapPath(filePath);
-}
-
-ClangProjectSettings &ClangModelManagerSupport::projectSettings(
- ProjectExplorer::Project *project) const
-{
- return *m_projectSettings.value(project);
-}
-
-QString ClangModelManagerSupport::dummyUiHeaderOnDiskDirPath() const
-{
- return m_uiHeaderOnDiskManager.directoryPath();
-}
-
QString ClangModelManagerSupportProvider::id() const
{
return QLatin1String(Constants::CLANG_MODELMANAGERSUPPORT_ID);
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
index b957ae69b90..64db859d388 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
@@ -25,15 +25,14 @@
#pragma once
-#include "clangcompletionassistprovider.h"
-#include "clanguiheaderondiskmanager.h"
-
#include <cppeditor/cppmodelmanagersupport.h>
#include <cppeditor/projectinfo.h>
+#include <utils/filepath.h>
#include <utils/futuresynchronizer.h>
#include <utils/id.h>
+#include <QHash>
#include <QObject>
#include <QPointer>
@@ -44,17 +43,14 @@ class QMenu;
class QWidget;
QT_END_NAMESPACE
+namespace Core { class IEditor; }
+namespace CppEditor { class RefactoringEngineInterface; }
namespace TextEditor { class TextEditorWidget; }
-namespace CppEditor {
-class FollowSymbolInterface;
-class RefactoringEngineInterface;
-} // namespace CppEditor
namespace ClangCodeModel {
namespace Internal {
class ClangdClient;
-class ClangProjectSettings;
class ClangModelManagerSupport:
public QObject,
@@ -67,21 +63,11 @@ public:
~ClangModelManagerSupport() override;
CppEditor::CppCompletionAssistProvider *completionAssistProvider() override;
- CppEditor::CppCompletionAssistProvider *functionHintAssistProvider() override;
- TextEditor::BaseHoverHandler *createHoverHandler() override;
+ TextEditor::BaseHoverHandler *createHoverHandler() override { return nullptr; }
CppEditor::BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) override;
- CppEditor::FollowSymbolInterface &followSymbolInterface() override;
- CppEditor::RefactoringEngineInterface &refactoringEngineInterface() override;
std::unique_ptr<CppEditor::AbstractOverviewModel> createOverviewModel() override;
- bool supportsOutline(const TextEditor::TextDocument *document) const override;
- bool supportsLocalUses(const TextEditor::TextDocument *document) const override;
-
- BackendCommunicator &communicator();
- QString dummyUiHeaderOnDiskDirPath() const;
- QString dummyUiHeaderOnDiskPath(const QString &filePath) const;
-
- ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const;
+ bool usesClangd(const TextEditor::TextDocument *document) const override;
ClangdClient *clientForProject(const ProjectExplorer::Project *project) const;
ClangdClient *clientForFile(const Utils::FilePath &file) const;
@@ -92,17 +78,20 @@ signals:
void createdClient(ClangdClient *client);
private:
+ void followSymbol(const CppEditor::CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback, bool resolveTarget,
+ bool inNextSplit) override;
+ void switchDeclDef(const CppEditor::CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback) override;
+ void startLocalRenaming(const CppEditor::CursorInEditor &data,
+ const CppEditor::ProjectPart *projectPart,
+ CppEditor::RenameCallback &&renameSymbolsCallback) override;
+ void globalRename(const CppEditor::CursorInEditor &cursor, const QString &replacement) override;
+ void findUsages(const CppEditor::CursorInEditor &cursor) const override;
+ void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) override;
+
void onEditorOpened(Core::IEditor *editor);
- void onEditorClosed(const QList<Core::IEditor *> &editors);
void onCurrentEditorChanged(Core::IEditor *newCurrent);
- void onCppDocumentAboutToReloadOnTranslationUnit();
- void onCppDocumentReloadFinishedOnTranslationUnit(bool success);
- void onCppDocumentContentsChangedOnTranslationUnit(int position,
- int charsRemoved,
- int charsAdded);
- void onCppDocumentAboutToReloadOnUnsavedFile();
- void onCppDocumentReloadFinishedOnUnsavedFile(bool success);
- void onCppDocumentContentsChangedOnUnsavedFile();
void onAbstractEditorSupportContentsUpdated(const QString &filePath,
const QString &sourceFilePath,
@@ -113,22 +102,13 @@ private:
int lineNumber,
QMenu *menu);
- void onProjectAdded(ProjectExplorer::Project *project);
- void onAboutToRemoveProject(ProjectExplorer::Project *project);
-
void onProjectPartsUpdated(ProjectExplorer::Project *project);
void onProjectPartsRemoved(const QStringList &projectPartIds);
void onClangdSettingsChanged();
- void onDiagnosticConfigsInvalidated(const QVector<::Utils::Id> &configIds);
-
void reinitializeBackendDocuments(const QStringList &projectPartIds);
void connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument);
- void connectTextDocumentToUnsavedFiles(TextEditor::TextDocument *textDocument);
- void connectToTextDocumentContentsChangedForTranslationUnit(
- TextEditor::TextDocument *textDocument);
- void connectToTextDocumentContentsChangedForUnsavedFile(TextEditor::TextDocument *textDocument);
void connectToWidgetsMarkContextMenuRequested(QWidget *editorWidget);
void updateLanguageClient(ProjectExplorer::Project *project,
@@ -138,16 +118,9 @@ private:
void watchForExternalChanges();
void watchForInternalChanges();
- UiHeaderOnDiskManager m_uiHeaderOnDiskManager;
- BackendCommunicator m_communicator;
- ClangCompletionAssistProvider m_completionAssistProvider;
- ClangCompletionAssistProvider m_functionHintAssistProvider;
- std::unique_ptr<CppEditor::FollowSymbolInterface> m_followSymbol;
- std::unique_ptr<CppEditor::RefactoringEngineInterface> m_refactoringEngine;
-
- QHash<ProjectExplorer::Project *, ClangProjectSettings *> m_projectSettings;
Utils::FutureSynchronizer m_generatorSynchronizer;
QList<QPointer<ClangdClient>> m_clientsToRestart;
+ QHash<Utils::FilePath, QString> m_queuedShadowDocuments;
};
class ClangModelManagerSupportProvider : public CppEditor::ModelManagerSupportProvider
diff --git a/src/plugins/clangcodemodel/clangoverviewmodel.cpp b/src/plugins/clangcodemodel/clangoverviewmodel.cpp
deleted file mode 100644
index cf1d879feb8..00000000000
--- a/src/plugins/clangcodemodel/clangoverviewmodel.cpp
+++ /dev/null
@@ -1,251 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangoverviewmodel.h"
-
-#include "clangeditordocumentprocessor.h"
-#include "clangutils.h"
-
-#include <cplusplus/Icons.h>
-
-#include <utils/dropsupport.h>
-#include <utils/linecolumn.h>
-#include <utils/qtcassert.h>
-
-using TokenContainer = ClangBackEnd::TokenInfoContainer;
-using TokenContainers = QVector<TokenContainer>;
-
-using namespace Utils;
-
-namespace ClangCodeModel {
-namespace Internal {
-
-void addFirstItem(TokenTreeItem *root)
-{
- ClangBackEnd::ExtraInfo extraInfo;
- if (!root->childCount()) {
- extraInfo.token = Utf8String::fromString(
- QString(QT_TRANSLATE_NOOP("ClangCodeModel", "<No Symbols>")));
- } else {
- extraInfo.token = Utf8String::fromString(
- QString(QT_TRANSLATE_NOOP("ClangCodeModel", "<Select Symbol>")));
- }
- ClangBackEnd::HighlightingTypes types;
- types.mainHighlightingType = ClangBackEnd::HighlightingType::Invalid;
- TokenContainer firstItem(0, 0, 0, types, extraInfo);
- root->prependChild(new TokenTreeItem(firstItem));
-}
-
-void buildTree(const TokenContainers &containers,
- TokenTreeItem *root)
-{
- // Most of the nodes are not used in this tree at all (all local variables and more)
- // therefore use unordered_map instead of vector.
- std::unordered_map<int, TokenTreeItem *> treeItemCache;
- for (int index = 0; index < containers.size(); ++index) {
- const TokenContainer &container = containers[index];
- if (!container.isGlobalDeclaration())
- continue;
-
- const int lexicalParentIndex = container.extraInfo.lexicalParentIndex;
- QTC_ASSERT(lexicalParentIndex < index, return;);
-
- auto item = std::make_unique<TokenTreeItem>(container);
- treeItemCache[index] = item.get();
-
- TokenTreeItem *parent = root;
- if (lexicalParentIndex >= 0 && treeItemCache[lexicalParentIndex])
- parent = treeItemCache[lexicalParentIndex];
-
- ClangBackEnd::HighlightingType parentType = parent->token.types.mainHighlightingType;
- if (parentType == ClangBackEnd::HighlightingType::VirtualFunction
- || parentType == ClangBackEnd::HighlightingType::Function) {
- // Treat everything inside a function scope as local variables.
- treeItemCache.erase(index);
- continue;
- }
-
- parent->appendChild(item.release());
- }
-
- addFirstItem(root);
-}
-
-static QString addType(const QString &name, const ClangBackEnd::ExtraInfo &extraInfo)
-{
- return name + QLatin1String(" -> ", 4) + extraInfo.typeSpelling.toString();
-}
-
-static QString fullName(const ClangBackEnd::ExtraInfo &extraInfo, TokenTreeItem *parent)
-{
- const QString parentType = parent->token.extraInfo.typeSpelling.toString();
- if (extraInfo.semanticParentTypeSpelling.startsWith(parentType)) {
- const QString parentQualification = parentType.isEmpty()
- ? extraInfo.semanticParentTypeSpelling
- : extraInfo.semanticParentTypeSpelling.mid(parentType.length() + 2);
- if (!parentQualification.isEmpty())
- return parentQualification + "::" + extraInfo.token.toString();
- }
-
- return extraInfo.token.toString();
-}
-
-QVariant TokenTreeItem::data(int column, int role) const
-{
- Q_UNUSED(column)
-
- if (token.types.mainHighlightingType == ClangBackEnd::HighlightingType::Invalid
- && token.line == 0 && token.column == 0 && token.length == 0) {
- if (role == Qt::DisplayRole)
- return token.extraInfo.token.toString();
- return QVariant();
- }
-
- switch (role) {
- case Qt::DisplayRole: {
- QString name = fullName(token.extraInfo, static_cast<TokenTreeItem *>(parent()));
-
- ClangBackEnd::HighlightingType mainType = token.types.mainHighlightingType;
-
- if (mainType == ClangBackEnd::HighlightingType::VirtualFunction
- || mainType == ClangBackEnd::HighlightingType::Function) {
- name = addType(name, token.extraInfo);
- } else if (mainType == ClangBackEnd::HighlightingType::GlobalVariable
- || mainType == ClangBackEnd::HighlightingType::Field
- || mainType == ClangBackEnd::HighlightingType::QtProperty) {
- name = addType(name, token.extraInfo);
- if (token.types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::ObjectiveCProperty)) {
- name = QLatin1String("@property ") + name;
- } else if (token.types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::ObjectiveCMethod)) {
- if (token.extraInfo.storageClass == ClangBackEnd::StorageClass::Static)
- name = QLatin1Char('+') + name;
- else
- name = QLatin1Char('-') + name;
- }
- } else if (mainType == ClangBackEnd::HighlightingType::Type) {
-
- if (token.types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::ObjectiveCClass)) {
- name = QLatin1String("@class ") + name;
- } else if (token.types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::ObjectiveCProtocol)) {
- name = QLatin1String("@protocol ") + name;
- } else if (token.types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::ObjectiveCInterface)) {
- name = QLatin1String("@interface ") + name;
- } else if (token.types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::ObjectiveCImplementation)) {
- name = QLatin1String("@implementation ") + name;
- } else if (token.types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::ObjectiveCCategory)) {
- name = name + " [category]";
- }
- }
- return name;
- }
-
- case Qt::EditRole: {
- return token.extraInfo.token.toString();
- }
-
- case Qt::DecorationRole: {
- return CodeModelIcon::iconForType(iconTypeForToken(token));
- }
-
- case CppEditor::AbstractOverviewModel::FileNameRole: {
- return token.extraInfo.cursorRange.start.filePath.toString();
- }
-
- case CppEditor::AbstractOverviewModel::LineNumberRole: {
- return token.line;
- }
-
- default:
- return QVariant();
- } // switch
-}
-
-bool OverviewModel::rebuild(const QString &filePath)
-{
- ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(filePath);
- if (!processor)
- return false;
- if (m_filePath != filePath) {
- if (!m_filePath.isEmpty()) {
- ClangEditorDocumentProcessor *previousProcessor
- = ClangEditorDocumentProcessor::get(m_filePath);
- if (previousProcessor) {
- disconnect(previousProcessor, &ClangEditorDocumentProcessor::tokenInfosUpdated,
- this, &OverviewModel::needsUpdate);
- }
- }
- m_filePath = filePath;
- connect(processor, &ClangEditorDocumentProcessor::tokenInfosUpdated, this,
- &OverviewModel::needsUpdate);
- }
-
- const TokenContainers &tokenContainers = processor->tokenInfos();
- auto *root = new TokenTreeItem;
- buildTree(tokenContainers, root);
- setRootItem(root);
-
- return true;
-}
-
-bool OverviewModel::isGenerated(const QModelIndex &) const
-{
- return false;
-}
-
-Link OverviewModel::linkFromIndex(const QModelIndex &sourceIndex) const
-{
- auto item = static_cast<TokenTreeItem *>(itemForIndex(sourceIndex));
- if (!item)
- return {};
- return Link(FilePath::fromString(m_filePath), item->token.line, item->token.column - 1);
-}
-
-LineColumn OverviewModel::lineColumnFromIndex(const QModelIndex &sourceIndex) const
-{
- auto item = static_cast<TokenTreeItem *>(itemForIndex(sourceIndex));
- if (!item)
- return {};
- return {item->token.line, item->token.column};
-}
-
-OverviewModel::Range OverviewModel::rangeFromIndex(const QModelIndex &sourceIndex) const
-{
- auto item = static_cast<TokenTreeItem *>(itemForIndex(sourceIndex));
- if (!item)
- return {};
- const ClangBackEnd::SourceRangeContainer &range = item->token.extraInfo.cursorRange;
- return std::make_pair(LineColumn(range.start.line, range.start.column),
- LineColumn(range.end.line, range.end.column));
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangoverviewmodel.h b/src/plugins/clangcodemodel/clangoverviewmodel.h
deleted file mode 100644
index 5d16574c32e..00000000000
--- a/src/plugins/clangcodemodel/clangoverviewmodel.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "tokeninfocontainer.h"
-
-#include <cppeditor/abstractoverviewmodel.h>
-
-namespace ClangBackEnd { class TokenInfoContainer; }
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangEditorDocumentProcessor;
-
-class TokenTreeItem : public ::Utils::TypedTreeItem<TokenTreeItem>
-{
-public:
- TokenTreeItem() noexcept
- : token()
- {}
- TokenTreeItem(const ClangBackEnd::TokenInfoContainer &token) noexcept
- : token(token)
- {}
-
- QVariant data(int column, int role) const override;
-
- const ClangBackEnd::TokenInfoContainer token;
-};
-
-class OverviewModel : public CppEditor::AbstractOverviewModel
-{
- Q_OBJECT
-
-public:
- bool rebuild(const QString &filePath) override;
-
- bool isGenerated(const QModelIndex &sourceIndex) const override;
- ::Utils::Link linkFromIndex(const QModelIndex &sourceIndex) const override;
- ::Utils::LineColumn lineColumnFromIndex(const QModelIndex &sourceIndex) const override;
- Range rangeFromIndex(const QModelIndex &sourceIndex) const override;
-private:
- QString m_filePath;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangprojectsettings.cpp b/src/plugins/clangcodemodel/clangprojectsettings.cpp
deleted file mode 100644
index 0e7a98924b1..00000000000
--- a/src/plugins/clangcodemodel/clangprojectsettings.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangprojectsettings.h"
-
-#include <cppeditor/cppcodemodelsettings.h>
-#include <cppeditor/cpptoolsreuse.h>
-
-#include <utils/qtcassert.h>
-#include <utils/hostosinfo.h>
-
-#include <QDebug>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-static QString useGlobalConfigKey()
-{ return QStringLiteral("ClangCodeModel.UseGlobalConfig"); }
-
-static QString warningConfigIdKey()
-{ return QStringLiteral("ClangCodeModel.WarningConfigId"); }
-
-static QString customCommandLineKey()
-{ return QLatin1String("ClangCodeModel.CustomCommandLineKey"); }
-
-static bool useGlobalConfigFromSettings(ProjectExplorer::Project *project)
-{
- const QVariant useGlobalConfigVariant = project->namedSettings(useGlobalConfigKey());
- return useGlobalConfigVariant.isValid() ? useGlobalConfigVariant.toBool() : true;
-}
-
-static Utils::Id warningConfigIdFromSettings(ProjectExplorer::Project *project)
-{
- return Utils::Id::fromSetting(project->namedSettings(warningConfigIdKey()));
-}
-
-static QStringList customCommandLineFromSettings(ProjectExplorer::Project *project)
-{
- QStringList options = project->namedSettings(customCommandLineKey()).toStringList();
- if (options.empty())
- options = ClangProjectSettings::globalCommandLineOptions();
- return options;
-}
-
-ClangProjectSettings::ClangProjectSettings(ProjectExplorer::Project *project)
- : m_project(project)
-{
- load();
-
- connect(project, &ProjectExplorer::Project::settingsLoaded,
- this, &ClangProjectSettings::load);
- connect(project, &ProjectExplorer::Project::aboutToSaveSettings,
- this, &ClangProjectSettings::store);
-}
-
-Utils::Id ClangProjectSettings::warningConfigId() const
-{
- const CppEditor::ClangDiagnosticConfigsModel model = CppEditor::diagnosticConfigsModel();
- if (!model.hasConfigWithId(m_warningConfigId))
- return CppEditor::codeModelSettings()->defaultClangDiagnosticConfigId();
- return m_warningConfigId;
-}
-
-void ClangProjectSettings::setWarningConfigId(const Utils::Id &customConfigId)
-{
- m_warningConfigId = customConfigId;
-}
-
-bool ClangProjectSettings::useGlobalConfig() const
-{
- return m_useGlobalConfig;
-}
-
-void ClangProjectSettings::setUseGlobalConfig(bool useGlobalConfig)
-{
- m_useGlobalConfig = useGlobalConfig;
-}
-
-QStringList ClangProjectSettings::commandLineOptions() const
-{
- return m_useGlobalConfig ? globalCommandLineOptions()
- : m_customCommandLineOptions;
-}
-
-void ClangProjectSettings::setCommandLineOptions(const QStringList &options)
-{
- QTC_ASSERT(!m_useGlobalConfig, qDebug()
- << "setCommandLineOptions was called while using global project config");
- m_customCommandLineOptions = options;
-}
-
-void ClangProjectSettings::load()
-{
- setUseGlobalConfig(useGlobalConfigFromSettings(m_project));
- setWarningConfigId(warningConfigIdFromSettings(m_project));
- m_customCommandLineOptions = customCommandLineFromSettings(m_project);
-}
-
-void ClangProjectSettings::store()
-{
- bool settingsChanged = false;
- if (useGlobalConfig() != useGlobalConfigFromSettings(m_project))
- settingsChanged = true;
- if (warningConfigId() != warningConfigIdFromSettings(m_project))
- settingsChanged = true;
- if (commandLineOptions() != customCommandLineFromSettings(m_project))
- settingsChanged = true;
-
- m_project->setNamedSettings(useGlobalConfigKey(), useGlobalConfig());
- m_project->setNamedSettings(warningConfigIdKey(), warningConfigId().toSetting());
- m_project->setNamedSettings(customCommandLineKey(), m_customCommandLineOptions);
-
- if (settingsChanged)
- emit changed();
-}
-
-QStringList ClangProjectSettings::globalCommandLineOptions()
-{
- if (Utils::HostOsInfo::isWindowsHost())
- return {QLatin1String{GlobalWindowsCmdOptions}};
- return {};
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangprojectsettings.h b/src/plugins/clangcodemodel/clangprojectsettings.h
deleted file mode 100644
index 511ac60875f..00000000000
--- a/src/plugins/clangcodemodel/clangprojectsettings.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/project.h>
-
-#include <utils/id.h>
-
-#include <QObject>
-#include <QString>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class ClangProjectSettings: public QObject
-{
- Q_OBJECT
-
-public:
- constexpr static const char* DelayedTemplateParsing = "-fdelayed-template-parsing";
- constexpr static const char* NoDelayedTemplateParsing = "-fno-delayed-template-parsing";
- constexpr static const char* GlobalWindowsCmdOptions = NoDelayedTemplateParsing;
-
- ClangProjectSettings(ProjectExplorer::Project *project);
-
- bool useGlobalConfig() const;
- void setUseGlobalConfig(bool useGlobalConfig);
-
- ::Utils::Id warningConfigId() const;
- void setWarningConfigId(const ::Utils::Id &warningConfigId);
-
- QStringList commandLineOptions() const;
- void setCommandLineOptions(const QStringList &options);
-
- void load();
- void store();
-
- static QStringList globalCommandLineOptions();
-
-signals:
- void changed();
-
-private:
- ProjectExplorer::Project *m_project;
- bool m_useGlobalConfig = true;
- ::Utils::Id m_warningConfigId;
-
- QStringList m_customCommandLineOptions;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp b/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp
index 38521163d28..1bf419cba57 100644
--- a/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp
+++ b/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp
@@ -52,16 +52,12 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project
: m_projectSettings(ClangModelManagerSupport::instance()->projectSettings(project))
{
m_ui.setupUi(this);
+ setGlobalSettingsId(CppEditor::Constants::CPP_CODE_MODEL_SETTINGS_ID);
using namespace CppEditor;
m_ui.delayedTemplateParseCheckBox->setVisible(Utils::HostOsInfo::isWindowsHost());
- // Links
- connect(m_ui.gotoGlobalSettingsLabel, &QLabel::linkActivated, [](const QString &) {
- Core::ICore::showOptionsDialog(CppEditor::Constants::CPP_CODE_MODEL_SETTINGS_ID);
- });
-
connect(m_ui.clangDiagnosticConfigsSelectionWidget,
&ClangDiagnosticConfigsSelectionWidget::changed,
this,
@@ -78,11 +74,10 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project
CppEditor::codeModelSettings()->toSettings(Core::ICore::settings());
});
+ connect(this, &ProjectSettingsWidget::useGlobalSettingsChanged,
+ this, &ClangProjectSettingsWidget::onGlobalCustomChanged);
connect(m_ui.delayedTemplateParseCheckBox, &QCheckBox::toggled,
this, &ClangProjectSettingsWidget::onDelayedTemplateParseClicked);
- connect(m_ui.globalOrCustomComboBox,
- QOverload<int>::of(&QComboBox::currentIndexChanged),
- this, &ClangProjectSettingsWidget::onGlobalCustomChanged);
connect(project, &ProjectExplorer::Project::aboutToSaveSettings,
this, &ClangProjectSettingsWidget::onAboutToSaveProjectSettings);
@@ -109,9 +104,9 @@ void ClangProjectSettingsWidget::onDelayedTemplateParseClicked(bool checked)
m_projectSettings.setCommandLineOptions(options);
}
-void ClangProjectSettingsWidget::onGlobalCustomChanged(int index)
+void ClangProjectSettingsWidget::onGlobalCustomChanged(bool useGlobalSettings)
{
- m_projectSettings.setUseGlobalConfig(index == 0 ? true : false);
+ m_projectSettings.setUseGlobalConfig(useGlobalSettings);
syncOtherWidgetsToComboBox();
}
@@ -122,15 +117,10 @@ void ClangProjectSettingsWidget::onAboutToSaveProjectSettings()
void ClangProjectSettingsWidget::syncWidgets()
{
- syncGlobalCustomComboBox();
+ setUseGlobalSettings(m_projectSettings.useGlobalConfig());
syncOtherWidgetsToComboBox();
}
-void ClangProjectSettingsWidget::syncGlobalCustomComboBox()
-{
- m_ui.globalOrCustomComboBox->setCurrentIndex(m_projectSettings.useGlobalConfig() ? 0 : 1);
-}
-
void ClangProjectSettingsWidget::syncOtherWidgetsToComboBox()
{
const QStringList options = m_projectSettings.commandLineOptions();
diff --git a/src/plugins/clangcodemodel/clangprojectsettingswidget.h b/src/plugins/clangcodemodel/clangprojectsettingswidget.h
index c1127ee6cb7..a2086cf227f 100644
--- a/src/plugins/clangcodemodel/clangprojectsettingswidget.h
+++ b/src/plugins/clangcodemodel/clangprojectsettingswidget.h
@@ -28,6 +28,7 @@
#include "ui_clangprojectsettingswidget.h"
#include "clangprojectsettings.h"
+#include <projectexplorer/projectsettingswidget.h>
#include <QPointer>
@@ -36,7 +37,7 @@ namespace ProjectExplorer { class Project; }
namespace ClangCodeModel {
namespace Internal {
-class ClangProjectSettingsWidget: public QWidget
+class ClangProjectSettingsWidget: public ProjectExplorer::ProjectSettingsWidget
{
Q_OBJECT
@@ -45,11 +46,10 @@ public:
private:
void onDelayedTemplateParseClicked(bool);
- void onGlobalCustomChanged(int index);
+ void onGlobalCustomChanged(bool useGlobalSettings);
void onAboutToSaveProjectSettings();
void syncWidgets();
- void syncGlobalCustomComboBox();
void syncOtherWidgetsToComboBox();
private:
diff --git a/src/plugins/clangcodemodel/clangprojectsettingswidget.ui b/src/plugins/clangcodemodel/clangprojectsettingswidget.ui
index d21ac3c7317..f7200ecead9 100644
--- a/src/plugins/clangcodemodel/clangprojectsettingswidget.ui
+++ b/src/plugins/clangcodemodel/clangprojectsettingswidget.ui
@@ -27,37 +27,6 @@
<number>0</number>
</property>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QComboBox" name="globalOrCustomComboBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <item>
- <property name="text">
- <string>Use Global Settings</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Use Customized Settings</string>
- </property>
- </item>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="gotoGlobalSettingsLabel">
- <property name="text">
- <string>&lt;a href=&quot;target&quot;&gt;Open Global Settings&lt;/a&gt;</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
<widget class="QCheckBox" name="delayedTemplateParseCheckBox">
<property name="toolTip">
<string>Parse templates in a MSVC-compliant way. This helps to parse headers for example from Active Template Library (ATL) or Windows Runtime Library (WRL).
diff --git a/src/plugins/clangcodemodel/clangrefactoringengine.cpp b/src/plugins/clangcodemodel/clangrefactoringengine.cpp
deleted file mode 100644
index fb2a743a845..00000000000
--- a/src/plugins/clangcodemodel/clangrefactoringengine.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangrefactoringengine.h"
-#include "clangeditordocumentprocessor.h"
-
-#include "clangdclient.h"
-#include "clangmodelmanagersupport.h"
-#include "sourcelocationscontainer.h"
-
-#include <cppeditor/cppmodelmanager.h>
-#include <languageclient/languageclientsymbolsupport.h>
-#include <utils/textutils.h>
-#include <utils/qtcassert.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-void RefactoringEngine::startLocalRenaming(const CppEditor::CursorInEditor &data,
- const CppEditor::ProjectPart *,
- RenameCallback &&renameSymbolsCallback)
-{
- ClangdClient * const client
- = ClangModelManagerSupport::instance()->clientForFile(data.filePath());
- if (client && client->reachable()) {
- client->findLocalUsages(data.textDocument(), data.cursor(),
- std::move(renameSymbolsCallback));
- return;
- }
-
- ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(
- data.filePath().toString());
- const int startRevision = data.cursor().document()->revision();
-
- using ClangBackEnd::SourceLocationsContainer;
- auto defaultCallback = [renameSymbolsCallback, startRevision]() {
- return renameSymbolsCallback(QString(), SourceLocationsContainer{}, startRevision);
- };
-
- if (!processor)
- return defaultCallback();
-
- QFuture<CppEditor::CursorInfo> cursorFuture = processor->requestLocalReferences(data.cursor());
- if (cursorFuture.isCanceled())
- return defaultCallback();
-
- if (m_watcher)
- m_watcher->cancel();
-
- m_watcher.reset(new FutureCursorWatcher());
- QObject::connect(m_watcher.get(), &FutureCursorWatcher::finished, [=]() {
- if (m_watcher->isCanceled())
- return defaultCallback();
- const CppEditor::CursorInfo info = m_watcher->result();
- if (info.useRanges.empty())
- return defaultCallback();
-
- QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor());
- cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor,
- info.useRanges.first().length);
- const QString symbolName = cursor.selectedText();
- ClangBackEnd::SourceLocationsContainer container;
- for (auto& use : info.useRanges) {
- container.insertSourceLocation({},
- use.line,
- use.column);
- }
- renameSymbolsCallback(symbolName, container, data.cursor().document()->revision());
- });
-
- m_watcher->setFuture(cursorFuture);
-}
-
-void RefactoringEngine::globalRename(const CppEditor::CursorInEditor &cursor,
- CppEditor::UsagesCallback &&callback,
- const QString &replacement)
-{
- ClangdClient * const client
- = ClangModelManagerSupport::instance()->clientForFile(cursor.filePath());
- if (!client || !client->isFullyIndexed()) {
- CppEditor::CppModelManager::builtinRefactoringEngine()
- ->globalRename(cursor, std::move(callback), replacement);
- return;
- }
- QTC_ASSERT(client->documentOpen(cursor.textDocument()),
- client->openDocument(cursor.textDocument()));
- client->findUsages(cursor.textDocument(), cursor.cursor(), replacement);
-}
-
-void RefactoringEngine::findUsages(const CppEditor::CursorInEditor &cursor,
- CppEditor::UsagesCallback &&callback) const
-{
- ClangdClient * const client
- = ClangModelManagerSupport::instance()->clientForFile(cursor.filePath());
- if (!client || !client->isFullyIndexed()) {
- CppEditor::CppModelManager::builtinRefactoringEngine()
- ->findUsages(cursor, std::move(callback));
- return;
- }
- QTC_ASSERT(client->documentOpen(cursor.textDocument()),
- client->openDocument(cursor.textDocument()));
- client->findUsages(cursor.textDocument(), cursor.cursor(), {});
-}
-
-void RefactoringEngine::globalFollowSymbol(
- const CppEditor::CursorInEditor &cursor,
- Utils::ProcessLinkCallback &&callback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &doc,
- CppEditor::SymbolFinder *symbolFinder,
- bool inNextSplit) const
-{
- ClangdClient * const client
- = ClangModelManagerSupport::instance()->clientForFile(cursor.filePath());
- if (!client || !client->isFullyIndexed()) {
- CppEditor::CppModelManager::builtinRefactoringEngine()
- ->globalFollowSymbol(cursor, std::move(callback), snapshot, doc, symbolFinder,
- inNextSplit);
- return;
- }
- client->followSymbol(cursor.textDocument(), cursor.cursor(), cursor.editorWidget(),
- std::move(callback), true, inNextSplit);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangrefactoringengine.h b/src/plugins/clangcodemodel/clangrefactoringengine.h
deleted file mode 100644
index ea324f98995..00000000000
--- a/src/plugins/clangcodemodel/clangrefactoringengine.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <cppeditor/refactoringengineinterface.h>
-#include <cppeditor/cppcursorinfo.h>
-
-#include <QFutureWatcher>
-
-namespace ClangBackEnd {
-class RefactoringClientInterface;
-class RefactoringServerInterface;
-}
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class RefactoringEngine : public CppEditor::RefactoringEngineInterface
-{
-public:
- void startLocalRenaming(const CppEditor::CursorInEditor &data,
- const CppEditor::ProjectPart *projectPart,
- RenameCallback &&renameSymbolsCallback) override;
- void globalRename(const CppEditor::CursorInEditor &cursor, CppEditor::UsagesCallback &&callback,
- const QString &replacement) override;
- void findUsages(const CppEditor::CursorInEditor &cursor,
- CppEditor::UsagesCallback &&callback) const override;
- void globalFollowSymbol(const CppEditor::CursorInEditor &cursor,
- ::Utils::ProcessLinkCallback &&callback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &doc,
- CppEditor::SymbolFinder *symbolFinder,
- bool inNextSplit) const override;
-
-private:
- using FutureCursorWatcher = QFutureWatcher<CppEditor::CursorInfo>;
- std::unique_ptr<FutureCursorWatcher> m_watcher;
-};
-
-} // namespace Internal
-} // namespace ClangRefactoring
diff --git a/src/plugins/clangcodemodel/clangtextmark.cpp b/src/plugins/clangcodemodel/clangtextmark.cpp
index 20bef44e3bd..1de16f9914d 100644
--- a/src/plugins/clangcodemodel/clangtextmark.cpp
+++ b/src/plugins/clangcodemodel/clangtextmark.cpp
@@ -29,8 +29,6 @@
#include "clangdclient.h"
#include "clangdiagnostictooltipwidget.h"
#include "clangeditordocumentprocessor.h"
-#include "clangmodelmanagersupport.h"
-#include "clangprojectsettings.h"
#include "clangutils.h"
#include <coreplugin/icore.h>
@@ -39,23 +37,24 @@
#include <cppeditor/cpptoolsreuse.h>
#include <cppeditor/cppcodemodelsettings.h>
+#include <projectexplorer/task.h>
+
#include <utils/fadingindicator.h>
#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
#include <utils/theme/theme.h>
#include <utils/utilsicons.h>
#include <QAction>
-#include <QApplication>
-#include <QClipboard>
#include <QLayout>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QString>
using namespace CppEditor;
-using namespace ClangCodeModel::Internal;
using namespace LanguageClient;
using namespace LanguageServerProtocol;
+using namespace ProjectExplorer;
using namespace Utils;
namespace ClangCodeModel {
@@ -63,26 +62,7 @@ namespace Internal {
namespace {
-bool isWarningOrNote(ClangBackEnd::DiagnosticSeverity severity)
-{
- using ClangBackEnd::DiagnosticSeverity;
- switch (severity) {
- case DiagnosticSeverity::Ignored:
- case DiagnosticSeverity::Note:
- case DiagnosticSeverity::Warning: return true;
- case DiagnosticSeverity::Error:
- case DiagnosticSeverity::Fatal: return false;
- }
-
- Q_UNREACHABLE();
-}
-
-static Id categoryForSeverity(ClangBackEnd::DiagnosticSeverity severity)
-{
- return isWarningOrNote(severity) ? Constants::CLANG_WARNING : Constants::CLANG_ERROR;
-}
-
-ProjectExplorer::Project *projectForCurrentEditor()
+Project *projectForCurrentEditor()
{
const QString filePath = currentCppEditorDocumentFilePath();
if (filePath.isEmpty())
@@ -97,7 +77,7 @@ ProjectExplorer::Project *projectForCurrentEditor()
}
enum class DiagnosticType { Clang, Tidy, Clazy };
-DiagnosticType diagnosticType(const ClangBackEnd::DiagnosticContainer &diagnostic)
+DiagnosticType diagnosticType(const ClangDiagnostic &diagnostic)
{
if (!diagnostic.disableOption.isEmpty())
@@ -109,8 +89,7 @@ DiagnosticType diagnosticType(const ClangBackEnd::DiagnosticContainer &diagnosti
return DiagnosticType::Tidy;
}
-void disableDiagnosticInConfig(ClangDiagnosticConfig &config,
- const ClangBackEnd::DiagnosticContainer &diagnostic)
+void disableDiagnosticInConfig(ClangDiagnosticConfig &config, const ClangDiagnostic &diagnostic)
{
switch (diagnosticType(diagnostic)) {
case DiagnosticType::Clang:
@@ -131,34 +110,18 @@ void disableDiagnosticInConfig(ClangDiagnosticConfig &config,
}
}
-ClangDiagnosticConfig diagnosticConfig(const ClangProjectSettings &projectSettings,
- const CppCodeModelSettings &globalSettings)
+ClangDiagnosticConfig diagnosticConfig()
{
- ProjectExplorer::Project *project = projectForCurrentEditor();
+ Project *project = projectForCurrentEditor();
QTC_ASSERT(project, return {});
-
- // Get config id
- Id currentConfigId = projectSettings.warningConfigId();
- if (projectSettings.useGlobalConfig())
- currentConfigId = globalSettings.clangDiagnosticConfigId();
-
- // Get config
- ClangDiagnosticConfigsModel configsModel = CppEditor::diagnosticConfigsModel();
- QTC_ASSERT(configsModel.hasConfigWithId(currentConfigId), return {});
- return configsModel.configWithId(currentConfigId);
+ return warningsConfigForProject(project);
}
-bool isDiagnosticConfigChangable(ProjectExplorer::Project *project,
- const ClangBackEnd::DiagnosticContainer &diagnostic)
+bool isDiagnosticConfigChangable(Project *project, const ClangDiagnostic &diagnostic)
{
if (!project)
return false;
-
- ClangProjectSettings &projectSettings = ClangModelManagerSupport::instance()->projectSettings(
- project);
- const CppCodeModelSettings *globalSettings = codeModelSettings();
- const ClangDiagnosticConfig config = diagnosticConfig(projectSettings, *globalSettings);
-
+ const ClangDiagnosticConfig config = diagnosticConfig();
if (config.clangTidyMode() == ClangDiagnosticConfig::TidyMode::UseConfigFile
&& diagnosticType(diagnostic) == DiagnosticType::Tidy) {
return false;
@@ -166,18 +129,13 @@ bool isDiagnosticConfigChangable(ProjectExplorer::Project *project,
return true;
}
-void disableDiagnosticInCurrentProjectConfig(const ClangBackEnd::DiagnosticContainer &diagnostic)
+void disableDiagnosticInCurrentProjectConfig(const ClangDiagnostic &diagnostic)
{
- ProjectExplorer::Project *project = projectForCurrentEditor();
+ Project *project = projectForCurrentEditor();
QTC_ASSERT(project, return );
- // Get settings
- ClangProjectSettings &projectSettings = ClangModelManagerSupport::instance()->projectSettings(
- project);
- CppCodeModelSettings *globalSettings = codeModelSettings();
-
// Get config
- ClangDiagnosticConfig config = diagnosticConfig(projectSettings, *globalSettings);
+ ClangDiagnosticConfig config = diagnosticConfig();
ClangDiagnosticConfigsModel configsModel = CppEditor::diagnosticConfigsModel();
// Create copy if needed
@@ -193,14 +151,13 @@ void disableDiagnosticInCurrentProjectConfig(const ClangBackEnd::DiagnosticConta
configsModel.appendOrUpdate(config);
// Set global settings
- globalSettings->setClangCustomDiagnosticConfigs(configsModel.customConfigs());
- globalSettings->toSettings(Core::ICore::settings());
+ ClangdSettings::setCustomDiagnosticConfigs(configsModel.customConfigs());
// Set project settings
- if (projectSettings.useGlobalConfig())
- projectSettings.setUseGlobalConfig(false);
- projectSettings.setWarningConfigId(config.id());
- projectSettings.store();
+ ClangdProjectSettings projectSettings(project);
+ if (projectSettings.useGlobalSettings())
+ projectSettings.setUseGlobalSettings(false);
+ projectSettings.setDiagnosticConfigId(config.id());
// Notify the user about changed project specific settings
const QString text
@@ -211,114 +168,26 @@ void disableDiagnosticInCurrentProjectConfig(const ClangBackEnd::DiagnosticConta
FadingIndicator::SmallText);
}
-} // anonymous namespace
-
-ClangTextMark::ClangTextMark(const FilePath &fileName,
- const ClangBackEnd::DiagnosticContainer &diagnostic,
- const RemovedFromEditorHandler &removedHandler,
- bool fullVisualization, const ClangDiagnosticManager *diagMgr)
- : TextEditor::TextMark(fileName,
- int(diagnostic.location.line),
- categoryForSeverity(diagnostic.severity))
- , m_diagnostic(diagnostic)
- , m_removedFromEditorHandler(removedHandler)
- , m_diagMgr(diagMgr)
-{
- setSettingsPage(CppEditor::Constants::CPP_CODE_MODEL_SETTINGS_ID);
-
- const bool warning = isWarningOrNote(diagnostic.severity);
- setDefaultToolTip(warning ? QApplication::translate("Clang Code Model Marks", "Code Model Warning")
- : QApplication::translate("Clang Code Model Marks", "Code Model Error"));
- setPriority(warning ? TextEditor::TextMark::NormalPriority
- : TextEditor::TextMark::HighPriority);
- updateIcon();
- if (fullVisualization) {
- setLineAnnotation(diagnosticCategoryPrefixRemoved(diagnostic.text.toString()));
- setColor(warning ? Theme::CodeModel_Warning_TextMarkColor
- : Theme::CodeModel_Error_TextMarkColor);
- }
-
- // Copy to clipboard action
- QVector<QAction *> actions;
- QAction *action = new QAction();
- action->setIcon(QIcon::fromTheme("edit-copy", Icons::COPY.icon()));
- action->setToolTip(QApplication::translate("Clang Code Model Marks", "Copy to Clipboard"));
- QObject::connect(action, &QAction::triggered, [diagnostic]() {
- const QString text = ClangDiagnosticWidget::createText({diagnostic},
- ClangDiagnosticWidget::InfoBar);
- QApplication::clipboard()->setText(text, QClipboard::Clipboard);
- });
- actions << action;
-
- // Remove diagnostic warning action
- ProjectExplorer::Project *project = projectForCurrentEditor();
- if (project && isDiagnosticConfigChangable(project, diagnostic)) {
- action = new QAction();
- action->setIcon(Icons::BROKEN.icon());
- action->setToolTip(QApplication::translate("Clang Code Model Marks",
- "Disable Diagnostic in Current Project"));
- QObject::connect(action, &QAction::triggered, [diagnostic]() {
- disableDiagnosticInCurrentProjectConfig(diagnostic);
- });
- actions << action;
- }
-
- setActions(actions);
-}
-
-void ClangTextMark::updateIcon(bool valid)
-{
- using namespace Icons;
- if (isWarningOrNote(m_diagnostic.severity))
- setIcon(valid ? CODEMODEL_WARNING.icon() : CODEMODEL_DISABLED_WARNING.icon());
- else
- setIcon(valid ? CODEMODEL_ERROR.icon() : CODEMODEL_DISABLED_ERROR.icon());
-}
-
-bool ClangTextMark::addToolTipContent(QLayout *target) const
-{
- const auto canApplyFixIt = [diag = m_diagnostic, diagMgr = m_diagMgr, c = color()] {
- return c != Utils::Theme::Color::IconsDisabledColor
- && !diagMgr->diagnosticsInvalidated()
- && diagMgr->diagnosticsWithFixIts().contains(diag);
- };
- QWidget *widget = ClangDiagnosticWidget::createWidget(
- {m_diagnostic}, ClangDiagnosticWidget::ToolTip, canApplyFixIt, "libclang");
- target->addWidget(widget);
-
- return true;
-}
-
-void ClangTextMark::removedFromEditor()
-{
- QTC_ASSERT(m_removedFromEditorHandler, return);
- m_removedFromEditorHandler(this);
-}
-
-ClangBackEnd::DiagnosticSeverity convertSeverity(DiagnosticSeverity src)
+ClangDiagnostic::Severity convertSeverity(DiagnosticSeverity src)
{
if (src == DiagnosticSeverity::Error)
- return ClangBackEnd::DiagnosticSeverity::Error;
+ return ClangDiagnostic::Severity::Error;
if (src == DiagnosticSeverity::Warning)
- return ClangBackEnd::DiagnosticSeverity::Warning;
- return ClangBackEnd::DiagnosticSeverity::Note;
+ return ClangDiagnostic::Severity::Warning;
+ return ClangDiagnostic::Severity::Note;
}
-ClangBackEnd::SourceRangeContainer convertRange(const FilePath &filePath, const Range &src)
+ClangSourceRange convertRange(const FilePath &filePath, const Range &src)
{
- const ClangBackEnd::SourceLocationContainer start(filePath.toString(), src.start().line() + 1,
- src.start().character() + 1);
- const ClangBackEnd::SourceLocationContainer end(filePath.toString(), src.end().line() + 1,
- src.end().character() + 1);
- return ClangBackEnd::SourceRangeContainer(start, end);
+ const Utils::Link start(filePath, src.start().line() + 1, src.start().character());
+ const Utils::Link end(filePath, src.end().line() + 1, src.end().character());
+ return ClangSourceRange(start, end);
}
-ClangBackEnd::DiagnosticContainer convertDiagnostic(const ClangdDiagnostic &src,
- const FilePath &filePath)
+ClangDiagnostic convertDiagnostic(const ClangdDiagnostic &src, const FilePath &filePath)
{
- ClangBackEnd::DiagnosticContainer target;
- target.ranges.append(convertRange(filePath, src.range()));
- target.location = target.ranges.first().start;
+ ClangDiagnostic target;
+ target.location = convertRange(filePath, src.range()).start;
const QStringList messages = src.message().split("\n\n", Qt::SkipEmptyParts);
if (!messages.isEmpty())
target.text = messages.first();
@@ -331,7 +200,7 @@ ClangBackEnd::DiagnosticContainer convertDiagnostic(const ClangdDiagnostic &src,
"^(<command line>|([A-Za-z]:)?[^:]+\\.[^:]+)"
"(:(\\d+):(\\d+)|\\((\\d+)\\) *): +(fatal +)?(error|warning|note): (.*)$");
- ClangBackEnd::DiagnosticContainer aux;
+ ClangDiagnostic aux;
if (const QRegularExpressionMatch match = msgRegex.match(auxMessage); match.hasMatch()) {
bool ok = false;
int line = match.captured(4).toInt(&ok);
@@ -343,17 +212,17 @@ ClangBackEnd::DiagnosticContainer convertDiagnostic(const ClangdDiagnostic &src,
FilePath auxFilePath = FilePath::fromUserInput(match.captured(1));
if (auxFilePath.isRelativePath() && auxFilePath.fileName() == filePath.fileName())
auxFilePath = filePath;
- aux.location = {auxFilePath.toString(), line, column};
+ aux.location = {auxFilePath, line, column - 1};
aux.text = match.captured(9);
const QString type = match.captured(8);
if (type == "fatal")
- aux.severity = ClangBackEnd::DiagnosticSeverity::Fatal;
+ aux.severity = ClangDiagnostic::Severity::Fatal;
else if (type == "error")
- aux.severity = ClangBackEnd::DiagnosticSeverity::Error;
+ aux.severity = ClangDiagnostic::Severity::Error;
else if (type == "warning")
- aux.severity = ClangBackEnd::DiagnosticSeverity::Warning;
+ aux.severity = ClangDiagnostic::Severity::Warning;
else if (type == "note")
- aux.severity = ClangBackEnd::DiagnosticSeverity::Note;
+ aux.severity = ClangDiagnostic::Severity::Note;
} else {
aux.text = auxMessage;
}
@@ -373,26 +242,59 @@ ClangBackEnd::DiagnosticContainer convertDiagnostic(const ClangdDiagnostic &src,
const Utils::optional<WorkspaceEdit::Changes> changes = edit->changes();
if (!changes)
continue;
+ ClangDiagnostic fixItDiag;
+ fixItDiag.text = codeAction.title();
for (auto it = changes->cbegin(); it != changes->cend(); ++it) {
for (const TextEdit &textEdit : it.value()) {
- target.fixIts << ClangBackEnd::FixItContainer(textEdit.newText(),
+ fixItDiag.fixIts << ClangFixIt(textEdit.newText(),
convertRange(it.key().toFilePath(), textEdit.range()));
}
}
+ target.children << fixItDiag;
}
return target;
}
+Task createTask(const ClangDiagnostic &diagnostic)
+{
+ Task::TaskType taskType = Task::TaskType::Unknown;
+ QIcon icon;
+
+ switch (diagnostic.severity) {
+ case ClangDiagnostic::Severity::Fatal:
+ case ClangDiagnostic::Severity::Error:
+ taskType = Task::TaskType::Error;
+ icon = ::Utils::Icons::CODEMODEL_ERROR.icon();
+ break;
+ case ClangDiagnostic::Severity::Warning:
+ taskType = Task::TaskType::Warning;
+ icon = ::Utils::Icons::CODEMODEL_WARNING.icon();
+ break;
+ default:
+ break;
+ }
+
+ return Task(taskType,
+ diagnosticCategoryPrefixRemoved(diagnostic.text),
+ diagnostic.location.targetFilePath,
+ diagnostic.location.targetLine,
+ Constants::TASK_CATEGORY_DIAGNOSTICS,
+ icon,
+ Task::NoOptions);
+}
+
+} // anonymous namespace
+
ClangdTextMark::ClangdTextMark(const FilePath &filePath,
const Diagnostic &diagnostic,
bool isProjectFile,
- const Client *client)
+ ClangdClient *client)
: TextEditor::TextMark(filePath, int(diagnostic.range().start().line() + 1), client->id())
, m_lspDiagnostic(diagnostic)
, m_diagnostic(convertDiagnostic(ClangdDiagnostic(diagnostic), filePath))
, m_client(client)
{
- setSettingsPage(CppEditor::Constants::CPP_CODE_MODEL_SETTINGS_ID);
+ setSettingsPage(CppEditor::Constants::CPP_CLANGD_SETTINGS_ID);
const bool isError = diagnostic.severity()
&& *diagnostic.severity() == DiagnosticSeverity::Error;
@@ -404,34 +306,35 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
setLineAnnotation(diagnostic.message());
setColor(isError ? Theme::CodeModel_Error_TextMarkColor
: Theme::CodeModel_Warning_TextMarkColor);
- ClangDiagnosticManager::addTask(m_diagnostic);
+ client->addTask(createTask(m_diagnostic));
}
- // Copy to clipboard action
- QVector<QAction *> actions;
- QAction *action = new QAction();
- action->setIcon(QIcon::fromTheme("edit-copy", Icons::COPY.icon()));
- action->setToolTip(tr("Copy to Clipboard", "Clang Code Model Marks"));
- QObject::connect(action, &QAction::triggered, [diag = m_diagnostic]() {
- const QString text = ClangDiagnosticWidget::createText({diag},
- ClangDiagnosticWidget::InfoBar);
- QApplication::clipboard()->setText(text, QClipboard::Clipboard);
- });
- actions << action;
-
- // Remove diagnostic warning action
- ProjectExplorer::Project *project = projectForCurrentEditor();
- if (project && isDiagnosticConfigChangable(project, m_diagnostic)) {
- action = new QAction();
- action->setIcon(Icons::BROKEN.icon());
- action->setToolTip(tr("Disable Diagnostic in Current Project"));
- QObject::connect(action, &QAction::triggered, [diag = m_diagnostic]() {
- disableDiagnosticInCurrentProjectConfig(diag);
+ setActionsProvider([diag = m_diagnostic] {
+ // Copy to clipboard action
+ QList<QAction *> actions;
+ QAction *action = new QAction();
+ action->setIcon(QIcon::fromTheme("edit-copy", Icons::COPY.icon()));
+ action->setToolTip(tr("Copy to Clipboard", "Clang Code Model Marks"));
+ QObject::connect(action, &QAction::triggered, [diag] {
+ const QString text = ClangDiagnosticWidget::createText({diag},
+ ClangDiagnosticWidget::InfoBar);
+ setClipboardAndSelection(text);
});
actions << action;
- }
- setActions(actions);
+ // Remove diagnostic warning action
+ Project *project = projectForCurrentEditor();
+ if (project && isDiagnosticConfigChangable(project, diag)) {
+ action = new QAction();
+ action->setIcon(Icons::BROKEN.icon());
+ action->setToolTip(tr("Disable Diagnostic in Current Project"));
+ QObject::connect(action, &QAction::triggered, [diag] {
+ disableDiagnosticInCurrentProjectConfig(diag);
+ });
+ actions << action;
+ }
+ return actions;
+ });
}
bool ClangdTextMark::addToolTipContent(QLayout *target) const
diff --git a/src/plugins/clangcodemodel/clangtextmark.h b/src/plugins/clangcodemodel/clangtextmark.h
index 2c08e875900..39f30bc36cf 100644
--- a/src/plugins/clangcodemodel/clangtextmark.h
+++ b/src/plugins/clangcodemodel/clangtextmark.h
@@ -25,8 +25,7 @@
#pragma once
-#include <clangsupport_global.h>
-#include <clangsupport/diagnosticcontainer.h>
+#include "clangutils.h"
#include <languageserverprotocol/lsptypes.h>
@@ -40,31 +39,8 @@ namespace LanguageClient { class Client; }
namespace ClangCodeModel {
namespace Internal {
-class ClangDiagnosticManager;
-class ClangTextMark : public TextEditor::TextMark
-{
-public:
- using RemovedFromEditorHandler = std::function<void(ClangTextMark *)>;
-
- ClangTextMark(const ::Utils::FilePath &fileName,
- const ClangBackEnd::DiagnosticContainer &diagnostic,
- const RemovedFromEditorHandler &removedHandler,
- bool fullVisualization,
- const ClangDiagnosticManager *diagMgr);
-
- ClangBackEnd::DiagnosticContainer diagnostic() const { return m_diagnostic; }
- void updateIcon(bool valid = true);
-
-private:
- bool addToolTipContent(QLayout *target) const override;
- void removedFromEditor() override;
-
-private:
- ClangBackEnd::DiagnosticContainer m_diagnostic;
- RemovedFromEditorHandler m_removedFromEditorHandler;
- const ClangDiagnosticManager * const m_diagMgr;
-};
+class ClangdClient;
class ClangdTextMark : public TextEditor::TextMark
{
@@ -73,13 +49,13 @@ public:
ClangdTextMark(const ::Utils::FilePath &filePath,
const LanguageServerProtocol::Diagnostic &diagnostic,
bool isProjectFile,
- const LanguageClient::Client *client);
+ ClangdClient *client);
private:
bool addToolTipContent(QLayout *target) const override;
const LanguageServerProtocol::Diagnostic m_lspDiagnostic;
- const ClangBackEnd::DiagnosticContainer m_diagnostic;
+ const ClangDiagnostic m_diagnostic;
const QPointer<const LanguageClient::Client> m_client;
};
diff --git a/src/plugins/clangcodemodel/clanguiheaderondiskmanager.cpp b/src/plugins/clangcodemodel/clanguiheaderondiskmanager.cpp
deleted file mode 100644
index 696ced1c6f7..00000000000
--- a/src/plugins/clangcodemodel/clanguiheaderondiskmanager.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clanguiheaderondiskmanager.h"
-
-#include <QFile>
-#include <QFileInfo>
-
-#include <utils/fileutils.h>
-#include <utils/qtcassert.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-UiHeaderOnDiskManager::UiHeaderOnDiskManager() : m_temporaryDir("clang-uiheader-XXXXXX")
-{
- QTC_CHECK(m_temporaryDir.isValid());
-}
-
-QString UiHeaderOnDiskManager::write(const QString &filePath, const QByteArray &content)
-{
- const QString mappedPath = mapPath(filePath);
- QFile file(mappedPath);
- const bool fileCreated = file.open(QFile::WriteOnly);
- const qint64 bytesWritten = file.write(content);
- QTC_CHECK(fileCreated && bytesWritten != -1);
-
- return mappedPath;
-}
-
-QString UiHeaderOnDiskManager::remove(const QString &filePath)
-{
- const QString mappedPath = mapPath(filePath);
- if (QFileInfo::exists(mappedPath)) {
- const bool fileRemoved = QFile::remove(mappedPath);
- QTC_CHECK(fileRemoved);
- }
-
- return mappedPath;
-}
-
-QString UiHeaderOnDiskManager::directoryPath() const
-{
- return m_temporaryDir.path().path();
-}
-
-QString UiHeaderOnDiskManager::mapPath(const QString &filePath) const
-{
- return directoryPath() + '/' + QFileInfo(filePath).fileName();
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanguiheaderondiskmanager.h b/src/plugins/clangcodemodel/clanguiheaderondiskmanager.h
deleted file mode 100644
index a244fdb1781..00000000000
--- a/src/plugins/clangcodemodel/clanguiheaderondiskmanager.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/temporarydirectory.h>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-// TODO: Remove once libclang supports unsaved files that do not exist.
-class UiHeaderOnDiskManager
-{
-public:
- UiHeaderOnDiskManager();
-
- QString write(const QString &filePath, const QByteArray &content);
- QString remove(const QString &filePath);
-
- QString mapPath(const QString &filePath) const;
- QString directoryPath() const;
-
-private:
- ::Utils::TemporaryDirectory m_temporaryDir;
-};
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp
index 466a062644b..b98ad7e91be 100644
--- a/src/plugins/clangcodemodel/clangutils.cpp
+++ b/src/plugins/clangcodemodel/clangutils.cpp
@@ -25,15 +25,10 @@
#include "clangutils.h"
-#include "clangeditordocumentprocessor.h"
-#include "clangmodelmanagersupport.h"
-#include "clangprojectsettings.h"
-
-#include <clangsupport/tokeninfocontainer.h>
-
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <cppeditor/baseeditordocumentparser.h>
+#include <cppeditor/clangdiagnosticconfigsmodel.h>
#include <cppeditor/compileroptionsbuilder.h>
#include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/cppmodelmanager.h>
@@ -67,48 +62,6 @@ using namespace Utils;
namespace ClangCodeModel {
namespace Internal {
-class LibClangOptionsBuilder final : public CompilerOptionsBuilder
-{
-public:
- LibClangOptionsBuilder(const ProjectPart &projectPart,
- UseBuildSystemWarnings useBuildSystemWarnings)
- : CompilerOptionsBuilder(projectPart,
- UseSystemHeader::No,
- UseTweakedHeaderPaths::Yes,
- UseLanguageDefines::No,
- useBuildSystemWarnings,
- QString(CLANG_VERSION),
- FilePath(CLANG_INCLUDE_DIR))
- {
- }
-
- void addProjectMacros() final
- {
- addMacros({ProjectExplorer::Macro("Q_CREATOR_RUN", "1")});
- CompilerOptionsBuilder::addProjectMacros();
- }
-
- void addExtraOptions() final
- {
- addDummyUiHeaderOnDiskIncludePath();
- add("-fmessage-length=0", /*gccOnlyOption=*/true);
- add("-fdiagnostics-show-note-include-stack", /*gccOnlyOption=*/true);
- add("-fretain-comments-from-system-headers", /*gccOnlyOption=*/true);
- add("-fmacro-backtrace-limit=0");
- add("-ferror-limit=1000");
- }
-
-private:
- void addDummyUiHeaderOnDiskIncludePath()
- {
- const QString path = ClangModelManagerSupport::instance()->dummyUiHeaderOnDiskDirPath();
- if (!path.isEmpty()) {
- prepend(QDir::toNativeSeparators(path));
- prepend("-I");
- }
- }
-};
-
ProjectPart::ConstPtr projectPartForFile(const QString &filePath)
{
if (const auto parser = CppEditor::BaseEditorDocumentParser::get(filePath))
@@ -116,163 +69,6 @@ ProjectPart::ConstPtr projectPartForFile(const QString &filePath)
return ProjectPart::ConstPtr();
}
-ProjectPart::ConstPtr projectPartForFileBasedOnProcessor(const QString &filePath)
-{
- if (const auto processor = ClangEditorDocumentProcessor::get(filePath))
- return processor->projectPart();
- return ProjectPart::ConstPtr();
-}
-
-bool isProjectPartLoaded(const ProjectPart::ConstPtr projectPart)
-{
- if (projectPart)
- return !CppModelManager::instance()->projectPartForId(projectPart->id()).isNull();
- return false;
-}
-
-QString projectPartIdForFile(const QString &filePath)
-{
- const ProjectPart::ConstPtr projectPart = projectPartForFile(filePath);
-
- if (isProjectPartLoaded(projectPart))
- return projectPart->id(); // OK, Project Part is still loaded
- return QString();
-}
-
-CppEditorDocumentHandle *cppDocument(const QString &filePath)
-{
- return CppEditor::CppModelManager::instance()->cppEditorDocument(filePath);
-}
-
-void setLastSentDocumentRevision(const QString &filePath, uint revision)
-{
- if (CppEditorDocumentHandle *document = cppDocument(filePath))
- document->sendTracker().setLastSentRevision(int(revision));
-}
-
-int clangColumn(const QTextBlock &line, int cppEditorColumn)
-{
- // (1) cppEditorColumn is the actual column shown by CppEditor.
- // (2) The return value is the column in Clang which is the utf8 byte offset from the beginning
- // of the line.
- // Here we convert column from (1) to (2).
- // '- 1' and '+ 1' are because of 1-based columns
- return line.text().left(cppEditorColumn - 1).toUtf8().size() + 1;
-}
-
-int cppEditorColumn(const QTextBlock &line, int clangColumn)
-{
- // (1) clangColumn is the column in Clang which is the utf8 byte offset from the beginning
- // of the line.
- // (2) The return value is the actual column shown by CppEditor.
- // Here we convert column from (1) to (2).
- // '- 1' and '+ 1' are because of 1-based columns
- return QString::fromUtf8(line.text().toUtf8().left(clangColumn - 1)).size() + 1;
-}
-
-CodeModelIcon::Type iconTypeForToken(const ClangBackEnd::TokenInfoContainer &token)
-{
- const ClangBackEnd::ExtraInfo &extraInfo = token.extraInfo;
- if (extraInfo.signal)
- return CodeModelIcon::Signal;
-
- ClangBackEnd::AccessSpecifier access = extraInfo.accessSpecifier;
- if (extraInfo.slot) {
- switch (access) {
- case ClangBackEnd::AccessSpecifier::Public:
- case ClangBackEnd::AccessSpecifier::Invalid:
- return CodeModelIcon::SlotPublic;
- case ClangBackEnd::AccessSpecifier::Protected:
- return CodeModelIcon::SlotProtected;
- case ClangBackEnd::AccessSpecifier::Private:
- return CodeModelIcon::SlotPrivate;
- }
- }
-
- ClangBackEnd::HighlightingType mainType = token.types.mainHighlightingType;
-
- if (mainType == ClangBackEnd::HighlightingType::QtProperty)
- return CodeModelIcon::Property;
-
- if (mainType == ClangBackEnd::HighlightingType::PreprocessorExpansion
- || mainType == ClangBackEnd::HighlightingType::PreprocessorDefinition) {
- return CodeModelIcon::Macro;
- }
-
- if (mainType == ClangBackEnd::HighlightingType::Enumeration)
- return CodeModelIcon::Enumerator;
-
- if (mainType == ClangBackEnd::HighlightingType::Type
- || mainType == ClangBackEnd::HighlightingType::Keyword) {
- const ClangBackEnd::MixinHighlightingTypes &types = token.types.mixinHighlightingTypes;
- if (types.contains(ClangBackEnd::HighlightingType::Enum))
- return CodeModelIcon::Enum;
- if (types.contains(ClangBackEnd::HighlightingType::Struct))
- return CodeModelIcon::Struct;
- if (types.contains(ClangBackEnd::HighlightingType::Namespace))
- return CodeModelIcon::Namespace;
- if (types.contains(ClangBackEnd::HighlightingType::Class))
- return CodeModelIcon::Class;
- if (mainType == ClangBackEnd::HighlightingType::Keyword)
- return CodeModelIcon::Keyword;
- return CodeModelIcon::Class;
- }
-
- ClangBackEnd::StorageClass storageClass = extraInfo.storageClass;
- if (mainType == ClangBackEnd::HighlightingType::VirtualFunction
- || mainType == ClangBackEnd::HighlightingType::Function
- || token.types.mixinHighlightingTypes.contains(
- ClangBackEnd::HighlightingType::Operator)) {
- if (storageClass != ClangBackEnd::StorageClass::Static) {
- switch (access) {
- case ClangBackEnd::AccessSpecifier::Public:
- case ClangBackEnd::AccessSpecifier::Invalid:
- return CodeModelIcon::FuncPublic;
- case ClangBackEnd::AccessSpecifier::Protected:
- return CodeModelIcon::FuncProtected;
- case ClangBackEnd::AccessSpecifier::Private:
- return CodeModelIcon::FuncPrivate;
- }
- } else {
- switch (access) {
- case ClangBackEnd::AccessSpecifier::Public:
- case ClangBackEnd::AccessSpecifier::Invalid:
- return CodeModelIcon::FuncPublicStatic;
- case ClangBackEnd::AccessSpecifier::Protected:
- return CodeModelIcon::FuncProtectedStatic;
- case ClangBackEnd::AccessSpecifier::Private:
- return CodeModelIcon::FuncPrivateStatic;
- }
- }
- }
- if (mainType == ClangBackEnd::HighlightingType::GlobalVariable
- || mainType == ClangBackEnd::HighlightingType::Field) {
- if (storageClass != ClangBackEnd::StorageClass::Static) {
- switch (access) {
- case ClangBackEnd::AccessSpecifier::Public:
- case ClangBackEnd::AccessSpecifier::Invalid:
- return CodeModelIcon::VarPublic;
- case ClangBackEnd::AccessSpecifier::Protected:
- return CodeModelIcon::VarProtected;
- case ClangBackEnd::AccessSpecifier::Private:
- return CodeModelIcon::VarPrivate;
- }
- } else {
- switch (access) {
- case ClangBackEnd::AccessSpecifier::Public:
- case ClangBackEnd::AccessSpecifier::Invalid:
- return CodeModelIcon::VarPublicStatic;
- case ClangBackEnd::AccessSpecifier::Protected:
- return CodeModelIcon::VarProtectedStatic;
- case ClangBackEnd::AccessSpecifier::Private:
- return CodeModelIcon::VarPrivateStatic;
- }
- }
- }
-
- return CodeModelIcon::Unknown;
-}
-
QString diagnosticCategoryPrefixRemoved(const QString &text)
{
QString theText = text;
@@ -280,15 +76,14 @@ QString diagnosticCategoryPrefixRemoved(const QString &text)
// Prefixes are taken from $LLVM_SOURCE_DIR/tools/clang/lib/Frontend/TextDiagnostic.cpp,
// function TextDiagnostic::printDiagnosticLevel (llvm-3.6.2).
static const QStringList categoryPrefixes = {
- QStringLiteral("note"),
- QStringLiteral("remark"),
- QStringLiteral("warning"),
- QStringLiteral("error"),
- QStringLiteral("fatal error")
+ QStringLiteral("note: "),
+ QStringLiteral("remark: "),
+ QStringLiteral("warning: "),
+ QStringLiteral("error: "),
+ QStringLiteral("fatal error: ")
};
- for (const QString &prefix : categoryPrefixes) {
- const QString fullPrefix = prefix + QStringLiteral(": ");
+ for (const QString &fullPrefix : categoryPrefixes) {
if (theText.startsWith(fullPrefix)) {
theText.remove(0, fullPrefix.length());
return theText;
@@ -333,8 +128,9 @@ static QJsonObject createFileObject(const FilePath &buildDir,
const ProjectPart &projectPart,
const ProjectFile &projFile,
CompilationDbPurpose purpose,
- const ClangDiagnosticConfig &warningsConfig,
- const QStringList &projectOptions)
+ const QJsonArray &projectPartOptions,
+ UsePrecompiledHeaders usePch,
+ bool clStyle)
{
QJsonObject fileObject;
fileObject["file"] = projFile.path;
@@ -359,9 +155,7 @@ static QJsonObject createFileObject(const FilePath &buildDir,
args.append(langOptionPart);
}
} else {
- // TODO: Do we really need to re-calculate the project part options per source file?
- args = QJsonArray::fromStringList(createClangOptions(projectPart, projFile.path,
- warningsConfig, projectOptions));
+ args = clangOptionsForFile(projFile, projectPart, projectPartOptions, usePch, clStyle);
args.prepend("clang"); // TODO: clang-cl for MSVC targets? Does it matter at all what we put here?
}
@@ -375,7 +169,8 @@ GenerateCompilationDbResult generateCompilationDB(const CppEditor::ProjectInfo::
const Utils::FilePath &baseDir,
CompilationDbPurpose purpose,
const ClangDiagnosticConfig &warningsConfig,
- const QStringList &projectOptions)
+ const QStringList &projectOptions,
+ const FilePath &clangIncludeDir)
{
QTC_ASSERT(!baseDir.isEmpty(), return GenerateCompilationDbResult(QString(),
QCoreApplication::translate("ClangUtils", "Could not retrieve build directory.")));
@@ -391,13 +186,22 @@ GenerateCompilationDbResult generateCompilationDB(const CppEditor::ProjectInfo::
}
compileCommandsFile.write("[");
+ const UsePrecompiledHeaders usePch = getPchUsage();
+ const QJsonArray jsonProjectOptions = QJsonArray::fromStringList(projectOptions);
for (ProjectPart::ConstPtr projectPart : projectInfo->projectParts()) {
QStringList args;
- if (purpose == CompilationDbPurpose::Project)
+ const CompilerOptionsBuilder optionsBuilder = clangOptionsBuilder(
+ *projectPart, warningsConfig, clangIncludeDir);
+ QJsonArray ppOptions;
+ if (purpose == CompilationDbPurpose::Project) {
args = projectPartArguments(*projectPart);
+ } else {
+ ppOptions = fullProjectPartOptions(projectPartOptions(optionsBuilder), jsonProjectOptions);
+ }
for (const ProjectFile &projFile : projectPart->files) {
const QJsonObject json = createFileObject(baseDir, args, *projectPart, projFile,
- purpose, warningsConfig, projectOptions);
+ purpose, ppOptions, usePch,
+ optionsBuilder.isClStyle());
if (compileCommandsFile.size() > 1)
compileCommandsFile.write(",");
compileCommandsFile.write('\n' + QJsonDocument(json).toJson().trimmed());
@@ -470,151 +274,38 @@ QString DiagnosticTextInfo::clazyCheckName(const QString &option)
}
-namespace {
-static ClangProjectSettings &getProjectSettings(ProjectExplorer::Project *project)
-{
- QTC_CHECK(project);
- return ClangModelManagerSupport::instance()->projectSettings(project);
-}
-
-// TODO: Can we marry this with CompilerOptionsBuilder?
-class FileOptionsBuilder
+QJsonArray clangOptionsForFile(const ProjectFile &file, const ProjectPart &projectPart,
+ const QJsonArray &generalOptions, UsePrecompiledHeaders usePch,
+ bool clStyle)
{
-public:
- FileOptionsBuilder(const QString &filePath, const CppEditor::ProjectPart &projectPart,
- const ClangDiagnosticConfig &warningsConfig,
- const QStringList &projectOptions)
- : m_filePath(filePath)
- , m_projectPart(projectPart)
- , m_warningsConfig(warningsConfig)
- , m_builder(projectPart)
- {
- // Determine the driver mode from toolchain and flags.
- m_builder.evaluateCompilerFlags();
- m_isClMode = m_builder.isClStyle();
-
- addLanguageOptions();
- addGlobalDiagnosticOptions(); // Before addDiagnosticOptions() so users still can overwrite.
- addDiagnosticOptions();
- m_options.append(projectOptions);
- addPrecompiledHeaderOptions();
- }
-
- const QStringList &options() const { return m_options; }
- CppEditor::UseBuildSystemWarnings useBuildSystemWarnings() const
- {
- return m_useBuildSystemWarnings;
- }
-
-private:
- void addLanguageOptions()
- {
- // Determine file kind with respect to ambiguous headers.
- CppEditor::ProjectFile::Kind fileKind = CppEditor::ProjectFile::Unclassified;
- if (!m_filePath.isEmpty())
- fileKind = CppEditor::ProjectFile::classify(m_filePath);
- if (fileKind == CppEditor::ProjectFile::AmbiguousHeader) {
- fileKind = m_projectPart.languageVersion <= ::Utils::LanguageVersion::LatestC
- ? CppEditor::ProjectFile::CHeader
- : CppEditor::ProjectFile::CXXHeader;
- }
-
- m_builder.reset();
- m_builder.updateFileLanguage(fileKind);
-
- m_options.append(m_builder.options());
- }
-
- void addDiagnosticOptions()
- {
- addDiagnosticOptionsForConfig(m_warningsConfig);
- }
-
- void addDiagnosticOptionsForConfig(const CppEditor::ClangDiagnosticConfig &diagnosticConfig)
- {
- m_useBuildSystemWarnings = diagnosticConfig.useBuildSystemWarnings()
- ? CppEditor::UseBuildSystemWarnings::Yes
- : CppEditor::UseBuildSystemWarnings::No;
-
- const QStringList options = m_isClMode
- ? CppEditor::clangArgsForCl(diagnosticConfig.clangOptions())
- : diagnosticConfig.clangOptions();
- m_options.append(options);
- }
-
- void addGlobalDiagnosticOptions()
- {
- m_options += CppEditor::ClangDiagnosticConfigsModel::globalDiagnosticOptions();
+ CompilerOptionsBuilder optionsBuilder(projectPart);
+ optionsBuilder.setClStyle(clStyle);
+ ProjectFile::Kind fileKind = file.kind;
+ if (fileKind == ProjectFile::AmbiguousHeader) {
+ fileKind = projectPart.languageVersion <= LanguageVersion::LatestC
+ ? ProjectFile::CHeader : ProjectFile::CXXHeader;
}
-
- void addPrecompiledHeaderOptions()
- {
- using namespace CppEditor;
-
- if (getPchUsage() == UsePrecompiledHeaders::No)
- return;
-
- if (m_projectPart.precompiledHeaders.contains(m_filePath))
- return;
-
- m_builder.reset();
- m_builder.addPrecompiledHeaderOptions(UsePrecompiledHeaders::Yes);
-
- m_options.append(m_builder.options());
+ if (usePch == UsePrecompiledHeaders::Yes
+ && projectPart.precompiledHeaders.contains(file.path)) {
+ usePch = UsePrecompiledHeaders::No;
}
-
-private:
- const QString &m_filePath;
- const CppEditor::ProjectPart &m_projectPart;
- const ClangDiagnosticConfig &m_warningsConfig;
-
- CppEditor::UseBuildSystemWarnings m_useBuildSystemWarnings = CppEditor::UseBuildSystemWarnings::No;
- CppEditor::CompilerOptionsBuilder m_builder;
- bool m_isClMode = false;
- QStringList m_options;
-};
-} // namespace
-
-QStringList createClangOptions(const ProjectPart &projectPart, const QString &filePath,
- const ClangDiagnosticConfig &warningsConfig,
- const QStringList &projectOptions)
-{
- const FileOptionsBuilder fileOptions(filePath, projectPart, warningsConfig, projectOptions);
- LibClangOptionsBuilder optionsBuilder(projectPart, fileOptions.useBuildSystemWarnings());
- const QStringList projectPartOptions = optionsBuilder.build(CppEditor::ProjectFile::Unsupported,
- UsePrecompiledHeaders::No);
-
- // FIXME: Sanitize FileOptionsBuilder instead.
- QStringList fileArgs = fileOptions.options();
- if (projectPartOptions.contains(QLatin1String("-TP")))
- fileArgs.removeAll(QLatin1String("/TP"));
- if (projectPartOptions.contains(QLatin1String("-TC")))
- fileArgs.removeAll(QLatin1String("/TC"));
-
- return projectPartOptions + fileArgs;
+ optionsBuilder.updateFileLanguage(file.kind);
+ optionsBuilder.addPrecompiledHeaderOptions(usePch);
+ const QJsonArray specificOptions = QJsonArray::fromStringList(optionsBuilder.options());
+ QJsonArray fullOptions = generalOptions;
+ for (const QJsonValue &opt : specificOptions)
+ fullOptions << opt;
+ return fullOptions;
}
ClangDiagnosticConfig warningsConfigForProject(Project *project)
{
- if (project) {
- ClangProjectSettings &projectSettings = ClangModelManagerSupport::instance()
- ->projectSettings(project);
- if (!projectSettings.useGlobalConfig()) {
- const Utils::Id warningConfigId = projectSettings.warningConfigId();
- const CppEditor::ClangDiagnosticConfigsModel configsModel
- = CppEditor::diagnosticConfigsModel();
- if (configsModel.hasConfigWithId(warningConfigId))
- return configsModel.configWithId(warningConfigId);
- }
- }
- return CppEditor::codeModelSettings()->clangDiagnosticConfig();
+ return ClangdSettings(ClangdProjectSettings(project).settings()).diagnosticConfig();
}
-const QStringList optionsForProject(ProjectExplorer::Project *project)
+const QStringList globalClangOptions()
{
- if (project)
- return getProjectSettings(project).commandLineOptions();
- return ClangProjectSettings::globalCommandLineOptions();
+ return ClangDiagnosticConfigsModel::globalDiagnosticOptions();
}
// 7.3.3: using typename(opt) nested-name-specifier unqualified-id ;
@@ -653,5 +344,60 @@ QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface
return manipulator.textAt(endPosition, startPosition - endPosition);
}
+CompilerOptionsBuilder clangOptionsBuilder(const ProjectPart &projectPart,
+ const ClangDiagnosticConfig &warningsConfig,
+ const Utils::FilePath &clangIncludeDir)
+{
+ const auto useBuildSystemWarnings = warningsConfig.useBuildSystemWarnings()
+ ? UseBuildSystemWarnings::Yes
+ : UseBuildSystemWarnings::No;
+ CompilerOptionsBuilder optionsBuilder(projectPart, UseSystemHeader::No,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No,
+ useBuildSystemWarnings, clangIncludeDir);
+ optionsBuilder.provideAdditionalMacros({ProjectExplorer::Macro("Q_CREATOR_RUN", "1")});
+ optionsBuilder.build(ProjectFile::Unclassified, UsePrecompiledHeaders::No);
+ optionsBuilder.add("-fmessage-length=0", /*gccOnlyOption=*/true);
+ optionsBuilder.add("-fdiagnostics-show-note-include-stack", /*gccOnlyOption=*/true);
+ optionsBuilder.add("-fretain-comments-from-system-headers", /*gccOnlyOption=*/true);
+ optionsBuilder.add("-fmacro-backtrace-limit=0");
+ optionsBuilder.add("-ferror-limit=1000");
+
+ if (useBuildSystemWarnings == UseBuildSystemWarnings::No) {
+ for (const QString &opt : warningsConfig.clangOptions())
+ optionsBuilder.add(opt, true);
+ }
+
+ return optionsBuilder;
+}
+
+QJsonArray projectPartOptions(const CppEditor::CompilerOptionsBuilder &optionsBuilder)
+{
+ const QStringList optionsList = optionsBuilder.options();
+ QJsonArray optionsArray;
+ for (const QString &opt : optionsList) {
+ // These will be added later by the file-specific code, and they trigger warnings
+ // if they appear twice; see QTCREATORBUG-26664.
+ if (opt != "-TP" && opt != "-TC")
+ optionsArray << opt;
+ }
+ return optionsArray;
+}
+
+QJsonArray fullProjectPartOptions(const CppEditor::CompilerOptionsBuilder &optionsBuilder,
+ const QStringList &projectOptions)
+{
+ return fullProjectPartOptions(projectPartOptions(optionsBuilder),
+ QJsonArray::fromStringList(projectOptions));
+}
+
+QJsonArray fullProjectPartOptions(const QJsonArray &projectPartOptions,
+ const QJsonArray &projectOptions)
+{
+ QJsonArray fullProjectPartOptions = projectPartOptions;
+ for (const QJsonValue &opt : projectOptions)
+ fullProjectPartOptions.prepend(opt);
+ return fullProjectPartOptions;
+}
+
} // namespace Internal
} // namespace Clang
diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h
index c3a496f7797..bb90b84bfc8 100644
--- a/src/plugins/clangcodemodel/clangutils.h
+++ b/src/plugins/clangcodemodel/clangutils.h
@@ -30,6 +30,8 @@
#include <cppeditor/projectinfo.h>
#include <cppeditor/compileroptionsbuilder.h>
+#include <utils/link.h>
+
#include <QPair>
#include <QTextCursor>
@@ -44,36 +46,34 @@ class CppEditorDocumentHandle;
namespace TextEditor { class TextDocumentManipulatorInterface; }
-namespace ClangBackEnd { class TokenInfoContainer; }
-
namespace ProjectExplorer { class Project; }
namespace ClangCodeModel {
namespace Internal {
-CppEditor::CppEditorDocumentHandle *cppDocument(const QString &filePath);
-void setLastSentDocumentRevision(const QString &filePath, uint revision);
-
CppEditor::ClangDiagnosticConfig warningsConfigForProject(ProjectExplorer::Project *project);
-const QStringList optionsForProject(ProjectExplorer::Project *project);
-
-QStringList createClangOptions(const CppEditor::ProjectPart &projectPart, const QString &filePath,
- const CppEditor::ClangDiagnosticConfig &warningsConfig,
- const QStringList &projectOptions);
+const QStringList globalClangOptions();
+
+CppEditor::CompilerOptionsBuilder clangOptionsBuilder(
+ const CppEditor::ProjectPart &projectPart,
+ const CppEditor::ClangDiagnosticConfig &warningsConfig,
+ const Utils::FilePath &clangIncludeDir);
+QJsonArray projectPartOptions(const CppEditor::CompilerOptionsBuilder &optionsBuilder);
+QJsonArray fullProjectPartOptions(const CppEditor::CompilerOptionsBuilder &optionsBuilder,
+ const QStringList &projectOptions);
+QJsonArray fullProjectPartOptions(const QJsonArray &projectPartOptions,
+ const QJsonArray &projectOptions);
+QJsonArray clangOptionsForFile(const CppEditor::ProjectFile &file,
+ const CppEditor::ProjectPart &projectPart,
+ const QJsonArray &generalOptions,
+ CppEditor::UsePrecompiledHeaders usePch, bool clStyle);
CppEditor::ProjectPart::ConstPtr projectPartForFile(const QString &filePath);
-CppEditor::ProjectPart::ConstPtr projectPartForFileBasedOnProcessor(const QString &filePath);
-bool isProjectPartLoaded(const CppEditor::ProjectPart::ConstPtr projectPart);
-QString projectPartIdForFile(const QString &filePath);
-int clangColumn(const QTextBlock &line, int cppEditorColumn);
-int cppEditorColumn(const QTextBlock &line, int clangColumn);
QString currentCppEditorDocumentFilePath();
QString diagnosticCategoryPrefixRemoved(const QString &text);
-Utils::CodeModelIcon::Type iconTypeForToken(const ClangBackEnd::TokenInfoContainer &token);
-
class GenerateCompilationDbResult
{
public:
@@ -89,7 +89,8 @@ public:
enum class CompilationDbPurpose { Project, CodeModel };
GenerateCompilationDbResult generateCompilationDB(const CppEditor::ProjectInfo::ConstPtr projectInfo,
const Utils::FilePath &baseDir, CompilationDbPurpose purpose,
- const CppEditor::ClangDiagnosticConfig &warningsConfig, const QStringList &projectOptions);
+ const CppEditor::ClangDiagnosticConfig &warningsConfig, const QStringList &projectOptions,
+ const Utils::FilePath &clangIncludeDir);
class DiagnosticTextInfo
{
@@ -159,5 +160,73 @@ QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface
bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &manipulator,
int basePosition);
+class ClangSourceRange
+{
+public:
+ ClangSourceRange(const Utils::Link &start, const Utils::Link &end) : start(start), end(end) {}
+
+ bool contains(int line, int column) const
+ {
+ if (line < start.targetLine || line > end.targetLine)
+ return false;
+ if (line == start.targetLine && column < start.targetLine)
+ return false;
+ if (line == end.targetLine && column > end.targetColumn)
+ return false;
+ return true;
+ }
+
+ bool contains(const Utils::Link &sourceLocation) const
+ {
+ return contains(sourceLocation.targetLine, sourceLocation.targetColumn);
+ }
+
+ Utils::Link start;
+ Utils::Link end;
+};
+
+inline bool operator==(const ClangSourceRange &first, const ClangSourceRange &second)
+{
+ return first.start == second.start && first.end == second.end;
+}
+
+class ClangFixIt
+{
+public:
+ ClangFixIt(const QString &text, const ClangSourceRange &range) : range(range), text(text) {}
+
+ ClangSourceRange range;
+ QString text;
+};
+
+inline bool operator==(const ClangFixIt &first, const ClangFixIt &second)
+{
+ return first.text == second.text && first.range == second.range;
+}
+
+class ClangDiagnostic
+{
+public:
+ enum class Severity { Ignored, Note, Warning, Error, Fatal };
+
+ Utils::Link location;
+ QString text;
+ QString category;
+ QString enableOption;
+ QString disableOption;
+ QList<ClangDiagnostic> children;
+ QList<ClangFixIt> fixIts;
+ Severity severity = Severity::Ignored;
+};
+
+inline bool operator==(const ClangDiagnostic &first, const ClangDiagnostic &second)
+{
+ return first.text == second.text && first.location == second.location;
+}
+inline bool operator!=(const ClangDiagnostic &first, const ClangDiagnostic &second)
+{
+ return !(first == second);
+}
+
} // namespace Internal
} // namespace Clang
diff --git a/src/plugins/clangcodemodel/tasktimers.cpp b/src/plugins/clangcodemodel/tasktimers.cpp
new file mode 100644
index 00000000000..e9e82d7d149
--- /dev/null
+++ b/src/plugins/clangcodemodel/tasktimers.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "tasktimers.h"
+
+#include <utils/qtcassert.h>
+
+#include <QDateTime>
+
+namespace ClangCodeModel::Internal {
+
+Q_LOGGING_CATEGORY(clangdLogTiming, "qtc.clangcodemodel.clangd.timing", QtWarningMsg);
+
+void ClangCodeModel::Internal::TaskTimer::stopTask()
+{
+ // This can happen due to the RAII mechanism employed with SubtaskTimer.
+ // The subtask timers will expire immediately after, so this does not distort
+ // the timing data.
+ if (m_subtasks > 0) {
+ QTC_CHECK(m_timer.isValid());
+ m_elapsedMs += m_timer.elapsed();
+ m_timer.invalidate();
+ m_subtasks = 0;
+ }
+ m_started = false;
+ qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": took " << m_elapsedMs
+ << " ms in UI thread";
+ m_elapsedMs = 0;
+}
+
+void TaskTimer::startSubtask()
+{
+ // We have some callbacks that are either synchronous or asynchronous, depending on
+ // dynamic conditions. In the sync case, we will have nested subtasks, in which case
+ // the inner ones must not collect timing data, as their code blocks are already covered.
+ if (++m_subtasks > 1)
+ return;
+ if (!m_started) {
+ QTC_ASSERT(m_elapsedMs == 0, m_elapsedMs = 0);
+ m_started = true;
+ m_finalized = false;
+ qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": starting";
+
+ // Used by ThreadedSubtaskTimer to mark the end of the whole highlighting operation
+ m_startTimer.restart();
+ }
+ qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": subtask started at "
+ << QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz");
+ QTC_CHECK(!m_timer.isValid());
+ m_timer.start();
+}
+
+void TaskTimer::stopSubtask(bool isFinalizing)
+{
+ if (m_subtasks == 0) // See stopTask().
+ return;
+ if (isFinalizing)
+ m_finalized = true;
+ if (--m_subtasks > 0) // See startSubtask().
+ return;
+ qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": subtask stopped at "
+ << QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz");
+ QTC_CHECK(m_timer.isValid());
+ m_elapsedMs += m_timer.elapsed();
+ m_timer.invalidate();
+ if (m_finalized)
+ stopTask();
+}
+
+ThreadedSubtaskTimer::ThreadedSubtaskTimer(const QString &task, const TaskTimer &taskTimer)
+ : m_task(task), m_taskTimer(taskTimer)
+{
+ qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": starting thread";
+ m_timer.start();
+}
+
+ThreadedSubtaskTimer::~ThreadedSubtaskTimer()
+{
+ qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": took " << m_timer.elapsed()
+ << " ms in dedicated thread";
+
+ qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": Start to end: "
+ << m_taskTimer.startTimer().elapsed() << " ms";
+}
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/tasktimers.h b/src/plugins/clangcodemodel/tasktimers.h
new file mode 100644
index 00000000000..8995700d79b
--- /dev/null
+++ b/src/plugins/clangcodemodel/tasktimers.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QElapsedTimer>
+#include <QLoggingCategory>
+#include <QString>
+
+namespace ClangCodeModel::Internal {
+
+Q_DECLARE_LOGGING_CATEGORY(clangdLogTiming);
+
+// TODO: Generalize, document interface and move to Utils?
+class TaskTimer
+{
+public:
+ TaskTimer(const QString &task) : m_task(task) {}
+
+ void stopTask();
+ void startSubtask();
+ void stopSubtask(bool isFinalizing);
+
+ QElapsedTimer startTimer() const { return m_startTimer; }
+
+private:
+ const QString m_task;
+ QElapsedTimer m_timer;
+ QElapsedTimer m_startTimer;
+ qint64 m_elapsedMs = 0;
+ int m_subtasks = 0;
+ bool m_started = false;
+ bool m_finalized = false;
+};
+
+class SubtaskTimer
+{
+public:
+ SubtaskTimer(TaskTimer &timer) : m_timer(timer) { m_timer.startSubtask(); }
+ ~SubtaskTimer() { m_timer.stopSubtask(m_isFinalizing); }
+
+protected:
+ void makeFinalizing() { m_isFinalizing = true; }
+
+private:
+ TaskTimer &m_timer;
+ bool m_isFinalizing = false;
+};
+
+class FinalizingSubtaskTimer : public SubtaskTimer
+{
+public:
+ FinalizingSubtaskTimer(TaskTimer &timer) : SubtaskTimer(timer) { makeFinalizing(); }
+};
+
+class ThreadedSubtaskTimer
+{
+public:
+ ThreadedSubtaskTimer(const QString &task, const TaskTimer &taskTimer);
+ ~ThreadedSubtaskTimer();
+
+private:
+ const QString m_task;
+ QElapsedTimer m_timer;
+ const TaskTimer &m_taskTimer;
+};
+
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/test/activationsequenceprocessortest.cpp b/src/plugins/clangcodemodel/test/activationsequenceprocessortest.cpp
new file mode 100644
index 00000000000..491289096de
--- /dev/null
+++ b/src/plugins/clangcodemodel/test/activationsequenceprocessortest.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "activationsequenceprocessortest.h"
+
+#include "../clangactivationsequenceprocessor.h"
+
+#include <cplusplus/Token.h>
+
+#include <QtTest>
+
+using namespace CPlusPlus;
+
+namespace ClangCodeModel::Internal::Tests {
+
+static bool resultIs(const ActivationSequenceProcessor &processor, Kind expectedKind,
+ int expectedOffset, int expectedNewPos)
+{
+ return processor.completionKind() == expectedKind
+ && processor.offset() == expectedOffset
+ && processor.operatorStartPosition() == expectedNewPos;
+}
+
+void ActivationSequenceProcessorTest::testCouldNotProcesseRandomCharacters()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("xxx"), 3, false);
+ QVERIFY(resultIs(processor, T_EOF_SYMBOL, 0, 3));
+}
+
+void ActivationSequenceProcessorTest::testCouldNotProcesseEmptyString()
+{
+ ActivationSequenceProcessor processor(QStringLiteral(""), 0, true);
+ QVERIFY(resultIs(processor, T_EOF_SYMBOL, 0, 0));
+}
+
+void ActivationSequenceProcessorTest::testDot()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("."), 1, true);
+ QVERIFY(resultIs(processor, T_DOT, 1, 0));
+}
+
+void ActivationSequenceProcessorTest::testComma()
+{
+ ActivationSequenceProcessor processor(QStringLiteral(","), 2, false);
+ QVERIFY(resultIs(processor, T_COMMA, 1, 1));
+}
+
+void ActivationSequenceProcessorTest::testLeftParenAsFunctionCall()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("("), 3, true);
+ QVERIFY(resultIs(processor, T_LPAREN, 1, 2));
+}
+
+void ActivationSequenceProcessorTest::testLeftParenNotAsFunctionCall()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("("), 3, false);
+ QVERIFY(resultIs(processor, T_EOF_SYMBOL, 0, 3));
+}
+
+void ActivationSequenceProcessorTest::testColonColon()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("::"), 20, true);
+
+ QVERIFY(resultIs(processor, T_COLON_COLON, 2, 18));
+}
+
+void ActivationSequenceProcessorTest::testArrow()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("->"), 2, true);
+
+ QVERIFY(resultIs(processor, T_ARROW, 2, 0));
+}
+
+void ActivationSequenceProcessorTest::testDotStar()
+{
+ ActivationSequenceProcessor processor(QStringLiteral(".*"), 3, true);
+
+ QVERIFY(resultIs(processor, T_DOT_STAR, 2, 1));
+}
+
+void ActivationSequenceProcessorTest::testArrowStar()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("->*"), 3, true);
+
+ QVERIFY(resultIs(processor, T_ARROW_STAR, 3, 0));
+}
+
+void ActivationSequenceProcessorTest::testDoxyGenCommentBackSlash()
+{
+ ActivationSequenceProcessor processor(QStringLiteral(" \\"), 3, true);
+
+ QVERIFY(resultIs(processor, T_DOXY_COMMENT, 1, 2));
+}
+
+void ActivationSequenceProcessorTest::testDoxyGenCommentAt()
+{
+ ActivationSequenceProcessor processor(QStringLiteral(" @"), 2, true);
+
+ QVERIFY(resultIs(processor, T_DOXY_COMMENT, 1, 1));
+}
+
+void ActivationSequenceProcessorTest::testAngleStringLiteral()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("<"), 1, true);
+
+ QVERIFY(resultIs(processor, T_ANGLE_STRING_LITERAL, 1, 0));
+}
+
+void ActivationSequenceProcessorTest::testStringLiteral()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("\""), 1, true);
+
+ QVERIFY(resultIs(processor, T_STRING_LITERAL, 1, 0));
+}
+
+void ActivationSequenceProcessorTest::testSlash()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("/"), 1, true);
+
+ QVERIFY(resultIs(processor, T_SLASH, 1, 0));
+}
+
+void ActivationSequenceProcessorTest::testPound()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("#"), 1, true);
+
+ QVERIFY(resultIs(processor, T_POUND, 1, 0));
+}
+
+void ActivationSequenceProcessorTest::testPositionIsOne()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("<xx"), 1, false);
+
+ QVERIFY(resultIs(processor, T_ANGLE_STRING_LITERAL, 1, 0));
+}
+
+void ActivationSequenceProcessorTest::testPositionIsTwo()
+{
+ ActivationSequenceProcessor processor(QStringLiteral(" @x"), 2, true);
+
+ QVERIFY(resultIs(processor, T_DOXY_COMMENT, 1, 1));
+}
+
+void ActivationSequenceProcessorTest::testPositionIsTwoWithASingleSign()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("x<x"), 2, false);
+
+ QVERIFY(resultIs(processor, T_ANGLE_STRING_LITERAL, 1, 1));
+}
+
+void ActivationSequenceProcessorTest::testPositionIsThree()
+{
+ ActivationSequenceProcessor processor(QStringLiteral("xx<"), 3, false);
+
+ QVERIFY(resultIs(processor, T_ANGLE_STRING_LITERAL, 1, 2));
+}
+
+} // namespace ClangCodeModel::Internal::Tests
diff --git a/src/plugins/clangcodemodel/test/activationsequenceprocessortest.h b/src/plugins/clangcodemodel/test/activationsequenceprocessortest.h
new file mode 100644
index 00000000000..3d356f57b14
--- /dev/null
+++ b/src/plugins/clangcodemodel/test/activationsequenceprocessortest.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace ClangCodeModel::Internal::Tests {
+
+class ActivationSequenceProcessorTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testCouldNotProcesseRandomCharacters();
+ void testCouldNotProcesseEmptyString();
+ void testDot();
+ void testComma();
+ void testLeftParenAsFunctionCall();
+ void testLeftParenNotAsFunctionCall();
+ void testColonColon();
+ void testArrow();
+ void testDotStar();
+ void testArrowStar();
+ void testDoxyGenCommentBackSlash();
+ void testDoxyGenCommentAt();
+ void testAngleStringLiteral();
+ void testStringLiteral();
+ void testSlash();
+ void testPound();
+ void testPositionIsOne();
+ void testPositionIsTwo();
+ void testPositionIsTwoWithASingleSign();
+ void testPositionIsThree();
+};
+
+} // namespace ClangCodeModel::Internal::Tests
diff --git a/src/plugins/clangcodemodel/test/clangautomationutils.cpp b/src/plugins/clangcodemodel/test/clangautomationutils.cpp
deleted file mode 100644
index ec2b6e9207c..00000000000
--- a/src/plugins/clangcodemodel/test/clangautomationutils.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangautomationutils.h"
-
-#include "../clangcompletionassistinterface.h"
-#include "../clangcompletionassistprovider.h"
-
-#include <texteditor/codeassist/assistinterface.h>
-#include <texteditor/codeassist/assistproposalitem.h>
-#include <texteditor/codeassist/completionassistprovider.h>
-#include <texteditor/codeassist/genericproposalmodel.h>
-#include <texteditor/codeassist/iassistprocessor.h>
-#include <texteditor/codeassist/iassistproposal.h>
-#include <texteditor/textdocument.h>
-#include <texteditor/texteditor.h>
-
-#include <utils/qtcassert.h>
-
-#include <QCoreApplication>
-#include <QElapsedTimer>
-#include <QScopedPointer>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class WaitForAsyncCompletions
-{
-public:
- enum WaitResult { GotResults, GotInvalidResults, Timeout };
-
- WaitResult wait(TextEditor::IAssistProcessor *processor,
- TextEditor::AssistInterface *assistInterface,
- int timeoutInMs)
- {
- QTC_ASSERT(processor, return Timeout);
- QTC_ASSERT(assistInterface, return Timeout);
-
- bool gotResults = false;
-
- processor->setAsyncCompletionAvailableHandler(
- [this, processor, &gotResults] (TextEditor::IAssistProposal *proposal) {
- QTC_ASSERT(proposal, return);
- QTC_CHECK(!processor->running());
- proposalModel = proposal->model();
- delete proposal;
- gotResults = true;
- });
-
- // Are there any immediate results?
- if (TextEditor::IAssistProposal *proposal = processor->perform(assistInterface)) {
- proposalModel = proposal->model();
- delete proposal;
- QTC_ASSERT(proposalModel, return GotInvalidResults);
- return GotResults;
- }
-
- // There are not any, so wait for async results.
- QElapsedTimer timer;
- timer.start();
- while (!gotResults) {
- if (timer.elapsed() >= timeoutInMs) {
- processor->cancel();
- return Timeout;
- }
- QCoreApplication::processEvents();
- }
-
- return proposalModel ? GotResults : GotInvalidResults;
- }
-
-public:
- TextEditor::ProposalModelPtr proposalModel;
-};
-
-TextEditor::ProposalModelPtr completionResults(TextEditor::BaseTextEditor *textEditor,
- const QStringList &includePaths,
- int timeOutInMs)
-{
- using namespace TextEditor;
-
- auto textEditorWidget = TextEditorWidget::fromEditor(textEditor);
- QTC_ASSERT(textEditorWidget, return TextEditor::ProposalModelPtr());
- AssistInterface *assistInterface = textEditorWidget->createAssistInterface(
- TextEditor::Completion, TextEditor::ExplicitlyInvoked);
- QTC_ASSERT(assistInterface, return TextEditor::ProposalModelPtr());
- if (!includePaths.isEmpty()) {
- auto clangAssistInterface = static_cast<ClangCompletionAssistInterface *>(assistInterface);
- clangAssistInterface->setHeaderPaths(ProjectExplorer::toUserHeaderPaths(includePaths));
- }
-
- CompletionAssistProvider *assistProvider
- = textEditor->textDocument()->completionAssistProvider();
- QTC_ASSERT(qobject_cast<ClangCompletionAssistProvider *>(assistProvider),
- return TextEditor::ProposalModelPtr());
- QTC_ASSERT(assistProvider, return TextEditor::ProposalModelPtr());
- QTC_ASSERT(assistProvider->runType() == IAssistProvider::Asynchronous,
- return TextEditor::ProposalModelPtr());
-
- QScopedPointer<IAssistProcessor> processor(assistProvider->createProcessor(assistInterface));
- QTC_ASSERT(processor, return TextEditor::ProposalModelPtr());
-
- WaitForAsyncCompletions waitForCompletions;
- const WaitForAsyncCompletions::WaitResult result = waitForCompletions.wait(processor.data(),
- assistInterface,
- timeOutInMs);
- QTC_ASSERT(result == WaitForAsyncCompletions::GotResults,
- return TextEditor::ProposalModelPtr());
- return waitForCompletions.proposalModel;
-}
-
-QString qrcPath(const QByteArray &relativeFilePath)
-{
- return QLatin1String(":/unittests/ClangCodeModel/") + QString::fromUtf8(relativeFilePath);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/test/clangautomationutils.h b/src/plugins/clangcodemodel/test/clangautomationutils.h
deleted file mode 100644
index 7b9a5bb262e..00000000000
--- a/src/plugins/clangcodemodel/test/clangautomationutils.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <texteditor/codeassist/iassistproposalmodel.h>
-
-#include <QList>
-#include <QSharedPointer>
-#include <QString>
-
-namespace TextEditor { class BaseTextEditor; }
-
-namespace ClangCodeModel {
-namespace Internal {
-
-TextEditor::ProposalModelPtr completionResults(TextEditor::BaseTextEditor *textEditor,
- const QStringList &includePaths = QStringList(),
- int timeOutInMs = 10000);
-
-QString qrcPath(const QByteArray &relativeFilePath);
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp b/src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp
index a5041ea1c98..0038a1eb6ba 100644
--- a/src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp
+++ b/src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp
@@ -25,8 +25,6 @@
#include "clangbatchfileprocessor.h"
-#include "clangautomationutils.h"
-
#include <clangcodemodel/clangeditordocumentprocessor.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -57,7 +55,6 @@
#include <QString>
#include <QThread>
-using namespace ClangBackEnd;
using namespace ProjectExplorer;
namespace ClangCodeModel {
@@ -442,45 +439,6 @@ Command::Ptr InsertTextCommand::parse(BatchFileLineTokenizer &arguments,
return Command::Ptr(new InsertTextCommand(context, textToInsert));
}
-class CompleteCommand : public Command
-{
-public:
- CompleteCommand(const CommandContext &context);
-
- bool run() override;
-
- static Command::Ptr parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context);
-};
-
-CompleteCommand::CompleteCommand(const CommandContext &context)
- : Command(context)
-{
-}
-
-bool CompleteCommand::run()
-{
- qCDebug(debug) << "line" << context().lineNumber << "CompleteCommand";
-
- TextEditor::BaseTextEditor *editor = currentTextEditor();
- QTC_ASSERT(editor, return false);
-
- const QString documentFilePath = editor->document()->filePath().toString();
- auto *processor = ClangEditorDocumentProcessor::get(documentFilePath);
- QTC_ASSERT(processor, return false);
-
- return !completionResults(editor, QStringList(), timeOutInMs()).isNull();
-}
-
-Command::Ptr CompleteCommand::parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context)
-{
- Q_UNUSED(arguments)
- Q_UNUSED(context)
-
- return Command::Ptr(new CompleteCommand(context));
-}
-
class SetCursorCommand : public Command
{
public:
@@ -687,7 +645,6 @@ BatchFileParser::BatchFileParser(const QString &filePath,
m_commandParsers.insert("closeAllDocuments", &CloseAllDocuments::parse);
m_commandParsers.insert("setCursor", &SetCursorCommand::parse);
m_commandParsers.insert("insertText", &InsertTextCommand::parse);
- m_commandParsers.insert("complete", &CompleteCommand::parse);
m_commandParsers.insert("processEvents", &ProcessEventsCommand::parse);
}
@@ -775,7 +732,7 @@ bool runClangBatchFile(const QString &filePath)
QTC_CHECK(Core::EditorManager::closeAllEditors(/*askAboutModifiedEditors=*/ false));
});
- foreach (const Command::Ptr &command, commands) {
+ for (const Command::Ptr &command : commands) {
const bool runSucceeded = command->run();
QCoreApplication::processEvents(); // Update GUI
diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
deleted file mode 100644
index 4fa51c94b7c..00000000000
--- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
+++ /dev/null
@@ -1,846 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcodecompletion_test.h"
-
-#include "clangautomationutils.h"
-#include "clangbatchfileprocessor.h"
-#include "../clangcompletionassistinterface.h"
-#include "../clangmodelmanagersupport.h"
-
-#include <clangcodemodel/clangeditordocumentprocessor.h>
-
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/editormanager/ieditor.h>
-#include <coreplugin/icore.h>
-#include <cppeditor/cppcodemodelsettings.h>
-#include <cppeditor/cpptoolsreuse.h>
-#include <cppeditor/cpptoolstestcase.h>
-#include <cppeditor/modelmanagertesthelper.h>
-#include <cppeditor/projectinfo.h>
-#include <languageclient/languageclientmanager.h>
-#include <texteditor/codeassist/assistproposalitem.h>
-#include <texteditor/codeassist/genericproposalmodel.h>
-#include <texteditor/textdocument.h>
-#include <texteditor/texteditor.h>
-
-#include <clangsupport/clangcodemodelservermessages.h>
-
-#include <utils/changeset.h>
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-#include <QtTest>
-
-using namespace ClangCodeModel;
-using namespace ClangCodeModel::Internal;
-
-namespace {
-
-CppEditor::Tests::TemporaryDir *globalTemporaryDir()
-{
- static CppEditor::Tests::TemporaryDir dir;
- QTC_CHECK(dir.isValid());
- return &dir;
-}
-
-QByteArray readFile(const QString &filePath)
-{
- QFile file(filePath);
- QTC_ASSERT(file.open(QFile::ReadOnly | QFile::Text), return QByteArray());
- return file.readAll();
-}
-
-bool writeFile(const QString &filePath, const QByteArray &contents)
-{
- QFile file(filePath);
- if (!file.open(QFile::WriteOnly | QFile::Text))
- return false;
- if (file.write(contents) != contents.size())
- return false;
- return true;
-}
-
-class ChangeDocumentReloadSetting
-{
-public:
- ChangeDocumentReloadSetting(Core::IDocument::ReloadSetting reloadSetting)
- : m_previousValue(Core::EditorManager::reloadSetting())
- {
- Core::EditorManager::setReloadSetting(reloadSetting);
- }
-
- ~ChangeDocumentReloadSetting()
- {
- Core::EditorManager::setReloadSetting(m_previousValue);
- }
-
-private:
- Core::IDocument::ReloadSetting m_previousValue;
-};
-
-class TestDocument
-{
-public:
- TestDocument(const QByteArray &fileName, CppEditor::Tests::TemporaryDir *temporaryDir = nullptr)
- {
- QTC_ASSERT(!fileName.isEmpty(), return);
- const QResource resource(qrcPath("completion/" + fileName));
- QTC_ASSERT(resource.isValid(), return);
- const QByteArray contents = QByteArray(reinterpret_cast<const char*>(resource.data()),
- resource.size());
- finish(fileName, contents, temporaryDir);
- }
-
- static TestDocument fromExistingFile(const QString &filePath)
- {
- TestDocument testDocument;
- QTC_ASSERT(!filePath.isEmpty(), return testDocument);
- testDocument.filePath = filePath;
- testDocument.cursorPosition = findCursorMarkerPosition(readFile(filePath));
- return testDocument;
- }
-
- static TestDocument fromString(const QByteArray &fileName, const QByteArray &contents,
- CppEditor::Tests::TemporaryDir *tempDir = nullptr)
- {
- TestDocument testDocument;
- testDocument.finish(fileName, contents, tempDir);
- return testDocument;
- }
-
- static int findCursorMarkerPosition(const QByteArray &contents)
- {
- return contents.indexOf(" /* COMPLETE HERE */");
- }
-
- bool isCreated() const { return !filePath.isEmpty(); }
- bool hasValidCursorPosition() const { return cursorPosition >= 0; }
- bool isCreatedAndHasValidCursorPosition() const
- { return isCreated() && hasValidCursorPosition(); }
-
- QString filePath;
- int cursorPosition = -1;
-
-private:
- TestDocument() = default;
-
- void finish(const QByteArray &fileName, const QByteArray &contents,
- CppEditor::Tests::TemporaryDir *temporaryDir = nullptr)
- {
- cursorPosition = findCursorMarkerPosition(contents);
- if (!contents.isEmpty()) {
- if (!temporaryDir) {
- m_temporaryDir.reset(new CppEditor::Tests::TemporaryDir);
- temporaryDir = m_temporaryDir.data();
- }
-
- filePath = temporaryDir->createFile(fileName, contents);
- }
- }
-
- QSharedPointer<CppEditor::Tests::TemporaryDir> m_temporaryDir;
-};
-
-class OpenEditorAtCursorPosition
-{
-public:
- OpenEditorAtCursorPosition(const TestDocument &testDocument);
- ~OpenEditorAtCursorPosition(); // Close editor
-
- bool succeeded() const { return m_editor && m_backendIsNotified; }
- bool waitUntilBackendIsNotified(int timeout = 10000);
- bool waitUntilProjectPartChanged(const QString &newProjectPartId, int timeout = 10000);
- bool waitUntil(const std::function<bool()> &condition, int timeout);
- TextEditor::BaseTextEditor *editor() const { return m_editor; }
-
-private:
- TextEditor::BaseTextEditor *m_editor;
- bool m_backendIsNotified = false;
-};
-
-OpenEditorAtCursorPosition::OpenEditorAtCursorPosition(const TestDocument &testDocument)
-{
- Core::IEditor *coreEditor = Core::EditorManager::openEditor(
- Utils::FilePath::fromString(testDocument.filePath));
- m_editor = qobject_cast<TextEditor::BaseTextEditor *>(coreEditor);
- QTC_CHECK(m_editor);
- if (m_editor) {
- if (testDocument.hasValidCursorPosition())
- m_editor->setCursorPosition(testDocument.cursorPosition);
- m_backendIsNotified = waitUntilBackendIsNotified();
- }
- QTC_CHECK(m_backendIsNotified);
-}
-
-OpenEditorAtCursorPosition::~OpenEditorAtCursorPosition()
-{
- if (m_editor)
- Core::EditorManager::closeEditors({m_editor}, /* askAboutModifiedEditors= */ false);
-}
-
-
-
-bool OpenEditorAtCursorPosition::waitUntilBackendIsNotified(int timeout)
-{
- const QString filePath = m_editor->document()->filePath().toString();
-
- auto condition = [filePath] () {
- const auto *processor = ClangEditorDocumentProcessor::get(filePath);
- return processor && processor->projectPart();
- };
-
- return waitUntil(condition, timeout);
-}
-
-bool OpenEditorAtCursorPosition::waitUntilProjectPartChanged(const QString &newProjectPartId,
- int timeout)
-{
- const QString filePath = m_editor->document()->filePath().toString();
-
- auto condition = [newProjectPartId, filePath] () {
- const auto *processor = ClangEditorDocumentProcessor::get(filePath);
- return processor
- && processor->projectPart()
- && processor->projectPart()->id() == newProjectPartId;
- };
-
- return waitUntil(condition, timeout);
-}
-
-bool OpenEditorAtCursorPosition::waitUntil(const std::function<bool ()> &condition, int timeout)
-{
- QElapsedTimer time;
- time.start();
-
- forever {
- if (time.elapsed() > timeout)
- return false;
-
- if (condition())
- return true;
-
- QCoreApplication::processEvents();
- QThread::msleep(20);
- }
-
- return false;
-}
-
-CppEditor::ProjectPart::ConstPtr createProjectPart(const Utils::FilePath &projectFilePath,
- const QStringList &files,
- const ProjectExplorer::Macros &macros)
-{
- using namespace CppEditor;
-
- ProjectExplorer::RawProjectPart rpp;
- rpp.setProjectFileLocation("myproject.project");
- rpp.setQtVersion(Utils::QtMajorVersion::None);
- rpp.setMacros(macros);
- const auto projectFiles = Utils::transform<ProjectFiles>(files, [](const QString &f) {
- return ProjectFile(f, ProjectFile::classify(f));
- });
- return ProjectPart::create(projectFilePath, rpp, {}, projectFiles);
-}
-
-CppEditor::ProjectInfo::ConstPtr createProjectInfo(ProjectExplorer::Project *project,
- const QStringList &files,
- const ProjectExplorer::Macros &macros)
-{
- using namespace CppEditor;
- QTC_ASSERT(project, return {});
-
- const CppEditor::ProjectPart::ConstPtr projectPart
- = createProjectPart(project->projectFilePath(), files, macros);
- const auto projectInfo = ProjectInfo::create(
- {project, ProjectExplorer::KitInfo(nullptr), {}, {}}, {projectPart});
- return projectInfo;
-}
-
-class ProjectLoader
-{
-public:
- ProjectLoader(const QStringList &projectFiles,
- const ProjectExplorer::Macros &projectMacros,
- bool testOnlyForCleanedProjects = false)
- : m_project(nullptr)
- , m_projectFiles(projectFiles)
- , m_projectMacros(projectMacros)
- , m_helper(nullptr, testOnlyForCleanedProjects)
- {
- }
-
- bool load()
- {
- m_project = m_helper.createProject(QLatin1String("testProject"));
- const CppEditor::ProjectInfo::ConstPtr projectInfo = createProjectInfo(m_project,
- m_projectFiles,
- m_projectMacros);
- const QSet<QString> filesIndexedAfterLoading = m_helper.updateProjectInfo(projectInfo);
- return m_projectFiles.size() == filesIndexedAfterLoading.size();
- }
-
- bool updateProject(const ProjectExplorer::Macros &updatedProjectMacros)
- {
- QTC_ASSERT(m_project, return false);
- const CppEditor::ProjectInfo::ConstPtr updatedProjectInfo
- = createProjectInfo(m_project, m_projectFiles, updatedProjectMacros);
- return updateProjectInfo(updatedProjectInfo);
-
- }
-
-private:
- bool updateProjectInfo(const CppEditor::ProjectInfo::ConstPtr &projectInfo)
- {
- const QSet<QString> filesIndexedAfterLoading = m_helper.updateProjectInfo(projectInfo);
- return m_projectFiles.size() == filesIndexedAfterLoading.size();
- }
-
- ProjectExplorer::Project *m_project;
- QStringList m_projectFiles;
- ProjectExplorer::Macros m_projectMacros;
- CppEditor::Tests::ModelManagerTestHelper m_helper;
-};
-
-class ProjectLessCompletionTest
-{
-public:
- ProjectLessCompletionTest(const QByteArray &testFileName,
- const QString &textToInsert = QString(),
- const QStringList &includePaths = QStringList(),
- const QByteArray &contents = {})
- {
- CppEditor::Tests::TestCase garbageCollectionGlobalSnapshot;
- QVERIFY(garbageCollectionGlobalSnapshot.succeededSoFar());
-
- const auto testDocument = contents.isEmpty()
- ? TestDocument(testFileName, globalTemporaryDir())
- : TestDocument::fromString(testFileName, contents, globalTemporaryDir());
- QVERIFY(testDocument.isCreatedAndHasValidCursorPosition());
- OpenEditorAtCursorPosition openEditor(testDocument);
- QVERIFY(openEditor.succeeded());
-
- if (!textToInsert.isEmpty())
- openEditor.editor()->insert(textToInsert);
-
- proposal = completionResults(openEditor.editor(), includePaths, timeOutInMs());
- }
-
- TextEditor::ProposalModelPtr proposal;
-};
-
-int indexOfItemWithText(TextEditor::ProposalModelPtr model, const QByteArray &text)
-{
- if (!model)
- return -1;
-
- for (int i = 0, size = model->size(); i < size; ++i) {
- const QString itemText = model->text(i);
- if (itemText == QString::fromUtf8(text))
- return i;
- }
-
- return -1;
-}
-
-bool hasItem(TextEditor::ProposalModelPtr model, const QByteArray &text)
-{
- return indexOfItemWithText(model, text) != -1;
-}
-
-int itemsWithText(TextEditor::ProposalModelPtr model, const QByteArray &text)
-{
- if (!model)
- return 0;
-
- int amount = 0;
- for (int i = 0, size = model->size(); i < size; ++i) {
- if (model->text(i) == QString::fromUtf8(text))
- ++amount;
- }
-
- return amount;
-}
-
-bool hasItem(TextEditor::ProposalModelPtr model, const QByteArray &text, const QByteArray &detail)
-{
- const int index = indexOfItemWithText(model, text);
- if (index != -1 && index < model->size()) {
- TextEditor::IAssistProposalModel *imodel = model.data();
- const auto genericModel = static_cast<TextEditor::GenericProposalModel *>(imodel);
- const auto itemDetail = genericModel->detail(index);
- return itemDetail == QString::fromUtf8(detail);
- }
-
- return false;
-}
-
-bool hasSnippet(TextEditor::ProposalModelPtr model, const QByteArray &text)
-{
- if (!model)
- return false;
-
- // Snippets seem to end with a whitespace
- const QString snippetText = QString::fromUtf8(text) + QLatin1Char(' ');
-
- auto *genericModel = static_cast<TextEditor::GenericProposalModel *>(model.data());
- for (int i = 0, size = genericModel->size(); i < size; ++i) {
- TextEditor::AssistProposalItemInterface *item = genericModel->proposalItem(i);
- QTC_ASSERT(item, continue);
- if (item->text() == snippetText)
- return item->isSnippet();
- }
-
- return false;
-}
-
-class MonitorGeneratedUiFile : public QObject
-{
-public:
- MonitorGeneratedUiFile();
- bool waitUntilGenerated(int timeout = 10000) const;
-
-private:
- void onUiFileGenerated() { m_isGenerated = true; }
-
- bool m_isGenerated = false;
-};
-
-MonitorGeneratedUiFile::MonitorGeneratedUiFile()
-{
- connect(CppEditor::CppModelManager::instance(),
- &CppEditor::CppModelManager::abstractEditorSupportContentsUpdated,
- this, &MonitorGeneratedUiFile::onUiFileGenerated);
-}
-
-bool MonitorGeneratedUiFile::waitUntilGenerated(int timeout) const
-{
- if (m_isGenerated)
- return true;
-
- QElapsedTimer time;
- time.start();
-
- forever {
- if (m_isGenerated)
- return true;
-
- if (time.elapsed() > timeout)
- return false;
-
- QCoreApplication::processEvents();
- QThread::msleep(20);
- }
-
- return false;
-}
-
-class WriteFileAndWaitForReloadedDocument : public QObject
-{
-public:
- WriteFileAndWaitForReloadedDocument(const QString &filePath,
- const QByteArray &fileContents,
- Core::IDocument *document)
- : m_filePath(filePath)
- , m_fileContents(fileContents)
- {
- QTC_CHECK(document);
- connect(document, &Core::IDocument::reloadFinished,
- this, &WriteFileAndWaitForReloadedDocument::onReloadFinished);
- }
-
- void onReloadFinished()
- {
- m_onReloadFinished = true;
- }
-
- bool wait() const
- {
- QTC_ASSERT(writeFile(m_filePath, m_fileContents), return false);
-
- QElapsedTimer totalTime;
- totalTime.start();
-
- QElapsedTimer writeFileAgainTime;
- writeFileAgainTime.start();
-
- forever {
- if (m_onReloadFinished)
- return true;
-
- if (totalTime.elapsed() > 10000)
- return false;
-
- if (writeFileAgainTime.elapsed() > 3000) {
- // The timestamp did not change, try again now.
- QTC_ASSERT(writeFile(m_filePath, m_fileContents), return false);
- writeFileAgainTime.restart();
- }
-
- QCoreApplication::processEvents();
- QThread::msleep(20);
- }
- }
-
-private:
- bool m_onReloadFinished = false;
- QString m_filePath;
- QByteArray m_fileContents;
-};
-
-} // anonymous namespace
-
-namespace ClangCodeModel {
-namespace Internal {
-namespace Tests {
-
-void ClangCodeCompletionTest::initTestCase()
-{
- CppEditor::ClangdSettings::setUseClangd(false);
- for (LanguageClient::Client * const c : LanguageClient::LanguageClientManager::clients())
- LanguageClient::LanguageClientManager::shutdownClient(c);
-}
-
-void ClangCodeCompletionTest::testCompleteDoxygenKeywords()
-{
- ProjectLessCompletionTest t("doxygenKeywordsCompletion.cpp");
-
- QVERIFY(hasItem(t.proposal, "brief"));
- QVERIFY(hasItem(t.proposal, "param"));
- QVERIFY(hasItem(t.proposal, "return"));
- QVERIFY(!hasSnippet(t.proposal, "class"));
-}
-
-void ClangCodeCompletionTest::testCompletePreprocessorKeywords()
-{
- ProjectLessCompletionTest t("preprocessorKeywordsCompletion.cpp");
-
- QVERIFY(hasItem(t.proposal, "ifdef"));
- QVERIFY(hasItem(t.proposal, "endif"));
- QVERIFY(!hasSnippet(t.proposal, "class"));
-}
-
-void ClangCodeCompletionTest::testCompleteIncludeDirective()
-{
- CppEditor::Tests::TemporaryCopiedDir testDir(qrcPath("completion/exampleIncludeDir"));
- ProjectLessCompletionTest t("includeDirectiveCompletion.cpp",
- QString(),
- QStringList(testDir.path()));
-
- QVERIFY(hasItem(t.proposal, "file.h"));
- QVERIFY(hasItem(t.proposal, "otherFile.h"));
- QVERIFY(hasItem(t.proposal, "mylib/"));
- QVERIFY(!hasSnippet(t.proposal, "class"));
-}
-
-void ClangCodeCompletionTest::testCompleteGlobals()
-{
- ProjectLessCompletionTest t("globalCompletion.cpp");
-
- QVERIFY(hasItem(t.proposal, "globalVariable", "int globalVariable"));
- QVERIFY(hasItem(t.proposal, "globalFunction", "void globalFunction()"));
- QVERIFY(hasItem(t.proposal, "GlobalClass", "GlobalClass"));
- QVERIFY(hasItem(t.proposal, "class", "class")); // Keyword
- QVERIFY(hasSnippet(t.proposal, "class")); // Snippet
-}
-
-void ClangCodeCompletionTest::testCompleteMembers()
-{
- ProjectLessCompletionTest t("memberCompletion.cpp");
-
- QVERIFY(hasItem(t.proposal, "member"));
- QVERIFY(!hasItem(t.proposal, "globalVariable"));
- QVERIFY(!hasItem(t.proposal, "class")); // Keyword
- QVERIFY(!hasSnippet(t.proposal, "class")); // Snippet
-}
-
-void ClangCodeCompletionTest::testCompleteMembersFromInside()
-{
- ProjectLessCompletionTest t("membercompletion-inside.cpp");
-
- QVERIFY(hasItem(t.proposal, "publicFunc"));
- QVERIFY(hasItem(t.proposal, "privateFunc"));
-}
-
-void ClangCodeCompletionTest::testCompleteMembersFromOutside()
-{
- ProjectLessCompletionTest t("membercompletion-outside.cpp");
-
- QVERIFY(hasItem(t.proposal, "publicFunc"));
- QVERIFY(!hasItem(t.proposal, "privateFunc"));
-}
-
-void ClangCodeCompletionTest::testCompleteMembersFromFriend()
-{
- ProjectLessCompletionTest t("membercompletion-friend.cpp");
-
- QVERIFY(hasItem(t.proposal, "publicFunc"));
- QVERIFY(hasItem(t.proposal, "privateFunc"));
-}
-
-void ClangCodeCompletionTest::testCompleteFunctions()
-{
- ProjectLessCompletionTest t("functionCompletion.cpp");
-
- QVERIFY(hasItem(t.proposal, "void f()"));
- QVERIFY(hasItem(t.proposal, "void f(int a)"));
- QVERIFY(hasItem(t.proposal, "void f(const QString &amp;s)"));
- QVERIFY(hasItem(t.proposal, "void f(char c<i>, int optional = 3</i>)"));
- QVERIFY(hasItem(t.proposal, "void f(char c<i>, int optional1 = 3, int optional2 = 3</i>)"));
- QVERIFY(hasItem(t.proposal, "void f(const TType&lt;QString&gt; *t)"));
- QVERIFY(hasItem(t.proposal, "TType&lt;QString&gt; f(bool)"));
-}
-
-void ClangCodeCompletionTest::testCompleteOverloads()
-{
- ProjectLessCompletionTest t("functionCompletionFiltered.cpp");
- QCOMPARE(t.proposal->size(), 1);
- QVERIFY(hasItem(t.proposal, "void func(int i, int j)"));
-
- ProjectLessCompletionTest t2("functionCompletionFiltered2.cpp");
- QCOMPARE(t2.proposal->size(), 2);
- QVERIFY(hasItem(t2.proposal, "void func(const S &amp;s, int j)"));
- QVERIFY(hasItem(t2.proposal, "void func(const S &amp;s, int j, int k)"));
-}
-
-void ClangCodeCompletionTest::testCompleteConstructor()
-{
- ProjectLessCompletionTest t("constructorCompletion.cpp");
-
- QVERIFY(!hasItem(t.proposal, "globalVariable"));
- QVERIFY(!hasItem(t.proposal, "class"));
- QVERIFY(hasItem(t.proposal, "Foo(int)"));
- QVERIFY(hasItem(t.proposal, "Foo(int, double)"));
-}
-
-void ClangCodeCompletionTest::testCompleteClassAndConstructor()
-{
- ProjectLessCompletionTest t("classAndConstructorCompletion.cpp");
-
- QCOMPARE(itemsWithText(t.proposal, "Foo"), 2);
-}
-
-// Explicitly Inserting The Dot
-// ----------------------------
-// Inserting the dot for is important since it will send the editor
-// content to the backend and thus generate an unsaved file on the backend
-// side. The unsaved file enables us to do the dot to arrow correction.
-
-void ClangCodeCompletionTest::testCompleteWithDotToArrowCorrection()
-{
- ProjectLessCompletionTest t("dotToArrowCorrection.cpp",
- QStringLiteral(".")); // See above "Explicitly Inserting The Dot"
-
- QVERIFY(hasItem(t.proposal, "member"));
-}
-
-void ClangCodeCompletionTest::testDontCompleteWithDotToArrowCorrectionForFloats()
-{
- ProjectLessCompletionTest t("noDotToArrowCorrectionForFloats.cpp",
- QStringLiteral(".")); // See above "Explicitly Inserting The Dot"
-
- QCOMPARE(t.proposal->size(), 0);
-}
-
-void ClangCodeCompletionTest::testCompleteProjectDependingCode()
-{
- const TestDocument testDocument("completionWithProject.cpp");
- QVERIFY(testDocument.isCreatedAndHasValidCursorPosition());
-
- ProjectLoader projectLoader(QStringList(testDocument.filePath), {{"PROJECT_CONFIGURATION_1"}});
- QVERIFY(projectLoader.load());
-
- OpenEditorAtCursorPosition openEditor(testDocument);
- QVERIFY(openEditor.succeeded());
-
- TextEditor::ProposalModelPtr proposal = completionResults(openEditor.editor(), {},
- timeOutInMs());
- QVERIFY(hasItem(proposal, "projectConfiguration1"));
-}
-
-void ClangCodeCompletionTest::testCompleteProjectDependingCodeAfterChangingProject()
-{
- const TestDocument testDocument("completionWithProject.cpp");
- QVERIFY(testDocument.isCreatedAndHasValidCursorPosition());
-
- OpenEditorAtCursorPosition openEditor(testDocument);
- QVERIFY(openEditor.succeeded());
-
- // Check completion without project
- TextEditor::ProposalModelPtr proposal = completionResults(openEditor.editor(), {},
- timeOutInMs());
- QVERIFY(hasItem(proposal, "noProjectConfigurationDetected"));
-
- {
- // Check completion with project configuration 1
- ProjectLoader projectLoader(QStringList(testDocument.filePath),
- {{"PROJECT_CONFIGURATION_1"}},
- /* testOnlyForCleanedProjects= */ true);
- QVERIFY(projectLoader.load());
- openEditor.waitUntilProjectPartChanged(QLatin1String("myproject.project"));
-
- proposal = completionResults(openEditor.editor(), {}, timeOutInMs());
-
- QVERIFY(hasItem(proposal, "projectConfiguration1"));
- QVERIFY(!hasItem(proposal, "projectConfiguration2"));
-
- // Check completion with project configuration 2
- QVERIFY(projectLoader.updateProject({{"PROJECT_CONFIGURATION_2"}}));
- openEditor.waitUntilBackendIsNotified();
- proposal = completionResults(openEditor.editor(), {}, timeOutInMs());
-
- QVERIFY(!hasItem(proposal, "projectConfiguration1"));
- QVERIFY(hasItem(proposal, "projectConfiguration2"));
- } // Project closed
-
- // Check again completion without project
- openEditor.waitUntilProjectPartChanged(QLatin1String(""));
- proposal = completionResults(openEditor.editor(), {}, timeOutInMs());
- QVERIFY(hasItem(proposal, "noProjectConfigurationDetected"));
-}
-
-void ClangCodeCompletionTest::testCompleteProjectDependingCodeInGeneratedUiFile()
-{
- CppEditor::Tests::TemporaryCopiedDir testDir(qrcPath("qt-widgets-app"));
- QVERIFY(testDir.isValid());
-
- MonitorGeneratedUiFile monitorGeneratedUiFile;
-
- // Open project
- const QString projectFilePath = testDir.absolutePath("qt-widgets-app.pro");
- CppEditor::Tests::ProjectOpenerAndCloser projectManager;
- QVERIFY(projectManager.open(projectFilePath, true));
- QVERIFY(monitorGeneratedUiFile.waitUntilGenerated());
-
- // Open file with ui object
- const QString completionFile = testDir.absolutePath("mainwindow.cpp");
- const TestDocument testDocument = TestDocument::fromExistingFile(completionFile);
- QVERIFY(testDocument.isCreatedAndHasValidCursorPosition());
- OpenEditorAtCursorPosition openSource(testDocument);
- QVERIFY(openSource.succeeded());
-
- // ...and check comletions
- TextEditor::ProposalModelPtr proposal = completionResults(openSource.editor(), {},
- timeOutInMs());
- QVERIFY(hasItem(proposal, "menuBar"));
- QVERIFY(hasItem(proposal, "statusBar"));
- QVERIFY(hasItem(proposal, "centralWidget"));
- QVERIFY(hasItem(proposal, "setupUi"));
-}
-
-static QByteArray makeSignalCompletionContents(const QByteArray &customContents)
-{
- static const QByteArray definitions = R"(
- class QObject {
- public:
- void aSignal() __attribute__((annotate("qt_signal")));
- void anotherSignal() __attribute__((annotate("qt_signal")));
- void notASignal();
- static void connect();
- static void disconnect();
- };
- class DerivedFromQObject : public QObject {
- public:
- void myOwnSignal() __attribute__((annotate("qt_signal")));
- void alsoNotASignal();
- };
- class NotAQObject {
- public:
- void notASignal();
- void alsoNotASignal();
- static void connect();
- };)";
-
- return definitions + customContents + " /* COMPLETE HERE */";
-}
-
-void ClangCodeCompletionTest::testSignalCompletion_data()
-{
- QTest::addColumn<QByteArray>("customContents");
- QTest::addColumn<QByteArrayList>("hits");
-
- // libclang mis-reports CXCursor_ClassDecl instead of CXCursor_Constructor, so the lists
- // below include the class name.
- QTest::addRow("positive: connect() on QObject class")
- << QByteArray("int main() { QObject::connect(dummy, QObject::")
- << QByteArrayList{"aSignal", "anotherSignal", "QObject"};
- QTest::addRow("positive: connect() on QObject object")
- << QByteArray("int main() { QObject o; o.connect(dummy, QObject::")
- << QByteArrayList{"aSignal", "anotherSignal", "QObject"};
- QTest::addRow("positive: connect() on QObject pointer")
- << QByteArray("int main() { QObject *o; o->connect(dummy, QObject::")
- << QByteArrayList{"aSignal", "anotherSignal", "QObject"};
- QTest::addRow("positive: connect() on QObject rvalue")
- << QByteArray("int main() { QObject().connect(dummy, QObject::")
- << QByteArrayList{"aSignal", "anotherSignal", "QObject"};
- QTest::addRow("positive: connect() on QObject pointer rvalue")
- << QByteArray("int main() { (new QObject)->connect(dummy, QObject::")
- << QByteArrayList{"aSignal", "anotherSignal", "QObject"};
- QTest::addRow("positive: disconnect() on QObject")
- << QByteArray("int main() { QObject::disconnect(dummy, QObject::")
- << QByteArrayList{"aSignal", "anotherSignal", "QObject"};
- QTest::addRow("positive: connect() in member function of derived class")
- << QByteArray("void DerivedFromQObject::alsoNotASignal() { connect(this, DerivedFromQObject::")
- << QByteArrayList{"aSignal", "anotherSignal", "myOwnSignal", "QObject", "DerivedFromQObject"};
-
- const QByteArrayList allQObjectFunctions{"aSignal", "anotherSignal", "notASignal", "connect",
- "disconnect", "QObject", "~QObject", "operator="};
- QTest::addRow("negative: different function name")
- << QByteArray("int main() { QObject::notASignal(dummy, QObject::")
- << allQObjectFunctions;
- QTest::addRow("negative: connect function from other class")
- << QByteArray("int main() { NotAQObject::connect(dummy, QObject::")
- << allQObjectFunctions;
- QTest::addRow("negative: first argument")
- << QByteArray("int main() { QObject::connect(QObject::")
- << allQObjectFunctions;
- QTest::addRow("negative: third argument")
- << QByteArray("int main() { QObject::connect(dummy1, dummy2, QObject::")
- << allQObjectFunctions;
-
- QTest::addRow("negative: not a QObject")
- << QByteArray("int main() { QObject::connect(dummy, NotAQObject::")
- << QByteArrayList{"notASignal", "alsoNotASignal", "connect", "NotAQObject",
- "~NotAQObject", "operator="};
-}
-
-
-void ClangCodeCompletionTest::testSignalCompletion()
-{
- QFETCH(QByteArray, customContents);
- QFETCH(QByteArrayList, hits);
-
- const QByteArray contents = makeSignalCompletionContents(customContents);
- const ProjectLessCompletionTest t("signalcompletion.cpp", {}, {}, contents);
-
- QVERIFY(t.proposal);
- QCOMPARE(t.proposal->size(), hits.size());
- for (const QByteArray &hit : qAsConst(hits))
- QVERIFY(hasItem(t.proposal, hit));
-}
-
-} // namespace Tests
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h
deleted file mode 100644
index ad2dd83ada2..00000000000
--- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QObject>
-
-namespace ClangCodeModel {
-namespace Internal {
-namespace Tests {
-
-class ActivateClangModelManagerSupport;
-
-class ClangCodeCompletionTest : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase();
-
- void testCompleteDoxygenKeywords();
- void testCompletePreprocessorKeywords();
- void testCompleteIncludeDirective();
-
- void testCompleteGlobals();
- void testCompleteMembers();
- void testCompleteMembersFromInside();
- void testCompleteMembersFromOutside();
- void testCompleteMembersFromFriend();
- void testCompleteFunctions();
- void testCompleteOverloads();
- void testCompleteConstructor();
- void testCompleteClassAndConstructor();
-
- void testCompleteWithDotToArrowCorrection();
- void testDontCompleteWithDotToArrowCorrectionForFloats();
-
- void testCompleteProjectDependingCode();
- void testCompleteProjectDependingCodeAfterChangingProject();
- void testCompleteProjectDependingCodeInGeneratedUiFile();
-
- void testSignalCompletion_data();
- void testSignalCompletion();
-};
-
-} // namespace Tests
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp
index e22f2dc6fff..244cef4cba3 100644
--- a/src/plugins/clangcodemodel/test/clangdtests.cpp
+++ b/src/plugins/clangcodemodel/test/clangdtests.cpp
@@ -25,12 +25,10 @@
#include "clangdtests.h"
-#include "clangautomationutils.h"
#include "clangbatchfileprocessor.h"
#include "../clangdclient.h"
#include "../clangmodelmanagersupport.h"
-#include <clangsupport/sourcelocationscontainer.h>
#include <cplusplus/FindUsages.h>
#include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/cpptoolsreuse.h>
@@ -83,6 +81,11 @@ namespace ClangCodeModel {
namespace Internal {
namespace Tests {
+static QString qrcPath(const QByteArray &relativeFilePath)
+{
+ return QLatin1String(":/unittests/ClangCodeModel/") + QString::fromUtf8(relativeFilePath);
+}
+
ClangdTest::~ClangdTest()
{
EditorManager::closeAllEditors(false);
@@ -171,6 +174,7 @@ void ClangdTest::initTestCase()
QVERIFY(doc);
QVERIFY2(m_client->documentForFilePath(sourceFilePath) == doc,
qPrintable(sourceFilePath.toUserOutput()));
+ doc->setSuspendAllowed(false);
m_sourceDocuments.insert(sourceFileName, doc);
}
}
@@ -234,8 +238,6 @@ void ClangdTestFindReferences::test_data()
ItemList pureVirtualRefs{makeItem(17, 17, Usage::Type::Declaration),
makeItem(21, 9, Usage::Type::Declaration)};
- if (client()->versionNumber() < QVersionNumber(14))
- pureVirtualRefs << pureVirtualRefs.last();
QTest::newRow("pure virtual declaration") << "defs.h" << 420 << pureVirtualRefs;
QTest::newRow("pointer variable") << "main.cpp" << 52 << ItemList{
@@ -396,8 +398,6 @@ void ClangdTestFollowSymbol::test()
timer.stop();
QCOMPARE(actualLink.targetFilePath, filePath(targetFile));
- if (client()->versionNumber() < QVersionNumber(14))
- QEXPECT_FAIL("union member ref", "https://github.com/clangd/clangd/issues/877", Abort);
QCOMPARE(actualLink.targetLine, targetLine);
QCOMPARE(actualLink.targetColumn + 1, targetColumn);
}
@@ -419,9 +419,9 @@ void ClangdTestLocalReferences::test_data()
QTest::addColumn<QList<Range>>("expectedRanges");
QTest::newRow("cursor not on identifier") << 3 << 5 << QList<Range>();
- QTest::newRow("local variable, one use") << 3 << 9 << QList<Range>{{3, 9, 3}};
+ QTest::newRow("local variable, one use") << 3 << 9 << QList<Range>{{3, 8, 3}};
QTest::newRow("local variable, two uses") << 10 << 9
- << QList<Range>{{10, 9, 3}, {11, 12, 3}};
+ << QList<Range>{{10, 8, 3}, {11, 11, 3}};
QTest::newRow("class name") << 16 << 7 << QList<Range>()
/* QList<Range>{{16, 7, 3}, {19, 5, 3}} */;
QTest::newRow("namespace") << 24 << 11 << QList<Range>()
@@ -433,9 +433,9 @@ void ClangdTestLocalReferences::test_data()
QTest::newRow("class name and new expression") << 40 << 7 << QList<Range>()
/* QList<Range>{{40, 7, 3}, {43, 9, 3}} */;
QTest::newRow("instantiated template object") << 52 << 19
- << QList<Range>{{52, 19, 3}, {53, 5, 3}};
+ << QList<Range>{{52, 18, 3}, {53, 4, 3}};
QTest::newRow("variable in template") << 62 << 13
- << QList<Range>{{62, 13, 3}, {63, 11, 3}};
+ << QList<Range>{{62, 12, 3}, {63, 10, 3}};
QTest::newRow("member in template") << 67 << 7 << QList<Range>()
/* QList<Range>{{64, 16, 3}, {67, 7, 3}} */;
QTest::newRow("template type") << 58 << 19 << QList<Range>()
@@ -454,9 +454,9 @@ void ClangdTestLocalReferences::test_data()
QTest::newRow("enum type") << 112 << 6 << QList<Range>()
/* QList<Range>{{112, 6, 2}, {113, 8, 2}} */;
QTest::newRow("captured lambda var") << 122 << 15
- << QList<Range>{{122, 15, 3}, {122, 33, 3}};
+ << QList<Range>{{122, 14, 3}, {122, 32, 3}};
QTest::newRow("lambda initializer") << 122 << 19
- << QList<Range>{{121, 19, 3}, {122, 19, 3}};
+ << QList<Range>{{121, 18, 3}, {122, 18, 3}};
QTest::newRow("template specialization") << 127 << 25 << QList<Range>()
/* QList<Range>{{127, 5, 3}, {128, 25, 3}, {129, 18, 3}} */;
QTest::newRow("dependent name") << 133 << 34 << QList<Range>()
@@ -468,16 +468,16 @@ void ClangdTestLocalReferences::test_data()
QTest::newRow("function-like macro") << 155 << 9 << QList<Range>()
/* QList<Range>{{155, 9, 3}, {158, 12, 3}} */;
QTest::newRow("argument to function-like macro") << 156 << 27
- << QList<Range>{{156, 27, 3}, {158, 16, 3}};
+ << QList<Range>{{156, 26, 3}, {158, 15, 3}};
QTest::newRow("overloaded bracket operator argument") << 172 << 7
- << QList<Range>{{171, 7, 1}, {172, 7, 1}, {172, 12, 1},
- {173, 7, 1}, {173, 10, 1}};
+ << QList<Range>{{171, 6, 1}, {172, 6, 1}, {172, 11, 1},
+ {173, 6, 1}, {173, 9, 1}};
QTest::newRow("overloaded call operator second argument") << 173 << 10
- << QList<Range>{{171, 7, 1}, {172, 7, 1}, {172, 12, 1},
- {173, 7, 1}, {173, 10, 1}};
+ << QList<Range>{{171, 6, 1}, {172, 6, 1}, {172, 11, 1},
+ {173, 6, 1}, {173, 9, 1}};
QTest::newRow("overloaded operators arguments from outside") << 171 << 7
- << QList<Range>{{171, 7, 1}, {172, 7, 1}, {172, 12, 1},
- {173, 7, 1}, {173, 10, 1}};
+ << QList<Range>{{171, 6, 1}, {172, 6, 1}, {172, 11, 1},
+ {173, 6, 1}, {173, 9, 1}};
}
void ClangdTestLocalReferences::test()
@@ -495,11 +495,9 @@ void ClangdTestLocalReferences::test()
QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
QList<Range> actualRanges;
const auto handler = [&actualRanges, &loop](const QString &symbol,
- const ClangBackEnd::SourceLocationsContainer &container, int) {
- for (const ClangBackEnd::SourceLocationContainer &c
- : container.m_sourceLocationContainers) {
- actualRanges << Range(c.line, c.column, symbol.length());
- }
+ const Utils::Links &links, int) {
+ for (const Utils::Link &link : links)
+ actualRanges << Range(link.targetLine, link.targetColumn, symbol.length());
loop.quit();
};
@@ -623,11 +621,6 @@ void ClangdTestTooltips::test()
QCOMPARE(editor->document(), doc);
QVERIFY(editor->editorWidget());
- if (client()->versionNumber() < QVersionNumber(14)
- && QLatin1String(QTest::currentDataTag()) == QLatin1String("IncludeDirective")) {
- QSKIP("clangd <= 13 sends empty or no hover data for includes");
- }
-
QTimer timer;
timer.setSingleShot(true);
QEventLoop loop;
@@ -650,10 +643,8 @@ void ClangdTestTooltips::test()
timer.stop();
QEXPECT_FAIL("TypeName_ResolveTemplateTypeAlias", "typedef already resolved in AST", Abort);
- if (client()->versionNumber() >= QVersionNumber(14)) {
- QEXPECT_FAIL("TypeNameIntroducedByUsingDeclarationQualified",
- "https://github.com/clangd/clangd/issues/989", Abort);
- }
+ QEXPECT_FAIL("TypeNameIntroducedByUsingDeclarationQualified",
+ "https://github.com/clangd/clangd/issues/989", Abort);
QCOMPARE(int(helpItem.category()), expectedCategory);
QEXPECT_FAIL("TemplateClassQualified", "Additional look-up needed?", Abort);
QCOMPARE(helpItem.helpIds(), expectedIds);
@@ -898,11 +889,11 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("closing angle bracket in class template declaration") << 261 << 18 << 261 << 19
<< QList<int>{C_PUNCTUATION} << int(CppEditor::SemanticHighlighter::AngleBracketClose);
QTest::newRow("macro definition") << 231 << 9 << 231 << 31
- << QList<int>{C_PREPROCESSOR, C_DECLARATION} << 0;
+ << QList<int>{C_MACRO, C_DECLARATION} << 0;
QTest::newRow("function-like macro definition") << 232 << 9 << 232 << 24
- << QList<int>{C_PREPROCESSOR, C_DECLARATION} << 0;
+ << QList<int>{C_MACRO, C_DECLARATION} << 0;
QTest::newRow("function-like macro call") << 236 << 5 << 236 << 20
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("function-like macro call argument 1") << 236 << 21 << 236 << 22
<< QList<int>{C_NUMBER} << 0;
QTest::newRow("function-like macro call argument 2") << 236 << 24 << 236 << 25
@@ -1063,7 +1054,7 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("using declaration for function template") << 584 << 10 << 584 << 16
<< QList<int>{C_FUNCTION} << 0;
QTest::newRow("Q_PROPERTY (macro name)") << 599 << 5 << 599 << 15
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("Q_PROPERTY (property name)") << 599 << 52 << 599 << 56
<< QList<int>{C_FIELD} << 0;
QTest::newRow("Q_PROPERTY (READ keyword)") << 599 << 57 << 599 << 61
@@ -1087,7 +1078,7 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("Q_PROPERTY (REVISION keyword [new])") << 600 << 46 << 600 << 54
<< QList<int>{C_KEYWORD} << 0;
QTest::newRow("multi-line Q_PROPERTY (macro name)") << 704 << 5 << 704 << 15
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("multi-line Q_PROPERTY (property name)") << 718 << 13 << 718 << 17
<< QList<int>{C_FIELD} << 0;
QTest::newRow("multi-line Q_PROPERTY (getter)") << 722 << 13 << 722 << 20
@@ -1095,19 +1086,19 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("multi-line Q_PROPERTY (notifier)") << 730 << 13 << 730 << 24
<< QList<int>{C_FUNCTION} << 0;
QTest::newRow("old-style signal (macro)") << 672 << 5 << 672 << 11
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("old-style signal (signal)") << 672 << 12 << 672 << 21
<< QList<int>{C_FUNCTION} << 0;
QTest::newRow("old-style signal (signal parameter)") << 672 << 22 << 672 << 29
<< QList<int>{C_TYPE} << 0;
QTest::newRow("old-style slot (macro)") << 673 << 5 << 673 << 9
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("old-style slot (slot)") << 673 << 10 << 673 << 19
<< QList<int>{C_FUNCTION} << 0;
QTest::newRow("old-style slot (slot parameter)") << 673 << 20 << 673 << 27
<< QList<int>{C_TYPE} << 0;
QTest::newRow("old-style signal with complex parameter (macro)") << 674 << 5 << 674 << 11
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("old-style signal with complex parameter (signal)") << 674 << 12 << 674 << 21
<< QList<int>{C_FUNCTION} << 0;
QTest::newRow("old-style signal with complex parameter (signal parameter part 1)")
@@ -1255,7 +1246,7 @@ void ClangdTestHighlighting::test_data()
<< QList<int>{C_PUNCTUATION} << int(CppEditor::SemanticHighlighter::AngleBracketClose);
QTest::newRow("cyrillic string") << 792 << 24 << 792 << 27 << QList<int>{C_STRING} << 0;
QTest::newRow("macro in struct") << 795 << 9 << 795 << 14
- << QList<int>{C_PREPROCESSOR, C_DECLARATION} << 0;
+ << QList<int>{C_MACRO, C_DECLARATION} << 0;
QTest::newRow("#ifdef'ed out code") << 800 << 1 << 800 << 17
<< QList<int>{C_DISABLED_CODE} << 0;
QTest::newRow("static function call (object)") << 819 << 5 << 819 << 6
@@ -1307,11 +1298,11 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("output arg") << 945 << 20 << 945 << 23
<< QList<int>{C_LOCAL, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("built-in define 1") << 950 << 21 << 950 << 29
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("built-in define 2") << 951 << 21 << 951 << 33
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("built-in define 3") << 952 << 21 << 952 << 40
- << QList<int>{C_PREPROCESSOR} << 0;
+ << QList<int>{C_MACRO} << 0;
QTest::newRow("deref operator (object)") << 960 << 10 << 960 << 11 << QList<int>{C_LOCAL} << 0;
QTest::newRow("deref operator (member)") << 960 << 12 << 960 << 13 << QList<int>{C_FIELD} << 0;
QTest::newRow("nested call") << 979 << 20 << 979 << 21 << QList<int>{C_LOCAL} << 0;
@@ -1372,11 +1363,6 @@ void ClangdTestHighlighting::test()
};
const TextEditor::HighlightingResults results = findResults();
- if (client()->versionNumber() < QVersionNumber(14)) {
- QEXPECT_FAIL("typedef as underlying type in enum declaration",
- "https://github.com/clangd/clangd/issues/878",
- Abort);
- }
QEXPECT_FAIL("old-style signal (signal)", "check if and how we want to support this", Abort);
QEXPECT_FAIL("old-style signal (signal parameter)",
"check if and how we want to support this", Abort);
@@ -1413,17 +1399,6 @@ void ClangdTestHighlighting::test()
actualStyles << s;
}
-
- if (client()->versionNumber() < QVersionNumber(14)) {
- QEXPECT_FAIL("final virtual function call via pointer",
- "clangd < 14 does not send virtual modifier", Continue);
- QEXPECT_FAIL("virtual member function definition outside of class body",
- "clangd < 14 does not send virtual modifier", Continue);
- QEXPECT_FAIL("virtual function call via pointer",
- "clangd < 14 does not send virtual modifier", Continue);
- QEXPECT_FAIL("non-final virtual function call via pointer",
- "clangd < 14 does not send virtual modifier", Continue);
- }
QEXPECT_FAIL("non-const reference via member function call as output argument (object)",
"See below", Continue);
QEXPECT_FAIL("non-const reference via member function call as output argument (function)",
@@ -1579,15 +1554,9 @@ void ClangdTestCompletion::testCompleteIncludeDirective()
getProposal("includeDirectiveCompletion.cpp", proposal);
QVERIFY(proposal);
- if (client()->versionNumber() < QVersionNumber(14)) {
- QVERIFY(hasItem(proposal, "file.h"));
- QVERIFY(hasItem(proposal, "otherFile.h"));
- QVERIFY(hasItem(proposal, "mylib/"));
- } else {
- QVERIFY(hasItem(proposal, " file.h>"));
- QVERIFY(hasItem(proposal, " otherFile.h>"));
- QVERIFY(hasItem(proposal, " mylib/"));
- }
+ QVERIFY(hasItem(proposal, " file.h>"));
+ QVERIFY(hasItem(proposal, " otherFile.h>"));
+ QVERIFY(hasItem(proposal, " mylib/"));
QVERIFY(!hasSnippet(proposal, "class "));
}
@@ -1885,10 +1854,6 @@ void ClangdTestCompletion::testSignalCompletion()
getProposal("signalCompletion.cpp", proposal, customCode);
QVERIFY(proposal);
- if (client()->versionNumber() < QVersionNumber(14)
- && QString::fromLatin1(QTest::currentDataTag()).startsWith("positive:")) {
- QEXPECT_FAIL("", "Signal info in completions requires clangd >= 14", Abort);
- }
QCOMPARE(proposal->size(), expectedSuggestions.size());
for (const QString &expectedSuggestion : qAsConst(expectedSuggestions))
QVERIFY2(hasItem(proposal, ' ' + expectedSuggestion), qPrintable(expectedSuggestion));
diff --git a/src/plugins/clangcodemodel/test/clangfixittest.cpp b/src/plugins/clangcodemodel/test/clangfixittest.cpp
new file mode 100644
index 00000000000..6377f65802f
--- /dev/null
+++ b/src/plugins/clangcodemodel/test/clangfixittest.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangfixittest.h"
+
+#include "../clangfixitoperation.h"
+
+#include <utils/changeset.h>
+
+#include <QFile>
+#include <QtTest>
+#include <QVector>
+
+namespace ClangCodeModel::Internal::Tests {
+
+static QString qrcPath(const QString &relativeFilePath)
+{
+ return QLatin1String(":/unittests/ClangCodeModel/") + relativeFilePath;
+}
+
+static QString diagnosticText() { return QString("expected ';' at end of declaration"); }
+
+void ClangFixItTest::testDescription()
+{
+ ClangFixItOperation operation(diagnosticText(), {semicolonFixIt()});
+ QCOMPARE(operation.description(),
+ QLatin1String("Apply Fix: expected ';' at end of declaration"));
+}
+
+Utils::FilePath ClangFixItTest::semicolonFilePath() const
+{
+ return Utils::FilePath::fromString(m_dataDir->absolutePath("diagnostic_semicolon_fixit.cpp"));
+}
+
+Utils::FilePath ClangFixItTest::compareFilePath() const
+{
+ return Utils::FilePath::fromString(m_dataDir->absolutePath("diagnostic_comparison_fixit.cpp"));
+}
+
+QString ClangFixItTest::fileContent(const QByteArray &relFilePath) const
+{
+ QFile file(m_dataDir->absolutePath(relFilePath));
+ const bool isOpen = file.open(QFile::ReadOnly | QFile::Text);
+ if (!isOpen)
+ qDebug() << "File with the unsaved content cannot be opened!";
+ return QString::fromUtf8(file.readAll());
+}
+
+ClangFixIt ClangFixItTest::semicolonFixIt() const
+{
+ return {";", {{semicolonFilePath(), 3u, 12u}, {semicolonFilePath(), 3u, 12u}}};
+}
+
+void ClangFixItTest::init()
+{
+ m_dataDir.reset(new CppEditor::Tests::TemporaryCopiedDir(qrcPath("fixits")));
+}
+
+void ClangFixItTest::testAppendSemicolon()
+{
+ ClangFixItOperation operation(diagnosticText(), {semicolonFixIt()});
+ operation.perform();
+ QCOMPARE(operation.firstRefactoringFileContent_forTestOnly(),
+ fileContent("diagnostic_semicolon_fixit_expected.cpp"));
+}
+
+void ClangFixItTest::testComparisonVersusAssignmentChooseComparison()
+{
+ const ClangFixIt compareFixIt{"==", {{compareFilePath(), 4u, 10u},
+ {compareFilePath(), 4u, 11u}}};
+ ClangFixItOperation operation(diagnosticText(), {compareFixIt});
+ operation.perform();
+ QCOMPARE(operation.firstRefactoringFileContent_forTestOnly(),
+ fileContent("diagnostic_comparison_fixit_expected1.cpp"));
+}
+
+void ClangFixItTest::testComparisonVersusAssignmentChooseParentheses()
+{
+ const ClangFixIt assignmentFixItParenLeft{"(", {{compareFilePath(), 4u, 8u},
+ {compareFilePath(), 4u, 8u}}};
+ const ClangFixIt assignmentFixItParenRight{")", {{compareFilePath(), 4u, 13u},
+ {compareFilePath(), 4u, 13u}}};
+ ClangFixItOperation operation(diagnosticText(), {assignmentFixItParenLeft,
+ assignmentFixItParenRight});
+ operation.perform();
+ QCOMPARE(operation.firstRefactoringFileContent_forTestOnly(),
+ fileContent("diagnostic_comparison_fixit_expected2.cpp"));
+}
+
+} // namespace ClangCodeModel::Internal::Tests
diff --git a/src/plugins/clangcodemodel/test/clangfixittest.h b/src/plugins/clangcodemodel/test/clangfixittest.h
new file mode 100644
index 00000000000..0d71de70a09
--- /dev/null
+++ b/src/plugins/clangcodemodel/test/clangfixittest.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <cppeditor/cpptoolstestcase.h>
+
+#include <QObject>
+#include <QScopedPointer>
+#include <QString>
+
+namespace Utils { class FilePath; }
+
+namespace ClangCodeModel::Internal {
+class ClangFixIt;
+
+namespace Tests {
+
+class ClangFixItTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void init();
+ void testAppendSemicolon();
+ void testComparisonVersusAssignmentChooseComparison();
+ void testComparisonVersusAssignmentChooseParentheses();
+ void testDescription();
+
+private:
+ Utils::FilePath semicolonFilePath() const;
+ Utils::FilePath compareFilePath() const;
+ QString fileContent(const QByteArray &relFilePath) const;
+
+ ClangFixIt semicolonFixIt() const;
+
+private:
+ QScopedPointer<CppEditor::Tests::TemporaryCopiedDir> m_dataDir;
+};
+
+} //namespace Tests
+} // namespace ClangCodeModel::Internal
diff --git a/src/plugins/clangcodemodel/test/data/clangtestdata.qrc b/src/plugins/clangcodemodel/test/data/clangtestdata.qrc
index 9dcc3fbae15..1ee4bdee92c 100644
--- a/src/plugins/clangcodemodel/test/data/clangtestdata.qrc
+++ b/src/plugins/clangcodemodel/test/data/clangtestdata.qrc
@@ -55,5 +55,10 @@
<file>completion/preprocessorKeywordsCompletion3.cpp</file>
<file>completion/privateFuncDefCompletion.cpp</file>
<file>highlighting/highlightingmarks.h</file>
+ <file>fixits/diagnostic_comparison_fixit_expected1.cpp</file>
+ <file>fixits/diagnostic_comparison_fixit_expected2.cpp</file>
+ <file>fixits/diagnostic_comparison_fixit.cpp</file>
+ <file>fixits/diagnostic_semicolon_fixit_expected.cpp</file>
+ <file>fixits/diagnostic_semicolon_fixit.cpp</file>
</qresource>
</RCC>
diff --git a/src/plugins/clangcodemodel/test/data/completion/completion.pro b/src/plugins/clangcodemodel/test/data/completion/completion.pro
index 832b9aac07f..a249b163393 100644
--- a/src/plugins/clangcodemodel/test/data/completion/completion.pro
+++ b/src/plugins/clangcodemodel/test/data/completion/completion.pro
@@ -27,7 +27,7 @@ SOURCES = \
privateFuncDefCompletion.cpp \
signalCompletion.cpp
-QMAKE_CXXFLAGS += -ffoo
+QMAKE_CXXFLAGS += -broken
HEADERS = mainwindow.h
FORMS = mainwindow.ui
diff --git a/src/plugins/clangcodemodel/test/data/find-usages/find-usages.pro b/src/plugins/clangcodemodel/test/data/find-usages/find-usages.pro
index cf511fee40a..e2b4ace37b3 100644
--- a/src/plugins/clangcodemodel/test/data/find-usages/find-usages.pro
+++ b/src/plugins/clangcodemodel/test/data/find-usages/find-usages.pro
@@ -2,4 +2,4 @@ TEMPLATE = app
QT = core
HEADERS = defs.h
SOURCES = main.cpp
-QMAKE_CXXFLAGS += -ffoo
+QMAKE_CXXFLAGS += -broken
diff --git a/tests/unit/unittest/data/diagnostic_comparison_fixit.cpp b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit.cpp
index 016356c24b8..016356c24b8 100644
--- a/tests/unit/unittest/data/diagnostic_comparison_fixit.cpp
+++ b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit.cpp
diff --git a/tests/unit/unittest/data/diagnostic_comparison_fixit_expected1.cpp b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit_expected1.cpp
index 92d0cfd23ca..92d0cfd23ca 100644
--- a/tests/unit/unittest/data/diagnostic_comparison_fixit_expected1.cpp
+++ b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit_expected1.cpp
diff --git a/tests/unit/unittest/data/diagnostic_comparison_fixit_expected2.cpp b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit_expected2.cpp
index 233dd48075f..233dd48075f 100644
--- a/tests/unit/unittest/data/diagnostic_comparison_fixit_expected2.cpp
+++ b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_comparison_fixit_expected2.cpp
diff --git a/tests/unit/unittest/data/diagnostic_semicolon_fixit.cpp b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_semicolon_fixit.cpp
index 8b7eb2c657c..8b7eb2c657c 100644
--- a/tests/unit/unittest/data/diagnostic_semicolon_fixit.cpp
+++ b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_semicolon_fixit.cpp
diff --git a/tests/unit/unittest/data/diagnostic_semicolon_fixit_expected.cpp b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_semicolon_fixit_expected.cpp
index b13ee73c5f1..b13ee73c5f1 100644
--- a/tests/unit/unittest/data/diagnostic_semicolon_fixit_expected.cpp
+++ b/src/plugins/clangcodemodel/test/data/fixits/diagnostic_semicolon_fixit_expected.cpp
diff --git a/src/plugins/clangcodemodel/test/data/follow-symbol/follow-symbol.pro b/src/plugins/clangcodemodel/test/data/follow-symbol/follow-symbol.pro
index 8b0d6d1879b..9f9dee988b3 100644
--- a/src/plugins/clangcodemodel/test/data/follow-symbol/follow-symbol.pro
+++ b/src/plugins/clangcodemodel/test/data/follow-symbol/follow-symbol.pro
@@ -2,4 +2,4 @@ TEMPLATE = app
CONFIG -= qt
HEADERS = cursor.h header.h
SOURCES = cursor.cpp main.cpp
-QMAKE_CXXFLAGS += -ffoo
+QMAKE_CXXFLAGS += -broken
diff --git a/src/plugins/clangcodemodel/test/data/highlighting/highlighting.pro b/src/plugins/clangcodemodel/test/data/highlighting/highlighting.pro
index 32196b9724f..33722d7d67b 100644
--- a/src/plugins/clangcodemodel/test/data/highlighting/highlighting.pro
+++ b/src/plugins/clangcodemodel/test/data/highlighting/highlighting.pro
@@ -1,4 +1,4 @@
TEMPLATE = app
CONFIG -= qt
SOURCES = highlighting.cpp
-QMAKE_CXXFLAGS += -ffoo
+QMAKE_CXXFLAGS += -broken
diff --git a/src/plugins/clangcodemodel/test/data/local-references/local-references.pro b/src/plugins/clangcodemodel/test/data/local-references/local-references.pro
index f47c1c68154..3fa3891018a 100644
--- a/src/plugins/clangcodemodel/test/data/local-references/local-references.pro
+++ b/src/plugins/clangcodemodel/test/data/local-references/local-references.pro
@@ -1,4 +1,4 @@
TEMPLATE = app
CONFIG -= qt
SOURCES = references.cpp
-QMAKE_CXXFLAGS += -ffoo
+QMAKE_CXXFLAGS += -broken
diff --git a/src/plugins/clangformat/CMakeLists.txt b/src/plugins/clangformat/CMakeLists.txt
index dbeaed94888..3c648da5923 100644
--- a/src/plugins/clangformat/CMakeLists.txt
+++ b/src/plugins/clangformat/CMakeLists.txt
@@ -1,7 +1,6 @@
add_qtc_plugin(ClangFormat
- CONDITION TARGET libclang AND LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 10.0.0 AND (QTC_CLANG_BUILDMODE_MATCH OR CLANGTOOLING_LINK_CLANG_DYLIB)
+ CONDITION TARGET ${CLANG_FORMAT_LIB} AND LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 10.0.0 AND (QTC_CLANG_BUILDMODE_MATCH OR CLANGTOOLING_LINK_CLANG_DYLIB)
DEPENDS Utils Qt5::Widgets ${CLANG_FORMAT_LIB}
- INCLUDES "${CLANG_INCLUDE_DIRS}"
PLUGIN_DEPENDS Core TextEditor CppEditor ProjectExplorer
SOURCES
clangformatbaseindenter.cpp clangformatbaseindenter.h
@@ -15,6 +14,11 @@ add_qtc_plugin(ClangFormat
clangformatutils.cpp clangformatutils.h
)
+if(TARGET ClangFormat)
+ # "system" includes, so warnings are ignored
+ target_include_directories(ClangFormat SYSTEM PRIVATE "${CLANG_INCLUDE_DIRS}")
+endif()
+
if(MSVC AND TARGET ClangFormat)
target_compile_options(ClangFormat PUBLIC /wd4267 /wd4624)
endif()
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp
index d9e36e3717a..4ee5daebdba 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.cpp
+++ b/src/plugins/clangformat/clangformatbaseindenter.cpp
@@ -24,8 +24,17 @@
****************************************************************************/
#include "clangformatbaseindenter.h"
+#include "clangformatconstants.h"
+#include "clangformatsettings.h"
#include "clangformatutils.h"
+#include <coreplugin/icore.h>
+#include <projectexplorer/editorconfiguration.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
+#include <texteditor/icodestylepreferences.h>
+#include <texteditor/texteditorsettings.h>
+
#include <clang/Tooling/Core/Replacement.h>
#include <utils/algorithm.h>
@@ -57,7 +66,6 @@ void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
return;
- style.DisableFormat = false;
style.ColumnLimit = 0;
#ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED
style.KeepLineBreaksForNonEmptyLines = true;
@@ -727,14 +735,43 @@ void ClangFormatBaseIndenter::autoIndent(const QTextCursor &cursor,
clang::format::FormatStyle ClangFormatBaseIndenter::styleForFile() const
{
- llvm::Expected<clang::format::FormatStyle> style
- = clang::format::getStyle("file", m_fileName.toString().toStdString(), "none");
- if (style) {
- addQtcStatementMacros(*style);
- return *style;
+ llvm::Expected<clang::format::FormatStyle> styleFromProjectFolder
+ = clang::format::getStyle("file", m_fileName.path().toStdString(), "none");
+
+ const ProjectExplorer::Project *projectForFile
+ = ProjectExplorer::SessionManager::projectForFile(m_fileName);
+ const bool overrideStyleFile
+ = projectForFile ? projectForFile->namedSettings(Constants::OVERRIDE_FILE_ID).toBool()
+ : ClangFormatSettings::instance().overrideDefaultFile();
+ const TextEditor::ICodeStylePreferences *preferences
+ = projectForFile
+ ? projectForFile->editorConfiguration()->codeStyle("Cpp")->currentPreferences()
+ : TextEditor::TextEditorSettings::codeStyle("Cpp")->currentPreferences();
+
+ if (overrideStyleFile || !styleFromProjectFolder
+ || *styleFromProjectFolder == clang::format::getNoStyle()) {
+ Utils::FilePath filePath = filePathToCurrentSettings(preferences);
+
+ if (!filePath.exists())
+ return qtcStyle();
+
+ clang::format::FormatStyle currentSettingsStyle;
+ currentSettingsStyle.Language = clang::format::FormatStyle::LK_Cpp;
+ const std::error_code error
+ = clang::format::parseConfiguration(filePath.fileContents().toStdString(),
+ &currentSettingsStyle);
+ QTC_ASSERT(error.value() == static_cast<int>(clang::format::ParseError::Success),
+ return qtcStyle());
+
+ return currentSettingsStyle;
+ }
+
+ if (styleFromProjectFolder) {
+ addQtcStatementMacros(*styleFromProjectFolder);
+ return *styleFromProjectFolder;
}
- handleAllErrors(style.takeError(), [](const llvm::ErrorInfoBase &) {
+ handleAllErrors(styleFromProjectFolder.takeError(), [](const llvm::ErrorInfoBase &) {
// do nothing
});
diff --git a/src/plugins/clangformat/clangformatbaseindenter.h b/src/plugins/clangformat/clangformatbaseindenter.h
index 14c54db7609..0b96451aca0 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.h
+++ b/src/plugins/clangformat/clangformatbaseindenter.h
@@ -68,8 +68,9 @@ public:
Utils::optional<int> margin() const override;
+ clang::format::FormatStyle styleForFile() const;
+
protected:
- virtual clang::format::FormatStyle styleForFile() const;
virtual bool formatCodeInsteadOfIndent() const { return false; }
virtual bool formatWhileTyping() const { return false; }
virtual int lastSaveRevision() const { return 0; }
diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp
index d6fa8721b1c..e3e7629065b 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.cpp
+++ b/src/plugins/clangformat/clangformatconfigwidget.cpp
@@ -43,7 +43,9 @@
#include <extensionsystem/pluginspec.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
+#include <projectexplorer/editorconfiguration.h>
#include <texteditor/displaysettings.h>
+#include <texteditor/icodestylepreferences.h>
#include <texteditor/snippets/snippeteditor.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditorsettings.h>
@@ -60,36 +62,6 @@ using namespace ProjectExplorer;
namespace ClangFormat {
-static const char kFileSaveWarning[]
- = "Disable formatting on file save in the Beautifier plugin to enable this check";
-
-static bool isBeautifierPluginActivated()
-{
- const QVector<ExtensionSystem::PluginSpec *> specs = ExtensionSystem::PluginManager::plugins();
- return std::find_if(specs.begin(),
- specs.end(),
- [](ExtensionSystem::PluginSpec *spec) {
- return spec->name() == "Beautifier";
- })
- != specs.end();
-}
-
-static bool isBeautifierOnSaveActivated()
-{
- if (!isBeautifierPluginActivated())
- return false;
-
- QSettings *s = Core::ICore::settings();
- bool activated = false;
- s->beginGroup(Utils::Constants::BEAUTIFIER_SETTINGS_GROUP);
- s->beginGroup(Utils::Constants::BEAUTIFIER_GENERAL_GROUP);
- if (s->value(Utils::Constants::BEAUTIFIER_AUTO_FORMAT_ON_SAVE, false).toBool())
- activated = true;
- s->endGroup();
- s->endGroup();
- return activated;
-}
-
bool ClangFormatConfigWidget::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::Wheel && qobject_cast<QComboBox *>(object)) {
@@ -99,55 +71,24 @@ bool ClangFormatConfigWidget::eventFilter(QObject *object, QEvent *event)
return QWidget::eventFilter(object, event);
}
-void ClangFormatConfigWidget::showEvent(QShowEvent *event)
-{
- TextEditor::CodeStyleEditorWidget::showEvent(event);
- if (isBeautifierOnSaveActivated()) {
- bool wasEnabled = m_ui->formatOnSave->isEnabled();
- m_ui->formatOnSave->setChecked(false);
- m_ui->formatOnSave->setEnabled(false);
- m_ui->fileSaveWarning->setText(tr(kFileSaveWarning));
- if (wasEnabled)
- apply();
- } else {
- m_ui->formatOnSave->setEnabled(true);
- m_ui->fileSaveWarning->setText("");
- }
-}
-
-ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *project, QWidget *parent)
+ClangFormatConfigWidget::ClangFormatConfigWidget(TextEditor::ICodeStylePreferences *codeStyle,
+ ProjectExplorer::Project *project,
+ QWidget *parent)
: CppCodeStyleWidget(parent)
, m_project(project)
, m_checks(std::make_unique<Ui::ClangFormatChecksWidget>())
, m_ui(std::make_unique<Ui::ClangFormatConfigWidget>())
{
m_ui->setupUi(this);
+ m_config = std::make_unique<ClangFormatFile>(filePathToCurrentSettings(codeStyle),
+ codeStyle->isReadOnly());
- Utils::FilePath filePath = Core::ICore::userResourcePath();
- if (m_project)
- filePath = filePath / "clang-format/" / currentProjectUniqueId();
- filePath = filePath / QLatin1String(Constants::SETTINGS_FILE_NAME);
- m_config = std::make_unique<ClangFormatFile>(filePath);
-
- initChecksAndPreview();
+ initChecksAndPreview(!codeStyle->isReadOnly());
+ initOverrideCheckBox();
+ initCheckBoxes();
+ initIndentationOrFormattingCombobox();
- m_ui->applyButton->show();
- if (m_project) {
- hideGlobalCheckboxes();
- m_ui->fallbackConfig->hide();
- m_ui->overrideDefault->setChecked(
- m_project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool());
- } else {
- showGlobalCheckboxes();
- m_ui->overrideDefault->setChecked(ClangFormatSettings::instance().overrideDefaultFile());
- m_ui->overrideDefault->setToolTip(
- tr("Override Clang Format configuration file with the fallback configuration."));
- }
-
- connect(m_ui->overrideDefault, &QCheckBox::toggled,
- this, &ClangFormatConfigWidget::showOrHideWidgets);
showOrHideWidgets();
-
fillTable();
updatePreview();
@@ -156,13 +97,14 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *proje
ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
-void ClangFormatConfigWidget::initChecksAndPreview()
+void ClangFormatConfigWidget::initChecksAndPreview(bool enabled)
{
m_checksScrollArea = new QScrollArea();
m_checksWidget = new QWidget;
m_checks->setupUi(m_checksWidget);
m_checksScrollArea->setWidget(m_checksWidget);
m_checksScrollArea->setMaximumWidth(500);
+ m_checksWidget->setEnabled(enabled);
m_ui->horizontalLayout_2->addWidget(m_checksScrollArea);
@@ -178,7 +120,6 @@ void ClangFormatConfigWidget::initChecksAndPreview()
m_preview->textDocument()->setSyntaxHighlighter(new CppEditor::CppHighlighter);
Utils::FilePath fileName;
- connect(m_ui->applyButton, &QPushButton::clicked, this, &ClangFormatConfigWidget::apply);
if (m_project) {
fileName = m_project->projectFilePath().pathAppended("snippet.cpp");
} else {
@@ -188,6 +129,68 @@ void ClangFormatConfigWidget::initChecksAndPreview()
m_preview->textDocument()->indenter()->setFileName(fileName);
}
+void ClangFormatConfigWidget::initCheckBoxes()
+{
+ if (m_project) {
+ m_ui->formatOnSave->hide();
+ m_ui->formatWhileTyping->hide();
+ return;
+ }
+
+ m_ui->formatOnSave->show();
+ m_ui->formatWhileTyping->show();
+
+ auto setEnableCheckBoxes = [this](int index) {
+ bool isFormatting = index == static_cast<int>(ClangFormatSettings::Mode::Formatting);
+
+ m_ui->formatOnSave->setEnabled(isFormatting);
+ m_ui->formatWhileTyping->setEnabled(isFormatting);
+ };
+ setEnableCheckBoxes(m_ui->indentingOrFormatting->currentIndex());
+ connect(m_ui->indentingOrFormatting, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, setEnableCheckBoxes);
+
+ m_ui->formatOnSave->setChecked(ClangFormatSettings::instance().formatOnSave());
+ m_ui->formatWhileTyping->setChecked(ClangFormatSettings::instance().formatWhileTyping());
+
+ connect(m_ui->formatOnSave, &QCheckBox::toggled,
+ this, [](bool checked) {
+ ClangFormatSettings &settings = ClangFormatSettings::instance();
+ settings.setFormatOnSave(checked);
+ settings.write();
+ });
+
+ connect(m_ui->formatWhileTyping, &QCheckBox::toggled,
+ this, [](bool checked) {
+ ClangFormatSettings &settings = ClangFormatSettings::instance();
+ settings.setFormatWhileTyping(checked);
+ settings.write();
+ });
+}
+
+void ClangFormatConfigWidget::initOverrideCheckBox()
+{
+ if (m_project) {
+ m_ui->overrideDefault->setChecked(
+ m_project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool());
+ } else {
+ m_ui->overrideDefault->setChecked(ClangFormatSettings::instance().overrideDefaultFile());
+ m_ui->overrideDefault->setToolTip(
+ tr("Override Clang Format configuration file with the fallback configuration."));
+ }
+
+ connect(m_ui->overrideDefault, &QCheckBox::toggled,
+ this, &ClangFormatConfigWidget::showOrHideWidgets);
+ connect(m_ui->overrideDefault, &QCheckBox::toggled, this, [this](bool checked) {
+ if (m_project)
+ m_project->setNamedSettings(Constants::OVERRIDE_FILE_ID, checked);
+ else {
+ ClangFormatSettings::instance().setOverrideDefaultFile(checked);
+ ClangFormatSettings::instance().write();
+ }
+ });
+}
+
void ClangFormatConfigWidget::connectChecks()
{
for (QObject *child : m_checksWidget->children()) {
@@ -215,28 +218,28 @@ void ClangFormatConfigWidget::onTableChanged()
saveChanges(sender());
}
-void ClangFormatConfigWidget::hideGlobalCheckboxes()
+void ClangFormatConfigWidget::initIndentationOrFormattingCombobox()
{
- m_ui->formatAlways->hide();
- m_ui->formatWhileTyping->hide();
- m_ui->formatOnSave->hide();
-}
-
-void ClangFormatConfigWidget::showGlobalCheckboxes()
-{
- m_ui->formatAlways->setChecked(ClangFormatSettings::instance().formatCodeInsteadOfIndent());
- m_ui->formatAlways->show();
-
- m_ui->formatWhileTyping->setChecked(ClangFormatSettings::instance().formatWhileTyping());
- m_ui->formatWhileTyping->show();
-
- m_ui->formatOnSave->setChecked(ClangFormatSettings::instance().formatOnSave());
- m_ui->formatOnSave->show();
- if (isBeautifierOnSaveActivated()) {
- m_ui->formatOnSave->setChecked(false);
- m_ui->formatOnSave->setEnabled(false);
- m_ui->fileSaveWarning->setText(tr(kFileSaveWarning));
- }
+ m_ui->indentingOrFormatting->insertItem(static_cast<int>(ClangFormatSettings::Mode::Indenting),
+ tr("Indenting only"));
+ m_ui->indentingOrFormatting->insertItem(static_cast<int>(ClangFormatSettings::Mode::Formatting),
+ tr("Full formatting"));
+ m_ui->indentingOrFormatting->insertItem(static_cast<int>(ClangFormatSettings::Mode::Disable),
+ tr("Disable"));
+
+ m_ui->indentingOrFormatting->setCurrentIndex(
+ static_cast<int>(ClangFormatSettings::instance().mode()));
+
+ const bool isGlobal = !m_project;
+ m_ui->indentingOrFormatting->setVisible(isGlobal);
+ m_ui->formattingModeLabel->setVisible(isGlobal);
+
+ connect(m_ui->indentingOrFormatting, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, [](int index) {
+ ClangFormatSettings &settings = ClangFormatSettings::instance();
+ settings.setMode(static_cast<ClangFormatSettings::Mode>(index));
+ settings.write();
+ });
}
static bool projectConfigExists()
@@ -258,6 +261,7 @@ void ClangFormatConfigWidget::showOrHideWidgets()
if (!m_ui->overrideDefault->isChecked() && m_project) {
// Show the fallback configuration only globally.
+ m_ui->fallbackConfig->hide();
m_checksScrollArea->hide();
m_preview->hide();
m_ui->verticalLayout->addStretch(1);
@@ -265,12 +269,11 @@ void ClangFormatConfigWidget::showOrHideWidgets()
}
createStyleFileIfNeeded(!m_project);
+ m_ui->fallbackConfig->show();
m_checksScrollArea->show();
m_preview->show();
- if (m_project) {
- m_ui->projectHasClangFormat->hide();
- } else {
+ if (!m_project) {
const Project *currentProject = SessionManager::startupProject();
if (!currentProject || !projectConfigExists()) {
m_ui->projectHasClangFormat->hide();
@@ -361,8 +364,7 @@ void ClangFormatConfigWidget::fillTable()
Utils::ExecuteOnDestruction executeOnDestruction([this]() { m_disableTableUpdate = false; });
m_disableTableUpdate = true;
- const std::string configText = m_project ? currentProjectConfigText()
- : currentGlobalConfigText();
+ const std::string configText = readFile(m_config->filePath().path());
for (QObject *child : m_checksWidget->children()) {
if (!qobject_cast<QComboBox *>(child) && !qobject_cast<QLineEdit *>(child)
@@ -466,18 +468,7 @@ void ClangFormatConfigWidget::synchronize()
void ClangFormatConfigWidget::apply()
{
- ClangFormatSettings &settings = ClangFormatSettings::instance();
- if (!m_project) {
- settings.setFormatCodeInsteadOfIndent(m_ui->formatAlways->isChecked());
- settings.setFormatWhileTyping(m_ui->formatWhileTyping->isChecked());
- settings.setFormatOnSave(m_ui->formatOnSave->isChecked());
- settings.setOverrideDefaultFile(m_ui->overrideDefault->isChecked());
- } else {
- m_project->setNamedSettings(Constants::OVERRIDE_FILE_ID, m_ui->overrideDefault->isChecked());
- }
- settings.write();
-
- if (!m_checksWidget->isVisible())
+ if (!m_checksWidget->isVisible() && !m_checksWidget->isEnabled())
return;
saveChanges(this);
diff --git a/src/plugins/clangformat/clangformatconfigwidget.h b/src/plugins/clangformat/clangformatconfigwidget.h
index cf4bc1104c3..3b6f2aa1634 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.h
+++ b/src/plugins/clangformat/clangformatconfigwidget.h
@@ -48,7 +48,8 @@ class ClangFormatConfigWidget : public CppEditor::CppCodeStyleWidget
Q_OBJECT
public:
- explicit ClangFormatConfigWidget(ProjectExplorer::Project *project = nullptr,
+ explicit ClangFormatConfigWidget(TextEditor::ICodeStylePreferences *codeStyle,
+ ProjectExplorer::Project *project = nullptr,
QWidget *parent = nullptr);
~ClangFormatConfigWidget() override;
void apply() override;
@@ -60,17 +61,17 @@ private:
void onTableChanged();
bool eventFilter(QObject *object, QEvent *event) override;
- void showEvent(QShowEvent *event) override;
void showOrHideWidgets();
- void initChecksAndPreview();
+ void initChecksAndPreview(bool enabled);
+ void initOverrideCheckBox();
+ void initCheckBoxes();
void connectChecks();
void fillTable();
void saveChanges(QObject *sender);
- void hideGlobalCheckboxes();
- void showGlobalCheckboxes();
+ void initIndentationOrFormattingCombobox();
void updatePreview();
ProjectExplorer::Project *m_project;
diff --git a/src/plugins/clangformat/clangformatconfigwidget.ui b/src/plugins/clangformat/clangformatconfigwidget.ui
index 45b9801d7ff..a0a042c273e 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.ui
+++ b/src/plugins/clangformat/clangformatconfigwidget.ui
@@ -27,37 +27,19 @@
<number>8</number>
</property>
<item>
- <widget class="QCheckBox" name="formatAlways">
- <property name="text">
- <string>Format instead of indenting</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="formatWhileTyping">
- <property name="text">
- <string>Format while typing</string>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <layout class="QHBoxLayout" name="formattingModeLayout">
<item>
- <widget class="QCheckBox" name="formatOnSave">
+ <widget class="QLabel" name="formattingModeLabel">
<property name="text">
- <string>Format edited code on file save</string>
+ <string>Formatting mode:</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="fileSaveWarning">
- <property name="text">
- <string/>
- </property>
- </widget>
+ <widget class="QComboBox" name="indentingOrFormatting"/>
</item>
<item>
- <spacer name="horizontalSpacer_2">
+ <spacer name="formattingModeSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@@ -72,6 +54,20 @@
</layout>
</item>
<item>
+ <widget class="QCheckBox" name="formatWhileTyping">
+ <property name="text">
+ <string>Format while typing</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="formatOnSave">
+ <property name="text">
+ <string>Format edited code on file save</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLabel" name="projectHasClangFormat">
<property name="text">
<string/>
@@ -88,37 +84,12 @@
<item>
<widget class="QLabel" name="fallbackConfig">
<property name="text">
- <string>Fallback configuration</string>
+ <string>Clang-Format Style</string>
</property>
</widget>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QPushButton" name="applyButton">
- <property name="text">
- <string>Apply</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <layout class="QHBoxLayout" name="horizontalLayout_2"/>
</item>
</layout>
</widget>
diff --git a/src/plugins/clangformat/clangformatconstants.h b/src/plugins/clangformat/clangformatconstants.h
index 2635dbedeac..cb201665da9 100644
--- a/src/plugins/clangformat/clangformatconstants.h
+++ b/src/plugins/clangformat/clangformatconstants.h
@@ -31,10 +31,10 @@ static const char SETTINGS_FILE_NAME[] = ".clang-format";
static const char SETTINGS_FILE_ALT_NAME[] = "_clang-format";
static const char SAMPLE_FILE_NAME[] = "test.cpp";
static const char SETTINGS_ID[] = "ClangFormat";
-static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent";
-static const char FORMAT_WHILE_TYPING_ID[] = "ClangFormat.FormatWhileTyping";
-static const char FORMAT_CODE_ON_SAVE_ID[] = "ClangFormat.FormatCodeOnSave";
static const char OVERRIDE_FILE_ID[] = "ClangFormat.OverrideFile";
+static const char FORMAT_CODE_ON_SAVE_ID[] = "ClangFormat.FormatCodeOnSave";
+static const char FORMAT_WHILE_TYPING_ID[] = "ClangFormat.FormatWhileTyping";
+static const char MODE_ID[] = "ClangFormat.Mode";
static const char OPEN_CURRENT_CONFIG_ID[] = "ClangFormat.OpenCurrentConfig";
} // namespace Constants
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatfile.cpp b/src/plugins/clangformat/clangformatfile.cpp
index 3c64ebe1b48..ef96f26ce1e 100644
--- a/src/plugins/clangformat/clangformatfile.cpp
+++ b/src/plugins/clangformat/clangformatfile.cpp
@@ -25,6 +25,7 @@
#include "clangformatfile.h"
#include "clangformatsettings.h"
+#include "clangformatutils.h"
#include <cppeditor/cppcodestylesettings.h>
#include <projectexplorer/project.h>
#include <texteditor/tabsettings.h>
@@ -34,11 +35,18 @@
using namespace ClangFormat;
-ClangFormatFile::ClangFormatFile(Utils::FilePath filePath)
+ClangFormatFile::ClangFormatFile(Utils::FilePath filePath, bool isReadOnly)
: m_filePath(filePath)
+ , m_isReadOnly(isReadOnly)
{
if (!m_filePath.exists()) {
- resetStyleToLLVM();
+ // create file and folder
+ m_filePath.parentDir().createDir();
+ std::fstream newStyleFile(m_filePath.path().toStdString(), std::fstream::out);
+ if (newStyleFile.is_open()) {
+ newStyleFile.close();
+ }
+ resetStyleToQtC();
return;
}
@@ -46,7 +54,7 @@ ClangFormatFile::ClangFormatFile(Utils::FilePath filePath)
const std::error_code error
= clang::format::parseConfiguration(m_filePath.fileContents().toStdString(), &m_style);
if (error.value() != static_cast<int>(clang::format::ParseError::Success)) {
- resetStyleToLLVM();
+ resetStyleToQtC();
}
}
@@ -65,10 +73,15 @@ void ClangFormatFile::setStyle(clang::format::FormatStyle style)
saveNewFormat();
}
-void ClangFormatFile::resetStyleToLLVM()
+bool ClangFormatFile::isReadOnly() const
{
- m_style = clang::format::getLLVMStyle();
- saveNewFormat();
+ return m_isReadOnly;
+}
+
+void ClangFormatFile::resetStyleToQtC()
+{
+ m_style = qtcStyle();
+ saveStyleToFile(m_style, m_filePath);
}
void ClangFormatFile::setBasedOnStyle(QString styleName)
@@ -107,17 +120,17 @@ QString ClangFormatFile::changeFields(QList<Field> fields)
void ClangFormatFile::saveNewFormat()
{
- std::string style = clang::format::configurationAsText(m_style);
+ if (m_isReadOnly)
+ return;
- // workaround: configurationAsText() add comment "# " before BasedOnStyle line
- const int pos = style.find("# BasedOnStyle");
- if (pos != int(std::string::npos))
- style.erase(pos, 2);
- m_filePath.writeFileContents(QByteArray::fromStdString(style));
+ saveStyleToFile(m_style, m_filePath);
}
void ClangFormatFile::saveNewFormat(QByteArray style)
{
+ if (m_isReadOnly)
+ return;
+
m_filePath.writeFileContents(style);
}
@@ -153,7 +166,7 @@ CppEditor::CppCodeStyleSettings ClangFormatFile::toCppCodeStyleSettings(
settings.indentControlFlowRelativeToSwitchLabels = style.IndentCaseBlocks;
#endif
if (style.DerivePointerAlignment
- && ClangFormatSettings::instance().formatCodeInsteadOfIndent()) {
+ && ClangFormatSettings::instance().mode() == ClangFormatSettings::Mode::Formatting) {
settings.bindStarToIdentifier = style.PointerAlignment == FormatStyle::PAS_Right;
settings.bindStarToTypeName = style.PointerAlignment == FormatStyle::PAS_Left;
settings.bindStarToLeftSpecifier = style.PointerAlignment == FormatStyle::PAS_Left;
@@ -173,6 +186,8 @@ void ClangFormatFile::fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSett
if (settings.indentNamespaceBody || settings.indentNamespaceBraces)
m_style.NamespaceIndentation = FormatStyle::NamespaceIndentationKind::NI_All;
+ else
+ m_style.NamespaceIndentation = FormatStyle::NamespaceIndentationKind::NI_None;
if (settings.indentClassBraces || settings.indentEnumBraces || settings.indentBlockBraces
|| settings.indentFunctionBraces)
@@ -196,11 +211,11 @@ void ClangFormatFile::fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSett
|| settings.bindStarToRightSpecifier;
if ((settings.bindStarToIdentifier || settings.bindStarToRightSpecifier)
- && ClangFormatSettings::instance().formatCodeInsteadOfIndent())
+ && ClangFormatSettings::instance().mode() == ClangFormatSettings::Mode::Formatting)
m_style.PointerAlignment = FormatStyle::PAS_Right;
if ((settings.bindStarToTypeName || settings.bindStarToLeftSpecifier)
- && ClangFormatSettings::instance().formatCodeInsteadOfIndent())
+ && ClangFormatSettings::instance().mode() == ClangFormatSettings::Mode::Formatting)
m_style.PointerAlignment = FormatStyle::PAS_Left;
saveNewFormat();
diff --git a/src/plugins/clangformat/clangformatfile.h b/src/plugins/clangformat/clangformatfile.h
index f0dddd4ec03..da864c2a753 100644
--- a/src/plugins/clangformat/clangformatfile.h
+++ b/src/plugins/clangformat/clangformatfile.h
@@ -37,11 +37,11 @@ namespace ClangFormat {
class ClangFormatFile
{
public:
- explicit ClangFormatFile(Utils::FilePath file);
+ explicit ClangFormatFile(Utils::FilePath file, bool isReadOnly);
clang::format::FormatStyle format();
Utils::FilePath filePath();
- void resetStyleToLLVM();
+ void resetStyleToQtC();
void setBasedOnStyle(QString styleName);
void setStyle(clang::format::FormatStyle style);
QString setStyle(QString style);
@@ -54,6 +54,7 @@ public:
TextEditor::TabSettings toTabSettings(ProjectExplorer::Project *project) const;
void fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings);
void fromTabSettings(const TextEditor::TabSettings &settings);
+ bool isReadOnly() const;
private:
void saveNewFormat();
@@ -62,6 +63,7 @@ private:
private:
Utils::FilePath m_filePath;
clang::format::FormatStyle m_style;
+ const bool m_isReadOnly;
};
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp
index 381762ee7f2..4d7273024ec 100644
--- a/src/plugins/clangformat/clangformatindenter.cpp
+++ b/src/plugins/clangformat/clangformatindenter.cpp
@@ -24,11 +24,16 @@
****************************************************************************/
#include "clangformatindenter.h"
+#include "clangformatconstants.h"
#include "clangformatsettings.h"
#include "clangformatutils.h"
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+#include <extensionsystem/pluginspec.h>
#include <texteditor/tabsettings.h>
#include <texteditor/textdocumentlayout.h>
+#include <utils/genericconstants.h>
using namespace clang;
using namespace format;
@@ -36,23 +41,40 @@ using namespace TextEditor;
namespace ClangFormat {
-ClangFormatIndenter::ClangFormatIndenter(QTextDocument *doc)
- : ClangFormatBaseIndenter(doc)
-{}
-
-FormatStyle ClangFormatIndenter::styleForFile() const
+static bool isBeautifierPluginActivated()
{
- return ClangFormat::styleForFile(m_fileName);
+ const QVector<ExtensionSystem::PluginSpec *> specs = ExtensionSystem::PluginManager::plugins();
+ return std::find_if(specs.begin(),
+ specs.end(),
+ [](ExtensionSystem::PluginSpec *spec) {
+ return spec->name() == "Beautifier";
+ })
+ != specs.end();
}
-bool ClangFormatIndenter::formatCodeInsteadOfIndent() const
+static bool isBeautifierOnSaveActivated()
{
- return ClangFormatSettings::instance().formatCodeInsteadOfIndent();
+ if (!isBeautifierPluginActivated())
+ return false;
+
+ QSettings *s = Core::ICore::settings();
+ bool activated = false;
+ s->beginGroup(Utils::Constants::BEAUTIFIER_SETTINGS_GROUP);
+ s->beginGroup(Utils::Constants::BEAUTIFIER_GENERAL_GROUP);
+ if (s->value(Utils::Constants::BEAUTIFIER_AUTO_FORMAT_ON_SAVE, false).toBool())
+ activated = true;
+ s->endGroup();
+ s->endGroup();
+ return activated;
}
-bool ClangFormatIndenter::formatWhileTyping() const
+ClangFormatIndenter::ClangFormatIndenter(QTextDocument *doc)
+ : ClangFormatBaseIndenter(doc)
+{}
+
+bool ClangFormatIndenter::formatCodeInsteadOfIndent() const
{
- return ClangFormatSettings::instance().formatWhileTyping();
+ return ClangFormatSettings::instance().mode() == ClangFormatSettings::Mode::Formatting;
}
Utils::optional<TabSettings> ClangFormatIndenter::tabSettings() const
@@ -92,7 +114,13 @@ int ClangFormatIndenter::lastSaveRevision() const
bool ClangFormatIndenter::formatOnSave() const
{
- return ClangFormatSettings::instance().formatOnSave();
+ return ClangFormatSettings::instance().formatOnSave() && !isBeautifierOnSaveActivated()
+ && formatCodeInsteadOfIndent();
+}
+
+bool ClangFormatIndenter::formatWhileTyping() const
+{
+ return ClangFormatSettings::instance().formatWhileTyping() && formatCodeInsteadOfIndent();
}
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatindenter.h b/src/plugins/clangformat/clangformatindenter.h
index 6d605eb5c91..9e1a65fb3d4 100644
--- a/src/plugins/clangformat/clangformatindenter.h
+++ b/src/plugins/clangformat/clangformatindenter.h
@@ -41,7 +41,6 @@ public:
private:
bool formatCodeInsteadOfIndent() const override;
bool formatWhileTyping() const override;
- clang::format::FormatStyle styleForFile() const override;
int lastSaveRevision() const override;
};
diff --git a/src/plugins/clangformat/clangformatplugin.cpp b/src/plugins/clangformat/clangformatplugin.cpp
index fbba24f24c2..0b2c2fd5a6f 100644
--- a/src/plugins/clangformat/clangformatplugin.cpp
+++ b/src/plugins/clangformat/clangformatplugin.cpp
@@ -28,6 +28,7 @@
#include "clangformatconfigwidget.h"
#include "clangformatconstants.h"
#include "clangformatindenter.h"
+#include "clangformatsettings.h"
#include "clangformatutils.h"
#include "tests/clangformat-test.h"
@@ -56,6 +57,7 @@
#include <projectexplorer/target.h>
#include <texteditor/icodestylepreferences.h>
+#include <texteditor/textindenter.h>
#include <texteditor/texteditorsettings.h>
#include <clang/Format/Format.h>
@@ -81,13 +83,17 @@ class ClangFormatStyleFactory : public CppEditor::CppCodeStylePreferencesFactory
public:
TextEditor::Indenter *createIndenter(QTextDocument *doc) const override
{
+ if (ClangFormatSettings::instance().mode() == ClangFormatSettings::Disable)
+ return CppEditor::CppCodeStylePreferencesFactory::createIndenter(doc);
return new ClangFormatIndenter(doc);
}
std::pair<CppEditor::CppCodeStyleWidget *, QString> additionalTab(
- ProjectExplorer::Project *project, QWidget *parent) const override
+ TextEditor::ICodeStylePreferences *codeStyle,
+ ProjectExplorer::Project *project,
+ QWidget *parent) const override
{
- return {new ClangFormatConfigWidget(project, parent), tr("ClangFormat")};
+ return {new ClangFormatConfigWidget(codeStyle, project, parent), tr("ClangFormat")};
}
};
diff --git a/src/plugins/clangformat/clangformatsettings.cpp b/src/plugins/clangformat/clangformatsettings.cpp
index 8f70130ae3a..7ab17c00418 100644
--- a/src/plugins/clangformat/clangformatsettings.cpp
+++ b/src/plugins/clangformat/clangformatsettings.cpp
@@ -29,6 +29,7 @@
#include <coreplugin/icore.h>
namespace ClangFormat {
+static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent";
ClangFormatSettings &ClangFormatSettings::instance()
{
@@ -40,14 +41,27 @@ ClangFormatSettings::ClangFormatSettings()
{
QSettings *settings = Core::ICore::settings();
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
- m_formatCodeInsteadOfIndent
- = settings->value(QLatin1String(Constants::FORMAT_CODE_INSTEAD_OF_INDENT_ID), false).toBool();
+ m_overrideDefaultFile = settings->value(QLatin1String(Constants::OVERRIDE_FILE_ID), false)
+ .toBool();
m_formatWhileTyping = settings->value(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), false)
.toBool();
m_formatOnSave = settings->value(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), false)
.toBool();
- m_overrideDefaultFile = settings->value(QLatin1String(Constants::OVERRIDE_FILE_ID), false)
- .toBool();
+
+ // Convert old settings to new ones. New settings were added to QtC 8.0
+ bool isOldFormattingOn
+ = settings->value(QLatin1String(FORMAT_CODE_INSTEAD_OF_INDENT_ID), false).toBool();
+ Core::ICore::settings()->remove(QLatin1String(FORMAT_CODE_INSTEAD_OF_INDENT_ID));
+
+ if (isOldFormattingOn) {
+ settings->setValue(QLatin1String(Constants::MODE_ID),
+ static_cast<int>(ClangFormatSettings::Mode::Formatting));
+ m_mode = ClangFormatSettings::Mode::Formatting;
+ } else
+ m_mode = static_cast<ClangFormatSettings::Mode>(
+ settings->value(QLatin1String(Constants::MODE_ID), ClangFormatSettings::Mode::Indenting)
+ .toInt());
+
settings->endGroup();
}
@@ -55,22 +69,21 @@ void ClangFormatSettings::write() const
{
QSettings *settings = Core::ICore::settings();
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
- settings->setValue(QLatin1String(Constants::FORMAT_CODE_INSTEAD_OF_INDENT_ID),
- m_formatCodeInsteadOfIndent);
+ settings->setValue(QLatin1String(Constants::OVERRIDE_FILE_ID), m_overrideDefaultFile);
settings->setValue(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), m_formatWhileTyping);
settings->setValue(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), m_formatOnSave);
- settings->setValue(QLatin1String(Constants::OVERRIDE_FILE_ID), m_overrideDefaultFile);
+ settings->setValue(QLatin1String(Constants::MODE_ID), static_cast<int>(m_mode));
settings->endGroup();
}
-void ClangFormatSettings::setFormatCodeInsteadOfIndent(bool enable)
+void ClangFormatSettings::setOverrideDefaultFile(bool enable)
{
- m_formatCodeInsteadOfIndent = enable;
+ m_overrideDefaultFile = enable;
}
-bool ClangFormatSettings::formatCodeInsteadOfIndent() const
+bool ClangFormatSettings::overrideDefaultFile() const
{
- return m_formatCodeInsteadOfIndent;
+ return m_overrideDefaultFile;
}
void ClangFormatSettings::setFormatWhileTyping(bool enable)
@@ -93,14 +106,14 @@ bool ClangFormatSettings::formatOnSave() const
return m_formatOnSave;
}
-void ClangFormatSettings::setOverrideDefaultFile(bool enable)
+void ClangFormatSettings::setMode(Mode mode)
{
- m_overrideDefaultFile = enable;
+ m_mode = mode;
}
-bool ClangFormatSettings::overrideDefaultFile() const
+ClangFormatSettings::Mode ClangFormatSettings::mode() const
{
- return m_overrideDefaultFile;
+ return m_mode;
}
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatsettings.h b/src/plugins/clangformat/clangformatsettings.h
index 9344cf34a96..685dc042e8c 100644
--- a/src/plugins/clangformat/clangformatsettings.h
+++ b/src/plugins/clangformat/clangformatsettings.h
@@ -37,8 +37,17 @@ public:
ClangFormatSettings();
void write() const;
- void setFormatCodeInsteadOfIndent(bool enable);
- bool formatCodeInsteadOfIndent() const;
+ void setOverrideDefaultFile(bool enable);
+ bool overrideDefaultFile() const;
+
+ enum Mode {
+ Indenting = 0,
+ Formatting,
+ Disable
+ };
+
+ void setMode(Mode mode);
+ Mode mode() const;
void setFormatWhileTyping(bool enable);
bool formatWhileTyping() const;
@@ -46,13 +55,11 @@ public:
void setFormatOnSave(bool enable);
bool formatOnSave() const;
- void setOverrideDefaultFile(bool enable);
- bool overrideDefaultFile() const;
private:
- bool m_formatCodeInsteadOfIndent = false;
+ Mode m_mode;
+ bool m_overrideDefaultFile = false;
bool m_formatWhileTyping = false;
bool m_formatOnSave = false;
- bool m_overrideDefaultFile = false;
};
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp
index cf32bff3545..230078558e5 100644
--- a/src/plugins/clangformat/clangformatutils.cpp
+++ b/src/plugins/clangformat/clangformatutils.cpp
@@ -30,7 +30,9 @@
#include <coreplugin/icore.h>
#include <cppeditor/cppcodestylesettings.h>
+#include <texteditor/icodestylepreferences.h>
#include <texteditor/tabsettings.h>
+#include <texteditor/texteditorsettings.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <utils/qtcassert.h>
@@ -200,6 +202,18 @@ QString currentProjectUniqueId()
.toHex(0));
}
+void saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath)
+{
+ std::string styleStr = clang::format::configurationAsText(style);
+
+ // workaround: configurationAsText() add comment "# " before BasedOnStyle line
+ const int pos = styleStr.find("# BasedOnStyle");
+ if (pos != int(std::string::npos))
+ styleStr.erase(pos, 2);
+ styleStr.append("\n");
+ filePath.writeFileContents(QByteArray::fromStdString(styleStr));
+}
+
static bool useProjectOverriddenSettings()
{
const Project *project = SessionManager::startupProject();
@@ -371,7 +385,14 @@ void addQtcStatementMacros(clang::format::FormatStyle &style)
}
}
-static std::string readFile(const QString &path)
+Utils::FilePath filePathToCurrentSettings(const TextEditor::ICodeStylePreferences *codeStyle)
+{
+ return Core::ICore::userResourcePath() / "clang-format/"
+ / Utils::FileUtils::fileSystemFriendlyName(codeStyle->displayName())
+ / QLatin1String(Constants::SETTINGS_FILE_NAME);
+}
+
+std::string readFile(const QString &path)
{
const std::string defaultStyle = clang::format::configurationAsText(qtcStyle());
diff --git a/src/plugins/clangformat/clangformatutils.h b/src/plugins/clangformat/clangformatutils.h
index 3caf6c9d6fc..830ab42475b 100644
--- a/src/plugins/clangformat/clangformatutils.h
+++ b/src/plugins/clangformat/clangformatutils.h
@@ -34,6 +34,7 @@
#include <fstream>
+namespace TextEditor { class ICodeStylePreferences; }
namespace ClangFormat {
// Creates the style for the current project or the global style if needed.
@@ -46,11 +47,15 @@ std::string currentGlobalConfigText();
clang::format::FormatStyle currentProjectStyle();
clang::format::FormatStyle currentGlobalStyle();
+std::string readFile(const QString &path);
// Is the style from the matching .clang-format file or global one if it's not found.
QString configForFile(Utils::FilePath fileName);
clang::format::FormatStyle styleForFile(Utils::FilePath fileName);
+void saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath);
void addQtcStatementMacros(clang::format::FormatStyle &style);
clang::format::FormatStyle qtcStyle();
+
+Utils::FilePath filePathToCurrentSettings(const TextEditor::ICodeStylePreferences *codeStyle);
}
diff --git a/src/plugins/clangformat/tests/clangformat-test.cpp b/src/plugins/clangformat/tests/clangformat-test.cpp
index bc5e07328df..0493eeca97a 100644
--- a/src/plugins/clangformat/tests/clangformat-test.cpp
+++ b/src/plugins/clangformat/tests/clangformat-test.cpp
@@ -52,6 +52,7 @@ public:
ClangFormatExtendedTestIndenter(QTextDocument *doc) : ClangFormatTestIndenter(doc) {}
private:
+ bool formatCodeInsteadOfIndent() const override { return true; }
bool formatWhileTyping() const override { return true; }
};
diff --git a/src/plugins/clangtools/CMakeLists.txt b/src/plugins/clangtools/CMakeLists.txt
index e372da8e091..cdb6f279214 100644
--- a/src/plugins/clangtools/CMakeLists.txt
+++ b/src/plugins/clangtools/CMakeLists.txt
@@ -1,11 +1,17 @@
find_package(yaml-cpp QUIET MODULE)
+set(CLANG_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH})
+
add_qtc_plugin(ClangTools
CONDITION TARGET yaml-cpp
- DEPENDS ClangSupport yaml-cpp
+ DEPENDS yaml-cpp
PLUGIN_DEPENDS Core Debugger CppEditor
PLUGIN_RECOMMENDS CppEditor
PLUGIN_TEST_DEPENDS QmakeProjectManager QbsProjectManager
+ DEFINES
+ CLANG_VERSION="${CLANG_VERSION}"
+ CLANG_INCLUDE_DIR="${LLVM_LIBRARY_DIR}/clang/${CLANG_VERSION}/include"
+ CLANG_BINDIR="${LLVM_TOOLS_BINARY_DIR}"
INCLUDES ${CLANG_INCLUDE_DIRS}
SOURCES
clangfileinfo.h
@@ -45,4 +51,5 @@ extend_qtc_plugin(ClangTools
clangtoolspreconfiguredsessiontests.cpp clangtoolspreconfiguredsessiontests.h
clangtoolsunittests.cpp clangtoolsunittests.h
clangtoolsunittests.qrc
+ readexporteddiagnosticstest.cpp readexporteddiagnosticstest.h
)
diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp
index c422114f28e..72eb1c1bcdf 100644
--- a/src/plugins/clangtools/clangtool.cpp
+++ b/src/plugins/clangtools/clangtool.cpp
@@ -33,7 +33,6 @@
#include "clangtoolsdiagnosticmodel.h"
#include "clangtoolsdiagnosticview.h"
#include "clangtoolslogfilereader.h"
-#include "clangtoolsplugin.h"
#include "clangtoolsprojectsettings.h"
#include "clangtoolssettings.h"
#include "clangtoolsutils.h"
@@ -51,8 +50,10 @@
#include <debugger/analyzer/analyzermanager.h>
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectexplorericons.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -421,8 +422,8 @@ ClangTool::ClangTool()
connect(m_diagnosticView, &DiagnosticView::filterOutCurrentKind,
this, &ClangTool::filterOutCurrentKind);
- foreach (auto * const model,
- QList<QAbstractItemModel *>({m_diagnosticModel, m_diagnosticFilterModel})) {
+ for (QAbstractItemModel *const model :
+ QList<QAbstractItemModel *>({m_diagnosticModel, m_diagnosticFilterModel})) {
connect(model, &QAbstractItemModel::rowsInserted,
this, &ClangTool::updateForCurrentState);
connect(model, &QAbstractItemModel::rowsRemoved,
diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp
index b3a97393c87..5751ee5c3b2 100644
--- a/src/plugins/clangtools/clangtoolruncontrol.cpp
+++ b/src/plugins/clangtools/clangtoolruncontrol.cpp
@@ -119,13 +119,14 @@ AnalyzeUnit::AnalyzeUnit(const FileInfo &fileInfo,
const FilePath &clangIncludeDir,
const QString &clangVersion)
{
+ const FilePath actualClangIncludeDir = Core::ICore::clangIncludeDirectory(
+ clangVersion, clangIncludeDir);
CompilerOptionsBuilder optionsBuilder(*fileInfo.projectPart,
UseSystemHeader::No,
UseTweakedHeaderPaths::Tools,
UseLanguageDefines::No,
UseBuildSystemWarnings::No,
- clangVersion,
- clangIncludeDir);
+ actualClangIncludeDir);
file = fileInfo.file.toString();
arguments = extraClangToolsPrependOptions();
arguments.append(optionsBuilder.build(fileInfo.kind, CppEditor::getPchUsage()));
@@ -252,10 +253,10 @@ void ClangToolRunWorker::start()
// Collect files
const auto clangIncludeDirAndVersion =
- getClangIncludeDirAndVersion(runControl()->runnable().command.executable());
+ getClangIncludeDirAndVersion(runControl()->commandLine().executable());
const AnalyzeUnits unitsToProcess = unitsToAnalyze(clangIncludeDirAndVersion.first,
clangIncludeDirAndVersion.second);
- qCDebug(LOG) << Q_FUNC_INFO << runControl()->runnable().command.executable()
+ qCDebug(LOG) << Q_FUNC_INFO << runControl()->commandLine().executable()
<< clangIncludeDirAndVersion.first << clangIncludeDirAndVersion.second;
qCDebug(LOG) << "Files to process:" << unitsToProcess;
diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp
index 9a207a82d48..afad727e7c8 100644
--- a/src/plugins/clangtools/clangtoolrunner.cpp
+++ b/src/plugins/clangtools/clangtoolrunner.cpp
@@ -25,8 +25,6 @@
#include "clangtoolrunner.h"
-#include "clangtoolsconstants.h"
-
#include <utils/environment.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -60,33 +58,18 @@ static QString finishedWithBadExitCode(const QString &name, int exitCode)
}
ClangToolRunner::ClangToolRunner(QObject *parent)
- : QObject(parent), m_process(new Utils::QtcProcess)
+ : QObject(parent)
{}
-ClangToolRunner::~ClangToolRunner()
-{
- if (m_process->state() != QProcess::NotRunning) {
- // asking politly to terminate costs ~300 ms on windows so skip the courtasy and direct kill the process
- if (Utils::HostOsInfo::isWindowsHost()) {
- m_process->kill();
- m_process->waitForFinished(100);
- } else {
- m_process->stopProcess();
- }
- }
-
- m_process->deleteLater();
-}
-
void ClangToolRunner::init(const FilePath &outputDirPath, const Environment &environment)
{
m_outputDirPath = outputDirPath;
QTC_CHECK(!m_outputDirPath.isEmpty());
- m_process->setEnvironment(environment);
- m_process->setWorkingDirectory(m_outputDirPath); // Current clang-cl puts log file into working dir.
- connect(m_process, &QtcProcess::finished, this, &ClangToolRunner::onProcessFinished);
- connect(m_process, &QtcProcess::errorOccurred, this, &ClangToolRunner::onProcessError);
+ m_process.setEnvironment(environment);
+ m_process.setUseCtrlCStub(true);
+ m_process.setWorkingDirectory(m_outputDirPath); // Current clang-cl puts log file into working dir.
+ connect(&m_process, &QtcProcess::done, this, &ClangToolRunner::onProcessDone);
}
QStringList ClangToolRunner::mainToolArguments() const
@@ -140,40 +123,34 @@ bool ClangToolRunner::run(const QString &fileToAnalyze, const QStringList &compi
m_commandLine = {m_executable, m_argsCreator(compilerOptions)};
qCDebug(LOG).noquote() << "Starting" << m_commandLine.toUserOutput();
- m_process->setCommand(m_commandLine);
- m_process->start();
+ m_process.setCommand(m_commandLine);
+ m_process.start();
return true;
}
-void ClangToolRunner::onProcessFinished()
+void ClangToolRunner::onProcessDone()
{
- if (m_process->result() == QtcProcess::FinishedWithSuccess) {
- qCDebug(LOG).noquote() << "Output:\n" << m_process->stdOut();
+ if (m_process.result() == ProcessResult::StartFailed) {
+ emit finishedWithFailure(generalProcessError(m_name), commandlineAndOutput());
+ } else if (m_process.result() == ProcessResult::FinishedWithSuccess) {
+ qCDebug(LOG).noquote() << "Output:\n" << m_process.cleanedStdOut();
emit finishedWithSuccess(m_fileToAnalyze);
- } else if (m_process->result() == QtcProcess::FinishedWithError) {
- emit finishedWithFailure(finishedWithBadExitCode(m_name, m_process->exitCode()),
+ } else if (m_process.result() == ProcessResult::FinishedWithError) {
+ emit finishedWithFailure(finishedWithBadExitCode(m_name, m_process.exitCode()),
commandlineAndOutput());
} else { // == QProcess::CrashExit
emit finishedWithFailure(finishedDueToCrash(m_name), commandlineAndOutput());
}
}
-void ClangToolRunner::onProcessError(QProcess::ProcessError error)
-{
- if (error == QProcess::Crashed)
- return; // handled by slot of finished()
-
- emit finishedWithFailure(generalProcessError(m_name), commandlineAndOutput());
-}
-
QString ClangToolRunner::commandlineAndOutput() const
{
return tr("Command line: %1\n"
"Process Error: %2\n"
"Output:\n%3")
.arg(m_commandLine.toUserOutput())
- .arg(m_process->error())
- .arg(m_process->stdOut());
+ .arg(m_process.error())
+ .arg(m_process.cleanedStdOut());
}
} // namespace Internal
diff --git a/src/plugins/clangtools/clangtoolrunner.h b/src/plugins/clangtools/clangtoolrunner.h
index 45ed11387f4..6df1213642b 100644
--- a/src/plugins/clangtools/clangtoolrunner.h
+++ b/src/plugins/clangtools/clangtoolrunner.h
@@ -27,6 +27,7 @@
#include "clangtoolslogfilereader.h"
+#include <utils/commandline.h>
#include <utils/qtcprocess.h>
#include <memory>
@@ -42,7 +43,6 @@ class ClangToolRunner : public QObject
public:
ClangToolRunner(QObject *parent = nullptr);
- ~ClangToolRunner() override;
void init(const Utils::FilePath &outputDirPath, const Utils::Environment &environment);
void setName(const QString &name) { m_name = name; }
@@ -73,14 +73,13 @@ protected:
private:
void onProcessOutput();
- void onProcessFinished();
- void onProcessError(QProcess::ProcessError error);
+ void onProcessDone();
QString commandlineAndOutput() const;
private:
Utils::FilePath m_outputDirPath;
- Utils::QtcProcess *m_process = nullptr;
+ Utils::QtcProcess m_process;
QString m_name;
Utils::FilePath m_executable;
diff --git a/src/plugins/clangtools/clangtools.qbs b/src/plugins/clangtools/clangtools.qbs
index 066b6848c3e..01d680e537c 100644
--- a/src/plugins/clangtools/clangtools.qbs
+++ b/src/plugins/clangtools/clangtools.qbs
@@ -9,7 +9,6 @@ QtcPlugin {
Depends { name: "Debugger" }
Depends { name: "ProjectExplorer" }
Depends { name: "QtSupport"; condition: qtc.testsEnabled }
- Depends { name: "QtcSsh" }
Depends { name: "TextEditor" }
Depends { name: "Utils" }
@@ -92,6 +91,8 @@ QtcPlugin {
"clangtoolsunittests.cpp",
"clangtoolsunittests.h",
"clangtoolsunittests.qrc",
+ "readexporteddiagnosticstest.cpp",
+ "readexporteddiagnosticstest.h",
]
}
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
index 1a0cc352eae..70729a68137 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
+++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
@@ -225,7 +225,7 @@ static QString createExplainingStepToolTipString(const ExplainingStep &step)
"<style>dt { font-weight:bold; } dd { font-family: monospace; }</style>\n"
"<body><dl>");
- foreach (const StringPair &pair, lines) {
+ for (const StringPair &pair : qAsConst(lines)) {
html += QLatin1String("<dt>");
html += pair.first;
html += QLatin1String("</dt><dd>");
@@ -273,7 +273,7 @@ static QString fullText(const Diagnostic &diagnostic)
// Explaining steps.
int explainingStepNumber = 1;
- foreach (const ExplainingStep &explainingStep, diagnostic.explainingSteps) {
+ for (const ExplainingStep &explainingStep : qAsConst(diagnostic.explainingSteps)) {
text += createExplainingStepString(explainingStep, explainingStepNumber++)
+ QLatin1Char('\n');
}
@@ -645,7 +645,7 @@ bool DiagnosticFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &s
}
// Explicitly suppressed?
- foreach (const SuppressedDiagnostic &d, m_suppressedDiagnostics) {
+ for (const SuppressedDiagnostic &d : qAsConst(m_suppressedDiagnostics)) {
if (d.description != diag.description)
continue;
Utils::FilePath filePath = d.filePath;
diff --git a/src/plugins/clangtools/clangtoolsplugin.cpp b/src/plugins/clangtools/clangtoolsplugin.cpp
index 82806284e70..615e7e59d3e 100644
--- a/src/plugins/clangtools/clangtoolsplugin.cpp
+++ b/src/plugins/clangtools/clangtoolsplugin.cpp
@@ -34,12 +34,12 @@
#include "settingswidget.h"
#ifdef WITH_TESTS
+#include "readexporteddiagnosticstest.h"
#include "clangtoolspreconfiguredsessiontests.h"
#include "clangtoolsunittests.h"
#endif
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/mimetypes/mimetype.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <coreplugin/actionmanager/actioncontainer.h>
@@ -127,7 +127,8 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt
panelFactory->setPriority(100);
panelFactory->setId(Constants::PROJECT_PANEL_ID);
panelFactory->setDisplayName(tr("Clang Tools"));
- panelFactory->setCreateWidgetFunction([](Project *project) { return new ProjectSettingsWidget(project); });
+ panelFactory->setCreateWidgetFunction(
+ [](Project *project) { return new ClangToolsProjectSettingsWidget(project); });
ProjectPanelFactory::registerFactory(panelFactory);
connect(Core::EditorManager::instance(),
@@ -193,6 +194,7 @@ QVector<QObject *> ClangToolsPlugin::createTestObjects() const
#ifdef WITH_TESTS
tests << new PreconfiguredSessionTests;
tests << new ClangToolsUnitTests;
+ tests << new ReadExportedDiagnosticsTest;
#endif
return tests;
}
diff --git a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
index fb5609fe37d..492ed15d802 100644
--- a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
+++ b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
@@ -130,7 +130,7 @@ void PreconfiguredSessionTests::testPreconfiguredSession()
QCOMPARE(ClangTool::instance()->diagnostics().count(), 0);
}
-static QList<Project *> validProjects(const QList<Project *> projectsOfSession)
+static const QList<Project *> validProjects(const QList<Project *> projectsOfSession)
{
QList<Project *> sortedProjects = projectsOfSession;
Utils::sort(sortedProjects, [](Project *lhs, Project *rhs){
@@ -196,8 +196,8 @@ void PreconfiguredSessionTests::testPreconfiguredSession_data()
bool hasAddedTestData = false;
- foreach (Project *project, validProjects(SessionManager::projects())) {
- foreach (Target *target, validTargets(project)) {
+ for (Project *project : validProjects(SessionManager::projects())) {
+ for (Target *target : validTargets(project)) {
hasAddedTestData = true;
QTest::newRow(dataTagName(project, target)) << project << target;
}
diff --git a/src/plugins/clangtools/clangtoolsprojectsettings.cpp b/src/plugins/clangtools/clangtoolsprojectsettings.cpp
index 2953245c3b2..78a2736a354 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettings.cpp
+++ b/src/plugins/clangtools/clangtoolsprojectsettings.cpp
@@ -166,7 +166,7 @@ void ClangToolsProjectSettings::load()
m_selectedFiles = Utils::transform<QSet>(files, toFileName);
const QVariantList list = map.value(SETTINGS_KEY_SUPPRESSED_DIAGS).toList();
- foreach (const QVariant &v, list) {
+ for (const QVariant &v : list) {
const QVariantMap diag = v.toMap();
const QString fp = diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_FILEPATH).toString();
if (fp.isEmpty())
diff --git a/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp b/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp
index 417226168cf..a46143d6d3b 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp
+++ b/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp
@@ -70,21 +70,13 @@ private:
SuppressedDiagnosticsList m_diagnostics;
};
-enum { UseGlobalSettings, UseCustomSettings }; // Values in sync with m_globalCustomComboBox
-
-ProjectSettingsWidget::ProjectSettingsWidget(ProjectExplorer::Project *project, QWidget *parent) :
- QWidget(parent),
+ClangToolsProjectSettingsWidget::ClangToolsProjectSettingsWidget(ProjectExplorer::Project *project, QWidget *parent) :
+ ProjectExplorer::ProjectSettingsWidget(parent),
m_projectSettings(ClangToolsProjectSettings::getSettings(project))
{
- m_globalCustomComboBox = new QComboBox;
- m_globalCustomComboBox->addItem(tr("Use Global Settings"));
- m_globalCustomComboBox->addItem(tr("Use Customized Settings"));
-
+ setGlobalSettingsId(ClangTools::Constants::SETTINGS_PAGE_ID);
m_restoreGlobal = new QPushButton(tr("Restore Global Settings"));
- auto gotoGlobalSettingsLabel =
- new QLabel("<a href=\"target\">" + tr("Open Global Settings") + "</a>");
-
auto gotoAnalyzerModeLabel =
new QLabel("<a href=\"target\">" + tr("Go to Analyzer") + "</a>");
@@ -100,9 +92,7 @@ ProjectSettingsWidget::ProjectSettingsWidget(ProjectExplorer::Project *project,
Column {
Row {
- m_globalCustomComboBox,
m_restoreGlobal,
- gotoGlobalSettingsLabel,
Stretch(),
gotoAnalyzerModeLabel
},
@@ -122,36 +112,26 @@ ProjectSettingsWidget::ProjectSettingsWidget(ProjectExplorer::Project *project,
}
}.attachTo(this, false);
- // Use global/custom settings combo box
- const int globalOrCustomIndex = m_projectSettings->useGlobalSettings() ? UseGlobalSettings
- : UseCustomSettings;
- m_globalCustomComboBox->setCurrentIndex(globalOrCustomIndex);
- onGlobalCustomChanged(globalOrCustomIndex);
- connect(m_globalCustomComboBox,
- QOverload<int>::of(&QComboBox::currentIndexChanged),
- this,
- QOverload<int>::of(&ProjectSettingsWidget::onGlobalCustomChanged));
+ setUseGlobalSettings(m_projectSettings->useGlobalSettings());
+ onGlobalCustomChanged();
+ connect(this, &ProjectSettingsWidget::useGlobalSettingsChanged,
+ this, QOverload<bool>::of(&ClangToolsProjectSettingsWidget::onGlobalCustomChanged));
// Global settings
connect(ClangToolsSettings::instance(),
&ClangToolsSettings::changed,
this,
- QOverload<>::of(&ProjectSettingsWidget::onGlobalCustomChanged));
+ QOverload<>::of(&ClangToolsProjectSettingsWidget::onGlobalCustomChanged));
connect(m_restoreGlobal, &QPushButton::clicked, this, [this]() {
m_runSettingsWidget->fromSettings(ClangToolsSettings::instance()->runSettings());
});
- // Links
- connect(gotoGlobalSettingsLabel, &QLabel::linkActivated, [](const QString &) {
- Core::ICore::showOptionsDialog(ClangTools::Constants::SETTINGS_PAGE_ID);
- });
-
connect(gotoAnalyzerModeLabel, &QLabel::linkActivated, [](const QString &) {
ClangTool::instance()->selectPerspective();
});
// Run options
- connect(m_runSettingsWidget, &RunSettingsWidget::changed, [this]() {
+ connect(m_runSettingsWidget, &RunSettingsWidget::changed, this, [this]() {
// Save project run settings
m_projectSettings->setRunSettings(m_runSettingsWidget->toSettings());
@@ -165,31 +145,30 @@ ProjectSettingsWidget::ProjectSettingsWidget(ProjectExplorer::Project *project,
// Suppressed diagnostics
auto * const model = new SuppressedDiagnosticsModel(this);
model->setDiagnostics(m_projectSettings->suppressedDiagnostics());
- connect(m_projectSettings.data(), &ClangToolsProjectSettings::suppressedDiagnosticsChanged,
+ connect(m_projectSettings.data(), &ClangToolsProjectSettings::suppressedDiagnosticsChanged, this,
[model, this] {
model->setDiagnostics(m_projectSettings->suppressedDiagnostics());
updateButtonStates();
});
m_diagnosticsView->setModel(model);
updateButtonStates();
- connect(m_diagnosticsView->selectionModel(), &QItemSelectionModel::selectionChanged,
+ connect(m_diagnosticsView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
[this](const QItemSelection &, const QItemSelection &) {
updateButtonStateRemoveSelected();
});
connect(m_removeSelectedButton, &QAbstractButton::clicked,
- [this](bool) { removeSelected(); });
+ this, [this](bool) { removeSelected(); });
connect(m_removeAllButton, &QAbstractButton::clicked,
- [this](bool) { m_projectSettings->removeAllSuppressedDiagnostics();});
+ this, [this](bool) { m_projectSettings->removeAllSuppressedDiagnostics();});
}
-void ProjectSettingsWidget::onGlobalCustomChanged()
+void ClangToolsProjectSettingsWidget::onGlobalCustomChanged()
{
- onGlobalCustomChanged(m_globalCustomComboBox->currentIndex());
+ onGlobalCustomChanged(useGlobalSettings());
}
-void ProjectSettingsWidget::onGlobalCustomChanged(int index)
+void ClangToolsProjectSettingsWidget::onGlobalCustomChanged(bool useGlobal)
{
- const bool useGlobal = index == UseGlobalSettings;
const RunSettings runSettings = useGlobal ? ClangToolsSettings::instance()->runSettings()
: m_projectSettings->runSettings();
m_runSettingsWidget->fromSettings(runSettings);
@@ -199,25 +178,25 @@ void ProjectSettingsWidget::onGlobalCustomChanged(int index)
m_projectSettings->setUseGlobalSettings(useGlobal);
}
-void ProjectSettingsWidget::updateButtonStates()
+void ClangToolsProjectSettingsWidget::updateButtonStates()
{
updateButtonStateRemoveSelected();
updateButtonStateRemoveAll();
}
-void ProjectSettingsWidget::updateButtonStateRemoveSelected()
+void ClangToolsProjectSettingsWidget::updateButtonStateRemoveSelected()
{
const auto selectedRows = m_diagnosticsView->selectionModel()->selectedRows();
QTC_ASSERT(selectedRows.count() <= 1, return);
m_removeSelectedButton->setEnabled(!selectedRows.isEmpty());
}
-void ProjectSettingsWidget::updateButtonStateRemoveAll()
+void ClangToolsProjectSettingsWidget::updateButtonStateRemoveAll()
{
m_removeAllButton->setEnabled(m_diagnosticsView->model()->rowCount() > 0);
}
-void ProjectSettingsWidget::removeSelected()
+void ClangToolsProjectSettingsWidget::removeSelected()
{
const auto selectedRows = m_diagnosticsView->selectionModel()->selectedRows();
QTC_ASSERT(selectedRows.count() == 1, return);
diff --git a/src/plugins/clangtools/clangtoolsprojectsettingswidget.h b/src/plugins/clangtools/clangtoolsprojectsettingswidget.h
index 4d3a9c0ca94..dc3342901a4 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettingswidget.h
+++ b/src/plugins/clangtools/clangtoolsprojectsettingswidget.h
@@ -25,6 +25,8 @@
#pragma once
+#include <projectexplorer/projectsettingswidget.h>
+
#include <QWidget>
QT_BEGIN_NAMESPACE
@@ -41,16 +43,16 @@ namespace Internal {
class ClangToolsProjectSettings;
class RunSettingsWidget;
-class ProjectSettingsWidget : public QWidget
+class ClangToolsProjectSettingsWidget : public ProjectExplorer::ProjectSettingsWidget
{
Q_OBJECT
public:
- explicit ProjectSettingsWidget(ProjectExplorer::Project *project, QWidget *parent = nullptr);
+ explicit ClangToolsProjectSettingsWidget(ProjectExplorer::Project *project, QWidget *parent = nullptr);
private:
void onGlobalCustomChanged();
- void onGlobalCustomChanged(int index);
+ void onGlobalCustomChanged(bool useGlobal);
void updateButtonStates();
void updateButtonStateRemoveSelected();
diff --git a/src/plugins/clangtools/clangtoolssettings.cpp b/src/plugins/clangtools/clangtoolssettings.cpp
index ee099ddfae8..7578b252786 100644
--- a/src/plugins/clangtools/clangtoolssettings.cpp
+++ b/src/plugins/clangtools/clangtoolssettings.cpp
@@ -30,6 +30,7 @@
#include <coreplugin/icore.h>
#include <cppeditor/clangdiagnosticconfig.h>
+#include <cppeditor/clangdiagnosticconfigsmodel.h>
#include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/cpptoolsreuse.h>
@@ -123,7 +124,7 @@ static QVariantMap convertToMapFromVersionBefore410(QSettings *s)
ClangDiagnosticConfigs importDiagnosticConfigsFromCodeModel()
{
- const ClangDiagnosticConfigs configs = codeModelSettings()->clangCustomDiagnosticConfigs();
+ const ClangDiagnosticConfigs configs = ClangdSettings::instance().customDiagnosticConfigs();
ClangDiagnosticConfigs tidyClazyConfigs;
ClangDiagnosticConfigs clangOnlyConfigs;
@@ -132,12 +133,6 @@ ClangDiagnosticConfigs importDiagnosticConfigsFromCodeModel()
return !config.clazyChecks().isEmpty()
|| (!config.clangTidyChecks().isEmpty() && config.clangTidyChecks() != "-*");
});
-
- if (!tidyClazyConfigs.isEmpty()) {
- codeModelSettings()->setClangCustomDiagnosticConfigs(clangOnlyConfigs);
- codeModelSettings()->toSettings(Core::ICore::settings());
- }
-
return tidyClazyConfigs;
}
diff --git a/src/plugins/clangtools/clangtoolsunittests.cpp b/src/plugins/clangtools/clangtoolsunittests.cpp
index 14c4d7305ec..0e4d35fc733 100644
--- a/src/plugins/clangtools/clangtoolsunittests.cpp
+++ b/src/plugins/clangtools/clangtoolsunittests.cpp
@@ -28,16 +28,18 @@
#include "clangtool.h"
#include "clangtoolsdiagnostic.h"
#include "clangtoolssettings.h"
-#include "clangtoolsutils.h"
#include <coreplugin/icore.h>
+
#include <cppeditor/clangdiagnosticconfig.h>
#include <cppeditor/cppmodelmanager.h>
#include <cppeditor/cpptoolsreuse.h>
#include <cppeditor/cpptoolstestcase.h>
+
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>
#include <qtsupport/qtkitinformation.h>
diff --git a/src/plugins/clangtools/clangtoolsunittests.qrc b/src/plugins/clangtools/clangtoolsunittests.qrc
index 598de3e3671..54bb416eab5 100644
--- a/src/plugins/clangtools/clangtoolsunittests.qrc
+++ b/src/plugins/clangtools/clangtoolsunittests.qrc
@@ -22,5 +22,17 @@
<file>unit-tests/clangtidy_clazy/clangtidy_clazy.pro</file>
<file>unit-tests/clangtidy_clazy/clazy_example.cpp</file>
<file>unit-tests/clangtidy_clazy/tidy_example.cpp</file>
+ <file>unit-tests/exported-diagnostics/clang-analyzer.dividezero.cpp</file>
+ <file>unit-tests/exported-diagnostics/clang-analyzer.dividezero.yaml</file>
+ <file>unit-tests/exported-diagnostics/clang-analyzer.dividezero_win.yaml</file>
+ <file>unit-tests/exported-diagnostics/clazy.qgetenv.cpp</file>
+ <file>unit-tests/exported-diagnostics/clazy.qgetenv.yaml</file>
+ <file>unit-tests/exported-diagnostics/clazy.qgetenv_win.yaml</file>
+ <file>unit-tests/exported-diagnostics/CMakeLists.txt</file>
+ <file>unit-tests/exported-diagnostics/empty.yaml</file>
+ <file>unit-tests/exported-diagnostics/main.cpp</file>
+ <file>unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.cpp</file>
+ <file>unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.yaml</file>
+ <file>unit-tests/exported-diagnostics/tidy.modernize-use-nullptr_win.yaml</file>
</qresource>
</RCC>
diff --git a/src/plugins/clangtools/diagnosticmark.cpp b/src/plugins/clangtools/diagnosticmark.cpp
index 0e29a1c7313..985d917b80d 100644
--- a/src/plugins/clangtools/diagnosticmark.cpp
+++ b/src/plugins/clangtools/diagnosticmark.cpp
@@ -30,10 +30,9 @@
#include "diagnosticconfigswidget.h"
#include <utils/utilsicons.h>
+#include <utils/stringutils.h>
#include <QAction>
-#include <QApplication>
-#include <QClipboard>
namespace ClangTools {
namespace Internal {
@@ -55,28 +54,28 @@ DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic)
setIcon(markIcon.isNull() ? Utils::Icons::CODEMODEL_WARNING.icon() : markIcon);
setToolTip(createDiagnosticToolTipString(diagnostic, Utils::nullopt, true));
setLineAnnotation(diagnostic.description);
+ setActionsProvider([diagnostic] {
+ // Copy to clipboard action
+ QList<QAction *> actions;
+ QAction *action = new QAction();
+ action->setIcon(QIcon::fromTheme("edit-copy", Utils::Icons::COPY.icon()));
+ action->setToolTip(tr("Copy to Clipboard"));
+ QObject::connect(action, &QAction::triggered, [diagnostic]() {
+ const QString text = createFullLocationString(diagnostic.location)
+ + ": "
+ + diagnostic.description;
+ Utils::setClipboardAndSelection(text);
+ });
+ actions << action;
- // Copy to clipboard action
- QVector<QAction *> actions;
- QAction *action = new QAction();
- action->setIcon(QIcon::fromTheme("edit-copy", Utils::Icons::COPY.icon()));
- action->setToolTip(tr("Copy to Clipboard"));
- QObject::connect(action, &QAction::triggered, [diagnostic]() {
- const QString text = createFullLocationString(diagnostic.location)
- + ": "
- + diagnostic.description;
- QApplication::clipboard()->setText(text);
+ // Disable diagnostic action
+ action = new QAction();
+ action->setIcon(Utils::Icons::BROKEN.icon());
+ action->setToolTip(tr("Disable Diagnostic"));
+ QObject::connect(action, &QAction::triggered, [diagnostic] { disableChecks({diagnostic}); });
+ actions << action;
+ return actions;
});
- actions << action;
-
- // Disable diagnostic action
- action = new QAction();
- action->setIcon(Utils::Icons::BROKEN.icon());
- action->setToolTip(tr("Disable Diagnostic"));
- QObject::connect(action, &QAction::triggered, [diagnostic] { disableChecks({diagnostic}); });
- actions << action;
-
- setActions(actions);
}
void DiagnosticMark::disable()
@@ -89,7 +88,6 @@ void DiagnosticMark::disable()
else
setIcon(Utils::Icons::CODEMODEL_DISABLED_WARNING.icon());
setColor(Utils::Theme::Color::IconsDisabledColor);
- updateMarker();
}
bool DiagnosticMark::enabled() const
diff --git a/src/plugins/clangtools/documentclangtoolrunner.cpp b/src/plugins/clangtools/documentclangtoolrunner.cpp
index d62b882d4a2..9b8b206f2cc 100644
--- a/src/plugins/clangtools/documentclangtoolrunner.cpp
+++ b/src/plugins/clangtools/documentclangtoolrunner.cpp
@@ -26,7 +26,6 @@
#include "documentclangtoolrunner.h"
#include "clangfileinfo.h"
-#include "clangfixitsrefactoringchanges.h"
#include "clangtidyclazyrunner.h"
#include "clangtoolruncontrol.h"
#include "clangtoolsconstants.h"
@@ -39,13 +38,18 @@
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
+
#include <cppeditor/cppmodelmanager.h>
+
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildtargettype.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
+
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
#include <texteditor/textmark.h>
+
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
@@ -179,7 +183,7 @@ static Environment projectBuildEnvironment(Project *project)
if (BuildConfiguration *buildConfig = target->activeBuildConfiguration())
env = buildConfig->environment();
}
- if (env.size() == 0)
+ if (!env.isValid())
env = Environment::systemEnvironment();
return env;
}
@@ -247,6 +251,8 @@ QPair<FilePath, QString> getClangIncludeDirAndVersion(ClangToolRunner *runner)
void DocumentClangToolRunner::runNext()
{
+ if (m_currentRunner)
+ m_currentRunner.release()->deleteLater();
m_currentRunner.reset(m_runnerCreators.isEmpty() ? nullptr : m_runnerCreators.takeFirst()());
if (m_currentRunner) {
auto [clangIncludeDir, clangVersion] = getClangIncludeDirAndVersion(m_currentRunner.get());
@@ -358,10 +364,7 @@ void DocumentClangToolRunner::cancel()
if (m_projectSettingsUpdate)
disconnect(m_projectSettingsUpdate);
m_runnerCreators.clear();
- if (m_currentRunner) {
- m_currentRunner->disconnect(this);
- m_currentRunner.reset(nullptr);
- }
+ m_currentRunner.reset(nullptr);
}
bool DocumentClangToolRunner::isSuppressed(const Diagnostic &diagnostic) const
diff --git a/src/plugins/clangtools/executableinfo.cpp b/src/plugins/clangtools/executableinfo.cpp
index 45b2ea8e2cc..f27d4aef8b5 100644
--- a/src/plugins/clangtools/executableinfo.cpp
+++ b/src/plugins/clangtools/executableinfo.cpp
@@ -55,15 +55,15 @@ static QString runExecutable(const Utils::CommandLine &commandLine, QueryFailMod
cpp.setCommand(commandLine);
cpp.runBlocking();
- if (cpp.result() != QtcProcess::FinishedWithSuccess
+ if (cpp.result() != ProcessResult::FinishedWithSuccess
&& (queryFailMode == QueryFailMode::Noisy
- || cpp.result() != QtcProcess::FinishedWithError)) {
+ || cpp.result() != ProcessResult::FinishedWithError)) {
Core::MessageManager::writeFlashing(cpp.exitMessage());
Core::MessageManager::writeFlashing(QString::fromUtf8(cpp.allRawOutput()));
return {};
}
- return cpp.stdOut();
+ return cpp.cleanedStdOut();
}
static QStringList queryClangTidyChecks(const FilePath &executable,
diff --git a/src/plugins/clangtools/readexporteddiagnosticstest.cpp b/src/plugins/clangtools/readexporteddiagnosticstest.cpp
new file mode 100644
index 00000000000..6bd9eb5a116
--- /dev/null
+++ b/src/plugins/clangtools/readexporteddiagnosticstest.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "readexporteddiagnosticstest.h"
+
+#include "clangtoolslogfilereader.h"
+
+#include <cppeditor/cpptoolstestcase.h>
+#include <utils/fileutils.h>
+#include <utils/hostosinfo.h>
+#include <utils/qtcassert.h>
+
+#include <QtTest>
+
+using namespace CppEditor::Tests;
+using namespace Debugger;
+using namespace Utils;
+
+namespace ClangTools::Internal {
+
+const char asciiWord[] = "FOO";
+const char asciiMultiLine[] = "FOO\nBAR";
+const char asciiMultiLine_dos[] = "FOO\r\nBAR";
+const char nonAsciiMultiLine[] = "\xc3\xbc" "\n"
+ "\xe4\xba\x8c" "\n"
+ "\xf0\x90\x8c\x82" "X";
+
+ReadExportedDiagnosticsTest::ReadExportedDiagnosticsTest()
+ : m_baseDir(new TemporaryCopiedDir(":/clangtools/unit-tests/exported-diagnostics")) {}
+
+ReadExportedDiagnosticsTest::~ReadExportedDiagnosticsTest() { delete m_baseDir; }
+
+void ReadExportedDiagnosticsTest::initTestCase() { QVERIFY(m_baseDir->isValid()); }
+void ReadExportedDiagnosticsTest::init() { m_message.clear(); }
+
+void ReadExportedDiagnosticsTest::testNonExistingFile()
+{
+ const Diagnostics diags = readExportedDiagnostics("nonExistingFile.yaml", {}, &m_message);
+ QVERIFY(diags.isEmpty());
+ QVERIFY(!m_message.isEmpty());
+}
+
+void ReadExportedDiagnosticsTest::testEmptyFile()
+{
+ const Diagnostics diags = readExportedDiagnostics(filePath("empty.yaml"), {}, &m_message);
+ QVERIFY(diags.isEmpty());
+ QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
+}
+
+void ReadExportedDiagnosticsTest::testUnexpectedFileContents()
+{
+ const Diagnostics diags = readExportedDiagnostics(filePath("tidy.modernize-use-nullptr.cpp"),
+ {}, &m_message);
+ QVERIFY(!m_message.isEmpty());
+ QVERIFY(diags.isEmpty());
+}
+
+static QString appendYamlSuffix(const char *filePathFragment)
+{
+ const QString yamlSuffix = QLatin1String(Utils::HostOsInfo::isWindowsHost()
+ ? "_win.yaml" : ".yaml");
+ return filePathFragment + yamlSuffix;
+}
+
+void ReadExportedDiagnosticsTest::testTidy()
+{
+ const FilePath sourceFile = filePath("tidy.modernize-use-nullptr.cpp");
+ const QString exportedFile = createFile(
+ filePath(appendYamlSuffix("tidy.modernize-use-nullptr")).toString(),
+ sourceFile.toString());
+ Diagnostic expectedDiag;
+ expectedDiag.name = "modernize-use-nullptr";
+ expectedDiag.location = {sourceFile, 2, 25};
+ expectedDiag.description = "use nullptr [modernize-use-nullptr]";
+ expectedDiag.type = "warning";
+ expectedDiag.hasFixits = true;
+ expectedDiag.explainingSteps = {
+ ExplainingStep{"nullptr",
+ expectedDiag.location,
+ {expectedDiag.location, {sourceFile, 2, 26}},
+ true}};
+ const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
+ {}, &m_message);
+
+ QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
+ QCOMPARE(diags, {expectedDiag});
+}
+
+void ReadExportedDiagnosticsTest::testAcceptDiagsFromFilePaths_None()
+{
+ const QString sourceFile = filePath("tidy.modernize-use-nullptr.cpp").toString();
+ const QString exportedFile = createFile(filePath("tidy.modernize-use-nullptr.yaml").toString(),
+ sourceFile);
+ const auto acceptNone = [](const Utils::FilePath &) { return false; };
+ const Diagnostics diags = readExportedDiagnostics(FilePath::fromString(exportedFile),
+ acceptNone, &m_message);
+ QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
+ QVERIFY(diags.isEmpty());
+}
+
+// Diagnostics from clang (static) analyzer passed through via clang-tidy
+void ReadExportedDiagnosticsTest::testTidy_ClangAnalyzer()
+{
+ const FilePath sourceFile = filePath("clang-analyzer.dividezero.cpp");
+ const QString exportedFile = createFile(
+ filePath(appendYamlSuffix("clang-analyzer.dividezero")).toString(),
+ sourceFile.toString());
+ Diagnostic expectedDiag;
+ expectedDiag.name = "clang-analyzer-core.DivideZero";
+ expectedDiag.location = {sourceFile, 4, 15};
+ expectedDiag.description = "Division by zero [clang-analyzer-core.DivideZero]";
+ expectedDiag.type = "warning";
+ expectedDiag.hasFixits = false;
+ expectedDiag.explainingSteps = {
+ ExplainingStep{"Assuming 'z' is equal to 0",
+ {sourceFile, 3, 7},
+ {},
+ false,
+ },
+ ExplainingStep{"Taking true branch",
+ {sourceFile, 3, 3},
+ {},
+ false,
+ },
+ ExplainingStep{"Division by zero",
+ {sourceFile, 4, 15},
+ {},
+ false,
+ },
+ };
+ const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
+ {}, &m_message);
+ QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
+ QCOMPARE(diags, {expectedDiag});
+}
+
+void ReadExportedDiagnosticsTest::testClazy()
+{
+ const FilePath sourceFile = filePath("clazy.qgetenv.cpp");
+ const QString exportedFile = createFile(filePath(appendYamlSuffix("clazy.qgetenv")).toString(),
+ sourceFile.toString());
+ Diagnostic expectedDiag;
+ expectedDiag.name = "clazy-qgetenv";
+ expectedDiag.location = {sourceFile, 7, 5};
+ expectedDiag.description = "qgetenv().isEmpty() allocates. Use qEnvironmentVariableIsEmpty() instead [clazy-qgetenv]";
+ expectedDiag.type = "warning";
+ expectedDiag.hasFixits = true;
+ expectedDiag.explainingSteps = {
+ ExplainingStep{"qEnvironmentVariableIsEmpty",
+ expectedDiag.location,
+ {expectedDiag.location, {sourceFile, 7, 12}},
+ true
+ },
+ ExplainingStep{")",
+ {sourceFile, 7, 18},
+ {{sourceFile, 7, 18}, {sourceFile, 7, 29}},
+ true},
+ };
+ const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
+ {}, &m_message);
+ QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
+ QCOMPARE(diags, {expectedDiag});
+}
+
+void ReadExportedDiagnosticsTest::testOffsetInvalidText()
+{
+ QVERIFY(!byteOffsetInUtf8TextToLineColumn(nullptr, 0));
+}
+
+void ReadExportedDiagnosticsTest::testOffsetInvalidOffset_EmptyInput()
+{
+ QVERIFY(!byteOffsetInUtf8TextToLineColumn("", 0));
+}
+
+void ReadExportedDiagnosticsTest::testOffsetInvalidOffset_Before()
+{
+ QVERIFY(!byteOffsetInUtf8TextToLineColumn(asciiWord, -1));
+}
+
+void ReadExportedDiagnosticsTest::testOffsetInvalidOffset_After()
+{
+ QVERIFY(!byteOffsetInUtf8TextToLineColumn(asciiWord, 3));
+}
+
+void ReadExportedDiagnosticsTest::testOffsetInvalidOffset_NotFirstByteOfMultiByte()
+{
+ QVERIFY(!byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 1));
+}
+
+void ReadExportedDiagnosticsTest::testOffsetStartOfFirstLine()
+{
+ const auto info = byteOffsetInUtf8TextToLineColumn(asciiWord, 0);
+ QVERIFY(info);
+ QCOMPARE(info->line, 1);
+ QCOMPARE(info->column, 1);
+}
+
+void ReadExportedDiagnosticsTest::testOffsetEndOfFirstLine()
+{
+ const auto info = byteOffsetInUtf8TextToLineColumn(asciiWord, 2);
+ QVERIFY(info);
+ QCOMPARE(info->line, 1);
+ QCOMPARE(info->column, 3);
+}
+
+// The invocation
+//
+// clang-tidy "-checks=-*,readability-braces-around-statements" /path/to/file
+//
+// for the code
+//
+// void f(bool b)
+// {
+// if (b)
+// f(b);
+// }
+//
+// emits
+//
+// 3:11: warning: statement should be inside braces [readability-braces-around-statements]
+//
+// The newline in the if-line is considered as column 11, which is normally not visible in the
+// editor.
+void ReadExportedDiagnosticsTest::testOffsetOffsetPointingToLineSeparator_unix()
+{
+ const auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine, 3);
+ QVERIFY(info);
+ QCOMPARE(info->line, 1);
+ QCOMPARE(info->column, 4);
+}
+
+// For a file with dos style line endings ("\r\n"), clang-tidy points to '\r'.
+void ReadExportedDiagnosticsTest::testOffsetOffsetPointingToLineSeparator_dos()
+{
+ const auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine_dos, 3);
+ QVERIFY(info);
+ QCOMPARE(info->line, 1);
+ QCOMPARE(info->column, 4);
+}
+
+void ReadExportedDiagnosticsTest::testOffsetStartOfSecondLine()
+{
+ const auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine, 4);
+ QVERIFY(info);
+ QCOMPARE(info->line, 2);
+ QCOMPARE(info->column, 1);
+}
+
+void ReadExportedDiagnosticsTest::testOffsetMultiByteCodePoint1()
+{
+ const auto info = byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 3);
+ QVERIFY(info);
+ QCOMPARE(info->line, 2);
+ QCOMPARE(info->column, 1);
+}
+
+void ReadExportedDiagnosticsTest::testOffsetMultiByteCodePoint2()
+{
+ const auto info = byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 11);
+ QVERIFY(info);
+ QCOMPARE(info->line, 3);
+ QCOMPARE(info->column, 2);
+}
+
+// Replace FILE_PATH with a real absolute file path in the *.yaml files.
+QString ReadExportedDiagnosticsTest::createFile(const QString &yamlFilePath,
+ const QString &filePathToInject) const
+{
+ QTC_ASSERT(QDir::isAbsolutePath(filePathToInject), return QString());
+ const Utils::FilePath newFileName = FilePath::fromString(m_baseDir->absolutePath(
+ QFileInfo(yamlFilePath).fileName().toLocal8Bit()));
+
+ Utils::FileReader reader;
+ if (QTC_GUARD(reader.fetch(Utils::FilePath::fromString(yamlFilePath),
+ QIODevice::ReadOnly | QIODevice::Text))) {
+ QByteArray contents = reader.data();
+ contents.replace("FILE_PATH", filePathToInject.toLocal8Bit());
+
+ Utils::FileSaver fileSaver(newFileName, QIODevice::WriteOnly | QIODevice::Text);
+ QTC_CHECK(fileSaver.write(contents));
+ QTC_CHECK(fileSaver.finalize());
+ }
+
+ return newFileName.toString();
+}
+
+FilePath ReadExportedDiagnosticsTest::filePath(const QString &fileName) const
+{
+ return FilePath::fromString(m_baseDir->absolutePath(fileName.toUtf8()));
+}
+
+} // namespace ClangTools::Internal
diff --git a/src/plugins/clangtools/readexporteddiagnosticstest.h b/src/plugins/clangtools/readexporteddiagnosticstest.h
new file mode 100644
index 00000000000..007ae7802e8
--- /dev/null
+++ b/src/plugins/clangtools/readexporteddiagnosticstest.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+#include <QString>
+
+namespace CppEditor::Tests { class TemporaryCopiedDir; }
+namespace Utils { class FilePath; }
+
+namespace ClangTools::Internal {
+
+class ReadExportedDiagnosticsTest : public QObject
+{
+ Q_OBJECT
+public:
+ ReadExportedDiagnosticsTest();
+ ~ReadExportedDiagnosticsTest();
+
+private slots:
+ void initTestCase();
+ void init();
+
+ void testNonExistingFile();
+ void testEmptyFile();
+ void testUnexpectedFileContents();
+ void testTidy();
+ void testAcceptDiagsFromFilePaths_None();
+ void testTidy_ClangAnalyzer();
+ void testClazy();
+
+ void testOffsetInvalidText();
+ void testOffsetInvalidOffset_EmptyInput();
+ void testOffsetInvalidOffset_Before();
+ void testOffsetInvalidOffset_After();
+ void testOffsetInvalidOffset_NotFirstByteOfMultiByte();
+ void testOffsetStartOfFirstLine();
+ void testOffsetEndOfFirstLine();
+ void testOffsetOffsetPointingToLineSeparator_unix();
+ void testOffsetOffsetPointingToLineSeparator_dos();
+ void testOffsetStartOfSecondLine();
+ void testOffsetMultiByteCodePoint1();
+ void testOffsetMultiByteCodePoint2();
+
+private:
+ QString createFile(const QString &yamlFilePath, const QString &filePathToInject) const;
+ Utils::FilePath filePath(const QString &fileName) const;
+
+ CppEditor::Tests::TemporaryCopiedDir * const m_baseDir;
+ QString m_message;
+};
+
+} // namespace ClangTools::Internal
diff --git a/tests/unit/unittest/data/clangtools/CMakeLists.txt b/src/plugins/clangtools/unit-tests/exported-diagnostics/CMakeLists.txt
index b445f81b7dd..b445f81b7dd 100644
--- a/tests/unit/unittest/data/clangtools/CMakeLists.txt
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/CMakeLists.txt
diff --git a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.cpp b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.cpp
index 5f623dc114b..5f623dc114b 100644
--- a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.cpp
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.cpp
diff --git a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.yaml
index d19c5887a98..d19c5887a98 100644
--- a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.yaml
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.yaml
diff --git a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero_win.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero_win.yaml
index d54844d25cf..d54844d25cf 100644
--- a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero_win.yaml
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero_win.yaml
diff --git a/tests/unit/unittest/data/clangtools/clazy.qgetenv.cpp b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.cpp
index e04518821cb..e04518821cb 100644
--- a/tests/unit/unittest/data/clangtools/clazy.qgetenv.cpp
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.cpp
diff --git a/tests/unit/unittest/data/clangtools/clazy.qgetenv.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.yaml
index a465a1ca638..a465a1ca638 100644
--- a/tests/unit/unittest/data/clangtools/clazy.qgetenv.yaml
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.yaml
diff --git a/tests/unit/unittest/data/clangtools/clazy.qgetenv_win.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv_win.yaml
index c80a701373b..c80a701373b 100644
--- a/tests/unit/unittest/data/clangtools/clazy.qgetenv_win.yaml
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv_win.yaml
diff --git a/tests/unit/unittest/data/clangtools/empty.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/empty.yaml
index e69de29bb2d..e69de29bb2d 100644
--- a/tests/unit/unittest/data/clangtools/empty.yaml
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/empty.yaml
diff --git a/tests/unit/unittest/data/clangtools/main.cpp b/src/plugins/clangtools/unit-tests/exported-diagnostics/main.cpp
index df38a776481..df38a776481 100644
--- a/tests/unit/unittest/data/clangtools/main.cpp
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/main.cpp
diff --git a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.cpp b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.cpp
index fedae863306..fedae863306 100644
--- a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.cpp
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.cpp
diff --git a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.yaml
index 7724d3bdfcb..7724d3bdfcb 100644
--- a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.yaml
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.yaml
diff --git a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr_win.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr_win.yaml
index c6bb6766adb..c6bb6766adb 100644
--- a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr_win.yaml
+++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr_win.yaml
diff --git a/src/plugins/classview/classviewparsertreeitem.cpp b/src/plugins/classview/classviewparsertreeitem.cpp
index 39f5074105c..cc5f79d3425 100644
--- a/src/plugins/classview/classviewparsertreeitem.cpp
+++ b/src/plugins/classview/classviewparsertreeitem.cpp
@@ -105,17 +105,17 @@ void ParserTreeItemPrivate::mergeSymbol(const CPlusPlus::Symbol *symbol)
// any symbol which does not contain :: in the name
//! \todo collect statistics and reorder to optimize
- if (symbol->isForwardClassDeclaration()
+ if (symbol->asForwardClassDeclaration()
|| symbol->isExtern()
|| symbol->isFriend()
|| symbol->isGenerated()
- || symbol->isUsingNamespaceDirective()
- || symbol->isUsingDeclaration()
+ || symbol->asUsingNamespaceDirective()
+ || symbol->asUsingDeclaration()
)
return;
const CPlusPlus::Name *symbolName = symbol->name();
- if (symbolName && symbolName->isQualifiedNameId())
+ if (symbolName && symbolName->asQualifiedNameId())
return;
QString name = g_overview.prettyName(symbolName).trimmed();
@@ -139,7 +139,7 @@ void ParserTreeItemPrivate::mergeSymbol(const CPlusPlus::Symbol *symbol)
childItem->d->m_symbolLocations.insert(location);
// prevent showing a content of the functions
- if (!symbol->isFunction()) {
+ if (!symbol->asFunction()) {
if (const CPlusPlus::Scope *scope = symbol->asScope()) {
CPlusPlus::Scope::iterator cur = scope->memberBegin();
CPlusPlus::Scope::iterator last = scope->memberEnd();
@@ -155,7 +155,7 @@ void ParserTreeItemPrivate::mergeSymbol(const CPlusPlus::Symbol *symbol)
}
// if item is empty and has not to be added
- if (!symbol->isNamespace() || childItem->childCount())
+ if (!symbol->asNamespace() || childItem->childCount())
m_symbolInformations.insert(information, childItem);
}
diff --git a/src/plugins/classview/classviewutils.cpp b/src/plugins/classview/classviewutils.cpp
index cebea9a6f28..d33cb2090a0 100644
--- a/src/plugins/classview/classviewutils.cpp
+++ b/src/plugins/classview/classviewutils.cpp
@@ -43,7 +43,7 @@ namespace Internal {
QSet<SymbolLocation> roleToLocations(const QList<QVariant> &locationsVar)
{
QSet<SymbolLocation> locations;
- foreach (const QVariant &loc, locationsVar) {
+ for (const QVariant &loc : locationsVar) {
if (loc.canConvert<SymbolLocation>())
locations.insert(loc.value<SymbolLocation>());
}
diff --git a/src/plugins/clearcase/activityselector.cpp b/src/plugins/clearcase/activityselector.cpp
index ad7644d3946..952b9278d44 100644
--- a/src/plugins/clearcase/activityselector.cpp
+++ b/src/plugins/clearcase/activityselector.cpp
@@ -77,9 +77,9 @@ void ActivitySelector::userChanged()
bool ActivitySelector::refresh()
{
int current;
- QList<QStringPair> activities = ClearCasePlugin::activities(&current);
+ const QList<QStringPair> activities = ClearCasePlugin::activities(&current);
m_cmbActivity->clear();
- foreach (const QStringPair &activity, activities)
+ for (const QStringPair &activity : activities)
m_cmbActivity->addItem(activity.second, activity.first);
m_cmbActivity->setCurrentIndex(current);
m_cmbActivity->updateGeometry();
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index 9f8afc89aba..7450ad9ff76 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -1673,11 +1673,11 @@ ClearCasePluginPrivate::runCleartool(const FilePath &workingDir,
command.setCodec(outputCodec);
command.runCommand(proc, {FilePath::fromString(executable), arguments});
- response.error = proc.result() != QtcProcess::FinishedWithSuccess;
+ response.error = proc.result() != ProcessResult::FinishedWithSuccess;
if (response.error)
response.message = proc.exitMessage();
- response.stdErr = proc.stdErr();
- response.stdOut = proc.stdOut();
+ response.stdErr = proc.cleanedStdErr();
+ response.stdOut = proc.cleanedStdOut();
return response;
}
@@ -2354,8 +2354,8 @@ QString ClearCasePluginPrivate::runExtDiff(const FilePath &workingDir, const QSt
process.setWorkingDirectory(workingDir);
process.setCodec(outputCodec ? outputCodec : QTextCodec::codecForName("UTF-8"));
process.setCommand(diff);
- process.runBlocking(QtcProcess::WithEventLoop);
- if (process.result() != QtcProcess::FinishedWithSuccess)
+ process.runBlocking(EventLoopMode::On);
+ if (process.result() != ProcessResult::FinishedWithSuccess)
return QString();
return process.allOutput();
}
diff --git a/src/plugins/clearcase/clearcasesettings.cpp b/src/plugins/clearcase/clearcasesettings.cpp
index be57ebcd4a7..e32593e62b7 100644
--- a/src/plugins/clearcase/clearcasesettings.cpp
+++ b/src/plugins/clearcase/clearcasesettings.cpp
@@ -88,7 +88,8 @@ void ClearCaseSettings::fromSettings(QSettings *settings)
indexOnlyVOBs = settings->value(QLatin1String(indexOnlyVOBsC), QString()).toString();
extDiffAvailable = !Utils::Environment::systemEnvironment().searchInPath(QLatin1String("diff")).isEmpty();
settings->beginGroup(QLatin1String(totalFilesKeyC));
- foreach (const QString &view, settings->childKeys())
+ const QStringList views = settings->childKeys();
+ for (const QString &view : views)
totalFiles[view] = settings->value(view).toInt();
settings->endGroup();
settings->endGroup();
diff --git a/src/plugins/cmakeprojectmanager/CMakeLists.txt b/src/plugins/cmakeprojectmanager/CMakeLists.txt
index ce6b8f8ce1e..848411a761f 100644
--- a/src/plugins/cmakeprojectmanager/CMakeLists.txt
+++ b/src/plugins/cmakeprojectmanager/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(CMakeProjectManager
+ PLUGIN_CLASS CMakeProjectPlugin
DEPENDS QmlJS
PLUGIN_DEPENDS Core CppEditor ProjectExplorer TextEditor QtSupport
SOURCES
diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.cpp b/src/plugins/cmakeprojectmanager/builddirparameters.cpp
index 048dead9d28..939920e4b82 100644
--- a/src/plugins/cmakeprojectmanager/builddirparameters.cpp
+++ b/src/plugins/cmakeprojectmanager/builddirparameters.cpp
@@ -26,8 +26,8 @@
#include "builddirparameters.h"
#include "cmakebuildconfiguration.h"
+#include "cmakebuildsystem.h"
#include "cmakekitinformation.h"
-#include "cmakeprojectconstants.h"
#include "cmakeprojectplugin.h"
#include "cmakespecificsettings.h"
#include "cmaketoolmanager.h"
@@ -47,23 +47,25 @@ namespace Internal {
BuildDirParameters::BuildDirParameters() = default;
-BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc)
+BuildDirParameters::BuildDirParameters(CMakeBuildSystem *buildSystem)
{
- QTC_ASSERT(bc, return );
+ QTC_ASSERT(buildSystem, return);
+ auto bc = buildSystem->cmakeBuildConfiguration();
+ QTC_ASSERT(bc, return);
const Utils::MacroExpander *expander = bc->macroExpander();
- const QStringList expandedArguments = Utils::transform(bc->initialCMakeArguments(),
+ const QStringList expandedArguments = Utils::transform(buildSystem->initialCMakeArguments(),
[expander](const QString &s) {
return expander->expand(s);
});
initialCMakeArguments = Utils::filtered(expandedArguments,
[](const QString &s) { return !s.isEmpty(); });
- configurationChangesArguments = Utils::transform(bc->configurationChangesArguments(),
+ configurationChangesArguments = Utils::transform(buildSystem->configurationChangesArguments(),
[expander](const QString &s) {
return expander->expand(s);
});
- additionalCMakeArguments = Utils::transform(bc->additionalCMakeArguments(),
+ additionalCMakeArguments = Utils::transform(buildSystem->additionalCMakeArguments(),
[expander](const QString &s) {
return expander->expand(s);
});
@@ -78,7 +80,7 @@ BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc)
sourceDirectory = p->projectDirectory();
buildDirectory = bc->buildDirectory();
- cmakeBuildType = bc->cmakeBuildType();
+ cmakeBuildType = buildSystem->cmakeBuildType();
environment = bc->environment();
// Disable distributed building for configuration runs. CMake does not do those in parallel,
@@ -87,12 +89,6 @@ BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc)
if (Utils::HostOsInfo::isAnyUnixHost())
environment.set("ICECC", "no");
- CMakeSpecificSettings *settings = CMakeProjectPlugin::projectTypeSpecificSettings();
- if (!settings->ninjaPath.filePath().isEmpty()) {
- const Utils::FilePath ninja = settings->ninjaPath.filePath();
- environment.appendOrSetPath(ninja.isFile() ? ninja.parentDir() : ninja);
- }
-
cmakeToolId = CMakeKitAspect::cmakeToolId(k);
}
@@ -106,8 +102,5 @@ CMakeTool *BuildDirParameters::cmakeTool() const
return CMakeToolManager::findById(cmakeToolId);
}
-BuildDirParameters::BuildDirParameters(const BuildDirParameters &) = default;
-BuildDirParameters &BuildDirParameters::operator=(const BuildDirParameters &) = default;
-
} // namespace Internal
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.h b/src/plugins/cmakeprojectmanager/builddirparameters.h
index 13ecedee24f..354a18678fe 100644
--- a/src/plugins/cmakeprojectmanager/builddirparameters.h
+++ b/src/plugins/cmakeprojectmanager/builddirparameters.h
@@ -25,27 +25,21 @@
#pragma once
-#include "cmakeconfigitem.h"
#include "cmaketool.h"
#include <utils/environment.h>
-#include <utils/fileutils.h>
-#include <utils/macroexpander.h>
-
-#include <QString>
+#include <utils/filepath.h>
namespace CMakeProjectManager {
-
-class CMakeBuildConfiguration;
-
namespace Internal {
-class BuildDirParameters {
+class CMakeBuildSystem;
+
+class BuildDirParameters
+{
public:
BuildDirParameters();
- explicit BuildDirParameters(CMakeBuildConfiguration *bc);
- BuildDirParameters(const BuildDirParameters &other);
- BuildDirParameters &operator=(const BuildDirParameters &other);
+ explicit BuildDirParameters(CMakeBuildSystem *buildSystem);
bool isValid() const;
CMakeTool *cmakeTool() const;
diff --git a/src/plugins/cmakeprojectmanager/cmake_global.h b/src/plugins/cmakeprojectmanager/cmake_global.h
index 59945a2977d..0406e4d07a2 100644
--- a/src/plugins/cmakeprojectmanager/cmake_global.h
+++ b/src/plugins/cmakeprojectmanager/cmake_global.h
@@ -29,6 +29,8 @@
#if defined(CMAKEPROJECTMANAGER_LIBRARY)
# define CMAKE_EXPORT Q_DECL_EXPORT
+#elif defined(CMAKEPROJECTMANAGER_STATIC_LIBRARY)
+# define CMAKE_EXPORT
#else
# define CMAKE_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
index 6bd0fed36a9..a052fdc8b3b 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
@@ -50,10 +50,12 @@
#include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/namedwidget.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
@@ -64,6 +66,7 @@
#include <utils/algorithm.h>
#include <utils/categorysortfiltermodel.h>
#include <utils/checkablemessagebox.h>
+#include <utils/commandline.h>
#include <utils/detailswidget.h>
#include <utils/headerviewstretcher.h>
#include <utils/infolabel.h>
@@ -101,8 +104,10 @@ const char CONFIGURATION_KEY[] = "CMake.Configuration";
const char DEVELOPMENT_TEAM_FLAG[] = "Ios:DevelopmentTeam:Flag";
const char PROVISIONING_PROFILE_FLAG[] = "Ios:ProvisioningProfile:Flag";
const char CMAKE_OSX_ARCHITECTURES_FLAG[] = "CMAKE_OSX_ARCHITECTURES:DefaultFlag";
-const char CMAKE_QT6_TOOLCHAIN_FILE_ARG[] =
- "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=%{Qt:QT_INSTALL_PREFIX}/lib/cmake/Qt6/qt.toolchain.cmake";
+const char QT_QML_DEBUG_FLAG[] = "Qt:QML_DEBUG_FLAG";
+const char CMAKE_QT6_TOOLCHAIN_FILE_ARG[]
+ = "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=%{Qt:QT_INSTALL_PREFIX}/lib/cmake/Qt6/qt.toolchain.cmake";
+const char CMAKE_BUILD_TYPE[] = "CMake.Build.Type";
namespace Internal {
@@ -111,7 +116,7 @@ class CMakeBuildSettingsWidget : public NamedWidget
Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeBuildSettingsWidget)
public:
- CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc);
+ CMakeBuildSettingsWidget(CMakeBuildSystem *bc);
void setError(const QString &message);
void setWarning(const QString &message);
@@ -133,11 +138,11 @@ private:
bool eventFilter(QObject *target, QEvent *event) override;
void batchEditConfiguration();
- void reconfigureWithInitialParameters(CMakeBuildConfiguration *bc);
+ void reconfigureWithInitialParameters();
void updateInitialCMakeArguments();
void kitCMakeConfiguration();
- CMakeBuildConfiguration *m_buildConfiguration;
+ CMakeBuildSystem *m_buildSystem;
QTreeView *m_configView;
ConfigModel *m_configModel;
CategorySortFilterModel *m_configFilterModel;
@@ -173,14 +178,15 @@ static QModelIndex mapToSource(const QAbstractItemView *view, const QModelIndex
return result;
}
-CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) :
+CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildSystem *bs) :
NamedWidget(tr("CMake")),
- m_buildConfiguration(bc),
+ m_buildSystem(bs),
m_configModel(new ConfigModel(this)),
m_configFilterModel(new CategorySortFilterModel(this)),
m_configTextFilterModel(new CategorySortFilterModel(this))
{
- QTC_CHECK(bc);
+ QTC_ASSERT(bs, return);
+ BuildConfiguration *bc = bs->buildConfiguration();
auto vbox = new QVBoxLayout(this);
vbox->setContentsMargins(0, 0, 0, 0);
@@ -198,8 +204,8 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
});
auto buildTypeAspect = bc->aspect<BuildTypeAspect>();
- connect(buildTypeAspect, &BaseAspect::changed, this, [this, buildTypeAspect]() {
- if (!m_buildConfiguration->isMultiConfig()) {
+ connect(buildTypeAspect, &BaseAspect::changed, this, [this, buildTypeAspect] {
+ if (!m_buildSystem->isMultiConfig()) {
CMakeConfig config;
config << CMakeConfigItem("CMAKE_BUILD_TYPE", buildTypeAspect->value().toUtf8());
@@ -262,7 +268,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
m_configView->setSelectionBehavior(QAbstractItemView::SelectItems);
m_configView->setAlternatingRowColors(true);
m_configView->setFrameShape(QFrame::NoFrame);
- m_configView->setItemDelegate(new ConfigModelItemDelegate(m_buildConfiguration->project()->projectDirectory(),
+ m_configView->setItemDelegate(new ConfigModelItemDelegate(bc->project()->projectDirectory(),
m_configView));
m_configView->setRootIsDecorated(false);
QFrame *findWrapper = Core::ItemViewFind::createSearchableWrapper(m_configView, Core::ItemViewFind::LightColored);
@@ -354,30 +360,39 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
}.attachTo(details, false);
updateAdvancedCheckBox();
- setError(bc->error());
- setWarning(bc->warning());
+ setError(m_buildSystem->error());
+ setWarning(m_buildSystem->warning());
- connect(bc->buildSystem(), &BuildSystem::parsingStarted, this, [this] {
+ connect(m_buildSystem, &BuildSystem::parsingStarted, this, [this] {
updateButtonState();
m_configView->setEnabled(false);
m_showProgressTimer.start();
});
- m_configModel->setMacroExpander(m_buildConfiguration->macroExpander());
+ m_configModel->setMacroExpander(bc->macroExpander());
- if (bc->buildSystem()->isParsing())
+ if (m_buildSystem->isParsing())
m_showProgressTimer.start();
else {
- m_configModel->setConfiguration(m_buildConfiguration->configurationFromCMake());
+ m_configModel->setConfiguration(m_buildSystem->configurationFromCMake());
m_configModel->setInitialParametersConfiguration(
- m_buildConfiguration->initialCMakeConfiguration());
+ m_buildSystem->initialCMakeConfiguration());
}
- connect(bc->buildSystem(), &BuildSystem::parsingFinished, this, [this] {
- m_configModel->setConfiguration(m_buildConfiguration->configurationFromCMake());
+ connect(m_buildSystem, &BuildSystem::parsingFinished, this, [this] {
+ const CMakeConfig config = m_buildSystem->configurationFromCMake();
+ auto qmlDebugAspect = m_buildSystem->buildConfiguration()
+ ->aspect<QtSupport::QmlDebuggingAspect>();
+ const TriState qmlDebugSetting = qmlDebugAspect->value();
+ bool qmlDebugConfig = CMakeBuildConfiguration::hasQmlDebugging(config);
+ if ((qmlDebugSetting == TriState::Enabled && !qmlDebugConfig)
+ || (qmlDebugSetting == TriState::Disabled && qmlDebugConfig)) {
+ qmlDebugAspect->setValue(TriState::Default);
+ }
+ m_configModel->setConfiguration(config);
m_configModel->setInitialParametersConfiguration(
- m_buildConfiguration->initialCMakeConfiguration());
- m_buildConfiguration->filterConfigArgumentsFromAdditionalCMakeArguments();
+ m_buildSystem->initialCMakeConfiguration());
+ m_buildSystem->filterConfigArgumentsFromAdditionalCMakeArguments();
updateFromKit();
m_configView->setEnabled(true);
updateButtonState();
@@ -386,13 +401,11 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
updateConfigurationStateSelection();
});
- auto cbc = static_cast<CMakeBuildSystem *>(bc->buildSystem());
- connect(cbc, &CMakeBuildSystem::configurationCleared, this, [this]() {
+ connect(m_buildSystem, &CMakeBuildSystem::configurationCleared, this, [this] {
updateConfigurationStateSelection();
});
- connect(m_buildConfiguration, &CMakeBuildConfiguration::errorOccurred,
- this, [this]() {
+ connect(m_buildSystem, &CMakeBuildSystem::errorOccurred, this, [this] {
m_showProgressTimer.stop();
m_progressIndicator->hide();
updateConfigurationStateSelection();
@@ -403,7 +416,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_configModel, &QAbstractItemModel::modelReset,
this, &CMakeBuildSettingsWidget::updateButtonState);
- connect(m_buildConfiguration,
+ connect(m_buildSystem->cmakeBuildConfiguration(),
&CMakeBuildConfiguration::signingFlagsChanged,
this,
&CMakeBuildSettingsWidget::updateButtonState);
@@ -423,16 +436,15 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_resetButton, &QPushButton::clicked, this, [this](){
m_configModel->resetAllChanges(isInitialConfiguration());
});
- connect(m_reconfigureButton, &QPushButton::clicked, this, [this, bc]() {
- auto buildSystem = static_cast<CMakeBuildSystem *>(m_buildConfiguration->buildSystem());
- if (!buildSystem->isParsing()) {
+ connect(m_reconfigureButton, &QPushButton::clicked, this, [this] {
+ if (!m_buildSystem->isParsing()) {
if (isInitialConfiguration()) {
- reconfigureWithInitialParameters(bc);
+ reconfigureWithInitialParameters();
} else {
- buildSystem->runCMakeWithExtraArguments();
+ m_buildSystem->runCMakeWithExtraArguments();
}
} else {
- buildSystem->stopCMakeRun();
+ m_buildSystem->stopCMakeRun();
m_reconfigureButton->setEnabled(false);
}
});
@@ -469,18 +481,19 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_batchEditButton, &QAbstractButton::clicked,
this, &CMakeBuildSettingsWidget::batchEditConfiguration);
- connect(bc, &CMakeBuildConfiguration::errorOccurred, this, &CMakeBuildSettingsWidget::setError);
- connect(bc, &CMakeBuildConfiguration::warningOccurred, this, &CMakeBuildSettingsWidget::setWarning);
- connect(bc, &CMakeBuildConfiguration::configurationChanged, this, [this](const CMakeConfig &config) {
- m_configModel->setBatchEditConfiguration(config);
- });
+ connect(m_buildSystem, &CMakeBuildSystem::errorOccurred,
+ this, &CMakeBuildSettingsWidget::setError);
+ connect(m_buildSystem, &CMakeBuildSystem::warningOccurred,
+ this, &CMakeBuildSettingsWidget::setWarning);
+
+ connect(m_buildSystem, &CMakeBuildSystem::configurationChanged,
+ m_configModel, &ConfigModel::setBatchEditConfiguration);
updateFromKit();
- connect(m_buildConfiguration->target(), &Target::kitChanged,
+ connect(m_buildSystem->target(), &Target::kitChanged,
this, &CMakeBuildSettingsWidget::updateFromKit);
- connect(m_buildConfiguration, &CMakeBuildConfiguration::enabledChanged,
- this, [this]() {
- if (m_buildConfiguration->isEnabled())
+ connect(bc, &CMakeBuildConfiguration::enabledChanged, this, [this, bc] {
+ if (bc->isEnabled())
setError(QString());
});
connect(this, &QObject::destroyed, this, [this] {
@@ -491,16 +504,12 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
&Utils::BaseAspect::labelLinkActivated,
this,
[this](const QString &) {
- const CMakeTool *tool = CMakeKitAspect::cmakeTool(
- m_buildConfiguration->target()->kit());
+ const CMakeTool *tool = CMakeKitAspect::cmakeTool(m_buildSystem->kit());
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake.1.html#options");
});
connect(bc->aspect<AdditionalCMakeOptionsAspect>(),
- &Utils::BaseAspect::labelLinkActivated,
- this,
- [this](const QString &) {
- const CMakeTool *tool = CMakeKitAspect::cmakeTool(
- m_buildConfiguration->target()->kit());
+ &Utils::BaseAspect::labelLinkActivated, this, [this](const QString &) {
+ const CMakeTool *tool = CMakeKitAspect::cmakeTool(m_buildSystem->kit());
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake.1.html#options");
});
@@ -523,14 +532,14 @@ void CMakeBuildSettingsWidget::batchEditConfiguration()
"&lt;type&gt; can have one of the following values: FILEPATH, PATH, BOOL, INTERNAL, or STRING.<br/>"
"To unset a variable, use -U&lt;variable&gt;.<br/>"));
connect(label, &QLabel::linkActivated, this, [this](const QString &) {
- const CMakeTool *tool = CMakeKitAspect::cmakeTool(m_buildConfiguration->target()->kit());
+ const CMakeTool *tool = CMakeKitAspect::cmakeTool(m_buildSystem->target()->kit());
CMakeTool::openCMakeHelpUrl(tool, "%1/manual/cmake-variables.7.html");
});
editor->setMinimumSize(800, 200);
auto chooser = new Utils::VariableChooser(dialog);
chooser->addSupportedWidget(editor);
- chooser->addMacroExpanderProvider([this]() { return m_buildConfiguration->macroExpander(); });
+ chooser->addMacroExpanderProvider([this] { return m_buildSystem->buildConfiguration()->macroExpander(); });
auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
@@ -541,7 +550,7 @@ void CMakeBuildSettingsWidget::batchEditConfiguration()
connect(buttons, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, dialog, &QDialog::reject);
connect(dialog, &QDialog::accepted, this, [=]{
- const auto expander = m_buildConfiguration->macroExpander();
+ const auto expander = m_buildSystem->buildConfiguration()->macroExpander();
const QStringList lines = editor->toPlainText().split('\n', Qt::SkipEmptyParts);
const QStringList expandedLines = Utils::transform(lines,
@@ -559,13 +568,13 @@ void CMakeBuildSettingsWidget::batchEditConfiguration()
});
editor->setPlainText(
- m_buildConfiguration->configurationChangesArguments(isInitialConfiguration())
+ m_buildSystem->configurationChangesArguments(isInitialConfiguration())
.join('\n'));
dialog->show();
}
-void CMakeBuildSettingsWidget::reconfigureWithInitialParameters(CMakeBuildConfiguration *bc)
+void CMakeBuildSettingsWidget::reconfigureWithInitialParameters()
{
CMakeSpecificSettings *settings = CMakeProjectPlugin::projectTypeSpecificSettings();
bool doNotAsk = !settings->askBeforeReConfigureInitialParams.value();
@@ -587,20 +596,19 @@ void CMakeBuildSettingsWidget::reconfigureWithInitialParameters(CMakeBuildConfig
}
}
- auto cbc = static_cast<CMakeBuildSystem*>(bc->buildSystem());
- cbc->clearCMakeCache();
+ m_buildSystem->clearCMakeCache();
updateInitialCMakeArguments();
if (ProjectExplorerPlugin::saveModifiedFiles())
- cbc->runCMake();
+ m_buildSystem->runCMake();
}
void CMakeBuildSettingsWidget::updateInitialCMakeArguments()
{
- CMakeConfig initialList = m_buildConfiguration->initialCMakeConfiguration();
+ CMakeConfig initialList = m_buildSystem->initialCMakeConfiguration();
- for (const CMakeConfigItem &ci : m_buildConfiguration->configurationChanges()) {
+ for (const CMakeConfigItem &ci : m_buildSystem->configurationChanges()) {
if (!ci.isInitial)
continue;
auto it = std::find_if(initialList.begin(),
@@ -617,26 +625,27 @@ void CMakeBuildSettingsWidget::updateInitialCMakeArguments()
}
}
- m_buildConfiguration->aspect<InitialCMakeArgumentsAspect>()->setCMakeConfiguration(initialList);
+ auto bc = m_buildSystem->buildConfiguration();
+ bc->aspect<InitialCMakeArgumentsAspect>()->setCMakeConfiguration(initialList);
// value() will contain only the unknown arguments (the non -D/-U arguments)
// As the user would expect to have e.g. "--preset" from "Initial Configuration"
// to "Current Configuration" as additional parameters
- m_buildConfiguration->setAdditionalCMakeArguments(ProcessArgs::splitArgs(
- m_buildConfiguration->aspect<InitialCMakeArgumentsAspect>()->value()));
+ m_buildSystem->setAdditionalCMakeArguments(ProcessArgs::splitArgs(
+ bc->aspect<InitialCMakeArgumentsAspect>()->value()));
}
void CMakeBuildSettingsWidget::kitCMakeConfiguration()
{
- m_buildConfiguration->kit()->blockNotification();
+ m_buildSystem->kit()->blockNotification();
auto dialog = new QDialog(this);
dialog->setWindowTitle(tr("Kit CMake Configuration"));
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setModal(true);
dialog->setSizeGripEnabled(true);
- connect(dialog, &QDialog::finished, this, [=]{
- m_buildConfiguration->kit()->unblockNotification();
+ connect(dialog, &QDialog::finished, this, [this] {
+ m_buildSystem->kit()->unblockNotification();
});
CMakeKitAspect kitAspect;
@@ -645,11 +654,11 @@ void CMakeBuildSettingsWidget::kitCMakeConfiguration()
auto layout = new QGridLayout(dialog);
- kitAspect.createConfigWidget(m_buildConfiguration->kit())
+ kitAspect.createConfigWidget(m_buildSystem->kit())
->addToLayoutWithLabel(layout->parentWidget());
- generatorAspect.createConfigWidget(m_buildConfiguration->kit())
+ generatorAspect.createConfigWidget(m_buildSystem->kit())
->addToLayoutWithLabel(layout->parentWidget());
- configurationKitAspect.createConfigWidget(m_buildConfiguration->kit())
+ configurationKitAspect.createConfigWidget(m_buildSystem->kit())
->addToLayoutWithLabel(layout->parentWidget());
layout->setColumnStretch(1, 1);
@@ -667,7 +676,7 @@ void CMakeBuildSettingsWidget::kitCMakeConfiguration()
void CMakeBuildSettingsWidget::setError(const QString &message)
{
- m_buildConfiguration->buildDirectoryAspect()->setProblem(message);
+ m_buildSystem->buildConfiguration()->buildDirectoryAspect()->setProblem(message);
}
void CMakeBuildSettingsWidget::setWarning(const QString &message)
@@ -679,7 +688,7 @@ void CMakeBuildSettingsWidget::setWarning(const QString &message)
void CMakeBuildSettingsWidget::updateButtonState()
{
- const bool isParsing = m_buildConfiguration->buildSystem()->isParsing();
+ const bool isParsing = m_buildSystem->isParsing();
// Update extra data in buildconfiguration
const QList<ConfigModel::DataItem> changes = m_configModel->configurationForCMake();
@@ -720,11 +729,12 @@ void CMakeBuildSettingsWidget::updateButtonState()
const bool isInitial = isInitialConfiguration();
m_resetButton->setEnabled(m_configModel->hasChanges(isInitial) && !isParsing);
- m_buildConfiguration->aspect<InitialCMakeArgumentsAspect>()->setVisible(isInitialConfiguration());
- m_buildConfiguration->aspect<AdditionalCMakeOptionsAspect>()->setVisible(!isInitialConfiguration());
+ BuildConfiguration *bc = m_buildSystem->buildConfiguration();
+ bc->aspect<InitialCMakeArgumentsAspect>()->setVisible(isInitialConfiguration());
+ bc->aspect<AdditionalCMakeOptionsAspect>()->setVisible(!isInitialConfiguration());
- m_buildConfiguration->aspect<InitialCMakeArgumentsAspect>()->setEnabled(!isParsing);
- m_buildConfiguration->aspect<AdditionalCMakeOptionsAspect>()->setEnabled(!isParsing);
+ bc->aspect<InitialCMakeArgumentsAspect>()->setEnabled(!isParsing);
+ bc->aspect<AdditionalCMakeOptionsAspect>()->setEnabled(!isParsing);
// Update label and text boldness of the reconfigure button
QFont reconfigureButtonFont = m_reconfigureButton->font();
@@ -738,15 +748,16 @@ void CMakeBuildSettingsWidget::updateButtonState()
} else {
m_reconfigureButton->setText(tr("Run CMake"));
}
- reconfigureButtonFont.setBold(m_configModel->hasChanges(isInitial));
+ reconfigureButtonFont.setBold(isInitial ? m_configModel->hasChanges(isInitial)
+ : !configChanges.isEmpty());
}
m_reconfigureButton->setFont(reconfigureButtonFont);
- m_buildConfiguration->setConfigurationChanges(configChanges);
+ m_buildSystem->setConfigurationChanges(configChanges);
// Update the tooltip with the changes
m_reconfigureButton->setToolTip(
- m_buildConfiguration->configurationChangesArguments(isInitialConfiguration()).join('\n'));
+ m_buildSystem->configurationChangesArguments(isInitialConfiguration()).join('\n'));
}
void CMakeBuildSettingsWidget::updateAdvancedCheckBox()
@@ -764,7 +775,7 @@ void CMakeBuildSettingsWidget::updateAdvancedCheckBox()
void CMakeBuildSettingsWidget::updateFromKit()
{
- const Kit *k = m_buildConfiguration->kit();
+ const Kit *k = m_buildSystem->kit();
CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
config.append(CMakeGeneratorKitAspect::generatorCMakeConfig(k));
@@ -780,7 +791,7 @@ void CMakeBuildSettingsWidget::updateFromKit()
const QStringList additionalKitCMake = ProcessArgs::splitArgs(
CMakeConfigurationKitAspect::additionalConfiguration(k));
const QStringList additionalInitialCMake = ProcessArgs::splitArgs(
- m_buildConfiguration->aspect<InitialCMakeArgumentsAspect>()->value());
+ m_buildSystem->buildConfiguration()->aspect<InitialCMakeArgumentsAspect>()->value());
QStringList mergedArgumentList;
std::set_union(additionalInitialCMake.begin(),
@@ -788,7 +799,7 @@ void CMakeBuildSettingsWidget::updateFromKit()
additionalKitCMake.begin(),
additionalKitCMake.end(),
std::back_inserter(mergedArgumentList));
- m_buildConfiguration->aspect<InitialCMakeArgumentsAspect>()->setValue(
+ m_buildSystem->buildConfiguration()->aspect<InitialCMakeArgumentsAspect>()->setValue(
ProcessArgs::joinArgs(mergedArgumentList));
}
@@ -808,30 +819,46 @@ void CMakeBuildSettingsWidget::updateConfigurationStateIndex(int index)
CMakeConfig CMakeBuildSettingsWidget::getQmlDebugCxxFlags()
{
- const auto aspect = m_buildConfiguration->aspect<QtSupport::QmlDebuggingAspect>();
+ const auto aspect = m_buildSystem->buildConfiguration()->aspect<QtSupport::QmlDebuggingAspect>();
const TriState qmlDebuggingState = aspect->value();
if (qmlDebuggingState == TriState::Default) // don't touch anything
return {};
const bool enable = aspect->value() == TriState::Enabled;
- const CMakeConfig configList = m_buildConfiguration->configurationFromCMake();
- const QByteArrayList cxxFlags{"CMAKE_CXX_FLAGS", "CMAKE_CXX_FLAGS_DEBUG",
- "CMAKE_CXX_FLAGS_RELWITHDEBINFO"};
+ const CMakeConfig configList = m_buildSystem->configurationFromCMake();
+ const QByteArrayList cxxFlagsPrev{"CMAKE_CXX_FLAGS",
+ "CMAKE_CXX_FLAGS_DEBUG",
+ "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
+ "CMAKE_CXX_FLAGS_INIT"};
+ const QByteArrayList cxxFlags{"CMAKE_CXX_FLAGS_INIT", "CMAKE_CXX_FLAGS"};
const QByteArray qmlDebug("-DQT_QML_DEBUG");
CMakeConfig changedConfig;
- for (const CMakeConfigItem &item : configList) {
- if (!cxxFlags.contains(item.key))
- continue;
+ if (enable) {
+ const FilePath cmakeCache = m_buildSystem->cmakeBuildConfiguration()->buildDirectory().pathAppended("CMakeCache.txt");
- CMakeConfigItem it(item);
- if (enable) {
- if (!it.value.contains(qmlDebug)) {
- it.value = it.value.append(' ').append(qmlDebug).trimmed();
- changedConfig.append(it);
+ // Only modify the CMAKE_CXX_FLAGS variable if the project was previously configured
+ // otherwise CMAKE_CXX_FLAGS_INIT will take care of setting the qmlDebug define
+ if (cmakeCache.exists()) {
+ for (const CMakeConfigItem &item : configList) {
+ if (!cxxFlags.contains(item.key))
+ continue;
+
+ CMakeConfigItem it(item);
+ if (!it.value.contains(qmlDebug)) {
+ it.value = it.value.append(' ').append(qmlDebug).trimmed();
+ changedConfig.append(it);
+ }
}
- } else {
+ }
+ } else {
+ // Remove -DQT_QML_DEBUG from all configurations, potentially set by previous Qt Creator versions
+ for (const CMakeConfigItem &item : configList) {
+ if (!cxxFlagsPrev.contains(item.key))
+ continue;
+
+ CMakeConfigItem it(item);
int index = it.value.indexOf(qmlDebug);
if (index != -1) {
it.value.remove(index, qmlDebug.length());
@@ -845,10 +872,10 @@ CMakeConfig CMakeBuildSettingsWidget::getQmlDebugCxxFlags()
CMakeConfig CMakeBuildSettingsWidget::getSigningFlagsChanges()
{
- const CMakeConfig flags = m_buildConfiguration->signingFlags();
+ const CMakeConfig flags = m_buildSystem->cmakeBuildConfiguration()->signingFlags();
if (flags.isEmpty())
return {};
- const CMakeConfig configList = m_buildConfiguration->configurationFromCMake();
+ const CMakeConfig configList = m_buildSystem->configurationFromCMake();
if (configList.isEmpty()) {
// we don't have any configuration --> initial configuration takes care of this itself
return {};
@@ -892,7 +919,8 @@ void CMakeBuildSettingsWidget::updateSelection()
void CMakeBuildSettingsWidget::updateConfigurationStateSelection()
{
const bool hasReplyFile
- = FileApiParser::scanForCMakeReplyFile(m_buildConfiguration->buildDirectory()).exists();
+ = FileApiParser::scanForCMakeReplyFile(
+ m_buildSystem->buildConfiguration()->buildDirectory()).exists();
const int switchToIndex = hasReplyFile ? 1 : 0;
if (m_configurationStates->currentIndex() != switchToIndex)
@@ -970,7 +998,7 @@ bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event)
connect(help, &QAction::triggered, this, [=] {
const CMakeConfigItem item = ConfigModel::dataItemFromIndex(idx).toCMakeConfigItem();
- const CMakeTool *tool = CMakeKitAspect::cmakeTool(m_buildConfiguration->target()->kit());
+ const CMakeTool *tool = CMakeKitAspect::cmakeTool(m_buildSystem->target()->kit());
const QString linkUrl = "%1/variable/" + QString::fromUtf8(item.key) + ".html";
CMakeTool::openCMakeHelpUrl(tool, linkUrl);
});
@@ -1023,7 +1051,8 @@ bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event)
const QStringList variableList
= Utils::transform(validIndexes, [this](const QModelIndex &index) {
return ConfigModel::dataItemFromIndex(index).toCMakeConfigItem().toArgument(
- isInitialConfiguration() ? nullptr : m_buildConfiguration->macroExpander());
+ isInitialConfiguration() ? nullptr
+ : m_buildSystem->buildConfiguration()->macroExpander());
});
QApplication::clipboard()->setText(variableList.join('\n'), QClipboard::Clipboard);
@@ -1035,13 +1064,6 @@ bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event)
return true;
}
-static bool isIos(const Kit *k)
-{
- const Id deviceType = DeviceTypeKitAspect::deviceTypeId(k);
- return deviceType == Ios::Constants::IOS_DEVICE_TYPE
- || deviceType == Ios::Constants::IOS_SIMULATOR_TYPE;
-}
-
static bool isWebAssembly(const Kit *k)
{
return DeviceTypeKitAspect::deviceTypeId(k) == WebAssembly::Constants::WEBASSEMBLY_DEVICE_TYPE;
@@ -1052,11 +1074,6 @@ static bool isQnx(const Kit *k)
return DeviceTypeKitAspect::deviceTypeId(k) == Qnx::Constants::QNX_QNX_OS_TYPE;
}
-static bool isDocker(const Kit *k)
-{
- return DeviceTypeKitAspect::deviceTypeId(k) == Docker::Constants::DOCKER_DEVICE_TYPE;
-}
-
static bool isWindowsARM64(const Kit *k)
{
ToolChain *toolchain = ToolChainKitAspect::cxxToolChain(k);
@@ -1083,14 +1100,15 @@ static CommandLine defaultInitialCMakeCommand(const Kit *k, const QString buildT
Internal::CMakeSpecificSettings *settings
= Internal::CMakeProjectPlugin::projectTypeSpecificSettings();
- // Package manager
- if (!isDocker(k) && settings->packageManagerAutoSetup.value()) {
+ // Package manager auto setup. The file auto-setup.cmake resides on the host,
+ // so it's not accessible for remotely running cmakes. We need to exclude that case.
+ if (!cmd.executable().needsDevice() && settings->packageManagerAutoSetup.value()) {
cmd.addArg("-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH="
"%{IDE:ResourcePath}/package-manager/auto-setup.cmake");
}
// Cross-compilation settings:
- if (!isIos(k)) { // iOS handles this differently
+ if (!CMakeBuildConfiguration::isIos(k)) { // iOS handles this differently
const QString sysRoot = SysRootKitAspect::sysRoot(k).path();
if (!sysRoot.isEmpty()) {
cmd.addArg("-DCMAKE_SYSROOT:PATH=" + sysRoot);
@@ -1180,18 +1198,38 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
}
return QLatin1String();
});
+ macroExpander()->registerVariable(QT_QML_DEBUG_FLAG,
+ tr("The CMake flag for QML debugging, if enabled"),
+ [this] {
+ if (aspect<QtSupport::QmlDebuggingAspect>()->value()
+ == TriState::Enabled) {
+ return QLatin1String(
+ "-DQT_QML_DEBUG");
+ }
+ return QLatin1String();
+ });
addAspect<SourceDirectoryAspect>();
addAspect<BuildTypeAspect>();
+ addAspect<QtSupport::QmlDebuggingAspect>(this);
appendInitialBuildStep(Constants::CMAKE_BUILD_STEP_ID);
appendInitialCleanStep(Constants::CMAKE_BUILD_STEP_ID);
setInitializer([this, target](const BuildInfo &info) {
const Kit *k = target->kit();
-
- CommandLine cmd = defaultInitialCMakeCommand(k, info.typeName);
- setIsMultiConfig(CMakeGeneratorKitAspect::isMultiConfigGenerator(k));
+ const QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(k);
+ const QVariantMap extraInfoMap = info.extraInfo.value<QVariantMap>();
+ const QString buildType = extraInfoMap.contains(CMAKE_BUILD_TYPE)
+ ? extraInfoMap.value(CMAKE_BUILD_TYPE).toString()
+ : info.typeName;
+ const TriState qmlDebugging = extraInfoMap.contains(Constants::QML_DEBUG_SETTING)
+ ? TriState::fromVariant(
+ extraInfoMap.value(Constants::QML_DEBUG_SETTING))
+ : TriState::Default;
+
+ CommandLine cmd = defaultInitialCMakeCommand(k, buildType);
+ m_buildSystem->setIsMultiConfig(CMakeGeneratorKitAspect::isMultiConfigGenerator(k));
// Android magic:
if (DeviceTypeKitAspect::deviceTypeId(k) == Android::Constants::ANDROID_DEVICE_TYPE) {
@@ -1219,7 +1257,6 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
cmd.addArg("-DANDROID_STL:STRING=c++_shared");
cmd.addArg("-DCMAKE_FIND_ROOT_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}");
- QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(k);
auto sdkLocation = bs->data(Android::Constants::SdkLocation).value<FilePath>();
if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber{6, 0, 0}) {
@@ -1234,8 +1271,7 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
}
const IDevice::ConstPtr device = DeviceKitAspect::device(k);
- if (isIos(k)) {
- QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(k);
+ if (CMakeBuildConfiguration::isIos(k)) {
if (qt && qt->qtVersion().majorVersion >= 6) {
// TODO it would be better if we could set
// CMAKE_SYSTEM_NAME=iOS and CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=YES
@@ -1261,7 +1297,6 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
}
if (isWebAssembly(k) || isQnx(k) || isWindowsARM64(k)) {
- const QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(k);
if (qt && qt->qtVersion().majorVersion >= 6)
cmd.addArg(CMAKE_QT6_TOOLCHAIN_FILE_ARG);
}
@@ -1273,18 +1308,17 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id)
info.buildType));
}
- if (info.extraInfo.isValid()) {
- setSourceDirectory(FilePath::fromVariant(
- info.extraInfo.value<QVariantMap>().value(Constants::CMAKE_HOME_DIR)));
- }
+ if (extraInfoMap.contains(Constants::CMAKE_HOME_DIR))
+ setSourceDirectory(FilePath::fromVariant(extraInfoMap.value(Constants::CMAKE_HOME_DIR)));
- setInitialCMakeArguments(cmd.splitArguments());
- setCMakeBuildType(info.typeName);
- });
+ aspect<QtSupport::QmlDebuggingAspect>()->setValue(qmlDebugging);
+
+ if (qt && qt->isQmlDebuggingSupported())
+ cmd.addArg("-DCMAKE_CXX_FLAGS_INIT:STRING=%{" + QLatin1String(QT_QML_DEBUG_FLAG) + "}");
- const auto qmlDebuggingAspect = addAspect<QtSupport::QmlDebuggingAspect>();
- qmlDebuggingAspect->setKit(target->kit());
- setIsMultiConfig(CMakeGeneratorKitAspect::isMultiConfigGenerator(target->kit()));
+ m_buildSystem->setInitialCMakeArguments(cmd.splitArguments());
+ m_buildSystem->setCMakeBuildType(buildType);
+ });
}
CMakeBuildConfiguration::~CMakeBuildConfiguration()
@@ -1322,11 +1356,11 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map)
return QString("");
}
}();
- if (initialCMakeArguments().isEmpty()) {
+ if (m_buildSystem->initialCMakeArguments().isEmpty()) {
CommandLine cmd = defaultInitialCMakeCommand(kit(), buildTypeName);
for (const CMakeConfigItem &item : conf)
cmd.addArg(item.toArgument(macroExpander()));
- setInitialCMakeArguments(cmd.splitArguments());
+ m_buildSystem->setInitialCMakeArguments(cmd.splitArguments());
}
return true;
@@ -1342,8 +1376,8 @@ FilePath CMakeBuildConfiguration::shadowBuildDirectory(const FilePath &projectFi
const QString projectName = projectFilePath.parentDir().fileName();
const FilePath projectDir = Project::projectDirectory(projectFilePath);
- FilePath buildPath = BuildConfiguration::buildDirectoryFromTemplate(projectDir,
- projectFilePath, projectName, k, bcName, buildType, BuildConfiguration::ReplaceSpaces);
+ FilePath buildPath = buildDirectoryFromTemplate(projectDir, projectFilePath, projectName, k,
+ bcName, buildType, "cmake");
if (CMakeGeneratorKitAspect::isMultiConfigGenerator(k)) {
QString path = buildPath.path();
@@ -1354,6 +1388,23 @@ FilePath CMakeBuildConfiguration::shadowBuildDirectory(const FilePath &projectFi
return buildPath;
}
+bool CMakeBuildConfiguration::isIos(const Kit *k)
+{
+ const Id deviceType = DeviceTypeKitAspect::deviceTypeId(k);
+ return deviceType == Ios::Constants::IOS_DEVICE_TYPE
+ || deviceType == Ios::Constants::IOS_SIMULATOR_TYPE;
+}
+
+bool CMakeBuildConfiguration::hasQmlDebugging(const CMakeConfig &config)
+{
+ // Determine QML debugging flags. This must match what we do in
+ // CMakeBuildSettingsWidget::getQmlDebugCxxFlags()
+ // such that in doubt we leave the QML Debugging setting at "Leave at default"
+ const QString cxxFlagsInit = config.stringValueOf("CMAKE_CXX_FLAGS_INIT");
+ const QString cxxFlags = config.stringValueOf("CMAKE_CXX_FLAGS");
+ return cxxFlagsInit.contains("-DQT_QML_DEBUG") && cxxFlags.contains("-DQT_QML_DEBUG");
+}
+
void CMakeBuildConfiguration::buildTarget(const QString &buildTarget)
{
auto cmBs = qobject_cast<CMakeBuildStep *>(findOrDefault(
@@ -1374,17 +1425,17 @@ void CMakeBuildConfiguration::buildTarget(const QString &buildTarget)
cmBs->setBuildTargets(originalBuildTargets);
}
-CMakeConfig CMakeBuildConfiguration::configurationFromCMake() const
+CMakeConfig CMakeBuildSystem::configurationFromCMake() const
{
return m_configurationFromCMake;
}
-CMakeConfig CMakeBuildConfiguration::configurationChanges() const
+CMakeConfig CMakeBuildSystem::configurationChanges() const
{
return m_configurationChanges;
}
-QStringList CMakeBuildConfiguration::configurationChangesArguments(bool initialParameters) const
+QStringList CMakeBuildSystem::configurationChangesArguments(bool initialParameters) const
{
const QList<CMakeConfigItem> filteredInitials
= Utils::filtered(m_configurationChanges, [initialParameters](const CMakeConfigItem &ci) {
@@ -1393,22 +1444,22 @@ QStringList CMakeBuildConfiguration::configurationChangesArguments(bool initialP
return Utils::transform(filteredInitials, &CMakeConfigItem::toArgument);
}
-QStringList CMakeBuildConfiguration::initialCMakeArguments() const
+QStringList CMakeBuildSystem::initialCMakeArguments() const
{
- return aspect<InitialCMakeArgumentsAspect>()->allValues();
+ return buildConfiguration()->aspect<InitialCMakeArgumentsAspect>()->allValues();
}
-CMakeConfig CMakeBuildConfiguration::initialCMakeConfiguration() const
+CMakeConfig CMakeBuildSystem::initialCMakeConfiguration() const
{
- return aspect<InitialCMakeArgumentsAspect>()->cmakeConfiguration();
+ return buildConfiguration()->aspect<InitialCMakeArgumentsAspect>()->cmakeConfiguration();
}
-void CMakeBuildConfiguration::setConfigurationFromCMake(const CMakeConfig &config)
+void CMakeBuildSystem::setConfigurationFromCMake(const CMakeConfig &config)
{
m_configurationFromCMake = config;
}
-void CMakeBuildConfiguration::setConfigurationChanges(const CMakeConfig &config)
+void CMakeBuildSystem::setConfigurationChanges(const CMakeConfig &config)
{
qCDebug(cmakeBuildConfigurationLog)
<< "Configuration changes before:" << configurationChangesArguments();
@@ -1422,7 +1473,7 @@ void CMakeBuildConfiguration::setConfigurationChanges(const CMakeConfig &config)
// FIXME: Run clean steps when a setting starting with "ANDROID_BUILD_ABI_" is changed.
// FIXME: Warn when kit settings are overridden by a project.
-void CMakeBuildConfiguration::clearError(ForceEnabledChanged fec)
+void CMakeBuildSystem::clearError(ForceEnabledChanged fec)
{
if (!m_error.isEmpty()) {
m_error.clear();
@@ -1430,52 +1481,52 @@ void CMakeBuildConfiguration::clearError(ForceEnabledChanged fec)
}
if (fec == ForceEnabledChanged::True) {
qCDebug(cmakeBuildConfigurationLog) << "Emitting enabledChanged signal";
- emit enabledChanged();
+ emit buildConfiguration()->enabledChanged();
}
}
-void CMakeBuildConfiguration::setInitialCMakeArguments(const QStringList &args)
+void CMakeBuildSystem::setInitialCMakeArguments(const QStringList &args)
{
QStringList additionalArguments;
- aspect<InitialCMakeArgumentsAspect>()->setAllValues(args.join('\n'), additionalArguments);
+ buildConfiguration()->aspect<InitialCMakeArgumentsAspect>()->setAllValues(args.join('\n'), additionalArguments);
// Set the unknown additional arguments also for the "Current Configuration"
setAdditionalCMakeArguments(additionalArguments);
}
-QStringList CMakeBuildConfiguration::additionalCMakeArguments() const
+QStringList CMakeBuildSystem::additionalCMakeArguments() const
{
- return ProcessArgs::splitArgs(aspect<AdditionalCMakeOptionsAspect>()->value());
+ return ProcessArgs::splitArgs(buildConfiguration()->aspect<AdditionalCMakeOptionsAspect>()->value());
}
-void CMakeBuildConfiguration::setAdditionalCMakeArguments(const QStringList &args)
+void CMakeBuildSystem::setAdditionalCMakeArguments(const QStringList &args)
{
const QStringList expandedAdditionalArguments = Utils::transform(args, [this](const QString &s) {
- return macroExpander()->expand(s);
+ return buildConfiguration()->macroExpander()->expand(s);
});
const QStringList nonEmptyAdditionalArguments = Utils::filtered(expandedAdditionalArguments,
[](const QString &s) {
return !s.isEmpty();
});
- aspect<AdditionalCMakeOptionsAspect>()->setValue(
+ buildConfiguration()->aspect<AdditionalCMakeOptionsAspect>()->setValue(
ProcessArgs::joinArgs(nonEmptyAdditionalArguments));
}
-void CMakeBuildConfiguration::filterConfigArgumentsFromAdditionalCMakeArguments()
+void CMakeBuildSystem::filterConfigArgumentsFromAdditionalCMakeArguments()
{
// On iOS the %{Ios:DevelopmentTeam:Flag} evalues to something like
// -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM:STRING=MAGICSTRING
// which is already part of the CMake variables and should not be also
// in the addtional CMake options
const QStringList arguments = ProcessArgs::splitArgs(
- aspect<AdditionalCMakeOptionsAspect>()->value());
+ buildConfiguration()->aspect<AdditionalCMakeOptionsAspect>()->value());
QStringList unknownOptions;
const CMakeConfig config = CMakeConfig::fromArguments(arguments, unknownOptions);
- aspect<AdditionalCMakeOptionsAspect>()->setValue(ProcessArgs::joinArgs(unknownOptions));
+ buildConfiguration()->aspect<AdditionalCMakeOptionsAspect>()->setValue(ProcessArgs::joinArgs(unknownOptions));
}
-void CMakeBuildConfiguration::setError(const QString &message)
+void CMakeBuildSystem::setError(const QString &message)
{
qCDebug(cmakeBuildConfigurationLog) << "Setting error to" << message;
QTC_ASSERT(!message.isEmpty(), return );
@@ -1485,13 +1536,13 @@ void CMakeBuildConfiguration::setError(const QString &message)
m_error = message;
if (oldMessage.isEmpty() != !message.isEmpty()) {
qCDebug(cmakeBuildConfigurationLog) << "Emitting enabledChanged signal";
- emit enabledChanged();
+ emit buildConfiguration()->enabledChanged();
}
TaskHub::addTask(BuildSystemTask(Task::TaskType::Error, message));
emit errorOccurred(m_error);
}
-void CMakeBuildConfiguration::setWarning(const QString &message)
+void CMakeBuildSystem::setWarning(const QString &message)
{
if (m_warning == message)
return;
@@ -1500,19 +1551,19 @@ void CMakeBuildConfiguration::setWarning(const QString &message)
emit warningOccurred(m_warning);
}
-QString CMakeBuildConfiguration::error() const
+QString CMakeBuildSystem::error() const
{
return m_error;
}
-QString CMakeBuildConfiguration::warning() const
+QString CMakeBuildSystem::warning() const
{
return m_warning;
}
NamedWidget *CMakeBuildConfiguration::createConfigWidget()
{
- return new CMakeBuildSettingsWidget(this);
+ return new CMakeBuildSettingsWidget(m_buildSystem);
}
CMakeConfig CMakeBuildConfiguration::signingFlags() const
@@ -1568,15 +1619,7 @@ CMakeBuildConfigurationFactory::BuildType CMakeBuildConfigurationFactory::buildT
BuildConfiguration::BuildType CMakeBuildConfigurationFactory::cmakeBuildTypeToBuildType(
const CMakeBuildConfigurationFactory::BuildType &in)
{
- // Cover all common CMake build types
- if (in == BuildTypeRelease || in == BuildTypeMinSizeRel)
- return BuildConfiguration::Release;
- else if (in == BuildTypeDebug)
- return BuildConfiguration::Debug;
- else if (in == BuildTypeRelWithDebInfo)
- return BuildConfiguration::Profile;
- else
- return BuildConfiguration::Unknown;
+ return createBuildInfo(in).buildType;
}
BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(BuildType buildType)
@@ -1589,11 +1632,16 @@ BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(BuildType buildType)
info.displayName = BuildConfiguration::tr("Build");
info.buildType = BuildConfiguration::Unknown;
break;
- case BuildTypeDebug:
+ case BuildTypeDebug: {
info.typeName = "Debug";
info.displayName = BuildConfiguration::tr("Debug");
info.buildType = BuildConfiguration::Debug;
+ QVariantMap extraInfo;
+ // enable QML debugging by default
+ extraInfo.insert(Constants::QML_DEBUG_SETTING, TriState::Enabled.toVariant());
+ info.extraInfo = extraInfo;
break;
+ }
case BuildTypeRelease:
info.typeName = "Release";
info.displayName = BuildConfiguration::tr("Release");
@@ -1609,6 +1657,18 @@ BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(BuildType buildType)
info.displayName = CMakeBuildConfiguration::tr("Release with Debug Information");
info.buildType = BuildConfiguration::Profile;
break;
+ case BuildTypeProfile: {
+ info.typeName = "Profile";
+ info.displayName = CMakeBuildConfiguration::tr("Profile");
+ info.buildType = BuildConfiguration::Profile;
+ QVariantMap extraInfo;
+ // override CMake build type, which defaults to info.typeName
+ extraInfo.insert(CMAKE_BUILD_TYPE, "RelWithDebInfo");
+ // enable QML debugging by default
+ extraInfo.insert(Constants::QML_DEBUG_SETTING, TriState::Enabled.toVariant());
+ info.extraInfo = extraInfo;
+ break;
+ }
default:
QTC_CHECK(false);
break;
@@ -1619,6 +1679,11 @@ BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(BuildType buildType)
BuildConfiguration::BuildType CMakeBuildConfiguration::buildType() const
{
+ return m_buildSystem->buildType();
+}
+
+BuildConfiguration::BuildType CMakeBuildSystem::buildType() const
+{
QByteArray cmakeBuildTypeName = m_configurationFromCMake.valueOf("CMAKE_BUILD_TYPE");
if (cmakeBuildTypeName.isEmpty()) {
QByteArray cmakeCfgTypes = m_configurationFromCMake.valueOf("CMAKE_CONFIGURATION_TYPES");
@@ -1646,24 +1711,33 @@ FilePath CMakeBuildConfiguration::sourceDirectory() const
return aspect<SourceDirectoryAspect>()->filePath();
}
-QString CMakeBuildConfiguration::cmakeBuildType() const
+void CMakeBuildConfiguration::addToEnvironment(Utils::Environment &env) const
+{
+ CMakeSpecificSettings *settings = CMakeProjectPlugin::projectTypeSpecificSettings();
+ if (!settings->ninjaPath.filePath().isEmpty()) {
+ const Utils::FilePath ninja = settings->ninjaPath.filePath();
+ env.appendOrSetPath(ninja.isFile() ? ninja.parentDir() : ninja);
+ }
+}
+
+QString CMakeBuildSystem::cmakeBuildType() const
{
auto setBuildTypeFromConfig = [this](const CMakeConfig &config) {
auto it = std::find_if(config.begin(), config.end(), [](const CMakeConfigItem &item) {
return item.key == "CMAKE_BUILD_TYPE" && !item.isInitial;
});
if (it != config.end())
- const_cast<CMakeBuildConfiguration*>(this)
+ const_cast<CMakeBuildSystem*>(this)
->setCMakeBuildType(QString::fromUtf8(it->value));
};
if (!isMultiConfig())
setBuildTypeFromConfig(configurationChanges());
- QString cmakeBuildType = aspect<BuildTypeAspect>()->value();
+ QString cmakeBuildType = buildConfiguration()->aspect<BuildTypeAspect>()->value();
- const Utils::FilePath cmakeCacheTxt = buildDirectory().pathAppended("CMakeCache.txt");
- const bool hasCMakeCache = QFile::exists(cmakeCacheTxt.toString());
+ const Utils::FilePath cmakeCacheTxt = buildConfiguration()->buildDirectory().pathAppended("CMakeCache.txt");
+ const bool hasCMakeCache = cmakeCacheTxt.exists();
CMakeConfig config;
if (cmakeBuildType == "Unknown") {
@@ -1671,7 +1745,7 @@ QString CMakeBuildConfiguration::cmakeBuildType() const
// that doesn't have the "CMake.Build.Type" aspect saved
if (hasCMakeCache) {
QString errorMessage;
- config = CMakeBuildSystem::parseCMakeCacheDotTxt(cmakeCacheTxt, &errorMessage);
+ config = CMakeConfig::fromFile(cmakeCacheTxt, &errorMessage);
} else {
config = initialCMakeConfiguration();
}
@@ -1685,26 +1759,17 @@ QString CMakeBuildConfiguration::cmakeBuildType() const
return cmakeBuildType;
}
-void CMakeBuildConfiguration::setCMakeBuildType(const QString &cmakeBuildType, bool quiet)
+void CMakeBuildSystem::setCMakeBuildType(const QString &cmakeBuildType, bool quiet)
{
+ auto aspect = buildConfiguration()->aspect<BuildTypeAspect>();
if (quiet) {
- aspect<BuildTypeAspect>()->setValueQuietly(cmakeBuildType);
- aspect<BuildTypeAspect>()->update();
+ aspect->setValueQuietly(cmakeBuildType);
+ aspect->update();
} else {
- aspect<BuildTypeAspect>()->setValue(cmakeBuildType);
+ aspect->setValue(cmakeBuildType);
}
}
-bool CMakeBuildConfiguration::isMultiConfig() const
-{
- return m_isMultiConfig;
-}
-
-void CMakeBuildConfiguration::setIsMultiConfig(bool isMultiConfig)
-{
- m_isMultiConfig = isMultiConfig;
-}
-
namespace Internal {
// ----------------------------------------------------------------------
@@ -1816,7 +1881,7 @@ SourceDirectoryAspect::SourceDirectoryAspect()
// -----------------------------------------------------------------------------
BuildTypeAspect::BuildTypeAspect()
{
- setSettingsKey("CMake.Build.Type");
+ setSettingsKey(CMAKE_BUILD_TYPE);
setLabelText(tr("Build type:"));
setDisplayStyle(LineEditDisplay);
setDefaultValue("Unknown");
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
index 2ac05c33d3a..7d279b1bba1 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
@@ -51,20 +51,11 @@ public:
CMakeBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id);
~CMakeBuildConfiguration() override;
- CMakeConfig configurationFromCMake() const;
- CMakeConfig configurationChanges() const;
-
- QStringList configurationChangesArguments(bool initialParameters = false) const;
-
- QStringList initialCMakeArguments() const;
- CMakeConfig initialCMakeConfiguration() const;
-
- QString error() const;
- QString warning() const;
-
static Utils::FilePath
shadowBuildDirectory(const Utils::FilePath &projectFilePath, const ProjectExplorer::Kit *k,
const QString &bcName, BuildConfiguration::BuildType buildType);
+ static bool isIos(const ProjectExplorer::Kit *k);
+ static bool hasQmlDebugging(const CMakeConfig &config);
// Context menu action:
void buildTarget(const QString &buildTarget);
@@ -73,21 +64,10 @@ public:
void setSourceDirectory(const Utils::FilePath& path);
Utils::FilePath sourceDirectory() const;
- QString cmakeBuildType() const;
- void setCMakeBuildType(const QString &cmakeBuildType, bool quiet = false);
-
- bool isMultiConfig() const;
- void setIsMultiConfig(bool isMultiConfig);
-
- QStringList additionalCMakeArguments() const;
- void setAdditionalCMakeArguments(const QStringList &args);
- void filterConfigArgumentsFromAdditionalCMakeArguments();
+ void addToEnvironment(Utils::Environment &env) const override;
signals:
- void errorOccurred(const QString &message);
- void warningOccurred(const QString &message);
void signingFlagsChanged();
- void configurationChanged(const CMakeConfig &config);
protected:
bool fromMap(const QVariantMap &map) override;
@@ -100,26 +80,8 @@ private:
virtual CMakeConfig signingFlags() const;
- enum ForceEnabledChanged { False, True };
- void clearError(ForceEnabledChanged fec = ForceEnabledChanged::False);
-
- void setConfigurationFromCMake(const CMakeConfig &config);
- void setConfigurationChanges(const CMakeConfig &config);
-
- void setInitialCMakeArguments(const QStringList &args);
-
- void setError(const QString &message);
- void setWarning(const QString &message);
-
- QString m_error;
- QString m_warning;
-
- CMakeConfig m_configurationFromCMake;
- CMakeConfig m_configurationChanges;
Internal::CMakeBuildSystem *m_buildSystem = nullptr;
- bool m_isMultiConfig = false;
-
friend class Internal::CMakeBuildSettingsWidget;
friend class Internal::CMakeBuildSystem;
};
@@ -130,12 +92,15 @@ class CMAKE_EXPORT CMakeBuildConfigurationFactory
public:
CMakeBuildConfigurationFactory();
- enum BuildType { BuildTypeNone = 0,
- BuildTypeDebug = 1,
- BuildTypeRelease = 2,
- BuildTypeRelWithDebInfo = 3,
- BuildTypeMinSizeRel = 4,
- BuildTypeLast = 5 };
+ enum BuildType {
+ BuildTypeNone = 0,
+ BuildTypeDebug = 1,
+ BuildTypeRelease = 2,
+ BuildTypeRelWithDebInfo = 3,
+ BuildTypeProfile = 4,
+ BuildTypeMinSizeRel = 5,
+ BuildTypeLast = 6
+ };
static BuildType buildTypeFromByteArray(const QByteArray &in);
static ProjectExplorer::BuildConfiguration::BuildType cmakeBuildTypeToBuildType(const BuildType &in);
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
index cd537172c8e..98364ee7732 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
@@ -39,6 +39,7 @@
#include <projectexplorer/processparameters.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
#include <projectexplorer/xcodebuildparser.h>
@@ -61,6 +62,8 @@ namespace Internal {
const char BUILD_TARGETS_KEY[] = "CMakeProjectManager.MakeStep.BuildTargets";
const char CMAKE_ARGUMENTS_KEY[] = "CMakeProjectManager.MakeStep.CMakeArguments";
const char TOOL_ARGUMENTS_KEY[] = "CMakeProjectManager.MakeStep.AdditionalArguments";
+const char IOS_AUTOMATIC_PROVISIONG_UPDATES_ARGUMENTS_KEY[] =
+ "CMakeProjectManager.MakeStep.iOSAutomaticProvisioningUpdates";
// CmakeProgressParser
@@ -181,6 +184,19 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Utils::Id id) :
m_toolArguments->setLabelText(tr("Tool arguments:"));
m_toolArguments->setDisplayStyle(StringAspect::LineEditDisplay);
+ Kit *kit = buildConfiguration()->kit();
+ if (CMakeBuildConfiguration::isIos(kit)) {
+ m_useiOSAutomaticProvisioningUpdates = addAspect<BoolAspect>();
+ m_useiOSAutomaticProvisioningUpdates->setDefaultValue(true);
+ m_useiOSAutomaticProvisioningUpdates->setSettingsKey(
+ IOS_AUTOMATIC_PROVISIONG_UPDATES_ARGUMENTS_KEY);
+ m_useiOSAutomaticProvisioningUpdates->setLabel(
+ tr("Enable automatic provisioning updates:"));
+ m_useiOSAutomaticProvisioningUpdates->setToolTip(
+ tr("Tells xcodebuild to create and download a provisioning profile "
+ "if a valid one does not exist."));
+ }
+
m_buildTargetModel.setHeader({tr("Target")});
setBuildTargets({defaultBuildTarget()});
@@ -405,18 +421,26 @@ CommandLine CMakeBuildStep::cmakeCommand() const
}));
auto bs = qobject_cast<CMakeBuildSystem*>(buildSystem());
- auto bc = qobject_cast<CMakeBuildConfiguration*>(buildConfiguration());
- if (bc && bs && bs->isMultiConfig()) {
+ if (bs && bs->isMultiConfigReader()) {
cmd.addArg("--config");
- cmd.addArg(bc->cmakeBuildType());
+ cmd.addArg(bs->cmakeBuildType());
}
if (!m_cmakeArguments->value().isEmpty())
cmd.addArgs(m_cmakeArguments->value(), CommandLine::Raw);
+ bool toolArgumentsSpecified = false;
if (!m_toolArguments->value().isEmpty()) {
cmd.addArg("--");
cmd.addArgs(m_toolArguments->value(), CommandLine::Raw);
+ toolArgumentsSpecified = true;
+ }
+
+ if (m_useiOSAutomaticProvisioningUpdates && m_useiOSAutomaticProvisioningUpdates->value()) {
+ // Only add the double dash if it wasn't added before.
+ if (!toolArgumentsSpecified)
+ cmd.addArg("--");
+ cmd.addArgs("-allowProvisioningUpdates", CommandLine::Raw);
}
return cmd;
@@ -474,6 +498,10 @@ QWidget *CMakeBuildStep::createConfigWidget()
Layouting::Form builder;
builder.addRow(m_cmakeArguments);
builder.addRow(m_toolArguments);
+
+ if (m_useiOSAutomaticProvisioningUpdates)
+ builder.addRow(m_useiOSAutomaticProvisioningUpdates);
+
builder.addRow({new QLabel(tr("Targets:")), frame});
auto widget = builder.emerge();
@@ -482,6 +510,9 @@ QWidget *CMakeBuildStep::createConfigWidget()
connect(m_cmakeArguments, &StringAspect::changed, this, updateDetails);
connect(m_toolArguments, &StringAspect::changed, this, updateDetails);
+ if (m_useiOSAutomaticProvisioningUpdates)
+ connect(m_useiOSAutomaticProvisioningUpdates, &BoolAspect::changed, this, updateDetails);
+
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
this, updateDetails);
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
index 5b5e17eb5dd..aabac3226e4 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
@@ -105,6 +105,7 @@ private:
QStringList m_buildTargets; // Convention: Empty string member signifies "Current executable"
Utils::StringAspect *m_cmakeArguments = nullptr;
Utils::StringAspect *m_toolArguments = nullptr;
+ Utils::BoolAspect *m_useiOSAutomaticProvisioningUpdates = nullptr;
bool m_waiting = false;
QString m_allTarget = "all";
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp
index e89878a6b30..1bca2bbb651 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp
@@ -36,30 +36,35 @@
#include "cmakeprojectplugin.h"
#include "cmakespecificsettings.h"
#include "projecttreehelper.h"
-#include "utils/algorithm.h"
#include <android/androidconstants.h>
+
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
+
#include <cppeditor/cppeditorconstants.h>
#include <cppeditor/cppprojectupdater.h>
#include <cppeditor/generatedcodemodelsupport.h>
+
+#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
+
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qtsupport/qtcppkitinfo.h>
#include <qtsupport/qtkitinformation.h>
#include <app/app_version.h>
+#include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
#include <utils/fileutils.h>
#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimetype.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
@@ -188,8 +193,8 @@ CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc)
return type;
});
- connect(&m_reader, &FileApiReader::configurationStarted, this, [this]() {
- cmakeBuildConfiguration()->clearError(CMakeBuildConfiguration::ForceEnabledChanged::True);
+ connect(&m_reader, &FileApiReader::configurationStarted, this, [this] {
+ clearError(ForceEnabledChanged::True);
});
connect(&m_reader,
@@ -200,6 +205,8 @@ CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc)
connect(&m_reader, &FileApiReader::dirty, this, &CMakeBuildSystem::becameDirty);
wireUpConnections();
+
+ m_isMultiConfig = CMakeGeneratorKitAspect::isMultiConfigGenerator(bc->kit());
}
CMakeBuildSystem::~CMakeBuildSystem()
@@ -217,9 +224,9 @@ CMakeBuildSystem::~CMakeBuildSystem()
void CMakeBuildSystem::triggerParsing()
{
- qCDebug(cmakeBuildSystemLog) << cmakeBuildConfiguration()->displayName() << "Parsing has been triggered";
+ qCDebug(cmakeBuildSystemLog) << buildConfiguration()->displayName() << "Parsing has been triggered";
- if (!cmakeBuildConfiguration()->isActive()) {
+ if (!buildConfiguration()->isActive()) {
qCDebug(cmakeBuildSystemLog)
<< "Parsing has been triggered: SKIPPING since BC is not active -- clearing state.";
stopParsingAndClearState();
@@ -317,8 +324,7 @@ FilePaths CMakeBuildSystem::filesGeneratedFrom(const FilePath &sourceFile) const
}
const FilePath relativePath = baseDirectory.relativePath(project);
- FilePath generatedFilePath = cmakeBuildConfiguration()->buildDirectory().resolvePath(
- relativePath);
+ FilePath generatedFilePath = buildConfiguration()->buildDirectory().resolvePath(relativePath);
if (sourceFile.suffix() == "ui") {
generatedFilePath = generatedFilePath
@@ -351,37 +357,43 @@ QString CMakeBuildSystem::reparseParametersString(int reparseFlags)
return result.trimmed();
}
+void CMakeBuildSystem::reparse(int reparseParameters)
+{
+ setParametersAndRequestParse(BuildDirParameters(this), reparseParameters);
+}
+
void CMakeBuildSystem::setParametersAndRequestParse(const BuildDirParameters &parameters,
const int reparseParameters)
{
project()->clearIssues();
- qCDebug(cmakeBuildSystemLog) << cmakeBuildConfiguration()->displayName()
+ qCDebug(cmakeBuildSystemLog) << buildConfiguration()->displayName()
<< "setting parameters and requesting reparse"
<< reparseParametersString(reparseParameters);
- if (!cmakeBuildConfiguration()->isActive()) {
+ if (!buildConfiguration()->isActive()) {
qCDebug(cmakeBuildSystemLog) << "setting parameters and requesting reparse: SKIPPING since BC is not active -- clearing state.";
stopParsingAndClearState();
return; // ignore request, this build configuration is not active!
}
- if (!parameters.cmakeTool()) {
+ const CMakeTool *tool = parameters.cmakeTool();
+ if (!tool || !tool->isValid()) {
TaskHub::addTask(
BuildSystemTask(Task::Error,
tr("The kit needs to define a CMake tool to parse this project.")));
return;
}
- if (!parameters.cmakeTool()->hasFileApi()) {
- TaskHub::addTask(BuildSystemTask(Task::Error,
- CMakeKitAspect::msgUnsupportedVersion(
- parameters.cmakeTool()->version().fullVersion)));
+ if (!tool->hasFileApi()) {
+ TaskHub::addTask(
+ BuildSystemTask(Task::Error,
+ CMakeKitAspect::msgUnsupportedVersion(tool->version().fullVersion)));
return;
}
QTC_ASSERT(parameters.isValid(), return );
m_parameters = parameters;
- m_parameters.buildDirectory = buildDirectory(parameters);
+ ensureBuildDirectory(parameters);
updateReparseParameters(reparseParameters);
m_reader.setParameters(m_parameters);
@@ -413,31 +425,25 @@ bool CMakeBuildSystem::mustApplyConfigurationChangesArguments(const BuildDirPara
void CMakeBuildSystem::runCMake()
{
- BuildDirParameters parameters(cmakeBuildConfiguration());
qCDebug(cmakeBuildSystemLog) << "Requesting parse due \"Run CMake\" command";
- setParametersAndRequestParse(parameters, REPARSE_FORCE_CMAKE_RUN | REPARSE_URGENT);
+ reparse(REPARSE_FORCE_CMAKE_RUN | REPARSE_URGENT);
}
void CMakeBuildSystem::runCMakeAndScanProjectTree()
{
- BuildDirParameters parameters(cmakeBuildConfiguration());
qCDebug(cmakeBuildSystemLog) << "Requesting parse due to \"Rescan Project\" command";
- setParametersAndRequestParse(parameters,
- REPARSE_FORCE_CMAKE_RUN | REPARSE_URGENT);
+ reparse(REPARSE_FORCE_CMAKE_RUN | REPARSE_URGENT);
}
void CMakeBuildSystem::runCMakeWithExtraArguments()
{
- BuildDirParameters parameters(cmakeBuildConfiguration());
qCDebug(cmakeBuildSystemLog) << "Requesting parse due to \"Rescan Project\" command";
- setParametersAndRequestParse(parameters,
- REPARSE_FORCE_CMAKE_RUN | REPARSE_FORCE_EXTRA_CONFIGURATION
- | REPARSE_URGENT);
+ reparse(REPARSE_FORCE_CMAKE_RUN | REPARSE_FORCE_EXTRA_CONFIGURATION | REPARSE_URGENT);
}
void CMakeBuildSystem::stopCMakeRun()
{
- qCDebug(cmakeBuildSystemLog) << cmakeBuildConfiguration()->displayName()
+ qCDebug(cmakeBuildSystemLog) << buildConfiguration()->displayName()
<< "stopping CMake's run";
m_reader.stopCMakeRun();
}
@@ -451,19 +457,18 @@ void CMakeBuildSystem::buildCMakeTarget(const QString &buildTarget)
bool CMakeBuildSystem::persistCMakeState()
{
- BuildDirParameters parameters(cmakeBuildConfiguration());
+ BuildDirParameters parameters(this);
QTC_ASSERT(parameters.isValid(), return false);
const bool hadBuildDirectory = parameters.buildDirectory.exists();
- parameters.buildDirectory = buildDirectory(parameters);
+ ensureBuildDirectory(parameters);
int reparseFlags = REPARSE_DEFAULT;
qCDebug(cmakeBuildSystemLog) << "Checking whether build system needs to be persisted:"
<< "buildDir:" << parameters.buildDirectory
<< "Has extraargs:" << !parameters.configurationChangesArguments.isEmpty();
- if (parameters.buildDirectory == parameters.buildDirectory
- && mustApplyConfigurationChangesArguments(parameters)) {
+ if (mustApplyConfigurationChangesArguments(parameters)) {
reparseFlags = REPARSE_FORCE_EXTRA_CONFIGURATION;
qCDebug(cmakeBuildSystemLog) << " -> must run CMake with extra arguments.";
}
@@ -504,7 +509,7 @@ void CMakeBuildSystem::clearCMakeCache()
void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
{
- if (cmakeBuildConfiguration()->isActive()) {
+ if (buildConfiguration()->isActive()) {
if (m_waitingForParse)
return;
@@ -517,8 +522,8 @@ void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
CMakeProject::IssueType::Warning,
tr("<b>CMake configuration failed<b>"
"<p>The backup of the previous configuration has been restored.</p>"
- "<p>Have a look at the Issues pane or in the \"Projects > Build\" settings "
- "for more information about the failure.</p"));
+ "<p>Issues and \"Projects > Build\" settings "
+ "show more information about the failure.</p"));
m_reader.resetData();
@@ -534,8 +539,8 @@ void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
project()->addIssue(
CMakeProject::IssueType::Warning,
tr("<b>Failed to load project<b>"
- "<p>Have a look at the Issues pane or in the \"Projects > Build\" settings "
- "for more information about the failure.</p"));
+ "<p>Issues and \"Projects > Build\" settings "
+ "show more information about the failure.</p"));
}
}
}
@@ -543,7 +548,7 @@ void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
void CMakeBuildSystem::checkAndReportError(QString &errorMessage)
{
if (!errorMessage.isEmpty()) {
- cmakeBuildConfiguration()->setError(errorMessage);
+ setError(errorMessage);
errorMessage.clear();
}
}
@@ -554,9 +559,9 @@ void CMakeBuildSystem::updateProjectData()
QTC_ASSERT(m_treeScanner.isFinished() && !m_reader.isParsing(), return );
- cmakeBuildConfiguration()->project()->setExtraProjectFiles(m_reader.projectFilesToWatch());
+ buildConfiguration()->project()->setExtraProjectFiles(m_reader.projectFilesToWatch());
- CMakeConfig patchedConfig = cmakeBuildConfiguration()->configurationFromCMake();
+ CMakeConfig patchedConfig = configurationFromCMake();
{
QSet<QString> res;
QStringList apps;
@@ -621,7 +626,7 @@ void CMakeBuildSystem::updateProjectData()
QString errorMessage;
RawProjectParts rpps = m_reader.createRawProjectParts(errorMessage);
if (!errorMessage.isEmpty())
- cmakeBuildConfiguration()->setError(errorMessage);
+ setError(errorMessage);
qCDebug(cmakeBuildSystemLog) << "Raw project parts created." << errorMessage;
{
@@ -639,7 +644,7 @@ void CMakeBuildSystem::updateProjectData()
}
}
- m_cppCodeModelUpdater->update({p, kitInfo, cmakeBuildConfiguration()->environment(), rpps},
+ m_cppCodeModelUpdater->update({p, kitInfo, buildConfiguration()->environment(), rpps},
m_extraCompilers);
}
{
@@ -648,7 +653,7 @@ void CMakeBuildSystem::updateProjectData()
QStringList extraHeaderPaths;
QList<QByteArray> moduleMappings;
for (const RawProjectPart &rpp : qAsConst(rpps)) {
- FilePath moduleMapFile = cmakeBuildConfiguration()->buildDirectory()
+ FilePath moduleMapFile = buildConfiguration()->buildDirectory()
.pathAppended("qml_module_mappings/" + rpp.buildSystemTarget);
if (moduleMapFile.exists()) {
QFile mmf(moduleMapFile.toString());
@@ -673,7 +678,7 @@ void CMakeBuildSystem::updateProjectData()
}
updateInitialCMakeExpandableVars();
- emit cmakeBuildConfiguration()->buildTypeChanged();
+ emit buildConfiguration()->buildTypeChanged();
qCDebug(cmakeBuildSystemLog) << "All CMake project data up to date.";
}
@@ -732,7 +737,7 @@ void CMakeBuildSystem::updateCMakeConfiguration(QString &errorMessage)
for (auto &ci : cmakeConfig)
ci.inCMakeCache = true;
if (!errorMessage.isEmpty()) {
- const CMakeConfig changes = cmakeBuildConfiguration()->configurationChanges();
+ const CMakeConfig changes = configurationChanges();
for (const auto &ci : changes) {
if (ci.isInitial)
continue;
@@ -743,17 +748,17 @@ void CMakeBuildSystem::updateCMakeConfiguration(QString &errorMessage)
cmakeConfig.append(ci);
}
}
- cmakeBuildConfiguration()->setConfigurationFromCMake(cmakeConfig);
+ setConfigurationFromCMake(cmakeConfig);
}
void CMakeBuildSystem::handleParsingSucceeded(bool restoredFromBackup)
{
- if (!cmakeBuildConfiguration()->isActive()) {
+ if (!buildConfiguration()->isActive()) {
stopParsingAndClearState();
return;
}
- cmakeBuildConfiguration()->clearError();
+ clearError();
QString errorMessage;
{
@@ -786,7 +791,7 @@ void CMakeBuildSystem::handleParsingSucceeded(bool restoredFromBackup)
void CMakeBuildSystem::handleParsingFailed(const QString &msg)
{
- cmakeBuildConfiguration()->setError(msg);
+ setError(msg);
QString errorMessage;
updateCMakeConfiguration(errorMessage);
@@ -810,82 +815,72 @@ void CMakeBuildSystem::wireUpConnections()
connect(target(), &Target::activeBuildConfigurationChanged, this, [this]() {
// Build configuration has changed:
qCDebug(cmakeBuildSystemLog) << "Requesting parse due to active BC changed";
- setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()),
- CMakeBuildSystem::REPARSE_DEFAULT);
+ reparse(CMakeBuildSystem::REPARSE_DEFAULT);
});
connect(project(), &Project::activeTargetChanged, this, [this]() {
// Build configuration has changed:
qCDebug(cmakeBuildSystemLog) << "Requesting parse due to active target changed";
- setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()),
- CMakeBuildSystem::REPARSE_DEFAULT);
+ reparse(CMakeBuildSystem::REPARSE_DEFAULT);
});
// BuildConfiguration changed:
- connect(cmakeBuildConfiguration(), &CMakeBuildConfiguration::environmentChanged, this, [this]() {
+ connect(buildConfiguration(), &BuildConfiguration::environmentChanged, this, [this] {
// The environment on our BC has changed, force CMake run to catch up with possible changes
qCDebug(cmakeBuildSystemLog) << "Requesting parse due to environment change";
- setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()),
- CMakeBuildSystem::REPARSE_FORCE_CMAKE_RUN);
+ reparse(CMakeBuildSystem::REPARSE_FORCE_CMAKE_RUN);
});
- connect(cmakeBuildConfiguration(),
- &CMakeBuildConfiguration::buildDirectoryChanged,
- this,
- [this]() {
- // The build directory of our BC has changed:
- // Does the directory contain a CMakeCache ? Existing build, just parse
- // No CMakeCache? Run with initial arguments!
- qCDebug(cmakeBuildSystemLog) << "Requesting parse due to build directory change";
- const BuildDirParameters parameters(cmakeBuildConfiguration());
- const FilePath cmakeCacheTxt = parameters.buildDirectory.pathAppended("CMakeCache.txt");
- const bool hasCMakeCache = QFile::exists(cmakeCacheTxt.toString());
- const auto options = ReparseParameters(
+ connect(buildConfiguration(), &BuildConfiguration::buildDirectoryChanged, this, [this] {
+ // The build directory of our BC has changed:
+ // Does the directory contain a CMakeCache ? Existing build, just parse
+ // No CMakeCache? Run with initial arguments!
+ qCDebug(cmakeBuildSystemLog) << "Requesting parse due to build directory change";
+ const BuildDirParameters parameters(this);
+ const FilePath cmakeCacheTxt = parameters.buildDirectory.pathAppended("CMakeCache.txt");
+ const bool hasCMakeCache = cmakeCacheTxt.exists();
+ const auto options = ReparseParameters(
hasCMakeCache
- ? REPARSE_DEFAULT
- : (REPARSE_FORCE_INITIAL_CONFIGURATION | REPARSE_FORCE_CMAKE_RUN));
- if (hasCMakeCache) {
- QString errorMessage;
- const CMakeConfig config = CMakeBuildSystem::parseCMakeCacheDotTxt(cmakeCacheTxt, &errorMessage);
- if (!config.isEmpty() && errorMessage.isEmpty()) {
- QString cmakeBuildTypeName = config.stringValueOf("CMAKE_BUILD_TYPE");
- cmakeBuildConfiguration()->setCMakeBuildType(cmakeBuildTypeName, true);
- }
- }
- setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()), options);
- });
+ ? REPARSE_DEFAULT
+ : (REPARSE_FORCE_INITIAL_CONFIGURATION | REPARSE_FORCE_CMAKE_RUN));
+ if (hasCMakeCache) {
+ QString errorMessage;
+ const CMakeConfig config = CMakeConfig::fromFile(cmakeCacheTxt, &errorMessage);
+ if (!config.isEmpty() && errorMessage.isEmpty()) {
+ QString cmakeBuildTypeName = config.stringValueOf("CMAKE_BUILD_TYPE");
+ setCMakeBuildType(cmakeBuildTypeName, true);
+ }
+ }
+ reparse(options);
+ });
- connect(project(), &Project::projectFileIsDirty, this, [this]() {
- if (cmakeBuildConfiguration()->isActive() && !isParsing()) {
- const auto cmake = CMakeKitAspect::cmakeTool(cmakeBuildConfiguration()->kit());
+ connect(project(), &Project::projectFileIsDirty, this, [this] {
+ if (buildConfiguration()->isActive() && !isParsing()) {
+ const auto cmake = CMakeKitAspect::cmakeTool(kit());
if (cmake && cmake->isAutoRun()) {
qCDebug(cmakeBuildSystemLog) << "Requesting parse due to dirty project file";
- setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()),
- CMakeBuildSystem::REPARSE_FORCE_CMAKE_RUN);
+ reparse(CMakeBuildSystem::REPARSE_FORCE_CMAKE_RUN);
}
}
});
// Force initial parsing run:
- if (cmakeBuildConfiguration()->isActive()) {
+ if (buildConfiguration()->isActive()) {
qCDebug(cmakeBuildSystemLog) << "Initial run:";
- setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()),
- CMakeBuildSystem::REPARSE_DEFAULT);
+ reparse(CMakeBuildSystem::REPARSE_DEFAULT);
}
}
-FilePath CMakeBuildSystem::buildDirectory(const BuildDirParameters &parameters)
+void CMakeBuildSystem::ensureBuildDirectory(const BuildDirParameters &parameters)
{
const FilePath bdir = parameters.buildDirectory;
- if (!cmakeBuildConfiguration()->createBuildDirectory())
+ if (!buildConfiguration()->createBuildDirectory())
handleParsingFailed(
tr("Failed to create build directory \"%1\".").arg(bdir.toUserOutput()));
-
- return bdir;
}
void CMakeBuildSystem::stopParsingAndClearState()
{
- qCDebug(cmakeBuildSystemLog) << cmakeBuildConfiguration()->displayName()
+ qCDebug(cmakeBuildSystemLog) << buildConfiguration()->displayName()
<< "stopping parsing run!";
m_reader.stop();
m_reader.resetData();
@@ -897,7 +892,7 @@ void CMakeBuildSystem::becameDirty()
if (isParsing())
return;
- setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()), REPARSE_DEFAULT);
+ reparse(REPARSE_DEFAULT);
}
void CMakeBuildSystem::updateReparseParameters(const int parameters)
@@ -914,19 +909,20 @@ int CMakeBuildSystem::takeReparseParameters()
void CMakeBuildSystem::runCTest()
{
- if (!cmakeBuildConfiguration()->error().isEmpty() || m_ctestPath.isEmpty()) {
+ if (!m_error.isEmpty() || m_ctestPath.isEmpty()) {
qCDebug(cmakeBuildSystemLog) << "Cancel ctest run after failed cmake run";
emit testInformationUpdated();
return;
}
qCDebug(cmakeBuildSystemLog) << "Requesting ctest run after cmake run";
- const BuildDirParameters parameters(cmakeBuildConfiguration());
+ const BuildDirParameters parameters(this);
QTC_ASSERT(parameters.isValid(), return);
const CommandLine cmd { m_ctestPath, { "-N", "--show-only=json-v1" } };
- const FilePath workingDirectory = buildDirectory(parameters);
- const Environment environment = cmakeBuildConfiguration()->environment();
+ ensureBuildDirectory(parameters);
+ const FilePath workingDirectory = parameters.buildDirectory;
+ const Environment environment = buildConfiguration()->environment();
auto future = Utils::runAsync([cmd, workingDirectory, environment]
(QFutureInterface<QByteArray> &futureInterface) {
@@ -1048,20 +1044,6 @@ const QList<CMakeBuildTarget> &CMakeBuildSystem::buildTargets() const
return m_buildTargets;
}
-CMakeConfig CMakeBuildSystem::parseCMakeCacheDotTxt(const Utils::FilePath &cacheFile,
- QString *errorMessage)
-{
- if (!cacheFile.exists()) {
- if (errorMessage)
- *errorMessage = tr("CMakeCache.txt file not found.");
- return {};
- }
- CMakeConfig result = CMakeConfig::fromFile(cacheFile, errorMessage);
- if (!errorMessage->isEmpty())
- return {};
- return result;
-}
-
bool CMakeBuildSystem::filteredOutTarget(const CMakeBuildTarget &target)
{
return target.title.endsWith("_autogen") ||
@@ -1070,6 +1052,16 @@ bool CMakeBuildSystem::filteredOutTarget(const CMakeBuildTarget &target)
bool CMakeBuildSystem::isMultiConfig() const
{
+ return m_isMultiConfig;
+}
+
+void CMakeBuildSystem::setIsMultiConfig(bool isMultiConfig)
+{
+ m_isMultiConfig = isMultiConfig;
+}
+
+bool CMakeBuildSystem::isMultiConfigReader() const
+{
return m_reader.isMultiConfig();
}
@@ -1111,7 +1103,7 @@ DeploymentData CMakeBuildSystem::deploymentData() const
DeploymentData result;
QDir sourceDir = project()->projectDirectory().toString();
- QDir buildDir = cmakeBuildConfiguration()->buildDirectory().toString();
+ QDir buildDir = buildConfiguration()->buildDirectory().toString();
QString deploymentPrefix;
QString deploymentFilePath = sourceDir.filePath("QtCreatorDeployment.txt");
@@ -1209,11 +1201,12 @@ void CMakeBuildSystem::updateQmlJSCodeModel(const QStringList &extraHeaderPaths,
projectInfo.importPaths.clear();
auto addImports = [&projectInfo](const QString &imports) {
- foreach (const QString &import, CMakeConfigItem::cmakeSplitValue(imports))
+ const QStringList importList = CMakeConfigItem::cmakeSplitValue(imports);
+ for (const QString &import : importList)
projectInfo.importPaths.maybeInsert(FilePath::fromString(import), QmlJS::Dialect::Qml);
};
- const CMakeConfig &cm = cmakeBuildConfiguration()->configurationFromCMake();
+ const CMakeConfig &cm = configurationFromCMake();
addImports(cm.stringValueOf("QML_IMPORT_PATH"));
addImports(kit()->value(QtSupport::KitQmlImportPath::id()).toString());
@@ -1246,9 +1239,8 @@ void CMakeBuildSystem::updateQmlJSCodeModel(const QStringList &extraHeaderPaths,
void CMakeBuildSystem::updateInitialCMakeExpandableVars()
{
- const CMakeConfig &cm = cmakeBuildConfiguration()->configurationFromCMake();
- const CMakeConfig &initialConfig
- = cmakeBuildConfiguration()->initialCMakeConfiguration();
+ const CMakeConfig &cm = configurationFromCMake();
+ const CMakeConfig &initialConfig = initialCMakeConfiguration();
CMakeConfig config;
@@ -1325,7 +1317,33 @@ void CMakeBuildSystem::updateInitialCMakeExpandableVars()
}
if (!config.isEmpty())
- emit cmakeBuildConfiguration()->configurationChanged(config);
+ emit configurationChanged(config);
+}
+
+MakeInstallCommand CMakeBuildSystem::makeInstallCommand(const FilePath &installRoot) const
+{
+ MakeInstallCommand cmd;
+ if (CMakeTool *tool = CMakeKitAspect::cmakeTool(target()->kit()))
+ cmd.command.setExecutable(tool->cmakeExecutable());
+
+ QString installTarget = "install";
+ if (usesAllCapsTargets())
+ installTarget = "INSTALL";
+
+ FilePath buildDirectory = ".";
+ if (auto bc = buildConfiguration())
+ buildDirectory = bc->buildDirectory();
+
+ cmd.command.addArg("--build");
+ cmd.command.addArg(buildDirectory.onDevice(cmd.command.executable()).path());
+ cmd.command.addArg("--target");
+ cmd.command.addArg(installTarget);
+
+ if (isMultiConfigReader())
+ cmd.command.addArgs({"--config", cmakeBuildType()});
+
+ cmd.environment.set("DESTDIR", installRoot.nativePath());
+ return cmd;
}
} // namespace Internal
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h
index 51901eb701a..5ebfd6dfbe0 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h
@@ -30,6 +30,7 @@
#include "cmakeprojectnodes.h"
#include "fileapireader.h"
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsystem.h>
#include <utils/fileutils.h>
@@ -97,21 +98,57 @@ public:
Utils::CommandLine commandLineForTests(const QList<QString> &tests,
const QStringList &options) const final;
- // Generic CMake helper functions:
- static CMakeConfig parseCMakeCacheDotTxt(const Utils::FilePath &cacheFile,
- QString *errorMessage);
+ ProjectExplorer::MakeInstallCommand makeInstallCommand(
+ const Utils::FilePath &installRoot) const final;
static bool filteredOutTarget(const CMakeBuildTarget &target);
bool isMultiConfig() const;
+ void setIsMultiConfig(bool isMultiConfig);
+
+ bool isMultiConfigReader() const;
bool usesAllCapsTargets() const;
CMakeProject *project() const;
+ QString cmakeBuildType() const;
+ void setCMakeBuildType(const QString &cmakeBuildType, bool quiet = false);
+ ProjectExplorer::BuildConfiguration::BuildType buildType() const;
+
+ CMakeConfig configurationFromCMake() const;
+ CMakeConfig configurationChanges() const;
+
+ QStringList configurationChangesArguments(bool initialParameters = false) const;
+
+ QStringList initialCMakeArguments() const;
+ CMakeConfig initialCMakeConfiguration() const;
+
+ QStringList additionalCMakeArguments() const;
+ void setAdditionalCMakeArguments(const QStringList &args);
+
+ void filterConfigArgumentsFromAdditionalCMakeArguments();
+
+ void setConfigurationFromCMake(const CMakeConfig &config);
+ void setConfigurationChanges(const CMakeConfig &config);
+
+ void setInitialCMakeArguments(const QStringList &args);
+
+ QString error() const;
+ QString warning() const;
+
signals:
void configurationCleared();
+ void configurationChanged(const CMakeConfig &config);
+ void errorOccurred(const QString &message);
+ void warningOccurred(const QString &message);
private:
+ enum ForceEnabledChanged { False, True };
+ void clearError(ForceEnabledChanged fec = ForceEnabledChanged::False);
+
+ void setError(const QString &message);
+ void setWarning(const QString &message);
+
// Actually ask for parsing:
enum ReparseParameters {
REPARSE_DEFAULT = 0, // Nothing special:-)
@@ -122,6 +159,7 @@ private:
REPARSE_FORCE_EXTRA_CONFIGURATION = (1 << 2), // Force extra configuration arguments to cmake
REPARSE_URGENT = (1 << 3), // Do not delay the parser run by 1s
};
+ void reparse(int reparseParameters);
QString reparseParametersString(int reparseFlags);
void setParametersAndRequestParse(const BuildDirParameters &parameters,
const int reparseParameters);
@@ -156,7 +194,7 @@ private:
void wireUpConnections();
- Utils::FilePath buildDirectory(const BuildDirParameters &parameters);
+ void ensureBuildDirectory(const BuildDirParameters &parameters);
void stopParsingAndClearState();
void becameDirty();
@@ -172,6 +210,8 @@ private:
bool m_waitingForParse = false;
bool m_combinedScanAndParseResult = false;
+ bool m_isMultiConfig = false;
+
ParseGuard m_currentGuard;
CppEditor::CppProjectUpdater *m_cppCodeModelUpdater = nullptr;
@@ -188,6 +228,12 @@ private:
Utils::FilePath m_ctestPath;
QList<ProjectExplorer::TestCaseInfo> m_testNames;
Utils::FutureSynchronizer m_futureSynchronizer;
+
+ CMakeConfig m_configurationFromCMake;
+ CMakeConfig m_configurationChanges;
+
+ QString m_error;
+ QString m_warning;
};
} // namespace Internal
diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp
index 002ece93261..51aab9a9836 100644
--- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp
@@ -413,7 +413,6 @@ CMakeConfig CMakeConfig::fromFile(const Utils::FilePath &cacheFile, QString *err
Utils::sort(result, &CMakeConfigItem::less);
return result;
-
}
QString CMakeConfigItem::toString(const Utils::MacroExpander *expander) const
diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
index 1ec3414b2d6..7ca0c54f327 100644
--- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
@@ -108,7 +108,7 @@ public:
private:
bool save(const QString &fileName = QString());
void findLinkAt(const QTextCursor &cursor,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool resolveTarget = true,
bool inNextSplit = false) override;
void contextMenuEvent(QContextMenuEvent *e) override;
@@ -152,7 +152,7 @@ static QString unescape(const QString &s)
}
void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool/* resolveTarget*/,
bool /*inNextSplit*/)
{
diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
index 22c0847b74c..bddffdc762e 100644
--- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
@@ -87,8 +87,6 @@ static Id defaultCMakeToolId()
return defaultTool ? defaultTool->id() : Id();
}
-const char TOOL_ID[] = "CMakeProjectManager.CMakeKitInformation";
-
class CMakeKitAspectWidget final : public KitAspectWidget
{
Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeKitAspect)
@@ -101,7 +99,8 @@ public:
m_comboBox->setEnabled(false);
m_comboBox->setToolTip(ki->description());
- foreach (CMakeTool *tool, CMakeToolManager::cmakeTools())
+ const QList<CMakeTool *> tools = CMakeToolManager::cmakeTools();
+ for (const CMakeTool *tool : tools)
cmakeToolAdded(tool->id());
updateComboBox();
@@ -218,7 +217,7 @@ private:
CMakeKitAspect::CMakeKitAspect()
{
setObjectName(QLatin1String("CMakeKitAspect"));
- setId(TOOL_ID);
+ setId(Constants::TOOL_ID);
setDisplayName(tr("CMake Tool"));
setDescription(tr("The CMake Tool to use when building a project with CMake.<br>"
"This setting is ignored when using other build systems."));
@@ -235,14 +234,14 @@ CMakeKitAspect::CMakeKitAspect()
Id CMakeKitAspect::id()
{
- return TOOL_ID;
+ return Constants::TOOL_ID;
}
Id CMakeKitAspect::cmakeToolId(const Kit *k)
{
if (!k)
return {};
- return Id::fromSetting(k->value(TOOL_ID));
+ return Id::fromSetting(k->value(Constants::TOOL_ID));
}
CMakeTool *CMakeKitAspect::cmakeTool(const Kit *k)
@@ -255,14 +254,14 @@ void CMakeKitAspect::setCMakeTool(Kit *k, const Id id)
const Id toSet = id.isValid() ? id : defaultCMakeToolId();
QTC_ASSERT(!id.isValid() || CMakeToolManager::findById(toSet), return);
if (k)
- k->setValue(TOOL_ID, toSet.toSetting());
+ k->setValue(Constants::TOOL_ID, toSet.toSetting());
}
Tasks CMakeKitAspect::validate(const Kit *k) const
{
Tasks result;
CMakeTool *tool = CMakeKitAspect::cmakeTool(k);
- if (tool) {
+ if (tool && tool->isValid()) {
CMakeTool::Version version = tool->version();
if (version.major < 3 || (version.major == 3 && version.minor < 14)) {
result << BuildSystemTask(Task::Warning, msgUnsupportedVersion(version.fullVersion));
@@ -1220,7 +1219,7 @@ Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const
if (!tcC || !tcC->isValid()) {
addWarning(tr("CMake configuration has a path to a C compiler set, "
"even though the kit has no valid tool chain."));
- } else if (tcCPath != tcC->compilerCommand()) {
+ } else if (tcCPath != tcC->compilerCommand() && tcCPath != tcC->compilerCommand().onDevice(tcCPath)) {
addWarning(tr("CMake configuration has a path to a C compiler set "
"that does not match the compiler path "
"configured in the tool chain of the kit."));
@@ -1236,7 +1235,7 @@ Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const
if (!tcCxx || !tcCxx->isValid()) {
addWarning(tr("CMake configuration has a path to a C++ compiler set, "
"even though the kit has no valid tool chain."));
- } else if (tcCxxPath != tcCxx->compilerCommand()) {
+ } else if (tcCxxPath != tcCxx->compilerCommand() && tcCxxPath != tcCxx->compilerCommand().onDevice(tcCxxPath)) {
addWarning(tr("CMake configuration has a path to a C++ compiler set "
"that does not match the compiler path "
"configured in the tool chain of the kit."));
diff --git a/src/plugins/cmakeprojectmanager/cmakeparser.cpp b/src/plugins/cmakeprojectmanager/cmakeparser.cpp
index 3da9a18b49a..addde5fd239 100644
--- a/src/plugins/cmakeprojectmanager/cmakeparser.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeparser.cpp
@@ -64,6 +64,13 @@ void CMakeParser::setSourceDirectory(const QString &sourceDir)
OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputFormat type)
{
+ if (line.startsWith("ninja: build stopped")) {
+ m_lastTask = BuildSystemTask(Task::Error, line);
+ m_lines = 1;
+ flush();
+ return Status::Done;
+ }
+
if (type != StdErrFormat)
return Status::NotHandled;
diff --git a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp
index 90699b86213..8ffe635419f 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp
@@ -25,6 +25,7 @@
#include "cmakeprocess.h"
+#include "builddirparameters.h"
#include "cmakeparser.h"
#include <coreplugin/progressmanager/progressmanager.h>
@@ -32,14 +33,19 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/taskhub.h>
+#include <utils/processinterface.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
+#include <QFutureWatcher>
+
using namespace Utils;
namespace CMakeProjectManager {
namespace Internal {
using namespace ProjectExplorer;
+const int USER_STOP_EXIT_CODE = 15;
static QString stripTrailingNewline(QString str)
{
@@ -48,26 +54,23 @@ static QString stripTrailingNewline(QString str)
return str;
}
-CMakeProcess::CMakeProcess()
-{
- connect(&m_cancelTimer, &QTimer::timeout, this, &CMakeProcess::checkForCancelled);
- m_cancelTimer.setInterval(500);
-}
+CMakeProcess::CMakeProcess() = default;
CMakeProcess::~CMakeProcess()
{
- m_process.reset();
m_parser.flush();
- if (m_future) {
- reportCanceled();
- reportFinished();
+ if (m_futureWatcher) {
+ m_futureWatcher.reset();
+ // None of the progress related functions will work after this!
+ m_futureInterface.reportCanceled();
+ m_futureInterface.reportFinished();
}
}
void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &arguments)
{
- QTC_ASSERT(!m_process && !m_future, return);
+ QTC_ASSERT(!m_process, return);
CMakeTool *cmake = parameters.cmakeTool();
QTC_ASSERT(parameters.isValid() && cmake, return);
@@ -78,8 +81,9 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
const FilePath buildDirectory = parameters.buildDirectory.onDevice(cmakeExecutable);
if (!buildDirectory.exists()) {
- QString msg = tr("The build directory \"%1\" does not exist")
- .arg(buildDirectory.toUserOutput());
+ QString msg = ::CMakeProjectManager::Internal::CMakeProcess::tr(
+ "The build directory \"%1\" does not exist")
+ .arg(buildDirectory.toUserOutput());
BuildSystem::appendBuildSystemOutput(msg + '\n');
emit finished();
return;
@@ -87,9 +91,11 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
if (buildDirectory.needsDevice()) {
if (cmake->cmakeExecutable().host() != buildDirectory.host()) {
- QString msg = tr("CMake executable \"%1\" and build directory "
- "\"%2\" must be on the same device.")
- .arg(cmake->cmakeExecutable().toUserOutput(), buildDirectory.toUserOutput());
+ QString msg = ::CMakeProjectManager::Internal::CMakeProcess::tr(
+ "CMake executable \"%1\" and build directory "
+ "\"%2\" must be on the same device.")
+ .arg(cmake->cmakeExecutable().toUserOutput(),
+ buildDirectory.toUserOutput());
BuildSystem::appendBuildSystemOutput(msg + '\n');
emit finished();
return;
@@ -103,25 +109,23 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
// Always use the sourceDir: If we are triggered because the build directory is getting deleted
// then we are racing against CMakeCache.txt also getting deleted.
- auto process = std::make_unique<QtcProcess>();
- m_processWasCanceled = false;
-
- m_cancelTimer.start();
+ m_process.reset(new QtcProcess);
- process->setWorkingDirectory(buildDirectory);
- process->setEnvironment(parameters.environment);
+ m_process->setWorkingDirectory(buildDirectory);
+ m_process->setEnvironment(parameters.environment);
- process->setStdOutLineCallback([](const QString &s) {
+ m_process->setStdOutLineCallback([](const QString &s) {
BuildSystem::appendBuildSystemOutput(stripTrailingNewline(s));
});
- process->setStdErrLineCallback([this](const QString &s) {
+ m_process->setStdErrLineCallback([this](const QString &s) {
m_parser.appendMessage(s, StdErrFormat);
BuildSystem::appendBuildSystemOutput(stripTrailingNewline(s));
});
- connect(process.get(), &QtcProcess::finished,
- this, &CMakeProcess::handleProcessFinished);
+ connect(m_process.get(), &QtcProcess::done, this, [this] {
+ handleProcessDone(m_process->resultData());
+ });
CommandLine commandLine(cmakeExecutable);
commandLine.addArgs({"-S", sourceDirectory.path(), "-B", buildDirectory.path()});
@@ -130,87 +134,68 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
BuildSystem::startNewBuildSystemOutput(
- tr("Running %1 in %2.").arg(commandLine.toUserOutput()).arg(buildDirectory.toUserOutput()));
-
- auto future = std::make_unique<QFutureInterface<void>>();
- future->setProgressRange(0, 1);
- Core::ProgressManager::addTimedTask(*future.get(),
- tr("Configuring \"%1\"").arg(parameters.projectName),
+ ::CMakeProjectManager::Internal::CMakeProcess::tr("Running %1 in %2.")
+ .arg(commandLine.toUserOutput(), buildDirectory.toUserOutput()));
+
+ m_futureInterface = QFutureInterface<void>();
+ m_futureInterface.setProgressRange(0, 1);
+ Core::ProgressManager::addTimedTask(m_futureInterface,
+ ::CMakeProjectManager::Internal::CMakeProcess::tr(
+ "Configuring \"%1\"")
+ .arg(parameters.projectName),
"CMake.Configure",
10);
+ m_futureWatcher.reset(new QFutureWatcher<void>);
+ connect(m_futureWatcher.get(), &QFutureWatcher<void>::canceled, this, &CMakeProcess::stop);
+ m_futureWatcher->setFuture(m_futureInterface.future());
- process->setCommand(commandLine);
+ m_process->setCommand(commandLine);
emit started();
m_elapsed.start();
- process->start();
-
- m_process = std::move(process);
- m_future = std::move(future);
-}
-
-void CMakeProcess::terminate()
-{
- if (m_process) {
- m_processWasCanceled = true;
- m_process->terminate();
- }
-}
-
-QProcess::ProcessState CMakeProcess::state() const
-{
- if (m_process)
- return m_process->state();
- return QProcess::NotRunning;
+ m_process->start();
}
-void CMakeProcess::reportCanceled()
+void CMakeProcess::stop()
{
- QTC_ASSERT(m_future, return);
- m_future->reportCanceled();
-}
-
-void CMakeProcess::reportFinished()
-{
- QTC_ASSERT(m_future, return);
- m_future->reportFinished();
- m_future.reset();
-}
-
-void CMakeProcess::setProgressValue(int p)
-{
- QTC_ASSERT(m_future, return);
- m_future->setProgressValue(p);
+ if (!m_process)
+ return;
+ m_process->close();
+ handleProcessDone({USER_STOP_EXIT_CODE, QProcess::CrashExit, QProcess::Crashed, {}});
}
-void CMakeProcess::handleProcessFinished()
+void CMakeProcess::handleProcessDone(const Utils::ProcessResultData &resultData)
{
- QTC_ASSERT(m_process && m_future, return);
-
- m_cancelTimer.stop();
-
- const int code = m_process->exitCode();
+ if (m_futureWatcher) {
+ m_futureWatcher->disconnect();
+ m_futureWatcher.release()->deleteLater();
+ }
+ const int code = resultData.m_exitCode;
QString msg;
- if (m_process->exitStatus() != QProcess::NormalExit) {
- if (m_processWasCanceled) {
- msg = tr("CMake process was canceled by the user.");
- } else {
- msg = tr("CMake process crashed.");
- }
+ if (resultData.m_error == QProcess::FailedToStart) {
+ msg = ::CMakeProjectManager::Internal::CMakeProcess::tr("CMake process failed to start.");
+ } else if (resultData.m_exitStatus != QProcess::NormalExit) {
+ if (m_futureInterface.isCanceled() || code == USER_STOP_EXIT_CODE)
+ msg = ::CMakeProjectManager::Internal::CMakeProcess::tr(
+ "CMake process was canceled by the user.");
+ else
+ msg = ::CMakeProjectManager::Internal::CMakeProcess::tr("CMake process crashed.");
} else if (code != 0) {
- msg = tr("CMake process exited with exit code %1.").arg(code);
+ msg = ::CMakeProjectManager::Internal::CMakeProcess::tr(
+ "CMake process exited with exit code %1.")
+ .arg(code);
}
m_lastExitCode = code;
if (!msg.isEmpty()) {
BuildSystem::appendBuildSystemOutput(msg + '\n');
TaskHub::addTask(BuildSystemTask(Task::Error, msg));
- m_future->reportCanceled();
+ m_futureInterface.reportCanceled();
} else {
- m_future->setProgressValue(1);
+ m_futureInterface.setProgressValue(1);
}
- m_future->reportFinished();
+ m_futureInterface.reportFinished();
emit finished();
@@ -218,17 +203,5 @@ void CMakeProcess::handleProcessFinished()
BuildSystem::appendBuildSystemOutput(elapsedTime + '\n');
}
-void CMakeProcess::checkForCancelled()
-{
- if (!m_process || !m_future)
- return;
-
- if (m_future->isCanceled()) {
- m_cancelTimer.stop();
- m_processWasCanceled = true;
- m_process->close();
- }
-}
-
} // namespace Internal
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakeprocess.h b/src/plugins/cmakeprojectmanager/cmakeprocess.h
index 946687a4748..99d159ffceb 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprocess.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprocess.h
@@ -25,40 +25,40 @@
#pragma once
-#include "builddirparameters.h"
-
#include <utils/outputformatter.h>
-#include <utils/qtcprocess.h>
#include <QElapsedTimer>
#include <QFutureInterface>
#include <QObject>
#include <QStringList>
-#include <QTimer>
#include <memory>
+QT_BEGIN_NAMESPACE
+template<class T>
+class QFutureWatcher;
+QT_END_NAMESPACE
+
+namespace Utils {
+class ProcessResultData;
+class QtcProcess;
+}
+
namespace CMakeProjectManager {
namespace Internal {
+class BuildDirParameters;
+
class CMakeProcess : public QObject
{
Q_OBJECT
public:
CMakeProcess();
- CMakeProcess(const CMakeProcess&) = delete;
~CMakeProcess();
void run(const BuildDirParameters &parameters, const QStringList &arguments);
- void terminate();
-
- QProcess::ProcessState state() const;
-
- // Update progress information:
- void reportCanceled();
- void reportFinished(); // None of the progress related functions will work after this!
- void setProgressValue(int p);
+ void stop();
int lastExitCode() const { return m_lastExitCode; }
@@ -67,14 +67,12 @@ signals:
void finished();
private:
- void handleProcessFinished();
- void checkForCancelled();
+ void handleProcessDone(const Utils::ProcessResultData &resultData);
std::unique_ptr<Utils::QtcProcess> m_process;
Utils::OutputFormatter m_parser;
- std::unique_ptr<QFutureInterface<void>> m_future;
- bool m_processWasCanceled = false;
- QTimer m_cancelTimer;
+ QFutureInterface<void> m_futureInterface;
+ std::unique_ptr<QFutureWatcher<void>> m_futureWatcher;
QElapsedTimer m_elapsed;
int m_lastExitCode = 0;
};
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index aa78dd534e7..ee6696b0e62 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -25,7 +25,6 @@
#include "cmakeproject.h"
-#include "cmakebuildconfiguration.h"
#include "cmakebuildstep.h"
#include "cmakebuildsystem.h"
#include "cmakekitinformation.h"
@@ -117,38 +116,4 @@ ProjectExplorer::DeploymentKnowledge CMakeProject::deploymentKnowledge() const
: DeploymentKnowledge::Bad;
}
-MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target,
- const QString &installRoot)
-{
- MakeInstallCommand cmd;
- if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) {
- if (const auto cmakeStep = bc->buildSteps()->firstOfType<CMakeBuildStep>()) {
- if (CMakeTool *tool = CMakeKitAspect::cmakeTool(target->kit()))
- cmd.command = tool->cmakeExecutable();
- }
- }
-
- QString installTarget = "install";
- QStringList config;
-
- auto bs = qobject_cast<CMakeBuildSystem*>(target->buildSystem());
- auto bc = qobject_cast<CMakeBuildConfiguration*>(target->activeBuildConfiguration());
- if (bs && bc) {
- if (bs->usesAllCapsTargets())
- installTarget = "INSTALL";
- if (bs->isMultiConfig())
- config << "--config" << bc->cmakeBuildType();
- }
-
- FilePath buildDirectory = ".";
- if (bc)
- buildDirectory = bc->buildDirectory();
-
- cmd.arguments << "--build" << buildDirectory.onDevice(cmd.command).path()
- << "--target" << installTarget << config;
-
- cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot));
- return cmd;
-}
-
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h
index 3ff9303936b..33239234046 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.h
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.h
@@ -31,10 +31,7 @@
namespace CMakeProjectManager {
-namespace Internal {
-class CMakeProjectImporter;
-class CMakeBuildSystem;
-}
+namespace Internal { class CMakeProjectImporter; }
class CMAKE_EXPORT CMakeProject final : public ProjectExplorer::Project
{
@@ -57,13 +54,9 @@ protected:
private:
ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
- ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target,
- const QString &installRoot) override;
mutable Internal::CMakeProjectImporter *m_projectImporter = nullptr;
- friend class Internal::CMakeBuildSystem;
-
ProjectExplorer::Tasks m_issues;
};
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h
index 2e689f6b5ad..d354076e6d4 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h
@@ -38,6 +38,7 @@ const char RUN_CMAKE_CONTEXT_MENU[] = "CMakeProject.RunCMakeContextMenu";
const char BUILD_FILE_CONTEXT_MENU[] = "CMakeProject.BuildFileContextMenu";
const char BUILD_FILE[] = "CMakeProject.BuildFile";
const char CMAKE_HOME_DIR[] = "CMakeProject.HomeDirectory";
+const char QML_DEBUG_SETTING[] = "CMakeProject.EnableQmlDebugging";
// Project
const char CMAKE_PROJECT_ID[] = "CMakeProjectManager.CMakeProject";
@@ -65,5 +66,9 @@ const char CMAKE_BUILD_STEP_ID[] = "CMakeProjectManager.MakeStep";
// Features
const char CMAKE_FEATURE_ID[] = "CMakeProjectManager.Wizard.FeatureCMake";
+// Tool
+const char TOOL_ID[] = "CMakeProjectManager.CMakeKitInformation";
+
+
} // namespace Constants
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
index add008f756d..ed2e24c9909 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
@@ -42,6 +42,7 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <QDir>
@@ -62,6 +63,7 @@ struct DirectoryData
QByteArray cmakeBuildType;
FilePath buildDirectory;
FilePath cmakeHomeDirectory;
+ bool hasQmlDebugging = false;
// Kit Stuff
FilePath cmakeBinary;
@@ -79,7 +81,8 @@ static QStringList scanDirectory(const FilePath &path, const QString &prefix)
QStringList result;
qCDebug(cmInputLog) << "Scanning for directories matching" << prefix << "in" << path;
- foreach (const FilePath &entry, path.dirEntries({{prefix + "*"}, QDir::Dirs | QDir::NoDotAndDotDot})) {
+ const QList<FilePath> entries = path.dirEntries({{prefix + "*"}, QDir::Dirs | QDir::NoDotAndDotDot});
+ for (const FilePath &entry : entries) {
QTC_ASSERT(entry.isDir(), continue);
result.append(entry.toString());
}
@@ -88,6 +91,9 @@ static QStringList scanDirectory(const FilePath &path, const QString &prefix)
static QString baseCMakeToolDisplayName(CMakeTool &tool)
{
+ if (!tool.isValid())
+ return QString("CMake");
+
CMakeTool::Version version = tool.version();
return QString("CMake %1.%2.%3").arg(version.major).arg(version.minor).arg(version.patch);
}
@@ -118,7 +124,8 @@ QStringList CMakeProjectImporter::importCandidates()
candidates << scanDirectory(projectFilePath().absolutePath(), "build");
- foreach (Kit *k, KitManager::kits()) {
+ const QList<Kit *> kits = KitManager::kits();
+ for (const Kit *k : kits) {
FilePath shadowBuildDirectory
= CMakeBuildConfiguration::shadowBuildDirectory(projectFilePath(),
k,
@@ -303,7 +310,7 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
}
QString errorMessage;
- const CMakeConfig config = CMakeBuildSystem::parseCMakeCacheDotTxt(cacheFile, &errorMessage);
+ const CMakeConfig config = CMakeConfig::fromFile(cacheFile, &errorMessage);
if (config.isEmpty() || !errorMessage.isEmpty()) {
qCDebug(cmInputLog) << "Failed to read configuration from" << cacheFile << errorMessage;
return { };
@@ -333,6 +340,8 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
canonicalProjectDirectory.toUserOutput());
}
+ data->hasQmlDebugging = CMakeBuildConfiguration::hasQmlDebugging(config);
+
data->buildDirectory = importPath;
data->cmakeBuildType = buildType;
@@ -382,10 +391,7 @@ bool CMakeProjectImporter::matchKit(void *directoryData, const Kit *k) const
if (!Utils::contains(allLanguages, [&tcd](const Id& language) {return language == tcd.language;}))
continue;
ToolChain *tc = ToolChainKitAspect::toolChain(k, tcd.language);
- if (!tc
- || !Utils::Environment::systemEnvironment()
- .isSameExecutable(tc->compilerCommand().toString(),
- tcd.compilerPath.toString())) {
+ if (!tc || !tc->matchesCompilerCommand(tcd.compilerPath)) {
return false;
}
}
@@ -434,13 +440,22 @@ const QList<BuildInfo> CMakeProjectImporter::buildInfoList(void *directoryData)
auto data = static_cast<const DirectoryData *>(directoryData);
// create info:
- BuildInfo info = CMakeBuildConfigurationFactory::createBuildInfo(
- CMakeBuildConfigurationFactory::buildTypeFromByteArray(data->cmakeBuildType));
+ CMakeBuildConfigurationFactory::BuildType buildType
+ = CMakeBuildConfigurationFactory::buildTypeFromByteArray(data->cmakeBuildType);
+ // RelWithDebInfo + QML Debugging = Profile
+ if (buildType == CMakeBuildConfigurationFactory::BuildTypeRelWithDebInfo
+ && data->hasQmlDebugging)
+ buildType = CMakeBuildConfigurationFactory::BuildTypeProfile;
+ BuildInfo info = CMakeBuildConfigurationFactory::createBuildInfo(buildType);
info.buildDirectory = data->buildDirectory;
- info.displayName = info.typeName;
- QVariantMap config;
+ QVariantMap config = info.extraInfo.toMap(); // new empty, or existing one from createBuildInfo
config.insert(Constants::CMAKE_HOME_DIR, data->cmakeHomeDirectory.toString());
+ // Potentially overwrite the default QML Debugging settings for the build type as set by
+ // createBuildInfo, in case we are importing a "Debug" CMake configuration without QML Debugging
+ config.insert(Constants::QML_DEBUG_SETTING,
+ data->hasQmlDebugging ? TriState::Enabled.toVariant()
+ : TriState::Default.toVariant());
info.extraInfo = config;
qCDebug(cmInputLog) << "BuildInfo configured.";
@@ -532,7 +547,7 @@ void CMakeProjectPlugin::testCMakeProjectImporterQt()
QFETCH(QString, expectedQmake);
CMakeConfig config;
- foreach (const QString &c, cache) {
+ for (const QString &c : qAsConst(cache)) {
const int pos = c.indexOf('=');
Q_ASSERT(pos > 0);
const QString key = c.left(pos);
@@ -589,7 +604,7 @@ void CMakeProjectPlugin::testCMakeProjectImporterToolChain()
QCOMPARE(expectedLanguages.count(), expectedToolChains.count());
CMakeConfig config;
- foreach (const QString &c, cache) {
+ for (const QString &c : qAsConst(cache)) {
const int pos = c.indexOf('=');
Q_ASSERT(pos > 0);
const QString key = c.left(pos);
diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
index 8b17b264544..09a6bfbf2e9 100644
--- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
@@ -243,7 +243,8 @@ CMakeToolItemModel::CMakeToolItemModel()
{ProjectExplorer::Constants::msgAutoDetectedToolTip()}));
rootItem()->appendChild(new StaticTreeItem(tr("Manual")));
- foreach (const CMakeTool *item, CMakeToolManager::cmakeTools())
+ const QList<CMakeTool *> items = CMakeToolManager::cmakeTools();
+ for (const CMakeTool *item : items)
addCMakeTool(item, false);
CMakeTool *defTool = CMakeToolManager::defaultCMakeTool();
@@ -355,7 +356,7 @@ void CMakeToolItemModel::removeCMakeTool(const Utils::Id &id)
void CMakeToolItemModel::apply()
{
- foreach (const Utils::Id &id, m_removedItems)
+ for (const Utils::Id &id : qAsConst(m_removedItems))
CMakeToolManager::deregisterCMakeTool(id);
QList<CMakeToolTreeItem *> toRegister;
@@ -372,7 +373,7 @@ void CMakeToolItemModel::apply()
}
});
- foreach (CMakeToolTreeItem *item, toRegister) {
+ for (CMakeToolTreeItem *item : qAsConst(toRegister)) {
CMakeTool::Detection detection = item->m_autodetected ? CMakeTool::AutoDetection
: CMakeTool::ManualDetection;
auto cmake = std::make_unique<CMakeTool>(detection, item->m_id);
diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp
index e3526737ea4..dbcede75081 100644
--- a/src/plugins/cmakeprojectmanager/cmaketool.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp
@@ -37,6 +37,7 @@
#include <QDir>
#include <QJsonDocument>
#include <QJsonObject>
+#include <QLoggingCategory>
#include <QRegularExpression>
#include <QSet>
#include <QUuid>
@@ -47,6 +48,9 @@ using namespace Utils;
namespace CMakeProjectManager {
+static Q_LOGGING_CATEGORY(cmakeToolLog, "qtc.cmake.tool", QtWarningMsg);
+
+
const char CMAKE_INFORMATION_ID[] = "Id";
const char CMAKE_INFORMATION_COMMAND[] = "Binary";
const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName";
@@ -275,20 +279,20 @@ TextEditor::Keywords CMakeTool::keywords()
if (m_introspection->m_functions.isEmpty() && m_introspection->m_didRun) {
QtcProcess proc;
runCMake(proc, {"--help-command-list"}, 5);
- if (proc.result() == QtcProcess::FinishedWithSuccess)
- m_introspection->m_functions = proc.stdOut().split('\n');
+ if (proc.result() == ProcessResult::FinishedWithSuccess)
+ m_introspection->m_functions = proc.cleanedStdOut().split('\n');
runCMake(proc, {"--help-commands"}, 5);
- if (proc.result() == QtcProcess::FinishedWithSuccess)
- parseFunctionDetailsOutput(proc.stdOut());
+ if (proc.result() == ProcessResult::FinishedWithSuccess)
+ parseFunctionDetailsOutput(proc.cleanedStdOut());
runCMake(proc, {"--help-property-list"}, 5);
- if (proc.result() == QtcProcess::FinishedWithSuccess)
- m_introspection->m_variables = parseVariableOutput(proc.stdOut());
+ if (proc.result() == ProcessResult::FinishedWithSuccess)
+ m_introspection->m_variables = parseVariableOutput(proc.cleanedStdOut());
runCMake(proc, {"--help-variable-list"}, 5);
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- m_introspection->m_variables.append(parseVariableOutput(proc.stdOut()));
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ m_introspection->m_variables.append(parseVariableOutput(proc.cleanedStdOut()));
m_introspection->m_variables = Utils::filteredUnique(m_introspection->m_variables);
Utils::sort(m_introspection->m_variables);
}
@@ -306,12 +310,12 @@ bool CMakeTool::hasFileApi() const
CMakeTool::Version CMakeTool::version() const
{
- return m_introspection ? m_introspection->m_version : CMakeTool::Version();
+ return isValid() ? m_introspection->m_version : CMakeTool::Version();
}
QString CMakeTool::versionDisplay() const
{
- if (!m_introspection)
+ if (!isValid())
return CMakeToolManager::tr("Version not parseable");
const Version &version = m_introspection->m_version;
@@ -428,7 +432,7 @@ static QStringList parseDefinition(const QString &definition)
bool ignoreWord = false;
QVector<QChar> braceStack;
- foreach (const QChar &c, definition) {
+ for (const QChar &c : definition) {
if (c == '[' || c == '<' || c == '(') {
braceStack.append(c);
ignoreWord = false;
@@ -494,7 +498,7 @@ QStringList CMakeTool::parseVariableOutput(const QString &output)
{
const QStringList variableList = output.split('\n');
QStringList result;
- foreach (const QString &v, variableList) {
+ for (const QString &v : variableList) {
if (v.startsWith("CMAKE_COMPILER_IS_GNU<LANG>")) { // This key takes a compiler name :-/
result << "CMAKE_COMPILER_IS_GNUCC"
<< "CMAKE_COMPILER_IS_GNUCXX";
@@ -517,10 +521,11 @@ void CMakeTool::fetchFromCapabilities() const
QtcProcess cmake;
runCMake(cmake, {"-E", "capabilities"});
- if (cmake.result() == QtcProcess::FinishedWithSuccess) {
+ if (cmake.result() == ProcessResult::FinishedWithSuccess) {
m_introspection->m_didRun = true;
- parseFromCapabilities(cmake.stdOut());
+ parseFromCapabilities(cmake.cleanedStdOut());
} else {
+ qCCritical(cmakeToolLog) << "Fetching capabilities failed: " << cmake.allOutput() << cmake.error();
m_introspection->m_didRun = false;
}
}
diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
index 379af3510af..aff75421e2d 100644
--- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
@@ -180,36 +180,44 @@ void CMakeToolManager::updateDocumentation()
Core::HelpManager::registerDocumentation(docs);
}
-void CMakeToolManager::autoDetectCMakeForDevice(const FilePaths &searchPaths,
+QList<Id> CMakeToolManager::autoDetectCMakeForDevice(const FilePaths &searchPaths,
const QString &detectionSource,
QString *logMessage)
{
+ QList<Id> result;
QStringList messages{tr("Searching CMake binaries...")};
for (const FilePath &path : searchPaths) {
const FilePath cmake = path.pathAppended("cmake").withExecutableSuffix();
if (cmake.isExecutableFile()) {
- registerCMakeByPath(cmake, detectionSource);
+ const Id currentId = registerCMakeByPath(cmake, detectionSource);
+ if (currentId.isValid())
+ result.push_back(currentId);
messages.append(tr("Found \"%1\"").arg(cmake.toUserOutput()));
}
}
if (logMessage)
*logMessage = messages.join('\n');
+
+ return result;
}
-void CMakeToolManager::registerCMakeByPath(const FilePath &cmakePath, const QString &detectionSource)
+Id CMakeToolManager::registerCMakeByPath(const FilePath &cmakePath, const QString &detectionSource)
{
- const Id id = Id::fromString(cmakePath.toUserOutput());
+ Id id = Id::fromString(cmakePath.toUserOutput());
CMakeTool *cmakeTool = findById(id);
if (cmakeTool)
- return;
+ return cmakeTool->id();
auto newTool = std::make_unique<CMakeTool>(CMakeTool::ManualDetection, id);
newTool->setFilePath(cmakePath);
newTool->setDetectionSource(detectionSource);
newTool->setDisplayName(cmakePath.toUserOutput());
+ id = newTool->id();
registerCMakeTool(std::move(newTool));
+
+ return id;
}
void CMakeToolManager::removeDetectedCMake(const QString &detectionSource, QString *logMessage)
diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h
index 2364b0f0b50..07ca4eaedec 100644
--- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h
+++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h
@@ -29,7 +29,7 @@
#include "cmaketool.h"
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <utils/id.h>
#include <QObject>
@@ -63,10 +63,10 @@ public:
static void updateDocumentation();
public slots:
- void autoDetectCMakeForDevice(const Utils::FilePaths &searchPaths,
+ QList<Utils::Id> autoDetectCMakeForDevice(const Utils::FilePaths &searchPaths,
const QString &detectionSource,
QString *logMessage);
- void registerCMakeByPath(const Utils::FilePath &cmakePath,
+ Utils::Id registerCMakeByPath(const Utils::FilePath &cmakePath,
const QString &detectionSource);
void removeDetectedCMake(const QString &detectionSource, QString *logMessage);
void listDetectedCMake(const QString &detectionSource, QString *logMessage);
diff --git a/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp b/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp
index 093e5f24ac7..fb17b33657d 100644
--- a/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp
@@ -93,7 +93,7 @@ static std::vector<std::unique_ptr<CMakeTool>> autoDetectCMakeTools()
const QStringList execs = env.appendExeExtensions(QLatin1String("cmake"));
FilePaths suspects;
- foreach (const FilePath &base, path) {
+ for (const FilePath &base : qAsConst(path)) {
if (base.isEmpty())
continue;
@@ -106,10 +106,11 @@ static std::vector<std::unique_ptr<CMakeTool>> autoDetectCMakeTools()
}
std::vector<std::unique_ptr<CMakeTool>> found;
- foreach (const FilePath &command, suspects) {
+ for (const FilePath &command : qAsConst(suspects)) {
auto item = std::make_unique<CMakeTool>(CMakeTool::AutoDetection, CMakeTool::createId());
item->setFilePath(command);
- item->setDisplayName(CMakeToolManager::tr("System CMake at %1").arg(command.toUserOutput()));
+ item->setDisplayName(::CMakeProjectManager::CMakeToolManager::tr("System CMake at %1")
+ .arg(command.toUserOutput()));
found.emplace_back(std::move(item));
}
diff --git a/src/plugins/cmakeprojectmanager/configmodel.cpp b/src/plugins/cmakeprojectmanager/configmodel.cpp
index e170fc49179..4dfbbef4a54 100644
--- a/src/plugins/cmakeprojectmanager/configmodel.cpp
+++ b/src/plugins/cmakeprojectmanager/configmodel.cpp
@@ -687,7 +687,7 @@ QString ConfigModelTreeItem::toolTip() const
if (!dataItem->description.isEmpty())
tooltip << dataItem->description;
- const QString pattern = "<p><b>%1</b> %2</p>";
+ const QString pattern = "<dt style=\"font-weight:bold\">%1</dt><dd>%2</dd>";
if (dataItem->isInitial) {
if (!dataItem->kitValue.isEmpty())
tooltip << pattern.arg(ConfigModel::tr("Kit:")).arg(dataItem->kitValue);
@@ -708,7 +708,7 @@ QString ConfigModelTreeItem::toolTip() const
}
tooltip << pattern.arg(ConfigModel::tr("Type:")).arg(dataItem->typeDisplay());
- return tooltip.join(QString());
+ return "<dl style=\"white-space:pre\">" + tooltip.join(QString()) + "</dl>";
}
QString ConfigModelTreeItem::currentValue() const
diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
index c09a6cd0d56..32e63cfd611 100644
--- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
+++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
@@ -64,6 +64,7 @@ QWidget *ConfigModelItemDelegate::createEditor(QWidget *parent, const QStyleOpti
auto edit = new QComboBox(parent);
edit->setAttribute(Qt::WA_MacSmallSize);
edit->setFocusPolicy(Qt::StrongFocus);
+ edit->setAutoFillBackground(true);
for (const QString &s : qAsConst(data.values))
edit->addItem(s);
return edit;
diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp
index 8a21729fafb..9970fc019c4 100644
--- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp
+++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp
@@ -31,7 +31,7 @@
#include <cppeditor/cppeditorconstants.h>
#include <utils/algorithm.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/utilsicons.h>
@@ -402,18 +402,18 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input,
const bool hasPchSource = anyOf(sources, [buildDirectory](const QString &path) {
return isPchFile(buildDirectory, FilePath::fromString(path));
});
- if (!hasPchSource) {
- QString headerMimeType;
- if (ci.language == "C")
- headerMimeType = CppEditor::Constants::C_HEADER_MIMETYPE;
- else if (ci.language == "CXX")
- headerMimeType = CppEditor::Constants::CPP_HEADER_MIMETYPE;
+ QString headerMimeType;
+ if (ci.language == "C")
+ headerMimeType = CppEditor::Constants::C_HEADER_MIMETYPE;
+ else if (ci.language == "CXX")
+ headerMimeType = CppEditor::Constants::CPP_HEADER_MIMETYPE;
+ if (!hasPchSource) {
for (const SourceInfo &si : t.sources) {
if (si.isGenerated)
continue;
const auto mimeTypes = Utils::mimeTypesForFileName(si.path);
- for (auto mime : mimeTypes)
+ for (const auto &mime : mimeTypes)
if (mime.name() == headerMimeType)
sources.push_back(sourceDir.absoluteFilePath(si.path));
}
@@ -421,8 +421,14 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input,
// Set project files except pch files
rpp.setFiles(Utils::filtered(sources, [buildDirectory](const QString &path) {
- return !isPchFile(buildDirectory, FilePath::fromString(path));
- }));
+ return !isPchFile(buildDirectory, FilePath::fromString(path));
+ }), {}, [headerMimeType](const QString &path) {
+ // Similar to ProjectFile::classify but classify headers with language
+ // of compile group instead of ambiguous header
+ if (path.endsWith(".h"))
+ return headerMimeType;
+ return Utils::mimeTypeForFile(path).name();
+ });
FilePath precompiled_header
= FilePath::fromString(findOrDefault(t.sources, [&ending](const SourceInfo &si) {
diff --git a/src/plugins/cmakeprojectmanager/fileapireader.cpp b/src/plugins/cmakeprojectmanager/fileapireader.cpp
index aa50147aab4..a6f4c01e06e 100644
--- a/src/plugins/cmakeprojectmanager/fileapireader.cpp
+++ b/src/plugins/cmakeprojectmanager/fileapireader.cpp
@@ -25,6 +25,7 @@
#include "fileapireader.h"
+#include "cmakeprocess.h"
#include "fileapidataextractor.h"
#include "fileapiparser.h"
@@ -175,7 +176,7 @@ void FileApiReader::stop()
void FileApiReader::stopCMakeRun()
{
if (m_cmakeProcess)
- m_cmakeProcess->terminate();
+ m_cmakeProcess->stop();
}
bool FileApiReader::isParsing() const
diff --git a/src/plugins/cmakeprojectmanager/fileapireader.h b/src/plugins/cmakeprojectmanager/fileapireader.h
index 298d3c0b973..19949127f64 100644
--- a/src/plugins/cmakeprojectmanager/fileapireader.h
+++ b/src/plugins/cmakeprojectmanager/fileapireader.h
@@ -25,8 +25,8 @@
#pragma once
+#include "builddirparameters.h"
#include "cmakebuildtarget.h"
-#include "cmakeprocess.h"
#include "cmakeprojectnodes.h"
#include "fileapidataextractor.h"
@@ -49,6 +49,7 @@ class ProjectNode;
namespace CMakeProjectManager {
namespace Internal {
+class CMakeProcess;
class FileApiQtcData;
class FileApiReader final : public QObject
diff --git a/src/plugins/coco/CMakeLists.txt b/src/plugins/coco/CMakeLists.txt
new file mode 100644
index 00000000000..ee5685ccbbf
--- /dev/null
+++ b/src/plugins/coco/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_qtc_plugin(Coco
+ PUBLIC_DEPENDS app_version
+ PLUGIN_DEPENDS Core LanguageClient
+ SOURCES
+ cocoplugin.cpp cocoplugin.h
+ cocolanguageclient.cpp cocolanguageclient.h
+)
diff --git a/src/plugins/coco/Coco.json.in b/src/plugins/coco/Coco.json.in
new file mode 100644
index 00000000000..d4a16e34a65
--- /dev/null
+++ b/src/plugins/coco/Coco.json.in
@@ -0,0 +1,19 @@
+{
+ \"Name\" : \"Coco\",
+ \"Version\" : \"$$QTCREATOR_VERSION\",
+ \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
+ \"Experimental\" : true,
+ \"Vendor\" : \"The Qt Company Ltd\",
+ \"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\",
+ \"License\" : [ \"Commercial Usage\",
+ \"\",
+ \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\",
+ \"\",
+ \"GNU General Public License Usage\",
+ \"\",
+ \"Alternatively, this plugin may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this plugin. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html.\"
+ ],
+ \"Description\" : \"Squish Coco support. Squish Coco is a code coverage tool for Tcl, QML, C# and C/C++.\",
+ \"Url\" : \"http://www.qt.io\",
+ $$dependencyList
+}
diff --git a/src/plugins/coco/coco.qbs b/src/plugins/coco/coco.qbs
new file mode 100644
index 00000000000..3a771f27175
--- /dev/null
+++ b/src/plugins/coco/coco.qbs
@@ -0,0 +1,21 @@
+import qbs 1.0
+
+QtcPlugin {
+ name: "Coco"
+
+ Depends { name: "Core" }
+ Depends { name: "LanguageClient" }
+ Depends { name: "TextEditor" }
+
+ Depends { name: "app_version_header" }
+
+ Depends { name: "Qt"; submodules: ["widgets"] }
+
+ files: [
+ "cocoplugin.cpp",
+ "cocoplugin.h",
+ "cocolanguageclient.cpp",
+ "cocolanguageclient.h",
+ ]
+}
+
diff --git a/src/plugins/coco/cocolanguageclient.cpp b/src/plugins/coco/cocolanguageclient.cpp
new file mode 100644
index 00000000000..c26bd83bc45
--- /dev/null
+++ b/src/plugins/coco/cocolanguageclient.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "cocolanguageclient.h"
+
+#include <app/app_version.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <languageclient/diagnosticmanager.h>
+#include <languageclient/languageclienthoverhandler.h>
+#include <languageclient/languageclientinterface.h>
+#include <languageclient/languageclientsettings.h>
+#include <languageserverprotocol/diagnostics.h>
+#include <languageserverprotocol/initializemessages.h>
+#include <projectexplorer/project.h>
+#include <texteditor/texteditor.h>
+#include <texteditor/texteditorsettings.h>
+#include <texteditor/textmark.h>
+#include <utils/utilsicons.h>
+
+#include <QTextEdit>
+
+using namespace LanguageClient;
+using namespace LanguageServerProtocol;
+using namespace Utils;
+using namespace Core;
+
+namespace Coco {
+
+CocoLanguageClient::CocoLanguageClient(const FilePath &coco, const FilePath &csmes)
+ : Client(clientInterface(coco, csmes))
+{
+ setName("Coco");
+ hoverHandler()->setPreferDiagnosticts(false);
+ setActivateDocumentAutomatically(false);
+ LanguageFilter allFiles;
+ allFiles.filePattern = QStringList{"*"};
+ setSupportedLanguage(allFiles);
+ connect(EditorManager::instance(),
+ &EditorManager::documentOpened,
+ this,
+ &CocoLanguageClient::onDocumentOpened);
+ connect(EditorManager::instance(),
+ &EditorManager::documentClosed,
+ this,
+ &CocoLanguageClient::onDocumentClosed);
+ connect(EditorManager::instance(),
+ &EditorManager::editorOpened,
+ this,
+ &CocoLanguageClient::handleEditorOpened);
+ for (IDocument *openDocument : DocumentModel::openedDocuments())
+ onDocumentOpened(openDocument);
+
+ ClientInfo info;
+ info.setName("CocoQtCreator");
+ info.setVersion(Core::Constants::IDE_VERSION_DISPLAY);
+ setClientInfo(info);
+
+ initClientCapabilities();
+}
+
+CocoLanguageClient::~CocoLanguageClient()
+{
+ const QList<Core::IEditor *> &editors = Core::DocumentModel::editorsForOpenedDocuments();
+ for (Core::IEditor *editor : editors) {
+ if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor))
+ textEditor->editorWidget()->removeHoverHandler(hoverHandler());
+ }
+}
+
+BaseClientInterface *CocoLanguageClient::clientInterface(const FilePath &coco,
+ const FilePath &csmes)
+{
+ auto interface = new StdIOClientInterface();
+ interface->setCommandLine(CommandLine(coco, {"--lsp-stdio", csmes.toUserOutput()}));
+ return interface;
+}
+
+enum class CocoDiagnosticSeverity {
+ Error = 1,
+ Warning = 2,
+ Information = 3,
+ Hint = 4,
+
+ CodeAdded = 100,
+ PartiallyCovered = 101,
+ NotCovered = 102,
+ FullyCovered = 103,
+ ManuallyValidated = 104,
+ DeadCode = 105,
+ ExecutionCountTooLow = 106,
+ NotCoveredInfo = 107,
+ CoveredInfo = 108,
+ ManuallyValidatedInfo = 109
+};
+
+static TextEditor::TextStyle styleForSeverity(const CocoDiagnosticSeverity &severity)
+{
+ using namespace TextEditor;
+ switch (severity) {
+ case CocoDiagnosticSeverity::Error: return C_ERROR;
+ case CocoDiagnosticSeverity::Warning: return C_WARNING;
+ case CocoDiagnosticSeverity::Information: return C_WARNING;
+ case CocoDiagnosticSeverity::Hint: return C_WARNING;
+ case CocoDiagnosticSeverity::CodeAdded: return C_COCO_CODE_ADDED;
+ case CocoDiagnosticSeverity::PartiallyCovered: return C_COCO_PARTIALLY_COVERED;
+ case CocoDiagnosticSeverity::NotCovered: return C_COCO_NOT_COVERED;
+ case CocoDiagnosticSeverity::FullyCovered: return C_COCO_FULLY_COVERED;
+ case CocoDiagnosticSeverity::ManuallyValidated: return C_COCO_MANUALLY_VALIDATED;
+ case CocoDiagnosticSeverity::DeadCode: return C_COCO_DEAD_CODE;
+ case CocoDiagnosticSeverity::ExecutionCountTooLow: return C_COCO_EXECUTION_COUNT_TOO_LOW;
+ case CocoDiagnosticSeverity::NotCoveredInfo: return C_COCO_NOT_COVERED_INFO;
+ case CocoDiagnosticSeverity::CoveredInfo: return C_COCO_COVERED_INFO;
+ case CocoDiagnosticSeverity::ManuallyValidatedInfo: return C_COCO_MANUALLY_VALIDATED_INFO;
+ }
+ return C_TEXT;
+}
+
+class CocoDiagnostic : public Diagnostic
+{
+public:
+ using Diagnostic::Diagnostic;
+ optional<CocoDiagnosticSeverity> cocoSeverity() const
+ {
+ if (auto val = optionalValue<int>(severityKey))
+ return Utils::make_optional(static_cast<CocoDiagnosticSeverity>(*val));
+ return Utils::nullopt;
+ }
+};
+
+class CocoTextMark : public TextEditor::TextMark
+{
+public:
+ CocoTextMark(const FilePath &fileName, const CocoDiagnostic &diag, const Id &clientId)
+ : TextEditor::TextMark(fileName, diag.range().start().line() + 1, clientId)
+ , m_severity(diag.cocoSeverity())
+ {
+ setLineAnnotation(diag.message());
+ setToolTip(diag.message());
+ updateAnnotationColor();
+ }
+
+ QColor annotationColor() const override
+ {
+ return m_annotationColor.isValid() ? m_annotationColor
+ : TextEditor::TextMark::annotationColor();
+ }
+
+ void updateAnnotationColor()
+ {
+ if (m_severity) {
+ const TextEditor::TextStyle style = styleForSeverity(*m_severity);
+ m_annotationColor =
+ TextEditor::TextEditorSettings::fontSettings().formatFor(style).foreground();
+ }
+ }
+
+ optional<CocoDiagnosticSeverity> m_severity;
+ QColor m_annotationColor;
+};
+
+class CocoDiagnosticManager : public DiagnosticManager
+{
+public:
+ CocoDiagnosticManager(Client *client)
+ : DiagnosticManager(client)
+ {
+ connect(TextEditor::TextEditorSettings::instance(),
+ &TextEditor::TextEditorSettings::fontSettingsChanged,
+ this,
+ &CocoDiagnosticManager::fontSettingsChanged);
+ setExtraSelectionsId("CocoExtraSelections");
+ }
+
+private:
+ void fontSettingsChanged()
+ {
+ forAllMarks([](TextEditor::TextMark *mark){
+ static_cast<CocoTextMark *>(mark)->updateAnnotationColor();
+ mark->updateMarker();
+ });
+ }
+
+ TextEditor::TextMark *createTextMark(const FilePath &filePath,
+ const Diagnostic &diagnostic,
+ bool /*isProjectFile*/) const override
+ {
+ const CocoDiagnostic cocoDiagnostic(diagnostic);
+ if (optional<CocoDiagnosticSeverity> severity = cocoDiagnostic.cocoSeverity())
+ return new CocoTextMark(filePath, cocoDiagnostic, client()->id());
+ return nullptr;
+ }
+
+ QTextEdit::ExtraSelection createDiagnosticSelection(const Diagnostic &diagnostic,
+ QTextDocument *textDocument) const override
+ {
+ if (optional<CocoDiagnosticSeverity> severity = CocoDiagnostic(diagnostic).cocoSeverity()) {
+ QTextCursor cursor(textDocument);
+ cursor.setPosition(diagnostic.range().start().toPositionInDocument(textDocument));
+ cursor.setPosition(diagnostic.range().end().toPositionInDocument(textDocument),
+ QTextCursor::KeepAnchor);
+
+ const TextEditor::TextStyle style = styleForSeverity(*severity);
+ QTextCharFormat format = TextEditor::TextEditorSettings::fontSettings()
+ .toTextCharFormat(style);
+ format.clearForeground();
+ return QTextEdit::ExtraSelection{cursor, format};
+ }
+ return {};
+ }
+
+ void setDiagnostics(const DocumentUri &uri,
+ const QList<Diagnostic> &diagnostics,
+ const Utils::optional<int> &version) override
+ {
+ DiagnosticManager::setDiagnostics(uri, diagnostics, version);
+ showDiagnostics(uri, client()->documentVersion(uri.toFilePath()));
+ }
+};
+
+DiagnosticManager *CocoLanguageClient::createDiagnosticManager()
+{
+ return new CocoDiagnosticManager(this);
+}
+
+void CocoLanguageClient::handleDiagnostics(const PublishDiagnosticsParams &params)
+{
+ using namespace TextEditor;
+ Client::handleDiagnostics(params);
+ TextDocument *document = documentForFilePath(params.uri().toFilePath());
+ for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(document))
+ editor->editorWidget()->addHoverHandler(hoverHandler());
+}
+
+class CocoTextDocumentCapabilities : public TextDocumentClientCapabilities
+{
+public:
+ using TextDocumentClientCapabilities::TextDocumentClientCapabilities;
+ void enableCodecoverageSupport()
+ {
+ JsonObject coverageSupport(QJsonObject{{"codeCoverageSupport", true}});
+ insert(u"publishDiagnostics", coverageSupport);
+ }
+};
+
+void CocoLanguageClient::initClientCapabilities()
+{
+ ClientCapabilities capabilities = defaultClientCapabilities();
+ CocoTextDocumentCapabilities textDocumentCapabilities(
+ capabilities.textDocument().value_or(TextDocumentClientCapabilities()));
+ textDocumentCapabilities.enableCodecoverageSupport();
+ capabilities.setTextDocument(textDocumentCapabilities);
+ setClientCapabilities(capabilities);
+}
+
+void CocoLanguageClient::onDocumentOpened(IDocument *document)
+{
+ if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
+ openDocument(textDocument);
+}
+
+void CocoLanguageClient::onDocumentClosed(IDocument *document)
+{
+ if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
+ closeDocument(textDocument);
+}
+
+void CocoLanguageClient::handleEditorOpened(IEditor *editor)
+{
+ if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor);
+ textEditor && hasDiagnostics(textEditor->textDocument())) {
+ textEditor->editorWidget()->addHoverHandler(hoverHandler());
+ }
+}
+
+} // namespace Coco
diff --git a/src/plugins/coco/cocolanguageclient.h b/src/plugins/coco/cocolanguageclient.h
new file mode 100644
index 00000000000..a1315ea81c3
--- /dev/null
+++ b/src/plugins/coco/cocolanguageclient.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <languageclient/client.h>
+
+namespace Coco {
+
+class CocoLanguageClient : public LanguageClient::Client
+{
+public:
+ CocoLanguageClient(const Utils::FilePath &coco, const Utils::FilePath &csmes);
+ ~CocoLanguageClient() override;
+
+ LanguageClient::BaseClientInterface *clientInterface(const Utils::FilePath &coco,
+ const Utils::FilePath &csmes);
+
+protected:
+ LanguageClient::DiagnosticManager *createDiagnosticManager() override;
+ void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params) override;
+
+private:
+ void initClientCapabilities();
+ void onDocumentOpened(Core::IDocument *document);
+ void onDocumentClosed(Core::IDocument *document);
+ void handleEditorOpened(Core::IEditor *editor);
+};
+
+} // namespace Coco
diff --git a/src/plugins/coco/cocoplugin.cpp b/src/plugins/coco/cocoplugin.cpp
new file mode 100644
index 00000000000..be5ade51592
--- /dev/null
+++ b/src/plugins/coco/cocoplugin.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "cocoplugin.h"
+
+#include "cocolanguageclient.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/icore.h>
+#include <debugger/analyzer/analyzerconstants.h>
+#include <utils/environment.h>
+#include <utils/pathchooser.h>
+
+#include <QAction>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+
+using namespace Utils;
+
+namespace Coco {
+
+class CocoPluginPrivate
+{
+public:
+ void startCoco();
+
+ CocoLanguageClient *m_client = nullptr;
+};
+
+void CocoPluginPrivate::startCoco()
+{
+ if (m_client)
+ m_client->shutdown();
+ m_client = nullptr;
+
+ QDialog dialog(Core::ICore::dialogParent());
+ dialog.setModal(true);
+ auto layout = new QFormLayout();
+
+ const Environment env = Environment::systemEnvironment();
+ FilePath squishCocoPath = FilePath::fromString(env.value("SQUISHCOCO"));
+ const FilePaths candidates = env.findAllInPath("coveragebrowser", {squishCocoPath});
+
+ PathChooser cocoChooser;
+ if (!candidates.isEmpty())
+ cocoChooser.setFilePath(candidates.first());
+ cocoChooser.setExpectedKind(PathChooser::Command);
+ cocoChooser.setPromptDialogTitle(CocoPlugin::tr(
+ "Select a Squish Coco CoverageBrowser Executable"));
+
+ cocoChooser.setHistoryCompleter("Coco.CoverageBrowser.history", true);
+ layout->addRow(CocoPlugin::tr("CoverageBrowser:"), &cocoChooser);
+ PathChooser csmesChoser;
+ csmesChoser.setHistoryCompleter("Coco.CSMes.history", true);
+ csmesChoser.setExpectedKind(PathChooser::File);
+ csmesChoser.setInitialBrowsePathBackup(FileUtils::homePath());
+ csmesChoser.setPromptDialogFilter(CocoPlugin::tr("Coco instrumentation files (*.csmes)"));
+ csmesChoser.setPromptDialogTitle(CocoPlugin::tr("Select a Squish Coco Instrumentation File"));
+ layout->addRow(CocoPlugin::tr("CSMes:"), &csmesChoser);
+ QDialogButtonBox buttons(QDialogButtonBox::Cancel | QDialogButtonBox::Open);
+ layout->addItem(new QSpacerItem(0, 20, QSizePolicy::Expanding, QSizePolicy::MinimumExpanding));
+ layout->addWidget(&buttons);
+ dialog.setLayout(layout);
+ dialog.resize(480, dialog.height());
+
+ QObject::connect(&buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
+ QObject::connect(&buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
+
+ if (dialog.exec() == QDialog::Accepted) {
+ const FilePath cocoPath = cocoChooser.filePath();
+ const FilePath csmesPath = csmesChoser.filePath();
+ if (cocoPath.isExecutableFile() && csmesPath.exists()) {
+ m_client = new CocoLanguageClient(cocoPath, csmesPath);
+ m_client->start();
+ }
+ }
+}
+
+CocoPlugin::CocoPlugin()
+ : d (new CocoPluginPrivate)
+{}
+
+CocoPlugin::~CocoPlugin()
+{
+ delete d;
+}
+
+bool CocoPlugin::initialize(const QStringList &, QString *)
+{
+ using namespace Core;
+ ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
+ if (menu) {
+ auto startCoco = new QAction("Squish Coco ...", this);
+ Command *cmd = ActionManager::registerAction(startCoco, "Coco.startCoco");
+ menu->addAction(cmd, Debugger::Constants::G_ANALYZER_TOOLS);
+
+ connect(startCoco, &QAction::triggered, this, [this]() { d->startCoco(); });
+ }
+ return true;
+}
+
+} // namespace Coco
+
+
diff --git a/src/plugins/coco/cocoplugin.h b/src/plugins/coco/cocoplugin.h
new file mode 100644
index 00000000000..129a047d53c
--- /dev/null
+++ b/src/plugins/coco/cocoplugin.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <extensionsystem/iplugin.h>
+
+namespace Coco {
+
+class CocoPluginPrivate;
+
+class CocoPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Coco.json")
+
+public:
+ CocoPlugin();
+ ~CocoPlugin() override;
+
+ bool initialize(const QStringList &arguments, QString *errorString) override;
+private:
+ CocoPluginPrivate *d;
+};
+
+} // namespace Coco
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp
index 113e60ad740..d5fdc2dd172 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp
@@ -30,17 +30,22 @@
#include <coreplugin/icore.h>
#include <cppeditor/cpptoolstestcase.h>
#include <cppeditor/projectinfo.h>
+
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/toolchainmanager.h>
+
#include <utils/algorithm.h>
+#include <utils/hostosinfo.h>
#include <QtTest>
using namespace CppEditor;
using namespace ProjectExplorer;
+using namespace Utils;
namespace CompilationDatabaseProjectManager {
namespace Internal {
@@ -120,7 +125,7 @@ public:
QStringList flags;
QString fileName;
QString workingDir;
- QString sysRoot;
+ FilePath sysRoot;
};
}
@@ -131,7 +136,7 @@ void CompilationDatabaseTests::testFilterEmptyFlags()
void CompilationDatabaseTests::testFilterFromFilename()
{
- QCOMPARE(filterFromFileName(QStringList{"-o", "foo.o"}, "foo"), QStringList{"-o"});
+ QCOMPARE(filterFromFileName(QStringList{"-o", "foo.o"}, "foo.c"), QStringList());
}
void CompilationDatabaseTests::testFilterArguments()
@@ -164,8 +169,10 @@ void CompilationDatabaseTests::testFilterArguments()
"c++",
QString("--sysroot=") + (HostOsInfo::isWindowsHost()
? "C:\\sysroot\\embedded" : "/opt/sysroot/embedded"),
- "C:\\qt-creator\\src\\plugins\\cpptools\\compileroptionsbuilder.cpp"},
- "compileroptionsbuilder");
+ QLatin1String(HostOsInfo::isWindowsHost()
+ ? "C:\\qt-creator\\src\\plugins\\cpptools\\compileroptionsbuilder.cpp"
+ : "/opt/qt-creator/src/plugins/cpptools/compileroptionsbuilder.cpp")},
+ "compileroptionsbuilder.cpp");
testData.getFilteredFlags();
@@ -179,8 +186,8 @@ void CompilationDatabaseTests::testFilterArguments()
{"RELATIVE_PLUGIN_PATH", "\"../lib/qtcreator/plugins\""},
{"QT_CREATOR", "1"}}));
QCOMPARE(testData.fileKind, CppEditor::ProjectFile::Kind::CXXSource);
- QCOMPARE(testData.sysRoot, HostOsInfo::isWindowsHost() ? QString("C:\\sysroot\\embedded")
- : QString("/opt/sysroot/embedded"));
+ QCOMPARE(testData.sysRoot.toString(), HostOsInfo::isWindowsHost() ? QString("C:\\sysroot\\embedded")
+ : QString("/opt/sysroot/embedded"));
}
static QString kCmakeCommand
@@ -236,16 +243,18 @@ void CompilationDatabaseTests::testFilterCommand()
testData.fileName = "SemaCodeComplete.cpp";
testData.workingDir = "C:/build-qt_llvm-msvc2017_64bit-Debug";
testData.flags = filterFromFileName(testData.getSplitCommandLine(kCmakeCommand),
- "SemaCodeComplete");
+ "SemaCodeComplete.cpp");
testData.getFilteredFlags();
- QCOMPARE(testData.flags,
- (QStringList{"/Zc:inline", "/Zc:strictStrings", "/Zc:rvalueCast", "/Zi"}));
- QCOMPARE(testData.headerPaths,
- toUserHeaderPaths(QStringList{"C:/build-qt_llvm-msvc2017_64bit-Debug/tools\\clang\\lib\\Sema"}));
- QCOMPARE(testData.macros, (Macros{{"UNICODE", "1"}, {"_HAS_EXCEPTIONS", "0"}, {"WIN32", "1"},
- {"_WINDOWS", "1"}}));
- QCOMPARE(testData.fileKind, CppEditor::ProjectFile::Kind::CXXSource);
+ if (Utils::HostOsInfo::isWindowsHost()) {
+ QCOMPARE(testData.flags,
+ (QStringList{"/Zc:inline", "/Zc:strictStrings", "/Zc:rvalueCast", "/Zi"}));
+ QCOMPARE(testData.headerPaths,
+ toUserHeaderPaths(QStringList{"C:/build-qt_llvm-msvc2017_64bit-Debug/tools\\clang\\lib\\Sema"}));
+ QCOMPARE(testData.macros, (Macros{{"UNICODE", "1"}, {"_HAS_EXCEPTIONS", "0"}, {"WIN32", "1"},
+ {"_WINDOWS", "1"}}));
+ QCOMPARE(testData.fileKind, CppEditor::ProjectFile::Kind::CXXSource);
+ }
}
void CompilationDatabaseTests::testFileKindDifferentFromExtension()
@@ -271,7 +280,7 @@ void CompilationDatabaseTests::testFileKindDifferentFromExtension2()
void CompilationDatabaseTests::testSkipOutputFiles()
{
CompilationDatabaseUtilsTestData testData;
- testData.flags = filterFromFileName(QStringList{"-o", "foo.o"}, "foo");
+ testData.flags = filterFromFileName(QStringList{"-o", "foo.o"}, "foo.cpp");
QVERIFY(testData.getFilteredFlags().isEmpty());
}
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
index b17b2c3a0e5..03b5d590792 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
@@ -38,6 +38,7 @@
#include <QSet>
using namespace ProjectExplorer;
+using namespace Utils;
namespace CompilationDatabaseProjectManager {
namespace Internal {
@@ -83,14 +84,24 @@ static CppEditor::ProjectFile::Kind fileKindFromString(QString flag)
return ProjectFile::Unclassified;
}
-QStringList filterFromFileName(const QStringList &flags, QString baseName)
+QStringList filterFromFileName(const QStringList &flags, QString fileName)
{
- baseName.append('.'); // to match name.c, name.o, etc.
QStringList result;
result.reserve(flags.size());
- for (const QString &flag : flags) {
- if (!flag.contains(baseName))
- result.push_back(flag);
+ bool skipNext = false;
+ for (int i = 0; i < flags.size(); ++i) {
+ const QString &flag = flags.at(i);
+ if (skipNext) {
+ skipNext = false;
+ continue;
+ }
+ if (FilePath::fromUserInput(flag).fileName() == fileName)
+ continue;
+ if (flag == "-o" || flag.startsWith("/Fo")) {
+ skipNext = true;
+ continue;
+ }
+ result.push_back(flag);
}
return result;
@@ -102,7 +113,7 @@ void filteredFlags(const QString &fileName,
HeaderPaths &headerPaths,
Macros &macros,
CppEditor::ProjectFile::Kind &fileKind,
- QString &sysRoot)
+ Utils::FilePath &sysRoot)
{
if (flags.empty())
return;
@@ -192,7 +203,7 @@ void filteredFlags(const QString &fileName,
if (flag.startsWith("--sysroot=")) {
if (sysRoot.isEmpty())
- sysRoot = updatedPathFlag(flag.mid(10), workingDir);
+ sysRoot = FilePath::fromString(updatedPathFlag(flag.mid(10), workingDir));
continue;
}
@@ -206,7 +217,7 @@ void filteredFlags(const QString &fileName,
}
// Skip all remaining Windows flags except feature flags.
- if (flag.startsWith("/") && !flag.startsWith("/Z"))
+ if (Utils::HostOsInfo::isWindowsHost() && flag.startsWith("/") && !flag.startsWith("/Z"))
continue;
filtered.push_back(flag);
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
index 3952b41c6b2..70a94382923 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
@@ -25,10 +25,8 @@
#pragma once
-#include "compilationdatabaseconstants.h"
-
#include <cppeditor/cppprojectfile.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <QHash>
#include <QStringList>
@@ -65,7 +63,7 @@ void filteredFlags(const QString &fileName,
QVector<ProjectExplorer::HeaderPath> &headerPaths,
QVector<ProjectExplorer::Macro> &macros,
CppEditor::ProjectFile::Kind &fileKind,
- QString &sysRoot);
+ Utils::FilePath &sysRoot);
QStringList splitCommandLine(QString commandLine, QSet<QString> &flagsCache);
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp
index 37216a48878..c244eebb2b9 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp
@@ -25,10 +25,12 @@
#include "compilationdbparser.h"
+#include "compilationdatabaseconstants.h"
+
#include <coreplugin/progressmanager/progressmanager.h>
#include <projectexplorer/task.h>
#include <projectexplorer/treescanner.h>
-#include <utils/mimetypes/mimetype.h>
+#include <utils/mimeutils.h>
#include <utils/runextensions.h>
#include <QCryptographicHash>
@@ -151,6 +153,9 @@ void CompilationDbParser::parserJobFinished()
void CompilationDbParser::finish(ParseResult result)
{
+ if (result != ParseResult::Failure)
+ m_guard.markAsSuccess();
+
emit finished(result);
deleteLater();
}
@@ -172,7 +177,7 @@ static QStringList jsonObjectFlags(const QJsonObject &object, QSet<QString> &fla
return flags;
}
-static FilePath jsonObjectFilename(const QJsonObject &object)
+static FilePath jsonObjectFilePath(const QJsonObject &object)
{
const QString workingDir = QDir::cleanPath(object["directory"].toString());
FilePath fileName = FilePath::fromString(QDir::cleanPath(object["file"].toString()));
@@ -199,10 +204,10 @@ std::vector<DbEntry> CompilationDbParser::readJsonObjects() const
}
const QJsonObject object = document.object();
- const Utils::FilePath fileName = jsonObjectFilename(object);
+ const Utils::FilePath filePath = jsonObjectFilePath(object);
const QStringList flags = filterFromFileName(jsonObjectFlags(object, flagsCache),
- fileName.baseName());
- result.push_back({flags, fileName, object["directory"].toString()});
+ filePath.fileName());
+ result.push_back({flags, filePath, object["directory"].toString()});
objectStart = m_projectFileContents.indexOf('{', objectEnd + 1);
objectEnd = m_projectFileContents.indexOf('}', objectStart + 1);
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h
index 72425fa3c51..b5e97a8840c 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h
@@ -69,7 +69,6 @@ public:
QList<ProjectExplorer::FileNode *> scannedFiles() const;
DbContents dbContents() const
{
- m_guard.markAsSuccess();
return m_dbContents;
}
diff --git a/src/plugins/coreplugin/actionmanager/actioncontainer.cpp b/src/plugins/coreplugin/actionmanager/actioncontainer.cpp
index a1f66f9a5b3..078fea7c056 100644
--- a/src/plugins/coreplugin/actionmanager/actioncontainer.cpp
+++ b/src/plugins/coreplugin/actionmanager/actioncontainer.cpp
@@ -351,7 +351,7 @@ Command *ActionContainerPrivate::addSeparator(const Context &context, Id group,
void ActionContainerPrivate::clear()
{
for (Group &group : m_groups) {
- foreach (QObject *item, group.items) {
+ for (QObject *item : qAsConst(group.items)) {
if (auto command = qobject_cast<Command *>(item)) {
removeAction(command);
disconnect(command, &Command::activeStateChanged,
@@ -482,7 +482,7 @@ bool MenuActionContainer::updateInternal()
QList<QAction *> actions = m_menu->actions();
for (const Group &group : qAsConst(m_groups)) {
- foreach (QObject *item, group.items) {
+ for (QObject *item : qAsConst(group.items)) {
if (auto container = qobject_cast<ActionContainerPrivate*>(item)) {
actions.removeAll(container->menu()->menuAction());
if (container == this) {
@@ -512,7 +512,7 @@ bool MenuActionContainer::updateInternal()
}
if (!hasitems) {
// look if there were actions added that we don't control and check if they are enabled
- foreach (const QAction *action, actions) {
+ for (const QAction *action : qAsConst(actions)) {
if (!action->isSeparator() && action->isEnabled()) {
hasitems = true;
break;
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
index 411b7f2cfb9..b328bc3afd4 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
@@ -45,7 +45,6 @@ namespace {
enum { warnAboutFindFailures = 0 };
}
-static const char kKeyboardSettingsKey[] = "KeyboardShortcuts";
static const char kKeyboardSettingsKeyV2[] = "KeyboardShortcutsV2";
using namespace Core;
@@ -244,13 +243,13 @@ ActionContainer *ActionManager::createTouchBar(Id id, const QIcon &icon, const Q
*/
Command *ActionManager::registerAction(QAction *action, Id id, const Context &context, bool scriptable)
{
- Action *a = d->overridableAction(id);
- if (a) {
- a->addOverrideAction(action, context, scriptable);
+ Command *cmd = d->overridableAction(id);
+ if (cmd) {
+ cmd->d->addOverrideAction(action, context, scriptable);
emit m_instance->commandListChanged();
emit m_instance->commandAdded(id);
}
- return a;
+ return cmd;
}
/*!
@@ -302,11 +301,7 @@ ActionContainer *ActionManager::actionContainer(Id id)
*/
QList<Command *> ActionManager::commands()
{
- // transform list of Action into list of Command
- QList<Command *> result;
- foreach (Command *cmd, d->m_idCmdMap)
- result << cmd;
- return result;
+ return d->m_idCmdMap.values();
}
/*!
@@ -319,21 +314,21 @@ QList<Command *> ActionManager::commands()
*/
void ActionManager::unregisterAction(QAction *action, Id id)
{
- Action *a = d->m_idCmdMap.value(id, nullptr);
- if (!a) {
+ Command *cmd = d->m_idCmdMap.value(id, nullptr);
+ if (!cmd) {
qWarning() << "unregisterAction: id" << id.name()
<< "is registered with a different command type.";
return;
}
- a->removeOverrideAction(action);
- if (a->isEmpty()) {
+ cmd->d->removeOverrideAction(action);
+ if (cmd->d->isEmpty()) {
// clean up
- ActionManagerPrivate::saveSettings(a);
- ICore::mainWindow()->removeAction(a->action());
+ ActionManagerPrivate::saveSettings(cmd);
+ ICore::mainWindow()->removeAction(cmd->action());
// ActionContainers listen to the commands' destroyed signals
- delete a->action();
+ delete cmd->action();
d->m_idCmdMap.remove(id);
- delete a;
+ delete cmd;
}
emit m_instance->commandListChanged();
}
@@ -347,7 +342,8 @@ void ActionManager::setPresentationModeEnabled(bool enabled)
return;
// Signal/slots to commands:
- foreach (Command *c, commands()) {
+ const QList<Command *> commandList = commands();
+ for (Command *c : commandList) {
if (c->action()) {
if (enabled)
connect(c->action(), &QAction::triggered, d, &ActionManagerPrivate::actionTriggered);
@@ -407,7 +403,7 @@ void ActionManager::setContext(const Context &context)
ActionManagerPrivate::~ActionManagerPrivate()
{
// first delete containers to avoid them reacting to command deletion
- foreach (ActionContainerPrivate *container, m_idContainerMap)
+ for (const ActionContainerPrivate *container : qAsConst(m_idContainerMap))
disconnect(container, &QObject::destroyed, this, &ActionManagerPrivate::containerDestroyed);
qDeleteAll(m_idContainerMap);
qDeleteAll(m_idCmdMap);
@@ -421,7 +417,7 @@ void ActionManagerPrivate::setContext(const Context &context)
m_context = context;
const IdCmdMap::const_iterator cmdcend = m_idCmdMap.constEnd();
for (IdCmdMap::const_iterator it = m_idCmdMap.constBegin(); it != cmdcend; ++it)
- it.value()->setCurrentContext(m_context);
+ it.value()->d->setCurrentContext(m_context);
}
bool ActionManagerPrivate::hasContext(const Context &context) const
@@ -463,34 +459,32 @@ void ActionManagerPrivate::showShortcutPopup(const QString &shortcut)
Utils::FadingIndicator::showText(window, shortcut);
}
-Action *ActionManagerPrivate::overridableAction(Id id)
+Command *ActionManagerPrivate::overridableAction(Id id)
{
- Action *a = m_idCmdMap.value(id, nullptr);
- if (!a) {
- a = new Action(id);
- m_idCmdMap.insert(id, a);
- readUserSettings(id, a);
- ICore::mainWindow()->addAction(a->action());
- a->action()->setObjectName(id.toString());
- a->action()->setShortcutContext(Qt::ApplicationShortcut);
- a->setCurrentContext(m_context);
+ Command *cmd = m_idCmdMap.value(id, nullptr);
+ if (!cmd) {
+ cmd = new Command(id);
+ m_idCmdMap.insert(id, cmd);
+ readUserSettings(id, cmd);
+ ICore::mainWindow()->addAction(cmd->action());
+ cmd->action()->setObjectName(id.toString());
+ cmd->action()->setShortcutContext(Qt::ApplicationShortcut);
+ cmd->d->setCurrentContext(m_context);
if (ActionManager::isPresentationModeEnabled())
- connect(a->action(), &QAction::triggered, this, &ActionManagerPrivate::actionTriggered);
+ connect(cmd->action(),
+ &QAction::triggered,
+ this,
+ &ActionManagerPrivate::actionTriggered);
}
- return a;
+ return cmd;
}
-void ActionManagerPrivate::readUserSettings(Id id, Action *cmd)
+void ActionManagerPrivate::readUserSettings(Id id, Command *cmd)
{
- // TODO Settings V2 were introduced in Qt Creator 4.13, remove old settings at some point
QSettings *settings = ICore::settings();
- // transfer from old settings if not done before
- const QString group = settings->childGroups().contains(kKeyboardSettingsKeyV2)
- ? QString(kKeyboardSettingsKeyV2)
- : QString(kKeyboardSettingsKey);
- settings->beginGroup(group);
+ settings->beginGroup(kKeyboardSettingsKeyV2);
if (settings->contains(id.toString())) {
const QVariant v = settings->value(id.toString());
if (QMetaType::Type(v.type()) == QMetaType::QStringList) {
@@ -504,20 +498,17 @@ void ActionManagerPrivate::readUserSettings(Id id, Action *cmd)
settings->endGroup();
}
-void ActionManagerPrivate::saveSettings(Action *cmd)
+void ActionManagerPrivate::saveSettings(Command *cmd)
{
const QString id = cmd->id().toString();
const QString settingsKey = QLatin1String(kKeyboardSettingsKeyV2) + '/' + id;
- const QString compatSettingsKey = QLatin1String(kKeyboardSettingsKey) + '/' + id;
const QList<QKeySequence> keys = cmd->keySequences();
const QList<QKeySequence> defaultKeys = cmd->defaultKeySequences();
if (keys != defaultKeys) {
if (keys.isEmpty()) {
ICore::settings()->setValue(settingsKey, QString());
- ICore::settings()->setValue(compatSettingsKey, QString());
} else if (keys.size() == 1) {
ICore::settings()->setValue(settingsKey, keys.first().toString());
- ICore::settings()->setValue(compatSettingsKey, keys.first().toString());
} else {
ICore::settings()->setValue(settingsKey,
Utils::transform<QStringList>(keys,
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager_p.h b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
index 9fdc96aef1a..9226b0380ad 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager_p.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
@@ -25,8 +25,6 @@
#pragma once
-#include <coreplugin/actionmanager/command_p.h>
-#include <coreplugin/actionmanager/actioncontainer_p.h>
#include <coreplugin/icontext.h>
#include <QMap>
@@ -36,9 +34,10 @@
namespace Core {
+class Command;
+
namespace Internal {
-class Action;
class ActionContainerPrivate;
class ActionManagerPrivate : public QObject
@@ -46,7 +45,7 @@ class ActionManagerPrivate : public QObject
Q_OBJECT
public:
- using IdCmdMap = QHash<Utils::Id, Action *>;
+ using IdCmdMap = QHash<Utils::Id, Command *>;
using IdContainerMap = QHash<Utils::Id, ActionContainerPrivate *>;
~ActionManagerPrivate() override;
@@ -55,13 +54,13 @@ public:
bool hasContext(int context) const;
void saveSettings();
- static void saveSettings(Action *cmd);
+ static void saveSettings(Command *cmd);
static void showShortcutPopup(const QString &shortcut);
bool hasContext(const Context &context) const;
- Action *overridableAction(Utils::Id id);
+ Command *overridableAction(Utils::Id id);
- static void readUserSettings(Utils::Id id, Action *cmd);
+ static void readUserSettings(Utils::Id id, Command *cmd);
void containerDestroyed();
void actionTriggered();
diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp
index d41637eaba9..fe2b1c31e95 100644
--- a/src/plugins/coreplugin/actionmanager/command.cpp
+++ b/src/plugins/coreplugin/actionmanager/command.cpp
@@ -23,6 +23,7 @@
**
****************************************************************************/
+#include "command.h"
#include "command_p.h"
#include <coreplugin/coreconstants.h>
@@ -260,82 +261,92 @@
using namespace Utils;
namespace Core {
-namespace Internal {
-Action::Action(Id id)
- : m_attributes({}),
- m_id(id),
- m_action(new Utils::ProxyAction(this))
+Command::Command(Utils::Id id)
+ : d(new Internal::CommandPrivate(this))
+{
+ d->m_id = id;
+}
+
+Command::~Command()
+{
+ delete d;
+}
+
+Internal::CommandPrivate::CommandPrivate(Command *parent)
+ : m_q(parent)
+ , m_attributes({})
+ , m_action(new Utils::ProxyAction(this))
{
m_action->setShortcutVisibleInToolTip(true);
- connect(m_action, &QAction::changed, this, &Action::updateActiveState);
+ connect(m_action, &QAction::changed, this, &CommandPrivate::updateActiveState);
}
-Id Action::id() const
+Id Command::id() const
{
- return m_id;
+ return d->m_id;
}
-void Action::setDefaultKeySequence(const QKeySequence &key)
+void Command::setDefaultKeySequence(const QKeySequence &key)
{
- if (!m_isKeyInitialized)
+ if (!d->m_isKeyInitialized)
setKeySequences({key});
- m_defaultKeys = {key};
+ d->m_defaultKeys = {key};
}
-void Action::setDefaultKeySequences(const QList<QKeySequence> &keys)
+void Command::setDefaultKeySequences(const QList<QKeySequence> &keys)
{
- if (!m_isKeyInitialized)
+ if (!d->m_isKeyInitialized)
setKeySequences(keys);
- m_defaultKeys = keys;
+ d->m_defaultKeys = keys;
}
-QList<QKeySequence> Action::defaultKeySequences() const
+QList<QKeySequence> Command::defaultKeySequences() const
{
- return m_defaultKeys;
+ return d->m_defaultKeys;
}
-QAction *Action::action() const
+QAction *Command::action() const
{
- return m_action;
+ return d->m_action;
}
-QString Action::stringWithAppendedShortcut(const QString &str) const
+QString Command::stringWithAppendedShortcut(const QString &str) const
{
return Utils::ProxyAction::stringWithAppendedShortcut(str, keySequence());
}
-Context Action::context() const
+Context Command::context() const
{
- return m_context;
+ return d->m_context;
}
-void Action::setKeySequences(const QList<QKeySequence> &keys)
+void Command::setKeySequences(const QList<QKeySequence> &keys)
{
- m_isKeyInitialized = true;
- m_action->setShortcuts(keys);
+ d->m_isKeyInitialized = true;
+ d->m_action->setShortcuts(keys);
emit keySequenceChanged();
}
-QList<QKeySequence> Action::keySequences() const
+QList<QKeySequence> Command::keySequences() const
{
- return m_action->shortcuts();
+ return d->m_action->shortcuts();
}
-QKeySequence Action::keySequence() const
+QKeySequence Command::keySequence() const
{
- return m_action->shortcut();
+ return d->m_action->shortcut();
}
-void Action::setDescription(const QString &text)
+void Command::setDescription(const QString &text)
{
- m_defaultText = text;
+ d->m_defaultText = text;
}
-QString Action::description() const
+QString Command::description() const
{
- if (!m_defaultText.isEmpty())
- return m_defaultText;
+ if (!d->m_defaultText.isEmpty())
+ return d->m_defaultText;
if (QAction *act = action()) {
const QString text = Utils::stripAccelerator(act->text());
if (!text.isEmpty())
@@ -344,7 +355,7 @@ QString Action::description() const
return id().toString();
}
-void Action::setCurrentContext(const Context &context)
+void Internal::CommandPrivate::setCurrentContext(const Context &context)
{
m_context = context;
@@ -360,7 +371,7 @@ void Action::setCurrentContext(const Context &context)
updateActiveState();
}
-void Action::updateActiveState()
+void Internal::CommandPrivate::updateActiveState()
{
setActive(m_action->isEnabled() && m_action->isVisible() && !m_action->isSeparator());
}
@@ -377,7 +388,9 @@ static QString msgActionWarning(QAction *newAction, Id id, QAction *oldAction)
return msg;
}
-void Action::addOverrideAction(QAction *action, const Context &context, bool scriptable)
+void Internal::CommandPrivate::addOverrideAction(QAction *action,
+ const Context &context,
+ bool scriptable)
{
// disallow TextHeuristic menu role, because it doesn't work with translations,
// e.g. QTCREATORBUG-13101
@@ -398,7 +411,7 @@ void Action::addOverrideAction(QAction *action, const Context &context, bool scr
setCurrentContext(m_context);
}
-void Action::removeOverrideAction(QAction *action)
+void Internal::CommandPrivate::removeOverrideAction(QAction *action)
{
QList<Id> toRemove;
for (auto it = m_contextActionMap.cbegin(), end = m_contextActionMap.cend(); it != end; ++it) {
@@ -410,125 +423,123 @@ void Action::removeOverrideAction(QAction *action)
setCurrentContext(m_context);
}
-bool Action::isActive() const
+bool Command::isActive() const
{
- return m_active;
+ return d->m_active;
}
-void Action::setActive(bool state)
+void Internal::CommandPrivate::setActive(bool state)
{
if (state != m_active) {
m_active = state;
- emit activeStateChanged();
+ emit m_q->activeStateChanged();
}
}
-bool Action::isEmpty() const
+bool Internal::CommandPrivate::isEmpty() const
{
return m_contextActionMap.isEmpty();
}
-bool Action::isScriptable() const
+bool Command::isScriptable() const
{
- return std::find(m_scriptableMap.cbegin(), m_scriptableMap.cend(), true) !=
- m_scriptableMap.cend();
+ return std::find(d->m_scriptableMap.cbegin(), d->m_scriptableMap.cend(), true)
+ != d->m_scriptableMap.cend();
}
-bool Action::isScriptable(const Context &context) const
+bool Command::isScriptable(const Context &context) const
{
- if (context == m_context && m_scriptableMap.contains(m_action->action()))
- return m_scriptableMap.value(m_action->action());
+ if (context == d->m_context && d->m_scriptableMap.contains(d->m_action->action()))
+ return d->m_scriptableMap.value(d->m_action->action());
for (int i = 0; i < context.size(); ++i) {
- if (QAction *a = m_contextActionMap.value(context.at(i), nullptr)) {
- if (m_scriptableMap.contains(a) && m_scriptableMap.value(a))
+ if (QAction *a = d->m_contextActionMap.value(context.at(i), nullptr)) {
+ if (d->m_scriptableMap.contains(a) && d->m_scriptableMap.value(a))
return true;
}
}
return false;
}
-void Action::setAttribute(CommandAttribute attr)
+void Command::setAttribute(CommandAttribute attr)
{
- m_attributes |= attr;
+ d->m_attributes |= attr;
switch (attr) {
case Command::CA_Hide:
- m_action->setAttribute(Utils::ProxyAction::Hide);
+ d->m_action->setAttribute(Utils::ProxyAction::Hide);
break;
case Command::CA_UpdateText:
- m_action->setAttribute(Utils::ProxyAction::UpdateText);
+ d->m_action->setAttribute(Utils::ProxyAction::UpdateText);
break;
case Command::CA_UpdateIcon:
- m_action->setAttribute(Utils::ProxyAction::UpdateIcon);
+ d->m_action->setAttribute(Utils::ProxyAction::UpdateIcon);
break;
case Command::CA_NonConfigurable:
break;
}
}
-void Action::removeAttribute(CommandAttribute attr)
+void Command::removeAttribute(CommandAttribute attr)
{
- m_attributes &= ~attr;
+ d->m_attributes &= ~attr;
switch (attr) {
case Command::CA_Hide:
- m_action->removeAttribute(Utils::ProxyAction::Hide);
+ d->m_action->removeAttribute(Utils::ProxyAction::Hide);
break;
case Command::CA_UpdateText:
- m_action->removeAttribute(Utils::ProxyAction::UpdateText);
+ d->m_action->removeAttribute(Utils::ProxyAction::UpdateText);
break;
case Command::CA_UpdateIcon:
- m_action->removeAttribute(Utils::ProxyAction::UpdateIcon);
+ d->m_action->removeAttribute(Utils::ProxyAction::UpdateIcon);
break;
case Command::CA_NonConfigurable:
break;
}
}
-bool Action::hasAttribute(Command::CommandAttribute attr) const
+bool Command::hasAttribute(CommandAttribute attr) const
{
- return (m_attributes & attr);
+ return (d->m_attributes & attr);
}
-void Action::setTouchBarText(const QString &text)
+void Command::setTouchBarText(const QString &text)
{
- m_touchBarText = text;
+ d->m_touchBarText = text;
}
-QString Action::touchBarText() const
+QString Command::touchBarText() const
{
- return m_touchBarText;
+ return d->m_touchBarText;
}
-void Action::setTouchBarIcon(const QIcon &icon)
+void Command::setTouchBarIcon(const QIcon &icon)
{
- m_touchBarIcon = icon;
+ d->m_touchBarIcon = icon;
}
-QIcon Action::touchBarIcon() const
+QIcon Command::touchBarIcon() const
{
- return m_touchBarIcon;
+ return d->m_touchBarIcon;
}
-QAction *Action::touchBarAction() const
+QAction *Command::touchBarAction() const
{
- if (!m_touchBarAction) {
- m_touchBarAction = std::make_unique<Utils::ProxyAction>();
- m_touchBarAction->initialize(m_action);
- m_touchBarAction->setIcon(m_touchBarIcon);
- m_touchBarAction->setText(m_touchBarText);
+ if (!d->m_touchBarAction) {
+ d->m_touchBarAction = std::make_unique<Utils::ProxyAction>();
+ d->m_touchBarAction->initialize(d->m_action);
+ d->m_touchBarAction->setIcon(d->m_touchBarIcon);
+ d->m_touchBarAction->setText(d->m_touchBarText);
// the touch bar action should be hidden if the command is not valid for the context
- m_touchBarAction->setAttribute(Utils::ProxyAction::Hide);
- m_touchBarAction->setAction(m_action->action());
- connect(m_action,
+ d->m_touchBarAction->setAttribute(Utils::ProxyAction::Hide);
+ d->m_touchBarAction->setAction(d->m_action->action());
+ connect(d->m_action,
&Utils::ProxyAction::currentActionChanged,
- m_touchBarAction.get(),
+ d->m_touchBarAction.get(),
&Utils::ProxyAction::setAction);
}
- return m_touchBarAction.get();
+ return d->m_touchBarAction.get();
}
-} // namespace Internal
-
/*!
Appends the main keyboard shortcut that is currently assigned to the action
\a a to its tool tip.
diff --git a/src/plugins/coreplugin/actionmanager/command.h b/src/plugins/coreplugin/actionmanager/command.h
index 677a1308185..f2c89469f34 100644
--- a/src/plugins/coreplugin/actionmanager/command.h
+++ b/src/plugins/coreplugin/actionmanager/command.h
@@ -40,7 +40,12 @@ QT_END_NAMESPACE
namespace Core {
+namespace Internal {
+class ActionManagerPrivate;
+class CommandPrivate;
+} // namespace Internal
+class ActionManager;
class Context;
constexpr bool useMacShortcuts = Utils::HostOsInfo::isMacHost();
@@ -57,46 +62,56 @@ public:
};
Q_DECLARE_FLAGS(CommandAttributes, CommandAttribute)
- virtual void setDefaultKeySequence(const QKeySequence &key) = 0;
- virtual void setDefaultKeySequences(const QList<QKeySequence> &keys) = 0;
- virtual QList<QKeySequence> defaultKeySequences() const = 0;
- virtual QList<QKeySequence> keySequences() const = 0;
- virtual QKeySequence keySequence() const = 0;
+ ~Command();
+
+ void setDefaultKeySequence(const QKeySequence &key);
+ void setDefaultKeySequences(const QList<QKeySequence> &keys);
+ QList<QKeySequence> defaultKeySequences() const;
+ QList<QKeySequence> keySequences() const;
+ QKeySequence keySequence() const;
// explicitly set the description (used e.g. in shortcut settings)
// default is to use the action text for actions, or the whatsThis for shortcuts,
// or, as a last fall back if these are empty, the command ID string
// override the default e.g. if the text is context dependent and contains file names etc
- virtual void setDescription(const QString &text) = 0;
- virtual QString description() const = 0;
+ void setDescription(const QString &text);
+ QString description() const;
- virtual Utils::Id id() const = 0;
+ Utils::Id id() const;
- virtual QAction *action() const = 0;
- virtual Context context() const = 0;
+ QAction *action() const;
+ Context context() const;
- virtual void setAttribute(CommandAttribute attr) = 0;
- virtual void removeAttribute(CommandAttribute attr) = 0;
- virtual bool hasAttribute(CommandAttribute attr) const = 0;
+ void setAttribute(CommandAttribute attr);
+ void removeAttribute(CommandAttribute attr);
+ bool hasAttribute(CommandAttribute attr) const;
- virtual bool isActive() const = 0;
+ bool isActive() const;
- virtual void setKeySequences(const QList<QKeySequence> &keys) = 0;
- virtual QString stringWithAppendedShortcut(const QString &str) const = 0;
+ void setKeySequences(const QList<QKeySequence> &keys);
+ QString stringWithAppendedShortcut(const QString &str) const;
void augmentActionWithShortcutToolTip(QAction *action) const;
static QToolButton *toolButtonWithAppendedShortcut(QAction *action, Command *cmd);
- virtual bool isScriptable() const = 0;
- virtual bool isScriptable(const Context &) const = 0;
+ bool isScriptable() const;
+ bool isScriptable(const Context &) const;
- virtual void setTouchBarText(const QString &text) = 0;
- virtual QString touchBarText() const = 0;
- virtual void setTouchBarIcon(const QIcon &icon) = 0;
- virtual QIcon touchBarIcon() const = 0;
- virtual QAction *touchBarAction() const = 0;
+ void setTouchBarText(const QString &text);
+ QString touchBarText() const;
+ void setTouchBarIcon(const QIcon &icon);
+ QIcon touchBarIcon() const;
+ QAction *touchBarAction() const;
signals:
void keySequenceChanged();
void activeStateChanged();
+
+private:
+ friend class ActionManager;
+ friend class Internal::ActionManagerPrivate;
+
+ Command(Utils::Id id);
+
+ Internal::CommandPrivate *d;
};
} // namespace Core
diff --git a/src/plugins/coreplugin/actionmanager/command_p.h b/src/plugins/coreplugin/actionmanager/command_p.h
index 94f72ddfa1e..a0b412c1ee9 100644
--- a/src/plugins/coreplugin/actionmanager/command_p.h
+++ b/src/plugins/coreplugin/actionmanager/command_p.h
@@ -43,56 +43,24 @@
namespace Core {
namespace Internal {
-class Action : public Command
+class CommandPrivate : public QObject
{
Q_OBJECT
public:
- Action(Utils::Id id);
+ CommandPrivate(Command *parent);
- Utils::Id id() const override;
-
- void setDefaultKeySequence(const QKeySequence &key) override;
- void setDefaultKeySequences(const QList<QKeySequence> &key) override;
- QList<QKeySequence> defaultKeySequences() const override;
-
- void setKeySequences(const QList<QKeySequence> &keys) override;
- QList<QKeySequence> keySequences() const override;
- QKeySequence keySequence() const override;
-
- void setDescription(const QString &text) override;
- QString description() const override;
-
- QAction *action() const override;
-
- QString stringWithAppendedShortcut(const QString &str) const override;
-
- Context context() const override;
void setCurrentContext(const Context &context);
- bool isActive() const override;
void addOverrideAction(QAction *action, const Context &context, bool scriptable);
void removeOverrideAction(QAction *action);
bool isEmpty() const;
- bool isScriptable() const override;
- bool isScriptable(const Context &context) const override;
-
- void setAttribute(CommandAttribute attr) override;
- void removeAttribute(CommandAttribute attr) override;
- bool hasAttribute(CommandAttribute attr) const override;
-
- void setTouchBarText(const QString &text) override;
- QString touchBarText() const override;
- void setTouchBarIcon(const QIcon &icon) override;
- QIcon touchBarIcon() const override;
- QAction *touchBarAction() const override;
-
-private:
void updateActiveState();
void setActive(bool state);
+ Command *m_q = nullptr;
Context m_context;
- CommandAttributes m_attributes;
+ Command::CommandAttributes m_attributes;
Utils::Id m_id;
QList<QKeySequence> m_defaultKeys;
QString m_defaultText;
diff --git a/src/plugins/coreplugin/actionmanager/commandsfile.cpp b/src/plugins/coreplugin/actionmanager/commandsfile.cpp
index fff6c6779f6..8d4964999be 100644
--- a/src/plugins/coreplugin/actionmanager/commandsfile.cpp
+++ b/src/plugins/coreplugin/actionmanager/commandsfile.cpp
@@ -24,7 +24,7 @@
****************************************************************************/
#include "commandsfile.h"
-#include "command_p.h"
+#include "command.h"
#include <coreplugin/dialogs/shortcutsettings.h>
#include <coreplugin/icore.h>
@@ -131,7 +131,7 @@ bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
arg(ICore::versionString(),
QDateTime::currentDateTime().toString(Qt::ISODate)));
w.writeStartElement(ctx.mappingElement);
- foreach (const ShortcutItem *item, items) {
+ for (const ShortcutItem *item : qAsConst(items)) {
const Id id = item->m_cmd->id();
if (item->m_keys.isEmpty() || item->m_keys.first().isEmpty()) {
w.writeEmptyElement(ctx.shortCutElement);
diff --git a/src/plugins/coreplugin/basefilewizardfactory.cpp b/src/plugins/coreplugin/basefilewizardfactory.cpp
index 83d9721bce8..7d069b29dce 100644
--- a/src/plugins/coreplugin/basefilewizardfactory.cpp
+++ b/src/plugins/coreplugin/basefilewizardfactory.cpp
@@ -26,14 +26,14 @@
#include "basefilewizardfactory.h"
#include "basefilewizard.h"
+#include "dialogs/promptoverwritedialog.h"
+#include "editormanager/editormanager.h"
#include "icontext.h"
#include "icore.h"
#include "ifilewizardextension.h"
-#include "editormanager/editormanager.h"
-#include "dialogs/promptoverwritedialog.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/filewizardpage.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/wizard.h>
@@ -152,7 +152,7 @@ bool BaseFileWizardFactory::writeFiles(const GeneratedFiles &files, QString *err
{
const GeneratedFile::Attributes noWriteAttributes
= GeneratedFile::CustomGeneratorAttribute|GeneratedFile::KeepExistingFileAttribute;
- foreach (const GeneratedFile &generatedFile, files)
+ for (const GeneratedFile &generatedFile : qAsConst(files))
if (!(generatedFile.attributes() & noWriteAttributes ))
if (!generatedFile.write(errorMessage))
return false;
@@ -186,7 +186,7 @@ bool BaseFileWizardFactory::postGenerateFiles(const QWizard *, const GeneratedFi
bool BaseFileWizardFactory::postGenerateOpenEditors(const GeneratedFiles &l, QString *errorMessage)
{
- foreach (const GeneratedFile &file, l) {
+ for (const GeneratedFile &file : qAsConst(l)) {
if (file.attributes() & GeneratedFile::OpenEditorAttribute) {
if (!EditorManager::openEditor(FilePath::fromString(file.path()), file.editorId())) {
if (errorMessage)
@@ -218,7 +218,7 @@ BaseFileWizardFactory::OverwriteResult BaseFileWizardFactory::promptOverwrite(Ge
static const QString directoryMsg = tr("[folder]");
static const QString symLinkMsg = tr("[symbolic link]");
- foreach (const GeneratedFile &file, *files) {
+ for (const GeneratedFile &file : qAsConst(*files)) {
const QString path = file.path();
if (QFileInfo::exists(path))
existingFiles.append(path);
@@ -230,7 +230,7 @@ BaseFileWizardFactory::OverwriteResult BaseFileWizardFactory::promptOverwrite(Ge
// Format a file list message as ( "<file1> [readonly], <file2> [folder]").
const QString commonExistingPath = Utils::commonPath(existingFiles);
QString fileNamesMsgPart;
- foreach (const QString &fileName, existingFiles) {
+ for (const QString &fileName : qAsConst(existingFiles)) {
const QFileInfo fi(fileName);
if (fi.exists()) {
if (!fileNamesMsgPart.isEmpty())
@@ -264,7 +264,7 @@ BaseFileWizardFactory::OverwriteResult BaseFileWizardFactory::promptOverwrite(Ge
PromptOverwriteDialog overwriteDialog;
// Scripts cannot handle overwrite
overwriteDialog.setFiles(existingFiles);
- foreach (const GeneratedFile &file, *files)
+ for (const GeneratedFile &file : qAsConst(*files))
if (file.attributes() & GeneratedFile::CustomGeneratorAttribute)
overwriteDialog.setFileEnabled(file.path(), false);
if (overwriteDialog.exec() != QDialog::Accepted)
@@ -273,7 +273,7 @@ BaseFileWizardFactory::OverwriteResult BaseFileWizardFactory::promptOverwrite(Ge
if (existingFilesToKeep.size() == files->size()) // All exist & all unchecked->Cancel.
return OverwriteCanceled;
// Set 'keep' attribute in files
- foreach (const QString &keepFile, existingFilesToKeep) {
+ for (const QString &keepFile : qAsConst(existingFilesToKeep)) {
const int i = indexOfFile(*files, keepFile);
QTC_ASSERT(i != -1, return OverwriteCanceled);
GeneratedFile &file = (*files)[i];
diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h
index 96234c16c33..77ada82f061 100644
--- a/src/plugins/coreplugin/coreconstants.h
+++ b/src/plugins/coreplugin/coreconstants.h
@@ -188,7 +188,7 @@ const char G_VIEW_PANES[] = "QtCreator.Group.View.Panes";
// Tools menu groups
const char G_TOOLS_DEBUG[] = "QtCreator.Group.Tools.Debug";
-const char G_TOOLS_OPTIONS[] = "QtCreator.Group.Tools.Options";
+const char G_EDIT_PREFERENCES[] = "QtCreator.Group.Edit.Preferences";
// Window menu groups
const char G_WINDOW_SIZE[] = "QtCreator.Group.Window.Size";
diff --git a/src/plugins/coreplugin/corejsextensions.cpp b/src/plugins/coreplugin/corejsextensions.cpp
index 6b6a380108f..a88de1020c4 100644
--- a/src/plugins/coreplugin/corejsextensions.cpp
+++ b/src/plugins/coreplugin/corejsextensions.cpp
@@ -28,12 +28,14 @@
#include <app/app_version.h>
#include <utils/fileutils.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <QDir>
+#include <QDirIterator>
#include <QTemporaryFile>
#include <QVariant>
+#include <QVersionNumber>
namespace Core {
namespace Internal {
@@ -165,5 +167,34 @@ QString UtilsJsExtension::asciify(const QString &input) const
return result;
}
+QString UtilsJsExtension::qtQuickVersion(const QString &filePath) const
+{
+ QDirIterator dirIt(Utils::FilePath::fromString(filePath).parentDir().path(), {"*.qml"},
+ QDir::Files, QDirIterator::Subdirectories);
+ while (dirIt.hasNext()) {
+ Utils::FileReader reader;
+ if (!reader.fetch(Utils::FilePath::fromString(dirIt.next())))
+ continue;
+ const QString data = QString::fromUtf8(reader.data());
+ static const QString importString("import QtQuick");
+ const int importIndex = data.indexOf(importString);
+ if (importIndex == -1)
+ continue;
+ const int versionIndex = importIndex + importString.length();
+ const int newLineIndex = data.indexOf('\n', versionIndex);
+ if (newLineIndex == -1)
+ continue;
+ const QString versionString = data.mid(versionIndex,
+ newLineIndex - versionIndex).simplified();
+ if (versionString.isEmpty())
+ return {};
+ const auto version = QVersionNumber::fromString(versionString);
+ if (version.isNull())
+ return {};
+ return version.toString();
+ }
+ return QLatin1String("2.15");
+}
+
} // namespace Internal
} // namespace Core
diff --git a/src/plugins/coreplugin/corejsextensions.h b/src/plugins/coreplugin/corejsextensions.h
index bbdc8762512..8a668cbd161 100644
--- a/src/plugins/coreplugin/corejsextensions.h
+++ b/src/plugins/coreplugin/corejsextensions.h
@@ -76,6 +76,9 @@ public:
// Generate a ascii-only string:
Q_INVOKABLE QString asciify(const QString &input) const;
+
+ // Heuristic to find out which QtQuick import version to use for the given file.
+ Q_INVOKABLE QString qtQuickVersion(const QString &filePath) const;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp
index 483c8c3c2b9..d0c9f2265f6 100644
--- a/src/plugins/coreplugin/coreplugin.cpp
+++ b/src/plugins/coreplugin/coreplugin.cpp
@@ -53,7 +53,7 @@
#include <utils/commandline.h>
#include <utils/infobar.h>
#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/pathchooser.h>
#include <utils/savefile.h>
#include <utils/stringutils.h>
@@ -95,6 +95,7 @@ CorePlugin::CorePlugin()
qRegisterMetaType<Core::Search::TextPosition>();
qRegisterMetaType<Utils::CommandLine>();
qRegisterMetaType<Utils::FilePath>();
+ qRegisterMetaType<Utils::Environment>();
m_instance = this;
setupSystemEnvironment();
}
@@ -410,7 +411,7 @@ void CorePlugin::warnAboutCrashReporing()
Core::Constants::IDE_DISPLAY_NAME + tr(" > Preferences > Environment > System"));
} else {
warnStr = warnStr.arg(QLatin1String(Core::Constants::IDE_DISPLAY_NAME),
- tr("Tools > Options > Environment > System"));
+ tr("Edit > Preferences > Environment > System"));
}
Utils::InfoBarEntry info(kWarnCrashReportingSetting, warnStr,
diff --git a/src/plugins/coreplugin/designmode.cpp b/src/plugins/coreplugin/designmode.cpp
index de32db86337..08675fb2794 100644
--- a/src/plugins/coreplugin/designmode.cpp
+++ b/src/plugins/coreplugin/designmode.cpp
@@ -140,7 +140,7 @@ void DesignMode::registerDesignWidget(QWidget *widget,
void DesignMode::unregisterDesignWidget(QWidget *widget)
{
d->m_stackWidget->removeWidget(widget);
- foreach (DesignEditorInfo *info, d->m_editors) {
+ for (DesignEditorInfo *info : qAsConst(d->m_editors)) {
if (info->widget == widget) {
d->m_editors.removeAll(info);
delete info;
@@ -160,8 +160,8 @@ void DesignMode::currentEditorChanged(IEditor *editor)
if (editor) {
const QString mimeType = editor->document()->mimeType();
if (!mimeType.isEmpty()) {
- foreach (DesignEditorInfo *editorInfo, d->m_editors) {
- foreach (const QString &mime, editorInfo->mimeTypes) {
+ for (const DesignEditorInfo *editorInfo : qAsConst(d->m_editors)) {
+ for (const QString &mime : editorInfo->mimeTypes) {
if (mime == mimeType) {
d->m_stackWidget->setCurrentIndex(editorInfo->widgetIndex);
setActiveContext(editorInfo->context);
@@ -169,10 +169,10 @@ void DesignMode::currentEditorChanged(IEditor *editor)
setEnabled(true);
break;
}
- } // foreach mime
+ }
if (mimeEditorAvailable)
break;
- } // foreach editorInfo
+ }
}
}
if (d->m_currentEditor)
diff --git a/src/plugins/coreplugin/dialogs/codecselector.cpp b/src/plugins/coreplugin/dialogs/codecselector.cpp
index 9b5786c1b42..864d56d2097 100644
--- a/src/plugins/coreplugin/dialogs/codecselector.cpp
+++ b/src/plugins/coreplugin/dialogs/codecselector.cpp
@@ -77,15 +77,15 @@ CodecSelector::CodecSelector(QWidget *parent, Core::BaseTextDocument *doc)
QList<int> mibs = QTextCodec::availableMibs();
Utils::sort(mibs);
QList<int> sortedMibs;
- foreach (int mib, mibs)
+ for (const int mib : qAsConst(mibs))
if (mib >= 0)
sortedMibs += mib;
- foreach (int mib, mibs)
+ for (const int mib : qAsConst(mibs))
if (mib < 0)
sortedMibs += mib;
int currentIndex = -1;
- foreach (int mib, sortedMibs) {
+ for (const int mib : qAsConst(sortedMibs)) {
QTextCodec *c = QTextCodec::codecForMib(mib);
if (!doc->supportsCodec(c))
continue;
@@ -101,7 +101,8 @@ CodecSelector::CodecSelector(QWidget *parent, Core::BaseTextDocument *doc)
continue;
}
QString names = QString::fromLatin1(c->name());
- foreach (const QByteArray &alias, c->aliases())
+ const QList<QByteArray> aliases = c->aliases();
+ for (const QByteArray &alias : aliases)
names += QLatin1String(" / ") + QString::fromLatin1(alias);
if (doc->codec() == c)
currentIndex = encodings.count();
diff --git a/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp b/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp
index d17d02f51b6..21b09d08ce4 100644
--- a/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp
+++ b/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp
@@ -673,7 +673,8 @@ static QString findUnusedId(const QString &proposal, const QMap<QString, QList<E
++number;
found = false;
for (auto it = tools.cbegin(), end = tools.cend(); it != end; ++it) {
- foreach (ExternalTool *tool, it.value()) {
+ const QList<ExternalTool *> tools = it.value();
+ for (const ExternalTool *tool : tools) {
if (tool->id() == result) {
found = true;
break;
@@ -695,7 +696,8 @@ void ExternalToolConfig::apply()
QMap<QString, QList<ExternalTool *> > resultMap;
for (auto it = newToolsMap.cbegin(), end = newToolsMap.cend(); it != end; ++it) {
QList<ExternalTool *> items;
- foreach (ExternalTool *tool, it.value()) {
+ const QList<ExternalTool *> tools = it.value();
+ for (ExternalTool *tool : tools) {
ExternalTool *toolToAdd = nullptr;
if (ExternalTool *originalTool = originalTools.take(tool->id())) {
// check if it has different category and is custom tool
@@ -752,7 +754,7 @@ void ExternalToolConfig::apply()
resultMap.insert(it.key(), items);
}
// Remove tools that have been deleted from the settings (and are no preset)
- foreach (ExternalTool *tool, originalTools) {
+ for (const ExternalTool *tool : qAsConst(originalTools)) {
QTC_ASSERT(!tool->preset(), continue);
// TODO error handling
tool->fileName().removeFile();
diff --git a/src/plugins/coreplugin/dialogs/externaltoolconfig.ui b/src/plugins/coreplugin/dialogs/externaltoolconfig.ui
index a49ae83b892..57fe84c348e 100644
--- a/src/plugins/coreplugin/dialogs/externaltoolconfig.ui
+++ b/src/plugins/coreplugin/dialogs/externaltoolconfig.ui
@@ -192,7 +192,7 @@
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;
&lt;p&gt;What to do with the executable's standard output.
-&lt;ul&gt;&lt;li&gt;Ignore: Do nothing with it.&lt;/li&gt;&lt;li&gt;Show in pane: Show it in the general output pane.&lt;/li&gt;&lt;li&gt;Replace selection: Replace the current selection in the current document with it.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
+&lt;ul&gt;&lt;li&gt;Ignore: Do nothing with it.&lt;/li&gt;&lt;li&gt;Show in General Messages.&lt;/li&gt;&lt;li&gt;Replace selection: Replace the current selection in the current document with it.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</string>
</property>
<property name="text">
@@ -209,7 +209,7 @@
</item>
<item>
<property name="text">
- <string>Show in Pane</string>
+ <string>Show in General Messages</string>
</property>
</item>
<item>
@@ -225,7 +225,7 @@
<string>&lt;html&gt;&lt;head&gt;&lt;body&gt;
&lt;p &gt;What to do with the executable's standard error output.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Ignore: Do nothing with it.&lt;/li&gt;
-&lt;li&gt;Show in pane: Show it in the general output pane.&lt;/li&gt;
+&lt;li&gt;Show in General Messages.&lt;/li&gt;
&lt;li&gt;Replace selection: Replace the current selection in the current document with it.&lt;/li&gt;
&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@@ -243,7 +243,7 @@
</item>
<item>
<property name="text">
- <string>Show in Pane</string>
+ <string>Show in General Messages</string>
</property>
</item>
<item>
diff --git a/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp b/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp
index 8901ee109e0..5236511adc0 100644
--- a/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp
@@ -29,7 +29,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditorfactory.h>
#include <utils/fileutils.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QDateTime>
#include <QDebug>
@@ -152,7 +152,7 @@ void FilePropertiesDialog::refresh()
m_ui->name->setText(fileInfo.fileName());
m_ui->path->setText(QDir::toNativeSeparators(fileInfo.canonicalPath()));
- const Utils::MimeType mimeType = Utils::mimeTypeForFile(fileInfo);
+ const Utils::MimeType mimeType = Utils::mimeTypeForFile(m_filePath);
m_ui->mimeType->setText(mimeType.name());
const EditorTypeList factories = IEditorFactory::preferredEditorTypes(m_filePath);
diff --git a/src/plugins/coreplugin/dialogs/ioptionspage.cpp b/src/plugins/coreplugin/dialogs/ioptionspage.cpp
index 22096a22603..af4d8529b94 100644
--- a/src/plugins/coreplugin/dialogs/ioptionspage.cpp
+++ b/src/plugins/coreplugin/dialogs/ioptionspage.cpp
@@ -270,18 +270,18 @@ bool IOptionsPage::matches(const QRegularExpression &regexp) const
if (!widget)
return false;
// find common subwidgets
- foreach (const QLabel *label, widget->findChildren<QLabel *>())
+ for (const QLabel *label : widget->findChildren<QLabel *>())
m_keywords << Utils::stripAccelerator(label->text());
- foreach (const QCheckBox *checkbox, widget->findChildren<QCheckBox *>())
+ for (const QCheckBox *checkbox : widget->findChildren<QCheckBox *>())
m_keywords << Utils::stripAccelerator(checkbox->text());
- foreach (const QPushButton *pushButton, widget->findChildren<QPushButton *>())
+ for (const QPushButton *pushButton : widget->findChildren<QPushButton *>())
m_keywords << Utils::stripAccelerator(pushButton->text());
- foreach (const QGroupBox *groupBox, widget->findChildren<QGroupBox *>())
+ for (const QGroupBox *groupBox : widget->findChildren<QGroupBox *>())
m_keywords << Utils::stripAccelerator(groupBox->title());
m_keywordsInitialized = true;
}
- foreach (const QString &keyword, m_keywords)
+ for (const QString &keyword : qAsConst(m_keywords))
if (keyword.contains(regexp))
return true;
return false;
diff --git a/src/plugins/coreplugin/dialogs/newdialogwidget.cpp b/src/plugins/coreplugin/dialogs/newdialogwidget.cpp
index a6feb9b11ce..3b005307b0c 100644
--- a/src/plugins/coreplugin/dialogs/newdialogwidget.cpp
+++ b/src/plugins/coreplugin/dialogs/newdialogwidget.cpp
@@ -401,7 +401,8 @@ void NewDialogWidget::currentItemChanged(const QModelIndex &index)
if (const IWizardFactory *wizard = factoryOfItem(cat)) {
QString desciption = wizard->description();
QStringList displayNamesForSupportedPlatforms;
- foreach (Id platform, wizard->supportedPlatforms())
+ const QSet<Id> platforms = wizard->supportedPlatforms();
+ for (const Id platform : platforms)
displayNamesForSupportedPlatforms << IWizardFactory::displayNameForPlatform(platform);
Utils::sort(displayNamesForSupportedPlatforms);
if (!Qt::mightBeRichText(desciption))
diff --git a/src/plugins/coreplugin/dialogs/openwithdialog.cpp b/src/plugins/coreplugin/dialogs/openwithdialog.cpp
index 8ea340a65c6..746160645de 100644
--- a/src/plugins/coreplugin/dialogs/openwithdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/openwithdialog.cpp
@@ -58,7 +58,7 @@ void OpenWithDialog::setOkButtonEnabled(bool v)
void OpenWithDialog::setEditors(const QStringList &editors)
{
- foreach (const QString &e, editors)
+ for (const QString &e : editors)
editorListWidget->addItem(e);
}
diff --git a/src/plugins/coreplugin/dialogs/promptoverwritedialog.cpp b/src/plugins/coreplugin/dialogs/promptoverwritedialog.cpp
index ef696df28b6..ae2ba7d2c8c 100644
--- a/src/plugins/coreplugin/dialogs/promptoverwritedialog.cpp
+++ b/src/plugins/coreplugin/dialogs/promptoverwritedialog.cpp
@@ -82,7 +82,7 @@ void PromptOverwriteDialog::setFiles(const QStringList &l)
{
// Format checkable list excluding common path
const QString nativeCommonPath = QDir::toNativeSeparators(Utils::commonPath(l));
- foreach (const QString &fileName, l) {
+ for (const QString &fileName : l) {
const QString nativeFileName = QDir::toNativeSeparators(fileName);
const int length = nativeFileName.size() - nativeCommonPath.size() - 1;
QStandardItem *item = new QStandardItem(nativeFileName.right(length));
diff --git a/src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp b/src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp
index 8f59478003e..687288ad449 100644
--- a/src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp
@@ -124,7 +124,7 @@ ReadOnlyFilesDialogPrivate::ReadOnlyFilesDialogPrivate(ReadOnlyFilesDialog *pare
ReadOnlyFilesDialogPrivate::~ReadOnlyFilesDialogPrivate()
{
- foreach (const ButtonGroupForFile &groupForFile, buttonGroups)
+ for (const ButtonGroupForFile &groupForFile : qAsConst(buttonGroups))
delete groupForFile.group;
}
@@ -371,8 +371,9 @@ void ReadOnlyFilesDialogPrivate::setAll(int index)
type = SaveAs;
// Check for every file if the selected operation is available and change it to the operation.
- foreach (ReadOnlyFilesDialogPrivate::ButtonGroupForFile groupForFile, buttonGroups) {
- auto radioButton = qobject_cast<QRadioButton*> (groupForFile.group->button(type));
+ for (const ReadOnlyFilesDialogPrivate::ButtonGroupForFile &groupForFile :
+ qAsConst(buttonGroups)) {
+ auto radioButton = qobject_cast<QRadioButton *>(groupForFile.group->button(type));
if (radioButton)
radioButton->setChecked(true);
}
@@ -386,7 +387,8 @@ void ReadOnlyFilesDialogPrivate::setAll(int index)
void ReadOnlyFilesDialogPrivate::updateSelectAll()
{
int selectedOperation = -1;
- foreach (ReadOnlyFilesDialogPrivate::ButtonGroupForFile groupForFile, buttonGroups) {
+ for (const ReadOnlyFilesDialogPrivate::ButtonGroupForFile &groupForFile :
+ qAsConst(buttonGroups)) {
if (selectedOperation == -1) {
selectedOperation = groupForFile.group->checkedId();
} else if (selectedOperation != groupForFile.group->checkedId()) {
diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
index 302a02f871e..d110beac0a4 100644
--- a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
@@ -45,7 +45,7 @@ using namespace Core;
using namespace Core::Internal;
SaveItemsDialog::SaveItemsDialog(QWidget *parent,
- QList<IDocument *> items)
+ const QList<IDocument *> &items)
: QDialog(parent)
{
m_ui.setupUi(this);
@@ -65,7 +65,7 @@ SaveItemsDialog::SaveItemsDialog(QWidget *parent,
m_ui.saveBeforeBuildCheckBox->setVisible(false);
- foreach (IDocument *document, items) {
+ for (IDocument *document : items) {
QString visibleName;
QString directory;
Utils::FilePath filePath = document->filePath();
@@ -135,7 +135,7 @@ void SaveItemsDialog::adjustButtonWidths()
possibleTexts << tr("Save Selected");
int maxTextWidth = 0;
QPushButton *saveButton = m_ui.buttonBox->button(QDialogButtonBox::Save);
- foreach (const QString &text, possibleTexts) {
+ for (const QString &text : qAsConst(possibleTexts)) {
saveButton->setText(text);
int hint = saveButton->sizeHint().width();
if (hint > maxTextWidth)
@@ -154,7 +154,8 @@ void SaveItemsDialog::adjustButtonWidths()
void SaveItemsDialog::collectItemsToSave()
{
m_itemsToSave.clear();
- foreach (QTreeWidgetItem *item, m_ui.treeWidget->selectedItems()) {
+ const QList<QTreeWidgetItem *> items = m_ui.treeWidget->selectedItems();
+ for (const QTreeWidgetItem *item : items) {
m_itemsToSave.append(item->data(0, Qt::UserRole).value<IDocument*>());
}
accept();
@@ -163,7 +164,8 @@ void SaveItemsDialog::collectItemsToSave()
void SaveItemsDialog::collectFilesToDiff()
{
m_filesToDiff.clear();
- foreach (QTreeWidgetItem *item, m_ui.treeWidget->selectedItems()) {
+ const QList<QTreeWidgetItem *> items = m_ui.treeWidget->selectedItems();
+ for (const QTreeWidgetItem *item : items) {
if (auto doc = item->data(0, Qt::UserRole).value<IDocument*>())
m_filesToDiff.append(doc->filePath().toString());
}
diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.h b/src/plugins/coreplugin/dialogs/saveitemsdialog.h
index f62af247689..1eea8666de5 100644
--- a/src/plugins/coreplugin/dialogs/saveitemsdialog.h
+++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.h
@@ -41,7 +41,7 @@ class SaveItemsDialog : public QDialog
Q_OBJECT
public:
- SaveItemsDialog(QWidget *parent, QList<IDocument *> items);
+ SaveItemsDialog(QWidget *parent, const QList<IDocument *> &items);
void setMessage(const QString &msg);
void setAlwaysSaveMessage(const QString &msg);
diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
index 3901b995e09..d9a503a1a5f 100644
--- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
@@ -170,7 +170,7 @@ void CategoryModel::setPages(const QList<IOptionsPage*> &pages,
m_pageIds.clear();
// Put the pages in categories
- foreach (IOptionsPage *page, pages) {
+ for (IOptionsPage *page : pages) {
QTC_ASSERT(!m_pageIds.contains(page->id()),
qWarning("duplicate options page id '%s'", qPrintable(page->id().toString())));
m_pageIds.insert(page->id());
@@ -190,7 +190,7 @@ void CategoryModel::setPages(const QList<IOptionsPage*> &pages,
category->pages.append(page);
}
- foreach (IOptionsPageProvider *provider, providers) {
+ for (IOptionsPageProvider *provider : providers) {
const Id categoryId = provider->category();
Category *category = findCategoryById(categoryId);
if (!category) {
@@ -217,11 +217,11 @@ void CategoryModel::ensurePages(Category *category)
{
if (!category->providerPagesCreated) {
QList<IOptionsPage *> createdPages;
- foreach (const IOptionsPageProvider *provider, category->providers)
+ for (const IOptionsPageProvider *provider : qAsConst(category->providers))
createdPages += provider->pages();
// check for duplicate ids
- foreach (IOptionsPage *page, createdPages) {
+ for (const IOptionsPage *page : qAsConst(createdPages)) {
QTC_ASSERT(!m_pageIds.contains(page->id()),
qWarning("duplicate options page id '%s'", qPrintable(page->id().toString())));
}
@@ -451,10 +451,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
m_filterLineEdit->setFiltering(true);
createGui();
- if (Utils::HostOsInfo::isMacHost())
- setWindowTitle(QCoreApplication::translate("Core::Internal::SettingsDialog", "Preferences"));
- else
- setWindowTitle(QCoreApplication::translate("Core::Internal::SettingsDialog", "Options"));
+ setWindowTitle(QCoreApplication::translate("Core::Internal::SettingsDialog", "Preferences"));
m_model.setPages(m_pages, IOptionsPageProvider::allOptionsPagesProviders());
@@ -702,9 +699,9 @@ void SettingsDialog::accept()
m_finished = true;
disconnectTabWidgets();
m_applied = true;
- foreach (IOptionsPage *page, m_visitedPages)
+ for (IOptionsPage *page : qAsConst(m_visitedPages))
page->apply();
- foreach (IOptionsPage *page, m_pages)
+ for (IOptionsPage *page : qAsConst(m_pages))
page->finish();
done(QDialog::Accepted);
}
@@ -715,14 +712,14 @@ void SettingsDialog::reject()
return;
m_finished = true;
disconnectTabWidgets();
- foreach (IOptionsPage *page, m_pages)
+ for (IOptionsPage *page : qAsConst(m_pages))
page->finish();
done(QDialog::Rejected);
}
void SettingsDialog::apply()
{
- foreach (IOptionsPage *page, m_visitedPages)
+ for (IOptionsPage *page : qAsConst(m_visitedPages))
page->apply();
m_applied = true;
}
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
index 6d6ab01060a..37f860926c4 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
+++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
@@ -29,7 +29,6 @@
#include <coreplugin/icore.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
-#include <coreplugin/actionmanager/command_p.h>
#include <coreplugin/actionmanager/commandsfile.h>
#include <utils/algorithm.h>
@@ -38,15 +37,16 @@
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
-#include <QKeyEvent>
+#include <QAction>
+#include <QApplication>
+#include <QDebug>
#include <QFileDialog>
#include <QGroupBox>
#include <QHBoxLayout>
+#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QTreeWidgetItem>
-#include <QApplication>
-#include <QDebug>
using namespace Utils;
@@ -332,7 +332,7 @@ QWidget *ShortcutSettings::widget()
void ShortcutSettingsWidget::apply()
{
- foreach (ShortcutItem *item, m_scitems)
+ for (const ShortcutItem *item : qAsConst(m_scitems))
item->m_cmd->setKeySequences(item->m_keys);
}
@@ -520,7 +520,7 @@ void ShortcutSettingsWidget::importAction()
void ShortcutSettingsWidget::defaultAction()
{
- foreach (ShortcutItem *item, m_scitems) {
+ for (ShortcutItem *item : qAsConst(m_scitems)) {
item->m_keys = item->m_cmd->defaultKeySequences();
item->m_item->setText(2, keySequencesToNativeString(item->m_keys));
setModified(item->m_item, false);
@@ -557,7 +557,8 @@ void ShortcutSettingsWidget::initialize()
clear();
QMap<QString, QTreeWidgetItem *> sections;
- foreach (Command *c, ActionManager::commands()) {
+ const QList<Command *> commands = ActionManager::commands();
+ for (Command *c : commands) {
if (c->hasAttribute(Command::CA_NonConfigurable))
continue;
if (c->action() && c->action()->isSeparator())
diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp
index 43ddad0ceef..789374133cf 100644
--- a/src/plugins/coreplugin/documentmanager.cpp
+++ b/src/plugins/coreplugin/documentmanager.cpp
@@ -50,7 +50,7 @@
#include <utils/fileutils.h>
#include <utils/globalfilechangeblocker.h>
#include <utils/hostosinfo.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/optional.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
@@ -370,7 +370,7 @@ void DocumentManager::addDocuments(const QList<IDocument *> &documents, bool add
if (!addWatcher) {
// We keep those in a separate list
- foreach (IDocument *document, documents) {
+ for (IDocument *document : documents) {
if (document && !d->m_documentsWithoutWatch.contains(document)) {
connect(document, &QObject::destroyed,
m_instance, &DocumentManager::documentDestroyed);
@@ -406,7 +406,8 @@ static void removeFileInfo(IDocument *document)
QTC_ASSERT(isMainThread(), return);
if (!d->m_documentsWithWatch.contains(document))
return;
- foreach (const FilePath &filePath, d->m_documentsWithWatch.value(document)) {
+ const FilePaths filePaths = d->m_documentsWithWatch.value(document);
+ for (const FilePath &filePath : filePaths) {
if (!d->m_states.contains(filePath))
continue;
qCDebug(log) << "removing document (" << filePath << ")";
@@ -491,7 +492,7 @@ void DocumentManager::renamedFile(const Utils::FilePath &from, const Utils::File
}
// rename the IDocuments
- foreach (IDocument *document, documentsToRename) {
+ for (IDocument *document : qAsConst(documentsToRename)) {
d->m_blockedIDocument = document;
removeFileInfo(document);
document->setFilePath(to);
@@ -599,7 +600,7 @@ QList<IDocument *> DocumentManager::modifiedDocuments()
modified << document;
}
- foreach (IDocument *document, d->m_documentsWithoutWatch) {
+ for (IDocument *document : qAsConst(d->m_documentsWithoutWatch)) {
if (document->isModified())
modified << document;
}
@@ -665,7 +666,7 @@ static bool saveModifiedFilesHelper(const QList<IDocument *> &documents,
QHash<IDocument *, QString> modifiedDocumentsMap;
QList<IDocument *> modifiedDocuments;
- foreach (IDocument *document, documents) {
+ for (IDocument *document : documents) {
if (document && document->isModified() && !document->isTemporary()) {
QString name = document->filePath().toString();
if (name.isEmpty())
@@ -709,7 +710,7 @@ static bool saveModifiedFilesHelper(const QList<IDocument *> &documents,
}
// Check for files without write permissions.
QList<IDocument *> roDocuments;
- foreach (IDocument *document, documentsToSave) {
+ for (IDocument *document : qAsConst(documentsToSave)) {
if (document->isFileReadOnly())
roDocuments << document;
}
@@ -726,7 +727,7 @@ static bool saveModifiedFilesHelper(const QList<IDocument *> &documents,
return false;
}
}
- foreach (IDocument *document, documentsToSave) {
+ for (IDocument *document : qAsConst(documentsToSave)) {
if (!EditorManagerPrivate::saveDocument(document)) {
if (cancelled)
*cancelled = true;
@@ -781,6 +782,17 @@ QString DocumentManager::fileDialogFilter(QString *selectedFilter)
return allDocumentFactoryFiltersString(selectedFilter);
}
+#ifdef Q_OS_WIN
+static struct {const char *source; const char *comment; } ALL_FILES_FILTER = QT_TRANSLATE_NOOP3("Core", "All Files (*.*)", "On Windows");
+#else
+static struct {const char *source; const char *comment; } ALL_FILES_FILTER = QT_TRANSLATE_NOOP3("Core", "All Files (*)", "On Linux/macOS");
+#endif
+
+QString DocumentManager::allFilesFilterString()
+{
+ return QCoreApplication::translate("Core", ALL_FILES_FILTER.source, ALL_FILES_FILTER.comment);
+}
+
QString DocumentManager::allDocumentFactoryFiltersString(QString *allFilesFilter = nullptr)
{
QSet<QString> uniqueFilters;
@@ -803,7 +815,7 @@ QString DocumentManager::allDocumentFactoryFiltersString(QString *allFilesFilter
QStringList filters = Utils::toList(uniqueFilters);
filters.sort();
- const QString allFiles = Utils::allFilesFilterString();
+ const QString allFiles = allFilesFilterString();
if (allFilesFilter)
*allFilesFilter = allFiles;
filters.prepend(allFiles);
@@ -818,14 +830,13 @@ FilePath DocumentManager::getSaveFileName(const QString &title, const FilePath &
bool repeat;
do {
repeat = false;
- filePath = FileUtils::getSaveFilePath(nullptr, title, path, filter, selectedFilter,
- QFileDialog::DontConfirmOverwrite);
+ filePath = FileUtils::getSaveFilePath(nullptr, title, path, filter, selectedFilter);
if (!filePath.isEmpty()) {
// If the selected filter is All Files (*) we leave the name exactly as the user
// specified. Otherwise the suffix must be one available in the selected filter. If
// the name already ends with such suffix nothing needs to be done. But if not, the
// first one from the filter is appended.
- if (selectedFilter && *selectedFilter != Utils::allFilesFilterString()) {
+ if (selectedFilter && *selectedFilter != allFilesFilterString()) {
// Mime database creates filter strings like this: Anything here (*.foo *.bar)
const QRegularExpression regExp(QLatin1String(".*\\s+\\((.*)\\)$"));
QRegularExpressionMatchIterator matchIt = regExp.globalMatch(*selectedFilter);
@@ -840,18 +851,20 @@ FilePath DocumentManager::getSaveFileName(const QString &title, const FilePath &
suffixOk = true;
break;
}
- if (!suffixOk && !suffixes.isEmpty())
+ if (!suffixOk && !suffixes.isEmpty()) {
filePath = filePath.stringAppended(suffixes.at(0));
+ if (filePath.exists()) {
+ if (QMessageBox::warning(ICore::dialogParent(), tr("Overwrite?"),
+ tr("An item named \"%1\" already exists at this location. "
+ "Do you want to overwrite it?").arg(filePath.toUserOutput()),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
+ repeat = true;
+ }
+ }
+ }
}
}
- if (filePath.exists()) {
- if (QMessageBox::warning(ICore::dialogParent(), tr("Overwrite?"),
- tr("An item named \"%1\" already exists at this location. "
- "Do you want to overwrite it?").arg(filePath.toUserOutput()),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
- repeat = true;
- }
- }
+
}
} while (repeat);
if (!filePath.isEmpty())
@@ -1103,7 +1116,7 @@ void DocumentManager::checkForReload()
QMap<FilePath, FileStateItem> currentStates;
QMap<FilePath, IDocument::ChangeType> changeTypes;
QSet<IDocument *> changedIDocuments;
- foreach (const FilePath &filePath, d->m_changedFiles) {
+ for (const FilePath &filePath : qAsConst(d->m_changedFiles)) {
const FilePath fileKey = filePathKey(filePath, KeepLinks);
qCDebug(log) << "handling file change for" << filePath << "(" << fileKey << ")";
IDocument::ChangeType type = IDocument::TypeContents;
@@ -1119,7 +1132,8 @@ void DocumentManager::checkForReload()
}
currentStates.insert(fileKey, state);
changeTypes.insert(fileKey, type);
- foreach (IDocument *document, d->m_states.value(fileKey).lastUpdatedState.keys())
+ QList<IDocument *> documents = d->m_states.value(fileKey).lastUpdatedState.keys();
+ for (IDocument *document : documents)
changedIDocuments.insert(document);
}
@@ -1133,7 +1147,7 @@ void DocumentManager::checkForReload()
// if the resolved names are different when unexpectFileChange is called
// we would end up with never-unexpected file names
QSet<FilePath> expectedFileKeys;
- foreach (const FilePath &filePath, d->m_expectedFileNames) {
+ for (const FilePath &filePath : qAsConst(d->m_expectedFileNames)) {
const FilePath cleanAbsFilePath = filePathKey(filePath, KeepLinks);
expectedFileKeys.insert(filePathKey(filePath, KeepLinks));
const FilePath resolvedCleanAbsFilePath = cleanAbsFilePath.canonicalPath();
@@ -1144,14 +1158,15 @@ void DocumentManager::checkForReload()
// handle the IDocuments
QStringList errorStrings;
QStringList filesToDiff;
- foreach (IDocument *document, changedIDocuments) {
+ for (IDocument *document : qAsConst(changedIDocuments)) {
IDocument::ChangeTrigger trigger = IDocument::TriggerInternal;
optional<IDocument::ChangeType> type;
bool changed = false;
// find out the type & behavior from the two possible files
// behavior is internal if all changes are expected (and none removed)
// type is "max" of both types (remove > contents > permissions)
- foreach (const FilePath &fileKey, d->m_documentsWithWatch.value(document)) {
+ const FilePaths files = d->m_documentsWithWatch.value(document);
+ for (const FilePath &fileKey : files) {
// was the file reported?
if (!currentStates.contains(fileKey))
continue;
@@ -1368,7 +1383,7 @@ void DocumentManager::saveSettings()
{
QVariantList recentFiles;
QStringList recentEditorIds;
- foreach (const RecentFile &file, d->m_recentFiles) {
+ for (const RecentFile &file : qAsConst(d->m_recentFiles)) {
recentFiles.append(file.first.toVariant());
recentEditorIds.append(file.second.toString());
}
diff --git a/src/plugins/coreplugin/documentmanager.h b/src/plugins/coreplugin/documentmanager.h
index 46667cf8ded..236a43037fc 100644
--- a/src/plugins/coreplugin/documentmanager.h
+++ b/src/plugins/coreplugin/documentmanager.h
@@ -27,7 +27,7 @@
#include <coreplugin/core_global.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <utils/id.h>
#include <QObject>
@@ -145,6 +145,7 @@ public:
static void setFileDialogFilter(const QString &filter);
static QString fileDialogFilter(QString *selectedFilter = nullptr);
+ static QString allFilesFilterString();
signals:
/* Used to notify e.g. the code model to update the given files. Does *not*
diff --git a/src/plugins/coreplugin/editormanager/documentmodel.cpp b/src/plugins/coreplugin/editormanager/documentmodel.cpp
index 52915311d6d..f3ff09161cb 100644
--- a/src/plugins/coreplugin/editormanager/documentmodel.cpp
+++ b/src/plugins/coreplugin/editormanager/documentmodel.cpp
@@ -276,7 +276,7 @@ Qt::ItemFlags DocumentModelPrivate::flags(const QModelIndex &index) const
QMimeData *DocumentModelPrivate::mimeData(const QModelIndexList &indexes) const
{
auto data = new Utils::DropMimeData;
- foreach (const QModelIndex &index, indexes) {
+ for (const QModelIndex &index : indexes) {
const DocumentModel::Entry *e = DocumentModel::entryAtRow(index.row());
if (!e || e->fileName().isEmpty())
continue;
@@ -485,13 +485,18 @@ void DocumentModelPrivate::removeAllSuspendedEntries(PinnedFileRemovalPolicy pin
if (pinnedFileRemovalPolicy == DoNotRemovePinnedFiles && entry->pinned)
continue;
+ const FilePath fixedPath = DocumentManager::filePathKey(entry->fileName(),
+ DocumentManager::ResolveLinks);
int row = i + 1/*<no document>*/;
d->beginRemoveRows(QModelIndex(), row, row);
delete d->m_entries.takeAt(i);
d->endRemoveRows();
+
+ if (!fixedPath.isEmpty())
+ d->m_entryByFixedPath.remove(fixedPath);
}
QSet<QString> displayNames;
- foreach (DocumentModel::Entry *entry, d->m_entries) {
+ for (DocumentModel::Entry *entry : qAsConst(d->m_entries)) {
const QString displayName = entry->plainDisplayName();
if (displayNames.contains(displayName))
continue;
@@ -594,7 +599,7 @@ QList<IEditor *> DocumentModel::editorsForOpenedDocuments()
QList<IEditor *> DocumentModel::editorsForDocuments(const QList<IDocument *> &documents)
{
QList<IEditor *> result;
- foreach (IDocument *document, documents)
+ for (IDocument *document : documents)
result += d->m_editors.value(document);
return result;
}
@@ -617,10 +622,10 @@ DocumentModel::Entry *DocumentModel::entryForDocument(IDocument *document)
DocumentModel::Entry *DocumentModel::entryForFilePath(const Utils::FilePath &filePath)
{
- const Utils::optional<int> index = d->indexOfFilePath(filePath);
- if (!index)
+ if (filePath.isEmpty())
return nullptr;
- return d->m_entries.at(*index);
+ const FilePath fixedPath = DocumentManager::filePathKey(filePath, DocumentManager::ResolveLinks);
+ return d->m_entryByFixedPath.value(fixedPath);
}
QList<IDocument *> DocumentModel::openedDocuments()
@@ -630,10 +635,8 @@ QList<IDocument *> DocumentModel::openedDocuments()
IDocument *DocumentModel::documentForFilePath(const Utils::FilePath &filePath)
{
- const Utils::optional<int> index = d->indexOfFilePath(filePath);
- if (!index)
- return nullptr;
- return d->m_entries.at(*index)->document;
+ const Entry *entry = entryForFilePath(filePath);
+ return entry ? entry->document : nullptr;
}
QList<IEditor *> DocumentModel::editorsForFilePath(const Utils::FilePath &filePath)
diff --git a/src/plugins/coreplugin/editormanager/documentmodel.h b/src/plugins/coreplugin/editormanager/documentmodel.h
index e5261326548..a4f759d4d74 100644
--- a/src/plugins/coreplugin/editormanager/documentmodel.h
+++ b/src/plugins/coreplugin/editormanager/documentmodel.h
@@ -65,7 +65,7 @@ public:
// This is typically the case for files that have not been opened yet,
// but can also happen later after they have been opened.
// The related setting for this is found in:
- // Options > Environment > System > Auto-suspend unmodified files
+ // Edit > Preferences > Environment > System > Auto-suspend unmodified files
bool isSuspended;
// The entry has been pinned, which means that it should stick to
// the top of any lists of open files, and that any actions that close
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 657400027b5..4fc365496b7 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -67,13 +67,12 @@
#include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
#include <utils/executeondestruction.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <utils/hostosinfo.h>
#include <utils/infobar.h>
#include <utils/link.h>
#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/mimetypes/mimetype.h>
+#include <utils/mimeutils.h>
#include <utils/overridecursor.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
@@ -129,6 +128,8 @@ static const char preferredEditorFactoriesKey[] = "EditorManager/PreferredEditor
static const char scratchBufferKey[] = "_q_emScratchBuffer";
+static const int kMaxViews = 20;
+
// for lupdate
using namespace Core;
@@ -910,7 +911,7 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
auto button = qobject_cast<QPushButton *>(msgbox.button(QMessageBox::Open));
QTC_ASSERT(button, return nullptr);
auto menu = new QMenu(button);
- foreach (EditorType *factory, factories) {
+ for (EditorType *factory : qAsConst(factories)) {
QAction *action = menu->addAction(factory->displayName());
connect(action, &QAction::triggered, &msgbox, [&selectedFactory, factory, &msgbox]() {
selectedFactory = factory;
@@ -970,8 +971,8 @@ IEditor *EditorManagerPrivate::openEditorWith(const FilePath &filePath, Id edito
// close any open editors that have this file open
// remember the views to open new editors in there
QList<EditorView *> views;
- QList<IEditor *> editorsOpenForFile = DocumentModel::editorsForFilePath(filePath);
- foreach (IEditor *openEditor, editorsOpenForFile) {
+ const QList<IEditor *> editorsOpenForFile = DocumentModel::editorsForFilePath(filePath);
+ for (IEditor *openEditor : editorsOpenForFile) {
EditorView *view = EditorManagerPrivate::viewForEditor(openEditor);
if (view && view->currentEditor() == openEditor) // visible
views.append(view);
@@ -988,7 +989,7 @@ IEditor *EditorManagerPrivate::openEditorWith(const FilePath &filePath, Id edito
views.prepend(currentView); // open editor in current view first
}
EditorManager::OpenEditorFlags flags;
- foreach (EditorView *view, views) {
+ for (EditorView *view : qAsConst(views)) {
IEditor *editor = EditorManagerPrivate::openEditor(view, filePath, editorId, flags);
if (!openedEditor && editor)
openedEditor = editor;
@@ -1147,7 +1148,7 @@ void EditorManagerPrivate::showPopupOrSelectDocument()
// if the active window has editors, we want that editor area as a reference
// TODO: this does not work correctly with multiple editor areas in the same window
EditorArea *activeEditorArea = nullptr;
- foreach (EditorArea *area, d->m_editorAreas) {
+ for (EditorArea *area : qAsConst(d->m_editorAreas)) {
if (area->window() == activeWindow) {
activeEditorArea = area;
break;
@@ -1645,9 +1646,10 @@ bool EditorManagerPrivate::closeEditors(const QList<IEditor*> &editors, CloseFla
// 2. keep track of the document and all the editors that might remain open for it
QSet<IEditor*> acceptedEditors;
QHash<IDocument *, QList<IEditor *> > editorsForDocuments;
- foreach (IEditor *editor, editors) {
+ for (IEditor *editor : qAsConst(editors)) {
bool editorAccepted = true;
- foreach (const std::function<bool(IEditor*)> listener, d->m_closeEditorListeners) {
+ const QList<std::function<bool(IEditor *)>> listeners = d->m_closeEditorListeners;
+ for (const std::function<bool(IEditor *)> &listener : listeners) {
if (!listener(editor)) {
editorAccepted = false;
closingFailed = true;
@@ -1795,8 +1797,7 @@ bool EditorManagerPrivate::closeEditors(const QList<IEditor*> &editors, CloseFla
setCurrentEditor(currentView->currentEditor());
}
- foreach (IEditor *editor, acceptedEditors)
- delete editor;
+ qDeleteAll(acceptedEditors);
if (!EditorManager::currentEditor()) {
emit m_instance->currentEditorChanged(nullptr);
@@ -1836,7 +1837,7 @@ int EditorManagerPrivate::visibleDocumentsCount()
return editorsCount;
QSet<const IDocument *> visibleDocuments;
- foreach (IEditor *editor, editors) {
+ for (const IEditor *editor : editors) {
if (const IDocument *document = editor->document())
visibleDocuments << document;
}
@@ -2000,7 +2001,8 @@ void EditorManagerPrivate::splitNewWindow(EditorView *view)
IEditor *EditorManagerPrivate::pickUnusedEditor(EditorView **foundView)
{
- foreach (IEditor *editor, DocumentModel::editorsForOpenedDocuments()) {
+ const QList<IEditor *> editors = DocumentModel::editorsForOpenedDocuments();
+ for (IEditor *editor : editors) {
EditorView *view = viewForEditor(editor);
if (!view || view->currentEditor() != editor) {
if (foundView)
@@ -2098,6 +2100,7 @@ void EditorManagerPrivate::setupSaveActions(IDocument *document, QAction *saveAc
void EditorManagerPrivate::updateActions()
{
IDocument *curDocument = EditorManager::currentDocument();
+ const int viewCount = allEditorViews().size();
const int openedCount = DocumentModel::entryCount();
if (curDocument)
@@ -2129,6 +2132,10 @@ void EditorManagerPrivate::updateActions()
d->m_removeCurrentSplitAction->setEnabled(hasSplitter);
d->m_removeAllSplitsAction->setEnabled(hasSplitter);
d->m_gotoNextSplitAction->setEnabled(hasSplitter || d->m_editorAreas.size() > 1);
+ const bool splitActionsEnabled = viewCount < kMaxViews;
+ d->m_splitAction->setEnabled(splitActionsEnabled);
+ d->m_splitNewWindowAction->setEnabled(splitActionsEnabled);
+ d->m_splitSideBySideAction->setEnabled(splitActionsEnabled);
}
void EditorManagerPrivate::updateWindowTitleForDocument(IDocument *document, QWidget *window)
@@ -2141,8 +2148,8 @@ void EditorManagerPrivate::updateWindowTitleForDocument(IDocument *document, QWi
if (!documentName.isEmpty())
windowTitle.append(documentName);
- const QString filePath = document ? document->filePath().absoluteFilePath().path()
- : QString();
+ const Utils::FilePath filePath = document ? document->filePath().absoluteFilePath()
+ : Utils::FilePath();
const QString windowTitleAddition = d->m_titleAdditionHandler
? d->m_titleAdditionHandler(filePath)
: QString();
@@ -2174,7 +2181,7 @@ void EditorManagerPrivate::updateWindowTitleForDocument(IDocument *document, QWi
windowTitle.append(dashSep);
windowTitle.append(Core::Constants::IDE_DISPLAY_NAME);
window->window()->setWindowTitle(windowTitle);
- window->window()->setWindowFilePath(filePath);
+ window->window()->setWindowFilePath(filePath.path());
if (HostOsInfo::isMacHost()) {
if (document)
@@ -2360,7 +2367,8 @@ void EditorManagerPrivate::autoSave()
{
QStringList errors;
// FIXME: the saving should be staggered
- foreach (IDocument *document, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents) {
if (!document->isModified() || !document->shouldAutoSave())
continue;
const FilePath saveName = autoSaveName(document->filePath());
@@ -2385,7 +2393,7 @@ void EditorManagerPrivate::handleContextChange(const QList<IContext *> &context)
qDebug() << Q_FUNC_INFO;
d->m_scheduledCurrentEditor = nullptr;
IEditor *editor = nullptr;
- foreach (IContext *c, context)
+ for (IContext *c : context)
if ((editor = qobject_cast<IEditor*>(c)))
break;
if (editor && editor != d->m_currentEditor) {
@@ -2525,7 +2533,8 @@ bool EditorManagerPrivate::saveDocumentAs(IDocument *document)
if (absoluteFilePath.isEmpty())
return false;
- if (absoluteFilePath != document->filePath()) {
+ if (DocumentManager::filePathKey(absoluteFilePath, DocumentManager::ResolveLinks)
+ != DocumentManager::filePathKey(document->filePath(), DocumentManager::ResolveLinks)) {
// close existing editors for the new file name
IDocument *otherDocument = DocumentModel::documentForFilePath(absoluteFilePath);
if (otherDocument)
@@ -2560,7 +2569,8 @@ void EditorManagerPrivate::closeAllEditorsExceptVisible()
DocumentModel::Entry *entry = DocumentModel::entryForDocument(document);
return !entry->pinned;
});
- foreach (IEditor *editor, EditorManager::visibleEditors())
+ const QList<IEditor *> editors = EditorManager::visibleEditors();
+ for (const IEditor *editor : editors)
documentsToClose.removeAll(editor->document());
EditorManager::closeDocuments(documentsToClose, true);
}
@@ -2611,7 +2621,7 @@ void EditorManagerPrivate::autoSuspendDocuments()
&IEditor::document);
int keptEditorCount = 0;
QList<IDocument *> documentsToSuspend;
- foreach (const EditLocation &editLocation, d->m_globalHistory) {
+ for (const EditLocation &editLocation : qAsConst(d->m_globalHistory)) {
IDocument *document = editLocation.document;
if (!document || !document->isSuspendAllowed() || document->isModified()
|| document->isTemporary() || document->filePath().isEmpty()
@@ -2699,7 +2709,7 @@ EditorView *EditorManagerPrivate::currentEditorView()
}
QTC_CHECK(view);
if (!view) { // should not happen, we should always have either currentview or currentdocument
- foreach (EditorArea *area, d->m_editorAreas) {
+ for (const EditorArea *area : qAsConst(d->m_editorAreas)) {
if (area->window()->isActiveWindow()) {
view = area->findFirstView();
break;
@@ -2711,6 +2721,24 @@ EditorView *EditorManagerPrivate::currentEditorView()
return view;
}
+QList<EditorView *> EditorManagerPrivate::allEditorViews()
+{
+ QList<EditorView *> views;
+ for (const EditorArea *area : qAsConst(d->m_editorAreas)) {
+ EditorView *firstView = area->findFirstView();
+ EditorView *view = firstView;
+ if (view) {
+ do {
+ views.append(view);
+ view = view->findNextView();
+ // we start with firstView and shouldn't have cycles
+ QTC_ASSERT(view != firstView, break);
+ } while (view);
+ }
+ }
+ return views;
+}
+
/*!
Returns the pointer to the instance. Only use for connecting to signals.
*/
@@ -3259,7 +3287,8 @@ static QString makeTitleUnique(QString *titlePattern)
if (base.contains(dollar)) {
int i = 1;
QSet<QString> docnames;
- foreach (DocumentModel::Entry *entry, DocumentModel::entries()) {
+ const QList<DocumentModel::Entry *> entries = DocumentModel::entries();
+ for (const DocumentModel::Entry *entry : entries) {
QString name = entry->fileName().toString();
if (name.isEmpty())
name = entry->displayName();
@@ -3316,7 +3345,8 @@ IEditor *EditorManager::openEditorWithContents(Id editorId,
IEditor *edt = nullptr;
if (!uniqueId.isEmpty()) {
- foreach (IDocument *document, DocumentModel::openedDocuments())
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents)
if (document->property(scratchBufferKey).toString() == uniqueId) {
edt = DocumentModel::editorsForDocument(document).constFirst();
@@ -3401,23 +3431,11 @@ bool EditorManager::hasSplitter()
*/
QList<IEditor*> EditorManager::visibleEditors()
{
+ const QList<EditorView *> allViews = EditorManagerPrivate::allEditorViews();
QList<IEditor *> editors;
- foreach (EditorArea *area, d->m_editorAreas) {
- if (area->isSplitter()) {
- EditorView *firstView = area->findFirstView();
- EditorView *view = firstView;
- if (view) {
- do {
- if (view->currentEditor())
- editors.append(view->currentEditor());
- view = view->findNextView();
- QTC_ASSERT(view != firstView, break); // we start with firstView and shouldn't have cycles
- } while (view);
- }
- } else {
- if (area->editor())
- editors.append(area->editor());
- }
+ for (const EditorView *view : allViews) {
+ if (view->currentEditor())
+ editors.append(view->currentEditor());
}
return editors;
}
@@ -3536,7 +3554,7 @@ QByteArray EditorManager::saveState()
// TODO: In case of split views it's not possible to restore these for all correctly with this
QList<IDocument *> documents = DocumentModel::openedDocuments();
- foreach (IDocument *document, documents) {
+ for (IDocument *document : documents) {
if (!document->filePath().isEmpty() && !document->isTemporary()) {
IEditor *editor = DocumentModel::editorsForDocument(document).constFirst();
QByteArray state = editor->saveState();
@@ -3547,9 +3565,9 @@ QByteArray EditorManager::saveState()
stream << d->m_editorStates;
- QList<DocumentModel::Entry *> entries = DocumentModel::entries();
+ const QList<DocumentModel::Entry *> entries = DocumentModel::entries();
int entriesCount = 0;
- foreach (DocumentModel::Entry *entry, entries) {
+ for (const DocumentModel::Entry *entry : entries) {
// The editor may be 0 if it was not loaded yet: In that case it is not temporary
if (!entry->document->isTemporary())
++entriesCount;
@@ -3557,7 +3575,7 @@ QByteArray EditorManager::saveState()
stream << entriesCount;
- foreach (DocumentModel::Entry *entry, entries) {
+ for (const DocumentModel::Entry *entry : entries) {
if (!entry->document->isTemporary()) {
stream << entry->fileName().toString() << entry->plainDisplayName() << entry->id()
<< entry->pinned;
@@ -3805,7 +3823,7 @@ void EditorManager::setSessionTitleHandler(WindowTitleHandler handler)
*/
void EditorManager::updateWindowTitles()
{
- foreach (EditorArea *area, d->m_editorAreas)
+ for (EditorArea *area : qAsConst(d->m_editorAreas))
emit area->windowTitleNeedsUpdate();
}
diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h
index 4b722c6dce9..dbfe5849514 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.h
+++ b/src/plugins/coreplugin/editormanager/editormanager.h
@@ -71,7 +71,7 @@ class CORE_EXPORT EditorManager : public QObject
Q_OBJECT
public:
- using WindowTitleHandler = std::function<QString (const QString &)>;
+ using WindowTitleHandler = std::function<QString (const Utils::FilePath &)>;
static EditorManager *instance();
diff --git a/src/plugins/coreplugin/editormanager/editormanager_p.h b/src/plugins/coreplugin/editormanager/editormanager_p.h
index bbbc345c04c..571299f54b3 100644
--- a/src/plugins/coreplugin/editormanager/editormanager_p.h
+++ b/src/plugins/coreplugin/editormanager/editormanager_p.h
@@ -83,6 +83,7 @@ public:
static EditorArea *mainEditorArea();
static EditorView *currentEditorView();
+ static QList<EditorView *> allEditorViews();
static void setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory = false);
static IEditor *openEditor(EditorView *view,
const Utils::FilePath &filePath,
@@ -292,7 +293,7 @@ private:
int autoSaveInterval = 5;
bool autoSuspendEnabled = true;
- int autoSuspendMinDocumentCount = 30;
+ int autoSuspendMinDocumentCount = 10;
bool autoSaveAfterRefactoring = true;
bool warnBeforeOpeningBigFilesEnabled = true;
diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp
index d3b3f6cfa41..a8ee45501dc 100644
--- a/src/plugins/coreplugin/editormanager/editorview.cpp
+++ b/src/plugins/coreplugin/editormanager/editorview.cpp
@@ -407,8 +407,7 @@ void EditorView::openDroppedFiles(const QList<DropSupport::FileSpec> &files)
};
auto openEntry = [&](const DropSupport::FileSpec &spec) {
if (first) {
- first = false;
- EditorManagerPrivate::openEditorAt(this, specToLink(spec));
+ first = !EditorManagerPrivate::openEditorAt(this, specToLink(spec));
} else if (spec.column != -1 || spec.line != -1) {
EditorManagerPrivate::openEditorAt(this,
specToLink(spec),
@@ -466,10 +465,7 @@ QList<IEditor *> EditorView::editors() const
IEditor *EditorView::editorForDocument(const IDocument *document) const
{
- foreach (IEditor *editor, m_editors)
- if (editor->document() == document)
- return editor;
- return nullptr;
+ return Utils::findOrDefault(m_editors, Utils::equal(&IEditor::document, document));
}
void EditorView::updateEditorHistory(IEditor *editor)
@@ -477,6 +473,8 @@ void EditorView::updateEditorHistory(IEditor *editor)
updateEditorHistory(editor, m_editorHistory);
}
+constexpr int navigationHistorySize = 100;
+
void EditorView::addCurrentPositionToNavigationHistory(const QByteArray &saveState)
{
IEditor *editor = currentEditor();
@@ -502,8 +500,8 @@ void EditorView::addCurrentPositionToNavigationHistory(const QByteArray &saveSta
m_navigationHistory.insert(m_currentNavigationHistoryPosition, location);
++m_currentNavigationHistoryPosition;
- while (m_navigationHistory.size() >= 30) {
- if (m_currentNavigationHistoryPosition > 15) {
+ while (m_navigationHistory.size() >= navigationHistorySize) {
+ if (m_currentNavigationHistoryPosition > navigationHistorySize / 2) {
m_navigationHistory.removeFirst();
--m_currentNavigationHistoryPosition;
} else {
@@ -679,7 +677,7 @@ SplitterOrView::~SplitterOrView()
m_splitter = nullptr;
}
-EditorView *SplitterOrView::findFirstView()
+EditorView *SplitterOrView::findFirstView() const
{
if (m_splitter) {
for (int i = 0; i < m_splitter->count(); ++i) {
@@ -692,7 +690,7 @@ EditorView *SplitterOrView::findFirstView()
return m_view;
}
-EditorView *SplitterOrView::findLastView()
+EditorView *SplitterOrView::findLastView() const
{
if (m_splitter) {
for (int i = m_splitter->count() - 1; 0 < i; --i) {
@@ -919,13 +917,10 @@ QByteArray SplitterOrView::saveState() const
// don't save state of temporary or ad-hoc editors
if (e && (e->document()->isTemporary() || e->document()->filePath().isEmpty())) {
// look for another editor that is more suited
- e = nullptr;
- foreach (IEditor *otherEditor, editors()) {
- if (!otherEditor->document()->isTemporary() && !otherEditor->document()->filePath().isEmpty()) {
- e = otherEditor;
- break;
- }
- }
+ e = Utils::findOrDefault(editors(), [](IEditor *otherEditor) {
+ return !otherEditor->document()->isTemporary()
+ && !otherEditor->document()->filePath().isEmpty();
+ });
}
if (!e) {
diff --git a/src/plugins/coreplugin/editormanager/editorview.h b/src/plugins/coreplugin/editormanager/editorview.h
index 6dca73353a5..024371674b3 100644
--- a/src/plugins/coreplugin/editormanager/editorview.h
+++ b/src/plugins/coreplugin/editormanager/editorview.h
@@ -194,8 +194,8 @@ public:
QByteArray saveState() const;
void restoreState(const QByteArray &);
- EditorView *findFirstView();
- EditorView *findLastView();
+ EditorView *findFirstView() const;
+ EditorView *findLastView() const;
SplitterOrView *findParentSplitter() const;
QSize sizeHint() const override { return minimumSizeHint(); }
diff --git a/src/plugins/coreplugin/editormanager/ieditorfactory.cpp b/src/plugins/coreplugin/editormanager/ieditorfactory.cpp
index a4e323b8d2f..af7627a0c20 100644
--- a/src/plugins/coreplugin/editormanager/ieditorfactory.cpp
+++ b/src/plugins/coreplugin/editormanager/ieditorfactory.cpp
@@ -28,7 +28,7 @@
#include "editormanager.h"
#include <utils/algorithm.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <QFileInfo>
diff --git a/src/plugins/coreplugin/editormanager/ieditorfactory.h b/src/plugins/coreplugin/editormanager/ieditorfactory.h
index 20787c29155..dfefb53c185 100644
--- a/src/plugins/coreplugin/editormanager/ieditorfactory.h
+++ b/src/plugins/coreplugin/editormanager/ieditorfactory.h
@@ -28,14 +28,16 @@
#include <coreplugin/core_global.h>
#include <utils/id.h>
-#include <utils/mimetypes/mimetype.h>
#include <QObject>
#include <QStringList>
#include <functional>
-namespace Utils { class FilePath; }
+namespace Utils {
+class FilePath;
+class MimeType;
+}
namespace Core {
diff --git a/src/plugins/coreplugin/editormanager/ieditorfactory_p.h b/src/plugins/coreplugin/editormanager/ieditorfactory_p.h
index 842772c2e58..fc9cfb384e7 100644
--- a/src/plugins/coreplugin/editormanager/ieditorfactory_p.h
+++ b/src/plugins/coreplugin/editormanager/ieditorfactory_p.h
@@ -25,8 +25,7 @@
#pragma once
-#include <utils/mimetypes/mimetype.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QHash>
#include <QSet>
@@ -60,9 +59,10 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
while (!queue.isEmpty()) {
Utils::MimeType mt = queue.takeFirst();
// check for matching factories
- foreach (EditorTypeLike *factory, allFactories) {
+ for (EditorTypeLike *factory : allFactories) {
if (!matches.contains(factory)) {
- foreach (const QString &mimeName, factory->mimeTypes()) {
+ const QStringList mimeTypes = factory->mimeTypes();
+ for (const QString &mimeName : mimeTypes) {
if (mt.matchesName(mimeName)) {
list->append(factory);
matches.insert(factory);
@@ -71,8 +71,8 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
}
}
// add parent mime types
- QStringList parentNames = mt.parentMimeTypes();
- foreach (const QString &parentName, parentNames) {
+ const QStringList parentNames = mt.parentMimeTypes();
+ for (const QString &parentName : parentNames) {
const Utils::MimeType parent = Utils::mimeTypeForName(parentName);
if (parent.isValid()) {
int seenSize = seen.size();
diff --git a/src/plugins/coreplugin/editormanager/iexternaleditor.h b/src/plugins/coreplugin/editormanager/iexternaleditor.h
index d37fc9fd12d..a3ed21c64a1 100644
--- a/src/plugins/coreplugin/editormanager/iexternaleditor.h
+++ b/src/plugins/coreplugin/editormanager/iexternaleditor.h
@@ -30,11 +30,13 @@
#include <coreplugin/core_global.h>
#include <utils/id.h>
-#include <utils/mimetypes/mimetype.h>
#include <QObject>
-namespace Utils { class FilePath; }
+namespace Utils {
+class FilePath;
+class MimeType;
+}
namespace Core {
diff --git a/src/plugins/coreplugin/editormanager/openeditorswindow.cpp b/src/plugins/coreplugin/editormanager/openeditorswindow.cpp
index fdcd6b57be2..77bcddc4fb6 100644
--- a/src/plugins/coreplugin/editormanager/openeditorswindow.cpp
+++ b/src/plugins/coreplugin/editormanager/openeditorswindow.cpp
@@ -223,7 +223,7 @@ static DocumentModel::Entry *entryForEditLocation(const EditLocation &item)
void OpenEditorsWindow::addHistoryItems(const QList<EditLocation> &history, EditorView *view,
QSet<const DocumentModel::Entry *> &entriesDone)
{
- foreach (const EditLocation &hi, history) {
+ for (const EditLocation &hi : history) {
if (DocumentModel::Entry *entry = entryForEditLocation(hi))
addItem(entry, entriesDone, view);
}
@@ -232,7 +232,8 @@ void OpenEditorsWindow::addHistoryItems(const QList<EditLocation> &history, Edit
void OpenEditorsWindow::addRemainingItems(EditorView *view,
QSet<const DocumentModel::Entry *> &entriesDone)
{
- foreach (DocumentModel::Entry *entry, DocumentModel::entries())
+ const QList<DocumentModel::Entry *> entries = DocumentModel::entries();
+ for (DocumentModel::Entry *entry : entries)
addItem(entry, entriesDone, view);
}
diff --git a/src/plugins/coreplugin/externaltool.cpp b/src/plugins/coreplugin/externaltool.cpp
index 04ff8c9e0c5..ac3ef7796cb 100644
--- a/src/plugins/coreplugin/externaltool.cpp
+++ b/src/plugins/coreplugin/externaltool.cpp
@@ -51,7 +51,6 @@ using namespace Utils;
using namespace Core::Internal;
namespace Core {
-namespace Internal {
const char kExternalTool[] = "externaltool";
const char kId[] = "id";
@@ -331,7 +330,7 @@ static void localizedText(const QStringList &locales, QXmlStreamReader *reader,
}
} else {
if (*currentLocale < 0 && currentText->isEmpty()) {
- *currentText = QCoreApplication::translate("Core::Internal::ExternalTool",
+ *currentText = QCoreApplication::translate("Core::ExternalTool",
reader->readElementText().toUtf8().constData(),
"");
} else {
@@ -648,8 +647,7 @@ void ExternalToolRunner::run()
}
}
m_process = new QtcProcess(this);
- connect(m_process, &QtcProcess::finished, this, &ExternalToolRunner::finished);
- connect(m_process, &QtcProcess::errorOccurred, this, &ExternalToolRunner::error);
+ connect(m_process, &QtcProcess::done, this, &ExternalToolRunner::done);
connect(m_process, &QtcProcess::readyReadStandardOutput,
this, &ExternalToolRunner::readStandardOutput);
connect(m_process, &QtcProcess::readyReadStandardError,
@@ -668,28 +666,23 @@ void ExternalToolRunner::run()
m_process->start();
}
-void ExternalToolRunner::finished()
+void ExternalToolRunner::done()
{
- if (m_process->result() == QtcProcess::FinishedWithSuccess
- && (m_tool->outputHandling() == ExternalTool::ReplaceSelection
- || m_tool->errorHandling() == ExternalTool::ReplaceSelection)) {
+ if (m_process->result() == ProcessResult::FinishedWithSuccess
+ && (m_tool->outputHandling() == ExternalTool::ReplaceSelection
+ || m_tool->errorHandling() == ExternalTool::ReplaceSelection)) {
ExternalToolManager::emitReplaceSelectionRequested(m_processOutput);
}
+ const QString message = (m_process->result() == ProcessResult::FinishedWithSuccess)
+ ? tr("\"%1\" finished").arg(m_resolvedExecutable.toUserOutput())
+ : tr("\"%1\" finished with error").arg(m_resolvedExecutable.toUserOutput());
+
if (m_tool->modifiesCurrentDocument())
DocumentManager::unexpectFileChange(m_expectedFilePath);
const auto write = m_tool->outputHandling() == ExternalTool::ShowInPane
? QOverload<const QString &>::of(MessageManager::writeFlashing)
: QOverload<const QString &>::of(MessageManager::writeSilently);
- write(tr("\"%1\" finished").arg(m_resolvedExecutable.toUserOutput()));
- deleteLater();
-}
-
-void ExternalToolRunner::error(QProcess::ProcessError error)
-{
- if (m_tool->modifiesCurrentDocument())
- DocumentManager::unexpectFileChange(m_expectedFilePath);
- // TODO inform about errors
- Q_UNUSED(error)
+ write(message);
deleteLater();
}
@@ -721,6 +714,4 @@ void ExternalToolRunner::readStandardError()
m_processOutput.append(output);
}
-} // namespace Internal
-
} // namespace Core
diff --git a/src/plugins/coreplugin/externaltool.h b/src/plugins/coreplugin/externaltool.h
index 38fc517bd2d..a1e16f10f56 100644
--- a/src/plugins/coreplugin/externaltool.h
+++ b/src/plugins/coreplugin/externaltool.h
@@ -25,6 +25,8 @@
#pragma once
+#include <coreplugin/core_global.h>
+
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/id.h>
@@ -38,9 +40,8 @@
namespace Utils { class QtcProcess; }
namespace Core {
-namespace Internal {
-class ExternalTool : public QObject
+class CORE_EXPORT ExternalTool : public QObject
{
Q_OBJECT
@@ -123,7 +124,7 @@ private:
QSharedPointer<ExternalTool> m_presetTool;
};
-class ExternalToolRunner : public QObject
+class CORE_EXPORT ExternalToolRunner : public QObject
{
Q_OBJECT
public:
@@ -134,8 +135,7 @@ public:
QString errorString() const;
private:
- void finished();
- void error(QProcess::ProcessError error);
+ void done();
void readStandardOutput();
void readStandardError();
@@ -158,7 +158,6 @@ private:
QString m_errorString;
};
-} // Internal
} // Core
-Q_DECLARE_METATYPE(Core::Internal::ExternalTool *)
+Q_DECLARE_METATYPE(Core::ExternalTool *)
diff --git a/src/plugins/coreplugin/externaltoolmanager.cpp b/src/plugins/coreplugin/externaltoolmanager.cpp
index 94bd49495a4..ef3383e9603 100644
--- a/src/plugins/coreplugin/externaltoolmanager.cpp
+++ b/src/plugins/coreplugin/externaltoolmanager.cpp
@@ -61,13 +61,6 @@ static ExternalToolManager *m_instance = nullptr;
static ExternalToolManagerPrivate *d = nullptr;
static void writeSettings();
-static void readSettings(const QMap<QString, ExternalTool *> &tools,
- QMap<QString, QList<ExternalTool*> > *categoryPriorityMap);
-
-static void parseDirectory(const QString &directory,
- QMap<QString, QMultiMap<int, ExternalTool*> > *categoryMenus,
- QMap<QString, ExternalTool *> *tools,
- bool isPreset = false);
ExternalToolManager::ExternalToolManager()
: QObject(ICore::instance())
@@ -120,7 +113,7 @@ ExternalToolManager *ExternalToolManager::instance()
return m_instance;
}
-static void parseDirectory(const QString &directory,
+void ExternalToolManager::parseDirectory(const QString &directory,
QMap<QString, QMultiMap<int, ExternalTool*> > *categoryMenus,
QMap<QString, ExternalTool *> *tools,
bool isPreset)
@@ -128,7 +121,8 @@ static void parseDirectory(const QString &directory,
QTC_ASSERT(categoryMenus, return);
QTC_ASSERT(tools, return);
QDir dir(directory, QLatin1String("*.xml"), QDir::Unsorted, QDir::Files | QDir::Readable);
- foreach (const QFileInfo &info, dir.entryInfoList()) {
+ const QList<QFileInfo> infoList = dir.entryInfoList();
+ for (const QFileInfo &info : infoList) {
const QString &fileName = info.absoluteFilePath();
QString error;
ExternalTool *tool = ExternalTool::createFromFile(Utils::FilePath::fromString(fileName), &error, ICore::userInterfaceLanguage());
@@ -176,7 +170,8 @@ void ExternalToolManager::setToolsByCategory(const QMap<QString, QList<ExternalT
QMap<QString, ExternalTool *> newTools;
QMap<QString, QAction *> newActions;
for (auto it = tools.cbegin(), end = tools.cend(); it != end; ++it) {
- foreach (ExternalTool *tool, it.value()) {
+ const QList<ExternalTool *> values = it.value();
+ for (ExternalTool *tool : values) {
const QString id = tool->id();
if (d->m_tools.value(id) == tool) {
newActions.insert(id, d->m_actions.value(id));
@@ -217,7 +212,8 @@ void ExternalToolManager::setToolsByCategory(const QMap<QString, QList<ExternalT
mexternaltools->addMenu(container, Constants::G_DEFAULT_ONE);
container->menu()->setTitle(containerName);
}
- foreach (ExternalTool *tool, it.value()) {
+ const QList<ExternalTool *> values = it.value();
+ for (ExternalTool *tool : values) {
const QString &toolId = tool->id();
// tool action and command
QAction *action = nullptr;
@@ -254,7 +250,7 @@ void ExternalToolManager::setToolsByCategory(const QMap<QString, QList<ExternalT
mexternaltools->menu()->addAction(d->m_configureAction);
}
-static void readSettings(const QMap<QString, ExternalTool *> &tools,
+void ExternalToolManager::readSettings(const QMap<QString, ExternalTool *> &tools,
QMap<QString, QList<ExternalTool *> > *categoryMap)
{
QSettings *settings = ICore::settings();
@@ -262,7 +258,8 @@ static void readSettings(const QMap<QString, ExternalTool *> &tools,
if (categoryMap) {
settings->beginGroup(QLatin1String("OverrideCategories"));
- foreach (const QString &settingsCategory, settings->childGroups()) {
+ const QStringList settingsCategories = settings->childGroups();
+ for (const QString &settingsCategory : settingsCategories) {
QString displayCategory = settingsCategory;
if (displayCategory == QLatin1String(kSpecialUncategorizedSetting))
displayCategory = QLatin1String("");
@@ -301,7 +298,8 @@ static void writeSettings()
category = QLatin1String(kSpecialUncategorizedSetting);
settings->beginWriteArray(category, it.value().count());
int i = 0;
- foreach (ExternalTool *tool, it.value()) {
+ const QList<ExternalTool *> values = it.value();
+ for (const ExternalTool *tool : values) {
settings->setArrayIndex(i);
settings->setValue(QLatin1String("Tool"), tool->id());
++i;
diff --git a/src/plugins/coreplugin/externaltoolmanager.h b/src/plugins/coreplugin/externaltoolmanager.h
index 23ec6adc8af..67a932fee81 100644
--- a/src/plugins/coreplugin/externaltoolmanager.h
+++ b/src/plugins/coreplugin/externaltoolmanager.h
@@ -34,7 +34,7 @@
namespace Core {
-namespace Internal { class ExternalTool; }
+class ExternalTool;
class CORE_EXPORT ExternalToolManager : public QObject
{
@@ -45,10 +45,17 @@ public:
~ExternalToolManager() override;
static ExternalToolManager *instance();
- static QMap<QString, QList<Internal::ExternalTool *> > toolsByCategory();
- static QMap<QString, Internal::ExternalTool *> toolsById();
- static void setToolsByCategory(const QMap<QString, QList<Internal::ExternalTool *> > &tools);
+ static QMap<QString, QList<ExternalTool *> > toolsByCategory();
+ static QMap<QString, ExternalTool *> toolsById();
+ static void setToolsByCategory(const QMap<QString, QList<ExternalTool *> > &tools);
static void emitReplaceSelectionRequested(const QString &output);
+ static void readSettings(const QMap<QString, ExternalTool *> &tools,
+ QMap<QString, QList<ExternalTool*> > *categoryPriorityMap);
+
+ static void parseDirectory(const QString &directory,
+ QMap<QString, QMultiMap<int, ExternalTool*> > *categoryMenus,
+ QMap<QString, ExternalTool *> *tools,
+ bool isPreset = false);
signals:
void replaceSelectionRequested(const QString &text);
diff --git a/src/plugins/coreplugin/fancytabwidget.h b/src/plugins/coreplugin/fancytabwidget.h
index 8c5544665df..1b227f51c06 100644
--- a/src/plugins/coreplugin/fancytabwidget.h
+++ b/src/plugins/coreplugin/fancytabwidget.h
@@ -49,8 +49,9 @@ class FancyTab : public QObject
Q_PROPERTY(qreal fader READ fader WRITE setFader)
public:
- FancyTab(QWidget *tabbar)
- : m_tabbar(tabbar)
+ FancyTab(QWidget *parentTabBar)
+ : QObject(parentTabBar)
+ , m_tabbar(parentTabBar)
{
m_animator.setPropertyName("fader");
m_animator.setTargetObject(this);
diff --git a/src/plugins/coreplugin/fileiconprovider.cpp b/src/plugins/coreplugin/fileiconprovider.cpp
index e2149ce35a4..217e2df8b90 100644
--- a/src/plugins/coreplugin/fileiconprovider.cpp
+++ b/src/plugins/coreplugin/fileiconprovider.cpp
@@ -27,7 +27,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/optional.h>
#include <utils/qtcassert.h>
#include <utils/variant.h>
@@ -120,7 +120,8 @@ public:
void registerIconOverlayForMimeType(const QString &iconFilePath, const Utils::MimeType &mimeType)
{
- foreach (const QString &suffix, mimeType.suffixes())
+ const QStringList suffixes = mimeType.suffixes();
+ for (const QString &suffix : suffixes)
registerIconOverlayForSuffix(iconFilePath, suffix);
}
diff --git a/src/plugins/coreplugin/find/basetextfind.cpp b/src/plugins/coreplugin/find/basetextfind.cpp
index 12afaf8a659..e450061af03 100644
--- a/src/plugins/coreplugin/find/basetextfind.cpp
+++ b/src/plugins/coreplugin/find/basetextfind.cpp
@@ -199,7 +199,7 @@ QString BaseTextFind::currentFindString() const
cursor.movePosition(QTextCursor::StartOfWord);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
QString s = cursor.selectedText();
- foreach (QChar c, s) {
+ for (const QChar c : s) {
if (!c.isLetterOrNumber() && c != QLatin1Char('_')) {
s.clear();
break;
diff --git a/src/plugins/coreplugin/find/finddialog.ui b/src/plugins/coreplugin/find/finddialog.ui
index bcd64728b4e..620e1041f7f 100644
--- a/src/plugins/coreplugin/find/finddialog.ui
+++ b/src/plugins/coreplugin/find/finddialog.ui
@@ -2,20 +2,6 @@
<ui version="4.0">
<class>Core::Internal::FindDialog</class>
<widget class="QWidget" name="Core::Internal::FindDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>673</width>
- <height>240</height>
- </rect>
- </property>
- <property name="maximumSize">
- <size>
- <width>680</width>
- <height>16777215</height>
- </size>
- </property>
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
@@ -202,6 +188,12 @@
<verstretch>10</verstretch>
</sizepolicy>
</property>
+ <property name="minimumSize">
+ <size>
+ <width>680</width>
+ <height>0</height>
+ </size>
+ </property>
</widget>
</item>
</layout>
diff --git a/src/plugins/coreplugin/find/findplugin.cpp b/src/plugins/coreplugin/find/findplugin.cpp
index 57b6a5649ec..ccde488bc55 100644
--- a/src/plugins/coreplugin/find/findplugin.cpp
+++ b/src/plugins/coreplugin/find/findplugin.cpp
@@ -313,7 +313,7 @@ void FindPrivate::setupFilterMenuItems()
const Id base("FindFilter.");
QList<IFindFilter *> sortedFilters = IFindFilter::allFindFilters();
Utils::sort(sortedFilters, &IFindFilter::displayName);
- foreach (IFindFilter *filter, sortedFilters) {
+ for (IFindFilter *filter : qAsConst(sortedFilters)) {
QAction *action = new QAction(filterActionName(filter), this);
bool isEnabled = filter->isEnabled();
if (isEnabled)
diff --git a/src/plugins/coreplugin/find/findtoolwindow.cpp b/src/plugins/coreplugin/find/findtoolwindow.cpp
index e689242941d..2e1f363b29f 100644
--- a/src/plugins/coreplugin/find/findtoolwindow.cpp
+++ b/src/plugins/coreplugin/find/findtoolwindow.cpp
@@ -178,12 +178,12 @@ void FindToolWindow::setFindFilters(const QList<IFindFilter *> &filters)
{
qDeleteAll(m_configWidgets);
m_configWidgets.clear();
- foreach (IFindFilter *filter, m_filters)
+ for (IFindFilter *filter : qAsConst(m_filters))
filter->disconnect(this);
m_filters = filters;
m_ui.filterList->clear();
QStringList names;
- foreach (IFindFilter *filter, filters) {
+ for (IFindFilter *filter : filters) {
names << filter->displayName();
m_configWidgets.append(filter->createConfigWidget());
connect(filter, &IFindFilter::displayNameChanged,
@@ -303,7 +303,7 @@ void FindToolWindow::writeSettings()
settings->beginGroup("Find");
settings->setValueWithDefault("CurrentFilter",
m_currentFilter ? m_currentFilter->id() : QString());
- foreach (IFindFilter *filter, m_filters)
+ for (IFindFilter *filter : qAsConst(m_filters))
filter->writeSettings(settings);
settings->endGroup();
}
diff --git a/src/plugins/coreplugin/find/searchresultcolor.h b/src/plugins/coreplugin/find/searchresultcolor.h
index 9a68f1c35ab..5934a235b30 100644
--- a/src/plugins/coreplugin/find/searchresultcolor.h
+++ b/src/plugins/coreplugin/find/searchresultcolor.h
@@ -39,14 +39,21 @@ public:
SearchResultColor() = default;
SearchResultColor(const QColor &textBg, const QColor &textFg,
- const QColor &highlightBg, const QColor &highlightFg)
+ const QColor &highlightBg, const QColor &highlightFg,
+ const QColor &functionBg, const QColor &functionFg
+ )
: textBackground(textBg), textForeground(textFg),
- highlightBackground(highlightBg), highlightForeground(highlightFg)
+ highlightBackground(highlightBg), highlightForeground(highlightFg),
+ containingFunctionBackground(functionBg),containingFunctionForeground(functionFg)
{
if (!highlightBackground.isValid())
highlightBackground = textBackground;
if (!highlightForeground.isValid())
highlightForeground = textForeground;
+ if (!containingFunctionBackground.isValid())
+ containingFunctionBackground = textBackground;
+ if (!containingFunctionForeground.isValid())
+ containingFunctionForeground = textForeground;
}
friend auto qHash(SearchResultColor::Style style)
@@ -58,6 +65,8 @@ public:
QColor textForeground;
QColor highlightBackground;
QColor highlightForeground;
+ QColor containingFunctionBackground;
+ QColor containingFunctionForeground;
};
using SearchResultColors = QHash<SearchResultColor::Style, SearchResultColor>;
diff --git a/src/plugins/coreplugin/find/searchresultitem.h b/src/plugins/coreplugin/find/searchresultitem.h
index f4e7a781628..04e9bae1b5c 100644
--- a/src/plugins/coreplugin/find/searchresultitem.h
+++ b/src/plugins/coreplugin/find/searchresultitem.h
@@ -29,6 +29,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
+#include <utils/optional.h>
#include <QIcon>
#include <QStringList>
@@ -127,6 +128,13 @@ public:
bool selectForReplacement() const { return m_selectForReplacement; }
void setSelectForReplacement(bool select) { m_selectForReplacement = select; }
+ Utils::optional<QString> containingFunctionName() const { return m_containingFunctionName; }
+
+ void setContainingFunctionName(Utils::optional<QString> containingFunctionName)
+ {
+ m_containingFunctionName = std::move(containingFunctionName);
+ }
+
private:
QStringList m_path; // hierarchy to the parent item of this item
QString m_lineText; // text to show for the item itself
@@ -136,6 +144,7 @@ private:
bool m_useTextEditorFont = false;
bool m_selectForReplacement = true;
SearchResultColor::Style m_style = SearchResultColor::Style::Default;
+ Utils::optional<QString> m_containingFunctionName;
};
} // namespace Core
diff --git a/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp b/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp
index 7bd37a555bc..a8afde231e3 100644
--- a/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp
+++ b/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp
@@ -58,15 +58,33 @@ static std::pair<int, QString> lineNumberInfo(const QStyleOptionViewItem &option
lineNumberText};
}
-static QString itemText(const QModelIndex &index)
+// Aligns text by appending spaces
+static QPair<QString, QString> align(QString text, const QString& containingFunction) {
+ constexpr int minimumTextSize = 80;
+ constexpr int textSizeIncrement = 20;
+
+ int textSize = ((text.size() / textSizeIncrement) + 1) * textSizeIncrement;
+ textSize = std::max(minimumTextSize, textSize);
+ text.resize(textSize, ' ');
+ return QPair<QString, QString>{std::move(text), containingFunction};
+}
+
+static QPair<QString, QString> itemText(const QModelIndex &index)
{
- const QString text = index.data(Qt::DisplayRole).toString();
+ QString text = index.data(Qt::DisplayRole).toString();
// show number of subresults in displayString
+ QString containingFunction;
+ const auto contFnName = index.data(ItemDataRoles::ContainingFunctionNameRole).toString();
+ if (contFnName.length())
+ containingFunction = QLatin1String("[in ") + contFnName + QLatin1String("]");
+
if (index.model()->hasChildren(index)) {
- return text + QLatin1String(" (") + QString::number(index.model()->rowCount(index))
- + QLatin1Char(')');
+ QString textAndCount{text + QLatin1String(" (")
+ + QString::number(index.model()->rowCount(index)) + QLatin1Char(')')};
+
+ return align(std::move(textAndCount), containingFunction);
}
- return text;
+ return align(std::move(text), containingFunction);
}
LayoutInfo SearchResultTreeItemDelegate::getLayoutInfo(const QStyleOptionViewItem &option,
@@ -150,7 +168,9 @@ QSize SearchResultTreeItemDelegate::sizeHint(const QStyleOptionViewItem &option,
const LayoutInfo info = getLayoutInfo(option, index);
const int height = index.data(Qt::SizeHintRole).value<QSize>().height();
// get text width, see QItemDelegatePrivate::displayRect
- const QString text = itemText(index).replace('\t', m_tabString);
+ auto texts = itemText(index);
+ const QString text = texts.first.replace('\t', m_tabString)
+ + texts.second.replace('\t', m_tabString);
const QRect textMaxRect(0, 0, INT_MAX / 256, height);
const QRect textLayoutRect = textRectangle(nullptr, textMaxRect, info.option.font, text);
const QRect textRect(info.textRect.x(), info.textRect.y(), textLayoutRect.width(), height);
@@ -198,7 +218,8 @@ void SearchResultTreeItemDelegate::drawText(QPainter *painter,
const QRect &rect,
const QModelIndex &index) const
{
- const QString text = itemText(index);
+ const auto texts = itemText(index);
+ const QString text = texts.first;
const int searchTermStart = index.model()->data(index, ItemDataRoles::ResultBeginColumnNumberRole).toInt();
int searchTermLength = index.model()->data(index, ItemDataRoles::SearchTermLengthRole).toInt();
@@ -218,6 +239,8 @@ void SearchResultTreeItemDelegate::drawText(QPainter *painter,
const QString textAfter = text.mid(searchTermStart + searchTermLength).replace(QLatin1Char('\t'), m_tabString);
int searchTermStartPixels = option.fontMetrics.horizontalAdvance(textBefore);
int searchTermLengthPixels = option.fontMetrics.horizontalAdvance(textHighlight);
+ int textAfterLengthPixels = option.fontMetrics.horizontalAdvance(textAfter);
+ int containingFunctionLengthPixels = option.fontMetrics.horizontalAdvance(texts.second);
// rects
QRect beforeHighlightRect(rect);
@@ -229,6 +252,11 @@ void SearchResultTreeItemDelegate::drawText(QPainter *painter,
QRect afterHighlightRect(rect);
afterHighlightRect.setLeft(resultHighlightRect.right());
+ afterHighlightRect.setRight(afterHighlightRect.left() + textAfterLengthPixels);
+
+ QRect containingFunctionRect(rect);
+ containingFunctionRect.setLeft(afterHighlightRect.right());
+ containingFunctionRect.setRight(afterHighlightRect.right() + containingFunctionLengthPixels);
// paint all highlight backgrounds
// qitemdelegate has problems with painting background when highlighted
@@ -249,7 +277,14 @@ void SearchResultTreeItemDelegate::drawText(QPainter *painter,
}
const QColor highlightBackground =
index.model()->data(index, ItemDataRoles::ResultHighlightBackgroundColor).value<QColor>();
- painter->fillRect(resultHighlightRect.adjusted(textMargin, 0, textMargin - 1, 0), QBrush(highlightBackground));
+ painter->fillRect(resultHighlightRect.adjusted(textMargin, 0, textMargin - 1, 0),
+ QBrush(highlightBackground));
+
+ // Background of containing function
+ const QColor funcHighlightBackground
+ = index.model()->data(index, ItemDataRoles::FunctionHighlightBackgroundColor).value<QColor>();
+ painter->fillRect(containingFunctionRect.adjusted(textMargin, 0, textMargin - 1, 0),
+ QBrush(funcHighlightBackground));
// Text before the highlighting
QStyleOptionViewItem noHighlightOpt = baseOption;
@@ -261,12 +296,19 @@ void SearchResultTreeItemDelegate::drawText(QPainter *painter,
// Highlight text
QStyleOptionViewItem highlightOpt = noHighlightOpt;
- const QColor highlightForeground =
- index.model()->data(index, ItemDataRoles::ResultHighlightForegroundColor).value<QColor>();
+ const QColor highlightForeground
+ = index.model()->data(index, ItemDataRoles::ResultHighlightForegroundColor).value<QColor>();
highlightOpt.palette.setColor(QPalette::Text, highlightForeground);
QItemDelegate::drawDisplay(painter, highlightOpt, resultHighlightRect, textHighlight);
// Text after the Highlight
noHighlightOpt.rect = afterHighlightRect;
QItemDelegate::drawDisplay(painter, noHighlightOpt, afterHighlightRect, textAfter);
+
+ // Containing function
+ const QColor funcHighlightForeground
+ = index.model()->data(index, ItemDataRoles::FunctionHighlightForegroundColor).value<QColor>();
+ highlightOpt.palette.setColor(QPalette::Text, funcHighlightForeground);
+ highlightOpt.rect = containingFunctionRect;
+ QItemDelegate::drawDisplay(painter, highlightOpt, containingFunctionRect, texts.second);
}
diff --git a/src/plugins/coreplugin/find/searchresulttreeitemroles.h b/src/plugins/coreplugin/find/searchresulttreeitemroles.h
index 987129be29a..bc248ff455e 100644
--- a/src/plugins/coreplugin/find/searchresulttreeitemroles.h
+++ b/src/plugins/coreplugin/find/searchresulttreeitemroles.h
@@ -31,16 +31,18 @@ namespace Core {
namespace Internal {
namespace ItemDataRoles {
-enum Roles
-{
+enum Roles {
ResultItemRole = Qt::UserRole,
ResultLineRole,
ResultBeginLineNumberRole,
ResultIconRole,
ResultHighlightBackgroundColor,
ResultHighlightForegroundColor,
+ FunctionHighlightBackgroundColor,
+ FunctionHighlightForegroundColor,
ResultBeginColumnNumberRole,
SearchTermLengthRole,
+ ContainingFunctionNameRole,
IsGeneratedRole
};
diff --git a/src/plugins/coreplugin/find/searchresulttreemodel.cpp b/src/plugins/coreplugin/find/searchresulttreemodel.cpp
index 71712c18fee..7522d701d0d 100644
--- a/src/plugins/coreplugin/find/searchresulttreemodel.cpp
+++ b/src/plugins/coreplugin/find/searchresulttreemodel.cpp
@@ -332,12 +332,21 @@ QVariant SearchResultTreeModel::data(const SearchResultTreeItem *row, int role)
case ItemDataRoles::ResultHighlightForegroundColor:
result = m_colors.value(row->item.style()).highlightForeground;
break;
+ case ItemDataRoles::FunctionHighlightBackgroundColor:
+ result = m_colors.value(row->item.style()).containingFunctionBackground;
+ break;
+ case ItemDataRoles::FunctionHighlightForegroundColor:
+ result = m_colors.value(row->item.style()).containingFunctionForeground;
+ break;
case ItemDataRoles::ResultBeginColumnNumberRole:
result = row->item.mainRange().begin.column;
break;
case ItemDataRoles::SearchTermLengthRole:
result = row->item.mainRange().length(row->item.lineText());
break;
+ case ItemDataRoles::ContainingFunctionNameRole:
+ result = row->item.containingFunctionName().value_or(QString{});
+ break;
case ItemDataRoles::IsGeneratedRole:
result = row->isGenerated();
break;
@@ -369,7 +378,7 @@ QSet<SearchResultTreeItem *> SearchResultTreeModel::addPath(const QStringList &p
QModelIndex currentItemIndex = QModelIndex();
SearchResultTreeItem *partItem = nullptr;
QStringList currentPath;
- foreach (const QString &part, path) {
+ for (const QString &part : path) {
const int insertionIndex = currentItem->insertionIndex(part, &partItem);
if (!partItem) {
SearchResultItem item;
@@ -403,12 +412,12 @@ void SearchResultTreeModel::addResultsToCurrentParent(const QList<SearchResultIt
if (mode == SearchResult::AddOrdered) {
// this is the mode for e.g. text search
beginInsertRows(m_currentIndex, m_currentParent->childrenCount(), m_currentParent->childrenCount() + items.count());
- foreach (const SearchResultItem &item, items) {
+ for (const SearchResultItem &item : items) {
m_currentParent->appendChild(item);
}
endInsertRows();
} else if (mode == SearchResult::AddSorted) {
- foreach (const SearchResultItem &item, items) {
+ for (const SearchResultItem &item : items) {
SearchResultTreeItem *existingItem;
const int insertionIndex = m_currentParent->insertionIndex(item, &existingItem);
if (existingItem) {
@@ -452,7 +461,7 @@ QList<QModelIndex> SearchResultTreeModel::addResults(const QList<SearchResultIte
QList<SearchResultItem> sortedItems = items;
std::stable_sort(sortedItems.begin(), sortedItems.end(), lessThanByPath);
QList<SearchResultItem> itemSet;
- foreach (const SearchResultItem &item, sortedItems) {
+ for (const SearchResultItem &item : sortedItems) {
m_editorFontIsUsed |= item.useTextEditorFont();
if (!m_currentParent || (m_currentPath != item.path())) {
// first add all the items from before
@@ -470,7 +479,7 @@ QList<QModelIndex> SearchResultTreeModel::addResults(const QList<SearchResultIte
itemSet.clear();
}
QList<QModelIndex> pathIndices;
- foreach (SearchResultTreeItem *item, pathNodes)
+ for (SearchResultTreeItem *item : qAsConst(pathNodes))
pathIndices << index(item);
return pathIndices;
}
diff --git a/src/plugins/coreplugin/find/searchresulttreeview.cpp b/src/plugins/coreplugin/find/searchresulttreeview.cpp
index 8c2b92116a0..e21902cf4de 100644
--- a/src/plugins/coreplugin/find/searchresulttreeview.cpp
+++ b/src/plugins/coreplugin/find/searchresulttreeview.cpp
@@ -94,9 +94,9 @@ void SearchResultTreeView::clear()
void SearchResultTreeView::addResults(const QList<SearchResultItem> &items, SearchResult::AddMode mode)
{
- QList<QModelIndex> addedParents = m_model->addResults(items, mode);
+ const QList<QModelIndex> addedParents = m_model->addResults(items, mode);
if (m_autoExpandResults && !addedParents.isEmpty()) {
- foreach (const QModelIndex &index, addedParents)
+ for (const QModelIndex &index : addedParents)
setExpanded(index, true);
}
}
diff --git a/src/plugins/coreplugin/find/searchresultwindow.cpp b/src/plugins/coreplugin/find/searchresultwindow.cpp
index 94739a2edba..3deaa653227 100644
--- a/src/plugins/coreplugin/find/searchresultwindow.cpp
+++ b/src/plugins/coreplugin/find/searchresultwindow.cpp
@@ -545,7 +545,7 @@ void SearchResultWindow::clearContents()
for (int i = d->m_recentSearchesBox->count() - 1; i > 0 /* don't want i==0 */; --i)
d->m_recentSearchesBox->removeItem(i);
}
- foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
+ for (Internal::SearchResultWidget *widget : qAsConst(d->m_searchResultWidgets))
widget->notifyVisibilityChanged(false);
qDeleteAll(d->m_searchResultWidgets);
d->m_searchResultWidgets.clear();
@@ -599,7 +599,7 @@ void SearchResultWindow::setTextEditorFont(const QFont &font, const SearchResult
{
d->m_font = font;
d->m_colors = colors;
- foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
+ for (Internal::SearchResultWidget *widget : qAsConst(d->m_searchResultWidgets))
widget->setTextEditorFont(font, colors);
}
@@ -609,7 +609,7 @@ void SearchResultWindow::setTextEditorFont(const QFont &font, const SearchResult
void SearchResultWindow::setTabWidth(int tabWidth)
{
d->m_tabWidth = tabWidth;
- foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
+ for (Internal::SearchResultWidget *widget : qAsConst(d->m_searchResultWidgets))
widget->setTabWidth(tabWidth);
}
/*!
diff --git a/src/plugins/coreplugin/foldernavigationwidget.cpp b/src/plugins/coreplugin/foldernavigationwidget.cpp
index 1c7d82a1452..428249e72ee 100644
--- a/src/plugins/coreplugin/foldernavigationwidget.cpp
+++ b/src/plugins/coreplugin/foldernavigationwidget.cpp
@@ -694,6 +694,7 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
const bool hasCurrentItem = current.isValid();
QAction *actionOpenFile = nullptr;
QAction *newFolder = nullptr;
+ QAction *removeFolder = nullptr;
const bool isDir = m_fileSystemModel->isDir(current);
const Utils::FilePath filePath = hasCurrentItem ? Utils::FilePath::fromString(
m_fileSystemModel->filePath(current))
@@ -719,6 +720,13 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
if (m_fileSystemModel->flags(current) & Qt::ItemIsEditable)
menu.addAction(Core::ActionManager::command(RENAMEFILE)->action());
newFolder = menu.addAction(tr("New Folder"));
+ if (isDir) {
+ QDirIterator it(filePath.toString(),
+ QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
+ // only allow removing folders that are empty
+ if (!it.hasNext())
+ removeFolder = menu.addAction(tr("Remove Folder"));
+ }
}
menu.addSeparator();
@@ -736,6 +744,8 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
createNewFolder(current);
else
createNewFolder(current.parent());
+ } else if (action == removeFolder) {
+ QDir().rmdir(filePath.toString());
} else if (action == collapseAllAction) {
m_listView->collapseAll();
}
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index 32de08b64ec..8b32c30b110 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -616,6 +616,8 @@ static QString compilerString()
#elif defined(Q_CC_MSVC)
if (_MSC_VER > 1999)
return QLatin1String("MSVC <unknown>");
+ if (_MSC_VER >= 1930)
+ return QLatin1String("MSVC 2022");
if (_MSC_VER >= 1920)
return QLatin1String("MSVC 2019");
if (_MSC_VER >= 1910)
@@ -645,9 +647,9 @@ QString ICore::versionString()
*/
QString ICore::buildCompatibilityString()
{
- return tr("Based on Qt %1 (%2, %3 bit)").arg(QLatin1String(qVersion()),
+ return tr("Based on Qt %1 (%2, %3)").arg(QLatin1String(qVersion()),
compilerString(),
- QString::number(QSysInfo::WordSize));
+ QSysInfo::buildCpuArchitecture());
}
/*!
diff --git a/src/plugins/coreplugin/idocument.cpp b/src/plugins/coreplugin/idocument.cpp
index 0ece562f4ba..114f9914d3f 100644
--- a/src/plugins/coreplugin/idocument.cpp
+++ b/src/plugins/coreplugin/idocument.cpp
@@ -27,12 +27,15 @@
#include <utils/fileutils.h>
#include <utils/infobar.h>
+#include <utils/minimizableinfobars.h>
#include <utils/optional.h>
#include <utils/qtcassert.h>
#include <QFile>
#include <QFileInfo>
+#include <memory>
+
/*!
\class Core::IDocument
\inheaderfile coreplugin/idocument.h
@@ -226,6 +229,7 @@ public:
QString uniqueDisplayName;
Utils::FilePath autoSavePath;
Utils::InfoBar *infoBar = nullptr;
+ std::unique_ptr<MinimizableInfoBars> minimizableInfoBars;
Id id;
optional<bool> fileIsReadOnly;
bool temporary = false;
@@ -678,6 +682,13 @@ Utils::InfoBar *IDocument::infoBar()
return d->infoBar;
}
+MinimizableInfoBars *IDocument::minimizableInfoBars()
+{
+ if (!d->minimizableInfoBars)
+ d->minimizableInfoBars.reset(new Utils::MinimizableInfoBars(*infoBar()));
+ return d->minimizableInfoBars.get();
+}
+
/*!
Sets the absolute \a filePath of the file that backs this document. The
default implementation sets the file name and sends the filePathChanged() and
diff --git a/src/plugins/coreplugin/idocument.h b/src/plugins/coreplugin/idocument.h
index 788e1b792b6..16d94fa7797 100644
--- a/src/plugins/coreplugin/idocument.h
+++ b/src/plugins/coreplugin/idocument.h
@@ -35,6 +35,7 @@
namespace Utils {
class FilePath;
class InfoBar;
+class MinimizableInfoBars;
} // namespace Utils
namespace Core {
@@ -133,6 +134,7 @@ public:
void setWriteWarning(bool has);
Utils::InfoBar *infoBar();
+ Utils::MinimizableInfoBars *minimizableInfoBars();
signals:
// For meta data changes: file name, modified state, ...
diff --git a/src/plugins/coreplugin/iwelcomepage.h b/src/plugins/coreplugin/iwelcomepage.h
index b95947ecb4b..4487e985588 100644
--- a/src/plugins/coreplugin/iwelcomepage.h
+++ b/src/plugins/coreplugin/iwelcomepage.h
@@ -28,7 +28,6 @@
#include "core_global.h"
#include <utils/id.h>
-#include <utils/porting.h>
#include <QWidget>
#include <QObject>
diff --git a/src/plugins/coreplugin/iwizardfactory.cpp b/src/plugins/coreplugin/iwizardfactory.cpp
index 60ec5c2b35d..ca83939d1c4 100644
--- a/src/plugins/coreplugin/iwizardfactory.cpp
+++ b/src/plugins/coreplugin/iwizardfactory.cpp
@@ -195,9 +195,9 @@ QList<IWizardFactory*> IWizardFactory::allWizardFactories()
s_areFactoriesLoaded = true;
QHash<Id, IWizardFactory *> sanityCheck;
- foreach (const FactoryCreator &fc, s_factoryCreators) {
- QList<IWizardFactory *> tmp = fc();
- foreach (IWizardFactory *newFactory, tmp) {
+ for (const FactoryCreator &fc : qAsConst(s_factoryCreators)) {
+ const QList<IWizardFactory *> tmp = fc();
+ for (IWizardFactory *newFactory : tmp) {
QTC_ASSERT(newFactory, continue);
IWizardFactory *existingFactory = sanityCheck.value(newFactory->id());
@@ -315,7 +315,8 @@ QSet<Id> IWizardFactory::supportedPlatforms() const
{
QSet<Id> platformIds;
- foreach (Id platform, allAvailablePlatforms()) {
+ const QSet<Id> platforms = allAvailablePlatforms();
+ for (const Id platform : platforms) {
if (isAvailable(platform))
platformIds.insert(platform);
}
@@ -331,7 +332,7 @@ void IWizardFactory::registerFactoryCreator(const IWizardFactory::FactoryCreator
QSet<Id> IWizardFactory::allAvailablePlatforms()
{
QSet<Id> platforms;
- foreach (const IFeatureProvider *featureManager, s_providerList)
+ for (const IFeatureProvider *featureManager : qAsConst(s_providerList))
platforms.unite(featureManager->availablePlatforms());
return platforms;
@@ -339,7 +340,7 @@ QSet<Id> IWizardFactory::allAvailablePlatforms()
QString IWizardFactory::displayNameForPlatform(Id i)
{
- foreach (const IFeatureProvider *featureManager, s_providerList) {
+ for (const IFeatureProvider *featureManager : qAsConst(s_providerList)) {
const QString displayName = featureManager->displayNameForPlatform(i);
if (!displayName.isEmpty())
return displayName;
@@ -384,7 +385,7 @@ void IWizardFactory::destroyFeatureProvider()
void IWizardFactory::clearWizardFactories()
{
- foreach (IWizardFactory *factory, s_allFactories)
+ for (IWizardFactory *factory : qAsConst(s_allFactories))
ActionManager::unregisterAction(factory->m_action, actionId(factory));
qDeleteAll(s_allFactories);
@@ -398,7 +399,8 @@ QSet<Id> IWizardFactory::pluginFeatures()
static QSet<Id> plugins;
if (plugins.isEmpty()) {
// Implicitly create a feature for each plugin loaded:
- foreach (ExtensionSystem::PluginSpec *s, ExtensionSystem::PluginManager::plugins()) {
+ const QVector<ExtensionSystem::PluginSpec *> pluginVector = ExtensionSystem::PluginManager::plugins();
+ for (const ExtensionSystem::PluginSpec *s : pluginVector) {
if (s->state() == ExtensionSystem::PluginSpec::Running)
plugins.insert(Id::fromString(s->name()));
}
@@ -410,7 +412,7 @@ QSet<Id> IWizardFactory::availableFeatures(Id platformId)
{
QSet<Id> availableFeatures;
- foreach (const IFeatureProvider *featureManager, s_providerList)
+ for (const IFeatureProvider *featureManager : qAsConst(s_providerList))
availableFeatures.unite(featureManager->availableFeatures(platformId));
return availableFeatures;
diff --git a/src/plugins/coreplugin/locator/executefilter.cpp b/src/plugins/coreplugin/locator/executefilter.cpp
index ba74db177cd..fe54059efc8 100644
--- a/src/plugins/coreplugin/locator/executefilter.cpp
+++ b/src/plugins/coreplugin/locator/executefilter.cpp
@@ -28,8 +28,10 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <utils/algorithm.h>
+#include <utils/environment.h>
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QJsonArray>
#include <QJsonObject>
@@ -130,16 +132,10 @@ void ExecuteFilter::accept(const LocatorFilterEntry &selection,
p->runHeadCommand();
}
-void ExecuteFilter::finished()
+void ExecuteFilter::done()
{
QTC_ASSERT(m_process, return);
- const QString commandName = headCommand();
- QString message;
- if (m_process->result() == QtcProcess::FinishedWithSuccess)
- message = tr("Command \"%1\" finished.").arg(commandName);
- else
- message = tr("Command \"%1\" failed.").arg(commandName);
- MessageManager::writeFlashing(message);
+ MessageManager::writeFlashing(m_process->exitMessage());
removeProcess();
runHeadCommand();
@@ -178,12 +174,6 @@ void ExecuteFilter::runHeadCommand()
m_process->setWorkingDirectory(d.workingDirectory);
m_process->setCommand(d.command);
m_process->start();
- if (!m_process->waitForStarted(1000)) {
- MessageManager::writeFlashing(
- tr("Could not start process: %1.").arg(m_process->errorString()));
- removeProcess();
- runHeadCommand();
- }
}
}
@@ -192,9 +182,9 @@ void ExecuteFilter::createProcess()
if (m_process)
return;
- m_process = new Utils::QtcProcess();
+ m_process = new Utils::QtcProcess;
m_process->setEnvironment(Utils::Environment::systemEnvironment());
- connect(m_process, &QtcProcess::finished, this, &ExecuteFilter::finished);
+ connect(m_process, &QtcProcess::done, this, &ExecuteFilter::done);
connect(m_process, &QtcProcess::readyReadStandardOutput, this, &ExecuteFilter::readStandardOutput);
connect(m_process, &QtcProcess::readyReadStandardError, this, &ExecuteFilter::readStandardError);
}
@@ -205,7 +195,7 @@ void ExecuteFilter::removeProcess()
return;
m_taskQueue.dequeue();
- delete m_process;
+ m_process->deleteLater();
m_process = nullptr;
}
diff --git a/src/plugins/coreplugin/locator/executefilter.h b/src/plugins/coreplugin/locator/executefilter.h
index 7742637cda4..7da5c086753 100644
--- a/src/plugins/coreplugin/locator/executefilter.h
+++ b/src/plugins/coreplugin/locator/executefilter.h
@@ -27,12 +27,14 @@
#include "ilocatorfilter.h"
-#include <utils/qtcprocess.h>
+#include <utils/commandline.h>
#include <QQueue>
#include <QStringList>
#include <QTextCodec>
+namespace Utils { class QtcProcess; }
+
namespace Core {
namespace Internal {
@@ -55,7 +57,7 @@ public:
QString *newText, int *selectionStart, int *selectionLength) const override;
private:
- void finished();
+ void done();
void readStandardOutput();
void readStandardError();
void runHeadCommand();
diff --git a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp
index 4c43a9832f8..3dde746a91e 100644
--- a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp
+++ b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp
@@ -90,11 +90,11 @@ SpotlightIterator::SpotlightIterator(const QStringList &command)
m_process->setCommand({Environment::systemEnvironment().searchInPath(command.first()),
command.mid(1)});
m_process->setEnvironment(Utils::Environment::systemEnvironment());
- QObject::connect(m_process.get(), &QtcProcess::finished, [this] { scheduleKillProcess(); });
- QObject::connect(m_process.get(), &QtcProcess::errorOccurred, [this, command] {
- MessageManager::writeFlashing(
- SpotlightLocatorFilter::tr("Locator: Error occurred when running \"%1\".")
- .arg(command.first()));
+ QObject::connect(m_process.get(), &QtcProcess::done, [this, cmd = command.first()] {
+ if (m_process->result() != ProcessResult::FinishedWithSuccess) {
+ MessageManager::writeFlashing(SpotlightLocatorFilter::tr(
+ "Locator: Error occurred when running \"%1\".").arg(cmd));
+ }
scheduleKillProcess();
});
QObject::connect(m_process.get(), &QtcProcess::readyReadStandardOutput, [this] {
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index 145244f7d85..65249726b04 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -56,13 +56,13 @@
#include <coreplugin/actionmanager/actionmanager_p.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/dialogs/externaltoolconfig.h>
-#include <coreplugin/iwizardfactory.h>
#include <coreplugin/dialogs/shortcutsettings.h>
#include <coreplugin/editormanager/documentmodel_p.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/editormanager_p.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/inavigationwidgetfactory.h>
+#include <coreplugin/iwizardfactory.h>
#include <coreplugin/progressmanager/progressmanager_p.h>
#include <coreplugin/progressmanager/progressview.h>
#include <coreplugin/settingsdatabase.h>
@@ -70,11 +70,13 @@
#include <utils/algorithm.h>
#include <utils/historycompleter.h>
#include <utils/hostosinfo.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
+#include <utils/proxyaction.h>
#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
#include <utils/stylehelper.h>
#include <utils/theme/theme.h>
-#include <utils/stringutils.h>
+#include <utils/touchbar/touchbar.h>
#include <utils/utilsicons.h>
#include <QActionGroup>
@@ -141,7 +143,8 @@ MainWindow::MainWindow()
// if the user has specified as base style in the theme settings,
// prefer that
const QStringList available = QStyleFactory::keys();
- foreach (const QString &s, Utils::creatorTheme()->preferredStyles()) {
+ const QStringList styles = Utils::creatorTheme()->preferredStyles();
+ for (const QString &s : styles) {
if (available.contains(s, Qt::CaseInsensitive)) {
baseName = s;
break;
@@ -370,7 +373,8 @@ void MainWindow::closeEvent(QCloseEvent *event)
return;
}
- foreach (const std::function<bool()> &listener, m_preCloseListeners) {
+ const QList<std::function<bool()>> listeners = m_preCloseListeners;
+ for (const std::function<bool()> &listener : listeners) {
if (!listener()) {
cancelClose();
return;
@@ -713,14 +717,14 @@ void MainWindow::registerDefaultActions()
connect(m_loggerAction, &QAction::triggered, this, [] { LoggingViewer::showLoggingView(); });
// Options Action
- mtools->appendGroup(Constants::G_TOOLS_OPTIONS);
- mtools->addSeparator(Constants::G_TOOLS_OPTIONS);
+ medit->appendGroup(Constants::G_EDIT_PREFERENCES);
+ medit->addSeparator(Constants::G_EDIT_PREFERENCES);
- m_optionsAction = new QAction(tr("&Options..."), this);
+ m_optionsAction = new QAction(tr("Pr&eferences..."), this);
m_optionsAction->setMenuRole(QAction::PreferencesRole);
cmd = ActionManager::registerAction(m_optionsAction, Constants::OPTIONS);
cmd->setDefaultKeySequence(QKeySequence::Preferences);
- mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
+ medit->addAction(cmd, Constants::G_EDIT_PREFERENCES);
connect(m_optionsAction, &QAction::triggered, this, [] { ICore::showOptionsDialog(Id()); });
mwindow->addSeparator(Constants::G_WINDOW_LIST);
@@ -1089,7 +1093,7 @@ void MainWindow::updateContextObject(const QList<IContext *> &context)
updateContext();
if (debugMainWindow) {
qDebug() << "new context objects =" << context;
- foreach (IContext *c, context)
+ for (const IContext *c : context)
qDebug() << (c ? c->widget() : nullptr) << (c ? c->widget()->metaObject()->className() : nullptr);
}
}
@@ -1210,7 +1214,7 @@ void MainWindow::updateModeSelectorStyleMenu()
void MainWindow::updateAdditionalContexts(const Context &remove, const Context &add,
ICore::ContextPriority priority)
{
- foreach (const Id id, remove) {
+ for (const Id id : remove) {
if (!id.isValid())
continue;
int index = m_lowPrioAdditionalContexts.indexOf(id);
@@ -1221,7 +1225,7 @@ void MainWindow::updateAdditionalContexts(const Context &remove, const Context &
m_highPrioAdditionalContexts.removeAt(index);
}
- foreach (const Id id, add) {
+ for (const Id id : add) {
if (!id.isValid())
continue;
Context &cref = (priority == ICore::ContextPriority::High ? m_highPrioAdditionalContexts
@@ -1237,7 +1241,7 @@ void MainWindow::updateContext()
{
Context contexts = m_highPrioAdditionalContexts;
- foreach (IContext *context, m_activeContext)
+ for (IContext *context : qAsConst(m_activeContext))
contexts.add(context->context());
contexts.add(m_lowPrioAdditionalContexts);
diff --git a/src/plugins/coreplugin/mimetypemagicdialog.cpp b/src/plugins/coreplugin/mimetypemagicdialog.cpp
index 18bd8516732..633977638f1 100644
--- a/src/plugins/coreplugin/mimetypemagicdialog.cpp
+++ b/src/plugins/coreplugin/mimetypemagicdialog.cpp
@@ -37,11 +37,11 @@
using namespace Core;
using namespace Internal;
-static Utils::Internal::MimeMagicRule::Type typeValue(int i)
+static Utils::MimeMagicRule::Type typeValue(int i)
{
- QTC_ASSERT(i < Utils::Internal::MimeMagicRule::Byte,
- return Utils::Internal::MimeMagicRule::Invalid);
- return Utils::Internal::MimeMagicRule::Type(i + 1/*0==invalid*/);
+ QTC_ASSERT(i < Utils::MimeMagicRule::Byte,
+ return Utils::MimeMagicRule::Invalid);
+ return Utils::MimeMagicRule::Type(i + 1/*0==invalid*/);
}
MimeTypeMagicDialog::MimeTypeMagicDialog(QWidget *parent) :
@@ -96,7 +96,7 @@ void MimeTypeMagicDialog::applyRecommended(bool checked)
void MimeTypeMagicDialog::validateAccept()
{
QString errorMessage;
- Utils::Internal::MimeMagicRule rule = createRule(&errorMessage);
+ Utils::MimeMagicRule rule = createRule(&errorMessage);
if (rule.isValid())
accept();
else
@@ -130,12 +130,12 @@ bool MagicData::operator==(const MagicData &other) const
Returns the mask, or an empty string if the mask is the default mask which is set by
MimeMagicRule when setting an empty mask for string patterns.
*/
-QByteArray MagicData::normalizedMask(const Utils::Internal::MimeMagicRule &rule)
+QByteArray MagicData::normalizedMask(const Utils::MimeMagicRule &rule)
{
// convert mask and see if it is the "default" one (which corresponds to "empty" mask)
// see MimeMagicRule constructor
QByteArray mask = rule.mask();
- if (rule.type() == Utils::Internal::MimeMagicRule::String) {
+ if (rule.type() == Utils::MimeMagicRule::String) {
QByteArray actualMask = QByteArray::fromHex(QByteArray::fromRawData(mask.constData() + 2,
mask.size() - 2));
if (actualMask.count(char(-1)) == actualMask.size()) {
@@ -146,16 +146,16 @@ QByteArray MagicData::normalizedMask(const Utils::Internal::MimeMagicRule &rule)
return mask;
}
-Utils::Internal::MimeMagicRule MimeTypeMagicDialog::createRule(QString *errorMessage) const
+Utils::MimeMagicRule MimeTypeMagicDialog::createRule(QString *errorMessage) const
{
- Utils::Internal::MimeMagicRule::Type type = typeValue(ui.typeSelector->currentIndex());
- Utils::Internal::MimeMagicRule rule(type,
+ Utils::MimeMagicRule::Type type = typeValue(ui.typeSelector->currentIndex());
+ Utils::MimeMagicRule rule(type,
ui.valueLineEdit->text().toUtf8(),
ui.startRangeSpinBox->value(),
ui.endRangeSpinBox->value(),
ui.maskLineEdit->text().toLatin1(),
errorMessage);
- if (type == Utils::Internal::MimeMagicRule::Invalid) {
+ if (type == Utils::MimeMagicRule::Invalid) {
if (errorMessage)
*errorMessage = tr("Internal error: Type is invalid");
}
diff --git a/src/plugins/coreplugin/mimetypemagicdialog.h b/src/plugins/coreplugin/mimetypemagicdialog.h
index 9480369e2eb..06868ff1d82 100644
--- a/src/plugins/coreplugin/mimetypemagicdialog.h
+++ b/src/plugins/coreplugin/mimetypemagicdialog.h
@@ -27,7 +27,7 @@
#include "ui_mimetypemagicdialog.h"
-#include <utils/mimetypes/mimemagicrule_p.h>
+#include <utils/mimeutils.h>
namespace Core {
namespace Internal {
@@ -36,11 +36,11 @@ class MagicData
{
public:
MagicData()
- : m_rule(Utils::Internal::MimeMagicRule::String, QByteArray(" "), 0, 0)
+ : m_rule(Utils::MimeMagicRule::String, QByteArray(" "), 0, 0)
{
}
- MagicData(Utils::Internal::MimeMagicRule rule, int priority)
+ MagicData(Utils::MimeMagicRule rule, int priority)
: m_rule(rule)
, m_priority(priority)
{
@@ -49,9 +49,9 @@ public:
bool operator==(const MagicData &other) const;
bool operator!=(const MagicData &other) { return !(*this == other); }
- static QByteArray normalizedMask(const Utils::Internal::MimeMagicRule &rule);
+ static QByteArray normalizedMask(const Utils::MimeMagicRule &rule);
- Utils::Internal::MimeMagicRule m_rule;
+ Utils::MimeMagicRule m_rule;
int m_priority = 0;
};
@@ -68,7 +68,7 @@ private:
void setToRecommendedValues();
void applyRecommended(bool checked);
void validateAccept();
- Utils::Internal::MimeMagicRule createRule(QString *errorMessage = nullptr) const;
+ Utils::MimeMagicRule createRule(QString *errorMessage = nullptr) const;
Ui::MimeTypeMagicDialog ui;
int m_customRangeStart = 0;
diff --git a/src/plugins/coreplugin/mimetypesettings.cpp b/src/plugins/coreplugin/mimetypesettings.cpp
index d8f3b9ca64d..05da64dbca0 100644
--- a/src/plugins/coreplugin/mimetypesettings.cpp
+++ b/src/plugins/coreplugin/mimetypesettings.cpp
@@ -35,7 +35,7 @@
#include <utils/algorithm.h>
#include <utils/headerviewstretcher.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
@@ -52,6 +52,8 @@
#include <QStringList>
#include <QStyledItemDelegate>
#include <QSortFilterProxyModel>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
static const char kModifiedMimeTypesFile[] = "mimetypes/modifiedmimetypes.xml";
@@ -87,7 +89,7 @@ public:
bool isValid() const { return !name.isEmpty(); }
QString name;
QStringList globPatterns;
- QMap<int, QList<Utils::Internal::MimeMagicRule> > rules;
+ QMap<int, QList<Utils::MimeMagicRule> > rules;
};
// MimeTypeSettingsModel
@@ -346,12 +348,12 @@ void MimeTypeSettingsPrivate::syncData(const QModelIndex &current,
modifiedType.isValid() ? modifiedType.globPatterns.join(kSemiColon)
: currentMimeType.globPatterns().join(kSemiColon));
- QMap<int, QList<Utils::Internal::MimeMagicRule> > rules =
+ QMap<int, QList<Utils::MimeMagicRule> > rules =
modifiedType.isValid() ? modifiedType.rules
: Utils::magicRulesForMimeType(currentMimeType);
for (auto it = rules.constBegin(); it != rules.constEnd(); ++it) {
int priority = it.key();
- foreach (const Utils::Internal::MimeMagicRule &rule, it.value()) {
+ for (const Utils::MimeMagicRule &rule : it.value()) {
addMagicHeaderRow(MagicData(rule, priority));
}
}
@@ -394,7 +396,7 @@ void MimeTypeSettingsPrivate::editMagicHeaderRowData(const int row, const MagicD
{
auto item = new QTreeWidgetItem;
item->setText(0, QString::fromUtf8(data.m_rule.value()));
- item->setText(1, QString::fromLatin1(Utils::Internal::MimeMagicRule::typeName(data.m_rule.type())));
+ item->setText(1, QString::fromLatin1(Utils::MimeMagicRule::typeName(data.m_rule.type())));
item->setText(2, QString::fromLatin1("%1:%2").arg(data.m_rule.startPos()).arg(data.m_rule.endPos()));
item->setText(3, QString::number(data.m_priority));
item->setData(0, Qt::UserRole, QVariant::fromValue(data));
@@ -515,19 +517,19 @@ void MimeTypeSettingsPrivate::writeUserModifiedMimeTypes()
writer.writeStartDocument();
writer.writeStartElement(QLatin1String(mimeInfoTagC));
- foreach (const UserMimeType &mt, m_userModifiedMimeTypes) {
+ for (const UserMimeType &mt : qAsConst(m_userModifiedMimeTypes)) {
writer.writeStartElement(QLatin1String(mimeTypeTagC));
writer.writeAttribute(QLatin1String(mimeTypeAttributeC), mt.name);
writer.writeAttribute(QLatin1String(patternAttributeC),
mt.globPatterns.join(kSemiColon));
for (auto prioIt = mt.rules.constBegin(); prioIt != mt.rules.constEnd(); ++prioIt) {
const QString priorityString = QString::number(prioIt.key());
- foreach (const Utils::Internal::MimeMagicRule &rule, prioIt.value()) {
+ for (const Utils::MimeMagicRule &rule : prioIt.value()) {
writer.writeStartElement(QLatin1String(matchTagC));
writer.writeAttribute(QLatin1String(matchValueAttributeC),
QString::fromUtf8(rule.value()));
writer.writeAttribute(QLatin1String(matchTypeAttributeC),
- QString::fromUtf8(Utils::Internal::MimeMagicRule::typeName(rule.type())));
+ QString::fromUtf8(Utils::MimeMagicRule::typeName(rule.type())));
writer.writeAttribute(QLatin1String(matchOffsetAttributeC),
QString::fromLatin1("%1:%2").arg(rule.startPos())
.arg(rule.endPos()));
@@ -585,7 +587,7 @@ MimeTypeSettingsPrivate::UserMimeTypeHash MimeTypeSettingsPrivate::readUserModif
int priority = atts.value(QLatin1String(priorityAttributeC)).toString().toInt();
QByteArray mask = atts.value(QLatin1String(matchMaskAttributeC)).toLatin1();
QString errorMessage;
- Utils::Internal::MimeMagicRule rule(Utils::Internal::MimeMagicRule::type(typeName),
+ Utils::MimeMagicRule rule(Utils::MimeMagicRule::type(typeName),
value, range.first, range.second, mask,
&errorMessage);
if (rule.isValid()) {
diff --git a/src/plugins/coreplugin/modemanager.cpp b/src/plugins/coreplugin/modemanager.cpp
index 4a7e3cf3695..eaaa3d3e339 100644
--- a/src/plugins/coreplugin/modemanager.cpp
+++ b/src/plugins/coreplugin/modemanager.cpp
@@ -301,7 +301,7 @@ void ModeManager::addAction(QAction *action, int priority)
// Count the number of commands with a higher priority
int index = 0;
- foreach (int p, d->m_actions) {
+ for (int p : qAsConst(d->m_actions)) {
if (p > priority)
++index;
}
diff --git a/src/plugins/coreplugin/navigationsubwidget.cpp b/src/plugins/coreplugin/navigationsubwidget.cpp
index fd516d4306c..c2f2b406925 100644
--- a/src/plugins/coreplugin/navigationsubwidget.cpp
+++ b/src/plugins/coreplugin/navigationsubwidget.cpp
@@ -113,7 +113,7 @@ void NavigationSubWidget::comboBoxIndexChanged(int factoryIndex)
saveSettings();
// Remove toolbutton
- foreach (QWidget *w, m_additionalToolBarWidgets)
+ for (QWidget *w : qAsConst(m_additionalToolBarWidgets))
delete w;
m_additionalToolBarWidgets.clear();
@@ -134,9 +134,8 @@ void NavigationSubWidget::comboBoxIndexChanged(int factoryIndex)
// Add Toolbutton
m_additionalToolBarWidgets = n.dockToolBarWidgets;
auto layout = qobject_cast<QHBoxLayout *>(m_toolBar->layout());
- foreach (QToolButton *w, m_additionalToolBarWidgets) {
+ for (QToolButton *w : qAsConst(m_additionalToolBarWidgets))
layout->insertWidget(layout->count()-2, w);
- }
restoreSettings();
emit factoryIndexChanged(factoryIndex);
diff --git a/src/plugins/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp
index fbc9d5ad6a1..018d300a597 100644
--- a/src/plugins/coreplugin/navigationwidget.cpp
+++ b/src/plugins/coreplugin/navigationwidget.cpp
@@ -244,7 +244,7 @@ QWidget *NavigationWidget::activateSubWidget(Id factoryId, Side fallbackSide)
void NavigationWidget::setFactories(const QList<INavigationWidgetFactory *> &factories)
{
Context navicontext(Constants::C_NAVIGATION_PANE);
- foreach (INavigationWidgetFactory *factory, factories) {
+ for (INavigationWidgetFactory *factory : qAsConst(factories)) {
const Id id = factory->id();
const Id actionId = id.withPrefix("QtCreator.Sidebar.");
@@ -349,7 +349,7 @@ Internal::NavigationSubWidget *NavigationWidget::insertSubItem(int position, int
QWidget *NavigationWidget::activateSubWidget(Id factoryId, int preferredPosition)
{
setShown(true);
- foreach (Internal::NavigationSubWidget *subWidget, d->m_subWidgets) {
+ for (Internal::NavigationSubWidget *subWidget : qAsConst(d->m_subWidgets)) {
if (subWidget->factory()->id() == factoryId) {
subWidget->setFocusWidget();
ICore::raiseWindow(this);
@@ -457,7 +457,7 @@ void NavigationWidget::restoreSettings(QSettings *settings)
}
int position = 0;
- foreach (const QString &id, viewIds) {
+ for (const QString &id : qAsConst(viewIds)) {
int index = factoryIndex(Id::fromString(id));
if (index >= 0) {
// Only add if the id was actually found!
@@ -509,7 +509,7 @@ void NavigationWidget::restoreSettings(QSettings *settings)
void NavigationWidget::closeSubWidgets()
{
- foreach (Internal::NavigationSubWidget *subWidget, d->m_subWidgets) {
+ for (Internal::NavigationSubWidget *subWidget : qAsConst(d->m_subWidgets)) {
subWidget->saveSettings();
delete subWidget;
}
diff --git a/src/plugins/coreplugin/outputpane.cpp b/src/plugins/coreplugin/outputpane.cpp
index 481f341bfd8..477bb513ed0 100644
--- a/src/plugins/coreplugin/outputpane.cpp
+++ b/src/plugins/coreplugin/outputpane.cpp
@@ -126,7 +126,7 @@ void OutputPanePlaceHolder::setMaximized(bool maximize)
if (maximize) {
d->m_nonMaximizedSize = sizes[idx];
int sum = 0;
- foreach (int s, sizes)
+ for (const int s : qAsConst(sizes))
sum += s;
for (int i = 0; i < sizes.count(); ++i) {
sizes[i] = 32;
diff --git a/src/plugins/coreplugin/outputpanemanager.cpp b/src/plugins/coreplugin/outputpanemanager.cpp
index 6ae58c88b28..a7a209f3277 100644
--- a/src/plugins/coreplugin/outputpanemanager.cpp
+++ b/src/plugins/coreplugin/outputpanemanager.cpp
@@ -303,10 +303,10 @@ void OutputPaneManager::updateMaximizeButton(bool maximized)
{
if (maximized) {
m_instance->m_minMaxAction->setIcon(m_instance->m_minimizeIcon);
- m_instance->m_minMaxAction->setText(tr("Minimize Output Pane"));
+ m_instance->m_minMaxAction->setText(tr("Minimize"));
} else {
m_instance->m_minMaxAction->setIcon(m_instance->m_maximizeIcon);
- m_instance->m_minMaxAction->setText(tr("Maximize Output Pane"));
+ m_instance->m_minMaxAction->setText(tr("Maximize"));
}
}
@@ -352,7 +352,7 @@ OutputPaneManager::OutputPaneManager(QWidget *parent) :
m_minMaxAction = new QAction(this);
m_minMaxAction->setIcon(m_maximizeIcon);
- m_minMaxAction->setText(tr("Maximize Output Pane"));
+ m_minMaxAction->setText(tr("Maximize"));
m_closeButton->setIcon(Icons::CLOSE_SPLIT_BOTTOM.icon());
connect(m_closeButton, &QAbstractButton::clicked, this, &OutputPaneManager::slotHide);
@@ -396,7 +396,7 @@ OutputPaneManager::OutputPaneManager(QWidget *parent) :
// Window->Output Panes
ActionContainer *mpanes = ActionManager::createMenu(Constants::M_VIEW_PANES);
mview->addMenu(mpanes, Constants::G_VIEW_PANES);
- mpanes->menu()->setTitle(tr("Output &Panes"));
+ mpanes->menu()->setTitle(tr("Out&put"));
mpanes->appendGroup("Coreplugin.OutputPane.ActionsGroup");
mpanes->appendGroup("Coreplugin.OutputPane.PanesGroup");
@@ -473,7 +473,8 @@ void OutputPaneManager::initialize()
auto toolButtonsLayout = new QHBoxLayout;
toolButtonsLayout->setContentsMargins(0, 0, 0, 0);
toolButtonsLayout->setSpacing(0);
- foreach (QWidget *toolButton, outPane->toolBarWidgets())
+ const QList<QWidget *> toolBarWidgets = outPane->toolBarWidgets();
+ for (QWidget *toolButton : toolBarWidgets)
toolButtonsLayout->addWidget(toolButton);
toolButtonsLayout->addStretch(5);
toolButtonsContainer->setLayout(toolButtonsLayout);
diff --git a/src/plugins/coreplugin/patchtool.cpp b/src/plugins/coreplugin/patchtool.cpp
index f49185ea0ef..d26fcba6c08 100644
--- a/src/plugins/coreplugin/patchtool.cpp
+++ b/src/plugins/coreplugin/patchtool.cpp
@@ -112,7 +112,8 @@ static bool runPatchHelper(const QByteArray &input, const FilePath &workingDirec
QByteArray stdOut;
QByteArray stdErr;
if (!patchProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
- patchProcess.stopProcess();
+ patchProcess.stop();
+ patchProcess.waitForFinished();
MessageManager::writeFlashing(
QApplication::translate("Core::PatchTool", "A timeout occurred running \"%1\"")
.arg(patch.toUserOutput()));
diff --git a/src/plugins/coreplugin/plugininstallwizard.cpp b/src/plugins/coreplugin/plugininstallwizard.cpp
index af091b29ec2..c6cd1bbba43 100644
--- a/src/plugins/coreplugin/plugininstallwizard.cpp
+++ b/src/plugins/coreplugin/plugininstallwizard.cpp
@@ -207,60 +207,66 @@ public:
m_cancelButton->setVisible(true);
m_output->clear();
- m_archive = Archive::unarchive(m_data->sourcePath, m_tempDir->path());
-
- if (!m_archive) {
+ m_archive.reset(new Archive(m_data->sourcePath, m_tempDir->path()));
+ if (!m_archive->isValid()) {
m_label->setType(InfoLabel::Error);
m_label->setText(PluginInstallWizard::tr("The file is not an archive."));
-
return;
}
- QObject::connect(m_archive, &Archive::outputReceived, this, [this](const QString &output) {
+ QObject::connect(m_archive.get(), &Archive::outputReceived, this,
+ [this](const QString &output) {
m_output->append(output);
});
- QObject::connect(m_archive, &Archive::finished, this, [this](bool success) {
- m_archive = nullptr; // we don't own it
- m_cancelButton->disconnect();
- if (!success) { // unarchiving failed
+ QObject::connect(m_archive.get(), &Archive::finished, this, [this](bool success) {
+ m_archive.release()->deleteLater();
+ handleFinished(success);
+ });
+ QObject::connect(m_cancelButton, &QPushButton::clicked, this, [this] {
+ m_canceled = true;
+ m_archive.reset();
+ handleFinished(false);
+ });
+ m_archive->unarchive();
+ }
+
+ void handleFinished(bool success)
+ {
+ m_cancelButton->disconnect();
+ if (!success) { // unarchiving failed
+ m_cancelButton->setVisible(false);
+ if (m_canceled) {
+ m_label->setType(InfoLabel::Information);
+ m_label->setText(PluginInstallWizard::tr("Canceled."));
+ } else {
+ m_label->setType(InfoLabel::Error);
+ m_label->setText(
+ PluginInstallWizard::tr("There was an error while unarchiving."));
+ }
+ } else { // unarchiving was successful, run a check
+ m_archiveCheck = Utils::runAsync(
+ [this](QFutureInterface<ArchiveIssue> &fi) { return checkContents(fi); });
+ Utils::onFinished(m_archiveCheck, this, [this](const QFuture<ArchiveIssue> &f) {
m_cancelButton->setVisible(false);
- if (m_canceled) {
+ m_cancelButton->disconnect();
+ const bool ok = f.resultCount() == 0 && !f.isCanceled();
+ if (f.isCanceled()) {
m_label->setType(InfoLabel::Information);
m_label->setText(PluginInstallWizard::tr("Canceled."));
+ } else if (ok) {
+ m_label->setType(InfoLabel::Ok);
+ m_label->setText(PluginInstallWizard::tr("Archive is OK."));
} else {
- m_label->setType(InfoLabel::Error);
- m_label->setText(
- PluginInstallWizard::tr("There was an error while unarchiving."));
+ const ArchiveIssue issue = f.result();
+ m_label->setType(issue.type);
+ m_label->setText(issue.message);
}
- } else { // unarchiving was successful, run a check
- m_archiveCheck = Utils::runAsync(
- [this](QFutureInterface<ArchiveIssue> &fi) { return checkContents(fi); });
- Utils::onFinished(m_archiveCheck, this, [this](const QFuture<ArchiveIssue> &f) {
- m_cancelButton->setVisible(false);
- m_cancelButton->disconnect();
- const bool ok = f.resultCount() == 0 && !f.isCanceled();
- if (f.isCanceled()) {
- m_label->setType(InfoLabel::Information);
- m_label->setText(PluginInstallWizard::tr("Canceled."));
- } else if (ok) {
- m_label->setType(InfoLabel::Ok);
- m_label->setText(PluginInstallWizard::tr("Archive is OK."));
- } else {
- const ArchiveIssue issue = f.result();
- m_label->setType(issue.type);
- m_label->setText(issue.message);
- }
- m_isComplete = ok;
- emit completeChanged();
- });
- QObject::connect(m_cancelButton, &QPushButton::clicked, this, [this] {
- m_archiveCheck.cancel();
- });
- }
- });
- QObject::connect(m_cancelButton, &QPushButton::clicked, m_archive, [this] {
- m_canceled = true;
- m_archive->cancel();
- });
+ m_isComplete = ok;
+ emit completeChanged();
+ });
+ QObject::connect(m_cancelButton, &QPushButton::clicked, this, [this] {
+ m_archiveCheck.cancel();
+ });
+ }
}
// Async. Result is set if any issue was found.
@@ -311,11 +317,7 @@ public:
{
// back button pressed
m_cancelButton->disconnect();
- if (m_archive) {
- m_archive->disconnect();
- m_archive->cancel();
- m_archive = nullptr; // we don't own it
- }
+ m_archive.reset();
if (m_archiveCheck.isRunning()) {
m_archiveCheck.cancel();
m_archiveCheck.waitForFinished();
@@ -326,7 +328,7 @@ public:
bool isComplete() const final { return m_isComplete; }
std::unique_ptr<TemporaryDirectory> m_tempDir;
- Archive *m_archive = nullptr;
+ std::unique_ptr<Archive> m_archive;
QFuture<ArchiveIssue> m_archiveCheck;
InfoLabel *m_label = nullptr;
QPushButton *m_cancelButton = nullptr;
diff --git a/src/plugins/coreplugin/progressmanager/progressmanager.cpp b/src/plugins/coreplugin/progressmanager/progressmanager.cpp
index 482ccde7f05..cac1b2bc427 100644
--- a/src/plugins/coreplugin/progressmanager/progressmanager.cpp
+++ b/src/plugins/coreplugin/progressmanager/progressmanager.cpp
@@ -226,6 +226,27 @@ using namespace Utils;
static ProgressManagerPrivate *m_instance = nullptr;
+const int RASTER = 20;
+
+class StatusDetailsWidgetContainer : public QWidget
+{
+public:
+ StatusDetailsWidgetContainer(QWidget *parent)
+ : QWidget(parent)
+ {}
+
+ QSize sizeHint() const override
+ {
+ // make size fit on raster, to avoid flickering in status bar
+ // because the output pane buttons resize, if the widget changes a lot (like it is the case for
+ // the language server indexing)
+ const QSize preferredSize = layout()->sizeHint();
+ const int preferredWidth = preferredSize.width();
+ const int width = preferredWidth + (RASTER - preferredWidth % RASTER);
+ return {width, preferredSize.height()};
+ }
+};
+
ProgressManagerPrivate::ProgressManagerPrivate()
: m_opacityEffect(new QGraphicsOpacityEffect(this))
{
@@ -273,13 +294,13 @@ void ProgressManagerPrivate::init()
summaryProgressLayout->setContentsMargins(0, 0, 0, 2);
summaryProgressLayout->setSpacing(0);
m_summaryProgressWidget->setLayout(summaryProgressLayout);
- m_statusDetailsWidgetContainer = new QWidget(m_summaryProgressWidget);
- m_statusDetailsWidgetLayout = new QHBoxLayout(m_statusDetailsWidgetContainer);
+ auto statusDetailsWidgetContainer = new StatusDetailsWidgetContainer(m_summaryProgressWidget);
+ m_statusDetailsWidgetLayout = new QHBoxLayout(statusDetailsWidgetContainer);
m_statusDetailsWidgetLayout->setContentsMargins(0, 0, 0, 0);
m_statusDetailsWidgetLayout->setSpacing(0);
m_statusDetailsWidgetLayout->addStretch(1);
- m_statusDetailsWidgetContainer->setLayout(m_statusDetailsWidgetLayout);
- summaryProgressLayout->addWidget(m_statusDetailsWidgetContainer);
+ statusDetailsWidgetContainer->setLayout(m_statusDetailsWidgetLayout);
+ summaryProgressLayout->addWidget(statusDetailsWidgetContainer);
m_summaryProgressBar = new ProgressBar(m_summaryProgressWidget);
m_summaryProgressBar->setMinimumWidth(70);
m_summaryProgressBar->setTitleVisible(false);
@@ -510,7 +531,7 @@ void ProgressManagerPrivate::stopFadeOfSummaryProgress()
bool ProgressManagerPrivate::hasError() const
{
- foreach (FutureProgress *progress, m_taskList)
+ for (const FutureProgress *progress : qAsConst(m_taskList))
if (progress->hasError())
return true;
return false;
@@ -520,7 +541,7 @@ bool ProgressManagerPrivate::isLastFading() const
{
if (m_taskList.isEmpty())
return false;
- foreach (FutureProgress *progress, m_taskList) {
+ for (const FutureProgress *progress : qAsConst(m_taskList)) {
if (!progress->isFading()) // we still have progress bars that are not fading
return false;
}
@@ -571,7 +592,7 @@ void ProgressManagerPrivate::removeOneOldTask()
Id type = (*i)->type();
int taskCount = 0;
- foreach (FutureProgress *p, m_taskList)
+ for (const FutureProgress *p : qAsConst(m_taskList))
if (p->type() == type)
++taskCount;
@@ -616,8 +637,6 @@ void ProgressManagerPrivate::updateVisibilityWithDelay()
QTimer::singleShot(150, this, &ProgressManagerPrivate::updateVisibility);
}
-const int RASTER = 20;
-
void ProgressManagerPrivate::updateStatusDetailsWidget()
{
QWidget *candidateWidget = nullptr;
@@ -645,15 +664,6 @@ void ProgressManagerPrivate::updateStatusDetailsWidget()
}
}
- // make size fit on raster, to avoid flickering in status bar
- // because the output pane buttons resize, if the widget changes a lot (like it is the case for
- // the language server indexing)
- if (candidateWidget) {
- const int preferredWidth = candidateWidget->sizeHint().width();
- const int width = preferredWidth + (RASTER - preferredWidth % RASTER);
- m_statusDetailsWidgetContainer->setFixedWidth(width);
- }
-
if (candidateWidget == m_currentStatusDetailsWidget)
return;
diff --git a/src/plugins/coreplugin/progressmanager/progressmanager_p.h b/src/plugins/coreplugin/progressmanager/progressmanager_p.h
index edd933fa2cb..b28ad4f711d 100644
--- a/src/plugins/coreplugin/progressmanager/progressmanager_p.h
+++ b/src/plugins/coreplugin/progressmanager/progressmanager_p.h
@@ -101,7 +101,6 @@ private:
StatusBarWidget *m_statusBarWidgetContainer;
QWidget *m_statusBarWidget;
QWidget *m_summaryProgressWidget;
- QWidget *m_statusDetailsWidgetContainer = nullptr;
QHBoxLayout *m_statusDetailsWidgetLayout = nullptr;
QWidget *m_currentStatusDetailsWidget = nullptr;
QPointer<FutureProgress> m_currentStatusDetailsProgress;
diff --git a/src/plugins/coreplugin/settingsdatabase.cpp b/src/plugins/coreplugin/settingsdatabase.cpp
index a7e9a1ca167..db6977d5b8b 100644
--- a/src/plugins/coreplugin/settingsdatabase.cpp
+++ b/src/plugins/coreplugin/settingsdatabase.cpp
@@ -217,7 +217,8 @@ void SettingsDatabase::remove(const QString &key)
const QString effectiveKey = d->effectiveKey(key);
// Remove keys from the cache
- foreach (const QString &k, d->m_settings.keys()) {
+ const QStringList keys = d->m_settings.keys();
+ for (const QString &k : keys) {
// Either it's an exact match, or it matches up to a /
if (k.startsWith(effectiveKey)
&& (k.length() == effectiveKey.length()
diff --git a/src/plugins/coreplugin/sidebar.cpp b/src/plugins/coreplugin/sidebar.cpp
index 4accc99cd98..f8334dfda85 100644
--- a/src/plugins/coreplugin/sidebar.cpp
+++ b/src/plugins/coreplugin/sidebar.cpp
@@ -85,13 +85,13 @@ SideBar::SideBar(QList<SideBarItem*> itemList,
d(new SideBarPrivate)
{
setOrientation(Qt::Vertical);
- foreach (SideBarItem *item, itemList) {
+ for (SideBarItem *item : qAsConst(itemList)) {
d->m_itemMap.insert(item->id(), item);
d->m_availableItemIds.append(item->id());
d->m_availableItemTitles.append(item->title());
}
- foreach (SideBarItem *item, defaultVisible) {
+ for (SideBarItem *item : qAsConst(defaultVisible)) {
if (!itemList.contains(item))
continue;
d->m_defaultVisible.append(item->id());
@@ -100,7 +100,7 @@ SideBar::SideBar(QList<SideBarItem*> itemList,
SideBar::~SideBar()
{
- foreach (const QPointer<SideBarItem> &i, d->m_itemMap)
+ for (const QPointer<SideBarItem> &i : qAsConst(d->m_itemMap))
if (!i.isNull())
delete i.data();
delete d;
@@ -160,14 +160,14 @@ void SideBar::makeItemAvailable(SideBarItem *item)
void SideBar::setUnavailableItemIds(const QStringList &itemIds)
{
// re-enable previous items
- foreach (const QString &id, d->m_unavailableItemIds) {
+ for (const QString &id : qAsConst(d->m_unavailableItemIds)) {
d->m_availableItemIds.append(id);
d->m_availableItemTitles.append(d->m_itemMap.value(id).data()->title());
}
d->m_unavailableItemIds.clear();
- foreach (const QString &id, itemIds) {
+ for (const QString &id : itemIds) {
if (!d->m_unavailableItemIds.contains(id))
d->m_unavailableItemIds.append(id);
d->m_availableItemIds.removeAll(id);
@@ -250,7 +250,7 @@ void SideBar::closeSubWidget()
void SideBar::updateWidgets()
{
- foreach (Internal::SideBarWidget *i, d->m_widgets)
+ for (Internal::SideBarWidget *i : qAsConst(d->m_widgets))
i->updateAvailableItems();
}
@@ -276,7 +276,7 @@ void SideBar::saveSettings(QSettings *settings, const QString &name)
void SideBar::closeAllWidgets()
{
- foreach (Internal::SideBarWidget *widget, d->m_widgets)
+ for (Internal::SideBarWidget *widget : qAsConst(d->m_widgets))
removeSideBarWidget(widget);
}
@@ -288,9 +288,9 @@ void SideBar::readSettings(QSettings *settings, const QString &name)
const QString viewsKey = prefix + QLatin1String("Views");
if (settings->contains(viewsKey)) {
- QStringList views = settings->value(viewsKey).toStringList();
+ const QStringList views = settings->value(viewsKey).toStringList();
if (!views.isEmpty()) {
- foreach (const QString &id, views)
+ for (const QString &id : views)
if (availableItemIds().contains(id))
insertSideBarWidget(d->m_widgets.count(), id);
@@ -299,7 +299,7 @@ void SideBar::readSettings(QSettings *settings, const QString &name)
}
}
if (d->m_widgets.size() == 0) {
- foreach (const QString &id, d->m_defaultVisible)
+ for (const QString &id : qAsConst(d->m_defaultVisible))
insertSideBarWidget(d->m_widgets.count(), id);
}
diff --git a/src/plugins/coreplugin/sidebarwidget.cpp b/src/plugins/coreplugin/sidebarwidget.cpp
index 0d13db69763..8c1d9b10809 100644
--- a/src/plugins/coreplugin/sidebarwidget.cpp
+++ b/src/plugins/coreplugin/sidebarwidget.cpp
@@ -90,7 +90,7 @@ SideBarWidget::SideBarWidget(SideBar *sideBar, const QString &id)
Utils::sort(titleList);
QString t = id;
if (!titleList.isEmpty()) {
- foreach (const QString &itemTitle, titleList)
+ for (const QString &itemTitle : qAsConst(titleList))
m_comboBox->addItem(itemTitle, m_sideBar->idForTitle(itemTitle));
m_comboBox->setCurrentIndex(0);
@@ -139,7 +139,8 @@ void SideBarWidget::setCurrentItem(const QString &id)
m_currentItem->widget()->show();
// Add buttons and remember their actions for later removal
- foreach (QToolButton *b, m_currentItem->createToolBarWidgets())
+ QList<QToolButton *> buttons = m_currentItem->createToolBarWidgets();
+ for (QToolButton *b : buttons)
m_addedToolBarActions.append(m_toolbar->insertWidget(m_splitAction, b));
}
@@ -153,7 +154,7 @@ void SideBarWidget::updateAvailableItems()
titleList.append(currentTitle);
Utils::sort(titleList);
- foreach (const QString &itemTitle, titleList)
+ for (const QString &itemTitle : qAsConst(titleList))
m_comboBox->addItem(itemTitle, m_sideBar->idForTitle(itemTitle));
int idx = m_comboBox->findText(currentTitle);
diff --git a/src/plugins/coreplugin/statusbarmanager.cpp b/src/plugins/coreplugin/statusbarmanager.cpp
index 1366b0c0d02..32bcfb8cfaf 100644
--- a/src/plugins/coreplugin/statusbarmanager.cpp
+++ b/src/plugins/coreplugin/statusbarmanager.cpp
@@ -164,7 +164,8 @@ void StatusBarManager::restoreSettings()
leftSplitWidth = m_splitter->widget(0)->sizeHint().width();
}
int sum = 0;
- foreach (int w, m_splitter->sizes())
+ const QList<int> sizes = m_splitter->sizes();
+ for (const int w : sizes)
sum += w;
m_splitter->setSizes(QList<int>() << leftSplitWidth << (sum - leftSplitWidth));
}
diff --git a/src/plugins/coreplugin/themechooser.cpp b/src/plugins/coreplugin/themechooser.cpp
index f3d828d4b4b..0ea465ae058 100644
--- a/src/plugins/coreplugin/themechooser.cpp
+++ b/src/plugins/coreplugin/themechooser.cpp
@@ -201,7 +201,7 @@ static void addThemesFromPath(const QString &path, QList<ThemeEntry> *themes)
themeDir.setNameFilters({extension});
themeDir.setFilter(QDir::Files);
const QStringList themeList = themeDir.entryList();
- foreach (const QString &fileName, themeList) {
+ for (const QString &fileName : qAsConst(themeList)) {
QString id = QFileInfo(fileName).completeBaseName();
themes->append(ThemeEntry(Id::fromString(id), themeDir.absoluteFilePath(fileName)));
}
diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp
index 9258d81d441..dd5963eb1ad 100644
--- a/src/plugins/coreplugin/vcsmanager.cpp
+++ b/src/plugins/coreplugin/vcsmanager.cpp
@@ -101,7 +101,8 @@ public:
QTC_ASSERT(QDir::fromNativeSeparators(dir) == dir, return);
const QString dirSlash = dir + QLatin1Char('/');
- foreach (const QString &key, m_cachedMatches.keys()) {
+ const QList<QString> keys = m_cachedMatches.keys();
+ for (const QString &key : keys) {
if (key == dir || key.startsWith(dirSlash))
m_cachedMatches.remove(key);
}
@@ -172,7 +173,8 @@ VcsManager *VcsManager::instance()
void VcsManager::extensionsInitialized()
{
// Change signal connections
- foreach (IVersionControl *versionControl, versionControls()) {
+ const QList<IVersionControl *> versionControlList = versionControls();
+ for (const IVersionControl *versionControl : versionControlList) {
connect(versionControl, &IVersionControl::filesChanged, DocumentManager::instance(),
[](const QStringList fileNames) {
DocumentManager::notifyFilesChangedInternally(
@@ -240,7 +242,8 @@ IVersionControl* VcsManager::findVersionControlForDirectory(const FilePath &inpu
// Nothing: ask the IVersionControls directly.
StringVersionControlPairs allThatCanManage;
- foreach (IVersionControl * versionControl, versionControls()) {
+ const QList<IVersionControl *> versionControlList = versionControls();
+ for (IVersionControl *versionControl : versionControlList) {
FilePath topLevel;
if (versionControl->managesDirectory(FilePath::fromString(directory), &topLevel))
allThatCanManage.push_back(StringVersionControlPair(topLevel.toString(), versionControl));
@@ -465,9 +468,9 @@ void VcsManager::emitRepositoryChanged(const FilePath &repository)
void VcsManager::clearVersionControlCache()
{
- QStringList repoList = d->m_cachedMatches.keys();
+ const QStringList repoList = d->m_cachedMatches.keys();
d->clearCache();
- foreach (const QString &repo, repoList)
+ for (const QString &repo : repoList)
emit m_instance->repositoryChanged(FilePath::fromString(repo));
}
@@ -589,7 +592,7 @@ void CorePlugin::testVcsManager()
// From VCSes:
int expectedCount = 0;
- foreach (const QString &result, results) {
+ for (const QString &result : qAsConst(results)) {
// qDebug() << "Expecting:" << result;
QStringList split = result.split(QLatin1Char(':'));
diff --git a/src/plugins/coreplugin/welcomepagehelper.cpp b/src/plugins/coreplugin/welcomepagehelper.cpp
index 0bbd3fa2520..802bc6bdbed 100644
--- a/src/plugins/coreplugin/welcomepagehelper.cpp
+++ b/src/plugins/coreplugin/welcomepagehelper.cpp
@@ -416,10 +416,13 @@ void ListItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
}
constexpr float hoverAnimationDuration = 260;
animationProgress = m_startTime.elapsed() / hoverAnimationDuration;
- static const QEasingCurve animationCurve(QEasingCurve::OutCubic);
- offset = animationCurve.valueForProgress(animationProgress) * shiftY;
- if (offset < shiftY)
+ if (animationProgress < 1) {
+ static const QEasingCurve animationCurve(QEasingCurve::OutCubic);
+ offset = animationCurve.valueForProgress(animationProgress) * shiftY;
QTimer::singleShot(10, this, &ListItemDelegate::goon);
+ } else {
+ offset = shiftY;
+ }
} else if (index == m_previousIndex) {
m_previousIndex = QModelIndex();
}
diff --git a/src/plugins/cpaster/cpasterplugin.cpp b/src/plugins/cpaster/cpasterplugin.cpp
index 825cacd4a4e..3cf987e1efe 100644
--- a/src/plugins/cpaster/cpasterplugin.cpp
+++ b/src/plugins/cpaster/cpasterplugin.cpp
@@ -43,7 +43,7 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/temporarydirectory.h>
diff --git a/src/plugins/cpaster/frontend/argumentscollector.cpp b/src/plugins/cpaster/frontend/argumentscollector.cpp
index 99f9f0c0370..446c4cb9923 100644
--- a/src/plugins/cpaster/frontend/argumentscollector.cpp
+++ b/src/plugins/cpaster/frontend/argumentscollector.cpp
@@ -25,7 +25,7 @@
#include "argumentscollector.h"
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <QCoreApplication>
diff --git a/src/plugins/cpaster/protocol.cpp b/src/plugins/cpaster/protocol.cpp
index e9eb1984292..8a748058d38 100644
--- a/src/plugins/cpaster/protocol.cpp
+++ b/src/plugins/cpaster/protocol.cpp
@@ -48,6 +48,8 @@
#include <QApplication>
#include <QPushButton>
+#include <memory>
+
namespace CodePaster {
Protocol::Protocol()
@@ -215,19 +217,19 @@ bool NetworkProtocol::httpStatus(QString url, QString *errorMessage, bool useHtt
url.prepend(useHttps ? httpsPrefix : httpPrefix);
url.append(QLatin1Char('/'));
}
- QScopedPointer<QNetworkReply> reply(httpGet(url));
+ std::unique_ptr<QNetworkReply> reply(httpGet(url));
QMessageBox box(QMessageBox::Information,
tr("Checking connection"),
tr("Connecting to %1...").arg(url),
QMessageBox::Cancel,
Core::ICore::dialogParent());
- connect(reply.data(), &QNetworkReply::finished, &box, &QWidget::close);
+ connect(reply.get(), &QNetworkReply::finished, &box, &QWidget::close);
QApplication::setOverrideCursor(Qt::WaitCursor);
box.exec();
QApplication::restoreOverrideCursor();
// User canceled, discard and be happy.
if (!reply->isFinished()) {
- QNetworkReply *replyPtr = reply.take();
+ QNetworkReply *replyPtr = reply.release();
connect(replyPtr, &QNetworkReply::finished, replyPtr, &QNetworkReply::deleteLater);
return false;
}
diff --git a/src/plugins/cpaster/settings.cpp b/src/plugins/cpaster/settings.cpp
index d10af8fb807..a27e9876f95 100644
--- a/src/plugins/cpaster/settings.cpp
+++ b/src/plugins/cpaster/settings.cpp
@@ -68,7 +68,7 @@ Settings::Settings()
registerAspect(&displayOutput);
displayOutput.setSettingsKey("DisplayOutput");
displayOutput.setDefaultValue(true);
- displayOutput.setLabelText(tr("Display Output pane after sending a post"));
+ displayOutput.setLabelText(tr("Display General Messages after sending a post"));
}
// SettingsPage
diff --git a/src/plugins/cppcheck/cppcheckplugin.cpp b/src/plugins/cppcheck/cppcheckplugin.cpp
index 6d338a1df36..fed438d9ee3 100644
--- a/src/plugins/cppcheck/cppcheckplugin.cpp
+++ b/src/plugins/cppcheck/cppcheckplugin.cpp
@@ -32,10 +32,11 @@
#include "cppcheckdiagnosticsmodel.h"
#include "cppcheckmanualrundialog.h"
-#include <projectexplorer/session.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/project.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <coreplugin/actionmanager/actioncontainer.h>
diff --git a/src/plugins/cppcheck/cppcheckrunner.cpp b/src/plugins/cppcheck/cppcheckrunner.cpp
index 4e4e3d40524..542631beb71 100644
--- a/src/plugins/cppcheck/cppcheckrunner.cpp
+++ b/src/plugins/cppcheck/cppcheckrunner.cpp
@@ -28,7 +28,6 @@
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <coreplugin/messagemanager.h>
@@ -37,11 +36,9 @@ using namespace Utils;
namespace Cppcheck {
namespace Internal {
-CppcheckRunner::CppcheckRunner(CppcheckTool &tool) :
- m_tool(tool),
- m_process(new Utils::QtcProcess(this))
+CppcheckRunner::CppcheckRunner(CppcheckTool &tool) : m_tool(tool)
{
- if (Utils::HostOsInfo::hostOs() == Utils::OsTypeLinux) {
+ if (HostOsInfo::hostOs() == OsTypeLinux) {
QtcProcess getConf;
getConf.setCommand({"getconf", {"ARG_MAX"}});
getConf.start();
@@ -50,17 +47,15 @@ CppcheckRunner::CppcheckRunner(CppcheckTool &tool) :
m_maxArgumentsLength = std::max(argMax.toInt(), m_maxArgumentsLength);
}
- m_process->setStdOutLineCallback([this](const QString &line) {
+ m_process.setStdOutLineCallback([this](const QString &line) {
m_tool.parseOutputLine(line);
});
- m_process->setStdErrLineCallback([this](const QString &line) {
+ m_process.setStdErrLineCallback([this](const QString &line) {
m_tool.parseErrorLine(line);
});
- connect(m_process, &QtcProcess::started,
- this, &CppcheckRunner::handleStarted);
- connect(m_process, &QtcProcess::finished,
- this, &CppcheckRunner::handleFinished);
+ connect(&m_process, &QtcProcess::started, &m_tool, &CppcheckTool::startParsing);
+ connect(&m_process, &QtcProcess::done, this, &CppcheckRunner::handleDone);
m_queueTimer.setSingleShot(true);
const int checkDelayInMs = 200;
@@ -81,18 +76,18 @@ void CppcheckRunner::reconfigure(const FilePath &binary, const QString &argument
m_arguments = arguments;
}
-void CppcheckRunner::addToQueue(const Utils::FilePaths &files,
+void CppcheckRunner::addToQueue(const FilePaths &files,
const QString &additionalArguments)
{
- Utils::FilePaths &existing = m_queue[additionalArguments];
+ FilePaths &existing = m_queue[additionalArguments];
if (existing.isEmpty()) {
existing = files;
} else {
std::copy_if(files.cbegin(), files.cend(), std::back_inserter(existing),
- [&existing](const Utils::FilePath &file) { return !existing.contains(file); });
+ [&existing](const FilePath &file) { return !existing.contains(file); });
}
- if (m_isRunning) {
+ if (m_process.isRunning()) {
stop(existing);
return;
}
@@ -100,16 +95,16 @@ void CppcheckRunner::addToQueue(const Utils::FilePaths &files,
m_queueTimer.start();
}
-void CppcheckRunner::stop(const Utils::FilePaths &files)
+void CppcheckRunner::stop(const FilePaths &files)
{
- if (!m_isRunning)
+ if (!m_process.isRunning())
return;
if (files.isEmpty() || m_currentFiles == files)
- m_process->kill();
+ m_process.stop();
}
-void CppcheckRunner::removeFromQueue(const Utils::FilePaths &files)
+void CppcheckRunner::removeFromQueue(const FilePaths &files)
{
if (m_queue.isEmpty())
return;
@@ -118,21 +113,21 @@ void CppcheckRunner::removeFromQueue(const Utils::FilePaths &files)
m_queue.clear();
} else {
for (auto it = m_queue.begin(), end = m_queue.end(); it != end;) {
- for (const Utils::FilePath &file : files)
+ for (const FilePath &file : files)
it.value().removeOne(file);
it = !it.value().isEmpty() ? ++it : m_queue.erase(it);
}
}
}
-const Utils::FilePaths &CppcheckRunner::currentFiles() const
+const FilePaths &CppcheckRunner::currentFiles() const
{
return m_currentFiles;
}
QString CppcheckRunner::currentCommand() const
{
- return m_process->commandLine().toUserOutput();
+ return m_process.commandLine().toUserOutput();
}
void CppcheckRunner::checkQueued()
@@ -140,7 +135,7 @@ void CppcheckRunner::checkQueued()
if (m_queue.isEmpty() || m_binary.isEmpty())
return;
- Utils::FilePaths files = m_queue.begin().value();
+ FilePaths files = m_queue.begin().value();
QString arguments = m_arguments + ' ' + m_queue.begin().key();
m_currentFiles.clear();
int argumentsLength = arguments.length();
@@ -158,30 +153,19 @@ void CppcheckRunner::checkQueued()
else
m_queue.begin().value() = files;
- m_process->setCommand(CommandLine(m_binary, arguments, CommandLine::Raw));
- m_process->start();
+ m_process.setCommand(CommandLine(m_binary, arguments, CommandLine::Raw));
+ m_process.start();
}
-void CppcheckRunner::handleStarted()
+void CppcheckRunner::handleDone()
{
- if (m_isRunning)
- return;
-
- m_isRunning = true;
- m_tool.startParsing();
-}
-
-void CppcheckRunner::handleFinished()
-{
- if (m_process->error() != QProcess::FailedToStart) {
+ if (m_process.result() == ProcessResult::FinishedWithSuccess)
m_tool.finishParsing();
- } else {
- const QString message = tr("Cppcheck failed to start: \"%1\".").arg(currentCommand());
- Core::MessageManager::writeSilently(message);
- }
+ else
+ Core::MessageManager::writeSilently(m_process.exitMessage());
+
m_currentFiles.clear();
- m_process->close();
- m_isRunning = false;
+ m_process.close();
if (!m_queue.isEmpty())
checkQueued();
diff --git a/src/plugins/cppcheck/cppcheckrunner.h b/src/plugins/cppcheck/cppcheckrunner.h
index d49a9016dea..d35943b31f0 100644
--- a/src/plugins/cppcheck/cppcheckrunner.h
+++ b/src/plugins/cppcheck/cppcheckrunner.h
@@ -26,12 +26,11 @@
#pragma once
#include <utils/filepath.h>
+#include <utils/qtcprocess.h>
#include <QHash>
#include <QTimer>
-namespace Utils { class QtcProcess; }
-
namespace Cppcheck {
namespace Internal {
@@ -58,18 +57,16 @@ private:
void checkQueued();
void readOutput();
void readError();
- void handleStarted();
- void handleFinished();
+ void handleDone();
CppcheckTool &m_tool;
- Utils::QtcProcess *m_process = nullptr;
+ Utils::QtcProcess m_process;
Utils::FilePath m_binary;
QString m_arguments;
QHash<QString, Utils::FilePaths> m_queue;
Utils::FilePaths m_currentFiles;
QTimer m_queueTimer;
int m_maxArgumentsLength = 32767;
- bool m_isRunning = false;
};
} // namespace Internal
diff --git a/src/plugins/cppcheck/cppchecktextmark.cpp b/src/plugins/cppcheck/cppchecktextmark.cpp
index 55d5b43f4ce..a81ac7e6f74 100644
--- a/src/plugins/cppcheck/cppchecktextmark.cpp
+++ b/src/plugins/cppcheck/cppchecktextmark.cpp
@@ -29,6 +29,9 @@
#include <utils/utilsicons.h>
+#include <QAction>
+#include <QApplication>
+#include <QClipboard>
#include <QMap>
namespace Cppcheck {
@@ -77,6 +80,20 @@ CppcheckTextMark::CppcheckTextMark (const Diagnostic &diagnostic)
setToolTip(toolTipText(diagnostic.severityText));
setLineAnnotation(diagnostic.message);
setSettingsPage(Constants::OPTIONS_PAGE_ID);
+ setActionsProvider([diagnostic] {
+ // Copy to clipboard action
+ QAction *action = new QAction;
+ action->setIcon(QIcon::fromTheme("edit-copy", Utils::Icons::COPY.icon()));
+ action->setToolTip(TextMark::tr("Copy to Clipboard"));
+ QObject::connect(action, &QAction::triggered, [diagnostic]() {
+ const QString text = QString("%1:%2: %3")
+ .arg(diagnostic.fileName.toUserOutput())
+ .arg(diagnostic.lineNumber)
+ .arg(diagnostic.message);
+ QApplication::clipboard()->setText(text);
+ });
+ return QList<QAction *>{action};
+ });
}
QString CppcheckTextMark::toolTipText(const QString &severityText) const
diff --git a/src/plugins/cppcheck/cppchecktextmarkmanager.h b/src/plugins/cppcheck/cppchecktextmarkmanager.h
index 0f9a01fb7da..12ccba194e3 100644
--- a/src/plugins/cppcheck/cppchecktextmarkmanager.h
+++ b/src/plugins/cppcheck/cppchecktextmarkmanager.h
@@ -27,7 +27,7 @@
#include <cppcheck/cppcheckdiagnosticmanager.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <unordered_map>
diff --git a/src/plugins/cppcheck/cppchecktool.cpp b/src/plugins/cppcheck/cppchecktool.cpp
index 9636443b0e3..6501ed583a4 100644
--- a/src/plugins/cppcheck/cppchecktool.cpp
+++ b/src/plugins/cppcheck/cppchecktool.cpp
@@ -118,7 +118,7 @@ void CppcheckTool::updateArguments()
if (!m_options.unusedFunction && !m_options.customArguments.contains("-j "))
arguments.push_back("-j " + QString::number(QThread::idealThreadCount()));
- arguments.push_back("--template={file},{line},{severity},{id},{message}");
+ arguments.push_back("--template=\"{file},{line},{severity},{id},{message}\"");
m_runner->reconfigure(m_options.binary, arguments.join(' '));
}
diff --git a/src/plugins/cppeditor/CMakeLists.txt b/src/plugins/cppeditor/CMakeLists.txt
index 31f28cd13cc..a2f09056bbc 100644
--- a/src/plugins/cppeditor/CMakeLists.txt
+++ b/src/plugins/cppeditor/CMakeLists.txt
@@ -1,7 +1,6 @@
add_qtc_plugin(CppEditor
- DEFINES CPPEDITOR_LIBRARY
DEPENDS Qt5::Network Qt5::Xml
- PUBLIC_DEPENDS CPlusPlus ClangSupport Qt5::Widgets
+ PUBLIC_DEPENDS CPlusPlus Qt5::Widgets
PLUGIN_DEPENDS Core ProjectExplorer TextEditor
PLUGIN_TEST_DEPENDS QbsProjectManager QmakeProjectManager
SOURCES
@@ -61,7 +60,6 @@ add_qtc_plugin(CppEditor
cpplocalsymbols.cpp cpplocalsymbols.h
cpplocatordata.cpp cpplocatordata.h
cpplocatorfilter.cpp cpplocatorfilter.h
- cppminimizableinfobars.cpp cppminimizableinfobars.h
cppmodelmanager.cpp cppmodelmanager.h
cppmodelmanagersupport.cpp cppmodelmanagersupport.h
cppoutline.cpp cppoutline.h
@@ -86,7 +84,6 @@ add_qtc_plugin(CppEditor
cppquickfixsettingspage.cpp cppquickfixsettingspage.h
cppquickfixsettingswidget.cpp cppquickfixsettingswidget.h cppquickfixsettingswidget.ui
cpprefactoringchanges.cpp cpprefactoringchanges.h
- cpprefactoringengine.cpp cpprefactoringengine.h
cppselectionchanger.cpp cppselectionchanger.h
cppsemanticinfo.h
cppsemanticinfoupdater.cpp cppsemanticinfoupdater.h
@@ -102,7 +99,6 @@ add_qtc_plugin(CppEditor
cursorineditor.h
doxygengenerator.cpp doxygengenerator.h
editordocumenthandle.cpp editordocumenthandle.h
- followsymbolinterface.h
functionutils.cpp functionutils.h
generatedcodemodelsupport.cpp generatedcodemodelsupport.h
headerpathfilter.cpp headerpathfilter.h
@@ -111,7 +107,6 @@ add_qtc_plugin(CppEditor
insertionpointlocator.cpp insertionpointlocator.h
projectinfo.cpp projectinfo.h
projectpart.cpp projectpart.h
- refactoringengineinterface.h
resourcepreviewhoverhandler.cpp resourcepreviewhoverhandler.h
searchsymbols.cpp searchsymbols.h
semantichighlighter.cpp semantichighlighter.h
@@ -120,7 +115,6 @@ add_qtc_plugin(CppEditor
symbolfinder.cpp symbolfinder.h
symbolsfindfilter.cpp symbolsfindfilter.h
typehierarchybuilder.cpp typehierarchybuilder.h
- usages.h
wrappablelineedit.cpp wrappablelineedit.h
EXPLICIT_MOC
cppquickfixsettingswidget.h
diff --git a/src/plugins/cppeditor/abstractoverviewmodel.h b/src/plugins/cppeditor/abstractoverviewmodel.h
index eb7c9968e27..57fef64924c 100644
--- a/src/plugins/cppeditor/abstractoverviewmodel.h
+++ b/src/plugins/cppeditor/abstractoverviewmodel.h
@@ -77,7 +77,7 @@ public:
QMimeData *mimeData(const QModelIndexList &indexes) const override
{
auto mimeData = new Utils::DropMimeData;
- foreach (const QModelIndex &index, indexes) {
+ for (const QModelIndex &index : indexes) {
const QVariant fileName = data(index, FileNameRole);
if (!fileName.canConvert<QString>())
continue;
diff --git a/src/plugins/cppeditor/baseeditordocumentprocessor.cpp b/src/plugins/cppeditor/baseeditordocumentprocessor.cpp
index dcd64222e4a..cb6736df7a9 100644
--- a/src/plugins/cppeditor/baseeditordocumentprocessor.cpp
+++ b/src/plugins/cppeditor/baseeditordocumentprocessor.cpp
@@ -70,10 +70,6 @@ BaseEditorDocumentProcessor::extraRefactoringOperations(const TextEditor::Assist
return TextEditor::QuickFixOperations();
}
-void BaseEditorDocumentProcessor::editorDocumentTimerRestarted()
-{
-}
-
void BaseEditorDocumentProcessor::invalidateDiagnostics()
{
}
@@ -84,13 +80,6 @@ void BaseEditorDocumentProcessor::setParserConfig(
parser()->setConfiguration(config);
}
-QFuture<ToolTipInfo> BaseEditorDocumentProcessor::toolTipInfo(const QByteArray &/*codecName*/,
- int /*line*/,
- int /*column*/)
-{
- return QFuture<ToolTipInfo>();
-}
-
void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
BaseEditorDocumentParser::Ptr parser,
BaseEditorDocumentParser::UpdateParams updateParams)
diff --git a/src/plugins/cppeditor/baseeditordocumentprocessor.h b/src/plugins/cppeditor/baseeditordocumentprocessor.h
index 3a7f9844fb1..91689542191 100644
--- a/src/plugins/cppeditor/baseeditordocumentprocessor.h
+++ b/src/plugins/cppeditor/baseeditordocumentprocessor.h
@@ -83,27 +83,18 @@ public:
virtual void invalidateDiagnostics();
- virtual void editorDocumentTimerRestarted();
-
virtual void setParserConfig(const BaseEditorDocumentParser::Configuration &config);
virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params) = 0;
- virtual QFuture<CursorInfo> requestLocalReferences(const QTextCursor &cursor) = 0;
- virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0;
- virtual QFuture<ToolTipInfo> toolTipInfo(const QByteArray &codecName, int line, int column);
QString filePath() const { return m_filePath; }
-public:
- using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
-
signals:
// Signal interface to implement
void projectPartInfoUpdated(const ProjectPartInfo &projectPartInfo);
void codeWarningsUpdated(unsigned revision,
const QList<QTextEdit::ExtraSelection> &selections,
- const HeaderErrorDiagnosticWidgetCreator &creator,
const TextEditor::RefactorMarkers &refactorMarkers);
void ifdefedOutBlocksUpdated(unsigned revision,
diff --git a/src/plugins/cppeditor/builtincursorinfo.cpp b/src/plugins/cppeditor/builtincursorinfo.cpp
index dbbb7d92b0f..5fb945166f2 100644
--- a/src/plugins/cppeditor/builtincursorinfo.cpp
+++ b/src/plugins/cppeditor/builtincursorinfo.cpp
@@ -209,7 +209,7 @@ private:
const SemanticUses &uses = it.value();
bool good = false;
- foreach (const SemanticInfo::Use &use, uses) {
+ for (const SemanticInfo::Use &use : uses) {
if (m_line == use.line && m_column >= use.column
&& m_column <= static_cast<int>(use.column + use.length)) {
good = true;
@@ -296,7 +296,8 @@ bool handleMacroCase(const Document::Ptr document,
ranges->append(toRange(textCursor, macro->utf16CharOffset(), length));
// Other macro uses
- foreach (const Document::MacroUse &use, document->macroUses()) {
+ const QList<Document::MacroUse> macroUses = document->macroUses();
+ for (const Document::MacroUse &use : macroUses) {
if (isMacroUseOf(use, *macro))
ranges->append(toRange(textCursor, use.utf16charsBegin(), length));
}
diff --git a/src/plugins/cppeditor/builtineditordocumentparser.cpp b/src/plugins/cppeditor/builtineditordocumentparser.cpp
index 9b3a649f657..f29368a3992 100644
--- a/src/plugins/cppeditor/builtineditordocumentparser.cpp
+++ b/src/plugins/cppeditor/builtineditordocumentparser.cpp
@@ -155,7 +155,7 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur
} else {
// Remove changed files from the snapshot
QSet<Utils::FilePath> toRemove;
- foreach (const Document::Ptr &doc, state.snapshot) {
+ for (const Document::Ptr &doc : qAsConst(state.snapshot)) {
const Utils::FilePath fileName = Utils::FilePath::fromString(doc->fileName());
if (workingCopy.contains(fileName)) {
if (workingCopy.get(fileName).second != doc->editorRevision())
@@ -169,7 +169,7 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur
if (!toRemove.isEmpty()) {
invalidateSnapshot = true;
- foreach (const Utils::FilePath &fileName, toRemove)
+ for (const Utils::FilePath &fileName : qAsConst(toRemove))
state.snapshot.remove(fileName);
}
}
@@ -215,7 +215,7 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur
sourceProcessor.setLanguageFeatures(features);
sourceProcessor.run(configurationFileName);
if (baseConfig.usePrecompiledHeaders) {
- foreach (const QString &precompiledHeader, state.precompiledHeaders)
+ for (const QString &precompiledHeader : qAsConst(state.precompiledHeaders))
sourceProcessor.run(precompiledHeader);
}
if (!baseState.editorDefines.isEmpty())
diff --git a/src/plugins/cppeditor/builtineditordocumentprocessor.cpp b/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
index cfd3187b095..21cacae9c00 100644
--- a/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
+++ b/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
@@ -62,7 +62,7 @@ QList<QTextEdit::ExtraSelection> toTextEditorSelections(
QTextCharFormat errorFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR);
QList<QTextEdit::ExtraSelection> result;
- foreach (const CPlusPlus::Document::DiagnosticMessage &m, diagnostics) {
+ for (const CPlusPlus::Document::DiagnosticMessage &m : diagnostics) {
QTextEdit::ExtraSelection sel;
if (m.isWarning())
sel.format = warningFormat;
@@ -108,7 +108,8 @@ CheckSymbols *createHighlighter(const CPlusPlus::Document::Ptr &doc,
using Utils::Text::convertPosition;
// Get macro definitions
- foreach (const CPlusPlus::Macro& macro, doc->definedMacros()) {
+ const QList<CPlusPlus::Macro> definedMacros = doc->definedMacros();
+ for (const CPlusPlus::Macro &macro : definedMacros) {
int line, column;
convertPosition(textDocument, macro.utf16CharOffset(), &line, &column);
@@ -119,7 +120,8 @@ CheckSymbols *createHighlighter(const CPlusPlus::Document::Ptr &doc,
const LanguageFeatures features = doc->languageFeatures();
// Get macro uses
- foreach (const Document::MacroUse &macro, doc->macroUses()) {
+ const QList<Document::MacroUse> macroUseList = doc->macroUses();
+ for (const Document::MacroUse &macro : macroUseList) {
const QString name = macro.macro().nameToQString();
//Filter out QtKeywords
@@ -150,23 +152,19 @@ QList<TextEditor::BlockRange> toTextEditorBlocks(
{
QList<TextEditor::BlockRange> result;
result.reserve(skippedBlocks.size());
- foreach (const CPlusPlus::Document::Block &block, skippedBlocks)
+ for (const CPlusPlus::Document::Block &block : skippedBlocks)
result.append(TextEditor::BlockRange(block.utf16charsBegin(), block.utf16charsEnd()));
return result;
}
} // anonymous namespace
-BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
- TextEditor::TextDocument *document,
- bool enableSemanticHighlighter)
+BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(TextEditor::TextDocument *document)
: BaseEditorDocumentProcessor(document->document(), document->filePath().toString())
, m_parser(new BuiltinEditorDocumentParser(document->filePath().toString(),
indexerFileSizeLimitInMb()))
, m_codeWarningsUpdated(false)
- , m_semanticHighlighter(enableSemanticHighlighter
- ? new SemanticHighlighter(document)
- : nullptr)
+ , m_semanticHighlighter(new SemanticHighlighter(document))
{
using namespace Internal;
@@ -176,18 +174,16 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
config.usePrecompiledHeaders = cms->pchUsage() != CppCodeModelSettings::PchUse_None;
m_parser->setConfiguration(config);
- if (m_semanticHighlighter) {
- m_semanticHighlighter->setHighlightingRunner(
- [this]() -> QFuture<TextEditor::HighlightingResult> {
- const SemanticInfo semanticInfo = m_semanticInfoUpdater.semanticInfo();
- CheckSymbols *checkSymbols = createHighlighter(semanticInfo.doc, semanticInfo.snapshot,
- textDocument());
- QTC_ASSERT(checkSymbols, return QFuture<TextEditor::HighlightingResult>());
- connect(checkSymbols, &CheckSymbols::codeWarningsUpdated,
- this, &BuiltinEditorDocumentProcessor::onCodeWarningsUpdated);
- return checkSymbols->start();
- });
- }
+ m_semanticHighlighter->setHighlightingRunner(
+ [this]() -> QFuture<TextEditor::HighlightingResult> {
+ const SemanticInfo semanticInfo = m_semanticInfoUpdater.semanticInfo();
+ CheckSymbols *checkSymbols = createHighlighter(semanticInfo.doc, semanticInfo.snapshot,
+ textDocument());
+ QTC_ASSERT(checkSymbols, return QFuture<TextEditor::HighlightingResult>());
+ connect(checkSymbols, &CheckSymbols::codeWarningsUpdated,
+ this, &BuiltinEditorDocumentProcessor::onCodeWarningsUpdated);
+ return checkSymbols->start();
+ });
connect(m_parser.data(), &BuiltinEditorDocumentParser::projectPartInfoUpdated,
this, &BaseEditorDocumentProcessor::projectPartInfoUpdated);
@@ -229,7 +225,7 @@ void BuiltinEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force)
void BuiltinEditorDocumentProcessor::semanticRehighlight()
{
- if (m_semanticHighlighter && m_semanticInfoUpdater.semanticInfo().doc) {
+ if (m_semanticInfoUpdater.semanticInfo().doc) {
if (const CPlusPlus::Document::Ptr document = m_documentSnapshot.document(filePath())) {
m_codeWarnings = toTextEditorSelections(document->diagnosticMessages(), textDocument());
m_codeWarningsUpdated = false;
@@ -257,22 +253,10 @@ BuiltinEditorDocumentProcessor::cursorInfo(const CursorInfoParams &params)
return BuiltinCursorInfo::run(params);
}
-QFuture<CursorInfo> BuiltinEditorDocumentProcessor::requestLocalReferences(const QTextCursor &)
-{
- QFutureInterface<CursorInfo> futureInterface;
- futureInterface.reportResult(CursorInfo());
- futureInterface.reportFinished();
-
- return futureInterface.future();
-}
-
-QFuture<SymbolInfo> BuiltinEditorDocumentProcessor::requestFollowSymbol(int, int)
+void BuiltinEditorDocumentProcessor::setSemanticHighlightingChecker(
+ const SemanticHighlightingChecker &checker)
{
- QFutureInterface<SymbolInfo> futureInterface;
- futureInterface.reportResult(SymbolInfo());
- futureInterface.reportFinished();
-
- return futureInterface.future();
+ m_semanticHighlightingChecker = checker;
}
void BuiltinEditorDocumentProcessor::onParserFinished(CPlusPlus::Document::Ptr document,
@@ -312,7 +296,7 @@ void BuiltinEditorDocumentProcessor::onSemanticInfoUpdated(const SemanticInfo se
emit semanticInfoUpdated(semanticInfo);
- if (m_semanticHighlighter)
+ if (!m_semanticHighlightingChecker || m_semanticHighlightingChecker())
m_semanticHighlighter->run();
}
@@ -336,7 +320,6 @@ void BuiltinEditorDocumentProcessor::onCodeWarningsUpdated(
m_codeWarningsUpdated = true;
emit codeWarningsUpdated(revision(),
m_codeWarnings,
- HeaderErrorDiagnosticWidgetCreator(),
TextEditor::RefactorMarkers());
}
diff --git a/src/plugins/cppeditor/builtineditordocumentprocessor.h b/src/plugins/cppeditor/builtineditordocumentprocessor.h
index e547d9066e0..a058f4f6fcb 100644
--- a/src/plugins/cppeditor/builtineditordocumentprocessor.h
+++ b/src/plugins/cppeditor/builtineditordocumentprocessor.h
@@ -31,6 +31,8 @@
#include "cppsemanticinfoupdater.h"
#include "semantichighlighter.h"
+#include <functional>
+
namespace CppEditor {
class CPPEDITOR_EXPORT BuiltinEditorDocumentProcessor : public BaseEditorDocumentProcessor
@@ -38,8 +40,7 @@ class CPPEDITOR_EXPORT BuiltinEditorDocumentProcessor : public BaseEditorDocumen
Q_OBJECT
public:
- BuiltinEditorDocumentProcessor(TextEditor::TextDocument *document,
- bool enableSemanticHighlighter = true);
+ BuiltinEditorDocumentProcessor(TextEditor::TextDocument *document);
~BuiltinEditorDocumentProcessor() override;
// BaseEditorDocumentProcessor interface
@@ -52,8 +53,9 @@ public:
bool isParserRunning() const override;
QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params) override;
- QFuture<CursorInfo> requestLocalReferences(const QTextCursor &) override;
- QFuture<SymbolInfo> requestFollowSymbol(int, int) override;
+
+ using SemanticHighlightingChecker = std::function<bool()>;
+ void setSemanticHighlightingChecker(const SemanticHighlightingChecker &checker);
private:
void onParserFinished(CPlusPlus::Document::Ptr document, CPlusPlus::Snapshot snapshot);
@@ -73,6 +75,7 @@ private:
SemanticInfoUpdater m_semanticInfoUpdater;
QScopedPointer<SemanticHighlighter> m_semanticHighlighter;
+ SemanticHighlightingChecker m_semanticHighlightingChecker;
};
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/builtinindexingsupport.cpp b/src/plugins/cppeditor/builtinindexingsupport.cpp
index 7bbad4179c0..0865fe7fbe8 100644
--- a/src/plugins/cppeditor/builtinindexingsupport.cpp
+++ b/src/plugins/cppeditor/builtinindexingsupport.cpp
@@ -95,7 +95,8 @@ public:
using namespace CPlusPlus;
const QString fileName = document->fileName();
- foreach (const Document::DiagnosticMessage &message, document->diagnosticMessages()) {
+ const QList<Document::DiagnosticMessage> messages = document->diagnosticMessages();
+ for (const Document::DiagnosticMessage &message : messages) {
++m_processedDiagnostics;
QString type;
@@ -125,7 +126,7 @@ private:
void classifyFiles(const QSet<QString> &files, QStringList *headers, QStringList *sources)
{
- foreach (const QString &file, files) {
+ for (const QString &file : files) {
if (ProjectFile::isSource(ProjectFile::classify(file)))
sources->append(file);
else
@@ -189,7 +190,7 @@ void index(QFutureInterface<void> &indexingFuture,
QStringList headers;
classifyFiles(params.sourceFiles, &headers, &sources);
- foreach (const QString &file, params.sourceFiles)
+ for (const QString &file : qAsConst(params.sourceFiles))
sourceProcessor->removeFromCache(file);
const int sourceCount = sources.size();
diff --git a/src/plugins/cppeditor/clangdiagnosticconfig.cpp b/src/plugins/cppeditor/clangdiagnosticconfig.cpp
index a1aed99a5ce..0dcbbe24f80 100644
--- a/src/plugins/cppeditor/clangdiagnosticconfig.cpp
+++ b/src/plugins/cppeditor/clangdiagnosticconfig.cpp
@@ -52,7 +52,7 @@ void ClangDiagnosticConfig::setDisplayName(const QString &displayName)
m_displayName = displayName;
}
-QStringList ClangDiagnosticConfig::clangOptions() const
+const QStringList ClangDiagnosticConfig::clangOptions() const
{
return m_clangOptions;
}
diff --git a/src/plugins/cppeditor/clangdiagnosticconfig.h b/src/plugins/cppeditor/clangdiagnosticconfig.h
index 6536f0dd902..ced20ca8a35 100644
--- a/src/plugins/cppeditor/clangdiagnosticconfig.h
+++ b/src/plugins/cppeditor/clangdiagnosticconfig.h
@@ -53,7 +53,7 @@ public:
bool isReadOnly() const;
void setIsReadOnly(bool isReadOnly);
- QStringList clangOptions() const;
+ const QStringList clangOptions() const;
void setClangOptions(const QStringList &options);
bool useBuildSystemWarnings() const;
diff --git a/src/plugins/cppeditor/clangdiagnosticconfigsmodel.cpp b/src/plugins/cppeditor/clangdiagnosticconfigsmodel.cpp
index c3794099b58..ead0ef97c91 100644
--- a/src/plugins/cppeditor/clangdiagnosticconfigsmodel.cpp
+++ b/src/plugins/cppeditor/clangdiagnosticconfigsmodel.cpp
@@ -87,23 +87,6 @@ const ClangDiagnosticConfig &ClangDiagnosticConfigsModel::configWithId(const Uti
return m_diagnosticConfigs.at(indexOfConfig(id));
}
-QVector<Utils::Id> ClangDiagnosticConfigsModel::changedOrRemovedConfigs(
- const ClangDiagnosticConfigs &oldConfigs, const ClangDiagnosticConfigs &newConfigs)
-{
- ClangDiagnosticConfigsModel newConfigsModel(newConfigs);
- QVector<Utils::Id> changedConfigs;
-
- for (const ClangDiagnosticConfig &old: oldConfigs) {
- const int i = newConfigsModel.indexOfConfig(old.id());
- if (i == -1)
- changedConfigs.append(old.id()); // Removed
- else if (newConfigsModel.allConfigs().value(i) != old)
- changedConfigs.append(old.id()); // Changed
- }
-
- return changedConfigs;
-}
-
ClangDiagnosticConfig ClangDiagnosticConfigsModel::createCustomConfig(
const ClangDiagnosticConfig &baseConfig, const QString &displayName)
{
diff --git a/src/plugins/cppeditor/clangdiagnosticconfigsmodel.h b/src/plugins/cppeditor/clangdiagnosticconfigsmodel.h
index edc4b164d33..d4b2584d46b 100644
--- a/src/plugins/cppeditor/clangdiagnosticconfigsmodel.h
+++ b/src/plugins/cppeditor/clangdiagnosticconfigsmodel.h
@@ -52,8 +52,6 @@ public:
const ClangDiagnosticConfig &configWithId(const Utils::Id &id) const;
int indexOfConfig(const Utils::Id &id) const;
- static QVector<Utils::Id> changedOrRemovedConfigs(const ClangDiagnosticConfigs &oldConfigs,
- const ClangDiagnosticConfigs &newConfigs);
static ClangDiagnosticConfig createCustomConfig(const ClangDiagnosticConfig &baseConfig,
const QString &displayName);
static QStringList globalDiagnosticOptions();
diff --git a/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp b/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp
index a1de9d125dd..25d438f7952 100644
--- a/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp
+++ b/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp
@@ -33,6 +33,7 @@
#include <QDialog>
#include <QDialogButtonBox>
+#include <QFormLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
@@ -41,20 +42,15 @@ namespace CppEditor {
ClangDiagnosticConfigsSelectionWidget::ClangDiagnosticConfigsSelectionWidget(QWidget *parent)
: QWidget(parent)
- , m_label(new QLabel(tr("Diagnostic configuration:")))
- , m_button(new QPushButton)
{
- auto *layout = new QHBoxLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
- setLayout(layout);
- layout->addWidget(m_label);
- layout->addWidget(m_button, 1);
- layout->addStretch();
+ setUpUi(true);
+}
- connect(m_button,
- &QPushButton::clicked,
- this,
- &ClangDiagnosticConfigsSelectionWidget::onButtonClicked);
+ClangDiagnosticConfigsSelectionWidget::ClangDiagnosticConfigsSelectionWidget(
+ QFormLayout *parentLayout)
+{
+ setUpUi(false);
+ parentLayout->addRow(label(), this);
}
void ClangDiagnosticConfigsSelectionWidget::refresh(const ClangDiagnosticConfigsModel &model,
@@ -79,6 +75,25 @@ ClangDiagnosticConfigs ClangDiagnosticConfigsSelectionWidget::customConfigs() co
return m_diagnosticConfigsModel.customConfigs();
}
+QString ClangDiagnosticConfigsSelectionWidget::label() const
+{
+ return tr("Diagnostic configuration:");
+}
+
+void ClangDiagnosticConfigsSelectionWidget::setUpUi(bool withLabel)
+{
+ m_button = new QPushButton;
+ const auto layout = new QHBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ if (withLabel)
+ layout->addWidget(new QLabel(label()));
+ layout->addWidget(m_button);
+ layout->addStretch();
+
+ connect(m_button, &QPushButton::clicked,
+ this, &ClangDiagnosticConfigsSelectionWidget::onButtonClicked);
+}
+
void ClangDiagnosticConfigsSelectionWidget::onButtonClicked()
{
ClangDiagnosticConfigsWidget *widget = m_createEditWidget(m_diagnosticConfigsModel.allConfigs(),
diff --git a/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.h b/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.h
index 10fdd76039b..e18006c8908 100644
--- a/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.h
+++ b/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.h
@@ -34,7 +34,7 @@
#include <functional>
QT_BEGIN_NAMESPACE
-class QLabel;
+class QFormLayout;
class QPushButton;
QT_END_NAMESPACE
@@ -48,6 +48,7 @@ class CPPEDITOR_EXPORT ClangDiagnosticConfigsSelectionWidget : public QWidget
public:
explicit ClangDiagnosticConfigsSelectionWidget(QWidget *parent = nullptr);
+ explicit ClangDiagnosticConfigsSelectionWidget(QFormLayout *parentLayout);
using CreateEditWidget
= std::function<ClangDiagnosticConfigsWidget *(const ClangDiagnosticConfigs &configs,
@@ -64,13 +65,14 @@ signals:
void changed();
private:
+ QString label() const;
+ void setUpUi(bool withLabel);
void onButtonClicked();
ClangDiagnosticConfigsModel m_diagnosticConfigsModel;
Utils::Id m_currentConfigId;
bool m_showTidyClazyUi = true;
- QLabel *m_label = nullptr;
QPushButton *m_button = nullptr;
CreateEditWidget m_createEditWidget;
diff --git a/src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp b/src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp
index bf70ba4bb64..7e17171d5d5 100644
--- a/src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp
+++ b/src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp
@@ -25,7 +25,7 @@
#include "clangdiagnosticconfigswidget.h"
-#include "cppcodemodelsettings.h"
+#include "clangdiagnosticconfigsmodel.h"
#include "ui_clangdiagnosticconfigswidget.h"
#include "ui_clangbasechecks.h"
diff --git a/src/plugins/cppeditor/compileroptionsbuilder.cpp b/src/plugins/cppeditor/compileroptionsbuilder.cpp
index f92975c8dd7..d663b227bca 100644
--- a/src/plugins/cppeditor/compileroptionsbuilder.cpp
+++ b/src/plugins/cppeditor/compileroptionsbuilder.cpp
@@ -108,20 +108,16 @@ CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart,
UseTweakedHeaderPaths useTweakedHeaderPaths,
UseLanguageDefines useLanguageDefines,
UseBuildSystemWarnings useBuildSystemWarnings,
- const QString &clangVersion,
const FilePath &clangIncludeDirectory)
: m_projectPart(projectPart)
, m_useSystemHeader(useSystemHeader)
, m_useTweakedHeaderPaths(useTweakedHeaderPaths)
, m_useLanguageDefines(useLanguageDefines)
, m_useBuildSystemWarnings(useBuildSystemWarnings)
- , m_clangVersion(clangVersion)
, m_clangIncludeDirectory(clangIncludeDirectory)
{
}
-CompilerOptionsBuilder::~CompilerOptionsBuilder() = default;
-
QStringList CompilerOptionsBuilder::build(ProjectFile::Kind fileKind,
UsePrecompiledHeaders usePrecompiledHeaders)
{
@@ -158,14 +154,17 @@ QStringList CompilerOptionsBuilder::build(ProjectFile::Kind fileKind,
addHeaderPathOptions();
- addExtraOptions();
-
insertWrappedQtHeaders();
insertWrappedMingwHeaders();
return options();
}
+void CompilerOptionsBuilder::provideAdditionalMacros(const ProjectExplorer::Macros &macros)
+{
+ m_additionalMacros = macros;
+}
+
void CompilerOptionsBuilder::add(const QString &arg, bool gccOnlyOption)
{
add(QStringList{arg}, gccOnlyOption);
@@ -350,7 +349,6 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
Internal::HeaderPathFilter filter{
m_projectPart,
m_useTweakedHeaderPaths,
- m_clangVersion,
m_clangIncludeDirectory};
filter.process();
@@ -361,8 +359,6 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
addIncludeDirOptionForPath(headerPath);
if (m_useTweakedHeaderPaths != UseTweakedHeaderPaths::No) {
- QTC_CHECK(!m_clangVersion.isEmpty()
- && "Clang resource directory is required with UseTweakedHeaderPaths::Yes.");
// Exclude all built-in includes and Clang resource directory.
m_options.prepend("-nostdinc++");
@@ -413,6 +409,7 @@ void CompilerOptionsBuilder::addProjectMacros()
}
addMacros(m_projectPart.projectMacros);
+ addMacros(m_additionalMacros);
}
void CompilerOptionsBuilder::addMacros(const Macros &macros)
@@ -476,16 +473,16 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
default:
break;
case LanguageVersion::CXX14:
- option = "/std:c++14";
+ option = "-clang:-std=c++14";
break;
case LanguageVersion::CXX17:
- option = "/std:c++17";
+ option = "-clang:-std=c++17";
break;
case LanguageVersion::CXX20:
- option = "/std:c++20";
+ option = "-clang:-std=c++20";
break;
case LanguageVersion::CXX2b:
- option = "/std:c++latest";
+ option = "-clang:-std=c++2b";
break;
}
@@ -913,12 +910,10 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
theOption[0] = '-';
}
- // Clang-cl (as of Clang 12) frontend doesn't know about -std:c++20
- // but the clang front end knows about -std=c++20
- // https://github.com/llvm/llvm-project/blob/release/12.x/clang/lib/Driver/ToolChains/Clang.cpp#L5855
if (toolChain == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID ||
toolChain == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) {
- theOption.replace("-std:c++20", "-clang:-std=c++20");
+ theOption.replace("-std:c++latest", "-clang:-std=c++2b");
+ theOption.replace("-std:c++", "-clang:-std=c++");
}
m_compilerFlags.flags.append(theOption);
diff --git a/src/plugins/cppeditor/compileroptionsbuilder.h b/src/plugins/cppeditor/compileroptionsbuilder.h
index 6ae97323354..3a0b1e459a9 100644
--- a/src/plugins/cppeditor/compileroptionsbuilder.h
+++ b/src/plugins/cppeditor/compileroptionsbuilder.h
@@ -50,15 +50,14 @@ public:
UseTweakedHeaderPaths useTweakedHeaderPaths = UseTweakedHeaderPaths::No,
UseLanguageDefines useLanguageDefines = UseLanguageDefines::No,
UseBuildSystemWarnings useBuildSystemWarnings = UseBuildSystemWarnings::No,
- const QString &clangVersion = {},
const Utils::FilePath &clangIncludeDirectory = {});
- virtual ~CompilerOptionsBuilder();
QStringList build(ProjectFile::Kind fileKind, UsePrecompiledHeaders usePrecompiledHeaders);
QStringList options() const { return m_options; }
// Add options based on project part
- virtual void addProjectMacros();
+ void provideAdditionalMacros(const ProjectExplorer::Macros &macros);
+ void addProjectMacros();
void addSyntaxOnly();
void addWordWidth();
void addHeaderPathOptions();
@@ -90,13 +89,15 @@ public:
void add(const QString &arg, bool gccOnlyOption = false);
void prepend(const QString &arg);
void add(const QStringList &args, bool gccOnlyOptions = false);
- virtual void addExtraOptions() {}
static UseToolchainMacros useToolChainMacros();
void reset();
void evaluateCompilerFlags();
bool isClStyle() const;
+ void setClStyle(bool clStyle) { m_clStyle = clStyle; }
+
+ const ProjectPart &projectPart() const { return m_projectPart; }
private:
void addIncludeDirOptionForPath(const ProjectExplorer::HeaderPath &path);
@@ -115,9 +116,10 @@ private:
const UseLanguageDefines m_useLanguageDefines;
const UseBuildSystemWarnings m_useBuildSystemWarnings;
- const QString m_clangVersion;
const Utils::FilePath m_clangIncludeDirectory;
+ ProjectExplorer::Macros m_additionalMacros;
+
struct {
QStringList flags;
bool isLanguageVersionSpecified = false;
diff --git a/src/plugins/cppeditor/compileroptionsbuilder_test.cpp b/src/plugins/cppeditor/compileroptionsbuilder_test.cpp
index bd2f92fdaed..6131ce5f023 100644
--- a/src/plugins/cppeditor/compileroptionsbuilder_test.cpp
+++ b/src/plugins/cppeditor/compileroptionsbuilder_test.cpp
@@ -192,7 +192,7 @@ void CompilerOptionsBuilderTest::testLanguageVersionIsExplicitlySetIfNotProvided
UseTweakedHeaderPaths::No, UseLanguageDefines::Yes};
compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
- QVERIFY(compilerOptionsBuilder.options().contains("/std:c++17"));
+ QVERIFY(compilerOptionsBuilder.options().contains("-clang:-std=c++17"));
}
void CompilerOptionsBuilderTest::testAddWordWidth()
@@ -209,13 +209,13 @@ void CompilerOptionsBuilderTest::testHeaderPathOptionsOrder()
TestHelper t;
CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", ""};
+ "/dummy"};
compilerOptionsBuilder.addHeaderPathOptions();
QCOMPARE(compilerOptionsBuilder.options(),
(QStringList{"-nostdinc", "-nostdinc++", "-I", t.toNative("/tmp/path"),
- "-I", t.toNative("/tmp/system_path"), "-isystem", "", "-isystem",
- t.toNative("/tmp/builtin_path")}));
+ "-I", t.toNative("/tmp/system_path"), "-isystem", t.toNative("/dummy"),
+ "-isystem", t.toNative("/tmp/builtin_path")}));
}
void CompilerOptionsBuilderTest::testHeaderPathOptionsOrderMsvc()
@@ -224,14 +224,14 @@ void CompilerOptionsBuilderTest::testHeaderPathOptionsOrderMsvc()
t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", ""};
+ "/dummy"};
compilerOptionsBuilder.evaluateCompilerFlags();
compilerOptionsBuilder.addHeaderPathOptions();
QCOMPARE(compilerOptionsBuilder.options(),
(QStringList{"-nostdinc", "-nostdinc++", "-I", t.toNative("/tmp/path"),
"-I", t.toNative("/tmp/system_path"), "/clang:-isystem",
- "/clang:", "/clang:-isystem",
+ "/clang:" + t.toNative("/dummy"), "/clang:-isystem",
"/clang:" + t.toNative("/tmp/builtin_path")}));
}
@@ -240,13 +240,14 @@ void CompilerOptionsBuilderTest::testUseSystemHeader()
TestHelper t;
CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::Yes,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", ""};
+ "/dummy"};
compilerOptionsBuilder.addHeaderPathOptions();
QCOMPARE(compilerOptionsBuilder.options(),
(QStringList{"-nostdinc", "-nostdinc++", "-I", t.toNative("/tmp/path"),
"-isystem", t.toNative("/tmp/system_path"),
- "-isystem", "", "-isystem", t.toNative("/tmp/builtin_path")}));
+ "-isystem", t.toNative("/dummy"),
+ "-isystem", t.toNative("/tmp/builtin_path")}));
}
void CompilerOptionsBuilderTest::testNoClangHeadersPath()
@@ -272,7 +273,7 @@ void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderMacOs()
t.headerPaths = additionalHeaderPaths + t.headerPaths;
CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", "");
+ "/dummy");
compilerOptionsBuilder.addHeaderPathOptions();
QCOMPARE(compilerOptionsBuilder.options(),
@@ -281,7 +282,7 @@ void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderMacOs()
"-isystem", t.toNative("/usr/include/c++/4.2.1"),
"-isystem", t.toNative("/usr/include/c++/4.2.1/backward"),
"-isystem", t.toNative("/usr/local/include"),
- "-isystem", "",
+ "-isystem", t.toNative("/dummy"),
"-isystem", t.toNative("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include"),
"-isystem", t.toNative("/usr/include"),
"-isystem", t.toNative("/tmp/builtin_path")}));
@@ -301,7 +302,7 @@ void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderLinux()
t.builtIn("/usr/include")};
CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", "");
+ "/dummy");
compilerOptionsBuilder.addHeaderPathOptions();
QCOMPARE(compilerOptionsBuilder.options(),
@@ -310,7 +311,7 @@ void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderLinux()
"-isystem", t.toNative("/usr/include/c++/4.8/backward"),
"-isystem", t.toNative("/usr/include/x86_64-linux-gnu/c++/4.8"),
"-isystem", t.toNative("/usr/local/include"),
- "-isystem", "",
+ "-isystem", t.toNative("/dummy"),
"-isystem", t.toNative("/usr/lib/gcc/x86_64-linux-gnu/4.8/include"),
"-isystem", t.toNative("/usr/include/x86_64-linux-gnu"),
"-isystem", t.toNative("/usr/include")}));
@@ -327,7 +328,7 @@ void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderNoVersio
t.builtIn("C:/mingw530/i686-w64-mingw32/include/c++/backward")};
CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", "");
+ "/dummy");
compilerOptionsBuilder.addHeaderPathOptions();
QCOMPARE(compilerOptionsBuilder.options(),
@@ -335,7 +336,7 @@ void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderNoVersio
"-isystem", t.toNative("C:/mingw530/i686-w64-mingw32/include/c++"),
"-isystem", t.toNative("C:/mingw530/i686-w64-mingw32/include/c++/i686-w64-mingw32"),
"-isystem", t.toNative("C:/mingw530/i686-w64-mingw32/include/c++/backward"),
- "-isystem", "",
+ "-isystem", t.toNative("/dummy"),
"-isystem", t.toNative("C:/mingw530/i686-w64-mingw32/include")}));
}
@@ -351,14 +352,14 @@ void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderAndroidC
t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include")};
CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", "");
+ "/dummy");
compilerOptionsBuilder.addHeaderPathOptions();
QCOMPARE(compilerOptionsBuilder.options(),
(QStringList{"-nostdinc", "-nostdinc++",
"-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include"),
"-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++abi/include"),
- "-isystem", t.toNative(""),
+ "-isystem", t.toNative("/dummy"),
"-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sysroot/usr/include/i686-linux-android"),
"-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sources/android/support/include"),
"-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sysroot/usr/include")}));
@@ -434,8 +435,7 @@ void CompilerOptionsBuilderTest::testInsertWrappedQtHeaders()
{
TestHelper t;
CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::Yes,
- UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", ""};
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No};
compilerOptionsBuilder.insertWrappedQtHeaders();
QVERIFY(Utils::contains(compilerOptionsBuilder.options(),
@@ -446,7 +446,7 @@ void CompilerOptionsBuilderTest::testInsertWrappedMingwHeadersWithNonMingwToolch
{
TestHelper t;
CompilerOptionsBuilder builder{t.finalize(), UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes,
- UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""};
+ UseLanguageDefines::No, UseBuildSystemWarnings::No};
builder.insertWrappedMingwHeaders();
QVERIFY(!Utils::contains(builder.options(),
@@ -458,7 +458,7 @@ void CompilerOptionsBuilderTest::testInsertWrappedMingwHeadersWithMingwToolchain
TestHelper t;
t.toolchainType = Constants::MINGW_TOOLCHAIN_TYPEID;
CompilerOptionsBuilder builder{t.finalize(), UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes,
- UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""};
+ UseLanguageDefines::No, UseBuildSystemWarnings::No};
builder.insertWrappedMingwHeaders();
QVERIFY(Utils::contains(builder.options(),
@@ -600,7 +600,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptions()
t.extraFlags = QStringList{"-arch", "x86_64"};
CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", "");
+ "/dummy");
compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
const QString wrappedQtHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
@@ -614,7 +614,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptions()
"-I", wrappedQtCoreHeadersPath,
"-I", t.toNative("/tmp/path"),
"-I", t.toNative("/tmp/system_path"),
- "-isystem", "",
+ "-isystem", t.toNative("/dummy"),
"-isystem", t.toNative("/tmp/builtin_path")}));
}
@@ -624,7 +624,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvc()
t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", "");
+ "/dummy");
compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
const QString wrappedQtHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
@@ -633,7 +633,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvc()
[&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
QCOMPARE(compilerOptionsBuilder.options(),
(QStringList{"-nostdinc", "-nostdinc++", "--driver-mode=cl", "/Zs", "-m64",
- "--target=x86_64-apple-darwin10", "/TP", "/std:c++17",
+ "--target=x86_64-apple-darwin10", "/TP", "-clang:-std=c++17",
"-fms-compatibility-version=19.00", "-DprojectFoo=projectBar",
"-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"",
"-D__FUNCTION__=\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\"",
@@ -642,7 +642,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvc()
"-I", wrappedQtCoreHeadersPath,
"-I", t.toNative("/tmp/path"),
"-I", t.toNative("/tmp/system_path"),
- "/clang:-isystem", "/clang:",
+ "/clang:-isystem", "/clang:" + t.toNative("/dummy"),
"/clang:-isystem", "/clang:" + t.toNative("/tmp/builtin_path")}));
}
@@ -653,7 +653,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvcWithExceptions()
t.toolchainMacros.append(Macro{"_CPPUNWIND", "1"});
CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
- "dummy_version", "");
+ "/dummy");
compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
const QString wrappedQtHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
@@ -662,7 +662,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvcWithExceptions()
[&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
QCOMPARE(compilerOptionsBuilder.options(),
(QStringList{"-nostdinc", "-nostdinc++", "--driver-mode=cl", "/Zs", "-m64",
- "--target=x86_64-apple-darwin10", "/TP", "/std:c++17", "-fcxx-exceptions",
+ "--target=x86_64-apple-darwin10", "/TP", "-clang:-std=c++17", "-fcxx-exceptions",
"-fexceptions", "-fms-compatibility-version=19.00",
"-DprojectFoo=projectBar",
"-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"",
@@ -672,7 +672,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvcWithExceptions()
"-I", wrappedQtCoreHeadersPath,
"-I", t.toNative("/tmp/path"),
"-I", t.toNative("/tmp/system_path"),
- "/clang:-isystem", "/clang:",
+ "/clang:-isystem", "/clang:" + t.toNative("/dummy"),
"/clang:-isystem", "/clang:" + t.toNative("/tmp/builtin_path")}));
}
diff --git a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp
index 18dac937535..425ff3f657c 100644
--- a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp
+++ b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp
@@ -26,16 +26,19 @@
#include "cppbuiltinmodelmanagersupport.h"
#include "builtineditordocumentprocessor.h"
+#include "cppcanonicalsymbol.h"
#include "cppcompletionassist.h"
+#include "cppeditorwidget.h"
#include "cppelementevaluator.h"
#include "cppfollowsymbolundercursor.h"
#include "cppoverviewmodel.h"
-#include "cpprefactoringengine.h"
#include "cpptoolsreuse.h"
+#include "symbolfinder.h"
#include <app/app_version.h>
#include <texteditor/basehoverhandler.h>
#include <utils/executeondestruction.h>
+#include <utils/qtcassert.h>
#include <QCoreApplication>
@@ -51,6 +54,11 @@ private:
int pos,
ReportPriority report) override
{
+ if (CppModelManager::usesClangd(editorWidget->textDocument())) {
+ report(Priority_None);
+ return;
+ }
+
Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); });
QTextCursor tc(editorWidget->document());
@@ -98,8 +106,7 @@ ModelManagerSupport::Ptr BuiltinModelManagerSupportProvider::createModelManagerS
BuiltinModelManagerSupport::BuiltinModelManagerSupport()
: m_completionAssistProvider(new InternalCompletionAssistProvider),
- m_followSymbol(new FollowSymbolUnderCursor),
- m_refactoringEngine(new CppRefactoringEngine)
+ m_followSymbol(new FollowSymbolUnderCursor)
{
}
@@ -117,29 +124,100 @@ CppCompletionAssistProvider *BuiltinModelManagerSupport::completionAssistProvide
}
-CppCompletionAssistProvider *BuiltinModelManagerSupport::functionHintAssistProvider()
+TextEditor::BaseHoverHandler *BuiltinModelManagerSupport::createHoverHandler()
{
- return nullptr;
+ return new CppHoverHandler;
}
-TextEditor::BaseHoverHandler *BuiltinModelManagerSupport::createHoverHandler()
+std::unique_ptr<AbstractOverviewModel> BuiltinModelManagerSupport::createOverviewModel()
{
- return new CppHoverHandler;
+ return std::make_unique<OverviewModel>();
}
-FollowSymbolInterface &BuiltinModelManagerSupport::followSymbolInterface()
+void BuiltinModelManagerSupport::followSymbol(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback,
+ bool resolveTarget, bool inNextSplit)
{
- return *m_followSymbol;
+ SymbolFinder finder;
+ m_followSymbol->findLink(data, processLinkCallback,
+ resolveTarget, CppModelManager::instance()->snapshot(),
+ data.editorWidget()->semanticInfo().doc, &finder, inNextSplit);
}
-RefactoringEngineInterface &BuiltinModelManagerSupport::refactoringEngineInterface()
+void BuiltinModelManagerSupport::switchDeclDef(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback)
{
- return *m_refactoringEngine;
+ SymbolFinder finder;
+ m_followSymbol->switchDeclDef(data, processLinkCallback,
+ CppModelManager::instance()->snapshot(), data.editorWidget()->semanticInfo().doc,
+ &finder);
}
-std::unique_ptr<AbstractOverviewModel> BuiltinModelManagerSupport::createOverviewModel()
+void BuiltinModelManagerSupport::startLocalRenaming(const CursorInEditor &data,
+ const ProjectPart *,
+ RenameCallback &&renameSymbolsCallback)
{
- return std::make_unique<OverviewModel>();
+ CppEditorWidget *editorWidget = data.editorWidget();
+ QTC_ASSERT(editorWidget, renameSymbolsCallback(QString(), {}, 0); return;);
+ editorWidget->updateSemanticInfo();
+ // Call empty callback
+ renameSymbolsCallback(QString(), {}, data.cursor().document()->revision());
+}
+
+void BuiltinModelManagerSupport::globalRename(const CursorInEditor &data,
+ const QString &replacement)
+{
+ CppModelManager *modelManager = CppModelManager::instance();
+ if (!modelManager)
+ return;
+
+ CppEditorWidget *editorWidget = data.editorWidget();
+ QTC_ASSERT(editorWidget, return;);
+
+ SemanticInfo info = editorWidget->semanticInfo();
+ info.snapshot = modelManager->snapshot();
+ info.snapshot.insert(info.doc);
+ const QTextCursor &cursor = data.cursor();
+ if (const CPlusPlus::Macro *macro = findCanonicalMacro(cursor, info.doc)) {
+ modelManager->renameMacroUsages(*macro, replacement);
+ } else {
+ Internal::CanonicalSymbol cs(info.doc, info.snapshot);
+ CPlusPlus::Symbol *canonicalSymbol = cs(cursor);
+ if (canonicalSymbol)
+ modelManager->renameUsages(canonicalSymbol, cs.context(), replacement);
+ }
+}
+
+void BuiltinModelManagerSupport::findUsages(const CursorInEditor &data) const
+{
+ CppModelManager *modelManager = CppModelManager::instance();
+ if (!modelManager)
+ return;
+
+ CppEditorWidget *editorWidget = data.editorWidget();
+ QTC_ASSERT(editorWidget, return;);
+
+ SemanticInfo info = editorWidget->semanticInfo();
+ info.snapshot = modelManager->snapshot();
+ info.snapshot.insert(info.doc);
+ const QTextCursor &cursor = data.cursor();
+ if (const CPlusPlus::Macro *macro = findCanonicalMacro(cursor, info.doc)) {
+ modelManager->findMacroUsages(*macro);
+ } else {
+ Internal::CanonicalSymbol cs(info.doc, info.snapshot);
+ CPlusPlus::Symbol *canonicalSymbol = cs(cursor);
+ if (canonicalSymbol)
+ modelManager->findUsages(canonicalSymbol, cs.context());
+ }
+}
+
+void BuiltinModelManagerSupport::switchHeaderSource(const Utils::FilePath &filePath,
+ bool inNextSplit)
+{
+ const auto otherFile = Utils::FilePath::fromString(
+ correspondingHeaderOrSource(filePath.toString()));
+ if (!otherFile.isEmpty())
+ openEditor(otherFile, inNextSplit);
}
} // namespace CppEditor::Internal
diff --git a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h
index bf96f227aa1..fed35cf89cc 100644
--- a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h
+++ b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h
@@ -29,6 +29,8 @@
#include <QScopedPointer>
+namespace CppEditor { class FollowSymbolUnderCursor; }
+
namespace CppEditor::Internal {
class BuiltinModelManagerSupport: public ModelManagerSupport
@@ -40,18 +42,27 @@ public:
~BuiltinModelManagerSupport() override;
CppCompletionAssistProvider *completionAssistProvider() final;
- CppCompletionAssistProvider *functionHintAssistProvider() override;
TextEditor::BaseHoverHandler *createHoverHandler() final;
BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) final;
- FollowSymbolInterface &followSymbolInterface() final;
- RefactoringEngineInterface &refactoringEngineInterface() final;
std::unique_ptr<AbstractOverviewModel> createOverviewModel() final;
+ FollowSymbolUnderCursor &followSymbolInterface() { return *m_followSymbol; }
+
private:
+ void followSymbol(const CursorInEditor &data, const Utils::LinkHandler &processLinkCallback,
+ bool resolveTarget, bool inNextSplit) override;
+ void switchDeclDef(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback) override;
+ void startLocalRenaming(const CursorInEditor &data,
+ const ProjectPart *projectPart,
+ RenameCallback &&renameSymbolsCallback) override;
+ void globalRename(const CursorInEditor &data, const QString &replacement) override;
+ void findUsages(const CursorInEditor &data) const override;
+ void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) override;
+
QScopedPointer<CppCompletionAssistProvider> m_completionAssistProvider;
- QScopedPointer<FollowSymbolInterface> m_followSymbol;
- QScopedPointer<RefactoringEngineInterface> m_refactoringEngine;
+ QScopedPointer<FollowSymbolUnderCursor> m_followSymbol;
};
class BuiltinModelManagerSupportProvider : public ModelManagerSupportProvider
diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp
index 2c75a426ed7..fe5b3fca724 100644
--- a/src/plugins/cppeditor/cppchecksymbols.cpp
+++ b/src/plugins/cppeditor/cppchecksymbols.cpp
@@ -97,7 +97,8 @@ protected:
if (!processed->contains(doc->globalNamespace())) {
processed->insert(doc->globalNamespace());
- foreach (const Document::Include &i, doc->resolvedIncludes())
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &i : includes)
process(_snapshot.document(i.resolvedFileName()), processed);
_mainDocument = (doc == _doc); // ### improve
@@ -120,7 +121,7 @@ protected:
addType(q->base());
addType(q->name());
- } else if (name->isNameId() || name->isTemplateNameId()) {
+ } else if (name->asNameId() || name->asTemplateNameId()) {
addType(name->identifier());
}
@@ -131,7 +132,7 @@ protected:
if (!name) {
return;
- } else if (name->isNameId()) {
+ } else if (name->asNameId()) {
const Identifier *id = name->identifier();
_fields.insert(QByteArray::fromRawData(id->chars(), id->size()));
@@ -143,7 +144,7 @@ protected:
if (!name) {
return;
- } else if (name->isNameId()) {
+ } else if (name->asNameId()) {
const Identifier *id = name->identifier();
_functions.insert(QByteArray::fromRawData(id->chars(), id->size()));
}
@@ -154,7 +155,7 @@ protected:
if (!name) {
return;
- } else if (name->isNameId() || name->isTemplateNameId()) {
+ } else if (name->asNameId() || name->asTemplateNameId()) {
const Identifier *id = name->identifier();
_statics.insert(QByteArray::fromRawData(id->chars(), id->size()));
@@ -194,7 +195,7 @@ protected:
if (symbol->isTypedef())
addType(symbol->name());
- else if (!symbol->type()->isFunctionType() && symbol->enclosingScope()->isClass())
+ else if (!symbol->type()->isFunctionType() && symbol->enclosingScope()->asClass())
addField(symbol->name());
return true;
@@ -752,7 +753,8 @@ bool CheckSymbols::visit(NewExpressionAST *ast)
}
Scope *scope = enclosingScope();
- foreach (Symbol *s, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols) {
if (Class *klass = s->asClass()) {
scope = klass;
break;
@@ -787,8 +789,9 @@ void CheckSymbols::checkNamespace(NameAST *name)
getTokenStartPosition(name->firstToken(), &line, &column);
if (ClassOrNamespace *b = _context.lookupType(name->name, enclosingScope())) {
- foreach (Symbol *s, b->symbols()) {
- if (s->isNamespace())
+ const QList<Symbol *> symbols = b->symbols();
+ for (const Symbol *s : symbols) {
+ if (s->asNamespace())
return;
}
}
@@ -809,7 +812,7 @@ bool CheckSymbols::hasVirtualDestructor(Class *klass) const
for (Symbol *s = klass->find(id); s; s = s->next()) {
if (!s->name())
continue;
- if (s->name()->isDestructorNameId()) {
+ if (s->name()->asDestructorNameId()) {
if (Function *funTy = s->type()->asFunctionType()) {
if (funTy->isVirtual() && id->match(s->identifier()))
return true;
@@ -829,7 +832,8 @@ bool CheckSymbols::hasVirtualDestructor(ClassOrNamespace *binding) const
ClassOrNamespace *b = todo.takeFirst();
if (b && !processed.contains(b)) {
processed.insert(b);
- foreach (Symbol *s, b->symbols()) {
+ const QList<Symbol *> symbols = b->symbols();
+ for (Symbol *s : symbols) {
if (Class *k = s->asClass()) {
if (hasVirtualDestructor(k))
return true;
@@ -1006,7 +1010,8 @@ bool CheckSymbols::visit(MemInitializerAST *ast)
if (FunctionDefinitionAST *enclosingFunction = enclosingFunctionDefinition()) {
if (ast->name && enclosingFunction->symbol) {
if (ClassOrNamespace *binding = _context.lookupType(enclosingFunction->symbol)) {
- foreach (Symbol *s, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols) {
if (Class *klass = s->asClass()) {
NameAST *nameAST = ast->name;
if (QualifiedNameAST *q = nameAST->asQualifiedName()) {
@@ -1137,8 +1142,8 @@ bool CheckSymbols::visit(FunctionDefinitionAST *ast)
accept(ast->function_body);
const Internal::LocalSymbols locals(_doc, ast);
- foreach (const QList<Result> &uses, locals.uses) {
- foreach (const Result &u, uses)
+ for (const QList<Result> &uses : qAsConst(locals.uses)) {
+ for (const Result &u : uses)
addUse(u);
}
@@ -1224,7 +1229,7 @@ void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast)
Kind kind = SemanticHighlighter::TypeUse;
const QList<Symbol *> &symbols = b->symbols();
for (const Symbol * const s : symbols) {
- if (s->isNamespace()) {
+ if (s->asNamespace()) {
kind = SemanticHighlighter::NamespaceUse;
break;
}
@@ -1238,8 +1243,8 @@ bool CheckSymbols::isTemplateClass(Symbol *symbol) const
if (symbol) {
if (Template *templ = symbol->asTemplate()) {
if (Symbol *declaration = templ->declaration()) {
- return declaration->isClass()
- || declaration->isForwardClassDeclaration()
+ return declaration->asClass()
+ || declaration->asForwardClassDeclaration()
|| declaration->isTypedef();
}
}
@@ -1257,16 +1262,16 @@ bool CheckSymbols::maybeAddTypeOrStatic(const QList<LookupItem> &candidates, Nam
if (tok.generated())
return false;
- foreach (const LookupItem &r, candidates) {
+ for (const LookupItem &r : candidates) {
Symbol *c = r.declaration();
- if (c->isUsingDeclaration()) // skip using declarations...
+ if (c->asUsingDeclaration()) // skip using declarations...
continue;
- if (c->isUsingNamespaceDirective()) // ... and using namespace directives.
+ if (c->asUsingNamespaceDirective()) // ... and using namespace directives.
continue;
- if (c->isTypedef() || c->isNamespace() ||
+ if (c->isTypedef() || c->asNamespace() ||
c->isStatic() || //consider also static variable
- c->isClass() || c->isEnum() || isTemplateClass(c) ||
- c->isForwardClassDeclaration() || c->isTypenameArgument() || c->enclosingEnum()) {
+ c->asClass() || c->asEnum() || isTemplateClass(c) ||
+ c->asForwardClassDeclaration() || c->asTypenameArgument() || c->enclosingEnum()) {
int line, column;
getTokenStartPosition(startToken, &line, &column);
const unsigned length = tok.utf16chars();
@@ -1274,7 +1279,7 @@ bool CheckSymbols::maybeAddTypeOrStatic(const QList<LookupItem> &candidates, Nam
Kind kind = SemanticHighlighter::TypeUse;
if (c->enclosingEnum() != nullptr)
kind = SemanticHighlighter::EnumerationUse;
- else if (c->isNamespace())
+ else if (c->asNamespace())
kind = SemanticHighlighter::NamespaceUse;
else if (c->isStatic())
// treat static variable as a field(highlighting)
@@ -1300,13 +1305,13 @@ bool CheckSymbols::maybeAddField(const QList<LookupItem> &candidates, NameAST *a
if (tok.generated())
return false;
- foreach (const LookupItem &r, candidates) {
+ for (const LookupItem &r : candidates) {
Symbol *c = r.declaration();
if (!c)
continue;
- if (!c->isDeclaration())
+ if (!c->asDeclaration())
return false;
- if (!(c->enclosingScope() && c->enclosingScope()->isClass()))
+ if (!(c->enclosingScope() && c->enclosingScope()->asClass()))
return false; // shadowed
if (c->isTypedef() || (c->type() && c->type()->isFunctionType()))
return false; // shadowed
@@ -1345,7 +1350,7 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
Kind kind = functionKind == FunctionDeclaration ? SemanticHighlighter::FunctionDeclarationUse
: SemanticHighlighter::FunctionUse;
- foreach (const LookupItem &r, candidates) {
+ for (const LookupItem &r : candidates) {
Symbol *c = r.declaration();
// Skip current if there's no declaration or name.
@@ -1354,7 +1359,7 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
// In addition check for destructors, since the leading ~ is not taken into consideration.
// We don't want to compare destructors with something else or the other way around.
- if (isDestructor != c->name()->isDestructorNameId())
+ if (isDestructor != (c->name()->asDestructorNameId() != nullptr))
continue;
isConstructor = isConstructorDeclaration(c);
diff --git a/src/plugins/cppeditor/cppcodeformatter.cpp b/src/plugins/cppeditor/cppcodeformatter.cpp
index 6df0a44659b..f24778fd2b4 100644
--- a/src/plugins/cppeditor/cppcodeformatter.cpp
+++ b/src/plugins/cppeditor/cppcodeformatter.cpp
@@ -1112,9 +1112,9 @@ void CodeFormatter::dump() const
qDebug() << "Current token index" << m_tokenIndex;
qDebug() << "Current state:";
- foreach (const State &s, m_currentState) {
+ for (const State &s : qAsConst(m_currentState))
qDebug() << metaEnum.valueToKey(s.type) << s.savedIndentDepth << s.savedPaddingDepth;
- }
+
qDebug() << "Current indent depth:" << m_indentDepth;
qDebug() << "Current padding depth:" << m_paddingDepth;
}
diff --git a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
index f5a0a5025af..437461de25e 100644
--- a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
+++ b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
@@ -951,7 +951,7 @@ QVariant SymbolsModel::data(const QModelIndex &index, int role) const
} else if (column == SymbolColumn) {
QString name = Overview().prettyName(symbol->name());
if (name.isEmpty())
- name = QLatin1String(symbol->isBlock() ? "<block>" : "<no name>");
+ name = QLatin1String(symbol->asBlock() ? "<block>" : "<no name>");
return name;
}
}
@@ -1139,8 +1139,9 @@ void ProjectPartsModel::configure(const QList<ProjectInfo::ConstPtr> &projectInf
{
emit layoutAboutToBeChanged();
m_projectPartsList.clear();
- foreach (const ProjectInfo::ConstPtr &info, projectInfos) {
- foreach (const ProjectPart::ConstPtr &projectPart, info->projectParts()) {
+ for (const ProjectInfo::ConstPtr &info : qAsConst(projectInfos)) {
+ const QVector<ProjectPart::ConstPtr> projectParts = info->projectParts();
+ for (const ProjectPart::ConstPtr &projectPart : projectParts) {
if (!m_projectPartsList.contains(projectPart)) {
m_projectPartsList << projectPart;
if (projectPart == currentEditorsProjectPart)
@@ -1160,7 +1161,7 @@ QModelIndex ProjectPartsModel::indexForCurrentEditorsProjectPart() const
ProjectPart::ConstPtr ProjectPartsModel::projectPartForProjectId(const QString &projectPartId) const
{
- foreach (const ProjectPart::ConstPtr &part, m_projectPartsList) {
+ for (const ProjectPart::ConstPtr &part : qAsConst(m_projectPartsList)) {
if (part->id() == projectPartId)
return part;
}
diff --git a/src/plugins/cppeditor/cppcodemodelinspectordumper.cpp b/src/plugins/cppeditor/cppcodemodelinspectordumper.cpp
index 9cd6c4cbaec..62f6173db2c 100644
--- a/src/plugins/cppeditor/cppcodemodelinspectordumper.cpp
+++ b/src/plugins/cppeditor/cppcodemodelinspectordumper.cpp
@@ -411,7 +411,7 @@ QString Utils::partsForFile(const QString &fileName)
const QList<ProjectPart::ConstPtr> parts
= CppModelManager::instance()->projectPart(fileName);
QString result;
- foreach (const ProjectPart::ConstPtr &part, parts)
+ for (const ProjectPart::ConstPtr &part : parts)
result += part->displayName + QLatin1Char(',');
if (result.endsWith(QLatin1Char(',')))
result.chop(1);
@@ -429,7 +429,7 @@ QString Utils::unresolvedFileNameWithDelimiters(const CPlusPlus::Document::Inclu
QString Utils::pathListToString(const QStringList &pathList)
{
QStringList result;
- foreach (const QString &path, pathList)
+ for (const QString &path : pathList)
result << QDir::toNativeSeparators(path);
return result.join(QLatin1Char('\n'));
}
@@ -437,10 +437,10 @@ QString Utils::pathListToString(const QStringList &pathList)
QString Utils::pathListToString(const ProjectExplorer::HeaderPaths &pathList)
{
QStringList result;
- foreach (const ProjectExplorer::HeaderPath &path, pathList) {
+ for (const ProjectExplorer::HeaderPath &path : pathList)
result << QString(QLatin1String("%1 (%2 path)")).arg(
QDir::toNativeSeparators(path.path), toString(path.type));
- }
+
return result.join(QLatin1Char('\n'));
}
@@ -509,12 +509,12 @@ void Dumper::dumpProjectInfos(const QList<ProjectInfo::ConstPtr> &projectInfos)
const QByteArray i4 = indent(4);
m_out << "Projects loaded: " << projectInfos.size() << "{{{1\n";
- foreach (const ProjectInfo::ConstPtr &info, projectInfos) {
+ for (const ProjectInfo::ConstPtr &info : projectInfos) {
m_out << i1 << "Project " << info->projectName()
<< " (" << info->projectFilePath().toUserOutput() << "){{{2\n";
const QVector<ProjectPart::ConstPtr> projectParts = info->projectParts();
- foreach (const ProjectPart::ConstPtr &part, projectParts) {
+ for (const ProjectPart::ConstPtr &part : projectParts) {
QString projectName = QLatin1String("<None>");
QString projectFilePath = "<None>";
if (part->hasProject()) {
@@ -543,7 +543,7 @@ void Dumper::dumpProjectInfos(const QList<ProjectInfo::ConstPtr> &projectInfos)
if (!part->files.isEmpty()) {
m_out << i3 << "Files:{{{4\n";
- foreach (const ProjectFile &projectFile, part->files) {
+ for (const ProjectFile &projectFile : qAsConst(part->files)) {
m_out << i4 << Utils::toString(projectFile.kind) << ": " << projectFile.path;
if (!projectFile.active)
m_out << " (inactive)";
@@ -555,20 +555,20 @@ void Dumper::dumpProjectInfos(const QList<ProjectInfo::ConstPtr> &projectInfos)
m_out << i3 << "Toolchain Defines:{{{4\n";
const QList<QByteArray> defineLines =
ProjectExplorer::Macro::toByteArray(part->toolChainMacros).split('\n');
- foreach (const QByteArray &defineLine, defineLines)
+ for (const QByteArray &defineLine : defineLines)
m_out << i4 << defineLine << "\n";
}
if (!part->projectMacros.isEmpty()) {
m_out << i3 << "Project Defines:{{{4\n";
const QList<QByteArray> defineLines =
ProjectExplorer::Macro::toByteArray(part->projectMacros).split('\n');
- foreach (const QByteArray &defineLine, defineLines)
+ for (const QByteArray &defineLine : defineLines)
m_out << i4 << defineLine << "\n";
}
if (!part->headerPaths.isEmpty()) {
m_out << i3 << "Header Paths:{{{4\n";
- foreach (const ProjectExplorer::HeaderPath &headerPath, part->headerPaths) {
+ for (const ProjectExplorer::HeaderPath &headerPath : qAsConst(part->headerPaths)) {
m_out << i4 << headerPath.path;
printIncludeType(m_out, headerPath.type);
m_out << "\n";
@@ -577,7 +577,7 @@ void Dumper::dumpProjectInfos(const QList<ProjectInfo::ConstPtr> &projectInfos)
if (!part->precompiledHeaders.isEmpty()) {
m_out << i3 << "Precompiled Headers:{{{4\n";
- foreach (const QString &precompiledHeader, part->precompiledHeaders)
+ for (const QString &precompiledHeader : qAsConst(part->precompiledHeaders))
m_out << i4 << precompiledHeader << "\n";
}
} // for part
@@ -601,7 +601,7 @@ void Dumper::dumpSnapshot(const CPlusPlus::Snapshot &snapshot, const QString &ti
// Divide into shared and not shared
QList<CPlusPlus::Document::Ptr> globallyShared;
QList<CPlusPlus::Document::Ptr> notGloballyShared;
- foreach (const CPlusPlus::Document::Ptr &document, documents) {
+ for (const CPlusPlus::Document::Ptr &document : documents) {
CPlusPlus::Document::Ptr globalDocument = m_globalSnapshot.document(document->fileName());
if (globalDocument && globalDocument->fingerprint() == document->fingerprint())
globallyShared.append(document);
@@ -641,7 +641,7 @@ void Dumper::dumpMergedEntities(const ProjectExplorer::HeaderPaths &mergedHeader
const QByteArray i3 = indent(3);
m_out << i2 << "Merged Header Paths{{{2\n";
- foreach (const ProjectExplorer::HeaderPath &hp, mergedHeaderPaths) {
+ for (const ProjectExplorer::HeaderPath &hp : mergedHeaderPaths) {
m_out << i3 << hp.path;
printIncludeType(m_out, hp.type);
m_out << "\n";
@@ -652,7 +652,7 @@ void Dumper::dumpMergedEntities(const ProjectExplorer::HeaderPaths &mergedHeader
void Dumper::dumpStringList(const QStringList &list, const QByteArray &indent)
{
- foreach (const QString &item, list)
+ for (const QString &item : list)
m_out << indent << item << "\n";
}
@@ -661,7 +661,7 @@ void Dumper::dumpDocuments(const QList<CPlusPlus::Document::Ptr> &documents, boo
const QByteArray i2 = indent(2);
const QByteArray i3 = indent(3);
const QByteArray i4 = indent(4);
- foreach (const CPlusPlus::Document::Ptr &document, documents) {
+ for (const CPlusPlus::Document::Ptr &document : documents) {
if (skipDetails) {
m_out << i2 << "\"" << document->fileName() << "\"\n";
continue;
@@ -680,7 +680,7 @@ void Dumper::dumpDocuments(const QList<CPlusPlus::Document::Ptr> &documents, boo
+ document->resolvedIncludes();
if (!includes.isEmpty()) {
m_out << i3 << "Includes:{{{4\n";
- foreach (const CPlusPlus::Document::Include &include, includes) {
+ for (const CPlusPlus::Document::Include &include : includes) {
m_out << i4 << "at line " << include.line() << ": "
<< Utils::unresolvedFileNameWithDelimiters(include) << " ==> "
<< include.resolvedFileName() << "\n";
@@ -691,7 +691,7 @@ void Dumper::dumpDocuments(const QList<CPlusPlus::Document::Ptr> &documents, boo
= document->diagnosticMessages();
if (!diagnosticMessages.isEmpty()) {
m_out << i3 << "Diagnostic Messages:{{{4\n";
- foreach (const CPlusPlus::Document::DiagnosticMessage &msg, diagnosticMessages) {
+ for (const CPlusPlus::Document::DiagnosticMessage &msg : diagnosticMessages) {
const auto level =
static_cast<CPlusPlus::Document::DiagnosticMessage::Level>(msg.level());
m_out << i4 << "at " << msg.line() << ":" << msg.column() << ", " << Utils::toString(level)
@@ -702,14 +702,14 @@ void Dumper::dumpDocuments(const QList<CPlusPlus::Document::Ptr> &documents, boo
const QList<CPlusPlus::Macro> macroDefinitions = document->definedMacros();
if (!macroDefinitions.isEmpty()) {
m_out << i3 << "(Un)Defined Macros:{{{4\n";
- foreach (const CPlusPlus::Macro &macro, macroDefinitions)
+ for (const CPlusPlus::Macro &macro : macroDefinitions)
m_out << i4 << "at line " << macro.line() << ": " << macro.toString() << "\n";
}
const QList<CPlusPlus::Document::MacroUse> macroUses = document->macroUses();
if (!macroUses.isEmpty()) {
m_out << i3 << "Macro Uses:{{{4\n";
- foreach (const CPlusPlus::Document::MacroUse &use, macroUses) {
+ for (const CPlusPlus::Document::MacroUse &use : macroUses) {
const QString type = use.isFunctionLike()
? QLatin1String("function-like") : QLatin1String("object-like");
m_out << i4 << "at line " << use.beginLine() << ", "
diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp
index 9c7f995c064..ccf3c9a4df7 100644
--- a/src/plugins/cppeditor/cppcodemodelsettings.cpp
+++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp
@@ -34,6 +34,7 @@
#include <projectexplorer/session.h>
#include <utils/algorithm.h>
+#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/settingsutils.h>
@@ -42,6 +43,7 @@
#include <QHash>
#include <QPair>
#include <QSettings>
+#include <QStandardPaths>
using namespace Utils;
@@ -53,9 +55,6 @@ static Id initialClangDiagnosticConfigId()
static CppCodeModelSettings::PCHUsage initialPchUsage()
{ return CppCodeModelSettings::PchUse_BuildSystem; }
-static QString clangDiagnosticConfigKey()
-{ return QStringLiteral("ClangDiagnosticConfig"); }
-
static QString enableLowerClazyLevelsKey()
{ return QLatin1String("enableLowerClazyLevels"); }
@@ -78,102 +77,25 @@ static QString clangdIndexingKey() { return QLatin1String("ClangdIndexing"); }
static QString clangdHeaderInsertionKey() { return QLatin1String("ClangdHeaderInsertion"); }
static QString clangdThreadLimitKey() { return QLatin1String("ClangdThreadLimit"); }
static QString clangdDocumentThresholdKey() { return QLatin1String("ClangdDocumentThreshold"); }
+static QString clangdSizeThresholdEnabledKey() { return QLatin1String("ClangdSizeThresholdEnabled"); }
+static QString clangdSizeThresholdKey() { return QLatin1String("ClangdSizeThreshold"); }
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
static QString sessionsWithOneClangdKey() { return QLatin1String("SessionsWithOneClangd"); }
+static QString diagnosticConfigIdKey() { return QLatin1String("diagnosticConfigId"); }
+static QString checkedHardwareKey() { return QLatin1String("checkedHardware"); }
static FilePath g_defaultClangdFilePath;
static FilePath fallbackClangdFilePath()
{
if (g_defaultClangdFilePath.exists())
return g_defaultClangdFilePath;
- return "clangd";
-}
-
-static Id clangDiagnosticConfigIdFromSettings(QSettings *s)
-{
- QTC_ASSERT(s->group() == QLatin1String(Constants::CPPEDITOR_SETTINGSGROUP), return Id());
-
- return Id::fromSetting(
- s->value(clangDiagnosticConfigKey(), initialClangDiagnosticConfigId().toSetting()));
-}
-
-// Removed since Qt Creator 4.11
-static ClangDiagnosticConfigs removedBuiltinConfigs()
-{
- ClangDiagnosticConfigs configs;
-
- // Pedantic
- ClangDiagnosticConfig config;
- config.setId("Builtin.Pedantic");
- config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
- "Pedantic checks"));
- config.setIsReadOnly(true);
- config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")});
- config.setClangTidyMode(ClangDiagnosticConfig::TidyMode::UseCustomChecks);
- config.setClazyMode(ClangDiagnosticConfig::ClazyMode::UseCustomChecks);
- configs << config;
-
- // Everything with exceptions
- config = ClangDiagnosticConfig();
- config.setId("Builtin.EverythingWithExceptions");
- config.setDisplayName(QCoreApplication::translate(
- "ClangDiagnosticConfigsModel",
- "Checks for almost everything"));
- config.setIsReadOnly(true);
- config.setClangOptions(QStringList{
- QStringLiteral("-Weverything"),
- QStringLiteral("-Wno-c++98-compat"),
- QStringLiteral("-Wno-c++98-compat-pedantic"),
- QStringLiteral("-Wno-unused-macros"),
- QStringLiteral("-Wno-newline-eof"),
- QStringLiteral("-Wno-exit-time-destructors"),
- QStringLiteral("-Wno-global-constructors"),
- QStringLiteral("-Wno-gnu-zero-variadic-macro-arguments"),
- QStringLiteral("-Wno-documentation"),
- QStringLiteral("-Wno-shadow"),
- QStringLiteral("-Wno-switch-enum"),
- QStringLiteral("-Wno-missing-prototypes"), // Not optimal for C projects.
- QStringLiteral("-Wno-used-but-marked-unused"), // e.g. QTest::qWait
- });
- config.setClangTidyMode(ClangDiagnosticConfig::TidyMode::UseCustomChecks);
- config.setClazyMode(ClangDiagnosticConfig::ClazyMode::UseCustomChecks);
- configs << config;
-
- return configs;
-}
-
-static ClangDiagnosticConfig convertToCustomConfig(const Id &id)
-{
- const ClangDiagnosticConfig config
- = findOrDefault(removedBuiltinConfigs(), [id](const ClangDiagnosticConfig &config) {
- return config.id() == id;
- });
- return ClangDiagnosticConfigsModel::createCustomConfig(config, config.displayName());
+ return Environment::systemEnvironment().searchInPath("clangd");
}
void CppCodeModelSettings::fromSettings(QSettings *s)
{
s->beginGroup(QLatin1String(Constants::CPPEDITOR_SETTINGSGROUP));
- setClangCustomDiagnosticConfigs(diagnosticConfigsFromSettings(s));
- setClangDiagnosticConfigId(clangDiagnosticConfigIdFromSettings(s));
-
- // Qt Creator 4.11 removes some built-in configs.
- bool write = false;
- const Id id = m_clangDiagnosticConfigId;
- if (id == "Builtin.Pedantic" || id == "Builtin.EverythingWithExceptions") {
- // If one of them was used, continue to use it, but convert it to a custom config.
- const ClangDiagnosticConfig customConfig = convertToCustomConfig(id);
- m_clangCustomDiagnosticConfigs.append(customConfig);
- m_clangDiagnosticConfigId = customConfig.id();
- write = true;
- }
-
- // Before Qt Creator 4.8, inconsistent settings might have been written.
- const ClangDiagnosticConfigsModel model = diagnosticConfigsModel(m_clangCustomDiagnosticConfigs);
- if (!model.hasConfigWithId(m_clangDiagnosticConfigId))
- setClangDiagnosticConfigId(initialClangDiagnosticConfigId());
-
setEnableLowerClazyLevels(s->value(enableLowerClazyLevelsKey(), true).toBool());
const QVariant pchUsageVariant = s->value(pchUsageKey(), initialPchUsage());
@@ -191,21 +113,13 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
s->endGroup();
- if (write)
- toSettings(s);
-
emit changed();
}
void CppCodeModelSettings::toSettings(QSettings *s)
{
s->beginGroup(QLatin1String(Constants::CPPEDITOR_SETTINGSGROUP));
- const ClangDiagnosticConfigs previousConfigs = diagnosticConfigsFromSettings(s);
- const Id previousConfigId = clangDiagnosticConfigIdFromSettings(s);
-
- diagnosticConfigsToSettings(s, m_clangCustomDiagnosticConfigs);
- s->setValue(clangDiagnosticConfigKey(), clangDiagnosticConfigId().toSetting());
s->setValue(enableLowerClazyLevelsKey(), enableLowerClazyLevels());
s->setValue(pchUsageKey(), pchUsage());
@@ -215,53 +129,9 @@ void CppCodeModelSettings::toSettings(QSettings *s)
s->endGroup();
- QVector<Id> invalidated
- = ClangDiagnosticConfigsModel::changedOrRemovedConfigs(previousConfigs,
- m_clangCustomDiagnosticConfigs);
-
- if (previousConfigId != clangDiagnosticConfigId() && !invalidated.contains(previousConfigId))
- invalidated.append(previousConfigId);
-
- if (!invalidated.isEmpty())
- emit clangDiagnosticConfigsInvalidated(invalidated);
emit changed();
}
-Id CppCodeModelSettings::clangDiagnosticConfigId() const
-{
- if (!diagnosticConfigsModel().hasConfigWithId(m_clangDiagnosticConfigId))
- return defaultClangDiagnosticConfigId();
- return m_clangDiagnosticConfigId;
-}
-
-void CppCodeModelSettings::setClangDiagnosticConfigId(const Id &configId)
-{
- m_clangDiagnosticConfigId = configId;
-}
-
-Id CppCodeModelSettings::defaultClangDiagnosticConfigId()
-{
- return initialClangDiagnosticConfigId();
-}
-
-const ClangDiagnosticConfig CppCodeModelSettings::clangDiagnosticConfig() const
-{
- const ClangDiagnosticConfigsModel configsModel = diagnosticConfigsModel(
- m_clangCustomDiagnosticConfigs);
-
- return configsModel.configWithId(clangDiagnosticConfigId());
-}
-
-ClangDiagnosticConfigs CppCodeModelSettings::clangCustomDiagnosticConfigs() const
-{
- return m_clangCustomDiagnosticConfigs;
-}
-
-void CppCodeModelSettings::setClangCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs)
-{
- m_clangCustomDiagnosticConfigs = configs;
-}
-
CppCodeModelSettings::PCHUsage CppCodeModelSettings::pchUsage() const
{
return m_pchUsage;
@@ -335,7 +205,23 @@ ClangdSettings::ClangdSettings()
bool ClangdSettings::useClangd() const
{
- return m_data.useClangd && clangdVersion() >= QVersionNumber(13);
+ return m_data.useClangd && clangdVersion() >= QVersionNumber(14);
+}
+
+void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; }
+
+bool ClangdSettings::hardwareFulfillsRequirements()
+{
+ instance().m_data.haveCheckedHardwareReqirements = true;
+ instance().saveSettings();
+ const quint64 minRam = quint64(12) * 1024 * 1024 * 1024;
+ const Utils::optional<quint64> totalRam = Utils::HostOsInfo::totalMemoryInstalledInBytes();
+ return !totalRam || *totalRam >= minRam;
+}
+
+bool ClangdSettings::haveCheckedHardwareRequirements()
+{
+ return instance().data().haveCheckedHardwareReqirements;
}
void ClangdSettings::setDefaultClangdPath(const FilePath &filePath)
@@ -343,6 +229,14 @@ void ClangdSettings::setDefaultClangdPath(const FilePath &filePath)
g_defaultClangdFilePath = filePath;
}
+void ClangdSettings::setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs)
+{
+ if (instance().customDiagnosticConfigs() == configs)
+ return;
+ instance().m_data.customDiagnosticConfigs = configs;
+ instance().saveSettings();
+}
+
FilePath ClangdSettings::clangdFilePath() const
{
if (!m_data.executableFilePath.isEmpty())
@@ -350,6 +244,28 @@ FilePath ClangdSettings::clangdFilePath() const
return fallbackClangdFilePath();
}
+bool ClangdSettings::sizeIsOkay(const Utils::FilePath &fp) const
+{
+ return !sizeThresholdEnabled() || sizeThresholdInKb() * 1024 >= fp.fileSize();
+}
+
+ClangDiagnosticConfigs ClangdSettings::customDiagnosticConfigs() const
+{
+ return m_data.customDiagnosticConfigs;
+}
+
+Id ClangdSettings::diagnosticConfigId() const
+{
+ if (!diagnosticConfigsModel().hasConfigWithId(m_data.diagnosticConfigId))
+ return initialClangDiagnosticConfigId();
+ return m_data.diagnosticConfigId;
+}
+
+ClangDiagnosticConfig ClangdSettings::diagnosticConfig() const
+{
+ return diagnosticConfigsModel(customDiagnosticConfigs()).configWithId(diagnosticConfigId());
+}
+
ClangdSettings::Granularity ClangdSettings::granularity() const
{
if (m_data.sessionsWithOneClangd.contains(ProjectExplorer::SessionManager::activeSession()))
@@ -398,19 +314,97 @@ QVersionNumber ClangdSettings::clangdVersion(const FilePath &clangdFilePath)
return it->second;
}
+static FilePath getClangHeadersPathFromClang(const FilePath &clangdFilePath)
+{
+ const FilePath clangFilePath = clangdFilePath.absolutePath().pathAppended("clang")
+ .withExecutableSuffix();
+ if (!clangFilePath.exists())
+ return {};
+ QtcProcess clang;
+ clang.setCommand({clangFilePath, {"-print-resource-dir"}});
+ clang.start();
+ if (!clang.waitForFinished())
+ return {};
+ const FilePath resourceDir = FilePath::fromUserInput(QString::fromLocal8Bit(
+ clang.readAllStandardOutput().trimmed()));
+ if (resourceDir.isEmpty() || !resourceDir.exists())
+ return {};
+ const FilePath includeDir = resourceDir.pathAppended("include");
+ if (!includeDir.exists())
+ return {};
+ return includeDir;
+}
+
+static FilePath getClangHeadersPath(const FilePath &clangdFilePath)
+{
+ const FilePath headersPath = getClangHeadersPathFromClang(clangdFilePath);
+ if (!headersPath.isEmpty())
+ return headersPath;
+
+ const QVersionNumber version = ClangdSettings::clangdVersion(clangdFilePath);
+ QTC_ASSERT(!version.isNull(), return {});
+ static const QStringList libDirs{"lib", "lib64"};
+ for (const QString &libDir : libDirs) {
+ const FilePath includePath = clangdFilePath.absolutePath().parentDir().pathAppended(libDir)
+ .pathAppended("clang").pathAppended(version.toString()).pathAppended("include");
+ if (includePath.exists())
+ return includePath;
+ }
+ QTC_CHECK(false);
+ return {};
+}
+
+FilePath ClangdSettings::clangdIncludePath() const
+{
+ QTC_ASSERT(useClangd(), return {});
+ FilePath clangdPath = clangdFilePath();
+ QTC_ASSERT(!clangdPath.isEmpty() && clangdPath.exists(), return {});
+ static QHash<FilePath, FilePath> headersPathCache;
+ const auto it = headersPathCache.constFind(clangdPath);
+ if (it != headersPathCache.constEnd())
+ return *it;
+ const FilePath headersPath = getClangHeadersPath(clangdPath);
+ if (!headersPath.isEmpty())
+ headersPathCache.insert(clangdPath, headersPath);
+ return headersPath;
+}
+
+FilePath ClangdSettings::clangdUserConfigFilePath()
+{
+ return FilePath::fromString(
+ QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation))
+ / "clangd/config.yaml";
+}
+
void ClangdSettings::loadSettings()
{
- Utils::fromSettings(clangdSettingsKey(), {}, Core::ICore::settings(), &m_data);
+ const auto settings = Core::ICore::settings();
+ Utils::fromSettings(clangdSettingsKey(), {}, settings, &m_data);
+
+ settings->beginGroup(QLatin1String(Constants::CPPEDITOR_SETTINGSGROUP));
+ m_data.customDiagnosticConfigs = diagnosticConfigsFromSettings(settings);
+
+ // Pre-8.0 compat
+ static const QString oldKey("ClangDiagnosticConfig");
+ const QVariant configId = settings->value(oldKey);
+ if (configId.isValid()) {
+ m_data.diagnosticConfigId = Id::fromSetting(configId);
+ settings->setValue(oldKey, {});
+ }
+
+ settings->endGroup();
}
void ClangdSettings::saveSettings()
{
- Utils::toSettings(clangdSettingsKey(), {}, Core::ICore::settings(), &m_data);
+ const auto settings = Core::ICore::settings();
+ Utils::toSettings(clangdSettingsKey(), {}, settings, &m_data);
+ settings->beginGroup(QLatin1String(Constants::CPPEDITOR_SETTINGSGROUP));
+ diagnosticConfigsToSettings(settings, m_data.customDiagnosticConfigs);
+ settings->endGroup();
}
#ifdef WITH_TESTS
-void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; }
-
void ClangdSettings::setClangdFilePath(const FilePath &filePath)
{
instance().m_data.executableFilePath = filePath;
@@ -431,6 +425,9 @@ ClangdSettings::Data ClangdProjectSettings::settings() const
// This property is global by definition.
data.sessionsWithOneClangd = ClangdSettings::instance().data().sessionsWithOneClangd;
+ // This list exists only once.
+ data.customDiagnosticConfigs = ClangdSettings::instance().data().customDiagnosticConfigs;
+
return data;
}
@@ -438,6 +435,7 @@ void ClangdProjectSettings::setSettings(const ClangdSettings::Data &data)
{
m_customSettings = data;
saveSettings();
+ ClangdSettings::setCustomDiagnosticConfigs(data.customDiagnosticConfigs);
emit ClangdSettings::instance().changed();
}
@@ -448,6 +446,12 @@ void ClangdProjectSettings::setUseGlobalSettings(bool useGlobal)
emit ClangdSettings::instance().changed();
}
+void ClangdProjectSettings::setDiagnosticConfigId(Utils::Id configId)
+{
+ m_customSettings.diagnosticConfigId = configId;
+ saveSettings();
+}
+
void ClangdProjectSettings::loadSettings()
{
if (!m_project)
@@ -473,13 +477,18 @@ QVariantMap ClangdSettings::Data::toMap() const
{
QVariantMap map;
map.insert(useClangdKey(), useClangd);
- if (executableFilePath != fallbackClangdFilePath())
- map.insert(clangdPathKey(), executableFilePath.toString());
+ map.insert(clangdPathKey(),
+ executableFilePath != fallbackClangdFilePath() ? executableFilePath.toString()
+ : QString());
map.insert(clangdIndexingKey(), enableIndexing);
map.insert(clangdHeaderInsertionKey(), autoIncludeHeaders);
map.insert(clangdThreadLimitKey(), workerThreadLimit);
map.insert(clangdDocumentThresholdKey(), documentUpdateThreshold);
+ map.insert(clangdSizeThresholdEnabledKey(), sizeThresholdEnabled);
+ map.insert(clangdSizeThresholdKey(), sizeThresholdInKb);
map.insert(sessionsWithOneClangdKey(), sessionsWithOneClangd);
+ map.insert(diagnosticConfigIdKey(), diagnosticConfigId.toSetting());
+ map.insert(checkedHardwareKey(), true);
return map;
}
@@ -491,7 +500,12 @@ void ClangdSettings::Data::fromMap(const QVariantMap &map)
autoIncludeHeaders = map.value(clangdHeaderInsertionKey(), false).toBool();
workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt();
documentUpdateThreshold = map.value(clangdDocumentThresholdKey(), 500).toInt();
+ sizeThresholdEnabled = map.value(clangdSizeThresholdEnabledKey(), false).toBool();
+ sizeThresholdInKb = map.value(clangdSizeThresholdKey(), 1024).toLongLong();
sessionsWithOneClangd = map.value(sessionsWithOneClangdKey()).toStringList();
+ diagnosticConfigId = Id::fromSetting(map.value(diagnosticConfigIdKey(),
+ initialClangDiagnosticConfigId().toSetting()));
+ haveCheckedHardwareReqirements = map.value(checkedHardwareKey(), false).toBool();
}
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppcodemodelsettings.h b/src/plugins/cppeditor/cppcodemodelsettings.h
index 7550c011b2d..8cf0bac463c 100644
--- a/src/plugins/cppeditor/cppcodemodelsettings.h
+++ b/src/plugins/cppeditor/cppcodemodelsettings.h
@@ -25,9 +25,11 @@
#pragma once
-#include "clangdiagnosticconfigsmodel.h"
+#include "clangdiagnosticconfig.h"
+#include "cppeditor_global.h"
#include <utils/fileutils.h>
+#include <utils/id.h>
#include <QObject>
#include <QStringList>
@@ -56,14 +58,6 @@ public:
void toSettings(QSettings *s);
public:
- Utils::Id clangDiagnosticConfigId() const;
- void setClangDiagnosticConfigId(const Utils::Id &configId);
- static Utils::Id defaultClangDiagnosticConfigId() ;
- const ClangDiagnosticConfig clangDiagnosticConfig() const;
-
- ClangDiagnosticConfigs clangCustomDiagnosticConfigs() const;
- void setClangCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs);
-
bool enableLowerClazyLevels() const;
void setEnableLowerClazyLevels(bool yesno);
@@ -91,8 +85,6 @@ private:
bool m_interpretAmbigiousHeadersAsCHeaders = false;
bool m_skipIndexingBigFiles = true;
int m_indexerFileSizeLimitInMB = 5;
- ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs;
- Utils::Id m_clangDiagnosticConfigId;
bool m_enableLowerClazyLevels = true; // For UI behavior only
bool m_categorizeFindReferences = false; // Ephemeral!
};
@@ -112,33 +104,54 @@ public:
return s1.useClangd == s2.useClangd
&& s1.executableFilePath == s2.executableFilePath
&& s1.sessionsWithOneClangd == s2.sessionsWithOneClangd
+ && s1.customDiagnosticConfigs == s2.customDiagnosticConfigs
+ && s1.diagnosticConfigId == s2.diagnosticConfigId
&& s1.workerThreadLimit == s2.workerThreadLimit
&& s1.enableIndexing == s2.enableIndexing
&& s1.autoIncludeHeaders == s2.autoIncludeHeaders
- && s1.documentUpdateThreshold == s2.documentUpdateThreshold;
+ && s1.documentUpdateThreshold == s2.documentUpdateThreshold
+ && s1.sizeThresholdEnabled == s2.sizeThresholdEnabled
+ && s1.sizeThresholdInKb == s2.sizeThresholdInKb
+ && s1.haveCheckedHardwareReqirements == s2.haveCheckedHardwareReqirements;
}
friend bool operator!=(const Data &s1, const Data &s2) { return !(s1 == s2); }
Utils::FilePath executableFilePath;
QStringList sessionsWithOneClangd;
+ ClangDiagnosticConfigs customDiagnosticConfigs;
+ Utils::Id diagnosticConfigId;
int workerThreadLimit = 0;
+ int documentUpdateThreshold = 500;
+ qint64 sizeThresholdInKb = 1024;
bool useClangd = true;
bool enableIndexing = true;
bool autoIncludeHeaders = false;
- int documentUpdateThreshold = 500;
+ bool sizeThresholdEnabled = false;
+ bool haveCheckedHardwareReqirements = false;
};
ClangdSettings(const Data &data) : m_data(data) {}
static ClangdSettings &instance();
bool useClangd() const;
+ static void setUseClangd(bool use);
+
+ static bool hardwareFulfillsRequirements();
+ static bool haveCheckedHardwareRequirements();
static void setDefaultClangdPath(const Utils::FilePath &filePath);
+ static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs);
Utils::FilePath clangdFilePath() const;
bool indexingEnabled() const { return m_data.enableIndexing; }
bool autoIncludeHeaders() const { return m_data.autoIncludeHeaders; }
int workerThreadLimit() const { return m_data.workerThreadLimit; }
int documentUpdateThreshold() const { return m_data.documentUpdateThreshold; }
+ qint64 sizeThresholdInKb() const { return m_data.sizeThresholdInKb; }
+ bool sizeThresholdEnabled() const { return m_data.sizeThresholdEnabled; }
+ bool sizeIsOkay(const Utils::FilePath &fp) const;
+ ClangDiagnosticConfigs customDiagnosticConfigs() const;
+ Utils::Id diagnosticConfigId() const;
+ ClangDiagnosticConfig diagnosticConfig() const;
enum class Granularity { Project, Session };
Granularity granularity() const;
@@ -148,9 +161,10 @@ public:
static QVersionNumber clangdVersion(const Utils::FilePath &clangdFilePath);
QVersionNumber clangdVersion() const { return clangdVersion(clangdFilePath()); }
+ Utils::FilePath clangdIncludePath() const;
+ static Utils::FilePath clangdUserConfigFilePath();
#ifdef WITH_TESTS
- static void setUseClangd(bool use);
static void setClangdFilePath(const Utils::FilePath &filePath);
#endif
@@ -175,6 +189,7 @@ public:
void setSettings(const ClangdSettings::Data &data);
bool useGlobalSettings() const { return m_useGlobalSettings; }
void setUseGlobalSettings(bool useGlobal);
+ void setDiagnosticConfigId(Utils::Id configId);
private:
void loadSettings();
diff --git a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp
index bea6d5fe33d..f82649d11f6 100644
--- a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp
+++ b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp
@@ -26,9 +26,9 @@
#include "cppcodemodelsettingspage.h"
#include "ui_cppcodemodelsettingspage.h"
+#include "clangdiagnosticconfigsselectionwidget.h"
#include "clangdiagnosticconfigswidget.h"
#include "cppeditorconstants.h"
-#include "cppmodelmanager.h"
#include "cpptoolsreuse.h"
#include <coreplugin/icore.h>
@@ -39,6 +39,7 @@
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
+#include <QDesktopServices>
#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
@@ -50,6 +51,8 @@
#include <QVBoxLayout>
#include <QVersionNumber>
+#include <limits>
+
namespace CppEditor::Internal {
class CppCodeModelSettingsWidget final : public Core::IOptionsPageWidget
@@ -64,10 +67,8 @@ private:
void apply() final;
void setupGeneralWidgets();
- void setupClangCodeModelWidgets();
bool applyGeneralWidgetsToSettings() const;
- bool applyClangCodeModelWidgetsToSettings() const;
Ui::CppCodeModelSettingsPage *m_ui = nullptr;
CppCodeModelSettings *m_settings = nullptr;
@@ -81,7 +82,6 @@ CppCodeModelSettingsWidget::CppCodeModelSettingsWidget(CppCodeModelSettings *s)
m_settings = s;
setupGeneralWidgets();
- setupClangCodeModelWidgets();
}
CppCodeModelSettingsWidget::~CppCodeModelSettingsWidget()
@@ -91,35 +91,10 @@ CppCodeModelSettingsWidget::~CppCodeModelSettingsWidget()
void CppCodeModelSettingsWidget::apply()
{
- bool changed = false;
-
- changed |= applyGeneralWidgetsToSettings();
- changed |= applyClangCodeModelWidgetsToSettings();
-
- if (changed)
+ if (applyGeneralWidgetsToSettings())
m_settings->toSettings(Core::ICore::settings());
}
-void CppCodeModelSettingsWidget::setupClangCodeModelWidgets()
-{
- m_ui->clangDiagnosticConfigsSelectionWidget
- ->refresh(diagnosticConfigsModel(),
- m_settings->clangDiagnosticConfigId(),
- [](const ClangDiagnosticConfigs &configs, const Utils::Id &configToSelect) {
- return new ClangDiagnosticConfigsWidget(configs, configToSelect);
- });
-
- const bool isClangActive = CppModelManager::instance()->isClangCodeModelActive();
- m_ui->clangCodeModelIsDisabledHint->setVisible(!isClangActive);
- m_ui->clangCodeModelIsEnabledHint->setVisible(isClangActive);
-
- for (int i = 0; i < m_ui->clangDiagnosticConfigsSelectionWidget->layout()->count(); ++i) {
- QWidget *widget = m_ui->clangDiagnosticConfigsSelectionWidget->layout()->itemAt(i)->widget();
- if (widget)
- widget->setEnabled(isClangActive);
- }
-}
-
void CppCodeModelSettingsWidget::setupGeneralWidgets()
{
m_ui->interpretAmbiguousHeadersAsCHeaders->setChecked(
@@ -132,28 +107,6 @@ void CppCodeModelSettingsWidget::setupGeneralWidgets()
m_ui->ignorePCHCheckBox->setChecked(ignorePch);
}
-bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const
-{
- bool changed = false;
-
- const Utils::Id oldConfigId = m_settings->clangDiagnosticConfigId();
- const Utils::Id currentConfigId = m_ui->clangDiagnosticConfigsSelectionWidget->currentConfigId();
- if (oldConfigId != currentConfigId) {
- m_settings->setClangDiagnosticConfigId(currentConfigId);
- changed = true;
- }
-
- const ClangDiagnosticConfigs oldConfigs = m_settings->clangCustomDiagnosticConfigs();
- const ClangDiagnosticConfigs currentConfigs = m_ui->clangDiagnosticConfigsSelectionWidget
- ->customConfigs();
- if (oldConfigs != currentConfigs) {
- m_settings->setClangCustomDiagnosticConfigs(currentConfigs);
- changed = true;
- }
-
- return changed;
-}
-
bool CppCodeModelSettingsWidget::applyGeneralWidgetsToSettings() const
{
bool settingsChanged = false;
@@ -206,10 +159,13 @@ public:
QCheckBox useClangdCheckBox;
QCheckBox indexingCheckBox;
QCheckBox autoIncludeHeadersCheckBox;
+ QCheckBox sizeThresholdCheckBox;
QSpinBox threadLimitSpinBox;
QSpinBox documentUpdateThreshold;
+ QSpinBox sizeThresholdSpinBox;
Utils::PathChooser clangdChooser;
Utils::InfoLabel versionWarningLabel;
+ ClangDiagnosticConfigsSelectionWidget *configSelectionWidget = nullptr;
QGroupBox *sessionsGroupBox = nullptr;
QStringListModel sessionsModel;
};
@@ -243,6 +199,15 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
tr("Defines the amount of time Qt Creator waits before sending document changes to the "
"server.\n"
"If the document changes again while waiting, this timeout resets.\n"));
+ d->sizeThresholdCheckBox.setText(tr("Ignore files greater than"));
+ d->sizeThresholdCheckBox.setChecked(settings.sizeThresholdEnabled());
+ d->sizeThresholdSpinBox.setMinimum(1);
+ d->sizeThresholdSpinBox.setMaximum(std::numeric_limits<int>::max());
+ d->sizeThresholdSpinBox.setSuffix(" KB");
+ d->sizeThresholdSpinBox.setValue(settings.sizeThresholdInKb());
+ d->sizeThresholdSpinBox.setToolTip(tr(
+ "Files greater than this will not be opened as documents in clangd.\n"
+ "The built-in code model will handle highlighting, completion and so on."));
const auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
@@ -265,8 +230,19 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
documentUpdateThresholdLayout->addStretch(1);
const auto documentUpdateThresholdLabel = new QLabel(tr("Document update threshold:"));
formLayout->addRow(documentUpdateThresholdLabel, documentUpdateThresholdLayout);
- layout->addLayout(formLayout);
+ const auto sizeThresholdLayout = new QHBoxLayout;
+ sizeThresholdLayout->addWidget(&d->sizeThresholdSpinBox);
+ sizeThresholdLayout->addStretch(1);
+ formLayout->addRow(&d->sizeThresholdCheckBox, sizeThresholdLayout);
+ d->configSelectionWidget = new ClangDiagnosticConfigsSelectionWidget(formLayout);
+ d->configSelectionWidget->refresh(
+ diagnosticConfigsModel(settings.customDiagnosticConfigs()),
+ settings.diagnosticConfigId(),
+ [](const ClangDiagnosticConfigs &configs, const Utils::Id &configToSelect) {
+ return new CppEditor::ClangDiagnosticConfigsWidget(configs, configToSelect);
+ });
+ layout->addLayout(formLayout);
if (!isForProject) {
d->sessionsModel.setStringList(settingsData.sessionsWithOneClangd);
d->sessionsModel.sort(0);
@@ -324,6 +300,26 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
// TODO: Remove once the concept is functional.
d->sessionsGroupBox->hide();
}
+
+ const auto configFilesHelpLabel = new QLabel;
+ configFilesHelpLabel->setText(tr("Additional settings are available via "
+ "<a href=\"https://clangd.llvm.org/config\"> clangd configuration files</a>.<br>"
+ "General settings go <a href=\"%1\">here</a> "
+ "and can be overridden per project by putting a .clangd file into "
+ "the project source tree.")
+ .arg(ClangdSettings::clangdUserConfigFilePath().toUserOutput()));
+ connect(configFilesHelpLabel, &QLabel::linkHovered, configFilesHelpLabel, &QLabel::setToolTip);
+ connect(configFilesHelpLabel, &QLabel::linkActivated, [](const QString &link) {
+ if (link.startsWith("https"))
+ QDesktopServices::openUrl(link);
+ else
+ Core::EditorManager::openEditor(Utils::FilePath::fromString(link));
+ });
+ const auto separator = new QFrame;
+ separator->setFrameShape(QFrame::HLine);
+ layout->addWidget(separator);
+ layout->addWidget(configFilesHelpLabel);
+
layout->addStretch(1);
static const auto setWidgetsEnabled = [](QLayout *layout, bool enabled, const auto &f) -> void {
@@ -364,9 +360,9 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
"Unexpected clangd output."));
return;
}
- if (clangdVersion < QVersionNumber(13)) {
+ if (clangdVersion < QVersionNumber(14)) {
labelSetter.setWarning(tr("The clangd version is %1, but %2 or greater is required.")
- .arg(clangdVersion.toString()).arg(13));
+ .arg(clangdVersion.toString()).arg(14));
return;
}
};
@@ -381,10 +377,16 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
this, &ClangdSettingsWidget::settingsDataChanged);
connect(&d->threadLimitSpinBox, qOverload<int>(&QSpinBox::valueChanged),
this, &ClangdSettingsWidget::settingsDataChanged);
+ connect(&d->sizeThresholdCheckBox, &QCheckBox::toggled,
+ this, &ClangdSettingsWidget::settingsDataChanged);
+ connect(&d->sizeThresholdSpinBox, qOverload<int>(&QSpinBox::valueChanged),
+ this, &ClangdSettingsWidget::settingsDataChanged);
connect(&d->documentUpdateThreshold, qOverload<int>(&QSpinBox::valueChanged),
this, &ClangdSettingsWidget::settingsDataChanged);
connect(&d->clangdChooser, &Utils::PathChooser::pathChanged,
this, &ClangdSettingsWidget::settingsDataChanged);
+ connect(d->configSelectionWidget, &ClangDiagnosticConfigsSelectionWidget::changed,
+ this, &ClangdSettingsWidget::settingsDataChanged);
}
ClangdSettingsWidget::~ClangdSettingsWidget()
@@ -401,7 +403,11 @@ ClangdSettings::Data ClangdSettingsWidget::settingsData() const
data.autoIncludeHeaders = d->autoIncludeHeadersCheckBox.isChecked();
data.workerThreadLimit = d->threadLimitSpinBox.value();
data.documentUpdateThreshold = d->documentUpdateThreshold.value();
+ data.sizeThresholdEnabled = d->sizeThresholdCheckBox.isChecked();
+ data.sizeThresholdInKb = d->sizeThresholdSpinBox.value();
data.sessionsWithOneClangd = d->sessionsModel.stringList();
+ data.customDiagnosticConfigs = d->configSelectionWidget->customConfigs();
+ data.diagnosticConfigId = d->configSelectionWidget->currentConfigId();
return data;
}
@@ -444,43 +450,35 @@ public:
ClangdProjectSettingsWidget::ClangdProjectSettingsWidget(const ClangdProjectSettings &settings)
: d(new Private(settings))
{
+ setGlobalSettingsId(Constants::CPP_CLANGD_SETTINGS_ID);
const auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
- const auto globalSettingsLayout = new QHBoxLayout;
- globalSettingsLayout->addWidget(&d->useGlobalSettingsCheckBox);
- const auto globalSettingsLabel = new QLabel("Use <a href=\"dummy\">global settings</a>");
- connect(globalSettingsLabel, &QLabel::linkActivated,
- this, [] { Core::ICore::showOptionsDialog(Constants::CPP_CLANGD_SETTINGS_ID); });
- globalSettingsLayout->addWidget(globalSettingsLabel);
- globalSettingsLayout->addStretch(1);
- layout->addLayout(globalSettingsLayout);
-
- const auto separator = new QFrame;
- separator->setFrameShape(QFrame::HLine);
- layout->addWidget(separator);
layout->addWidget(&d->widget);
const auto updateGlobalSettingsCheckBox = [this] {
if (ClangdSettings::instance().granularity() == ClangdSettings::Granularity::Session) {
- d->useGlobalSettingsCheckBox.setEnabled(false);
- d->useGlobalSettingsCheckBox.setChecked(true);
+ setUseGlobalSettingsCheckBoxEnabled(false);
+ setUseGlobalSettings(true);
} else {
- d->useGlobalSettingsCheckBox.setEnabled(true);
- d->useGlobalSettingsCheckBox.setChecked(d->settings.useGlobalSettings());
+ setUseGlobalSettingsCheckBoxEnabled(true);
+ setUseGlobalSettings(d->settings.useGlobalSettings());
}
- d->widget.setEnabled(!d->useGlobalSettingsCheckBox.isChecked());
+ d->widget.setEnabled(!useGlobalSettings());
};
+
updateGlobalSettingsCheckBox();
connect(&ClangdSettings::instance(), &ClangdSettings::changed,
this, updateGlobalSettingsCheckBox);
- connect(&d->useGlobalSettingsCheckBox, &QCheckBox::clicked, [this](bool checked) {
- d->widget.setEnabled(!checked);
- d->settings.setUseGlobalSettings(checked);
- if (!checked)
- d->settings.setSettings(d->widget.settingsData());
- });
- connect(&d->widget, &ClangdSettingsWidget::settingsDataChanged, [this] {
+ connect(this, &ProjectSettingsWidget::useGlobalSettingsChanged, this,
+ [this](bool checked) {
+ d->widget.setEnabled(!checked);
+ d->settings.setUseGlobalSettings(checked);
+ if (!checked)
+ d->settings.setSettings(d->widget.settingsData());
+ });
+
+ connect(&d->widget, &ClangdSettingsWidget::settingsDataChanged, this, [this] {
d->settings.setSettings(d->widget.settingsData());
});
}
diff --git a/src/plugins/cppeditor/cppcodemodelsettingspage.h b/src/plugins/cppeditor/cppcodemodelsettingspage.h
index 6abe21cf2c3..8daae3b9b12 100644
--- a/src/plugins/cppeditor/cppcodemodelsettingspage.h
+++ b/src/plugins/cppeditor/cppcodemodelsettingspage.h
@@ -26,6 +26,7 @@
#pragma once
#include "cppcodemodelsettings.h"
+#include <projectexplorer/projectsettingswidget.h>
#include <coreplugin/dialogs/ioptionspage.h>
@@ -61,7 +62,7 @@ private:
Private * const d;
};
-class ClangdProjectSettingsWidget : public QWidget
+class ClangdProjectSettingsWidget : public ProjectExplorer::ProjectSettingsWidget
{
Q_OBJECT
diff --git a/src/plugins/cppeditor/cppcodemodelsettingspage.ui b/src/plugins/cppeditor/cppcodemodelsettingspage.ui
index e4cf04fcd2e..43b9e70352e 100644
--- a/src/plugins/cppeditor/cppcodemodelsettingspage.ui
+++ b/src/plugins/cppeditor/cppcodemodelsettingspage.ui
@@ -87,49 +87,6 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Clang Code Model</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QLabel" name="clangCodeModelIsEnabledHint">
- <property name="text">
- <string>&lt;i&gt;The Clang Code Model is enabled because the corresponding plugin is loaded.&lt;/i&gt;</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="clangCodeModelIsDisabledHint">
- <property name="text">
- <string>&lt;i&gt;The Clang Code Model is disabled because the corresponding plugin is not loaded.&lt;/i&gt;</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="CppEditor::ClangDiagnosticConfigsSelectionWidget" name="clangDiagnosticConfigsSelectionWidget" native="true"/>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -144,13 +101,6 @@
</item>
</layout>
</widget>
- <customwidgets>
- <customwidget>
- <class>CppEditor::ClangDiagnosticConfigsSelectionWidget</class>
- <extends>QWidget</extends>
- <header>cppeditor/clangdiagnosticconfigsselectionwidget.h</header>
- </customwidget>
- </customwidgets>
<resources/>
<connections/>
</ui>
diff --git a/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp b/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp
index 344e834bcf4..695b5c931d5 100644
--- a/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp
+++ b/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp
@@ -97,9 +97,10 @@ TextEditor::ICodeStylePreferences *CppCodeStylePreferencesFactory::createCodeSty
return new CppCodeStylePreferences();
}
-QWidget *CppCodeStylePreferencesFactory::createEditor(TextEditor::ICodeStylePreferences *preferences,
- ProjectExplorer::Project *project,
- QWidget *parent) const
+TextEditor::CodeStyleEditorWidget *CppCodeStylePreferencesFactory::createEditor(
+ TextEditor::ICodeStylePreferences *preferences,
+ ProjectExplorer::Project *project,
+ QWidget *parent) const
{
auto cppPreferences = qobject_cast<CppCodeStylePreferences *>(preferences);
if (!cppPreferences)
@@ -109,7 +110,7 @@ QWidget *CppCodeStylePreferencesFactory::createEditor(TextEditor::ICodeStylePref
widget->layout()->setContentsMargins(0, 0, 0, 0);
widget->setCodeStyle(cppPreferences);
- const auto tab = additionalTab(project, parent);
+ const auto tab = additionalTab(preferences, project, parent);
widget->addTab(tab.first, tab.second);
return widget;
@@ -130,8 +131,12 @@ QString CppCodeStylePreferencesFactory::previewText() const
return QLatin1String(defaultPreviewText);
}
-std::pair<CppCodeStyleWidget *, QString> CppCodeStylePreferencesFactory::additionalTab(ProjectExplorer::Project *project, QWidget *parent) const
+std::pair<CppCodeStyleWidget *, QString> CppCodeStylePreferencesFactory::additionalTab(
+ TextEditor::ICodeStylePreferences *codeStyle,
+ ProjectExplorer::Project *project,
+ QWidget *parent) const
{
+ Q_UNUSED(codeStyle)
Q_UNUSED(parent)
Q_UNUSED(project)
return {nullptr, ""};
diff --git a/src/plugins/cppeditor/cppcodestylepreferencesfactory.h b/src/plugins/cppeditor/cppcodestylepreferencesfactory.h
index d08baa81467..a2241783dce 100644
--- a/src/plugins/cppeditor/cppcodestylepreferencesfactory.h
+++ b/src/plugins/cppeditor/cppcodestylepreferencesfactory.h
@@ -40,14 +40,16 @@ public:
Utils::Id languageId() override;
QString displayName() override;
TextEditor::ICodeStylePreferences *createCodeStyle() const override;
- QWidget *createEditor(TextEditor::ICodeStylePreferences *settings,
- ProjectExplorer::Project *project,
- QWidget *parent) const override;
+ TextEditor::CodeStyleEditorWidget *createEditor(TextEditor::ICodeStylePreferences *settings,
+ ProjectExplorer::Project *project,
+ QWidget *parent) const override;
TextEditor::Indenter *createIndenter(QTextDocument *doc) const override;
QString snippetProviderGroupId() const override;
QString previewText() const override;
- virtual std::pair<CppCodeStyleWidget *, QString> additionalTab(ProjectExplorer::Project *project,
- QWidget *parent) const;
+ virtual std::pair<CppCodeStyleWidget *, QString> additionalTab(
+ TextEditor::ICodeStylePreferences *codeStyle,
+ ProjectExplorer::Project *project,
+ QWidget *parent) const;
};
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppcodestylesettingspage.cpp b/src/plugins/cppeditor/cppcodestylesettingspage.cpp
index c56f69dc95b..594102a9462 100644
--- a/src/plugins/cppeditor/cppcodestylesettingspage.cpp
+++ b/src/plugins/cppeditor/cppcodestylesettingspage.cpp
@@ -97,7 +97,7 @@ static void applyRefactorings(QTextDocument *textDocument, TextEditorWidget *edi
// ------------------ CppCodeStyleSettingsWidget
CppCodeStylePreferencesWidget::CppCodeStylePreferencesWidget(QWidget *parent)
- : QWidget(parent),
+ : TextEditor::CodeStyleEditorWidget(parent),
m_ui(new Ui::CppCodeStyleSettingsPage)
{
m_ui->setupUi(this);
@@ -307,7 +307,7 @@ void CppCodeStylePreferencesWidget::updatePreview()
const CppCodeStyleSettings ccss = cppCodeStylePreferences->currentCodeStyleSettings();
const TabSettings ts = cppCodeStylePreferences->currentTabSettings();
QtStyleCodeFormatter formatter(ts, ccss);
- foreach (SnippetEditorWidget *preview, m_previews) {
+ for (SnippetEditorWidget *preview : qAsConst(m_previews)) {
preview->textDocument()->setTabSettings(ts);
preview->setCodeStyle(cppCodeStylePreferences);
@@ -329,7 +329,7 @@ void CppCodeStylePreferencesWidget::updatePreview()
void CppCodeStylePreferencesWidget::decorateEditors(const FontSettings &fontSettings)
{
- foreach (SnippetEditorWidget *editor, m_previews) {
+ for (SnippetEditorWidget *editor : qAsConst(m_previews)) {
editor->textDocument()->setFontSettings(fontSettings);
SnippetProvider::decorateEditor(editor, CppEditor::Constants::CPP_SNIPPETS_GROUP_ID);
}
@@ -337,7 +337,7 @@ void CppCodeStylePreferencesWidget::decorateEditors(const FontSettings &fontSett
void CppCodeStylePreferencesWidget::setVisualizeWhitespace(bool on)
{
- foreach (SnippetEditorWidget *editor, m_previews) {
+ for (SnippetEditorWidget *editor : qAsConst(m_previews)) {
DisplaySettings displaySettings = editor->displaySettings();
displaySettings.m_visualizeWhitespace = on;
editor->setDisplaySettings(displaySettings);
@@ -346,7 +346,9 @@ void CppCodeStylePreferencesWidget::setVisualizeWhitespace(bool on)
void CppCodeStylePreferencesWidget::addTab(CppCodeStyleWidget *page, QString tabName)
{
- QTC_ASSERT(page, return);
+ if (!page)
+ return;
+
m_ui->categoryTab->addTab(page, tabName);
connect(page, &CppEditor::CppCodeStyleWidget::codeStyleSettingsChanged,
@@ -363,9 +365,17 @@ void CppCodeStylePreferencesWidget::addTab(CppCodeStyleWidget *page, QString tab
connect(this, &CppCodeStylePreferencesWidget::tabSettingsChanged,
page, &CppCodeStyleWidget::setTabSettings);
+ connect(this, &CppCodeStylePreferencesWidget::applyEmitted,
+ page, &CppCodeStyleWidget::apply);
+
page->synchronize();
}
+void CppCodeStylePreferencesWidget::apply()
+{
+ emit applyEmitted();
+}
+
// ------------------ CppCodeStyleSettingsPage
CppCodeStyleSettingsPage::CppCodeStyleSettingsPage()
diff --git a/src/plugins/cppeditor/cppcodestylesettingspage.h b/src/plugins/cppeditor/cppcodestylesettingspage.h
index 7c04185165f..14c2eeb27b0 100644
--- a/src/plugins/cppeditor/cppcodestylesettingspage.h
+++ b/src/plugins/cppeditor/cppcodestylesettingspage.h
@@ -66,7 +66,7 @@ namespace Internal {
namespace Ui { class CppCodeStyleSettingsPage; }
-class CppCodeStylePreferencesWidget : public QWidget
+class CppCodeStylePreferencesWidget : public TextEditor::CodeStyleEditorWidget
{
Q_OBJECT
public:
@@ -75,6 +75,7 @@ public:
void setCodeStyle(CppCodeStylePreferences *codeStylePreferences);
void addTab(CppCodeStyleWidget *page, QString tabName);
+ void apply() override;
private:
void decorateEditors(const TextEditor::FontSettings &fontSettings);
@@ -96,6 +97,7 @@ private:
signals:
void codeStyleSettingsChanged(const CppEditor::CppCodeStyleSettings &);
void tabSettingsChanged(const TextEditor::TabSettings &);
+ void applyEmitted();
};
diff --git a/src/plugins/cppeditor/cppcodestylesnippets.h b/src/plugins/cppeditor/cppcodestylesnippets.h
index d58a728f233..83cb3555d54 100644
--- a/src/plugins/cppeditor/cppcodestylesnippets.h
+++ b/src/plugins/cppeditor/cppcodestylesnippets.h
@@ -135,6 +135,12 @@ static const char *DEFAULT_CODE_STYLE_SNIPPETS[]
"private:\n"
" int _a;\n"
" };\n"
+ "enum class E\n"
+ "{\n"
+ " V1,\n"
+ " V2,\n"
+ " V3\n"
+ "};\n"
"}\n"
"}\n",
"#include \"bar.h\"\n"
diff --git a/src/plugins/cppeditor/cppcompletion_test.cpp b/src/plugins/cppeditor/cppcompletion_test.cpp
index 532acd6b533..d03c4b8390f 100644
--- a/src/plugins/cppeditor/cppcompletion_test.cpp
+++ b/src/plugins/cppeditor/cppcompletion_test.cpp
@@ -105,9 +105,12 @@ public:
QStringList completions;
LanguageFeatures languageFeatures = LanguageFeatures::defaultFeatures();
languageFeatures.objCEnabled = false;
+ QTextCursor textCursor = m_editorWidget->textCursor();
+ textCursor.setPosition(m_position);
+ m_editorWidget->setTextCursor(textCursor);
CppCompletionAssistInterface *ai
= new CppCompletionAssistInterface(m_editorWidget->textDocument()->filePath(),
- m_textDocument, m_position,
+ m_editorWidget,
ExplicitlyInvoked, m_snapshot,
ProjectExplorer::HeaderPaths(),
languageFeatures);
@@ -277,7 +280,7 @@ void CompletionTest::testCompletionTemplateFunction()
QStringList actualCompletions = test.getCompletions();
QString errorPattern(QLatin1String("Completion not found: %1"));
- foreach (const QString &completion, expectedCompletions) {
+ for (const QString &completion : qAsConst(expectedCompletions)) {
QByteArray errorMessage = errorPattern.arg(completion).toUtf8();
QVERIFY2(actualCompletions.contains(completion), errorMessage.data());
}
@@ -371,7 +374,7 @@ void CompletionTest::testGlobalCompletion_data()
"<REPLACEMENT>\n"
"@\n";
const QStringList replacements = QStringList({"// text", "// text.", "/// text", "/// text."});
- foreach (const QString &replacement, replacements) {
+ for (const QString &replacement : replacements) {
QByteArray code = codeTemplate;
code.replace("<REPLACEMENT>", replacement.toUtf8());
const QByteArray tag = _("completion after comment: ") + replacement.toUtf8();
diff --git a/src/plugins/cppeditor/cppcompletionassist.cpp b/src/plugins/cppeditor/cppcompletionassist.cpp
index ee04a159570..672ca389b12 100644
--- a/src/plugins/cppeditor/cppcompletionassist.cpp
+++ b/src/plugins/cppeditor/cppcompletionassist.cpp
@@ -42,9 +42,9 @@
#include <texteditor/texteditorsettings.h>
#include <texteditor/completionsettings.h>
-#include <utils/textutils.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
+#include <utils/textutils.h>
#include <cplusplus/BackwardsScanner.h>
#include <cplusplus/CppRewriter.h>
@@ -232,7 +232,7 @@ void CppAssistProposalItem::applyContextualContent(TextDocumentManipulatorInterf
// except when it might take template parameters.
if (!function->hasReturnType()
&& (function->unqualifiedName()
- && !function->unqualifiedName()->isDestructorNameId())) {
+ && !function->unqualifiedName()->asDestructorNameId())) {
// Don't insert any magic, since the user might have just wanted to select the class
/// ### port me
@@ -426,7 +426,6 @@ AssistInterface *InternalCompletionAssistProvider::createAssistInterface(
const Utils::FilePath &filePath,
const TextEditorWidget *textEditorWidget,
const LanguageFeatures &languageFeatures,
- int position,
AssistReason reason) const
{
QTC_ASSERT(textEditorWidget, return nullptr);
@@ -435,7 +434,6 @@ AssistInterface *InternalCompletionAssistProvider::createAssistInterface(
textEditorWidget,
BuiltinEditorDocumentParser::get(filePath.toString()),
languageFeatures,
- position,
reason,
CppModelManager::instance()->workingCopy());
}
@@ -490,7 +488,7 @@ public:
AssistProposalItem *operator()(Symbol *symbol)
{
//using declaration can be qualified
- if (!symbol || !symbol->name() || (symbol->name()->isQualifiedNameId()
+ if (!symbol || !symbol->name() || (symbol->name()->asQualifiedNameId()
&& !symbol->asUsingDeclaration()))
return nullptr;
@@ -528,7 +526,7 @@ protected:
void visit(const Identifier *name) override
{
_item = newCompletionItem(name);
- if (!_symbol->isScope() || _symbol->isFunction())
+ if (!_symbol->asScope() || _symbol->asFunction())
_item->setDetail(overview.prettyType(_symbol->type(), name));
}
@@ -790,7 +788,8 @@ Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &co
if (!b)
return nullptr;
- foreach (Symbol *s, b->symbols()) {
+ const QList<Symbol *> symbols = b->symbols();
+ for (Symbol *s : symbols) {
if (Class *klass = s->asClass())
return klass;
}
@@ -1105,7 +1104,7 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
const QList<LookupItem> items = (*m_model->m_typeOfExpression)(expr.toUtf8(), scope);
LookupContext lookupContext(thisDocument, m_interface->snapshot());
- foreach (const LookupItem &item, items) {
+ for (const LookupItem &item : items) {
FullySpecifiedType ty = item.type().simplified();
if (ty->isPointerType()) {
ty = ty->asPointerType()->elementType().simplified();
@@ -1169,12 +1168,14 @@ void InternalCppCompletionAssistProcessor::completeObjCMsgSend(ClassOrNamespace
bool staticClassAccess)
{
QList<Scope*> memberScopes;
- foreach (Symbol *s, binding->symbols()) {
+
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols) {
if (ObjCClass *c = s->asObjCClass())
memberScopes.append(c);
}
- foreach (Scope *scope, memberScopes) {
+ for (Scope *scope : qAsConst(memberScopes)) {
for (int i = 0; i < scope->memberCount(); ++i) {
Symbol *symbol = scope->memberAt(i);
@@ -1239,7 +1240,7 @@ bool InternalCppCompletionAssistProcessor::completeInclude(const QTextCursor &cu
const QStringList suffixes = Utils::mimeTypeForName(QLatin1String("text/x-c++hdr")).suffixes();
- foreach (const ProjectExplorer::HeaderPath &headerPath, headerPaths) {
+ for (const ProjectExplorer::HeaderPath &headerPath : qAsConst(headerPaths)) {
QString realPath = headerPath.path;
if (!directoryPrefix.isEmpty()) {
realPath += QLatin1Char('/');
@@ -1272,7 +1273,8 @@ void InternalCppCompletionAssistProcessor::completeInclude(const QString &realPa
void InternalCppCompletionAssistProcessor::completePreprocessor()
{
- foreach (const QString &preprocessorCompletion, preprocessorCompletions())
+ const QStringList preprocessorCompletionList = preprocessorCompletions();
+ for (const QString &preprocessorCompletion : preprocessorCompletionList)
addCompletionItem(preprocessorCompletion);
if (objcKeywordsWanted())
@@ -1351,7 +1353,7 @@ int InternalCppCompletionAssistProcessor::startCompletionInternal(const QString
TypeOfExpression::Preprocess);
// If it's a class, add completions for the constructors
- foreach (const LookupItem &result, results) {
+ for (const LookupItem &result : results) {
if (result.type()->isClassType()) {
if (completeConstructorOrFunction(results, endOfExpression, true))
return m_positionForProposal;
@@ -1439,7 +1441,7 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
if (ClassOrNamespace *binding = context.lookupType(scope)) {
for (int i = 0; i < scope->memberCount(); ++i) {
Symbol *member = scope->memberAt(i);
- if (member->isEnum()) {
+ if (member->asEnum()) {
if (ClassOrNamespace *b = binding->findBlock(block))
completeNamespace(b);
}
@@ -1449,21 +1451,21 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
if (ClassOrNamespace *b = binding->lookupType(u->name()))
usingBindings.append(b);
} else if (Class *c = member->asClass()) {
- if (c->name()->isAnonymousNameId()) {
+ if (c->name()->asAnonymousNameId()) {
if (ClassOrNamespace *b = binding->findBlock(block))
completeClass(b);
}
}
}
}
- } else if (scope->isFunction() || scope->isClass() || scope->isNamespace()) {
+ } else if (scope->asFunction() || scope->asClass() || scope->asNamespace()) {
currentBinding = context.lookupType(scope);
break;
}
}
for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) {
- if (scope->isBlock()) {
+ if (scope->asBlock()) {
for (int i = 0; i < scope->memberCount(); ++i)
addCompletionItem(scope->memberAt(i), FunctionLocalsOrder);
} else if (Function *fun = scope->asFunction()) {
@@ -1482,20 +1484,21 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
break;
processed.insert(currentBinding);
- foreach (ClassOrNamespace* u, currentBinding->usings())
+ const QList<ClassOrNamespace*> usings = currentBinding->usings();
+ for (ClassOrNamespace* u : usings)
usingBindings.append(u);
const QList<Symbol *> symbols = currentBinding->symbols();
if (!symbols.isEmpty()) {
- if (symbols.first()->isClass())
+ if (symbols.first()->asClass())
completeClass(currentBinding);
else
completeNamespace(currentBinding);
}
}
- foreach (ClassOrNamespace *b, usingBindings)
+ for (ClassOrNamespace *b : qAsConst(usingBindings))
completeNamespace(b);
addKeywords();
@@ -1547,7 +1550,7 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
if (results.isEmpty())
return false;
- foreach (const LookupItem &result, results) {
+ for (const LookupItem &result : results) {
FullySpecifiedType ty = result.type();
Scope *scope = result.scope();
@@ -1564,7 +1567,7 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
}
// it can be class defined inside a block
- if (classTy->enclosingScope()->isBlock()) {
+ if (classTy->enclosingScope()->asBlock()) {
if (ClassOrNamespace *b = context.lookupType(classTy->name(), classTy->enclosingScope())) {
completeClass(b);
break;
@@ -1587,7 +1590,7 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
} else if (Enum *e = ty->asEnumType()) {
// it can be class defined inside a block
- if (e->enclosingScope()->isBlock()) {
+ if (e->enclosingScope()->asBlock()) {
if (ClassOrNamespace *b = context.lookupType(e)) {
Block *block = e->enclosingScope()->asBlock();
if (ClassOrNamespace *bb = b->findBlock(block)) {
@@ -1625,12 +1628,14 @@ void InternalCppCompletionAssistProcessor::completeNamespace(ClassOrNamespace *b
QList<Scope *> scopesToVisit;
QSet<Scope *> scopesVisited;
- foreach (Symbol *bb, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *bb : symbols) {
if (Scope *scope = bb->asScope())
scopesToVisit.append(scope);
}
- foreach (Enum *e, binding->unscopedEnums())
+ const QList<Enum *> enums = binding->unscopedEnums();
+ for (Enum *e : enums)
scopesToVisit.append(e);
while (!scopesToVisit.isEmpty()) {
@@ -1665,14 +1670,16 @@ void InternalCppCompletionAssistProcessor::completeClass(ClassOrNamespace *b, bo
QList<Scope *> scopesToVisit;
QSet<Scope *> scopesVisited;
- foreach (Symbol *bb, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *bb : symbols) {
if (Class *k = bb->asClass())
scopesToVisit.append(k);
else if (Block *b = bb->asBlock())
scopesToVisit.append(b);
}
- foreach (Enum *e, binding->unscopedEnums())
+ const QList<Enum *> enums = binding->unscopedEnums();
+ for (Enum *e : enums)
scopesToVisit.append(e);
while (!scopesToVisit.isEmpty()) {
@@ -1701,18 +1708,18 @@ void InternalCppCompletionAssistProcessor::addClassMembersToCompletion(Scope *sc
for (Scope::iterator it = scope->memberBegin(); it != scope->memberEnd(); ++it) {
Symbol *member = *it;
if (member->isFriend()
- || member->isQtPropertyDeclaration()
- || member->isQtEnum()) {
+ || member->asQtPropertyDeclaration()
+ || member->asQtEnum()) {
continue;
} else if (!staticLookup && (member->isTypedef() ||
- member->isEnum() ||
- member->isClass())) {
+ member->asEnum() ||
+ member->asClass())) {
continue;
- } else if (member->isClass() && member->name()->isAnonymousNameId()) {
+ } else if (member->asClass() && member->name()->asAnonymousNameId()) {
nestedAnonymouses.insert(member->asClass());
- } else if (member->isDeclaration()) {
+ } else if (member->asDeclaration()) {
Class *declTypeAsClass = member->asDeclaration()->type()->asClassType();
- if (declTypeAsClass && declTypeAsClass->name()->isAnonymousNameId())
+ if (declTypeAsClass && declTypeAsClass->name()->asAnonymousNameId())
nestedAnonymouses.erase(declTypeAsClass);
}
@@ -1740,7 +1747,7 @@ bool InternalCppCompletionAssistProcessor::completeQtMethod(const QList<LookupIt
o.showFunctionSignatures = true;
QSet<QString> signatures;
- foreach (const LookupItem &lookupItem, results) {
+ for (const LookupItem &lookupItem : results) {
ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context);
if (!b)
continue;
@@ -1754,7 +1761,8 @@ bool InternalCppCompletionAssistProcessor::completeQtMethod(const QList<LookupIt
if (!processed.contains(binding)) {
processed.insert(binding);
- foreach (Symbol *s, binding->symbols())
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols)
if (Class *clazz = s->asClass())
scopes.append(clazz);
@@ -1764,7 +1772,7 @@ bool InternalCppCompletionAssistProcessor::completeQtMethod(const QList<LookupIt
const bool wantSignals = type == CompleteQt4Signals || type == CompleteQt5Signals;
const bool wantQt5SignalOrSlot = type == CompleteQt5Signals || type == CompleteQt5Slots;
- foreach (Scope *scope, scopes) {
+ for (Scope *scope : qAsConst(scopes)) {
Class *klass = scope->asClass();
if (!klass)
continue;
@@ -1821,7 +1829,7 @@ bool InternalCppCompletionAssistProcessor::completeQtMethodClassName(
const QIcon classIcon = Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Class);
Overview overview;
- foreach (const LookupItem &lookupItem, results) {
+ for (const LookupItem &lookupItem : results) {
Class *klass = classFromLookupItem(lookupItem, context);
if (!klass)
continue;
@@ -1864,7 +1872,7 @@ void InternalCppCompletionAssistProcessor::addMacros(const QString &fileName,
addMacros_helper(snapshot, fileName, &processed, &definedMacros);
- foreach (const QString &macroName, definedMacros)
+ for (const QString &macroName : qAsConst(definedMacros))
addCompletionItem(macroName, Icons::macroIcon(), MacrosOrder);
}
@@ -1880,10 +1888,12 @@ void InternalCppCompletionAssistProcessor::addMacros_helper(const Snapshot &snap
processed->insert(doc->fileName());
- foreach (const Document::Include &i, doc->resolvedIncludes())
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &i : includes)
addMacros_helper(snapshot, i.resolvedFileName(), processed, definedMacros);
- foreach (const CPlusPlus::Macro &macro, doc->definedMacros()) {
+ const QList<CPlusPlus::Macro> macros = doc->definedMacros();
+ for (const CPlusPlus::Macro &macro : macros) {
const QString macroName = macro.nameToQString();
if (!macro.isHidden())
definedMacros->insert(macroName);
@@ -1899,7 +1909,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
const LookupContext &context = m_model->m_typeOfExpression->context();
QList<Function *> functions;
- foreach (const LookupItem &result, results) {
+ for (const LookupItem &result : results) {
FullySpecifiedType exprTy = result.type().simplified();
if (Class *klass = asClassOrTemplateClassType(exprTy)) {
@@ -1914,7 +1924,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
if (!memberName)
continue; // skip anonymous member.
- else if (memberName->isQualifiedNameId())
+ else if (memberName->asQualifiedNameId())
continue; // skip
if (Function *funTy = member->type()->asFunctionType()) {
@@ -1930,7 +1940,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
}
if (functions.isEmpty()) {
- foreach (const LookupItem &result, results) {
+ for (const LookupItem &result : results) {
FullySpecifiedType ty = result.type().simplified();
if (Function *fun = asFunctionOrTemplateFunctionType(ty)) {
@@ -1945,7 +1955,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
bool newOverload = true;
- foreach (Function *f, functions) {
+ for (Function *f : qAsConst(functions)) {
if (fun->match(f)) {
newOverload = false;
break;
@@ -1961,13 +1971,14 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
if (functions.isEmpty()) {
const Name *functionCallOp = context.bindings()->control()->operatorNameId(OperatorNameId::FunctionCallOp);
- foreach (const LookupItem &result, results) {
+ for (const LookupItem &result : results) {
FullySpecifiedType ty = result.type().simplified();
Scope *scope = result.scope();
if (NamedType *namedTy = ty->asNamedType()) {
if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) {
- foreach (const LookupItem &r, b->lookup(functionCallOp)) {
+ const QList<LookupItem> items = b->lookup(functionCallOp);
+ for (const LookupItem &r : items) {
Symbol *overload = r.declaration();
FullySpecifiedType overloadTy = overload->type().simplified();
@@ -2004,7 +2015,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
Scope *sc = context.thisDocument()->scopeAt(line, column);
- if (sc && (sc->isClass() || sc->isNamespace())) {
+ if (sc && (sc->asClass() || sc->asNamespace())) {
// It may still be a function call. If the whole line parses as a function
// declaration, we should be certain that it isn't.
bool autocompleteSignature = false;
@@ -2057,7 +2068,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
Control *control = context.bindings()->control().data();
// set up signature autocompletion
- foreach (Function *f, functions) {
+ for (Function *f : qAsConst(functions)) {
Overview overview;
overview.showArgumentNames = true;
overview.showDefaultArguments = false;
diff --git a/src/plugins/cppeditor/cppcompletionassist.h b/src/plugins/cppeditor/cppcompletionassist.h
index 1d477cff792..674f6bf4a78 100644
--- a/src/plugins/cppeditor/cppcompletionassist.h
+++ b/src/plugins/cppeditor/cppcompletionassist.h
@@ -87,7 +87,6 @@ public:
const Utils::FilePath &filePath,
const TextEditor::TextEditorWidget *textEditorWidget,
const CPlusPlus::LanguageFeatures &languageFeatures,
- int position,
TextEditor::AssistReason reason) const override;
};
@@ -168,10 +167,9 @@ public:
const TextEditor::TextEditorWidget *textEditorWidget,
BuiltinEditorDocumentParser::Ptr parser,
const CPlusPlus::LanguageFeatures &languageFeatures,
- int position,
TextEditor::AssistReason reason,
const WorkingCopy &workingCopy)
- : TextEditor::AssistInterface(textEditorWidget->document(), position, filePath, reason)
+ : TextEditor::AssistInterface(textEditorWidget->textCursor(), filePath, reason)
, m_parser(parser)
, m_gotCppSpecifics(false)
, m_workingCopy(workingCopy)
@@ -179,13 +177,12 @@ public:
{}
CppCompletionAssistInterface(const Utils::FilePath &filePath,
- QTextDocument *textDocument,
- int position,
+ const TextEditor::TextEditorWidget *textEditorWidget,
TextEditor::AssistReason reason,
const CPlusPlus::Snapshot &snapshot,
const ProjectExplorer::HeaderPaths &headerPaths,
const CPlusPlus::LanguageFeatures &features)
- : TextEditor::AssistInterface(textDocument, position, filePath, reason)
+ : TextEditor::AssistInterface(textEditorWidget->textCursor(), filePath, reason)
, m_gotCppSpecifics(true)
, m_snapshot(snapshot)
, m_headerPaths(headerPaths)
@@ -197,6 +194,7 @@ public:
{ getCppSpecifics(); return m_headerPaths; }
CPlusPlus::LanguageFeatures languageFeatures() const
{ getCppSpecifics(); return m_languageFeatures; }
+ bool isBaseObject() const override { return false; }
private:
void getCppSpecifics() const;
diff --git a/src/plugins/cppeditor/cppcompletionassistprovider.h b/src/plugins/cppeditor/cppcompletionassistprovider.h
index eb9410973a2..bd851b0d02c 100644
--- a/src/plugins/cppeditor/cppcompletionassistprovider.h
+++ b/src/plugins/cppeditor/cppcompletionassistprovider.h
@@ -59,7 +59,6 @@ public:
const Utils::FilePath &filePath,
const TextEditor::TextEditorWidget *textEditorWidget,
const CPlusPlus::LanguageFeatures &languageFeatures,
- int position,
TextEditor::AssistReason reason) const = 0;
static int activationSequenceChar(const QChar &ch, const QChar &ch2,
diff --git a/src/plugins/cppeditor/cppcurrentdocumentfilter.cpp b/src/plugins/cppeditor/cppcurrentdocumentfilter.cpp
index 7c83ceaec61..81b95cf424e 100644
--- a/src/plugins/cppeditor/cppcurrentdocumentfilter.cpp
+++ b/src/plugins/cppeditor/cppcurrentdocumentfilter.cpp
@@ -60,6 +60,15 @@ CppCurrentDocumentFilter::CppCurrentDocumentFilter(CppModelManager *manager)
this, &CppCurrentDocumentFilter::onEditorAboutToClose);
}
+void CppCurrentDocumentFilter::makeAuxiliary()
+{
+ setId({});
+ setDisplayName({});
+ setDefaultShortcutString({});
+ setEnabled(false);
+ setHidden(true);
+}
+
QList<Core::LocatorFilterEntry> CppCurrentDocumentFilter::matchesFor(
QFutureInterface<Core::LocatorFilterEntry> &future, const QString & entry)
{
diff --git a/src/plugins/cppeditor/cppcurrentdocumentfilter.h b/src/plugins/cppeditor/cppcurrentdocumentfilter.h
index b6c715c70db..0a484dabd25 100644
--- a/src/plugins/cppeditor/cppcurrentdocumentfilter.h
+++ b/src/plugins/cppeditor/cppcurrentdocumentfilter.h
@@ -45,6 +45,8 @@ public:
explicit CppCurrentDocumentFilter(CppModelManager *manager);
~CppCurrentDocumentFilter() override = default;
+ void makeAuxiliary();
+
QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
const QString &entry) override;
void accept(const Core::LocatorFilterEntry &selection,
diff --git a/src/plugins/cppeditor/cppdoxygen_test.cpp b/src/plugins/cppeditor/cppdoxygen_test.cpp
index 7e2781a6ce4..2ec1558e521 100644
--- a/src/plugins/cppeditor/cppdoxygen_test.cpp
+++ b/src/plugins/cppeditor/cppdoxygen_test.cpp
@@ -441,7 +441,7 @@ void DoxygenTest::runTest(const QByteArray &original,
testDocument.m_source.remove(testDocument.m_cursorPosition, 1);
testDocument.setBaseDirectory(temporaryDir.path());
QVERIFY(testDocument.writeToDisk());
- foreach (CppTestDocument testDocument, includedHeaderDocuments) {
+ for (CppTestDocument testDocument : includedHeaderDocuments) {
testDocument.setBaseDirectory(temporaryDir.path());
QVERIFY(testDocument.writeToDisk());
}
diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs
index 0e9ed0ae8b2..59037cfc1a9 100644
--- a/src/plugins/cppeditor/cppeditor.qbs
+++ b/src/plugins/cppeditor/cppeditor.qbs
@@ -6,7 +6,6 @@ QtcPlugin {
Depends { name: "Qt.widgets" }
Depends { condition: project.withAutotests; name: "Qt.testlib" }
- Depends { name: "ClangSupport" }
Depends { name: "CPlusPlus" }
Depends { name: "Utils" }
@@ -139,8 +138,6 @@ QtcPlugin {
"cpplocatordata.h",
"cpplocatorfilter.cpp",
"cpplocatorfilter.h",
- "cppminimizableinfobars.cpp",
- "cppminimizableinfobars.h",
"cppmodelmanager.cpp",
"cppmodelmanager.h",
"cppmodelmanagersupport.cpp",
@@ -189,8 +186,6 @@ QtcPlugin {
"cppqtstyleindenter.h",
"cpprefactoringchanges.cpp",
"cpprefactoringchanges.h",
- "cpprefactoringengine.cpp",
- "cpprefactoringengine.h",
"cppselectionchanger.cpp",
"cppselectionchanger.h",
"cppsemanticinfo.h",
@@ -219,7 +214,6 @@ QtcPlugin {
"doxygengenerator.h",
"editordocumenthandle.cpp",
"editordocumenthandle.h",
- "followsymbolinterface.h",
"functionutils.cpp",
"functionutils.h",
"generatedcodemodelsupport.cpp",
@@ -236,7 +230,6 @@ QtcPlugin {
"projectinfo.h",
"projectpart.cpp",
"projectpart.h",
- "refactoringengineinterface.h",
"resourcepreviewhoverhandler.cpp",
"resourcepreviewhoverhandler.h",
"searchsymbols.cpp",
@@ -253,7 +246,6 @@ QtcPlugin {
"symbolsfindfilter.h",
"typehierarchybuilder.cpp",
"typehierarchybuilder.h",
- "usages.h",
"wrappablelineedit.cpp", // FIXME: Is this used?
"wrappablelineedit.h",
]
diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h
index d657f317e31..11883d2fd6e 100644
--- a/src/plugins/cppeditor/cppeditorconstants.h
+++ b/src/plugins/cppeditor/cppeditorconstants.h
@@ -37,9 +37,7 @@ const char CPPEDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "C+
const char SWITCH_DECLARATION_DEFINITION[] = "CppEditor.SwitchDeclarationDefinition";
const char OPEN_DECLARATION_DEFINITION_IN_NEXT_SPLIT[] = "CppEditor.OpenDeclarationDefinitionInNextSplit";
const char OPEN_PREPROCESSOR_DIALOG[] = "CppEditor.OpenPreprocessorDialog";
-const char ERRORS_IN_HEADER_FILES[] = "CppEditor.ErrorsInHeaderFiles";
const char MULTIPLE_PARSE_CONTEXTS_AVAILABLE[] = "CppEditor.MultipleParseContextsAvailable";
-const char NO_PROJECT_CONFIGURATION[] = "CppEditor.NoProjectConfiguration";
const char M_REFACTORING_MENU_INSERTION_POINT[] = "CppEditor.RefactorGroup";
const char UPDATE_CODEMODEL[] = "CppEditor.UpdateCodeModel";
const char INSPECT_CPP_CODEMODEL[] = "CppEditor.InspectCppCodeModel";
@@ -101,8 +99,6 @@ const char CPPEDITOR_SETTINGSGROUP[] = "CppTools";
const char LOWERCASE_CPPFILES_KEY[] = "LowerCaseFiles";
const bool LOWERCASE_CPPFILES_DEFAULT = true;
const char CPPEDITOR_SORT_EDITOR_DOCUMENT_OUTLINE[] = "SortedMethodOverview";
-const char CPPEDITOR_SHOW_INFO_BAR_FOR_HEADER_ERRORS[] = "ShowInfoBarForHeaderErrors";
-const char CPPEDITOR_SHOW_INFO_BAR_FOR_FOR_NO_PROJECT[] = "ShowInfoBarForNoProject";
const char CPPEDITOR_MODEL_MANAGER_PCH_USAGE[] = "PCHUsage";
const char CPPEDITOR_INTERPRET_AMBIGIUOUS_HEADERS_AS_C_HEADERS[]
= "InterpretAmbiguousHeadersAsCHeaders";
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index f8214401262..2b01b86c273 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -26,16 +26,13 @@
#include "cppeditordocument.h"
#include "baseeditordocumentparser.h"
-#include "builtineditordocumentprocessor.h"
#include "cppcodeformatter.h"
-#include "cppcodemodelsettings.h"
#include "cppeditorconstants.h"
#include "cppeditorplugin.h"
#include "cppmodelmanager.h"
#include "cppeditorconstants.h"
#include "cppeditorplugin.h"
#include "cpphighlighter.h"
-#include "cppqtstyleindenter.h"
#include "cppquickfixassistant.h"
#include <coreplugin/editormanager/editormanager.h>
@@ -49,26 +46,28 @@
#include <utils/executeondestruction.h>
#include <utils/infobar.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
+#include <utils/minimizableinfobars.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
+#include <utils/utilsicons.h>
+#include <QApplication>
#include <QTextDocument>
-namespace {
-
-CppEditor::CppModelManager *mm()
-{
- return CppEditor::CppModelManager::instance();
-}
-
-} // anonymous namespace
+const char NO_PROJECT_CONFIGURATION[] = "NoProject";
using namespace TextEditor;
+using namespace Utils;
namespace CppEditor {
namespace Internal {
+static CppEditor::CppModelManager *mm()
+{
+ return CppEditor::CppModelManager::instance();
+}
+
enum { processDocumentIntervalInMs = 150 };
class CppEditorDocumentHandleImpl : public CppEditorDocumentHandle
@@ -104,7 +103,6 @@ private:
};
CppEditorDocument::CppEditorDocument()
- : m_minimizableInfoBars(*infoBar())
{
setId(CppEditor::Constants::CPPEDITOR_ID);
setSyntaxHighlighter(new CppHighlighter);
@@ -125,9 +123,18 @@ CppEditorDocument::CppEditorDocument()
connect(this, &IDocument::filePathChanged,
this, &CppEditorDocument::onFilePathChanged);
+ connect(mm(), &CppModelManager::diagnosticsChanged,
+ this, &CppEditorDocument::onDiagnosticsChanged);
+
connect(&m_parseContextModel, &ParseContextModel::preferredParseContextChanged,
this, &CppEditorDocument::reparseWithPreferredParseContext);
+ minimizableInfoBars()->setSettingsGroup(Constants::CPPEDITOR_SETTINGSGROUP);
+ minimizableInfoBars()->setPossibleInfoBarEntries(
+ {{NO_PROJECT_CONFIGURATION,
+ tr("<b>Warning</b>: This file is not part of any project. "
+ "The code model might have issues parsing this file properly.")}});
+
// See also onFilePathChanged() for more initialization
}
@@ -142,26 +149,16 @@ void CppEditorDocument::setCompletionAssistProvider(TextEditor::CompletionAssist
m_completionAssistProvider = nullptr;
}
-void CppEditorDocument::setFunctionHintAssistProvider(TextEditor::CompletionAssistProvider *provider)
-{
- TextDocument::setFunctionHintAssistProvider(provider);
- m_functionHintAssistProvider = nullptr;
-}
-
CompletionAssistProvider *CppEditorDocument::completionAssistProvider() const
{
return m_completionAssistProvider
? m_completionAssistProvider : TextDocument::completionAssistProvider();
}
-CompletionAssistProvider *CppEditorDocument::functionHintAssistProvider() const
-{
- return m_functionHintAssistProvider
- ? m_functionHintAssistProvider : TextDocument::functionHintAssistProvider();
-}
-
TextEditor::IAssistProvider *CppEditorDocument::quickFixAssistProvider() const
{
+ if (const auto baseProvider = TextDocument::quickFixAssistProvider())
+ return baseProvider;
return CppEditorPlugin::instance()->quickFixProvider();
}
@@ -213,7 +210,6 @@ void CppEditorDocument::onMimeTypeChanged()
m_isObjCEnabled = (mt == QLatin1String(Constants::OBJECTIVE_C_SOURCE_MIMETYPE)
|| mt == QLatin1String(Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
m_completionAssistProvider = mm()->completionAssistProvider();
- m_functionHintAssistProvider = mm()->functionHintAssistProvider();
initializeTimer();
}
@@ -248,14 +244,13 @@ void CppEditorDocument::reparseWithPreferredParseContext(const QString &parseCon
scheduleProcessDocument();
}
-void CppEditorDocument::onFilePathChanged(const Utils::FilePath &oldPath,
- const Utils::FilePath &newPath)
+void CppEditorDocument::onFilePathChanged(const FilePath &oldPath, const FilePath &newPath)
{
Q_UNUSED(oldPath)
if (!newPath.isEmpty()) {
indenter()->setFileName(newPath);
- setMimeType(Utils::mimeTypeForFile(newPath.toFileInfo()).name());
+ setMimeType(mimeTypeForFile(newPath).name());
connect(this, &Core::IDocument::contentsChanged,
this, &CppEditorDocument::scheduleProcessDocument,
@@ -280,7 +275,6 @@ void CppEditorDocument::scheduleProcessDocument()
m_processorRevision = document()->revision();
m_processorTimer.start();
- processor()->editorDocumentTimerRestarted();
}
void CppEditorDocument::processDocument()
@@ -289,7 +283,6 @@ void CppEditorDocument::processDocument()
if (processor()->isParserRunning() || m_processorRevision != contentsRevision()) {
m_processorTimer.start();
- processor()->editorDocumentTimerRestarted();
return;
}
@@ -368,13 +361,13 @@ void CppEditorDocument::releaseResources()
void CppEditorDocument::showHideInfoBarAboutMultipleParseContexts(bool show)
{
- const Utils::Id id = Constants::MULTIPLE_PARSE_CONTEXTS_AVAILABLE;
+ const Id id = Constants::MULTIPLE_PARSE_CONTEXTS_AVAILABLE;
if (show) {
- Utils::InfoBarEntry info(id,
- tr("Note: Multiple parse contexts are available for this file. "
- "Choose the preferred one from the editor toolbar."),
- Utils::InfoBarEntry::GlobalSuppression::Enabled);
+ InfoBarEntry info(id,
+ tr("Note: Multiple parse contexts are available for this file. "
+ "Choose the preferred one from the editor toolbar."),
+ InfoBarEntry::GlobalSuppression::Enabled);
info.removeCancelButton();
if (infoBar()->canInfoBeAdded(id))
infoBar()->addInfo(info);
@@ -405,32 +398,25 @@ QFuture<CursorInfo> CppEditorDocument::cursorInfo(const CursorInfoParams &params
return processor()->cursorInfo(params);
}
-const MinimizableInfoBars &CppEditorDocument::minimizableInfoBars() const
-{
- return m_minimizableInfoBars;
-}
-
BaseEditorDocumentProcessor *CppEditorDocument::processor()
{
if (!m_processor) {
m_processor.reset(mm()->createEditorDocumentProcessor(this));
- connect(m_processor.data(), &BaseEditorDocumentProcessor::projectPartInfoUpdated,
- [this] (const ProjectPartInfo &info)
- {
- const bool hasProjectPart = !(info.hints & ProjectPartInfo::IsFallbackMatch);
- m_minimizableInfoBars.processHasProjectPart(hasProjectPart);
- m_parseContextModel.update(info);
- const bool isAmbiguous = info.hints & ProjectPartInfo::IsAmbiguousMatch;
- const bool isProjectFile = info.hints & ProjectPartInfo::IsFromProjectMatch;
- showHideInfoBarAboutMultipleParseContexts(isAmbiguous && isProjectFile);
- });
+ connect(m_processor.data(),
+ &BaseEditorDocumentProcessor::projectPartInfoUpdated,
+ [this](const ProjectPartInfo &info) {
+ const bool hasProjectPart = !(info.hints & ProjectPartInfo::IsFallbackMatch);
+ minimizableInfoBars()->setInfoVisible(NO_PROJECT_CONFIGURATION, !hasProjectPart);
+ m_parseContextModel.update(info);
+ const bool isAmbiguous = info.hints & ProjectPartInfo::IsAmbiguousMatch;
+ const bool isProjectFile = info.hints & ProjectPartInfo::IsFromProjectMatch;
+ showHideInfoBarAboutMultipleParseContexts(isAmbiguous && isProjectFile);
+ });
connect(m_processor.data(), &BaseEditorDocumentProcessor::codeWarningsUpdated,
[this] (unsigned revision,
const QList<QTextEdit::ExtraSelection> selections,
- const std::function<QWidget*()> &creator,
const TextEditor::RefactorMarkers &refactorMarkers) {
emit codeWarningsUpdated(revision, selections, refactorMarkers);
- m_minimizableInfoBars.processHeaderDiagnostics(creator);
});
connect(m_processor.data(), &BaseEditorDocumentProcessor::ifdefedOutBlocksUpdated,
this, &CppEditorDocument::ifdefedOutBlocksUpdated);
@@ -456,9 +442,9 @@ TextEditor::TabSettings CppEditorDocument::tabSettings() const
return indenter()->tabSettings().value_or(TextEditor::TextDocument::tabSettings());
}
-bool CppEditorDocument::save(QString *errorString, const Utils::FilePath &filePath, bool autoSave)
+bool CppEditorDocument::save(QString *errorString, const FilePath &filePath, bool autoSave)
{
- Utils::ExecuteOnDestruction resetSettingsOnScopeExit;
+ ExecuteOnDestruction resetSettingsOnScopeExit;
if (indenter()->formatOnSave() && !autoSave) {
auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout());
@@ -502,5 +488,51 @@ bool CppEditorDocument::save(QString *errorString, const Utils::FilePath &filePa
return TextEditor::TextDocument::save(errorString, filePath, autoSave);
}
+void CppEditorDocument::onDiagnosticsChanged(const QString &fileName, const QString &kind)
+{
+ if (FilePath::fromString(fileName) != filePath())
+ return;
+
+ TextMarks removedMarks = marks();
+
+ const Utils::Id category = Utils::Id::fromString(kind);
+
+ for (const auto &diagnostic : mm()->diagnosticMessages()) {
+ if (FilePath::fromString(diagnostic.fileName()) == filePath()) {
+ auto it = std::find_if(std::begin(removedMarks),
+ std::end(removedMarks),
+ [&category, &diagnostic](TextMark *existing) {
+ return (diagnostic.line() == existing->lineNumber()
+ && diagnostic.text() == existing->lineAnnotation()
+ && category == existing->category());
+ });
+
+ if (it != std::end(removedMarks)) {
+ removedMarks.erase(it);
+ continue;
+ }
+
+ auto mark = new TextMark(filePath(), diagnostic.line(), category);
+ mark->setLineAnnotation(diagnostic.text());
+ mark->setToolTip(diagnostic.text());
+
+ mark->setIcon(diagnostic.isWarning() ? Utils::Icons::CODEMODEL_WARNING.icon()
+ : Utils::Icons::CODEMODEL_ERROR.icon());
+ mark->setColor(diagnostic.isWarning() ? Utils::Theme::CodeModel_Warning_TextMarkColor
+ : Utils::Theme::CodeModel_Error_TextMarkColor);
+ mark->setPriority(diagnostic.isWarning() ? TextEditor::TextMark::NormalPriority
+ : TextEditor::TextMark::HighPriority);
+ addMark(mark);
+ }
+ }
+
+ for (auto it = removedMarks.begin(); it != removedMarks.end(); ++it) {
+ if ((*it)->category() == category) {
+ removeMark(*it);
+ delete *it;
+ }
+ }
+}
+
} // namespace Internal
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppeditordocument.h b/src/plugins/cppeditor/cppeditordocument.h
index 24f77691c59..09d5ab96b63 100644
--- a/src/plugins/cppeditor/cppeditordocument.h
+++ b/src/plugins/cppeditor/cppeditordocument.h
@@ -27,7 +27,6 @@
#include "baseeditordocumentprocessor.h"
#include "cppcompletionassistprovider.h"
-#include "cppminimizableinfobars.h"
#include "cppmodelmanager.h"
#include "cppparsecontext.h"
#include "cppsemanticinfo.h"
@@ -52,9 +51,7 @@ public:
bool isObjCEnabled() const;
void setCompletionAssistProvider(TextEditor::CompletionAssistProvider *provider) override;
- void setFunctionHintAssistProvider(TextEditor::CompletionAssistProvider *provider) override;
TextEditor::CompletionAssistProvider *completionAssistProvider() const override;
- TextEditor::CompletionAssistProvider *functionHintAssistProvider() const override;
TextEditor::IAssistProvider *quickFixAssistProvider() const override;
void recalculateSemanticInfoDetached();
@@ -65,7 +62,6 @@ public:
void scheduleProcessDocument();
- const MinimizableInfoBars &minimizableInfoBars() const;
ParseContextModel &parseContextModel();
QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params);
@@ -98,6 +94,8 @@ private:
void onAboutToReload();
void onReloadFinished();
+ void onDiagnosticsChanged(const QString &fileName, const QString &kind);
+
void reparseWithPreferredParseContext(const QString &id);
@@ -130,12 +128,10 @@ private:
QScopedPointer<BaseEditorDocumentProcessor> m_processor;
CppCompletionAssistProvider *m_completionAssistProvider = nullptr;
- CppCompletionAssistProvider *m_functionHintAssistProvider = nullptr;
// (Un)Registration in CppModelManager
QScopedPointer<CppEditorDocumentHandle> m_editorDocumentHandle;
- MinimizableInfoBars m_minimizableInfoBars;
ParseContextModel m_parseContextModel;
};
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index 8b144601e24..e2999002e35 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -107,7 +107,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
@@ -270,7 +270,8 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
Command *command = ActionManager::registerAction(switchAction, Constants::SWITCH_HEADER_SOURCE, context, true);
command->setDefaultKeySequence(QKeySequence(Qt::Key_F4));
mcpptools->addAction(command);
- connect(switchAction, &QAction::triggered, this, &CppEditorPlugin::switchHeaderSource);
+ connect(switchAction, &QAction::triggered,
+ this, [] { CppModelManager::switchHeaderSource(false); });
QAction *openInNextSplitAction = new QAction(tr("Open Corresponding Header/Source in Next Split"), this);
command = ActionManager::registerAction(openInNextSplitAction, Constants::OPEN_HEADER_SOURCE_IN_NEXT_SPLIT, context, true);
@@ -279,7 +280,7 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
: tr("Ctrl+E, F4")));
mcpptools->addAction(command);
connect(openInNextSplitAction, &QAction::triggered,
- this, &CppEditorPlugin::switchHeaderSourceInNextSplit);
+ this, [] { CppModelManager::switchHeaderSource(true); });
MacroExpander *expander = globalMacroExpander();
expander->registerVariable("Cpp:LicenseTemplate",
@@ -622,19 +623,6 @@ CppFileSettings *CppEditorPlugin::fileSettings()
return &instance()->d->m_fileSettings;
}
-void CppEditorPlugin::switchHeaderSource()
-{
- CppEditor::switchHeaderSource();
-}
-
-void CppEditorPlugin::switchHeaderSourceInNextSplit()
-{
- const auto otherFile = FilePath::fromString(
- correspondingHeaderOrSource(EditorManager::currentDocument()->filePath().toString()));
- if (!otherFile.isEmpty())
- EditorManager::openEditor(otherFile, Id(), EditorManager::OpenInOtherSplit);
-}
-
static QStringList findFilesInProject(const QString &name, const Project *project)
{
if (debug)
diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h
index 6a4bb5040cc..81a1e327f65 100644
--- a/src/plugins/cppeditor/cppeditorplugin.h
+++ b/src/plugins/cppeditor/cppeditorplugin.h
@@ -66,8 +66,6 @@ public:
void showPreProcessorDialog();
void renameSymbolUnderCursor();
void switchDeclarationDefinition();
- void switchHeaderSource();
- void switchHeaderSourceInNextSplit();
CppCodeModelSettings *codeModelSettings();
static CppFileSettings *fileSettings();
diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp
index 8c9887b1de2..f797a59ffdd 100644
--- a/src/plugins/cppeditor/cppeditorwidget.cpp
+++ b/src/plugins/cppeditor/cppeditorwidget.cpp
@@ -39,7 +39,6 @@
#include "cppfunctiondecldeflink.h"
#include "cpphighlighter.h"
#include "cpplocalrenaming.h"
-#include "cppminimizableinfobars.h"
#include "cppmodelmanager.h"
#include "cpppreprocessordialog.h"
#include "cppsemanticinfo.h"
@@ -50,12 +49,8 @@
#include "cpptoolssettings.h"
#include "cppuseselectionsupdater.h"
#include "cppworkingcopy.h"
-#include "followsymbolinterface.h"
-#include "refactoringengineinterface.h"
#include "symbolfinder.h"
-#include <clangsupport/sourcelocationscontainer.h>
-
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/documentmodel.h>
@@ -409,7 +404,7 @@ class CppEditorWidgetPrivate
public:
CppEditorWidgetPrivate(CppEditorWidget *q);
- bool shouldOfferOutline() const { return CppModelManager::supportsOutline(m_cppEditorDocument); }
+ bool shouldOfferOutline() const { return !CppModelManager::usesClangd(m_cppEditorDocument); }
public:
QPointer<CppModelManager> m_modelManager;
@@ -428,7 +423,6 @@ public:
QAction *m_parseContextAction = nullptr;
ParseContextWidget *m_parseContextWidget = nullptr;
QToolButton *m_preprocessorButton = nullptr;
- MinimizableInfoBars::Actions m_showInfoBarActions;
CppLocalRenaming m_localRenaming;
CppUseSelectionsUpdater m_useSelectionsUpdater;
@@ -558,13 +552,6 @@ void CppEditorWidget::finalizeInitialization()
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton);
}
- // Toolbar: Actions to show minimized info bars
- d->m_showInfoBarActions = MinimizableInfoBars::createShowInfoBarActions([this](QWidget *w) {
- return this->insertExtraToolBarWidget(TextEditorWidget::Left, w);
- });
- connect(&cppEditorDocument()->minimizableInfoBars(), &MinimizableInfoBars::showAction,
- this, &CppEditorWidget::onShowInfoBarAction);
-
d->m_outlineTimer.setInterval(5000);
d->m_outlineTimer.setSingleShot(true);
connect(&d->m_outlineTimer, &QTimer::timeout, this, [this] {
@@ -607,6 +594,9 @@ void CppEditorWidget::setProposals(const TextEditor::IAssistProposal *immediateP
QTC_ASSERT(isInTestMode(), return);
#ifdef WITH_TESTS
emit proposalsReady(immediateProposal, finalProposal);
+#else
+ Q_UNUSED(immediateProposal)
+ Q_UNUSED(finalProposal)
#endif
}
@@ -673,134 +663,6 @@ void CppEditorWidget::onIfdefedOutBlocksUpdated(unsigned revision,
textDocument()->setIfdefedOutBlocks(ifdefedOutBlocks);
}
-void CppEditorWidget::onShowInfoBarAction(const Id &id, bool show)
-{
- QAction *action = d->m_showInfoBarActions.value(id);
- QTC_ASSERT(action, return);
- action->setVisible(show);
-}
-
-static QString getDocumentLine(QTextDocument *document, int line)
-{
- if (document)
- return document->findBlockByNumber(line - 1).text();
-
- return {};
-}
-
-static std::unique_ptr<QTextDocument> getCurrentDocument(const QString &path)
-{
- const QTextCodec *defaultCodec = Core::EditorManager::defaultTextCodec();
- QString contents;
- Utils::TextFileFormat format;
- QString error;
- if (Utils::TextFileFormat::readFile(Utils::FilePath::fromString(path),
- defaultCodec,
- &contents,
- &format,
- &error)
- != Utils::TextFileFormat::ReadSuccess) {
- qWarning() << "Error reading file " << path << " : " << error;
- return {};
- }
-
- return std::make_unique<QTextDocument>(contents);
-}
-
-static void onReplaceUsagesClicked(const QString &text,
- const QList<SearchResultItem> &items,
- bool preserveCase)
-{
- CppModelManager *modelManager = CppModelManager::instance();
- if (!modelManager)
- return;
-
- const FilePaths filePaths = TextEditor::BaseFileFind::replaceAll(text, items, preserveCase);
- if (!filePaths.isEmpty()) {
- modelManager->updateSourceFiles(Utils::transform<QSet>(filePaths, &FilePath::toString));
- SearchResultWindow::instance()->hide();
- }
-}
-
-static QTextDocument *getOpenDocument(const QString &path)
-{
- const IDocument *document = DocumentModel::documentForFilePath(FilePath::fromString(path));
- if (document)
- return qobject_cast<const TextDocument *>(document)->document();
-
- return {};
-}
-
-static void addSearchResults(Usages usages, SearchResult &search, const QString &text)
-{
- std::sort(usages.begin(), usages.end());
-
- std::unique_ptr<QTextDocument> currentDocument;
- QString lastPath;
-
- for (const Usage &usage : usages) {
- QTextDocument *document = getOpenDocument(usage.path);
-
- if (!document) {
- if (usage.path != lastPath) {
- currentDocument = getCurrentDocument(usage.path);
- lastPath = usage.path;
- }
- document = currentDocument.get();
- }
-
- const QString lineContent = getDocumentLine(document, usage.line);
-
- if (!lineContent.isEmpty()) {
- Search::TextRange range{Search::TextPosition(usage.line, usage.column - 1),
- Search::TextPosition(usage.line, usage.column + text.length() - 1)};
- SearchResultItem item;
- item.setFilePath(FilePath::fromString(usage.path));
- item.setLineText(lineContent);
- item.setMainRange(range);
- item.setUseTextEditorFont(true);
- search.addResult(item);
- }
- }
-}
-
-static void findRenameCallback(CppEditorWidget *widget,
- const QTextCursor &baseCursor,
- const Usages &usages,
- bool rename = false,
- const QString &replacement = QString())
-{
- QTextCursor cursor = Utils::Text::wordStartCursor(baseCursor);
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- const QString text = cursor.selectedText();
- SearchResultWindow::SearchMode mode = SearchResultWindow::SearchOnly;
- if (rename)
- mode = SearchResultWindow::SearchAndReplace;
- SearchResult *search = SearchResultWindow::instance()->startNewSearch(
- QObject::tr("C++ Usages:"),
- QString(),
- text,
- mode,
- SearchResultWindow::PreserveCaseDisabled,
- QLatin1String("CppEditor"));
- search->setTextToReplace(replacement);
- search->setSearchAgainSupported(true);
- QObject::connect(search, &SearchResult::replaceButtonClicked, &onReplaceUsagesClicked);
- QObject::connect(search, &SearchResult::searchAgainRequested,
- [widget, rename, replacement, baseCursor]() {
- rename ? widget->renameUsages(replacement, baseCursor) : widget->findUsages(baseCursor);
- });
-
- addSearchResults(usages, *search, text);
-
- search->finishSearch(false);
- QObject::connect(search, &SearchResult::activated,
- [](const Core::SearchResultItem& item) {
- Core::EditorManager::openEditorAtSearchResult(item);
- });
- search->popup();
-}
-
void CppEditorWidget::findUsages()
{
findUsages(textCursor());
@@ -809,32 +671,18 @@ void CppEditorWidget::findUsages()
void CppEditorWidget::findUsages(QTextCursor cursor)
{
// 'this' in cursorInEditor is never used (and must never be used) asynchronously.
- const CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this,
- textDocument()};
+ const CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this, textDocument()};
QPointer<CppEditorWidget> cppEditorWidget = this;
- d->m_modelManager->findUsages(cursorInEditor,
- [=](const Usages &usages) {
- if (!cppEditorWidget)
- return;
- findRenameCallback(cppEditorWidget.data(), cursor, usages);
- });
+ d->m_modelManager->findUsages(cursorInEditor);
}
void CppEditorWidget::renameUsages(const QString &replacement, QTextCursor cursor)
{
if (cursor.isNull())
cursor = textCursor();
- CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this,
- textDocument()};
+ CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this, textDocument()};
QPointer<CppEditorWidget> cppEditorWidget = this;
- d->m_modelManager->globalRename(cursorInEditor,
- [=](const Usages &usages) {
- if (!cppEditorWidget)
- return;
- findRenameCallback(cppEditorWidget.data(), cursor, usages,
- true, replacement);
- },
- replacement);
+ d->m_modelManager->globalRename(cursorInEditor, replacement);
}
bool CppEditorWidget::selectBlockUp()
@@ -933,7 +781,6 @@ const ProjectPart *CppEditorWidget::projectPart() const
namespace {
-using ClangBackEnd::SourceLocationContainer;
using Utils::Text::selectAt;
QTextCharFormat occurrencesTextCharFormat()
@@ -944,7 +791,7 @@ QTextCharFormat occurrencesTextCharFormat()
}
QList<QTextEdit::ExtraSelection> sourceLocationsToExtraSelections(
- const std::vector<SourceLocationContainer> &sourceLocations,
+ const Links &sourceLocations,
uint selectionLength,
CppEditorWidget *cppEditorWidget)
{
@@ -953,12 +800,12 @@ QList<QTextEdit::ExtraSelection> sourceLocationsToExtraSelections(
QList<QTextEdit::ExtraSelection> selections;
selections.reserve(int(sourceLocations.size()));
- auto sourceLocationToExtraSelection = [&](const SourceLocationContainer &sourceLocation) {
+ auto sourceLocationToExtraSelection = [&](const Link &sourceLocation) {
QTextEdit::ExtraSelection selection;
selection.cursor = selectAt(cppEditorWidget->textCursor(),
- sourceLocation.line,
- sourceLocation.column,
+ sourceLocation.targetLine,
+ sourceLocation.targetColumn + 1,
selectionLength);
selection.format = textCharFormat;
@@ -977,8 +824,6 @@ QList<QTextEdit::ExtraSelection> sourceLocationsToExtraSelections(
void CppEditorWidget::renameSymbolUnderCursor()
{
- using ClangBackEnd::SourceLocationsContainer;
-
const ProjectPart *projPart = projectPart();
if (!projPart)
return;
@@ -991,17 +836,15 @@ void CppEditorWidget::renameSymbolUnderCursor()
QPointer<CppEditorWidget> cppEditorWidget = this;
- auto renameSymbols = [=](const QString &symbolName,
- const SourceLocationsContainer &sourceLocations,
- int revision) {
+ auto renameSymbols = [=](const QString &symbolName, const Links &links, int revision) {
if (cppEditorWidget) {
viewport()->setCursor(Qt::IBeamCursor);
if (revision != document()->revision())
return;
- if (sourceLocations.hasContent()) {
+ if (!links.isEmpty()) {
QList<QTextEdit::ExtraSelection> selections
- = sourceLocationsToExtraSelections(sourceLocations.sourceLocationContainers(),
+ = sourceLocationsToExtraSelections(links,
static_cast<uint>(symbolName.size()),
cppEditorWidget);
setExtraSelections(TextEditor::TextEditorWidget::CodeSemanticsSelection, selections);
@@ -1042,13 +885,11 @@ void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
if (self && link.hasValidTarget())
self->openLink(link, split);
};
- followSymbolInterface().switchDeclDef(cursor, std::move(callback),
- d->m_modelManager->snapshot(), d->m_lastSemanticInfo.doc,
- d->m_modelManager->symbolFinder());
+ CppModelManager::switchDeclDef(cursor, std::move(callback));
}
void CppEditorWidget::findLinkAt(const QTextCursor &cursor,
- ProcessLinkCallback &&processLinkCallback,
+ const LinkHandler &processLinkCallback,
bool resolveTarget,
bool inNextSplit)
{
@@ -1061,8 +902,8 @@ void CppEditorWidget::findLinkAt(const QTextCursor &cursor,
// UI header.
QTextCursor c(cursor);
c.select(QTextCursor::WordUnderCursor);
- ProcessLinkCallback callbackWrapper = [start = c.selectionStart(), end = c.selectionEnd(),
- doc = QPointer(cursor.document()), callback = std::move(processLinkCallback),
+ LinkHandler callbackWrapper = [start = c.selectionStart(), end = c.selectionEnd(),
+ doc = QPointer(cursor.document()), callback = processLinkCallback,
filePath](const Link &link) {
const int linkPos = doc ? Text::positionInText(doc, link.targetLine, link.targetColumn + 1)
: -1;
@@ -1084,13 +925,10 @@ void CppEditorWidget::findLinkAt(const QTextCursor &cursor,
}
callback(link);
};
- followSymbolInterface().findLink(
+ CppModelManager::followSymbol(
CursorInEditor{cursor, filePath, this, textDocument()},
- std::move(callbackWrapper),
+ callbackWrapper,
resolveTarget,
- d->m_modelManager->snapshot(),
- d->m_lastSemanticInfo.doc,
- d->m_modelManager->symbolFinder(),
inNextSplit);
}
@@ -1099,11 +937,6 @@ unsigned CppEditorWidget::documentRevision() const
return document()->revision();
}
-FollowSymbolInterface &CppEditorWidget::followSymbolInterface() const
-{
- return d->m_modelManager->followSymbolInterface();
-}
-
bool CppEditorWidget::isSemanticInfoValidExceptLocalUses() const
{
return d->m_lastSemanticInfo.doc && d->m_lastSemanticInfo.revision == documentRevision()
@@ -1330,23 +1163,43 @@ void CppEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo,
updateFunctionDeclDefLink();
}
+bool CppEditorWidget::isOldStyleSignalOrSlot() const
+{
+ QTextCursor tc(textCursor());
+ const QString content = textDocument()->plainText();
+
+ return CppEditor::CppModelManager::instance()
+ ->getSignalSlotType(textDocument()->filePath().toString(),
+ content.toUtf8(),
+ tc.position())
+ == CppEditor::SignalSlotType::OldStyleSignal;
+}
+
AssistInterface *CppEditorWidget::createAssistInterface(AssistKind kind, AssistReason reason) const
{
if (kind == Completion || kind == FunctionHint) {
CppCompletionAssistProvider * const cap = kind == Completion
? qobject_cast<CppCompletionAssistProvider *>(cppEditorDocument()->completionAssistProvider())
: qobject_cast<CppCompletionAssistProvider *>(cppEditorDocument()->functionHintAssistProvider());
- if (cap) {
+
+ auto getFeatures = [this]() {
LanguageFeatures features = LanguageFeatures::defaultFeatures();
if (Document::Ptr doc = d->m_lastSemanticInfo.doc)
features = doc->languageFeatures();
features.objCEnabled |= cppEditorDocument()->isObjCEnabled();
+ return features;
+ };
+
+ if (cap)
return cap->createAssistInterface(textDocument()->filePath(),
this,
- features,
- position(),
+ getFeatures(),
reason);
- } else {
+ else {
+ if (isOldStyleSignalOrSlot())
+ return CppModelManager::instance()
+ ->completionAssistProvider()
+ ->createAssistInterface(textDocument()->filePath(), this, getFeatures(), reason);
return TextEditorWidget::createAssistInterface(kind, reason);
}
} else if (kind == QuickFix) {
diff --git a/src/plugins/cppeditor/cppeditorwidget.h b/src/plugins/cppeditor/cppeditorwidget.h
index 837954d6c59..5f76a40e69b 100644
--- a/src/plugins/cppeditor/cppeditorwidget.h
+++ b/src/plugins/cppeditor/cppeditorwidget.h
@@ -38,7 +38,6 @@ class IAssistProvider;
}
namespace CppEditor {
-class FollowSymbolInterface;
class SemanticInfo;
class ProjectPart;
@@ -117,7 +116,7 @@ protected:
bool handleStringSplitting(QKeyEvent *e) const;
void findLinkAt(const QTextCursor &cursor,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool resolveTarget = true,
bool inNextSplit = false) override;
@@ -137,8 +136,6 @@ private:
void onIfdefedOutBlocksUpdated(unsigned revision,
const QList<TextEditor::BlockRange> ifdefedOutBlocks);
- void onShowInfoBarAction(const Utils::Id &id, bool show);
-
void updateSemanticInfo(const SemanticInfo &semanticInfo,
bool updateUseSelectionSynchronously = false);
void updatePreprocessorButtonTooltip();
@@ -149,11 +146,10 @@ private:
void finalizeInitializationAfterDuplication(TextEditorWidget *other) override;
unsigned documentRevision() const;
+ bool isOldStyleSignalOrSlot() const;
QMenu *createRefactorMenu(QWidget *parent) const;
- FollowSymbolInterface &followSymbolInterface() const;
-
const ProjectPart *projectPart() const;
private:
diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp
index 240ea7c26e8..7fbe8d2c41c 100644
--- a/src/plugins/cppeditor/cppelementevaluator.cpp
+++ b/src/plugins/cppeditor/cppelementevaluator.cpp
@@ -124,10 +124,10 @@ CppDeclarableElement::CppDeclarableElement(Symbol *declaration)
overview.showReturnTypes = true;
overview.showTemplateParameters = true;
name = overview.prettyName(declaration->name());
- if (declaration->enclosingScope()->isClass() ||
- declaration->enclosingScope()->isNamespace() ||
- declaration->enclosingScope()->isEnum() ||
- declaration->enclosingScope()->isTemplate()) {
+ if (declaration->enclosingScope()->asClass() ||
+ declaration->enclosingScope()->asNamespace() ||
+ declaration->enclosingScope()->asEnum() ||
+ declaration->enclosingScope()->asTemplate()) {
qualifiedName = overview.prettyName(LookupContext::fullyQualifiedName(declaration));
helpIdCandidates = stripName(qualifiedName);
} else {
@@ -184,10 +184,10 @@ void CppClass::lookupBases(QFutureInterfaceBase &futureInterface,
clazz = current.first;
visited.insert(clazz);
const QList<ClassOrNamespace *> &bases = clazz->usings();
- foreach (ClassOrNamespace *baseClass, bases) {
+ for (ClassOrNamespace *baseClass : bases) {
const QList<Symbol *> &symbols = baseClass->symbols();
- foreach (Symbol *symbol, symbols) {
- if (symbol->isClass() && (
+ for (Symbol *symbol : symbols) {
+ if (symbol->asClass() && (
clazz = context.lookupType(symbol)) &&
!visited.contains(clazz)) {
CppClass baseCppClass(symbol);
@@ -220,7 +220,8 @@ void CppClass::lookupDerived(QFutureInterfaceBase &futureInterface,
const Data &current = q.dequeue();
CppClass *clazz = current.first;
const TypeHierarchy &classHierarchy = current.second;
- foreach (const TypeHierarchy &derivedHierarchy, classHierarchy.hierarchy()) {
+ const QList<TypeHierarchy> hierarchy = classHierarchy.hierarchy();
+ for (const TypeHierarchy &derivedHierarchy : hierarchy) {
clazz->derived.append(CppClass(derivedHierarchy.symbol()));
q.enqueue(qMakePair(&clazz->derived.last(), derivedHierarchy));
}
@@ -344,16 +345,16 @@ public:
static bool isCppClass(Symbol *symbol)
{
- return symbol->isClass() || symbol->isForwardClassDeclaration()
- || (symbol->isTemplate() && symbol->asTemplate()->declaration()
- && (symbol->asTemplate()->declaration()->isClass()
- || symbol->asTemplate()->declaration()->isForwardClassDeclaration()));
+ return symbol->asClass() || symbol->asForwardClassDeclaration()
+ || (symbol->asTemplate() && symbol->asTemplate()->declaration()
+ && (symbol->asTemplate()->declaration()->asClass()
+ || symbol->asTemplate()->declaration()->asForwardClassDeclaration()));
}
static Symbol *followClassDeclaration(Symbol *symbol, const Snapshot &snapshot, SymbolFinder symbolFinder,
LookupContext *context = nullptr)
{
- if (!symbol->isForwardClassDeclaration())
+ if (!symbol->asForwardClassDeclaration())
return symbol;
Symbol *classDeclaration = symbolFinder.findMatchingClassDeclaration(symbol, snapshot);
@@ -421,7 +422,7 @@ static QSharedPointer<CppElement> handleLookupItemMatch(const Snapshot &snapshot
element = QSharedPointer<CppElement>(new Unknown(type));
} else {
const FullySpecifiedType &type = declaration->type();
- if (declaration->isNamespace()) {
+ if (declaration->asNamespace()) {
element = QSharedPointer<CppElement>(new CppNamespace(declaration));
} else if (isCppClass(declaration)) {
LookupContext contextToUse = context;
@@ -433,11 +434,11 @@ static QSharedPointer<CppElement> handleLookupItemMatch(const Snapshot &snapshot
element = QSharedPointer<CppElement>(new CppEnumerator(enumerator));
} else if (declaration->isTypedef()) {
element = QSharedPointer<CppElement>(new CppTypedef(declaration));
- } else if (declaration->isFunction()
+ } else if (declaration->asFunction()
|| (type.isValid() && type->isFunctionType())
- || declaration->isTemplate()) {
+ || declaration->asTemplate()) {
element = QSharedPointer<CppElement>(new CppFunction(declaration));
- } else if (declaration->isDeclaration() && type.isValid()) {
+ } else if (declaration->asDeclaration() && type.isValid()) {
element = QSharedPointer<CppElement>(
new CppVariable(declaration, context, lookupItem.scope()));
} else {
@@ -450,7 +451,7 @@ static QSharedPointer<CppElement> handleLookupItemMatch(const Snapshot &snapshot
// special case for bug QTCREATORBUG-4780
static bool shouldOmitElement(const LookupItem &lookupItem, const Scope *scope)
{
- return !lookupItem.declaration() && scope && scope->isFunction()
+ return !lookupItem.declaration() && scope && scope->asFunction()
&& lookupItem.type().match(scope->asFunction()->returnType());
}
@@ -483,8 +484,8 @@ static LookupItem findLookupItem(const CPlusPlus::Snapshot &snapshot, CPlusPlus:
return LookupItem();
auto isInteresting = [followTypedef](Symbol *symbol) {
- return symbol && (!followTypedef || (symbol->isClass() || symbol->isTemplate()
- || symbol->isForwardClassDeclaration() || symbol->isTypedef()));
+ return symbol && (!followTypedef || (symbol->asClass() || symbol->asTemplate()
+ || symbol->asForwardClassDeclaration() || symbol->isTypedef()));
};
for (const LookupItem &item : lookupItems) {
@@ -633,8 +634,9 @@ QFuture<QSharedPointer<CppElement>> FromGuiFunctor::syncExec(
void FromGuiFunctor::checkDiagnosticMessage(int pos)
{
- foreach (const QTextEdit::ExtraSelection &sel,
- m_editor->extraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection)) {
+ const QList<QTextEdit::ExtraSelection> &selections = m_editor->extraSelections(
+ TextEditor::TextEditorWidget::CodeWarningsSelection);
+ for (const QTextEdit::ExtraSelection &sel : selections) {
if (pos >= sel.cursor.selectionStart() && pos <= sel.cursor.selectionEnd()) {
m_diagnosis = sel.format.toolTip();
break;
@@ -747,7 +749,7 @@ Utils::Link CppElementEvaluator::linkFromExpression(const QString &expression, c
Symbol *symbol = item.declaration();
if (!symbol)
continue;
- if (!symbol->isClass() && !symbol->isTemplate())
+ if (!symbol->asClass() && !symbol->asTemplate())
continue;
return symbol->toLink();
}
diff --git a/src/plugins/cppeditor/cppfilesettingspage.cpp b/src/plugins/cppeditor/cppfilesettingspage.cpp
index d6abddffc40..7dc16bb0acb 100644
--- a/src/plugins/cppeditor/cppfilesettingspage.cpp
+++ b/src/plugins/cppeditor/cppfilesettingspage.cpp
@@ -37,7 +37,7 @@
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/stringutils.h>
#include <QCoreApplication>
@@ -285,13 +285,15 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
// populate suffix combos
const Utils::MimeType sourceMt = Utils::mimeTypeForName(QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
if (sourceMt.isValid()) {
- foreach (const QString &suffix, sourceMt.suffixes())
+ const QStringList suffixes = sourceMt.suffixes();
+ for (const QString &suffix : suffixes)
m_ui.sourceSuffixComboBox->addItem(suffix);
}
const Utils::MimeType headerMt = Utils::mimeTypeForName(QLatin1String(Constants::CPP_HEADER_MIMETYPE));
if (headerMt.isValid()) {
- foreach (const QString &suffix, headerMt.suffixes())
+ const QStringList suffixes = headerMt.suffixes();
+ for (const QString &suffix : suffixes)
m_ui.headerSuffixComboBox->addItem(suffix);
}
m_ui.licenseTemplatePathChooser->setExpectedKind(Utils::PathChooser::File);
@@ -314,7 +316,7 @@ void CppFileSettingsWidget::setLicenseTemplatePath(const FilePath &lp)
static QStringList trimmedPaths(const QString &paths)
{
QStringList res;
- foreach (const QString &path, paths.split(QLatin1Char(','), Qt::SkipEmptyParts))
+ for (const QString &path : paths.split(QLatin1Char(','), Qt::SkipEmptyParts))
res << path.trimmed();
return res;
}
diff --git a/src/plugins/cppeditor/cppfindreferences.cpp b/src/plugins/cppeditor/cppfindreferences.cpp
index 35bca7da7b0..1b4f78bef97 100644
--- a/src/plugins/cppeditor/cppfindreferences.cpp
+++ b/src/plugins/cppeditor/cppfindreferences.cpp
@@ -369,7 +369,7 @@ public:
void operator()(QList<CPlusPlus::Usage> &, const QList<CPlusPlus::Usage> &usages)
{
- foreach (const CPlusPlus::Usage &u, usages)
+ for (const CPlusPlus::Usage &u : usages)
future->reportResult(u);
future->setProgressValue(future->progressValue() + 1);
@@ -413,11 +413,11 @@ static void find_helper(QFutureInterface<CPlusPlus::Usage> &future,
symbol->fileNameLength());
Utils::FilePaths files{sourceFile};
- if (symbol->isClass()
- || symbol->isForwardClassDeclaration()
+ if (symbol->asClass()
+ || symbol->asForwardClassDeclaration()
|| (symbol->enclosingScope()
&& !symbol->isStatic()
- && symbol->enclosingScope()->isNamespace())) {
+ && symbol->enclosingScope()->asNamespace())) {
const CPlusPlus::Snapshot snapshotFromContext = context.snapshot();
for (auto i = snapshotFromContext.begin(), ei = snapshotFromContext.end(); i != ei; ++i) {
if (i.key() == sourceFile)
@@ -479,7 +479,7 @@ void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
parameters.symbolFileName = QByteArray(symbol->fileName());
parameters.categorize = codeModelSettings()->categorizeFindReferences();
- if (symbol->isClass() || symbol->isForwardClassDeclaration()) {
+ if (symbol->asClass() || symbol->asForwardClassDeclaration()) {
CPlusPlus::Overview overview;
parameters.prettySymbolName =
overview.prettyName(CPlusPlus::LookupContext::path(symbol).constLast());
@@ -632,8 +632,10 @@ CPlusPlus::Symbol *CppFindReferences::findSymbol(const CppFindReferencesParamete
return nullptr;
}
-static void displayResults(SearchResult *search, QFutureWatcher<CPlusPlus::Usage> *watcher,
- int first, int last)
+static void displayResults(SearchResult *search,
+ QFutureWatcher<CPlusPlus::Usage> *watcher,
+ int first,
+ int last)
{
CppFindReferencesParameters parameters = search->userData().value<CppFindReferencesParameters>();
@@ -644,6 +646,7 @@ static void displayResults(SearchResult *search, QFutureWatcher<CPlusPlus::Usage
item.setMainRange(result.line, result.col, result.len);
item.setLineText(result.lineText);
item.setUserData(int(result.type));
+ item.setContainingFunctionName(result.containingFunction);
item.setStyle(colorStyleForUsageType(result.type));
item.setUseTextEditorFont(true);
if (search->supportsReplace())
@@ -724,7 +727,8 @@ restart_search:
return usages;
usages.clear();
- foreach (const CPlusPlus::Document::MacroUse &use, doc->macroUses()) {
+ const QList<CPlusPlus::Document::MacroUse> uses = doc->macroUses();
+ for (const CPlusPlus::Document::MacroUse &use : uses) {
const CPlusPlus::Macro &useMacro = use.macro();
if (useMacro.fileName() == macro.fileName()) { // Check if this is a match, but possibly against an outdated document.
@@ -741,7 +745,7 @@ restart_search:
if (macro.name() == useMacro.name()) {
unsigned column;
const QString &lineSource = matchingLine(use.bytesBegin(), source, &column);
- usages.append(CPlusPlus::Usage(fileName, lineSource,
+ usages.append(CPlusPlus::Usage(fileName, lineSource, {},
CPlusPlus::Usage::Type::Other, use.beginLine(),
column, useMacro.nameToQString().size()));
}
diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
index 11a3a70be09..9a33620702f 100644
--- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
+++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
@@ -117,13 +117,13 @@ bool VirtualFunctionHelper::canLookupVirtualFunctionOverrides(Function *function
if (!m_document || m_snapshot.isEmpty() || !m_function || !m_scope)
return false;
- if (m_scope->isClass() && m_function->isPureVirtual()) {
+ if (m_scope->asClass() && m_function->isPureVirtual()) {
m_staticClassOfFunctionCallExpression = m_scope->asClass();
return true;
}
if (!m_baseExpressionAST || !m_expressionDocument
- || m_scope->isClass() || m_scope->isFunction()) {
+ || m_scope->asClass() || m_scope->asFunction()) {
return false;
}
@@ -191,7 +191,7 @@ Class *VirtualFunctionHelper::staticClassOfFunctionCallExpression_internal() con
const QList<Symbol *> symbols = binding->symbols();
if (!symbols.isEmpty()) {
Symbol * const first = symbols.first();
- if (first->isForwardClassDeclaration())
+ if (first->asForwardClassDeclaration())
result = m_finder->findMatchingClassDeclaration(first, m_snapshot);
}
}
@@ -207,7 +207,8 @@ Link findMacroLink_helper(const QByteArray &name, Document::Ptr doc, const Snaps
if (doc && !name.startsWith('<') && !processed->contains(doc->fileName())) {
processed->insert(doc->fileName());
- foreach (const Macro &macro, doc->definedMacros()) {
+ const QList<Macro> macros = doc->definedMacros();
+ for (const Macro &macro : macros) {
if (macro.name() == name) {
Link link;
link.targetFilePath = Utils::FilePath::fromString(macro.fileName());
@@ -252,7 +253,7 @@ static bool isForwardClassDeclaration(Type *type)
return true;
} else if (Template *templ = type->asTemplateType()) {
if (Symbol *declaration = templ->declaration()) {
- if (declaration->isForwardClassDeclaration())
+ if (declaration->asForwardClassDeclaration())
return true;
}
}
@@ -383,7 +384,7 @@ Link attemptDeclDef(const QTextCursor &cursor, Snapshot snapshot,
Symbol *findDefinition(Symbol *symbol, const Snapshot &snapshot, SymbolFinder *symbolFinder)
{
- if (symbol->isFunction())
+ if (symbol->asFunction())
return nullptr; // symbol is a function definition.
if (!symbol->type()->isFunctionType())
@@ -491,7 +492,7 @@ static int skipMatchingParentheses(const Tokens &tokens, int idx, int initialDep
void FollowSymbolUnderCursor::findLink(
const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool resolveTarget,
const Snapshot &theSnapshot,
const Document::Ptr &documentFromSemanticInfo,
@@ -644,7 +645,8 @@ void FollowSymbolUnderCursor::findLink(
// Handle include directives
if (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL)) {
const int lineno = cursor.blockNumber() + 1;
- foreach (const Document::Include &incl, doc->resolvedIncludes()) {
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &incl : includes) {
if (incl.line() == lineno) {
link.targetFilePath = Utils::FilePath::fromString(incl.resolvedFileName());
link.linkTextStart = beginOfToken + 1;
@@ -702,9 +704,9 @@ void FollowSymbolUnderCursor::findLink(
if (!resolvedSymbols.isEmpty()) {
LookupItem result = skipForwardDeclarations(resolvedSymbols);
- foreach (const LookupItem &r, resolvedSymbols) {
+ for (const LookupItem &r : resolvedSymbols) {
if (Symbol *d = r.declaration()) {
- if (d->isDeclaration() || d->isFunction()) {
+ if (d->asDeclaration() || d->asFunction()) {
const QString fileName = QString::fromUtf8(d->fileName(), d->fileNameLength());
if (data.filePath().toString() == fileName) {
if (line == d->line() && positionInBlock >= d->column()) {
@@ -713,7 +715,7 @@ void FollowSymbolUnderCursor::findLink(
break;
}
}
- } else if (d->isUsingDeclaration()) {
+ } else if (d->asUsingDeclaration()) {
int tokenBeginLineNumber = 0;
int tokenBeginColumnNumber = 0;
Utils::Text::convertPosition(document, beginOfToken, &tokenBeginLineNumber,
@@ -766,11 +768,11 @@ void FollowSymbolUnderCursor::findLink(
if (def == lastVisibleSymbol)
def = nullptr; // jump to declaration then.
- if (symbol->isForwardClassDeclaration()) {
+ if (symbol->asForwardClassDeclaration()) {
def = symbolFinder->findMatchingClassDeclaration(symbol, snapshot);
} else if (Template *templ = symbol->asTemplate()) {
if (Symbol *declaration = templ->declaration()) {
- if (declaration->isForwardClassDeclaration())
+ if (declaration->asForwardClassDeclaration())
def = symbolFinder->findMatchingClassDeclaration(declaration, snapshot);
}
}
@@ -801,7 +803,7 @@ void FollowSymbolUnderCursor::findLink(
void FollowSymbolUnderCursor::switchDeclDef(
const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
const CPlusPlus::Snapshot &snapshot,
const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
SymbolFinder *symbolFinder)
@@ -826,7 +828,7 @@ void FollowSymbolUnderCursor::switchDeclDef(
} else if (SimpleDeclarationAST *simpleDeclaration = ast->asSimpleDeclaration()) {
if (List<Symbol *> *symbols = simpleDeclaration->symbols) {
if (Symbol *symbol = symbols->value) {
- if (symbol->isDeclaration()) {
+ if (symbol->asDeclaration()) {
declarationSymbol = symbol;
if (symbol->type()->isFunctionType()) {
functionDeclarationSymbol = symbol;
@@ -856,7 +858,7 @@ void FollowSymbolUnderCursor::switchDeclDef(
functionDefinitionSymbol->enclosingScope());
QList<Symbol *> best;
- foreach (const LookupItem &r, declarations) {
+ for (const LookupItem &r : declarations) {
if (Symbol *decl = r.declaration()) {
if (Function *funTy = decl->type()->asFunctionType()) {
if (funTy->match(functionDefinitionSymbol)) {
diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.h b/src/plugins/cppeditor/cppfollowsymbolundercursor.h
index 08cb72027d4..d5780d948ec 100644
--- a/src/plugins/cppeditor/cppfollowsymbolundercursor.h
+++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.h
@@ -25,30 +25,35 @@
#pragma once
-#include "followsymbolinterface.h"
+#include "cppeditor_global.h"
+#include "cursorineditor.h"
-namespace CppEditor {
+#include <cplusplus/CppDocument.h>
+
+#include <texteditor/texteditor.h>
+namespace CppEditor {
+class SymbolFinder;
class VirtualFunctionAssistProvider;
-class CPPEDITOR_EXPORT FollowSymbolUnderCursor : public FollowSymbolInterface
+class CPPEDITOR_EXPORT FollowSymbolUnderCursor
{
public:
FollowSymbolUnderCursor();
void findLink(const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool resolveTarget,
const CPlusPlus::Snapshot &snapshot,
const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
SymbolFinder *symbolFinder,
- bool inNextSplit) override;
+ bool inNextSplit);
void switchDeclDef(const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
const CPlusPlus::Snapshot &snapshot,
const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder) override;
+ SymbolFinder *symbolFinder);
QSharedPointer<VirtualFunctionAssistProvider> virtualFunctionAssistProvider();
void setVirtualFunctionAssistProvider(
diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
index 41fb2b82c5e..99a8287afe5 100644
--- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
+++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
@@ -883,7 +883,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse
for (auto it = renamedTargetParameters.cbegin(), end = renamedTargetParameters.cend();
it != end; ++it) {
const QList<SemanticInfo::Use> &uses = localSymbols.uses.value(it.key());
- foreach (const SemanticInfo::Use &use, uses) {
+ for (const SemanticInfo::Use &use : uses) {
if (use.isInvalid())
continue;
const int useStart = targetFile->position(use.line, use.column);
diff --git a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
index d4fa1646cc7..8ca840e1282 100644
--- a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
+++ b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
@@ -218,7 +218,7 @@ ClassItem::~ClassItem()
Qt::ItemFlags ClassItem::flags() const
{
- foreach (FunctionItem *func, functions) {
+ for (FunctionItem *func : qAsConst(functions)) {
if (!func->alreadyFound)
return Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
}
@@ -231,7 +231,7 @@ Qt::CheckState ClassItem::checkState() const
if (functions.isEmpty())
return Qt::Unchecked;
Qt::CheckState state = functions.first()->checkState();
- foreach (FunctionItem *function, functions) {
+ for (FunctionItem *function : qAsConst(functions)) {
Qt::CheckState functionState = function->checkState();
if (functionState != state)
return Qt::PartiallyChecked;
@@ -280,7 +280,7 @@ QStringList defaultOverrideReplacements()
QStringList sortedAndTrimmedStringListWithoutEmptyElements(const QStringList &list)
{
QStringList result;
- foreach (const QString &replacement, list) {
+ for (const QString &replacement : list) {
const QString trimmedReplacement = replacement.trimmed();
if (!trimmedReplacement.isEmpty())
result << trimmedReplacement;
@@ -491,7 +491,7 @@ public:
}
} else {
auto classItem = static_cast<ClassItem *>(item);
- foreach (FunctionItem *funcItem, classItem->functions) {
+ for (FunctionItem *funcItem : qAsConst(classItem->functions)) {
if (funcItem->alreadyFound || funcItem->checked == checked)
continue;
QModelIndex funcIndex = createIndex(funcItem->row, 0, funcItem);
@@ -578,8 +578,9 @@ public:
ClassOrNamespace *clazz = baseClassQueue.dequeue();
visitedBaseClasses.insert(clazz);
const QList<ClassOrNamespace *> bases = clazz->usings();
- foreach (ClassOrNamespace *baseClass, bases) {
- foreach (Symbol *symbol, baseClass->symbols()) {
+ for (const ClassOrNamespace *baseClass : bases) {
+ const QList<Symbol *> symbols = baseClass->symbols();
+ for (Symbol *symbol : symbols) {
Class *base = symbol->asClass();
if (base
&& (clazz = interface.context().lookupType(symbol))
@@ -597,7 +598,7 @@ public:
Overview printer = CppCodeStyleSettings::currentProjectCodeStyleOverview();
printer.showFunctionSignatures = true;
QHash<const Function *, FunctionItem *> virtualFunctions;
- foreach (const Class *clazz, baseClasses) {
+ for (const Class *clazz : qAsConst(baseClasses)) {
ClassItem *itemBase = new ClassItem(printer.prettyName(clazz->name()), clazz);
for (Scope::iterator it = clazz->memberBegin(); it != clazz->memberEnd(); ++it) {
if (const Function *func = (*it)->type()->asFunctionType()) {
@@ -794,14 +795,14 @@ public:
UseMinimalNames useMinimalNames(targetCoN);
Control *control = context().bindings()->control().data();
QList<const Function *> insertedFunctions;
- foreach (ClassItem *classItem, m_factory->classFunctionModel->classes) {
+ for (ClassItem *classItem : qAsConst(m_factory->classFunctionModel->classes)) {
if (classItem->checkState() == Qt::Unchecked)
continue;
// Insert Declarations (+ definitions)
QString lastAccessSpecString;
bool first = true;
- foreach (FunctionItem *funcItem, classItem->functions) {
+ for (FunctionItem *funcItem : qAsConst(classItem->functions)) {
if (funcItem->reimplemented || funcItem->alreadyFound || !funcItem->checked)
continue;
@@ -1219,7 +1220,7 @@ void InsertVirtualMethodsDialog::setHideReimplementedFunctions(bool hide)
void InsertVirtualMethodsDialog::updateOverrideReplacementsComboBox()
{
m_overrideReplacementComboBox->clear();
- foreach (const QString &replacement, m_availableOverrideReplacements)
+ for (const QString &replacement : qAsConst(m_availableOverrideReplacements))
m_overrideReplacementComboBox->addItem(replacement);
}
diff --git a/src/plugins/cppeditor/cpplocalsymbols.cpp b/src/plugins/cppeditor/cpplocalsymbols.cpp
index ca20fbe92da..367efa83a9b 100644
--- a/src/plugins/cppeditor/cpplocalsymbols.cpp
+++ b/src/plugins/cppeditor/cpplocalsymbols.cpp
@@ -76,8 +76,8 @@ protected:
if (Symbol *member = scope->memberAt(i)) {
if (member->isTypedef())
continue;
- if (!member->isGenerated() && (member->isDeclaration() || member->isArgument())) {
- if (member->name() && member->name()->isNameId()) {
+ if (!member->isGenerated() && (member->asDeclaration() || member->asArgument())) {
+ if (member->name() && member->name()->asNameId()) {
const Token token = tokenAt(member->sourceLocation());
int line, column;
getPosition(token.utf16charsBegin(), &line, &column);
@@ -99,10 +99,10 @@ protected:
const Identifier *id = identifier(simpleName->identifier_token);
for (int i = _scopeStack.size() - 1; i != -1; --i) {
if (Symbol *member = _scopeStack.at(i)->find(id)) {
- if (member->isTypedef() || !(member->isDeclaration() || member->isArgument()))
+ if (member->isTypedef() || !(member->asDeclaration() || member->asArgument()))
continue;
if (!member->isGenerated() && (member->sourceLocation() < firstToken
- || member->enclosingScope()->isFunction())) {
+ || member->enclosingScope()->asFunction())) {
int line, column;
getTokenStartPosition(simpleName->identifier_token, &line, &column);
localUses[member].append(
diff --git a/src/plugins/cppeditor/cpplocalsymbols_test.cpp b/src/plugins/cppeditor/cpplocalsymbols_test.cpp
index ba0998e5695..4b9a8ef1fad 100644
--- a/src/plugins/cppeditor/cpplocalsymbols_test.cpp
+++ b/src/plugins/cppeditor/cpplocalsymbols_test.cpp
@@ -96,7 +96,7 @@ struct Result
for (auto it = localUses.cbegin(), end = localUses.cend(); it != end; ++it) {
const CPlusPlus::Symbol *symbol = it.key();
const QList<CppEditor::SemanticInfo::Use> &uses = it.value();
- foreach (const CppEditor::SemanticInfo::Use &use, uses)
+ for (const CppEditor::SemanticInfo::Use &use : uses)
result << fromHighlightingResult(symbol, use);
}
diff --git a/src/plugins/cppeditor/cpplocatordata.cpp b/src/plugins/cppeditor/cpplocatordata.cpp
index 6553bc93152..8c0453797f8 100644
--- a/src/plugins/cppeditor/cpplocatordata.cpp
+++ b/src/plugins/cppeditor/cpplocatordata.cpp
@@ -68,7 +68,7 @@ void CppLocatorData::onAboutToRemoveFiles(const QStringList &files)
QMutexLocker locker(&m_pendingDocumentsMutex);
- foreach (const QString &file, files) {
+ for (const QString &file : files) {
m_infosByFile.remove(file);
for (int i = 0; i < m_pendingDocuments.size(); ++i) {
@@ -91,7 +91,7 @@ void CppLocatorData::flushPendingDocument(bool force) const
if (m_pendingDocuments.isEmpty())
return;
- foreach (CPlusPlus::Document::Ptr doc, m_pendingDocuments)
+ for (CPlusPlus::Document::Ptr doc : qAsConst(m_pendingDocuments))
m_infosByFile.insert(Internal::StringTable::insert(doc->fileName()), m_search(doc));
m_pendingDocuments.clear();
diff --git a/src/plugins/cppeditor/cppminimizableinfobars.cpp b/src/plugins/cppeditor/cppminimizableinfobars.cpp
deleted file mode 100644
index 7eb80622c0e..00000000000
--- a/src/plugins/cppeditor/cppminimizableinfobars.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cppminimizableinfobars.h"
-
-#include "cppeditorconstants.h"
-#include "cpptoolssettings.h"
-
-#include <QToolButton>
-
-#include <utils/infobar.h>
-#include <utils/qtcassert.h>
-#include <utils/utilsicons.h>
-
-using namespace Utils;
-
-namespace CppEditor {
-namespace Internal {
-
-static CppToolsSettings *settings() { return CppToolsSettings::instance(); }
-
-MinimizableInfoBars::MinimizableInfoBars(InfoBar &infoBar, QObject *parent)
- : QObject(parent)
- , m_infoBar(infoBar)
-{
- connect(settings(), &CppToolsSettings::showHeaderErrorInfoBarChanged,
- this, &MinimizableInfoBars::updateHeaderErrors);
- connect(settings(), &CppToolsSettings::showNoProjectInfoBarChanged,
- this, &MinimizableInfoBars::updateNoProjectConfiguration);
-}
-
-MinimizableInfoBars::Actions MinimizableInfoBars::createShowInfoBarActions(
- const ActionCreator &actionCreator)
-{
- Actions result;
- QTC_ASSERT(actionCreator, return result);
-
- // No project configuration available
- auto *button = new QToolButton();
- button->setToolTip(tr("File is not part of any project."));
- button->setIcon(Utils::Icons::WARNING_TOOLBAR.pixmap());
- connect(button, &QAbstractButton::clicked, []() {
- settings()->setShowNoProjectInfoBar(true);
- });
- QAction *action = actionCreator(button);
- action->setVisible(!settings()->showNoProjectInfoBar());
- result.insert(Constants::NO_PROJECT_CONFIGURATION, action);
-
- // Errors in included files
- button = new QToolButton();
- button->setToolTip(tr("File contains errors in included files."));
- button->setIcon(Utils::Icons::WARNING_TOOLBAR.pixmap());
- connect(button, &QAbstractButton::clicked, []() {
- settings()->setShowHeaderErrorInfoBar(true);
- });
- action = actionCreator(button);
- action->setVisible(!settings()->showHeaderErrorInfoBar());
- result.insert(Constants::ERRORS_IN_HEADER_FILES, action);
-
- return result;
-}
-
-void MinimizableInfoBars::processHeaderDiagnostics(
- const DiagnosticWidgetCreator &diagnosticWidgetCreator)
-{
- m_diagnosticWidgetCreator = diagnosticWidgetCreator;
- updateHeaderErrors();
-}
-
-void MinimizableInfoBars::processHasProjectPart(bool hasProjectPart)
-{
- m_hasProjectPart = hasProjectPart;
- updateNoProjectConfiguration();
-}
-
-void MinimizableInfoBars::updateHeaderErrors()
-{
- const Id id(Constants::ERRORS_IN_HEADER_FILES);
- m_infoBar.removeInfo(id);
-
- bool show = false;
- // Show the info entry only if there is a project configuration.
- if (m_hasProjectPart && m_diagnosticWidgetCreator) {
- if (settings()->showHeaderErrorInfoBar())
- addHeaderErrorEntry(id, m_diagnosticWidgetCreator);
- else
- show = true;
- }
-
- emit showAction(id, show);
-}
-
-void MinimizableInfoBars::updateNoProjectConfiguration()
-{
- const Id id(Constants::NO_PROJECT_CONFIGURATION);
- m_infoBar.removeInfo(id);
-
- bool show = false;
- if (!m_hasProjectPart) {
- if (settings()->showNoProjectInfoBar())
- addNoProjectConfigurationEntry(id);
- else
- show = true;
- }
-
- emit showAction(id, show);
-}
-
-static InfoBarEntry createMinimizableInfo(const Id &id,
- const QString &text,
- std::function<void()> minimizer)
-{
- QTC_CHECK(minimizer);
-
- InfoBarEntry info(id, text);
- info.removeCancelButton();
- // The minimizer() might delete the "Minimize" button immediately and as
- // result invalid reads will happen in QToolButton::mouseReleaseEvent().
- // Avoid this by running the minimizer in the next event loop iteration.
- info.addCustomButton(MinimizableInfoBars::tr("Minimize"), [minimizer] {
- QMetaObject::invokeMethod(settings(), [minimizer] { minimizer(); }, Qt::QueuedConnection);
- });
-
- return info;
-}
-
-void MinimizableInfoBars::addNoProjectConfigurationEntry(const Id &id)
-{
- const QString text = tr("<b>Warning</b>: This file is not part of any project. "
- "The code model might have issues parsing this file properly.");
-
- m_infoBar.addInfo(createMinimizableInfo(id, text, []() {
- settings()->setShowNoProjectInfoBar(false);
- }));
-}
-
-void MinimizableInfoBars::addHeaderErrorEntry(const Id &id,
- const DiagnosticWidgetCreator &diagnosticWidgetCreator)
-{
- const QString text = tr("<b>Warning</b>: The code model could not parse an included file, "
- "which might lead to incorrect code completion and "
- "highlighting, for example.");
-
- InfoBarEntry info = createMinimizableInfo(id, text, []() {
- settings()->setShowHeaderErrorInfoBar(false);
- });
- info.setDetailsWidgetCreator(diagnosticWidgetCreator);
-
- m_infoBar.addInfo(info);
-}
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppminimizableinfobars.h b/src/plugins/cppeditor/cppminimizableinfobars.h
deleted file mode 100644
index 8c9ef9dfd1b..00000000000
--- a/src/plugins/cppeditor/cppminimizableinfobars.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/id.h>
-
-#include <QAction>
-#include <QHash>
-#include <QObject>
-
-#include <functional>
-
-namespace Utils {
-class InfoBar;
-}
-
-namespace CppEditor {
-namespace Internal {
-
-class MinimizableInfoBars : public QObject
-{
- Q_OBJECT
-
-public:
- using DiagnosticWidgetCreator = std::function<QWidget *()>;
- using ActionCreator = std::function<QAction *(QWidget *widget)>;
- using Actions = QHash<Utils::Id, QAction *>;
-
- static Actions createShowInfoBarActions(const ActionCreator &actionCreator);
-
-public:
- explicit MinimizableInfoBars(Utils::InfoBar &infoBar, QObject *parent = nullptr);
-
- // Expected call order: processHasProjectPart(), processHeaderDiagnostics()
- void processHasProjectPart(bool hasProjectPart);
- void processHeaderDiagnostics(const DiagnosticWidgetCreator &diagnosticWidgetCreator);
-
-signals:
- void showAction(const Utils::Id &id, bool show);
-
-private:
- void updateNoProjectConfiguration();
- void updateHeaderErrors();
-
- void addNoProjectConfigurationEntry(const Utils::Id &id);
- void addHeaderErrorEntry(const Utils::Id &id,
- const DiagnosticWidgetCreator &diagnosticWidgetCreator);
-
-private:
- Utils::InfoBar &m_infoBar;
-
- bool m_hasProjectPart = true;
- DiagnosticWidgetCreator m_diagnosticWidgetCreator;
-};
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppmodelmanager.cpp b/src/plugins/cppeditor/cppmodelmanager.cpp
index 726b6c4f46d..dd47ae5f5a5 100644
--- a/src/plugins/cppeditor/cppmodelmanager.cpp
+++ b/src/plugins/cppeditor/cppmodelmanager.cpp
@@ -32,23 +32,18 @@
#include "cppcodemodelinspectordumper.h"
#include "cppcurrentdocumentfilter.h"
#include "cppeditorconstants.h"
-#include "cppeditorplugin.h"
#include "cppfindreferences.h"
#include "cppincludesfilter.h"
#include "cppindexingsupport.h"
#include "cpplocatordata.h"
#include "cpplocatorfilter.h"
#include "cppbuiltinmodelmanagersupport.h"
-#include "cpprefactoringchanges.h"
-#include "cpprefactoringengine.h"
#include "cppsourceprocessor.h"
#include "cpptoolsjsextension.h"
#include "cpptoolsreuse.h"
#include "editordocumenthandle.h"
-#include "stringtable.h"
#include "symbolfinder.h"
#include "symbolsfindfilter.h"
-#include "followsymbolinterface.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -57,15 +52,20 @@
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/vcsmanager.h>
#include <cplusplus/ASTPath.h>
+#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/TypeOfExpression.h>
#include <extensionsystem/pluginmanager.h>
+
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmacro.h>
#include <projectexplorer/session.h>
+
#include <texteditor/textdocument.h>
+
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
@@ -137,8 +137,6 @@ protected:
namespace CppEditor {
-using REType = RefactoringEngineType;
-
namespace Internal {
static CppModelManager *m_instance;
@@ -198,10 +196,6 @@ public:
QTimer m_delayedGcTimer;
QTimer m_fallbackProjectPartTimer;
- // Refactoring
- using REHash = QMap<REType, RefactoringEngineInterface *>;
- REHash m_refactoringEngines;
-
CppLocatorData m_locatorData;
std::unique_ptr<Core::ILocatorFilter> m_locatorFilter;
std::unique_ptr<Core::ILocatorFilter> m_classesFilter;
@@ -209,6 +203,8 @@ public:
std::unique_ptr<Core::ILocatorFilter> m_functionsFilter;
std::unique_ptr<Core::IFindFilter> m_symbolsFindFilter;
std::unique_ptr<Core::ILocatorFilter> m_currentDocumentFilter;
+
+ QList<Document::DiagnosticMessage> m_diagnosticMessages;
};
} // namespace Internal
@@ -267,7 +263,7 @@ QSet<QString> CppModelManager::timeStampModifiedFiles(const QList<Document::Ptr>
{
QSet<QString> sourceFiles;
- foreach (const Document::Ptr doc, documentsToCheck) {
+ for (const Document::Ptr &doc : documentsToCheck) {
const QDateTime lastModified = doc->lastModified();
if (!lastModified.isNull()) {
@@ -309,65 +305,64 @@ QString CppModelManager::editorConfigurationFileName()
return QLatin1String("<per-editor-defines>");
}
-static RefactoringEngineInterface *getRefactoringEngine(CppModelManagerPrivate::REHash &engines)
+ModelManagerSupport *CppModelManager::modelManagerSupport(Backend backend) const
{
- QTC_ASSERT(!engines.empty(), return nullptr;);
- RefactoringEngineInterface *currentEngine = engines[REType::BuiltIn];
- if (engines.find(REType::ClangCodeModel) != engines.end()) {
- currentEngine = engines[REType::ClangCodeModel];
- } else if (engines.find(REType::ClangRefactoring) != engines.end()) {
- RefactoringEngineInterface *engine = engines[REType::ClangRefactoring];
- if (engine->isRefactoringEngineAvailable())
- currentEngine = engine;
- }
- return currentEngine;
+ return (backend == Backend::Builtin
+ ? d->m_builtinModelManagerSupport : d->m_activeModelManagerSupport).data();
}
void CppModelManager::startLocalRenaming(const CursorInEditor &data,
const ProjectPart *projectPart,
- RenameCallback &&renameSymbolsCallback)
+ RenameCallback &&renameSymbolsCallback,
+ Backend backend)
{
- RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
- QTC_ASSERT(engine, return;);
- engine->startLocalRenaming(data, projectPart, std::move(renameSymbolsCallback));
+ instance()->modelManagerSupport(backend)
+ ->startLocalRenaming(data, projectPart, std::move(renameSymbolsCallback));
}
-void CppModelManager::globalRename(const CursorInEditor &data, UsagesCallback &&renameCallback,
- const QString &replacement)
+void CppModelManager::globalRename(const CursorInEditor &data, const QString &replacement,
+ Backend backend)
{
- RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
- QTC_ASSERT(engine, return;);
- engine->globalRename(data, std::move(renameCallback), replacement);
+ instance()->modelManagerSupport(backend)->globalRename(data, replacement);
}
-void CppModelManager::findUsages(const CursorInEditor &data,
- UsagesCallback &&showUsagesCallback) const
+void CppModelManager::findUsages(const CursorInEditor &data, Backend backend)
{
- RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
- QTC_ASSERT(engine, return;);
- engine->findUsages(data, std::move(showUsagesCallback));
+ instance()->modelManagerSupport(backend)->findUsages(data);
}
-void CppModelManager::globalFollowSymbol(
- const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder,
- bool inNextSplit) const
+void CppModelManager::switchHeaderSource(bool inNextSplit, Backend backend)
{
- RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
- QTC_ASSERT(engine, return;);
- engine->globalFollowSymbol(data, std::move(processLinkCallback), snapshot, documentFromSemanticInfo,
- symbolFinder, inNextSplit);
+ const Core::IDocument *currentDocument = Core::EditorManager::currentDocument();
+ QTC_ASSERT(currentDocument, return);
+ instance()->modelManagerSupport(backend)->switchHeaderSource(currentDocument->filePath(),
+ inNextSplit);
}
-bool CppModelManager::positionRequiresSignal(const QString &filePath, const QByteArray &content,
- int position) const
+int argumentPositionOf(const AST *last, const CallAST *callAst)
{
- if (content.isEmpty())
+ if (!callAst || !callAst->expression_list)
return false;
+ int num = 0;
+ for (ExpressionListAST *it = callAst->expression_list; it; it = it->next) {
+ ++num;
+ const ExpressionAST *const arg = it->value;
+ if (arg->firstToken() <= last->firstToken()
+ && arg->lastToken() >= last->lastToken()) {
+ return num;
+ }
+ }
+ return 0;
+}
+
+SignalSlotType CppModelManager::getSignalSlotType(const QString &filePath,
+ const QByteArray &content,
+ int position) const
+{
+ if (content.isEmpty())
+ return SignalSlotType::None;
+
// Insert a dummy prefix if we don't have a real one. Otherwise the AST path will not contain
// anything after the CallAST.
QByteArray fixedContent = content;
@@ -382,28 +377,36 @@ bool CppModelManager::positionRequiresSignal(const QString &filePath, const QByt
QTextCursor cursor(&textDocument);
cursor.setPosition(position);
- // Are we at the second argument of a function call?
const QList<AST *> path = ASTPath(document)(cursor);
- if (path.isEmpty() || !path.last()->asSimpleName())
- return false;
+ if (path.isEmpty())
+ return SignalSlotType::None;
const CallAST *callAst = nullptr;
for (auto it = path.crbegin(); it != path.crend(); ++it) {
if ((callAst = (*it)->asCall()))
break;
}
- if (!callAst)
- return false;
- if (!callAst->expression_list || !callAst->expression_list->next)
- return false;
- const ExpressionAST * const secondArg = callAst->expression_list->next->value;
- if (secondArg->firstToken() > path.last()->firstToken()
- || secondArg->lastToken() < path.last()->lastToken()) {
- return false;
- }
- // Is the function called "connect" or "disconnect"?
- if (!callAst->base_expression)
- return false;
+ if (!callAst || !callAst->base_expression)
+ return SignalSlotType::None;
+
+ const int argumentPosition = argumentPositionOf(path.last(), callAst);
+ if (argumentPosition != 2 && argumentPosition != 4)
+ return SignalSlotType::None;
+
+ const NameAST *nameAst = nullptr;
+ if (const IdExpressionAST * const idAst = callAst->base_expression->asIdExpression())
+ nameAst = idAst->name;
+ else if (const MemberAccessAST * const ast = callAst->base_expression->asMemberAccess())
+ nameAst = ast->member_name;
+ if (!nameAst || !nameAst->name)
+ return SignalSlotType::None;
+ const Identifier * const id = nameAst->name->identifier();
+ if (!id)
+ return SignalSlotType::None;
+ const QString funcName = QString::fromUtf8(id->chars(), id->size());
+ if (funcName != "connect" && funcName != "disconnect")
+ return SignalSlotType::None;
+
Scope *scope = document->globalNamespace();
for (auto it = path.crbegin(); it != path.crend(); ++it) {
if (const CompoundStatementAST * const stmtAst = (*it)->asCompoundStatement()) {
@@ -411,18 +414,14 @@ bool CppModelManager::positionRequiresSignal(const QString &filePath, const QByt
break;
}
}
- const NameAST *nameAst = nullptr;
const LookupContext context(document, snapshot);
- if (const IdExpressionAST * const idAst = callAst->base_expression->asIdExpression()) {
- nameAst = idAst->name;
- } else if (const MemberAccessAST * const ast = callAst->base_expression->asMemberAccess()) {
- nameAst = ast->member_name;
+ if (const MemberAccessAST * const ast = callAst->base_expression->asMemberAccess()) {
TypeOfExpression exprType;
exprType.setExpandTemplates(true);
exprType.init(document, snapshot);
const QList<LookupItem> typeMatches = exprType(ast->base_expression, document, scope);
if (typeMatches.isEmpty())
- return false;
+ return SignalSlotType::None;
const std::function<const NamedType *(const FullySpecifiedType &)> getNamedType
= [&getNamedType](const FullySpecifiedType &type ) -> const NamedType * {
Type * const t = type.type();
@@ -438,22 +437,14 @@ bool CppModelManager::positionRequiresSignal(const QString &filePath, const QByt
if (!namedType && typeMatches.first().declaration())
namedType = getNamedType(typeMatches.first().declaration()->type());
if (!namedType)
- return false;
+ return SignalSlotType::None;
const ClassOrNamespace * const result = context.lookupType(namedType->name(), scope);
if (!result)
- return false;
+ return SignalSlotType::None;
scope = result->rootClass();
if (!scope)
- return false;
+ return SignalSlotType::None;
}
- if (!nameAst || !nameAst->name)
- return false;
- const Identifier * const id = nameAst->name->identifier();
- if (!id)
- return false;
- const QString funcName = QString::fromUtf8(id->chars(), id->size());
- if (funcName != "connect" && funcName != "disconnect")
- return false;
// Is the function a member function of QObject?
const QList<LookupItem> matches = context.lookup(nameAst->name, scope);
@@ -464,32 +455,33 @@ bool CppModelManager::positionRequiresSignal(const QString &filePath, const QByt
if (!klass || !klass->name())
continue;
const Identifier * const classId = klass->name()->identifier();
- if (classId && QString::fromUtf8(classId->chars(), classId->size()) == "QObject")
- return true;
- }
+ if (classId && QString::fromUtf8(classId->chars(), classId->size()) == "QObject") {
+ QString expression;
+ LanguageFeatures features = LanguageFeatures::defaultFeatures();
+ CPlusPlus::ExpressionUnderCursor expressionUnderCursor(features);
+ for (int i = cursor.position(); i > 0; --i)
+ if (textDocument.characterAt(i) == '(') {
+ cursor.setPosition(i);
+ break;
+ }
- return false;
-}
+ expression = expressionUnderCursor(cursor);
-void CppModelManager::addRefactoringEngine(RefactoringEngineType type,
- RefactoringEngineInterface *refactoringEngine)
-{
- instance()->d->m_refactoringEngines[type] = refactoringEngine;
-}
+ if (expression.endsWith(QLatin1String("SIGNAL"))
+ || (expression.endsWith(QLatin1String("SLOT")) && argumentPosition == 4))
+ return SignalSlotType::OldStyleSignal;
-void CppModelManager::removeRefactoringEngine(RefactoringEngineType type)
-{
- instance()->d->m_refactoringEngines.remove(type);
-}
-
-RefactoringEngineInterface *CppModelManager::builtinRefactoringEngine()
-{
- return instance()->d->m_refactoringEngines.value(RefactoringEngineType::BuiltIn);
+ if (argumentPosition == 2)
+ return SignalSlotType::NewStyleSignal;
+ }
+ }
+ return SignalSlotType::None;
}
-FollowSymbolInterface &CppModelManager::builtinFollowSymbol()
+FollowSymbolUnderCursor &CppModelManager::builtinFollowSymbol()
{
- return instance()->d->m_builtinModelManagerSupport->followSymbolInterface();
+ return instance()->d->m_builtinModelManagerSupport.staticCast<BuiltinModelManagerSupport>()
+ ->followSymbolInterface();
}
template<class FilterClass>
@@ -560,14 +552,9 @@ Core::ILocatorFilter *CppModelManager::currentDocumentFilter() const
return d->m_currentDocumentFilter.get();
}
-FollowSymbolInterface &CppModelManager::followSymbolInterface() const
-{
- return d->m_activeModelManagerSupport->followSymbolInterface();
-}
-
std::unique_ptr<AbstractOverviewModel> CppModelManager::createOverviewModel() const
{
- return d->m_activeModelManagerSupport->createOverviewModel();
+ return d->m_builtinModelManagerSupport->createOverviewModel();
}
QString CppModelManager::configurationFileName()
@@ -579,7 +566,7 @@ void CppModelManager::updateModifiedSourceFiles()
{
const Snapshot snapshot = this->snapshot();
QList<Document::Ptr> documentsToCheck;
- foreach (const Document::Ptr document, snapshot)
+ for (const Document::Ptr &document : snapshot)
documentsToCheck << document;
updateSourceFiles(timeStampModifiedFiles(documentsToCheck));
@@ -641,8 +628,6 @@ void CppModelManager::initializeBuiltinModelManagerSupport()
d->m_builtinModelManagerSupport
= BuiltinModelManagerSupportProvider().createModelManagerSupport();
d->m_activeModelManagerSupport = d->m_builtinModelManagerSupport;
- d->m_refactoringEngines[RefactoringEngineType::BuiltIn] =
- &d->m_activeModelManagerSupport->refactoringEngineInterface();
}
CppModelManager::CppModelManager()
@@ -933,7 +918,8 @@ WorkingCopy CppModelManager::buildWorkingCopyList()
{
WorkingCopy workingCopy;
- foreach (const CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments()) {
+ const QList<CppEditorDocumentHandle *> cppEditorDocumentList = cppEditorDocuments();
+ for (const CppEditorDocumentHandle *cppEditorDocument : cppEditorDocumentList) {
workingCopy.insert(cppEditorDocument->filePath(),
cppEditorDocument->contents(),
cppEditorDocument->revision());
@@ -1012,16 +998,17 @@ ProjectInfo::ConstPtr CppModelManager::projectInfo(ProjectExplorer::Project *pro
void CppModelManager::removeProjectInfoFilesAndIncludesFromSnapshot(const ProjectInfo &projectInfo)
{
QMutexLocker snapshotLocker(&d->m_snapshotMutex);
- foreach (const ProjectPart::ConstPtr &projectPart, projectInfo.projectParts()) {
- foreach (const ProjectFile &cxxFile, projectPart->files) {
- foreach (const QString &fileName, d->m_snapshot.allIncludesForDocument(cxxFile.path))
+ for (const ProjectPart::ConstPtr &projectPart : projectInfo.projectParts()) {
+ for (const ProjectFile &cxxFile : qAsConst(projectPart->files)) {
+ const QSet<QString> fileNames = d->m_snapshot.allIncludesForDocument(cxxFile.path);
+ for (const QString &fileName : fileNames)
d->m_snapshot.remove(fileName);
d->m_snapshot.remove(cxxFile.path);
}
}
}
-QList<CppEditorDocumentHandle *> CppModelManager::cppEditorDocuments() const
+const QList<CppEditorDocumentHandle *> CppModelManager::cppEditorDocuments() const
{
QMutexLocker locker(&d->m_cppEditorDocumentsMutex);
return d->m_cppEditorDocuments.values();
@@ -1091,7 +1078,7 @@ private:
{
QSet<QString> ids;
- foreach (const ProjectPart::ConstPtr &projectPart, projectParts)
+ for (const ProjectPart::ConstPtr &projectPart : projectParts)
ids.insert(projectPart->id());
return ids;
@@ -1145,7 +1132,8 @@ void CppModelManager::updateCppEditorDocuments(bool projectsUpdated) const
{
// Refresh visible documents
QSet<Core::IDocument *> visibleCppEditorDocuments;
- foreach (Core::IEditor *editor, Core::EditorManager::visibleEditors()) {
+ const QList<Core::IEditor *> editors = Core::EditorManager::visibleEditors();
+ for (Core::IEditor *editor: editors) {
if (Core::IDocument *document = editor->document()) {
const QString filePath = document->filePath().toString();
if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) {
@@ -1159,7 +1147,7 @@ void CppModelManager::updateCppEditorDocuments(bool projectsUpdated) const
QSet<Core::IDocument *> invisibleCppEditorDocuments
= Utils::toSet(Core::DocumentModel::openedDocuments());
invisibleCppEditorDocuments.subtract(visibleCppEditorDocuments);
- foreach (Core::IDocument *document, invisibleCppEditorDocuments) {
+ for (Core::IDocument *document : qAsConst(invisibleCppEditorDocuments)) {
const QString filePath = document->filePath().toString();
if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) {
const CppEditorDocumentHandle::RefreshReason refreshReason = projectsUpdated
@@ -1316,14 +1304,9 @@ bool CppModelManager::isCppEditor(Core::IEditor *editor)
return editor->context().contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID);
}
-bool CppModelManager::supportsOutline(const TextEditor::TextDocument *document)
+bool CppModelManager::usesClangd(const TextEditor::TextDocument *document)
{
- return instance()->d->m_activeModelManagerSupport->supportsOutline(document);
-}
-
-bool CppModelManager::supportsLocalUses(const TextEditor::TextDocument *document)
-{
- return instance()->d->m_activeModelManagerSupport->supportsLocalUses(document);
+ return instance()->d->m_activeModelManagerSupport->usesClangd(document);
}
bool CppModelManager::isClangCodeModelActive() const
@@ -1481,8 +1464,9 @@ void CppModelManager::renameIncludes(const Utils::FilePath &oldFilePath,
const TextEditor::RefactoringChanges changes;
- foreach (Snapshot::IncludeLocation loc,
- snapshot().includeLocationsOfDocument(oldFilePath.toString())) {
+ const QList<Snapshot::IncludeLocation> locations = snapshot().includeLocationsOfDocument(
+ oldFilePath.toString());
+ for (const Snapshot::IncludeLocation &loc : locations) {
TextEditor::RefactoringFilePtr file = changes.file(
Utils::FilePath::fromString(loc.first->fileName()));
const QTextBlock &block = file->document()->findBlockByNumber(loc.second - 1);
@@ -1533,13 +1517,13 @@ QSet<QString> CppModelManager::symbolsInFiles(const QSet<Utils::FilePath> &files
const CPlusPlus::Identifier *symId = sym->identifier();
// Add any class, function or namespace identifiers
- if ((sym->isClass() || sym->isFunction() || sym->isNamespace()) && symId
+ if ((sym->asClass() || sym->asFunction() || sym->asNamespace()) && symId
&& symId->chars()) {
uniqueSymbols.insert(QString::fromUtf8(symId->chars()));
}
// Handle specific case : get "Foo" in "void Foo::function() {}"
- if (sym->isFunction() && !sym->asFunction()->isDeclaration()) {
+ if (sym->asFunction() && !sym->asFunction()->asDeclaration()) {
const char *className = belongingClassName(sym->asFunction());
if (className)
uniqueSymbols.insert(QString::fromUtf8(className));
@@ -1580,7 +1564,7 @@ void CppModelManager::setupFallbackProjectPart()
if (sysroot.isEmpty())
sysroot = Utils::FilePath::fromString(defaultTc->sysRoot());
Utils::Environment env = defaultKit->buildEnvironment();
- tcInfo = ToolChainInfo(defaultTc, sysroot.toString(), env);
+ tcInfo = ToolChainInfo(defaultTc, sysroot, env);
const auto macroInspectionWrapper = [runner = tcInfo.macroInspectionRunner](
const QStringList &flags) {
ToolChain::MacroInspectionReport report = runner(flags);
@@ -1605,10 +1589,12 @@ void CppModelManager::GC()
// Collect files of opened editors and editor supports (e.g. ui code model)
QStringList filesInEditorSupports;
- foreach (const CppEditorDocumentHandle *editorDocument, cppEditorDocuments())
+ const QList<CppEditorDocumentHandle *> editorDocuments = cppEditorDocuments();
+ for (const CppEditorDocumentHandle *editorDocument : editorDocuments)
filesInEditorSupports << editorDocument->filePath();
- foreach (AbstractEditorSupport *abstractEditorSupport, abstractEditorSupports())
+ const QSet<AbstractEditorSupport *> abstractEditorSupportList = abstractEditorSupports();
+ for (AbstractEditorSupport *abstractEditorSupport : abstractEditorSupportList)
filesInEditorSupports << abstractEditorSupport->fileName();
Snapshot currentSnapshot = snapshot();
@@ -1661,23 +1647,38 @@ void CppModelManager::activateClangCodeModel(
QTC_ASSERT(modelManagerSupportProvider, return);
d->m_activeModelManagerSupport = modelManagerSupportProvider->createModelManagerSupport();
- d->m_refactoringEngines[RefactoringEngineType::ClangCodeModel] =
- &d->m_activeModelManagerSupport->refactoringEngineInterface();
}
CppCompletionAssistProvider *CppModelManager::completionAssistProvider() const
{
- return d->m_activeModelManagerSupport->completionAssistProvider();
+ return d->m_builtinModelManagerSupport->completionAssistProvider();
+}
+
+TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const
+{
+ return d->m_builtinModelManagerSupport->createHoverHandler();
}
-CppCompletionAssistProvider *CppModelManager::functionHintAssistProvider() const
+void CppModelManager::followSymbol(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback,
+ bool resolveTarget, bool inNextSplit, Backend backend)
{
- return d->m_activeModelManagerSupport->functionHintAssistProvider();
+ instance()->modelManagerSupport(backend)->followSymbol(data, processLinkCallback,
+ resolveTarget, inNextSplit);
}
-TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const
+void CppModelManager::switchDeclDef(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback,
+ Backend backend)
{
- return d->m_activeModelManagerSupport->createHoverHandler();
+ instance()->modelManagerSupport(backend)->switchDeclDef(data, processLinkCallback);
+}
+
+Core::ILocatorFilter *CppModelManager::createAuxiliaryCurrentDocumentFilter()
+{
+ const auto filter = new Internal::CppCurrentDocumentFilter(instance());
+ filter->makeAuxiliary();
+ return filter;
}
BaseEditorDocumentProcessor *CppModelManager::createEditorDocumentProcessor(
@@ -1737,4 +1738,18 @@ QThreadPool *CppModelManager::sharedThreadPool()
return &d->m_threadPool;
}
+bool CppModelManager::setExtraDiagnostics(const QString &fileName,
+ const QString &kind,
+ const QList<Document::DiagnosticMessage> &diagnostics)
+{
+ d->m_diagnosticMessages = diagnostics;
+ emit diagnosticsChanged(fileName, kind);
+ return true;
+}
+
+const QList<Document::DiagnosticMessage> CppModelManager::diagnosticMessages()
+{
+ return d->m_diagnosticMessages;
+}
+
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppmodelmanager.h b/src/plugins/cppeditor/cppmodelmanager.h
index fadb00657d9..e00dccbf33d 100644
--- a/src/plugins/cppeditor/cppmodelmanager.h
+++ b/src/plugins/cppeditor/cppmodelmanager.h
@@ -27,14 +27,15 @@
#include "cppeditor_global.h"
-#include "refactoringengineinterface.h"
+#include "cursorineditor.h"
#include "projectinfo.h"
#include "projectpart.h"
-#include <projectexplorer/headerpath.h>
#include <cplusplus/cppmodelmanagerbase.h>
#include <coreplugin/find/ifindfilter.h>
#include <coreplugin/locator/ilocatorfilter.h>
+#include <projectexplorer/headerpath.h>
+#include <utils/link.h>
#include <QFuture>
#include <QObject>
@@ -44,7 +45,11 @@ namespace Core {
class IDocument;
class IEditor;
}
-namespace CPlusPlus { class LookupContext; }
+namespace CPlusPlus {
+class AST;
+class CallAST;
+class LookupContext;
+} // namespace CPlusPlus
namespace ProjectExplorer { class Project; }
namespace TextEditor {
class BaseHoverHandler;
@@ -60,8 +65,9 @@ class CppCompletionAssistProvider;
class CppEditorDocumentHandle;
class CppIndexingSupport;
class CppLocatorData;
+class FollowSymbolUnderCursor;
class ModelManagerSupportProvider;
-class FollowSymbolInterface;
+class ModelManagerSupport;
class SymbolFinder;
class WorkingCopy;
@@ -73,15 +79,13 @@ class CppModelManagerPrivate;
namespace Tests { class ModelManagerTestHelper; }
-enum class RefactoringEngineType : int
-{
- BuiltIn = 0,
- ClangCodeModel = 1,
- ClangRefactoring = 2
+enum class SignalSlotType {
+ OldStyleSignal,
+ NewStyleSignal,
+ None
};
-class CPPEDITOR_EXPORT CppModelManager final : public CPlusPlus::CppModelManagerBase,
- public RefactoringEngineInterface
+class CPPEDITOR_EXPORT CppModelManager final : public CPlusPlus::CppModelManagerBase
{
Q_OBJECT
@@ -110,6 +114,12 @@ public:
QByteArray codeModelConfiguration() const;
CppLocatorData *locatorData() const;
+ bool setExtraDiagnostics(const QString &fileName,
+ const QString &kind,
+ const QList<Document::DiagnosticMessage> &diagnostics) override;
+
+ const QList<Document::DiagnosticMessage> diagnosticMessages();
+
QList<ProjectInfo::ConstPtr> projectInfos() const;
ProjectInfo::ConstPtr projectInfo(ProjectExplorer::Project *project) const;
QFuture<void> updateProjectInfo(const ProjectInfo::ConstPtr &newProjectInfo,
@@ -139,15 +149,14 @@ public:
void emitAbstractEditorSupportRemoved(const QString &filePath);
static bool isCppEditor(Core::IEditor *editor);
- static bool supportsOutline(const TextEditor::TextDocument *document);
- static bool supportsLocalUses(const TextEditor::TextDocument *document);
+ static bool usesClangd(const TextEditor::TextDocument *document);
bool isClangCodeModelActive() const;
QSet<AbstractEditorSupport*> abstractEditorSupports() const;
void addExtraEditorSupport(AbstractEditorSupport *editorSupport);
void removeExtraEditorSupport(AbstractEditorSupport *editorSupport);
- QList<CppEditorDocumentHandle *> cppEditorDocuments() const;
+ const QList<CppEditorDocumentHandle *> cppEditorDocuments() const;
CppEditorDocumentHandle *cppEditorDocument(const QString &filePath) const;
static BaseEditorDocumentProcessor *cppEditorDocumentProcessor(const QString &filePath);
void registerCppEditorDocument(CppEditorDocumentHandle *cppEditorDocument);
@@ -155,22 +164,9 @@ public:
QList<int> references(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
- void startLocalRenaming(const CursorInEditor &data,
- const ProjectPart *projectPart,
- RenameCallback &&renameSymbolsCallback) final;
- void globalRename(const CursorInEditor &data, UsagesCallback &&renameCallback,
- const QString &replacement) final;
- void findUsages(const CursorInEditor &data,
- UsagesCallback &&showUsagesCallback) const final;
- void globalFollowSymbol(const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- const CPlusPlus::Snapshot &snapshot,
- const Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder,
- bool inNextSplit) const final;
-
- bool positionRequiresSignal(const QString &filePath, const QByteArray &content,
- int position) const;
+ SignalSlotType getSignalSlotType(const QString &filePath,
+ const QByteArray &content,
+ int position) const;
void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context,
const QString &replacement = QString());
@@ -183,11 +179,28 @@ public:
void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider);
CppCompletionAssistProvider *completionAssistProvider() const;
- CppCompletionAssistProvider *functionHintAssistProvider() const;
BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) const;
TextEditor::BaseHoverHandler *createHoverHandler() const;
- FollowSymbolInterface &followSymbolInterface() const;
+ static FollowSymbolUnderCursor &builtinFollowSymbol();
+
+ enum class Backend { Builtin, Best };
+ static void followSymbol(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback,
+ bool resolveTarget, bool inNextSplit, Backend backend = Backend::Best);
+ static void switchDeclDef(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback,
+ Backend backend = Backend::Best);
+ static void startLocalRenaming(const CursorInEditor &data, const ProjectPart *projectPart,
+ RenameCallback &&renameSymbolsCallback,
+ Backend backend = Backend::Best);
+ static void globalRename(const CursorInEditor &data, const QString &replacement,
+ Backend backend = Backend::Best);
+ static void findUsages(const CursorInEditor &data, Backend backend = Backend::Best);
+ static void switchHeaderSource(bool inNextSplit, Backend backend = Backend::Best);
+
+ static Core::ILocatorFilter *createAuxiliaryCurrentDocumentFilter();
+
std::unique_ptr<AbstractOverviewModel> createOverviewModel() const;
CppIndexingSupport *indexingSupport();
@@ -213,12 +226,6 @@ public:
static QString configurationFileName();
static QString editorConfigurationFileName();
- static void addRefactoringEngine(RefactoringEngineType type,
- RefactoringEngineInterface *refactoringEngine);
- static void removeRefactoringEngine(RefactoringEngineType type);
- static RefactoringEngineInterface *builtinRefactoringEngine();
- static FollowSymbolInterface &builtinFollowSymbol();
-
void setLocatorFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
void setClassesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
void setIncludesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
@@ -266,6 +273,8 @@ signals:
void abstractEditorSupportRemoved(const QString &filePath);
void fallbackProjectPartUpdated();
+ void diagnosticsChanged(const QString &fileName, const QString &kind);
+
public slots:
void updateModifiedSourceFiles();
void GC();
@@ -292,6 +301,8 @@ private:
WorkingCopy buildWorkingCopyList();
+ ModelManagerSupport *modelManagerSupport(Backend backend) const;
+
void ensureUpdated();
QStringList internalProjectFiles() const;
ProjectExplorer::HeaderPaths internalHeaderPaths() const;
diff --git a/src/plugins/cppeditor/cppmodelmanager_test.cpp b/src/plugins/cppeditor/cppmodelmanager_test.cpp
index cfe552643af..2087d671cbd 100644
--- a/src/plugins/cppeditor/cppmodelmanager_test.cpp
+++ b/src/plugins/cppeditor/cppmodelmanager_test.cpp
@@ -91,7 +91,7 @@ QStringList toAbsolutePaths(const QStringList &relativePathList,
const TemporaryCopiedDir &temporaryDir)
{
QStringList result;
- foreach (const QString &file, relativePathList)
+ for (const QString &file : relativePathList)
result << temporaryDir.absolutePath(file.toUtf8());
return result;
}
@@ -108,7 +108,7 @@ public:
void create(const QString &name, const QString &dir, const QStringList &files)
{
const MyTestDataDir projectDir(dir);
- foreach (const QString &file, files)
+ for (const QString &file : files)
projectFiles << projectDir.file(file);
RawProjectPart rpp;
@@ -489,7 +489,7 @@ void ModelManagerTest::testRefreshTimeStampModifiedIfSourcefilesChange()
QCOMPARE(refreshedFiles.size(), initialProjectFiles.size());
snapshot = mm->snapshot();
- foreach (const QString &file, initialProjectFiles) {
+ for (const QString &file : qAsConst(initialProjectFiles)) {
QVERIFY(refreshedFiles.contains(file));
QVERIFY(snapshot.contains(file));
}
@@ -518,7 +518,7 @@ void ModelManagerTest::testRefreshTimeStampModifiedIfSourcefilesChange()
QCOMPARE(refreshedFiles.size(), finalProjectFiles.size());
snapshot = mm->snapshot();
- foreach (const QString &file, finalProjectFiles) {
+ for (const QString &file : qAsConst(finalProjectFiles)) {
QVERIFY(refreshedFiles.contains(file));
QVERIFY(snapshot.contains(file));
}
@@ -569,7 +569,7 @@ void ModelManagerTest::testSnapshotAfterTwoProjects()
QCOMPARE(refreshedFiles, Utils::toSet(project1.projectFiles));
const int snapshotSizeAfterProject1 = mm->snapshot().size();
- foreach (const QString &file, project1.projectFiles)
+ for (const QString &file : qAsConst(project1.projectFiles))
QVERIFY(mm->snapshot().contains(file));
// Project 2
@@ -584,9 +584,9 @@ void ModelManagerTest::testSnapshotAfterTwoProjects()
QVERIFY(snapshotSizeAfterProject2 > snapshotSizeAfterProject1);
QVERIFY(snapshotSizeAfterProject2 >= snapshotSizeAfterProject1 + project2.projectFiles.size());
- foreach (const QString &file, project1.projectFiles)
+ for (const QString &file : qAsConst(project1.projectFiles))
QVERIFY(mm->snapshot().contains(file));
- foreach (const QString &file, project2.projectFiles)
+ for (const QString &file : qAsConst(project2.projectFiles))
QVERIFY(mm->snapshot().contains(file));
}
@@ -1014,7 +1014,7 @@ void ModelManagerTest::testRenameIncludes()
// Copy test files to a temporary directory
QSet<QString> sourceFiles;
- foreach (const QString &fileName, fileNames) {
+ for (const QString &fileName : qAsConst(fileNames)) {
const QString &file = workingDir.filePath(fileName);
QVERIFY(QFile::copy(testDir.file(fileName), file));
// Saving source file names for the model manager update,
@@ -1027,7 +1027,7 @@ void ModelManagerTest::testRenameIncludes()
modelManager->updateSourceFiles(sourceFiles).waitForFinished();
QCoreApplication::processEvents();
CPlusPlus::Snapshot snapshot = modelManager->snapshot();
- foreach (const QString &sourceFile, sourceFiles)
+ for (const QString &sourceFile : qAsConst(sourceFiles))
QCOMPARE(snapshot.allIncludesForDocument(sourceFile), QSet<QString>() << oldHeader);
// Renaming the header
@@ -1039,7 +1039,7 @@ void ModelManagerTest::testRenameIncludes()
modelManager->updateSourceFiles(sourceFiles).waitForFinished();
QCoreApplication::processEvents();
snapshot = modelManager->snapshot();
- foreach (const QString &sourceFile, sourceFiles)
+ for (const QString &sourceFile : qAsConst(sourceFiles))
QCOMPARE(snapshot.allIncludesForDocument(sourceFile), QSet<QString>() << newHeader);
}
@@ -1072,7 +1072,7 @@ void ModelManagerTest::testRenameIncludesInEditor()
// Copy test files to a temporary directory
QSet<QString> sourceFiles;
- foreach (const QString &fileName, fileNames) {
+ for (const QString &fileName : fileNames) {
const QString &file = workingDir.filePath(fileName);
QVERIFY(QFile::copy(testDir.file(fileName), file));
// Saving source file names for the model manager update,
@@ -1085,7 +1085,7 @@ void ModelManagerTest::testRenameIncludesInEditor()
modelManager->updateSourceFiles(sourceFiles).waitForFinished();
QCoreApplication::processEvents();
CPlusPlus::Snapshot snapshot = modelManager->snapshot();
- foreach (const QString &sourceFile, sourceFiles)
+ for (const QString &sourceFile : qAsConst(sourceFiles))
QCOMPARE(snapshot.allIncludesForDocument(sourceFile), QSet<QString>() << headerWithPragmaOnce);
// Open a file in the editor
@@ -1163,7 +1163,7 @@ void ModelManagerTest::testRenameIncludesInEditor()
modelManager->updateSourceFiles(sourceFiles).waitForFinished();
QCoreApplication::processEvents();
snapshot = modelManager->snapshot();
- foreach (const QString &sourceFile, sourceFiles)
+ for (const QString &sourceFile : qAsConst(sourceFiles))
QCOMPARE(snapshot.allIncludesForDocument(sourceFile), QSet<QString>() << renamedHeaderWithPragmaOnce);
}
diff --git a/src/plugins/cppeditor/cppmodelmanagersupport.h b/src/plugins/cppeditor/cppmodelmanagersupport.h
index ca287d8baf7..2889cf7b67d 100644
--- a/src/plugins/cppeditor/cppmodelmanagersupport.h
+++ b/src/plugins/cppeditor/cppmodelmanagersupport.h
@@ -26,6 +26,9 @@
#pragma once
#include "cppeditor_global.h"
+#include "cursorineditor.h"
+
+#include <utils/link.h>
#include <QSharedPointer>
#include <QString>
@@ -42,7 +45,7 @@ namespace CppEditor {
class AbstractOverviewModel;
class BaseEditorDocumentProcessor;
class CppCompletionAssistProvider;
-class FollowSymbolInterface;
+class ProjectPart;
class RefactoringEngineInterface;
class CPPEDITOR_EXPORT ModelManagerSupport
@@ -54,15 +57,23 @@ public:
virtual ~ModelManagerSupport() = 0;
virtual CppCompletionAssistProvider *completionAssistProvider() = 0;
- virtual CppCompletionAssistProvider *functionHintAssistProvider() = 0;
virtual TextEditor::BaseHoverHandler *createHoverHandler() = 0;
virtual BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) = 0;
- virtual FollowSymbolInterface &followSymbolInterface() = 0;
- virtual RefactoringEngineInterface &refactoringEngineInterface() = 0;
virtual std::unique_ptr<AbstractOverviewModel> createOverviewModel() = 0;
- virtual bool supportsOutline(const TextEditor::TextDocument *) const { return true; }
- virtual bool supportsLocalUses(const TextEditor::TextDocument *) const { return true; }
+ virtual bool usesClangd(const TextEditor::TextDocument *) const { return false; }
+
+ virtual void followSymbol(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback,
+ bool resolveTarget, bool inNextSplit) = 0;
+ virtual void switchDeclDef(const CursorInEditor &data,
+ const Utils::LinkHandler &processLinkCallback) = 0;
+ virtual void startLocalRenaming(const CursorInEditor &data,
+ const ProjectPart *projectPart,
+ RenameCallback &&renameSymbolsCallback) = 0;
+ virtual void globalRename(const CursorInEditor &data, const QString &replacement) = 0;
+ virtual void findUsages(const CursorInEditor &data) const = 0;
+ virtual void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) = 0;
};
class CPPEDITOR_EXPORT ModelManagerSupportProvider
diff --git a/src/plugins/cppeditor/cppoutline.cpp b/src/plugins/cppeditor/cppoutline.cpp
index 272cea574a0..dbb06361d0f 100644
--- a/src/plugins/cppeditor/cppoutline.cpp
+++ b/src/plugins/cppeditor/cppoutline.cpp
@@ -213,7 +213,7 @@ bool CppOutlineWidgetFactory::supportsEditor(Core::IEditor *editor) const
const auto cppEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor);
if (!cppEditor || !CppModelManager::isCppEditor(cppEditor))
return false;
- return CppModelManager::supportsOutline(cppEditor->textDocument());
+ return !CppModelManager::usesClangd(cppEditor->textDocument());
}
TextEditor::IOutlineWidget *CppOutlineWidgetFactory::createWidget(Core::IEditor *editor)
diff --git a/src/plugins/cppeditor/cppoverviewmodel.cpp b/src/plugins/cppeditor/cppoverviewmodel.cpp
index 560d4701341..de7a8df2f41 100644
--- a/src/plugins/cppeditor/cppoverviewmodel.cpp
+++ b/src/plugins/cppeditor/cppoverviewmodel.cpp
@@ -67,11 +67,11 @@ public:
QString name = overviewModel->_overview.prettyName(symbol->name());
if (name.isEmpty())
name = QLatin1String("anonymous");
- if (symbol->isObjCForwardClassDeclaration())
+ if (symbol->asObjCForwardClassDeclaration())
name = QLatin1String("@class ") + name;
- if (symbol->isObjCForwardProtocolDeclaration() || symbol->isObjCProtocol())
+ if (symbol->asObjCForwardProtocolDeclaration() || symbol->asObjCProtocol())
name = QLatin1String("@protocol ") + name;
- if (symbol->isObjCClass()) {
+ if (symbol->asObjCClass()) {
ObjCClass *clazz = symbol->asObjCClass();
if (clazz->isInterface())
name = QLatin1String("@interface ") + name;
@@ -83,7 +83,7 @@ public:
clazz->categoryName()));
}
}
- if (symbol->isObjCPropertyDeclaration())
+ if (symbol->asObjCPropertyDeclaration())
name = QLatin1String("@property ") + name;
// if symbol is a template we might change it now - so, use a copy instead as we're const
Symbol *symbl = symbol;
@@ -98,13 +98,13 @@ public:
name += QString("<%1>").arg(parameters.join(QLatin1String(", ")));
symbl = templateDeclaration;
}
- if (symbl->isObjCMethod()) {
+ if (symbl->asObjCMethod()) {
ObjCMethod *method = symbl->asObjCMethod();
if (method->isStatic())
name = QLatin1Char('+') + name;
else
name = QLatin1Char('-') + name;
- } else if (! symbl->isScope() || symbl->isFunction()) {
+ } else if (! symbl->asScope() || symbl->asFunction()) {
QString type = overviewModel->_overview.prettyType(symbl->type());
if (Function *f = symbl->type()->asFunctionType()) {
name += type;
diff --git a/src/plugins/cppeditor/cppparsecontext.cpp b/src/plugins/cppeditor/cppparsecontext.cpp
index 7e89e9d02e7..08b5362a0a8 100644
--- a/src/plugins/cppeditor/cppparsecontext.cpp
+++ b/src/plugins/cppeditor/cppparsecontext.cpp
@@ -144,7 +144,7 @@ ParseContextWidget::ParseContextWidget(ParseContextModel &parseContextModel, QWi
// Set up context menu with a clear action
setContextMenuPolicy(Qt::ActionsContextMenu);
m_clearPreferredAction = new QAction(tr("Clear Preferred Parse Context"), this);
- connect(m_clearPreferredAction, &QAction::triggered,[&]() {
+ connect(m_clearPreferredAction, &QAction::triggered, this, [this]() {
m_parseContextModel.clearPreferred();
});
addAction(m_clearPreferredAction);
diff --git a/src/plugins/cppeditor/cpppointerdeclarationformatter.cpp b/src/plugins/cppeditor/cpppointerdeclarationformatter.cpp
index a35b14fba61..35a27a1485e 100644
--- a/src/plugins/cppeditor/cpppointerdeclarationformatter.cpp
+++ b/src/plugins/cppeditor/cpppointerdeclarationformatter.cpp
@@ -412,9 +412,9 @@ void PointerDeclarationFormatter::checkAndRewrite(DeclaratorAST *declarator,
QString rewrittenDeclaration;
const Name *name = symbol->name();
if (name) {
- if (name->isOperatorNameId()
- || (name->isQualifiedNameId()
- && name->asQualifiedNameId()->name()->isOperatorNameId())) {
+ if (name->asOperatorNameId()
+ || (name->asQualifiedNameId()
+ && name->asQualifiedNameId()->name()->asOperatorNameId())) {
const QString operatorText = m_cppRefactoringFile->textOf(declarator->core_declarator);
m_overview.includeWhiteSpaceInOperatorName = operatorText.contains(QLatin1Char(' '));
}
diff --git a/src/plugins/cppeditor/cppprojectfile.cpp b/src/plugins/cppeditor/cppprojectfile.cpp
index 58196521ca1..c565df9bb40 100644
--- a/src/plugins/cppeditor/cppprojectfile.cpp
+++ b/src/plugins/cppeditor/cppprojectfile.cpp
@@ -28,7 +28,7 @@
#include "cppeditorconstants.h"
#include <coreplugin/icore.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QDebug>
diff --git a/src/plugins/cppeditor/cppprojectfilecategorizer.cpp b/src/plugins/cppeditor/cppprojectfilecategorizer.cpp
index 55ed9a5be75..45f889d69e9 100644
--- a/src/plugins/cppeditor/cppprojectfilecategorizer.cpp
+++ b/src/plugins/cppeditor/cppprojectfilecategorizer.cpp
@@ -59,7 +59,7 @@ ProjectFiles ProjectFileCategorizer::classifyFiles(const QStringList &filePaths,
{
ProjectFiles ambiguousHeaders;
- foreach (const QString &filePath, filePaths) {
+ for (const QString &filePath : filePaths) {
const ProjectFile projectFile(filePath,
getMimeType
? ProjectFile::classifyByMimeType(getMimeType(filePath))
diff --git a/src/plugins/cppeditor/cppprojectinfogenerator.cpp b/src/plugins/cppeditor/cppprojectinfogenerator.cpp
index 67ebd19f6d5..55bbf3d3560 100644
--- a/src/plugins/cppeditor/cppprojectinfogenerator.cpp
+++ b/src/plugins/cppeditor/cppprojectinfogenerator.cpp
@@ -87,7 +87,8 @@ const QVector<ProjectPart::ConstPtr> ProjectInfoGenerator::createProjectParts(
QVector<ProjectPart::ConstPtr> result;
ProjectFileCategorizer cat(rawProjectPart.displayName,
rawProjectPart.files,
- rawProjectPart.fileIsActive);
+ rawProjectPart.fileIsActive,
+ rawProjectPart.getMimeType);
if (!cat.hasParts())
return result;
diff --git a/src/plugins/cppeditor/cppqtstyleindenter.cpp b/src/plugins/cppeditor/cppqtstyleindenter.cpp
index 8573d981a68..988b2d347da 100644
--- a/src/plugins/cppeditor/cppqtstyleindenter.cpp
+++ b/src/plugins/cppeditor/cppqtstyleindenter.cpp
@@ -196,7 +196,7 @@ TextEditor::IndentationForBlock CppQtStyleIndenter::indentationForBlocks(
codeFormatter.updateStateUntil(blocks.last());
TextEditor::IndentationForBlock ret;
- foreach (QTextBlock block, blocks) {
+ for (const QTextBlock &block : blocks) {
int indent;
int padding;
codeFormatter.indentFor(block, &indent, &padding);
diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp
index ce17fbdf9b9..6471134ec47 100644
--- a/src/plugins/cppeditor/cppquickfix_test.cpp
+++ b/src/plugins/cppeditor/cppquickfix_test.cpp
@@ -91,7 +91,7 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDoc
// Check if there is exactly one cursor marker
unsigned cursorMarkersCount = 0;
- foreach (const TestDocumentPtr document, m_testDocuments) {
+ for (const TestDocumentPtr &document : qAsConst(m_testDocuments)) {
if (document->hasCursorMarker())
++cursorMarkersCount;
}
@@ -100,7 +100,7 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDoc
// Write documents to disk
m_temporaryDirectory.reset(new TemporaryDir);
QVERIFY(m_temporaryDirectory->isValid());
- foreach (TestDocumentPtr document, m_testDocuments) {
+ for (const TestDocumentPtr &document : qAsConst(m_testDocuments)) {
if (QFileInfo(document->m_fileName).isRelative())
document->setBaseDirectory(m_temporaryDirectory->path());
document->writeToDisk();
@@ -115,12 +115,12 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDoc
// Update Code Model
QSet<QString> filePaths;
- foreach (const TestDocumentPtr &document, m_testDocuments)
+ for (const TestDocumentPtr &document : qAsConst(m_testDocuments))
filePaths << document->filePath();
QVERIFY(parseFiles(filePaths));
// Open Files
- foreach (TestDocumentPtr document, m_testDocuments) {
+ for (const TestDocumentPtr &document : qAsConst(m_testDocuments)) {
QVERIFY(openCppEditor(document->filePath(), &document->m_editor,
&document->m_editorWidget));
closeEditorAtEndOfTestCase(document->m_editor);
@@ -149,7 +149,7 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDoc
m_cppCodeStylePreferences->setCurrentDelegate("qt");
// Find the document having the cursor marker
- foreach (const TestDocumentPtr document, m_testDocuments) {
+ for (const TestDocumentPtr &document : qAsConst(m_testDocuments)) {
if (document->hasCursorMarker()){
m_documentWithMarker = document;
break;
@@ -171,7 +171,7 @@ BaseQuickFixTestCase::~BaseQuickFixTestCase()
m_modelManager->setHeaderPaths(m_headerPathsToRestore);
// Remove created files from file system
- foreach (const TestDocumentPtr &testDocument, m_testDocuments)
+ for (const TestDocumentPtr &testDocument : qAsConst(m_testDocuments))
QVERIFY(QFile::remove(testDocument->filePath()));
}
@@ -223,7 +223,7 @@ QuickFixOperationTest::QuickFixOperationTest(const QList<TestDocumentPtr> &testD
operation->perform();
// Compare all files
- foreach (const TestDocumentPtr testDocument, m_testDocuments) {
+ for (const TestDocumentPtr &testDocument : qAsConst(m_testDocuments)) {
// Check
QString result = testDocument->m_editorWidget->document()->toPlainText();
removeTrailingWhitespace(result);
@@ -269,7 +269,7 @@ QuickFixOfferedOperationsTest::QuickFixOfferedOperationsTest(
// Convert to QStringList
QStringList actualOperationsAsStringList;
- foreach (const QuickFixOperation::Ptr &operation, actualOperations)
+ for (const QuickFixOperation::Ptr &operation : qAsConst(actualOperations))
actualOperationsAsStringList << operation->description();
QCOMPARE(actualOperationsAsStringList, expectedOperations);
@@ -1077,7 +1077,7 @@ void QuickfixTest::testGeneric_data()
"void bar() {fo@o();}\n"
) << _(
"int foo() {return 1;}\n"
- "void bar() {int localFoo = foo();}\n"
+ "void bar() {auto localFoo = foo();}\n"
);
// Check: Add local variable for a member function.
@@ -1092,7 +1092,7 @@ void QuickfixTest::testGeneric_data()
"class Foo {public: int* fooFunc();}\n"
"void bar() {\n"
" Foo *f = new Foo;\n"
- " int *localFooFunc = f->fooFunc();\n"
+ " auto localFooFunc = f->fooFunc();\n"
"}\n"
);
@@ -1110,7 +1110,7 @@ void QuickfixTest::testGeneric_data()
"struct Baz {Foo* foo();};\n"
"void bar() {\n"
" Baz *b = new Baz;\n"
- " int *localFunc = b->foo()->func();\n"
+ " auto localFunc = b->foo()->func();\n"
"}"
);
@@ -1128,7 +1128,7 @@ void QuickfixTest::testGeneric_data()
"struct Baz {Foo* foo();};\n"
"void bar() {\n"
" Baz *b = new Baz;\n"
- " int *localFunc = b->foo()->func();\n"
+ " auto localFunc = b->foo()->func();\n"
"}"
);
@@ -1142,7 +1142,7 @@ void QuickfixTest::testGeneric_data()
) << _(
"class Foo {public: static int* fooFunc();}\n"
"void bar() {\n"
- " int *localFooFunc = Foo::fooFunc();\n"
+ " auto localFooFunc = Foo::fooFunc();\n"
"}"
);
@@ -1156,7 +1156,7 @@ void QuickfixTest::testGeneric_data()
) << _(
"class Foo {}\n"
"void bar() {\n"
- " Foo *localFoo = new Foo;\n"
+ " auto localFoo = new Foo;\n"
"}"
);
@@ -1745,6 +1745,16 @@ void QuickfixTest::testGeneric_data()
<< CppQuickFixFactoryPtr(new EscapeStringLiteral)
<< _(R"(const char *str = @"\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)")
<< _(R"(const char *str = "àf23бgб1";)");
+ QTest::newRow("AddLocalDeclaration_QTCREATORBUG-26004")
+ << CppQuickFixFactoryPtr(new AddLocalDeclaration)
+ << _("void func() {\n"
+ " QStringList list;\n"
+ " @it = list.cbegin();\n"
+ "}\n")
+ << _("void func() {\n"
+ " QStringList list;\n"
+ " auto it = list.cbegin();\n"
+ "}\n");
}
void QuickfixTest::testGeneric()
@@ -5874,7 +5884,7 @@ void QuickfixTest::testAddIncludeForUndefinedIdentifier()
TemporaryDir temporaryDir;
QVERIFY(temporaryDir.isValid());
- foreach (TestDocumentPtr testDocument, testDocuments)
+ for (const TestDocumentPtr &testDocument : qAsConst(testDocuments))
testDocument->setBaseDirectory(temporaryDir.path());
QScopedPointer<CppQuickFixFactory> factory;
@@ -7384,7 +7394,7 @@ void QuickfixTest::testAssignToLocalVariableTemplates()
"#include \"file.h\"\n"
"void foo() {\n"
" List<int> list;\n"
- " int localFirst = list.first();\n"
+ " auto localFirst = list.first();\n"
"}\n";
testDocuments << CppTestDocument::create("file.cpp", original, expected);
diff --git a/src/plugins/cppeditor/cppquickfixassistant.cpp b/src/plugins/cppeditor/cppquickfixassistant.cpp
index f254abc8df3..5310ef7f7a7 100644
--- a/src/plugins/cppeditor/cppquickfixassistant.cpp
+++ b/src/plugins/cppeditor/cppquickfixassistant.cpp
@@ -53,14 +53,8 @@ class CppQuickFixAssistProcessor : public IAssistProcessor
{
IAssistProposal *perform(const AssistInterface *interface) override
{
- QSharedPointer<const AssistInterface> assistInterface(interface);
- auto cppInterface = assistInterface.staticCast<const CppQuickFixInterface>();
-
- QuickFixOperations quickFixes;
- for (CppQuickFixFactory *factory : CppQuickFixFactory::cppQuickFixFactories())
- factory->match(*cppInterface, quickFixes);
-
- return GenericProposal::createProposal(interface, quickFixes);
+ QSharedPointer<const AssistInterface> dummy(interface); // FIXME: Surely this cannot be our way of doing memory management???
+ return GenericProposal::createProposal(interface, quickFixOperations(interface));
}
};
@@ -80,10 +74,8 @@ IAssistProcessor *CppQuickFixAssistProvider::createProcessor(const AssistInterfa
// --------------------------
// CppQuickFixAssistInterface
// --------------------------
-CppQuickFixInterface::CppQuickFixInterface(CppEditorWidget *editor,
- AssistReason reason)
- : AssistInterface(editor->document(), editor->position(),
- editor->textDocument()->filePath(), reason)
+CppQuickFixInterface::CppQuickFixInterface(CppEditorWidget *editor, AssistReason reason)
+ : AssistInterface(editor->textCursor(), editor->textDocument()->filePath(), reason)
, m_editor(editor)
, m_semanticInfo(editor->semanticInfo())
, m_snapshot(CppModelManager::instance()->snapshot())
@@ -137,5 +129,15 @@ bool CppQuickFixInterface::isCursorOn(const AST *ast) const
return currentFile()->isCursorOn(ast);
}
+QuickFixOperations quickFixOperations(const TextEditor::AssistInterface *interface)
+{
+ const auto cppInterface = dynamic_cast<const CppQuickFixInterface *>(interface);
+ QTC_ASSERT(cppInterface, return {});
+ QuickFixOperations quickFixes;
+ for (CppQuickFixFactory *factory : CppQuickFixFactory::cppQuickFixFactories())
+ factory->match(*cppInterface, quickFixes);
+ return quickFixes;
+}
+
} // namespace Internal
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppquickfixassistant.h b/src/plugins/cppeditor/cppquickfixassistant.h
index d5e626cb0e0..0824b82cd1f 100644
--- a/src/plugins/cppeditor/cppquickfixassistant.h
+++ b/src/plugins/cppeditor/cppquickfixassistant.h
@@ -29,6 +29,7 @@
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/iassistprovider.h>
+#include <texteditor/quickfix.h>
#include <cplusplus/LookupContext.h>
@@ -55,6 +56,7 @@ public:
bool isCursorOn(unsigned tokenIndex) const;
bool isCursorOn(const CPlusPlus::AST *ast) const;
+ bool isBaseObject() const override { return false; }
private:
CppEditorWidget *m_editor;
@@ -73,5 +75,7 @@ public:
TextEditor::IAssistProcessor *createProcessor(const TextEditor::AssistInterface *) const override;
};
+TextEditor::QuickFixOperations quickFixOperations(const TextEditor::AssistInterface *interface);
+
} // Internal
} // CppEditor
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index 6c98b2dd10a..0f76dd8e53b 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -159,7 +159,7 @@ Class *isMemberFunction(const LookupContext &context, Function *function)
QTC_ASSERT(function, return nullptr);
Scope *enclosingScope = function->enclosingScope();
- while (!(enclosingScope->isNamespace() || enclosingScope->isClass()))
+ while (!(enclosingScope->asNamespace() || enclosingScope->asClass()))
enclosingScope = enclosingScope->enclosingScope();
QTC_ASSERT(enclosingScope != nullptr, return nullptr);
@@ -167,7 +167,7 @@ Class *isMemberFunction(const LookupContext &context, Function *function)
if (!functionName)
return nullptr;
- if (!functionName->isQualifiedNameId())
+ if (!functionName->asQualifiedNameId())
return nullptr; // trying to add a declaration for a global function
const QualifiedNameId *q = functionName->asQualifiedNameId();
@@ -175,7 +175,8 @@ Class *isMemberFunction(const LookupContext &context, Function *function)
return nullptr;
if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) {
- foreach (Symbol *s, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols) {
if (Class *matchingClass = s->asClass())
return matchingClass;
}
@@ -191,7 +192,7 @@ Namespace *isNamespaceFunction(const LookupContext &context, Function *function)
return nullptr;
Scope *enclosingScope = function->enclosingScope();
- while (!(enclosingScope->isNamespace() || enclosingScope->isClass()))
+ while (!(enclosingScope->asNamespace() || enclosingScope->asClass()))
enclosingScope = enclosingScope->enclosingScope();
QTC_ASSERT(enclosingScope != nullptr, return nullptr);
@@ -200,8 +201,9 @@ Namespace *isNamespaceFunction(const LookupContext &context, Function *function)
return nullptr;
// global namespace
- if (!functionName->isQualifiedNameId()) {
- foreach (Symbol *s, context.globalNamespace()->symbols()) {
+ if (!functionName->asQualifiedNameId()) {
+ const QList<Symbol *> symbols = context.globalNamespace()->symbols();
+ for (Symbol *s : symbols) {
if (Namespace *matchingNamespace = s->asNamespace())
return matchingNamespace;
}
@@ -213,7 +215,8 @@ Namespace *isNamespaceFunction(const LookupContext &context, Function *function)
return nullptr;
if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) {
- foreach (Symbol *s, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols) {
if (Namespace *matchingNamespace = s->asNamespace())
return matchingNamespace;
}
@@ -256,8 +259,8 @@ void insertNewIncludeDirective(const QString &include, CppRefactoringFilePtr fil
bool nameIncludesOperatorName(const Name *name)
{
- return name->isOperatorNameId()
- || (name->isQualifiedNameId() && name->asQualifiedNameId()->name()->isOperatorNameId());
+ return name->asOperatorNameId()
+ || (name->asQualifiedNameId() && name->asQualifiedNameId()->name()->asOperatorNameId());
}
QString memberBaseName(const QString &name)
@@ -1337,7 +1340,8 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
ClassOrNamespace *b = interface.context().lookupType(function);
if (b) {
// Do we have a tr function?
- foreach (const LookupItem &r, b->find(trName)) {
+ const QList<LookupItem> items = b->find(trName);
+ for (const LookupItem &r : items) {
Symbol *s = r.declaration();
if (s->type()->isFunctionType()) {
// no context required for tr
@@ -1351,7 +1355,8 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
// We need to do a QCA::translate, so we need a context.
// Use fully qualified class name:
Overview oo;
- foreach (const Name *n, LookupContext::path(function)) {
+ const QList<const Name *> names = LookupContext::path(function);
+ for (const Name *n : names) {
if (!trContext.isEmpty())
trContext.append(QLatin1String("::"));
trContext.append(oo.prettyName(n));
@@ -1612,14 +1617,35 @@ public:
{
CppRefactoringChanges refactoring(snapshot());
CppRefactoringFilePtr currentFile = refactoring.file(filePath());
+ QString declaration = getDeclaration();
+
+ if (!declaration.isEmpty()) {
+ ChangeSet changes;
+ changes.replace(currentFile->startOf(binaryAST),
+ currentFile->endOf(simpleNameAST),
+ declaration);
+ currentFile->setChangeSet(changes);
+ currentFile->apply();
+ }
+ }
+
+private:
+ QString getDeclaration()
+ {
+ CppRefactoringChanges refactoring(snapshot());
+ CppRefactoringFilePtr currentFile = refactoring.file(filePath());
+ Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview();
+
+ if (currentFile->cppDocument()->languageFeatures().cxx11Enabled)
+ return "auto " + oo.prettyName(simpleNameAST->name);
TypeOfExpression typeOfExpression;
typeOfExpression.init(semanticInfo().doc, snapshot(), context().bindings());
Scope *scope = currentFile->scopeAt(binaryAST->firstToken());
const QList<LookupItem> result =
- typeOfExpression(currentFile->textOf(binaryAST->right_expression).toUtf8(),
- scope,
- TypeOfExpression::Preprocess);
+ typeOfExpression(currentFile->textOf(binaryAST->right_expression).toUtf8(),
+ scope,
+ TypeOfExpression::Preprocess);
if (!result.isEmpty()) {
SubstitutionEnvironment env;
@@ -1634,20 +1660,13 @@ public:
Control *control = context().bindings()->control().data();
FullySpecifiedType tn = rewriteType(result.first().type(), &env, control);
- Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview();
- QString ty = oo.prettyType(tn, simpleNameAST->name);
- if (!ty.isEmpty()) {
- ChangeSet changes;
- changes.replace(currentFile->startOf(binaryAST),
- currentFile->endOf(simpleNameAST),
- ty);
- currentFile->setChangeSet(changes);
- currentFile->apply();
- }
+ QString declaration = oo.prettyType(tn, simpleNameAST->name);
+ return declaration;
}
+
+ return {};
}
-private:
const BinaryExpressionAST *binaryAST;
const SimpleNameAST *simpleNameAST;
};
@@ -1669,7 +1688,7 @@ void AddLocalDeclaration::match(const CppQuickFixInterface &interface, QuickFixO
SimpleNameAST *nameAST = idExpr->name->asSimpleName();
const QList<LookupItem> results = interface.context().lookup(nameAST->name, file->scopeAt(nameAST->firstToken()));
Declaration *decl = nullptr;
- foreach (const LookupItem &r, results) {
+ for (const LookupItem &r : results) {
if (!r.declaration())
continue;
if (Declaration *d = r.declaration()->asDeclaration()) {
@@ -1875,7 +1894,7 @@ QString findShortestInclude(const QString currentDocumentFilePath,
if (fileInfo.path() == QFileInfo(currentDocumentFilePath).path()) {
result = QLatin1Char('"') + fileInfo.fileName() + QLatin1Char('"');
} else {
- foreach (const ProjectExplorer::HeaderPath &headerPath, headerPaths) {
+ for (const ProjectExplorer::HeaderPath &headerPath : headerPaths) {
if (!candidateFilePath.startsWith(headerPath.path))
continue;
QString relativePath = candidateFilePath.mid(headerPath.path.size());
@@ -1914,7 +1933,7 @@ ProjectExplorer::HeaderPaths relevantHeaderPaths(const QString &filePath)
if (projectParts.isEmpty()) { // Not part of any project, better use all include paths than none
headerPaths += modelManager->headerPaths();
} else {
- foreach (const ProjectPart::ConstPtr &part, projectParts)
+ for (const ProjectPart::ConstPtr &part : projectParts)
headerPaths += part->headerPaths;
}
@@ -1960,17 +1979,17 @@ LookupResult lookUpDefinition(const CppQuickFixInterface &interface, const NameA
// Try to find the class/template definition
const Name *name = nameAst->name;
const QList<LookupItem> results = interface.context().lookup(name, scope);
- foreach (const LookupItem &item, results) {
+ for (const LookupItem &item : results) {
if (Symbol *declaration = item.declaration()) {
- if (declaration->isClass())
+ if (declaration->asClass())
return LookupResult::Declared;
- if (declaration->isForwardClassDeclaration())
+ if (declaration->asForwardClassDeclaration())
return LookupResult::ForwardDeclared;
if (Template *templ = declaration->asTemplate()) {
if (Symbol *declaration = templ->declaration()) {
- if (declaration->isClass())
+ if (declaration->asClass())
return LookupResult::Declared;
- if (declaration->isForwardClassDeclaration())
+ if (declaration->asForwardClassDeclaration())
return LookupResult::ForwardDeclared;
}
}
@@ -1991,7 +2010,8 @@ Snapshot forwardingHeaders(const CppQuickFixInterface &interface)
{
Snapshot result;
- foreach (Document::Ptr doc, interface.snapshot()) {
+ const Snapshot docs = interface.snapshot();
+ for (Document::Ptr doc : docs) {
if (doc->globalSymbolCount() == 0 && doc->resolvedIncludes().size() == 1)
result.insert(doc);
}
@@ -2063,7 +2083,7 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
if (matchName(nameAst->name, &matches, &className)) {
QList<IndexItem::Ptr> indexItems;
const Snapshot forwardHeaders = forwardingHeaders(interface);
- foreach (const Core::LocatorFilterEntry &entry, matches) {
+ for (const Core::LocatorFilterEntry &entry : qAsConst(matches)) {
IndexItem::Ptr info = entry.internalData.value<IndexItem::Ptr>();
if (!info || info->symbolName() != className)
continue;
@@ -2075,7 +2095,7 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
headerAndItsForwardingHeaders << Utils::FilePath::fromString(info->fileName());
headerAndItsForwardingHeaders += localForwardHeaders.filesDependingOn(info->fileName());
- foreach (const Utils::FilePath &header, headerAndItsForwardingHeaders) {
+ for (const Utils::FilePath &header : qAsConst(headerAndItsForwardingHeaders)) {
const QString include = findShortestInclude(currentDocumentFilePath,
header.toString(),
headerPaths);
@@ -2328,7 +2348,7 @@ void ReformatPointerDeclaration::match(const CppQuickFixInterface &interface,
} else {
const QList<AST *> suitableASTs
= ReformatPointerDeclarationASTPathResultsFilter().filter(path);
- foreach (AST *ast, suitableASTs) {
+ for (AST *ast : suitableASTs) {
change = formatter.format(ast);
if (!change.isEmpty()) {
result << new ReformatPointerDeclarationOp(interface, change);
@@ -2421,7 +2441,7 @@ public:
static Enum *findEnum(const QList<LookupItem> &results, const LookupContext &ctxt)
{
- foreach (const LookupItem &result, results) {
+ for (const LookupItem &result : results) {
const FullySpecifiedType fst = result.type();
Type *type = result.declaration() ? result.declaration()->type().type()
@@ -2442,7 +2462,7 @@ static Enum *findEnum(const QList<LookupItem> &results, const LookupContext &ctx
const Name *referenceName = namedType->name();
if (const QualifiedNameId *qualifiedName = referenceName->asQualifiedNameId())
referenceName = qualifiedName->name();
- foreach (Enum *e, enums) {
+ for (Enum *e : qAsConst(enums)) {
if (const Name *candidateName = e->name()) {
if (candidateName->match(referenceName))
return e;
@@ -2474,6 +2494,9 @@ Enum *conditionEnum(const CppQuickFixInterface &interface, SwitchStatementAST *s
void CompleteSwitchCaseStatement::match(const CppQuickFixInterface &interface,
QuickFixOperations &result)
{
+ if (CppModelManager::usesClangd(interface.currentFile()->editor()->textDocument()))
+ return;
+
const QList<AST *> &path = interface.path();
if (path.isEmpty())
@@ -2502,9 +2525,9 @@ void CompleteSwitchCaseStatement::match(const CppQuickFixInterface &interface,
Block *block = switchStatement->symbol;
CaseStatementCollector caseValues(interface.semanticInfo().doc, interface.snapshot(),
interface.semanticInfo().doc->scopeAt(block->line(), block->column()));
- QStringList usedValues = caseValues(switchStatement);
+ const QStringList usedValues = caseValues(switchStatement);
// save the values that would be added
- foreach (const QString &usedValue, usedValues)
+ for (const QString &usedValue : usedValues)
values.removeAll(usedValue);
if (!values.isEmpty())
result << new CompleteSwitchCaseStatementOp(interface, depth,
@@ -2625,7 +2648,7 @@ void InsertDeclFromDef::match(const CppQuickFixInterface &interface, QuickFixOpe
for (Symbol *symbol = matchingClass->find(qName->identifier());
symbol; symbol = symbol->next()) {
Symbol *s = symbol;
- if (fun->enclosingScope()->isTemplate()) {
+ if (fun->enclosingScope()->asTemplate()) {
if (const Template *templ = s->type()->asTemplateType()) {
if (Symbol *decl = templ->declaration()) {
if (decl->type()->isFunctionType())
@@ -2890,8 +2913,8 @@ void InsertDefFromDecl::match(const CppQuickFixInterface &interface, QuickFixOpe
// find appropriate implementation file, but do not use this
// location, because insertLocationForMethodDefinition() should
// be used in perform() to get consistent insert positions.
- foreach (const InsertionLocation &location,
- locator.methodDefinition(decl, false, QString())) {
+ for (const InsertionLocation &location :
+ locator.methodDefinition(decl, false, QString())) {
if (!location.isValid())
continue;
@@ -3198,7 +3221,7 @@ public:
// Collect all member functions.
for (auto it = theClass->memberBegin(); it != theClass->memberEnd(); ++it) {
Symbol * const s = *it;
- if (!s->identifier() || !s->type() || !s->isDeclaration() || s->asFunction())
+ if (!s->identifier() || !s->type() || !s->asDeclaration() || s->asFunction())
continue;
Function * const func = s->type()->asFunctionType();
if (!func || func->isSignal() || func->isFriend())
@@ -3653,7 +3676,7 @@ protected:
if (m_settings->addUsingNamespaceinCppFile()) {
// check if we have to insert a using namespace ...
auto requiredNamespaces = getNamespaceNames(
- symbol->isClass() ? symbol : symbol->enclosingClass());
+ symbol->asClass() ? symbol : symbol->enclosingClass());
NSCheckerVisitor visitor(m_sourceFile.get(),
requiredNamespaces,
m_sourceFile->position(m_sourceFileInsertionPoint.line(),
@@ -3910,7 +3933,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
auto getterLocation = m_settings->determineGetterLocation(1);
// if we have an anonymous class we must add code inside the class
- if (data.clazz->name()->isAnonymousNameId())
+ if (data.clazz->name()->asAnonymousNameId())
getterLocation = CppQuickFixSettings::FunctionLocation::InsideClass;
if (getterLocation == CppQuickFixSettings::FunctionLocation::InsideClass) {
@@ -4032,7 +4055,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
auto setterLocation = m_settings->determineSetterLocation(body.count('\n') - 2);
// if we have an anonymous class we must add code inside the class
- if (data.clazz->name()->isAnonymousNameId())
+ if (data.clazz->name()->asAnonymousNameId())
setterLocation = CppQuickFixSettings::FunctionLocation::InsideClass;
if (setterLocation == CppQuickFixSettings::FunctionLocation::CppFile && !hasSourceFile())
@@ -4110,7 +4133,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
// body.count('\n') - 2 : do not count the 2 at start
auto resetLocation = m_settings->determineSetterLocation(body.count('\n') - 2);
// if we have an anonymous class we must add code inside the class
- if (data.clazz->name()->isAnonymousNameId())
+ if (data.clazz->name()->asAnonymousNameId())
resetLocation = CppQuickFixSettings::FunctionLocation::InsideClass;
if (resetLocation == CppQuickFixSettings::FunctionLocation::CppFile && !hasSourceFile())
@@ -4166,9 +4189,12 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
// member variable
if (generateFlags & Flag::GenerateMemberVariable) {
- const QString storageDeclaration = overview.prettyType(memberVariableType,
- data.memberVariableName)
- + QLatin1String(";\n");
+ QString storageDeclaration = overview.prettyType(memberVariableType, data.memberVariableName);
+ if (memberVariableType->isPointerType()
+ && m_operation->semanticInfo().doc->translationUnit()->languageFeatures().cxx11Enabled) {
+ storageDeclaration.append(" = nullptr");
+ }
+ storageDeclaration.append(";\n");
addHeaderCode(InsertionPointLocator::Private, storageDeclaration);
}
@@ -4264,7 +4290,7 @@ QList<Symbol *> getMemberFunctions(const Class *clazz)
Symbol *const s = *it;
if (!s->identifier() || !s->type())
continue;
- if ((s->isDeclaration() && s->type()->asFunctionType()) || s->asFunction())
+ if ((s->asDeclaration() && s->type()->asFunctionType()) || s->asFunction())
memberFunctions << s;
}
return memberFunctions;
@@ -4349,7 +4375,7 @@ void GenerateGetterSetter::match(const CppQuickFixInterface &interface, QuickFix
// no type can be determined
return;
}
- if (!symbol->isDeclaration()) {
+ if (!symbol->asDeclaration()) {
return;
}
existing.declarationSymbol = symbol->asDeclaration();
@@ -4645,9 +4671,9 @@ public:
Symbol *const s = *it;
if (!s->identifier() || !s->type() || s->type().isTypedef())
continue;
- if ((s->isDeclaration() && s->type()->asFunctionType()) || s->asFunction())
+ if ((s->asDeclaration() && s->type()->asFunctionType()) || s->asFunction())
memberFunctions << s;
- else if (s->isDeclaration() && (s->isPrivate() || s->isProtected()))
+ else if (s->asDeclaration() && (s->isPrivate() || s->isProtected()))
dataMembers << s;
}
@@ -5216,7 +5242,13 @@ ExtractFunction::ExtractFunction(FunctionNameGetter functionNameGetter)
void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOperations &result)
{
- CppRefactoringFilePtr file = interface.currentFile();
+ const CppRefactoringFilePtr file = interface.currentFile();
+
+ // TODO: Fix upstream and uncomment; see QTCREATORBUG-28030.
+// if (CppModelManager::usesClangd(file->editor()->textDocument())
+// && file->cppDocument()->languageFeatures().cxxEnabled) {
+// return;
+// }
QTextCursor cursor = file->cursor();
if (!cursor.hasSelection())
@@ -5236,7 +5268,7 @@ void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOpera
|| !refFuncDef->function_body->asCompoundStatement()->statement_list
|| !refFuncDef->symbol
|| !refFuncDef->symbol->name()
- || refFuncDef->symbol->enclosingScope()->isTemplate() /* TODO: Templates... */) {
+ || refFuncDef->symbol->enclosingScope()->asTemplate() /* TODO: Templates... */) {
return;
}
@@ -5296,7 +5328,7 @@ void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOpera
bool usedAfterExtraction = false;
bool usedInsideExtraction = false;
const QList<SemanticInfo::Use> &uses = it.value();
- foreach (const SemanticInfo::Use &use, uses) {
+ for (const SemanticInfo::Use &use : uses) {
if (use.isInvalid())
continue;
@@ -5440,7 +5472,7 @@ public:
|| !qName->identifier()->match(s->identifier())
|| !s->type()->isFunctionType()
|| !s->type().match(func->type())
- || s->isFunction()) {
+ || s->asFunction()) {
continue;
}
@@ -5778,7 +5810,8 @@ private:
// Fix all occurrences of the identifier in this function.
ASTPath astPath(m_document);
- foreach (const SemanticInfo::Use &use, semanticInfo().localUses.value(m_symbol)) {
+ const QList<SemanticInfo::Use> uses = semanticInfo().localUses.value(m_symbol);
+ for (const SemanticInfo::Use &use : uses) {
const QList<AST *> path = astPath(use.line, use.column);
AST *idAST = path.last();
bool declarationFound = false;
@@ -5900,7 +5933,8 @@ private:
// Fix all occurrences of the identifier in this function.
ASTPath astPath(m_document);
- foreach (const SemanticInfo::Use &use, semanticInfo().localUses.value(m_symbol)) {
+ const QList<SemanticInfo::Use> uses = semanticInfo().localUses.value(m_symbol);
+ for (const SemanticInfo::Use &use : uses) {
const QList<AST *> path = astPath(use.line, use.column);
AST *idAST = path.last();
bool insertStar = true;
@@ -6628,7 +6662,7 @@ void MoveFuncDefToDecl::match(const CppQuickFixInterface &interface, QuickFixOpe
for (Symbol *symbol = matchingClass->find(qName->identifier());
symbol; symbol = symbol->next()) {
Symbol *s = symbol;
- if (func->enclosingScope()->isTemplate()) {
+ if (func->enclosingScope()->asTemplate()) {
if (const Template *templ = s->type()->asTemplateType()) {
if (Symbol *decl = templ->declaration()) {
if (decl->type()->isFunctionType())
@@ -6640,7 +6674,7 @@ void MoveFuncDefToDecl::match(const CppQuickFixInterface &interface, QuickFixOpe
|| !qName->identifier()->match(s->identifier())
|| !s->type()->isFunctionType()
|| !s->type().match(func->type())
- || s->isFunction()) {
+ || s->asFunction()) {
continue;
}
@@ -6718,78 +6752,90 @@ public:
, m_insertPos(insertPos)
, m_ast(ast)
, m_name(name)
+ , m_oo(CppCodeStyleSettings::currentProjectCodeStyleOverview())
+ , m_originalName(m_oo.prettyName(m_name))
+ , m_file(CppRefactoringChanges(snapshot()).file(filePath()))
{
setDescription(QApplication::translate("CppEditor::QuickFix", "Assign to Local Variable"));
}
+private:
void perform() override
{
- CppRefactoringChanges refactoring(snapshot());
- CppRefactoringFilePtr file = refactoring.file(filePath());
+ QString type = deduceType();
+ if (type.isEmpty())
+ return;
+ const int origNameLength = m_originalName.length();
+ const QString varName = constructVarName();
+ const QString insertString = type.replace(type.length() - origNameLength, origNameLength,
+ varName + QLatin1String(" = "));
+ ChangeSet changes;
+ changes.insert(m_insertPos, insertString);
+ m_file->setChangeSet(changes);
+ m_file->apply();
+
+ // move cursor to new variable name
+ QTextCursor c = m_file->cursor();
+ c.setPosition(m_insertPos + insertString.length() - varName.length() - 3);
+ c.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ editor()->setTextCursor(c);
+ }
+
+ QString deduceType() const
+ {
+ if (m_file->cppDocument()->languageFeatures().cxx11Enabled)
+ return "auto " + m_originalName;
- // Determine return type and new variable name
TypeOfExpression typeOfExpression;
- typeOfExpression.init(semanticInfo().doc, snapshot(),
- context().bindings());
+ typeOfExpression.init(semanticInfo().doc, snapshot(), context().bindings());
typeOfExpression.setExpandTemplates(true);
- Scope *scope = file->scopeAt(m_ast->firstToken());
- const QList<LookupItem> result = typeOfExpression(file->textOf(m_ast).toUtf8(),
+ Scope * const scope = m_file->scopeAt(m_ast->firstToken());
+ const QList<LookupItem> result = typeOfExpression(m_file->textOf(m_ast).toUtf8(),
scope, TypeOfExpression::Preprocess);
+ if (result.isEmpty())
+ return {};
- if (!result.isEmpty()) {
- SubstitutionEnvironment env;
- env.setContext(context());
- env.switchScope(result.first().scope());
- ClassOrNamespace *con = typeOfExpression.context().lookupType(scope);
- if (!con)
- con = typeOfExpression.context().globalNamespace();
- UseMinimalNames q(con);
- env.enter(&q);
+ SubstitutionEnvironment env;
+ env.setContext(context());
+ env.switchScope(result.first().scope());
+ ClassOrNamespace *con = typeOfExpression.context().lookupType(scope);
+ if (!con)
+ con = typeOfExpression.context().globalNamespace();
+ UseMinimalNames q(con);
+ env.enter(&q);
- Control *control = context().bindings()->control().data();
- FullySpecifiedType type = rewriteType(result.first().type(), &env, control);
+ Control *control = context().bindings()->control().data();
+ FullySpecifiedType type = rewriteType(result.first().type(), &env, control);
- Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview();
- QString originalName = oo.prettyName(m_name);
- QString newName = originalName;
- if (newName.startsWith(QLatin1String("get"), Qt::CaseInsensitive)
- && newName.length() > 3
- && newName.at(3).isUpper()) {
- newName.remove(0, 3);
- newName.replace(0, 1, newName.at(0).toLower());
- } else if (newName.startsWith(QLatin1String("to"), Qt::CaseInsensitive)
- && newName.length() > 2
- && newName.at(2).isUpper()) {
- newName.remove(0, 2);
- newName.replace(0, 1, newName.at(0).toLower());
- } else {
- newName.replace(0, 1, newName.at(0).toUpper());
- newName.prepend(QLatin1String("local"));
- }
+ return m_oo.prettyType(type, m_name);
+ }
- const int nameLength = originalName.length();
- QString tempType = oo.prettyType(type, m_name);
- const QString insertString = tempType.replace(
- tempType.length() - nameLength, nameLength, newName + QLatin1String(" = "));
- if (!tempType.isEmpty()) {
- ChangeSet changes;
- changes.insert(m_insertPos, insertString);
- file->setChangeSet(changes);
- file->apply();
-
- // move cursor to new variable name
- QTextCursor c = file->cursor();
- c.setPosition(m_insertPos + insertString.length() - newName.length() - 3);
- c.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- editor()->setTextCursor(c);
- }
+ QString constructVarName() const
+ {
+ QString newName = m_originalName;
+ if (newName.startsWith(QLatin1String("get"), Qt::CaseInsensitive)
+ && newName.length() > 3
+ && newName.at(3).isUpper()) {
+ newName.remove(0, 3);
+ newName.replace(0, 1, newName.at(0).toLower());
+ } else if (newName.startsWith(QLatin1String("to"), Qt::CaseInsensitive)
+ && newName.length() > 2
+ && newName.at(2).isUpper()) {
+ newName.remove(0, 2);
+ newName.replace(0, 1, newName.at(0).toLower());
+ } else {
+ newName.replace(0, 1, newName.at(0).toUpper());
+ newName.prepend(QLatin1String("local"));
}
+ return newName;
}
-private:
const int m_insertPos;
- const AST *m_ast;
- const Name *m_name;
+ const AST * const m_ast;
+ const Name * const m_name;
+ const Overview m_oo;
+ const QString m_originalName;
+ const CppRefactoringFilePtr m_file;
};
} // anonymous namespace
@@ -6891,7 +6937,7 @@ void AssignToLocalVariable::match(const CppQuickFixInterface &interface, QuickFi
TypeOfExpression::Preprocess);
}
- foreach (const LookupItem &item, items) {
+ for (const LookupItem &item : qAsConst(items)) {
if (!item.declaration())
continue;
@@ -7307,7 +7353,7 @@ private:
Symbol *skipForwardDeclarations(const QList<Symbol *> &symbols)
{
- foreach (Symbol *symbol, symbols) {
+ for (Symbol *symbol : symbols) {
if (!symbol->type()->isForwardClassDeclarationType())
return symbol;
}
@@ -7321,8 +7367,8 @@ bool findRawAccessFunction(Class *klass, PointerType *pointerType, QString *objA
for (auto it = klass->memberBegin(), end = klass->memberEnd(); it != end; ++it) {
if (Function *func = (*it)->asFunction()) {
const Name *funcName = func->name();
- if (!funcName->isOperatorNameId()
- && !funcName->isConversionNameId()
+ if (!funcName->asOperatorNameId()
+ && !funcName->asConversionNameId()
&& func->returnType().type() == pointerType
&& func->isConst()
&& func->argumentCount() == 0) {
@@ -7339,7 +7385,7 @@ bool findRawAccessFunction(Class *klass, PointerType *pointerType, QString *objA
break;
default:
// Multiple candidates - prefer a function named data
- foreach (Function *func, candidates) {
+ for (Function *func : qAsConst(candidates)) {
if (!strcmp(func->name()->identifier()->chars(), "data")) {
funcName = func->name();
break;
@@ -8144,6 +8190,9 @@ private:
void RemoveUsingNamespace::match(const CppQuickFixInterface &interface, QuickFixOperations &result)
{
+ if (CppModelManager::usesClangd(interface.currentFile()->editor()->textDocument()))
+ return;
+
const QList<AST *> &path = interface.path();
// We expect something like
// [0] TranslationUnitAST
@@ -8156,7 +8205,7 @@ void RemoveUsingNamespace::match(const CppQuickFixInterface &interface, QuickFix
if (path.last()->asName())
--n;
UsingDirectiveAST *usingDirective = path.at(n)->asUsingDirective();
- if (usingDirective && usingDirective->name->name->isNameId()) {
+ if (usingDirective && usingDirective->name->name->asNameId()) {
result << new RemoveUsingNamespaceOperation(interface, usingDirective, false);
const bool isHeader = ProjectFile::isHeader(ProjectFile::classify(interface.filePath().toString()));
if (isHeader && path.at(n - 1)->asTranslationUnit()) // using namespace at global scope
@@ -8769,9 +8818,9 @@ public:
Symbol *const s = *it;
if (!s->identifier() || !s->type() || s->type().isTypedef())
continue;
- if ((s->isDeclaration() && s->type()->asFunctionType()) || s->asFunction())
+ if ((s->asDeclaration() && s->type()->asFunctionType()) || s->asFunction())
continue;
- if (s->isDeclaration() && (s->isPrivate() || s->isProtected()) && !s->isStatic()) {
+ if (s->asDeclaration() && (s->isPrivate() || s->isProtected()) && !s->isStatic()) {
const auto name = QString::fromUtf8(s->identifier()->chars(),
s->identifier()->size());
parameterModel.emplaceBackParameter(name, s, memberCounter++);
diff --git a/src/plugins/cppeditor/cppquickfixprojectsettingswidget.cpp b/src/plugins/cppeditor/cppquickfixprojectsettingswidget.cpp
index 3414cb3a6c0..62299a937d2 100644
--- a/src/plugins/cppeditor/cppquickfixprojectsettingswidget.cpp
+++ b/src/plugins/cppeditor/cppquickfixprojectsettingswidget.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "cppquickfixprojectsettingswidget.h"
+#include "cppeditorconstants.h"
#include "cppquickfixsettingswidget.h"
#include "ui_cppquickfixprojectsettingswidget.h"
@@ -33,9 +34,10 @@ using namespace CppEditor::Internal;
CppQuickFixProjectSettingsWidget::CppQuickFixProjectSettingsWidget(ProjectExplorer::Project *project,
QWidget *parent)
- : QWidget(parent)
+ : ProjectExplorer::ProjectSettingsWidget(parent)
, ui(new Ui::CppQuickFixProjectSettingsWidget)
{
+ setGlobalSettingsId(CppEditor::Constants::QUICK_FIX_SETTINGS_ID);
m_projectSettings = CppQuickFixProjectsSettings::getSettings(project);
ui->setupUi(this);
m_settingsWidget = new CppEditor::Internal::CppQuickFixSettingsWidget(this);
@@ -43,20 +45,20 @@ CppQuickFixProjectSettingsWidget::CppQuickFixProjectSettingsWidget(ProjectExplor
if (QLayout *layout = m_settingsWidget->layout())
layout->setContentsMargins(0, 0, 0, 0);
ui->layout->addWidget(m_settingsWidget);
- connect(ui->comboBox,
- QOverload<int>::of(&QComboBox::currentIndexChanged),
- this,
- &CppQuickFixProjectSettingsWidget::currentItemChanged);
- connect(ui->pushButton_custom,
- &QAbstractButton::clicked,
- this,
- &CppQuickFixProjectSettingsWidget::buttonCustomClicked);
- connect(m_settingsWidget, &CppEditor::Internal::CppQuickFixSettingsWidget::settingsChanged, [this] {
- m_settingsWidget->saveSettings(m_projectSettings->getSettings());
- if (!useGlobalSettings())
- m_projectSettings->saveOwnSettings();
- });
- ui->comboBox->setCurrentIndex(m_projectSettings->isUsingGlobalSettings() ? 0 : 1);
+
+ connect(this, &ProjectSettingsWidget::useGlobalSettingsChanged,
+ this, &CppQuickFixProjectSettingsWidget::currentItemChanged);
+ setUseGlobalSettings(m_projectSettings->isUsingGlobalSettings());
+ currentItemChanged(m_projectSettings->useCustomSettings());
+
+ connect(ui->pushButton_custom, &QAbstractButton::clicked,
+ this, &CppQuickFixProjectSettingsWidget::buttonCustomClicked);
+ connect(m_settingsWidget, &CppEditor::Internal::CppQuickFixSettingsWidget::settingsChanged, this,
+ [this] {
+ m_settingsWidget->saveSettings(m_projectSettings->getSettings());
+ if (!useGlobalSettings())
+ m_projectSettings->saveOwnSettings();
+ });
}
CppQuickFixProjectSettingsWidget::~CppQuickFixProjectSettingsWidget()
@@ -64,9 +66,9 @@ CppQuickFixProjectSettingsWidget::~CppQuickFixProjectSettingsWidget()
delete ui;
}
-void CppQuickFixProjectSettingsWidget::currentItemChanged()
+void CppQuickFixProjectSettingsWidget::currentItemChanged(bool useGlobalSettings)
{
- if (useGlobalSettings()) {
+ if (useGlobalSettings) {
const auto &path = m_projectSettings->filePathOfSettingsFile();
ui->pushButton_custom->setToolTip(tr("Custom settings are saved in a file. If you use the "
"global settings, you can delete that file."));
@@ -75,7 +77,7 @@ void CppQuickFixProjectSettingsWidget::currentItemChanged()
m_projectSettings->useGlobalSettings();
} else /*Custom*/ {
if (!m_projectSettings->useCustomSettings()) {
- ui->comboBox->setCurrentIndex(0);
+ setUseGlobalSettings(!m_projectSettings->useCustomSettings());
return;
}
ui->pushButton_custom->setToolTip(tr("Resets all settings to the global settings."));
@@ -99,8 +101,3 @@ void CppQuickFixProjectSettingsWidget::buttonCustomClicked()
m_settingsWidget->loadSettings(m_projectSettings->getSettings());
}
}
-
-bool CppQuickFixProjectSettingsWidget::useGlobalSettings()
-{
- return ui->comboBox->currentIndex() == 0;
-}
diff --git a/src/plugins/cppeditor/cppquickfixprojectsettingswidget.h b/src/plugins/cppeditor/cppquickfixprojectsettingswidget.h
index d0347973c66..6921bb658d0 100644
--- a/src/plugins/cppeditor/cppquickfixprojectsettingswidget.h
+++ b/src/plugins/cppeditor/cppquickfixprojectsettingswidget.h
@@ -26,6 +26,7 @@
#pragma once
#include "cppquickfixprojectsettings.h"
+#include <projectexplorer/projectsettingswidget.h>
#include <QWidget>
@@ -38,7 +39,7 @@ namespace ProjectExplorer { class Project; }
namespace CppEditor {
namespace Internal {
class CppQuickFixSettingsWidget;
-class CppQuickFixProjectSettingsWidget : public QWidget
+class CppQuickFixProjectSettingsWidget : public ProjectExplorer::ProjectSettingsWidget
{
Q_OBJECT
@@ -48,12 +49,10 @@ public:
~CppQuickFixProjectSettingsWidget();
private slots:
- void currentItemChanged();
+ void currentItemChanged(bool useGlobalSettings);
void buttonCustomClicked();
private:
- bool useGlobalSettings();
-
QT_PREPEND_NAMESPACE(Ui)::CppQuickFixProjectSettingsWidget *ui;
CppQuickFixSettingsWidget *m_settingsWidget;
CppQuickFixProjectsSettings::CppQuickFixProjectsSettingsPtr m_projectSettings;
diff --git a/src/plugins/cppeditor/cppquickfixprojectsettingswidget.ui b/src/plugins/cppeditor/cppquickfixprojectsettingswidget.ui
index b90b668a747..5628cd4033e 100644
--- a/src/plugins/cppeditor/cppquickfixprojectsettingswidget.ui
+++ b/src/plugins/cppeditor/cppquickfixprojectsettingswidget.ui
@@ -23,33 +23,16 @@
<property name="bottomMargin">
<number>0</number>
</property>
- <item row="0" column="1">
+ <item row="2" column="0" colspan="2">
+ <layout class="QVBoxLayout" name="layout"/>
+ </item>
+ <item row="1" column="0">
<widget class="QPushButton" name="pushButton_custom">
<property name="text">
<string/>
</property>
</widget>
</item>
- <item row="1" column="0" colspan="2">
- <layout class="QVBoxLayout" name="layout"/>
- </item>
- <item row="0" column="0">
- <widget class="QComboBox" name="comboBox">
- <property name="currentIndex">
- <number>-1</number>
- </property>
- <item>
- <property name="text">
- <string>Global Settings</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Custom Settings</string>
- </property>
- </item>
- </widget>
- </item>
</layout>
</widget>
<resources/>
diff --git a/src/plugins/cppeditor/cpprefactoringchanges.cpp b/src/plugins/cppeditor/cpprefactoringchanges.cpp
index 6e48ae1500b..8c16686824c 100644
--- a/src/plugins/cppeditor/cpprefactoringchanges.cpp
+++ b/src/plugins/cppeditor/cpprefactoringchanges.cpp
@@ -28,8 +28,6 @@
#include "cppqtstyleindenter.h"
#include "cppcodeformatter.h"
#include "cppeditorconstants.h"
-#include "cppmodelmanager.h"
-#include "cppworkingcopy.h"
#include <projectexplorer/editorconfiguration.h>
@@ -45,63 +43,15 @@ using namespace CPlusPlus;
namespace CppEditor {
-class CppRefactoringChangesData : public TextEditor::RefactoringChangesData
+static std::unique_ptr<TextEditor::Indenter> createIndenter(const Utils::FilePath &filePath,
+ QTextDocument *textDocument)
{
- static std::unique_ptr<TextEditor::Indenter> createIndenter(const Utils::FilePath &filePath,
- QTextDocument *textDocument)
- {
- TextEditor::ICodeStylePreferencesFactory *factory
- = TextEditor::TextEditorSettings::codeStyleFactory(Constants::CPP_SETTINGS_ID);
- std::unique_ptr<TextEditor::Indenter> indenter(factory->createIndenter(textDocument));
- indenter->setFileName(filePath);
- return indenter;
- }
-
-public:
- explicit CppRefactoringChangesData(const Snapshot &snapshot)
- : m_snapshot(snapshot)
- , m_modelManager(CppModelManager::instance())
- , m_workingCopy(m_modelManager->workingCopy())
- {}
-
- void indentSelection(const QTextCursor &selection,
- const Utils::FilePath &filePath,
- const TextEditor::TextDocument *textDocument) const override
- {
- if (textDocument) { // use the indenter from the textDocument if there is one, can be ClangFormat
- textDocument->indenter()->indent(selection, QChar::Null, textDocument->tabSettings());
- } else {
- const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath.toString(),
- textDocument);
- auto indenter = createIndenter(filePath, selection.document());
- indenter->indent(selection, QChar::Null, tabSettings);
- }
- }
-
- void reindentSelection(const QTextCursor &selection,
- const Utils::FilePath &filePath,
- const TextEditor::TextDocument *textDocument) const override
- {
- if (textDocument) { // use the indenter from the textDocument if there is one, can be ClangFormat
- textDocument->indenter()->reindent(selection, textDocument->tabSettings());
- } else {
- const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath.toString(),
- textDocument);
- auto indenter = createIndenter(filePath, selection.document());
- indenter->reindent(selection, tabSettings);
- }
- }
-
- void fileChanged(const Utils::FilePath &filePath) override
- {
- m_modelManager->updateSourceFiles({filePath.toString()});
- }
-
- Snapshot m_snapshot;
- CppModelManager *m_modelManager;
- WorkingCopy m_workingCopy;
-
-};
+ TextEditor::ICodeStylePreferencesFactory *factory
+ = TextEditor::TextEditorSettings::codeStyleFactory(Constants::CPP_SETTINGS_ID);
+ std::unique_ptr<TextEditor::Indenter> indenter(factory->createIndenter(textDocument));
+ indenter->setFileName(filePath);
+ return indenter;
+}
CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot)
: RefactoringChanges(new CppRefactoringChangesData(snapshot))
@@ -283,4 +233,41 @@ void CppRefactoringFile::fileChanged()
RefactoringFile::fileChanged();
}
+CppRefactoringChangesData::CppRefactoringChangesData(const Snapshot &snapshot)
+ : m_snapshot(snapshot)
+ , m_modelManager(CppModelManager::instance())
+ , m_workingCopy(m_modelManager->workingCopy())
+{}
+
+void CppRefactoringChangesData::indentSelection(const QTextCursor &selection,
+ const Utils::FilePath &filePath,
+ const TextEditor::TextDocument *textDocument) const
+{
+ if (textDocument) { // use the indenter from the textDocument if there is one, can be ClangFormat
+ textDocument->indenter()->indent(selection, QChar::Null, textDocument->tabSettings());
+ } else {
+ const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath, textDocument);
+ auto indenter = createIndenter(filePath, selection.document());
+ indenter->indent(selection, QChar::Null, tabSettings);
+ }
+}
+
+void CppRefactoringChangesData::reindentSelection(const QTextCursor &selection,
+ const Utils::FilePath &filePath,
+ const TextEditor::TextDocument *textDocument) const
+{
+ if (textDocument) { // use the indenter from the textDocument if there is one, can be ClangFormat
+ textDocument->indenter()->reindent(selection, textDocument->tabSettings());
+ } else {
+ const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath, textDocument);
+ auto indenter = createIndenter(filePath, selection.document());
+ indenter->reindent(selection, tabSettings);
+ }
+}
+
+void CppRefactoringChangesData::fileChanged(const Utils::FilePath &filePath)
+{
+ m_modelManager->updateSourceFiles({filePath.toString()});
+}
+
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cpprefactoringchanges.h b/src/plugins/cppeditor/cpprefactoringchanges.h
index a50631856a3..2b4d09b9e56 100644
--- a/src/plugins/cppeditor/cpprefactoringchanges.h
+++ b/src/plugins/cppeditor/cpprefactoringchanges.h
@@ -27,6 +27,9 @@
#include "cppeditor_global.h"
+#include "cppmodelmanager.h"
+#include "cppworkingcopy.h"
+
#include <cplusplus/CppDocument.h>
#include <texteditor/refactoringchanges.h>
@@ -79,6 +82,26 @@ protected:
friend class CppRefactoringChanges; // for access to constructor
};
+class CPPEDITOR_EXPORT CppRefactoringChangesData : public TextEditor::RefactoringChangesData
+{
+public:
+ explicit CppRefactoringChangesData(const CPlusPlus::Snapshot &snapshot);
+
+ void indentSelection(const QTextCursor &selection,
+ const Utils::FilePath &filePath,
+ const TextEditor::TextDocument *textDocument) const override;
+
+ void reindentSelection(const QTextCursor &selection,
+ const Utils::FilePath &filePath,
+ const TextEditor::TextDocument *textDocument) const override;
+
+ void fileChanged(const Utils::FilePath &filePath) override;
+
+ CPlusPlus::Snapshot m_snapshot;
+ CppModelManager *m_modelManager;
+ WorkingCopy m_workingCopy;
+};
+
class CPPEDITOR_EXPORT CppRefactoringChanges: public TextEditor::RefactoringChanges
{
public:
diff --git a/src/plugins/cppeditor/cpprefactoringengine.cpp b/src/plugins/cppeditor/cpprefactoringengine.cpp
deleted file mode 100644
index 653598143f5..00000000000
--- a/src/plugins/cppeditor/cpprefactoringengine.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cpprefactoringengine.h"
-
-#include "cppcanonicalsymbol.h"
-#include "cppeditorwidget.h"
-#include "cppmodelmanager.h"
-#include "cppsemanticinfo.h"
-#include "cpptoolsreuse.h"
-#include "cppfollowsymbolundercursor.h"
-
-#include <clangsupport/sourcelocationscontainer.h>
-#include <texteditor/texteditor.h>
-
-#include <utils/qtcassert.h>
-
-namespace CppEditor::Internal {
-
-void CppRefactoringEngine::startLocalRenaming(const CursorInEditor &data,
- const ProjectPart *,
- RenameCallback &&renameSymbolsCallback)
-{
- CppEditorWidget *editorWidget = data.editorWidget();
- QTC_ASSERT(editorWidget, renameSymbolsCallback(QString(),
- ClangBackEnd::SourceLocationsContainer(),
- 0); return;);
- editorWidget->updateSemanticInfo();
- // Call empty callback
- renameSymbolsCallback(QString(),
- ClangBackEnd::SourceLocationsContainer(),
- data.cursor().document()->revision());
-}
-
-void CppRefactoringEngine::globalRename(const CursorInEditor &data,
- UsagesCallback &&,
- const QString &replacement)
-{
- CppModelManager *modelManager = CppModelManager::instance();
- if (!modelManager)
- return;
-
- CppEditorWidget *editorWidget = data.editorWidget();
- QTC_ASSERT(editorWidget, return;);
-
- SemanticInfo info = editorWidget->semanticInfo();
- info.snapshot = modelManager->snapshot();
- info.snapshot.insert(info.doc);
- const QTextCursor &cursor = data.cursor();
- if (const CPlusPlus::Macro *macro = findCanonicalMacro(cursor, info.doc)) {
- modelManager->renameMacroUsages(*macro, replacement);
- } else {
- Internal::CanonicalSymbol cs(info.doc, info.snapshot);
- CPlusPlus::Symbol *canonicalSymbol = cs(cursor);
- if (canonicalSymbol)
- modelManager->renameUsages(canonicalSymbol, cs.context(), replacement);
- }
-}
-
-void CppRefactoringEngine::findUsages(const CursorInEditor &data,
- UsagesCallback &&) const
-{
- CppModelManager *modelManager = CppModelManager::instance();
- if (!modelManager)
- return;
-
- CppEditorWidget *editorWidget = data.editorWidget();
- QTC_ASSERT(editorWidget, return;);
-
- SemanticInfo info = editorWidget->semanticInfo();
- info.snapshot = modelManager->snapshot();
- info.snapshot.insert(info.doc);
- const QTextCursor &cursor = data.cursor();
- if (const CPlusPlus::Macro *macro = findCanonicalMacro(cursor, info.doc)) {
- modelManager->findMacroUsages(*macro);
- } else {
- Internal::CanonicalSymbol cs(info.doc, info.snapshot);
- CPlusPlus::Symbol *canonicalSymbol = cs(cursor);
- if (canonicalSymbol)
- modelManager->findUsages(canonicalSymbol, cs.context());
- }
-}
-
-void CppRefactoringEngine::globalFollowSymbol(
- const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder,
- bool inNextSplit) const
-{
- FollowSymbolUnderCursor followSymbol;
- return followSymbol.findLink(data, std::move(processLinkCallback), true, snapshot,
- documentFromSemanticInfo, symbolFinder, inNextSplit);
-}
-
-} // namespace CppEditor::Internal
diff --git a/src/plugins/cppeditor/cpprefactoringengine.h b/src/plugins/cppeditor/cpprefactoringengine.h
deleted file mode 100644
index 18b0a2555fd..00000000000
--- a/src/plugins/cppeditor/cpprefactoringengine.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "refactoringengineinterface.h"
-
-namespace CppEditor::Internal {
-
-class CppRefactoringEngine : public RefactoringEngineInterface
-{
-public:
- void startLocalRenaming(const CursorInEditor &data,
- const ProjectPart *projectPart,
- RenameCallback &&renameSymbolsCallback) override;
- void globalRename(const CursorInEditor &data, UsagesCallback &&,
- const QString &replacement) override;
- void findUsages(const CursorInEditor &data, UsagesCallback &&) const override;
- void globalFollowSymbol(const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder,
- bool inNextSplit) const override;
-};
-
-} // namespace CppEditor::Internal
diff --git a/src/plugins/cppeditor/cppsourceprocessor.cpp b/src/plugins/cppeditor/cppsourceprocessor.cpp
index b4008cfa625..68204bf8eb6 100644
--- a/src/plugins/cppeditor/cppsourceprocessor.cpp
+++ b/src/plugins/cppeditor/cppsourceprocessor.cpp
@@ -67,7 +67,7 @@ inline QByteArray generateFingerPrint(const QList<CPlusPlus::Macro> &definedMacr
{
QCryptographicHash hash(QCryptographicHash::Sha1);
hash.addData(code);
- foreach (const CPlusPlus::Macro &macro, definedMacros) {
+ for (const CPlusPlus::Macro &macro : definedMacros) {
if (macro.isHidden()) {
static const QByteArray undef("#undef ");
hash.addData(undef);
@@ -168,7 +168,8 @@ void CppSourceProcessor::addFrameworkPath(const ProjectExplorer::HeaderPath &fra
const QDir frameworkDir(cleanFrameworkPath.path);
const QStringList filter = QStringList("*.framework");
- foreach (const QFileInfo &framework, frameworkDir.entryInfoList(filter)) {
+ const QList<QFileInfo> frameworks = frameworkDir.entryInfoList(filter);
+ for (const QFileInfo &framework : frameworks) {
if (!framework.isDir())
continue;
const QFileInfo privateFrameworks(framework.absoluteFilePath(),
@@ -400,7 +401,8 @@ void CppSourceProcessor::mergeEnvironment(Document::Ptr doc)
m_processed.insert(fn);
- foreach (const Document::Include &incl, doc->resolvedIncludes()) {
+ const QList<Document::Include> includes = doc->resolvedIncludes();
+ for (const Document::Include &incl : includes) {
const QString includedFile = incl.resolvedFileName();
if (Document::Ptr includedDoc = m_snapshot.document(includedFile))
@@ -468,7 +470,7 @@ void CppSourceProcessor::sourceNeeded(int line, const QString &fileName, Include
Document::Ptr document = Document::create(absoluteFileName);
document->setEditorRevision(editorRevision);
document->setLanguageFeatures(m_languageFeatures);
- foreach (const QString &include, initialIncludes) {
+ for (const QString &include : initialIncludes) {
m_included.insert(include);
Document::Include inc(include, include, 0, IncludeLocal);
document->addIncludeFile(inc);
diff --git a/src/plugins/cppeditor/cppsourceprocessor_test.cpp b/src/plugins/cppeditor/cppsourceprocessor_test.cpp
index f381cf4d6d6..a8c555ff595 100644
--- a/src/plugins/cppeditor/cppsourceprocessor_test.cpp
+++ b/src/plugins/cppeditor/cppsourceprocessor_test.cpp
@@ -187,7 +187,8 @@ void SourceProcessorTest::testMacroUses()
static bool isMacroDefinedInDocument(const QByteArray &macroName, const Document::Ptr &document)
{
- foreach (const Macro &macro, document->definedMacros()) {
+ const QList<Macro> macros = document->definedMacros();
+ for (const Macro &macro : macros) {
if (macro.name() == macroName)
return true;
}
diff --git a/src/plugins/cppeditor/cpptoolsreuse.cpp b/src/plugins/cppeditor/cpptoolsreuse.cpp
index bd5b702360d..91794a18384 100644
--- a/src/plugins/cppeditor/cpptoolsreuse.cpp
+++ b/src/plugins/cppeditor/cpptoolsreuse.cpp
@@ -25,12 +25,15 @@
#include "cpptoolsreuse.h"
+#include "clangdiagnosticconfigsmodel.h"
#include "cppautocompleter.h"
#include "cppcodemodelsettings.h"
+#include "cppcompletionassist.h"
#include "cppeditorconstants.h"
#include "cppeditorplugin.h"
#include "cpphighlighter.h"
#include "cppqtstyleindenter.h"
+#include "cppquickfixassistant.h"
#include "cpprefactoringchanges.h"
#include "projectinfo.h"
@@ -176,7 +179,7 @@ bool isOwnershipRAIIType(Symbol *symbol, const LookupContext &context)
// This is not a "real" comparison of types. What we do is to resolve the symbol
// in question and then try to match its name with already known ones.
- if (symbol->isDeclaration()) {
+ if (symbol->asDeclaration()) {
Declaration *declaration = symbol->asDeclaration();
const NamedType *namedType = declaration->type()->asNamedType();
if (namedType) {
@@ -269,16 +272,6 @@ bool isQtKeyword(QStringView text)
return false;
}
-void switchHeaderSource()
-{
- const Core::IDocument *currentDocument = Core::EditorManager::currentDocument();
- QTC_ASSERT(currentDocument, return);
- const auto otherFile = Utils::FilePath::fromString(
- correspondingHeaderOrSource(currentDocument->filePath().toString()));
- if (!otherFile.isEmpty())
- Core::EditorManager::openEditor(otherFile);
-}
-
QString identifierUnderCursor(QTextCursor *cursor)
{
cursor->movePosition(QTextCursor::StartOfWord);
@@ -339,6 +332,16 @@ bool isInCommentOrString(const TextEditor::AssistInterface *interface,
return true;
}
+TextEditor::QuickFixOperations quickFixOperations(const TextEditor::AssistInterface *interface)
+{
+ return Internal::quickFixOperations(interface);
+}
+
+CppCompletionAssistProcessor *getCppCompletionAssistProcessor()
+{
+ return new Internal::InternalCppCompletionAssistProcessor();
+}
+
CppCodeModelSettings *codeModelSettings()
{
return Internal::CppEditorPlugin::instance()->codeModelSettings();
@@ -427,7 +430,7 @@ ClangDiagnosticConfigsModel diagnosticConfigsModel(const ClangDiagnosticConfigs
ClangDiagnosticConfigsModel diagnosticConfigsModel()
{
- return diagnosticConfigsModel(codeModelSettings()->clangCustomDiagnosticConfigs());
+ return diagnosticConfigsModel(ClangdSettings::instance().customDiagnosticConfigs());
}
NSVisitor::NSVisitor(const CppRefactoringFile *file, const QStringList &namespaces, int symbolPos)
@@ -627,6 +630,13 @@ ProjectExplorer::Project *projectForProjectInfo(const ProjectInfo &info)
return ProjectExplorer::SessionManager::projectWithProjectFilePath(info.projectFilePath());
}
+void openEditor(const Utils::FilePath &filePath, bool inNextSplit)
+{
+ using Core::EditorManager;
+ EditorManager::openEditor(filePath, {}, inNextSplit ? EditorManager::OpenInOtherSplit
+ : EditorManager::NoFlags);
+}
+
namespace Internal {
void decorateCppEditor(TextEditor::TextEditorWidget *editor)
diff --git a/src/plugins/cppeditor/cpptoolsreuse.h b/src/plugins/cppeditor/cpptoolsreuse.h
index e7023b7be78..4743ec3377e 100644
--- a/src/plugins/cppeditor/cpptoolsreuse.h
+++ b/src/plugins/cppeditor/cpptoolsreuse.h
@@ -31,6 +31,7 @@
#include "compileroptionsbuilder.h"
#include "projectpart.h"
+#include <texteditor/quickfix.h>
#include <texteditor/texteditor.h>
#include <cplusplus/ASTVisitor.h>
@@ -54,6 +55,7 @@ namespace TextEditor { class AssistInterface; }
namespace CppEditor {
class CppRefactoringFile;
class ProjectInfo;
+class CppCompletionAssistProcessor;
void CPPEDITOR_EXPORT moveCursorToEndOfIdentifier(QTextCursor *tc);
void CPPEDITOR_EXPORT moveCursorToStartOfIdentifier(QTextCursor *tc);
@@ -76,13 +78,16 @@ const CPlusPlus::Macro CPPEDITOR_EXPORT *findCanonicalMacro(const QTextCursor &c
bool CPPEDITOR_EXPORT isInCommentOrString(const TextEditor::AssistInterface *interface,
CPlusPlus::LanguageFeatures features);
+TextEditor::QuickFixOperations CPPEDITOR_EXPORT
+quickFixOperations(const TextEditor::AssistInterface *interface);
+
+CppCompletionAssistProcessor CPPEDITOR_EXPORT *getCppCompletionAssistProcessor();
enum class CacheUsage { ReadWrite, ReadOnly };
QString CPPEDITOR_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = nullptr,
CacheUsage cacheUsage = CacheUsage::ReadWrite);
-void CPPEDITOR_EXPORT switchHeaderSource();
-
+void CPPEDITOR_EXPORT openEditor(const Utils::FilePath &filePath, bool inNextSplit);
class CppCodeModelSettings;
CppCodeModelSettings CPPEDITOR_EXPORT *codeModelSettings();
diff --git a/src/plugins/cppeditor/cpptoolssettings.cpp b/src/plugins/cppeditor/cpptoolssettings.cpp
index 4d77f04d61f..31b8740cc89 100644
--- a/src/plugins/cppeditor/cpptoolssettings.cpp
+++ b/src/plugins/cppeditor/cpptoolssettings.cpp
@@ -44,8 +44,6 @@
static const char idKey[] = "CppGlobal";
const bool kSortEditorDocumentOutlineDefault = true;
-const bool kShowHeaderErrorInfoBarDefault = true;
-const bool kShowNoProjectInfoBarDefault = true;
using namespace Core;
using namespace TextEditor;
@@ -265,46 +263,4 @@ void CppToolsSettings::setSortedEditorDocumentOutline(bool sorted)
emit editorDocumentOutlineSortingChanged(sorted);
}
-static QString showHeaderErrorInfoBarKey()
-{
- return QLatin1String(Constants::CPPEDITOR_SETTINGSGROUP)
- + QLatin1Char('/')
- + QLatin1String(Constants::CPPEDITOR_SHOW_INFO_BAR_FOR_HEADER_ERRORS);
-}
-
-bool CppToolsSettings::showHeaderErrorInfoBar() const
-{
- return ICore::settings()
- ->value(showHeaderErrorInfoBarKey(), kShowHeaderErrorInfoBarDefault)
- .toBool();
-}
-
-void CppToolsSettings::setShowHeaderErrorInfoBar(bool show)
-{
- ICore::settings()->setValueWithDefault(showHeaderErrorInfoBarKey(),
- show,
- kShowHeaderErrorInfoBarDefault);
- emit showHeaderErrorInfoBarChanged(show);
-}
-
-static QString showNoProjectInfoBarKey()
-{
- return QLatin1String(Constants::CPPEDITOR_SETTINGSGROUP)
- + QLatin1Char('/')
- + QLatin1String(Constants::CPPEDITOR_SHOW_INFO_BAR_FOR_FOR_NO_PROJECT);
-}
-
-bool CppToolsSettings::showNoProjectInfoBar() const
-{
- return ICore::settings()->value(showNoProjectInfoBarKey(), kShowNoProjectInfoBarDefault).toBool();
-}
-
-void CppToolsSettings::setShowNoProjectInfoBar(bool show)
-{
- ICore::settings()->setValueWithDefault(showNoProjectInfoBarKey(),
- show,
- kShowNoProjectInfoBarDefault);
- emit showNoProjectInfoBarChanged(show);
-}
-
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cpptoolssettings.h b/src/plugins/cppeditor/cpptoolssettings.h
index 3f31d72ff0e..1c5d3cbe104 100644
--- a/src/plugins/cppeditor/cpptoolssettings.h
+++ b/src/plugins/cppeditor/cpptoolssettings.h
@@ -58,16 +58,8 @@ public:
bool sortedEditorDocumentOutline() const;
void setSortedEditorDocumentOutline(bool sorted);
- bool showHeaderErrorInfoBar() const;
- void setShowHeaderErrorInfoBar(bool show);
-
- bool showNoProjectInfoBar() const;
- void setShowNoProjectInfoBar(bool show);
-
signals:
void editorDocumentOutlineSortingChanged(bool isSorted);
- void showHeaderErrorInfoBarChanged(bool isShown);
- void showNoProjectInfoBarChanged(bool isShown);
private:
Internal::CppToolsSettingsPrivate *d;
diff --git a/src/plugins/cppeditor/cpptoolstestcase.cpp b/src/plugins/cppeditor/cpptoolstestcase.cpp
index 2e48964bed2..9b809008d46 100644
--- a/src/plugins/cppeditor/cpptoolstestcase.cpp
+++ b/src/plugins/cppeditor/cpptoolstestcase.cpp
@@ -399,7 +399,7 @@ ProjectOpenerAndCloser::~ProjectOpenerAndCloser()
hasGcFinished = true;
});
- foreach (Project *project, m_openProjects)
+ for (Project *project : qAsConst(m_openProjects))
ProjectExplorerPlugin::unloadProject(project);
QElapsedTimer t;
diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp
index d8b627946a2..9d98a75bed5 100644
--- a/src/plugins/cppeditor/cpptypehierarchy.cpp
+++ b/src/plugins/cppeditor/cpptypehierarchy.cpp
@@ -275,7 +275,9 @@ QStandardItem *CppTypeHierarchyWidget::buildHierarchy(const CppClass &cppClass,
if (m_showOldClass && cppClass.qualifiedName == m_oldClass)
selectedItem = item;
}
- foreach (const CppClass &klass, sortClasses(cppClass.*member)) {
+
+ const QList<CppClass> classes = sortClasses(cppClass.*member);
+ for (const CppClass &klass : classes) {
QStandardItem *item = buildHierarchy(klass, parent, false, member);
if (!selectedItem)
selectedItem = item;
@@ -383,7 +385,7 @@ QMimeData *CppTypeHierarchyModel::mimeData(const QModelIndexList &indexes) const
{
auto data = new DropMimeData;
data->setOverrideFileDropAction(Qt::CopyAction); // do not remove the item from the model
- foreach (const QModelIndex &index, indexes) {
+ for (const QModelIndex &index : indexes) {
auto link = index.data(LinkRole).value<Link>();
if (link.hasValidTarget())
data->addFile(link.targetFilePath, link.targetLine, link.targetColumn);
diff --git a/src/plugins/cppeditor/cppuseselections_test.cpp b/src/plugins/cppeditor/cppuseselections_test.cpp
index 2bf5e6271c3..4670befb791 100644
--- a/src/plugins/cppeditor/cppuseselections_test.cpp
+++ b/src/plugins/cppeditor/cppuseselections_test.cpp
@@ -122,7 +122,7 @@ SelectionList UseSelectionsTestCase::toSelectionList(
const QList<QTextEdit::ExtraSelection> &extraSelections) const
{
SelectionList result;
- foreach (const QTextEdit::ExtraSelection &selection, extraSelections) {
+ for (const QTextEdit::ExtraSelection &selection : extraSelections) {
int line, column;
const int position = qMin(selection.cursor.position(), selection.cursor.anchor());
m_editorWidget->convertPosition(position, &line, &column);
diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp
index b26165ca023..babff089b7f 100644
--- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp
+++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp
@@ -74,7 +74,7 @@ CppUseSelectionsUpdater::RunnerInfo CppUseSelectionsUpdater::update(CallType cal
auto *cppEditorDocument = qobject_cast<CppEditorDocument *>(cppEditorWidget->textDocument());
QTC_ASSERT(cppEditorDocument, return RunnerInfo::FailedToStart);
- m_updateSelections = CppModelManager::instance()->supportsLocalUses(cppEditorDocument);
+ m_updateSelections = !CppModelManager::usesClangd(cppEditorDocument);
CursorInfoParams params;
params.semanticInfo = cppEditorWidget->semanticInfo();
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
index ff7d8ca8a2a..1bd5ba76de2 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
+++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
@@ -142,7 +142,7 @@ public:
return nullptr;
QList<AssistProposalItemInterface *> items;
- foreach (Function *func, overrides)
+ for (Function *func : overrides)
items << itemFromFunction(func);
items.first()->setOrder(1000); // Ensure top position for function of static type
diff --git a/src/plugins/cppeditor/cursorineditor.h b/src/plugins/cppeditor/cursorineditor.h
index 6bd2e83af2e..9a397578bfd 100644
--- a/src/plugins/cppeditor/cursorineditor.h
+++ b/src/plugins/cppeditor/cursorineditor.h
@@ -26,14 +26,20 @@
#pragma once
#include <utils/fileutils.h>
+#include <utils/link.h>
#include <QTextCursor>
+#include <functional>
+
namespace TextEditor { class TextDocument; }
namespace CppEditor {
class CppEditorWidget;
+// TODO: Move to a better place.
+using RenameCallback = std::function<void(const QString &, const Utils::Links &, int)>;
+
class CursorInEditor
{
public:
diff --git a/src/plugins/cppeditor/doxygengenerator.cpp b/src/plugins/cppeditor/doxygengenerator.cpp
index 23d551afc87..555c1502f4b 100644
--- a/src/plugins/cppeditor/doxygengenerator.cpp
+++ b/src/plugins/cppeditor/doxygengenerator.cpp
@@ -92,7 +92,7 @@ QString DoxygenGenerator::generate(QTextCursor cursor,
while (block.isValid()) {
const QString &text = block.text();
const Tokens &tks = lexer(text);
- foreach (const Token &tk, tks) {
+ for (const Token &tk : tks) {
if (tk.is(T_SEMICOLON) || tk.is(T_LBRACE)) {
// No need to continue beyond this, we might already have something meaningful.
cursor.setPosition(block.position() + tk.utf16charsEnd(), QTextCursor::KeepAnchor);
@@ -216,7 +216,7 @@ QString DoxygenGenerator::generate(QTextCursor cursor, DeclarationAST *decl)
if (ClassSpecifierAST *classSpec = spec->asClassSpecifier()) {
if (classSpec->name) {
QString aggregate;
- if (classSpec->symbol->isClass())
+ if (classSpec->symbol->asClass())
aggregate = QLatin1String("class");
else if (classSpec->symbol->isStruct())
aggregate = QLatin1String("struct");
diff --git a/src/plugins/cppeditor/fileandtokenactions_test.cpp b/src/plugins/cppeditor/fileandtokenactions_test.cpp
index 373d1e7d142..4e4281534ea 100644
--- a/src/plugins/cppeditor/fileandtokenactions_test.cpp
+++ b/src/plugins/cppeditor/fileandtokenactions_test.cpp
@@ -154,17 +154,18 @@ TestActionsTestCase::TestActionsTestCase(const Actions &tokenActions, const Acti
QList<QPointer<ProjectExplorer::Project> > projects;
const QList<ProjectInfo::ConstPtr> projectInfos = m_modelManager->projectInfos();
- foreach (const ProjectInfo::ConstPtr &info, projectInfos) {
+ for (const ProjectInfo::ConstPtr &info : projectInfos) {
qDebug() << "Project" << info->projectFilePath().toUserOutput() << "- files to process:"
<< info->sourceFiles().size();
- foreach (const QString &sourceFile, info->sourceFiles())
+ const QSet<QString> sourceFiles = info->sourceFiles();
+ for (const QString &sourceFile : sourceFiles)
filesToOpen << sourceFile;
}
Utils::sort(filesToOpen);
// Process all files from the projects
- foreach (const QString filePath, filesToOpen) {
+ for (const QString &filePath : qAsConst(filesToOpen)) {
// Skip e.g. "<configuration>"
if (!QFileInfo::exists(filePath))
continue;
@@ -260,16 +261,17 @@ void TestActionsTestCase::undoChangesInDocument(TextDocument *editorDocument)
void TestActionsTestCase::undoChangesInAllEditorWidgets()
{
- foreach (IDocument *document, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents) {
TextDocument *baseTextDocument = qobject_cast<TextDocument *>(document);
undoChangesInDocument(baseTextDocument);
}
}
void TestActionsTestCase::executeActionsOnEditorWidget(CppEditorWidget *editorWidget,
- TestActionsTestCase::Actions actions)
+ TestActionsTestCase::Actions actions)
{
- foreach (const ActionPointer &action, actions)
+ for (const ActionPointer &action : qAsConst(actions))
action->run(editorWidget);
QApplication::processEvents();
}
@@ -461,7 +463,7 @@ void RunAllQuickFixesTokenAction::run(CppEditorWidget *editorWidget)
cppQuickFixFactory->match(qfi, operations);
}
- foreach (QuickFixOperation::Ptr operation, operations) {
+ for (QuickFixOperation::Ptr operation : qAsConst(operations)) {
qDebug() << " -- Performing Quick Fix" << operation->description();
operation->perform();
TestActionsTestCase::escape();
@@ -481,7 +483,7 @@ void SwitchHeaderSourceFileAction::run(CppEditorWidget *)
{
// Switch Header/Source
IEditor *editorBefore = EditorManager::currentEditor();
- switchHeaderSource();
+ CppModelManager::switchHeaderSource(false);
QApplication::processEvents();
// Go back
diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
index 63f16e98096..997298eae0b 100644
--- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
+++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
@@ -271,7 +271,7 @@ F2TestCase::F2TestCase(CppEditorAction action,
CppEditor::Tests::TemporaryDir temporaryDir;
QVERIFY(temporaryDir.isValid());
QString projectFileContent = "CppApplication { files: [";
- foreach (TestDocumentPtr testFile, testFiles) {
+ for (TestDocumentPtr testFile : testFiles) {
QVERIFY(testFile->baseDirectory().isEmpty());
testFile->setBaseDirectory(temporaryDir.path());
QVERIFY(testFile->writeToDisk());
@@ -306,12 +306,12 @@ F2TestCase::F2TestCase(CppEditorAction action,
// Update Code Model
QSet<QString> filePaths;
- foreach (const TestDocumentPtr &testFile, testFiles)
+ for (const TestDocumentPtr &testFile : testFiles)
filePaths << testFile->filePath();
QVERIFY(parseFiles(filePaths));
// Open Files
- foreach (TestDocumentPtr testFile, testFiles) {
+ for (TestDocumentPtr testFile : testFiles) {
QVERIFY(openCppEditor(testFile->filePath(), &testFile->m_editor,
&testFile->m_editorWidget));
if (!useClangd) // Editors get closed when unloading project.
@@ -350,9 +350,7 @@ F2TestCase::F2TestCase(CppEditorAction action,
switch (action) {
case FollowSymbolUnderCursorAction: {
CppEditorWidget *widget = initialTestFile->m_editorWidget;
- FollowSymbolInterface &delegate = CppModelManager::instance()->followSymbolInterface();
- auto* builtinFollowSymbol = dynamic_cast<FollowSymbolUnderCursor *>(&delegate);
- if (!builtinFollowSymbol) {
+ if (CppModelManager::instance()->isClangCodeModelActive()) {
if (curTestName == "testFollowSymbolQTCREATORBUG7903")
QSKIP((curTestName + " is not supported by Clang FollowSymbol").toLatin1());
widget->enableTestMode();
@@ -360,6 +358,7 @@ F2TestCase::F2TestCase(CppEditorAction action,
break;
}
+ FollowSymbolUnderCursor *builtinFollowSymbol = &CppModelManager::builtinFollowSymbol();
QSharedPointer<VirtualFunctionAssistProvider> original
= builtinFollowSymbol->virtualFunctionAssistProvider();
@@ -482,7 +481,7 @@ F2TestCase::F2TestCase(CppEditorAction action,
TestDocumentPtr F2TestCase::testFileWithInitialCursorMarker(const QList<TestDocumentPtr> &testFiles)
{
- foreach (const TestDocumentPtr testFile, testFiles) {
+ for (const TestDocumentPtr &testFile : testFiles) {
if (testFile->hasCursorMarker())
return testFile;
}
@@ -491,7 +490,7 @@ TestDocumentPtr F2TestCase::testFileWithInitialCursorMarker(const QList<TestDocu
TestDocumentPtr F2TestCase::testFileWithTargetCursorMarker(const QList<TestDocumentPtr> &testFiles)
{
- foreach (const TestDocumentPtr testFile, testFiles) {
+ for (const TestDocumentPtr &testFile : testFiles) {
if (testFile->hasTargetCursorMarker())
return testFile;
}
diff --git a/src/plugins/cppeditor/followsymbolinterface.h b/src/plugins/cppeditor/followsymbolinterface.h
deleted file mode 100644
index e31b8703ff8..00000000000
--- a/src/plugins/cppeditor/followsymbolinterface.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "cppeditor_global.h"
-#include "cursorineditor.h"
-
-#include <cplusplus/CppDocument.h>
-
-#include <texteditor/texteditor.h>
-
-namespace CppEditor {
-
-class SymbolFinder;
-
-class CPPEDITOR_EXPORT FollowSymbolInterface
-{
-public:
- using Link = Utils::Link;
-
- virtual ~FollowSymbolInterface() = default;
- virtual void findLink(const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- bool resolveTarget,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder,
- bool inNextSplit) = 0;
- virtual void switchDeclDef(const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder) = 0;
-};
-
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/functionutils.cpp b/src/plugins/cppeditor/functionutils.cpp
index a993e165139..a4e8ac06fe0 100644
--- a/src/plugins/cppeditor/functionutils.cpp
+++ b/src/plugins/cppeditor/functionutils.cpp
@@ -128,13 +128,13 @@ static bool isVirtualFunction_helper(const Function *function,
if (!firstVirtuals && res != Unknown)
return res == True;
- QList<LookupItem> results = context.lookup(function->name(), function->enclosingScope());
+ const QList<LookupItem> results = context.lookup(function->name(), function->enclosingScope());
if (!results.isEmpty()) {
- const bool isDestructor = function->name()->isDestructorNameId();
- foreach (const LookupItem &item, results) {
+ const bool isDestructor = function->name()->asDestructorNameId();
+ for (const LookupItem &item : results) {
if (Symbol *symbol = item.declaration()) {
if (Function *functionType = symbol->type()->asFunctionType()) {
- if (functionType->name()->isDestructorNameId() != isDestructor)
+ if ((functionType->name()->asDestructorNameId() != nullptr) != isDestructor)
continue;
if (functionType == function) // already tested
continue;
@@ -197,7 +197,7 @@ QList<Function *> FunctionUtils::overrides(Function *function, Class *functionsC
Class *c = hierarchy.symbol()->asClass();
QTC_ASSERT(c, continue);
- foreach (const TypeHierarchy &t, hierarchy.hierarchy()) {
+ for (const TypeHierarchy &t : hierarchy.hierarchy()) {
if (!l.contains(t))
l << t;
}
diff --git a/src/plugins/cppeditor/generatedcodemodelsupport.cpp b/src/plugins/cppeditor/generatedcodemodelsupport.cpp
index 73bc61f7ff7..7d8beb444bc 100644
--- a/src/plugins/cppeditor/generatedcodemodelsupport.cpp
+++ b/src/plugins/cppeditor/generatedcodemodelsupport.cpp
@@ -119,7 +119,7 @@ void GeneratedCodeModelSupport::update(const QList<ProjectExplorer::ExtraCompile
CppModelManager * const mm = CppModelManager::instance();
- foreach (ExtraCompiler *generator, generators) {
+ for (ExtraCompiler *generator : generators) {
if (extraCompilerCache.contains(generator))
continue;
diff --git a/src/plugins/cppeditor/headerpathfilter.cpp b/src/plugins/cppeditor/headerpathfilter.cpp
index 1c108882604..beba91106b3 100644
--- a/src/plugins/cppeditor/headerpathfilter.cpp
+++ b/src/plugins/cppeditor/headerpathfilter.cpp
@@ -103,17 +103,6 @@ void HeaderPathFilter::filterHeaderPath(const ProjectExplorer::HeaderPath &heade
namespace {
-FilePath clangIncludeDirectory(const QString &clangVersion, const FilePath &clangFallbackIncludeDir)
-{
-#ifndef UNIT_TESTS
- return Core::ICore::clangIncludeDirectory(clangVersion, clangFallbackIncludeDir);
-#else
- Q_UNUSED(clangVersion)
- Q_UNUSED(clangFallbackIncludeDir)
- return {CLANG_INCLUDE_DIR};
-#endif
-}
-
HeaderPaths::iterator resourceIterator(HeaderPaths &headerPaths)
{
// include/c++, include/g++, libc++\include and libc++abi\include
@@ -156,11 +145,8 @@ void HeaderPathFilter::tweakHeaderPaths()
auto split = resourceIterator(builtInHeaderPaths);
- if (!clangVersion.isEmpty()) {
- const FilePath clangIncludePath
- = clangIncludeDirectory(clangVersion, clangFallbackIncludeDirectory);
- builtInHeaderPaths.insert(split, HeaderPath::makeBuiltIn(clangIncludePath));
- }
+ if (!clangIncludeDirectory.isEmpty())
+ builtInHeaderPaths.insert(split, HeaderPath::makeBuiltIn(clangIncludeDirectory));
}
void HeaderPathFilter::addPreIncludesPath()
diff --git a/src/plugins/cppeditor/headerpathfilter.h b/src/plugins/cppeditor/headerpathfilter.h
index 1fdef8b88d1..c6ebb6a7432 100644
--- a/src/plugins/cppeditor/headerpathfilter.h
+++ b/src/plugins/cppeditor/headerpathfilter.h
@@ -37,13 +37,11 @@ class HeaderPathFilter
public:
HeaderPathFilter(const ProjectPart &projectPart,
UseTweakedHeaderPaths useTweakedHeaderPaths = UseTweakedHeaderPaths::Yes,
- const QString &clangVersion = {},
const Utils::FilePath &clangIncludeDirectory = {},
const QString &projectDirectory = {},
const QString &buildDirectory = {})
: projectPart{projectPart}
- , clangVersion{clangVersion}
- , clangFallbackIncludeDirectory{clangIncludeDirectory}
+ , clangIncludeDirectory{clangIncludeDirectory}
, projectDirectory(ensurePathWithSlashEnding(projectDirectory))
, buildDirectory(ensurePathWithSlashEnding(buildDirectory))
, useTweakedHeaderPaths{useTweakedHeaderPaths}
@@ -69,8 +67,7 @@ public:
ProjectExplorer::HeaderPaths systemHeaderPaths;
ProjectExplorer::HeaderPaths userHeaderPaths;
const ProjectPart &projectPart;
- const QString clangVersion;
- const Utils::FilePath clangFallbackIncludeDirectory;
+ const Utils::FilePath clangIncludeDirectory;
const QString projectDirectory;
const QString buildDirectory;
const UseTweakedHeaderPaths useTweakedHeaderPaths;
diff --git a/src/plugins/cppeditor/includeutils.cpp b/src/plugins/cppeditor/includeutils.cpp
index f6789394987..eb9fcab1668 100644
--- a/src/plugins/cppeditor/includeutils.cpp
+++ b/src/plugins/cppeditor/includeutils.cpp
@@ -139,7 +139,7 @@ LineForNewIncludeDirective::LineForNewIncludeDirective(const QTextDocument *text
// Ignore *.moc includes if requested
if (mocIncludeMode == IgnoreMocIncludes) {
- foreach (const Document::Include &include, includes) {
+ for (const Document::Include &include : qAsConst(includes)) {
if (!include.unresolvedFileName().endsWith(QLatin1String(".moc")))
m_includes << include;
}
@@ -179,7 +179,7 @@ int LineForNewIncludeDirective::findInsertLineForVeryFirstInclude(unsigned *newL
const QByteArray includeGuardMacroName = m_cppDocument->includeGuardMacroName();
if (!includeGuardMacroName.isEmpty()) {
const QList<Macro> definedMacros = m_cppDocument->definedMacros();
- foreach (const Macro &definedMacro, definedMacros) {
+ for (const Macro &definedMacro : definedMacros) {
if (definedMacro.name() == includeGuardMacroName) {
if (newLinesToPrepend)
*newLinesToPrepend = 1;
@@ -256,7 +256,7 @@ int LineForNewIncludeDirective::operator()(const QString &newIncludeFileName,
IncludeGroups groupsSameIncludeDir;
IncludeGroups groupsMixedIncludeDirs;
- foreach (const IncludeGroup &group, groupsMatchingIncludeType) {
+ for (const IncludeGroup &group : qAsConst(groupsMatchingIncludeType)) {
if (group.hasCommonIncludeDir())
groupsSameIncludeDir << group;
else
@@ -264,7 +264,7 @@ int LineForNewIncludeDirective::operator()(const QString &newIncludeFileName,
}
IncludeGroups groupsMatchingIncludeDir;
- foreach (const IncludeGroup &group, groupsSameIncludeDir) {
+ for (const IncludeGroup &group : qAsConst(groupsSameIncludeDir)) {
if (group.commonIncludeDir() == includeDir(pureIncludeFileName))
groupsMatchingIncludeDir << group;
}
@@ -274,7 +274,7 @@ int LineForNewIncludeDirective::operator()(const QString &newIncludeFileName,
if (!groupsMatchingIncludeDir.isEmpty()) {
// The group with the longest common matching prefix is the best group
int longestPrefixSoFar = 0;
- foreach (const IncludeGroup &group, groupsMatchingIncludeDir) {
+ for (const IncludeGroup &group : qAsConst(groupsMatchingIncludeDir)) {
const int groupPrefixLength = group.commonPrefix().length();
if (groupPrefixLength >= longestPrefixSoFar) {
bestGroup = group;
@@ -295,12 +295,12 @@ int LineForNewIncludeDirective::operator()(const QString &newIncludeFileName,
// group with mixed include dirs
} else {
IncludeGroups groupsIncludeDir;
- foreach (const IncludeGroup &group, groupsMixedIncludeDirs) {
+ for (const IncludeGroup &group : qAsConst(groupsMixedIncludeDirs)) {
groupsIncludeDir.append(
IncludeGroup::detectIncludeGroupsByIncludeDir(group.includes()));
}
IncludeGroup localBestIncludeGroup = IncludeGroup(QList<Include>());
- foreach (const IncludeGroup &group, groupsIncludeDir) {
+ for (const IncludeGroup &group : qAsConst(groupsIncludeDir)) {
if (group.commonIncludeDir() == includeDir(pureIncludeFileName))
localBestIncludeGroup = group;
}
@@ -330,7 +330,7 @@ QList<IncludeGroup> IncludeGroup::detectIncludeGroupsByNewLines(QList<Document::
int lastLine = 0;
QList<Include> currentIncludes;
bool isFirst = true;
- foreach (const Include &include, includes) {
+ for (const Include &include : qAsConst(includes)) {
// First include...
if (isFirst) {
isFirst = false;
@@ -361,7 +361,7 @@ QList<IncludeGroup> IncludeGroup::detectIncludeGroupsByIncludeDir(const QList<In
QString lastDir;
QList<Include> currentIncludes;
bool isFirst = true;
- foreach (const Include &include, includes) {
+ for (const Include &include : includes) {
const QString currentDirPrefix = includeDir(include.unresolvedFileName());
// First include...
@@ -394,7 +394,7 @@ QList<IncludeGroup> IncludeGroup::detectIncludeGroupsByIncludeType(const QList<I
Client::IncludeType lastIncludeType = Client::IncludeLocal;
QList<Include> currentIncludes;
bool isFirst = true;
- foreach (const Include &include, includes) {
+ for (const Include &include : includes) {
const Client::IncludeType currentIncludeType = include.type();
// First include...
@@ -425,7 +425,7 @@ QList<IncludeGroup> IncludeGroup::filterIncludeGroups(const QList<IncludeGroup>
Client::IncludeType includeType)
{
QList<IncludeGroup> result;
- foreach (const IncludeGroup &group, groups) {
+ for (const IncludeGroup &group : groups) {
if (group.hasOnlyIncludesOfType(includeType))
result << group;
}
@@ -436,7 +436,7 @@ QList<IncludeGroup> IncludeGroup::filterIncludeGroups(const QList<IncludeGroup>
QList<IncludeGroup> IncludeGroup::filterMixedIncludeGroups(const QList<IncludeGroup> &groups)
{
QList<IncludeGroup> result;
- foreach (const IncludeGroup &group, groups) {
+ for (const IncludeGroup &group : groups) {
if (!group.hasOnlyIncludesOfType(Client::IncludeLocal)
&& !group.hasOnlyIncludesOfType(Client::IncludeGlobal)) {
result << group;
@@ -447,7 +447,7 @@ QList<IncludeGroup> IncludeGroup::filterMixedIncludeGroups(const QList<IncludeGr
bool IncludeGroup::hasOnlyIncludesOfType(Client::IncludeType includeType) const
{
- foreach (const Include &include, m_includes) {
+ for (const Include &include : qAsConst(m_includes)) {
if (include.type() != includeType)
return false;
}
@@ -490,7 +490,7 @@ int IncludeGroup::lineForNewInclude(const QString &newIncludeFileName,
QStringList IncludeGroup::filesNames() const
{
QStringList names;
- foreach (const Include &include, m_includes)
+ for (const Include &include : qAsConst(m_includes))
names << include.unresolvedFileName();
return names;
}
diff --git a/src/plugins/cppeditor/indexitem.h b/src/plugins/cppeditor/indexitem.h
index f4e88a1db7c..0bb8cd8ecbb 100644
--- a/src/plugins/cppeditor/indexitem.h
+++ b/src/plugins/cppeditor/indexitem.h
@@ -99,7 +99,7 @@ public:
VisitorResult visitAllChildren(Visitor callback) const
{
VisitorResult result = Recurse;
- foreach (const IndexItem::Ptr &child, m_children) {
+ for (const IndexItem::Ptr &child : qAsConst(m_children)) {
result = callback(child);
switch (result) {
case Break:
diff --git a/src/plugins/cppeditor/insertionpointlocator.cpp b/src/plugins/cppeditor/insertionpointlocator.cpp
index fceb9a96055..00a4747bc06 100644
--- a/src/plugins/cppeditor/insertionpointlocator.cpp
+++ b/src/plugins/cppeditor/insertionpointlocator.cpp
@@ -445,8 +445,8 @@ public:
_bestToken.maybeSet(-1, lastToken);
if (lastToken >= 2) {
- QList<const Name *> names = LookupContext::fullyQualifiedName(decl);
- foreach (const Name *name, names) {
+ const QList<const Name *> names = LookupContext::fullyQualifiedName(decl);
+ for (const Name *name : names) {
const Identifier *id = name->asNameId();
if (!id)
break;
diff --git a/src/plugins/cppeditor/projectinfo_test.cpp b/src/plugins/cppeditor/projectinfo_test.cpp
index 825bd88b423..d5bc473838f 100644
--- a/src/plugins/cppeditor/projectinfo_test.cpp
+++ b/src/plugins/cppeditor/projectinfo_test.cpp
@@ -511,7 +511,7 @@ public:
tcInfo.targetTriple = targetTriple;
tcInfo.installDir = toolchainInstallDir;
projectPart = ProjectPart::create({}, rpp, {}, {}, {}, {}, {}, tcInfo);
- filter.emplace(HeaderPathFilter(*projectPart, UseTweakedHeaderPaths::No, {}, {},
+ filter.emplace(HeaderPathFilter(*projectPart, UseTweakedHeaderPaths::No, {},
"/project", "/build"));
return *projectPart;
}
@@ -602,7 +602,7 @@ void HeaderPathFilterTest::testDontAddInvalidPath()
void HeaderPathFilterTest::testClangHeadersPath()
{
HeaderPathFilterTestHelper t;
- HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "clang_dir");
filter.process();
QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("clang_dir"),
@@ -631,7 +631,7 @@ void HeaderPathFilterTest::testClangHeadersAndCppIncludesPathsOrderMacOs()
};
std::copy(builtIns.begin(), builtIns.end(),
std::inserter(t.headerPaths, t.headerPaths.begin()));
- HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "clang_dir");
filter.process();
QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{
@@ -653,7 +653,7 @@ void HeaderPathFilterTest::testClangHeadersAndCppIncludesPathsOrderLinux()
t.builtIn("/usr/include/x86_64-linux-gnu"), t.builtIn("/usr/include")};
std::copy(builtIns.begin(), builtIns.end(),
std::inserter(t.headerPaths, t.headerPaths.begin()));
- HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "clang_dir");
filter.process();
QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{
@@ -675,7 +675,7 @@ void HeaderPathFilterTest::testRemoveGccInternalPaths()
t.builtIn("/usr/lib/gcc/x86_64-linux-gnu/7/include"),
t.builtIn("/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed"),
};
- HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "clang_dir");
filter.process();
QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("clang_dir")}));
@@ -697,7 +697,7 @@ void HeaderPathFilterTest::testRemoveGccInternalPathsExceptForStandardPaths()
HeaderPaths expected = t.headerPaths;
expected.append(t.builtIn("clang_dir"));
- HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "clang_dir");
filter.process();
QCOMPARE(filter.builtInHeaderPaths, expected);
@@ -713,7 +713,7 @@ void HeaderPathFilterTest::testClangHeadersAndCppIncludesPathsOrderNoVersion()
t.builtIn("C:/mingw/i686-w64-mingw32/include/c++/backward"),
};
t.targetTriple = "x86_64-w64-windows-gnu";
- HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "clang_dir");
filter.process();
QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{
@@ -735,7 +735,7 @@ void HeaderPathFilterTest::testClangHeadersAndCppIncludesPathsOrderAndroidClang(
t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include")
};
t.targetTriple = "i686-linux-android";
- HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "clang_dir");
filter.process();
QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{
diff --git a/src/plugins/cppeditor/refactoringengineinterface.h b/src/plugins/cppeditor/refactoringengineinterface.h
deleted file mode 100644
index b4068fd33b8..00000000000
--- a/src/plugins/cppeditor/refactoringengineinterface.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "cppeditor_global.h"
-#include "cursorineditor.h"
-#include "usages.h"
-
-#include <utils/link.h>
-#include <utils/fileutils.h>
-
-#include <cplusplus/CppDocument.h>
-
-namespace ClangBackEnd { class SourceLocationsContainer; }
-namespace TextEditor { class TextEditorWidget; }
-
-namespace CppEditor {
-
-class ProjectPart;
-class SymbolFinder;
-
-enum class CallType
-{
- Synchronous,
- Asynchronous
-};
-
-// NOTE: This interface is not supposed to be owned as an interface pointer
-class CPPEDITOR_EXPORT RefactoringEngineInterface
-{
-public:
- using RenameCallback = std::function<void(const QString &,
- const ClangBackEnd::SourceLocationsContainer &,
- int)>;
- using Link = Utils::Link;
-
- virtual ~RefactoringEngineInterface() = default;
-
- virtual void startLocalRenaming(const CursorInEditor &data,
- const ProjectPart *projectPart,
- RenameCallback &&renameSymbolsCallback) = 0;
- virtual void globalRename(const CursorInEditor &data,
- UsagesCallback &&renameCallback,
- const QString &replacement) = 0;
- virtual void findUsages(const CursorInEditor &data,
- UsagesCallback &&showUsagesCallback) const = 0;
- virtual void globalFollowSymbol(const CursorInEditor &data,
- Utils::ProcessLinkCallback &&processLinkCallback,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder,
- bool inNextSplit) const = 0;
- virtual bool isRefactoringEngineAvailable() const { return true; }
-};
-
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp
index 8ebb0339a8c..85e1b6e0157 100644
--- a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp
+++ b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp
@@ -32,12 +32,13 @@
#include <texteditor/texteditor.h>
#include <utils/executeondestruction.h>
#include <utils/fileutils.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h>
#include <QPoint>
#include <QTextBlock>
+#include <QXmlStreamReader>
using namespace Core;
using namespace TextEditor;
diff --git a/src/plugins/cppeditor/searchsymbols.cpp b/src/plugins/cppeditor/searchsymbols.cpp
index 0845eb40bc7..e3f86e945ea 100644
--- a/src/plugins/cppeditor/searchsymbols.cpp
+++ b/src/plugins/cppeditor/searchsymbols.cpp
@@ -267,9 +267,9 @@ QString SearchSymbols::scopeName(const QString &name, const Symbol *symbol) cons
if (!name.isEmpty())
return name;
- if (symbol->isNamespace()) {
+ if (symbol->asNamespace()) {
return QLatin1String("<anonymous namespace>");
- } else if (symbol->isEnum()) {
+ } else if (symbol->asEnum()) {
return QLatin1String("<anonymous enum>");
} else if (const Class *c = symbol->asClass()) {
if (c->isUnion())
diff --git a/src/plugins/cppeditor/semantichighlighter.cpp b/src/plugins/cppeditor/semantichighlighter.cpp
index d1e4e678257..503ba407ff7 100644
--- a/src/plugins/cppeditor/semantichighlighter.cpp
+++ b/src/plugins/cppeditor/semantichighlighter.cpp
@@ -328,7 +328,7 @@ void SemanticHighlighter::updateFormatMapFromFontSettings()
m_formatMap[EnumerationUse] = fs.toTextCharFormat(C_ENUMERATION);
m_formatMap[VirtualMethodUse] = fs.toTextCharFormat(C_VIRTUAL_METHOD);
m_formatMap[LabelUse] = fs.toTextCharFormat(C_LABEL);
- m_formatMap[MacroUse] = fs.toTextCharFormat(C_PREPROCESSOR);
+ m_formatMap[MacroUse] = fs.toTextCharFormat(C_MACRO);
m_formatMap[FunctionUse] = fs.toTextCharFormat(C_FUNCTION);
m_formatMap[FunctionDeclarationUse] =
fs.toTextCharFormat(TextStyles::mixinStyle(C_FUNCTION, C_DECLARATION));
diff --git a/src/plugins/cppeditor/symbolfinder.cpp b/src/plugins/cppeditor/symbolfinder.cpp
index e91ac0035ad..f9da3591de7 100644
--- a/src/plugins/cppeditor/symbolfinder.cpp
+++ b/src/plugins/cppeditor/symbolfinder.cpp
@@ -172,7 +172,8 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration,
}
Hit best;
- foreach (const QString &fileName, fileIterationOrder(declFile, snapshot)) {
+ const QStringList fileNames = fileIterationOrder(declFile, snapshot);
+ for (const QString &fileName : fileNames) {
Document::Ptr doc = snapshot.document(fileName);
if (!doc) {
clearCache(declFile, fileName);
@@ -251,7 +252,8 @@ Symbol *SymbolFinder::findMatchingVarDefinition(Symbol *declaration, const Snaps
using SymbolWithPriority = QPair<Symbol *, bool>;
QList<SymbolWithPriority> candidates;
QList<SymbolWithPriority> fallbacks;
- foreach (const QString &fileName, fileIterationOrder(declFile, snapshot)) {
+ const QStringList fileNames = fileIterationOrder(declFile, snapshot);
+ for (const QString &fileName : fileNames) {
Document::Ptr doc = snapshot.document(fileName);
if (!doc) {
clearCache(declFile, fileName);
@@ -320,7 +322,8 @@ Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Sna
QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength());
- foreach (const QString &file, fileIterationOrder(declFile, snapshot)) {
+ const QStringList fileNames = fileIterationOrder(declFile, snapshot);
+ for (const QString &file : fileNames) {
Document::Ptr doc = snapshot.document(file);
if (!doc) {
clearCache(declFile, file);
@@ -337,7 +340,8 @@ Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Sna
if (!type)
continue;
- foreach (Symbol *s, type->symbols()) {
+ const QList<Symbol *> symbols = type->symbols();
+ for (Symbol *s : symbols) {
if (Class *c = s->asClass())
return c;
}
@@ -374,7 +378,7 @@ void SymbolFinder::findMatchingDeclaration(const LookupContext &context,
return;
Scope *enclosingScope = functionType->enclosingScope();
- while (!(enclosingScope->isNamespace() || enclosingScope->isClass()))
+ while (!(enclosingScope->asNamespace() || enclosingScope->asClass()))
enclosingScope = enclosingScope->enclosingScope();
QTC_ASSERT(enclosingScope != nullptr, return);
@@ -411,7 +415,8 @@ void SymbolFinder::findMatchingDeclaration(const LookupContext &context,
operatorNameId = onid->kind();
}
- foreach (Symbol *s, binding->symbols()) {
+ const QList<Symbol *> symbols = binding->symbols();
+ for (Symbol *s : symbols) {
Scope *scope = s->asScope();
if (!scope)
continue;
@@ -446,9 +451,9 @@ QList<Declaration *> SymbolFinder::findMatchingDeclaration(const LookupContext &
// For member functions not defined inline, add fuzzy matches as fallbacks. We cannot do
// this for free functions, because there is no guarantee that there's a separate declaration.
QList<Declaration *> fuzzyMatches = argumentCountMatch + nameMatch;
- if (!functionType->enclosingScope() || !functionType->enclosingScope()->isClass()) {
+ if (!functionType->enclosingScope() || !functionType->enclosingScope()->asClass()) {
for (Declaration * const d : fuzzyMatches) {
- if (d->enclosingScope() && d->enclosingScope()->isClass())
+ if (d->enclosingScope() && d->enclosingScope()->asClass())
result.append(d);
}
}
@@ -460,7 +465,7 @@ QStringList SymbolFinder::fileIterationOrder(const QString &referenceFile, const
if (m_filePriorityCache.contains(referenceFile)) {
checkCacheConsistency(referenceFile, snapshot);
} else {
- foreach (Document::Ptr doc, snapshot)
+ for (Document::Ptr doc : snapshot)
insertCache(referenceFile, doc->fileName());
}
@@ -484,7 +489,7 @@ void SymbolFinder::checkCacheConsistency(const QString &referenceFile, const Sna
// The counterpart validation for "old" files is done when one tries to access the
// corresponding document and notices it's now null.
const QSet<QString> &meta = m_fileMetaCache.value(referenceFile);
- foreach (const Document::Ptr &doc, snapshot) {
+ for (const Document::Ptr &doc : snapshot) {
if (!meta.contains(doc->fileName()))
insertCache(referenceFile, doc->fileName());
}
diff --git a/src/plugins/cppeditor/typehierarchybuilder.cpp b/src/plugins/cppeditor/typehierarchybuilder.cpp
index caaf849aeca..06b8ec0bb5e 100644
--- a/src/plugins/cppeditor/typehierarchybuilder.cpp
+++ b/src/plugins/cppeditor/typehierarchybuilder.cpp
@@ -159,7 +159,7 @@ LookupItem TypeHierarchyBuilder::followTypedef(const LookupContext &context, con
Symbol *s = item.declaration();
if (!s)
continue;
- if (!s->isClass() && !s->isTemplate() && !s->isTypedef())
+ if (!s->asClass() && !s->asTemplate() && !s->isTypedef())
continue;
if (!typedefs.insert(s).second)
continue;
diff --git a/src/plugins/cppeditor/typehierarchybuilder_test.cpp b/src/plugins/cppeditor/typehierarchybuilder_test.cpp
index 3c48dc8bd98..556b93e0988 100644
--- a/src/plugins/cppeditor/typehierarchybuilder_test.cpp
+++ b/src/plugins/cppeditor/typehierarchybuilder_test.cpp
@@ -56,7 +56,7 @@ QString toString(const TypeHierarchy &hierarchy, int indent = 0)
Utils::sort(sortedHierarchy, [&oo](const TypeHierarchy &h1, const TypeHierarchy &h2) -> bool {
return oo.prettyName(h1.symbol()->name()) < oo.prettyName(h2.symbol()->name());
});
- foreach (TypeHierarchy childHierarchy, sortedHierarchy)
+ for (const TypeHierarchy &childHierarchy : qAsConst(sortedHierarchy))
result += toString(childHierarchy, indent + 2);
return result;
}
diff --git a/src/plugins/cppeditor/usages.h b/src/plugins/cppeditor/usages.h
deleted file mode 100644
index 684b571efce..00000000000
--- a/src/plugins/cppeditor/usages.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/smallstringview.h>
-
-#include <QString>
-
-#include <vector>
-#include <functional>
-
-namespace CppEditor {
-
-class Usage
-{
-public:
- Usage() = default;
- Usage(Utils::SmallStringView path, int line, int column)
- : path(QString::fromUtf8(path.data(), int(path.size()))),
- line(line),
- column(column)
- {}
-
- friend bool operator==(const Usage &first, const Usage &second)
- {
- return first.line == second.line
- && first.column == second.column
- && first.path == second.path;
- }
-
- friend bool operator<(const Usage &first, const Usage &second)
- {
- return std::tie(first.path, first.line, first.column)
- < std::tie(second.path, second.line, second.column);
- }
-
-public:
- QString path;
- int line = 0;
- int column = 0;
-};
-
-using Usages = std::vector<Usage>;
-using UsagesCallback = std::function<void(const Usages &usages)>;
-
-} // namespace CppEditor
diff --git a/src/plugins/cvs/CMakeLists.txt b/src/plugins/cvs/CMakeLists.txt
index 2612f9a795a..47c91f8a720 100644
--- a/src/plugins/cvs/CMakeLists.txt
+++ b/src/plugins/cvs/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(CVS
+ PLUGIN_CLASS CvsPlugin
PLUGIN_DEPENDS Core TextEditor VcsBase
SOURCES
annotationhighlighter.cpp annotationhighlighter.h
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index b619c493f32..e004f6cd886 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -42,11 +42,6 @@
#include <texteditor/textdocument.h>
-#include <utils/parameteraction.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-#include <utils/stringutils.h>
-
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
@@ -58,18 +53,23 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/locator/commandlocator.h>
#include <coreplugin/vcsmanager.h>
+
+#include <utils/environment.h>
#include <utils/fileutils.h>
+#include <utils/parameteraction.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
-#include <QDebug>
+#include <QAction>
#include <QDate>
+#include <QDebug>
#include <QDir>
#include <QFileInfo>
-#include <QTextCodec>
-#include <QAction>
#include <QMainWindow>
#include <QMenu>
#include <QMessageBox>
+#include <QTextCodec>
#ifdef WITH_TESTS
#include <QTest>
@@ -181,7 +181,7 @@ public:
QStringList arguments() const override
{
- QStringList args = m_settings.diffOptions.value().split(' ', SkipEmptyParts);
+ QStringList args = m_settings.diffOptions.value().split(' ', Qt::SkipEmptyParts);
args += VcsBaseEditorConfig::arguments();
return args;
}
@@ -204,8 +204,8 @@ public:
{
if (cmd == DiffCommand) {
return [](int code) {
- return (code < 0 || code > 2) ? QtcProcess::FinishedWithError
- : QtcProcess::FinishedWithSuccess;
+ return (code < 0 || code > 2) ? ProcessResult::FinishedWithError
+ : ProcessResult::FinishedWithSuccess;
};
}
return {};
@@ -1449,18 +1449,18 @@ CvsResponse CvsPluginPrivate::runCvs(const FilePath &workingDirectory,
command.runCommand(proc, {executable, m_settings.addOptions(arguments)});
response.result = CvsResponse::OtherError;
- response.stdErr = proc.stdErr();
- response.stdOut = proc.stdOut();
+ response.stdErr = proc.cleanedStdErr();
+ response.stdOut = proc.cleanedStdOut();
switch (proc.result()) {
- case QtcProcess::FinishedWithSuccess:
+ case ProcessResult::FinishedWithSuccess:
response.result = CvsResponse::Ok;
break;
- case QtcProcess::FinishedWithError:
+ case ProcessResult::FinishedWithError:
response.result = CvsResponse::NonNullExitCode;
break;
- case QtcProcess::TerminatedAbnormally:
- case QtcProcess::StartFailed:
- case QtcProcess::Hang:
+ case ProcessResult::TerminatedAbnormally:
+ case ProcessResult::StartFailed:
+ case ProcessResult::Hang:
break;
}
diff --git a/src/plugins/cvs/cvssettings.cpp b/src/plugins/cvs/cvssettings.cpp
index 7ec116d79bf..a84764ee49a 100644
--- a/src/plugins/cvs/cvssettings.cpp
+++ b/src/plugins/cvs/cvssettings.cpp
@@ -27,6 +27,7 @@
#include <coreplugin/icore.h>
+#include <utils/hostosinfo.h>
#include <utils/layoutbuilder.h>
#include <utils/pathchooser.h>
diff --git a/src/plugins/debugger/CMakeLists.txt b/src/plugins/debugger/CMakeLists.txt
index 4d7830dcd4f..aeefdec4bb6 100644
--- a/src/plugins/debugger/CMakeLists.txt
+++ b/src/plugins/debugger/CMakeLists.txt
@@ -1,5 +1,5 @@
add_qtc_plugin(Debugger
- DEPENDS LanguageUtils QmlDebug QmlJS QtcSsh registryaccess
+ DEPENDS LanguageUtils QmlDebug QmlJS registryaccess
PLUGIN_DEPENDS Core CppEditor ProjectExplorer QtSupport TextEditor
PLUGIN_RECOMMENDS QmakeProjectManager
PLUGIN_TEST_DEPENDS QmakeProjectManager
diff --git a/src/plugins/debugger/analyzer/detailederrorview.cpp b/src/plugins/debugger/analyzer/detailederrorview.cpp
index a5fad37821f..b1ac155afb2 100644
--- a/src/plugins/debugger/analyzer/detailederrorview.cpp
+++ b/src/plugins/debugger/analyzer/detailederrorview.cpp
@@ -30,12 +30,12 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
#include <utils/utilsicons.h>
+#include <QApplication>
#include <QAbstractTextDocumentLayout>
#include <QAction>
-#include <QApplication>
-#include <QClipboard>
#include <QContextMenuEvent>
#include <QFileInfo>
#include <QHeaderView>
@@ -54,12 +54,12 @@ DetailedErrorView::DetailedErrorView(QWidget *parent) :
m_copyAction->setIcon(Utils::Icons::COPY.icon());
m_copyAction->setShortcut(QKeySequence::Copy);
m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
- connect(m_copyAction, &QAction::triggered, [this] {
+ connect(m_copyAction, &QAction::triggered, this, [this] {
const QModelIndexList selectedRows = selectionModel()->selectedRows();
QStringList data;
for (const QModelIndex &index : selectedRows)
data << model()->data(index, FullTextRole).toString();
- QApplication::clipboard()->setText(data.join('\n'));
+ Utils::setClipboardAndSelection(data.join('\n'));
});
connect(this, &QAbstractItemView::clicked, [](const QModelIndex &index) {
if (index.column() == LocationColumn) {
diff --git a/src/plugins/debugger/analyzer/startremotedialog.cpp b/src/plugins/debugger/analyzer/startremotedialog.cpp
index c5762013ae6..9f96ab89a2a 100644
--- a/src/plugins/debugger/analyzer/startremotedialog.cpp
+++ b/src/plugins/debugger/analyzer/startremotedialog.cpp
@@ -26,10 +26,12 @@
#include "startremotedialog.h"
#include <coreplugin/icore.h>
+
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <projectexplorer/kitchooser.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/runcontrol.h>
-#include <ssh/sshconnection.h>
#include <QDialogButtonBox>
#include <QFormLayout>
@@ -127,14 +129,16 @@ void StartRemoteDialog::validate()
d->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
}
-Runnable StartRemoteDialog::runnable() const
+CommandLine StartRemoteDialog::commandLine() const
+{
+ const Kit *kit = d->kitChooser->currentKit();
+ const FilePath filePath = DeviceKitAspect::deviceFilePath(kit, d->executable->text());
+ return {filePath, d->arguments->text(), CommandLine::Raw};
+}
+
+FilePath StartRemoteDialog::workingDirectory() const
{
- Kit *kit = d->kitChooser->currentKit();
- Runnable r;
- r.device = DeviceKitAspect::device(kit);
- r.command = {FilePath::fromString(d->executable->text()), d->arguments->text(), CommandLine::Raw};
- r.workingDirectory = FilePath::fromString(d->workingDirectory->text());
- return r;
+ return FilePath::fromString(d->workingDirectory->text());
}
} // namespace Debugger
diff --git a/src/plugins/debugger/analyzer/startremotedialog.h b/src/plugins/debugger/analyzer/startremotedialog.h
index b1b91bc62fd..72d7478fb7d 100644
--- a/src/plugins/debugger/analyzer/startremotedialog.h
+++ b/src/plugins/debugger/analyzer/startremotedialog.h
@@ -29,7 +29,10 @@
#include <QDialog>
-namespace ProjectExplorer { class Runnable; }
+namespace Utils {
+class CommandLine;
+class FilePath;
+} // Utils
namespace Debugger {
@@ -43,7 +46,8 @@ public:
explicit StartRemoteDialog(QWidget *parent = nullptr);
~StartRemoteDialog() override;
- ProjectExplorer::Runnable runnable() const;
+ Utils::CommandLine commandLine() const;
+ Utils::FilePath workingDirectory() const;
private:
void validate();
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index 0b577eb6e57..a075c324bb2 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -45,6 +45,7 @@
#include <texteditor/textmark.h>
#include <texteditor/texteditor.h>
+#include <utils/algorithm.h>
#include <utils/basetreeview.h>
#include <utils/checkablemessagebox.h>
#include <utils/fileutils.h>
diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h
index d4afbef62d8..91e3d066d9d 100644
--- a/src/plugins/debugger/breakpoint.h
+++ b/src/plugins/debugger/breakpoint.h
@@ -28,7 +28,7 @@
#include <QMetaType>
#include <QString>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
namespace Debugger {
namespace Internal {
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 520a2cb44f1..8474f6665c1 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -56,6 +56,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
+#include <projectexplorer/abi.h>
#include <projectexplorer/taskhub.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtversionmanager.h>
@@ -65,6 +66,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
+#include <utils/processinterface.h>
#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <utils/winutils.h>
@@ -182,9 +184,11 @@ void addCdbOptionPages(QList<Core::IOptionsPage *> *opts)
CdbEngine::CdbEngine() :
m_tokenPrefix("<token>"),
- m_process(ProcessMode::Writer),
m_extensionCommandPrefix("!" QT_CREATOR_CDB_EXT ".")
{
+ m_process.setProcessMode(ProcessMode::Writer);
+ m_process.setUseCtrlCStub(true);
+
setObjectName("CdbEngine");
setDebuggerName("CDB");
@@ -208,8 +212,8 @@ CdbEngine::CdbEngine() :
DebuggerSettings *s = debuggerSettings();
connect(s->createFullBacktrace.action(), &QAction::triggered,
this, &CdbEngine::createFullBacktrace);
- connect(&m_process, &QtcProcess::finished, this, &CdbEngine::processFinished);
- connect(&m_process, &QtcProcess::errorOccurred, this, &CdbEngine::processError);
+ connect(&m_process, &QtcProcess::started, this, &CdbEngine::processStarted);
+ connect(&m_process, &QtcProcess::done, this, &CdbEngine::processDone);
connect(&m_process, &QtcProcess::readyReadStandardOutput,
this, &CdbEngine::readyReadStandardOut);
connect(&m_process, &QtcProcess::readyReadStandardError,
@@ -264,7 +268,7 @@ void CdbEngine::init()
}
// update source path maps from debugger start params
mergeStartParametersSourcePathMap();
- QTC_ASSERT(m_process.state() != QProcess::Running, m_process.stopProcess());
+ QTC_ASSERT(m_process.state() != QProcess::Running, m_process.stop());
}
CdbEngine::~CdbEngine() = default;
@@ -288,14 +292,13 @@ bool CdbEngine::canHandleToolTip(const DebuggerToolTipContext &context) const
}
// Determine full path to the CDB extension library.
-QString CdbEngine::extensionLibraryName(bool is64Bit)
+QString CdbEngine::extensionLibraryName(bool is64Bit, bool isArm)
{
// Determine extension lib name and path to use
- QString rc;
- QTextStream(&rc) << QFileInfo(QCoreApplication::applicationDirPath()).path()
- << "/lib/" << (is64Bit ? QT_CREATOR_CDB_EXT "64" : QT_CREATOR_CDB_EXT "32")
- << '/' << QT_CREATOR_CDB_EXT << ".dll";
- return rc;
+ return QString("%1/lib/" QT_CREATOR_CDB_EXT "%2%3/" QT_CREATOR_CDB_EXT ".dll")
+ .arg(QFileInfo(QCoreApplication::applicationDirPath()).path())
+ .arg(isArm ? "arm" : QString())
+ .arg(is64Bit ? QLatin1String("64") : QLatin1String("32"));
}
int CdbEngine::elapsedLogTime()
@@ -351,10 +354,17 @@ void CdbEngine::setupEngine()
return;
}
- bool cdbIs64Bit = Utils::is64BitWindowsBinary(sp.debugger.command.executable());
- if (!cdbIs64Bit)
+ bool cdbIs64Bit = true;
+ bool cdbIsArm = false;
+ Abis abisOfCdb = Abi::abisOfBinary(sp.debugger.command.executable());
+ if (abisOfCdb.size() == 1) {
+ Abi abi = abisOfCdb.at(0);
+ cdbIs64Bit = abi.wordWidth() == 64;
+ cdbIsArm = abi.architecture() == Abi::Architecture::ArmArchitecture;
+ }
+ if (!cdbIs64Bit || cdbIsArm)
m_wow64State = noWow64Stack;
- const QFileInfo extensionFi(CdbEngine::extensionLibraryName(cdbIs64Bit));
+ const QFileInfo extensionFi(CdbEngine::extensionLibraryName(cdbIs64Bit, cdbIsArm));
if (!extensionFi.isFile()) {
handleSetupFailure(tr("Internal error: The extension %1 cannot be found.\n"
"If you have updated %2 via Maintenance Tool, you may "
@@ -373,12 +383,12 @@ void CdbEngine::setupEngine()
// Prepare command line.
CommandLine debugger{sp.debugger.command};
- const QString extensionFileName = extensionFi.fileName();
+ m_extensionFileName = extensionFi.fileName();
const bool isRemote = sp.startMode == AttachToRemoteServer;
if (isRemote) { // Must be first
debugger.addArgs({"-remote", sp.remoteChannel});
} else {
- debugger.addArg("-a" + extensionFileName);
+ debugger.addArg("-a" + m_extensionFileName);
}
// Source line info/No terminal breakpoint / Pull extension
@@ -437,8 +447,8 @@ void CdbEngine::setupEngine()
m_outputBuffer.clear();
m_autoBreakPointCorrection = false;
- Utils::Environment inferiorEnvironment = sp.inferior.environment.size() == 0
- ? Utils::Environment::systemEnvironment() : sp.inferior.environment;
+ Environment inferiorEnvironment = sp.inferior.environment.isValid()
+ ? sp.inferior.environment : Environment::systemEnvironment();
// Make sure that QTestLib uses OutputDebugString for logging.
const QString qtLoggingToConsoleKey = QStringLiteral("QT_LOGGING_TO_CONSOLE");
@@ -460,20 +470,19 @@ void CdbEngine::setupEngine()
m_process.setCommand(debugger);
m_process.start();
- if (!m_process.waitForStarted()) {
- handleSetupFailure(QString("Internal error: Cannot start process %1: %2").
- arg(debugger.toUserOutput(), m_process.errorString()));
- return;
- }
+}
+void CdbEngine::processStarted()
+{
const qint64 pid = m_process.processId();
- showMessage(QString("%1 running as %2").arg(debugger.executable().toUserOutput()).arg(pid),
- LogMisc);
+ const FilePath execPath = runParameters().debugger.command.executable();
+ showMessage(QString("%1 running as %2").arg(execPath.toUserOutput()).arg(pid), LogMisc);
m_hasDebuggee = true;
m_initialSessionIdleHandled = false;
- if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible
+ if (runParameters().startMode == AttachToRemoteServer) {
+ // We do not get an 'idle' in a remote session, but are accessible
m_accessible = true;
- runCommand({".load " + extensionFileName, NoFlags});
+ runCommand({".load " + m_extensionFileName, NoFlags});
handleInitialSessionIdle();
}
}
@@ -690,7 +699,7 @@ void CdbEngine::shutdownEngine()
}
} else {
// Remote process. No can do, currently
- m_process.stopProcess();
+ m_process.stop();
}
}
@@ -699,14 +708,23 @@ void CdbEngine::abortDebuggerProcess()
m_process.kill();
}
-void CdbEngine::processFinished()
+void CdbEngine::processDone()
{
- if (debug)
+ if (m_process.result() == ProcessResult::StartFailed) {
+ handleSetupFailure(m_process.exitMessage());
+ return;
+ }
+
+ if (m_process.error() != QProcess::UnknownError)
+ showMessage(m_process.errorString(), LogError);
+
+ if (debug) {
qDebug("CdbEngine::processFinished %dms '%s' (exit state=%d, ex=%d)",
elapsedLogTime(), qPrintable(stateName(state())),
m_process.exitStatus(), m_process.exitCode());
+ }
- notifyDebuggerProcessFinished(m_process.exitCode(), m_process.exitStatus(), "CDB");
+ notifyDebuggerProcessFinished(m_process.resultData(), "CDB");
}
void CdbEngine::detachDebugger()
@@ -787,32 +805,9 @@ void CdbEngine::interruptInferior()
if (debug)
qDebug() << "CdbEngine::interruptInferior()" << stateName(state());
- if (!canInterruptInferior()) {
- // Restore running state if inferior can't be stoped.
- showMessage(tr("Interrupting is not possible in remote sessions."), LogError);
- STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorStopOk")
- notifyInferiorStopOk();
- STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
- notifyInferiorRunRequested();
- STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunOk")
- notifyInferiorRunOk();
- return;
- }
doInterruptInferior();
}
-void CdbEngine::handleDoInterruptInferior(const QString &errorMessage)
-{
- if (errorMessage.isEmpty()) {
- showMessage("Interrupted " + QString::number(inferiorPid()));
- } else {
- showMessage(errorMessage, LogError);
- notifyInferiorStopFailed();
- }
- m_signalOperation->disconnect(this);
- m_signalOperation.clear();
-}
-
void CdbEngine::doInterruptInferior(const InterruptCallback &callback)
{
const bool requestInterrupt = m_stopMode == NoStopRequested;
@@ -829,15 +824,7 @@ void CdbEngine::doInterruptInferior(const InterruptCallback &callback)
if (!requestInterrupt)
return; // we already requested a stop no need to interrupt twice
showMessage(QString("Interrupting process %1...").arg(inferiorPid()), LogMisc);
- QTC_ASSERT(!m_signalOperation, notifyInferiorStopFailed(); return);
- QTC_ASSERT(device(), notifyInferiorRunFailed(); return);
- m_signalOperation = device()->signalOperation();
- QTC_ASSERT(m_signalOperation, notifyInferiorStopFailed(); return;);
- connect(m_signalOperation.data(), &DeviceProcessSignalOperation::finished,
- this, &CdbEngine::handleDoInterruptInferior);
-
- m_signalOperation->setDebuggerCommand(runParameters().debugger.command.executable());
- m_signalOperation->interruptProcess(inferiorPid());
+ m_process.interrupt();
}
void CdbEngine::executeRunToLine(const ContextData &data)
@@ -1036,7 +1023,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
QList<QStringView> splittedArguments;
int maxArgumentSize = maxCommandLength - prefix.length() - maxTokenLength;
while (argumentSplitPos < arguments.size()) {
- splittedArguments << Utils::midView(arguments, argumentSplitPos, maxArgumentSize);
+ splittedArguments << midView(arguments, argumentSplitPos, maxArgumentSize);
argumentSplitPos += splittedArguments.last().length();
}
QTC_CHECK(argumentSplitPos == arguments.size());
@@ -1059,7 +1046,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
qDebug("CdbEngine::postCommand: resulting command '%s'\n", qPrintable(fullCmd));
}
showMessage(cmd, LogInput);
- m_process.write(fullCmd.toLocal8Bit());
+ m_process.write(fullCmd);
}
void CdbEngine::activateFrame(int index)
@@ -2443,11 +2430,6 @@ void CdbEngine::readyReadStandardError()
showMessage(QString::fromLocal8Bit(m_process.readAllStandardError()), LogError);
}
-void CdbEngine::processError()
-{
- showMessage(m_process.errorString(), LogError);
-}
-
#if 0
// Join breakpoint ids for a multi-breakpoint id commands like 'bc', 'be', 'bd'
static QByteArray multiBreakpointCommand(const char *cmdC, const Breakpoints &bps)
@@ -2495,14 +2477,14 @@ public:
const CppEditor::WorkingCopy &workingCopy) :
m_snapshot(s), m_workingCopy(workingCopy) {}
- unsigned fixLineNumber(const Utils::FilePath &filePath, unsigned lineNumber) const;
+ unsigned fixLineNumber(const FilePath &filePath, unsigned lineNumber) const;
private:
const CPlusPlus::Snapshot m_snapshot;
CppEditor::WorkingCopy m_workingCopy;
};
-static CPlusPlus::Document::Ptr getParsedDocument(const Utils::FilePath &filePath,
+static CPlusPlus::Document::Ptr getParsedDocument(const FilePath &filePath,
const CppEditor::WorkingCopy &workingCopy,
const CPlusPlus::Snapshot &snapshot)
{
@@ -2517,7 +2499,7 @@ static CPlusPlus::Document::Ptr getParsedDocument(const Utils::FilePath &filePat
return doc;
}
-unsigned BreakpointCorrectionContext::fixLineNumber(const Utils::FilePath &filePath,
+unsigned BreakpointCorrectionContext::fixLineNumber(const FilePath &filePath,
unsigned lineNumber) const
{
const CPlusPlus::Document::Ptr doc = getParsedDocument(filePath,
@@ -2674,7 +2656,7 @@ static StackFrames parseFrames(const GdbMi &gdbmi, bool *incomplete = nullptr)
frame.level = QString::number(i);
const GdbMi fullName = frameMi["fullname"];
if (fullName.isValid()) {
- frame.file = Utils::FilePath::fromString(fullName.data()).normalizedPathName();
+ frame.file = FilePath::fromString(fullName.data()).normalizedPathName();
frame.line = frameMi["line"].data().toInt();
frame.usable = false; // To be decided after source path mapping.
const GdbMi languageMi = frameMi["language"];
diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h
index 6488605d09c..8dd3739dea0 100644
--- a/src/plugins/debugger/cdb/cdbengine.h
+++ b/src/plugins/debugger/cdb/cdbengine.h
@@ -32,6 +32,8 @@
#include <projectexplorer/devicesupport/idevice.h>
+#include <utils/qtcprocess.h>
+
#include <QElapsedTimer>
namespace Debugger {
@@ -99,20 +101,18 @@ public:
void loadAdditionalQmlStack() override;
void listBreakpoints();
- static QString extensionLibraryName(bool is64Bit);
+ static QString extensionLibraryName(bool is64Bit, bool isArm = false);
private:
void readyReadStandardOut();
void readyReadStandardError();
- void processError();
- void processFinished();
+ void processStarted();
+ void processDone();
void runCommand(const DebuggerCommand &cmd) override;
void adjustOperateByInstruction(bool);
void createFullBacktrace();
- void handleDoInterruptInferior(const QString &errorMessage);
-
typedef QPair<QString, QString> SourcePathMapping;
struct NormalizedSourceFileName // Struct for caching mapped/normalized source files.
{
@@ -205,7 +205,6 @@ private:
//! Debugger accessible (expecting commands)
bool m_accessible = false;
StopMode m_stopMode = NoStopRequested;
- ProjectExplorer::DeviceProcessSignalOperation::Ptr m_signalOperation;
int m_nextCommandToken = 0;
QHash<int, DebuggerCommand> m_commandForToken;
QString m_currentBuiltinResponse;
@@ -221,6 +220,7 @@ private:
wow64Stack64Bit
} m_wow64State = wow64Uninitialized;
QElapsedTimer m_logTimer;
+ QString m_extensionFileName;
QString m_extensionMessageBuffer;
bool m_sourceStepInto = false;
int m_watchPointX = 0;
diff --git a/src/plugins/debugger/console/consoleview.cpp b/src/plugins/debugger/console/consoleview.cpp
index 93fec5b73e6..72ff8cedef8 100644
--- a/src/plugins/debugger/console/consoleview.cpp
+++ b/src/plugins/debugger/console/consoleview.cpp
@@ -30,14 +30,15 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/manhattanstyle.h>
#include <qtsupport/baseqtversion.h>
+
#include <utils/hostosinfo.h>
+#include <utils/stringutils.h>
#include <QAction>
#include <QMenu>
#include <QMouseEvent>
#include <QPainter>
#include <QApplication>
-#include <QClipboard>
#include <QAbstractProxyModel>
#include <QFileInfo>
#include <QScrollBar>
@@ -204,8 +205,7 @@ void ConsoleView::copyToClipboard(const QModelIndex &index)
contents = QString::fromLatin1("%1 %2: %3").arg(contents).arg(filePath).arg(
model()->data(index, ConsoleItem::LineRole).toString());
}
- QClipboard *cb = QApplication::clipboard();
- cb->setText(contents);
+ Utils::setClipboardAndSelection(contents);
}
bool ConsoleView::canShowItemInTextEditor(const QModelIndex &index)
diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs
index 0e4143a6e21..a4f00665849 100644
--- a/src/plugins/debugger/debugger.qbs
+++ b/src/plugins/debugger/debugger.qbs
@@ -7,7 +7,6 @@ Project {
Depends { name: "Qt"; submodules: ["widgets", "network"] }
Depends { name: "Aggregation" }
Depends { name: "CPlusPlus" }
- Depends { name: "QtcSsh" }
Depends { name: "QmlDebug" }
Depends { name: "LanguageUtils" }
Depends { name: "QmlJS" }
@@ -256,7 +255,6 @@ Project {
}
Export {
- Depends { name: "QtcSsh" }
Depends { name: "CPlusPlus" }
}
}
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index 736869cc591..31b325c2bce 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -38,6 +38,7 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
+#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <QDebug>
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index 74ccf23e430..09ffe19365a 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -36,14 +36,6 @@ const char MODE_DEBUG[] = "Mode.Debug";
// Debug mode context
const char C_DEBUGMODE[] = "Debugger.DebugMode";
-// Common debugger constants.
-const char kPeripheralDescriptionFile[] = "PeripheralDescriptionFile";
-
-// UVSC-specific debugger constants.
-const char kUVisionProjectFilePath[] = "UVisionProjectFilePath";
-const char kUVisionOptionsFilePath[] = "UVisionOptionsFilePath";
-const char kUVisionSimulator[] = "UVisionSimulator";
-
} // namespace Constants
// Keep in sync with dumper.py
diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp
index 1493b5c6864..f65ddd91908 100644
--- a/src/plugins/debugger/debuggerdialogs.cpp
+++ b/src/plugins/debugger/debuggerdialogs.cpp
@@ -25,21 +25,22 @@
#include "debuggerdialogs.h"
+#include "cdb/cdbengine.h"
#include "debuggerkitinformation.h"
#include "debuggerruncontrol.h"
-#include "cdb/cdbengine.h"
+
+#include <app/app_version.h>
#include <coreplugin/icore.h>
+
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>
-#include <app/app_version.h>
-#include <utils/pathchooser.h>
#include <utils/fancylineedit.h>
+#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
-#include <ssh/sshconnection.h>
-
#include <QButtonGroup>
#include <QCheckBox>
#include <QComboBox>
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 058c0a3f7ce..eeaeb265ea5 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -33,7 +33,6 @@
#include "debuggerruncontrol.h"
#include "debuggertooltipmanager.h"
-#include "analyzer/analyzermanager.h"
#include "breakhandler.h"
#include "disassembleragent.h"
#include "localsandexpressionswindow.h"
@@ -54,7 +53,6 @@
#include "watchutils.h"
#include "watchwindow.h"
#include "debugger/shared/peutils.h"
-#include "console/console.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -66,6 +64,7 @@
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
+#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/taskhub.h>
@@ -73,10 +72,12 @@
#include <texteditor/texteditorsettings.h>
#include <texteditor/fontsettings.h>
+#include <utils/algorithm.h>
#include <utils/basetreeview.h>
#include <utils/checkablemessagebox.h>
#include <utils/macroexpander.h>
#include <utils/processhandle.h>
+#include <utils/processinterface.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/styledbar.h>
@@ -123,8 +124,8 @@ QDebug operator<<(QDebug str, const DebuggerRunParameters &sp)
nospace << "executable=" << sp.inferior.command.executable()
<< " coreFile=" << sp.coreFile
<< " processArgs=" << sp.inferior.command.arguments()
- << " inferior environment=<" << sp.inferior.environment.size() << " variables>"
- << " debugger environment=<" << sp.debugger.environment.size() << " variables>"
+ << " inferior environment=<" << sp.inferior.environment.toStringList().size() << " variables>"
+ << " debugger environment=<" << sp.debugger.environment.toStringList().size() << " variables>"
<< " workingDir=" << sp.inferior.workingDirectory
<< " attachPID=" << sp.attachPID.pid()
<< " remoteChannel=" << sp.remoteChannel
@@ -185,7 +186,6 @@ void LocationMark::updateIcon()
if (m_engine && EngineManager::currentEngine() == m_engine)
icon = m_engine->isReverseDebugging() ? &Icons::REVERSE_LOCATION : &Icons::LOCATION;
setIcon(icon->icon());
- updateMarker();
}
bool LocationMark::isDraggable() const
@@ -1059,12 +1059,13 @@ void DebuggerEngine::setRunId(const QString &id)
void DebuggerEngine::setRunTool(DebuggerRunTool *runTool)
{
- RunControl *runControl = runTool->runControl();
- d->m_device = runControl->device();
- if (!d->m_device)
- d->m_device = d->m_runParameters.inferior.device;
- if (d->m_device)
- d->m_runParameters.dumperPath = d->m_device->debugDumperPath();
+ d->m_device = runTool->device();
+
+ IDevice::ConstPtr debuggerDevice =
+ DeviceManager::deviceForPath(d->m_runParameters.debugger.command.executable());
+ if (QTC_GUARD(debuggerDevice))
+ d->m_runParameters.dumperPath = debuggerDevice->debugDumperPath();
+
d->m_terminalRunner = runTool->terminalRunner();
validateRunParameters(d->m_runParameters);
@@ -1373,7 +1374,8 @@ void DebuggerEngine::notifyInferiorSpontaneousStop()
{
showMessage("NOTE: INFERIOR SPONTANEOUS STOP");
QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
- d->m_perspective->select();
+ if (QTC_GUARD(d->m_perspective))
+ d->m_perspective->select();
showMessage(tr("Stopped."), StatusBar);
setState(InferiorStopOk);
if (debuggerSettings()->raiseOnInterrupt.value())
@@ -1611,7 +1613,8 @@ void DebuggerEnginePrivate::cleanupViews()
const bool closeMemory = debuggerSettings()->closeMemoryBuffersOnExit.value();
QList<IDocument *> toClose;
- foreach (IDocument *document, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents) {
const bool isMemory = document->property(Constants::OPENED_WITH_DISASSEMBLY).toBool();
if (document->property(Constants::OPENED_BY_DEBUGGER).toBool()) {
bool keepIt = true;
@@ -1790,14 +1793,14 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c
}
}
-void DebuggerEngine::notifyDebuggerProcessFinished(int exitCode,
- QProcess::ExitStatus exitStatus, const QString &backendName)
+void DebuggerEngine::notifyDebuggerProcessFinished(const ProcessResultData &result,
+ const QString &backendName)
{
showMessage(QString("%1 PROCESS FINISHED, status %2, exit code %3 (0x%4)")
.arg(backendName)
- .arg(exitStatus)
- .arg(exitCode)
- .arg(QString::number(exitCode, 16)));
+ .arg(result.m_exitStatus)
+ .arg(result.m_exitCode)
+ .arg(QString::number(result.m_exitCode, 16)));
switch (state()) {
case DebuggerFinished:
@@ -1817,9 +1820,9 @@ void DebuggerEngine::notifyDebuggerProcessFinished(int exitCode,
default: {
// Initiate shutdown sequence
notifyInferiorIll();
- const QString msg = exitStatus == QProcess::CrashExit ?
+ const QString msg = result.m_exitStatus == QProcess::CrashExit ?
tr("The %1 process terminated.") :
- tr("The %2 process terminated unexpectedly (exit code %1).").arg(exitCode);
+ tr("The %2 process terminated unexpectedly (exit code %1).").arg(result.m_exitCode);
AsynchronousMessageBox::critical(tr("Unexpected %1 Exit").arg(backendName),
msg.arg(backendName));
break;
@@ -2501,8 +2504,8 @@ void DebuggerEngine::handleExecRunToSelectedFunction()
QString functionName = cursor.selectedText();
if (functionName.isEmpty()) {
const QTextBlock block = cursor.block();
- const QString line = block.text();
- foreach (const QString &str, line.trimmed().split('(')) {
+ const QStringList lineList = block.text().trimmed().split('(');
+ for (const QString &str : lineList) {
QString a;
for (int i = str.size(); --i >= 0; ) {
if (!str.at(i).isLetterOrNumber())
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 810e00448a6..64d1933201d 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -27,18 +27,17 @@
#include "debugger_global.h"
#include "debuggerconstants.h"
-#include "debuggeritem.h"
#include "debuggerprotocol.h"
#include "breakhandler.h"
+#include "projectexplorer/abi.h"
#include "threadshandler.h"
#include <coreplugin/icontext.h>
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
#include <projectexplorer/runcontrol.h>
#include <texteditor/textmark.h>
-#include <utils/fileutils.h>
-#include <QProcess>
+#include <utils/filepath.h>
QT_BEGIN_NAMESPACE
class QDebug;
@@ -50,6 +49,7 @@ namespace Core { class IOptionsPage; }
namespace Utils {
class MacroExpander;
class Perspective;
+class ProcessResultData;
} // Utils
namespace Debugger {
@@ -184,8 +184,8 @@ public:
Utils::FilePaths projectSourceFiles;
// Used by Script debugging
- QString interpreter;
- QString mainScript;
+ Utils::FilePath interpreter;
+ Utils::FilePath mainScript;
// Used by AttachCrashedExternal.
QString crashParameter;
@@ -206,6 +206,14 @@ public:
Utils::FilePath dumperPath;
int fallbackQtVersion = 0x50200;
+
+ // Common debugger constants.
+ Utils::FilePath peripheralDescriptionFile;
+
+ // UVSC-specific debugger constants.
+ Utils::FilePath uVisionProjectFilePath;
+ Utils::FilePath uVisionOptionsFilePath;
+ bool uVisionSimulator = false;
};
class UpdateParameters
@@ -501,7 +509,7 @@ public:
protected:
void setDebuggerName(const QString &name);
- void notifyDebuggerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus,
+ void notifyDebuggerProcessFinished(const Utils::ProcessResultData &resultData,
const QString &backendName);
virtual void setState(DebuggerState state, bool forced = false);
@@ -554,7 +562,7 @@ protected:
bool isNativeMixedActiveFrame() const;
void startDying() const;
- ProjectExplorer::IDevice::ConstPtr device() const;
+ ProjectExplorer::IDeviceConstPtr device() const;
DebuggerEngine *companionEngine() const;
private:
diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp
index 382bd6af8f2..a6659506468 100644
--- a/src/plugins/debugger/debuggeritem.cpp
+++ b/src/plugins/debugger/debuggeritem.cpp
@@ -165,7 +165,7 @@ void DebuggerItem::reinitializeFromFile(const Environment &sysEnv, QString *erro
return;
}
- Environment env = sysEnv.size() == 0 ? Environment::systemEnvironment() : sysEnv;
+ Environment env = sysEnv.isValid() ? sysEnv : Environment::systemEnvironment();
// Prevent calling lldb on Windows because the lldb from the llvm package is linked against
// python but does not contain a python dll.
const bool isAndroidNdkLldb = DebuggerItem::addAndroidLldbPythonEnv(m_command, env);
@@ -191,7 +191,7 @@ void DebuggerItem::reinitializeFromFile(const Environment &sysEnv, QString *erro
proc.setCommand({m_command, {version}});
proc.runBlocking();
const QString output = proc.allOutput().trimmed();
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
if (error)
*error = output;
m_engineType = NoEngineType;
@@ -294,7 +294,7 @@ bool DebuggerItem::addAndroidLldbPythonEnv(const Utils::FilePath &lldbCmd, Utils
if (HostOsInfo::isAnyUnixHost()) {
const FilePath pythonLibDir = pythonDir.pathAppended("lib");
if (pythonLibDir.exists())
- env.prependOrSet("LD_LIBRARY_PATH", pythonLibDir.toString());
+ env.prependOrSetLibrarySearchPath(pythonLibDir);
}
return true;
diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp
index 8b3a31d2d5b..9afc0877680 100644
--- a/src/plugins/debugger/debuggeritemmanager.cpp
+++ b/src/plugins/debugger/debuggeritemmanager.cpp
@@ -669,12 +669,14 @@ void DebuggerItemManagerPrivate::autoDetectCdbDebuggers()
for (const QFileInfo &kitFolderFi : kitFolders) {
const QString path = kitFolderFi.absoluteFilePath();
- const QFileInfo cdb32(path + "/Debuggers/x86/cdb.exe");
- if (cdb32.isExecutable())
- cdbs.append(FilePath::fromString(cdb32.absoluteFilePath()));
- const QFileInfo cdb64(path + "/Debuggers/x64/cdb.exe");
- if (cdb64.isExecutable())
- cdbs.append(FilePath::fromString(cdb64.absoluteFilePath()));
+ QStringList abis = {"x86", "x64"};
+ if (HostOsInfo::hostArchitecture() == HostOsInfo::HostArchitectureArm64)
+ abis << "arm64";
+ for (const QString &abi: abis) {
+ const QFileInfo cdbBinary(path + "/Debuggers/" + abi + "/cdb.exe");
+ if (cdbBinary.isExecutable())
+ cdbs.append(FilePath::fromString(cdbBinary.absoluteFilePath()));
+ }
}
for (const FilePath &cdb : qAsConst(cdbs)) {
@@ -763,7 +765,7 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers(const FilePaths &s
proc.setCommand({"xcrun", {"--find", "lldb"}});
proc.runBlocking();
// FIXME:
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
QString lPath = proc.allOutput().trimmed();
if (!lPath.isEmpty()) {
const QFileInfo fi(lPath);
@@ -796,9 +798,7 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers(const FilePaths &s
DebuggerItem item;
item.createId();
item.setDetectionSource(detectionSource);
- // Intentionally set items with non-empty source as manual for now to
- // give the user a chance to remove them. FIXME: Think of a better way.
- item.setAutoDetected(detectionSource.isEmpty());
+ item.setAutoDetected(true);
item.setCommand(command);
item.reinitializeFromFile();
if (item.engineType() == NoEngineType)
@@ -937,7 +937,8 @@ void DebuggerItemManagerPrivate::readDebuggers(const FilePath &fileName, bool is
.arg(item.command().toUserOutput(), item.id().toString(), fileName.toUserOutput());
continue;
}
- if (!item.command().isExecutableFile()) {
+ // FIXME: During startup, devices are not yet available, so we cannot check if the file still exists.
+ if (!item.command().needsDevice() && !item.command().isExecutableFile()) {
qWarning() << QString("DebuggerItem \"%1\" (%2) read from \"%3\" dropped since the command is not executable.")
.arg(item.command().toUserOutput(), item.id().toString(), fileName.toUserOutput());
continue;
diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp
index e7f1c5f2d7f..1af1f95486a 100644
--- a/src/plugins/debugger/debuggerkitinformation.cpp
+++ b/src/plugins/debugger/debuggerkitinformation.cpp
@@ -28,9 +28,10 @@
#include "debuggeritemmanager.h"
#include "debuggeritem.h"
-#include <projectexplorer/toolchain.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runcontrol.h>
+#include <projectexplorer/toolchain.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 033d72f3bee..5de92dd4831 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -88,8 +88,9 @@
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildmanager.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
-#include <projectexplorer/devicesupport/deviceprocesslist.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <projectexplorer/itaskhandler.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
@@ -101,7 +102,6 @@
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
#include <projectexplorer/toolchain.h>
-#include <ssh/sshconnection.h>
#include <texteditor/texteditor.h>
#include <texteditor/textdocument.h>
@@ -114,6 +114,7 @@
#include <utils/checkablemessagebox.h>
#include <utils/fancymainwindow.h>
#include <utils/hostosinfo.h>
+#include <utils/processinfo.h>
#include <utils/proxyaction.h>
#include <utils/qtcassert.h>
#include <utils/statuslabel.h>
@@ -613,7 +614,7 @@ public:
void extensionsInitialized();
void aboutToShutdown();
- RunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process, bool contAfterAttach);
+ RunControl *attachToRunningProcess(Kit *kit, const ProcessInfo &process, bool contAfterAttach);
void writeSettings()
{
@@ -818,7 +819,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
vbox->insertWidget(0, label);
};
- const auto addFontSizeAdaptation = [this](QWidget *widget) {
+ const auto addFontSizeAdaptation = [](QWidget *widget) {
QObject::connect(TextEditorSettings::instance(), &TextEditorSettings::fontSettingsChanged,
[widget](const FontSettings &settings) {
if (!debuggerSettings()->fontSizeFollowsEditor.value())
@@ -1668,16 +1669,16 @@ void DebuggerPluginPrivate::attachToRunningApplication()
IDevice::ConstPtr device = DeviceKitAspect::device(kit);
QTC_ASSERT(device, return);
- DeviceProcessItem process = dlg->currentProcess();
+ const ProcessInfo processInfo = dlg->currentProcess();
if (device->type() == PE::DESKTOP_DEVICE_TYPE) {
- attachToRunningProcess(kit, process, false);
+ attachToRunningProcess(kit, processInfo, false);
} else {
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
runControl->setKit(kit);
//: %1: PID
- runControl->setDisplayName(tr("Process %1").arg(process.pid));
- auto debugger = new RemoteAttachRunner(runControl, ProcessHandle(process.pid));
+ runControl->setDisplayName(tr("Process %1").arg(processInfo.processId));
+ auto debugger = new RemoteAttachRunner(runControl, ProcessHandle(processInfo.processId));
debugger->startRunControl();
}
}
@@ -1702,23 +1703,23 @@ void DebuggerPluginPrivate::attachToUnstartedApplicationDialog()
}
RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
- DeviceProcessItem process, bool contAfterAttach)
+ const ProcessInfo &processInfo, bool contAfterAttach)
{
QTC_ASSERT(kit, return nullptr);
IDevice::ConstPtr device = DeviceKitAspect::device(kit);
QTC_ASSERT(device, return nullptr);
- if (process.pid == 0) {
+ if (processInfo.processId == 0) {
AsynchronousMessageBox::warning(tr("Warning"), tr("Cannot attach to process with PID 0"));
return nullptr;
}
const Abi tcAbi = ToolChainKitAspect::targetAbi(kit);
const bool isWindows = (tcAbi.os() == Abi::WindowsOS);
- if (isWindows && isWinProcessBeingDebugged(process.pid)) {
+ if (isWindows && isWinProcessBeingDebugged(processInfo.processId)) {
AsynchronousMessageBox::warning(
tr("Process Already Under Debugger Control"),
tr("The process %1 is already under the control of a debugger.\n"
- "%2 cannot attach to it.").arg(process.pid)
+ "%2 cannot attach to it.").arg(processInfo.processId)
.arg(Core::Constants::IDE_DISPLAY_NAME));
return nullptr;
}
@@ -1732,11 +1733,10 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
runControl->setKit(kit);
//: %1: PID
- runControl->setDisplayName(tr("Process %1").arg(process.pid));
+ runControl->setDisplayName(tr("Process %1").arg(processInfo.processId));
auto debugger = new DebuggerRunTool(runControl);
- debugger->setAttachPid(ProcessHandle(process.pid));
- debugger->setInferiorExecutable(FilePath::fromString(process.exe));
- debugger->setInferiorDevice(device);
+ debugger->setAttachPid(ProcessHandle(processInfo.processId));
+ debugger->setInferiorExecutable(device->filePath(processInfo.executable));
debugger->setStartMode(AttachToLocalProcess);
debugger->setCloseMode(DetachAtClose);
debugger->setContinueAfterAttach(contAfterAttach);
@@ -1753,6 +1753,7 @@ void DebuggerPlugin::attachExternalApplication(RunControl *rc)
runControl->setTarget(rc->target());
runControl->setDisplayName(tr("Process %1").arg(pid.pid()));
auto debugger = new DebuggerRunTool(runControl);
+ debugger->setInferiorExecutable(rc->targetFilePath());
debugger->setAttachPid(pid);
debugger->setStartMode(AttachToLocalProcess);
debugger->setCloseMode(DetachAtClose);
@@ -1834,7 +1835,7 @@ void DebuggerPluginPrivate::attachToQmlPort()
qmlServer.setPort(dlg.port());
debugger->setQmlServer(qmlServer);
- QSsh::SshConnectionParameters sshParameters = device->sshParameters();
+ SshParameters sshParameters = device->sshParameters();
debugger->setRemoteChannel(sshParameters.host(), sshParameters.port());
debugger->setStartMode(AttachToQmlServer);
@@ -2396,7 +2397,7 @@ void DebuggerUnitTests::testStateMachine()
QVERIFY(rc);
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
- runControl->setRunConfiguration(rc);
+ runControl->copyDataFromRunConfiguration(rc);
auto debugger = new DebuggerRunTool(runControl);
debugger->setInferior(rc->runnable());
diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
index 553dfafe875..4a339db3d79 100644
--- a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
+++ b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
@@ -182,6 +182,11 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target)
return builder.emerge(false);
});
+ addDataExtractor(this, &DebuggerRunConfigurationAspect::useCppDebugger, &Data::useCppDebugger);
+ addDataExtractor(this, &DebuggerRunConfigurationAspect::useQmlDebugger, &Data::useQmlDebugger);
+ addDataExtractor(this, &DebuggerRunConfigurationAspect::useMultiProcess, &Data::useMultiProcess);
+ addDataExtractor(this, &DebuggerRunConfigurationAspect::overrideStartup, &Data::overrideStartup);
+
m_cppAspect = new DebuggerLanguageAspect;
m_cppAspect->setLabel(tr("Enable C++"));
m_cppAspect->setSettingsKey("RunConfiguration.UseCppDebugger");
diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.h b/src/plugins/debugger/debuggerrunconfigurationaspect.h
index bd2a0a0e00e..4f390d65f60 100644
--- a/src/plugins/debugger/debuggerrunconfigurationaspect.h
+++ b/src/plugins/debugger/debuggerrunconfigurationaspect.h
@@ -56,6 +56,14 @@ public:
int portsUsedByDebugger() const;
+ struct Data : BaseAspect::Data
+ {
+ bool useCppDebugger;
+ bool useQmlDebugger;
+ bool useMultiProcess;
+ QString overrideStartup;
+ };
+
private:
Internal::DebuggerLanguageAspect *m_cppAspect;
Internal::DebuggerLanguageAspect *m_qmlAspect;
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index ca638e41036..5b88a067feb 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -42,7 +42,7 @@
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
-#include <projectexplorer/devicesupport/deviceprocesslist.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/environmentaspect.h> // For the environment
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
@@ -73,8 +73,6 @@
#include <qtsupport/qtkitinformation.h>
-#include <ssh/sshconnection.h>
-
#include <QTcpServer>
#include <QTimer>
@@ -117,9 +115,6 @@ public:
private:
~CoreUnpacker() final
{
- m_coreUnpackProcess.blockSignals(true);
- m_coreUnpackProcess.terminate();
- m_coreUnpackProcess.deleteLater();
if (m_tempCoreFile.isOpen())
m_tempCoreFile.close();
@@ -135,7 +130,13 @@ private:
}
m_coreUnpackProcess.setWorkingDirectory(TemporaryDirectory::masterDirectoryFilePath());
- connect(&m_coreUnpackProcess, &QtcProcess::finished, this, &CoreUnpacker::reportStarted);
+ connect(&m_coreUnpackProcess, &QtcProcess::done, this, [this] {
+ if (m_coreUnpackProcess.error() == QProcess::UnknownError) {
+ reportStopped();
+ return;
+ }
+ reportFailure("Error unpacking " + m_coreFilePath.toUserOutput());
+ });
const QString msg = DebuggerRunTool::tr("Unpacking core file to %1");
appendMessage(msg.arg(m_tempCoreFilePath.toUserOutput()), LogMessageFormat);
@@ -143,6 +144,7 @@ private:
if (m_coreFilePath.endsWith(".lzo")) {
m_coreUnpackProcess.setCommand({"lzop", {"-o", m_tempCoreFilePath.path(),
"-x", m_coreFilePath.path()}});
+ reportStarted();
m_coreUnpackProcess.start();
return;
}
@@ -155,6 +157,7 @@ private:
m_tempCoreFile.write(m_coreUnpackProcess.readAllStandardOutput());
});
m_coreUnpackProcess.setCommand({"gzip", {"-c", "-d", m_coreFilePath.path()}});
+ reportStarted();
m_coreUnpackProcess.start();
return;
}
@@ -208,7 +211,7 @@ void DebuggerRunTool::setStartMode(DebuggerStartMode startMode)
projects.removeOne(startupProject);
projects.insert(0, startupProject);
}
- foreach (Project *project, projects)
+ for (Project *project : qAsConst(projects))
m_runParameters.projectSourceFiles.append(project->files(Project::SourceFiles));
if (!projects.isEmpty())
m_runParameters.projectSourceDirectory = projects.first()->projectDirectory();
@@ -392,11 +395,6 @@ void DebuggerRunTool::setInferiorEnvironment(const Utils::Environment &env)
m_runParameters.inferior.environment = env;
}
-void DebuggerRunTool::setInferiorDevice(IDevice::ConstPtr device)
-{
- m_runParameters.inferior.device = device;
-}
-
void DebuggerRunTool::setRunControlName(const QString &name)
{
m_runParameters.displayName = name;
@@ -578,10 +576,8 @@ void DebuggerRunTool::start()
++d->engineStopsNeeded;
connect(m_engine, &DebuggerEngine::attachToCoreRequested, this, [this](const QString &coreFile) {
- auto runConfig = runControl()->runConfiguration();
- QTC_ASSERT(runConfig, return);
auto rc = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
- rc->setRunConfiguration(runConfig);
+ rc->copyDataFromRunControl(runControl());
auto name = QString(tr("%1 - Snapshot %2").arg(runControl()->displayName()).arg(++d->snapshotCounter));
auto debugger = new DebuggerRunTool(rc);
debugger->setStartMode(AttachToCore);
@@ -872,11 +868,11 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
m_runParameters.displayName = runControl->displayName();
if (auto symbolsAspect = runControl->aspect<SymbolFileAspect>())
- m_runParameters.symbolFile = symbolsAspect->filePath();
+ m_runParameters.symbolFile = symbolsAspect->filePath;
if (auto terminalAspect = runControl->aspect<TerminalAspect>())
- m_runParameters.useTerminal = terminalAspect->useTerminal();
+ m_runParameters.useTerminal = terminalAspect->useTerminal;
if (auto runAsRootAspect = runControl->aspect<RunAsRootAspect>())
- m_runParameters.runAsRoot = runAsRootAspect->value();
+ m_runParameters.runAsRoot = runAsRootAspect->value;
Kit *kit = runControl->kit();
QTC_ASSERT(kit, return);
@@ -890,13 +886,13 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
m_runParameters.qtPackageSourceLocation = qtVersion->qtPackageSourcePath().toString();
if (auto aspect = runControl->aspect<DebuggerRunConfigurationAspect>()) {
- if (!aspect->useCppDebugger())
+ if (!aspect->useCppDebugger)
m_runParameters.cppEngineType = NoEngineType;
- m_runParameters.isQmlDebugging = aspect->useQmlDebugger();
- m_runParameters.multiProcess = aspect->useMultiProcess();
- m_runParameters.additionalStartupCommands = aspect->overrideStartup();
+ m_runParameters.isQmlDebugging = aspect->useQmlDebugger;
+ m_runParameters.multiProcess = aspect->useMultiProcess;
+ m_runParameters.additionalStartupCommands = aspect->overrideStartup;
- if (aspect->useCppDebugger()) {
+ if (aspect->useCppDebugger) {
if (DebuggerKitAspect::debugger(kit)) {
const Tasks tasks = DebuggerKitAspect::validateDebugger(kit);
for (const Task &t : tasks) {
@@ -909,7 +905,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
}
}
- Runnable inferior = runnable();
+ Runnable inferior = runControl->runnable();
const FilePath &debuggerExecutable = m_runParameters.debugger.command.executable();
inferior.command.setExecutable(inferior.command.executable().onDevice(debuggerExecutable));
inferior.workingDirectory = inferior.workingDirectory.onDevice(debuggerExecutable);
@@ -936,16 +932,17 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
m_runParameters.nativeMixedEnabled = bool(nativeMixedOverride);
- RunConfiguration *runConfig = runControl->runConfiguration();
- if (runConfig && runConfig->property("supportsDebugger").toBool()) {
- const QString mainScript = runConfig->property("mainScript").toString();
- const QString interpreter = runConfig->property("interpreter").toString();
- if (!interpreter.isEmpty() && mainScript.endsWith(".py")) {
- m_runParameters.mainScript = mainScript;
- m_runParameters.interpreter = interpreter;
- const QString args = runConfig->property("arguments").toString();
- m_runParameters.inferior.command.addArgs(args, CommandLine::Raw);
- m_engine = createPdbEngine();
+ if (auto interpreterAspect = runControl->aspect<InterpreterAspect>()) {
+ if (auto mainScriptAspect = runControl->aspect<MainScriptAspect>()) {
+ const FilePath mainScript = mainScriptAspect->filePath;
+ const FilePath interpreter = interpreterAspect->interpreter.command;
+ if (!interpreter.isEmpty() && mainScript.endsWith(".py")) {
+ m_runParameters.mainScript = mainScript;
+ m_runParameters.interpreter = interpreter;
+ if (auto args = runControl->aspect<ArgumentsAspect>())
+ m_runParameters.inferior.command.addArgs(args->arguments, CommandLine::Raw);
+ m_engine = createPdbEngine();
+ }
}
}
@@ -1040,35 +1037,31 @@ DebugServerRunner::DebugServerRunner(RunControl *runControl, DebugServerPortsGat
: SimpleTargetRunner(runControl)
{
setId("DebugServerRunner");
- const Runnable mainRunnable = runControl->runnable();
addStartDependency(portsGatherer);
QTC_ASSERT(portsGatherer, reportFailure(); return);
- setStarter([this, runControl, mainRunnable, portsGatherer] {
+ setStartModifier([this, runControl, portsGatherer] {
QTC_ASSERT(portsGatherer, reportFailure(); return);
- Runnable debugServer;
- debugServer.environment = mainRunnable.environment;
- debugServer.workingDirectory = mainRunnable.workingDirectory;
-
- QStringList args = ProcessArgs::splitArgs(mainRunnable.command.arguments(), OsTypeLinux);
-
const bool isQmlDebugging = portsGatherer->useQmlServer();
const bool isCppDebugging = portsGatherer->useGdbServer();
+ CommandLine cmd;
+
+ QStringList args = ProcessArgs::splitArgs(commandLine().arguments(), OsTypeLinux);
if (isQmlDebugging) {
args.prepend(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
portsGatherer->qmlServer()));
}
if (isQmlDebugging && !isCppDebugging) {
- debugServer.command.setExecutable(mainRunnable.command.executable()); // FIXME: Case should not happen?
+ cmd.setExecutable(commandLine().executable()); // FIXME: Case should not happen?
} else {
- debugServer.command.setExecutable(runControl->device()->debugServerPath());
- if (debugServer.command.isEmpty())
- debugServer.command.setExecutable("gdbserver");
+ cmd.setExecutable(runControl->device()->debugServerPath());
+ if (cmd.isEmpty())
+ cmd.setExecutable(runControl->device()->filePath("gdbserver"));
args.clear();
- if (debugServer.command.executable().toString().contains("lldb-server")) {
+ if (cmd.executable().toString().contains("lldb-server")) {
args.append("platform");
args.append("--listen");
args.append(QString("*:%1").arg(portsGatherer->gdbServer().port()));
@@ -1084,9 +1077,9 @@ DebugServerRunner::DebugServerRunner(RunControl *runControl, DebugServerPortsGat
args.append(QString::number(m_pid.pid()));
}
}
- debugServer.command.setArguments(ProcessArgs::joinArgs(args, OsTypeLinux));
+ cmd.setArguments(ProcessArgs::joinArgs(args, OsTypeLinux));
- doStart(debugServer, runControl->device());
+ setCommandLine(cmd);
});
}
diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h
index a11cc098e90..a58ffaff9f6 100644
--- a/src/plugins/debugger/debuggerruncontrol.h
+++ b/src/plugins/debugger/debuggerruncontrol.h
@@ -76,7 +76,6 @@ public:
void setInferior(const ProjectExplorer::Runnable &runnable);
void setInferiorExecutable(const Utils::FilePath &executable);
void setInferiorEnvironment(const Utils::Environment &env); // Used by GammaRay plugin
- void setInferiorDevice(ProjectExplorer::IDevice::ConstPtr device); // Used by cdbengine
void setRunControlName(const QString &name);
void setStartMessage(const QString &msg);
void addQmlServerInferiorCommandLineArgumentIfNeeded();
@@ -132,6 +131,8 @@ public:
Internal::TerminalRunner *terminalRunner() const;
DebuggerEngineType cppEngineType() const;
+ Internal::DebuggerRunParameters &runParameters() { return m_runParameters; }
+
private:
bool fixupParameters();
void handleEngineStarted(Internal::DebuggerEngine *engine);
diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
index 659b75d1bc4..b5985ac214a 100644
--- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
+++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
@@ -34,6 +34,7 @@
#include <utils/layoutbuilder.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/variablechooser.h>
#include <QFileDialog>
@@ -452,7 +453,6 @@ static QString findQtInstallPath(const FilePath &qmakePath)
return QString();
}
if (!proc.waitForFinished()) {
- proc.stopProcess();
qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(qmakePath.toString()));
return QString();
}
diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp
index 814b71ecfb3..4177879653c 100644
--- a/src/plugins/debugger/debuggertooltipmanager.cpp
+++ b/src/plugins/debugger/debuggertooltipmanager.cpp
@@ -26,7 +26,6 @@
#include "debuggertooltipmanager.h"
#include "debuggeractions.h"
-#include "debuggercore.h"
#include "debuggerengine.h"
#include "debuggerinternalconstants.h"
#include "debuggermainwindow.h"
@@ -34,7 +33,6 @@
#include "sourceutils.h"
#include "stackhandler.h"
#include "watchhandler.h"
-#include "watchwindow.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -53,6 +51,7 @@
#include <utils/porting.h>
#include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h>
+#include <utils/stringutils.h>
#include <utils/treemodel.h>
#include <utils/utilsicons.h>
@@ -577,17 +576,14 @@ DebuggerToolTipWidget::DebuggerToolTipWidget()
mainLayout->addWidget(toolBar);
mainLayout->addWidget(treeView);
- connect(copyButton, &QAbstractButton::clicked, [this] {
+ connect(copyButton, &QAbstractButton::clicked, this, [this] {
QString text;
QTextStream str(&text);
model.forAllItems([&str](ToolTipWatchItem *item) {
str << QString(item->level(), '\t')
<< item->name << '\t' << item->value << '\t' << item->type << '\n';
});
- QClipboard *clipboard = QApplication::clipboard();
- if (clipboard->supportsSelection())
- clipboard->setText(text, QClipboard::Selection);
- clipboard->setText(text, QClipboard::Clipboard);
+ setClipboardAndSelection(text);
});
connect(treeView, &QTreeView::expanded, &model, &ToolTipModel::expandNode);
@@ -1319,7 +1315,8 @@ void DebuggerToolTipManagerPrivate::leavingDebugMode()
hideAllToolTips();
if (QWidget *topLevel = ICore::mainWindow()->topLevelWidget())
topLevel->removeEventFilter(this);
- foreach (IEditor *e, DocumentModel::editorsForOpenedDocuments()) {
+ const QList<IEditor *> editors = DocumentModel::editorsForOpenedDocuments();
+ for (IEditor *e : editors) {
if (auto toolTipEditor = qobject_cast<BaseTextEditor *>(e)) {
toolTipEditor->editorWidget()->verticalScrollBar()->disconnect(this);
toolTipEditor->editorWidget()->disconnect(this);
diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp
index 1b313efaea5..38d7af3b45d 100644
--- a/src/plugins/debugger/disassembleragent.cpp
+++ b/src/plugins/debugger/disassembleragent.cpp
@@ -43,7 +43,7 @@
#include <texteditor/texteditor.h>
#include <utils/aspects.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <QTextBlock>
@@ -265,7 +265,8 @@ void DisassemblerAgentPrivate::configureMimeType()
Utils::MimeType mtype = Utils::mimeTypeForName(mimeType);
if (mtype.isValid()) {
- foreach (IEditor *editor, DocumentModel::editorsForDocument(document))
+ const QList<IEditor *> editors = DocumentModel::editorsForDocument(document);
+ for (IEditor *editor : editors)
if (auto widget = TextEditorWidget::fromEditor(editor))
widget->configureGenericHighlighter();
} else {
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 6a644892fea..9da5a188f3b 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -54,13 +54,14 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
-#include <projectexplorer/devicesupport/deviceprocess.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/taskhub.h>
#include <app/app_version.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
+#include <utils/processinterface.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
@@ -145,8 +146,9 @@ const char tracepointCapturePropertyName[] = "GDB.TracepointCapture";
///////////////////////////////////////////////////////////////////////
GdbEngine::GdbEngine()
- : m_gdbProc(ProcessMode::Writer)
{
+ m_gdbProc.setProcessMode(ProcessMode::Writer);
+
setObjectName("GdbEngine");
setDebuggerName("GDB");
@@ -167,10 +169,10 @@ GdbEngine::GdbEngine()
connect(&s.useDynamicType, &BaseAspect::changed,
this, &GdbEngine::reloadLocals);
- connect(&m_gdbProc, &QtcProcess::errorOccurred,
- this, &GdbEngine::handleGdbError);
- connect(&m_gdbProc, &QtcProcess::finished,
- this, &GdbEngine::handleGdbFinished);
+ connect(&m_gdbProc, &QtcProcess::started,
+ this, &GdbEngine::handleGdbStarted);
+ connect(&m_gdbProc, &QtcProcess::done,
+ this, &GdbEngine::handleGdbDone);
connect(&m_gdbProc, &QtcProcess::readyReadStandardOutput,
this, &GdbEngine::readGdbStandardOutput);
connect(&m_gdbProc, &QtcProcess::readyReadStandardError,
@@ -786,7 +788,7 @@ void GdbEngine::runCommand(const DebuggerCommand &command)
.arg(token).arg(buffer));
QMetaObject::invokeMethod(this, [this, buffer] { handleResponse(buffer); });
} else {
- m_gdbProc.write(cmd.function.toUtf8() + "\r\n");
+ m_gdbProc.write(cmd.function + "\r\n");
if (command.flags & NeedsFlush) {
// We don't need the response or result here, just want to flush
// anything that's still on the gdb side.
@@ -819,13 +821,13 @@ void GdbEngine::commandTimeout()
QList<int> keys = m_commandForToken.keys();
Utils::sort(keys);
bool killIt = false;
- foreach (int key, keys) {
+ for (int key : qAsConst(keys)) {
const DebuggerCommand &cmd = m_commandForToken.value(key);
killIt = true;
showMessage(QString::number(key) + ": " + cmd.function);
}
QStringList commands;
- foreach (const DebuggerCommand &cmd, m_commandForToken)
+ for (const DebuggerCommand &cmd : qAsConst(m_commandForToken))
commands << QString("\"%1\"").arg(cmd.function);
if (killIt) {
showMessage(QString("TIMED OUT WAITING FOR GDB REPLY. "
@@ -2607,7 +2609,7 @@ void GdbEngine::insertBreakpoint(const Breakpoint &bp)
QVariant tpCaps = bp->property(tracepointCapturePropertyName);
if (tpCaps.isValid()) {
QJsonArray caps;
- foreach (const auto &tpCap, tpCaps.toList()) {
+ for (const QVariant &tpCap : tpCaps.toList()) {
TracepointCaptureData data = tpCap.value<TracepointCaptureData>();
QJsonArray cap;
cap.append(static_cast<int>(data.type));
@@ -2845,7 +2847,8 @@ static void handleShowModuleSymbols(const DebuggerResponse &response,
// Object file /opt/dev/qt/lib/libQtNetworkMyns.so.4:
// [ 0] A 0x16bd64 _DYNAMIC moc_qudpsocket.cpp
// [12] S 0xe94680 _ZN4myns5QFileC1Ev section .plt myns::QFile::QFile()
- foreach (const QString &line, QString::fromLocal8Bit(file.readAll()).split('\n')) {
+ const QStringList lines = QString::fromLocal8Bit(file.readAll()).split('\n');
+ for (const QString &line : lines) {
if (line.isEmpty())
continue;
if (line.at(0) != '[')
@@ -2929,7 +2932,7 @@ void GdbEngine::handleShowModuleSections(const DebuggerResponse &response,
const QString needle = prefix + moduleName;
Sections sections;
bool active = false;
- foreach (const QString &line, lines) {
+ for (const QString &line : qAsConst(lines)) {
if (line.startsWith(prefix)) {
if (active)
break;
@@ -3753,7 +3756,8 @@ bool GdbEngine::handleCliDisassemblerResult(const QString &output, DisassemblerA
// First line is something like
// "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
DisassemblerLines dlines;
- foreach (const QString &line, output.split('\n'))
+ const QStringList lineList = output.split('\n');
+ for (const QString &line : lineList)
dlines.appendUnparsed(line);
QVector<DisassemblerLine> lines = dlines.data();
@@ -3830,10 +3834,10 @@ void GdbEngine::setupEngine()
gdbCommand.addArg("--tty=" + m_outputCollector.serverName());
}
- const QString tests = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_TESTS"));
- foreach (const QString &test, tests.split(','))
+ const QStringList testList = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_TESTS")).split(',');
+ for (const QString &test : testList)
m_testCases.insert(test.toInt());
- foreach (int test, m_testCases)
+ for (int test : qAsConst(m_testCases))
showMessage("ENABLING TEST CASE: " + QString::number(test));
m_expectTerminalTrap = terminal();
@@ -3850,6 +3854,7 @@ void GdbEngine::setupEngine()
if (!debuggerSettings()->loadGdbInit.value())
gdbCommand.addArg("-n");
+ // This is filled in DebuggerKitAspect::runnable
Environment gdbEnv = rp.debugger.environment;
gdbEnv.setupEnglishOutput();
if (rp.runAsRoot)
@@ -3863,20 +3868,10 @@ void GdbEngine::setupEngine()
m_gdbProc.setWorkingDirectory(rp.debugger.workingDirectory);
m_gdbProc.setEnvironment(gdbEnv);
m_gdbProc.start();
+}
- if (!m_gdbProc.waitForStarted()) {
- handleGdbStartFailed();
- QString msg;
- FilePath wd = m_gdbProc.workingDirectory();
- if (!wd.isReadableDir())
- msg = failedToStartMessage() + ' ' + tr("The working directory \"%1\" is not usable.")
- .arg(wd.toUserOutput());
- else
- msg = RunWorker::userMessageForProcessError(QProcess::FailedToStart, rp.debugger.command.executable());
- handleAdapterStartFailed(msg);
- return;
- }
-
+void GdbEngine::handleGdbStarted()
+{
showMessage("GDB STARTED, INITIALIZING IT");
runCommand({"show version", CB(handleShowVersion)});
runCommand({"show debug-file-directory", CB(handleDebugInfoLocation)});
@@ -3936,6 +3931,7 @@ void GdbEngine::setupEngine()
showStatusMessage(tr("Setting up inferior..."));
+ const DebuggerRunParameters &rp = runParameters();
// Addint executable to modules list.
Module module;
module.startAddress = 0;
@@ -3988,8 +3984,8 @@ void GdbEngine::setupEngine()
//if (terminal()->isUsable())
// runCommand({"set inferior-tty " + QString::fromUtf8(terminal()->slaveDevice())});
- const QString uninstalledData =
- rp.debugger.command.executable().pathAppended("data-directory/python").path();
+ const QString uninstalledData = rp.debugger.command.executable().parentDir()
+ .pathAppended("data-directory/python").path();
runCommand({"python sys.path.insert(1, '" + rp.dumperPath.path() + "')"});
runCommand({"python sys.path.append('" + uninstalledData + "')"});
@@ -4051,9 +4047,10 @@ void GdbEngine::setEnvironmentVariables()
&& str.compare("path", Qt::CaseInsensitive) == 0;
};
- Environment sysEnv = Environment::systemEnvironment();
+ Environment baseEnv = runParameters().debugger.environment;
Environment runEnv = runParameters().inferior.environment;
- foreach (const EnvironmentItem &item, sysEnv.diff(runEnv)) {
+ const NameValueItems items = baseEnv.diff(runEnv);
+ for (const EnvironmentItem &item : items) {
// imitate the weird windows gdb behavior of setting the case of the path environment
// variable name to an all uppercase PATH
const QString name = isWindowsPath(item.name) ? "PATH" : item.name;
@@ -4074,39 +4071,41 @@ void GdbEngine::reloadDebuggingHelpers()
reloadLocals();
}
-void GdbEngine::handleGdbError(QProcess::ProcessError error)
+void GdbEngine::handleGdbDone()
{
- QString msg = RunWorker::userMessageForProcessError(error, runParameters().debugger.command.executable());
- QString errorString = m_gdbProc.errorString();
- if (!errorString.isEmpty())
- msg += '\n' + errorString;
- showMessage("HANDLE GDB ERROR: " + msg);
- // Show a message box for asynchronously reported issues.
- switch (error) {
- case QProcess::FailedToStart:
- // This should be handled by the code trying to start the process.
- break;
- case QProcess::Crashed:
- // At this time, m_gdbProc.state() can still return Running.
- // Wait for finished() instead.
- break;
- case QProcess::ReadError:
- case QProcess::WriteError:
- case QProcess::Timedout:
- default:
- //m_gdbProc->kill();
- //notifyEngineIll();
- AsynchronousMessageBox::critical(tr("GDB I/O Error"), msg);
- break;
+ if (m_gdbProc.result() == ProcessResult::StartFailed) {
+ handleGdbStartFailed();
+ QString msg;
+ const FilePath wd = m_gdbProc.workingDirectory();
+ if (!wd.isReadableDir()) {
+ msg = failedToStartMessage() + ' ' + tr("The working directory \"%1\" is not usable.")
+ .arg(wd.toUserOutput());
+ } else {
+ msg = RunWorker::userMessageForProcessError(QProcess::FailedToStart,
+ runParameters().debugger.command.executable());
+ }
+ handleAdapterStartFailed(msg);
+ return;
}
-}
-void GdbEngine::handleGdbFinished()
-{
+ const QProcess::ProcessError error = m_gdbProc.error();
+ if (error != QProcess::UnknownError) {
+ QString msg = RunWorker::userMessageForProcessError(error,
+ runParameters().debugger.command.executable());
+ const QString errorString = m_gdbProc.errorString();
+ if (!errorString.isEmpty())
+ msg += '\n' + errorString;
+ showMessage("HANDLE GDB ERROR: " + msg);
+
+ if (error == QProcess::FailedToStart)
+ return; // This should be handled by the code trying to start the process.
+
+ AsynchronousMessageBox::critical(tr("GDB I/O Error"), msg);
+ }
if (m_commandTimer.isActive())
m_commandTimer.stop();
- notifyDebuggerProcessFinished(m_gdbProc.exitCode(), m_gdbProc.exitStatus(), "GDB");
+ notifyDebuggerProcessFinished(m_gdbProc.resultData(), "GDB");
}
void GdbEngine::abortDebuggerProcess()
@@ -4117,8 +4116,8 @@ void GdbEngine::abortDebuggerProcess()
void GdbEngine::resetInferior()
{
if (!runParameters().commandsForReset.isEmpty()) {
- const QString commands = expand(runParameters().commandsForReset);
- foreach (QString command, commands.split('\n')) {
+ const QStringList commands = expand(runParameters().commandsForReset).split('\n');
+ for (QString command : commands) {
command = command.trimmed();
if (!command.isEmpty())
runCommand({command, ConsoleCommand | NeedsTemporaryStop | NativeCommand});
@@ -4199,7 +4198,7 @@ void GdbEngine::resetCommandQueue()
QString msg;
QTextStream ts(&msg);
ts << "RESETING COMMAND QUEUE. LEFT OVER TOKENS: ";
- foreach (const DebuggerCommand &cmd, m_commandForToken)
+ for (const DebuggerCommand &cmd : qAsConst(m_commandForToken))
ts << "CMD:" << cmd.function;
m_commandForToken.clear();
m_flagsForToken.clear();
@@ -4667,7 +4666,7 @@ void GdbEngine::interruptInferior2()
} else if (isTermEngine()) {
- terminal()->interruptProcess();
+ terminal()->interrupt();
}
}
@@ -5013,8 +5012,8 @@ CoreInfo CoreInfo::readExecutableNameFromCore(const Runnable &debugger, const Fi
proc.setCommand({debugger.command.executable(), args});
proc.runBlocking();
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- QString output = proc.stdOut();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ QString output = proc.cleanedStdOut();
// Core was generated by `/data/dev/creator-2.6/bin/qtcreator'.
// Program terminated with signal 11, Segmentation fault.
int pos1 = output.indexOf("Core was generated by");
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 54ee843ed23..49a090951a8 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -111,8 +111,8 @@ private: ////////// General Interface //////////
// The engine is still running just fine, but it failed to acquire a debuggee.
void notifyInferiorSetupFailedHelper(const QString &msg);
- void handleGdbFinished();
- void handleGdbError(QProcess::ProcessError error);
+ void handleGdbStarted();
+ void handleGdbDone();
void readGdbStandardOutput();
void readGdbStandardError();
void readDebuggeeOutput(const QByteArray &ba);
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index 287014ab7c8..5d54fc56b59 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -35,6 +35,7 @@
#include <debugger/terminal.h>
#include <debugger/breakhandler.h>
+#include <debugger/debuggeritem.h>
#include <debugger/debuggersourcepathmappingwidget.h>
#include <debugger/disassemblerlines.h>
#include <debugger/moduleshandler.h>
@@ -49,6 +50,7 @@
#include <coreplugin/idocument.h>
#include <coreplugin/icore.h>
+#include <utils/processinterface.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -82,27 +84,23 @@ static int &currentToken()
///////////////////////////////////////////////////////////////////////
LldbEngine::LldbEngine()
- : m_lldbProc(ProcessMode::Writer)
{
+ m_lldbProc.setUseCtrlCStub(true);
+ m_lldbProc.setProcessMode(ProcessMode::Writer);
+
setObjectName("LldbEngine");
setDebuggerName("LLDB");
DebuggerSettings &ds = *debuggerSettings();
- connect(&ds.autoDerefPointers, &BaseAspect::changed,
- this, &LldbEngine::updateLocals);
+ connect(&ds.autoDerefPointers, &BaseAspect::changed, this, &LldbEngine::updateLocals);
connect(ds.createFullBacktrace.action(), &QAction::triggered,
this, &LldbEngine::fetchFullBacktrace);
- connect(&ds.useDebuggingHelpers, &BaseAspect::changed,
- this, &LldbEngine::updateLocals);
- connect(&ds.useDynamicType, &BaseAspect::changed,
- this, &LldbEngine::updateLocals);
- connect(&ds.intelFlavor, &BaseAspect::changed,
- this, &LldbEngine::updateAll);
-
- connect(&m_lldbProc, &QtcProcess::errorOccurred,
- this, &LldbEngine::handleLldbError);
- connect(&m_lldbProc, &QtcProcess::finished,
- this, &LldbEngine::handleLldbFinished);
+ connect(&ds.useDebuggingHelpers, &BaseAspect::changed, this, &LldbEngine::updateLocals);
+ connect(&ds.useDynamicType, &BaseAspect::changed, this, &LldbEngine::updateLocals);
+ connect(&ds.intelFlavor, &BaseAspect::changed, this, &LldbEngine::updateAll);
+
+ connect(&m_lldbProc, &QtcProcess::started, this, &LldbEngine::handleLldbStarted);
+ connect(&m_lldbProc, &QtcProcess::done, this, &LldbEngine::handleLldbDone);
connect(&m_lldbProc, &QtcProcess::readyReadStandardOutput,
this, &LldbEngine::readLldbStandardOutput);
connect(&m_lldbProc, &QtcProcess::readyReadStandardError,
@@ -112,11 +110,6 @@ LldbEngine::LldbEngine()
this, &LldbEngine::handleResponse, Qt::QueuedConnection);
}
-LldbEngine::~LldbEngine()
-{
- m_lldbProc.disconnect();
-}
-
void LldbEngine::executeDebuggerCommand(const QString &command)
{
DebuggerCommand cmd("executeDebuggerCommand");
@@ -152,7 +145,7 @@ void LldbEngine::runCommand(const DebuggerCommand &command)
}
showMessage(msg, LogInput);
m_commandForToken[currentToken()] = cmd;
- executeCommand("script theDumper." + function.toUtf8());
+ executeCommand("script theDumper." + function);
}
void LldbEngine::debugLastCommand()
@@ -169,7 +162,7 @@ void LldbEngine::handleAttachedToCore()
updateLocals();
}
-void LldbEngine::executeCommand(const QByteArray &command)
+void LldbEngine::executeCommand(const QString &command)
{
// For some reason, sometimes LLDB misses the first character of the next command on Windows
// if passing only 1 LF.
@@ -185,16 +178,13 @@ void LldbEngine::shutdownInferior()
void LldbEngine::shutdownEngine()
{
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
- if (m_lldbProc.isRunning())
- m_lldbProc.terminate();
- else
- notifyEngineShutdownFinished();
+ abortDebuggerProcess();
}
void LldbEngine::abortDebuggerProcess()
{
if (m_lldbProc.isRunning())
- m_lldbProc.kill();
+ m_lldbProc.stop();
else
notifyEngineShutdownFinished();
}
@@ -214,6 +204,22 @@ void LldbEngine::setupEngine()
Environment environment = runParameters().debugger.environment;
environment.appendOrSet("PYTHONUNBUFFERED", "1"); // avoid flushing problem on macOS
DebuggerItem::addAndroidLldbPythonEnv(lldbCmd, environment);
+
+ if (lldbCmd.osType() == OsTypeLinux) {
+ // LLDB 14 installation on Ubuntu 22.04 is broken:
+ // https://bugs.launchpad.net/ubuntu/+source/llvm-defaults/+bug/1972855
+ // Brush over it:
+ QtcProcess lldbPythonPathFinder;
+ lldbPythonPathFinder.setCommand({lldbCmd, {"-P"}});
+ lldbPythonPathFinder.start();
+ lldbPythonPathFinder.waitForFinished();
+ QString lldbPythonPath = lldbPythonPathFinder.cleanedStdOut();
+ if (lldbPythonPath.endsWith('\n'))
+ lldbPythonPath.chop(1);
+ if (lldbPythonPath == "/usr/lib/local/lib/python3.10/dist-packages")
+ environment.appendOrSet("PYTHONPATH", "/usr/lib/llvm-14/lib/python3.10/dist-packages");
+ }
+
m_lldbProc.setEnvironment(environment);
if (runParameters().debugger.workingDirectory.isDir())
@@ -225,30 +231,23 @@ void LldbEngine::setupEngine()
m_lldbProc.setCommand(CommandLine(lldbCmd));
m_lldbProc.start();
+}
- if (!m_lldbProc.waitForStarted()) {
- const QString msg = tr("Unable to start LLDB \"%1\": %2")
- .arg(lldbCmd.toUserOutput(), m_lldbProc.errorString());
- notifyEngineSetupFailed();
- showMessage("ADAPTER START FAILED");
- if (!msg.isEmpty())
- ICore::showWarningWithOptions(adapterStartFailed(), msg);
- return;
- }
+void LldbEngine::handleLldbStarted()
+{
m_lldbProc.waitForReadyRead(1000);
showStatusMessage(tr("Setting up inferior..."));
const DebuggerRunParameters &rp = runParameters();
- executeCommand("script sys.path.insert(1, '" + rp.dumperPath.path().toLocal8Bit() + "')");
+ executeCommand("script sys.path.insert(1, '" + rp.dumperPath.path() + "')");
// This triggers reportState("enginesetupok") or "enginesetupfailed":
executeCommand("script from lldbbridge import *");
QString commands = nativeStartupCommands();
if (!commands.isEmpty())
- executeCommand(commands.toLocal8Bit());
-
+ executeCommand(commands);
const QString path = debuggerSettings()->extraDumperFile.value();
if (!path.isEmpty() && QFileInfo(path).isReadable()) {
@@ -279,6 +278,9 @@ void LldbEngine::setupEngine()
"settings append target.source-map " + it.key() + ' ' + expand(it.value()));
}
+ for (const QString &path : rp.solibSearchPath)
+ executeDebuggerCommand("settings append target.exec-search-paths " + path);
+
DebuggerCommand cmd2("setupInferior");
cmd2.arg("executable", rp.inferior.command.executable().toString());
cmd2.arg("breakonmain", rp.breakOnMain);
@@ -782,12 +784,26 @@ void LldbEngine::doUpdateLocals(const UpdateParameters &params)
runCommand(cmd);
}
-void LldbEngine::handleLldbError(QProcess::ProcessError error)
+void LldbEngine::handleLldbDone()
{
+ if (m_lldbProc.result() == ProcessResult::StartFailed) {
+ notifyEngineSetupFailed();
+ showMessage("ADAPTER START FAILED");
+ ICore::showWarningWithOptions(adapterStartFailed(), tr("Unable to start LLDB \"%1\": %2")
+ .arg(runParameters().debugger.command.executable().toUserOutput(),
+ m_lldbProc.errorString()));
+ return;
+ }
+
+ if (m_lldbProc.error() == QProcess::UnknownError) {
+ notifyDebuggerProcessFinished(m_lldbProc.resultData(), "LLDB");
+ return;
+ }
+
+ const QProcess::ProcessError error = m_lldbProc.error();
showMessage(QString("LLDB PROCESS ERROR: %1").arg(error));
switch (error) {
case QProcess::Crashed:
- m_lldbProc.disconnect();
notifyEngineShutdownFinished();
break; // will get a processExited() as well
// impossible case QProcess::FailedToStart:
@@ -796,7 +812,6 @@ void LldbEngine::handleLldbError(QProcess::ProcessError error)
case QProcess::Timedout:
default:
//setState(EngineShutdownRequested, true);
- m_lldbProc.kill();
AsynchronousMessageBox::critical(tr("LLDB I/O Error"), errorMessage(error));
break;
}
@@ -829,11 +844,6 @@ QString LldbEngine::errorMessage(QProcess::ProcessError error) const
}
}
-void LldbEngine::handleLldbFinished()
-{
- notifyDebuggerProcessFinished(m_lldbProc.exitCode(), m_lldbProc.exitStatus(), "LLDB");
-}
-
void LldbEngine::readLldbStandardError()
{
QString err = QString::fromUtf8(m_lldbProc.readAllStandardError());
@@ -921,7 +931,7 @@ void LldbEngine::handleStateNotification(const GdbMi &item)
void LldbEngine::handleLocationNotification(const GdbMi &reportedLocation)
{
qulonglong address = reportedLocation["address"].toAddress();
- Utils::FilePath fileName = FilePath::fromUserInput(reportedLocation["file"].data());
+ FilePath fileName = FilePath::fromUserInput(reportedLocation["file"].data());
QString function = reportedLocation["function"].data();
int lineNumber = reportedLocation["line"].toInt();
Location loc = Location(fileName, lineNumber);
diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h
index 4d80c0b9fd6..5a0f7d63284 100644
--- a/src/plugins/debugger/lldb/lldbengine.h
+++ b/src/plugins/debugger/lldb/lldbengine.h
@@ -53,7 +53,6 @@ class LldbEngine : public CppDebuggerEngine
public:
LldbEngine();
- ~LldbEngine() override;
signals:
void outputReady(const QString &data);
@@ -111,8 +110,8 @@ private:
QString errorMessage(QProcess::ProcessError error) const;
bool hasCapability(unsigned cap) const override;
- void handleLldbFinished();
- void handleLldbError(QProcess::ProcessError error);
+ void handleLldbStarted();
+ void handleLldbDone();
void readLldbStandardOutput();
void readLldbStandardError();
@@ -130,7 +129,7 @@ private:
void runCommand(const DebuggerCommand &cmd) override;
void debugLastCommand() override;
void handleAttachedToCore();
- void executeCommand(const QByteArray &command);
+ void executeCommand(const QString &command);
private:
DebuggerCommand m_lastDebuggableCommand;
diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp
index b5d04ead15c..39a753f3eb7 100644
--- a/src/plugins/debugger/loadcoredialog.cpp
+++ b/src/plugins/debugger/loadcoredialog.cpp
@@ -25,22 +25,21 @@
#include "loadcoredialog.h"
-#include "debuggerdialogs.h"
#include "debuggerkitinformation.h"
#include "gdb/gdbengine.h"
-#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/devicesupport/devicefilesystemmodel.h>
+#include <projectexplorer/devicesupport/filetransfer.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/kitchooser.h>
#include <projectexplorer/projectexplorerconstants.h>
-#include <ssh/sftpfilesystemmodel.h>
-#include <ssh/sshconnection.h>
+
#include <utils/pathchooser.h>
+#include <utils/processinterface.h>
#include <utils/qtcassert.h>
#include <utils/temporaryfile.h>
#include <QCheckBox>
-#include <QDebug>
-#include <QDir>
-
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QHeaderView>
@@ -53,7 +52,6 @@
using namespace Core;
using namespace ProjectExplorer;
-using namespace QSsh;
using namespace Utils;
namespace Debugger {
@@ -77,20 +75,16 @@ public:
FilePath remoteFile() const { return m_remoteFile; }
private:
- void handleSftpOperationFinished(SftpJobId, const QString &error);
- void handleSftpOperationFailed(const QString &errorMessage);
- void handleConnectionError(const QString &errorMessage);
- void handleRemoteError(const QString &errorMessage);
void selectFile();
QSortFilterProxyModel m_model;
- SftpFileSystemModel m_fileSystemModel;
+ DeviceFileSystemModel m_fileSystemModel;
QTreeView *m_fileSystemView;
QTextBrowser *m_textBrowser;
QDialogButtonBox *m_buttonBox;
FilePath m_localFile;
FilePath m_remoteFile;
- SftpJobId m_sftpJobId;
+ FileTransfer m_fileTransfer;
};
SelectRemoteFileDialog::SelectRemoteFileDialog(QWidget *parent)
@@ -109,7 +103,7 @@ SelectRemoteFileDialog::SelectRemoteFileDialog(QWidget *parent)
m_fileSystemView->header()->setStretchLastSection(true);
m_textBrowser = new QTextBrowser(this);
- m_textBrowser->setEnabled(false);
+ m_textBrowser->setReadOnly(true);
m_buttonBox = new QDialogButtonBox(this);
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
@@ -121,15 +115,23 @@ SelectRemoteFileDialog::SelectRemoteFileDialog(QWidget *parent)
layout->addWidget(m_textBrowser);
layout->addWidget(m_buttonBox);
- connect(m_buttonBox, &QDialogButtonBox::rejected,
- this, &QDialog::reject);
- connect(m_buttonBox, &QDialogButtonBox::accepted,
- this, &SelectRemoteFileDialog::selectFile);
-
- connect(&m_fileSystemModel, &SftpFileSystemModel::sftpOperationFailed,
- this, &SelectRemoteFileDialog::handleSftpOperationFailed);
- connect(&m_fileSystemModel, &SftpFileSystemModel::connectionError,
- this, &SelectRemoteFileDialog::handleConnectionError);
+ connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ connect(m_buttonBox, &QDialogButtonBox::accepted, this, &SelectRemoteFileDialog::selectFile);
+
+ connect(&m_fileTransfer, &FileTransfer::done, this, [this](const ProcessResultData &result) {
+ const bool success = result.m_error == QProcess::UnknownError
+ && result.m_exitStatus == QProcess::NormalExit
+ && result.m_exitCode == 0;
+ if (success) {
+ m_textBrowser->append(tr("Download of remote file succeeded."));
+ accept();
+ } else {
+ m_textBrowser->append(tr("Download of remote file failed: %1")
+ .arg(result.m_errorString));
+ m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
+ m_fileSystemView->setEnabled(true);
+ }
+ });
}
void SelectRemoteFileDialog::attachToDevice(Kit *k)
@@ -138,36 +140,7 @@ void SelectRemoteFileDialog::attachToDevice(Kit *k)
QTC_ASSERT(k, return);
IDevice::ConstPtr device = DeviceKitAspect::device(k);
QTC_ASSERT(device, return);
- SshConnectionParameters sshParams = device->sshParameters();
- m_fileSystemModel.setSshConnection(sshParams);
-}
-
-void SelectRemoteFileDialog::handleSftpOperationFailed(const QString &errorMessage)
-{
- m_textBrowser->append(errorMessage);
- //reject();
-}
-
-void SelectRemoteFileDialog::handleConnectionError(const QString &errorMessage)
-{
- m_textBrowser->append(errorMessage);
- //reject();
-}
-
-void SelectRemoteFileDialog::handleSftpOperationFinished(SftpJobId, const QString &error)
-{
- if (error.isEmpty()) {
- m_textBrowser->append(tr("Download of remote file succeeded."));
- accept();
- } else {
- m_textBrowser->append(error);
- //reject();
- }
-}
-
-void SelectRemoteFileDialog::handleRemoteError(const QString &errorMessage)
-{
- m_textBrowser->append(errorMessage);
+ m_fileSystemModel.setDevice(device);
}
void SelectRemoteFileDialog::selectFile()
@@ -179,18 +152,17 @@ void SelectRemoteFileDialog::selectFile()
m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
m_fileSystemView->setEnabled(false);
- connect(&m_fileSystemModel, &SftpFileSystemModel::sftpOperationFinished,
- this, &SelectRemoteFileDialog::handleSftpOperationFinished);
-
{
- Utils::TemporaryFile localFile("remotecore-XXXXXX");
+ TemporaryFile localFile("remotecore-XXXXXX");
localFile.open();
m_localFile = FilePath::fromString(localFile.fileName());
}
idx = idx.sibling(idx.row(), 1);
- m_remoteFile = FilePath::fromVariant(m_fileSystemModel.data(idx, SftpFileSystemModel::PathRole));
- m_sftpJobId = m_fileSystemModel.downloadFile(idx, m_localFile.toString());
+ m_remoteFile = FilePath::fromVariant(m_fileSystemModel.data(idx, DeviceFileSystemModel::PathRole));
+
+ m_fileTransfer.setFilesToTransfer({{m_remoteFile, m_localFile}});
+ m_fileTransfer.start();
}
///////////////////////////////////////////////////////////////////////
diff --git a/src/plugins/debugger/loadcoredialog.h b/src/plugins/debugger/loadcoredialog.h
index de181c9844e..6935773f496 100644
--- a/src/plugins/debugger/loadcoredialog.h
+++ b/src/plugins/debugger/loadcoredialog.h
@@ -35,8 +35,6 @@ namespace Utils { class FilePath; }
namespace Debugger {
namespace Internal {
-class AttachCoreDialogPrivate;
-
class AttachCoreDialog : public QDialog
{
Q_OBJECT
@@ -71,9 +69,8 @@ private:
void coreFileChanged(const QString &core);
void selectRemoteCoreFile();
- AttachCoreDialogPrivate *d;
+ class AttachCoreDialogPrivate *d;
};
-
} // namespace Debugger
} // namespace Internal
diff --git a/src/plugins/debugger/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp
index a040c7f1feb..4f4e8a75d1e 100644
--- a/src/plugins/debugger/moduleshandler.cpp
+++ b/src/plugins/debugger/moduleshandler.cpp
@@ -33,6 +33,7 @@
#include <utils/basetreeview.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/treemodel.h>
#include <QCoreApplication>
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index 5eae3b34821..54375baf7f1 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -42,6 +42,7 @@
#include <debugger/watchhandler.h>
#include <debugger/watchutils.h>
+#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -63,8 +64,10 @@ using namespace Utils;
namespace Debugger {
namespace Internal {
-PdbEngine::PdbEngine() : m_proc(ProcessMode::Writer)
+PdbEngine::PdbEngine()
{
+ m_proc.setProcessMode(ProcessMode::Writer);
+
setObjectName("PdbEngine");
setDebuggerName("PDB");
}
@@ -84,7 +87,7 @@ void PdbEngine::postDirectCommand(const QString &command)
{
QTC_ASSERT(m_proc.isRunning(), notifyEngineIll());
showMessage(command, LogInput);
- m_proc.write(command.toUtf8() + '\n');
+ m_proc.write(command + '\n');
}
void PdbEngine::runCommand(const DebuggerCommand &cmd)
@@ -96,7 +99,7 @@ void PdbEngine::runCommand(const DebuggerCommand &cmd)
QTC_ASSERT(m_proc.isRunning(), notifyEngineIll());
QString command = "qdebug('" + cmd.function + "'," + cmd.argsToPython() + ")";
showMessage(command, LogInput);
- m_proc.write(command.toUtf8() + '\n');
+ m_proc.write(command + '\n');
}
void PdbEngine::shutdownInferior()
@@ -118,37 +121,28 @@ void PdbEngine::setupEngine()
m_interpreter = runParameters().interpreter;
QString bridge = ICore::resourcePath("debugger/pdbbridge.py").toString();
- connect(&m_proc, &QtcProcess::errorOccurred, this, &PdbEngine::handlePdbError);
- connect(&m_proc, &QtcProcess::finished, this, &PdbEngine::handlePdbFinished);
+ connect(&m_proc, &QtcProcess::started, this, &PdbEngine::handlePdbStarted);
+ connect(&m_proc, &QtcProcess::done, this, &PdbEngine::handlePdbDone);
connect(&m_proc, &QtcProcess::readyReadStandardOutput, this, &PdbEngine::readPdbStandardOutput);
connect(&m_proc, &QtcProcess::readyReadStandardError, this, &PdbEngine::readPdbStandardError);
- QFile scriptFile(runParameters().mainScript);
- if (!scriptFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ const FilePath scriptFile = runParameters().mainScript;
+ if (!scriptFile.isReadableFile()) {
AsynchronousMessageBox::critical(tr("Python Error"),
- QString("Cannot open script file %1:\n%2").
- arg(scriptFile.fileName(), scriptFile.errorString()));
+ QString("Cannot open script file %1").arg(scriptFile.toUserOutput()));
notifyEngineSetupFailed();
}
- QStringList args = {bridge, scriptFile.fileName()};
- args.append(ProcessArgs::splitArgs(runParameters().inferior.workingDirectory.path()));
- showMessage("STARTING " + m_interpreter + ' ' + args.join(' '));
+ CommandLine cmd{m_interpreter, {bridge, scriptFile.path()}};
+ cmd.addArg(runParameters().inferior.workingDirectory.path());
+ showMessage("STARTING " + cmd.toUserOutput());
m_proc.setEnvironment(runParameters().debugger.environment);
- m_proc.setCommand({ FilePath::fromString(m_interpreter), args });
+ m_proc.setCommand(cmd);
m_proc.start();
+}
- if (!m_proc.waitForStarted()) {
- const QString msg = tr("Unable to start pdb \"%1\": %2")
- .arg(m_interpreter, m_proc.errorString());
- notifyEngineSetupFailed();
- showMessage("ADAPTER START FAILED");
- if (!msg.isEmpty())
- ICore::showWarningWithOptions(tr("Adapter start failed"), msg);
- notifyEngineSetupFailed();
- return;
- }
-
+void PdbEngine::handlePdbStarted()
+{
notifyEngineSetupOk();
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
@@ -389,24 +383,6 @@ void PdbEngine::updateItem(const QString &iname)
updateAll();
}
-void PdbEngine::handlePdbError(QProcess::ProcessError error)
-{
- showMessage("HANDLE PDB ERROR");
- switch (error) {
- case QProcess::Crashed:
- break; // will get a processExited() as well
- // impossible case QProcess::FailedToStart:
- case QProcess::ReadError:
- case QProcess::WriteError:
- case QProcess::Timedout:
- default:
- //setState(EngineShutdownRequested, true);
- m_proc.kill();
- AsynchronousMessageBox::critical(tr("Pdb I/O Error"), errorMessage(error));
- break;
- }
-}
-
QString PdbEngine::errorMessage(QProcess::ProcessError error) const
{
switch (error) {
@@ -414,7 +390,7 @@ QString PdbEngine::errorMessage(QProcess::ProcessError error) const
return tr("The Pdb process failed to start. Either the "
"invoked program \"%1\" is missing, or you may have insufficient "
"permissions to invoke the program.")
- .arg(m_interpreter);
+ .arg(m_interpreter.toUserOutput());
case QProcess::Crashed:
return tr("The Pdb process crashed some time after starting "
"successfully.");
@@ -434,8 +410,23 @@ QString PdbEngine::errorMessage(QProcess::ProcessError error) const
}
}
-void PdbEngine::handlePdbFinished()
+void PdbEngine::handlePdbDone()
{
+ if (m_proc.result() == ProcessResult::StartFailed) {
+ notifyEngineSetupFailed();
+ showMessage("ADAPTER START FAILED");
+ ICore::showWarningWithOptions(tr("Adapter start failed"), m_proc.exitMessage());
+ return;
+ }
+
+ const QProcess::ProcessError error = m_proc.error();
+ if (error != QProcess::UnknownError) {
+ showMessage("HANDLE PDB ERROR");
+ if (error != QProcess::Crashed)
+ AsynchronousMessageBox::critical(tr("Pdb I/O Error"), errorMessage(error));
+ if (error == QProcess::FailedToStart)
+ return;
+ }
showMessage(QString("PDB PROCESS FINISHED, status %1, code %2")
.arg(m_proc.exitStatus()).arg(m_proc.exitCode()));
notifyEngineSpontaneousShutdown();
diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h
index 0c645de55d3..efde41e2ce9 100644
--- a/src/plugins/debugger/pdb/pdbengine.h
+++ b/src/plugins/debugger/pdb/pdbengine.h
@@ -100,8 +100,8 @@ private:
QString errorMessage(QProcess::ProcessError error) const;
bool hasCapability(unsigned cap) const override;
- void handlePdbFinished();
- void handlePdbError(QProcess::ProcessError error);
+ void handlePdbStarted();
+ void handlePdbDone();
void readPdbStandardOutput();
void readPdbStandardError();
void handleOutput2(const QString &data);
@@ -112,7 +112,7 @@ private:
QString m_inbuffer;
Utils::QtcProcess m_proc;
- QString m_interpreter;
+ Utils::FilePath m_interpreter;
};
} // namespace Internal
diff --git a/src/plugins/debugger/peripheralregisterhandler.cpp b/src/plugins/debugger/peripheralregisterhandler.cpp
index 2cdf51c9773..b1748d3b986 100644
--- a/src/plugins/debugger/peripheralregisterhandler.cpp
+++ b/src/plugins/debugger/peripheralregisterhandler.cpp
@@ -37,6 +37,7 @@
#include <QLineEdit>
#include <QMenu>
#include <QPainter>
+#include <QXmlStreamReader>
using namespace Utils;
@@ -731,12 +732,9 @@ void PeripheralRegisterHandler::updateRegisterGroups()
clear();
const DebuggerRunParameters &rp = m_engine->runParameters();
- const FilePath peripheralDescriptionFile = FilePath::fromVariant(
- rp.inferior.extraData.value(Debugger::Constants::kPeripheralDescriptionFile));
-
- if (!peripheralDescriptionFile.exists())
+ if (!rp.peripheralDescriptionFile.exists())
return;
- m_peripheralRegisterGroups = availablePeripheralRegisterGroups(peripheralDescriptionFile);
+ m_peripheralRegisterGroups = availablePeripheralRegisterGroups(rp.peripheralDescriptionFile);
}
void PeripheralRegisterHandler::updateRegister(quint64 address, quint64 value)
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index db0df2dd232..9687179c44b 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -47,7 +47,8 @@
#include <coreplugin/helpmanager.h>
#include <coreplugin/icore.h>
-#include <projectexplorer/applicationlauncher.h>
+#include <projectexplorer/projectnodes.h>
+#include <projectexplorer/projecttree.h>
#include <qmljseditor/qmljseditorconstants.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
@@ -58,10 +59,12 @@
#include <texteditor/texteditor.h>
#include <app/app_version.h>
-#include <utils/treemodel.h>
+
#include <utils/basetreeview.h>
#include <utils/fileinprojectfinder.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+#include <utils/treemodel.h>
#include <QDebug>
#include <QDir>
@@ -220,7 +223,7 @@ public:
QHash<QString, QTextDocument*> sourceDocuments;
InteractiveInterpreter interpreter;
- ApplicationLauncher applicationLauncher;
+ QtcProcess process;
QmlInspectorAgent inspectorAgent;
QList<quint32> queryIds;
@@ -269,12 +272,17 @@ QmlEngine::QmlEngine()
connect(stackHandler(), &StackHandler::currentIndexChanged,
this, &QmlEngine::updateCurrentContext);
- connect(&d->applicationLauncher, &ApplicationLauncher::processExited,
- this, &QmlEngine::disconnected);
- connect(&d->applicationLauncher, &ApplicationLauncher::appendMessage,
- this, &QmlEngine::appMessage);
- connect(&d->applicationLauncher, &ApplicationLauncher::processStarted,
- this, &QmlEngine::handleLauncherStarted);
+ connect(&d->process, &QtcProcess::readyReadStandardOutput, this, [this] {
+ // FIXME: Redirect to RunControl
+ showMessage(QString::fromUtf8(d->process.readAllStandardOutput()), AppOutput);
+ });
+ connect(&d->process, &QtcProcess::readyReadStandardError, this, [this] {
+ // FIXME: Redirect to RunControl
+ showMessage(QString::fromUtf8(d->process.readAllStandardError()), AppOutput);
+ });
+
+ connect(&d->process, &QtcProcess::done, this, &QmlEngine::disconnected);
+ connect(&d->process, &QtcProcess::started, this, &QmlEngine::handleLauncherStarted);
debuggerConsole()->populateFileFinder();
debuggerConsole()->setScriptEvaluator([this](const QString &expr) {
@@ -329,11 +337,6 @@ void QmlEngine::handleLauncherStarted()
tryToConnect();
}
-void QmlEngine::appMessage(const QString &msg, Utils::OutputFormat /* format */)
-{
- showMessage(msg, AppOutput); // FIXME: Redirect to RunControl
-}
-
void QmlEngine::connectionEstablished()
{
connect(inspectorView(), &WatchTreeView::currentIndexChanged,
@@ -472,7 +475,8 @@ void QmlEngine::gotoLocation(const Location &location)
QString titlePattern = tr("JS Source for %1").arg(fileName);
//Check if there are open documents with the same title
- foreach (IDocument *document, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document: documents) {
if (document->displayName() == titlePattern) {
EditorManager::activateEditorForDocument(document);
return;
@@ -501,23 +505,23 @@ void QmlEngine::closeConnection()
}
}
-void QmlEngine::startApplicationLauncher()
+void QmlEngine::startProcess()
{
- if (!d->applicationLauncher.isRunning()) {
- const Runnable runnable = runParameters().inferior;
- showMessage(tr("Starting %1").arg(runnable.command.toUserOutput()),
- NormalMessageFormat);
- d->applicationLauncher.start(runnable);
- }
+ if (d->process.isRunning())
+ return;
+
+ d->process.setCommand(runParameters().inferior.command);
+ d->process.setWorkingDirectory(runParameters().inferior.workingDirectory);
+ d->process.setEnvironment(runParameters().inferior.environment);
+ showMessage(tr("Starting %1").arg(d->process.commandLine().toUserOutput()),
+ NormalMessageFormat);
+ d->process.start();
}
-void QmlEngine::stopApplicationLauncher()
+void QmlEngine::stopProcess()
{
- if (d->applicationLauncher.isRunning()) {
- disconnect(&d->applicationLauncher, &ApplicationLauncher::processExited,
- this, &QmlEngine::disconnected);
- d->applicationLauncher.stop();
- }
+ if (d->process.isRunning())
+ d->process.close();
}
void QmlEngine::shutdownInferior()
@@ -531,7 +535,7 @@ void QmlEngine::shutdownInferior()
d->runCommand({DISCONNECT});
resetLocation();
- stopApplicationLauncher();
+ stopProcess();
closeConnection();
notifyInferiorShutdownFinished();
@@ -544,7 +548,7 @@ void QmlEngine::shutdownEngine()
debuggerConsole()->setScriptEvaluator(ScriptEvaluator());
// double check (ill engine?):
- stopApplicationLauncher();
+ stopProcess();
notifyEngineShutdownFinished();
}
@@ -568,7 +572,7 @@ void QmlEngine::setupEngine()
else if (runParameters().startMode == AttachToRemoteProcess)
beginConnection();
else
- startApplicationLauncher();
+ startProcess();
} else {
tryToConnect();
}
@@ -893,7 +897,7 @@ static ConsoleItem *constructLogItemTree(const QVariant &result,
std::sort(children.begin(), children.end(), compareConsoleItems);
item = new ConsoleItem(ConsoleItem::DefaultType, text);
- foreach (ConsoleItem *child, children) {
+ for (ConsoleItem *child : qAsConst(children)) {
if (child)
item->appendChild(child);
}
@@ -913,7 +917,7 @@ static ConsoleItem *constructLogItemTree(const QVariant &result,
std::sort(children.begin(), children.end(), compareConsoleItems);
item = new ConsoleItem(ConsoleItem::DefaultType, text);
- foreach (ConsoleItem *child, children) {
+ for (ConsoleItem *child : qAsConst(children)) {
if (child)
item->appendChild(child);
}
@@ -956,7 +960,7 @@ void QmlEngine::quitDebugger()
{
d->automaticConnect = false;
d->retryOnConnectFail = false;
- stopApplicationLauncher();
+ stopProcess();
closeConnection();
}
@@ -1100,7 +1104,8 @@ void QmlEnginePrivate::updateScriptSource(const QString &fileName, int lineOffse
//update open editors
QString titlePattern = QCoreApplication::translate("QmlEngine", "JS Source for %1").arg(fileName);
//Check if there are open editors with the same title
- foreach (IDocument *doc, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *doc: documents) {
if (doc->displayName() == titlePattern) {
updateDocument(doc, document);
break;
@@ -1382,6 +1387,17 @@ void QmlEnginePrivate::scripts(int types, const QList<int> ids, bool includeSour
runCommand(cmd);
}
+static QString targetFile(const FilePath &original)
+{
+ auto projectTree = ProjectExplorer::ProjectTree::instance();
+ auto node = projectTree->nodeForFile(original);
+
+ if (auto resourceNode = dynamic_cast<ProjectExplorer::ResourceFileNode *>(node))
+ return QLatin1String("qrc:") + resourceNode->qrcPath();
+
+ return original.fileName();
+}
+
void QmlEnginePrivate::setBreakpoint(const QString type, const QString target,
bool enabled, int line, int column,
const QString condition, int ignoreCount)
@@ -1411,7 +1427,7 @@ void QmlEnginePrivate::setBreakpoint(const QString type, const QString target,
cmd.arg(ENABLED, enabled);
if (type == SCRIPTREGEXP)
- cmd.arg(TARGET, Utils::FilePath::fromString(target).fileName());
+ cmd.arg(TARGET, targetFile(FilePath::fromString(target)));
else
cmd.arg(TARGET, target);
@@ -1644,7 +1660,8 @@ void QmlEnginePrivate::runDirectCommand(const QString &type, const QByteArray &m
void QmlEnginePrivate::memorizeRefs(const QVariant &refs)
{
if (refs.isValid()) {
- foreach (const QVariant &ref, refs.toList()) {
+ const QList<QVariant> refList = refs.toList();
+ for (const QVariant &ref : refList) {
const QVariantMap refData = ref.toMap();
int handle = refData.value(HANDLE).toInt();
refVals[handle] = extractData(refData);
@@ -1809,7 +1826,7 @@ void QmlEnginePrivate::messageReceived(const QByteArray &data)
}
QMap<QString,QString> files;
- foreach (const QString &file, sourceFiles) {
+ for (const QString &file : qAsConst(sourceFiles)) {
QString shortName = file;
QString fullName = engine->toFileInProject(file);
files.insert(shortName, fullName);
@@ -1838,6 +1855,13 @@ void QmlEnginePrivate::messageReceived(const QByteArray &data)
QList<Breakpoint> v8Breakpoints;
const QVariantList v8BreakpointIdList = breakData.value("breakpoints").toList();
+ // skip debug break if no breakpoint and we have not done a single step as last
+ // action - likely stopped in another file with same naming
+ if (v8BreakpointIdList.isEmpty() && previousStepAction == Continue) {
+ inferiorStop = false;
+ continueDebugging(Continue);
+ }
+
for (const QVariant &breakpointId : v8BreakpointIdList) {
const QString responseId = QString::number(breakpointId.toInt());
Breakpoint bp = engine->breakHandler()->findBreakpointByResponseId(responseId);
@@ -2236,7 +2260,7 @@ void QmlEnginePrivate::constructChildLogItems(ConsoleItem *item, const QmlV8Obje
if (debuggerSettings()->sortStructMembers.value())
std::sort(children.begin(), children.end(), compareConsoleItems);
- foreach (ConsoleItem *child, children)
+ for (ConsoleItem *child : qAsConst(children))
item->appendChild(child);
}
@@ -2362,7 +2386,7 @@ void QmlEnginePrivate::handleExecuteDebuggerCommand(const QVariantMap &response)
debuggerConsole()->printItem(constructLogItemTree(extractData(response.value(BODY))));
// Update the locals
- foreach (int index, currentFrameScopes)
+ for (int index : qAsConst(currentFrameScopes))
scope(index);
} else {
debuggerConsole()->printItem(new ConsoleItem(ConsoleItem::ErrorType,
@@ -2437,7 +2461,7 @@ void QmlEnginePrivate::handleVersion(const QVariantMap &response)
void QmlEnginePrivate::flushSendBuffer()
{
QTC_ASSERT(state() == Enabled, return);
- foreach (const QByteArray &msg, sendBuffer)
+ for (const QByteArray &msg : qAsConst(sendBuffer))
sendMessage(msg);
sendBuffer.clear();
}
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index 4fc0230a5d7..100901fc25f 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -63,7 +63,6 @@ private:
void connectionEstablished();
void connectionStartupFailed();
void appStartupFailed(const QString &errorMessage);
- void appMessage(const QString &msg, Utils::OutputFormat);
void setState(DebuggerState state, bool forced) override;
@@ -123,8 +122,8 @@ private:
Core::Context languageContext() const override;
void closeConnection();
- void startApplicationLauncher();
- void stopApplicationLauncher();
+ void startProcess();
+ void stopProcess();
void connectionFailed();
diff --git a/src/plugins/debugger/qml/qmlengineutils.cpp b/src/plugins/debugger/qml/qmlengineutils.cpp
index 5b5bef2a86f..3fe5c4c8ddd 100644
--- a/src/plugins/debugger/qml/qmlengineutils.cpp
+++ b/src/plugins/debugger/qml/qmlengineutils.cpp
@@ -237,7 +237,8 @@ void clearExceptionSelection()
{
QList<QTextEdit::ExtraSelection> selections;
- foreach (IEditor *editor, DocumentModel::editorsForOpenedDocuments()) {
+ const QList<IEditor *> editors = DocumentModel::editorsForOpenedDocuments();
+ for (IEditor *editor : editors) {
if (auto ed = TextEditorWidget::fromEditor(editor))
ed->setExtraSelections(TextEditorWidget::DebuggerExceptionSelection, selections);
}
diff --git a/src/plugins/debugger/qml/qmlinspectoragent.cpp b/src/plugins/debugger/qml/qmlinspectoragent.cpp
index 0e9be2bb5dc..3aa668c78d0 100644
--- a/src/plugins/debugger/qml/qmlinspectoragent.cpp
+++ b/src/plugins/debugger/qml/qmlinspectoragent.cpp
@@ -649,7 +649,8 @@ void QmlInspectorAgent::addWatchData(const ObjectReference &obj,
propertiesWatch->value = "list";
propertiesWatch->wantsChildren = true;
- foreach (const PropertyReference &property, obj.properties()) {
+ const QList<PropertyReference> properties = obj.properties();
+ for (const PropertyReference &property : properties) {
const QString propertyName = property.name();
if (propertyName.isEmpty())
continue;
@@ -669,7 +670,8 @@ void QmlInspectorAgent::addWatchData(const ObjectReference &obj,
}
// recurse
- foreach (const ObjectReference &child, obj.children())
+ const QList<ObjectReference> children = obj.children();
+ for (const ObjectReference &child : children)
addWatchData(child, objIname, append);
}
diff --git a/src/plugins/debugger/sourcefileshandler.cpp b/src/plugins/debugger/sourcefileshandler.cpp
index 36b35ec63fa..53ae125ba7e 100644
--- a/src/plugins/debugger/sourcefileshandler.cpp
+++ b/src/plugins/debugger/sourcefileshandler.cpp
@@ -120,12 +120,13 @@ bool SourceFilesHandler::setData(const QModelIndex &idx, const QVariant &data, i
QModelIndex index = idx.sibling(idx.row(), 0);
QString name = index.data().toString();
- auto addAction = [this, menu](const QString &display, bool on, const std::function<void()> &onTriggered) {
- QAction *act = menu->addAction(display);
- act->setEnabled(on);
- QObject::connect(act, &QAction::triggered, onTriggered);
- return act;
- };
+ auto addAction =
+ [menu](const QString &display, bool on, const std::function<void()> &onTriggered) {
+ QAction *act = menu->addAction(display);
+ act->setEnabled(on);
+ QObject::connect(act, &QAction::triggered, onTriggered);
+ return act;
+ };
addAction(tr("Reload Data"), m_engine->debuggerActionsEnabled(),
[this] { m_engine->reloadSourceFiles(); });
diff --git a/src/plugins/debugger/sourceutils.cpp b/src/plugins/debugger/sourceutils.cpp
index 79850bdc420..e13c1afe605 100644
--- a/src/plugins/debugger/sourceutils.cpp
+++ b/src/plugins/debugger/sourceutils.cpp
@@ -70,15 +70,15 @@ static void debugCppSymbolRecursion(QTextStream &str, const Overview &o,
for (int i = 0; i < recursion; i++)
str << " ";
str << "Symbol: " << o.prettyName(s.name()) << " at line " << s.line();
- if (s.isFunction())
+ if (s.asFunction())
str << " function";
- if (s.isClass())
+ if (s.asClass())
str << " class";
- if (s.isDeclaration())
+ if (s.asDeclaration())
str << " declaration";
- if (s.isBlock())
+ if (s.asBlock())
str << " block";
- if (doRecurse && s.isScope()) {
+ if (doRecurse && s.asScope()) {
const Scope *scoped = s.asScope();
const int size = scoped->memberCount();
str << " scoped symbol of " << size << '\n';
@@ -106,17 +106,17 @@ QDebug operator<<(QDebug d, const Scope &scope)
QTextStream str(&output);
const int size = scope.memberCount();
str << "Scope of " << size;
- if (scope.isNamespace())
+ if (scope.asNamespace())
str << " namespace";
- if (scope.isClass())
+ if (scope.asClass())
str << " class";
- if (scope.isEnum())
+ if (scope.asEnum())
str << " enum";
- if (scope.isBlock())
+ if (scope.asBlock())
str << " block";
- if (scope.isFunction())
+ if (scope.asFunction())
str << " function";
- if (scope.isDeclaration())
+ if (scope.asDeclaration())
str << " prototype";
#if 0 // ### port me
if (const Symbol *owner = &scope) {
@@ -168,7 +168,7 @@ static void blockRecursion(const Overview &overview,
// Fixme: loop variables or similar are currently seen in the outer scope
for (int s = scope->memberCount() - 1; s >= 0; --s){
const CPlusPlus::Symbol *symbol = scope->memberAt(s);
- if (symbol->isDeclaration()) {
+ if (symbol->asDeclaration()) {
// Find out about shadowed symbols by bookkeeping
// the already seen occurrences in a hash.
const QString name = overview.prettyName(symbol->name());
@@ -210,7 +210,7 @@ QStringList getUninitializedVariables(const Snapshot &snapshot,
// and the innermost scope at cursor position
const Function *function = nullptr;
const Scope *innerMostScope = nullptr;
- if (symbolAtLine->isFunction()) {
+ if (symbolAtLine->asFunction()) {
function = symbolAtLine->asFunction();
if (function->memberCount() == 1) // Skip over function block
if (Block *block = function->memberAt(0)->asBlock())
@@ -218,7 +218,7 @@ QStringList getUninitializedVariables(const Snapshot &snapshot,
} else {
if (const Scope *functionScope = symbolAtLine->enclosingFunction()) {
function = functionScope->asFunction();
- innerMostScope = symbolAtLine->isBlock() ?
+ innerMostScope = symbolAtLine->asBlock() ?
symbolAtLine->asBlock() :
symbolAtLine->enclosingBlock();
}
@@ -380,7 +380,7 @@ static int firstRelevantLine(const Document::Ptr document, int line, int column)
if (!scope)
scope = symbol->enclosingScope();
- while (scope && !scope->isFunction() )
+ while (scope && !scope->asFunction() )
scope = scope->enclosingScope();
if (!scope)
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index c42c196b09f..4001b854486 100644
--- a/src/plugins/debugger/stackhandler.cpp
+++ b/src/plugins/debugger/stackhandler.cpp
@@ -40,9 +40,8 @@
#include <utils/basetreeview.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
-#include <QApplication>
-#include <QClipboard>
#include <QContextMenuEvent>
#include <QDebug>
#include <QDir>
@@ -410,14 +409,6 @@ static QString selectedText(QWidget *widget, bool useAll)
return str;
}
-static void copyTextToClipboard(const QString &str)
-{
- QClipboard *clipboard = QApplication::clipboard();
- if (clipboard->supportsSelection())
- clipboard->setText(str, QClipboard::Selection);
- clipboard->setText(str, QClipboard::Clipboard);
-}
-
// Write stack frames as task file for displaying it in the build issues pane.
void StackHandler::saveTaskFile()
{
@@ -458,11 +449,11 @@ bool StackHandler::contextMenuEvent(const ItemViewEvent &ev)
menu->addAction(debuggerSettings()->expandStack.action());
addAction(this, menu, tr("Copy Contents to Clipboard"), true, [ev] {
- copyTextToClipboard(selectedText(ev.view(), true));
+ setClipboardAndSelection(selectedText(ev.view(), true));
});
addAction(this, menu, tr("Copy Selection to Clipboard"), true, [ev] {
- copyTextToClipboard(selectedText(ev.view(), false));
+ setClipboardAndSelection(selectedText(ev.view(), false));
});
addAction(this, menu, tr("Save as Task File..."), true, [this] { saveTaskFile(); });
diff --git a/src/plugins/debugger/terminal.cpp b/src/plugins/debugger/terminal.cpp
index fc1d228d787..f2dd9b0b1de 100644
--- a/src/plugins/debugger/terminal.cpp
+++ b/src/plugins/debugger/terminal.cpp
@@ -182,10 +182,10 @@ void TerminalRunner::kickoffProcess()
m_stubProc->kickoffProcess();
}
-void TerminalRunner::interruptProcess()
+void TerminalRunner::interrupt()
{
if (m_stubProc)
- m_stubProc->interruptProcess();
+ m_stubProc->interrupt();
}
void TerminalRunner::start()
@@ -194,15 +194,14 @@ void TerminalRunner::start()
QTC_ASSERT(!m_stubProc, reportFailure({}); return);
Runnable stub = m_stubRunnable();
- const QtcProcess::TerminalMode terminalMode = HostOsInfo::isWindowsHost()
- ? QtcProcess::TerminalSuspend : QtcProcess::TerminalDebug;
- m_stubProc = new QtcProcess(terminalMode, this);
- connect(m_stubProc, &QtcProcess::errorOccurred,
- this, &TerminalRunner::stubError);
+ m_stubProc = new QtcProcess(this);
+ m_stubProc->setTerminalMode(HostOsInfo::isWindowsHost()
+ ? TerminalMode::Suspend : TerminalMode::Debug);
+
connect(m_stubProc, &QtcProcess::started,
this, &TerminalRunner::stubStarted);
- connect(m_stubProc, &QtcProcess::finished,
- this, &TerminalRunner::reportDone);
+ connect(m_stubProc, &QtcProcess::done,
+ this, &TerminalRunner::stubDone);
m_stubProc->setEnvironment(stub.environment);
m_stubProc->setWorkingDirectory(stub.workingDirectory);
@@ -214,21 +213,26 @@ void TerminalRunner::start()
void TerminalRunner::stop()
{
- if (m_stubProc)
- m_stubProc->stopProcess();
+ if (m_stubProc && m_stubProc->isRunning()) {
+ m_stubProc->stop();
+ m_stubProc->waitForFinished();
+ }
reportStopped();
}
void TerminalRunner::stubStarted()
{
m_applicationPid = m_stubProc->processId();
- m_applicationMainThreadId = m_stubProc->applicationMainThreadID();
+ m_applicationMainThreadId = m_stubProc->applicationMainThreadId();
reportStarted();
}
-void TerminalRunner::stubError()
+void TerminalRunner::stubDone()
{
- reportFailure(m_stubProc->errorString());
+ if (m_stubProc->error() != QProcess::UnknownError)
+ reportFailure(m_stubProc->errorString());
+ if (m_stubProc->error() != QProcess::FailedToStart)
+ reportDone();
}
} // namespace Internal
diff --git a/src/plugins/debugger/terminal.h b/src/plugins/debugger/terminal.h
index 2227bdbce4b..1c316d11ed7 100644
--- a/src/plugins/debugger/terminal.h
+++ b/src/plugins/debugger/terminal.h
@@ -78,14 +78,14 @@ public:
qint64 applicationMainThreadId() const { return m_applicationMainThreadId; }
void kickoffProcess();
- void interruptProcess();
+ void interrupt();
private:
void start() final;
void stop() final;
void stubStarted();
- void stubError();
+ void stubDone();
Utils::QtcProcess *m_stubProc = nullptr;
std::function<ProjectExplorer::Runnable()> m_stubRunnable;
diff --git a/src/plugins/debugger/threadshandler.cpp b/src/plugins/debugger/threadshandler.cpp
index aa96264e313..07e9fb8ae36 100644
--- a/src/plugins/debugger/threadshandler.cpp
+++ b/src/plugins/debugger/threadshandler.cpp
@@ -331,7 +331,7 @@ bool ThreadsHandler::notifyGroupExited(const QString &groupId)
if (item->threadData.groupId == groupId)
list.append(item);
});
- foreach (ThreadItem *item, list)
+ for (ThreadItem *item : qAsConst(list))
destroyItem(item);
m_pidForGroupId.remove(groupId);
diff --git a/src/plugins/debugger/unstartedappwatcherdialog.cpp b/src/plugins/debugger/unstartedappwatcherdialog.cpp
index 64e3e04def0..9463128f6ae 100644
--- a/src/plugins/debugger/unstartedappwatcherdialog.cpp
+++ b/src/plugins/debugger/unstartedappwatcherdialog.cpp
@@ -26,31 +26,34 @@
#include "unstartedappwatcherdialog.h"
#include "debuggeritem.h"
-#include "debuggerdialogs.h"
#include "debuggerkitinformation.h"
#include <utils/pathchooser.h>
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/kit.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/project.h>
+#include <projectexplorer/kitchooser.h>
#include <projectexplorer/kitmanager.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/runconfiguration.h>
-#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/runcontrol.h>
+#include <projectexplorer/target.h>
-#include <QVBoxLayout>
-#include <QHBoxLayout>
-#include <QPushButton>
#include <QCheckBox>
#include <QDialogButtonBox>
+#include <QFileDialog>
+#include <QFormLayout>
+#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLabel>
-#include <QFormLayout>
#include <QLineEdit>
-#include <QFileDialog>
+#include <QPushButton>
+#include <QVBoxLayout>
using namespace ProjectExplorer;
+using namespace Utils;
namespace Debugger {
namespace Internal {
@@ -224,7 +227,7 @@ void UnstartedAppWatcherDialog::startWatching()
}
}
-void UnstartedAppWatcherDialog::pidFound(const DeviceProcessItem &p)
+void UnstartedAppWatcherDialog::pidFound(const ProcessInfo &p)
{
setWaitingState(FoundState);
startStopTimer(false);
@@ -256,16 +259,17 @@ void UnstartedAppWatcherDialog::startStopTimer(bool start)
void UnstartedAppWatcherDialog::findProcess()
{
const QString &appName = m_pathChooser->filePath().normalizedPathName().toString();
- DeviceProcessItem fallback;
- foreach (const DeviceProcessItem &p, DeviceProcessList::localProcesses()) {
- if (Utils::FileUtils::normalizedPathName(p.exe) == appName) {
- pidFound(p);
+ ProcessInfo fallback;
+ const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
+ for (const ProcessInfo &processInfo : processInfoList) {
+ if (Utils::FileUtils::normalizedPathName(processInfo.executable) == appName) {
+ pidFound(processInfo);
return;
}
- if (p.cmdLine.startsWith(appName))
- fallback = p;
+ if (processInfo.commandLine.startsWith(appName))
+ fallback = processInfo;
}
- if (fallback.pid != 0)
+ if (fallback.processId != 0)
pidFound(fallback);
}
@@ -302,7 +306,7 @@ Kit *UnstartedAppWatcherDialog::currentKit() const
return m_kitChooser->currentKit();
}
-DeviceProcessItem UnstartedAppWatcherDialog::currentProcess() const
+ProcessInfo UnstartedAppWatcherDialog::currentProcess() const
{
return m_process;
}
diff --git a/src/plugins/debugger/unstartedappwatcherdialog.h b/src/plugins/debugger/unstartedappwatcherdialog.h
index 029266de17f..5186f304b53 100644
--- a/src/plugins/debugger/unstartedappwatcherdialog.h
+++ b/src/plugins/debugger/unstartedappwatcherdialog.h
@@ -28,7 +28,7 @@
#include <QDialog>
#include <QTimer>
-#include <projectexplorer/devicesupport/deviceprocesslist.h>
+#include <utils/processinfo.h>
QT_BEGIN_NAMESPACE
class QLabel;
@@ -53,7 +53,7 @@ public:
explicit UnstartedAppWatcherDialog(QWidget *parent = nullptr);
ProjectExplorer::Kit *currentKit() const;
- ProjectExplorer::DeviceProcessItem currentProcess() const;
+ Utils::ProcessInfo currentProcess() const;
bool hideOnAttach() const;
bool continueOnAttach() const;
void startWatching();
@@ -65,7 +65,7 @@ signals:
private:
void selectExecutable();
- void pidFound(const ProjectExplorer::DeviceProcessItem &p);
+ void pidFound(const Utils::ProcessInfo &p);
void startStopWatching(bool start);
void findProcess();
void stopAndCheckExecutable();
@@ -89,7 +89,7 @@ private:
QCheckBox *m_hideOnAttachCheckBox;
QCheckBox *m_continueOnAttachCheckBox;
QPushButton *m_watchingPushButton;
- ProjectExplorer::DeviceProcessItem m_process;
+ Utils::ProcessInfo m_process;
QTimer m_timer;
};
diff --git a/src/plugins/debugger/uvsc/uvscengine.cpp b/src/plugins/debugger/uvsc/uvscengine.cpp
index 915a6c970bd..6a6253c9dc9 100644
--- a/src/plugins/debugger/uvsc/uvscengine.cpp
+++ b/src/plugins/debugger/uvsc/uvscengine.cpp
@@ -536,10 +536,8 @@ void UvscEngine::updateAll()
bool UvscEngine::configureProject(const DebuggerRunParameters &rp)
{
// Fetch patchs for the generated uVision project files.
- const FilePath optionsPath = FilePath::fromString(rp.inferior.extraData.value(
- Constants::kUVisionOptionsFilePath).toString());
- const FilePath projectPath = FilePath::fromString(rp.inferior.extraData.value(
- Constants::kUVisionProjectFilePath).toString());
+ const FilePath optionsPath = rp.uVisionOptionsFilePath;
+ const FilePath projectPath = rp.uVisionProjectFilePath;
showMessage("UVSC: LOADING PROJECT...");
if (!optionsPath.exists()) {
@@ -557,7 +555,7 @@ bool UvscEngine::configureProject(const DebuggerRunParameters &rp)
}
showMessage("UVSC: SETTING PROJECT DEBUG TARGET...");
- m_simulator = rp.inferior.extraData.value(Constants::kUVisionSimulator).toBool();
+ m_simulator = rp.uVisionSimulator;
if (!m_client->setProjectDebugTarget(m_simulator)) {
handleSetupFailure(tr("Internal error: Unable to set the uVision debug target: %1.")
.arg(m_client->errorString()));
@@ -606,8 +604,7 @@ void UvscEngine::handleProjectClosed()
m_loadingRequired = false;
const DebuggerRunParameters &rp = runParameters();
- const FilePath projectPath = FilePath::fromString(rp.inferior.extraData.value(
- Constants::kUVisionProjectFilePath).toString());
+ const FilePath projectPath = rp.uVisionProjectFilePath;
// This magic function removes specific files from the uVision
// project directory. Without of this we can't enumerate the local
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 8818ceb4fd3..3663daa5296 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -60,7 +60,6 @@
#include <utils/theme/theme.h>
#include <QApplication>
-#include <QClipboard>
#include <QDebug>
#include <QFile>
#include <QFloat16>
@@ -663,7 +662,14 @@ static QString reformatInteger(quint64 value, int format, int size, bool isSigne
// Format printable (char-type) characters
static QString reformatCharacter(int code, int size, bool isSigned)
{
- const QChar c = QChar(uint(code));
+ QChar c;
+ switch (size) {
+ case 1: c = QChar(uchar(code)); break;
+ case 2: c = QChar(uint16_t(code)); break;
+ case 4: c = QChar(uint32_t(code)); break;
+ default: c = QChar(uint(code)); break;
+ }
+
QString out;
if (c.isPrint())
out = QString("'") + c + "' ";
@@ -1172,7 +1178,8 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role
if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) {
if (item && (kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace)
&& item->isWatcher()) {
- foreach (const QModelIndex &idx, ev.selectedRows())
+ const QModelIndexList selectedRows = ev.selectedRows();
+ for (const QModelIndex &idx : selectedRows)
removeWatchItem(itemForIndex(idx));
return true;
}
@@ -1544,7 +1551,7 @@ MemoryMarkupList WatchModel::variableMemoryMarkup(WatchItem *item,
name = ranges.at(i).second;
}
dbg << '\n';
- foreach (const MemoryMarkup &m, result)
+ for (const MemoryMarkup &m : qAsConst(result))
dbg << m.address << ' ' << m.length << ' ' << m.toolTip << '\n';
}
@@ -1655,14 +1662,6 @@ static QString removeWatchActionText(QString exp)
return WatchModel::tr("Remove Expression Evaluator for \"%1\"").arg(Utils::quoteAmpersands(exp));
}
-static void copyToClipboard(const QString &clipboardText)
-{
- QClipboard *clipboard = QApplication::clipboard();
- if (clipboard->supportsSelection())
- clipboard->setText(clipboardText, QClipboard::Selection);
- clipboard->setText(clipboardText, QClipboard::Clipboard);
-}
-
void WatchModel::inputNewExpression()
{
QDialog dlg;
@@ -1780,19 +1779,19 @@ bool WatchModel::contextMenuEvent(const ItemViewEvent &ev)
addAction(this, menu, tr("Copy View Contents to Clipboard"),
true,
- [this] { copyToClipboard(editorContents()); });
+ [this] { setClipboardAndSelection(editorContents()); });
addAction(this, menu,
tr("Copy Current Value to Clipboard"),
item,
[this, name = item ? item->iname : QString()] {
if (auto item = findItem(name))
- copyToClipboard(item->value);
+ setClipboardAndSelection(item->value);
});
// addAction(menu, tr("Copy Selected Rows to Clipboard"),
// selectionModel()->hasSelection(),
- // [this] { copyToClipboard(editorContents(selectionModel()->selectedRows())); });
+ // [this] { setClipboardAndSelection(editorContents(selectionModel()->selectedRows())); });
addAction(this, menu, tr("Open View Contents in Editor"),
m_engine->debuggerActionsEnabled(),
@@ -2180,7 +2179,7 @@ void WatchHandler::insertItems(const GdbMi &data)
itemsToSort.insert(static_cast<WatchItem *>(item->parent()));
}
- foreach (WatchItem *toplevel, itemsToSort)
+ for (WatchItem *toplevel : qAsConst(itemsToSort))
toplevel->sortChildren(&sortByName);
}
@@ -2219,7 +2218,7 @@ bool WatchHandler::insertItem(WatchItem *item)
void WatchModel::reexpandItems()
{
- foreach (const QString &iname, m_expandedINames) {
+ for (const QString &iname : qAsConst(m_expandedINames)) {
if (WatchItem *item = findItem(iname)) {
emit itemIsExpanded(indexForItem(item));
emit inameIsExpanded(iname);
@@ -2297,7 +2296,7 @@ void WatchHandler::notifyUpdateFinished()
return true;
});
- foreach (auto item, toRemove)
+ for (WatchItem *item : qAsConst(toRemove))
m_model->destroyItem(item);
m_model->forAllItems([this](WatchItem *item) {
@@ -2582,7 +2581,8 @@ void WatchHandler::loadSessionDataForEngine()
theWatcherCount = 0;
QVariant value = SessionManager::value("Watchers");
m_model->m_watchRoot->removeChildren();
- foreach (const QString &exp, value.toStringList())
+ const QStringList valueList = value.toStringList();
+ for (const QString &exp : valueList)
watchExpression(exp.trimmed());
}
@@ -2765,8 +2765,8 @@ void WatchHandler::addDumpers(const GdbMi &dumpers)
for (const GdbMi &dumper : dumpers) {
DisplayFormats formats;
formats.append(RawFormat);
- QString reportedFormats = dumper["formats"].data();
- foreach (const QString &format, reportedFormats.split(',')) {
+ const QStringList reportedFormats = dumper["formats"].data().split(',');
+ for (const QString &format : reportedFormats) {
if (int f = format.toInt())
formats.append(DisplayFormat(f));
}
diff --git a/src/plugins/designer/CMakeLists.txt b/src/plugins/designer/CMakeLists.txt
index 39c0c1d59ff..ebc81260d0c 100644
--- a/src/plugins/designer/CMakeLists.txt
+++ b/src/plugins/designer/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(Designer
+ PLUGIN_CLASS FormEditorPlugin
CONDITION TARGET Qt5::DesignerComponents AND TARGET Qt5::Designer
DEPENDS designerintegrationv2
Qt5::Designer Qt5::PrintSupport Qt5::DesignerComponents
@@ -9,7 +10,7 @@ add_qtc_plugin(Designer
codemodelhelpers.cpp codemodelhelpers.h
cpp/formclasswizard.cpp cpp/formclasswizard.h
cpp/formclasswizarddialog.cpp cpp/formclasswizarddialog.h
- cpp/formclasswizardpage.cpp cpp/formclasswizardpage.h cpp/formclasswizardpage.ui
+ cpp/formclasswizardpage.cpp cpp/formclasswizardpage.h
cpp/formclasswizardparameters.cpp cpp/formclasswizardparameters.h
cpp/newclasswidget.cpp cpp/newclasswidget.h cpp/newclasswidget.ui
designer_export.h
@@ -35,3 +36,10 @@ extend_qtc_plugin(Designer
CONDITION WITH_TESTS AND TARGET Qt5::DesignerComponents AND TARGET Qt5::Designer
SOURCES gotoslot_test.cpp
)
+
+if (QTC_STATIC_BUILD AND TARGET Designer)
+ get_target_property(_designerType Qt5::Designer TYPE)
+ if (${_designerType} STREQUAL "STATIC_LIBRARY")
+ extend_qtc_target(Designer PUBLIC_DEFINES QT_DESIGNER_STATIC)
+ endif()
+endif()
diff --git a/src/plugins/designer/cpp/formclasswizardpage.cpp b/src/plugins/designer/cpp/formclasswizardpage.cpp
index 6f7e244eb59..81220b532cf 100644
--- a/src/plugins/designer/cpp/formclasswizardpage.cpp
+++ b/src/plugins/designer/cpp/formclasswizardpage.cpp
@@ -24,42 +24,54 @@
****************************************************************************/
#include "formclasswizardpage.h"
-#include "ui_formclasswizardpage.h"
-#include "formclasswizardparameters.h"
-#include <utils/wizard.h>
+#include "formclasswizardparameters.h"
+#include "newclasswidget.h"
#include <coreplugin/icore.h>
+
#include <cppeditor/cppeditorconstants.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <QDebug>
+#include <utils/mimeutils.h>
+#include <utils/wizard.h>
+
+#include <QGridLayout>
+#include <QGroupBox>
#include <QMessageBox>
+#include <QVBoxLayout>
+#include <QVariant>
namespace Designer {
namespace Internal {
-// ----------------- FormClassWizardPage
-
-FormClassWizardPage::FormClassWizardPage(QWidget * parent) :
- QWizardPage(parent),
- m_ui(new Ui::FormClassWizardPage)
+FormClassWizardPage::FormClassWizardPage()
{
- m_ui->setupUi(this);
+ setTitle(tr("Choose a Class Name"));
+
+ auto classGroupBox = new QGroupBox(this);
+ classGroupBox->setTitle(tr("Class"));
- connect(m_ui->newClassWidget, &NewClassWidget::validChanged, this,
- &FormClassWizardPage::slotValidChanged);
+ m_newClassWidget = new NewClassWidget(classGroupBox);
+ m_newClassWidget->setHeaderExtension(
+ Utils::mimeTypeForName(CppEditor::Constants::CPP_HEADER_MIMETYPE).preferredSuffix());
+ m_newClassWidget->setSourceExtension(
+ Utils::mimeTypeForName(CppEditor::Constants::CPP_SOURCE_MIMETYPE).preferredSuffix());
+ m_newClassWidget->setLowerCaseFiles(lowercaseHeaderFiles());
- initFileGenerationSettings();
+ connect(m_newClassWidget, &NewClassWidget::validChanged,
+ this, &FormClassWizardPage::slotValidChanged);
setProperty(Utils::SHORT_TITLE_PROPERTY, tr("Class Details"));
-}
-FormClassWizardPage::~FormClassWizardPage()
-{
- delete m_ui;
+ auto verticalLayout = new QVBoxLayout(classGroupBox);
+ verticalLayout->addWidget(m_newClassWidget);
+
+ auto gridLayout = new QGridLayout(this);
+ gridLayout->addWidget(classGroupBox, 0, 0, 1, 1);
}
+FormClassWizardPage::~FormClassWizardPage() = default;
+
// Retrieve settings of CppEditor plugin.
bool FormClassWizardPage::lowercaseHeaderFiles()
{
@@ -70,45 +82,35 @@ bool FormClassWizardPage::lowercaseHeaderFiles()
return Core::ICore::settings()->value(lowerCaseSettingsKey, QVariant(lowerCaseDefault)).toBool();
}
-// Set up new class widget from settings
-void FormClassWizardPage::initFileGenerationSettings()
-{
- m_ui->newClassWidget->setHeaderExtension(
- Utils::mimeTypeForName(CppEditor::Constants::CPP_HEADER_MIMETYPE).preferredSuffix());
- m_ui->newClassWidget->setSourceExtension(
- Utils::mimeTypeForName(CppEditor::Constants::CPP_SOURCE_MIMETYPE).preferredSuffix());
- m_ui->newClassWidget->setLowerCaseFiles(lowercaseHeaderFiles());
-}
-
void FormClassWizardPage::setClassName(const QString &suggestedClassName)
{
// Is it valid, now?
- m_ui->newClassWidget->setClassName(suggestedClassName);
+ m_newClassWidget->setClassName(suggestedClassName);
slotValidChanged();
}
Utils::FilePath FormClassWizardPage::filePath() const
{
- return m_ui->newClassWidget->filePath();
+ return m_newClassWidget->filePath();
}
void FormClassWizardPage::setFilePath(const Utils::FilePath &p)
{
- m_ui->newClassWidget->setFilePath(p);
+ m_newClassWidget->setFilePath(p);
}
void FormClassWizardPage::getParameters(FormClassWizardParameters *p) const
{
- p->className = m_ui->newClassWidget->className();
+ p->className = m_newClassWidget->className();
p->path = filePath();
- p->sourceFile = m_ui->newClassWidget->sourceFileName();
- p->headerFile = m_ui->newClassWidget->headerFileName();
- p->uiFile = m_ui->newClassWidget-> formFileName();
+ p->sourceFile = m_newClassWidget->sourceFileName();
+ p->headerFile = m_newClassWidget->headerFileName();
+ p->uiFile = m_newClassWidget-> formFileName();
}
void FormClassWizardPage::slotValidChanged()
{
- const bool validNow = m_ui->newClassWidget->isValid();
+ const bool validNow = m_newClassWidget->isValid();
if (m_isValid != validNow) {
m_isValid = validNow;
emit completeChanged();
@@ -123,7 +125,7 @@ bool FormClassWizardPage::isComplete() const
bool FormClassWizardPage::validatePage()
{
QString errorMessage;
- const bool rc = m_ui->newClassWidget->isValid(&errorMessage);
+ const bool rc = m_newClassWidget->isValid(&errorMessage);
if (!rc)
QMessageBox::warning(this, tr("%1 - Error").arg(title()), errorMessage);
return rc;
diff --git a/src/plugins/designer/cpp/formclasswizardpage.h b/src/plugins/designer/cpp/formclasswizardpage.h
index 60e848433e1..7ba67ed42c6 100644
--- a/src/plugins/designer/cpp/formclasswizardpage.h
+++ b/src/plugins/designer/cpp/formclasswizardpage.h
@@ -25,6 +25,7 @@
#pragma once
+#include <QCoreApplication>
#include <QWizardPage>
namespace Utils { class FilePath; }
@@ -36,21 +37,21 @@ class FormClassWizardGenerationParameters;
namespace Internal {
-namespace Ui { class FormClassWizardPage; }
-
+class NewClassWidget;
class FormClassWizardPage : public QWizardPage
{
- Q_OBJECT
+ Q_DECLARE_TR_FUNCTIONS(Designer::Internal::FormClassWizardPage)
public:
- explicit FormClassWizardPage(QWidget *parent = nullptr);
+ FormClassWizardPage();
~FormClassWizardPage() override;
bool isComplete () const override;
bool validatePage() override;
void setClassName(const QString &suggestedClassName);
+
void setFilePath(const Utils::FilePath &);
Utils::FilePath filePath() const;
@@ -65,11 +66,8 @@ public:
private:
void slotValidChanged();
-private:
- void initFileGenerationSettings();
-
- Ui::FormClassWizardPage *m_ui = nullptr;
bool m_isValid = false;
+ Designer::Internal::NewClassWidget *m_newClassWidget;
};
} // namespace Internal
diff --git a/src/plugins/designer/cpp/formclasswizardpage.ui b/src/plugins/designer/cpp/formclasswizardpage.ui
deleted file mode 100644
index b58e58c4b5a..00000000000
--- a/src/plugins/designer/cpp/formclasswizardpage.ui
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Designer::Internal::FormClassWizardPage</class>
- <widget class="QWizardPage" name="Designer::Internal::FormClassWizardPage">
- <property name="title">
- <string>Choose a Class Name</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QGroupBox" name="classGroupBox">
- <property name="title">
- <string>Class</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="Designer::Internal::NewClassWidget" name="newClassWidget"/>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>Designer::Internal::NewClassWidget</class>
- <extends>QWidget</extends>
- <header location="global">designer/cpp/newclasswidget.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/designer/designer.qbs b/src/plugins/designer/designer.qbs
index 739b1c1f989..ff98dfb04ff 100644
--- a/src/plugins/designer/designer.qbs
+++ b/src/plugins/designer/designer.qbs
@@ -70,7 +70,7 @@ QtcPlugin {
files: [
"formclasswizard.cpp", "formclasswizard.h",
"formclasswizarddialog.cpp", "formclasswizarddialog.h",
- "formclasswizardpage.cpp", "formclasswizardpage.h", "formclasswizardpage.ui",
+ "formclasswizardpage.cpp", "formclasswizardpage.h",
"formclasswizardparameters.cpp", "formclasswizardparameters.h",
"newclasswidget.cpp", "newclasswidget.h", "newclasswidget.ui",
]
diff --git a/src/plugins/designer/designer_export.h b/src/plugins/designer/designer_export.h
index 000e6c6130c..a601f557abc 100644
--- a/src/plugins/designer/designer_export.h
+++ b/src/plugins/designer/designer_export.h
@@ -29,6 +29,8 @@
#if defined(DESIGNER_LIBRARY)
# define DESIGNER_EXPORT Q_DECL_EXPORT
+#elif defined(DESIGNER_STATIC_LIBRARY)
+# define DESIGNER_EXPORT
#else
# define DESIGNER_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp
index eafddea3e36..6643a78e734 100644
--- a/src/plugins/designer/formeditorplugin.cpp
+++ b/src/plugins/designer/formeditorplugin.cpp
@@ -27,7 +27,6 @@
#include "formeditorfactory.h"
#include "formeditorw.h"
#include "formtemplatewizardpage.h"
-#include "formwindoweditor.h"
#ifdef CPP_ENABLED
# include "cpp/formclasswizard.h"
@@ -39,14 +38,14 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/designmode.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/designmode.h>
#include <cppeditor/cppeditorconstants.h>
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QAction>
#include <QCoreApplication>
@@ -58,6 +57,7 @@
using namespace Core;
using namespace Designer::Constants;
+using namespace Utils;
namespace Designer {
namespace Internal {
@@ -141,24 +141,24 @@ void FormEditorPlugin::extensionsInitialized()
////////////////////////////////////////////////////
// Find out current existing editor file
-static QString currentFile()
+static FilePath currentFile()
{
if (const IDocument *document = EditorManager::currentDocument()) {
- const QString fileName = document->filePath().toString();
- if (!fileName.isEmpty() && QFileInfo(fileName).isFile())
- return fileName;
+ const FilePath filePath = document->filePath();
+ if (!filePath.isEmpty() && filePath.isFile())
+ return filePath;
}
- return QString();
+ return {};
}
// Switch between form ('ui') and source file ('cpp'):
// Find corresponding 'other' file, simply assuming it is in the same directory.
-static QString otherFile()
+static FilePath otherFile()
{
// Determine mime type of current file.
- const QString current = currentFile();
+ const FilePath current = currentFile();
if (current.isEmpty())
- return QString();
+ return {};
const Utils::MimeType currentMimeType = Utils::mimeTypeForFile(current);
// Determine potential suffixes of candidate files
// 'ui' -> 'cpp', 'cpp/h' -> 'ui'.
@@ -169,22 +169,21 @@ static QString otherFile()
|| currentMimeType.matchesName(CppEditor::Constants::CPP_HEADER_MIMETYPE)) {
candidateSuffixes += Utils::mimeTypeForName(FORM_MIMETYPE).suffixes();
} else {
- return QString();
+ return {};
}
// Try to find existing file with desired suffix
- const QFileInfo currentFI(current);
- const QString currentBaseName = currentFI.path() + '/' + currentFI.baseName() + '.';
+ const FilePath currentBaseName = current.parentDir().pathAppended(current.baseName() + '.');
for (const QString &candidateSuffix : qAsConst(candidateSuffixes)) {
- const QFileInfo fi(currentBaseName + candidateSuffix);
- if (fi.isFile())
- return fi.absoluteFilePath();
+ const FilePath filePath = currentBaseName.stringAppended(candidateSuffix);
+ if (filePath.isFile())
+ return filePath.absoluteFilePath();
}
- return QString();
+ return {};
}
void FormEditorPlugin::switchSourceForm()
{
- const auto fileToOpen = Utils::FilePath::fromString(otherFile());
+ const FilePath fileToOpen = otherFile();
if (!fileToOpen.isEmpty())
EditorManager::openEditor(fileToOpen);
}
diff --git a/src/plugins/designer/gotoslot_test.cpp b/src/plugins/designer/gotoslot_test.cpp
index 7f0e4cbbd91..02e7adc85bc 100644
--- a/src/plugins/designer/gotoslot_test.cpp
+++ b/src/plugins/designer/gotoslot_test.cpp
@@ -106,7 +106,7 @@ protected:
void postVisit(Symbol *symbol)
{
- if (symbol->isClass())
+ if (symbol->asClass())
m_currentClass.clear();
}
diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp
index 4559c1df996..00df6f19b84 100644
--- a/src/plugins/designer/qtcreatorintegration.cpp
+++ b/src/plugins/designer/qtcreatorintegration.cpp
@@ -46,7 +46,7 @@
#include <projectexplorer/projecttree.h>
#include <projectexplorer/session.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
diff --git a/src/plugins/designer/resourcehandler.cpp b/src/plugins/designer/resourcehandler.cpp
index 38e6dff6b03..0cfc22a5ecf 100644
--- a/src/plugins/designer/resourcehandler.cpp
+++ b/src/plugins/designer/resourcehandler.cpp
@@ -31,11 +31,11 @@
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <resourceeditor/resourcenode.h>
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
#include <QDesignerFormWindowInterface>
-#include <utils/qtcassert.h>
-
using namespace ProjectExplorer;
using namespace Utils;
diff --git a/src/plugins/diffeditor/CMakeLists.txt b/src/plugins/diffeditor/CMakeLists.txt
index f5fbb9630cc..695d7d1555d 100644
--- a/src/plugins/diffeditor/CMakeLists.txt
+++ b/src/plugins/diffeditor/CMakeLists.txt
@@ -1,6 +1,5 @@
add_qtc_plugin(DiffEditor
PLUGIN_DEPENDS Core TextEditor
- DEFINES DIFFEDITOR_LIBRARY
SOURCES
descriptionwidgetwatcher.cpp descriptionwidgetwatcher.h
diffeditor.cpp diffeditor.h
diff --git a/src/plugins/diffeditor/diffeditor_global.h b/src/plugins/diffeditor/diffeditor_global.h
index 763096abbf5..626762629b3 100644
--- a/src/plugins/diffeditor/diffeditor_global.h
+++ b/src/plugins/diffeditor/diffeditor_global.h
@@ -29,6 +29,8 @@
#if defined(DIFFEDITOR_LIBRARY)
# define DIFFEDITOR_EXPORT Q_DECL_EXPORT
+#elif defined(DIFFEDITOR_STATIC_LIBRARY)
+# define DIFFEDITOR_EXPORT
#else
# define DIFFEDITOR_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp
index 2a4e5288f53..57ce053cdfb 100644
--- a/src/plugins/diffeditor/diffeditordocument.cpp
+++ b/src/plugins/diffeditor/diffeditordocument.cpp
@@ -308,8 +308,8 @@ bool DiffEditorDocument::reload(QString *errorString, ReloadFlag flag, ChangeTyp
return open(errorString, filePath(), filePath()) == OpenResult::Success;
}
-Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const Utils::FilePath &filePath,
- const Utils::FilePath &realFilePath)
+Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const FilePath &filePath,
+ const FilePath &realFilePath)
{
QTC_CHECK(filePath == realFilePath); // does not support autosave
beginReload();
diff --git a/src/plugins/diffeditor/diffeditorfactory.cpp b/src/plugins/diffeditor/diffeditorfactory.cpp
index c88ff3b576d..d2a9b5513fd 100644
--- a/src/plugins/diffeditor/diffeditorfactory.cpp
+++ b/src/plugins/diffeditor/diffeditorfactory.cpp
@@ -61,7 +61,7 @@ DiffEditorFactory::DiffEditorFactory() :
},
rightHandler {
Constants::DIFF_EDITOR_ID,
- Utils::Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(2),
+ Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(2),
TextEditorActionHandler::None,
[](Core::IEditor *e) { return static_cast<DiffEditor *>(e)->rightEditorWidget(); }
}
diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp
index fc607535af5..b40e399eb49 100644
--- a/src/plugins/diffeditor/diffeditorplugin.cpp
+++ b/src/plugins/diffeditor/diffeditorplugin.cpp
@@ -150,9 +150,8 @@ DiffFilesController::DiffFilesController(IDocument *document)
setReloader([this] {
cancelReload();
- m_futureWatcher.setFuture(Utils::map(reloadInputList(),
- DiffFile(ignoreWhitespace(),
- contextLineCount())));
+ m_futureWatcher.setFuture(map(reloadInputList(),
+ DiffFile(ignoreWhitespace(), contextLineCount())));
Core::ProgressManager::addTask(m_futureWatcher.future(),
tr("Calculating diff"), "DiffEditor");
@@ -203,11 +202,11 @@ QList<ReloadInput> DiffCurrentFileController::reloadInputList() const
if (textDocument && textDocument->isModified()) {
QString errorString;
- Utils::TextFileFormat format = textDocument->format();
+ TextFileFormat format = textDocument->format();
QString leftText;
- const Utils::TextFileFormat::ReadResult leftResult
- = Utils::TextFileFormat::readFile(FilePath::fromString(m_fileName), format.codec,
+ const TextFileFormat::ReadResult leftResult
+ = TextFileFormat::readFile(FilePath::fromString(m_fileName), format.codec,
&leftText, &format, &errorString);
const QString rightText = textDocument->plainText();
@@ -220,9 +219,9 @@ QList<ReloadInput> DiffCurrentFileController::reloadInputList() const
reloadInput.leftFileInfo.typeInfo = tr("Saved");
reloadInput.rightFileInfo.typeInfo = tr("Modified");
reloadInput.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor;
- reloadInput.binaryFiles = (leftResult == Utils::TextFileFormat::ReadEncodingError);
+ reloadInput.binaryFiles = (leftResult == TextFileFormat::ReadEncodingError);
- if (leftResult == Utils::TextFileFormat::ReadIOError)
+ if (leftResult == TextFileFormat::ReadIOError)
reloadInput.fileOperation = FileData::NewFile;
result << reloadInput;
@@ -259,11 +258,11 @@ QList<ReloadInput> DiffOpenFilesController::reloadInputList() const
if (textDocument && textDocument->isModified()) {
QString errorString;
- Utils::TextFileFormat format = textDocument->format();
+ TextFileFormat format = textDocument->format();
QString leftText;
const QString fileName = textDocument->filePath().toString();
- const Utils::TextFileFormat::ReadResult leftResult = Utils::TextFileFormat::readFile(
+ const TextFileFormat::ReadResult leftResult = TextFileFormat::readFile(
FilePath::fromString(fileName), format.codec, &leftText, &format, &errorString);
const QString rightText = textDocument->plainText();
@@ -276,9 +275,9 @@ QList<ReloadInput> DiffOpenFilesController::reloadInputList() const
reloadInput.leftFileInfo.typeInfo = tr("Saved");
reloadInput.rightFileInfo.typeInfo = tr("Modified");
reloadInput.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor;
- reloadInput.binaryFiles = (leftResult == Utils::TextFileFormat::ReadEncodingError);
+ reloadInput.binaryFiles = (leftResult == TextFileFormat::ReadEncodingError);
- if (leftResult == Utils::TextFileFormat::ReadIOError)
+ if (leftResult == TextFileFormat::ReadIOError)
reloadInput.fileOperation = FileData::NewFile;
result << reloadInput;
@@ -313,15 +312,15 @@ QList<ReloadInput> DiffModifiedFilesController::reloadInputList() const
for (const QString &fileName : m_fileNames) {
auto textDocument = qobject_cast<TextEditor::TextDocument *>(
- DocumentModel::documentForFilePath(Utils::FilePath::fromString(fileName)));
+ DocumentModel::documentForFilePath(FilePath::fromString(fileName)));
if (textDocument && textDocument->isModified()) {
QString errorString;
- Utils::TextFileFormat format = textDocument->format();
+ TextFileFormat format = textDocument->format();
QString leftText;
const QString fileName = textDocument->filePath().toString();
- const Utils::TextFileFormat::ReadResult leftResult = Utils::TextFileFormat::readFile(
+ const TextFileFormat::ReadResult leftResult = TextFileFormat::readFile(
FilePath::fromString(fileName), format.codec, &leftText, &format, &errorString);
const QString rightText = textDocument->plainText();
@@ -334,9 +333,9 @@ QList<ReloadInput> DiffModifiedFilesController::reloadInputList() const
reloadInput.leftFileInfo.typeInfo = tr("Saved");
reloadInput.rightFileInfo.typeInfo = tr("Modified");
reloadInput.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor;
- reloadInput.binaryFiles = (leftResult == Utils::TextFileFormat::ReadEncodingError);
+ reloadInput.binaryFiles = (leftResult == TextFileFormat::ReadEncodingError);
- if (leftResult == Utils::TextFileFormat::ReadIOError)
+ if (leftResult == TextFileFormat::ReadIOError)
reloadInput.fileOperation = FileData::NewFile;
result << reloadInput;
@@ -371,15 +370,15 @@ DiffExternalFilesController::DiffExternalFilesController(IDocument *document, co
QList<ReloadInput> DiffExternalFilesController::reloadInputList() const
{
QString errorString;
- Utils::TextFileFormat format;
+ TextFileFormat format;
format.codec = EditorManager::defaultTextCodec();
QString leftText;
QString rightText;
- const Utils::TextFileFormat::ReadResult leftResult = Utils::TextFileFormat::readFile(
+ const TextFileFormat::ReadResult leftResult = TextFileFormat::readFile(
FilePath::fromString(m_leftFileName), format.codec, &leftText, &format, &errorString);
- const Utils::TextFileFormat::ReadResult rightResult = Utils::TextFileFormat::readFile(
+ const TextFileFormat::ReadResult rightResult = TextFileFormat::readFile(
FilePath::fromString(m_rightFileName), format.codec, &rightText, &format, &errorString);
ReloadInput reloadInput;
@@ -387,11 +386,11 @@ QList<ReloadInput> DiffExternalFilesController::reloadInputList() const
reloadInput.rightText = rightText;
reloadInput.leftFileInfo.fileName = m_leftFileName;
reloadInput.rightFileInfo.fileName = m_rightFileName;
- reloadInput.binaryFiles = (leftResult == Utils::TextFileFormat::ReadEncodingError
- || rightResult == Utils::TextFileFormat::ReadEncodingError);
+ reloadInput.binaryFiles = (leftResult == TextFileFormat::ReadEncodingError
+ || rightResult == TextFileFormat::ReadEncodingError);
- const bool leftFileExists = (leftResult != Utils::TextFileFormat::ReadIOError);
- const bool rightFileExists = (rightResult != Utils::TextFileFormat::ReadIOError);
+ const bool leftFileExists = (leftResult != TextFileFormat::ReadIOError);
+ const bool rightFileExists = (rightResult != TextFileFormat::ReadIOError);
if (!leftFileExists && rightFileExists)
reloadInput.fileOperation = FileData::NewFile;
else if (leftFileExists && !rightFileExists)
@@ -518,7 +517,7 @@ void DiffEditorPluginPrivate::updateDiffCurrentFileAction()
void DiffEditorPluginPrivate::updateDiffOpenFilesAction()
{
- const bool enabled = Utils::anyOf(DocumentModel::openedDocuments(), [](IDocument *doc) {
+ const bool enabled = anyOf(DocumentModel::openedDocuments(), [](IDocument *doc) {
QTC_ASSERT(doc, return false);
return doc->isModified() && qobject_cast<TextEditor::TextDocument *>(doc);
});
diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
index 271ff5708ed..f06bb37f6e2 100644
--- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
+++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
@@ -68,7 +68,7 @@ DiffEditorWidgetController::DiffEditorWidgetController(QWidget *diffEditorWidget
void DiffEditorWidgetController::setDocument(DiffEditorDocument *document)
{
if (!m_progressIndicator) {
- m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large);
+ m_progressIndicator = new ProgressIndicator(ProgressIndicatorSize::Large);
m_progressIndicator->attachToWidget(m_diffEditorWidget);
m_progressIndicator->hide();
}
@@ -182,7 +182,7 @@ void DiffEditorWidgetController::patch(bool revert, int fileIndex, int chunkInde
if (!textDocument)
return;
- Utils::TemporaryFile contentsCopy("diff");
+ TemporaryFile contentsCopy("diff");
if (!contentsCopy.open())
return;
@@ -306,12 +306,12 @@ void DiffEditorWidgetController::updateCannotDecodeInfo()
if (!m_document)
return;
- Utils::InfoBar *infoBar = m_document->infoBar();
+ InfoBar *infoBar = m_document->infoBar();
Id selectEncodingId(Constants::SELECT_ENCODING);
if (m_document->hasDecodingError()) {
if (!infoBar->canInfoBeAdded(selectEncodingId))
return;
- Utils::InfoBarEntry info(selectEncodingId,
+ InfoBarEntry info(selectEncodingId,
tr("<b>Error:</b> Could not decode \"%1\" with \"%2\"-encoding.")
.arg(m_document->displayName(),
QString::fromLatin1(m_document->codec()->name())));
diff --git a/src/plugins/docker/CMakeLists.txt b/src/plugins/docker/CMakeLists.txt
index e89c5b5ee23..b18baabf0c1 100644
--- a/src/plugins/docker/CMakeLists.txt
+++ b/src/plugins/docker/CMakeLists.txt
@@ -1,10 +1,13 @@
add_qtc_plugin(Docker
+ DEPENDS Utils
PLUGIN_DEPENDS Core ProjectExplorer QtSupport
SOURCES
docker_global.h
- dockerbuildstep.cpp dockerbuildstep.h
+ dockerapi.cpp dockerapi.h
dockerconstants.h
dockerdevice.cpp dockerdevice.h
+ dockerdevicewidget.cpp dockerdevicewidget.h
dockerplugin.cpp dockerplugin.h
dockersettings.cpp dockersettings.h
+ kitdetector.cpp kitdetector.h
)
diff --git a/src/plugins/docker/docker.qbs b/src/plugins/docker/docker.qbs
index 60c31290630..5664c1b5629 100644
--- a/src/plugins/docker/docker.qbs
+++ b/src/plugins/docker/docker.qbs
@@ -12,15 +12,19 @@ QtcPlugin {
files: [
"docker_global.h",
- "dockerbuildstep.h",
- "dockerbuildstep.cpp",
+ "dockerapi.cpp",
+ "dockerapi.h",
"dockerconstants.h",
- "dockerdevice.h",
"dockerdevice.cpp",
- "dockerplugin.h",
+ "dockerdevice.h",
+ "dockerdevicewidget.cpp",
+ "dockerdevicewidget.h",
"dockerplugin.cpp",
+ "dockerplugin.h",
+ "dockersettings.cpp",
"dockersettings.h",
- "dockersettings.cpp"
+ "kitdetector.cpp",
+ "kitdetector.h",
]
}
diff --git a/src/plugins/docker/dockerapi.cpp b/src/plugins/docker/dockerapi.cpp
new file mode 100644
index 00000000000..77260ed158e
--- /dev/null
+++ b/src/plugins/docker/dockerapi.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "dockerapi.h"
+
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+#include <utils/runextensions.h>
+
+#include <QLoggingCategory>
+
+#include <thread>
+
+Q_LOGGING_CATEGORY(dockerApiLog, "qtc.docker.api", QtDebugMsg);
+
+namespace Docker {
+namespace Internal {
+
+using namespace Utils;
+
+DockerApi *s_instance{nullptr};
+
+DockerApi::DockerApi()
+{
+ s_instance = this;
+}
+
+DockerApi *DockerApi::instance()
+{
+ return s_instance;
+}
+
+bool DockerApi::canConnect()
+{
+ QtcProcess process;
+ FilePath dockerExe = findDockerClient();
+ if (dockerExe.isEmpty() || !dockerExe.isExecutableFile())
+ return false;
+
+ bool result = false;
+
+ process.setCommand(CommandLine(dockerExe, QStringList{"info"}));
+ connect(&process, &QtcProcess::done, [&process, &result] {
+ qCInfo(dockerApiLog) << "'docker info' result:\n" << qPrintable(process.allOutput());
+ if (process.result() == ProcessResult::FinishedWithSuccess)
+ result = true;
+ });
+
+ process.start();
+ process.waitForFinished();
+
+ return result;
+}
+
+void DockerApi::checkCanConnect(bool async)
+{
+ if (async) {
+ std::unique_lock lk(m_daemonCheckGuard, std::try_to_lock);
+ if (!lk.owns_lock())
+ return;
+
+ m_dockerDaemonAvailable = nullopt;
+ dockerDaemonAvailableChanged();
+
+ auto future = Utils::runAsync([lk = std::move(lk), this] {
+ m_dockerDaemonAvailable = canConnect();
+ dockerDaemonAvailableChanged();
+ });
+
+ Core::ProgressManager::addTask(future, tr("Checking docker daemon"), "DockerPlugin");
+ return;
+ }
+
+ std::unique_lock lk(m_daemonCheckGuard);
+ bool isAvailable = canConnect();
+ if (!m_dockerDaemonAvailable.has_value() || isAvailable != m_dockerDaemonAvailable) {
+ m_dockerDaemonAvailable = isAvailable;
+ dockerDaemonAvailableChanged();
+ }
+}
+
+void DockerApi::recheckDockerDaemon()
+{
+ QTC_ASSERT(s_instance, return );
+ s_instance->checkCanConnect();
+}
+
+Utils::optional<bool> DockerApi::dockerDaemonAvailable(bool async)
+{
+ if (!m_dockerDaemonAvailable.has_value())
+ checkCanConnect(async);
+ return m_dockerDaemonAvailable;
+}
+
+Utils::optional<bool> DockerApi::isDockerDaemonAvailable(bool async)
+{
+ QTC_ASSERT(s_instance, return nullopt);
+ return s_instance->dockerDaemonAvailable(async);
+}
+
+FilePath DockerApi::findDockerClient()
+{
+ if (m_dockerExecutable.isEmpty() || m_dockerExecutable.isExecutableFile())
+ m_dockerExecutable = FilePath::fromString("docker").searchInPath();
+ return m_dockerExecutable;
+}
+
+} // namespace Internal
+} // namespace Docker
diff --git a/src/plugins/docker/dockerapi.h b/src/plugins/docker/dockerapi.h
new file mode 100644
index 00000000000..0194099a711
--- /dev/null
+++ b/src/plugins/docker/dockerapi.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QMutex>
+#include <QObject>
+
+#include <utils/filepath.h>
+#include <utils/guard.h>
+#include <utils/optional.h>
+
+namespace Docker {
+namespace Internal {
+
+class DockerApi : public QObject
+{
+ Q_OBJECT
+
+public:
+ DockerApi();
+
+ static DockerApi *instance();
+
+ bool canConnect();
+ void checkCanConnect(bool async = true);
+ static void recheckDockerDaemon();
+
+signals:
+ void dockerDaemonAvailableChanged();
+
+public:
+ Utils::optional<bool> dockerDaemonAvailable(bool async = true);
+ static Utils::optional<bool> isDockerDaemonAvailable(bool async = true);
+
+private:
+ Utils::FilePath findDockerClient();
+
+private:
+ Utils::FilePath m_dockerExecutable;
+ Utils::optional<bool> m_dockerDaemonAvailable;
+ QMutex m_daemonCheckGuard;
+};
+
+} // namespace Internal
+} // namespace Docker
diff --git a/src/plugins/docker/dockerbuildstep.cpp b/src/plugins/docker/dockerbuildstep.cpp
deleted file mode 100644
index 1970147569a..00000000000
--- a/src/plugins/docker/dockerbuildstep.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "dockerbuildstep.h"
-
-#include "dockerconstants.h"
-#include "dockerdevice.h"
-#include "dockersettings.h"
-
-#include <projectexplorer/abstractprocessstep.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/processparameters.h>
-#include <projectexplorer/runcontrol.h>
-#include <projectexplorer/target.h>
-
-#include <QRegularExpression>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Docker {
-namespace Internal {
-
-const char DOCKER_COMMAND[] = "docker";
-const char DEFAULT_DOCKER_COMMAND[] = "run --read-only --rm %{BuildDevice:DockerImage}";
-
-class DockerBuildStep : public AbstractProcessStep
-{
- Q_DECLARE_TR_FUNCTIONS(Docker::Internal::DockerBuildStep)
-
-public:
- DockerBuildStep(BuildStepList *bsl, Id id)
- : AbstractProcessStep(bsl, id)
- {
- setDisplayName(tr("Docker build host step"));
-
- m_dockerCommand = addAspect<StringAspect>();
- m_dockerCommand->setDisplayStyle(StringAspect::DisplayStyle::TextEditDisplay);
- m_dockerCommand->setLabelText(tr("Docker command:"));
- m_dockerCommand->setMacroExpanderProvider([=] { return macroExpander(); });
- m_dockerCommand->setDefaultValue(QLatin1String(DEFAULT_DOCKER_COMMAND));
- m_dockerCommand->setPlaceHolderText(QLatin1String(DEFAULT_DOCKER_COMMAND));
- m_dockerCommand->setSettingsKey("DockerCommand");
-
- auto setupField = [=](Utils::StringAspect* &aspect, const QString &label,
- const QString &settingsKey) {
- aspect = addAspect<StringAspect>();
- aspect->setDisplayStyle(StringAspect::DisplayStyle::LineEditDisplay);
- aspect->setLabelText(label);
- aspect->setSettingsKey(settingsKey);
- aspect->setMacroExpanderProvider([=] { return target()->kit()->macroExpander(); });
- };
- setupField(m_command, tr("Command:"), "Command");
- setupField(m_arguments, tr("Arguments:"), "Arguments");
- setupField(m_workingDirectory, tr("Working directory:"), "WorkingDirectory");
-
- setCommandLineProvider([=] { return commandLine(); });
- setWorkingDirectoryProvider([=] {
- return dockerBuildDevice() ? FilePath() : workingDirectory();
- });
- setSummaryUpdater([=] { return summary(); });
- }
-
-private:
- const DockerDevice *dockerBuildDevice() const
- {
- const IDevice::ConstPtr device = BuildDeviceKitAspect::device(target()->kit());
- return dynamic_cast<const DockerDevice *>(device.get());
- }
-
- MacroExpander *macroExpander() const
- {
- MacroExpander *expander = target()->kit()->macroExpander();
- expander->registerVariable("BuildDevice:DockerImage",
- "Build Host Docker Image ID", [this] {
- const DockerDevice *dockerDevice = dockerBuildDevice();
- return dockerDevice ? dockerDevice->data().imageId : QString();
- }, true);
- expander->registerVariable("BuildDevice:DockerRepo",
- "Build Host Docker Repo", [this] {
- const DockerDevice *dockerDevice = dockerBuildDevice();
- return dockerDevice ? dockerDevice->data().repo : QString();
- }, true);
- expander->registerVariable("BuildDevice:DockerTag",
- "Build Host Docker Tag", [this] {
- const DockerDevice *dockerDevice = dockerBuildDevice();
- return dockerDevice ? dockerDevice->data().tag : QString();
- }, true);
- return expander;
- }
-
- CommandLine commandLine() const
- {
- MacroExpander *expander = target()->kit()->macroExpander();
- CommandLine cmd;
- if (dockerBuildDevice()) {
- CommandLine dockerCmd(DOCKER_COMMAND);
- QString dockerCommand = m_dockerCommand->value();
-
- // Sneak working directory into docker "run" or "exec" call
- const QString workDir = m_workingDirectory->value();
- if (!workDir.isEmpty())
- dockerCommand.replace(QRegularExpression("[[:<:]](run|exec)[[:>:]]"),
- "\\1 --workdir " + workDir);
-
- dockerCmd.addArgs(expander->expand(dockerCommand), CommandLine::Raw);
- dockerCmd.addArgs(expander->expand(m_command->value()), CommandLine::Raw);
- cmd = dockerCmd;
- } else {
- CommandLine localCmd(FilePath::fromString(expander->expand(m_command->value())));
- cmd = localCmd;
- }
- cmd.addArgs(expander->expand(m_arguments->value()), CommandLine::Raw);
- return cmd;
- }
-
- FilePath workingDirectory() const
- {
- return FilePath::fromUserInput(target()->kit()->macroExpander()->
- expand(m_workingDirectory->value()));
- }
-
- QString summary() const
- {
- const IDevice::ConstPtr d = BuildDeviceKitAspect::device(target()->kit());
- if (!d)
- return QString(); // No build device selected in kit
- m_dockerCommand->setEnabled(dockerBuildDevice() != nullptr);
- const QString title = tr("Build on %1").arg(d->displayName());
- if (m_command->value().isEmpty()) {
- // Procuring the red "Invalid command" summary.
- ProcessParameters params;
- params.effectiveCommand();
- return params.summary(title);
- } else {
- return tr("<b>%1:</b> %2").arg(title).arg(commandLine().toUserOutput());
- }
- }
-
- Utils::StringAspect *m_dockerCommand = nullptr;
- Utils::StringAspect *m_command = nullptr;
- Utils::StringAspect *m_arguments = nullptr;
- Utils::StringAspect *m_workingDirectory = nullptr;
-};
-
-
-DockerBuildStepFactory::DockerBuildStepFactory()
-{
- registerStep<DockerBuildStep>(Constants::DOCKER_BUILDHOST_BUILDSTEP_ID);
- setDisplayName(DockerBuildStep::tr("Docker build host step"));
- setSupportedStepLists({ProjectExplorer::Constants::BUILDSTEPS_BUILD,
- ProjectExplorer::Constants::BUILDSTEPS_CLEAN});
-}
-
-} // Internal
-} // Docker
diff --git a/src/plugins/docker/dockerbuildstep.h b/src/plugins/docker/dockerbuildstep.h
deleted file mode 100644
index c00184edd00..00000000000
--- a/src/plugins/docker/dockerbuildstep.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/buildstep.h>
-
-namespace Docker {
-namespace Internal {
-
-class DockerBuildStepFactory final : public ProjectExplorer::BuildStepFactory
-{
-public:
- DockerBuildStepFactory();
-};
-
-} // Internal
-} // Docker
diff --git a/src/plugins/docker/dockerconstants.h b/src/plugins/docker/dockerconstants.h
index b8b8c6cfabf..41a98ba65ea 100644
--- a/src/plugins/docker/dockerconstants.h
+++ b/src/plugins/docker/dockerconstants.h
@@ -30,13 +30,8 @@ namespace Docker {
namespace Constants {
const char DOCKER_SETTINGS_ID[] = "Docker.Settings";
-const char ACTION_ID[] = "Docker.Action";
-const char MENU_ID[] = "Docker.Menu";
-
const char DOCKER_DEVICE_TYPE[] = "DockerDeviceType";
-const char DOCKER_BUILDHOST_BUILDSTEP_ID[] = "Docker.BuildStep.BuildHost";
-
} // namespace Constants
} // namespace Docker
diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp
index ef512981a94..2b7b671ef09 100644
--- a/src/plugins/docker/dockerdevice.cpp
+++ b/src/plugins/docker/dockerdevice.cpp
@@ -26,7 +26,8 @@
#include "dockerdevice.h"
#include "dockerconstants.h"
-#include "dockerplugin.h"
+#include "dockerdevicewidget.h"
+#include "kitdetector.h"
#include <extensionsystem/pluginmanager.h>
@@ -48,6 +49,7 @@
#include <utils/algorithm.h>
#include <utils/basetreeview.h>
+#include <utils/deviceshell.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
@@ -56,9 +58,9 @@
#include <utils/overridecursor.h>
#include <utils/pathlisteditor.h>
#include <utils/port.h>
+#include <utils/processinterface.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/stringutils.h>
#include <utils/temporaryfile.h>
#include <utils/treemodel.h>
#include <utils/utilsicons.h>
@@ -88,8 +90,6 @@
#include <sys/types.h>
#endif
-//#define ALLOW_LOCAL_ACCESS 1
-
using namespace Core;
using namespace ProjectExplorer;
using namespace QtSupport;
@@ -98,178 +98,45 @@ using namespace Utils;
namespace Docker {
namespace Internal {
+const QString s_pidMarker = "__qtc$$qtc__";
+
static Q_LOGGING_CATEGORY(dockerDeviceLog, "qtc.docker.device", QtWarningMsg);
#define LOG(x) qCDebug(dockerDeviceLog) << this << x << '\n'
-class DockerDeviceProcess : public ProjectExplorer::DeviceProcess
+class ContainerShell : public Utils::DeviceShell
{
public:
- DockerDeviceProcess(const QSharedPointer<const IDevice> &device, QObject *parent = nullptr);
- ~DockerDeviceProcess() {}
-
- void start(const Runnable &runnable) override;
- void interrupt() override;
-};
-
-DockerDeviceProcess::DockerDeviceProcess(const QSharedPointer<const IDevice> &device,
- QObject *parent)
- : DeviceProcess(device, ProcessMode::Writer, parent)
-{
-}
-
-void DockerDeviceProcess::start(const Runnable &runnable)
-{
- QTC_ASSERT(state() == QProcess::NotRunning, return);
- DockerDevice::ConstPtr dockerDevice = qSharedPointerCast<const DockerDevice>(device());
- QTC_ASSERT(dockerDevice, return);
-
- connect(this, &DeviceProcess::readyReadStandardOutput, this, [this] {
- MessageManager::writeSilently(QString::fromLocal8Bit(readAllStandardError()));
- });
- connect(this, &DeviceProcess::readyReadStandardError, this, [this] {
- MessageManager::writeDisrupting(QString::fromLocal8Bit(readAllStandardError()));
- });
-
- CommandLine command = runnable.command;
- command.setExecutable(
- command.executable().withNewPath(dockerDevice->mapToDevicePath(command.executable())));
- setCommand(command);
- setEnvironment(runnable.environment);
- setWorkingDirectory(runnable.workingDirectory);
-
- LOG("Running process:" << command.toUserOutput()
- << "in" << runnable.workingDirectory.toUserOutput());
- dockerDevice->runProcess(*this);
-}
-
-void DockerDeviceProcess::interrupt()
-{
- device()->signalOperation()->interruptProcess(processId());
-}
-
-class DockerPortsGatheringMethod : public PortsGatheringMethod
-{
- CommandLine commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const override
+ ContainerShell(const QString &containerId)
+ : m_containerId(containerId)
{
- // We might encounter the situation that protocol is given IPv6
- // but the consumer of the free port information decides to open
- // an IPv4(only) port. As a result the next IPv6 scan will
- // report the port again as open (in IPv6 namespace), while the
- // same port in IPv4 namespace might still be blocked, and
- // re-use of this port fails.
- // GDBserver behaves exactly like this.
-
- Q_UNUSED(protocol)
-
- // /proc/net/tcp* covers /proc/net/tcp and /proc/net/tcp6
- return {"sed", "-e 's/.*: [[:xdigit:]]*:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' /proc/net/tcp*",
- CommandLine::Raw};
}
- QList<Utils::Port> usedPorts(const QByteArray &output) const override
+private:
+ void setupShellProcess(QtcProcess *shellProcess) final
{
- QList<Utils::Port> ports;
- QList<QByteArray> portStrings = output.split('\n');
- foreach (const QByteArray &portString, portStrings) {
- if (portString.size() != 4)
- continue;
- bool ok;
- const Utils::Port port(portString.toInt(&ok, 16));
- if (ok) {
- if (!ports.contains(port))
- ports << port;
- } else {
- qWarning("%s: Unexpected string '%s' is not a port.",
- Q_FUNC_INFO, portString.data());
- }
- }
- return ports;
+ shellProcess->setCommand({"docker", {"container", "start", "-i", "-a", m_containerId}});
}
-};
-
-class KitDetectorPrivate
-{
- Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::KitItemDetector)
-
-public:
- KitDetectorPrivate(KitDetector *parent, const IDevice::ConstPtr &device)
- : q(parent), m_device(device)
- {}
-
- void autoDetect();
- void undoAutoDetect() const;
- void listAutoDetected() const;
-
- void setSharedId(const QString &sharedId) { m_sharedId = sharedId; }
- void setSearchPaths(const FilePaths &searchPaths) { m_searchPaths = searchPaths; }
private:
- QtVersions autoDetectQtVersions() const;
- QList<ToolChain *> autoDetectToolChains();
- void autoDetectCMake();
- void autoDetectDebugger();
-
- KitDetector *q;
- IDevice::ConstPtr m_device;
- QString m_sharedId;
- FilePaths m_searchPaths;
+ QString m_containerId;
};
-KitDetector::KitDetector(const IDevice::ConstPtr &device)
- : d(new KitDetectorPrivate(this, device))
-{}
-
-KitDetector::~KitDetector()
-{
- delete d;
-}
-
-void KitDetector::autoDetect(const QString &sharedId, const FilePaths &searchPaths) const
-{
- d->setSharedId(sharedId);
- d->setSearchPaths(searchPaths);
- d->autoDetect();
-}
-
-void KitDetector::undoAutoDetect(const QString &sharedId) const
-{
- d->setSharedId(sharedId);
- d->undoAutoDetect();
-}
-
-void KitDetector::listAutoDetected(const QString &sharedId) const
-{
- d->setSharedId(sharedId);
- d->listAutoDetected();
-}
-
class DockerDevicePrivate : public QObject
{
Q_DECLARE_TR_FUNCTIONS(Docker::Internal::DockerDevice)
public:
- DockerDevicePrivate(DockerDevice *parent) : q(parent)
- {
-#ifdef ALLOW_LOCAL_ACCESS
- connect(&m_mergedDirWatcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &path) {
- Q_UNUSED(path)
- LOG("Container watcher change, file: " << path);
- });
- connect(&m_mergedDirWatcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString &path) {
- Q_UNUSED(path)
- LOG("Container watcher change, directory: " << path);
- });
-#endif
- }
+ DockerDevicePrivate(DockerDevice *parent)
+ : q(parent)
+ {}
~DockerDevicePrivate() { stopCurrentContainer(); }
bool runInContainer(const CommandLine &cmd) const;
- bool runInShell(const CommandLine &cmd) const;
+ bool runInShell(const CommandLine &cmd, const QByteArray &stdInData = {}) const;
QByteArray outputForRunInShell(const CommandLine &cmd) const;
void updateContainerAccess();
- void updateFileSystemAccess();
void startContainer();
void stopCurrentContainer();
@@ -279,228 +146,143 @@ public:
DockerDeviceData m_data;
// For local file access
- QPointer<QtcProcess> m_shell;
- mutable QMutex m_shellMutex;
- QString m_container;
-#ifdef ALLOW_LOCAL_ACCESS
- QString m_mergedDir;
- QFileSystemWatcher m_mergedDirWatcher;
-#endif
+ std::unique_ptr<ContainerShell> m_shell;
+
+ QString m_container;
Environment m_cachedEnviroment;
bool m_useFind = true; // prefer find over ls and hacks, but be able to use ls as fallback
};
-class DockerDeviceWidget final : public IDeviceWidget
+class DockerProcessImpl : public Utils::ProcessInterface
{
- Q_DECLARE_TR_FUNCTIONS(Docker::Internal::DockerDevice)
-
public:
- explicit DockerDeviceWidget(const IDevice::Ptr &device)
- : IDeviceWidget(device), m_kitItemDetector(device)
- {
- auto dockerDevice = device.dynamicCast<DockerDevice>();
- QTC_ASSERT(dockerDevice, return);
+ DockerProcessImpl(DockerDevicePrivate *device);
+ virtual ~DockerProcessImpl();
- DockerDeviceData &data = dockerDevice->data();
+private:
+ void start() override;
+ qint64 write(const QByteArray &data) override;
+ void sendControlSignal(ControlSignal controlSignal) override;
- auto repoLabel = new QLabel(tr("Repository:"));
- m_repoLineEdit = new QLineEdit;
- m_repoLineEdit->setText(data.repo);
- m_repoLineEdit->setEnabled(false);
+private:
+ CommandLine fullLocalCommandLine(bool interactive);
- auto tagLabel = new QLabel(tr("Tag:"));
- m_tagLineEdit = new QLineEdit;
- m_tagLineEdit->setText(data.tag);
- m_tagLineEdit->setEnabled(false);
+private:
+ DockerDevicePrivate *m_devicePrivate = nullptr;
+ // Store the IDevice::ConstPtr in order to extend the lifetime of device for as long
+ // as this object is alive.
+ IDevice::ConstPtr m_device;
- auto idLabel = new QLabel(tr("Image ID:"));
- m_idLineEdit = new QLineEdit;
- m_idLineEdit->setText(data.imageId);
- m_idLineEdit->setEnabled(false);
+ QtcProcess m_process;
+ qint64 m_remotePID = -1;
+ bool m_hasReceivedFirstOutput = false;
+};
- auto daemonStateLabel = new QLabel(tr("Daemon state:"));
- m_daemonReset = new QToolButton;
- m_daemonReset->setToolTip(tr("Clears detected daemon state. "
- "It will be automatically re-evaluated next time access is needed."));
+CommandLine DockerProcessImpl::fullLocalCommandLine(bool interactive)
+{
+ QStringList args;
- m_daemonState = new QLabel;
- updateDaemonStateTexts();
+ if (!m_setup.m_workingDirectory.isEmpty()) {
+ QTC_CHECK(DeviceManager::deviceForPath(m_setup.m_workingDirectory) == m_device);
+ args.append({"cd", m_setup.m_workingDirectory.path()});
+ args.append("&&");
+ }
- connect(m_daemonReset, &QToolButton::clicked, this, [this, dockerDevice] {
- DockerPlugin::setGlobalDaemonState(Utils::nullopt);
- updateDaemonStateTexts();
- });
+ args.append({"echo", s_pidMarker, "&&"});
- m_runAsOutsideUser = new QCheckBox(tr("Run as outside user"));
- m_runAsOutsideUser->setToolTip(tr("Uses user ID and group ID of the user running Qt Creator "
- "in the docker container."));
- m_runAsOutsideUser->setChecked(data.useLocalUidGid);
- m_runAsOutsideUser->setEnabled(HostOsInfo::isLinuxHost());
+ const Environment &env = m_setup.m_environment;
+ for (auto it = env.constBegin(); it != env.constEnd(); ++it)
+ args.append(env.key(it) + "='" + env.expandedValueForKey(env.key(it)) + '\'');
- connect(m_runAsOutsideUser, &QCheckBox::toggled, this, [&data](bool on) {
- data.useLocalUidGid = on;
- });
+ args.append("exec");
+ args.append({m_setup.m_commandLine.executable().path(), m_setup.m_commandLine.arguments()});
-#ifdef ALLOW_LOCAL_ACCESS
- // This tries to find the directory in the host file system that corresponds to the
- // docker container root file system, which is a merge of the layers from the
- // container image and the volumes mapped using -v on container startup.
- //
- // Accessing files there is much faster than using 'docker exec', but conceptually
- // only works on Linux, and is restricted there by proper matching of user
- // permissions between host and container.
- m_usePathMapping = new QCheckBox(tr("Use local file path mapping"));
- m_usePathMapping->setToolTip(tr("Maps docker filesystem to a local directory."));
- m_usePathMapping->setChecked(data.useFilePathMapping);
- m_usePathMapping->setEnabled(HostOsInfo::isLinuxHost());
- connect(m_usePathMapping, &QCheckBox::toggled, this, [&, dockerDevice](bool on) {
- data.useFilePathMapping = on;
- dockerDevice->updateContainerAccess();
- });
-#endif
+ CommandLine shCmd("/bin/sh", {"-c", args.join(" ")});
+ return m_devicePrivate->q->withDockerExecCmd(shCmd, interactive);
+}
- m_pathsListLabel = new InfoLabel(tr("Paths to mount:"));
- // FIXME: 8.0: use
- //m_pathsListLabel->setToolTip(tr("Source directory list should not be empty"));
-
- m_pathsListEdit = new PathListEditor;
- // FIXME: 8.0: use
- //m_pathsListEdit->setPlaceholderText(tr("Host directories to mount into the container"));
- m_pathsListEdit->setToolTip(tr("Maps paths in this list one-to-one to the "
- "docker container."));
- m_pathsListEdit->setPathList(data.mounts);
-
- auto markupMounts = [this] {
- const bool isEmpty = m_pathsListEdit->pathList().isEmpty();
- m_pathsListLabel->setType(isEmpty ? InfoLabel::Warning : InfoLabel::None);
- };
- markupMounts();
-
- connect(m_pathsListEdit, &PathListEditor::changed, this, [dockerDevice, markupMounts, this] {
- dockerDevice->setMounts(m_pathsListEdit->pathList());
- markupMounts();
- });
+DockerProcessImpl::DockerProcessImpl(DockerDevicePrivate *device)
+ : m_devicePrivate(device)
+ , m_device(device->q->sharedFromThis())
+ , m_process(this)
+{
+ connect(&m_process, &QtcProcess::started, this, [this] {
+ qCDebug(dockerDeviceLog) << "Process started:" << m_process.commandLine();
+ });
- auto logView = new QTextBrowser;
- connect(&m_kitItemDetector, &KitDetector::logOutput,
- logView, &QTextBrowser::append);
-
- auto autoDetectButton = new QPushButton(tr("Auto-detect Kit Items"));
- auto undoAutoDetectButton = new QPushButton(tr("Remove Auto-Detected Kit Items"));
- auto listAutoDetectedButton = new QPushButton(tr("List Auto-Detected Kit Items"));
-
- auto searchDirsComboBox = new QComboBox;
- searchDirsComboBox->addItem(tr("Search in PATH"));
- searchDirsComboBox->addItem(tr("Search in Selected Directories"));
-
- auto searchDirsLineEdit = new FancyLineEdit;
- // FIXME: 8.0: use
- //searchDirsLineEdit->setPlaceholderText(tr("Semicolon-separated list of directories"));
- searchDirsLineEdit->setToolTip(
- tr("Select the paths in the docker image that should be scanned for kit entries."));
- searchDirsLineEdit->setHistoryCompleter("DockerMounts", true);
-
- auto searchPaths = [searchDirsComboBox, searchDirsLineEdit, dockerDevice] {
- FilePaths paths;
- if (searchDirsComboBox->currentIndex() == 0) {
- paths = dockerDevice->systemEnvironment().path();
- } else {
- for (const QString &path : searchDirsLineEdit->text().split(';'))
- paths.append(FilePath::fromString(path.trimmed()));
+ connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
+ if (!m_hasReceivedFirstOutput) {
+ QByteArray output = m_process.readAllStandardOutput();
+ qsizetype idx = output.indexOf('\n');
+ QByteArray firstLine = output.left(idx);
+ QByteArray rest = output.mid(idx+1);
+ qCDebug(dockerDeviceLog) << "Process first line received:" << m_process.commandLine() << firstLine;
+ if (firstLine.startsWith("__qtc")) {
+ bool ok = false;
+ m_remotePID = firstLine.mid(5, firstLine.size() -5 -5).toLongLong(&ok);
+
+ if (ok)
+ emit started(m_remotePID);
+
+ if (rest.size() > 0)
+ emit readyRead(rest, {});
+
+ m_hasReceivedFirstOutput = true;
+ return;
}
- paths = Utils::transform(paths, [dockerDevice](const FilePath &path) {
- return dockerDevice->mapToGlobalPath(path);
- });
- return paths;
- };
-
- connect(autoDetectButton, &QPushButton::clicked, this,
- [this, logView, dockerDevice, searchPaths] {
- logView->clear();
- dockerDevice->updateContainerAccess();
-
- m_kitItemDetector.autoDetect(dockerDevice->id().toString(), searchPaths());
-
- if (DockerPlugin::isDaemonRunning().value_or(false) == false)
- logView->append(tr("Docker daemon appears to be not running."));
- else
- logView->append(tr("Docker daemon appears to be running."));
- updateDaemonStateTexts();
- });
+ }
+ emit readyRead(m_process.readAllStandardOutput(), {});
+ });
- connect(undoAutoDetectButton, &QPushButton::clicked, this, [this, logView, device] {
- logView->clear();
- m_kitItemDetector.undoAutoDetect(device->id().toString());
- });
+ connect(&m_process, &QtcProcess::readyReadStandardError, this, [this] {
+ emit readyRead({}, m_process.readAllStandardError());
+ });
- connect(listAutoDetectedButton, &QPushButton::clicked, this, [this, logView, device] {
- logView->clear();
- m_kitItemDetector.listAutoDetected(device->id().toString());
- });
+ connect(&m_process, &QtcProcess::done, this, [this] {
+ qCDebug(dockerDeviceLog) << "Process exited:" << m_process.commandLine() << "with code:" << m_process.resultData().m_exitCode;
+ emit done(m_process.resultData());
+ });
- using namespace Layouting;
+}
- Form {
- repoLabel, m_repoLineEdit, Break(),
- tagLabel, m_tagLineEdit, Break(),
- idLabel, m_idLineEdit, Break(),
- daemonStateLabel, m_daemonReset, m_daemonState, Break(),
- m_runAsOutsideUser, Break(),
-#ifdef ALLOW_LOCAL_ACCESS
- m_usePathMapping, Break(),
-#endif
- Column {
- m_pathsListLabel,
- m_pathsListEdit,
- }, Break(),
- Column {
- Space(20),
- Row {
- searchDirsComboBox,
- searchDirsLineEdit
- },
- Row {
- autoDetectButton,
- undoAutoDetectButton,
- listAutoDetectedButton,
- Stretch(),
- },
- new QLabel(tr("Detection log:")),
- logView
- }
- }.attachTo(this);
+DockerProcessImpl::~DockerProcessImpl()
+{
+ if (m_process.state() == QProcess::Running)
+ sendControlSignal(ControlSignal::Kill);
+}
- searchDirsLineEdit->setVisible(false);
- auto updateDirectoriesLineEdit = [searchDirsLineEdit](int index) {
- searchDirsLineEdit->setVisible(index == 1);
- if (index == 1)
- searchDirsLineEdit->setFocus();
- };
- QObject::connect(searchDirsComboBox, qOverload<int>(&QComboBox::activated),
- this, updateDirectoriesLineEdit);
- }
+void DockerProcessImpl::start()
+{
+ m_process.setProcessImpl(m_setup.m_processImpl);
+ m_process.setProcessMode(m_setup.m_processMode);
+ m_process.setTerminalMode(m_setup.m_terminalMode);
+ m_process.setReaperTimeout(m_setup.m_reaperTimeout);
+ m_process.setWriteData(m_setup.m_writeData);
+ m_process.setProcessChannelMode(m_setup.m_processChannelMode);
+ m_process.setExtraData(m_setup.m_extraData);
+ m_process.setStandardInputFile(m_setup.m_standardInputFile);
+ m_process.setAbortOnMetaChars(m_setup.m_abortOnMetaChars);
+ if (m_setup.m_lowPriority)
+ m_process.setLowPriority();
- void updateDeviceFromUi() final {}
- void updateDaemonStateTexts();
+ m_process.setCommand(fullLocalCommandLine(m_setup.m_processMode == ProcessMode::Writer));
+ m_process.start();
+}
-private:
- QLineEdit *m_repoLineEdit;
- QLineEdit *m_tagLineEdit;
- QLineEdit *m_idLineEdit;
- QToolButton *m_daemonReset;
- QLabel *m_daemonState;
- QCheckBox *m_runAsOutsideUser;
-#ifdef ALLOW_LOCAL_ACCESS
- QCheckBox *m_usePathMapping;
-#endif
- InfoLabel *m_pathsListLabel;
- PathListEditor *m_pathsListEdit;
+qint64 DockerProcessImpl::write(const QByteArray &data)
+{
+ return m_process.writeRaw(data);
+}
- KitDetector m_kitItemDetector;
-};
+void DockerProcessImpl::sendControlSignal(ControlSignal controlSignal)
+{
+ int signal = controlSignalToInt(controlSignal);
+ m_devicePrivate->runInShell(
+ {"kill", {QString("-%1").arg(signal), QString("%2").arg(m_remotePID)}});
+}
IDeviceWidget *DockerDevice::createWidget()
{
@@ -519,7 +301,6 @@ Tasks DockerDevice::validate() const
return result;
}
-
// DockerDeviceData
QString DockerDeviceData::repoAndTag() const
@@ -554,11 +335,12 @@ DockerDevice::DockerDevice(const DockerDeviceData &data)
return;
}
- QtcProcess *proc = new QtcProcess(QtcProcess::TerminalOn);
- QObject::connect(proc, &QtcProcess::finished, proc, &QObject::deleteLater);
+ QtcProcess *proc = new QtcProcess(d);
+ proc->setTerminalMode(TerminalMode::On);
- QObject::connect(proc, &DeviceProcess::errorOccurred, [proc] {
- MessageManager::writeDisrupting(tr("Error starting remote shell."));
+ QObject::connect(proc, &QtcProcess::done, [proc] {
+ if (proc->error() != QProcess::UnknownError && MessageManager::instance())
+ MessageManager::writeDisrupting(tr("Error starting remote shell."));
proc->deleteLater();
});
@@ -588,236 +370,7 @@ DockerDeviceData &DockerDevice::data()
return d->m_data;
}
-void KitDetectorPrivate::undoAutoDetect() const
-{
- emit q->logOutput(tr("Start removing auto-detected items associated with this docker image."));
-
- emit q->logOutput('\n' + tr("Removing kits..."));
- for (Kit *kit : KitManager::kits()) {
- if (kit->autoDetectionSource() == m_sharedId) {
- emit q->logOutput(tr("Removed \"%1\"").arg(kit->displayName()));
- KitManager::deregisterKit(kit);
- }
- };
-
- emit q->logOutput('\n' + tr("Removing Qt version entries..."));
- for (QtVersion *qtVersion : QtVersionManager::versions()) {
- if (qtVersion->detectionSource() == m_sharedId) {
- emit q->logOutput(tr("Removed \"%1\"").arg(qtVersion->displayName()));
- QtVersionManager::removeVersion(qtVersion);
- }
- };
-
- emit q->logOutput('\n' + tr("Removing toolchain entries..."));
- const Toolchains toolchains = ToolChainManager::toolchains();
- for (ToolChain *toolChain : toolchains) {
- if (toolChain && toolChain->detectionSource() == m_sharedId) {
- emit q->logOutput(tr("Removed \"%1\"").arg(toolChain->displayName()));
- ToolChainManager::deregisterToolChain(toolChain);
- }
- };
-
- if (QObject *cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager")) {
- QString logMessage;
- const bool res = QMetaObject::invokeMethod(cmakeManager,
- "removeDetectedCMake",
- Q_ARG(QString, m_sharedId),
- Q_ARG(QString *, &logMessage));
- QTC_CHECK(res);
- emit q->logOutput('\n' + logMessage);
- }
-
- if (QObject *debuggerPlugin = ExtensionSystem::PluginManager::getObjectByName("DebuggerPlugin")) {
- QString logMessage;
- const bool res = QMetaObject::invokeMethod(debuggerPlugin,
- "removeDetectedDebuggers",
- Q_ARG(QString, m_sharedId),
- Q_ARG(QString *, &logMessage));
- QTC_CHECK(res);
- emit q->logOutput('\n' + logMessage);
- }
-
- emit q->logOutput('\n' + tr("Removal of previously auto-detected kit items finished.") + "\n\n");
-}
-
-void KitDetectorPrivate::listAutoDetected() const
-{
- emit q->logOutput(tr("Start listing auto-detected items associated with this docker image."));
-
- emit q->logOutput('\n' + tr("Kits:"));
- for (Kit *kit : KitManager::kits()) {
- if (kit->autoDetectionSource() == m_sharedId)
- emit q->logOutput(kit->displayName());
- };
-
- emit q->logOutput('\n' + tr("Qt versions:"));
- for (QtVersion *qtVersion : QtVersionManager::versions()) {
- if (qtVersion->detectionSource() == m_sharedId)
- emit q->logOutput(qtVersion->displayName());
- };
-
- emit q->logOutput('\n' + tr("Toolchains:"));
- for (ToolChain *toolChain : ToolChainManager::toolchains()) {
- if (toolChain->detectionSource() == m_sharedId)
- emit q->logOutput(toolChain->displayName());
- };
-
- if (QObject *cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager")) {
- QString logMessage;
- const bool res = QMetaObject::invokeMethod(cmakeManager,
- "listDetectedCMake",
- Q_ARG(QString, m_sharedId),
- Q_ARG(QString *, &logMessage));
- QTC_CHECK(res);
- emit q->logOutput('\n' + logMessage);
- }
-
- if (QObject *debuggerPlugin = ExtensionSystem::PluginManager::getObjectByName("DebuggerPlugin")) {
- QString logMessage;
- const bool res = QMetaObject::invokeMethod(debuggerPlugin,
- "listDetectedDebuggers",
- Q_ARG(QString, m_sharedId),
- Q_ARG(QString *, &logMessage));
- QTC_CHECK(res);
- emit q->logOutput('\n' + logMessage);
- }
-
- emit q->logOutput('\n' + tr("Listing of previously auto-detected kit items finished.") + "\n\n");
-}
-
-QtVersions KitDetectorPrivate::autoDetectQtVersions() const
-{
- QtVersions qtVersions;
-
- QString error;
-
- const auto handleQmake = [this, &qtVersions, &error](const FilePath &qmake) {
- if (QtVersion *qtVersion = QtVersionFactory::createQtVersionFromQMakePath(qmake, false, m_sharedId, &error)) {
- qtVersions.append(qtVersion);
- QtVersionManager::addVersion(qtVersion);
- emit q->logOutput(tr("Found \"%1\"").arg(qtVersion->qmakeFilePath().toUserOutput()));
- }
- return true;
- };
-
- emit q->logOutput(tr("Searching for qmake executables..."));
-
- const QStringList candidates = {"qmake-qt6", "qmake-qt5", "qmake"};
- for (const FilePath &searchPath : m_searchPaths) {
- searchPath.iterateDirectory(handleQmake, {candidates, QDir::Files | QDir::Executable,
- QDirIterator::Subdirectories});
- }
-
- if (!error.isEmpty())
- emit q->logOutput(tr("Error: %1.").arg(error));
- if (qtVersions.isEmpty())
- emit q->logOutput(tr("No Qt installation found."));
- return qtVersions;
-}
-
-Toolchains KitDetectorPrivate::autoDetectToolChains()
-{
- const QList<ToolChainFactory *> factories = ToolChainFactory::allToolChainFactories();
-
- Toolchains alreadyKnown = ToolChainManager::toolchains();
- Toolchains allNewToolChains;
- QApplication::processEvents();
- emit q->logOutput('\n' + tr("Searching toolchains..."));
- for (ToolChainFactory *factory : factories) {
- emit q->logOutput(tr("Searching toolchains of type %1").arg(factory->displayName()));
- const ToolchainDetector detector(alreadyKnown, m_device, m_searchPaths);
- const Toolchains newToolChains = factory->autoDetect(detector);
- for (ToolChain *toolChain : newToolChains) {
- emit q->logOutput(tr("Found \"%1\"").arg(toolChain->compilerCommand().toUserOutput()));
- toolChain->setDetectionSource(m_sharedId);
- ToolChainManager::registerToolChain(toolChain);
- alreadyKnown.append(toolChain);
- }
- allNewToolChains.append(newToolChains);
- }
- emit q->logOutput(tr("%1 new toolchains found.").arg(allNewToolChains.size()));
-
- return allNewToolChains;
-}
-
-void KitDetectorPrivate::autoDetectCMake()
-{
- QObject *cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager");
- if (!cmakeManager)
- return;
-
- QString logMessage;
- const bool res = QMetaObject::invokeMethod(cmakeManager,
- "autoDetectCMakeForDevice",
- Q_ARG(Utils::FilePaths, m_searchPaths),
- Q_ARG(QString, m_sharedId),
- Q_ARG(QString *, &logMessage));
- QTC_CHECK(res);
- emit q->logOutput('\n' + logMessage);
-}
-
-void KitDetectorPrivate::autoDetectDebugger()
-{
- QObject *debuggerPlugin = ExtensionSystem::PluginManager::getObjectByName("DebuggerPlugin");
- if (!debuggerPlugin)
- return;
-
- QString logMessage;
- const bool res = QMetaObject::invokeMethod(debuggerPlugin,
- "autoDetectDebuggersForDevice",
- Q_ARG(Utils::FilePaths, m_searchPaths),
- Q_ARG(QString, m_sharedId),
- Q_ARG(QString *, &logMessage));
- QTC_CHECK(res);
- emit q->logOutput('\n' + logMessage);
-}
-
-void KitDetectorPrivate::autoDetect()
-{
- QApplication::setOverrideCursor(Qt::WaitCursor);
-
- undoAutoDetect();
-
- emit q->logOutput(tr("Starting auto-detection. This will take a while..."));
-
- const Toolchains toolchains = autoDetectToolChains();
- const QtVersions qtVersions = autoDetectQtVersions();
- autoDetectCMake();
- autoDetectDebugger();
-
- const auto initializeKit = [this, toolchains, qtVersions](Kit *k) {
- k->setAutoDetected(false);
- k->setAutoDetectionSource(m_sharedId);
- k->setUnexpandedDisplayName("%{Device:Name}");
-
- DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DOCKER_DEVICE_TYPE);
- DeviceKitAspect::setDevice(k, m_device);
-
- QtVersion *qt = nullptr;
- if (!qtVersions.isEmpty()) {
- qt = qtVersions.at(0);
- QtSupport::QtKitAspect::setQtVersion(k, qt);
- }
- Toolchains toolchainsToSet;
- toolchainsToSet = ToolChainManager::toolchains([qt, this](const ToolChain *tc){
- return tc->detectionSource() == m_sharedId
- && (!qt || qt->qtAbis().contains(tc->targetAbi()));
- });
- for (ToolChain *toolChain : toolchainsToSet)
- ToolChainKitAspect::setToolChain(k, toolChain);
-
- k->setSticky(ToolChainKitAspect::id(), true);
- k->setSticky(QtSupport::QtKitAspect::id(), true);
- k->setSticky(DeviceKitAspect::id(), true);
- k->setSticky(DeviceTypeKitAspect::id(), true);
- };
-
- Kit *kit = KitManager::registerKit(initializeKit);
- emit q->logOutput('\n' + tr("Registered kit %1").arg(kit->displayName()));
-
- QApplication::restoreOverrideCursor();
-}
void DockerDevice::updateContainerAccess() const
{
@@ -826,32 +379,15 @@ void DockerDevice::updateContainerAccess() const
void DockerDevicePrivate::stopCurrentContainer()
{
- if (m_container.isEmpty() || !DockerPlugin::isDaemonRunning().value_or(false))
+ if (m_container.isEmpty() || !DockerApi::isDockerDaemonAvailable(false).value_or(false))
return;
- if (m_shell) {
- QMutexLocker l(&m_shellMutex);
- m_shell->write("exit\n");
- m_shell->waitForFinished(2000);
- if (m_shell->state() == QProcess::NotRunning) {
- LOG("Clean exit via shell");
- m_container.clear();
-#ifdef ALLOW_LOCAL_ACCESS
- m_mergedDir.clear();
-#endif
- delete m_shell;
- m_shell = nullptr;
- return;
- }
- }
+ m_shell.reset();
QtcProcess proc;
proc.setCommand({"docker", {"container", "stop", m_container}});
m_container.clear();
-#ifdef ALLOW_LOCAL_ACCESS
- m_mergedDir.clear();
-#endif
proc.runBlocking();
}
@@ -904,50 +440,32 @@ void DockerDevicePrivate::startContainer()
createProcess.setCommand(dockerCreate);
createProcess.runBlocking();
- if (createProcess.result() != QtcProcess::FinishedWithSuccess)
+ if (createProcess.result() != ProcessResult::FinishedWithSuccess)
return;
- m_container = createProcess.stdOut().trimmed();
+ m_container = createProcess.cleanedStdOut().trimmed();
if (m_container.isEmpty())
return;
LOG("Container via process: " << m_container);
- CommandLine dockerRun{"docker", {"container" , "start", "-i", "-a", m_container}};
- LOG("RUNNING: " << dockerRun.toUserOutput());
- QPointer<QtcProcess> shell = new QtcProcess(ProcessMode::Writer);
- connect(shell, &QtcProcess::finished, this, [this, shell] {
- LOG("\nSHELL FINISHED\n");
- QTC_ASSERT(shell, return);
- const int exitCode = shell->exitCode();
- LOG("RES: " << shell->result()
- << " EXIT CODE: " << exitCode
- << " STDOUT: " << shell->readAllStandardOutput()
- << " STDERR: " << shell->readAllStandardError());
- // negative exit codes indicate problems like no docker daemon, missing permissions,
- // no shell and seem to result in exit codes 125+
- if (exitCode > 120) {
- DockerPlugin::setGlobalDaemonState(false);
- LOG("DOCKER DAEMON NOT RUNNING?");
- MessageManager::writeFlashing(tr("Docker daemon appears to be not running. "
- "Verify daemon is up and running and reset the "
- "docker daemon on the docker device settings page "
- "or restart Qt Creator."));
- }
- });
+ m_shell = std::make_unique<ContainerShell>(m_container);
+ connect(m_shell.get(), &DeviceShell::done, this, [this] (const ProcessResultData &resultData) {
+ if (resultData.m_error != QProcess::UnknownError)
+ return;
- QTC_ASSERT(!m_shell, delete m_shell);
- m_shell = shell;
- m_shell->setCommand(dockerRun);
- m_shell->start();
- m_shell->waitForStarted();
+ qCWarning(dockerDeviceLog) << "Container shell encountered error:" << resultData.m_error;
+ m_shell.reset();
- if (!m_shell->isRunning()) {
- DockerPlugin::setGlobalDaemonState(false);
- LOG("DOCKER SHELL FAILED");
- return;
- }
+ DockerApi::recheckDockerDaemon();
+ MessageManager::writeFlashing(tr("Docker daemon appears to be not running. "
+ "Verify daemon is up and running and reset the "
+ "docker daemon on the docker device settings page "
+ "or restart Qt Creator."));
+ });
- DockerPlugin::setGlobalDaemonState(true);
+ if (!m_shell->start()) {
+ qCWarning(dockerDeviceLog) << "Container shell failed to start";
+ }
}
void DockerDevicePrivate::updateContainerAccess()
@@ -955,72 +473,13 @@ void DockerDevicePrivate::updateContainerAccess()
if (!m_container.isEmpty())
return;
- if (DockerPlugin::isDaemonRunning().value_or(true) == false)
+ if (DockerApi::isDockerDaemonAvailable(false).value_or(false) == false)
return;
- if (!m_shell)
- startContainer();
-
- updateFileSystemAccess();
-}
-
-void DockerDevicePrivate::updateFileSystemAccess()
-{
-#ifdef ALLOW_LOCAL_ACCESS
- if (!m_data.useFilePathMapping) {
- // Direct access was used previously, but is not wanted anymore.
- if (!m_mergedDir.isEmpty()) {
- m_mergedDirWatcher.removePath(m_mergedDir);
- m_mergedDir.clear();
- }
+ if (m_shell)
return;
- }
- if (!DockerPlugin::isDaemonRunning().value_or(false))
- return;
-
- QtcProcess proc;
- proc.setCommand({"docker", {"inspect", "--format={{.GraphDriver.Data.MergedDir}}", m_container}});
- LOG(proc.commandLine().toUserOutput());
- proc.start();
- proc.waitForFinished();
- const QString out = proc.stdOut();
- m_mergedDir = out.trimmed();
- LOG("Found merged dir: " << m_mergedDir);
- if (m_mergedDir.endsWith('/'))
- m_mergedDir.chop(1);
-
- if (!QFileInfo(m_mergedDir).isReadable()) {
- MessageManager::writeFlashing(
- tr("Local read access to docker container %1 unavailable through directory \"%2\".")
- .arg(m_container, m_mergedDir)
- + '\n' + tr("Output: \"%1\"").arg(out)
- + '\n' + tr("Error: \"%1\"").arg(proc.stdErr()));
- if (!HostOsInfo::isLinuxHost()) {
- // Disabling merged layer access. This is not supported and anything
- // related to accessing merged layers on Windows or macOS fails due
- // to the need of using wsl or a named pipe.
- // TODO investigate how to make it possible nevertheless.
- m_mergedDir.clear();
- MessageManager::writeSilently(tr("This is expected on Windows and macOS."));
- return;
- }
- }
-
- m_mergedDirWatcher.addPath(m_mergedDir);
-#endif
-}
-
-bool DockerDevice::hasLocalFileAccess() const
-{
-#ifdef ALLOW_LOCAL_ACCESS
- static const bool denyLocalAccess = qEnvironmentVariableIsSet("QTC_DOCKER_DENY_LOCAL_ACCESS");
- if (denyLocalAccess)
- return false;
- return !d->m_mergedDir.isEmpty();
-#else
- return false;
-#endif
+ startContainer();
}
void DockerDevice::setMounts(const QStringList &mounts) const
@@ -1029,42 +488,18 @@ void DockerDevice::setMounts(const QStringList &mounts) const
d->stopCurrentContainer(); // Force re-start with new mounts.
}
-FilePath DockerDevice::mapToLocalAccess(const FilePath &filePath) const
+CommandLine DockerDevice::withDockerExecCmd(const Utils::CommandLine &cmd, bool interactive) const
{
-#ifdef ALLOW_LOCAL_ACCESS
- QTC_ASSERT(!d->m_mergedDir.isEmpty(), return {});
- QString path = filePath.path();
- for (const QString &mount : qAsConst(d->m_data.mounts)) {
- if (path.startsWith(mount + '/'))
- return FilePath::fromString(path);
- }
- if (path.startsWith('/'))
- return FilePath::fromString(d->m_mergedDir + path);
- return FilePath::fromString(d->m_mergedDir + '/' + path);
-#else
- QTC_CHECK(false);
- Q_UNUSED(filePath)
- return {};
-#endif
-}
+ QStringList args;
-FilePath DockerDevice::mapFromLocalAccess(const FilePath &filePath) const
-{
- QTC_ASSERT(!filePath.needsDevice(), return {});
- return mapFromLocalAccess(filePath.toString());
-}
+ args << "exec";
+ if (interactive)
+ args << "-i";
+ args << d->m_container;
-FilePath DockerDevice::mapFromLocalAccess(const QString &filePath) const
-{
-#ifdef ALLOW_LOCAL_FILE_ACCESS
- QTC_ASSERT(!d->m_mergedDir.isEmpty(), return {});
- QTC_ASSERT(filePath.startsWith(d->m_mergedDir), return FilePath::fromString(filePath));
- return mapToGlobalPath(FilePath::fromString(filePath.mid(d->m_mergedDir.size())));
-#else
- Q_UNUSED(filePath)
- QTC_CHECK(false);
- return {};
-#endif
+ CommandLine dcmd{"docker", args};
+ dcmd.addCommandLineAsArgs(cmd);
+ return dcmd;
}
const char DockerDeviceDataImageIdKey[] = "DockerDeviceDataImageId";
@@ -1072,7 +507,6 @@ const char DockerDeviceDataRepoKey[] = "DockerDeviceDataRepo";
const char DockerDeviceDataTagKey[] = "DockerDeviceDataTag";
const char DockerDeviceDataSizeKey[] = "DockerDeviceDataSize";
const char DockerDeviceUseOutsideUser[] = "DockerDeviceUseUidGid";
-const char DockerDeviceUseFilePathMapping[] = "DockerDeviceFilePathMapping";
const char DockerDeviceMappedPaths[] = "DockerDeviceMappedPaths";
void DockerDevice::fromMap(const QVariantMap &map)
@@ -1084,8 +518,6 @@ void DockerDevice::fromMap(const QVariantMap &map)
d->m_data.size = map.value(DockerDeviceDataSizeKey).toString();
d->m_data.useLocalUidGid = map.value(DockerDeviceUseOutsideUser,
HostOsInfo::isLinuxHost()).toBool();
- d->m_data.useFilePathMapping = map.value(DockerDeviceUseFilePathMapping,
- HostOsInfo::isLinuxHost()).toBool();
d->m_data.mounts = map.value(DockerDeviceMappedPaths).toStringList();
}
@@ -1097,14 +529,13 @@ QVariantMap DockerDevice::toMap() const
map.insert(DockerDeviceDataImageIdKey, d->m_data.imageId);
map.insert(DockerDeviceDataSizeKey, d->m_data.size);
map.insert(DockerDeviceUseOutsideUser, d->m_data.useLocalUidGid);
- map.insert(DockerDeviceUseFilePathMapping, d->m_data.useFilePathMapping);
map.insert(DockerDeviceMappedPaths, d->m_data.mounts);
return map;
}
-DeviceProcess *DockerDevice::createProcess(QObject *parent) const
+ProcessInterface *DockerDevice::createProcessInterface() const
{
- return new DockerDeviceProcess(sharedFromThis(), parent);
+ return new DockerProcessImpl(d);
}
bool DockerDevice::canAutoDetectPorts() const
@@ -1112,10 +543,29 @@ bool DockerDevice::canAutoDetectPorts() const
return true;
}
-PortsGatheringMethod::Ptr DockerDevice::portsGatheringMethod() const
+PortsGatheringMethod DockerDevice::portsGatheringMethod() const
{
- return DockerPortsGatheringMethod::Ptr(new DockerPortsGatheringMethod);
-}
+ return {
+ [this](QAbstractSocket::NetworkLayerProtocol protocol) -> CommandLine {
+ // We might encounter the situation that protocol is given IPv6
+ // but the consumer of the free port information decides to open
+ // an IPv4(only) port. As a result the next IPv6 scan will
+ // report the port again as open (in IPv6 namespace), while the
+ // same port in IPv4 namespace might still be blocked, and
+ // re-use of this port fails.
+ // GDBserver behaves exactly like this.
+
+ Q_UNUSED(protocol)
+
+ // /proc/net/tcp* covers /proc/net/tcp and /proc/net/tcp6
+ return {filePath("sed"),
+ "-e 's/.*: [[:xdigit:]]*:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' /proc/net/tcp*",
+ CommandLine::Raw};
+ },
+
+ &Port::parseFromSedOutput
+ };
+};
DeviceProcessList *DockerDevice::createProcessListModel(QObject *) const
{
@@ -1189,12 +639,6 @@ bool DockerDevice::isExecutableFile(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.isExecutableFile();
- LOG("Executable? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"test", {"-x", path}});
}
@@ -1203,12 +647,6 @@ bool DockerDevice::isReadableFile(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.isReadableFile();
- LOG("ReadableFile? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"test", {"-r", path, "-a", "-f", path}});
}
@@ -1217,12 +655,6 @@ bool DockerDevice::isWritableFile(const Utils::FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.isWritableFile();
- LOG("WritableFile? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"test", {"-w", path, "-a", "-f", path}});
}
@@ -1231,12 +663,6 @@ bool DockerDevice::isReadableDirectory(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.isReadableDir();
- LOG("ReadableDirectory? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"test", {"-r", path, "-a", "-d", path}});
}
@@ -1245,12 +671,6 @@ bool DockerDevice::isWritableDirectory(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.isWritableDir();
- LOG("WritableDirectory? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"test", {"-w", path, "-a", "-d", path}});
}
@@ -1259,12 +679,6 @@ bool DockerDevice::isFile(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.isFile();
- LOG("IsFile? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"test", {"-f", path}});
}
@@ -1273,12 +687,6 @@ bool DockerDevice::isDirectory(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.isDir();
- LOG("IsDirectory? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"test", {"-d", path}});
}
@@ -1287,12 +695,6 @@ bool DockerDevice::createDirectory(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.createDir();
- LOG("CreateDirectory? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInContainer({"mkdir", {"-p", path}});
}
@@ -1301,12 +703,6 @@ bool DockerDevice::exists(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.exists();
- LOG("Exists? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"test", {"-e", path}});
}
@@ -1315,12 +711,6 @@ bool DockerDevice::ensureExistingFile(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.ensureExistingFile();
- LOG("Ensure existing file? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.path();
return d->runInShell({"touch", {path}});
}
@@ -1329,12 +719,6 @@ bool DockerDevice::removeFile(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.removeFile();
- LOG("Remove? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
return d->runInContainer({"rm", {filePath.path()}});
}
@@ -1343,12 +727,6 @@ bool DockerDevice::removeRecursively(const FilePath &filePath) const
QTC_ASSERT(handlesFile(filePath), return false);
QTC_ASSERT(filePath.path().startsWith('/'), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const bool res = localAccess.removeRecursively();
- LOG("Remove recursively? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
const QString path = filePath.cleanPath().path();
// We are expecting this only to be called in a context of build directories or similar.
@@ -1365,13 +743,6 @@ bool DockerDevice::copyFile(const FilePath &filePath, const FilePath &target) co
QTC_ASSERT(handlesFile(filePath), return false);
QTC_ASSERT(handlesFile(target), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const FilePath localTarget = mapToLocalAccess(target);
- const bool res = localAccess.copyFile(localTarget);
- LOG("Copy " << filePath.toUserOutput() << localAccess.toUserOutput() << localTarget << res);
- return res;
- }
return d->runInContainer({"cp", {filePath.path(), target.path()}});
}
@@ -1380,13 +751,6 @@ bool DockerDevice::renameFile(const FilePath &filePath, const FilePath &target)
QTC_ASSERT(handlesFile(filePath), return false);
QTC_ASSERT(handlesFile(target), return false);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const FilePath localTarget = mapToLocalAccess(target);
- const bool res = localAccess.renameFile(localTarget);
- LOG("Move " << filePath.toUserOutput() << localAccess.toUserOutput() << localTarget << res);
- return res;
- }
return d->runInContainer({"mv", {filePath.path(), target.path()}});
}
@@ -1394,14 +758,7 @@ QDateTime DockerDevice::lastModified(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return {});
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const QDateTime res = localAccess.lastModified();
- LOG("Last modified? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
- return res;
- }
-
- const QByteArray output = d->outputForRunInShell({"stat", {"-c", "%Y", filePath.path()}});
+ const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%Y", filePath.path()}});
qint64 secs = output.toLongLong();
const QDateTime dt = QDateTime::fromSecsSinceEpoch(secs, Qt::UTC);
return dt;
@@ -1411,15 +768,6 @@ FilePath DockerDevice::symLinkTarget(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return {});
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- const FilePath target = localAccess.symLinkTarget();
- LOG("SymLinkTarget? " << filePath.toUserOutput() << localAccess.toUserOutput() << target);
- if (target.isEmpty())
- return {};
- return mapToGlobalPath(target);
- }
-
const QByteArray output = d->outputForRunInShell({"readlink", {"-n", "-e", filePath.path()}});
const QString out = QString::fromUtf8(output.data(), output.size());
return out.isEmpty() ? FilePath() : filePath.withNewPath(out);
@@ -1429,13 +777,7 @@ qint64 DockerDevice::fileSize(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return -1);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- LOG("File size? " << filePath.toUserOutput() << localAccess.toUserOutput() << localAccess.fileSize());
- return localAccess.fileSize();
- }
-
- const QByteArray output = d->outputForRunInShell({"stat", {"-c", "%s", filePath.path()}});
+ const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%s", filePath.path()}});
return output.toLongLong();
}
@@ -1443,13 +785,8 @@ QFileDevice::Permissions DockerDevice::permissions(const FilePath &filePath) con
{
QTC_ASSERT(handlesFile(filePath), return {});
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- LOG("Permissions? " << filePath.toUserOutput() << localAccess.toUserOutput() << localAccess.permissions());
- return localAccess.permissions();
- }
- const QByteArray output = d->outputForRunInShell({"stat", {"-c", "%a", filePath.path()}});
+ const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%a", filePath.path()}});
const uint bits = output.toUInt(nullptr, 8);
QFileDevice::Permissions perm = {};
#define BIT(n, p) if (bits & (1<<n)) perm |= QFileDevice::p
@@ -1468,14 +805,9 @@ QFileDevice::Permissions DockerDevice::permissions(const FilePath &filePath) con
bool DockerDevice::setPermissions(const FilePath &filePath, QFileDevice::Permissions permissions) const
{
+ Q_UNUSED(permissions)
QTC_ASSERT(handlesFile(filePath), return {});
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath localAccess = mapToLocalAccess(filePath);
- LOG("Set permissions? " << filePath.toUserOutput() << localAccess.toUserOutput() << localAccess.permissions());
- return localAccess.setPermissions(permissions);
- }
-
QTC_CHECK(false); // FIXME: Implement.
return false;
}
@@ -1494,24 +826,43 @@ void DockerDevice::iterateWithFind(const FilePath &filePath,
else
arguments.prepend("-L");
+ arguments.append({"-mindepth", "1"});
+
if (!filter.iteratorFlags.testFlag(QDirIterator::Subdirectories))
arguments.append({"-maxdepth", "1"});
QStringList filterOptions;
+
+ if (!(filters & QDir::Hidden))
+ filterOptions << "!" << "-name" << ".*";
+
+ QStringList filterFilesAndDirs;
if (filters & QDir::Dirs)
- filterOptions << "-type" << "d";
+ filterFilesAndDirs << "-type" << "d";
if (filters & QDir::Files) {
- if (!filterOptions.isEmpty())
- filterOptions << "-o";
- filterOptions << "-type" << "f";
+ if (!filterFilesAndDirs.isEmpty())
+ filterFilesAndDirs << "-o";
+ filterFilesAndDirs << "-type" << "f";
}
+ if (!filterFilesAndDirs.isEmpty())
+ filterOptions << "(" << filterFilesAndDirs << ")";
+ QStringList accessOptions;
if (filters & QDir::Readable)
- filterOptions << "-readable";
- if (filters & QDir::Writable)
- filterOptions << "-writable";
- if (filters & QDir::Executable)
- filterOptions << "-executable";
+ accessOptions << "-readable";
+ if (filters & QDir::Writable) {
+ if (!accessOptions.isEmpty())
+ accessOptions << "-o";
+ accessOptions << "-writable";
+ }
+ if (filters & QDir::Executable) {
+ if (!accessOptions.isEmpty())
+ accessOptions << "-o";
+ accessOptions << "-executable";
+ }
+
+ if (!accessOptions.isEmpty())
+ filterOptions << "(" << accessOptions << ")";
QTC_CHECK(filters ^ QDir::AllDirs);
QTC_CHECK(filters ^ QDir::Drives);
@@ -1557,55 +908,12 @@ void DockerDevice::iterateWithFind(const FilePath &filePath,
}
}
-static void filterEntriesHelper(const FilePath &base,
- const std::function<bool(const FilePath &)> &callBack,
- const QStringList &entries,
- const FileFilter &filter)
-{
- QTC_CHECK(filter.iteratorFlags != QDirIterator::NoIteratorFlags); // FIXME: Not supported yet below.
-
- const QList<QRegularExpression> nameRegexps =
- transform(filter.nameFilters, [](const QString &filter) {
- QRegularExpression re;
- re.setPattern(QRegularExpression::wildcardToRegularExpression(filter));
- QTC_CHECK(re.isValid());
- return re;
- });
-
- const auto nameMatches = [&nameRegexps](const QString &fileName) {
- for (const QRegularExpression &re : nameRegexps) {
- const QRegularExpressionMatch match = re.match(fileName);
- if (match.hasMatch())
- return true;
- }
- return nameRegexps.isEmpty();
- };
-
- // FIXME: Handle filters. For now bark on unsupported options.
- QTC_CHECK(filter.fileFilters == QDir::NoFilter);
-
- for (const QString &entry : entries) {
- if (!nameMatches(entry))
- continue;
- if (!callBack(base.pathAppended(entry)))
- break;
- }
-}
-
void DockerDevice::iterateDirectory(const FilePath &filePath,
const std::function<bool(const FilePath &)> &callBack,
const FileFilter &filter) const
{
QTC_ASSERT(handlesFile(filePath), return);
updateContainerAccess();
- if (hasLocalFileAccess()) {
- const FilePath local = mapToLocalAccess(filePath);
- local.iterateDirectory([&callBack, this](const FilePath &entry) {
- return callBack(mapFromLocalAccess(entry));
- },
- filter);
- return;
- }
if (d->m_useFind) {
iterateWithFind(filePath, callBack, filter);
@@ -1617,17 +925,14 @@ void DockerDevice::iterateDirectory(const FilePath &filePath,
// if we do not have find - use ls as fallback
const QByteArray output = d->outputForRunInShell({"ls", {"-1", "-b", "--", filePath.path()}});
- const QString out = QString::fromUtf8(output.data(), output.size());
- const QStringList entries = out.split('\n', Qt::SkipEmptyParts);
- filterEntriesHelper(filePath, callBack, entries, filter);
+ const QStringList entries = QString::fromUtf8(output).split('\n', Qt::SkipEmptyParts);
+ FileUtils::iterateLsOutput(filePath, entries, filter, callBack);
}
QByteArray DockerDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const
{
QTC_ASSERT(handlesFile(filePath), return {});
updateContainerAccess();
- if (hasLocalFileAccess())
- return mapToLocalAccess(filePath).fileContents(limit, offset);
QStringList args = {"if=" + filePath.path(), "status=none"};
if (limit > 0 || offset > 0) {
@@ -1638,8 +943,8 @@ QByteArray DockerDevice::fileContents(const FilePath &filePath, qint64 limit, qi
}
QtcProcess proc;
- proc.setCommand({"dd", args});
- runProcess(proc);
+ proc.setCommand(withDockerExecCmd({"dd", args}));
+ proc.start();
proc.waitForFinished();
QByteArray output = proc.readAllStandardOutput();
@@ -1650,82 +955,17 @@ bool DockerDevice::writeFileContents(const FilePath &filePath, const QByteArray
{
QTC_ASSERT(handlesFile(filePath), return {});
updateContainerAccess();
- if (hasLocalFileAccess())
- return mapToLocalAccess(filePath).writeFileContents(data);
-
-// This following would be the generic Unix solution.
-// But it doesn't pass input. FIXME: Why?
-// QtcProcess proc;
-// proc.setCommand({"dd", {"of=" + filePath.path()}});
-// proc.setWriteData(data);
-// runProcess(proc);
-// proc.waitForFinished();
-
- TemporaryFile tempFile("dockertransport-XXXXXX");
- tempFile.open();
- tempFile.write(data);
-
- const QString tempName = tempFile.fileName();
- tempFile.close();
-
- CommandLine cmd{"docker", {"cp", tempName, d->m_container + ':' + filePath.path()}};
-
- QtcProcess proc;
- proc.setCommand(cmd);
- proc.runBlocking();
-
- return proc.exitCode() == 0;
-}
-
-void DockerDevice::runProcess(QtcProcess &process) const
-{
- updateContainerAccess();
- if (!DockerPlugin::isDaemonRunning().value_or(false))
- return;
- if (d->m_container.isEmpty()) {
- LOG("No container set to run " << process.commandLine().toUserOutput());
- QTC_CHECK(false);
- process.setResult(QtcProcess::StartFailed);
- return;
- }
-
- const FilePath workingDir = process.workingDirectory();
- const Environment env = process.environment();
-
- CommandLine cmd{"docker", {"exec"}};
- if (!workingDir.isEmpty()) {
- cmd.addArgs({"-w", mapToDevicePath(workingDir)});
- if (QTC_GUARD(workingDir.needsDevice())) // warn on local working directory for docker cmd
- process.setWorkingDirectory(FileUtils::homePath()); // reset working dir for docker exec
- }
- if (process.processMode() == ProcessMode::Writer)
- cmd.addArg("-i");
- if (env.size() != 0 && !hasLocalFileAccess()) {
- process.unsetEnvironment();
- // FIXME the below would be probably correct if the respective tools would use correct
- // environment already, but most are using the host environment which usually makes
- // no sense on the device and may degrade performance
- // const QStringList envList = env.toStringList();
- // for (const QString &keyValue : envList) {
- // cmd.addArg("-e");
- // cmd.addArg(keyValue);
- // }
- }
- cmd.addArg(d->m_container);
- cmd.addCommandLineAsArgs(process.commandLine());
-
- LOG("Run" << cmd.toUserOutput() << " in " << workingDir.toUserOutput());
- process.setCommand(cmd);
- process.start();
+ QTC_ASSERT(handlesFile(filePath), return {});
+ return d->runInShell({"dd", {"of=" + filePath.path()}}, data);
}
Environment DockerDevice::systemEnvironment() const
{
- if (d->m_cachedEnviroment.size() == 0)
+ if (!d->m_cachedEnviroment.isValid())
d->fetchSystemEnviroment();
- QTC_CHECK(d->m_cachedEnviroment.size() != 0);
+ QTC_CHECK(d->m_cachedEnviroment.isValid());
return d->m_cachedEnviroment;
}
@@ -1745,22 +985,21 @@ void DockerDevicePrivate::fetchSystemEnviroment()
}
QtcProcess proc;
- proc.setCommand({"env", {}});
-
- q->runProcess(proc); // FIXME: This only starts.
+ proc.setCommand(q->withDockerExecCmd({"env", {}}));
+ proc.start();
proc.waitForFinished();
+ const QString remoteOutput = proc.cleanedStdOut();
- const QString remoteOutput = proc.stdOut();
m_cachedEnviroment = Environment(remoteOutput.split('\n', Qt::SkipEmptyParts), q->osType());
- const QString remoteError = proc.stdErr();
+ const QString remoteError = proc.cleanedStdErr();
if (!remoteError.isEmpty())
qWarning("Cannot read container environment: %s\n", qPrintable(remoteError));
}
bool DockerDevicePrivate::runInContainer(const CommandLine &cmd) const
{
- if (!DockerPlugin::isDaemonRunning().value_or(false))
+ if (!DockerApi::isDockerDaemonAvailable(false).value_or(false))
return false;
CommandLine dcmd{"docker", {"exec", m_container}};
dcmd.addCommandLineAsArgs(cmd);
@@ -1776,62 +1015,16 @@ bool DockerDevicePrivate::runInContainer(const CommandLine &cmd) const
return exitCode == 0;
}
-bool DockerDevicePrivate::runInShell(const CommandLine &cmd) const
-{
- if (!QTC_GUARD(DockerPlugin::isDaemonRunning().value_or(false))) {
- LOG("No daemon. Could not run " << cmd.toUserOutput());
- return false;
- }
- QTC_ASSERT(m_shell, LOG("No shell. Could not run " << cmd.toUserOutput()); return false);
- QMutexLocker l(&m_shellMutex);
- m_shell->readAllStandardOutput(); // clean possible left-overs
- m_shell->write(cmd.toUserOutput().toUtf8() + "\necho $?\n");
- QTC_ASSERT(m_shell->waitForReadyRead(), return false);
- QByteArray output = m_shell->readAllStandardOutput();
- bool ok;
- int result = output.toInt(&ok);
- LOG("Run command in shell:" << cmd.toUserOutput() << "result: " << output << " ==>" << result);
- QTC_ASSERT(ok, return false);
- return result == 0;
-}
-
-// generate hex value
-static QByteArray randomHex()
+bool DockerDevicePrivate::runInShell(const CommandLine &cmd, const QByteArray& stdInData) const
{
- quint32 val = QRandomGenerator::global()->generate();
- return QString::number(val, 16).toUtf8();
+ QTC_ASSERT(m_shell, return false);
+ return m_shell->runInShell(cmd, stdInData);
}
QByteArray DockerDevicePrivate::outputForRunInShell(const CommandLine &cmd) const
{
- if (!DockerPlugin::isDaemonRunning().value_or(false))
- return {};
- QTC_ASSERT(m_shell && m_shell->isRunning(), return {});
- QMutexLocker l(&m_shellMutex);
- m_shell->readAllStandardOutput(); // clean possible left-overs
- const QByteArray oldError = m_shell->readAllStandardError(); // clean possible left-overs
- if (!oldError.isEmpty()) {
- LOG("Unexpected old stderr: " << oldError);
- QTC_CHECK(false);
- }
-
- const QByteArray markerWithNewLine("___QC_DOCKER_" + randomHex() + "_OUTPUT_MARKER___\n");
- m_shell->write(cmd.toUserOutput().toUtf8() + "\necho -n \"" + markerWithNewLine + "\"\n");
- QByteArray output;
- while (!output.endsWith(markerWithNewLine)) {
- QTC_ASSERT(m_shell->isRunning(), return {});
- m_shell->waitForReadyRead();
- output.append(m_shell->readAllStandardOutput());
- }
- LOG("Run command in shell:" << cmd.toUserOutput() << "output size:" << output.size());
- if (QTC_GUARD(output.endsWith(markerWithNewLine)))
- output.chop(markerWithNewLine.size());
- const QByteArray currentError = m_shell->readAllStandardError();
- if (!currentError.isEmpty()) {
- LOG("Unexpected current stderr: " << currentError);
- QTC_CHECK(false);
- }
- return output;
+ QTC_ASSERT(m_shell.get(), return {});
+ return m_shell->outputForRunInShell(cmd).stdOut;
}
// Factory
@@ -1933,15 +1126,12 @@ public:
});
connect(m_process, &Utils::QtcProcess::readyReadStandardError, this, [this] {
- const QString out = DockerDevice::tr("Error: %1").arg(m_process->stdErr());
+ const QString out = DockerDevice::tr("Error: %1").arg(m_process->cleanedStdErr());
m_log->append(DockerDevice::tr("Error: %1").arg(out));
});
- connect(m_process, &Utils::QtcProcess::finished,
- this, [this, errorLabel]() {
- if (m_process->exitCode() != 0) {
- errorLabel->setVisible(true);
- }
+ connect(m_process, &QtcProcess::done, errorLabel, [errorLabel, this] {
+ errorLabel->setVisible(m_process->result() != ProcessResult::FinishedWithSuccess);
});
connect(m_view->selectionModel(), &QItemSelectionModel::selectionChanged, [this] {
@@ -1978,21 +1168,6 @@ public:
QString m_selectedId;
};
-void DockerDeviceWidget::updateDaemonStateTexts()
-{
- Utils::optional<bool> daemonState = DockerPlugin::isDaemonRunning();
- if (!daemonState.has_value()) {
- m_daemonReset->setIcon(Icons::INFO.icon());
- m_daemonState->setText(tr("Daemon state not evaluated."));
- } else if (daemonState.value()) {
- m_daemonReset->setIcon(Icons::OK.icon());
- m_daemonState->setText(tr("Docker daemon running."));
- } else {
- m_daemonReset->setIcon(Icons::CRITICAL.icon());
- m_daemonState->setText(tr("Docker daemon not running."));
- }
-}
-
// Factory
DockerDeviceFactory::DockerDeviceFactory()
diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h
index f6f8f988539..d7a59aa38c0 100644
--- a/src/plugins/docker/dockerdevice.h
+++ b/src/plugins/docker/dockerdevice.h
@@ -27,7 +27,7 @@
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/idevicefactory.h>
-#include <projectexplorer/devicesupport/sshdeviceprocess.h>
+#include <coreplugin/documentmanager.h>
#include <utils/aspects.h>
@@ -45,8 +45,7 @@ public:
QString tag;
QString size;
bool useLocalUidGid = true;
- bool useFilePathMapping = false;
- QStringList mounts;
+ QStringList mounts = { Core::DocumentManager::projectsDirectory().toString() };
};
class DockerDevice : public ProjectExplorer::IDevice
@@ -65,10 +64,10 @@ public:
ProjectExplorer::IDeviceWidget *createWidget() override;
QList<ProjectExplorer::Task> validate() const override;
- bool canCreateProcess() const override { return true; }
- ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const override;
+ Utils::ProcessInterface *createProcessInterface() const override;
+
bool canAutoDetectPorts() const override;
- ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const override;
+ ProjectExplorer::PortsGatheringMethod portsGatheringMethod() const override;
bool canCreateProcessModel() const override { return false; }
ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const override;
bool hasDeviceTester() const override { return false; }
@@ -101,7 +100,6 @@ public:
QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const override;
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
QDateTime lastModified(const Utils::FilePath &filePath) const override;
- void runProcess(Utils::QtcProcess &process) const override;
qint64 fileSize(const Utils::FilePath &filePath) const override;
QFileDevice::Permissions permissions(const Utils::FilePath &filePath) const override;
bool setPermissions(const Utils::FilePath &filePath, QFileDevice::Permissions permissions) const override;
@@ -112,12 +110,9 @@ public:
DockerDeviceData &data();
void updateContainerAccess() const;
- bool hasLocalFileAccess() const;
void setMounts(const QStringList &mounts) const;
- Utils::FilePath mapToLocalAccess(const Utils::FilePath &filePath) const;
- Utils::FilePath mapFromLocalAccess(const Utils::FilePath &filePath) const;
- Utils::FilePath mapFromLocalAccess(const QString &filePath) const;
+ Utils::CommandLine withDockerExecCmd(const Utils::CommandLine& cmd, bool interactive = false) const;
protected:
void fromMap(const QVariantMap &map) final;
@@ -135,25 +130,6 @@ private:
friend class DockerDeviceWidget;
};
-class KitDetector : public QObject
-{
- Q_OBJECT
-
-public:
- explicit KitDetector(const ProjectExplorer::IDevice::ConstPtr &device);
- ~KitDetector() override;
-
- void autoDetect(const QString &sharedId, const Utils::FilePaths &selectedPaths) const;
- void undoAutoDetect(const QString &sharedId) const;
- void listAutoDetected(const QString &sharedId) const;
-
-signals:
- void logOutput(const QString &msg);
-
-private:
- class KitDetectorPrivate *d = nullptr;
-};
-
class DockerDeviceFactory final : public ProjectExplorer::IDeviceFactory
{
public:
diff --git a/src/plugins/docker/dockerdevicewidget.cpp b/src/plugins/docker/dockerdevicewidget.cpp
new file mode 100644
index 00000000000..ca24b27f3ea
--- /dev/null
+++ b/src/plugins/docker/dockerdevicewidget.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "dockerdevicewidget.h"
+
+#include <utils/algorithm.h>
+#include <utils/environment.h>
+#include <utils/hostosinfo.h>
+#include <utils/layoutbuilder.h>
+#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
+
+#include <QCoreApplication>
+#include <QToolButton>
+#include <QTextBrowser>
+#include <QPushButton>
+#include <QComboBox>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace Docker {
+namespace Internal {
+
+DockerDeviceWidget::DockerDeviceWidget(const IDevice::Ptr &device)
+ : IDeviceWidget(device), m_kitItemDetector(device)
+{
+ auto dockerDevice = device.dynamicCast<DockerDevice>();
+ QTC_ASSERT(dockerDevice, return);
+
+ DockerDeviceData &data = dockerDevice->data();
+
+ auto repoLabel = new QLabel(tr("Repository:"));
+ m_repoLineEdit = new QLineEdit;
+ m_repoLineEdit->setText(data.repo);
+ m_repoLineEdit->setEnabled(false);
+
+ auto tagLabel = new QLabel(tr("Tag:"));
+ m_tagLineEdit = new QLineEdit;
+ m_tagLineEdit->setText(data.tag);
+ m_tagLineEdit->setEnabled(false);
+
+ auto idLabel = new QLabel(tr("Image ID:"));
+ m_idLineEdit = new QLineEdit;
+ m_idLineEdit->setText(data.imageId);
+ m_idLineEdit->setEnabled(false);
+
+ auto daemonStateLabel = new QLabel(tr("Daemon state:"));
+ m_daemonReset = new QToolButton;
+ m_daemonReset->setToolTip(tr("Clears detected daemon state. "
+ "It will be automatically re-evaluated next time access is needed."));
+
+ m_daemonState = new QLabel;
+
+ connect(DockerApi::instance(), &DockerApi::dockerDaemonAvailableChanged, this, [this]{
+ updateDaemonStateTexts();
+ });
+
+ updateDaemonStateTexts();
+
+ connect(m_daemonReset, &QToolButton::clicked, this, [] {
+ DockerApi::recheckDockerDaemon();
+ });
+
+ m_runAsOutsideUser = new QCheckBox(tr("Run as outside user"));
+ m_runAsOutsideUser->setToolTip(tr("Uses user ID and group ID of the user running Qt Creator "
+ "in the docker container."));
+ m_runAsOutsideUser->setChecked(data.useLocalUidGid);
+ m_runAsOutsideUser->setEnabled(HostOsInfo::isLinuxHost());
+
+ connect(m_runAsOutsideUser, &QCheckBox::toggled, this, [&data](bool on) {
+ data.useLocalUidGid = on;
+ });
+
+ auto pathListLabel = new InfoLabel(tr("Paths to mount:"));
+ pathListLabel->setAdditionalToolTip(tr("Source directory list should not be empty."));
+
+ m_pathsListEdit = new PathListEditor;
+ m_pathsListEdit->setPlaceholderText(tr("Host directories to mount into the container"));
+ m_pathsListEdit->setToolTip(tr("Maps paths in this list one-to-one to the "
+ "docker container."));
+ m_pathsListEdit->setPathList(data.mounts);
+ m_pathsListEdit->setMaximumHeight(100);
+ m_pathsListEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ auto markupMounts = [this, pathListLabel] {
+ const bool isEmpty = m_pathsListEdit->pathList().isEmpty();
+ pathListLabel->setType(isEmpty ? InfoLabel::Warning : InfoLabel::None);
+ };
+ markupMounts();
+
+ connect(m_pathsListEdit, &PathListEditor::changed, this, [dockerDevice, markupMounts, this] {
+ dockerDevice->setMounts(m_pathsListEdit->pathList());
+ markupMounts();
+ });
+
+ auto logView = new QTextBrowser;
+ connect(&m_kitItemDetector, &KitDetector::logOutput,
+ logView, &QTextBrowser::append);
+
+ auto autoDetectButton = new QPushButton(tr("Auto-detect Kit Items"));
+ auto undoAutoDetectButton = new QPushButton(tr("Remove Auto-Detected Kit Items"));
+ auto listAutoDetectedButton = new QPushButton(tr("List Auto-Detected Kit Items"));
+
+ auto searchDirsComboBox = new QComboBox;
+ searchDirsComboBox->addItem(tr("Search in PATH"));
+ searchDirsComboBox->addItem(tr("Search in Selected Directories"));
+
+ auto searchDirsLineEdit = new FancyLineEdit;
+
+ searchDirsLineEdit->setPlaceholderText(tr("Semicolon-separated list of directories"));
+ searchDirsLineEdit->setToolTip(
+ tr("Select the paths in the docker image that should be scanned for kit entries."));
+ searchDirsLineEdit->setHistoryCompleter("DockerMounts", true);
+
+ auto searchPaths = [searchDirsComboBox, searchDirsLineEdit, dockerDevice] {
+ FilePaths paths;
+ if (searchDirsComboBox->currentIndex() == 0) {
+ paths = dockerDevice->systemEnvironment().path();
+ } else {
+ for (const QString &path : searchDirsLineEdit->text().split(';'))
+ paths.append(FilePath::fromString(path.trimmed()));
+ }
+ paths = Utils::transform(paths, [dockerDevice](const FilePath &path) {
+ return dockerDevice->mapToGlobalPath(path);
+ });
+ return paths;
+ };
+
+ connect(autoDetectButton, &QPushButton::clicked, this,
+ [this, logView, dockerDevice, searchPaths] {
+ logView->clear();
+ dockerDevice->updateContainerAccess();
+
+ m_kitItemDetector.autoDetect(dockerDevice->id().toString(), searchPaths());
+
+ if (DockerApi::instance()->dockerDaemonAvailable().value_or(false) == false)
+ logView->append(tr("Docker daemon appears to be not running."));
+ else
+ logView->append(tr("Docker daemon appears to be running."));
+ updateDaemonStateTexts();
+ });
+
+ connect(undoAutoDetectButton, &QPushButton::clicked, this, [this, logView, device] {
+ logView->clear();
+ m_kitItemDetector.undoAutoDetect(device->id().toString());
+ });
+
+ connect(listAutoDetectedButton, &QPushButton::clicked, this, [this, logView, device] {
+ logView->clear();
+ m_kitItemDetector.listAutoDetected(device->id().toString());
+ });
+
+ using namespace Layouting;
+
+ Form {
+ repoLabel, m_repoLineEdit, Break(),
+ tagLabel, m_tagLineEdit, Break(),
+ idLabel, m_idLineEdit, Break(),
+ daemonStateLabel, m_daemonReset, m_daemonState, Break(),
+ m_runAsOutsideUser, Break(),
+ Column {
+ pathListLabel,
+ m_pathsListEdit,
+ }, Break(),
+ Column {
+ Space(20),
+ Row {
+ searchDirsComboBox,
+ searchDirsLineEdit
+ },
+ Row {
+ autoDetectButton,
+ undoAutoDetectButton,
+ listAutoDetectedButton,
+ Stretch(),
+ },
+ new QLabel(tr("Detection log:")),
+ logView
+ }
+ }.attachTo(this);
+
+ searchDirsLineEdit->setVisible(false);
+ auto updateDirectoriesLineEdit = [searchDirsLineEdit](int index) {
+ searchDirsLineEdit->setVisible(index == 1);
+ if (index == 1)
+ searchDirsLineEdit->setFocus();
+ };
+ QObject::connect(searchDirsComboBox, qOverload<int>(&QComboBox::activated),
+ this, updateDirectoriesLineEdit);
+}
+
+void DockerDeviceWidget::updateDaemonStateTexts()
+{
+ Utils::optional<bool> daemonState = DockerApi::instance()->dockerDaemonAvailable();
+ if (!daemonState.has_value()) {
+ m_daemonReset->setIcon(Icons::INFO.icon());
+ m_daemonState->setText(tr("Daemon state not evaluated."));
+ } else if (daemonState.value()) {
+ m_daemonReset->setIcon(Icons::OK.icon());
+ m_daemonState->setText(tr("Docker daemon running."));
+ } else {
+ m_daemonReset->setIcon(Icons::CRITICAL.icon());
+ m_daemonState->setText(tr("Docker daemon not running."));
+ }
+}
+
+} // Internal
+} // Docker
diff --git a/src/plugins/docker/dockerdevicewidget.h b/src/plugins/docker/dockerdevicewidget.h
new file mode 100644
index 00000000000..f63a5cfc84b
--- /dev/null
+++ b/src/plugins/docker/dockerdevicewidget.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "dockerplugin.h"
+#include "dockerdevice.h"
+#include "kitdetector.h"
+
+#include <projectexplorer/devicesupport/idevicewidget.h>
+
+#include <utils/pathlisteditor.h>
+
+#include <QCheckBox>
+
+namespace Docker {
+namespace Internal {
+
+class DockerDeviceWidget final : public ProjectExplorer::IDeviceWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(Docker::Internal::DockerDevice)
+
+public:
+ explicit DockerDeviceWidget(const ProjectExplorer::IDevice::Ptr &device);
+
+ void updateDeviceFromUi() final {}
+ void updateDaemonStateTexts();
+
+private:
+ QLineEdit *m_repoLineEdit;
+ QLineEdit *m_tagLineEdit;
+ QLineEdit *m_idLineEdit;
+ QToolButton *m_daemonReset;
+ QLabel *m_daemonState;
+ QCheckBox *m_runAsOutsideUser;
+ Utils::PathListEditor *m_pathsListEdit;
+ KitDetector m_kitItemDetector;
+};
+
+} // Internal
+} // Docker
diff --git a/src/plugins/docker/dockerplugin.cpp b/src/plugins/docker/dockerplugin.cpp
index d195c81d6b3..fb5d410d05c 100644
--- a/src/plugins/docker/dockerplugin.cpp
+++ b/src/plugins/docker/dockerplugin.cpp
@@ -27,12 +27,14 @@
#include "dockerconstants.h"
-#include "dockerbuildstep.h"
+#include "dockerapi.h"
#include "dockerdevice.h"
#include "dockersettings.h"
#include <projectexplorer/projectexplorerconstants.h>
+#include <utils/qtcassert.h>
+
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;
@@ -43,13 +45,15 @@ namespace Internal {
class DockerPluginPrivate
{
public:
-// DockerSettings settings;
-// DockerOptionsPage optionsPage{&settings};
+ // DockerSettings settings;
+ // DockerOptionsPage optionsPage{&settings};
DockerDeviceFactory deviceFactory;
-// DockerBuildStepFactory buildStepFactory;
+ // DockerBuildStepFactory buildStepFactory;
Utils::optional<bool> daemonRunning;
+
+ DockerApi dockerApi;
};
static DockerPlugin *s_instance = nullptr;
@@ -59,16 +63,10 @@ DockerPlugin::DockerPlugin()
s_instance = this;
}
-// Utils::null_opt for not evaluated, true or false if it had been evaluated already
-Utils::optional<bool> DockerPlugin::isDaemonRunning()
-{
- return s_instance ? s_instance->d->daemonRunning : Utils::nullopt;
-}
-
-void DockerPlugin::setGlobalDaemonState(Utils::optional<bool> state)
+DockerApi *DockerPlugin::dockerApi()
{
- QTC_ASSERT(s_instance, return);
- s_instance->d->daemonRunning = state;
+ QTC_ASSERT(s_instance, return nullptr);
+ return &s_instance->d->dockerApi;
}
DockerPlugin::~DockerPlugin()
diff --git a/src/plugins/docker/dockerplugin.h b/src/plugins/docker/dockerplugin.h
index aa9c093556a..7eb1d3b10b4 100644
--- a/src/plugins/docker/dockerplugin.h
+++ b/src/plugins/docker/dockerplugin.h
@@ -25,6 +25,8 @@
#pragma once
+#include "dockerapi.h"
+
#include <extensionsystem/iplugin.h>
#include <utils/optional.h>
@@ -36,11 +38,11 @@ class DockerPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Docker.json")
+
public:
DockerPlugin();
- static Utils::optional<bool> isDaemonRunning();
- static void setGlobalDaemonState(Utils::optional<bool> state);
+ static DockerApi *dockerApi();
private:
~DockerPlugin() final;
diff --git a/src/plugins/docker/dockersettings.cpp b/src/plugins/docker/dockersettings.cpp
index fc28988e3ed..f9c615ed0ea 100644
--- a/src/plugins/docker/dockersettings.cpp
+++ b/src/plugins/docker/dockersettings.cpp
@@ -82,14 +82,9 @@ void DockerSettings::updateImageList()
{
QtcProcess process;
process.setCommand({"docker", {"search", imageListFilter.value()}});
-
- connect(&process, &QtcProcess::finished, this, [&process, this] {
- const QString data = QString::fromUtf8(process.readAllStandardOutput());
- imageList.setValue(data);
- });
-
process.start();
process.waitForFinished();
+ imageList.setValue(process.cleanedStdOut());
}
void DockerSettings::readSettings(const QSettings *settings)
diff --git a/src/plugins/docker/kitdetector.cpp b/src/plugins/docker/kitdetector.cpp
new file mode 100644
index 00000000000..5e0c2e86598
--- /dev/null
+++ b/src/plugins/docker/kitdetector.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "kitdetector.h"
+
+#include <cmakeprojectmanager/cmakeprojectconstants.h>
+
+#include <extensionsystem/pluginmanager.h>
+
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchainmanager.h>
+
+#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtkitinformation.h>
+#include <qtsupport/qtversionfactory.h>
+#include <qtsupport/qtversionmanager.h>
+
+#include <utils/filepath.h>
+#include <utils/qtcassert.h>
+#include <utils/algorithm.h>
+
+#include <QApplication>
+
+using namespace ProjectExplorer;
+using namespace QtSupport;
+using namespace Utils;
+
+namespace Docker {
+namespace Internal {
+
+class KitDetectorPrivate
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::KitItemDetector)
+
+public:
+ KitDetectorPrivate(KitDetector *parent, const IDevice::ConstPtr &device)
+ : q(parent)
+ , m_device(device)
+ {}
+
+ void autoDetect();
+ void undoAutoDetect() const;
+ void listAutoDetected() const;
+
+ void setSharedId(const QString &sharedId) { m_sharedId = sharedId; }
+ void setSearchPaths(const FilePaths &searchPaths) { m_searchPaths = searchPaths; }
+
+private:
+ QtVersions autoDetectQtVersions() const;
+ QList<ToolChain *> autoDetectToolChains();
+ QList<Id> autoDetectCMake();
+ void autoDetectDebugger();
+
+ KitDetector *q;
+ IDevice::ConstPtr m_device;
+ QString m_sharedId;
+ FilePaths m_searchPaths;
+};
+
+KitDetector::KitDetector(const IDevice::ConstPtr &device)
+ : d(new KitDetectorPrivate(this, device))
+{}
+
+KitDetector::~KitDetector()
+{
+ delete d;
+}
+
+void KitDetector::autoDetect(const QString &sharedId, const FilePaths &searchPaths) const
+{
+ d->setSharedId(sharedId);
+ d->setSearchPaths(searchPaths);
+ d->autoDetect();
+}
+
+void KitDetector::undoAutoDetect(const QString &sharedId) const
+{
+ d->setSharedId(sharedId);
+ d->undoAutoDetect();
+}
+
+void KitDetector::listAutoDetected(const QString &sharedId) const
+{
+ d->setSharedId(sharedId);
+ d->listAutoDetected();
+}
+
+void KitDetectorPrivate::undoAutoDetect() const
+{
+ emit q->logOutput(tr("Start removing auto-detected items associated with this docker image."));
+
+ emit q->logOutput('\n' + tr("Removing kits..."));
+ for (Kit *kit : KitManager::kits()) {
+ if (kit->autoDetectionSource() == m_sharedId) {
+ emit q->logOutput(tr("Removed \"%1\"").arg(kit->displayName()));
+ KitManager::deregisterKit(kit);
+ }
+ };
+
+ emit q->logOutput('\n' + tr("Removing Qt version entries..."));
+ for (QtVersion *qtVersion : QtVersionManager::versions()) {
+ if (qtVersion->detectionSource() == m_sharedId) {
+ emit q->logOutput(tr("Removed \"%1\"").arg(qtVersion->displayName()));
+ QtVersionManager::removeVersion(qtVersion);
+ }
+ };
+
+ emit q->logOutput('\n' + tr("Removing toolchain entries..."));
+ const Toolchains toolchains = ToolChainManager::toolchains();
+ for (ToolChain *toolChain : toolchains) {
+ if (toolChain && toolChain->detectionSource() == m_sharedId) {
+ emit q->logOutput(tr("Removed \"%1\"").arg(toolChain->displayName()));
+ ToolChainManager::deregisterToolChain(toolChain);
+ }
+ };
+
+ if (auto cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager")) {
+ QString logMessage;
+ const bool res = QMetaObject::invokeMethod(cmakeManager,
+ "removeDetectedCMake",
+ Q_ARG(QString, m_sharedId),
+ Q_ARG(QString *, &logMessage));
+ QTC_CHECK(res);
+ emit q->logOutput('\n' + logMessage);
+ }
+
+ if (auto debuggerPlugin = ExtensionSystem::PluginManager::getObjectByName("DebuggerPlugin")) {
+ QString logMessage;
+ const bool res = QMetaObject::invokeMethod(debuggerPlugin,
+ "removeDetectedDebuggers",
+ Q_ARG(QString, m_sharedId),
+ Q_ARG(QString *, &logMessage));
+ QTC_CHECK(res);
+ emit q->logOutput('\n' + logMessage);
+ }
+
+ emit q->logOutput('\n' + tr("Removal of previously auto-detected kit items finished.") + "\n\n");
+}
+
+void KitDetectorPrivate::listAutoDetected() const
+{
+ emit q->logOutput(tr("Start listing auto-detected items associated with this docker image."));
+
+ emit q->logOutput('\n' + tr("Kits:"));
+ for (Kit *kit : KitManager::kits()) {
+ if (kit->autoDetectionSource() == m_sharedId)
+ emit q->logOutput(kit->displayName());
+ }
+
+ emit q->logOutput('\n' + tr("Qt versions:"));
+ for (QtVersion *qtVersion : QtVersionManager::versions()) {
+ if (qtVersion->detectionSource() == m_sharedId)
+ emit q->logOutput(qtVersion->displayName());
+ }
+
+ emit q->logOutput('\n' + tr("Toolchains:"));
+ for (ToolChain *toolChain : ToolChainManager::toolchains()) {
+ if (toolChain->detectionSource() == m_sharedId)
+ emit q->logOutput(toolChain->displayName());
+ }
+
+ if (QObject *cmakeManager = ExtensionSystem::PluginManager::getObjectByName(
+ "CMakeToolManager")) {
+ QString logMessage;
+ const bool res = QMetaObject::invokeMethod(cmakeManager,
+ "listDetectedCMake",
+ Q_ARG(QString, m_sharedId),
+ Q_ARG(QString *, &logMessage));
+ QTC_CHECK(res);
+ emit q->logOutput('\n' + logMessage);
+ }
+
+ if (QObject *debuggerPlugin = ExtensionSystem::PluginManager::getObjectByName(
+ "DebuggerPlugin")) {
+ QString logMessage;
+ const bool res = QMetaObject::invokeMethod(debuggerPlugin,
+ "listDetectedDebuggers",
+ Q_ARG(QString, m_sharedId),
+ Q_ARG(QString *, &logMessage));
+ QTC_CHECK(res);
+ emit q->logOutput('\n' + logMessage);
+ }
+
+ emit q->logOutput('\n' + tr("Listing of previously auto-detected kit items finished.") + "\n\n");
+}
+
+QtVersions KitDetectorPrivate::autoDetectQtVersions() const
+{
+ QtVersions qtVersions;
+
+ QString error;
+
+ const auto handleQmake = [this, &qtVersions, &error](const FilePath &qmake) {
+ if (QtVersion *qtVersion = QtVersionFactory::createQtVersionFromQMakePath(qmake,
+ false,
+ m_sharedId,
+ &error)) {
+ if (qtVersion->isValid()) {
+ if (!Utils::anyOf(qtVersions,
+ [qtVersion](QtVersion* other) {
+ return qtVersion->mkspecPath() == other->mkspecPath();
+ })) {
+
+ qtVersions.append(qtVersion);
+ QtVersionManager::addVersion(qtVersion);
+ emit q->logOutput(
+ tr("Found \"%1\"").arg(qtVersion->qmakeFilePath().toUserOutput()));
+ }
+ }
+ }
+ return true;
+ };
+
+ emit q->logOutput(tr("Searching for qmake executables..."));
+
+ const QStringList candidates = {"qmake-qt6", "qmake-qt5", "qmake"};
+ for (const FilePath &searchPath : m_searchPaths) {
+ searchPath.iterateDirectory(handleQmake,
+ {candidates,
+ QDir::Files | QDir::Executable,
+ QDirIterator::Subdirectories});
+ }
+
+ if (!error.isEmpty())
+ emit q->logOutput(tr("Error: %1.").arg(error));
+ if (qtVersions.isEmpty())
+ emit q->logOutput(tr("No Qt installation found."));
+ return qtVersions;
+}
+
+Toolchains KitDetectorPrivate::autoDetectToolChains()
+{
+ const QList<ToolChainFactory *> factories = ToolChainFactory::allToolChainFactories();
+
+ Toolchains alreadyKnown = ToolChainManager::toolchains();
+ Toolchains allNewToolChains;
+ QApplication::processEvents();
+ emit q->logOutput('\n' + tr("Searching toolchains..."));
+ for (ToolChainFactory *factory : factories) {
+ emit q->logOutput(tr("Searching toolchains of type %1").arg(factory->displayName()));
+ const ToolchainDetector detector(alreadyKnown, m_device, m_searchPaths);
+ const Toolchains newToolChains = factory->autoDetect(detector);
+ for (ToolChain *toolChain : newToolChains) {
+ emit q->logOutput(tr("Found \"%1\"").arg(toolChain->compilerCommand().toUserOutput()));
+ toolChain->setDetectionSource(m_sharedId);
+ ToolChainManager::registerToolChain(toolChain);
+ alreadyKnown.append(toolChain);
+ }
+ allNewToolChains.append(newToolChains);
+ }
+ emit q->logOutput(tr("%1 new toolchains found.").arg(allNewToolChains.size()));
+
+ return allNewToolChains;
+}
+
+QList<Id> KitDetectorPrivate::autoDetectCMake()
+{
+ QList<Id> result;
+ QObject *cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager");
+ if (!cmakeManager)
+ return {};
+
+ QString logMessage;
+ const bool res = QMetaObject::invokeMethod(cmakeManager,
+ "autoDetectCMakeForDevice",
+ Q_RETURN_ARG(QList<Utils::Id>, result),
+ Q_ARG(Utils::FilePaths, m_searchPaths),
+ Q_ARG(QString, m_sharedId),
+ Q_ARG(QString *, &logMessage));
+ QTC_CHECK(res);
+ emit q->logOutput('\n' + logMessage);
+
+ return result;
+}
+
+void KitDetectorPrivate::autoDetectDebugger()
+{
+ QObject *debuggerPlugin = ExtensionSystem::PluginManager::getObjectByName("DebuggerPlugin");
+ if (!debuggerPlugin)
+ return;
+
+ QString logMessage;
+ const bool res = QMetaObject::invokeMethod(debuggerPlugin,
+ "autoDetectDebuggersForDevice",
+ Q_ARG(Utils::FilePaths, m_searchPaths),
+ Q_ARG(QString, m_sharedId),
+ Q_ARG(QString *, &logMessage));
+ QTC_CHECK(res);
+ emit q->logOutput('\n' + logMessage);
+}
+
+void KitDetectorPrivate::autoDetect()
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+
+ undoAutoDetect();
+
+ emit q->logOutput(tr("Starting auto-detection. This will take a while..."));
+
+ const Toolchains toolchains = autoDetectToolChains();
+ const QtVersions qtVersions = autoDetectQtVersions();
+
+ const QList<Id> cmakeIds = autoDetectCMake();
+ const Id cmakeId = cmakeIds.empty() ? Id() : cmakeIds.first();
+ autoDetectDebugger();
+
+ const auto initializeKit = [this, toolchains, qtVersions, cmakeId](Kit *k) {
+ k->setAutoDetected(false);
+ k->setAutoDetectionSource(m_sharedId);
+ k->setUnexpandedDisplayName("%{Device:Name}");
+
+ if (cmakeId.isValid())
+ k->setValue(CMakeProjectManager::Constants::TOOL_ID, cmakeId.toSetting());
+
+ DeviceTypeKitAspect::setDeviceTypeId(k, m_device->type());
+ DeviceKitAspect::setDevice(k, m_device);
+ BuildDeviceKitAspect::setDevice(k, m_device);
+
+ QtVersion *qt = nullptr;
+ if (!qtVersions.isEmpty()) {
+ qt = qtVersions.at(0);
+ QtSupport::QtKitAspect::setQtVersion(k, qt);
+ }
+ Toolchains toolchainsToSet;
+ toolchainsToSet = ToolChainManager::toolchains([qt, this](const ToolChain *tc) {
+ return tc->detectionSource() == m_sharedId
+ && (!qt || qt->qtAbis().contains(tc->targetAbi()));
+ });
+ for (ToolChain *toolChain : toolchainsToSet)
+ ToolChainKitAspect::setToolChain(k, toolChain);
+
+ if (cmakeId.isValid())
+ k->setSticky(CMakeProjectManager::Constants::TOOL_ID, true);
+
+ k->setSticky(ToolChainKitAspect::id(), true);
+ k->setSticky(QtSupport::QtKitAspect::id(), true);
+ k->setSticky(DeviceKitAspect::id(), true);
+ k->setSticky(DeviceTypeKitAspect::id(), true);
+ k->setSticky(BuildDeviceKitAspect::id(), true);
+ };
+
+ Kit *kit = KitManager::registerKit(initializeKit);
+ emit q->logOutput('\n' + tr("Registered kit %1").arg(kit->displayName()));
+
+ QApplication::restoreOverrideCursor();
+}
+
+} // namespace Internal
+} // namespace Docker
diff --git a/src/plugins/docker/kitdetector.h b/src/plugins/docker/kitdetector.h
new file mode 100644
index 00000000000..6e19d6f9597
--- /dev/null
+++ b/src/plugins/docker/kitdetector.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectexplorer/devicesupport/idevicefwd.h>
+#include <utils/filepath.h>
+
+#include <QObject>
+
+namespace Docker {
+namespace Internal {
+
+class KitDetector : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit KitDetector(const ProjectExplorer::IDeviceConstPtr &device);
+ ~KitDetector() override;
+
+ void autoDetect(const QString &sharedId, const Utils::FilePaths &selectedPaths) const;
+ void undoAutoDetect(const QString &sharedId) const;
+ void listAutoDetected(const QString &sharedId) const;
+
+signals:
+ void logOutput(const QString &msg);
+
+private:
+ class KitDetectorPrivate *d = nullptr;
+};
+
+} // Internal
+} // Docker
diff --git a/src/plugins/fakevim/fakevimactions.cpp b/src/plugins/fakevim/fakevimactions.cpp
index 0d2f1e2f18f..60b2c6467f2 100644
--- a/src/plugins/fakevim/fakevimactions.cpp
+++ b/src/plugins/fakevim/fakevimactions.cpp
@@ -31,6 +31,7 @@
// Qt Creator. The idea is to keep this file here in a "clean" state that
// allows easy reuse with any QTextEdit or QPlainTextEdit derived class.
+#include <utils/hostosinfo.h>
#include <utils/layoutbuilder.h>
#include <utils/qtcassert.h>
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 79e8153c01b..413ddae6ac9 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -864,15 +864,6 @@ static QByteArray toLocalEncoding(const QString &text)
#endif
}
-static QString fromLocalEncoding(const QByteArray &data)
-{
-#if defined(Q_OS_WIN)
- return QString::fromLocal8Bit(data).replace("\n", "\r\n");
-#else
- return QString::fromLocal8Bit(data);
-#endif
-}
-
static QString getProcessOutput(const QString &command, const QString &input)
{
Utils::QtcProcess proc;
@@ -884,7 +875,7 @@ static QString getProcessOutput(const QString &command, const QString &input)
// Solution is to create a QObject for each process and emit finished state.
proc.waitForFinished();
- return fromLocalEncoding(proc.readAllStandardOutput());
+ return proc.cleanedStdOut();
}
static const QMap<QString, int> &vimKeyNames()
@@ -1246,7 +1237,7 @@ public:
return '\n';
if (m_key == Key_Escape)
return QChar(27);
- return QChar(m_xkey);
+ return QChar(m_xkey & 0xffff); // FIXME
}
QString toString() const
@@ -1263,7 +1254,7 @@ public:
else if (m_xkey == '>')
key = "<GT>";
else
- key = QChar(m_xkey);
+ key = QChar(m_xkey & 0xffff); // FIXME
}
bool shift = isShift();
@@ -2279,6 +2270,7 @@ public:
bool handleExHistoryCommand(const ExCommand &cmd);
bool handleExRegisterCommand(const ExCommand &cmd);
bool handleExMapCommand(const ExCommand &cmd);
+ bool handleExMultiRepeatCommand(const ExCommand &cmd);
bool handleExNohlsearchCommand(const ExCommand &cmd);
bool handleExNormalCommand(const ExCommand &cmd);
bool handleExReadCommand(const ExCommand &cmd);
@@ -5916,7 +5908,7 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd)
bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
{
- // :substitute
+ // :[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
if (!cmd.matches("s", "substitute")
&& !(cmd.cmd.isEmpty() && !cmd.args.isEmpty() && QString("&~").contains(cmd.args[0]))) {
return false;
@@ -6513,6 +6505,61 @@ bool FakeVimHandler::Private::handleExShiftCommand(const ExCommand &cmd)
return true;
}
+bool FakeVimHandler::Private::handleExMultiRepeatCommand(const ExCommand &cmd)
+{
+ // :[range]g[lobal]/{pattern}/[cmd]
+ // :[range]g[lobal]!/{pattern}/[cmd]
+ // :[range]v[globa]!/{pattern}/[cmd]
+ const bool hasG = cmd.matches("g", "global");
+ const bool hasV = cmd.matches("v", "vglobal");
+ if (!hasG && !hasV)
+ return false;
+
+ // Force operation on full lines, and full document if only
+ // one line (the current one...) is specified
+ int beginLine = lineForPosition(cmd.range.beginPos);
+ int endLine = lineForPosition(cmd.range.endPos);
+ if (beginLine == endLine) {
+ beginLine = 0;
+ endLine = lineForPosition(lastPositionInDocument());
+ }
+
+ const bool negates = hasV || cmd.hasBang;
+
+ const QChar delim = cmd.args.front();
+ const QString pattern = cmd.args.section(delim, 1, 1);
+ const QRegularExpression re(pattern);
+
+ QString innerCmd = cmd.args.section(delim, 2, 2);
+ if (innerCmd.isEmpty())
+ innerCmd = "p";
+
+ QList<QTextCursor> matches;
+
+ for (int line = beginLine; line <= endLine; ++line) {
+ const int pos = firstPositionInLine(line);
+ const Range range(pos, pos, RangeLineMode);
+ const QString lineContents = selectText(range);
+ const QRegularExpressionMatch match = re.match(lineContents);
+ if (match.hasMatch() ^ negates) {
+ QTextCursor tc(document());
+ tc.setPosition(pos);
+ matches.append(tc);
+ }
+ }
+
+ beginEditBlock();
+
+ for (const QTextCursor &tc : qAsConst(matches)) {
+ setPosition(tc.position());
+ handleExCommand(innerCmd);
+ }
+
+ endEditBlock();
+
+ return true;
+}
+
bool FakeVimHandler::Private::handleExSortCommand(const ExCommand &cmd)
{
// :[range]sor[t][!] [b][f][i][n][o][r][u][x] [/{pattern}/]
@@ -6692,6 +6739,7 @@ bool FakeVimHandler::Private::handleExCommandHelper(ExCommand &cmd)
|| handleExMoveCommand(cmd)
|| handleExJoinCommand(cmd)
|| handleExMapCommand(cmd)
+ || handleExMultiRepeatCommand(cmd)
|| handleExNohlsearchCommand(cmd)
|| handleExNormalCommand(cmd)
|| handleExReadCommand(cmd)
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index 0ca936d4bff..24485b0c2a7 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -698,13 +698,8 @@ void FakeVimExCommandsPage::apply()
}
settings->endArray();
globalCommandMapping.clear();
-#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
globalCommandMapping.insert(defaultMap);
globalCommandMapping.insert(newMapping);
-#else
- globalCommandMapping.unite(defaultMap);
- globalCommandMapping.unite(newMapping);
-#endif
}
}
@@ -956,13 +951,8 @@ void FakeVimUserCommandsPage::apply()
}
settings->endArray();
userMap.clear();
-#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
userMap.insert(dd->m_defaultUserCommandMap);
userMap.insert(current);
-#else
- userMap.unite(dd->m_defaultUserCommandMap);
- userMap.unite(current);
-#endif
}
}
@@ -1219,7 +1209,7 @@ bool FakeVimPluginPrivate::initialize()
connect(act, &QAction::triggered, this, [this, i] { userActionTriggered(i); });
}
- connect(ICore::instance(), &ICore::coreAboutToClose, this, [this] {
+ connect(ICore::instance(), &ICore::coreAboutToClose, this, [] {
// Don't attach to editors anymore.
disconnect(EditorManager::instance(), &EditorManager::editorOpened,
dd, &FakeVimPluginPrivate::editorOpened);
diff --git a/src/plugins/genericprojectmanager/CMakeLists.txt b/src/plugins/genericprojectmanager/CMakeLists.txt
index 9aafbb82fdb..5b1ef6f84e4 100644
--- a/src/plugins/genericprojectmanager/CMakeLists.txt
+++ b/src/plugins/genericprojectmanager/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(GenericProjectManager
+ PLUGIN_CLASS GenericProjectPlugin
PLUGIN_DEPENDS Core ProjectExplorer QtSupport TextEditor
PLUGIN_TEST_DEPENDS CppEditor
PLUGIN_RECOMMENDS CppEditor
diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.cpp b/src/plugins/genericprojectmanager/genericprojectwizard.cpp
index af9b4343d4b..23020b97763 100644
--- a/src/plugins/genericprojectmanager/genericprojectwizard.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectwizard.cpp
@@ -36,7 +36,7 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/filewizardpage.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QApplication>
#include <QDebug>
diff --git a/src/plugins/git/CMakeLists.txt b/src/plugins/git/CMakeLists.txt
index 8c9bd94ac9b..25becbdf055 100644
--- a/src/plugins/git/CMakeLists.txt
+++ b/src/plugins/git/CMakeLists.txt
@@ -19,6 +19,7 @@ add_qtc_plugin(Git
gerrit/gerritremotechooser.cpp gerrit/gerritremotechooser.h
gerrit/gerritserver.cpp gerrit/gerritserver.h
git.qrc
+ git_global.h
gitclient.cpp gitclient.h
gitconstants.h
giteditor.cpp giteditor.h
diff --git a/src/plugins/git/changeselectiondialog.cpp b/src/plugins/git/changeselectiondialog.cpp
index b56ee47916a..5dd3e199b91 100644
--- a/src/plugins/git/changeselectiondialog.cpp
+++ b/src/plugins/git/changeselectiondialog.cpp
@@ -31,19 +31,20 @@
#include <coreplugin/vcsmanager.h>
#include <utils/pathchooser.h>
+#include <utils/qtcprocess.h>
#include <utils/theme/theme.h>
#include <vcsbase/vcscommand.h>
+#include <QCompleter>
+#include <QDir>
+#include <QFileDialog>
#include <QFormLayout>
-#include <QHBoxLayout>
-#include <QPushButton>
#include <QLabel>
+#include <QLayout>
#include <QLineEdit>
#include <QPlainTextEdit>
-#include <QDir>
-#include <QFileDialog>
-#include <QCompleter>
+#include <QPushButton>
#include <QStringListModel>
#include <QTimer>
@@ -105,7 +106,6 @@ ChangeSelectionDialog::ChangeSelectionDialog(const FilePath &workingDirectory, I
ChangeSelectionDialog::~ChangeSelectionDialog()
{
- terminateProcess();
delete m_ui;
}
@@ -161,10 +161,12 @@ void ChangeSelectionDialog::setDetails()
Theme *theme = creatorTheme();
QPalette palette;
- if (m_process->result() == QtcProcess::FinishedWithSuccess) {
- m_ui->detailsText->setPlainText(m_process->stdOut());
+ if (m_process->result() == ProcessResult::FinishedWithSuccess) {
+ m_ui->detailsText->setPlainText(m_process->cleanedStdOut());
palette.setColor(QPalette::Text, theme->color(Theme::TextColorNormal));
m_ui->changeNumberEdit->setPalette(palette);
+ } else if (m_process->result() == ProcessResult::StartFailed) {
+ m_ui->detailsText->setPlainText(tr("Error: Could not start Git."));
} else {
m_ui->detailsText->setPlainText(tr("Error: Unknown reference"));
palette.setColor(QPalette::Text, theme->color(Theme::TextColorError));
@@ -181,16 +183,6 @@ void ChangeSelectionDialog::enableButtons(bool b)
m_ui->checkoutButton->setEnabled(b);
}
-void ChangeSelectionDialog::terminateProcess()
-{
- if (!m_process)
- return;
- m_process->kill();
- m_process->waitForFinished();
- delete m_process;
- m_process = nullptr;
-}
-
void ChangeSelectionDialog::recalculateCompletion()
{
const FilePath workingDir = workingDirectory();
@@ -213,7 +205,6 @@ void ChangeSelectionDialog::recalculateCompletion()
void ChangeSelectionDialog::recalculateDetails()
{
- terminateProcess();
enableButtons(true);
const FilePath workingDir = workingDirectory();
@@ -228,18 +219,13 @@ void ChangeSelectionDialog::recalculateDetails()
return;
}
- m_process = new QtcProcess(this);
+ m_process.reset(new QtcProcess);
+ connect(m_process.get(), &QtcProcess::done, this, &ChangeSelectionDialog::setDetails);
m_process->setWorkingDirectory(workingDir);
m_process->setEnvironment(m_gitEnvironment);
m_process->setCommand({m_gitExecutable, {"show", "--decorate", "--stat=80", ref}});
-
- connect(m_process, &QtcProcess::finished, this, &ChangeSelectionDialog::setDetails);
-
m_process->start();
- if (!m_process->waitForStarted())
- m_ui->detailsText->setPlainText(tr("Error: Could not start Git."));
- else
- m_ui->detailsText->setPlainText(tr("Fetching commit data..."));
+ m_ui->detailsText->setPlainText(tr("Fetching commit data..."));
}
void ChangeSelectionDialog::changeTextChanged(const QString &text)
diff --git a/src/plugins/git/changeselectiondialog.h b/src/plugins/git/changeselectiondialog.h
index 45e9cb43fa0..d4bb7dc607f 100644
--- a/src/plugins/git/changeselectiondialog.h
+++ b/src/plugins/git/changeselectiondialog.h
@@ -72,11 +72,10 @@ private:
void acceptCommand(ChangeCommand command);
void enableButtons(bool b);
- void terminateProcess();
Ui::ChangeSelectionDialog *m_ui;
- Utils::QtcProcess *m_process = nullptr;
+ std::unique_ptr<Utils::QtcProcess> m_process;
Utils::FilePath m_gitExecutable;
Utils::Environment m_gitEnvironment;
ChangeCommand m_command = NoCommand;
diff --git a/src/plugins/git/gerrit/gerritdialog.ui b/src/plugins/git/gerrit/gerritdialog.ui
index 597cfd8f030..d44047a6552 100644
--- a/src/plugins/git/gerrit/gerritdialog.ui
+++ b/src/plugins/git/gerrit/gerritdialog.ui
@@ -70,6 +70,18 @@
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp
index b49be9a02e2..c213744b61a 100644
--- a/src/plugins/git/gerrit/gerritmodel.cpp
+++ b/src/plugins/git/gerrit/gerritmodel.cpp
@@ -31,6 +31,7 @@
#include <vcsbase/vcsoutputwindow.h>
#include <utils/algorithm.h>
+#include <utils/environment.h>
#include <utils/qtcprocess.h>
#include <QJsonArray>
@@ -245,8 +246,7 @@ signals:
void finished();
private:
- void processError(QProcess::ProcessError);
- void processFinished();
+ void processDone();
void timeout();
void errorTermination(const QString &msg);
@@ -292,8 +292,7 @@ QueryContext::QueryContext(const QString &query,
connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
m_output.append(m_process.readAllStandardOutput());
});
- connect(&m_process, &QtcProcess::finished, this, &QueryContext::processFinished);
- connect(&m_process, &QtcProcess::errorOccurred, this, &QueryContext::processError);
+ connect(&m_process, &QtcProcess::done, this, &QueryContext::processDone);
connect(&m_watcher, &QFutureWatcherBase::canceled, this, &QueryContext::terminate);
m_watcher.setFuture(m_progress.future());
m_process.setEnvironment(Git::Internal::GitClient::instance()->processEnvironment());
@@ -332,37 +331,31 @@ void QueryContext::errorTermination(const QString &msg)
if (!m_progress.isCanceled())
VcsOutputWindow::appendError(msg);
m_progress.reportCanceled();
- m_progress.reportFinished();
- emit finished();
}
void QueryContext::terminate()
{
- m_process.stopProcess();
-}
-
-void QueryContext::processError(QProcess::ProcessError e)
-{
- const QString msg = tr("Error running %1: %2").arg(m_binary.toUserOutput(), m_process.errorString());
- if (e == QProcess::FailedToStart)
- errorTermination(msg);
- else
- VcsOutputWindow::appendError(msg);
+ m_process.stop();
+ m_process.waitForFinished();
}
-void QueryContext::processFinished()
+void QueryContext::processDone()
{
if (m_timer.isActive())
m_timer.stop();
- emit errorText(m_error);
- if (m_process.exitStatus() != QProcess::NormalExit) {
+
+ if (!m_error.isEmpty())
+ emit errorText(m_error);
+
+ if (m_process.exitStatus() == QProcess::CrashExit)
errorTermination(tr("%1 crashed.").arg(m_binary.toUserOutput()));
- return;
- } else if (m_process.exitCode()) {
+ else if (m_process.exitCode())
errorTermination(tr("%1 returned %2.").arg(m_binary.toUserOutput()).arg(m_process.exitCode()));
- return;
- }
- emit resultRetrieved(m_output);
+ else if (m_process.result() != ProcessResult::FinishedWithSuccess)
+ errorTermination(tr("Error running %1: %2").arg(m_binary.toUserOutput(), m_process.errorString()));
+ else
+ emit resultRetrieved(m_output);
+
m_progress.reportFinished();
emit finished();
}
@@ -382,7 +375,7 @@ void QueryContext::timeout()
arg(timeOutMS / 1000), QMessageBox::NoButton, parent);
QPushButton *terminateButton = box.addButton(tr("Terminate"), QMessageBox::YesRole);
box.addButton(tr("Keep Running"), QMessageBox::NoRole);
- connect(&m_process, &QtcProcess::finished, &box, &QDialog::reject);
+ connect(&m_process, &QtcProcess::done, &box, &QDialog::reject);
box.exec();
if (m_process.state() != QProcess::Running)
return;
diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp
index d0904f96d6d..a92543dff8f 100644
--- a/src/plugins/git/gerrit/gerritplugin.cpp
+++ b/src/plugins/git/gerrit/gerritplugin.cpp
@@ -51,6 +51,7 @@
#include <vcsbase/vcsoutputwindow.h>
+#include <utils/environment.h>
#include <utils/qtcprocess.h>
#include <QDebug>
@@ -106,8 +107,7 @@ private:
ErrorState
};
- void processError(QProcess::ProcessError);
- void processFinished();
+ void processDone();
void processReadyReadStandardError();
void processReadyReadStandardOutput();
@@ -140,8 +140,7 @@ FetchContext::FetchContext(const QSharedPointer<GerritChange> &change,
, m_server(server)
, m_state(FetchState)
{
- connect(&m_process, &QtcProcess::errorOccurred, this, &FetchContext::processError);
- connect(&m_process, &QtcProcess::finished, this, &FetchContext::processFinished);
+ connect(&m_process, &QtcProcess::done, this, &FetchContext::processDone);
connect(&m_process, &QtcProcess::readyReadStandardError,
this, &FetchContext::processReadyReadStandardError);
connect(&m_process, &QtcProcess::readyReadStandardOutput,
@@ -174,29 +173,26 @@ void FetchContext::start()
m_process.start();
}
-void FetchContext::processFinished()
+void FetchContext::processDone()
{
- if (m_process.exitStatus() != QProcess::NormalExit) {
- handleError(tr("%1 crashed.").arg(m_git.toUserOutput()));
+ if (m_process.result() != ProcessResult::FinishedWithSuccess) {
+ handleError(m_process.exitMessage());
return;
}
- if (m_process.exitCode()) {
- handleError(tr("%1 returned %2.").arg(m_git.toUserOutput()).arg(m_process.exitCode()));
+ if (m_state != FetchState)
return;
- }
- if (m_state == FetchState) {
- m_progress.setProgressValue(m_progress.progressValue() + 1);
- if (m_fetchMode == FetchDisplay)
- show();
- else if (m_fetchMode == FetchCherryPick)
- cherryPick();
- else if (m_fetchMode == FetchCheckout)
- checkout();
- m_progress.reportFinished();
- m_state = DoneState;
- deleteLater();
- }
+ m_progress.setProgressValue(m_progress.progressValue() + 1);
+ if (m_fetchMode == FetchDisplay)
+ show();
+ else if (m_fetchMode == FetchCherryPick)
+ cherryPick();
+ else if (m_fetchMode == FetchCheckout)
+ checkout();
+
+ m_progress.reportFinished();
+ m_state = DoneState;
+ deleteLater();
}
void FetchContext::processReadyReadStandardError()
@@ -225,17 +221,6 @@ void FetchContext::handleError(const QString &e)
deleteLater();
}
-void FetchContext::processError(QProcess::ProcessError e)
-{
- if (m_progress.isCanceled())
- return;
- const QString msg = tr("Error running %1: %2").arg(m_git.toUserOutput(), m_process.errorString());
- if (e == QProcess::FailedToStart)
- handleError(msg);
- else
- VcsBase::VcsOutputWindow::appendError(msg);
-}
-
void FetchContext::show()
{
const QString title = QString::number(m_change->number) + '/'
@@ -258,10 +243,10 @@ void FetchContext::checkout()
void FetchContext::terminate()
{
- m_process.stopProcess();
+ m_process.stop();
+ m_process.waitForFinished();
}
-
GerritPlugin::GerritPlugin(QObject *parent)
: QObject(parent)
, m_parameters(new GerritParameters)
diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp
index efc1d02520e..9c891f457f3 100644
--- a/src/plugins/git/gerrit/gerritserver.cpp
+++ b/src/plugins/git/gerrit/gerritserver.cpp
@@ -120,7 +120,7 @@ QString GerritServer::url(UrlType urlType) const
case Https: protocol = "https"; break;
}
QString res = protocol + "://";
- if (type == Ssh || urlType != DefaultUrl)
+ if (type == Ssh || urlType == UrlWithHttpUser)
res += hostArgument();
else
res += host;
@@ -157,8 +157,7 @@ bool GerritServer::fillFromRemote(const QString &remote,
port = r.port;
user.userName = r.userName.isEmpty() ? parameters.server.user.userName : r.userName;
if (type == GerritServer::Ssh) {
- resolveVersion(parameters, forceReload);
- return true;
+ return resolveVersion(parameters, forceReload);
}
curlBinary = parameters.curl;
if (curlBinary.isEmpty() || !curlBinary.exists())
@@ -172,7 +171,8 @@ bool GerritServer::fillFromRemote(const QString &remote,
// (can be http://example.net/review)
ascendPath();
if (resolveRoot()) {
- resolveVersion(parameters, forceReload);
+ if (!resolveVersion(parameters, forceReload))
+ return false;
saveSettings(Valid);
return true;
}
@@ -180,8 +180,7 @@ bool GerritServer::fillFromRemote(const QString &remote,
case NotGerrit:
return false;
case Valid:
- resolveVersion(parameters, false);
- return true;
+ return resolveVersion(parameters, false);
}
return true;
}
@@ -247,8 +246,8 @@ int GerritServer::testConnection()
QtcProcess proc;
client->vcsFullySynchronousExec(proc, {}, {curlBinary, arguments},
Core::ShellCommand::NoOutput);
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- QString output = proc.stdOut();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ QString output = proc.cleanedStdOut();
// Gerrit returns an empty response for /p/qt-creator/a/accounts/self
// so consider this as 404.
if (output.isEmpty())
@@ -267,7 +266,7 @@ int GerritServer::testConnection()
if (proc.exitCode() == CertificateError)
return CertificateError;
const QRegularExpression errorRegexp("returned error: (\\d+)");
- QRegularExpressionMatch match = errorRegexp.match(proc.stdErr());
+ QRegularExpressionMatch match = errorRegexp.match(proc.cleanedStdErr());
if (match.hasMatch())
return match.captured(1).toInt();
return UnknownError;
@@ -332,14 +331,14 @@ bool GerritServer::resolveRoot()
return false;
}
-void GerritServer::resolveVersion(const GerritParameters &p, bool forceReload)
+bool GerritServer::resolveVersion(const GerritParameters &p, bool forceReload)
{
static GitClient *const client = GitClient::instance();
QSettings *settings = Core::ICore::settings();
const QString fullVersionKey = "Gerrit/" + host + '/' + versionKey;
version = settings->value(fullVersionKey).toString();
if (!version.isEmpty() && !forceReload)
- return;
+ return true;
if (type == Ssh) {
QtcProcess proc;
QStringList arguments;
@@ -347,9 +346,11 @@ void GerritServer::resolveVersion(const GerritParameters &p, bool forceReload)
arguments << p.portFlag << QString::number(port);
arguments << hostArgument() << "gerrit" << "version";
client->vcsFullySynchronousExec(proc, {}, {p.ssh, arguments}, Core::ShellCommand::NoOutput);
- QString stdOut = proc.stdOut().trimmed();
+ QString stdOut = proc.cleanedStdOut().trimmed();
stdOut.remove("gerrit version ");
version = stdOut;
+ if (version.isEmpty())
+ return false;
} else {
const QStringList arguments = curlArguments() << (url(RestUrl) + versionUrlC);
QtcProcess proc;
@@ -357,10 +358,10 @@ void GerritServer::resolveVersion(const GerritParameters &p, bool forceReload)
Core::ShellCommand::NoOutput);
// REST endpoint for version is only available from 2.8 and up. Do not consider invalid
// if it fails.
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- QString output = proc.stdOut();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ QString output = proc.cleanedStdOut();
if (output.isEmpty())
- return;
+ return false;
output.remove(0, output.indexOf('\n')); // Strip first line
output.remove('\n');
output.remove('"');
@@ -368,6 +369,7 @@ void GerritServer::resolveVersion(const GerritParameters &p, bool forceReload)
}
}
settings->setValue(fullVersionKey, version);
+ return true;
}
} // namespace Internal
diff --git a/src/plugins/git/gerrit/gerritserver.h b/src/plugins/git/gerrit/gerritserver.h
index ea0d8228ab6..80e119b65c8 100644
--- a/src/plugins/git/gerrit/gerritserver.h
+++ b/src/plugins/git/gerrit/gerritserver.h
@@ -94,7 +94,7 @@ private:
bool setupAuthentication();
bool ascendPath();
bool resolveRoot();
- void resolveVersion(const GerritParameters &p, bool forceReload);
+ bool resolveVersion(const GerritParameters &p, bool forceReload);
};
} // namespace Internal
diff --git a/src/plugins/git/git.qbs b/src/plugins/git/git.qbs
index de9effea893..7f48dfbf34d 100644
--- a/src/plugins/git/git.qbs
+++ b/src/plugins/git/git.qbs
@@ -32,6 +32,7 @@ QtcPlugin {
"commitdata.cpp",
"commitdata.h",
"git.qrc",
+ "git_global.h",
"gitclient.cpp",
"gitclient.h",
"gitconstants.h",
diff --git a/src/plugins/git/git_global.h b/src/plugins/git/git_global.h
new file mode 100644
index 00000000000..8eb2098a5b3
--- /dev/null
+++ b/src/plugins/git/git_global.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtGlobal>
+
+#if defined(GIT_LIBRARY)
+# define GITSHARED_EXPORT Q_DECL_EXPORT
+#elif defined(GIT_STATIC_LIBRARY)
+# define GITSHARED_EXPORT
+#else
+# define GITSHARED_EXPORT Q_DECL_IMPORT
+#endif
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 3a51e2c043b..5ac84c5ac45 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -45,9 +45,10 @@
#include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
#include <utils/commandline.h>
+#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
@@ -84,6 +85,8 @@
#include <QToolButton>
#include <QTextCodec>
+#include <vector>
+
const char GIT_DIRECTORY[] = ".git";
const char HEAD[] = "HEAD";
const char CHERRY_PICK_HEAD[] = "CHERRY_PICK_HEAD";
@@ -464,20 +467,32 @@ public:
setStartupFile(VcsBase::source(this->document()));
});
}
+ ~ShowController()
+ {
+ abortCommands();
+ }
void processCommandOutput(const QString &output) override;
private:
+ void processDescription(const QString &output);
+ void updateDescription();
+ void abortCommands();
const QString m_id;
enum State { Idle, GettingDescription, GettingDiff };
State m_state;
+ QString m_header;
+ QString m_body;
+ QString m_precedes;
+ std::vector<QString> m_follows;
+ QList<QPointer<VcsCommand>> m_commands;
};
void ShowController::processCommandOutput(const QString &output)
{
QTC_ASSERT(m_state != Idle, return);
if (m_state == GettingDescription) {
- setDescription(m_instance->extendedShowDescription(workingDirectory(), output));
+ processDescription(output);
// stage 2
m_state = GettingDiff;
const QStringList args = {"show", "--format=format:", // omit header, already generated
@@ -489,6 +504,72 @@ void ShowController::processCommandOutput(const QString &output)
}
}
+void ShowController::processDescription(const QString &output)
+{
+ abortCommands();
+ if (!output.startsWith("commit ")) {
+ setDescription(output);
+ return;
+ }
+ QString modText = output;
+ int lastHeaderLine = modText.indexOf("\n\n") + 1;
+ m_header = output.left(lastHeaderLine) + Constants::EXPAND_BRANCHES + '\n';
+ m_body = output.mid(lastHeaderLine + 1);
+ m_precedes = tr("<resolving>");
+ m_follows.push_back(m_precedes);
+ updateDescription();
+ const QString commit = modText.mid(7, 8);
+ m_commands.append(m_instance->execBgCommand(
+ workingDirectory(), {"describe", "--contains", commit},
+ [this](const QString &text) {
+ m_precedes = text.trimmed();
+ const int tilde = m_precedes.indexOf('~');
+ if (tilde != -1)
+ m_precedes.truncate(tilde);
+ if (m_precedes.endsWith("^0"))
+ m_precedes.chop(2);
+ updateDescription();
+ }));
+ QStringList parents;
+ QString errorMessage;
+ m_instance->synchronousParentRevisions(workingDirectory(), commit, &parents, &errorMessage);
+ m_follows.resize(parents.size());
+ for (int i = 0, total = parents.size(); i < total; ++i) {
+ m_commands.append(m_instance->execBgCommand(
+ workingDirectory(), {"describe", "--tags", "--abbrev=0", parents[i]},
+ [this, i](const QString &text) {
+ m_follows[i] = text.trimmed();
+ updateDescription();
+ }));
+ }
+}
+
+void ShowController::updateDescription()
+{
+ QString desc = m_header;
+ if (!m_precedes.isEmpty())
+ desc.append("Precedes: " + m_precedes + '\n');
+ QStringList follows;
+ for (const QString &str : m_follows) {
+ if (!str.isEmpty())
+ follows.append(str);
+ }
+ if (!follows.isEmpty())
+ desc.append("Follows: " + follows.join(", ") + '\n');
+ desc.append('\n' + m_body);
+
+ setDescription(desc);
+}
+
+void ShowController::abortCommands()
+{
+ for (QPointer<VcsCommand> command : m_commands) {
+ if (command)
+ command->abort();
+ }
+ m_commands.clear();
+}
+
///////////////////////////////
class BaseGitDiffArgumentsWidget : public VcsBaseEditorConfig
@@ -567,7 +648,7 @@ public:
static bool gitHasRgbColors()
{
- const unsigned gitVersion = GitClient::instance()->gitVersion();
+ const unsigned gitVersion = GitClient::instance()->gitVersion().result();
return gitVersion >= 0x020300U;
}
@@ -678,10 +759,10 @@ public:
{
ConflictHandler handler(workingDirectory, abortCommand);
// No conflicts => do nothing
- if (proc.result() == QtcProcess::FinishedWithSuccess)
+ if (proc.result() == ProcessResult::FinishedWithSuccess)
return;
- handler.readStdOut(proc.stdOut());
- handler.readStdErr(proc.stdErr());
+ handler.readStdOut(proc.cleanedStdOut());
+ handler.readStdErr(proc.cleanedStdErr());
}
private:
@@ -844,7 +925,7 @@ bool GitClient::managesFile(const FilePath &workingDirectory, const QString &fil
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, {"ls-files", "--error-unmatch", fileName},
Core::ShellCommand::NoOutput);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
FilePaths GitClient::unmanagedFiles(const FilePaths &filePaths) const
@@ -860,10 +941,10 @@ FilePaths GitClient::unmanagedFiles(const FilePaths &filePaths) const
args << transform(it.value(), [&wd](const QString &fp) { return wd.relativeFilePath(fp); });
QtcProcess proc;
vcsFullySynchronousExec(proc, it.key(), args, Core::ShellCommand::NoOutput);
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return filePaths;
const QStringList managedFilePaths
- = transform(proc.stdOut().split('\0', Qt::SkipEmptyParts),
+ = transform(proc.cleanedStdOut().split('\0', Qt::SkipEmptyParts),
[&wd](const QString &fp) { return wd.absoluteFilePath(fp); });
const QStringList filtered = Utils::filtered(it.value(), [&managedFilePaths, &wd](const QString &fp) {
return !managedFilePaths.contains(wd.absoluteFilePath(fp));
@@ -1060,8 +1141,7 @@ void GitClient::diffBranch(const FilePath &workingDirectory, const QString &bran
void GitClient::merge(const FilePath &workingDirectory, const QStringList &unmergedFileNames)
{
auto mergeTool = new MergeTool(this);
- if (!mergeTool->start(workingDirectory, unmergedFileNames))
- delete mergeTool;
+ mergeTool->start(workingDirectory, unmergedFileNames);
}
void GitClient::status(const FilePath &workingDirectory) const
@@ -1433,8 +1513,8 @@ void GitClient::recoverDeletedFiles(const FilePath &workingDirectory)
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, {"ls-files", "--deleted"},
VcsCommand::SuppressCommandLogging);
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- const QString stdOut = proc.stdOut().trimmed();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ const QString stdOut = proc.cleanedStdOut().trimmed();
if (stdOut.isEmpty()) {
VcsOutputWindow::appendError(tr("Nothing to recover"));
return;
@@ -1460,12 +1540,12 @@ bool GitClient::synchronousLog(const FilePath &workingDirectory, const QStringLi
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, allArguments, flags, vcsTimeoutS(),
encoding(workingDirectory, "i18n.logOutputEncoding"));
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- *output = proc.stdOut();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ *output = proc.cleanedStdOut();
return true;
} else {
msgCannotRun(tr("Cannot obtain log of \"%1\": %2")
- .arg(workingDirectory.toUserOutput(), proc.stdErr()), errorMessageIn);
+ .arg(workingDirectory.toUserOutput(), proc.cleanedStdErr()), errorMessageIn);
return false;
}
}
@@ -1478,7 +1558,7 @@ bool GitClient::synchronousAdd(const FilePath &workingDirectory,
args += extraOptions + files;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, args);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool GitClient::synchronousDelete(const FilePath &workingDirectory,
@@ -1491,7 +1571,7 @@ bool GitClient::synchronousDelete(const FilePath &workingDirectory,
arguments.append(files);
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool GitClient::synchronousMove(const FilePath &workingDirectory,
@@ -1500,7 +1580,7 @@ bool GitClient::synchronousMove(const FilePath &workingDirectory,
{
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, {"mv", from, to});
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool GitClient::synchronousReset(const FilePath &workingDirectory,
@@ -1515,18 +1595,18 @@ bool GitClient::synchronousReset(const FilePath &workingDirectory,
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments);
- const QString stdOut = proc.stdOut();
+ const QString stdOut = proc.cleanedStdOut();
VcsOutputWindow::append(stdOut);
// Note that git exits with 1 even if the operation is successful
// Assume real failure if the output does not contain "foo.cpp modified"
// or "Unstaged changes after reset" (git 1.7.0).
- if (proc.result() != QtcProcess::FinishedWithSuccess
+ if (proc.result() != ProcessResult::FinishedWithSuccess
&& (!stdOut.contains("modified") && !stdOut.contains("Unstaged changes after reset"))) {
if (files.isEmpty()) {
- msgCannotRun(arguments, workingDirectory, proc.stdErr(), errorMessage);
+ msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage);
} else {
msgCannotRun(tr("Cannot reset %n files in \"%1\": %2", nullptr, files.size())
- .arg(workingDirectory.toUserOutput(), proc.stdErr()),
+ .arg(workingDirectory.toUserOutput(), proc.cleanedStdErr()),
errorMessage);
}
return false;
@@ -1540,8 +1620,8 @@ bool GitClient::synchronousInit(const FilePath &workingDirectory)
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, QStringList{"init"});
// '[Re]Initialized...'
- VcsOutputWindow::append(proc.stdOut());
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
+ VcsOutputWindow::append(proc.cleanedStdOut());
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
resetCachedVcsInfo(workingDirectory);
return true;
} else {
@@ -1567,12 +1647,12 @@ bool GitClient::synchronousCheckoutFiles(const FilePath &workingDirectory, QStri
arguments << "--" << files;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, VcsCommand::ExpectRepoChanges);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
const QString fileArg = files.join(", ");
//: Meaning of the arguments: %1: revision, %2: files, %3: repository,
//: %4: Error message
msgCannotRun(tr("Cannot checkout \"%1\" of %2 in \"%3\": %4")
- .arg(revision, fileArg, workingDirectory.toUserOutput(), proc.stdErr()),
+ .arg(revision, fileArg, workingDirectory.toUserOutput(), proc.cleanedStdErr()),
errorMessage);
return false;
}
@@ -1619,11 +1699,11 @@ bool GitClient::synchronousRevListCmd(const FilePath &workingDirectory, const QS
const QStringList arguments = QStringList({"rev-list", noColorOption}) + extraArguments;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(arguments, workingDirectory, proc.stdErr(), errorMessage);
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
- *output = proc.stdOut();
+ *output = proc.cleanedStdOut();
return true;
}
@@ -1683,8 +1763,8 @@ QString GitClient::synchronousCurrentLocalBranch(const FilePath &workingDirector
QString branch;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, {"symbolic-ref", HEAD}, silentFlags);
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- branch = proc.stdOut().trimmed();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ branch = proc.cleanedStdOut().trimmed();
} else {
const QString gitDir = findGitDirForRepository(workingDirectory);
const QString rebaseHead = gitDir + "/rebase-merge/head-name";
@@ -1708,12 +1788,12 @@ bool GitClient::synchronousHeadRefs(const FilePath &workingDirectory, QStringLis
const QStringList arguments = {"show-ref", "--head", "--abbrev=10", "--dereference"};
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(arguments, workingDirectory, proc.stdErr(), errorMessage);
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
- const QString stdOut = proc.stdOut();
+ const QString stdOut = proc.cleanedStdOut();
const QString headSha = stdOut.left(10);
QString rest = stdOut.mid(15);
@@ -1757,8 +1837,8 @@ QString GitClient::synchronousTopic(const FilePath &workingDirectory) const
// No tag or remote branch - try git describe
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, QStringList{"describe"}, VcsCommand::NoOutput);
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- const QString stdOut = proc.stdOut().trimmed();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ const QString stdOut = proc.cleanedStdOut().trimmed();
if (!stdOut.isEmpty())
return stdOut;
}
@@ -1771,9 +1851,9 @@ bool GitClient::synchronousRevParseCmd(const FilePath &workingDirectory, const Q
const QStringList arguments = {"rev-parse", ref};
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags);
- *output = proc.stdOut().trimmed();
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(arguments, workingDirectory, proc.stdErr(), errorMessage);
+ *output = proc.cleanedStdOut().trimmed();
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
@@ -1786,9 +1866,9 @@ QString GitClient::synchronousTopRevision(const FilePath &workingDirectory, QDat
const QStringList arguments = {"show", "-s", "--pretty=format:%H:%ct", HEAD};
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags);
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return QString();
- const QStringList output = proc.stdOut().trimmed().split(':');
+ const QStringList output = proc.cleanedStdOut().trimmed().split(':');
if (dateTime && output.size() > 1) {
bool ok = false;
const qint64 timeT = output.at(1).toLongLong(&ok);
@@ -1797,35 +1877,6 @@ QString GitClient::synchronousTopRevision(const FilePath &workingDirectory, QDat
return output.first();
}
-void GitClient::synchronousTagsForCommit(const FilePath &workingDirectory, const QString &revision,
- QString &precedes, QString &follows) const
-{
- QtcProcess proc1;
- vcsFullySynchronousExec(proc1, workingDirectory, {"describe", "--contains", revision}, silentFlags);
- precedes = proc1.stdOut();
- int tilde = precedes.indexOf('~');
- if (tilde != -1)
- precedes.truncate(tilde);
- else
- precedes = precedes.trimmed();
-
- QStringList parents;
- QString errorMessage;
- synchronousParentRevisions(workingDirectory, revision, &parents, &errorMessage);
- for (const QString &p : qAsConst(parents)) {
- QtcProcess proc2;
- vcsFullySynchronousExec(proc2,
- workingDirectory, {"describe", "--tags", "--abbrev=0", p}, silentFlags);
- QString pf = proc2.stdOut();
- pf.truncate(pf.lastIndexOf('\n'));
- if (!pf.isEmpty()) {
- if (!follows.isEmpty())
- follows += ", ";
- follows += pf;
- }
- }
-}
-
bool GitClient::isRemoteCommit(const FilePath &workingDirectory, const QString &commit)
{
QtcProcess proc;
@@ -1837,7 +1888,7 @@ bool GitClient::isFastForwardMerge(const FilePath &workingDirectory, const QStri
{
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, {"merge-base", HEAD, branch}, silentFlags);
- return proc.stdOut().trimmed() == synchronousTopRevision(workingDirectory);
+ return proc.cleanedStdOut().trimmed() == synchronousTopRevision(workingDirectory);
}
// Format an entry in a one-liner for selection list using git log.
@@ -1848,12 +1899,12 @@ QString GitClient::synchronousShortDescription(const FilePath &workingDirectory,
"--max-count=1", revision};
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
VcsOutputWindow::appendSilently(tr("Cannot describe revision \"%1\" in \"%2\": %3")
- .arg(revision, workingDirectory.toUserOutput(), proc.stdErr()));
+ .arg(revision, workingDirectory.toUserOutput(), proc.cleanedStdErr()));
return revision;
}
- return stripLastNewline(proc.stdOut());
+ return stripLastNewline(proc.cleanedStdOut());
}
// Create a default message to be used for describing stashes
@@ -1929,8 +1980,8 @@ bool GitClient::executeSynchronousStash(const FilePath &workingDirectory,
| VcsCommand::ShowSuccessMessage;
QtcProcess proc;
vcsSynchronousExec(proc, workingDirectory, arguments, flags);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(arguments, workingDirectory, proc.stdErr(), errorMessage);
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
@@ -1969,9 +2020,9 @@ bool GitClient::synchronousBranchCmd(const FilePath &workingDirectory, QStringLi
branchArgs.push_front("branch");
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, branchArgs);
- *output = proc.stdOut();
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(branchArgs, workingDirectory, proc.stdErr(), errorMessage);
+ *output = proc.cleanedStdOut();
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(branchArgs, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
return true;
@@ -1983,9 +2034,9 @@ bool GitClient::synchronousTagCmd(const FilePath &workingDirectory, QStringList
tagArgs.push_front("tag");
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, tagArgs);
- *output = proc.stdOut();
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(tagArgs, workingDirectory, proc.stdErr(), errorMessage);
+ *output = proc.cleanedStdOut();
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(tagArgs, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
return true;
@@ -1997,9 +2048,9 @@ bool GitClient::synchronousForEachRefCmd(const FilePath &workingDirectory, QStri
args.push_front("for-each-ref");
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, args, silentFlags);
- *output = proc.stdOut();
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(args, workingDirectory, proc.stdErr(), errorMessage);
+ *output = proc.cleanedStdOut();
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(args, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
return true;
@@ -2018,11 +2069,11 @@ bool GitClient::synchronousRemoteCmd(const FilePath &workingDirectory, QStringLi
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, remoteArgs, silent ? silentFlags : 0);
- const QString stdErr = proc.stdErr();
+ const QString stdErr = proc.cleanedStdErr();
*errorMessage = stdErr;
- *output = proc.stdOut();
+ *output = proc.cleanedStdOut();
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
msgCannotRun(remoteArgs, workingDirectory, stdErr, errorMessage);
return false;
}
@@ -2062,12 +2113,12 @@ QStringList GitClient::synchronousSubmoduleStatus(const FilePath &workingDirecto
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, {"submodule", "status"}, silentFlags);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
msgCannotRun(tr("Cannot retrieve submodule status of \"%1\": %2")
- .arg(workingDirectory.toUserOutput(), proc.stdErr()), errorMessage);
+ .arg(workingDirectory.toUserOutput(), proc.cleanedStdErr()), errorMessage);
return QStringList();
}
- return splitLines(proc.stdOut());
+ return splitLines(proc.cleanedStdOut());
}
SubmoduleDataMap GitClient::submoduleList(const FilePath &workingDirectory) const
@@ -2142,8 +2193,8 @@ QByteArray GitClient::synchronousShow(const FilePath &workingDirectory, const QS
const QStringList arguments = {"show", decorateOption, noColorOption, "--no-patch", id};
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, flags);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(arguments, workingDirectory, proc.stdErr(), nullptr);
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), nullptr);
return {};
}
return proc.rawStdOut();
@@ -2158,8 +2209,8 @@ bool GitClient::cleanList(const FilePath &workingDirectory, const QString &modul
QtcProcess proc;
vcsFullySynchronousExec(proc, directory, arguments, VcsCommand::ForceCLocale);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(arguments, directory, proc.stdErr(), errorMessage);
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(arguments, directory, proc.cleanedStdErr(), errorMessage);
return false;
}
@@ -2167,7 +2218,7 @@ bool GitClient::cleanList(const FilePath &workingDirectory, const QString &modul
const QString relativeBase = modulePath.isEmpty() ? QString() : modulePath + '/';
const QString prefix = "Would remove ";
const QStringList removeLines = Utils::filtered(
- splitLines(proc.stdOut()), [](const QString &s) {
+ splitLines(proc.cleanedStdOut()), [](const QString &s) {
return s.startsWith("Would remove ");
});
*files = Utils::transform(removeLines, [&relativeBase, &prefix](const QString &s) -> QString {
@@ -2205,8 +2256,8 @@ bool GitClient::synchronousApplyPatch(const FilePath &workingDirectory,
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments);
- const QString stdErr = proc.stdErr();
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
+ const QString stdErr = proc.cleanedStdErr();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
if (!stdErr.isEmpty())
*errorMessage = tr("There were warnings while applying \"%1\" to \"%2\":\n%3")
.arg(file, workingDirectory.toUserOutput(), stdErr);
@@ -2342,17 +2393,17 @@ GitClient::StatusResult GitClient::gitStatus(const FilePath &workingDirectory, S
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags);
- const QString stdOut = proc.stdOut();
+ const QString stdOut = proc.cleanedStdOut();
if (output)
*output = stdOut;
- const bool statusRc = proc.result() == QtcProcess::FinishedWithSuccess;
+ const bool statusRc = proc.result() == ProcessResult::FinishedWithSuccess;
const bool branchKnown = !stdOut.startsWith("## HEAD (no branch)\n");
// Is it something really fatal?
if (!statusRc && !branchKnown) {
if (errorMessage) {
- *errorMessage = tr("Cannot obtain status: %1").arg(proc.stdErr());
+ *errorMessage = tr("Cannot obtain status: %1").arg(proc.cleanedStdErr());
}
return StatusFailed;
}
@@ -2477,28 +2528,6 @@ void GitClient::continuePreviousGitCommand(const FilePath &workingDirectory,
}
}
-QString GitClient::extendedShowDescription(const FilePath &workingDirectory, const QString &text) const
-{
- if (!text.startsWith("commit "))
- return text;
- QString modText = text;
- QString precedes, follows;
- int lastHeaderLine = modText.indexOf("\n\n") + 1;
- const QString commit = modText.mid(7, 8);
- synchronousTagsForCommit(workingDirectory, commit, precedes, follows);
- if (!precedes.isEmpty())
- modText.insert(lastHeaderLine, "Precedes: " + precedes + '\n');
- if (!follows.isEmpty())
- modText.insert(lastHeaderLine, "Follows: " + follows + '\n');
-
- // Empty line before headers and commit message
- const int emptyLine = modText.indexOf("\n\n");
- if (emptyLine != -1)
- modText.insert(emptyLine, QString('\n') + Constants::EXPAND_BRANCHES);
-
- return modText;
-}
-
// Quietly retrieve branch list of remote repository URL
//
// The branch HEAD is pointing to is always returned first.
@@ -2517,7 +2546,7 @@ QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryUR
// split "82bfad2f51d34e98b18982211c82220b8db049b<tab>refs/heads/master"
bool headFound = false;
bool branchFound = false;
- const QStringList lines = proc.stdOut().split('\n');
+ const QStringList lines = proc.cleanedStdOut().split('\n');
for (const QString &line : lines) {
if (line.endsWith("\tHEAD")) {
QTC_CHECK(headSha.isNull());
@@ -2545,31 +2574,7 @@ QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryUR
void GitClient::launchGitK(const FilePath &workingDirectory, const QString &fileName) const
{
- FilePath foundBinDir = vcsBinary().parentDir();
- Environment env = processEnvironment();
- if (tryLauchingGitK(env, workingDirectory, fileName, foundBinDir))
- return;
-
- VcsOutputWindow::appendSilently(msgCannotLaunch(foundBinDir / "gitk"));
-
- if (foundBinDir.fileName() == "bin") {
- foundBinDir = foundBinDir.parentDir();
- const QString binDirName = foundBinDir.fileName();
- if (binDirName == "usr" || binDirName.startsWith("mingw"))
- foundBinDir = foundBinDir.parentDir();
- if (tryLauchingGitK(env, workingDirectory, fileName, foundBinDir / "cmd"))
- return;
-
- VcsOutputWindow::appendSilently(msgCannotLaunch(foundBinDir / "cmd/gitk"));
- }
-
- Environment sysEnv = Environment::systemEnvironment();
- const FilePath exec = sysEnv.searchInPath("gitk");
-
- if (!exec.isEmpty() && tryLauchingGitK(env, workingDirectory, fileName, exec.parentDir()))
- return;
-
- VcsOutputWindow::appendError(msgCannotLaunch("gitk"));
+ tryLaunchingGitK(processEnvironment(), workingDirectory, fileName);
}
void GitClient::launchRepositoryBrowser(const FilePath &workingDirectory) const
@@ -2579,16 +2584,35 @@ void GitClient::launchRepositoryBrowser(const FilePath &workingDirectory) const
QtcProcess::startDetached({repBrowserBinary, {workingDirectory.toString()}}, workingDirectory);
}
-bool GitClient::tryLauchingGitK(const Environment &env,
- const FilePath &workingDirectory,
- const QString &fileName,
- const FilePath &gitBinDirectory) const
+static FilePath gitBinDir(const GitClient::GitKLaunchTrial trial, const FilePath &parentDir)
{
+ if (trial == GitClient::Bin)
+ return parentDir;
+ if (trial == GitClient::ParentOfBin) {
+ QTC_CHECK(parentDir.fileName() == "bin");
+ FilePath foundBinDir = parentDir.parentDir();
+ const QString binDirName = foundBinDir.fileName();
+ if (binDirName == "usr" || binDirName.startsWith("mingw"))
+ foundBinDir = foundBinDir.parentDir();
+ return foundBinDir / "cmd";
+ }
+ if (trial == GitClient::SystemPath)
+ return Environment::systemEnvironment().searchInPath("gitk").parentDir();
+ QTC_CHECK(false);
+ return FilePath();
+}
+
+void GitClient::tryLaunchingGitK(const Environment &env,
+ const FilePath &workingDirectory,
+ const QString &fileName,
+ GitClient::GitKLaunchTrial trial) const
+{
+ const FilePath gitBinDirectory = gitBinDir(trial, vcsBinary().parentDir());
FilePath binary = gitBinDirectory.pathAppended("gitk").withExecutableSuffix();
QStringList arguments;
if (HostOsInfo::isWindowsHost()) {
// If git/bin is in path, use 'wish' shell to run. Otherwise (git/cmd), directly run gitk
- FilePath wish = gitBinDirectory.pathAppended("wish").withExecutableSuffix();
+ const FilePath wish = gitBinDirectory.pathAppended("wish").withExecutableSuffix();
if (wish.withExecutableSuffix().exists()) {
arguments << binary.toString();
binary = wish;
@@ -2600,25 +2624,50 @@ bool GitClient::tryLauchingGitK(const Environment &env,
if (!fileName.isEmpty())
arguments << "--" << fileName;
VcsOutputWindow::appendCommand(workingDirectory, {binary, arguments});
+
// This should always use QtcProcess::startDetached (as not to kill
// the child), but that does not have an environment parameter.
- bool success = false;
if (!settings().path.value().isEmpty()) {
- auto process = new QtcProcess;
+ auto process = new QtcProcess(const_cast<GitClient*>(this));
process->setWorkingDirectory(workingDirectory);
process->setEnvironment(env);
process->setCommand({binary, arguments});
+ connect(process, &QtcProcess::done, this, [=] {
+ if (process->result() == ProcessResult::StartFailed)
+ handleGitKFailedToStart(env, workingDirectory, fileName, trial, gitBinDirectory);
+ process->deleteLater();
+ });
process->start();
- success = process->waitForStarted();
- if (success)
- connect(process, &QtcProcess::finished, process, &QObject::deleteLater);
- else
- delete process;
} else {
- success = QtcProcess::startDetached({binary, arguments}, workingDirectory);
+ if (!QtcProcess::startDetached({binary, arguments}, workingDirectory))
+ handleGitKFailedToStart(env, workingDirectory, fileName, trial, gitBinDirectory);
}
+}
- return success;
+void GitClient::handleGitKFailedToStart(const Environment &env,
+ const FilePath &workingDirectory,
+ const QString &fileName,
+ const GitClient::GitKLaunchTrial oldTrial,
+ const FilePath &oldGitBinDir) const
+{
+ QTC_ASSERT(oldTrial != None, return);
+ VcsOutputWindow::appendSilently(msgCannotLaunch(oldGitBinDir / "gitk"));
+
+ GitKLaunchTrial nextTrial = None;
+
+ if (oldTrial == Bin && vcsBinary().parentDir().fileName() == "bin") {
+ nextTrial = ParentOfBin;
+ } else if (oldTrial != SystemPath
+ && !Environment::systemEnvironment().searchInPath("gitk").isEmpty()) {
+ nextTrial = SystemPath;
+ }
+
+ if (nextTrial == None) {
+ VcsOutputWindow::appendError(msgCannotLaunch("gitk"));
+ return;
+ }
+
+ tryLaunchingGitK(env, workingDirectory, fileName, nextTrial);
}
bool GitClient::launchGitGui(const FilePath &workingDirectory) {
@@ -2718,7 +2767,7 @@ bool GitClient::readDataFromCommit(const FilePath &repoDirectory, const QString
QtcProcess proc;
vcsFullySynchronousExec(proc, repoDirectory, arguments, silentFlags);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
if (errorMessage) {
*errorMessage = tr("Cannot retrieve last commit data of repository \"%1\".")
.arg(repoDirectory.toUserOutput());
@@ -2886,9 +2935,9 @@ bool GitClient::getCommitData(const FilePath &workingDirectory,
static inline QString msgCommitted(const QString &amendSHA1, int fileCount)
{
if (amendSHA1.isEmpty())
- return GitClient::tr("Committed %n files.", nullptr, fileCount) + '\n';
+ return GitClient::tr("Committed %n files.", nullptr, fileCount);
if (fileCount)
- return GitClient::tr("Amended \"%1\" (%n files).", nullptr, fileCount).arg(amendSHA1) + '\n';
+ return GitClient::tr("Amended \"%1\" (%n files).", nullptr, fileCount).arg(amendSHA1);
return GitClient::tr("Amended \"%1\".").arg(amendSHA1);
}
@@ -2974,7 +3023,7 @@ bool GitClient::addAndCommit(const FilePath &repositoryDirectory,
QtcProcess proc;
vcsSynchronousExec(proc, repositoryDirectory, arguments, VcsCommand::NoFullySync);
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
VcsOutputWindow::appendMessage(msgCommitted(amendSHA1, commitCount));
GitPlugin::updateCurrentBranch();
return true;
@@ -3116,7 +3165,7 @@ bool GitClient::executeAndHandleConflicts(const FilePath &workingDirectory,
vcsSynchronousExec(proc, workingDirectory, arguments, flags);
// Notify about changed files or abort the rebase.
ConflictHandler::handleResponse(proc, workingDirectory, abortCommand);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
void GitClient::pull(const FilePath &workingDirectory, bool rebase)
@@ -3149,7 +3198,7 @@ void GitClient::synchronousAbortCommand(const FilePath &workingDir, const QStrin
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDir, {abortCommand, "--abort"},
VcsCommand::ExpectRepoChanges | VcsCommand::ShowSuccessMessage);
- VcsOutputWindow::append(proc.stdOut());
+ VcsOutputWindow::append(proc.cleanedStdOut());
}
QString GitClient::synchronousTrackingBranch(const FilePath &workingDirectory, const QString &branch)
@@ -3175,7 +3224,7 @@ bool GitClient::synchronousSetTrackingBranch(const FilePath &workingDirectory,
QtcProcess proc;
vcsFullySynchronousExec(proc,
workingDirectory, {"branch", "--set-upstream-to=" + tracking, branch});
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
VcsBase::VcsCommand *GitClient::asyncUpstreamStatus(const FilePath &workingDirectory,
@@ -3498,13 +3547,13 @@ bool GitClient::synchronousStashRemove(const FilePath &workingDirectory, const Q
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments);
- if (proc.result() == QtcProcess::FinishedWithSuccess) {
- const QString output = proc.stdOut();
+ if (proc.result() == ProcessResult::FinishedWithSuccess) {
+ const QString output = proc.cleanedStdOut();
if (!output.isEmpty())
VcsOutputWindow::append(output);
return true;
} else {
- msgCannotRun(arguments, workingDirectory, proc.stdErr(), errorMessage);
+ msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
}
@@ -3517,12 +3566,12 @@ bool GitClient::synchronousStashList(const FilePath &workingDirectory, QList<Sta
const QStringList arguments = {"stash", "list", noColorOption};
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, VcsCommand::ForceCLocale);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(arguments, workingDirectory, proc.stdErr(), errorMessage);
+ if (proc.result() != ProcessResult::FinishedWithSuccess) {
+ msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage);
return false;
}
Stash stash;
- const QStringList lines = splitLines(proc.stdOut());
+ const QStringList lines = splitLines(proc.cleanedStdOut());
for (const QString &line : lines) {
if (stash.parseStashLine(line))
stashes->push_back(stash);
@@ -3557,41 +3606,15 @@ QString GitClient::readOneLine(const FilePath &workingDirectory, const QStringLi
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags, vcsTimeoutS(), codec);
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return QString();
- return proc.stdOut().trimmed();
-}
-
-// determine version as '(major << 16) + (minor << 8) + patch' or 0.
-unsigned GitClient::gitVersion(QString *errorMessage) const
-{
- const FilePath newGitBinary = vcsBinary();
- if (m_gitVersionForBinary != newGitBinary && !newGitBinary.isEmpty()) {
- // Do not execute repeatedly if that fails (due to git
- // not being installed) until settings are changed.
- m_cachedGitVersion = synchronousGitVersion(errorMessage);
- m_gitVersionForBinary = newGitBinary;
- }
- return m_cachedGitVersion;
+ return proc.cleanedStdOut().trimmed();
}
-// determine version as '(major << 16) + (minor << 8) + patch' or 0.
-unsigned GitClient::synchronousGitVersion(QString *errorMessage) const
+static unsigned parseGitVersion(const QString &output)
{
- if (vcsBinary().isEmpty())
- return 0;
-
- // run git --version
- QtcProcess proc;
- vcsSynchronousExec(proc, {}, {"--version"}, silentFlags);
- if (proc.result() != QtcProcess::FinishedWithSuccess) {
- msgCannotRun(tr("Cannot determine Git version: %1").arg(proc.stdErr()), errorMessage);
- return 0;
- }
-
// cut 'git version 1.6.5.1.sha'
// another form: 'git version 1.9.rc1'
- const QString output = proc.stdOut();
const QRegularExpression versionPattern("^[^\\d]+(\\d+)\\.(\\d+)\\.(\\d+|rc\\d).*$");
QTC_ASSERT(versionPattern.isValid(), return 0);
const QRegularExpressionMatch match = versionPattern.match(output);
@@ -3602,6 +3625,41 @@ unsigned GitClient::synchronousGitVersion(QString *errorMessage) const
return version(majorV, minorV, patchV);
}
+// determine version as '(major << 16) + (minor << 8) + patch' or 0.
+QFuture<unsigned> GitClient::gitVersion() const
+{
+ QFutureInterface<unsigned> fi;
+ fi.reportStarted();
+
+ // Do not execute repeatedly if that fails (due to git
+ // not being installed) until settings are changed.
+ const FilePath newGitBinary = vcsBinary();
+ const bool needToRunGit = m_gitVersionForBinary != newGitBinary && !newGitBinary.isEmpty();
+ if (needToRunGit) {
+ auto proc = new QtcProcess(const_cast<GitClient *>(this));
+ connect(proc, &QtcProcess::done, this, [this, proc, fi, newGitBinary]() mutable {
+ if (proc->result() == ProcessResult::FinishedWithSuccess) {
+ m_cachedGitVersion = parseGitVersion(proc->cleanedStdOut());
+ m_gitVersionForBinary = newGitBinary;
+ fi.reportResult(m_cachedGitVersion);
+ fi.reportFinished();
+ }
+ proc->deleteLater();
+ });
+
+ proc->setTimeoutS(vcsTimeoutS());
+ proc->setEnvironment(processEnvironment());
+ proc->setCommand({newGitBinary, {"--version"}});
+ proc->start();
+ } else {
+ // already cached
+ fi.reportResult(m_cachedGitVersion);
+ fi.reportFinished();
+ }
+
+ return fi.future();
+}
+
bool GitClient::StashInfo::init(const FilePath &workingDirectory, const QString &command,
StashFlag flag, PushAction pushAction)
{
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 0a036e09367..1571183d5ca 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -26,6 +26,7 @@
#pragma once
#include "gitsettings.h"
+#include "git_global.h"
#include "commitdata.h"
#include <coreplugin/editormanager/ieditor.h>
@@ -105,13 +106,14 @@ public:
int behind = 0;
};
-class GitClient : public VcsBase::VcsBaseClientImpl
+class GITSHARED_EXPORT GitClient : public VcsBase::VcsBaseClientImpl
{
Q_OBJECT
public:
enum CommandInProgress { NoCommand, Revert, CherryPick,
Rebase, Merge, RebaseMerge };
+ enum GitKLaunchTrial { Bin, ParentOfBin, SystemPath, None };
class StashInfo
{
@@ -143,7 +145,7 @@ public:
static GitSettings &settings();
Utils::FilePath vcsBinary() const override;
- unsigned gitVersion(QString *errorMessage = nullptr) const;
+ QFuture<unsigned> gitVersion() const;
VcsBase::VcsCommand *vcsExecAbortable(const Utils::FilePath &workingDirectory,
const QStringList &arguments,
@@ -266,8 +268,6 @@ public:
bool synchronousRevParseCmd(const Utils::FilePath &workingDirectory, const QString &ref,
QString *output, QString *errorMessage = nullptr) const;
QString synchronousTopRevision(const Utils::FilePath &workingDirectory, QDateTime *dateTime = nullptr);
- void synchronousTagsForCommit(const Utils::FilePath &workingDirectory, const QString &revision,
- QString &precedes, QString &follows) const;
bool isRemoteCommit(const Utils::FilePath &workingDirectory, const QString &commit);
bool isFastForwardMerge(const Utils::FilePath &workingDirectory, const QString &branch);
@@ -332,8 +332,6 @@ public:
void continueCommandIfNeeded(const Utils::FilePath &workingDirectory, bool allowContinue = true);
- QString extendedShowDescription(const Utils::FilePath &workingDirectory, const QString &text) const;
-
void launchGitK(const Utils::FilePath &workingDirectory, const QString &fileName) const;
void launchGitK(const Utils::FilePath &workingDirectory) const { launchGitK(workingDirectory, QString()); }
bool launchGitGui(const Utils::FilePath &workingDirectory);
@@ -389,9 +387,6 @@ private:
const Utils::FilePath &workingDirectory,
std::function<GitBaseDiffEditorController *(Core::IDocument *)> factory) const;
- // determine version as '(major << 16) + (minor << 8) + patch' or 0.
- unsigned synchronousGitVersion(QString *errorMessage = nullptr) const;
-
QString readOneLine(const Utils::FilePath &workingDirectory, const QStringList &arguments) const;
enum RevertResult { RevertOk, RevertUnchanged, RevertCanceled, RevertFailed };
@@ -402,10 +397,15 @@ private:
void connectRepositoryChanged(const QString & repository, VcsBase::VcsCommand *cmd);
bool executeAndHandleConflicts(const Utils::FilePath &workingDirectory, const QStringList &arguments,
const QString &abortCommand = {}) const;
- bool tryLauchingGitK(const Utils::Environment &env,
- const Utils::FilePath &workingDirectory,
- const QString &fileName,
- const Utils::FilePath &gitBinDirectory) const;
+ void tryLaunchingGitK(const Utils::Environment &env,
+ const Utils::FilePath &workingDirectory,
+ const QString &fileName,
+ GitKLaunchTrial trial = GitKLaunchTrial::Bin) const;
+ void handleGitKFailedToStart(const Utils::Environment &env,
+ const Utils::FilePath &workingDirectory,
+ const QString &fileName,
+ const GitKLaunchTrial oldTrial,
+ const Utils::FilePath &oldGitBinDir) const;
bool cleanList(const Utils::FilePath &workingDirectory, const QString &modulePath,
const QString &flag, QStringList *files, QString *errorMessage);
diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp
index e7c3f2154ef..8fd16e26071 100644
--- a/src/plugins/git/giteditor.cpp
+++ b/src/plugins/git/giteditor.cpp
@@ -67,10 +67,9 @@ class GitLogFilterWidget : public QToolBar
public:
GitLogFilterWidget(GitEditorWidget *editor)
{
- auto addLineEdit = [this](const QString &placeholder,
- const QString &tooltip,
- GitEditorWidget *editor)
- {
+ auto addLineEdit = [](const QString &placeholder,
+ const QString &tooltip,
+ GitEditorWidget *editor) {
auto lineEdit = new Utils::FancyLineEdit;
lineEdit->setFiltering(true);
lineEdit->setToolTip(tooltip);
diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp
index f460cb9c7f3..fa2d9cdadda 100644
--- a/src/plugins/git/gitgrep.cpp
+++ b/src/plugins/git/gitgrep.cpp
@@ -204,13 +204,13 @@ public:
proc.setTimeoutS(0);
m_command->runCommand(proc, {m_vcsBinary, arguments});
switch (proc.result()) {
- case QtcProcess::TerminatedAbnormally:
- case QtcProcess::StartFailed:
- case QtcProcess::Hang:
+ case ProcessResult::TerminatedAbnormally:
+ case ProcessResult::StartFailed:
+ case ProcessResult::Hang:
fi.reportCanceled();
break;
- case QtcProcess::FinishedWithSuccess:
- case QtcProcess::FinishedWithError:
+ case ProcessResult::FinishedWithSuccess:
+ case ProcessResult::FinishedWithError:
// When no results are found, git-grep exits with non-zero status.
// Do not consider this as an error.
break;
@@ -247,10 +247,15 @@ GitGrep::GitGrep(GitClient *client)
const QRegularExpression refExpression("[\\S]*");
m_treeLineEdit->setValidator(new QRegularExpressionValidator(refExpression, this));
layout->addWidget(m_treeLineEdit);
- if (client->gitVersion() >= 0x021300) {
- m_recurseSubmodules = new QCheckBox(tr("Recurse submodules"));
- layout->addWidget(m_recurseSubmodules);
- }
+ // asynchronously check git version, add "recurse submodules" option if available
+ Utils::onResultReady(client->gitVersion(),
+ this,
+ [this, pLayout = QPointer<QHBoxLayout>(layout)](unsigned version) {
+ if (version >= 0x021300 && pLayout) {
+ m_recurseSubmodules = new QCheckBox(tr("Recurse submodules"));
+ pLayout->addWidget(m_recurseSubmodules);
+ }
+ });
TextEditor::FindInFiles *findInFiles = TextEditor::FindInFiles::instance();
QTC_ASSERT(findInFiles, return);
connect(findInFiles, &TextEditor::FindInFiles::pathChanged,
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 2dbcfeb56ff..f007303c4d3 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -61,10 +61,12 @@
#include <texteditor/texteditor.h>
#include <utils/algorithm.h>
+#include <utils/commandline.h>
#include <utils/infobar.h>
#include <utils/parameteraction.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
+#include <utils/runextensions.h>
#include <utils/stringutils.h>
#include <utils/utilsicons.h>
@@ -1366,20 +1368,22 @@ void GitPluginPrivate::startCommit(CommitType commitType)
void GitPluginPrivate::updateVersionWarning()
{
- unsigned version = m_gitClient.gitVersion();
- if (!version || version >= minimumRequiredVersion)
- return;
- IDocument *curDocument = EditorManager::currentDocument();
+ QPointer<IDocument> curDocument = EditorManager::currentDocument();
if (!curDocument)
return;
- InfoBar *infoBar = curDocument->infoBar();
- Id gitVersionWarning("GitVersionWarning");
- if (!infoBar->canInfoBeAdded(gitVersionWarning))
- return;
- infoBar->addInfo(InfoBarEntry(gitVersionWarning,
- tr("Unsupported version of Git found. Git %1 or later required.")
- .arg(versionString(minimumRequiredVersion)),
- InfoBarEntry::GlobalSuppression::Enabled));
+ Utils::onResultReady(m_gitClient.gitVersion(), this, [curDocument](unsigned version) {
+ if (!curDocument || !version || version >= minimumRequiredVersion)
+ return;
+ InfoBar *infoBar = curDocument->infoBar();
+ Id gitVersionWarning("GitVersionWarning");
+ if (!infoBar->canInfoBeAdded(gitVersionWarning))
+ return;
+ infoBar->addInfo(
+ InfoBarEntry(gitVersionWarning,
+ tr("Unsupported version of Git found. Git %1 or later required.")
+ .arg(versionString(minimumRequiredVersion)),
+ InfoBarEntry::GlobalSuppression::Enabled));
+ });
}
IEditor *GitPluginPrivate::openSubmitEditor(const QString &fileName, const CommitData &cd)
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index 341a312b4ca..6c36ae5db42 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -26,6 +26,7 @@
#pragma once
#include "gitsettings.h"
+#include "git_global.h"
#include <coreplugin/iversioncontrol.h>
@@ -42,7 +43,7 @@ namespace Internal {
class GitClient;
-class GitPlugin final : public ExtensionSystem::IPlugin
+class GITSHARED_EXPORT GitPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Git.json")
diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp
index 8a265d35bc5..6ab4b8edc6b 100644
--- a/src/plugins/git/gitsettings.cpp
+++ b/src/plugins/git/gitsettings.cpp
@@ -141,11 +141,9 @@ FilePath GitSettings::gitExecutable(bool *ok, QString *errorMessage) const
errorMessage->clear();
FilePath binPath = binaryPath.filePath();
- if (!binPath.isAbsolutePath()) {
- Environment env = Environment::systemEnvironment();
- env.prependOrSetPath(path.filePath());
- binPath = env.searchInPath(binPath.toString());
- }
+ if (!binPath.isAbsolutePath())
+ binPath = binPath.searchInPath({path.filePath()}, FilePath::PrependToPath);
+
if (binPath.isEmpty()) {
if (ok)
*ok = false;
diff --git a/src/plugins/git/mergetool.cpp b/src/plugins/git/mergetool.cpp
index b1da451b6b0..71ac736ef26 100644
--- a/src/plugins/git/mergetool.cpp
+++ b/src/plugins/git/mergetool.cpp
@@ -30,8 +30,7 @@
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
-#include <utils/commandline.h>
-#include <utils/qtcprocess.h>
+#include <utils/environment.h>
#include <vcsbase/vcsoutputwindow.h>
#include <QMessageBox>
@@ -44,38 +43,26 @@ namespace Git {
namespace Internal {
MergeTool::MergeTool(QObject *parent) : QObject(parent)
-{ }
-
-MergeTool::~MergeTool()
{
- delete m_process;
+ connect(&m_process, &QtcProcess::done, this, &MergeTool::done);
+ connect(&m_process, &QtcProcess::readyReadStandardOutput, this, &MergeTool::readData);
+ Environment env = Environment::systemEnvironment();
+ env.set("LANG", "C");
+ env.set("LANGUAGE", "C");
+ m_process.setEnvironment(env);
+ m_process.setProcessMode(ProcessMode::Writer);
+ m_process.setProcessChannelMode(QProcess::MergedChannels);
}
-bool MergeTool::start(const FilePath &workingDirectory, const QStringList &files)
+void MergeTool::start(const FilePath &workingDirectory, const QStringList &files)
{
QStringList arguments;
arguments << "mergetool" << "-y" << files;
- Environment env = Environment::systemEnvironment();
- env.set("LANG", "C");
- env.set("LANGUAGE", "C");
- m_process = new QtcProcess(ProcessMode::Writer);
- m_process->setWorkingDirectory(workingDirectory);
- m_process->setEnvironment(env);
- m_process->setProcessChannelMode(QProcess::MergedChannels);
- const Utils::FilePath binary = GitClient::instance()->vcsBinary();
- const CommandLine cmd = {binary, arguments};
+ const CommandLine cmd = {GitClient::instance()->vcsBinary(), arguments};
VcsOutputWindow::appendCommand(workingDirectory, cmd);
- m_process->setCommand(cmd);
- m_process->start();
- if (m_process->waitForStarted()) {
- connect(m_process, &QtcProcess::finished, this, &MergeTool::done);
- connect(m_process, &QtcProcess::readyReadStandardOutput, this, &MergeTool::readData);
- } else {
- delete m_process;
- m_process = nullptr;
- return false;
- }
- return true;
+ m_process.setCommand(cmd);
+ m_process.setWorkingDirectory(workingDirectory);
+ m_process.start();
}
MergeTool::FileState MergeTool::parseStatus(const QString &line, QString &extraInfo)
@@ -146,8 +133,7 @@ QString MergeTool::stateName(MergeTool::FileState state, const QString &extraInf
void MergeTool::chooseAction()
{
- m_merging = (m_mergeType == NormalMerge);
- if (m_merging)
+ if (m_mergeType == NormalMerge)
return;
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Merge Conflict"));
@@ -175,7 +161,6 @@ void MergeTool::chooseAction()
}
msgBox.exec();
- QByteArray ba;
QVariant key;
QAbstractButton *button = msgBox.clickedButton();
if (button)
@@ -183,9 +168,8 @@ void MergeTool::chooseAction()
// either the message box was closed without clicking anything, or abort was clicked
if (!key.isValid())
key = QVariant('a'); // abort
- ba.append(key.toChar().toLatin1());
- ba.append('\n');
- write(ba);
+
+ write(QString(key.toChar()) + '\n');
}
void MergeTool::addButton(QMessageBox *msgBox, const QString &text, char key)
@@ -206,7 +190,7 @@ void MergeTool::prompt(const QString &title, const QString &question)
void MergeTool::readData()
{
- QString newData = QString::fromLocal8Bit(m_process->readAllStandardOutput());
+ QString newData = QString::fromLocal8Bit(m_process.readAllStandardOutput());
newData.remove('\r');
VcsOutputWindow::append(newData);
QString data = m_unfinishedLine + newData;
@@ -230,7 +214,7 @@ void MergeTool::readData()
tr("Merge tool is not configured."),
tr("Run git config --global merge.tool &lt;tool&gt; "
"to configure it, then try again.")));
- m_process->kill();
+ m_process.stop();
} else {
m_unfinishedLine = data;
}
@@ -254,23 +238,22 @@ void MergeTool::readLine(const QString &line)
void MergeTool::done()
{
- const FilePath workingDirectory = m_process->workingDirectory();
- int exitCode = m_process->exitCode();
- if (!exitCode) {
- VcsOutputWindow::appendMessage(tr("Merge tool process finished successfully."));
- } else {
- VcsOutputWindow::appendError(tr("Merge tool process terminated with exit code %1")
- .arg(exitCode));
- }
- GitClient::instance()->continueCommandIfNeeded(workingDirectory, exitCode == 0);
+ const bool success = m_process.result() == ProcessResult::FinishedWithSuccess;
+ if (success)
+ VcsOutputWindow::appendMessage(m_process.exitMessage());
+ else
+ VcsOutputWindow::appendError(m_process.exitMessage());
+
+ const FilePath workingDirectory = m_process.workingDirectory();
+ GitClient::instance()->continueCommandIfNeeded(workingDirectory, success);
GitPlugin::emitRepositoryChanged(workingDirectory);
deleteLater();
}
-void MergeTool::write(const QByteArray &bytes)
+void MergeTool::write(const QString &str)
{
- m_process->write(bytes);
- VcsOutputWindow::append(QString::fromLocal8Bit(bytes));
+ m_process.write(str);
+ VcsOutputWindow::append(str);
}
} // namespace Internal
diff --git a/src/plugins/git/mergetool.h b/src/plugins/git/mergetool.h
index 5247a6217a4..735c53ea711 100644
--- a/src/plugins/git/mergetool.h
+++ b/src/plugins/git/mergetool.h
@@ -25,6 +25,8 @@
#pragma once
+#include <utils/qtcprocess.h>
+
#include <QObject>
#include <QStringList>
@@ -32,12 +34,6 @@ QT_BEGIN_NAMESPACE
class QMessageBox;
QT_END_NAMESPACE
-namespace Utils
-{
-class FilePath;
-class QtcProcess;
-}
-
namespace Git {
namespace Internal {
@@ -56,8 +52,7 @@ class MergeTool : public QObject
public:
explicit MergeTool(QObject *parent = nullptr);
- ~MergeTool() override;
- bool start(const Utils::FilePath &workingDirectory, const QStringList &files = {});
+ void start(const Utils::FilePath &workingDirectory, const QStringList &files = {});
enum MergeType {
NormalMerge,
@@ -71,7 +66,7 @@ private:
void readData();
void readLine(const QString &line);
void done();
- void write(const QByteArray &bytes);
+ void write(const QString &str);
FileState parseStatus(const QString &line, QString &extraInfo);
QString mergeTypeName();
@@ -79,7 +74,7 @@ private:
void chooseAction();
void addButton(QMessageBox *msgBox, const QString &text, char key);
- Utils::QtcProcess *m_process = nullptr;
+ Utils::QtcProcess m_process;
MergeType m_mergeType = NormalMerge;
QString m_fileName;
FileState m_localState = UnknownState;
@@ -87,7 +82,6 @@ private:
FileState m_remoteState = UnknownState;
QString m_remoteInfo;
QString m_unfinishedLine;
- bool m_merging = false;
};
} // namespace Internal
diff --git a/src/plugins/gitlab/CMakeLists.txt b/src/plugins/gitlab/CMakeLists.txt
new file mode 100644
index 00000000000..7bde1d67560
--- /dev/null
+++ b/src/plugins/gitlab/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_qtc_plugin(GitLab
+ PLUGIN_CLASS GitLabPlugin
+ PLUGIN_DEPENDS Core ProjectExplorer Git VcsBase
+ DEPENDS Utils
+ SOURCES
+ gitlabclonedialog.cpp gitlabclonedialog.h
+ gitlabdialog.cpp gitlabdialog.h gitlabdialog.ui
+ gitlaboptionspage.cpp gitlaboptionspage.h
+ gitlabparameters.cpp gitlabparameters.h
+ gitlabplugin.cpp gitlabplugin.h
+ gitlabprojectsettings.cpp gitlabprojectsettings.h
+ queryrunner.cpp queryrunner.h
+ resultparser.cpp resultparser.h
+)
diff --git a/src/plugins/gitlab/GitLab.json.in b/src/plugins/gitlab/GitLab.json.in
new file mode 100644
index 00000000000..cd65b9ee3ee
--- /dev/null
+++ b/src/plugins/gitlab/GitLab.json.in
@@ -0,0 +1,19 @@
+{
+\"Name\" : \"GitLab\",
+\"Version\" : \"$$QTCREATOR_VERSION\",
+\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
+\"Experimental\" : true,
+\"Vendor\" : \"The Qt Company Ltd\",
+\"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\",
+\"License\" : [ \"Commercial Usage\",
+\"\",
+\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\",
+\"\",
+\"GNU General Public License Usage\",
+\"\",
+\"Alternatively, this file may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this file. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html.\"
+],
+\"Description\" : \"GitLab plugin.\",
+\"Url\" : \"http://www.qt.io\",
+$$dependencyList
+}
diff --git a/src/plugins/gitlab/gitlab.qbs b/src/plugins/gitlab/gitlab.qbs
new file mode 100644
index 00000000000..96076b85d1a
--- /dev/null
+++ b/src/plugins/gitlab/gitlab.qbs
@@ -0,0 +1,31 @@
+import qbs
+
+QtcPlugin {
+ name: "GitLab"
+
+ Depends { name: "Core" }
+ Depends { name: "ProjectExplorer" }
+ Depends { name: "Git" }
+ Depends { name: "VcsBase" }
+ Depends { name: "Utils" }
+
+ files: [
+ "gitlabclonedialog.cpp",
+ "gitlabclonedialog.h",
+ "gitlabdialog.cpp",
+ "gitlabdialog.h",
+ "gitlabdialog.ui",
+ "gitlaboptionspage.cpp",
+ "gitlaboptionspage.h",
+ "gitlabparameters.cpp",
+ "gitlabparameters.h",
+ "gitlabplugin.cpp",
+ "gitlabplugin.h",
+ "gitlabprojectsettings.cpp",
+ "gitlabprojectsettings.h",
+ "queryrunner.cpp",
+ "queryrunner.h",
+ "resultparser.cpp",
+ "resultparser.h",
+ ]
+}
diff --git a/src/plugins/gitlab/gitlabclonedialog.cpp b/src/plugins/gitlab/gitlabclonedialog.cpp
new file mode 100644
index 00000000000..dcb9ec89268
--- /dev/null
+++ b/src/plugins/gitlab/gitlabclonedialog.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gitlabclonedialog.h"
+
+#include "gitlabprojectsettings.h"
+#include "resultparser.h"
+
+#include <coreplugin/documentmanager.h>
+#include <coreplugin/shellcommand.h>
+#include <coreplugin/vcsmanager.h>
+#include <git/gitclient.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectmanager.h>
+#include <utils/algorithm.h>
+#include <utils/commandline.h>
+#include <utils/environment.h>
+#include <utils/fancylineedit.h>
+#include <utils/filepath.h>
+#include <utils/infolabel.h>
+#include <utils/mimeutils.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+
+#include <QApplication>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QHBoxLayout>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QVBoxLayout>
+
+namespace GitLab {
+
+GitLabCloneDialog::GitLabCloneDialog(const Project &project, QWidget *parent)
+ : QDialog(parent)
+{
+ setWindowTitle(tr("Clone Repository"));
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(new QLabel(tr("Specify repository URL, checkout path and directory.")));
+ QHBoxLayout *centerLayout = new QHBoxLayout;
+ QFormLayout *form = new QFormLayout;
+ m_repositoryCB = new QComboBox(this);
+ m_repositoryCB->addItems({project.sshUrl, project.httpUrl});
+ form->addRow(tr("Repository"), m_repositoryCB);
+ m_pathChooser = new Utils::PathChooser(this);
+ m_pathChooser->setExpectedKind(Utils::PathChooser::ExistingDirectory);
+ form->addRow(tr("Path"), m_pathChooser);
+ m_directoryLE = new Utils::FancyLineEdit(this);
+ m_directoryLE->setValidationFunction([this](Utils::FancyLineEdit *e, QString *msg) {
+ const Utils::FilePath fullPath = m_pathChooser->filePath().pathAppended(e->text());
+ bool alreadyExists = fullPath.exists();
+ if (alreadyExists && msg)
+ *msg = tr("Path \"%1\" already exists.").arg(fullPath.toUserOutput());
+ return !alreadyExists;
+ });
+ form->addRow(tr("Directory"), m_directoryLE);
+ m_submodulesCB = new QCheckBox(this);
+ form->addRow(tr("Recursive"), m_submodulesCB);
+ form->addItem(new QSpacerItem(10, 10));
+ centerLayout->addLayout(form);
+ m_cloneOutput = new QPlainTextEdit(this);
+ m_cloneOutput->setReadOnly(true);
+ centerLayout->addWidget(m_cloneOutput);
+ layout->addLayout(centerLayout);
+ m_infoLabel = new Utils::InfoLabel(this);
+ layout->addWidget(m_infoLabel);
+ auto buttons = new QDialogButtonBox(QDialogButtonBox::Cancel, this);
+ m_cloneButton = new QPushButton(tr("Clone"), this);
+ buttons->addButton(m_cloneButton, QDialogButtonBox::ActionRole);
+ m_cancelButton = buttons->button(QDialogButtonBox::Cancel);
+ layout->addWidget(buttons);
+ setLayout(layout);
+
+ m_pathChooser->setFilePath(Core::DocumentManager::projectsDirectory());
+ auto [host, path, port]
+ = GitLabProjectSettings::remotePartsFromRemote(m_repositoryCB->currentText());
+ int slashIndex = path.indexOf('/');
+ QTC_ASSERT(slashIndex > 0, return);
+ m_directoryLE->setText(path.mid(slashIndex + 1));
+
+ connect(m_pathChooser, &Utils::PathChooser::pathChanged, this, [this]() {
+ m_directoryLE->validate();
+ GitLabCloneDialog::updateUi();
+ });
+ connect(m_directoryLE, &Utils::FancyLineEdit::textChanged, this, &GitLabCloneDialog::updateUi);
+ connect(m_cloneButton, &QPushButton::clicked, this, &GitLabCloneDialog::cloneProject);
+ connect(m_cancelButton, &QPushButton::clicked,
+ this, &GitLabCloneDialog::cancel);
+ connect(this, &QDialog::rejected, this, [this]() {
+ if (m_commandRunning) {
+ cancel();
+ QApplication::restoreOverrideCursor();
+ return;
+ }
+ });
+
+ updateUi();
+ resize(575, 265);
+}
+
+void GitLabCloneDialog::updateUi()
+{
+ bool pathValid = m_pathChooser->isValid();
+ bool directoryValid = m_directoryLE->isValid();
+ m_cloneButton->setEnabled(pathValid && directoryValid);
+ if (!pathValid) {
+ m_infoLabel->setText(m_pathChooser->errorMessage());
+ m_infoLabel->setType(Utils::InfoLabel::Error);
+ } else if (!directoryValid) {
+ m_infoLabel->setText(m_directoryLE->errorMessage());
+ m_infoLabel->setType(Utils::InfoLabel::Error);
+ }
+ m_infoLabel->setVisible(!pathValid || !directoryValid);
+}
+
+void GitLabCloneDialog::cloneProject()
+{
+ Core::IVersionControl *vc = Core::VcsManager::versionControl(Utils::Id::fromString("G.Git"));
+ QTC_ASSERT(vc, return);
+ const QStringList extraArgs = m_submodulesCB->isChecked() ? QStringList{ "--recursive" }
+ : QStringList{};
+ m_command = vc->createInitialCheckoutCommand(m_repositoryCB->currentText(),
+ m_pathChooser->absoluteFilePath(),
+ m_directoryLE->text(), extraArgs);
+ const Utils::FilePath workingDirectory = m_pathChooser->absoluteFilePath();
+ m_command->setProgressiveOutput(true);
+ connect(m_command, &Utils::ShellCommand::stdOutText, this, [this](const QString &text) {
+ m_cloneOutput->appendPlainText(text);
+ });
+ connect(m_command, &Utils::ShellCommand::stdErrText, this, [this](const QString &text) {
+ m_cloneOutput->appendPlainText(text);
+ });
+ connect(m_command, &Utils::ShellCommand::finished, this, &GitLabCloneDialog::cloneFinished);
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+
+ m_cloneOutput->clear();
+ m_cloneButton->setEnabled(false);
+ m_pathChooser->setReadOnly(true);
+ m_directoryLE->setReadOnly(true);
+ m_commandRunning = true;
+ m_command->execute();
+}
+
+void GitLabCloneDialog::cancel()
+{
+ if (m_commandRunning) {
+ m_cloneOutput->appendPlainText(tr("User canceled process."));
+ m_cancelButton->setEnabled(false);
+ m_command->cancel(); // FIXME does not cancel the git processes... QTCREATORBUG-27567
+ } else {
+ reject();
+ }
+}
+
+static Utils::FilePaths scanDirectoryForFiles(const Utils::FilePath &directory)
+{
+ Utils::FilePaths result;
+ const Utils::FilePaths entries = directory.dirEntries(QDir::AllEntries | QDir::NoDotAndDotDot);
+
+ for (const Utils::FilePath &entry : entries) {
+ if (entry.isDir())
+ result.append(scanDirectoryForFiles(entry));
+ else
+ result.append(entry);
+ }
+ return result;
+}
+
+void GitLabCloneDialog::cloneFinished(bool ok, int exitCode)
+{
+ const bool success = (ok && exitCode == 0);
+ m_commandRunning = false;
+ delete m_command;
+ m_command = nullptr;
+
+ const QString emptyLine("\n\n");
+ m_cloneOutput->appendPlainText(emptyLine);
+ QApplication::restoreOverrideCursor();
+
+ if (success) {
+ m_cloneOutput->appendPlainText(tr("Cloning succeeded.") + emptyLine);
+ m_cloneButton->setEnabled(false);
+
+ const Utils::FilePath base = m_pathChooser->filePath().pathAppended(m_directoryLE->text());
+ Utils::FilePaths filesWeMayOpen
+ = Utils::filtered(scanDirectoryForFiles(base), [](const Utils::FilePath &f) {
+ return ProjectExplorer::ProjectManager::canOpenProjectForMimeType(
+ Utils::mimeTypeForFile(f));
+ });
+
+ // limit the files to the most top-level item(s)
+ int minimum = std::numeric_limits<int>::max();
+ for (const Utils::FilePath &f : filesWeMayOpen) {
+ int parentCount = f.toString().count('/');
+ if (parentCount < minimum)
+ minimum = parentCount;
+ }
+ filesWeMayOpen = Utils::filtered(filesWeMayOpen, [minimum](const Utils::FilePath &f) {
+ return f.toString().count('/') == minimum;
+ });
+
+ hide(); // avoid to many dialogs.. FIXME: maybe change to some wizard approach?
+ if (filesWeMayOpen.isEmpty()) {
+ QMessageBox::warning(this, tr("Warning"),
+ tr("Cloned project does not have a project file that can be "
+ "opened. Try importing the project as a generic project."));
+ accept();
+ } else {
+ const QStringList pFiles = Utils::transform(filesWeMayOpen,
+ [base](const Utils::FilePath &f) {
+ return f.relativePath(base).toUserOutput();
+ });
+ bool ok = false;
+ const QString fileToOpen
+ = QInputDialog::getItem(this, tr("Open Project"),
+ tr("Choose the project file to be opened."),
+ pFiles, 0, false, &ok);
+ accept();
+ if (ok && !fileToOpen.isEmpty())
+ ProjectExplorer::ProjectExplorerPlugin::openProject(base.pathAppended(fileToOpen));
+ }
+ } else {
+ m_cloneOutput->appendPlainText(tr("Cloning failed.") + emptyLine);
+ const Utils::FilePath fullPath = m_pathChooser->filePath()
+ .pathAppended(m_directoryLE->text());
+ fullPath.removeRecursively();
+ m_cloneButton->setEnabled(true);
+ m_cancelButton->setEnabled(true);
+ m_pathChooser->setReadOnly(false);
+ m_directoryLE->setReadOnly(false);
+ m_directoryLE->validate();
+ }
+}
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabclonedialog.h b/src/plugins/gitlab/gitlabclonedialog.h
new file mode 100644
index 00000000000..5d3b19543aa
--- /dev/null
+++ b/src/plugins/gitlab/gitlabclonedialog.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QCoreApplication>
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+class QCheckBox;
+class QComboBox;
+class QPlainTextEdit;
+class QPushButton;
+QT_END_NAMESPACE
+
+namespace Core { class ShellCommand; }
+
+namespace Utils {
+class FancyLineEdit;
+class InfoLabel;
+class PathChooser;
+}
+
+namespace GitLab {
+
+class Project;
+
+class GitLabCloneDialog : public QDialog
+{
+ Q_DECLARE_TR_FUNCTIONS(GitLab::GitLabCloneDialog)
+public:
+ explicit GitLabCloneDialog(const Project &project, QWidget *parent = nullptr);
+
+private:
+ void updateUi();
+ void cloneProject();
+ void cancel();
+ void cloneFinished(bool ok, int exitCode);
+
+ QComboBox * m_repositoryCB = nullptr;
+ QCheckBox *m_submodulesCB = nullptr;
+ QPushButton *m_cloneButton = nullptr;
+ QPushButton *m_cancelButton = nullptr;
+ QPlainTextEdit *m_cloneOutput = nullptr;
+ Utils::PathChooser *m_pathChooser = nullptr;
+ Utils::FancyLineEdit *m_directoryLE = nullptr;
+ Utils::InfoLabel *m_infoLabel = nullptr;
+ Core::ShellCommand *m_command = nullptr;
+ bool m_commandRunning = false;
+};
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabdialog.cpp b/src/plugins/gitlab/gitlabdialog.cpp
new file mode 100644
index 00000000000..6b16c1fdc10
--- /dev/null
+++ b/src/plugins/gitlab/gitlabdialog.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gitlabdialog.h"
+
+#include "gitlabclonedialog.h"
+#include "gitlabparameters.h"
+#include "gitlabplugin.h"
+#include "gitlabprojectsettings.h"
+
+#include <projectexplorer/session.h>
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorsettings.h>
+#include <utils/listmodel.h>
+#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
+
+#include <QKeyEvent>
+#include <QLineEdit>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QRegularExpression>
+#include <QSyntaxHighlighter>
+
+namespace GitLab {
+
+GitLabDialog::GitLabDialog(QWidget *parent)
+ : QDialog(parent)
+ , m_lastTreeViewQuery(Query::NoQuery)
+{
+ m_ui.setupUi(this);
+ m_clonePB = new QPushButton(Utils::Icons::DOWNLOAD.icon(), tr("Clone..."), this);
+ m_ui.buttonBox->addButton(m_clonePB, QDialogButtonBox::ActionRole);
+ m_clonePB->setEnabled(false);
+
+ updateRemotes();
+
+ connect(m_ui.remoteCB, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &GitLabDialog::requestMainViewUpdate);
+ connect(m_ui.searchLE, &QLineEdit::returnPressed, this, &GitLabDialog::querySearch);
+ connect(m_ui.searchPB, &QPushButton::clicked, this, &GitLabDialog::querySearch);
+ connect(m_clonePB, &QPushButton::clicked, this, &GitLabDialog::cloneSelected);
+ connect(m_ui.firstTB, &QToolButton::clicked, this, &GitLabDialog::queryFirstPage);
+ connect(m_ui.previousTB, &QToolButton::clicked, this, &GitLabDialog::queryPreviousPage);
+ connect(m_ui.nextTB, &QToolButton::clicked, this, &GitLabDialog::queryNextPage);
+ connect(m_ui.lastTB, &QToolButton::clicked, this, &GitLabDialog::queryLastPage);
+ requestMainViewUpdate();
+}
+
+void GitLabDialog::resetTreeView(QTreeView *treeView, QAbstractItemModel *model)
+{
+ auto oldModel = treeView->model();
+ treeView->setModel(model);
+ delete oldModel;
+ if (model) {
+ connect(treeView->selectionModel(), &QItemSelectionModel::selectionChanged,
+ this, [this](const QItemSelection &selected, const QItemSelection &) {
+ m_clonePB->setEnabled(!selected.isEmpty());
+ });
+ m_clonePB->setEnabled(!treeView->selectionModel()->selectedIndexes().isEmpty());
+ }
+}
+
+void GitLabDialog::updateRemotes()
+{
+ m_ui.remoteCB->clear();
+ const GitLabParameters *global = GitLabPlugin::globalParameters();
+ for (const GitLabServer &server : qAsConst(global->gitLabServers))
+ m_ui.remoteCB->addItem(server.displayString(), QVariant::fromValue(server));
+
+ m_ui.remoteCB->setCurrentIndex(m_ui.remoteCB->findData(
+ QVariant::fromValue(global->currentDefaultServer())));
+}
+
+void GitLabDialog::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
+ return;
+ QDialog::keyPressEvent(event);
+}
+
+void GitLabDialog::requestMainViewUpdate()
+{
+ m_lastPageInformation = PageInformation();
+ m_lastTreeViewQuery = Query(Query::NoQuery);
+
+ m_ui.mainLabel->setText({});
+ m_ui.detailsLabel->setText({});
+ m_ui.treeViewTitle->setText({});
+ m_ui.searchLE->setText({});
+ resetTreeView(m_ui.treeView, nullptr);
+ updatePageButtons();
+
+ bool linked = false;
+ m_currentServerId = Utils::Id();
+ if (auto project = ProjectExplorer::SessionManager::startupProject()) {
+ GitLabProjectSettings *projSettings = GitLabPlugin::projectSettings(project);
+ if (projSettings->isLinked()) {
+ m_currentServerId = projSettings->currentServer();
+ linked = true;
+ }
+ }
+ if (!m_currentServerId.isValid())
+ m_currentServerId = m_ui.remoteCB->currentData().value<GitLabServer>().id;
+ if (m_currentServerId.isValid()) {
+ const GitLabParameters *global = GitLabPlugin::globalParameters();
+ const GitLabServer server = global->serverForId(m_currentServerId);
+ m_ui.remoteCB->setCurrentIndex(m_ui.remoteCB->findData(QVariant::fromValue(server)));
+ }
+ m_ui.remoteCB->setEnabled(!linked);
+
+ if (!m_currentServerId.isValid())
+ return;
+
+ const Query query(Query::User);
+ QueryRunner *runner = new QueryRunner(query, m_currentServerId, this);
+ connect(runner, &QueryRunner::resultRetrieved, this, [this](const QByteArray &result) {
+ handleUser(ResultParser::parseUser(result));
+ });
+ connect(runner, &QueryRunner::finished, [runner]() { runner->deleteLater(); });
+ runner->start();
+}
+
+void GitLabDialog::updatePageButtons()
+{
+ if (m_lastPageInformation.currentPage == -1) {
+ m_ui.currentPage->setVisible(false);
+ m_ui.firstTB->setVisible(false);
+ m_ui.lastTB->setVisible(false);
+ m_ui.previousTB->setVisible(false);
+ m_ui.nextTB->setVisible(false);
+ } else {
+ m_ui.currentPage->setText(QString::number(m_lastPageInformation.currentPage));
+ m_ui.currentPage->setVisible(true);
+ m_ui.firstTB->setVisible(true);
+ m_ui.lastTB->setVisible(true);
+ }
+ if (m_lastPageInformation.currentPage > 1) {
+ m_ui.firstTB->setEnabled(true);
+ m_ui.previousTB->setText(QString::number(m_lastPageInformation.currentPage - 1));
+ m_ui.previousTB->setVisible(true);
+ } else {
+ m_ui.firstTB->setEnabled(false);
+ m_ui.previousTB->setVisible(false);
+ }
+ if (m_lastPageInformation.currentPage < m_lastPageInformation.totalPages) {
+ m_ui.lastTB->setEnabled(true);
+ m_ui.nextTB->setText(QString::number(m_lastPageInformation.currentPage + 1));
+ m_ui.nextTB->setVisible(true);
+ } else {
+ m_ui.lastTB->setEnabled(false);
+ m_ui.nextTB->setVisible(false);
+ }
+}
+
+void GitLabDialog::queryFirstPage()
+{
+ QTC_ASSERT(m_lastTreeViewQuery.type() != Query::NoQuery, return);
+ QTC_ASSERT(m_lastPageInformation.currentPage != -1, return);
+ m_lastTreeViewQuery.setPageParameter(1);
+ fetchProjects();
+}
+
+void GitLabDialog::queryPreviousPage()
+{
+ QTC_ASSERT(m_lastTreeViewQuery.type() != Query::NoQuery, return);
+ QTC_ASSERT(m_lastPageInformation.currentPage != -1, return);
+ m_lastTreeViewQuery.setPageParameter(m_lastPageInformation.currentPage - 1);
+ fetchProjects();
+}
+
+void GitLabDialog::queryNextPage()
+{
+ QTC_ASSERT(m_lastTreeViewQuery.type() != Query::NoQuery, return);
+ QTC_ASSERT(m_lastPageInformation.currentPage != -1, return);
+ m_lastTreeViewQuery.setPageParameter(m_lastPageInformation.currentPage + 1);
+ fetchProjects();
+}
+
+void GitLabDialog::queryLastPage()
+{
+ QTC_ASSERT(m_lastTreeViewQuery.type() != Query::NoQuery, return);
+ QTC_ASSERT(m_lastPageInformation.currentPage != -1, return);
+ m_lastTreeViewQuery.setPageParameter(m_lastPageInformation.totalPages);
+ fetchProjects();
+}
+
+void GitLabDialog::querySearch()
+{
+ QTC_ASSERT(m_lastTreeViewQuery.type() != Query::NoQuery, return);
+ m_lastTreeViewQuery.setPageParameter(-1);
+ m_lastTreeViewQuery.setAdditionalParameters({"search=" + m_ui.searchLE->text()});
+ fetchProjects();
+}
+
+void GitLabDialog::handleUser(const User &user)
+{
+ m_lastPageInformation = {};
+ m_currentUserId = user.id;
+
+ if (!user.error.message.isEmpty()) {
+ m_ui.mainLabel->setText(tr("Not logged in."));
+ if (user.error.code == 1) {
+ m_ui.detailsLabel->setText(tr("Insufficient access token."));
+ m_ui.detailsLabel->setToolTip(user.error.message + QLatin1Char('\n')
+ + tr("Permission scope read_api or api needed."));
+ } else if (user.error.code >= 300 && user.error.code < 400) {
+ m_ui.detailsLabel->setText(tr("Check settings for misconfiguration."));
+ m_ui.detailsLabel->setToolTip(user.error.message);
+ } else {
+ m_ui.detailsLabel->setText({});
+ m_ui.detailsLabel->setToolTip({});
+ }
+ updatePageButtons();
+ m_ui.treeViewTitle->setText(tr("Projects (%1)").arg(0));
+ return;
+ }
+
+ if (user.id != -1) {
+ if (user.bot) {
+ m_ui.mainLabel->setText(tr("Using project access token."));
+ m_ui.detailsLabel->setText({});
+ } else {
+ m_ui.mainLabel->setText(tr("Logged in as %1").arg(user.name));
+ m_ui.detailsLabel->setText(tr("Id: %1 (%2)").arg(user.id).arg(user.email));
+ }
+ m_ui.detailsLabel->setToolTip({});
+ } else {
+ m_ui.mainLabel->setText(tr("Not logged in."));
+ m_ui.detailsLabel->setText({});
+ m_ui.detailsLabel->setToolTip({});
+ }
+ m_lastTreeViewQuery = Query(Query::Projects);
+ fetchProjects();
+}
+
+void GitLabDialog::handleProjects(const Projects &projects)
+{
+ Utils::ListModel<Project *> *listModel = new Utils::ListModel<Project *>(this);
+ for (const Project &project : projects.projects)
+ listModel->appendItem(new Project(project));
+
+ // TODO use a real model / delegate..?
+ listModel->setDataAccessor([](Project *data, int /*column*/, int role) -> QVariant {
+ if (role == Qt::DisplayRole)
+ return QString(data->displayName + " (" + data->visibility + ')');
+ if (role == Qt::UserRole)
+ return QVariant::fromValue(*data);
+ return QVariant();
+ });
+ resetTreeView(m_ui.treeView, listModel);
+ int count = projects.error.message.isEmpty() ? projects.pageInfo.total : 0;
+ m_ui.treeViewTitle->setText(tr("Projects (%1)").arg(count));
+
+ m_lastPageInformation = projects.pageInfo;
+ updatePageButtons();
+}
+
+void GitLabDialog::fetchProjects()
+{
+ QueryRunner *runner = new QueryRunner(m_lastTreeViewQuery, m_currentServerId, this);
+ connect(runner, &QueryRunner::resultRetrieved, this, [this](const QByteArray &result) {
+ handleProjects(ResultParser::parseProjects(result));
+ });
+ connect(runner, &QueryRunner::finished, [runner]() { runner->deleteLater(); });
+ runner->start();
+}
+
+void GitLabDialog::cloneSelected()
+{
+ const QModelIndexList indexes = m_ui.treeView->selectionModel()->selectedIndexes();
+ QTC_ASSERT(indexes.size() == 1, return);
+ const Project project = indexes.first().data(Qt::UserRole).value<Project>();
+ QTC_ASSERT(!project.sshUrl.isEmpty() && !project.httpUrl.isEmpty(), return);
+ GitLabCloneDialog dialog(project, this);
+ if (dialog.exec() == QDialog::Accepted)
+ reject();
+}
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabdialog.h b/src/plugins/gitlab/gitlabdialog.h
new file mode 100644
index 00000000000..907d786f474
--- /dev/null
+++ b/src/plugins/gitlab/gitlabdialog.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+#pragma once
+
+#include "ui_gitlabdialog.h"
+
+#include "queryrunner.h"
+#include "resultparser.h"
+
+#include <utils/filepath.h>
+#include <utils/id.h>
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+class QPushButton;
+QT_END_NAMESPACE
+
+namespace GitLab {
+
+class GitLabParameters;
+class GitLabDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit GitLabDialog(QWidget *parent = nullptr);
+
+ void updateRemotes();
+
+protected:
+ void keyPressEvent(QKeyEvent *event) override;
+
+private:
+ void resetTreeView(QTreeView *treeView, QAbstractItemModel *model);
+ void requestMainViewUpdate();
+ void updatePageButtons();
+
+ void queryFirstPage();
+ void queryPreviousPage();
+ void queryNextPage();
+ void queryLastPage();
+ void querySearch();
+ void continuePageUpdate();
+
+ void handleUser(const User &user);
+ void handleProjects(const Projects &projects);
+ void fetchProjects();
+
+ void cloneSelected();
+
+ Ui::GitLabDialog m_ui;
+ QPushButton *m_clonePB = nullptr;
+ Utils::Id m_currentServerId;
+ Query m_lastTreeViewQuery;
+ PageInformation m_lastPageInformation;
+ int m_currentUserId = -1;
+};
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabdialog.ui b/src/plugins/gitlab/gitlabdialog.ui
new file mode 100644
index 00000000000..2b4377b1263
--- /dev/null
+++ b/src/plugins/gitlab/gitlabdialog.ui
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GitLab::GitLabDialog</class>
+ <widget class="QDialog" name="GitLab::GitLabDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>665</width>
+ <height>530</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>GitLab</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_0">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_1">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_0">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="mainLabel">
+ <property name="text">
+ <string>Login</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="detailsLabel">
+ <property name="text">
+ <string>Details</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_0">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Remote:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="remoteCB">
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="treeViewTitle">
+ <property name="text">
+ <string>Projects</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_1">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="searchLE">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="placeholderText">
+ <string>Search</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="searchPB">
+ <property name="text">
+ <string>Search</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QTreeView" name="treeView">
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
+ </property>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
+ <property name="expandsOnDoubleClick">
+ <bool>false</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>200</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="QToolButton" name="firstTB">
+ <property name="text">
+ <string notr="true">|&lt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="previousTB">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="currentPage">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="nextTB">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="lastTB">
+ <property name="text">
+ <string notr="true">&gt;|</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>200</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>GitLab::GitLabDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/gitlab/gitlaboptionspage.cpp b/src/plugins/gitlab/gitlaboptionspage.cpp
new file mode 100644
index 00000000000..131fe6ec039
--- /dev/null
+++ b/src/plugins/gitlab/gitlaboptionspage.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gitlaboptionspage.h"
+
+#include "gitlabparameters.h"
+
+#include <coreplugin/icore.h>
+#include <utils/algorithm.h>
+#include <utils/layoutbuilder.h>
+#include <utils/qtcassert.h>
+#include <vcsbase/vcsbaseconstants.h>
+
+#include <QAction>
+#include <QComboBox>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QPushButton>
+#include <QRegularExpression>
+#include <QUuid>
+
+namespace GitLab {
+
+static bool hostValid(const QString &host)
+{
+ static const QRegularExpression ip(R"(^(\d+).(\d+).(\d+).(\d+)$)");
+ static const QRegularExpression dn(R"(^([a-zA-Z0-9][a-zA-Z0-9-]+\.)+[a-zA-Z0-9][a-zA-Z0-9-]+$)");
+ const QRegularExpressionMatch match = ip.match(host);
+ if (match.hasMatch()) {
+ for (int i = 1; i < 5; ++i) {
+ int val = match.captured(i).toInt();
+ if (val < 0 || val > 255)
+ return false;
+ }
+ return true;
+ }
+ return (host == "localhost") || dn.match(host).hasMatch();
+}
+
+GitLabServerWidget::GitLabServerWidget(Mode m, QWidget *parent)
+ : QWidget(parent)
+ , m_mode(m)
+{
+ m_host.setLabelText(GitLabOptionsPage::tr("Host:"));
+ m_host.setDisplayStyle(m == Display ? Utils::StringAspect::LabelDisplay
+ : Utils::StringAspect::LineEditDisplay);
+ m_host.setValidationFunction([](Utils::FancyLineEdit *l, QString *) {
+ return hostValid(l->text());
+ });
+
+ m_description.setLabelText(GitLabOptionsPage::tr("Description:"));
+ m_description.setDisplayStyle(m == Display ? Utils::StringAspect::LabelDisplay
+ : Utils::StringAspect::LineEditDisplay);
+
+ m_token.setLabelText(GitLabOptionsPage::tr("Access token:"));
+ m_token.setDisplayStyle(m == Display ? Utils::StringAspect::LabelDisplay
+ : Utils::StringAspect::LineEditDisplay);
+ m_token.setVisible(m == Edit);
+
+ m_port.setRange(1, 65535);
+ m_port.setValue(GitLabServer::defaultPort);
+ auto portLabel = new QLabel(GitLabOptionsPage::tr("Port:"), this);
+ m_port.setEnabled(m == Edit);
+ m_secure.setLabelText(GitLabOptionsPage::tr("HTTPS:"));
+ m_secure.setLabelPlacement(Utils::BoolAspect::LabelPlacement::InExtraLabel);
+ m_secure.setDefaultValue(true);
+ m_secure.setEnabled(m == Edit);
+
+ using namespace Utils::Layouting;
+ const Break nl;
+
+ Row {
+ Form {
+ m_host,
+ m_description,
+ m_token,
+ portLabel, &m_port, nl,
+ m_secure
+ },
+ Stretch()
+ }.attachTo(this, m == Edit);
+}
+
+GitLabServer GitLabServerWidget::gitLabServer() const
+{
+ GitLabServer result;
+ result.id = m_mode == Edit ? Utils::Id::fromName(QUuid::createUuid().toByteArray()) : m_id;
+ result.host = m_host.value();
+ result.description = m_description.value();
+ result.token = m_token.value();
+ result.port = m_port.value();
+ result.secure = m_secure.value();
+ return result;
+}
+
+void GitLabServerWidget::setGitLabServer(const GitLabServer &server)
+{
+ m_id = server.id;
+ m_host.setValue(server.host);
+ m_description.setValue(server.description);
+ m_token.setValue(server.token);
+ m_port.setValue(server.port);
+ m_secure.setValue(server.secure);
+}
+
+GitLabOptionsWidget::GitLabOptionsWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ auto defaultLabel = new QLabel(tr("Default:"), this);
+ m_defaultGitLabServer = new QComboBox(this);
+ m_curl.setDisplayStyle(Utils::StringAspect::DisplayStyle::PathChooserDisplay);
+ m_curl.setLabelText(tr("curl:"));
+ m_curl.setExpectedKind(Utils::PathChooser::ExistingCommand);
+
+ m_gitLabServerWidget = new GitLabServerWidget(GitLabServerWidget::Display, this);
+
+ m_edit = new QPushButton(tr("Edit..."), this);
+ m_edit->setToolTip(tr("Edit current selected GitLab server configuration."));
+ m_remove = new QPushButton(tr("Remove"), this);
+ m_remove->setToolTip(tr("Remove current selected GitLab server configuration."));
+ m_add = new QPushButton(tr("Add..."), this);
+ m_add->setToolTip(tr("Add new GitLab server configuration."));
+
+ using namespace Utils::Layouting;
+ const Break nl;
+
+ Grid {
+ Form {
+ defaultLabel, m_defaultGitLabServer, nl,
+ Row { Group { m_gitLabServerWidget, Space(1) } }, nl,
+ m_curl, nl,
+ }, Column { m_add, m_edit, m_remove, Stretch() },
+ }.attachTo(this);
+
+ connect(m_edit, &QPushButton::clicked, this, &GitLabOptionsWidget::showEditServerDialog);
+ connect(m_remove, &QPushButton::clicked, this, &GitLabOptionsWidget::removeCurrentTriggered);
+ connect(m_add, &QPushButton::clicked, this, &GitLabOptionsWidget::showAddServerDialog);
+ connect(m_defaultGitLabServer, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, [this]() {
+ m_gitLabServerWidget->setGitLabServer(
+ m_defaultGitLabServer->currentData().value<GitLabServer>());
+ });
+}
+
+GitLabParameters GitLabOptionsWidget::parameters() const
+{
+ GitLabParameters result;
+ // get all configured gitlabservers
+ for (int i = 0, end = m_defaultGitLabServer->count(); i < end; ++i)
+ result.gitLabServers.append(m_defaultGitLabServer->itemData(i).value<GitLabServer>());
+ if (m_defaultGitLabServer->count())
+ result.defaultGitLabServer = m_defaultGitLabServer->currentData().value<GitLabServer>().id;
+ result.curl = m_curl.filePath();
+ return result;
+}
+
+void GitLabOptionsWidget::setParameters(const GitLabParameters &params)
+{
+ m_curl.setFilePath(params.curl);
+
+ for (const auto &gitLabServer : params.gitLabServers) {
+ m_defaultGitLabServer->addItem(gitLabServer.displayString(),
+ QVariant::fromValue(gitLabServer));
+ }
+
+ const GitLabServer found = params.currentDefaultServer();
+ if (found.id.isValid()) {
+ m_defaultGitLabServer->setCurrentIndex(m_defaultGitLabServer->findData(
+ QVariant::fromValue(found)));
+ }
+ updateButtonsState();
+}
+
+void GitLabOptionsWidget::showEditServerDialog()
+{
+ const GitLabServer old = m_defaultGitLabServer->currentData().value<GitLabServer>();
+ QDialog d;
+ d.setWindowTitle(tr("Edit Server..."));
+ QVBoxLayout *layout = new QVBoxLayout;
+ GitLabServerWidget *serverWidget = new GitLabServerWidget(GitLabServerWidget::Edit, this);
+ serverWidget->setGitLabServer(old);
+ layout->addWidget(serverWidget);
+ auto buttons = new QDialogButtonBox(QDialogButtonBox::Cancel, this);
+ auto modifyButton = buttons->addButton(tr("Modify"), QDialogButtonBox::AcceptRole);
+ connect(modifyButton, &QPushButton::clicked, &d, &QDialog::accept);
+ connect(buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked, &d, &QDialog::reject);
+ layout->addWidget(buttons);
+ d.setLayout(layout);
+ d.resize(300, 200);
+ if (d.exec() != QDialog::Accepted)
+ return;
+
+ const GitLabServer server = serverWidget->gitLabServer();
+ if (server != old && hostValid(server.host))
+ modifyCurrentServer(server);
+}
+
+void GitLabOptionsWidget::showAddServerDialog()
+{
+ QDialog d;
+ d.setWindowTitle(tr("Add Server..."));
+ QVBoxLayout *layout = new QVBoxLayout;
+ GitLabServerWidget *serverWidget = new GitLabServerWidget(GitLabServerWidget::Edit, this);
+ layout->addWidget(serverWidget);
+ auto buttons = new QDialogButtonBox(QDialogButtonBox::Cancel, this);
+ auto addButton = buttons->addButton(tr("Add"), QDialogButtonBox::AcceptRole);
+ connect(addButton, &QPushButton::clicked, &d, &QDialog::accept);
+ connect(buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked, &d, &QDialog::reject);
+ layout->addWidget(buttons);
+ d.setLayout(layout);
+ d.resize(300, 200);
+ if (d.exec() != QDialog::Accepted)
+ return;
+
+ const GitLabServer server = serverWidget->gitLabServer();
+ if (hostValid(server.host))
+ addServer(server);
+}
+
+void GitLabOptionsWidget::removeCurrentTriggered()
+{
+ int current = m_defaultGitLabServer->currentIndex();
+ if (current > -1)
+ m_defaultGitLabServer->removeItem(current);
+ updateButtonsState();
+}
+
+void GitLabOptionsWidget::addServer(const GitLabServer &newServer)
+{
+ QTC_ASSERT(newServer.id.isValid(), return);
+ const QVariant variant = QVariant::fromValue(newServer);
+ m_defaultGitLabServer->addItem(newServer.displayString(), variant);
+ int index = m_defaultGitLabServer->findData(variant);
+ m_defaultGitLabServer->setCurrentIndex(index);
+ m_gitLabServerWidget->setGitLabServer(newServer);
+ updateButtonsState();
+}
+
+void GitLabOptionsWidget::modifyCurrentServer(const GitLabServer &newServer)
+{
+ int current = m_defaultGitLabServer->currentIndex();
+ if (current > -1)
+ m_defaultGitLabServer->setItemData(current, newServer.displayString(), Qt::DisplayRole);
+ m_defaultGitLabServer->setItemData(current, QVariant::fromValue(newServer));
+ m_gitLabServerWidget->setGitLabServer(newServer);
+}
+
+void GitLabOptionsWidget::updateButtonsState()
+{
+ const bool hasItems = m_defaultGitLabServer->count() > 0;
+ m_edit->setEnabled(hasItems);
+ m_remove->setEnabled(hasItems);
+}
+
+GitLabOptionsPage::GitLabOptionsPage(GitLabParameters *p, QObject *parent)
+ : Core::IOptionsPage{parent}
+ , m_parameters(p)
+{
+ setId(Constants::GITLAB_SETTINGS);
+ setDisplayName(tr("GitLab"));
+ setCategory(VcsBase::Constants::VCS_SETTINGS_CATEGORY);
+}
+
+QWidget *GitLabOptionsPage::widget()
+{
+ if (!m_widget) {
+ m_widget = new GitLabOptionsWidget;
+ m_widget->setParameters(*m_parameters);
+ }
+ return m_widget;
+}
+
+void GitLabOptionsPage::apply()
+{
+ if (GitLabOptionsWidget *w = m_widget.data()) {
+ GitLabParameters newParameters = w->parameters();
+ if (newParameters != *m_parameters) {
+ *m_parameters = newParameters;
+ m_parameters->toSettings(Core::ICore::settings());
+ emit settingsChanged();
+ }
+ }
+}
+
+void GitLabOptionsPage::finish()
+{
+ delete m_widget;
+}
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlaboptionspage.h b/src/plugins/gitlab/gitlaboptionspage.h
new file mode 100644
index 00000000000..3992d7228bc
--- /dev/null
+++ b/src/plugins/gitlab/gitlaboptionspage.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "gitlabparameters.h"
+
+#include <coreplugin/dialogs/ioptionspage.h>
+#include <utils/aspects.h>
+
+#include <QPointer>
+#include <QSpinBox>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+class QPushButton;
+QT_END_NAMESPACE
+
+namespace GitLab {
+
+namespace Constants {
+const char GITLAB_SETTINGS[] = "GitLab";
+} // namespace Constants
+
+class GitLabServerWidget : public QWidget
+{
+public:
+ enum Mode { Display, Edit };
+ explicit GitLabServerWidget(Mode m, QWidget *parent = nullptr);
+
+ GitLabServer gitLabServer() const;
+ void setGitLabServer(const GitLabServer &server);
+
+ bool isValid() const;
+private:
+ Mode m_mode = Display;
+ Utils::Id m_id;
+ Utils::StringAspect m_host;
+ Utils::StringAspect m_description;
+ Utils::StringAspect m_token;
+ QSpinBox m_port;
+ Utils::BoolAspect m_secure;
+};
+
+class GitLabOptionsWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit GitLabOptionsWidget(QWidget *parent = nullptr);
+
+ GitLabParameters parameters() const;
+ void setParameters(const GitLabParameters &params);
+
+private:
+ void showEditServerDialog();
+ void showAddServerDialog();
+ void removeCurrentTriggered();
+ void addServer(const GitLabServer &newServer);
+ void modifyCurrentServer(const GitLabServer &newServer);
+ void updateButtonsState();
+
+ GitLabServerWidget *m_gitLabServerWidget = nullptr;
+ QPushButton *m_edit = nullptr;
+ QPushButton *m_remove = nullptr;
+ QPushButton *m_add = nullptr;
+ QComboBox *m_defaultGitLabServer = nullptr;
+ Utils::StringAspect m_curl;
+};
+
+class GitLabOptionsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+public:
+ explicit GitLabOptionsPage(GitLabParameters *p, QObject *parent = nullptr);
+
+ QWidget *widget() final;
+ void apply() final;
+ void finish() final;
+
+signals:
+ void settingsChanged();
+
+private:
+ void addServer();
+
+ GitLabParameters *m_parameters;
+ QPointer<GitLabOptionsWidget> m_widget;
+};
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabparameters.cpp b/src/plugins/gitlab/gitlabparameters.cpp
new file mode 100644
index 00000000000..3e96c0b8f23
--- /dev/null
+++ b/src/plugins/gitlab/gitlabparameters.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gitlabparameters.h"
+
+#include <utils/algorithm.h>
+#include <utils/hostosinfo.h>
+
+#include <QFile>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QSettings>
+#include <QStandardPaths>
+
+namespace GitLab {
+
+const char settingsGroupC[] = "GitLab";
+const char curlKeyC[] = "Curl";
+const char defaultUuidKeyC[] = "DefaultUuid";
+
+GitLabServer::GitLabServer()
+{
+}
+
+GitLabServer::GitLabServer(const Utils::Id &id, const QString &host, const QString &description,
+ const QString &token, unsigned short port, bool secure)
+ : id(id)
+ , host(host)
+ , description(description)
+ , token(token)
+ , port(port)
+ , secure(secure)
+{
+}
+
+bool GitLabServer::operator==(const GitLabServer &other) const
+{
+ if (port && other.port && port != other.port)
+ return false;
+ return secure == other.secure && id == other.id && host == other.host
+ && description == other.description && token == other.token ;
+}
+
+bool GitLabServer::operator!=(const GitLabServer &other) const
+{
+ return !(*this == other);
+}
+
+QJsonObject GitLabServer::toJson() const
+{
+ QJsonObject result;
+ result.insert("id", id.toString());
+ result.insert("host", host);
+ result.insert("description", description);
+ result.insert("port", port);
+ result.insert("token", token);
+ result.insert("secure", secure);
+ return result;
+}
+
+GitLabServer GitLabServer::fromJson(const QJsonObject &json)
+{
+ GitLabServer invalid{Utils::Id(), "", "", "", 0, true};
+ const QJsonValue id = json.value("id");
+ if (id == QJsonValue::Undefined)
+ return invalid;
+ const QJsonValue host = json.value("host");
+ if (host == QJsonValue::Undefined)
+ return invalid;
+ const QJsonValue description = json.value("description");
+ if (description == QJsonValue::Undefined)
+ return invalid;
+ const QJsonValue token = json.value("token");
+ if (token == QJsonValue::Undefined)
+ return invalid;
+ const QJsonValue port = json.value("port");
+ if (port == QJsonValue::Undefined)
+ return invalid;
+ const bool secure = json.value("secure").toBool(true);
+ return {Utils::Id::fromString(id.toString()), host.toString(), description.toString(),
+ token.toString(), (unsigned short)port.toInt(), secure};
+}
+
+QStringList GitLabServer::curlArguments() const
+{
+ // credentials from .netrc (?), no progress
+ QStringList args = { "-nsS" };
+ if (secure && !validateCert)
+ args << "-k";
+ return args;
+}
+
+QString GitLabServer::displayString() const
+{
+ if (!description.isEmpty())
+ return host + " (" + description + ')';
+ return host;
+}
+
+GitLabParameters::GitLabParameters()
+{
+}
+
+bool GitLabParameters::equals(const GitLabParameters &other) const
+{
+ return curl == other.curl && defaultGitLabServer == other.defaultGitLabServer
+ && gitLabServers == other.gitLabServers;
+}
+
+bool GitLabParameters::isValid() const
+{
+ const GitLabServer found = currentDefaultServer();
+ return found.id.isValid() && !found.host.isEmpty() && curl.isExecutableFile() ;
+}
+
+static void writeTokensFile(const Utils::FilePath &filePath, const QList<GitLabServer> &servers)
+{
+ QJsonDocument doc;
+ QJsonArray array;
+ for (const GitLabServer &server : servers)
+ array.append(server.toJson());
+ doc.setArray(array);
+ filePath.writeFileContents(doc.toJson());
+ filePath.setPermissions(QFile::ReadUser | QFile::WriteUser);
+}
+
+static QList<GitLabServer> readTokensFile(const Utils::FilePath &filePath)
+{
+ if (!filePath.exists())
+ return {};
+ const QByteArray content = filePath.fileContents();
+ const QJsonDocument doc = QJsonDocument::fromJson(content);
+ if (!doc.isArray())
+ return {};
+
+ QList<GitLabServer> result;
+ const QJsonArray array = doc.array();
+ for (const auto &it : array) {
+ if (it.isObject())
+ result.append(GitLabServer::fromJson(it.toObject()));
+ }
+ return result;
+}
+
+static Utils::FilePath tokensFilePath(const QSettings *s)
+{
+ return Utils::FilePath::fromString(s->fileName()).parentDir()
+ .pathAppended("/qtcreator/gitlabtokens.json");
+}
+
+void GitLabParameters::toSettings(QSettings *s) const
+{
+
+ writeTokensFile(tokensFilePath(s), gitLabServers);
+ s->beginGroup(settingsGroupC);
+ s->setValue(curlKeyC, curl.toVariant());
+ s->setValue(defaultUuidKeyC, defaultGitLabServer.toSetting());
+ s->endGroup();
+}
+
+void GitLabParameters::fromSettings(const QSettings *s)
+{
+ const QString rootKey = QLatin1String(settingsGroupC) + '/';
+ curl = Utils::FilePath::fromVariant(s->value(rootKey + curlKeyC));
+ defaultGitLabServer = Utils::Id::fromSetting(s->value(rootKey + defaultUuidKeyC));
+
+ gitLabServers = readTokensFile(tokensFilePath(s));
+
+ if (gitLabServers.isEmpty())
+ defaultGitLabServer = Utils::Id();
+
+ if (curl.isEmpty() || !curl.exists()) {
+ const QString curlPath = QStandardPaths::findExecutable(
+ Utils::HostOsInfo::withExecutableSuffix("curl"));
+ if (!curlPath.isEmpty())
+ curl = Utils::FilePath::fromString(curlPath);
+ }
+}
+
+GitLabServer GitLabParameters::currentDefaultServer() const
+{
+ return serverForId(defaultGitLabServer);
+}
+
+GitLabServer GitLabParameters::serverForId(const Utils::Id &id) const
+{
+ return Utils::findOrDefault(gitLabServers, [id](const GitLabServer &s) {
+ return id == s.id;
+ });
+}
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabparameters.h b/src/plugins/gitlab/gitlabparameters.h
new file mode 100644
index 00000000000..1fb3b02a7f4
--- /dev/null
+++ b/src/plugins/gitlab/gitlabparameters.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/filepath.h>
+#include <utils/id.h>
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+class QJsonObject;
+QT_END_NAMESPACE
+
+namespace GitLab {
+
+class GitLabServer
+{
+public:
+ enum { defaultPort = 443 };
+
+ GitLabServer(); // TODO different protocol handling e.g. for clone / push?
+ GitLabServer(const Utils::Id &id, const QString &host, const QString &description,
+ const QString &token, unsigned short port, bool secure);
+ bool operator==(const GitLabServer &other) const;
+ bool operator!=(const GitLabServer &other) const;
+ QJsonObject toJson() const;
+ static GitLabServer fromJson(const QJsonObject &json);
+ QStringList curlArguments() const;
+ QString displayString() const;
+
+ Utils::Id id;
+ QString host;
+ QString description;
+ QString token;
+ unsigned short port = 0;
+
+ bool secure = true;
+ bool validateCert = true;
+};
+
+class GitLabParameters
+{
+public:
+ GitLabParameters();
+
+ bool equals(const GitLabParameters &other) const;
+ bool isValid() const;
+
+ void toSettings(QSettings *s) const;
+ void fromSettings(const QSettings *s);
+
+ GitLabServer currentDefaultServer() const;
+ GitLabServer serverForId(const Utils::Id &id) const;
+
+ friend bool operator==(const GitLabParameters &p1, const GitLabParameters &p2)
+ {
+ return p1.equals(p2);
+ }
+ friend bool operator!=(const GitLabParameters &p1, const GitLabParameters &p2)
+ {
+ return !p1.equals(p2);
+ }
+
+ Utils::Id defaultGitLabServer;
+ QList<GitLabServer> gitLabServers;
+ Utils::FilePath curl;
+};
+
+} // namespace GitLab
+
+Q_DECLARE_METATYPE(GitLab::GitLabServer)
diff --git a/src/plugins/gitlab/gitlabplugin.cpp b/src/plugins/gitlab/gitlabplugin.cpp
new file mode 100644
index 00000000000..7b5f8809665
--- /dev/null
+++ b/src/plugins/gitlab/gitlabplugin.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gitlabplugin.h"
+
+#include "gitlabdialog.h"
+#include "gitlaboptionspage.h"
+#include "gitlabparameters.h"
+#include "gitlabprojectsettings.h"
+#include "queryrunner.h"
+#include "resultparser.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/icore.h>
+#include <git/gitplugin.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectpanelfactory.h>
+#include <projectexplorer/session.h>
+#include <utils/qtcassert.h>
+#include <vcsbase/vcsoutputwindow.h>
+
+#include <QAction>
+#include <QMessageBox>
+#include <QPointer>
+#include <QTimer>
+
+namespace GitLab {
+namespace Constants {
+const char GITLAB_OPEN_VIEW[] = "GitLab.OpenView";
+} // namespace Constants
+
+class GitLabPluginPrivate : public QObject
+{
+public:
+ GitLabParameters parameters;
+ GitLabOptionsPage optionsPage{&parameters};
+ QHash<ProjectExplorer::Project *, GitLabProjectSettings *> projectSettings;
+ QPointer<GitLabDialog> dialog;
+
+ QTimer notificationTimer;
+ QString projectName;
+ Utils::Id serverId;
+ bool runningQuery = false;
+
+ void setupNotificationTimer();
+ void fetchEvents();
+ void fetchUser();
+ void createAndSendEventsRequest(const QDateTime timeStamp, int page = -1);
+ void handleUser(const User &user);
+ void handleEvents(const Events &events, const QDateTime &timeStamp);
+};
+
+static GitLabPluginPrivate *dd = nullptr;
+
+GitLabPlugin::GitLabPlugin()
+{
+}
+
+GitLabPlugin::~GitLabPlugin()
+{
+ if (!dd->projectSettings.isEmpty()) {
+ qDeleteAll(dd->projectSettings);
+ dd->projectSettings.clear();
+ }
+ delete dd;
+ dd = nullptr;
+}
+
+bool GitLabPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorString*/)
+{
+ dd = new GitLabPluginPrivate;
+ dd->parameters.fromSettings(Core::ICore::settings());
+ auto panelFactory = new ProjectExplorer::ProjectPanelFactory;
+ panelFactory->setPriority(999);
+ panelFactory->setDisplayName(tr("GitLab"));
+ panelFactory->setCreateWidgetFunction([](ProjectExplorer::Project *project) {
+ return new GitLabProjectSettingsWidget(project);
+ });
+ ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
+ QAction *openViewAction = new QAction(tr("GitLab..."), this);
+ auto gitlabCommand = Core::ActionManager::registerAction(openViewAction,
+ Constants::GITLAB_OPEN_VIEW);
+ connect(openViewAction, &QAction::triggered, this, &GitLabPlugin::openView);
+ Core::ActionContainer *ac = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
+ ac->addAction(gitlabCommand);
+ connect(&dd->optionsPage, &GitLabOptionsPage::settingsChanged, this, [] {
+ if (dd->dialog)
+ dd->dialog->updateRemotes();
+ });
+ connect(ProjectExplorer::SessionManager::instance(),
+ &ProjectExplorer::SessionManager::startupProjectChanged,
+ this, &GitLabPlugin::onStartupProjectChanged);
+ return true;
+}
+
+void GitLabPlugin::openView()
+{
+ if (dd->dialog.isNull()) {
+ while (!dd->parameters.isValid()) {
+ QMessageBox::warning(Core::ICore::dialogParent(), tr("Error"),
+ tr("Invalid GitLab configuration. For a fully functional "
+ "configuration, you need to set up host name or address and "
+ "an access token. Providing the path to curl is mandatory."));
+ if (!Core::ICore::showOptionsDialog("GitLab"))
+ return;
+ }
+ GitLabDialog *gitlabD = new GitLabDialog(Core::ICore::dialogParent());
+ gitlabD->setModal(true);
+ Core::ICore::registerWindow(gitlabD, Core::Context("Git.GitLab"));
+ dd->dialog = gitlabD;
+ }
+ const Qt::WindowStates state = dd->dialog->windowState();
+ if (state & Qt::WindowMinimized)
+ dd->dialog->setWindowState(state & ~Qt::WindowMinimized);
+ dd->dialog->show();
+ dd->dialog->raise();
+}
+
+void GitLabPlugin::onStartupProjectChanged()
+{
+ QTC_ASSERT(dd, return);
+ disconnect(&dd->notificationTimer);
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ if (!project) {
+ dd->notificationTimer.stop();
+ return;
+ }
+
+ const GitLabProjectSettings *projSettings = projectSettings(project);
+ if (!projSettings->isLinked()) {
+ dd->notificationTimer.stop();
+ return;
+ }
+
+ dd->fetchEvents();
+ dd->setupNotificationTimer();
+}
+
+void GitLabPluginPrivate::setupNotificationTimer()
+{
+ // make interval configurable?
+ notificationTimer.setInterval(15 * 60 * 1000);
+ QObject::connect(&notificationTimer, &QTimer::timeout, this, &GitLabPluginPrivate::fetchEvents);
+ notificationTimer.start();
+}
+
+void GitLabPluginPrivate::fetchEvents()
+{
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ QTC_ASSERT(project, return);
+
+ if (runningQuery)
+ return;
+
+ const GitLabProjectSettings *projSettings = GitLabPlugin::projectSettings(project);
+ projectName = projSettings->currentProject();
+ serverId = projSettings->currentServer();
+
+ const QDateTime lastRequest = projSettings->lastRequest();
+ if (!lastRequest.isValid()) { // we haven't queried events for this project yet
+ fetchUser();
+ return;
+ }
+ createAndSendEventsRequest(lastRequest);
+}
+
+void GitLabPluginPrivate::fetchUser()
+{
+ if (runningQuery)
+ return;
+
+ const Query query(Query::User);
+ QueryRunner *runner = new QueryRunner(query, serverId, this);
+ QObject::connect(runner, &QueryRunner::resultRetrieved, this, [this](const QByteArray &result) {
+ handleUser(ResultParser::parseUser(result));
+ });
+ QObject::connect(runner, &QueryRunner::finished, [runner]() { runner->deleteLater(); });
+ runningQuery = true;
+ runner->start();
+}
+
+void GitLabPluginPrivate::createAndSendEventsRequest(const QDateTime timeStamp, int page)
+{
+ if (runningQuery)
+ return;
+
+ Query query(Query::Events, {projectName});
+ QStringList additional = {"sort=asc"};
+
+ QDateTime after = timeStamp.addDays(-1);
+ additional.append(QLatin1String("after=%1").arg(after.toString("yyyy-MM-dd")));
+ query.setAdditionalParameters(additional);
+
+ if (page > 1)
+ query.setPageParameter(page);
+
+ QueryRunner *runner = new QueryRunner(query, serverId, this);
+ QObject::connect(runner, &QueryRunner::resultRetrieved, this,
+ [this, timeStamp](const QByteArray &result) {
+ handleEvents(ResultParser::parseEvents(result), timeStamp);
+ });
+ QObject::connect(runner, &QueryRunner::finished, [runner]() { runner->deleteLater(); });
+ runningQuery = true;
+ runner->start();
+}
+
+void GitLabPluginPrivate::handleUser(const User &user)
+{
+ runningQuery = false;
+
+ QTC_ASSERT(user.error.message.isEmpty(), return);
+ const QDateTime timeStamp = QDateTime::fromString(user.lastLogin, Qt::ISODateWithMs);
+ createAndSendEventsRequest(timeStamp);
+}
+
+void GitLabPluginPrivate::handleEvents(const Events &events, const QDateTime &timeStamp)
+{
+ runningQuery = false;
+
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ QTC_ASSERT(project, return);
+
+ GitLabProjectSettings *projSettings = GitLabPlugin::projectSettings(project);
+ QTC_ASSERT(projSettings->currentProject() == projectName, return);
+
+ if (!projSettings->isLinked()) // link state has changed meanwhile - ignore the request
+ return;
+
+ if (!events.error.message.isEmpty()) {
+ VcsBase::VcsOutputWindow::appendError("GitLab: Error while fetching events. "
+ + events.error.message + '\n');
+ return;
+ }
+
+ QDateTime lastTimeStamp;
+ for (const Event &event : events.events) {
+ const QDateTime eventTimeStamp = QDateTime::fromString(event.timeStamp, Qt::ISODateWithMs);
+ if (!timeStamp.isValid() || timeStamp < eventTimeStamp) {
+ VcsBase::VcsOutputWindow::appendMessage("GitLab: " + event.toMessage());
+ if (!lastTimeStamp.isValid() || lastTimeStamp < eventTimeStamp)
+ lastTimeStamp = eventTimeStamp;
+ }
+ }
+ if (lastTimeStamp.isValid()) {
+ if (auto outputWindow = VcsBase::VcsOutputWindow::instance())
+ outputWindow->flash();
+ projSettings->setLastRequest(lastTimeStamp);
+ }
+
+ if (events.pageInfo.currentPage < events.pageInfo.totalPages)
+ createAndSendEventsRequest(timeStamp, events.pageInfo.currentPage + 1);
+}
+
+QList<GitLabServer> GitLabPlugin::allGitLabServers()
+{
+ QTC_ASSERT(dd, return {});
+ return dd->parameters.gitLabServers;
+}
+
+GitLabServer GitLabPlugin::gitLabServerForId(const Utils::Id &id)
+{
+ QTC_ASSERT(dd, return {});
+ return dd->parameters.serverForId(id);
+}
+
+GitLabParameters *GitLabPlugin::globalParameters()
+{
+ return &dd->parameters;
+}
+
+GitLabProjectSettings *GitLabPlugin::projectSettings(ProjectExplorer::Project *project)
+{
+ QTC_ASSERT(project, return nullptr);
+ QTC_ASSERT(dd, return nullptr);
+ auto &settings = dd->projectSettings[project];
+ if (!settings)
+ settings = new GitLabProjectSettings(project);
+ return settings;
+}
+
+GitLabOptionsPage *GitLabPlugin::optionsPage()
+{
+ QTC_ASSERT(dd, return {});
+ return &dd->optionsPage;
+}
+
+bool GitLabPlugin::handleCertificateIssue(const Utils::Id &serverId)
+{
+ QTC_ASSERT(dd, return false);
+
+ GitLabServer server = dd->parameters.serverForId(serverId);
+ if (QMessageBox::question(Core::ICore::dialogParent(),
+ QCoreApplication::translate(
+ "GitLab::GitLabDialog", "Certificate Error"),
+ QCoreApplication::translate(
+ "GitLab::GitLabDialog",
+ "Server certificate for %1 cannot be authenticated.\n"
+ "Do you want to disable SSL verification for this server?\n"
+ "Note: This can expose you to man-in-the-middle attack.")
+ .arg(server.host))
+ == QMessageBox::Yes) {
+ int index = dd->parameters.gitLabServers.indexOf(server);
+ server.validateCert = false;
+ dd->parameters.gitLabServers.replace(index, server);
+ emit dd->optionsPage.settingsChanged();
+ return true;
+ }
+ return false;
+}
+
+void GitLabPlugin::linkedStateChanged(bool enabled)
+{
+ QTC_ASSERT(dd, return);
+
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ if (project) {
+ const GitLabProjectSettings *pSettings = projectSettings(project);
+ dd->serverId = pSettings->currentServer();
+ dd->projectName = pSettings->currentProject();
+ } else {
+ dd->serverId = Utils::Id();
+ dd->projectName = QString();
+ }
+
+ if (enabled) {
+ dd->fetchEvents();
+ dd->setupNotificationTimer();
+ } else {
+ QObject::disconnect(&dd->notificationTimer, &QTimer::timeout,
+ dd, &GitLabPluginPrivate::fetchEvents);
+ dd->notificationTimer.stop();
+ }
+}
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabplugin.h b/src/plugins/gitlab/gitlabplugin.h
new file mode 100644
index 00000000000..7ff7a567c8d
--- /dev/null
+++ b/src/plugins/gitlab/gitlabplugin.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "gitlabparameters.h"
+
+#include <extensionsystem/iplugin.h>
+
+namespace ProjectExplorer { class Project; }
+
+namespace GitLab {
+
+class Events;
+class GitLabProjectSettings;
+class GitLabOptionsPage;
+
+class GitLabPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "GitLab.json")
+
+public:
+ GitLabPlugin();
+ ~GitLabPlugin() override;
+
+ bool initialize(const QStringList &arguments, QString *errorString) override;
+
+ static QList<GitLabServer> allGitLabServers();
+ static GitLabServer gitLabServerForId(const Utils::Id &id);
+ static GitLabParameters *globalParameters();
+ static GitLabProjectSettings *projectSettings(ProjectExplorer::Project *project);
+ static GitLabOptionsPage *optionsPage();
+ static bool handleCertificateIssue(const Utils::Id &serverId);
+
+ static void linkedStateChanged(bool enabled);
+private:
+ void openView();
+ void onStartupProjectChanged();
+};
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabprojectsettings.cpp b/src/plugins/gitlab/gitlabprojectsettings.cpp
new file mode 100644
index 00000000000..519073b8dd6
--- /dev/null
+++ b/src/plugins/gitlab/gitlabprojectsettings.cpp
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gitlabprojectsettings.h"
+
+#include "gitlaboptionspage.h"
+#include "gitlabplugin.h"
+#include "queryrunner.h"
+#include "resultparser.h"
+
+#include <git/gitclient.h>
+#include <projectexplorer/project.h>
+#include <utils/infolabel.h>
+#include <utils/qtcassert.h>
+
+#include <QComboBox>
+#include <QFormLayout>
+#include <QHBoxLayout>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QUrl>
+#include <QVBoxLayout>
+#include <QVariant>
+
+namespace GitLab {
+
+const char PSK_LINKED_ID[] = "GitLab.LinkedId";
+const char PSK_SERVER[] = "GitLab.Server";
+const char PSK_PROJECT[] = "GitLab.Project";
+const char PSK_LAST_REQ[] = "GitLab.LastRequest";
+
+static QString accessLevelString(int accessLevel)
+{
+ const char trContext[] = "GitLab::GitLabProjectSettingsWidget";
+ switch (accessLevel) {
+ case 10: return QCoreApplication::translate(trContext, "Guest");
+ case 20: return QCoreApplication::translate(trContext, "Reporter");
+ case 30: return QCoreApplication::translate(trContext, "Developer");
+ case 40: return QCoreApplication::translate(trContext, "Maintainer");
+ case 50: return QCoreApplication::translate(trContext, "Owner");
+ }
+ return {};
+}
+
+std::tuple<QString, QString, int>
+GitLabProjectSettings::remotePartsFromRemote(const QString &remote)
+{
+ QString host;
+ QString path;
+ int port = -1;
+ if (remote.startsWith("git@")) {
+ int colon = remote.indexOf(':');
+ host = remote.mid(4, colon - 4);
+ path = remote.mid(colon + 1);
+ } else {
+ const QUrl url(remote);
+ host = url.host();
+ path = url.path().mid(1); // ignore leading slash
+ port = url.port();
+ }
+ if (path.endsWith(".git"))
+ path.chop(4);
+
+ return std::make_tuple(host, path, port);
+}
+
+GitLabProjectSettings::GitLabProjectSettings(ProjectExplorer::Project *project)
+ : m_project(project)
+{
+ load();
+ connect(project, &ProjectExplorer::Project::settingsLoaded,
+ this, &GitLabProjectSettings::load);
+ connect(project, &ProjectExplorer::Project::aboutToSaveSettings,
+ this, &GitLabProjectSettings::save);
+}
+
+void GitLabProjectSettings::setLinked(bool linked)
+{
+ m_linked = linked;
+ save();
+}
+
+void GitLabProjectSettings::load()
+{
+ m_id = Utils::Id::fromSetting(m_project->namedSettings(PSK_LINKED_ID));
+ m_host = m_project->namedSettings(PSK_SERVER).toString();
+ m_currentProject = m_project->namedSettings(PSK_PROJECT).toString();
+ m_lastRequest = m_project->namedSettings(PSK_LAST_REQ).toDateTime();
+
+ // may still be wrong, but we avoid an additional request by just doing sanity check here
+ if (!m_id.isValid() || m_host.isEmpty())
+ m_linked = false;
+ else
+ m_linked = GitLabPlugin::globalParameters()->serverForId(m_id).id.isValid();
+}
+
+void GitLabProjectSettings::save()
+{
+ if (m_linked) {
+ m_project->setNamedSettings(PSK_LINKED_ID, m_id.toSetting());
+ m_project->setNamedSettings(PSK_SERVER, m_host);
+ } else {
+ m_project->setNamedSettings(PSK_LINKED_ID, Utils::Id().toSetting());
+ m_project->setNamedSettings(PSK_SERVER, QString());
+ }
+ m_project->setNamedSettings(PSK_PROJECT, m_currentProject);
+ m_project->setNamedSettings(PSK_LAST_REQ, m_lastRequest);
+}
+
+GitLabProjectSettingsWidget::GitLabProjectSettingsWidget(ProjectExplorer::Project *project,
+ QWidget *parent)
+ : ProjectExplorer::ProjectSettingsWidget(parent)
+ , m_projectSettings(GitLabPlugin::projectSettings(project))
+{
+ setUseGlobalSettingsCheckBoxVisible(false);
+ setUseGlobalSettingsLabelVisible(true);
+ setGlobalSettingsId(Constants::GITLAB_SETTINGS);
+ // setup ui
+ auto verticalLayout = new QVBoxLayout(this);
+ verticalLayout->setContentsMargins(0, 0, 0, 0);
+ auto formLayout = new QFormLayout;
+ m_hostCB = new QComboBox;
+ formLayout->addRow(tr("Host:"), m_hostCB);
+ m_linkedGitLabServer = new QComboBox;
+ formLayout->addRow(tr("Linked GitLab Configuration:"), m_linkedGitLabServer);
+ verticalLayout->addLayout(formLayout);
+ m_infoLabel = new Utils::InfoLabel;
+ m_infoLabel->setVisible(false);
+ verticalLayout->addWidget(m_infoLabel);
+ auto horizontalLayout = new QHBoxLayout;
+ horizontalLayout->setContentsMargins(0, 0, 0, 0);
+ m_linkWithGitLab = new QPushButton(tr("Link with GitLab"));
+ horizontalLayout->addWidget(m_linkWithGitLab);
+ m_unlink = new QPushButton(tr("Unlink from GitLab"));
+ m_unlink->setEnabled(false);
+ horizontalLayout->addWidget(m_unlink);
+ m_checkConnection = new QPushButton(tr("Test Connection"));
+ m_checkConnection->setEnabled(false);
+ horizontalLayout->addWidget(m_checkConnection);
+ horizontalLayout->addStretch(1);
+ verticalLayout->addLayout(horizontalLayout);
+ verticalLayout->addWidget(new QLabel(tr("Projects linked with GitLab receive event "
+ "notifications in the Version Control output pane.")));
+
+ connect(m_linkWithGitLab, &QPushButton::clicked, this, [this]() {
+ checkConnection(Link);
+ });
+ connect(m_unlink, &QPushButton::clicked,
+ this, &GitLabProjectSettingsWidget::unlink);
+ connect(m_checkConnection, &QPushButton::clicked, this, [this]() {
+ checkConnection(Connection);
+ });
+ connect(m_linkedGitLabServer, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, [this]() {
+ m_infoLabel->setVisible(false);
+ });
+ connect(m_hostCB, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, [this]() {
+ m_infoLabel->setVisible(false);
+ });
+ connect(GitLabPlugin::optionsPage(), &GitLabOptionsPage::settingsChanged,
+ this, &GitLabProjectSettingsWidget::updateUi);
+ updateUi();
+}
+
+void GitLabProjectSettingsWidget::unlink()
+{
+ QTC_ASSERT(m_projectSettings->isLinked(), return);
+ m_projectSettings->setLinked(false);
+ m_projectSettings->setCurrentProject({});
+ updateEnabledStates();
+ GitLabPlugin::linkedStateChanged(false);
+}
+
+void GitLabProjectSettingsWidget::checkConnection(CheckMode mode)
+{
+ const GitLabServer server = m_linkedGitLabServer->currentData().value<GitLabServer>();
+ const QString remote = m_hostCB->currentData().toString();
+
+ const auto [remoteHost, projName, port] = GitLabProjectSettings::remotePartsFromRemote(remote);
+ if (remoteHost != server.host) { // port check as well
+ m_infoLabel->setType(Utils::InfoLabel::NotOk);
+ m_infoLabel->setText(tr("Remote host does not match chosen GitLab configuration."));
+ m_infoLabel->setVisible(true);
+ return;
+ }
+
+ // temporarily disable ui
+ m_linkedGitLabServer->setEnabled(false);
+ m_hostCB->setEnabled(false);
+ m_checkConnection->setEnabled(false);
+
+ m_checkMode = mode;
+ const Query query(Query::Project, {projName});
+ QueryRunner *runner = new QueryRunner(query, server.id, this);
+ // can't use server, projName as captures inside the lambda below (bindings vs. local vars) :/
+ const Utils::Id id = server.id;
+ const QString projectName = projName;
+ connect(runner, &QueryRunner::resultRetrieved, this,
+ [this, id, remote, projectName](const QByteArray &result) {
+ onConnectionChecked(ResultParser::parseProject(result), id, remote, projectName);
+ });
+ connect(runner, &QueryRunner::finished, this, [runner]() { runner->deleteLater(); });
+ runner->start();
+}
+
+void GitLabProjectSettingsWidget::onConnectionChecked(const Project &project,
+ const Utils::Id &serverId,
+ const QString &remote,
+ const QString &projectName)
+{
+ bool linkable = false;
+ if (!project.error.message.isEmpty()) {
+ m_infoLabel->setType(Utils::InfoLabel::Error);
+ m_infoLabel->setText(tr("Check settings for misconfiguration.")
+ + " (" + project.error.message + ')');
+ } else {
+ if (project.accessLevel != -1) {
+ m_infoLabel->setType(Utils::InfoLabel::Ok);
+ m_infoLabel->setText(tr("Accessible (%1)")
+ .arg(accessLevelString(project.accessLevel)));
+ linkable = true;
+ } else {
+ m_infoLabel->setType(Utils::InfoLabel::Warning);
+ m_infoLabel->setText(tr("Read only access"));
+ }
+ }
+ m_infoLabel->setVisible(true);
+
+ if (m_checkMode == Link && linkable) {
+ m_projectSettings->setCurrentServer(serverId);
+ m_projectSettings->setCurrentServerHost(remote);
+ m_projectSettings->setLinked(true);
+ m_projectSettings->setCurrentProject(projectName);
+ GitLabPlugin::linkedStateChanged(true);
+ }
+ updateEnabledStates();
+}
+
+void GitLabProjectSettingsWidget::updateUi()
+{
+ m_linkedGitLabServer->clear();
+ const QList<GitLabServer> allServers = GitLabPlugin::allGitLabServers();
+ for (const GitLabServer &server : allServers) {
+ const QString display = server.host + " (" + server.description + ')';
+ m_linkedGitLabServer->addItem(display, QVariant::fromValue(server));
+ }
+
+ const Utils::FilePath projectDirectory = m_projectSettings->project()->projectDirectory();
+ const auto *gitClient = Git::Internal::GitClient::instance();
+ const Utils::FilePath repository = gitClient
+ ? gitClient->findRepositoryForDirectory(projectDirectory) : Utils::FilePath();
+
+ m_hostCB->clear();
+ if (!repository.isEmpty()) {
+ const QMap<QString, QString> remotes = gitClient->synchronousRemotesList(repository);
+ for (auto it = remotes.begin(), end = remotes.end(); it != end; ++it) {
+ const QString display = it.key() + " (" + it.value() + ')';
+ m_hostCB->addItem(display, QVariant::fromValue(it.value()));
+ }
+ }
+
+ const Utils::Id id = m_projectSettings->currentServer();
+ const QString serverHost = m_projectSettings->currentServerHost();
+ if (id.isValid()) {
+ const GitLabServer server = GitLabPlugin::gitLabServerForId(id);
+ auto [remoteHost, projName, port] = GitLabProjectSettings::remotePartsFromRemote(serverHost);
+ if (server.id.isValid() && server.host == remoteHost) { // found config
+ m_projectSettings->setLinked(true);
+ m_hostCB->setCurrentIndex(m_hostCB->findData(QVariant::fromValue(serverHost)));
+ m_linkedGitLabServer->setCurrentIndex(
+ m_linkedGitLabServer->findData(QVariant::fromValue(server)));
+ GitLabPlugin::linkedStateChanged(true);
+ } else {
+ m_projectSettings->setLinked(false);
+ GitLabPlugin::linkedStateChanged(false);
+ }
+ }
+ updateEnabledStates();
+}
+
+void GitLabProjectSettingsWidget::updateEnabledStates()
+{
+ const bool isGitRepository = m_hostCB->count() > 0;
+ const bool hasGitLabServers = m_linkedGitLabServer->count();
+ const bool linked = m_projectSettings->isLinked();
+
+ m_linkedGitLabServer->setEnabled(isGitRepository && !linked);
+ m_hostCB->setEnabled(isGitRepository && !linked);
+ m_linkWithGitLab->setEnabled(isGitRepository && !linked && hasGitLabServers);
+ m_unlink->setEnabled(isGitRepository && linked);
+ m_checkConnection->setEnabled(isGitRepository && hasGitLabServers);
+ if (!isGitRepository) {
+ const Utils::FilePath projectDirectory = m_projectSettings->project()->projectDirectory();
+ const auto *gitClient = Git::Internal::GitClient::instance();
+ const Utils::FilePath repository = gitClient
+ ? gitClient->findRepositoryForDirectory(projectDirectory) : Utils::FilePath();
+ if (repository.isEmpty())
+ m_infoLabel->setText(tr("Not a git repository."));
+ else
+ m_infoLabel->setText(tr("Local git repository without remotes."));
+ m_infoLabel->setType(Utils::InfoLabel::None);
+ m_infoLabel->setVisible(true);
+ }
+}
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/gitlabprojectsettings.h b/src/plugins/gitlab/gitlabprojectsettings.h
new file mode 100644
index 00000000000..5a9081adc73
--- /dev/null
+++ b/src/plugins/gitlab/gitlabprojectsettings.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectexplorer/projectsettingswidget.h>
+#include <utils/id.h>
+
+#include <QDateTime>
+#include <QObject>
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+class QPushButton;
+QT_END_NAMESPACE
+
+#include <utility>
+
+namespace ProjectExplorer { class Project; }
+
+namespace Utils { class InfoLabel; }
+
+namespace GitLab {
+
+class Project;
+
+class GitLabProjectSettings : public QObject
+{
+ Q_OBJECT
+public:
+ explicit GitLabProjectSettings(ProjectExplorer::Project *project);
+ Utils::Id currentServer() const { return m_id; }
+ void setCurrentServer(const Utils::Id &id) { m_id = id; }
+ QString currentServerHost() const { return m_host; }
+ void setCurrentServerHost(const QString &server) { m_host = server; }
+ void setCurrentProject(const QString &projectName) { m_currentProject = projectName; }
+ QString currentProject() const { return m_currentProject; }
+ bool isLinked() const { return m_linked; }
+ void setLinked(bool linked);
+ QDateTime lastRequest() const { return m_lastRequest; }
+ void setLastRequest(const QDateTime &lastRequest) { m_lastRequest = lastRequest; }
+ ProjectExplorer::Project *project() const { return m_project; }
+
+ static std::tuple<QString, QString, int> remotePartsFromRemote(const QString &remote);
+
+private:
+ void load();
+ void save();
+
+ ProjectExplorer::Project *m_project = nullptr;
+ QString m_host;
+ Utils::Id m_id;
+ QDateTime m_lastRequest;
+ QString m_currentProject;
+ bool m_linked = false;
+};
+
+class GitLabProjectSettingsWidget : public ProjectExplorer::ProjectSettingsWidget
+{
+ Q_OBJECT
+public:
+ explicit GitLabProjectSettingsWidget(ProjectExplorer::Project *project,
+ QWidget *parent = nullptr);
+
+private:
+ enum CheckMode { Connection, Link };
+
+ void unlink();
+ void checkConnection(CheckMode mode);
+ void onConnectionChecked(const Project &project, const Utils::Id &serverId,
+ const QString &remote, const QString &projName);
+ void updateUi();
+ void updateEnabledStates();
+
+ GitLabProjectSettings *m_projectSettings = nullptr;
+ QComboBox *m_linkedGitLabServer = nullptr;
+ QComboBox *m_hostCB = nullptr;
+ QPushButton *m_linkWithGitLab = nullptr;
+ QPushButton *m_unlink = nullptr;
+ QPushButton *m_checkConnection = nullptr;
+ Utils::InfoLabel *m_infoLabel = nullptr;
+ CheckMode m_checkMode = Connection;
+};
+
+} // namespace GitLab
+
diff --git a/src/plugins/gitlab/queryrunner.cpp b/src/plugins/gitlab/queryrunner.cpp
new file mode 100644
index 00000000000..55d1572bd32
--- /dev/null
+++ b/src/plugins/gitlab/queryrunner.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "queryrunner.h"
+
+#include "gitlabparameters.h"
+#include "gitlabplugin.h"
+
+#include <coreplugin/progressmanager/futureprogress.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <utils/algorithm.h>
+#include <utils/commandline.h>
+#include <utils/qtcassert.h>
+#include <vcsbase/vcsoutputwindow.h>
+
+#include <QUrl>
+
+using namespace Utils;
+
+namespace GitLab {
+
+const char API_PREFIX[] = "/api/v4";
+const char QUERY_PROJECT[] = "/projects/%1";
+const char QUERY_PROJECTS[] = "/projects?simple=true";
+const char QUERY_USER[] = "/user";
+const char QUERY_EVENTS[] = "/projects/%1/events";
+
+Query::Query(Type type, const QStringList &parameter)
+ : m_type(type)
+ , m_parameter(parameter)
+{
+}
+
+void Query::setPageParameter(int page)
+{
+ m_pageParameter = page;
+}
+
+void Query::setAdditionalParameters(const QStringList &additional)
+{
+ m_additionalParameters = additional;
+}
+
+bool Query::hasPaginatedResults() const
+{
+ return m_type == Query::Projects || m_type == Query::Events;
+}
+
+QString Query::toString() const
+{
+ QString query = API_PREFIX;
+ switch (m_type) {
+ case Query::NoQuery:
+ return QString();
+ case Query::Project:
+ QTC_ASSERT(!m_parameter.isEmpty(), return {});
+ query += QLatin1String(QUERY_PROJECT).arg(QLatin1String(
+ QUrl::toPercentEncoding(m_parameter.at(0))));
+ break;
+ case Query::Projects:
+ query += QLatin1String(QUERY_PROJECTS);
+ break;
+ case Query::User:
+ query += QUERY_USER;
+ break;
+ case Query::Events:
+ QTC_ASSERT(!m_parameter.isEmpty(), return {});
+ query += QLatin1String(QUERY_EVENTS).arg(QLatin1String(
+ QUrl::toPercentEncoding(m_parameter.at(0))));
+ break;
+ }
+ if (m_pageParameter > 0) {
+ query.append(m_type == Query::Projects ? '&' : '?');
+ query.append("page=").append(QString::number(m_pageParameter));
+ }
+ if (!m_additionalParameters.isEmpty()) {
+ query.append((m_type == Query::Projects || m_pageParameter > 0) ? '&' : '?');
+ query.append(m_additionalParameters.join('&'));
+ }
+ return query;
+}
+
+QueryRunner::QueryRunner(const Query &query, const Id &id, QObject *parent)
+ : QObject(parent)
+{
+ const GitLabParameters *p = GitLabPlugin::globalParameters();
+ const auto server = p->serverForId(id);
+ QStringList args = server.curlArguments();
+ if (query.hasPaginatedResults())
+ args << "-i";
+ if (!server.token.isEmpty())
+ args << "--header" << "PRIVATE-TOKEN: " + server.token;
+ QString url = (server.secure ? "https://" : "http://") + server.host;
+ if (server.port && (server.port != (server.secure ? GitLabServer::defaultPort : 80)))
+ url.append(':' + QString::number(server.port));
+ url += query.toString();
+ args << url;
+ m_process.setCommand({p->curl, args});
+ connect(&m_process, &QtcProcess::done, this, [this, id] {
+ if (m_process.result() != ProcessResult::FinishedWithSuccess) {
+ const int exitCode = m_process.exitCode();
+ if (m_process.exitStatus() == QProcess::NormalExit
+ && (exitCode == 35 || exitCode == 60) // common ssl certificate issues
+ && GitLabPlugin::handleCertificateIssue(id)) {
+ // prepend -k for re-requesting the same query
+ CommandLine cmdline = m_process.commandLine();
+ cmdline.prependArgs({"-k"});
+ m_process.setCommand(cmdline);
+ start();
+ return;
+ }
+ VcsBase::VcsOutputWindow::appendError(m_process.exitMessage());
+ } else {
+ emit resultRetrieved(m_process.readAllStandardOutput());
+ }
+ emit finished();
+ });
+}
+
+void QueryRunner::start()
+{
+ QTC_ASSERT(!m_process.isRunning(), return);
+ m_process.start();
+}
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/queryrunner.h b/src/plugins/gitlab/queryrunner.h
new file mode 100644
index 00000000000..a60eb470ac7
--- /dev/null
+++ b/src/plugins/gitlab/queryrunner.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/id.h>
+#include <utils/qtcprocess.h>
+
+#include <QObject>
+
+namespace GitLab {
+
+class Query
+{
+public:
+ enum Type {
+ NoQuery,
+ User,
+ Project,
+ Projects,
+ Events
+ };
+
+ explicit Query(Type type, const QStringList &parameters = {});
+ void setPageParameter(int page);
+ void setAdditionalParameters(const QStringList &additional);
+ bool hasPaginatedResults() const;
+ Type type() const { return m_type; }
+ QString toString() const;
+
+private:
+ Type m_type = NoQuery;
+ QStringList m_parameter;
+ QStringList m_additionalParameters;
+ int m_pageParameter = -1;
+};
+
+class QueryRunner : public QObject
+{
+ Q_OBJECT
+public:
+ QueryRunner(const Query &query, const Utils::Id &id, QObject *parent = nullptr);
+ void start();
+
+signals:
+ void finished();
+ void resultRetrieved(const QByteArray &json);
+
+private:
+ Utils::QtcProcess m_process;
+};
+
+} // namespace GitLab
diff --git a/src/plugins/gitlab/resultparser.cpp b/src/plugins/gitlab/resultparser.cpp
new file mode 100644
index 00000000000..4794569821c
--- /dev/null
+++ b/src/plugins/gitlab/resultparser.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "resultparser.h"
+
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+
+#include <utility>
+
+namespace GitLab {
+
+
+QString Event::toMessage() const
+{
+ QString message;
+ if (author.realname.isEmpty())
+ message.append(author.name);
+ else
+ message.append(author.realname + " (" + author.name + ')');
+ message.append(' ');
+ if (!pushData.isEmpty())
+ message.append(pushData);
+ else if (!targetTitle.isEmpty())
+ message.append(action + ' ' + targetType + " '" + targetTitle +'\'');
+ else
+ message.append(action + ' ' + targetType);
+ return message;
+}
+
+namespace ResultParser {
+
+static PageInformation paginationInformation(const QByteArray &header)
+{
+ PageInformation result;
+ const QByteArrayList lines = header.split('\n');
+ for (const QByteArray &line : lines) {
+ const QByteArray lower = line.toLower(); // depending on OS this may be capitalized
+ if (lower.startsWith("x-page: "))
+ result.currentPage = line.mid(8).toInt();
+ else if (lower.startsWith("x-per-page: "))
+ result.perPage = line.mid(12).toInt();
+ else if (lower.startsWith("x-total: "))
+ result.total = line.mid(9).toInt();
+ else if (lower.startsWith("x-total-pages: "))
+ result.totalPages = line.mid(15).toInt();
+ }
+ return result;
+}
+
+static std::pair<QByteArray, QByteArray> splitHeaderAndBody(const QByteArray &input)
+{
+ QByteArray header;
+ QByteArray json;
+ int emptyLine = input.indexOf("\r\n\r\n"); // we always get \r\n as line separator?
+ if (emptyLine != -1) {
+ header = input.left(emptyLine);
+ json = input.mid(emptyLine + 4);
+ } else {
+ json = input;
+ }
+ return std::make_pair(header, json);
+}
+
+static std::pair<Error, QJsonObject> preHandleSingle(const QByteArray &json)
+{
+ Error result;
+ QJsonObject object;
+ QJsonParseError error;
+ const QJsonDocument doc = QJsonDocument::fromJson(json, &error);
+
+ if (error.error != QJsonParseError::NoError) {
+ if (!json.isEmpty() && json.at(0) == '<') // we likely got an HTML response
+ result.code = 399;
+ result.message = error.errorString();
+ } else if (!doc.isObject()) {
+ result.message = "Not an Object";
+ } else {
+ object = doc.object();
+ if (object.contains("message")) {
+ result = parseErrorMessage(object.value("message").toString());
+ } else if (object.contains("error")) {
+ if (object.value("error").toString() == "insufficient_scope")
+ result.code = 1;
+ result.message = object.value("error_description").toString();
+ }
+ }
+
+ return std::make_pair(result, object);
+}
+
+static std::pair<Error, QJsonDocument> preHandleHeaderAndBody(const QByteArray &header,
+ const QByteArray &json)
+{
+ Error result;
+ if (header.isEmpty()) {
+ result.message = "Missing Expected Header";
+ return std::make_pair(result, QJsonDocument());
+ }
+
+ QJsonParseError error;
+ const QJsonDocument doc = QJsonDocument::fromJson(json, &error);
+ if (error.error != QJsonParseError::NoError) {
+ result.message = error.errorString();
+ return std::make_pair(result, doc);
+ }
+
+ if (doc.isObject()) {
+ const QJsonObject obj = doc.object();
+ if (obj.contains("message")) {
+ result = parseErrorMessage(obj.value("message").toString());
+ return std::make_pair(result, doc);
+ } else if (obj.contains("error")) {
+ if (obj.value("error").toString() == "insufficient_scope")
+ result.code = 1;
+ result.message = obj.value("error_description").toString();
+ return std::make_pair(result, doc);
+ }
+ }
+
+ if (!doc.isArray())
+ result.message = "Not an Array";
+
+ return std::make_pair(result, doc);
+}
+
+static User userFromJson(const QJsonObject &jsonObj)
+{
+ User user;
+ user.name = jsonObj.value("username").toString();
+ user.realname = jsonObj.value("name").toString();
+ user.id = jsonObj.value("id").toInt(-1);
+ user.email = jsonObj.value("email").toString();
+ user.lastLogin = jsonObj.value("last_sign_in_at").toString();
+ user.bot = jsonObj.value("bot").toBool();
+ return user;
+}
+
+static Project projectFromJson(const QJsonObject &jsonObj)
+{
+ Project project;
+ project.name = jsonObj.value("name").toString();
+ project.displayName = jsonObj.value("name_with_namespace").toString();
+ project.pathName = jsonObj.value("path_with_namespace").toString();
+ project.id = jsonObj.value("id").toInt(-1);
+ project.visibility = jsonObj.value("visibility").toString("public");
+ project.httpUrl = jsonObj.value("http_url_to_repo").toString();
+ project.sshUrl = jsonObj.value("ssh_url_to_repo").toString();
+ if (jsonObj.contains("forks_count"))
+ project.forkCount = jsonObj.value("forks_count").toInt();
+ if (jsonObj.contains("star_count"))
+ project.starCount = jsonObj.value("star_count").toInt();
+ if (jsonObj.contains("open_issues_count"))
+ project.issuesCount = jsonObj.value("open_issues_count").toInt();
+ const QJsonObject permissions = jsonObj.value("permissions").toObject();
+ if (!permissions.isEmpty()) { // separate permissions obj?
+ const QJsonObject projAccObj = permissions.value("project_access").toObject();
+ if (!projAccObj.isEmpty())
+ project.accessLevel = projAccObj.value("access_level").toInt(-1);
+ }
+ return project;
+}
+
+static Event eventFromJson(const QJsonObject &jsonObj)
+{
+ Event event;
+ event.action = jsonObj.value("action_name").toString();
+ const QJsonValue value = jsonObj.value("target_type");
+ event.targetType = value.isNull() ? "project" : jsonObj.value("target_type").toString();
+ if (event.targetType == "DiffNote") {
+ const QJsonObject noteObject = jsonObj.value("note").toObject();
+ event.targetType = noteObject.value("noteable_type").toString();
+ }
+ event.targetTitle = jsonObj.value("target_title").toString();
+ event.author = userFromJson(jsonObj.value("author").toObject());
+ event.timeStamp = jsonObj.value("created_at").toString();
+ if (jsonObj.contains("push_data")) {
+ const QJsonObject pushDataObj = jsonObj.value("push_data").toObject();
+ if (!pushDataObj.isEmpty()) {
+ const QString action = pushDataObj.value("action").toString();
+ const QString ref = pushDataObj.value("ref").toString();
+ const QString refType = pushDataObj.value("ref_type").toString();
+ event.pushData = action + ' ' + refType + " '" + ref + '\'';
+ }
+ }
+ return event;
+}
+
+User parseUser(const QByteArray &input)
+{
+ auto [error, userObj] = preHandleSingle(input);
+ if (!error.message.isEmpty()) {
+ User result;
+ result.error = error;
+ return result;
+ }
+ return userFromJson(userObj);
+}
+
+Project parseProject(const QByteArray &input)
+{
+ auto [error, projectObj] = preHandleSingle(input);
+ if (!error.message.isEmpty()) {
+ Project result;
+ result.error = error;
+ return result;
+ }
+ return projectFromJson(projectObj);
+}
+
+Projects parseProjects(const QByteArray &input)
+{
+ auto [header, json] = splitHeaderAndBody(input);
+ auto [error, jsonDoc] = preHandleHeaderAndBody(header, json);
+ Projects result;
+ if (!error.message.isEmpty()) {
+ result.error = error;
+ return result;
+ }
+ result.pageInfo = paginationInformation(header);
+ const QJsonArray projectsArray = jsonDoc.array();
+ for (const QJsonValue &value : projectsArray) {
+ if (!value.isObject())
+ continue;
+ const QJsonObject projectObj = value.toObject();
+ result.projects.append(projectFromJson(projectObj));
+ }
+ return result;
+}
+
+Events parseEvents(const QByteArray &input)
+{
+ auto [header, json] = splitHeaderAndBody(input);
+ auto [error, jsonDoc] = preHandleHeaderAndBody(header, json);
+ Events result;
+ if (!error.message.isEmpty()) {
+ result.error = error;
+ return result;
+ }
+ result.pageInfo = paginationInformation(header);
+ const QJsonArray eventsArray = jsonDoc.array();
+ for (const QJsonValue &value : eventsArray) {
+ if (!value.isObject())
+ continue;
+ const QJsonObject eventObj = value.toObject();
+ result.events.append(eventFromJson(eventObj));
+ }
+ return result;
+
+}
+
+Error parseErrorMessage(const QString &message)
+{
+ Error error;
+ bool ok = false;
+ error.code = message.left(3).toInt(&ok);
+ if (ok)
+ error.message = message.mid(4);
+ else
+ error.message = "Internal Parse Error";
+ return error;
+}
+
+} // namespace ResultParser
+} // namespace GitLab
diff --git a/src/plugins/gitlab/resultparser.h b/src/plugins/gitlab/resultparser.h
new file mode 100644
index 00000000000..aeaeeadcc5a
--- /dev/null
+++ b/src/plugins/gitlab/resultparser.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QList>
+#include <QMetaType>
+#include <QString>
+
+namespace GitLab {
+
+struct Error
+{
+ int code = 200; // below 200: internal, 200+ HTTP
+ QString message;
+};
+
+class PageInformation
+{
+public:
+ int currentPage = -1;
+ int totalPages = -1;
+ int perPage = -1;
+ int total = -1;
+};
+
+class User
+{
+public:
+ QString name;
+ QString realname;
+ QString email;
+ QString lastLogin;
+ Error error;
+ int id = -1;
+ bool bot = false;
+};
+
+class Project
+{
+public:
+ QString name;
+ QString displayName;
+ QString pathName;
+ QString visibility;
+ QString httpUrl;
+ QString sshUrl;
+ Error error;
+ int id = -1;
+ int starCount = -1;
+ int forkCount = -1;
+ int issuesCount = -1;
+ int accessLevel = -1; // 50 owner, 40 maintainer, 30 developer, 20 reporter, 10 guest
+};
+
+class Projects
+{
+public:
+ QList<Project> projects;
+ Error error;
+ PageInformation pageInfo;
+};
+
+class Event
+{
+public:
+ QString action;
+ QString targetType;
+ QString targetTitle;
+ QString timeStamp;
+ QString pushData;
+ User author;
+ Error error;
+
+ QString toMessage() const;
+};
+
+class Events
+{
+public:
+ QList<Event> events;
+ Error error;
+ PageInformation pageInfo;
+};
+
+namespace ResultParser {
+
+User parseUser(const QByteArray &input);
+Project parseProject(const QByteArray &input);
+Projects parseProjects(const QByteArray &input);
+Events parseEvents(const QByteArray &input);
+Error parseErrorMessage(const QString &message);
+
+} // namespace ResultParser
+} // namespace GitLab
+
+Q_DECLARE_METATYPE(GitLab::Project)
diff --git a/src/plugins/glsleditor/CMakeLists.txt b/src/plugins/glsleditor/CMakeLists.txt
index a688988295d..85cbe99986f 100644
--- a/src/plugins/glsleditor/CMakeLists.txt
+++ b/src/plugins/glsleditor/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(GLSLEditor
+ PLUGIN_CLASS GlslEditorPlugin
DEPENDS GLSL
PLUGIN_DEPENDS Core CppEditor TextEditor
SOURCES
diff --git a/src/plugins/glsleditor/glslcompletionassist.cpp b/src/plugins/glsleditor/glslcompletionassist.cpp
index 60ee6c8214a..853209f392d 100644
--- a/src/plugins/glsleditor/glslcompletionassist.cpp
+++ b/src/plugins/glsleditor/glslcompletionassist.cpp
@@ -545,13 +545,12 @@ bool GlslCompletionAssistProcessor::acceptsIdleEditor() const
// -----------------------------
// GlslCompletionAssistInterface
// -----------------------------
-GlslCompletionAssistInterface::GlslCompletionAssistInterface(QTextDocument *textDocument,
- int position,
+GlslCompletionAssistInterface::GlslCompletionAssistInterface(const QTextCursor &cursor,
const Utils::FilePath &fileName,
AssistReason reason,
const QString &mimeType,
const Document::Ptr &glslDoc)
- : AssistInterface(textDocument, position, fileName, reason)
+ : AssistInterface(cursor, fileName, reason)
, m_mimeType(mimeType)
, m_glslDoc(glslDoc)
{
diff --git a/src/plugins/glsleditor/glslcompletionassist.h b/src/plugins/glsleditor/glslcompletionassist.h
index 596ddac25ff..e5fe1bed2d0 100644
--- a/src/plugins/glsleditor/glslcompletionassist.h
+++ b/src/plugins/glsleditor/glslcompletionassist.h
@@ -107,14 +107,14 @@ private:
class GlslCompletionAssistInterface : public TextEditor::AssistInterface
{
public:
- GlslCompletionAssistInterface(QTextDocument *textDocument,
- int position, const Utils::FilePath &fileName,
+ GlslCompletionAssistInterface(const QTextCursor &cursor, const Utils::FilePath &fileName,
TextEditor::AssistReason reason,
const QString &mimeType,
const Document::Ptr &glslDoc);
const QString &mimeType() const { return m_mimeType; }
const Document::Ptr &glslDocument() const { return m_glslDoc; }
+ bool isBaseObject() const override { return false; }
private:
QString m_mimeType;
diff --git a/src/plugins/glsleditor/glsleditor.cpp b/src/plugins/glsleditor/glsleditor.cpp
index 1f76e997eb2..85d4c15ae7d 100644
--- a/src/plugins/glsleditor/glsleditor.cpp
+++ b/src/plugins/glsleditor/glsleditor.cpp
@@ -369,8 +369,7 @@ AssistInterface *GlslEditorWidget::createAssistInterface(
AssistKind kind, AssistReason reason) const
{
if (kind == Completion)
- return new GlslCompletionAssistInterface(document(),
- position(),
+ return new GlslCompletionAssistInterface(textCursor(),
textDocument()->filePath(),
reason,
textDocument()->mimeType(),
diff --git a/src/plugins/help/docsettingspage.cpp b/src/plugins/help/docsettingspage.cpp
index 2aaada872b6..71b52f27f4f 100644
--- a/src/plugins/help/docsettingspage.cpp
+++ b/src/plugins/help/docsettingspage.cpp
@@ -30,6 +30,7 @@
#include "ui_docsettingspage.h"
#include <utils/algorithm.h>
+#include <utils/fileutils.h>
#include <QFileDialog>
#include <QKeyEvent>
diff --git a/src/plugins/help/helpmanager.cpp b/src/plugins/help/helpmanager.cpp
index b0755b703f6..c3f4dd738b6 100644
--- a/src/plugins/help/helpmanager.cpp
+++ b/src/plugins/help/helpmanager.cpp
@@ -34,6 +34,7 @@
#include <QDateTime>
#include <QDebug>
+#include <QDesktopServices>
#include <QDir>
#include <QFileInfo>
#include <QStringList>
@@ -109,10 +110,12 @@ HelpManager::HelpManager(QObject *parent) :
QTC_CHECK(!m_instance);
m_instance = this;
d = new HelpManagerPrivate;
+ QDesktopServices::setUrlHandler("qthelp", this, "showHelpUrl");
}
HelpManager::~HelpManager()
{
+ QDesktopServices::unsetUrlHandler("qthelp");
delete d;
m_instance = nullptr;
}
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index 99b1dca1654..bb0d45587f7 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -286,7 +286,6 @@ HelpPluginPrivate::HelpPluginPrivate()
connect(&helpIndexFilter, &HelpIndexFilter::linksActivated,
this, &HelpPluginPrivate::showLinksInCurrentViewer);
- QDesktopServices::setUrlHandler("qthelp", HelpManager::instance(), "showHelpUrl");
connect(ModeManager::instance(), &ModeManager::currentModeChanged,
this, &HelpPluginPrivate::modeChanged);
diff --git a/src/plugins/help/litehtmlhelpviewer.cpp b/src/plugins/help/litehtmlhelpviewer.cpp
index 3079c868fb7..4e1c697bed2 100644
--- a/src/plugins/help/litehtmlhelpviewer.cpp
+++ b/src/plugins/help/litehtmlhelpviewer.cpp
@@ -182,6 +182,7 @@ void LiteHtmlHelpViewer::addForwardHistoryItems(QMenu *forwardMenu)
bool LiteHtmlHelpViewer::findText(
const QString &text, Core::FindFlags flags, bool incremental, bool fromSearch, bool *wrapped)
{
+ Q_UNUSED(fromSearch)
return m_viewer->findText(text,
Core::textDocumentFlagsForFindFlags(flags),
incremental,
@@ -204,11 +205,14 @@ void LiteHtmlHelpViewer::backward()
{
goBackward(1);
}
+
void LiteHtmlHelpViewer::goForward(int count)
{
+ const int steps = qMin(count, int(m_forwardItems.size()));
+ if (steps == 0)
+ return;
HistoryItem nextItem = currentHistoryItem();
- for (int i = 0; i < count; ++i) {
- QTC_ASSERT(!m_forwardItems.empty(), return );
+ for (int i = 0; i < steps; ++i) {
m_backItems.push_back(nextItem);
nextItem = m_forwardItems.front();
m_forwardItems.erase(m_forwardItems.begin());
@@ -220,9 +224,11 @@ void LiteHtmlHelpViewer::goForward(int count)
void LiteHtmlHelpViewer::goBackward(int count)
{
+ const int steps = qMin(count, int(m_backItems.size()));
+ if (steps == 0)
+ return;
HistoryItem previousItem = currentHistoryItem();
- for (int i = 0; i < count; ++i) {
- QTC_ASSERT(!m_backItems.empty(), return );
+ for (int i = 0; i < steps; ++i) {
m_forwardItems.insert(m_forwardItems.begin(), previousItem);
previousItem = m_backItems.back();
m_backItems.pop_back();
@@ -234,6 +240,7 @@ void LiteHtmlHelpViewer::goBackward(int count)
void LiteHtmlHelpViewer::print(QPrinter *printer)
{
+ Q_UNUSED(printer)
// TODO
}
@@ -245,6 +252,15 @@ bool LiteHtmlHelpViewer::eventFilter(QObject *src, QEvent *e)
e->ignore();
return true;
}
+ } else if (e->type() == QEvent::MouseButtonPress) {
+ auto me = static_cast<QMouseEvent *>(e);
+ if (me->button() == Qt::BackButton) {
+ goBackward(1);
+ return true;
+ } else if (me->button() == Qt::ForwardButton) {
+ goForward(1);
+ return true;
+ }
}
return HelpViewer::eventFilter(src, e);
}
diff --git a/src/plugins/imageviewer/imageview.cpp b/src/plugins/imageviewer/imageview.cpp
index eebf8097bc0..e0770eb3c17 100644
--- a/src/plugins/imageviewer/imageview.cpp
+++ b/src/plugins/imageviewer/imageview.cpp
@@ -29,6 +29,7 @@
#include "exportdialog.h"
#include "multiexportdialog.h"
#include "imageviewerfile.h"
+#include "utils/mimeutils.h"
#include <coreplugin/messagemanager.h>
@@ -43,6 +44,8 @@
#include <QImage>
#include <QPainter>
#include <QPixmap>
+#include <QClipboard>
+#include <QGuiApplication>
#include <QDir>
#include <QFileInfo>
@@ -250,6 +253,16 @@ void ImageView::exportMultiImages()
#endif // !QT_NO_SVG
}
+void ImageView::copyDataUrl()
+{
+ Utils::MimeType mimeType = Utils::mimeTypeForFile(m_file->filePath());
+ QByteArray data = m_file->filePath().fileContents();
+ const auto url = QStringLiteral("data:%1;base64,%2")
+ .arg(mimeType.name())
+ .arg(QString::fromLatin1(data.toBase64()));
+ QGuiApplication::clipboard()->setText(url);
+}
+
void ImageView::setViewBackground(bool enable)
{
m_showBackground = enable;
diff --git a/src/plugins/imageviewer/imageview.h b/src/plugins/imageviewer/imageview.h
index 5404c69d7d7..4f18f7620c1 100644
--- a/src/plugins/imageviewer/imageview.h
+++ b/src/plugins/imageviewer/imageview.h
@@ -53,6 +53,7 @@ public:
void exportImage();
void exportMultiImages();
+ void copyDataUrl();
void setViewBackground(bool enable);
void setViewOutline(bool enable);
void zoomIn();
diff --git a/src/plugins/imageviewer/imageviewer.cpp b/src/plugins/imageviewer/imageviewer.cpp
index c676fe22d59..399ae70f5fe 100644
--- a/src/plugins/imageviewer/imageviewer.cpp
+++ b/src/plugins/imageviewer/imageviewer.cpp
@@ -102,6 +102,7 @@ void ImageViewer::ctor()
d->ui_toolbar.setupUi(d->toolbar);
d->ui_toolbar.toolButtonExportImage->setIcon(Utils::Icons::EXPORTFILE_TOOLBAR.icon());
d->ui_toolbar.toolButtonMultiExportImages->setIcon(Utils::Icons::MULTIEXPORTFILE_TOOLBAR.icon());
+ d->ui_toolbar.toolButtonCopyDataUrl->setIcon(Utils::Icons::COPY_TOOLBAR.icon());
const Utils::Icon backgroundIcon({
{":/utils/images/desktopdevicesmall.png", Utils::Theme::IconsBaseColor}});
d->ui_toolbar.toolButtonBackground->setIcon(backgroundIcon.icon());
@@ -123,6 +124,7 @@ void ImageViewer::ctor()
d->ui_toolbar.toolButtonExportImage->setCommandId(Constants::ACTION_EXPORT_IMAGE);
d->ui_toolbar.toolButtonMultiExportImages->setCommandId(Constants::ACTION_EXPORT_MULTI_IMAGES);
+ d->ui_toolbar.toolButtonCopyDataUrl->setCommandId(Constants::ACTION_COPY_DATA_URL);
d->ui_toolbar.toolButtonZoomIn->setCommandId(Core::Constants::ZOOM_IN);
d->ui_toolbar.toolButtonZoomOut->setCommandId(Core::Constants::ZOOM_OUT);
d->ui_toolbar.toolButtonOriginalSize->setCommandId(Core::Constants::ZOOM_RESET);
@@ -136,6 +138,8 @@ void ImageViewer::ctor()
d->imageView, &ImageView::exportImage);
connect(d->ui_toolbar.toolButtonMultiExportImages, &QAbstractButton::clicked,
d->imageView, &ImageView::exportMultiImages);
+ connect(d->ui_toolbar.toolButtonCopyDataUrl, &QAbstractButton::clicked,
+ d->imageView, &ImageView::copyDataUrl);
connect(d->ui_toolbar.toolButtonZoomIn, &QAbstractButton::clicked,
d->imageView, &ImageView::zoomIn);
connect(d->ui_toolbar.toolButtonZoomOut, &QAbstractButton::clicked,
@@ -207,6 +211,11 @@ void ImageViewer::exportMultiImages()
d->ui_toolbar.toolButtonMultiExportImages->click();
}
+void ImageViewer::copyDataUrl()
+{
+ d->ui_toolbar.toolButtonCopyDataUrl->click();
+}
+
void ImageViewer::imageSizeUpdated(const QSize &size)
{
QString imageSizeText;
diff --git a/src/plugins/imageviewer/imageviewer.h b/src/plugins/imageviewer/imageviewer.h
index 4dbf2ecf46e..5077b1521a4 100644
--- a/src/plugins/imageviewer/imageviewer.h
+++ b/src/plugins/imageviewer/imageviewer.h
@@ -56,6 +56,7 @@ public:
void exportImage();
void exportMultiImages();
+ void copyDataUrl();
void imageSizeUpdated(const QSize &size);
void scaleFactorUpdate(qreal factor);
diff --git a/src/plugins/imageviewer/imageviewerconstants.h b/src/plugins/imageviewer/imageviewerconstants.h
index 8a72fd4678c..af7766abe66 100644
--- a/src/plugins/imageviewer/imageviewerconstants.h
+++ b/src/plugins/imageviewer/imageviewerconstants.h
@@ -36,6 +36,7 @@ const char IMAGEVIEWER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "
const char ACTION_EXPORT_IMAGE[] = "ImageViewer.ExportImage";
const char ACTION_EXPORT_MULTI_IMAGES[] = "ImageViewer.ExportMultiImages";
+const char ACTION_COPY_DATA_URL[] = "ImageViewer.CopyDataUrl";
const char ACTION_FIT_TO_SCREEN[] = "ImageViewer.FitToScreen";
const char ACTION_BACKGROUND[] = "ImageViewer.Background";
const char ACTION_OUTLINE[] = "ImageViewer.Outline";
diff --git a/src/plugins/imageviewer/imageviewerfile.cpp b/src/plugins/imageviewer/imageviewerfile.cpp
index 1353de9a491..0133cce05c6 100644
--- a/src/plugins/imageviewer/imageviewerfile.cpp
+++ b/src/plugins/imageviewer/imageviewerfile.cpp
@@ -30,7 +30,7 @@
#include <coreplugin/editormanager/documentmodel.h>
#include <utils/fileutils.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <QFileInfo>
diff --git a/src/plugins/imageviewer/imageviewerplugin.cpp b/src/plugins/imageviewer/imageviewerplugin.cpp
index 2b8c68315f3..2c13f93ad8a 100644
--- a/src/plugins/imageviewer/imageviewerplugin.cpp
+++ b/src/plugins/imageviewer/imageviewerplugin.cpp
@@ -125,6 +125,12 @@ public:
&ImageViewer::exportMultiImages,
tr("Export Multiple Images"),
};
+
+ ImageViewerAction copyDataUrlAction {
+ Constants::ACTION_COPY_DATA_URL,
+ &ImageViewer::copyDataUrl,
+ tr("Copy as Data URL"),
+ };
};
ImageViewerPlugin::~ImageViewerPlugin()
diff --git a/src/plugins/imageviewer/imageviewertoolbar.ui b/src/plugins/imageviewer/imageviewertoolbar.ui
index 3aac796f5d3..6ad9334ea78 100644
--- a/src/plugins/imageviewer/imageviewertoolbar.ui
+++ b/src/plugins/imageviewer/imageviewertoolbar.ui
@@ -32,10 +32,11 @@
</widget>
</item>
<item>
+ <widget class="Core::CommandButton" name="toolButtonCopyDataUrl">
+ </widget>
+ </item>
+ <item>
<widget class="Core::CommandButton" name="toolButtonBackground">
- <property name="toolTipBase">
- <string>Show Background</string>
- </property>
<property name="checkable">
<bool>true</bool>
</property>
diff --git a/src/plugins/incredibuild/commandbuilderaspect.cpp b/src/plugins/incredibuild/commandbuilderaspect.cpp
index c5550cab156..43cbd39f009 100644
--- a/src/plugins/incredibuild/commandbuilderaspect.cpp
+++ b/src/plugins/incredibuild/commandbuilderaspect.cpp
@@ -168,7 +168,7 @@ void CommandBuilderAspect::addToLayout(LayoutBuilder &builder)
if (!d->label) {
d->label = new QLabel(tr("Command Helper:"));
- d->label->setToolTip(tr("Select an helper to establish the build command."));
+ d->label->setToolTip(tr("Select a helper to establish the build command."));
}
// On first creation of the step, attempt to detect and migrate from preceding steps
diff --git a/src/plugins/ios/iosbuildstep.cpp b/src/plugins/ios/iosbuildstep.cpp
index 8c518e3a00e..954ee1db172 100644
--- a/src/plugins/ios/iosbuildstep.cpp
+++ b/src/plugins/ios/iosbuildstep.cpp
@@ -79,7 +79,6 @@ private:
bool init() final;
void setupOutputFormatter(Utils::OutputFormatter *formatter) final;
- void doRun() final;
bool fromMap(const QVariantMap &map) final;
QVariantMap toMap() const final;
@@ -249,11 +248,6 @@ FilePath IosBuildStep::buildCommand() const
return "xcodebuild"; // add path?
}
-void IosBuildStep::doRun()
-{
- AbstractProcessStep::doRun();
-}
-
void IosBuildStep::setBaseArguments(const QStringList &args)
{
m_baseBuildArguments = args;
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp
index 30484fbd50a..41af86aa03e 100644
--- a/src/plugins/ios/iosconfigurations.cpp
+++ b/src/plugins/ios/iosconfigurations.cpp
@@ -100,7 +100,7 @@ const char profileTeamIdTag[] = "TeamIdentifier";
static const QString xcodePlistPath = QDir::homePath() + "/Library/Preferences/com.apple.dt.Xcode.plist";
static const QString provisioningProfileDirPath = QDir::homePath() + "/Library/MobileDevice/Provisioning Profiles";
-static Utils::Id deviceId(const QString &sdkName)
+static Id deviceId(const QString &sdkName)
{
if (sdkName.startsWith("iphoneos", Qt::CaseInsensitive))
return Constants::IOS_DEVICE_TYPE;
@@ -109,7 +109,7 @@ static Utils::Id deviceId(const QString &sdkName)
return {};
}
-static bool isSimulatorDeviceId(const Utils::Id &id)
+static bool isSimulatorDeviceId(const Id &id)
{
return id == Constants::IOS_SIMULATOR_TYPE;
}
@@ -126,7 +126,7 @@ static QList<ClangToolChain *> clangToolChains(const Toolchains &toolChains)
static QList<ClangToolChain *> autoDetectedIosToolChains()
{
const QList<ClangToolChain *> toolChains = clangToolChains(ToolChainManager::toolchains());
- return Utils::filtered(toolChains, [](ClangToolChain *toolChain) {
+ return filtered(toolChains, [](ClangToolChain *toolChain) {
return toolChain->isAutoDetected()
&& (toolChain->displayName().startsWith("iphone")
|| toolChain->displayName().startsWith("Apple Clang")); // TODO tool chains should be marked directly
@@ -138,15 +138,15 @@ static ToolChainPair findToolChainForPlatform(const XcodePlatform &platform,
const QList<ClangToolChain *> &toolChains)
{
ToolChainPair platformToolChains;
- auto toolchainMatch = [](ClangToolChain *toolChain, const Utils::FilePath &compilerPath, const QStringList &flags) {
+ auto toolchainMatch = [](ClangToolChain *toolChain, const FilePath &compilerPath, const QStringList &flags) {
return compilerPath == toolChain->compilerCommand()
&& flags == toolChain->platformCodeGenFlags()
&& flags == toolChain->platformLinkerFlags();
};
- platformToolChains.first = Utils::findOrDefault(toolChains, std::bind(toolchainMatch, std::placeholders::_1,
+ platformToolChains.first = findOrDefault(toolChains, std::bind(toolchainMatch, std::placeholders::_1,
platform.cCompilerPath,
target.backendFlags));
- platformToolChains.second = Utils::findOrDefault(toolChains, std::bind(toolchainMatch, std::placeholders::_1,
+ platformToolChains.second = findOrDefault(toolChains, std::bind(toolchainMatch, std::placeholders::_1,
platform.cxxCompilerPath,
target.backendFlags));
return platformToolChains;
@@ -169,8 +169,8 @@ static QHash<XcodePlatform::ToolchainTarget, ToolChainPair> findToolChains(const
static QSet<Kit *> existingAutoDetectedIosKits()
{
- return Utils::toSet(Utils::filtered(KitManager::kits(), [](Kit *kit) -> bool {
- Utils::Id deviceKind = DeviceTypeKitAspect::deviceTypeId(kit);
+ return toSet(filtered(KitManager::kits(), [](Kit *kit) -> bool {
+ Id deviceKind = DeviceTypeKitAspect::deviceTypeId(kit);
return kit->isAutoDetected() && (deviceKind == Constants::IOS_DEVICE_TYPE
|| deviceKind == Constants::IOS_SIMULATOR_TYPE);
}));
@@ -182,8 +182,8 @@ static void printKits(const QSet<Kit *> &kits)
qCDebug(kitSetupLog) << " -" << kit->displayName();
}
-static void setupKit(Kit *kit, Utils::Id pDeviceType, const ToolChainPair& toolChains,
- const QVariant &debuggerId, const Utils::FilePath &sdkPath, QtVersion *qtVersion)
+static void setupKit(Kit *kit, Id pDeviceType, const ToolChainPair& toolChains,
+ const QVariant &debuggerId, const FilePath &sdkPath, QtVersion *qtVersion)
{
DeviceTypeKitAspect::setDeviceTypeId(kit, pDeviceType);
if (toolChains.first)
@@ -214,7 +214,7 @@ static void setupKit(Kit *kit, Utils::Id pDeviceType, const ToolChainPair& toolC
SysRootKitAspect::setSysRoot(kit, sdkPath);
}
-static QVersionNumber findXcodeVersion(const Utils::FilePath &developerPath)
+static QVersionNumber findXcodeVersion(const FilePath &developerPath)
{
const FilePath xcodeInfo = developerPath.parentDir().pathAppended("Info.plist");
if (xcodeInfo.exists()) {
@@ -231,14 +231,14 @@ static QByteArray decodeProvisioningProfile(const QString &path)
{
QTC_ASSERT(!path.isEmpty(), return QByteArray());
- Utils::QtcProcess p;
+ QtcProcess p;
p.setTimeoutS(3);
// path is assumed to be valid file path to .mobileprovision
p.setCommand({"openssl", {"smime", "-inform", "der", "-verify", "-in", path}});
p.runBlocking();
- if (p.result() != Utils::QtcProcess::FinishedWithSuccess)
+ if (p.result() != ProcessResult::FinishedWithSuccess)
qCDebug(iosCommonLog) << "Reading signed provisioning file failed" << path;
- return p.stdOut().toLatin1();
+ return p.cleanedStdOut().toLatin1();
}
void IosConfigurations::updateAutomaticKitList()
@@ -251,7 +251,7 @@ void IosConfigurations::updateAutomaticKitList()
// target -> tool chain
const auto targetToolChainHash = findToolChains(platforms);
- const auto qtVersions = Utils::toSet(QtVersionManager::versions([](const QtVersion *v) {
+ const auto qtVersions = toSet(QtVersionManager::versions([](const QtVersion *v) {
return v->isValid() && v->type() == Constants::IOSQT;
}));
@@ -264,8 +264,8 @@ void IosConfigurations::updateAutomaticKitList()
QSet<Kit *> resultingKits;
for (const XcodePlatform &platform : platforms) {
for (const auto &sdk : platform.sdks) {
- const auto targets = Utils::filtered(platform.targets,
- [&sdk](const XcodePlatform::ToolchainTarget &target) {
+ const auto targets = filtered(platform.targets,
+ [&sdk](const XcodePlatform::ToolchainTarget &target) {
return sdk.architectures.first() == target.architecture;
});
if (targets.empty())
@@ -278,7 +278,7 @@ void IosConfigurations::updateAutomaticKitList()
qCDebug(kitSetupLog) << " - No tool chain found";
continue;
}
- Utils::Id pDeviceType = deviceId(sdk.directoryName);
+ Id pDeviceType = deviceId(sdk.directoryName);
if (!pDeviceType.isValid()) {
qCDebug(kitSetupLog) << "Unsupported/Invalid device type" << sdk.directoryName;
continue;
@@ -286,7 +286,7 @@ void IosConfigurations::updateAutomaticKitList()
for (QtVersion *qtVersion : qtVersions) {
qCDebug(kitSetupLog) << " - Qt version:" << qtVersion->displayName();
- Kit *kit = Utils::findOrDefault(existingKits, [&pDeviceType, &platformToolchains, &qtVersion](const Kit *kit) {
+ Kit *kit = findOrDefault(existingKits, [&pDeviceType, &platformToolchains, &qtVersion](const Kit *kit) {
// we do not compare the sdk (thus automatically upgrading it in place if a
// new Xcode is used). Change?
return DeviceTypeKitAspect::deviceTypeId(kit) == pDeviceType
@@ -418,7 +418,7 @@ void IosConfigurations::updateSimulators()
{
// currently we have just one simulator
DeviceManager *devManager = DeviceManager::instance();
- Utils::Id devId = Constants::IOS_SIMULATOR_DEVICE_ID;
+ Id devId = Constants::IOS_SIMULATOR_DEVICE_ID;
IDevice::ConstPtr dev = devManager->find(devId);
if (dev.isNull()) {
dev = IDevice::ConstPtr(new IosSimulator(devId));
@@ -492,7 +492,7 @@ void IosConfigurations::loadProvisioningData(bool notify)
}
// Sort team id's to move the free provisioning teams at last of the list.
- Utils::sort(teams, [](const QVariantMap &teamInfo1, const QVariantMap &teamInfo2) {
+ sort(teams, [](const QVariantMap &teamInfo1, const QVariantMap &teamInfo2) {
return teamInfo1.value(freeTeamTag).toInt() < teamInfo2.value(freeTeamTag).toInt();
});
@@ -564,7 +564,7 @@ DevelopmentTeamPtr IosConfigurations::developmentTeam(const QString &teamID)
QTC_CHECK(m_instance);
m_instance->initializeProvisioningData();
return findOrDefault(m_instance->m_developerTeams,
- Utils::equal(&DevelopmentTeam::identifier, teamID));
+ equal(&DevelopmentTeam::identifier, teamID));
}
const ProvisioningProfiles &IosConfigurations::provisioningProfiles()
@@ -578,8 +578,8 @@ ProvisioningProfilePtr IosConfigurations::provisioningProfile(const QString &pro
{
QTC_CHECK(m_instance);
m_instance->initializeProvisioningData();
- return Utils::findOrDefault(m_instance->m_provisioningProfiles,
- Utils::equal(&ProvisioningProfile::identifier, profileID));
+ return findOrDefault(m_instance->m_provisioningProfiles,
+ equal(&ProvisioningProfile::identifier, profileID));
}
IosToolChainFactory::IosToolChainFactory()
@@ -590,6 +590,9 @@ IosToolChainFactory::IosToolChainFactory()
Toolchains IosToolChainFactory::autoDetect(const ToolchainDetector &detector) const
{
+ if (detector.device)
+ return {};
+
QList<ClangToolChain *> existingClangToolChains = clangToolChains(detector.alreadyKnown);
const QList<XcodePlatform> platforms = XcodeProbe::detectPlatforms().values();
Toolchains toolChains;
@@ -598,7 +601,7 @@ Toolchains IosToolChainFactory::autoDetect(const ToolchainDetector &detector) co
for (const XcodePlatform::ToolchainTarget &target : platform.targets) {
ToolChainPair platformToolchains = findToolChainForPlatform(platform, target,
existingClangToolChains);
- auto createOrAdd = [&](ClangToolChain *toolChain, Utils::Id l) {
+ auto createOrAdd = [&](ClangToolChain *toolChain, Id l) {
if (!toolChain) {
toolChain = new ClangToolChain;
toolChain->setDetection(ToolChain::AutoDetection);
diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp
index fcc09f3a8bf..7fe7e99e7f0 100644
--- a/src/plugins/ios/iosdevice.cpp
+++ b/src/plugins/ios/iosdevice.cpp
@@ -486,7 +486,12 @@ void IosDeviceManager::monitorAvailableDevices()
CFRelease( cfProductIdMaskValue );
}
- IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
+#if QT_MACOS_DEPLOYMENT_TARGET_BELOW(120000)
+ const mach_port_t port = kIOMasterPortDefault; // deprecated in macOS 12
+#else
+ const mach_port_t port = kIOMainPortDefault; // available since macOS 12
+#endif
+ IONotificationPortRef notificationPort = IONotificationPortCreate(port);
CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
@@ -495,21 +500,19 @@ void IosDeviceManager::monitorAvailableDevices()
CFRetain(matchingDictionary);
// Now set up a notification to be called when a device is first matched by I/O Kit.
- kern_return_t kr;
- kr = IOServiceAddMatchingNotification(notificationPort,
- kIOMatchedNotification,
- matchingDictionary,
- deviceConnectedCallback,
- NULL,
- &gAddedIter);
-
-
- kr = IOServiceAddMatchingNotification(notificationPort,
- kIOTerminatedNotification,
- matchingDictionary,
- deviceDisconnectedCallback,
- NULL,
- &gRemovedIter);
+ IOServiceAddMatchingNotification(notificationPort,
+ kIOMatchedNotification,
+ matchingDictionary,
+ deviceConnectedCallback,
+ NULL,
+ &gAddedIter);
+
+ IOServiceAddMatchingNotification(notificationPort,
+ kIOTerminatedNotification,
+ matchingDictionary,
+ deviceDisconnectedCallback,
+ NULL,
+ &gRemovedIter);
// Iterate once to get already-present devices and arm the notification
deviceConnectedCallback(NULL, gAddedIter);
diff --git a/src/plugins/ios/iosdsymbuildstep.h b/src/plugins/ios/iosdsymbuildstep.h
index 2a92a0187cf..87776f6916b 100644
--- a/src/plugins/ios/iosdsymbuildstep.h
+++ b/src/plugins/ios/iosdsymbuildstep.h
@@ -27,8 +27,6 @@
#include <projectexplorer/abstractprocessstep.h>
-#include <utils/fileutils.h>
-
namespace Ios {
namespace Internal {
diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp
index 84bfa561027..4f09f556a07 100644
--- a/src/plugins/ios/iosprobe.cpp
+++ b/src/plugins/ios/iosprobe.cpp
@@ -68,11 +68,11 @@ void XcodeProbe::detectDeveloperPaths()
selectedXcode.setTimeoutS(5);
selectedXcode.setCommand({"/usr/bin/xcode-select", {"--print-path"}});
selectedXcode.runBlocking();
- if (selectedXcode.result() != QtcProcess::FinishedWithSuccess)
+ if (selectedXcode.result() != ProcessResult::FinishedWithSuccess)
qCWarning(probeLog)
<< QString::fromLatin1("Could not detect selected Xcode using xcode-select");
else
- addDeveloperPath(selectedXcode.stdOut().trimmed());
+ addDeveloperPath(selectedXcode.cleanedStdOut().trimmed());
addDeveloperPath(defaultDeveloperPath);
}
diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp
index 1198644a3ac..d4a93337d65 100644
--- a/src/plugins/ios/iosrunconfiguration.cpp
+++ b/src/plugins/ios/iosrunconfiguration.cpp
@@ -53,7 +53,6 @@
#include <QLabel>
#include <QLineEdit>
#include <QList>
-#include <QStandardItemModel>
#include <QVariant>
#include <QWidget>
@@ -78,38 +77,13 @@ static IosDeviceType toIosDeviceType(const SimulatorInfo &device)
return iosDeviceType;
}
-class IosDeviceTypeAspect : public BaseAspect
-{
-public:
- IosDeviceTypeAspect(IosRunConfiguration *runConfiguration);
-
- void fromMap(const QVariantMap &map) override;
- void toMap(QVariantMap &map) const override;
- void addToLayout(LayoutBuilder &builder) override;
-
- IosDeviceType deviceType() const;
- void setDeviceType(const IosDeviceType &deviceType);
-
- void updateValues();
- void setDeviceTypeIndex(int devIndex);
- void deviceChanges();
- void updateDeviceType();
-
-public:
- IosDeviceType m_deviceType;
- IosRunConfiguration *m_runConfiguration = nullptr;
- QStandardItemModel m_deviceTypeModel;
- QLabel *m_deviceTypeLabel = nullptr;
- QComboBox *m_deviceTypeComboBox = nullptr;
-};
-
-IosRunConfiguration::IosRunConfiguration(Target *target, Utils::Id id)
+IosRunConfiguration::IosRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- auto executableAspect = addAspect<ExecutableAspect>();
+ auto executableAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
executableAspect->setDisplayStyle(StringAspect::LabelDisplay);
- addAspect<ArgumentsAspect>();
+ addAspect<ArgumentsAspect>(macroExpander());
m_deviceTypeAspect = addAspect<IosDeviceTypeAspect>(this);
@@ -361,6 +335,11 @@ void IosDeviceTypeAspect::setDeviceType(const IosDeviceType &deviceType)
IosDeviceTypeAspect::IosDeviceTypeAspect(IosRunConfiguration *runConfiguration)
: m_runConfiguration(runConfiguration)
{
+ addDataExtractor(this, &IosDeviceTypeAspect::deviceType, &Data::deviceType);
+ addDataExtractor(this, &IosDeviceTypeAspect::bundleDirectory, &Data::bundleDirectory);
+ addDataExtractor(this, &IosDeviceTypeAspect::applicationName, &Data::applicationName);
+ addDataExtractor(this, &IosDeviceTypeAspect::localExecutable, &Data::localExecutable);
+
connect(DeviceManager::instance(), &DeviceManager::updated,
this, &IosDeviceTypeAspect::deviceChanges);
connect(KitManager::instance(), &KitManager::kitsChanged,
@@ -427,6 +406,20 @@ void IosDeviceTypeAspect::updateValues()
}
}
+FilePath IosDeviceTypeAspect::bundleDirectory() const
+{
+ return m_runConfiguration->bundleDirectory();
+}
+
+QString IosDeviceTypeAspect::applicationName() const
+{
+ return m_runConfiguration->applicationName();
+}
+
+FilePath IosDeviceTypeAspect::localExecutable() const
+{
+ return m_runConfiguration->localExecutable();
+}
// IosRunConfigurationFactory
diff --git a/src/plugins/ios/iosrunconfiguration.h b/src/plugins/ios/iosrunconfiguration.h
index bb747263305..6269dda32ee 100644
--- a/src/plugins/ios/iosrunconfiguration.h
+++ b/src/plugins/ios/iosrunconfiguration.h
@@ -30,12 +30,56 @@
#include "iossimulator.h"
#include <projectexplorer/runconfiguration.h>
+
#include <utils/fileutils.h>
+#include <QComboBox>
+#include <QStandardItemModel>
+
namespace Ios {
namespace Internal {
-class IosDeviceTypeAspect;
+class IosRunConfiguration;
+
+class IosDeviceTypeAspect : public Utils::BaseAspect
+{
+ Q_OBJECT
+
+public:
+ explicit IosDeviceTypeAspect(IosRunConfiguration *runConfiguration);
+
+ void fromMap(const QVariantMap &map) override;
+ void toMap(QVariantMap &map) const override;
+ void addToLayout(Utils::LayoutBuilder &builder) override;
+
+ IosDeviceType deviceType() const;
+ void setDeviceType(const IosDeviceType &deviceType);
+
+ void updateValues();
+ void setDeviceTypeIndex(int devIndex);
+ void deviceChanges();
+ void updateDeviceType();
+
+ class Data : public Utils::BaseAspect::Data
+ {
+ public:
+ Utils::FilePath bundleDirectory;
+ IosDeviceType deviceType;
+ QString applicationName;
+ Utils::FilePath localExecutable;
+ };
+
+private:
+ Utils::FilePath bundleDirectory() const;
+ QString applicationName() const;
+ Utils::FilePath localExecutable() const;
+
+ IosDeviceType m_deviceType;
+ IosRunConfiguration *m_runConfiguration = nullptr;
+ QStandardItemModel m_deviceTypeModel;
+ QLabel *m_deviceTypeLabel = nullptr;
+ QComboBox *m_deviceTypeComboBox = nullptr;
+};
class IosRunConfiguration : public ProjectExplorer::RunConfiguration
{
diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp
index 5a93615bf2f..aea7a28b9ca 100644
--- a/src/plugins/ios/iosrunner.cpp
+++ b/src/plugins/ios/iosrunner.cpp
@@ -96,10 +96,11 @@ IosRunner::IosRunner(RunControl *runControl)
{
setId("IosRunner");
stopRunningRunControl(runControl);
- auto runConfig = qobject_cast<IosRunConfiguration *>(runControl->runConfiguration());
- m_bundleDir = runConfig->bundleDirectory().toString();
+ const IosDeviceTypeAspect::Data *data = runControl->aspect<IosDeviceTypeAspect>();
+ QTC_ASSERT(data, return);
+ m_bundleDir = data->bundleDirectory.toString();
m_device = DeviceKitAspect::device(runControl->kit());
- m_deviceType = runConfig->deviceType();
+ m_deviceType = data->deviceType;
}
IosRunner::~IosRunner()
@@ -196,8 +197,8 @@ void IosRunner::start()
connect(m_toolHandler, &IosToolHandler::finished,
this, &IosRunner::handleFinished);
- const Runnable runnable = runControl()->runnable();
- QStringList args = ProcessArgs::splitArgs(runnable.command.arguments(), OsTypeMac);
+ const CommandLine command = runControl()->commandLine();
+ QStringList args = ProcessArgs::splitArgs(command.arguments(), OsTypeMac);
if (m_qmlServerPort.isValid()) {
QUrl qmlServer;
qmlServer.setPort(m_qmlServerPort.number());
@@ -456,8 +457,10 @@ void IosDebugSupport::start()
setIosPlatform("ios-simulator");
}
- auto iosRunConfig = qobject_cast<IosRunConfiguration *>(runControl()->runConfiguration());
- setRunControlName(iosRunConfig->applicationName());
+ const IosDeviceTypeAspect::Data *data = runControl()->aspect<IosDeviceTypeAspect>();
+ QTC_ASSERT(data, reportFailure("Broken IosDeviceTypeAspect setup."); return);
+
+ setRunControlName(data->applicationName);
setContinueAfterAttach(true);
Utils::Port gdbServerPort = m_runner->gdbServerPort();
@@ -467,14 +470,14 @@ void IosDebugSupport::start()
const bool cppDebug = isCppDebugging();
const bool qmlDebug = isQmlDebugging();
if (cppDebug) {
- setInferiorExecutable(iosRunConfig->localExecutable());
+ setInferiorExecutable(data->localExecutable);
setRemoteChannel("connect://localhost:" + gdbServerPort.toString());
- QString bundlePath = iosRunConfig->bundleDirectory().toString();
+ QString bundlePath = data->bundleDirectory.toString();
bundlePath.chop(4);
FilePath dsymPath = FilePath::fromString(bundlePath.append(".dSYM"));
if (dsymPath.exists()
- && dsymPath.lastModified() < iosRunConfig->localExecutable().lastModified()) {
+ && dsymPath.lastModified() < data->localExecutable.lastModified()) {
TaskHub::addTask(DeploymentTask(Task::Warning,
tr("The dSYM %1 seems to be outdated, it might confuse the debugger.")
.arg(dsymPath.toUserOutput())));
diff --git a/src/plugins/ios/iosrunner.h b/src/plugins/ios/iosrunner.h
index d4cbb03f013..a54d55e8b1a 100644
--- a/src/plugins/ios/iosrunner.h
+++ b/src/plugins/ios/iosrunner.h
@@ -32,7 +32,7 @@
#include <debugger/debuggerconstants.h>
#include <debugger/debuggerruncontrol.h>
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
#include <projectexplorer/runconfiguration.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
@@ -83,7 +83,7 @@ private:
IosToolHandler *m_toolHandler = nullptr;
QString m_bundleDir;
- ProjectExplorer::IDevice::ConstPtr m_device;
+ ProjectExplorer::IDeviceConstPtr m_device;
IosDeviceType m_deviceType;
bool m_cppDebug = false;
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices = QmlDebug::NoQmlDebugServices;
diff --git a/src/plugins/ios/iossimulator.h b/src/plugins/ios/iossimulator.h
index 8e4909ee342..4915d5e1841 100644
--- a/src/plugins/ios/iossimulator.h
+++ b/src/plugins/ios/iossimulator.h
@@ -28,7 +28,7 @@
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/idevicefactory.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <QDebug>
diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp
index c64a2731420..a3ccf2e5866 100644
--- a/src/plugins/ios/iostoolhandler.cpp
+++ b/src/plugins/ios/iostoolhandler.cpp
@@ -38,6 +38,7 @@
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
+#include <utils/temporarydirectory.h>
#include <QCoreApplication>
#include <QDir>
@@ -701,10 +702,14 @@ void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath,
{
m_bundlePath = bundlePath;
m_deviceId = deviceId;
+ QString tmpDeltaPath = Utils::TemporaryDirectory::masterDirectoryFilePath().pathAppended("ios").toString();
QStringList args;
args << QLatin1String("--id") << deviceId << QLatin1String("--bundle")
<< bundlePath << QLatin1String("--timeout") << QString::number(timeout)
- << QLatin1String("--install");
+ << QLatin1String("--install")
+ << QLatin1String("--delta-path")
+ << tmpDeltaPath;
+
start(IosToolHandler::iosDeviceToolPath(), args);
}
diff --git a/src/plugins/ios/simulatorcontrol.cpp b/src/plugins/ios/simulatorcontrol.cpp
index 0bf72b8a2f2..d4b154a0c9e 100644
--- a/src/plugins/ios/simulatorcontrol.cpp
+++ b/src/plugins/ios/simulatorcontrol.cpp
@@ -85,10 +85,10 @@ static bool runCommand(const CommandLine &command, QString *stdOutput, QString *
p.setCommand(command);
p.runBlocking();
if (stdOutput)
- *stdOutput = p.stdOut();
+ *stdOutput = p.cleanedStdOut();
if (allOutput)
*allOutput = p.allOutput();
- return p.result() == QtcProcess::FinishedWithSuccess;
+ return p.result() == ProcessResult::FinishedWithSuccess;
}
static bool runSimCtlCommand(QStringList args, QString *output, QString *allOutput = nullptr)
diff --git a/src/plugins/languageclient/CMakeLists.txt b/src/plugins/languageclient/CMakeLists.txt
index 0020a4d069b..50dd072dab4 100644
--- a/src/plugins/languageclient/CMakeLists.txt
+++ b/src/plugins/languageclient/CMakeLists.txt
@@ -1,5 +1,5 @@
add_qtc_plugin(LanguageClient
- PUBLIC_DEPENDS LanguageServerProtocol Qt5::Core
+ PUBLIC_DEPENDS LanguageServerProtocol Qt5::Core app_version
PLUGIN_DEPENDS ProjectExplorer Core TextEditor
SOURCES
client.cpp client.h
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp
index 541ba0d3e21..bb4c4e6e328 100644
--- a/src/plugins/languageclient/client.cpp
+++ b/src/plugins/languageclient/client.cpp
@@ -25,11 +25,22 @@
#include "client.h"
+#include "diagnosticmanager.h"
+#include "documentsymbolcache.h"
+#include "languageclientcompletionassist.h"
+#include "languageclientformatter.h"
+#include "languageclientfunctionhint.h"
+#include "languageclienthoverhandler.h"
#include "languageclientinterface.h"
#include "languageclientmanager.h"
+#include "languageclientquickfix.h"
+#include "languageclientsymbolsupport.h"
#include "languageclientutils.h"
+#include "progressmanager.h"
#include "semantichighlightsupport.h"
+#include <app/app_version.h>
+
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
@@ -38,11 +49,14 @@
#include <languageserverprotocol/completion.h>
#include <languageserverprotocol/diagnostics.h>
+#include <languageserverprotocol/initializemessages.h>
+#include <languageserverprotocol/jsonrpcmessages.h>
#include <languageserverprotocol/languagefeatures.h>
#include <languageserverprotocol/messages.h>
+#include <languageserverprotocol/progresssupport.h>
#include <languageserverprotocol/servercapabilities.h>
+#include <languageserverprotocol/shutdownmessages.h>
#include <languageserverprotocol/workspace.h>
-#include <languageserverprotocol/progresssupport.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
@@ -57,11 +71,11 @@
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorsettings.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcprocess.h>
-
#include <QDebug>
+#include <QJsonDocument>
#include <QLoggingCategory>
#include <QMessageBox>
#include <QPointer>
@@ -69,6 +83,7 @@
#include <QTextBlock>
#include <QTextCursor>
#include <QTextDocument>
+#include <QThread>
#include <QTimer>
using namespace LanguageServerProtocol;
@@ -78,53 +93,52 @@ namespace LanguageClient {
static Q_LOGGING_CATEGORY(LOGLSPCLIENT, "qtc.languageclient.client", QtWarningMsg);
-Client::Client(BaseClientInterface *clientInterface)
- : m_id(Utils::Id::fromString(QUuid::createUuid().toString()))
- , m_clientInterface(clientInterface)
- , m_diagnosticManager(this)
- , m_documentSymbolCache(this)
- , m_hoverHandler(this)
- , m_symbolSupport(this)
- , m_tokenSupport(this)
+class InterfaceController : public QObject
{
- using namespace ProjectExplorer;
- m_clientProviders.completionAssistProvider = new LanguageClientCompletionAssistProvider(this);
- m_clientProviders.functionHintProvider = new FunctionHintAssistProvider(this);
- m_clientProviders.quickFixAssistProvider = new LanguageClientQuickFixProvider(this);
-
- m_documentUpdateTimer.setSingleShot(true);
- m_documentUpdateTimer.setInterval(500);
- connect(&m_documentUpdateTimer, &QTimer::timeout, this,
- [this] { sendPostponedDocumentUpdates(Schedule::Now); });
- connect(SessionManager::instance(), &SessionManager::projectRemoved,
- this, &Client::projectClosed);
-
- m_contentHandler.insert(JsonRpcMessageHandler::jsonRpcMimeType(),
- &JsonRpcMessageHandler::parseContent);
- QTC_ASSERT(clientInterface, return);
- connect(clientInterface, &BaseClientInterface::messageReceived, this, &Client::handleMessage);
- connect(clientInterface, &BaseClientInterface::error, this, &Client::setError);
- connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
- connect(Core::EditorManager::instance(),
- &Core::EditorManager::documentClosed,
- this,
- &Client::documentClosed);
-
- m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
- m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
-
- m_shutdownTimer.setInterval(20 /*seconds*/ * 1000);
- connect(&m_shutdownTimer, &QTimer::timeout, this, [this] {
- LanguageClientManager::deleteClient(this);
- });
-}
+ Q_OBJECT
-QString Client::name() const
-{
- if (m_project && !m_project->displayName().isEmpty())
- return tr("%1 for %2").arg(m_displayName, m_project->displayName());
- return m_displayName;
-}
+public:
+ InterfaceController(BaseClientInterface *interface)
+ : m_interface(interface)
+ {
+ using Interface = BaseClientInterface;
+ interface->moveToThread(&m_thread);
+ connect(interface, &Interface::messageReceived, this, &InterfaceController::messageReceived);
+ connect(interface, &Interface::error, this, &InterfaceController::error);
+ connect(interface, &Interface::finished, this, &InterfaceController::finished);
+ connect(interface, &Interface::started, this, &InterfaceController::started);
+ m_thread.start();
+ }
+ ~InterfaceController()
+ {
+ m_interface->deleteLater();
+ m_thread.quit();
+ m_thread.wait();
+ }
+
+ void start()
+ {
+ QMetaObject::invokeMethod(m_interface, &BaseClientInterface::start);
+ }
+ void sendMessage(const JsonRpcMessage &message)
+ {
+ QMetaObject::invokeMethod(m_interface, [=]() { m_interface->sendMessage(message); });
+ }
+ void resetBuffer()
+ {
+ QMetaObject::invokeMethod(m_interface, &BaseClientInterface::resetBuffer);
+ }
+
+signals:
+ void messageReceived(const JsonRpcMessage &message);
+ void started();
+ void error(const QString &message);
+ void finished();
+
+private:
+ BaseClientInterface *m_interface;
+ QThread m_thread;
+};
static void updateEditorToolBar(QList<TextEditor::TextDocument *> documents)
{
@@ -134,30 +148,222 @@ static void updateEditorToolBar(QList<TextEditor::TextDocument *> documents)
}
}
-Client::~Client()
+class ClientPrivate : public QObject
{
- using namespace TextEditor;
- // FIXME: instead of replacing the completion provider in the text document store the
- // completion provider as a prioritised list in the text document
- // temporary container needed since m_resetAssistProvider is changed in resetAssistProviders
- for (TextDocument *document : m_resetAssistProvider.keys())
- resetAssistProviders(document);
- const QList<Core::IEditor *> &editors = Core::DocumentModel::editorsForOpenedDocuments();
- for (Core::IEditor *editor : editors) {
- if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
- TextEditorWidget *widget = textEditor->editorWidget();
- widget->setRefactorMarkers(RefactorMarker::filterOutType(widget->refactorMarkers(), id()));
- widget->removeHoverHandler(&m_hoverHandler);
+ Q_OBJECT
+public:
+ ClientPrivate(Client *client, BaseClientInterface *clientInterface)
+ : q(client)
+ , m_id(Utils::Id::fromString(QUuid::createUuid().toString()))
+ , m_clientCapabilities(q->defaultClientCapabilities())
+ , m_clientInterface(new InterfaceController(clientInterface))
+ , m_documentSymbolCache(q)
+ , m_hoverHandler(q)
+ , m_symbolSupport(q)
+ , m_tokenSupport(q)
+ {
+ using namespace ProjectExplorer;
+
+ m_clientInfo.setName(Core::Constants::IDE_DISPLAY_NAME);
+ m_clientInfo.setVersion(Core::Constants::IDE_VERSION_DISPLAY);
+
+ m_clientProviders.completionAssistProvider = new LanguageClientCompletionAssistProvider(q);
+ m_clientProviders.functionHintProvider = new FunctionHintAssistProvider(q);
+ m_clientProviders.quickFixAssistProvider = new LanguageClientQuickFixProvider(q);
+
+ m_documentUpdateTimer.setSingleShot(true);
+ m_documentUpdateTimer.setInterval(500);
+ connect(&m_documentUpdateTimer, &QTimer::timeout, this,
+ [this] { sendPostponedDocumentUpdates(Schedule::Now); });
+ connect(SessionManager::instance(), &SessionManager::projectRemoved,
+ q, &Client::projectClosed);
+
+ QTC_ASSERT(clientInterface, return);
+ connect(m_clientInterface, &InterfaceController::messageReceived, q, &Client::handleMessage);
+ connect(m_clientInterface, &InterfaceController::error, q, &Client::setError);
+ connect(m_clientInterface, &InterfaceController::finished, q, &Client::finished);
+ connect(m_clientInterface, &InterfaceController::started, this, [this]() {
+ LanguageClientManager::clientStarted(q);
+ });
+ connect(Core::EditorManager::instance(),
+ &Core::EditorManager::documentClosed,
+ this,
+ &ClientPrivate::documentClosed);
+
+ m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
+ m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
+
+ m_shutdownTimer.setInterval(20 /*seconds*/ * 1000);
+ connect(&m_shutdownTimer, &QTimer::timeout, this, [this] {
+ LanguageClientManager::deleteClient(q);
+ });
+ }
+
+ ~ClientPrivate()
+ {
+ using namespace TextEditor;
+ // FIXME: instead of replacing the completion provider in the text document store the
+ // completion provider as a prioritised list in the text document
+ // temporary container needed since m_resetAssistProvider is changed in resetAssistProviders
+ for (TextDocument *document : m_resetAssistProvider.keys())
+ resetAssistProviders(document);
+ const QList<Core::IEditor *> &editors = Core::DocumentModel::editorsForOpenedDocuments();
+ for (Core::IEditor *editor : editors) {
+ if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
+ TextEditorWidget *widget = textEditor->editorWidget();
+ widget->setRefactorMarkers(RefactorMarker::filterOutType(widget->refactorMarkers(), m_id));
+ widget->removeHoverHandler(&m_hoverHandler);
+ }
}
+ for (IAssistProcessor *processor : qAsConst(m_runningAssistProcessors))
+ processor->setAsyncProposalAvailable(nullptr);
+ qDeleteAll(m_documentHighlightsTimer);
+ m_documentHighlightsTimer.clear();
+ updateEditorToolBar(m_openedDocument.keys());
+ // do not handle messages while shutting down
+ disconnect(m_clientInterface, &InterfaceController::messageReceived,
+ q, &Client::handleMessage);
+ delete m_diagnosticManager;
+ delete m_clientInterface;
}
- for (IAssistProcessor *processor : qAsConst(m_runningAssistProcessors))
- processor->setAsyncProposalAvailable(nullptr);
- qDeleteAll(m_documentHighlightsTimer);
- m_documentHighlightsTimer.clear();
- updateEditorToolBar(m_openedDocument.keys());
- // do not handle messages while shutting down
- disconnect(m_clientInterface.data(), &BaseClientInterface::messageReceived,
- this, &Client::handleMessage);
+
+ Client *q;
+
+ void sendMessageNow(const JsonRpcMessage &message);
+ void handleResponse(const MessageId &id,
+ const JsonRpcMessage &message);
+ void handleMethod(const QString &method,
+ const MessageId &id,
+ const JsonRpcMessage &message);
+
+ void initializeCallback(const LanguageServerProtocol::InitializeRequest::Response &initResponse);
+ void shutDownCallback(const LanguageServerProtocol::ShutdownRequest::Response &shutdownResponse);
+ bool sendWorkspceFolderChanges() const;
+ void log(const LanguageServerProtocol::ShowMessageParams &message);
+
+ LanguageServerProtocol::LanguageClientValue<LanguageServerProtocol::MessageActionItem>
+ showMessageBox(const LanguageServerProtocol::ShowMessageRequestParams &message);
+
+ void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
+ void resetAssistProviders(TextEditor::TextDocument *document);
+
+ void sendPostponedDocumentUpdates(Schedule semanticTokensSchedule);
+
+ void updateCompletionProvider(TextEditor::TextDocument *document);
+ void updateFunctionHintProvider(TextEditor::TextDocument *document);
+
+ void requestDocumentHighlights(TextEditor::TextEditorWidget *widget);
+ void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget);
+ LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
+ void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
+ void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
+ const LanguageServerProtocol::Range &range,
+ const QList<LanguageServerProtocol::Diagnostic> &diagnostics);
+ void documentClosed(Core::IDocument *document);
+ void sendOpenNotification(const FilePath &filePath, const QString &mimeType,
+ const QString &content, int version);
+ void sendCloseNotification(const FilePath &filePath);
+ void openRequiredShadowDocuments(const TextEditor::TextDocument *doc);
+ void closeRequiredShadowDocuments(const TextEditor::TextDocument *doc);
+
+ using ShadowDocIterator = QMap<FilePath, QPair<QString, QList<const TextEditor::TextDocument *>>>::iterator;
+ void openShadowDocument(const TextEditor::TextDocument *requringDoc, ShadowDocIterator shadowIt);
+ void closeShadowDocument(ShadowDocIterator docIt);
+
+ bool reset();
+
+ Client::State m_state = Client::Uninitialized;
+ QHash<LanguageServerProtocol::MessageId,
+ LanguageServerProtocol::ResponseHandler::Callback> m_responseHandlers;
+ QString m_displayName;
+ LanguageFilter m_languagFilter;
+ QJsonObject m_initializationOptions;
+ class OpenedDocument
+ {
+ public:
+ ~OpenedDocument()
+ {
+ QObject::disconnect(contentsChangedConnection);
+ }
+ QMetaObject::Connection contentsChangedConnection;
+ QString documentContents;
+ };
+ QMap<TextEditor::TextDocument *, OpenedDocument> m_openedDocument;
+
+ // Used for build system artifacts (e.g. UI headers) that Qt Creator "live-generates" ahead of
+ // the build.
+ // The Value is the file content + the documents that require the shadow file to be open
+ // (empty <=> shadow document is not open).
+ QMap<FilePath, QPair<QString, QList<const TextEditor::TextDocument *>>> m_shadowDocuments;
+
+ QSet<TextEditor::TextDocument *> m_postponedDocuments;
+ QMap<Utils::FilePath, int> m_documentVersions;
+ std::unordered_map<TextEditor::TextDocument *,
+ QList<LanguageServerProtocol::DidChangeTextDocumentParams::TextDocumentContentChangeEvent>>
+ m_documentsToUpdate;
+ QMap<TextEditor::TextEditorWidget *, QTimer *> m_documentHighlightsTimer;
+ QTimer m_documentUpdateTimer;
+ Utils::Id m_id;
+ LanguageServerProtocol::ClientCapabilities m_clientCapabilities;
+ LanguageServerProtocol::ServerCapabilities m_serverCapabilities;
+ DynamicCapabilities m_dynamicCapabilities;
+ struct AssistProviders
+ {
+ QPointer<TextEditor::CompletionAssistProvider> completionAssistProvider;
+ QPointer<TextEditor::CompletionAssistProvider> functionHintProvider;
+ QPointer<TextEditor::IAssistProvider> quickFixAssistProvider;
+ };
+
+ AssistProviders m_clientProviders;
+ QMap<TextEditor::TextDocument *, AssistProviders> m_resetAssistProvider;
+ QHash<TextEditor::TextEditorWidget *, LanguageServerProtocol::MessageId> m_highlightRequests;
+ int m_restartsLeft = 5;
+ InterfaceController *m_clientInterface = nullptr;
+ DiagnosticManager *m_diagnosticManager = nullptr;
+ DocumentSymbolCache m_documentSymbolCache;
+ HoverHandler m_hoverHandler;
+ QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;
+ ProjectExplorer::Project *m_project = nullptr;
+ QSet<TextEditor::IAssistProcessor *> m_runningAssistProcessors;
+ SymbolSupport m_symbolSupport;
+ ProgressManager m_progressManager;
+ bool m_activateDocAutomatically = false;
+ SemanticTokenSupport m_tokenSupport;
+ QString m_serverName;
+ QString m_serverVersion;
+ LanguageServerProtocol::SymbolStringifier m_symbolStringifier;
+ Client::LogTarget m_logTarget = Client::LogTarget::Ui;
+ bool m_locatorsEnabled = true;
+ bool m_autoRequestCodeActions = true;
+ QTimer m_shutdownTimer;
+ LanguageServerProtocol::ClientInfo m_clientInfo;
+ QJsonValue m_configuration;
+};
+
+Client::Client(BaseClientInterface *clientInterface)
+ : d(new ClientPrivate(this, clientInterface))
+{}
+
+Id Client::id() const
+{
+ return d->m_id;
+}
+
+void Client::setName(const QString &name)
+{
+ d->m_displayName = name;
+}
+
+QString Client::name() const
+{
+ if (d->m_project && !d->m_project->displayName().isEmpty())
+ return tr("%1 for %2").arg(d->m_displayName, d->m_project->displayName());
+ return d->m_displayName;
+}
+
+Client::~Client()
+{
+ delete d;
}
static ClientCapabilities generateClientCapabilities()
@@ -295,52 +501,58 @@ static ClientCapabilities generateClientCapabilities()
void Client::initialize()
{
using namespace ProjectExplorer;
- QTC_ASSERT(m_clientInterface, return);
- QTC_ASSERT(m_state == Uninitialized, return);
- qCDebug(LOGLSPCLIENT) << "initializing language server " << m_displayName;
+ QTC_ASSERT(d->m_clientInterface, return);
+ QTC_ASSERT(d->m_state == Uninitialized, return);
+ qCDebug(LOGLSPCLIENT) << "initializing language server " << d->m_displayName;
InitializeParams params;
- params.setCapabilities(m_clientCapabilities);
- params.setInitializationOptions(m_initializationOptions);
- if (m_project) {
- params.setRootUri(DocumentUri::fromFilePath(m_project->projectDirectory()));
- params.setWorkSpaceFolders(Utils::transform(SessionManager::projects(), [](Project *pro) {
- return WorkSpaceFolder(DocumentUri::fromFilePath(pro->projectDirectory()),
- pro->displayName());
- }));
- }
+ params.setClientInfo(d->m_clientInfo);
+ params.setCapabilities(d->m_clientCapabilities);
+ params.setInitializationOptions(d->m_initializationOptions);
+ if (d->m_project)
+ params.setRootUri(DocumentUri::fromFilePath(d->m_project->projectDirectory()));
+
+ const QList<WorkSpaceFolder> workspaces
+ = Utils::transform(SessionManager::projects(), [](Project *pro) {
+ return WorkSpaceFolder(DocumentUri::fromFilePath(pro->projectDirectory()),
+ pro->displayName());
+ });
+ if (workspaces.isEmpty())
+ params.setWorkSpaceFolders(nullptr);
+ else
+ params.setWorkSpaceFolders(workspaces);
InitializeRequest initRequest(params);
initRequest.setResponseCallback([this](const InitializeRequest::Response &initResponse){
- initializeCallback(initResponse);
+ d->initializeCallback(initResponse);
});
if (Utils::optional<ResponseHandler> responseHandler = initRequest.responseHandler())
- m_responseHandlers[responseHandler->id] = responseHandler->callback;
+ d->m_responseHandlers[responseHandler->id] = responseHandler->callback;
- // directly send message otherwise the state check of sendContent would fail
- sendMessage(initRequest.toBaseMessage());
- m_state = InitializeRequested;
+ // directly send content now otherwise the state check of sendContent would fail
+ d->sendMessageNow(initRequest);
+ d->m_state = InitializeRequested;
}
void Client::shutdown()
{
- QTC_ASSERT(m_state == Initialized, emit finished(); return);
- qCDebug(LOGLSPCLIENT) << "shutdown language server " << m_displayName;
+ QTC_ASSERT(d->m_state == Initialized, emit finished(); return);
+ qCDebug(LOGLSPCLIENT) << "shutdown language server " << d->m_displayName;
ShutdownRequest shutdown;
shutdown.setResponseCallback([this](const ShutdownRequest::Response &shutdownResponse){
- shutDownCallback(shutdownResponse);
+ d->shutDownCallback(shutdownResponse);
});
- sendContent(shutdown);
- m_state = ShutdownRequested;
- m_shutdownTimer.start();
+ sendMessage(shutdown);
+ d->m_state = ShutdownRequested;
+ d->m_shutdownTimer.start();
}
Client::State Client::state() const
{
- return m_state;
+ return d->m_state;
}
QString Client::stateString() const
{
- switch (m_state){
+ switch (d->m_state){
case Uninitialized: return tr("uninitialized");
case InitializeRequested: return tr("initialize requested");
case Initialized: return tr("initialized");
@@ -351,6 +563,16 @@ QString Client::stateString() const
return {};
}
+bool Client::reachable() const
+{
+ return d->m_state == Initialized;
+}
+
+void Client::setClientInfo(const LanguageServerProtocol::ClientInfo &clientInfo)
+{
+ d->m_clientInfo = clientInfo;
+}
+
ClientCapabilities Client::defaultClientCapabilities()
{
return generateClientCapabilities();
@@ -358,99 +580,122 @@ ClientCapabilities Client::defaultClientCapabilities()
void Client::setClientCapabilities(const LanguageServerProtocol::ClientCapabilities &caps)
{
- m_clientCapabilities = caps;
+ d->m_clientCapabilities = caps;
}
void Client::openDocument(TextEditor::TextDocument *document)
{
using namespace TextEditor;
- if (m_openedDocument.contains(document) || !isSupportedDocument(document))
+ if (d->m_openedDocument.contains(document) || !isSupportedDocument(document))
return;
- if (m_state != Initialized) {
- m_postponedDocuments << document;
+ if (d->m_state != Initialized) {
+ d->m_postponedDocuments << document;
return;
}
const FilePath &filePath = document->filePath();
+ const auto shadowIt = d->m_shadowDocuments.find(filePath);
+ if (shadowIt != d->m_shadowDocuments.end()) {
+ d->closeShadowDocument(shadowIt);
+ emit shadowDocumentSwitched(filePath);
+ }
+ d->openRequiredShadowDocuments(document);
+
const QString method(DidOpenTextDocumentNotification::methodName);
- if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
- if (!registered.value())
+ if (Utils::optional<bool> registered = d->m_dynamicCapabilities.isRegistered(method)) {
+ if (!*registered)
return;
const TextDocumentRegistrationOptions option(
- m_dynamicCapabilities.option(method).toObject());
+ d->m_dynamicCapabilities.option(method).toObject());
if (option.isValid()
&& !option.filterApplies(filePath, Utils::mimeTypeForName(document->mimeType()))) {
return;
}
} else if (Utils::optional<ServerCapabilities::TextDocumentSync> _sync
- = m_serverCapabilities.textDocumentSync()) {
- if (auto options = Utils::get_if<TextDocumentSyncOptions>(&_sync.value())) {
+ = d->m_serverCapabilities.textDocumentSync()) {
+ if (auto options = Utils::get_if<TextDocumentSyncOptions>(&*_sync)) {
if (!options->openClose().value_or(true))
return;
}
}
- m_openedDocument[document] = document->plainText();
- connect(document, &TextDocument::contentsChangedWithPosition, this,
- [this, document](int position, int charsRemoved, int charsAdded) {
- documentContentsChanged(document, position, charsRemoved, charsAdded);
- });
- TextDocumentItem item;
- item.setLanguageId(TextDocumentItem::mimeTypeToLanguageId(document->mimeType()));
- item.setUri(DocumentUri::fromFilePath(filePath));
- item.setText(document->plainText());
- if (!m_documentVersions.contains(filePath))
- m_documentVersions[filePath] = 0;
- item.setVersion(m_documentVersions[filePath]);
- sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item)));
+ d->m_openedDocument[document].documentContents = document->plainText();
+ d->m_openedDocument[document].contentsChangedConnection
+ = connect(document,
+ &TextDocument::contentsChangedWithPosition,
+ this,
+ [this, document](int position, int charsRemoved, int charsAdded) {
+ documentContentsChanged(document, position, charsRemoved, charsAdded);
+ });
+ if (!d->m_documentVersions.contains(filePath))
+ d->m_documentVersions[filePath] = 0;
+ d->sendOpenNotification(filePath, document->mimeType(), document->plainText(),
+ d->m_documentVersions[filePath]);
handleDocumentOpened(document);
const Client *currentClient = LanguageClientManager::clientForDocument(document);
if (currentClient == this) {
// this is the active client for the document so directly activate it
activateDocument(document);
- } else if (m_activateDocAutomatically && currentClient == nullptr) {
+ } else if (d->m_activateDocAutomatically && currentClient == nullptr) {
// there is no client for this document so assign it to this server
LanguageClientManager::openDocumentWithClient(document, this);
}
}
-void Client::sendContent(const IContent &content, SendDocUpdates sendUpdates)
+void Client::sendMessage(const JsonRpcMessage &message, SendDocUpdates sendUpdates,
+ Schedule semanticTokensSchedule)
{
- QTC_ASSERT(m_clientInterface, return);
- QTC_ASSERT(m_state == Initialized, return);
+ QTC_ASSERT(d->m_clientInterface, return);
+ QTC_ASSERT(d->m_state == Initialized, return);
if (sendUpdates == SendDocUpdates::Send)
- sendPostponedDocumentUpdates(Schedule::Delayed);
- if (Utils::optional<ResponseHandler> responseHandler = content.responseHandler())
- m_responseHandlers[responseHandler->id] = responseHandler->callback;
+ d->sendPostponedDocumentUpdates(semanticTokensSchedule);
+ if (Utils::optional<ResponseHandler> responseHandler = message.responseHandler())
+ d->m_responseHandlers[responseHandler->id] = responseHandler->callback;
QString error;
- if (!QTC_GUARD(content.isValid(&error)))
+ if (!QTC_GUARD(message.isValid(&error)))
Core::MessageManager::writeFlashing(error);
- sendMessage(content.toBaseMessage());
+ d->sendMessageNow(message);
}
void Client::cancelRequest(const MessageId &id)
{
- m_responseHandlers.remove(id);
- sendContent(CancelRequest(CancelParameter(id)), SendDocUpdates::Ignore);
+ d->m_responseHandlers.remove(id);
+ if (reachable())
+ sendMessage(CancelRequest(CancelParameter(id)), SendDocUpdates::Ignore);
}
void Client::closeDocument(TextEditor::TextDocument *document)
{
deactivateDocument(document);
- const DocumentUri &uri = DocumentUri::fromFilePath(document->filePath());
- m_postponedDocuments.remove(document);
- if (m_openedDocument.remove(document) != 0) {
+ d->m_postponedDocuments.remove(document);
+ d->m_documentsToUpdate.erase(document);
+ if (d->m_openedDocument.remove(document) != 0) {
handleDocumentClosed(document);
- if (m_state == Initialized) {
- DidCloseTextDocumentParams params(TextDocumentIdentifier{uri});
- sendContent(DidCloseTextDocumentNotification(params));
+ if (d->m_state == Initialized)
+ d->sendCloseNotification(document->filePath());
+ }
+
+ if (d->m_state != Initialized)
+ return;
+ d->closeRequiredShadowDocuments(document);
+ const auto shadowIt = d->m_shadowDocuments.find(document->filePath());
+ if (shadowIt == d->m_shadowDocuments.constEnd())
+ return;
+ QTC_CHECK(shadowIt.value().second.isEmpty());
+ bool isReferenced = false;
+ for (auto it = d->m_openedDocument.cbegin(); it != d->m_openedDocument.cend(); ++it) {
+ if (referencesShadowFile(it.key(), shadowIt.key())) {
+ d->openShadowDocument(it.key(), shadowIt);
+ isReferenced = true;
}
}
+ if (isReferenced)
+ emit shadowDocumentSwitched(document->filePath());
}
-void Client::updateCompletionProvider(TextEditor::TextDocument *document)
+void ClientPrivate::updateCompletionProvider(TextEditor::TextDocument *document)
{
bool useLanguageServer = m_serverCapabilities.completionProvider().has_value();
auto clientCompletionProvider = static_cast<LanguageClientCompletionAssistProvider *>(
@@ -478,7 +723,7 @@ void Client::updateCompletionProvider(TextEditor::TextDocument *document)
}
}
-void Client::updateFunctionHintProvider(TextEditor::TextDocument *document)
+void ClientPrivate::updateFunctionHintProvider(TextEditor::TextDocument *document)
{
bool useLanguageServer = m_serverCapabilities.signatureHelpProvider().has_value();
auto clientFunctionHintProvider = static_cast<FunctionHintAssistProvider *>(
@@ -506,13 +751,13 @@ void Client::updateFunctionHintProvider(TextEditor::TextDocument *document)
}
}
-void Client::requestDocumentHighlights(TextEditor::TextEditorWidget *widget)
+void ClientPrivate::requestDocumentHighlights(TextEditor::TextEditorWidget *widget)
{
QTimer *timer = m_documentHighlightsTimer[widget];
if (!timer) {
const auto uri = DocumentUri::fromFilePath(widget->textDocument()->filePath());
if (m_highlightRequests.contains(widget))
- cancelRequest(m_highlightRequests.take(widget));
+ q->cancelRequest(m_highlightRequests.take(widget));
timer = new QTimer;
timer->setSingleShot(true);
m_documentHighlightsTimer.insert(widget, timer);
@@ -528,7 +773,7 @@ void Client::requestDocumentHighlights(TextEditor::TextEditorWidget *widget)
timer->start(250);
}
-void Client::requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget)
+void ClientPrivate::requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget)
{
const auto uri = DocumentUri::fromFilePath(widget->textDocument()->filePath());
if (m_dynamicCapabilities.isRegistered(DocumentHighlightsRequest::methodName).value_or(false)) {
@@ -546,15 +791,15 @@ void Client::requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget)
}
if (m_highlightRequests.contains(widget))
- cancelRequest(m_highlightRequests.take(widget));
+ q->cancelRequest(m_highlightRequests.take(widget));
- const QTextCursor adjustedCursor = adjustedCursorForHighlighting(widget->textCursor(),
- widget->textDocument());
+ const QTextCursor adjustedCursor = q->adjustedCursorForHighlighting(widget->textCursor(),
+ widget->textDocument());
DocumentHighlightsRequest request(
TextDocumentPositionParams(TextDocumentIdentifier(uri), Position{adjustedCursor}));
auto connection = connect(widget, &QObject::destroyed, this, [this, widget]() {
if (m_highlightRequests.contains(widget))
- cancelRequest(m_highlightRequests.take(widget));
+ q->cancelRequest(m_highlightRequests.take(widget));
});
request.setResponseCallback(
[widget, this, uri, connection]
@@ -565,7 +810,7 @@ void Client::requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget)
const Id &id = TextEditor::TextEditorWidget::CodeSemanticsSelection;
QList<QTextEdit::ExtraSelection> selections;
const Utils::optional<DocumentHighlightsResult> &result = response.result();
- if (!result.has_value() || holds_alternative<std::nullptr_t>(result.value())) {
+ if (!result.has_value() || holds_alternative<std::nullptr_t>(*result)) {
widget->setExtraSelections(id, selections);
return;
}
@@ -573,7 +818,7 @@ void Client::requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget)
const QTextCharFormat &format =
widget->textDocument()->fontSettings().toTextCharFormat(TextEditor::C_OCCURRENCES);
QTextDocument *document = widget->document();
- for (const auto &highlight : get<QList<DocumentHighlight>>(result.value())) {
+ for (const auto &highlight : get<QList<DocumentHighlight>>(*result)) {
QTextEdit::ExtraSelection selection{widget->textCursor(), format};
const int &start = highlight.range().start().toPositionInDocument(document);
const int &end = highlight.range().end().toPositionInDocument(document);
@@ -586,29 +831,30 @@ void Client::requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget)
widget->setExtraSelections(id, selections);
});
m_highlightRequests[widget] = request.id();
- sendContent(request);
+ q->sendMessage(request);
}
void Client::activateDocument(TextEditor::TextDocument *document)
{
const FilePath &filePath = document->filePath();
auto uri = DocumentUri::fromFilePath(filePath);
- m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(filePath));
- m_tokenSupport.updateSemanticTokens(document);
+ if (d->m_diagnosticManager)
+ d->m_diagnosticManager->showDiagnostics(uri, d->m_documentVersions.value(filePath));
+ d->m_tokenSupport.updateSemanticTokens(document);
// only replace the assist provider if the language server support it
- updateCompletionProvider(document);
- updateFunctionHintProvider(document);
- if (m_serverCapabilities.codeActionProvider()) {
- m_resetAssistProvider[document].quickFixAssistProvider = document->quickFixAssistProvider();
- document->setQuickFixAssistProvider(m_clientProviders.quickFixAssistProvider);
+ d->updateCompletionProvider(document);
+ d->updateFunctionHintProvider(document);
+ if (d->m_serverCapabilities.codeActionProvider()) {
+ d->m_resetAssistProvider[document].quickFixAssistProvider = document->quickFixAssistProvider();
+ document->setQuickFixAssistProvider(d->m_clientProviders.quickFixAssistProvider);
}
document->setFormatter(new LanguageClientFormatter(document, this));
for (Core::IEditor *editor : Core::DocumentModel::editorsForDocument(document)) {
updateEditorToolBar(editor);
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor)) {
TextEditor::TextEditorWidget *widget = textEditor->editorWidget();
- widget->addHoverHandler(&m_hoverHandler);
- requestDocumentHighlights(widget);
+ widget->addHoverHandler(&d->m_hoverHandler);
+ d->requestDocumentHighlights(widget);
if (symbolSupport().supportsRename(document))
widget->addOptionalActions(TextEditor::TextEditorActionHandler::RenameSymbol);
}
@@ -617,100 +863,189 @@ void Client::activateDocument(TextEditor::TextDocument *document)
void Client::deactivateDocument(TextEditor::TextDocument *document)
{
- m_diagnosticManager.hideDiagnostics(document->filePath());
- resetAssistProviders(document);
+ if (d->m_diagnosticManager)
+ d->m_diagnosticManager->hideDiagnostics(document->filePath());
+ d->resetAssistProviders(document);
document->setFormatter(nullptr);
- m_tokenSupport.clearHighlight(document);
+ d->m_tokenSupport.clearHighlight(document);
for (Core::IEditor *editor : Core::DocumentModel::editorsForDocument(document)) {
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor)) {
TextEditor::TextEditorWidget *widget = textEditor->editorWidget();
- widget->removeHoverHandler(&m_hoverHandler);
+ widget->removeHoverHandler(&d->m_hoverHandler);
widget->setExtraSelections(TextEditor::TextEditorWidget::CodeSemanticsSelection, {});
}
}
}
-void Client::documentClosed(Core::IDocument *document)
+void ClientPrivate::documentClosed(Core::IDocument *document)
{
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
- closeDocument(textDocument);
+ q->closeDocument(textDocument);
+}
+
+void ClientPrivate::sendOpenNotification(const FilePath &filePath, const QString &mimeType,
+ const QString &content, int version)
+{
+ TextDocumentItem item;
+ item.setLanguageId(TextDocumentItem::mimeTypeToLanguageId(mimeType));
+ item.setUri(DocumentUri::fromFilePath(filePath));
+ item.setText(content);
+ item.setVersion(version);
+ q->sendMessage(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item)),
+ Client::SendDocUpdates::Ignore);
+}
+
+void ClientPrivate::sendCloseNotification(const FilePath &filePath)
+{
+ q->sendMessage(DidCloseTextDocumentNotification(DidCloseTextDocumentParams(
+ TextDocumentIdentifier{DocumentUri::fromFilePath(filePath)})),
+ Client::SendDocUpdates::Ignore);
+}
+
+void ClientPrivate::openRequiredShadowDocuments(const TextEditor::TextDocument *doc)
+{
+ for (auto it = m_shadowDocuments.begin(); it != m_shadowDocuments.end(); ++it) {
+ if (!it.value().second.contains(doc) && q->referencesShadowFile(doc, it.key()))
+ openShadowDocument(doc, it);
+ }
+}
+
+void ClientPrivate::closeRequiredShadowDocuments(const TextEditor::TextDocument *doc)
+{
+ for (auto it = m_shadowDocuments.begin(); it != m_shadowDocuments.end(); ++it) {
+ if (it.value().second.removeOne(doc) && it.value().second.isEmpty())
+ closeShadowDocument(it);
+ }
}
bool Client::documentOpen(const TextEditor::TextDocument *document) const
{
- return m_openedDocument.contains(const_cast<TextEditor::TextDocument *>(document));
+ return d->m_openedDocument.contains(const_cast<TextEditor::TextDocument *>(document));
}
TextEditor::TextDocument *Client::documentForFilePath(const Utils::FilePath &file) const
{
- for (auto it = m_openedDocument.cbegin(); it != m_openedDocument.cend(); ++it) {
+ for (auto it = d->m_openedDocument.cbegin(); it != d->m_openedDocument.cend(); ++it) {
if (it.key()->filePath() == file)
return it.key();
}
return nullptr;
}
+void Client::setShadowDocument(const Utils::FilePath &filePath, const QString &content)
+{
+ QTC_ASSERT(reachable(), return);
+ auto shadowIt = d->m_shadowDocuments.find(filePath);
+ if (shadowIt == d->m_shadowDocuments.end()) {
+ shadowIt = d->m_shadowDocuments.insert(filePath, {content, {}});
+ } else {
+ shadowIt.value().first = content;
+ if (!shadowIt.value().second.isEmpty()) {
+ VersionedTextDocumentIdentifier docId(DocumentUri::fromFilePath(filePath));
+ docId.setVersion(++d->m_documentVersions[filePath]);
+ const DidChangeTextDocumentParams params(docId, content);
+ sendMessage(DidChangeTextDocumentNotification(params), SendDocUpdates::Ignore);
+ return;
+ }
+ }
+ if (documentForFilePath(filePath))
+ return;
+ for (auto docIt = d->m_openedDocument.cbegin(); docIt != d->m_openedDocument.cend(); ++docIt) {
+ if (referencesShadowFile(docIt.key(), filePath))
+ d->openShadowDocument(docIt.key(), shadowIt);
+ }
+}
+
+void Client::removeShadowDocument(const Utils::FilePath &filePath)
+{
+ const auto it = d->m_shadowDocuments.find(filePath);
+ if (it == d->m_shadowDocuments.end())
+ return;
+ if (!it.value().second.isEmpty())
+ d->closeShadowDocument(it);
+ d->m_shadowDocuments.erase(it);
+}
+
+void ClientPrivate::openShadowDocument(const TextEditor::TextDocument *requringDoc,
+ ShadowDocIterator shadowIt)
+{
+ shadowIt.value().second << requringDoc;
+ if (shadowIt.value().second.size() > 1)
+ return;
+ const auto uri = DocumentUri::fromFilePath(shadowIt.key());
+ const QString mimeType = mimeTypeForFile(shadowIt.key(), MimeMatchMode::MatchExtension).name();
+ sendOpenNotification(shadowIt.key(), mimeType, shadowIt.value().first,
+ ++m_documentVersions[shadowIt.key()]);
+}
+
+void ClientPrivate::closeShadowDocument(ShadowDocIterator shadowIt)
+{
+ sendCloseNotification(shadowIt.key());
+ shadowIt.value().second.clear();
+}
+
void Client::documentContentsSaved(TextEditor::TextDocument *document)
{
- if (!m_openedDocument.contains(document))
+ if (!d->m_openedDocument.contains(document))
return;
- bool sendMessage = true;
+ bool send = true;
bool includeText = false;
const QString method(DidSaveTextDocumentNotification::methodName);
- if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
- sendMessage = registered.value();
- if (sendMessage) {
+ if (Utils::optional<bool> registered = d->m_dynamicCapabilities.isRegistered(method)) {
+ send = *registered;
+ if (send) {
const TextDocumentSaveRegistrationOptions option(
- m_dynamicCapabilities.option(method).toObject());
+ d->m_dynamicCapabilities.option(method).toObject());
if (option.isValid()) {
- sendMessage = option.filterApplies(document->filePath(),
+ send = option.filterApplies(document->filePath(),
Utils::mimeTypeForName(document->mimeType()));
includeText = option.includeText().value_or(includeText);
}
}
} else if (Utils::optional<ServerCapabilities::TextDocumentSync> _sync
- = m_serverCapabilities.textDocumentSync()) {
- if (auto options = Utils::get_if<TextDocumentSyncOptions>(&_sync.value())) {
+ = d->m_serverCapabilities.textDocumentSync()) {
+ if (auto options = Utils::get_if<TextDocumentSyncOptions>(&*_sync)) {
if (Utils::optional<SaveOptions> saveOptions = options->save())
- includeText = saveOptions.value().includeText().value_or(includeText);
+ includeText = saveOptions->includeText().value_or(includeText);
}
}
- if (!sendMessage)
+ if (!send)
return;
DidSaveTextDocumentParams params(
TextDocumentIdentifier(DocumentUri::fromFilePath(document->filePath())));
+ d->openRequiredShadowDocuments(document);
if (includeText)
params.setText(document->plainText());
- sendContent(DidSaveTextDocumentNotification(params));
+ sendMessage(DidSaveTextDocumentNotification(params), SendDocUpdates::Send, Schedule::Now);
}
void Client::documentWillSave(Core::IDocument *document)
{
const FilePath &filePath = document->filePath();
auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
- if (!m_openedDocument.contains(textDocument))
+ if (!d->m_openedDocument.contains(textDocument))
return;
- bool sendMessage = false;
+ bool send = false;
const QString method(WillSaveTextDocumentNotification::methodName);
- if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
- sendMessage = registered.value();
- if (sendMessage) {
- const TextDocumentRegistrationOptions option(m_dynamicCapabilities.option(method));
+ if (Utils::optional<bool> registered = d->m_dynamicCapabilities.isRegistered(method)) {
+ send = *registered;
+ if (send) {
+ const TextDocumentRegistrationOptions option(d->m_dynamicCapabilities.option(method));
if (option.isValid()) {
- sendMessage = option.filterApplies(filePath,
+ send = option.filterApplies(filePath,
Utils::mimeTypeForName(document->mimeType()));
}
}
} else if (Utils::optional<ServerCapabilities::TextDocumentSync> _sync
- = m_serverCapabilities.textDocumentSync()) {
- if (auto options = Utils::get_if<TextDocumentSyncOptions>(&_sync.value()))
- sendMessage = options->willSave().value_or(sendMessage);
+ = d->m_serverCapabilities.textDocumentSync()) {
+ if (auto options = Utils::get_if<TextDocumentSyncOptions>(&*_sync))
+ send = options->willSave().value_or(send);
}
- if (!sendMessage)
+ if (!send)
return;
const WillSaveTextDocumentParams params(
TextDocumentIdentifier(DocumentUri::fromFilePath(filePath)));
- sendContent(WillSaveTextDocumentNotification(params));
+ sendMessage(WillSaveTextDocumentNotification(params));
}
void Client::documentContentsChanged(TextEditor::TextDocument *document,
@@ -718,15 +1053,17 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
int charsRemoved,
int charsAdded)
{
- if (!m_openedDocument.contains(document) || !reachable())
+ if (!d->m_openedDocument.contains(document) || !reachable())
return;
+ if (d->m_diagnosticManager)
+ d->m_diagnosticManager->disableDiagnostics(document);
const QString method(DidChangeTextDocumentNotification::methodName);
- TextDocumentSyncKind syncKind = m_serverCapabilities.textDocumentSyncKindHelper();
- if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
- syncKind = registered.value() ? TextDocumentSyncKind::Full : TextDocumentSyncKind::None;
+ TextDocumentSyncKind syncKind = d->m_serverCapabilities.textDocumentSyncKindHelper();
+ if (Utils::optional<bool> registered = d->m_dynamicCapabilities.isRegistered(method)) {
+ syncKind = *registered ? TextDocumentSyncKind::Full : TextDocumentSyncKind::None;
if (syncKind != TextDocumentSyncKind::None) {
const TextDocumentChangeRegistrationOptions option(
- m_dynamicCapabilities.option(method).toObject());
+ d->m_dynamicCapabilities.option(method).toObject());
syncKind = option.isValid() ? option.syncKind() : syncKind;
}
}
@@ -739,7 +1076,7 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
// this will save a lot of TextDocumentContentChangeEvent elements in the data stream,
// as otherwise we'd send tons of single-character changes.
const QString &text = document->textAt(position, charsAdded);
- auto &queue = m_documentsToUpdate[document];
+ auto &queue = d->m_documentsToUpdate[document];
bool append = true;
if (!queue.isEmpty() && charsRemoved == 0) {
auto &prev = queue.last();
@@ -751,7 +1088,7 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
}
}
if (append) {
- QTextDocument oldDoc(m_openedDocument[document]);
+ QTextDocument oldDoc(d->m_openedDocument[document].documentContents);
QTextCursor cursor(&oldDoc);
// Workaround https://bugreports.qt.io/browse/QTBUG-80662
// The contentsChanged gives a character count that can be wrong for QTextCursor
@@ -769,64 +1106,79 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
queue << change;
}
} else {
- m_documentsToUpdate[document] = {
+ d->m_documentsToUpdate[document] = {
DidChangeTextDocumentParams::TextDocumentContentChangeEvent(document->plainText())};
}
- m_openedDocument[document] = document->plainText();
+ d->m_openedDocument[document].documentContents = document->plainText();
}
- ++m_documentVersions[document->filePath()];
+ ++d->m_documentVersions[document->filePath()];
using namespace TextEditor;
for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(document)) {
TextEditorWidget *widget = editor->editorWidget();
QTC_ASSERT(widget, continue);
- delete m_documentHighlightsTimer.take(widget);
+ delete d->m_documentHighlightsTimer.take(widget);
widget->setRefactorMarkers(RefactorMarker::filterOutType(widget->refactorMarkers(), id()));
}
- m_documentUpdateTimer.start();
+ d->m_documentUpdateTimer.start();
}
void Client::registerCapabilities(const QList<Registration> &registrations)
{
- m_dynamicCapabilities.registerCapability(registrations);
+ d->m_dynamicCapabilities.registerCapability(registrations);
for (const Registration &registration : registrations) {
if (registration.method() == CompletionRequest::methodName) {
- for (auto document : m_openedDocument.keys())
- updateCompletionProvider(document);
+ for (auto document : d->m_openedDocument.keys())
+ d->updateCompletionProvider(document);
}
if (registration.method() == SignatureHelpRequest::methodName) {
- for (auto document : m_openedDocument.keys())
- updateFunctionHintProvider(document);
+ for (auto document : d->m_openedDocument.keys())
+ d->updateFunctionHintProvider(document);
}
if (registration.method() == "textDocument/semanticTokens") {
SemanticTokensOptions options(registration.registerOptions());
if (options.isValid())
- m_tokenSupport.setLegend(options.legend());
- for (auto document : m_openedDocument.keys())
- m_tokenSupport.updateSemanticTokens(document);
+ d->m_tokenSupport.setLegend(options.legend());
+ for (auto document : d->m_openedDocument.keys())
+ d->m_tokenSupport.updateSemanticTokens(document);
}
}
- emit capabilitiesChanged(m_dynamicCapabilities);
+ emit capabilitiesChanged(d->m_dynamicCapabilities);
}
void Client::unregisterCapabilities(const QList<Unregistration> &unregistrations)
{
- m_dynamicCapabilities.unregisterCapability(unregistrations);
+ d->m_dynamicCapabilities.unregisterCapability(unregistrations);
for (const Unregistration &unregistration : unregistrations) {
if (unregistration.method() == CompletionRequest::methodName) {
- for (auto document : m_openedDocument.keys())
- updateCompletionProvider(document);
+ for (auto document : d->m_openedDocument.keys())
+ d->updateCompletionProvider(document);
}
if (unregistration.method() == SignatureHelpRequest::methodName) {
- for (auto document : m_openedDocument.keys())
- updateFunctionHintProvider(document);
+ for (auto document : d->m_openedDocument.keys())
+ d->updateFunctionHintProvider(document);
}
if (unregistration.method() == "textDocument/semanticTokens") {
- for (auto document : m_openedDocument.keys())
- m_tokenSupport.updateSemanticTokens(document);
+ for (auto document : d->m_openedDocument.keys())
+ d->m_tokenSupport.updateSemanticTokens(document);
}
}
- emit capabilitiesChanged(m_dynamicCapabilities);
+ emit capabilitiesChanged(d->m_dynamicCapabilities);
+}
+
+void Client::setLocatorsEnabled(bool enabled)
+{
+ d->m_locatorsEnabled = enabled;
+}
+
+bool Client::locatorsEnabled() const
+{
+ return d->m_locatorsEnabled;
+}
+
+void Client::setAutoRequestCodeActions(bool enabled)
+{
+ d->m_autoRequestCodeActions = enabled;
}
TextEditor::HighlightingResult createHighlightingResult(const SymbolInformation &info)
@@ -843,9 +1195,9 @@ TextEditor::HighlightingResult createHighlightingResult(const SymbolInformation
void Client::cursorPositionChanged(TextEditor::TextEditorWidget *widget)
{
TextEditor::TextDocument *document = widget->textDocument();
- if (m_documentsToUpdate.find(document) != m_documentsToUpdate.end())
+ if (d->m_documentsToUpdate.find(document) != d->m_documentsToUpdate.end())
return; // we are currently changing this document so postpone the DocumentHighlightsRequest
- requestDocumentHighlights(widget);
+ d->requestDocumentHighlights(widget);
const Id selectionsId(TextEditor::TextEditorWidget::CodeSemanticsSelection);
const QList semanticSelections = widget->extraSelections(selectionsId);
if (!semanticSelections.isEmpty()) {
@@ -861,11 +1213,24 @@ void Client::cursorPositionChanged(TextEditor::TextEditorWidget *widget)
SymbolSupport &Client::symbolSupport()
{
- return m_symbolSupport;
+ return d->m_symbolSupport;
+}
+
+void Client::requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
+ const LanguageServerProtocol::Diagnostic &diagnostic)
+{
+ d->requestCodeActions(uri, diagnostic.range(), {diagnostic});
}
void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic> &diagnostics)
{
+ d->requestCodeActions(uri, {}, diagnostics);
+}
+
+void ClientPrivate::requestCodeActions(const DocumentUri &uri,
+ const Range &range,
+ const QList<Diagnostic> &diagnostics)
+{
const Utils::FilePath fileName = uri.toFilePath();
TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath(fileName);
if (!doc)
@@ -876,17 +1241,21 @@ void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic>
context.setDiagnostics(diagnostics);
codeActionParams.setContext(context);
codeActionParams.setTextDocument(TextDocumentIdentifier(uri));
- Position start(0, 0);
- const QTextBlock &lastBlock = doc->document()->lastBlock();
- Position end(lastBlock.blockNumber(), lastBlock.length() - 1);
- codeActionParams.setRange(Range(start, end));
+ if (range.isEmpty()) {
+ Position start(0, 0);
+ const QTextBlock &lastBlock = doc->document()->lastBlock();
+ Position end(lastBlock.blockNumber(), lastBlock.length() - 1);
+ codeActionParams.setRange(Range(start, end));
+ } else {
+ codeActionParams.setRange(range);
+ }
CodeActionRequest request(codeActionParams);
request.setResponseCallback(
- [uri, self = QPointer<Client>(this)](const CodeActionRequest::Response &response) {
- if (self)
- self->handleCodeActionResponse(response, uri);
+ [uri, q = QPointer<Client>(q)](const CodeActionRequest::Response &response) {
+ if (q)
+ q->handleCodeActionResponse(response, uri);
});
- requestCodeActions(request);
+ q->requestCodeActions(request);
}
void Client::requestCodeActions(const CodeActionRequest &request)
@@ -898,21 +1267,21 @@ void Client::requestCodeActions(const CodeActionRequest &request)
= request.params().value_or(CodeActionParams()).textDocument().uri().toFilePath();
const QString method(CodeActionRequest::methodName);
- if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
- if (!registered.value())
+ if (Utils::optional<bool> registered = d->m_dynamicCapabilities.isRegistered(method)) {
+ if (!*registered)
return;
const TextDocumentRegistrationOptions option(
- m_dynamicCapabilities.option(method).toObject());
+ d->m_dynamicCapabilities.option(method).toObject());
if (option.isValid() && !option.filterApplies(fileName))
return;
} else {
Utils::variant<bool, CodeActionOptions> provider
- = m_serverCapabilities.codeActionProvider().value_or(false);
+ = d->m_serverCapabilities.codeActionProvider().value_or(false);
if (!(Utils::holds_alternative<CodeActionOptions>(provider) || Utils::get<bool>(provider)))
return;
}
- sendContent(request);
+ sendMessage(request);
}
void Client::handleCodeActionResponse(const CodeActionRequest::Response &response,
@@ -920,54 +1289,54 @@ void Client::handleCodeActionResponse(const CodeActionRequest::Response &respons
{
if (const Utils::optional<CodeActionRequest::Response::Error> &error = response.error())
log(*error);
- if (const Utils::optional<CodeActionResult> &_result = response.result()) {
- const CodeActionResult &result = _result.value();
- if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&result)) {
+ if (const Utils::optional<CodeActionResult> &result = response.result()) {
+ if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&*result)) {
+ QList<CodeAction> codeActions;
for (const Utils::variant<Command, CodeAction> &item : *list) {
if (auto action = Utils::get_if<CodeAction>(&item))
- updateCodeActionRefactoringMarker(this, *action, uri);
- else if (auto command = Utils::get_if<Command>(&item)) {
+ codeActions << *action;
+ else if (auto command = Utils::get_if<Command>(&item))
Q_UNUSED(command) // todo
- }
}
+ updateCodeActionRefactoringMarker(this, codeActions, uri);
}
}
}
void Client::executeCommand(const Command &command)
{
- bool serverSupportsExecuteCommand = m_serverCapabilities.executeCommandProvider().has_value();
- serverSupportsExecuteCommand = m_dynamicCapabilities
+ bool serverSupportsExecuteCommand = d->m_serverCapabilities.executeCommandProvider().has_value();
+ serverSupportsExecuteCommand = d->m_dynamicCapabilities
.isRegistered(ExecuteCommandRequest::methodName)
.value_or(serverSupportsExecuteCommand);
if (serverSupportsExecuteCommand)
- sendContent(ExecuteCommandRequest(ExecuteCommandParams(command)));
+ sendMessage(ExecuteCommandRequest(ExecuteCommandParams(command)));
}
ProjectExplorer::Project *Client::project() const
{
- return m_project;
+ return d->m_project;
}
void Client::setCurrentProject(ProjectExplorer::Project *project)
{
- if (m_project == project)
+ if (d->m_project == project)
return;
- if (m_project)
- m_project->disconnect(this);
- m_project = project;
- if (m_project) {
- connect(m_project, &ProjectExplorer::Project::destroyed, this, [this]() {
+ if (d->m_project)
+ d->m_project->disconnect(this);
+ d->m_project = project;
+ if (d->m_project) {
+ connect(d->m_project, &ProjectExplorer::Project::destroyed, this, [this]() {
// the project of the client should already be null since we expect the session and
// the language client manager to reset it before it gets deleted.
- QTC_ASSERT(m_project == nullptr, projectClosed(m_project));
+ QTC_ASSERT(d->m_project == nullptr, projectClosed(d->m_project));
});
}
}
void Client::projectOpened(ProjectExplorer::Project *project)
{
- if (!sendWorkspceFolderChanges())
+ if (!d->sendWorkspceFolderChanges())
return;
WorkspaceFoldersChangeEvent event;
event.setAdded({WorkSpaceFolder(DocumentUri::fromFilePath(project->projectDirectory()),
@@ -975,143 +1344,196 @@ void Client::projectOpened(ProjectExplorer::Project *project)
DidChangeWorkspaceFoldersParams params;
params.setEvent(event);
DidChangeWorkspaceFoldersNotification change(params);
- sendContent(change);
+ sendMessage(change);
}
void Client::projectClosed(ProjectExplorer::Project *project)
{
- if (sendWorkspceFolderChanges()) {
+ if (d->sendWorkspceFolderChanges()) {
WorkspaceFoldersChangeEvent event;
event.setRemoved({WorkSpaceFolder(DocumentUri::fromFilePath(project->projectDirectory()),
project->displayName())});
DidChangeWorkspaceFoldersParams params;
params.setEvent(event);
DidChangeWorkspaceFoldersNotification change(params);
- sendContent(change);
+ sendMessage(change);
}
- if (project == m_project) {
- if (m_state == Initialized) {
+ if (project == d->m_project) {
+ if (d->m_state == Initialized) {
shutdown();
} else {
- m_state = Shutdown; // otherwise the manager would try to restart this server
+ d->m_state = Shutdown; // otherwise the manager would try to restart this server
emit finished();
}
- m_project = nullptr;
+ d->m_project = nullptr;
+ }
+}
+
+void Client::updateConfiguration(const QJsonValue &configuration)
+{
+ d->m_configuration = configuration;
+ if (reachable() && !configuration.isNull()
+ && d->m_dynamicCapabilities.isRegistered(DidChangeConfigurationNotification::methodName)
+ .value_or(true)) {
+ DidChangeConfigurationParams params;
+ params.setSettings(configuration);
+ DidChangeConfigurationNotification notification(params);
+ sendMessage(notification);
}
}
void Client::setSupportedLanguage(const LanguageFilter &filter)
{
- m_languagFilter = filter;
+ d->m_languagFilter = filter;
}
void Client::setActivateDocumentAutomatically(bool enabled)
{
- m_activateDocAutomatically = enabled;
+ d->m_activateDocAutomatically = enabled;
}
void Client::setInitializationOptions(const QJsonObject &initializationOptions)
{
- m_initializationOptions = initializationOptions;
+ d->m_initializationOptions = initializationOptions;
}
bool Client::isSupportedDocument(const TextEditor::TextDocument *document) const
{
QTC_ASSERT(document, return false);
- return m_languagFilter.isSupported(document);
+ return d->m_languagFilter.isSupported(document);
}
bool Client::isSupportedFile(const Utils::FilePath &filePath, const QString &mimeType) const
{
- return m_languagFilter.isSupported(filePath, mimeType);
+ return d->m_languagFilter.isSupported(filePath, mimeType);
}
bool Client::isSupportedUri(const DocumentUri &uri) const
{
const FilePath &filePath = uri.toFilePath();
- return m_languagFilter.isSupported(filePath, Utils::mimeTypeForFile(filePath).name());
+ return d->m_languagFilter.isSupported(filePath, Utils::mimeTypeForFile(filePath).name());
}
void Client::addAssistProcessor(TextEditor::IAssistProcessor *processor)
{
- m_runningAssistProcessors.insert(processor);
+ d->m_runningAssistProcessors.insert(processor);
}
void Client::removeAssistProcessor(TextEditor::IAssistProcessor *processor)
{
- m_runningAssistProcessors.remove(processor);
+ d->m_runningAssistProcessors.remove(processor);
}
QList<Diagnostic> Client::diagnosticsAt(const DocumentUri &uri, const QTextCursor &cursor) const
{
- return m_diagnosticManager.diagnosticsAt(uri, cursor);
+ if (d->m_diagnosticManager)
+ return d->m_diagnosticManager->diagnosticsAt(uri, cursor);
+ return {};
}
bool Client::hasDiagnostic(const LanguageServerProtocol::DocumentUri &uri,
const LanguageServerProtocol::Diagnostic &diag) const
{
- return m_diagnosticManager.hasDiagnostic(uri, documentForFilePath(uri.toFilePath()), diag);
+ if (d->m_diagnosticManager)
+ return d->m_diagnosticManager->hasDiagnostic(uri, documentForFilePath(uri.toFilePath()), diag);
+ return false;
+}
+
+bool Client::hasDiagnostics(const TextEditor::TextDocument *document) const
+{
+ if (d->m_diagnosticManager)
+ return d->m_diagnosticManager->hasDiagnostics(document);
+ return false;
}
-void Client::setDiagnosticsHandlers(const TextMarkCreator &textMarkCreator,
- const HideDiagnosticsHandler &hideHandler,
- const DiagnosticsFilter &filter)
+DiagnosticManager *Client::createDiagnosticManager()
{
- m_diagnosticManager.setDiagnosticsHandlers(textMarkCreator, hideHandler, filter);
+ return new DiagnosticManager(this);
}
void Client::setSemanticTokensHandler(const SemanticTokensHandler &handler)
{
- m_tokenSupport.setTokensHandler(handler);
+ d->m_tokenSupport.setTokensHandler(handler);
}
void Client::setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier)
{
- m_symbolStringifier = stringifier;
+ d->m_symbolStringifier = stringifier;
}
SymbolStringifier Client::symbolStringifier() const
{
- return m_symbolStringifier;
+ return d->m_symbolStringifier;
}
void Client::setSnippetsGroup(const QString &group)
{
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(
- m_clientProviders.completionAssistProvider)) {
+ d->m_clientProviders.completionAssistProvider)) {
provider->setSnippetsGroup(group);
}
}
void Client::setCompletionAssistProvider(LanguageClientCompletionAssistProvider *provider)
{
- delete m_clientProviders.completionAssistProvider;
- m_clientProviders.completionAssistProvider = provider;
+ delete d->m_clientProviders.completionAssistProvider;
+ d->m_clientProviders.completionAssistProvider = provider;
+}
+
+void Client::setQuickFixAssistProvider(LanguageClientQuickFixProvider *provider)
+{
+ delete d->m_clientProviders.quickFixAssistProvider;
+ d->m_clientProviders.quickFixAssistProvider = provider;
+}
+
+bool Client::supportsDocumentSymbols(const TextEditor::TextDocument *doc) const
+{
+ if (!doc)
+ return false;
+ DynamicCapabilities dc = dynamicCapabilities();
+ if (dc.isRegistered(DocumentSymbolsRequest::methodName).value_or(false)) {
+ TextDocumentRegistrationOptions options(dc.option(DocumentSymbolsRequest::methodName));
+ return !options.isValid()
+ || options.filterApplies(doc->filePath(), Utils::mimeTypeForName(doc->mimeType()));
+ }
+ const Utils::optional<Utils::variant<bool, WorkDoneProgressOptions>> &provider
+ = capabilities().documentSymbolProvider();
+ if (!provider.has_value())
+ return false;
+ if (Utils::holds_alternative<bool>(*provider))
+ return Utils::get<bool>(*provider);
+ return true;
+}
+
+void Client::setLogTarget(LogTarget target)
+{
+ d->m_logTarget = target;
}
void Client::start()
{
LanguageClientManager::addClient(this);
- if (m_clientInterface->start())
- LanguageClientManager::clientStarted(this);
- else
- LanguageClientManager::clientFinished(this);
+ d->m_clientInterface->start();
}
bool Client::reset()
{
+ return d->reset();
+}
+
+bool ClientPrivate::reset()
+{
if (!m_restartsLeft)
return false;
--m_restartsLeft;
- m_state = Uninitialized;
+ m_state = Client::Uninitialized;
m_responseHandlers.clear();
m_clientInterface->resetBuffer();
updateEditorToolBar(m_openedDocument.keys());
m_serverCapabilities = ServerCapabilities();
m_dynamicCapabilities.reset();
- m_diagnosticManager.clearDiagnostics();
- for (auto it = m_openedDocument.cbegin(); it != m_openedDocument.cend(); ++it)
- it.key()->disconnect(this);
+ if (m_diagnosticManager)
+ m_diagnosticManager->clearDiagnostics();
m_openedDocument.clear();
// temporary container needed since m_resetAssistProvider is changed in resetAssistProviders
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())
@@ -1122,6 +1544,8 @@ bool Client::reset()
qDeleteAll(m_documentHighlightsTimer);
m_documentHighlightsTimer.clear();
m_progressManager.reset();
+ for (auto &doc : m_shadowDocuments)
+ doc.second.clear();
m_documentVersions.clear();
return true;
}
@@ -1129,37 +1553,29 @@ bool Client::reset()
void Client::setError(const QString &message)
{
log(message);
- m_state = Error;
+ d->m_state = Error;
}
void Client::setProgressTitleForToken(const LanguageServerProtocol::ProgressToken &token,
const QString &message)
{
- m_progressManager.setTitleForToken(token, message);
+ d->m_progressManager.setTitleForToken(token, message);
}
-void Client::handleMessage(const BaseMessage &message)
+void Client::handleMessage(const LanguageServerProtocol::JsonRpcMessage &message)
{
- LanguageClientManager::logBaseMessage(LspLogMessage::ServerMessage, name(), message);
- if (auto handler = m_contentHandler[message.mimeType]) {
- QString parseError;
- handler(message.content, message.codec, parseError,
- [this](const MessageId &id, const QByteArray &content, QTextCodec *codec){
- this->handleResponse(id, content, codec);
- },
- [this](const QString &method, const MessageId &id, const IContent *content){
- this->handleMethod(method, id, content);
- });
- if (!parseError.isEmpty())
- log(parseError);
- } else {
- log(tr("Cannot handle content of type: %1").arg(QLatin1String(message.mimeType)));
- }
+ LanguageClientManager::logJsonRpcMessage(LspLogMessage::ServerMessage, name(), message);
+ const MessageId id(message.toJsonObject().value(idKey));
+ const QString method = message.toJsonObject().value(methodKey).toString();
+ if (method.isEmpty())
+ d->handleResponse(id, message);
+ else
+ d->handleMethod(method, id, message);
}
void Client::log(const QString &message) const
{
- switch (m_logTarget) {
+ switch (d->m_logTarget) {
case LogTarget::Ui:
Core::MessageManager::writeFlashing(QString("LanguageClient %1: %2").arg(name(), message));
break;
@@ -1169,32 +1585,47 @@ void Client::log(const QString &message) const
}
}
+TextEditor::RefactoringChangesData *Client::createRefactoringChangesBackend() const
+{
+ return new TextEditor::RefactoringChangesData;
+}
+
const ServerCapabilities &Client::capabilities() const
{
- return m_serverCapabilities;
+ return d->m_serverCapabilities;
+}
+
+QString Client::serverName() const
+{
+ return d->m_serverName;
+}
+
+QString Client::serverVersion() const
+{
+ return d->m_serverVersion;
}
const DynamicCapabilities &Client::dynamicCapabilities() const
{
- return m_dynamicCapabilities;
+ return d->m_dynamicCapabilities;
}
DocumentSymbolCache *Client::documentSymbolCache()
{
- return &m_documentSymbolCache;
+ return &d->m_documentSymbolCache;
}
HoverHandler *Client::hoverHandler()
{
- return &m_hoverHandler;
+ return &d->m_hoverHandler;
}
-void Client::log(const ShowMessageParams &message)
+void ClientPrivate::log(const ShowMessageParams &message)
{
- log(message.toString());
+ q->log(message.toString());
}
-LanguageClientValue<MessageActionItem> Client::showMessageBox(
+LanguageClientValue<MessageActionItem> ClientPrivate::showMessageBox(
const ShowMessageRequestParams &message)
{
auto box = new QMessageBox();
@@ -1208,7 +1639,7 @@ LanguageClientValue<MessageActionItem> Client::showMessageBox(
}
QHash<QAbstractButton *, MessageActionItem> itemForButton;
if (const Utils::optional<QList<MessageActionItem>> actions = message.actions()) {
- for (const MessageActionItem &action : actions.value())
+ for (const MessageActionItem &action : *actions)
itemForButton.insert(box->addButton(action.title(), QMessageBox::InvalidRole), action);
}
box->exec();
@@ -1217,7 +1648,7 @@ LanguageClientValue<MessageActionItem> Client::showMessageBox(
: LanguageClientValue<MessageActionItem>();
}
-void Client::resetAssistProviders(TextEditor::TextDocument *document)
+void ClientPrivate::resetAssistProviders(TextEditor::TextDocument *document)
{
const AssistProviders providers = m_resetAssistProvider.take(document);
@@ -1231,7 +1662,7 @@ void Client::resetAssistProviders(TextEditor::TextDocument *document)
document->setQuickFixAssistProvider(providers.quickFixAssistProvider);
}
-void Client::sendPostponedDocumentUpdates(Schedule semanticTokensSchedule)
+void ClientPrivate::sendPostponedDocumentUpdates(Schedule semanticTokensSchedule)
{
m_documentUpdateTimer.stop();
if (m_documentsToUpdate.empty())
@@ -1259,8 +1690,8 @@ void Client::sendPostponedDocumentUpdates(Schedule semanticTokensSchedule)
m_documentsToUpdate.clear();
for (const DocumentUpdate &update : updates) {
- sendContent(update.notification, SendDocUpdates::Ignore);
- emit documentUpdated(update.document);
+ q->sendMessage(update.notification, Client::SendDocUpdates::Ignore);
+ emit q->documentUpdated(update.document);
if (currentWidget && currentWidget->textDocument() == update.document)
requestDocumentHighlights(currentWidget);
@@ -1280,10 +1711,10 @@ void Client::sendPostponedDocumentUpdates(Schedule semanticTokensSchedule)
}
}
-void Client::handleResponse(const MessageId &id, const QByteArray &content, QTextCodec *codec)
+void ClientPrivate::handleResponse(const MessageId &id, const JsonRpcMessage &message)
{
- if (auto handler = m_responseHandlers[id])
- handler(content, codec);
+ if (auto handler = m_responseHandlers.take(id))
+ handler(message);
}
template<typename T>
@@ -1295,146 +1726,148 @@ static ResponseError<T> createInvalidParamsError(const QString &message)
return error;
}
-void Client::handleMethod(const QString &method, const MessageId &id, const IContent *content)
+void ClientPrivate::handleMethod(const QString &method, const MessageId &id, const JsonRpcMessage &message)
{
auto invalidParamsErrorMessage = [&](const JsonObject &params) {
return tr("Invalid parameter in \"%1\":\n%2")
.arg(method, QString::fromUtf8(QJsonDocument(params).toJson(QJsonDocument::Indented)));
};
- auto createDefaultResponse = [&]() -> IContent * {
- Response<std::nullptr_t, JsonObject> *response = nullptr;
- if (id.isValid()) {
- response = new Response<std::nullptr_t, JsonObject>(id);
- response->setResult(nullptr);
- }
+ auto createDefaultResponse = [&]() {
+ Response<std::nullptr_t, JsonObject> response;
+ if (QTC_GUARD(id.isValid()))
+ response.setId(id);
+ response.setResult(nullptr);
return response;
};
const bool isRequest = id.isValid();
- IContent *response = nullptr;
+
+ bool responseSend = false;
+ auto sendResponse =
+ [&](const JsonRpcMessage &response) {
+ responseSend = true;
+ if (q->reachable()) {
+ q->sendMessage(response);
+ } else {
+ qCDebug(LOGLSPCLIENT)
+ << QString("Dropped response to request %1 id %2 for unreachable server %3")
+ .arg(method, id.toString(), q->name());
+ }
+ };
if (method == PublishDiagnosticsNotification::methodName) {
- auto params = dynamic_cast<const PublishDiagnosticsNotification *>(content)->params().value_or(PublishDiagnosticsParams());
+ auto params = PublishDiagnosticsNotification(message.toJsonObject()).params().value_or(
+ PublishDiagnosticsParams());
if (params.isValid())
- handleDiagnostics(params);
+ q->handleDiagnostics(params);
else
- log(invalidParamsErrorMessage(params));
+ q->log(invalidParamsErrorMessage(params));
} else if (method == LogMessageNotification::methodName) {
- auto params = dynamic_cast<const LogMessageNotification *>(content)->params().value_or(LogMessageParams());
+ auto params = LogMessageNotification(message.toJsonObject()).params().value_or(
+ LogMessageParams());
if (params.isValid())
log(params);
else
- log(invalidParamsErrorMessage(params));
+ q->log(invalidParamsErrorMessage(params));
} else if (method == ShowMessageNotification::methodName) {
- auto params = dynamic_cast<const ShowMessageNotification *>(content)->params().value_or(ShowMessageParams());
+ auto params = ShowMessageNotification(message.toJsonObject()).params().value_or(
+ ShowMessageParams());
if (params.isValid())
log(params);
else
- log(invalidParamsErrorMessage(params));
+ q->log(invalidParamsErrorMessage(params));
} else if (method == ShowMessageRequest::methodName) {
- auto request = dynamic_cast<const ShowMessageRequest *>(content);
- auto showMessageResponse = new ShowMessageRequest::Response(id);
- auto params = request->params().value_or(ShowMessageRequestParams());
+ auto request = ShowMessageRequest(message.toJsonObject());
+ ShowMessageRequest::Response response(id);
+ auto params = request.params().value_or(ShowMessageRequestParams());
if (params.isValid()) {
- showMessageResponse->setResult(showMessageBox(params));
+ response.setResult(showMessageBox(params));
} else {
const QString errorMessage = invalidParamsErrorMessage(params);
- log(errorMessage);
- showMessageResponse->setError(createInvalidParamsError<std::nullptr_t>(errorMessage));
+ q->log(errorMessage);
+ response.setError(createInvalidParamsError<std::nullptr_t>(errorMessage));
}
- response = showMessageResponse;
+ sendResponse(response);
} else if (method == RegisterCapabilityRequest::methodName) {
- auto params = dynamic_cast<const RegisterCapabilityRequest *>(content)->params().value_or(
+ auto params = RegisterCapabilityRequest(message.toJsonObject()).params().value_or(
RegistrationParams());
if (params.isValid()) {
- registerCapabilities(params.registrations());
- response = createDefaultResponse();
+ q->registerCapabilities(params.registrations());
+ sendResponse(createDefaultResponse());
} else {
const QString errorMessage = invalidParamsErrorMessage(params);
- log(invalidParamsErrorMessage(params));
- auto registerResponse = new RegisterCapabilityRequest::Response(id);
- registerResponse->setError(createInvalidParamsError<std::nullptr_t>(errorMessage));
- response = registerResponse;
+ q->log(invalidParamsErrorMessage(params));
+ RegisterCapabilityRequest::Response response(id);
+ response.setError(createInvalidParamsError<std::nullptr_t>(errorMessage));
+ sendResponse(response);
}
} else if (method == UnregisterCapabilityRequest::methodName) {
- auto params = dynamic_cast<const UnregisterCapabilityRequest *>(content)->params().value_or(
+ auto params = UnregisterCapabilityRequest(message.toJsonObject()).params().value_or(
UnregistrationParams());
if (params.isValid()) {
- unregisterCapabilities(params.unregistrations());
- response = createDefaultResponse();
+ q->unregisterCapabilities(params.unregistrations());
+ sendResponse(createDefaultResponse());
} else {
const QString errorMessage = invalidParamsErrorMessage(params);
- log(invalidParamsErrorMessage(params));
- auto registerResponse = new UnregisterCapabilityRequest::Response(id);
- registerResponse->setError(createInvalidParamsError<std::nullptr_t>(errorMessage));
- response = registerResponse;
+ q->log(invalidParamsErrorMessage(params));
+ UnregisterCapabilityRequest::Response response(id);
+ response.setError(createInvalidParamsError<std::nullptr_t>(errorMessage));
+ sendResponse(response);
}
} else if (method == ApplyWorkspaceEditRequest::methodName) {
- auto editResponse = new ApplyWorkspaceEditRequest::Response(id);
- auto params = dynamic_cast<const ApplyWorkspaceEditRequest *>(content)->params().value_or(
+ ApplyWorkspaceEditRequest::Response response(id);
+ auto params = ApplyWorkspaceEditRequest(message.toJsonObject()).params().value_or(
ApplyWorkspaceEditParams());
if (params.isValid()) {
ApplyWorkspaceEditResult result;
- result.setApplied(applyWorkspaceEdit(this, params.edit()));
- editResponse->setResult(result);
+ result.setApplied(applyWorkspaceEdit(q, params.edit()));
+ response.setResult(result);
} else {
const QString errorMessage = invalidParamsErrorMessage(params);
- log(errorMessage);
- editResponse->setError(createInvalidParamsError<std::nullptr_t>(errorMessage));
+ q->log(errorMessage);
+ response.setError(createInvalidParamsError<std::nullptr_t>(errorMessage));
}
- response = editResponse;
+ sendResponse(response);
} else if (method == WorkSpaceFolderRequest::methodName) {
- auto workSpaceFolderResponse = new WorkSpaceFolderRequest::Response(id);
+ WorkSpaceFolderRequest::Response response(id);
const QList<ProjectExplorer::Project *> projects
= ProjectExplorer::SessionManager::projects();
- WorkSpaceFolderResult result;
if (projects.isEmpty()) {
- result = nullptr;
+ response.setResult(nullptr);
} else {
- result = Utils::transform(projects, [](ProjectExplorer::Project *project) {
- return WorkSpaceFolder(DocumentUri::fromFilePath(project->projectDirectory()),
- project->displayName());
- });
+ response.setResult(Utils::transform(
+ projects,
+ [](ProjectExplorer::Project *project) {
+ return WorkSpaceFolder(DocumentUri::fromFilePath(project->projectDirectory()),
+ project->displayName());
+ }));
}
- workSpaceFolderResponse->setResult(result);
- response = workSpaceFolderResponse;
+ sendResponse(response);
} else if (method == WorkDoneProgressCreateRequest::methodName) {
- response = createDefaultResponse();
+ sendResponse(createDefaultResponse());
} else if (method == SemanticTokensRefreshRequest::methodName) {
m_tokenSupport.refresh();
- response = createDefaultResponse();
+ sendResponse(createDefaultResponse());
} else if (method == ProgressNotification::methodName) {
if (Utils::optional<ProgressParams> params
- = dynamic_cast<const ProgressNotification *>(content)->params()) {
+ = ProgressNotification(message.toJsonObject()).params()) {
if (!params->isValid())
- log(invalidParamsErrorMessage(*params));
+ q->log(invalidParamsErrorMessage(*params));
m_progressManager.handleProgress(*params);
if (ProgressManager::isProgressEndMessage(*params))
- emit workDone(params->token());
+ emit q->workDone(params->token());
}
} else if (isRequest) {
- auto methodNotFoundResponse = new Response<JsonObject, JsonObject>(id);
+ Response<JsonObject, JsonObject> response(id);
ResponseError<JsonObject> error;
error.setCode(ResponseError<JsonObject>::MethodNotFound);
- methodNotFoundResponse->setError(error);
- response = methodNotFoundResponse;
+ response.setError(error);
+ sendResponse(response);
}
// we got a request and handled it somewhere above but we missed to generate a response for it
- QTC_ASSERT(!isRequest || response, response = createDefaultResponse());
-
- if (response) {
- if (reachable()) {
- sendContent(*response);
- } else {
- qCDebug(LOGLSPCLIENT)
- << QString("Dropped response to request %1 id %2 for unreachable server %3")
- .arg(method, id.toString(), name());
- }
- delete response;
- }
- delete content;
+ QTC_ASSERT(!isRequest || responseSend, sendResponse(createDefaultResponse()));
}
void Client::handleDiagnostics(const PublishDiagnosticsParams &params)
@@ -1442,80 +1875,82 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams &params)
const DocumentUri &uri = params.uri();
const QList<Diagnostic> &diagnostics = params.diagnostics();
- m_diagnosticManager.setDiagnostics(uri, diagnostics, params.version());
+ if (!d->m_diagnosticManager)
+ d->m_diagnosticManager = createDiagnosticManager();
+ d->m_diagnosticManager->setDiagnostics(uri, diagnostics, params.version());
if (LanguageClientManager::clientForUri(uri) == this) {
- m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(uri.toFilePath()));
- if (m_autoRequestCodeActions)
+ d->m_diagnosticManager->showDiagnostics(uri, d->m_documentVersions.value(uri.toFilePath()));
+ if (d->m_autoRequestCodeActions)
requestCodeActions(uri, diagnostics);
}
}
-void Client::sendMessage(const BaseMessage &message)
+void ClientPrivate::sendMessageNow(const JsonRpcMessage &message)
{
- LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, name(), message);
+ LanguageClientManager::logJsonRpcMessage(LspLogMessage::ClientMessage, q->name(), message);
m_clientInterface->sendMessage(message);
}
bool Client::documentUpdatePostponed(const Utils::FilePath &fileName) const
{
- return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) {
+ return Utils::contains(d->m_documentsToUpdate, [fileName](const auto &elem) {
return elem.first->filePath() == fileName;
});
}
int Client::documentVersion(const Utils::FilePath &filePath) const
{
- return m_documentVersions.value(filePath);
+ return d->m_documentVersions.value(filePath);
}
void Client::setDocumentChangeUpdateThreshold(int msecs)
{
- m_documentUpdateTimer.setInterval(msecs);
+ d->m_documentUpdateTimer.setInterval(msecs);
}
-void Client::initializeCallback(const InitializeRequest::Response &initResponse)
+void ClientPrivate::initializeCallback(const InitializeRequest::Response &initResponse)
{
- QTC_ASSERT(m_state == InitializeRequested, return);
+ QTC_ASSERT(m_state == Client::InitializeRequested, return);
if (optional<ResponseError<InitializeError>> error = initResponse.error()) {
- if (error.value().data().has_value() && error.value().data().value().retry()) {
- const QString title(tr("Language Server \"%1\" Initialize Error").arg(m_displayName));
- auto result = QMessageBox::warning(Core::ICore::dialogParent(),
- title,
- error.value().message(),
- QMessageBox::Retry | QMessageBox::Cancel,
- QMessageBox::Retry);
- if (result == QMessageBox::Retry) {
- m_state = Uninitialized;
- initialize();
- return;
+ if (Utils::optional<InitializeError> data = error->data()) {
+ if (data->retry()) {
+ const QString title(tr("Language Server \"%1\" Initialize Error").arg(m_displayName));
+ auto result = QMessageBox::warning(Core::ICore::dialogParent(),
+ title,
+ error->message(),
+ QMessageBox::Retry | QMessageBox::Cancel,
+ QMessageBox::Retry);
+ if (result == QMessageBox::Retry) {
+ m_state = Client::Uninitialized;
+ q->initialize();
+ return;
+ }
}
}
- setError(tr("Initialize error: ") + error.value().message());
- emit finished();
+ q->setError(tr("Initialize error: ") + error->message());
+ emit q->finished();
return;
}
- const optional<InitializeResult> &_result = initResponse.result();
- if (!_result.has_value()) {// continue on ill formed result
- log(tr("No initialize result."));
- } else {
- const InitializeResult &result = _result.value();
- if (!result.isValid()) { // continue on ill formed result
- log(QJsonDocument(result).toJson(QJsonDocument::Indented) + '\n'
- + tr("Initialize result is not valid"));
+ if (const optional<InitializeResult> &result = initResponse.result()) {
+ if (!result->isValid()) { // continue on ill formed result
+ q->log(QJsonDocument(*result).toJson(QJsonDocument::Indented) + '\n'
+ + tr("Initialize result is invalid."));
}
- const Utils::optional<ServerInfo> serverInfo = result.serverInfo();
+ const Utils::optional<ServerInfo> serverInfo = result->serverInfo();
if (serverInfo) {
if (!serverInfo->isValid()) {
- log(QJsonDocument(result).toJson(QJsonDocument::Indented) + '\n'
- + tr("Server Info is not valid"));
+ q->log(QJsonDocument(*result).toJson(QJsonDocument::Indented) + '\n'
+ + tr("Server Info is invalid."));
} else {
m_serverName = serverInfo->name();
if (const Utils::optional<QString> version = serverInfo->version())
- m_serverVersion = version.value();
+ m_serverVersion = *version;
}
}
- m_serverCapabilities = result.capabilities();
+ m_serverCapabilities = result->capabilities();
+ } else {
+ q->log(tr("No initialize result."));
}
if (auto completionProvider = qobject_cast<LanguageClientCompletionAssistProvider *>(
@@ -1538,10 +1973,10 @@ void Client::initializeCallback(const InitializeRequest::Response &initResponse)
m_tokenSupport.setLegend(tokenProvider.legend());
qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " initialized";
- m_state = Initialized;
- sendContent(InitializeNotification(InitializedParams()));
+ m_state = Client::Initialized;
+ q->sendMessage(InitializeNotification(InitializedParams()));
Utils::optional<Utils::variant<bool, WorkDoneProgressOptions>> documentSymbolProvider
- = capabilities().documentSymbolProvider();
+ = q->capabilities().documentSymbolProvider();
if (documentSymbolProvider.has_value()) {
if (!Utils::holds_alternative<bool>(*documentSymbolProvider)
|| Utils::get<bool>(*documentSymbolProvider)) {
@@ -1549,40 +1984,43 @@ void Client::initializeCallback(const InitializeRequest::Response &initResponse)
}
}
+ q->updateConfiguration(m_configuration);
+
+ m_tokenSupport.clearTokens(); // clear cached tokens from a pre reset run
for (TextEditor::TextDocument *doc : m_postponedDocuments)
- openDocument(doc);
+ q->openDocument(doc);
m_postponedDocuments.clear();
- emit initialized(m_serverCapabilities);
+ emit q->initialized(m_serverCapabilities);
}
-void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
+void ClientPrivate::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
{
m_shutdownTimer.stop();
- QTC_ASSERT(m_state == ShutdownRequested, return);
+ QTC_ASSERT(m_state == Client::ShutdownRequested, return);
QTC_ASSERT(m_clientInterface, return);
if (optional<ShutdownRequest::Response::Error> error = shutdownResponse.error())
- log(*error);
- // directly send message otherwise the state check of sendContent would fail
- sendMessage(ExitNotification().toBaseMessage());
+ q->log(*error);
+ // directly send content now otherwise the state check of sendContent would fail
+ sendMessageNow(ExitNotification());
qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown";
- m_state = Shutdown;
+ m_state = Client::Shutdown;
m_shutdownTimer.start();
}
-bool Client::sendWorkspceFolderChanges() const
+bool ClientPrivate::sendWorkspceFolderChanges() const
{
- if (!reachable())
+ if (!q->reachable())
return false;
if (m_dynamicCapabilities.isRegistered(
DidChangeWorkspaceFoldersNotification::methodName).value_or(false)) {
return true;
}
if (auto workspace = m_serverCapabilities.workspace()) {
- if (auto folder = workspace.value().workspaceFolders()) {
- if (folder.value().supported().value_or(false)) {
+ if (auto folder = workspace->workspaceFolders()) {
+ if (folder->supported().value_or(false)) {
// holds either the Id for deregistration or whether it is registered
- auto notification = folder.value().changeNotifications().value_or(false);
+ auto notification = folder->changeNotifications().value_or(false);
return holds_alternative<QString>(notification)
|| (holds_alternative<bool>(notification) && get<bool>(notification));
}
@@ -1598,4 +2036,14 @@ QTextCursor Client::adjustedCursorForHighlighting(const QTextCursor &cursor,
return cursor;
}
+bool Client::referencesShadowFile(const TextEditor::TextDocument *doc,
+ const Utils::FilePath &candidate)
+{
+ Q_UNUSED(doc)
+ Q_UNUSED(candidate)
+ return false;
+}
+
} // namespace LanguageClient
+
+#include <client.moc>
diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h
index f1e9c581f48..d718012e49d 100644
--- a/src/plugins/languageclient/client.h
+++ b/src/plugins/languageclient/client.h
@@ -25,45 +25,10 @@
#pragma once
-#include "diagnosticmanager.h"
-#include "documentsymbolcache.h"
-#include "dynamiccapabilities.h"
#include "languageclient_global.h"
-#include "languageclientcompletionassist.h"
-#include "languageclientformatter.h"
-#include "languageclientfunctionhint.h"
-#include "languageclienthoverhandler.h"
-#include "languageclientquickfix.h"
-#include "languageclientsettings.h"
-#include "languageclientsymbolsupport.h"
-#include "progressmanager.h"
+#include "languageclientutils.h"
#include "semantichighlightsupport.h"
-#include <coreplugin/messagemanager.h>
-
-#include <utils/id.h>
-#include <utils/link.h>
-
-#include <languageserverprotocol/client.h>
-#include <languageserverprotocol/diagnostics.h>
-#include <languageserverprotocol/initializemessages.h>
-#include <languageserverprotocol/languagefeatures.h>
-#include <languageserverprotocol/messages.h>
-#include <languageserverprotocol/progresssupport.h>
-#include <languageserverprotocol/semantictokens.h>
-#include <languageserverprotocol/shutdownmessages.h>
-#include <languageserverprotocol/textsynchronization.h>
-
-#include <texteditor/semantichighlighter.h>
-
-#include <QBuffer>
-#include <QHash>
-#include <QJsonDocument>
-#include <QTextCursor>
-
-#include <unordered_map>
-#include <utility>
-
namespace Core { class IDocument; }
namespace ProjectExplorer { class Project; }
namespace TextEditor
@@ -77,9 +42,29 @@ QT_BEGIN_NAMESPACE
class QWidget;
QT_END_NAMESPACE
+namespace LanguageServerProtocol {
+class ClientCapabilities;
+class ClientInfo;
+class ProgressToken;
+class PublishDiagnosticsParams;
+class Registration;
+class ServerCapabilities;
+class Unregistration;
+} // namespace LanguageServerProtocol
+
namespace LanguageClient {
class BaseClientInterface;
+class ClientPrivate;
+class DiagnosticManager;
+class DocumentSymbolCache;
+class DynamicCapabilities;
+class HoverHandler;
+class InterfaceController;
+class LanguageClientCompletionAssistProvider;
+class LanguageClientQuickFixProvider;
+class LanguageFilter;
+class SymbolSupport;
class LANGUAGECLIENT_EXPORT Client : public QObject
{
@@ -95,13 +80,14 @@ public:
Client &operator=(Client &&) = delete;
// basic properties
- Utils::Id id() const { return m_id; }
- void setName(const QString &name) { m_displayName = name; }
+ Utils::Id id() const;
+ void setName(const QString &name);
QString name() const;
enum class SendDocUpdates { Send, Ignore };
- void sendContent(const LanguageServerProtocol::IContent &content,
- SendDocUpdates sendUpdates = SendDocUpdates::Send);
+ void sendMessage(const LanguageServerProtocol::JsonRpcMessage &message,
+ SendDocUpdates sendUpdates = SendDocUpdates::Send,
+ Schedule semanticTokensSchedule = Schedule::Delayed);
void cancelRequest(const LanguageServerProtocol::MessageId &id);
@@ -121,21 +107,22 @@ public:
};
State state() const;
QString stateString() const;
- bool reachable() const { return m_state == Initialized; }
+ bool reachable() const;
+ void setClientInfo(const LanguageServerProtocol::ClientInfo &clientInfo);
// capabilities
static LanguageServerProtocol::ClientCapabilities defaultClientCapabilities();
void setClientCapabilities(const LanguageServerProtocol::ClientCapabilities &caps);
const LanguageServerProtocol::ServerCapabilities &capabilities() const;
- QString serverName() const { return m_serverName; }
- QString serverVersion() const { return m_serverVersion; }
+ QString serverName() const;
+ QString serverVersion() const;
const DynamicCapabilities &dynamicCapabilities() const;
void registerCapabilities(const QList<LanguageServerProtocol::Registration> &registrations);
void unregisterCapabilities(const QList<LanguageServerProtocol::Unregistration> &unregistrations);
- void setLocatorsEnabled(bool enabled) { m_locatorsEnabled = enabled; }
- bool locatorsEnabled() const { return m_locatorsEnabled; }
- void setAutoRequestCodeActions(bool enabled) { m_autoRequestCodeActions = enabled; }
+ void setLocatorsEnabled(bool enabled);
+ bool locatorsEnabled() const;
+ void setAutoRequestCodeActions(bool enabled);
// document synchronization
void setSupportedLanguage(const LanguageFilter &filter);
@@ -143,12 +130,14 @@ public:
bool isSupportedDocument(const TextEditor::TextDocument *document) const;
bool isSupportedFile(const Utils::FilePath &filePath, const QString &mimeType) const;
bool isSupportedUri(const LanguageServerProtocol::DocumentUri &uri) const;
- void openDocument(TextEditor::TextDocument *document);
+ virtual void openDocument(TextEditor::TextDocument *document);
void closeDocument(TextEditor::TextDocument *document);
void activateDocument(TextEditor::TextDocument *document);
void deactivateDocument(TextEditor::TextDocument *document);
bool documentOpen(const TextEditor::TextDocument *document) const;
TextEditor::TextDocument *documentForFilePath(const Utils::FilePath &file) const;
+ void setShadowDocument(const Utils::FilePath &filePath, const QString &contents);
+ void removeShadowDocument(const Utils::FilePath &filePath);
void documentContentsSaved(TextEditor::TextDocument *document);
void documentWillSave(Core::IDocument *document);
void documentContentsChanged(TextEditor::TextDocument *document,
@@ -165,9 +154,12 @@ public:
ProjectExplorer::Project *project() const;
virtual void projectOpened(ProjectExplorer::Project *project);
virtual void projectClosed(ProjectExplorer::Project *project);
+ void updateConfiguration(const QJsonValue &configuration);
// commands
void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
+ const LanguageServerProtocol::Diagnostic &diagnostic);
+ void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::Diagnostic> &diagnostics);
void requestCodeActions(const LanguageServerProtocol::CodeActionRequest &request);
void handleCodeActionResponse(const LanguageServerProtocol::CodeActionRequest::Response &response,
@@ -185,17 +177,18 @@ public:
const QTextCursor &cursor) const;
bool hasDiagnostic(const LanguageServerProtocol::DocumentUri &uri,
const LanguageServerProtocol::Diagnostic &diag) const;
- void setDiagnosticsHandlers(const TextMarkCreator &textMarkCreator,
- const HideDiagnosticsHandler &hideHandler, const DiagnosticsFilter &filter);
+ bool hasDiagnostics(const TextEditor::TextDocument *document) const;
void setSemanticTokensHandler(const SemanticTokensHandler &handler);
void setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier);
LanguageServerProtocol::SymbolStringifier symbolStringifier() const;
void setSnippetsGroup(const QString &group);
void setCompletionAssistProvider(LanguageClientCompletionAssistProvider *provider);
+ void setQuickFixAssistProvider(LanguageClientQuickFixProvider *provider);
+ virtual bool supportsDocumentSymbols(const TextEditor::TextDocument *doc) const;
// logging
enum class LogTarget { Console, Ui };
- void setLogTarget(LogTarget target) { m_logTarget = target; }
+ void setLogTarget(LogTarget target);
void log(const QString &message) const;
template<typename Error>
void log(const LanguageServerProtocol::ResponseError<Error> &responseError) const
@@ -206,106 +199,35 @@ public:
using CustomInspectorTabs = QList<CustomInspectorTab>;
virtual const CustomInspectorTabs createCustomInspectorTabs() { return {}; }
+ // Caller takes ownership
+ virtual TextEditor::RefactoringChangesData *createRefactoringChangesBackend() const;
+
signals:
void initialized(const LanguageServerProtocol::ServerCapabilities &capabilities);
void capabilitiesChanged(const DynamicCapabilities &capabilities);
void documentUpdated(TextEditor::TextDocument *document);
void workDone(const LanguageServerProtocol::ProgressToken &token);
+ void shadowDocumentSwitched(const Utils::FilePath &filePath);
void finished();
protected:
void setError(const QString &message);
void setProgressTitleForToken(const LanguageServerProtocol::ProgressToken &token,
const QString &message);
- void handleMessage(const LanguageServerProtocol::BaseMessage &message);
+ void handleMessage(const LanguageServerProtocol::JsonRpcMessage &message);
virtual void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params);
+ virtual DiagnosticManager *createDiagnosticManager();
private:
- void sendMessage(const LanguageServerProtocol::BaseMessage &message);
- void handleResponse(const LanguageServerProtocol::MessageId &id, const QByteArray &content,
- QTextCodec *codec);
- void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id,
- const LanguageServerProtocol::IContent *content);
-
- void initializeCallback(const LanguageServerProtocol::InitializeRequest::Response &initResponse);
- void shutDownCallback(const LanguageServerProtocol::ShutdownRequest::Response &shutdownResponse);
- bool sendWorkspceFolderChanges() const;
- void log(const LanguageServerProtocol::ShowMessageParams &message);
-
- LanguageServerProtocol::LanguageClientValue<LanguageServerProtocol::MessageActionItem>
- showMessageBox(const LanguageServerProtocol::ShowMessageRequestParams &message);
-
- void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
- void resetAssistProviders(TextEditor::TextDocument *document);
-
- void sendPostponedDocumentUpdates(Schedule semanticTokensSchedule);
-
- void updateCompletionProvider(TextEditor::TextDocument *document);
- void updateFunctionHintProvider(TextEditor::TextDocument *document);
-
- void requestDocumentHighlights(TextEditor::TextEditorWidget *widget);
- void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget);
- LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
- void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
- void documentClosed(Core::IDocument *document);
+ friend class ClientPrivate;
+ ClientPrivate *d = nullptr;
virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}
virtual QTextCursor adjustedCursorForHighlighting(const QTextCursor &cursor,
TextEditor::TextDocument *doc);
-
- using ContentHandler = std::function<void(const QByteArray &, QTextCodec *, QString &,
- LanguageServerProtocol::ResponseHandlers,
- LanguageServerProtocol::MethodHandler)>;
-
- State m_state = Uninitialized;
- QHash<LanguageServerProtocol::MessageId,
- LanguageServerProtocol::ResponseHandler::Callback> m_responseHandlers;
- QHash<QByteArray, ContentHandler> m_contentHandler;
- QString m_displayName;
- LanguageFilter m_languagFilter;
- QJsonObject m_initializationOptions;
- QMap<TextEditor::TextDocument *, QString> m_openedDocument;
- QSet<TextEditor::TextDocument *> m_postponedDocuments;
- QMap<Utils::FilePath, int> m_documentVersions;
- std::unordered_map<TextEditor::TextDocument *,
- QList<LanguageServerProtocol::DidChangeTextDocumentParams::TextDocumentContentChangeEvent>>
- m_documentsToUpdate;
- QMap<TextEditor::TextEditorWidget *, QTimer *> m_documentHighlightsTimer;
- QTimer m_documentUpdateTimer;
- Utils::Id m_id;
- LanguageServerProtocol::ClientCapabilities m_clientCapabilities = defaultClientCapabilities();
- LanguageServerProtocol::ServerCapabilities m_serverCapabilities;
- DynamicCapabilities m_dynamicCapabilities;
- struct AssistProviders
- {
- QPointer<TextEditor::CompletionAssistProvider> completionAssistProvider;
- QPointer<TextEditor::CompletionAssistProvider> functionHintProvider;
- QPointer<TextEditor::IAssistProvider> quickFixAssistProvider;
- };
-
- AssistProviders m_clientProviders;
- QMap<TextEditor::TextDocument *, AssistProviders> m_resetAssistProvider;
- QHash<TextEditor::TextEditorWidget *, LanguageServerProtocol::MessageId> m_highlightRequests;
- int m_restartsLeft = 5;
- QScopedPointer<BaseClientInterface> m_clientInterface;
- DiagnosticManager m_diagnosticManager;
- DocumentSymbolCache m_documentSymbolCache;
- HoverHandler m_hoverHandler;
- QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;
- ProjectExplorer::Project *m_project = nullptr;
- QSet<TextEditor::IAssistProcessor *> m_runningAssistProcessors;
- SymbolSupport m_symbolSupport;
- ProgressManager m_progressManager;
- bool m_activateDocAutomatically = false;
- SemanticTokenSupport m_tokenSupport;
- QString m_serverName;
- QString m_serverVersion;
- LanguageServerProtocol::SymbolStringifier m_symbolStringifier;
- LogTarget m_logTarget = LogTarget::Ui;
- bool m_locatorsEnabled = true;
- bool m_autoRequestCodeActions = true;
- QTimer m_shutdownTimer;
+ virtual bool referencesShadowFile(const TextEditor::TextDocument *doc,
+ const Utils::FilePath &candidate);
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/diagnosticmanager.cpp b/src/plugins/languageclient/diagnosticmanager.cpp
index a1b729ce9bf..cd6cad7e1d9 100644
--- a/src/plugins/languageclient/diagnosticmanager.cpp
+++ b/src/plugins/languageclient/diagnosticmanager.cpp
@@ -40,7 +40,6 @@
#include <QAction>
#include <QApplication>
#include <QClipboard>
-#include <QTextEdit>
using namespace LanguageServerProtocol;
using namespace Utils;
@@ -53,7 +52,6 @@ class TextMark : public TextEditor::TextMark
public:
TextMark(const FilePath &fileName, const Diagnostic &diag, const Id &clientId)
: TextEditor::TextMark(fileName, diag.range().start().line() + 1, clientId)
- , m_diagnostic(diag)
{
setLineAnnotation(diag.message());
setToolTip(diag.message());
@@ -65,19 +63,12 @@ public:
setIcon(isError ? Icons::CODEMODEL_ERROR.icon()
: Icons::CODEMODEL_WARNING.icon());
}
-
- const Diagnostic &diagnostic() const { return m_diagnostic; }
-
-private:
- const Diagnostic m_diagnostic;
};
DiagnosticManager::DiagnosticManager(Client *client)
: m_client(client)
+ , m_extraSelectionsId(TextEditorWidget::CodeWarningsSelection)
{
- m_textMarkCreator = [this](const FilePath &filePath, const Diagnostic &diagnostic, bool /*isProjectFile*/) {
- return createTextMark(filePath, diagnostic);
- };
}
DiagnosticManager::~DiagnosticManager()
@@ -85,40 +76,37 @@ DiagnosticManager::~DiagnosticManager()
clearDiagnostics();
}
-void DiagnosticManager::setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
- const QList<LanguageServerProtocol::Diagnostic> &diagnostics,
+void DiagnosticManager::setDiagnostics(const DocumentUri &uri,
+ const QList<Diagnostic> &diagnostics,
const Utils::optional<int> &version)
{
hideDiagnostics(uri.toFilePath());
- const QList<Diagnostic> filteredDiags = m_filter
- ? Utils::filtered(diagnostics, m_filter) : diagnostics;
- m_diagnostics[uri] = {version, filteredDiags};
+ m_diagnostics[uri] = {version, filteredDiagnostics(diagnostics)};
}
void DiagnosticManager::hideDiagnostics(const Utils::FilePath &filePath)
{
- if (m_hideHandler)
- m_hideHandler();
if (auto doc = TextDocument::textDocumentForFilePath(filePath)) {
for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc))
- editor->editorWidget()->setExtraSelections(TextEditorWidget::CodeWarningsSelection, {});
+ editor->editorWidget()->setExtraSelections(m_extraSelectionsId, {});
}
- qDeleteAll(m_marks.take(filePath));
+ m_marks.remove(filePath);
}
-static QTextEdit::ExtraSelection toDiagnosticsSelections(const Diagnostic &diagnostic,
- QTextDocument *textDocument)
+QList<Diagnostic> DiagnosticManager::filteredDiagnostics(const QList<Diagnostic> &diagnostics) const
{
- QTextCursor cursor(textDocument);
- cursor.setPosition(diagnostic.range().start().toPositionInDocument(textDocument));
- cursor.setPosition(diagnostic.range().end().toPositionInDocument(textDocument),
- QTextCursor::KeepAnchor);
+ return diagnostics;
+}
- const FontSettings &fontSettings = TextEditorSettings::fontSettings();
- const DiagnosticSeverity severity = diagnostic.severity().value_or(DiagnosticSeverity::Warning);
- const TextStyle style = severity == DiagnosticSeverity::Error ? C_ERROR : C_WARNING;
+void DiagnosticManager::disableDiagnostics(TextEditor::TextDocument *document)
+{
- return QTextEdit::ExtraSelection{cursor, fontSettings.toTextCharFormat(style)};
+ Marks &marks = m_marks[document->filePath()];
+ if (!marks.enabled)
+ return;
+ for (TextEditor::TextMark *mark : marks.marks)
+ mark->setColor(Utils::Theme::Color::IconsDisabledColor);
+ marks.enabled = false;
}
void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
@@ -128,49 +116,82 @@ void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
QList<QTextEdit::ExtraSelection> extraSelections;
const VersionedDiagnostics &versionedDiagnostics = m_diagnostics.value(uri);
if (versionedDiagnostics.version.value_or(version) == version
- && !versionedDiagnostics.diagnostics.isEmpty()) {
- QList<TextEditor::TextMark *> &marks = m_marks[filePath];
+ && !versionedDiagnostics.diagnostics.isEmpty()) {
+ Marks &marks = m_marks[filePath];
const bool isProjectFile = m_client->project()
&& m_client->project()->isKnownFile(filePath);
for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) {
- extraSelections << toDiagnosticsSelections(diagnostic, doc->document());
- marks.append(m_textMarkCreator(filePath, diagnostic, isProjectFile));
+ const QTextEdit::ExtraSelection selection
+ = createDiagnosticSelection(diagnostic, doc->document());
+ if (!selection.cursor.isNull())
+ extraSelections << selection;
+ if (TextEditor::TextMark *mark = createTextMark(filePath, diagnostic, isProjectFile))
+ marks.marks.append(mark);
}
+ if (!marks.marks.isEmpty())
+ emit textMarkCreated(filePath);
}
- for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc)) {
- editor->editorWidget()->setExtraSelections(TextEditorWidget::CodeWarningsSelection,
- extraSelections);
- }
+ for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc))
+ editor->editorWidget()->setExtraSelections(m_extraSelectionsId, extraSelections);
}
}
TextEditor::TextMark *DiagnosticManager::createTextMark(const FilePath &filePath,
- const Diagnostic &diagnostic) const
+ const Diagnostic &diagnostic,
+ bool /*isProjectFile*/) const
{
static const auto icon = QIcon::fromTheme("edit-copy", Utils::Icons::COPY.icon());
static const QString tooltip = tr("Copy to Clipboard");
- QAction *action = new QAction();
- action->setIcon(icon);
- action->setToolTip(tooltip);
- QObject::connect(action, &QAction::triggered, [text = diagnostic.message()]() {
- QApplication::clipboard()->setText(text);
- });
auto mark = new TextMark(filePath, diagnostic, m_client->id());
- mark->setActions({action});
+ mark->setActionsProvider([text = diagnostic.message()] {
+ QAction *action = new QAction();
+ action->setIcon(icon);
+ action->setToolTip(tooltip);
+ QObject::connect(action, &QAction::triggered, [text] {
+ QApplication::clipboard()->setText(text);
+ });
+ return QList<QAction *>{action};
+ });
return mark;
}
+QTextEdit::ExtraSelection DiagnosticManager::createDiagnosticSelection(
+ const LanguageServerProtocol::Diagnostic &diagnostic, QTextDocument *textDocument) const
+{
+ QTextCursor cursor(textDocument);
+ cursor.setPosition(diagnostic.range().start().toPositionInDocument(textDocument));
+ cursor.setPosition(diagnostic.range().end().toPositionInDocument(textDocument),
+ QTextCursor::KeepAnchor);
+
+ const FontSettings &fontSettings = TextEditorSettings::fontSettings();
+ const DiagnosticSeverity severity = diagnostic.severity().value_or(DiagnosticSeverity::Warning);
+ const TextStyle style = severity == DiagnosticSeverity::Error ? C_ERROR : C_WARNING;
+
+ return QTextEdit::ExtraSelection{cursor, fontSettings.toTextCharFormat(style)};
+}
+
+void DiagnosticManager::setExtraSelectionsId(const Utils::Id &extraSelectionsId)
+{
+ // this function should be called before any diagnostics are handled
+ QTC_CHECK(m_diagnostics.isEmpty());
+ m_extraSelectionsId = extraSelectionsId;
+}
+
+void DiagnosticManager::forAllMarks(std::function<void (TextEditor::TextMark *)> func)
+{
+ for (const Marks &marks : qAsConst(m_marks)) {
+ for (TextEditor::TextMark *mark : marks.marks)
+ func(mark);
+ }
+}
+
void DiagnosticManager::clearDiagnostics()
{
for (const DocumentUri &uri : m_diagnostics.keys())
hideDiagnostics(uri.toFilePath());
m_diagnostics.clear();
- if (!QTC_GUARD(m_marks.isEmpty())) {
- for (const QList<TextEditor::TextMark *> &marks : qAsConst(m_marks))
- qDeleteAll(marks);
- m_marks.clear();
- }
+ QTC_ASSERT(m_marks.isEmpty(), m_marks.clear());
}
QList<Diagnostic> DiagnosticManager::diagnosticsAt(const DocumentUri &uri,
@@ -202,13 +223,21 @@ bool DiagnosticManager::hasDiagnostic(const LanguageServerProtocol::DocumentUri
return it->diagnostics.contains(diag);
}
-void DiagnosticManager::setDiagnosticsHandlers(const TextMarkCreator &textMarkCreator,
- const HideDiagnosticsHandler &removalHandler,
- const DiagnosticsFilter &filter)
+bool DiagnosticManager::hasDiagnostics(const TextDocument *doc) const
+{
+ const FilePath docPath = doc->filePath();
+ const auto it = m_diagnostics.find(DocumentUri::fromFilePath(docPath));
+ if (it == m_diagnostics.end())
+ return {};
+ const int revision = m_client->documentVersion(docPath);
+ if (revision != it->version.value_or(revision))
+ return false;
+ return !it->diagnostics.isEmpty();
+}
+
+DiagnosticManager::Marks::~Marks()
{
- m_textMarkCreator = textMarkCreator;
- m_hideHandler = removalHandler;
- m_filter = filter;
+ qDeleteAll(marks);
}
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/diagnosticmanager.h b/src/plugins/languageclient/diagnosticmanager.h
index f201aaf50c2..282a5c3d065 100644
--- a/src/plugins/languageclient/diagnosticmanager.h
+++ b/src/plugins/languageclient/diagnosticmanager.h
@@ -25,11 +25,14 @@
#pragma once
+#include "languageclient_global.h"
+
#include <languageserverprotocol/lsptypes.h>
#include <utils/id.h>
#include <QMap>
+#include <QTextEdit>
#include <functional>
@@ -42,25 +45,23 @@ namespace LanguageClient {
class Client;
-using TextMarkCreator = std::function<TextEditor::TextMark *(const Utils::FilePath &,
- const LanguageServerProtocol::Diagnostic &, bool)>;
-using HideDiagnosticsHandler = std::function<void()>;
-using DiagnosticsFilter = std::function<bool(const LanguageServerProtocol::Diagnostic &)>;
-
-class DiagnosticManager
+class LANGUAGECLIENT_EXPORT DiagnosticManager : public QObject
{
- Q_DECLARE_TR_FUNCTIONS(LanguageClient::DiagnosticManager)
+ Q_OBJECT
public:
explicit DiagnosticManager(Client *client);
- ~DiagnosticManager();
+ ~DiagnosticManager() override;
- void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
- const QList<LanguageServerProtocol::Diagnostic> &diagnostics,
- const Utils::optional<int> &version);
+ virtual void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
+ const QList<LanguageServerProtocol::Diagnostic> &diagnostics,
+ const Utils::optional<int> &version);
- void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri, int version);
- void hideDiagnostics(const Utils::FilePath &filePath);
+ virtual void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri, int version);
+ virtual void hideDiagnostics(const Utils::FilePath &filePath);
+ virtual QList<LanguageServerProtocol::Diagnostic> filteredDiagnostics(
+ const QList<LanguageServerProtocol::Diagnostic> &diagnostics) const;
+ void disableDiagnostics(TextEditor::TextDocument *document);
void clearDiagnostics();
QList<LanguageServerProtocol::Diagnostic> diagnosticsAt(
@@ -69,24 +70,40 @@ public:
bool hasDiagnostic(const LanguageServerProtocol::DocumentUri &uri,
const TextEditor::TextDocument *doc,
const LanguageServerProtocol::Diagnostic &diag) const;
+ bool hasDiagnostics(const TextEditor::TextDocument *doc) const;
+
+signals:
+ void textMarkCreated(const Utils::FilePath &path);
- void setDiagnosticsHandlers(const TextMarkCreator &shownHandler,
- const HideDiagnosticsHandler &removalHandler,
- const DiagnosticsFilter &filter);
+protected:
+ Client *client() const { return m_client; }
+ virtual TextEditor::TextMark *createTextMark(const Utils::FilePath &filePath,
+ const LanguageServerProtocol::Diagnostic &diagnostic,
+ bool isProjectFile) const;
+ virtual QTextEdit::ExtraSelection createDiagnosticSelection(
+ const LanguageServerProtocol::Diagnostic &diagnostic, QTextDocument *textDocument) const;
+
+ void setExtraSelectionsId(const Utils::Id &extraSelectionsId);
+
+ void forAllMarks(std::function<void (TextEditor::TextMark *)> func);
private:
- TextEditor::TextMark *createTextMark(const Utils::FilePath &filePath,
- const LanguageServerProtocol::Diagnostic &diagnostic) const;
- struct VersionedDiagnostics {
+ struct VersionedDiagnostics
+ {
Utils::optional<int> version;
QList<LanguageServerProtocol::Diagnostic> diagnostics;
};
QMap<LanguageServerProtocol::DocumentUri, VersionedDiagnostics> m_diagnostics;
- QMap<Utils::FilePath, QList<TextEditor::TextMark *>> m_marks;
- TextMarkCreator m_textMarkCreator;
- HideDiagnosticsHandler m_hideHandler;
- DiagnosticsFilter m_filter;
+ class Marks
+ {
+ public:
+ ~Marks();
+ bool enabled = true;
+ QList<TextEditor::TextMark *> marks;
+ };
+ QMap<Utils::FilePath, Marks> m_marks;
Client *m_client;
+ Utils::Id m_extraSelectionsId;
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/documentsymbolcache.cpp b/src/plugins/languageclient/documentsymbolcache.cpp
index 1a46048d345..5b12870f104 100644
--- a/src/plugins/languageclient/documentsymbolcache.cpp
+++ b/src/plugins/languageclient/documentsymbolcache.cpp
@@ -40,7 +40,13 @@ DocumentSymbolCache::DocumentSymbolCache(Client *client)
{
auto connectDocument = [this](Core::IDocument *document) {
connect(document, &Core::IDocument::contentsChanged, this, [document, this]() {
+ const auto uri = DocumentUri::fromFilePath(document->filePath());
m_cache.remove(DocumentUri::fromFilePath(document->filePath()));
+ auto requestIdIt = m_runningRequests.find(uri);
+ if (requestIdIt != m_runningRequests.end()) {
+ m_client->cancelRequest(requestIdIt.value());
+ m_runningRequests.erase(requestIdIt);
+ }
});
};
@@ -67,6 +73,13 @@ void DocumentSymbolCache::requestSymbols(const DocumentUri &uri, Schedule schedu
}
}
+bool clientSupportsDocumentSymbols(const Client *client, const DocumentUri &uri)
+{
+ QTC_ASSERT(client, return false);
+ const auto doc = TextEditor::TextDocument::textDocumentForFilePath(uri.toFilePath());
+ return client->supportsDocumentSymbols(doc);
+}
+
void DocumentSymbolCache::requestSymbolsImpl()
{
if (!m_client->reachable()) {
@@ -80,6 +93,11 @@ void DocumentSymbolCache::requestSymbolsImpl()
continue;
}
+ if (!LanguageClient::clientSupportsDocumentSymbols(m_client, uri)) {
+ emit gotSymbols(uri, nullptr);
+ continue;
+ }
+
const DocumentSymbolParams params((TextDocumentIdentifier(uri)));
DocumentSymbolsRequest request(params);
request.setResponseCallback([uri, self = QPointer<DocumentSymbolCache>(this)](
@@ -87,7 +105,8 @@ void DocumentSymbolCache::requestSymbolsImpl()
if (self)
self->handleResponse(uri, response);
});
- m_client->sendContent(request);
+ m_runningRequests[uri] = request.id();
+ m_client->sendMessage(request);
}
m_compressedUris.clear();
}
@@ -95,9 +114,10 @@ void DocumentSymbolCache::requestSymbolsImpl()
void DocumentSymbolCache::handleResponse(const DocumentUri &uri,
const DocumentSymbolsRequest::Response &response)
{
+ m_runningRequests.remove(uri);
if (Utils::optional<DocumentSymbolsRequest::Response::Error> error = response.error()) {
if (m_client)
- m_client->log(error.value());
+ m_client->log(*error);
}
const DocumentSymbolsResult &symbols = response.result().value_or(DocumentSymbolsResult());
m_cache[uri] = symbols;
diff --git a/src/plugins/languageclient/documentsymbolcache.h b/src/plugins/languageclient/documentsymbolcache.h
index ada0953c071..8ae17bbd6df 100644
--- a/src/plugins/languageclient/documentsymbolcache.h
+++ b/src/plugins/languageclient/documentsymbolcache.h
@@ -60,6 +60,7 @@ private:
const LanguageServerProtocol::DocumentSymbolsRequest::Response &response);
QMap<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::DocumentSymbolsResult> m_cache;
+ QMap<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::MessageId> m_runningRequests;
Client *m_client = nullptr;
QTimer m_compressionTimer;
QSet<LanguageServerProtocol::DocumentUri> m_compressedUris;
diff --git a/src/plugins/languageclient/languageclient.qbs b/src/plugins/languageclient/languageclient.qbs
index 7cd37ab50db..257d54bef5a 100644
--- a/src/plugins/languageclient/languageclient.qbs
+++ b/src/plugins/languageclient/languageclient.qbs
@@ -17,6 +17,8 @@ QtcPlugin {
Depends { name: "Core" }
Depends { name: "TextEditor" }
+ Depends { name: "app_version_header" }
+
files: [
"client.cpp",
"client.h",
diff --git a/src/plugins/languageclient/languageclient_global.h b/src/plugins/languageclient/languageclient_global.h
index 37556715372..343ed48185e 100644
--- a/src/plugins/languageclient/languageclient_global.h
+++ b/src/plugins/languageclient/languageclient_global.h
@@ -29,6 +29,8 @@
#if defined(LANGUAGECLIENT_LIBRARY)
# define LANGUAGECLIENT_EXPORT Q_DECL_EXPORT
+#elif defined(LANGUAGECLIENT_STATIC_LIBRARY)
+# define LANGUAGECLIENT_EXPORT
#else
# define LANGUAGECLIENT_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/languageclient/languageclientcompletionassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp
index 3cec5a2e491..baac3b007e2 100644
--- a/src/plugins/languageclient/languageclientcompletionassist.cpp
+++ b/src/plugins/languageclient/languageclientcompletionassist.cpp
@@ -35,6 +35,7 @@
#include <texteditor/codeassist/genericproposalmodel.h>
#include <texteditor/snippets/snippet.h>
#include <texteditor/snippets/snippetassistcollector.h>
+#include <texteditor/textdocument.h>
#include <texteditor/texteditorsettings.h>
#include <utils/algorithm.h>
#include <utils/textutils.h>
@@ -66,7 +67,7 @@ bool LanguageClientCompletionItem::implicitlyApplies() const
bool LanguageClientCompletionItem::prematurelyApplies(const QChar &typedCharacter) const
{
- if (m_item.commitCharacters().has_value() && m_item.commitCharacters().value().contains(typedCharacter)) {
+ if (m_item.commitCharacters() && m_item.commitCharacters()->contains(typedCharacter)) {
m_triggeredCommitCharacter = typedCharacter;
return true;
}
@@ -194,10 +195,8 @@ bool LanguageClientCompletionItem::hasSortText() const
QString LanguageClientCompletionItem::filterText() const
{
- if (m_filterText.isEmpty()) {
- const Utils::optional<QString> filterText = m_item.filterText();
- m_filterText = filterText.has_value() ? filterText.value() : m_item.label();
- }
+ if (m_filterText.isEmpty())
+ m_filterText = m_item.filterText().value_or(m_item.label());
return m_filterText;
}
@@ -211,7 +210,7 @@ bool LanguageClientCompletionItem::isPerfectMatch(int pos, QTextDocument *doc) c
QTC_ASSERT(doc, return false);
using namespace Utils::Text;
if (auto additionalEdits = m_item.additionalTextEdits()) {
- if (!additionalEdits.value().isEmpty())
+ if (!additionalEdits->isEmpty())
return false;
}
if (isSnippet())
@@ -228,13 +227,22 @@ bool LanguageClientCompletionItem::isPerfectMatch(int pos, QTextDocument *doc) c
return textToInsert == textAt(QTextCursor(doc), pos - length, length);
}
+bool LanguageClientCompletionItem::isDeprecated() const
+{
+ if (const auto tags = m_item.tags(); tags && tags->contains(CompletionItem::Deprecated))
+ return true;
+ if (const auto deprecated = m_item.deprecated())
+ return *deprecated;
+ return false;
+}
+
class LanguageClientCompletionModel : public GenericProposalModel
{
public:
// GenericProposalModel interface
bool containsDuplicates() const override { return false; }
bool isSortable(const QString &/*prefix*/) const override;
- void sort(const QString &/*prefix*/) override;
+ void sort(const QString &prefix) override;
bool supportsPrefixExpansion() const override { return false; }
QList<AssistProposalItemInterface *> items() const { return m_currentItems; }
@@ -248,19 +256,21 @@ bool LanguageClientCompletionModel::isSortable(const QString &) const
});
}
-void LanguageClientCompletionModel::sort(const QString &/*prefix*/)
+void LanguageClientCompletionModel::sort(const QString &prefix)
{
std::sort(m_currentItems.begin(), m_currentItems.end(),
- [] (AssistProposalItemInterface *a, AssistProposalItemInterface *b){
+ [&prefix] (AssistProposalItemInterface *a, AssistProposalItemInterface *b){
const auto lca = dynamic_cast<LanguageClientCompletionItem *>(a);
const auto lcb = dynamic_cast<LanguageClientCompletionItem *>(b);
if (!lca && !lcb)
return a->text() < b->text();
if (lca && lcb)
return *lca < *lcb;
- if (lca && !lcb)
- return true;
- return false;
+ if (prefix.isEmpty())
+ return lca && !lcb;
+ if (!lca)
+ return a->text().toLower().startsWith(prefix.toLower());
+ return !b->text().toLower().startsWith(prefix.toLower());
});
}
@@ -373,7 +383,7 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(const AssistIn
completionRequest.setResponseCallback([this](auto response) {
this->handleCompletionResponse(response);
});
- m_client->sendContent(completionRequest);
+ m_client->sendMessage(completionRequest);
m_client->addAssistProcessor(this);
m_currentRequest = completionRequest.id();
m_document = interface->textDocument();
@@ -393,7 +403,7 @@ void LanguageClientCompletionAssistProcessor::cancel()
{
if (m_currentRequest.has_value()) {
if (m_client) {
- m_client->cancelRequest(m_currentRequest.value());
+ m_client->cancelRequest(*m_currentRequest);
m_client->removeAssistProcessor(this);
}
m_currentRequest.reset();
@@ -410,7 +420,7 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
m_currentRequest.reset();
QTC_ASSERT(m_client, setAsyncProposalAvailable(nullptr); return);
if (auto error = response.error())
- m_client->log(error.value());
+ m_client->log(*error);
const Utils::optional<CompletionResult> &result = response.result();
if (!result || Utils::holds_alternative<std::nullptr_t>(*result)) {
@@ -437,7 +447,6 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
model);
proposal->m_document = m_document;
proposal->m_pos = m_pos;
- proposal->setFragile(true);
proposal->setSupportsPrefix(false);
setAsyncProposalAvailable(proposal);
m_client->removeAssistProcessor(this);
diff --git a/src/plugins/languageclient/languageclientcompletionassist.h b/src/plugins/languageclient/languageclientcompletionassist.h
index 2f5ba014fab..19a8ec93063 100644
--- a/src/plugins/languageclient/languageclientcompletionassist.h
+++ b/src/plugins/languageclient/languageclientcompletionassist.h
@@ -135,6 +135,7 @@ public:
bool operator <(const LanguageClientCompletionItem &other) const;
bool isPerfectMatch(int pos, QTextDocument *doc) const;
+ bool isDeprecated() const;
private:
LanguageServerProtocol::CompletionItem m_item;
diff --git a/src/plugins/languageclient/languageclientformatter.cpp b/src/plugins/languageclient/languageclientformatter.cpp
index 6233d79bcc5..f1cea20b93d 100644
--- a/src/plugins/languageclient/languageclientformatter.cpp
+++ b/src/plugins/languageclient/languageclientformatter.cpp
@@ -26,11 +26,12 @@
#include "languageclientformatter.h"
#include "client.h"
+#include "dynamiccapabilities.h"
#include "languageclientutils.h"
#include <texteditor/tabsettings.h>
#include <texteditor/textdocument.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QTextDocument>
@@ -77,7 +78,7 @@ QFutureWatcher<ChangeSet> *LanguageClientFormatter::format(
const DynamicCapabilities dynamicCapabilities = m_client->dynamicCapabilities();
const QString method(DocumentRangeFormattingRequest::methodName);
if (optional<bool> registered = dynamicCapabilities.isRegistered(method)) {
- if (!registered.value())
+ if (!*registered)
return nullptr;
const TextDocumentRegistrationOptions option(dynamicCapabilities.option(method).toObject());
if (option.isValid()
@@ -108,7 +109,7 @@ QFutureWatcher<ChangeSet> *LanguageClientFormatter::format(
handleResponse(response);
});
m_currentRequest = request.id();
- m_client->sendContent(request);
+ m_client->sendMessage(request);
// ignore first contents changed, because this function is called inside a begin/endEdit block
m_ignoreCancel = true;
m_progress.reportStarted();
diff --git a/src/plugins/languageclient/languageclientformatter.h b/src/plugins/languageclient/languageclientformatter.h
index 795246b2837..4a15196c615 100644
--- a/src/plugins/languageclient/languageclientformatter.h
+++ b/src/plugins/languageclient/languageclientformatter.h
@@ -25,7 +25,6 @@
#pragma once
-#include <languageserverprotocol/icontent.h>
#include <languageserverprotocol/languagefeatures.h>
#include <texteditor/formatter.h>
diff --git a/src/plugins/languageclient/languageclientfunctionhint.cpp b/src/plugins/languageclient/languageclientfunctionhint.cpp
index 708fc399228..1e0cd62cfe3 100644
--- a/src/plugins/languageclient/languageclientfunctionhint.cpp
+++ b/src/plugins/languageclient/languageclientfunctionhint.cpp
@@ -96,7 +96,7 @@ IAssistProposal *FunctionHintProcessor::perform(const AssistInterface *interface
SignatureHelpRequest request((TextDocumentPositionParams(TextDocumentIdentifier(uri), Position(cursor))));
request.setResponseCallback([this](auto response) { this->handleSignatureResponse(response); });
m_client->addAssistProcessor(this);
- m_client->sendContent(request);
+ m_client->sendMessage(request);
m_currentRequest = request.id();
return nullptr;
}
@@ -105,7 +105,7 @@ void FunctionHintProcessor::cancel()
{
QTC_ASSERT(m_client, return);
if (running()) {
- m_client->cancelRequest(m_currentRequest.value());
+ m_client->cancelRequest(*m_currentRequest);
m_client->removeAssistProcessor(this);
m_currentRequest.reset();
}
@@ -116,7 +116,7 @@ void FunctionHintProcessor::handleSignatureResponse(const SignatureHelpRequest::
QTC_ASSERT(m_client, setAsyncProposalAvailable(nullptr); return);
m_currentRequest.reset();
if (auto error = response.error())
- m_client->log(error.value());
+ m_client->log(*error);
m_client->removeAssistProcessor(this);
auto result = response.result().value_or(LanguageClientValue<SignatureHelp>());
if (result.isNull()) {
diff --git a/src/plugins/languageclient/languageclienthoverhandler.cpp b/src/plugins/languageclient/languageclienthoverhandler.cpp
index 3fc137f9387..32db0e53191 100644
--- a/src/plugins/languageclient/languageclienthoverhandler.cpp
+++ b/src/plugins/languageclient/languageclienthoverhandler.cpp
@@ -26,10 +26,11 @@
#include "languageclienthoverhandler.h"
#include "client.h"
+#include "dynamiccapabilities.h"
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h>
@@ -48,23 +49,44 @@ HoverHandler::~HoverHandler()
void HoverHandler::abort()
{
- if (m_client && m_client->reachable() && m_currentRequest.has_value())
+ if (m_client && m_currentRequest.has_value()) {
m_client->cancelRequest(*m_currentRequest);
- m_currentRequest.reset();
+ m_currentRequest.reset();
+ }
m_response = {};
}
+void HoverHandler::setPreferDiagnosticts(bool prefer)
+{
+ m_preferDiagnostics = prefer;
+}
+
void HoverHandler::setHelpItem(const LanguageServerProtocol::MessageId &msgId,
const Core::HelpItem &help)
{
if (msgId == m_response.id()) {
- setContent(m_response.result().value().content());
+ if (Utils::optional<HoverResult> result = m_response.result()) {
+ if (auto hover = Utils::get_if<Hover>(&(*result)))
+ setContent(hover->content());
+ }
m_response = {};
setLastHelpItemIdentified(help);
m_report(priority());
}
}
+bool HoverHandler::reportDiagnostics(const QTextCursor &cursor)
+{
+ const QList<Diagnostic> &diagnostics = m_client->diagnosticsAt(m_uri, cursor);
+ if (diagnostics.isEmpty())
+ return false;
+
+ const QStringList messages = Utils::transform(diagnostics, &Diagnostic::message);
+ setToolTip(messages.join('\n'));
+ m_report(Priority_Diagnostic);
+ return true;
+}
+
void HoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget,
int pos,
TextEditor::BaseHoverHandler::ReportPriority report)
@@ -78,15 +100,12 @@ void HoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget,
}
m_uri = DocumentUri::fromFilePath(editorWidget->textDocument()->filePath());
m_response = {};
- QTextCursor tc = editorWidget->textCursor();
- tc.setPosition(pos);
- const QList<Diagnostic> &diagnostics = m_client->diagnosticsAt(m_uri, tc);
- if (!diagnostics.isEmpty()) {
- const QStringList messages = Utils::transform(diagnostics, &Diagnostic::message);
- setToolTip(messages.join('\n'));
- report(Priority_Diagnostic);
+ m_report = report;
+
+ QTextCursor cursor = editorWidget->textCursor();
+ cursor.setPosition(pos);
+ if (m_preferDiagnostics && reportDiagnostics(cursor))
return;
- }
const Utils::optional<Utils::variant<bool, WorkDoneProgressOptions>> &provider
= m_client->capabilities().hoverProvider();
@@ -95,7 +114,7 @@ void HoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget,
sendMessage = Utils::get<bool>(*provider);
if (Utils::optional<bool> registered = m_client->dynamicCapabilities().isRegistered(
HoverRequest::methodName)) {
- sendMessage = registered.value();
+ sendMessage = *registered;
if (sendMessage) {
const TextDocumentRegistrationOptions option(
m_client->dynamicCapabilities().option(HoverRequest::methodName).toObject());
@@ -111,30 +130,32 @@ void HoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget,
return;
}
- m_report = report;
- QTextCursor cursor = editorWidget->textCursor();
- cursor.setPosition(pos);
- HoverRequest request((TextDocumentPositionParams(TextDocumentIdentifier(m_uri), Position(cursor))));
+ HoverRequest request{TextDocumentPositionParams(TextDocumentIdentifier(m_uri),
+ Position(cursor))};
m_currentRequest = request.id();
request.setResponseCallback(
- [this](const HoverRequest::Response &response) { handleResponse(response); });
- m_client->sendContent(request);
+ [this, cursor](const HoverRequest::Response &response) { handleResponse(response, cursor); });
+ m_client->sendMessage(request);
}
-void HoverHandler::handleResponse(const HoverRequest::Response &response)
+void HoverHandler::handleResponse(const HoverRequest::Response &response, const QTextCursor &cursor)
{
m_currentRequest.reset();
if (Utils::optional<HoverRequest::Response::Error> error = response.error()) {
if (m_client)
- m_client->log(error.value());
+ m_client->log(*error);
}
- if (Utils::optional<Hover> result = response.result()) {
- if (m_helpItemProvider) {
- m_response = response;
- m_helpItemProvider(response, m_uri);
+ if (Utils::optional<HoverResult> result = response.result()) {
+ if (auto hover = Utils::get_if<Hover>(&(*result))) {
+ if (m_helpItemProvider) {
+ m_response = response;
+ m_helpItemProvider(response, m_uri);
+ return;
+ }
+ setContent(hover->content());
+ } else if (!m_preferDiagnostics && reportDiagnostics(cursor)) {
return;
}
- setContent(result.value().content());
}
m_report(priority());
}
diff --git a/src/plugins/languageclient/languageclienthoverhandler.h b/src/plugins/languageclient/languageclienthoverhandler.h
index c8bcb759fc6..f204de7fd9c 100644
--- a/src/plugins/languageclient/languageclienthoverhandler.h
+++ b/src/plugins/languageclient/languageclienthoverhandler.h
@@ -48,6 +48,13 @@ public:
void abort() override;
+ /// If prefer diagnostics is enabled the hover handler checks whether a diagnostics is at the
+ /// pos passed to identifyMatch _before_ sending hover request to the server. If a diagnostic
+ /// can be found it will be used as a tooltip and no hover request is sent to the server.
+ /// If prefer diagnostics is disabled the diagnostics are only checked if the response is empty.
+ /// Defaults to prefer diagnostics.
+ void setPreferDiagnosticts(bool prefer);
+
void setHelpItemProvider(const HelpItemProvider &provider) { m_helpItemProvider = provider; }
void setHelpItem(const LanguageServerProtocol::MessageId &msgId, const Core::HelpItem &help);
@@ -57,8 +64,10 @@ protected:
ReportPriority report) override;
private:
- void handleResponse(const LanguageServerProtocol::HoverRequest::Response &response);
+ void handleResponse(const LanguageServerProtocol::HoverRequest::Response &response,
+ const QTextCursor &cursor);
void setContent(const LanguageServerProtocol::HoverContent &content);
+ bool reportDiagnostics(const QTextCursor &cursor);
QPointer<Client> m_client;
Utils::optional<LanguageServerProtocol::MessageId> m_currentRequest;
@@ -66,6 +75,7 @@ private:
LanguageServerProtocol::HoverRequest::Response m_response;
TextEditor::BaseHoverHandler::ReportPriority m_report;
HelpItemProvider m_helpItemProvider;
+ bool m_preferDiagnostics = true;
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientinterface.cpp b/src/plugins/languageclient/languageclientinterface.cpp
index b2ac3836be9..3486240d9dc 100644
--- a/src/plugins/languageclient/languageclientinterface.cpp
+++ b/src/plugins/languageclient/languageclientinterface.cpp
@@ -46,9 +46,11 @@ BaseClientInterface::~BaseClientInterface()
m_buffer.close();
}
-void BaseClientInterface::sendMessage(const BaseMessage &message)
+void BaseClientInterface::sendMessage(const JsonRpcMessage message)
{
- sendData(message.toData());
+ const BaseMessage baseMessage = message.toBaseMessage();
+ sendData(baseMessage.header());
+ sendData(baseMessage.content);
}
void BaseClientInterface::resetBuffer()
@@ -77,8 +79,7 @@ void BaseClientInterface::parseData(const QByteArray &data)
emit error(parseError);
if (!m_currentMessage.isComplete())
break;
- emit messageReceived(m_currentMessage);
- m_currentMessage = BaseMessage();
+ parseCurrentMessage();
}
if (m_buffer.atEnd()) {
m_buffer.close();
@@ -87,71 +88,85 @@ void BaseClientInterface::parseData(const QByteArray &data)
}
}
-StdIOClientInterface::StdIOClientInterface()
- : m_process(ProcessMode::Writer)
+void BaseClientInterface::parseCurrentMessage()
{
- connect(&m_process, &QtcProcess::readyReadStandardError,
- this, &StdIOClientInterface::readError);
- connect(&m_process, &QtcProcess::readyReadStandardOutput,
- this, &StdIOClientInterface::readOutput);
- connect(&m_process, &QtcProcess::finished,
- this, &StdIOClientInterface::onProcessFinished);
+ if (m_currentMessage.mimeType == JsonRpcMessage::jsonRpcMimeType()) {
+ emit messageReceived(JsonRpcMessage(m_currentMessage));
+ } else {
+ emit error(tr("Cannot handle MIME type of message %1")
+ .arg(QString::fromUtf8(m_currentMessage.mimeType)));
+ }
+ m_currentMessage = BaseMessage();
}
StdIOClientInterface::~StdIOClientInterface()
{
- m_process.stopProcess();
+ delete m_process;
}
-bool StdIOClientInterface::start()
+void StdIOClientInterface::startImpl()
{
- m_process.start();
- if (!m_process.waitForStarted() || m_process.state() != QProcess::Running) {
- emit error(m_process.errorString());
- return false;
+ if (m_process) {
+ QTC_CHECK(!m_process->isRunning());
+ delete m_process;
}
- return true;
+ m_process = new Utils::QtcProcess;
+ m_process->setProcessMode(ProcessMode::Writer);
+ connect(m_process, &QtcProcess::readyReadStandardError,
+ this, &StdIOClientInterface::readError);
+ connect(m_process, &QtcProcess::readyReadStandardOutput,
+ this, &StdIOClientInterface::readOutput);
+ connect(m_process, &QtcProcess::started, this, &StdIOClientInterface::started);
+ connect(m_process, &QtcProcess::done, this, [this] {
+ if (m_process->result() != ProcessResult::FinishedWithSuccess)
+ emit error(m_process->exitMessage());
+ emit finished();
+ });
+ m_process->setCommand(m_cmd);
+ m_process->setWorkingDirectory(m_workingDirectory);
+ if (m_env.isValid())
+ m_process->setEnvironment(m_env);
+ m_process->start();
}
void StdIOClientInterface::setCommandLine(const CommandLine &cmd)
{
- m_process.setCommand(cmd);
+ m_cmd = cmd;
}
void StdIOClientInterface::setWorkingDirectory(const FilePath &workingDirectory)
{
- m_process.setWorkingDirectory(workingDirectory);
+ m_workingDirectory = workingDirectory;
+}
+
+void StdIOClientInterface::setEnvironment(const Utils::Environment &environment)
+{
+ m_env = environment;
}
void StdIOClientInterface::sendData(const QByteArray &data)
{
- if (m_process.state() != QProcess::Running) {
+ if (!m_process || m_process->state() != QProcess::Running) {
emit error(tr("Cannot send data to unstarted server %1")
- .arg(m_process.commandLine().toUserOutput()));
+ .arg(m_cmd.toUserOutput()));
return;
}
qCDebug(LOGLSPCLIENTV) << "StdIOClient send data:";
qCDebug(LOGLSPCLIENTV).noquote() << data;
- m_process.write(data);
-}
-
-void StdIOClientInterface::onProcessFinished()
-{
- if (m_process.exitStatus() == QProcess::CrashExit)
- emit error(tr("Crashed with exit code %1: %2")
- .arg(m_process.exitCode()).arg(m_process.errorString()));
- emit finished();
+ m_process->writeRaw(data);
}
void StdIOClientInterface::readError()
{
+ QTC_ASSERT(m_process, return);
qCDebug(LOGLSPCLIENTV) << "StdIOClient std err:\n";
- qCDebug(LOGLSPCLIENTV).noquote() << m_process.readAllStandardError();
+ qCDebug(LOGLSPCLIENTV).noquote() << m_process->readAllStandardError();
}
void StdIOClientInterface::readOutput()
{
- const QByteArray &out = m_process.readAllStandardOutput();
+ QTC_ASSERT(m_process, return);
+ const QByteArray &out = m_process->readAllStandardOutput();
qCDebug(LOGLSPCLIENTV) << "StdIOClient std out:\n";
qCDebug(LOGLSPCLIENTV).noquote() << out;
parseData(out);
diff --git a/src/plugins/languageclient/languageclientinterface.h b/src/plugins/languageclient/languageclientinterface.h
index 17cf222fd3f..4aa683f180d 100644
--- a/src/plugins/languageclient/languageclientinterface.h
+++ b/src/plugins/languageclient/languageclientinterface.h
@@ -27,8 +27,9 @@
#include "languageclient_global.h"
-#include <languageserverprotocol/basemessage.h>
+#include <languageserverprotocol/jsonrpcmessages.h>
+#include <utils/environment.h>
#include <utils/qtcprocess.h>
#include <QBuffer>
@@ -45,19 +46,22 @@ public:
~BaseClientInterface() override;
- void sendMessage(const LanguageServerProtocol::BaseMessage &message);
- virtual bool start() { return true; }
+ void sendMessage(const LanguageServerProtocol::JsonRpcMessage message);
+ void start() { startImpl(); }
void resetBuffer();
signals:
- void messageReceived(LanguageServerProtocol::BaseMessage message);
+ void messageReceived(const LanguageServerProtocol::JsonRpcMessage message);
void finished();
void error(const QString &message);
+ void started();
protected:
+ virtual void startImpl() { emit started(); }
virtual void sendData(const QByteArray &data) = 0;
void parseData(const QByteArray &data);
+ virtual void parseCurrentMessage();
private:
QBuffer m_buffer;
@@ -68,7 +72,7 @@ class LANGUAGECLIENT_EXPORT StdIOClientInterface : public BaseClientInterface
{
Q_OBJECT
public:
- StdIOClientInterface();
+ StdIOClientInterface() = default;
~StdIOClientInterface() override;
StdIOClientInterface(const StdIOClientInterface &) = delete;
@@ -76,20 +80,23 @@ public:
StdIOClientInterface &operator=(const StdIOClientInterface &) = delete;
StdIOClientInterface &operator=(StdIOClientInterface &&) = delete;
- bool start() override;
+ void startImpl() override;
// These functions only have an effect if they are called before start
void setCommandLine(const Utils::CommandLine &cmd);
void setWorkingDirectory(const Utils::FilePath &workingDirectory);
+ void setEnvironment(const Utils::Environment &environment);
protected:
void sendData(const QByteArray &data) final;
- Utils::QtcProcess m_process;
+ Utils::CommandLine m_cmd;
+ Utils::FilePath m_workingDirectory;
+ Utils::QtcProcess *m_process = nullptr;
+ Utils::Environment m_env;
private:
void readError();
void readOutput();
- void onProcessFinished();
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp
index 992138f06a1..88f9257327b 100644
--- a/src/plugins/languageclient/languageclientmanager.cpp
+++ b/src/plugins/languageclient/languageclientmanager.cpp
@@ -25,7 +25,9 @@
#include "languageclientmanager.h"
+#include "languageclienthoverhandler.h"
#include "languageclientplugin.h"
+#include "languageclientsymbolsupport.h"
#include "languageclientutils.h"
#include <coreplugin/editormanager/editormanager.h>
@@ -42,7 +44,6 @@
#include <texteditor/textmark.h>
#include <utils/algorithm.h>
#include <utils/executeondestruction.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/theme/theme.h>
#include <utils/utilsicons.h>
@@ -62,17 +63,6 @@ LanguageClientManager::LanguageClientManager(QObject *parent)
{
using namespace Core;
using namespace ProjectExplorer;
- JsonRpcMessageHandler::registerMessageProvider<PublishDiagnosticsNotification>();
- JsonRpcMessageHandler::registerMessageProvider<ApplyWorkspaceEditRequest>();
- JsonRpcMessageHandler::registerMessageProvider<LogMessageNotification>();
- JsonRpcMessageHandler::registerMessageProvider<ShowMessageRequest>();
- JsonRpcMessageHandler::registerMessageProvider<ShowMessageNotification>();
- JsonRpcMessageHandler::registerMessageProvider<WorkSpaceFolderRequest>();
- JsonRpcMessageHandler::registerMessageProvider<RegisterCapabilityRequest>();
- JsonRpcMessageHandler::registerMessageProvider<UnregisterCapabilityRequest>();
- JsonRpcMessageHandler::registerMessageProvider<WorkDoneProgressCreateRequest>();
- JsonRpcMessageHandler::registerMessageProvider<ProgressNotification>();
- JsonRpcMessageHandler::registerMessageProvider<SemanticTokensRefreshRequest>();
connect(EditorManager::instance(), &EditorManager::editorOpened,
this, &LanguageClientManager::editorOpened);
connect(EditorManager::instance(), &EditorManager::documentOpened,
@@ -177,7 +167,8 @@ void LanguageClientManager::clientFinished(Client *client)
emit managerInstance->shutdownFinished();
}
-Client *LanguageClientManager::startClient(BaseSettings *setting, ProjectExplorer::Project *project)
+Client *LanguageClientManager::startClient(const BaseSettings *setting,
+ ProjectExplorer::Project *project)
{
QTC_ASSERT(managerInstance, return nullptr);
QTC_ASSERT(setting, return nullptr);
@@ -190,7 +181,7 @@ Client *LanguageClientManager::startClient(BaseSettings *setting, ProjectExplore
return client;
}
-QVector<Client *> LanguageClientManager::clients()
+const QList<Client *> LanguageClientManager::clients()
{
QTC_ASSERT(managerInstance, return {});
return managerInstance->m_clients;
@@ -234,14 +225,11 @@ void LanguageClientManager::deleteClient(Client *client)
qCDebug(Log) << "delete client: " << client->name() << client;
client->disconnect(managerInstance);
managerInstance->m_clients.removeAll(client);
- for (QVector<Client *> &clients : managerInstance->m_clientsForSetting)
+ for (QList<Client *> &clients : managerInstance->m_clientsForSetting)
clients.removeAll(client);
- if (managerInstance->m_shuttingDown) {
- delete client;
- } else {
- client->deleteLater();
+ client->deleteLater();
+ if (!managerInstance->m_shuttingDown)
emit instance()->clientRemoved(client);
- }
}
void LanguageClientManager::shutdown()
@@ -273,7 +261,7 @@ QList<Client *> LanguageClientManager::clientsSupportingDocument(const TextEdito
QTC_ASSERT(doc, return {};);
return Utils::filtered(managerInstance->reachableClients(), [doc](Client *client) {
return client->isSupportedDocument(doc);
- }).toList();
+ });
}
void LanguageClientManager::applySettings()
@@ -287,7 +275,7 @@ void LanguageClientManager::applySettings()
for (BaseSettings *setting : restarts) {
QList<TextEditor::TextDocument *> documents;
- const QVector<Client *> currentClients = clientForSetting(setting);
+ const QList<Client *> currentClients = clientsForSetting(setting);
for (Client *client : currentClients) {
documents << managerInstance->m_clientForDocument.keys(client);
shutdownClient(client);
@@ -361,14 +349,14 @@ void LanguageClientManager::registerClientSettings(BaseSettings *settings)
managerInstance->applySettings();
}
-void LanguageClientManager::enableClientSettings(const QString &settingsId)
+void LanguageClientManager::enableClientSettings(const QString &settingsId, bool enable)
{
QTC_ASSERT(managerInstance, return);
- LanguageClientSettings::enableSettings(settingsId);
+ LanguageClientSettings::enableSettings(settingsId, enable);
managerInstance->applySettings();
}
-QVector<Client *> LanguageClientManager::clientForSetting(const BaseSettings *setting)
+QList<Client *> LanguageClientManager::clientsForSetting(const BaseSettings *setting)
{
QTC_ASSERT(managerInstance, return {});
auto instance = managerInstance;
@@ -415,7 +403,7 @@ const QList<Client *> LanguageClientManager::clientsForProject(
{
return Utils::filtered(managerInstance->m_clients, [project](const Client *c) {
return c->project() == project;
- }).toList();
+ });
}
void LanguageClientManager::openDocumentWithClient(TextEditor::TextDocument *document, Client *client)
@@ -438,9 +426,9 @@ void LanguageClientManager::openDocumentWithClient(TextEditor::TextDocument *doc
TextEditor::IOutlineWidgetFactory::updateOutline();
}
-void LanguageClientManager::logBaseMessage(const LspLogMessage::MessageSender sender,
- const QString &clientName,
- const BaseMessage &message)
+void LanguageClientManager::logJsonRpcMessage(const LspLogMessage::MessageSender sender,
+ const QString &clientName,
+ const LanguageServerProtocol::JsonRpcMessage &message)
{
instance()->m_inspector.log(sender, clientName, message);
}
@@ -456,7 +444,7 @@ void LanguageClientManager::showInspector()
inspectorWidget->show();
}
-QVector<Client *> LanguageClientManager::reachableClients()
+QList<Client *> LanguageClientManager::reachableClients()
{
return Utils::filtered(m_clients, &Client::reachable);
}
@@ -468,7 +456,7 @@ void LanguageClientManager::editorOpened(Core::IEditor *editor)
if (TextEditorWidget *widget = textEditor->editorWidget()) {
connect(widget, &TextEditorWidget::requestLinkAt, this,
[document = textEditor->textDocument()]
- (const QTextCursor &cursor, Utils::ProcessLinkCallback &callback, bool resolveTarget) {
+ (const QTextCursor &cursor, const Utils::LinkHandler &callback, bool resolveTarget) {
if (auto client = clientForDocument(document))
client->symbolSupport().findLinkAt(document, cursor, callback, resolveTarget);
});
@@ -507,7 +495,7 @@ void LanguageClientManager::documentOpened(Core::IDocument *document)
for (BaseSettings *setting : settings) {
if (setting->isValid() && setting->m_enabled
&& setting->m_languageFilter.isSupported(document)) {
- QVector<Client *> clients = clientForSetting(setting);
+ QList<Client *> clients = clientsForSetting(setting);
if (setting->m_startBehavior == BaseSettings::RequiresProject) {
const Utils::FilePath &filePath = document->filePath();
for (ProjectExplorer::Project *project :
@@ -549,7 +537,7 @@ void LanguageClientManager::documentClosed(Core::IDocument *document)
void LanguageClientManager::documentContentsSaved(Core::IDocument *document)
{
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document)) {
- const QVector<Client *> &clients = reachableClients();
+ const QList<Client *> &clients = reachableClients();
for (Client *client : clients)
client->documentContentsSaved(textDocument);
}
@@ -558,7 +546,7 @@ void LanguageClientManager::documentContentsSaved(Core::IDocument *document)
void LanguageClientManager::documentWillSave(Core::IDocument *document)
{
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document)) {
- const QVector<Client *> &clients = reachableClients();
+ const QList<Client *> &clients = reachableClients();
for (Client *client : clients)
client->documentWillSave(textDocument);
}
@@ -570,7 +558,7 @@ void LanguageClientManager::updateProject(ProjectExplorer::Project *project)
if (setting->isValid()
&& setting->m_enabled
&& setting->m_startBehavior == BaseSettings::RequiresProject) {
- if (Utils::findOrDefault(clientForSetting(setting),
+ if (Utils::findOrDefault(clientsForSetting(setting),
[project](const QPointer<Client> &client) {
return client->project() == project;
})
@@ -599,7 +587,7 @@ void LanguageClientManager::projectAdded(ProjectExplorer::Project *project)
connect(project, &ProjectExplorer::Project::fileListChanged, this, [this, project]() {
updateProject(project);
});
- const QVector<Client *> &clients = reachableClients();
+ const QList<Client *> &clients = reachableClients();
for (Client *client : clients)
client->projectOpened(project);
}
diff --git a/src/plugins/languageclient/languageclientmanager.h b/src/plugins/languageclient/languageclientmanager.h
index e585d0dd8c6..7fb7c045512 100644
--- a/src/plugins/languageclient/languageclientmanager.h
+++ b/src/plugins/languageclient/languageclientmanager.h
@@ -61,8 +61,8 @@ public:
static void clientStarted(Client *client);
static void clientFinished(Client *client);
- static Client *startClient(BaseSettings *setting, ProjectExplorer::Project *project = nullptr);
- static QVector<Client *> clients();
+ static Client *startClient(const BaseSettings *setting, ProjectExplorer::Project *project = nullptr);
+ static const QList<Client *> clients();
static void addClient(Client *client);
static void addExclusiveRequest(const LanguageServerProtocol::MessageId &id, Client *client);
@@ -80,8 +80,8 @@ public:
static void applySettings();
static QList<BaseSettings *> currentSettings();
static void registerClientSettings(BaseSettings *settings);
- static void enableClientSettings(const QString &settingsId);
- static QVector<Client *> clientForSetting(const BaseSettings *setting);
+ static void enableClientSettings(const QString &settingsId, bool enable = true);
+ static QList<Client *> clientsForSetting(const BaseSettings *setting);
static const BaseSettings *settingForClient(Client *setting);
static Client *clientForDocument(TextEditor::TextDocument *document);
static Client *clientForFilePath(const Utils::FilePath &filePath);
@@ -96,9 +96,10 @@ public:
///
static void openDocumentWithClient(TextEditor::TextDocument *document, Client *client);
- static void logBaseMessage(const LspLogMessage::MessageSender sender,
- const QString &clientName,
- const LanguageServerProtocol::BaseMessage &message);
+ static void logJsonRpcMessage(const LspLogMessage::MessageSender sender,
+ const QString &clientName,
+ const LanguageServerProtocol::JsonRpcMessage &message);
+
static void showInspector();
signals:
@@ -117,12 +118,12 @@ private:
void updateProject(ProjectExplorer::Project *project);
void projectAdded(ProjectExplorer::Project *project);
- QVector<Client *> reachableClients();
+ QList<Client *> reachableClients();
bool m_shuttingDown = false;
- QVector<Client *> m_clients;
+ QList<Client *> m_clients;
QList<BaseSettings *> m_currentSettings; // owned
- QMap<QString, QVector<Client *>> m_clientsForSetting;
+ QMap<QString, QList<Client *>> m_clientsForSetting;
QHash<TextEditor::TextDocument *, QPointer<Client>> m_clientForDocument;
QHash<LanguageServerProtocol::MessageId, QList<Client *>> m_exclusiveRequests;
DocumentLocatorFilter m_currentDocumentLocatorFilter;
diff --git a/src/plugins/languageclient/languageclientoutline.cpp b/src/plugins/languageclient/languageclientoutline.cpp
index 9331ad69e58..abaea39f954 100644
--- a/src/plugins/languageclient/languageclientoutline.cpp
+++ b/src/plugins/languageclient/languageclientoutline.cpp
@@ -25,17 +25,19 @@
#include "languageclientoutline.h"
+#include "documentsymbolcache.h"
#include "languageclientmanager.h"
#include "languageclientutils.h"
-#include <coreplugin/find/itemviewfind.h>
#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/find/itemviewfind.h>
#include <languageserverprotocol/languagefeatures.h>
#include <texteditor/outlinefactory.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
+#include <utils/dropsupport.h>
#include <utils/itemviews.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/navigationtreeview.h>
#include <utils/treemodel.h>
#include <utils/treeviewcombobox.h>
#include <utils/utilsicons.h>
@@ -48,6 +50,23 @@ using namespace LanguageServerProtocol;
namespace LanguageClient {
+const QList<SymbolInformation> sortedSymbols(const QList<SymbolInformation> &symbols)
+{
+ auto result = symbols;
+ Utils::sort(result, [](const SymbolInformation &a, const SymbolInformation &b){
+ return a.location().range().start() < b.location().range().start();
+ });
+ return result;
+}
+const QList<DocumentSymbol> sortedSymbols(const QList<DocumentSymbol> &symbols)
+{
+ auto result = symbols;
+ Utils::sort(result, [](const DocumentSymbol &a, const DocumentSymbol &b){
+ return a.range().start() < b.range().start();
+ });
+ return result;
+}
+
class LanguageClientOutlineItem : public Utils::TypedTreeItem<LanguageClientOutlineItem>
{
public:
@@ -65,7 +84,9 @@ public:
, m_symbolStringifier(stringifier)
, m_type(info.kind())
{
- for (const DocumentSymbol &child : info.children().value_or(QList<DocumentSymbol>()))
+ const QList<LanguageServerProtocol::DocumentSymbol> children = sortedSymbols(
+ info.children().value_or(QList<DocumentSymbol>()));
+ for (const DocumentSymbol &child : children)
appendChild(new LanguageClientOutlineItem(child, stringifier));
}
@@ -84,6 +105,13 @@ public:
}
}
+ Qt::ItemFlags flags(int column) const override
+ {
+ Q_UNUSED(column)
+ return Utils::TypedTreeItem<LanguageClientOutlineItem>::flags(column)
+ | Qt::ItemIsDragEnabled;
+ }
+
Range range() const { return m_range; }
Position pos() const { return m_range.start(); }
bool contains(const Position &pos) const { return m_range.contains(pos); }
@@ -100,16 +128,18 @@ class LanguageClientOutlineModel : public Utils::TreeModel<LanguageClientOutline
{
public:
using Utils::TreeModel<LanguageClientOutlineItem>::TreeModel;
+ void setFilePath(const Utils::FilePath &filePath) { m_filePath = filePath; }
+
void setInfo(const QList<SymbolInformation> &info)
{
clear();
- for (const SymbolInformation &symbol : info)
+ for (const SymbolInformation &symbol : sortedSymbols(info))
rootItem()->appendChild(new LanguageClientOutlineItem(symbol));
}
void setInfo(const QList<DocumentSymbol> &info)
{
clear();
- for (const DocumentSymbol &symbol : info)
+ for (const DocumentSymbol &symbol : sortedSymbols(info))
rootItem()->appendChild(new LanguageClientOutlineItem(symbol, m_symbolStringifier));
}
@@ -118,8 +148,42 @@ public:
m_symbolStringifier = stringifier;
}
+ Qt::DropActions supportedDragActions() const override
+ {
+ return Qt::MoveAction;
+ }
+
+ QStringList mimeTypes() const override
+ {
+ return Utils::DropSupport::mimeTypesForFilePaths();
+ }
+
+ QMimeData *mimeData(const QModelIndexList &indexes) const override
+ {
+ auto mimeData = new Utils::DropMimeData;
+ for (const QModelIndex &index : indexes) {
+ if (LanguageClientOutlineItem *item = itemForIndex(index)) {
+ const LanguageServerProtocol::Position pos = item->pos();
+ mimeData->addFile(m_filePath, pos.line() + 1, pos.character());
+ }
+ }
+ return mimeData;
+ }
+
private:
SymbolStringifier m_symbolStringifier;
+ Utils::FilePath m_filePath;
+};
+
+class DragSortFilterProxyModel : public QSortFilterProxyModel
+{
+public:
+ using QSortFilterProxyModel::QSortFilterProxyModel;
+
+ Qt::DropActions supportedDragActions() const override
+ {
+ return sourceModel()->supportedDragActions();
+ }
};
class LanguageClientOutlineWidget : public TextEditor::IOutlineWidget
@@ -145,8 +209,8 @@ private:
QPointer<Client> m_client;
QPointer<TextEditor::BaseTextEditor> m_editor;
LanguageClientOutlineModel m_model;
- QSortFilterProxyModel m_proxyModel;
- Utils::TreeView m_view;
+ DragSortFilterProxyModel m_proxyModel;
+ Utils::NavigationTreeView m_view;
DocumentUri m_uri;
bool m_sync = false;
bool m_sorted = false;
@@ -176,11 +240,14 @@ LanguageClientOutlineWidget::LanguageClientOutlineWidget(Client *client,
layout->addWidget(Core::ItemViewFind::createSearchableWrapper(&m_view));
setLayout(layout);
m_model.setSymbolStringifier(m_client->symbolStringifier());
+ m_model.setFilePath(editor->textDocument()->filePath());
m_proxyModel.setSourceModel(&m_model);
m_view.setModel(&m_proxyModel);
m_view.setHeaderHidden(true);
m_view.setExpandsOnDoubleClick(false);
m_view.setFrameStyle(QFrame::NoFrame);
+ m_view.setDragEnabled(true);
+ m_view.setDragDropMode(QAbstractItemView::DragOnly);
connect(&m_view, &QAbstractItemView::activated,
this, &LanguageClientOutlineWidget::onItemActivated);
connect(m_editor->editorWidget(), &TextEditor::TextEditorWidget::cursorPositionChanged,
@@ -188,6 +255,7 @@ LanguageClientOutlineWidget::LanguageClientOutlineWidget(Client *client,
if (m_sync)
updateSelectionInTree(m_editor->textCursor());
});
+ setFocusProxy(&m_view);
}
QList<QAction *> LanguageClientOutlineWidget::filterMenuActions() const
@@ -266,7 +334,7 @@ void LanguageClientOutlineWidget::updateSelectionInTree(const QTextCursor &curre
{
if (LanguageClientOutlineItem *item = itemForCursor(m_model, currentCursor)) {
const QModelIndex index = m_proxyModel.mapFromSource(m_model.indexForItem(item));
- m_view.selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
+ m_view.setCurrentIndex(index);
m_view.scrollTo(index);
} else {
m_view.clearSelection();
@@ -282,46 +350,29 @@ void LanguageClientOutlineWidget::onItemActivated(const QModelIndex &index)
m_editor->widget()->setFocus();
}
-bool LanguageClientOutlineWidgetFactory::clientSupportsDocumentSymbols(
- const Client *client, const TextEditor::TextDocument *doc)
-{
- if (!client)
- return false;
- DynamicCapabilities dc = client->dynamicCapabilities();
- if (dc.isRegistered(DocumentSymbolsRequest::methodName).value_or(false)) {
- TextDocumentRegistrationOptions options(dc.option(DocumentSymbolsRequest::methodName));
- return !options.isValid()
- || options.filterApplies(doc->filePath(), Utils::mimeTypeForName(doc->mimeType()));
- }
- const Utils::optional<Utils::variant<bool, WorkDoneProgressOptions>> &provider
- = client->capabilities().documentSymbolProvider();
- if (!provider.has_value())
- return false;
- if (Utils::holds_alternative<bool>(*provider))
- return Utils::get<bool>(*provider);
- return true;
-}
-
bool LanguageClientOutlineWidgetFactory::supportsEditor(Core::IEditor *editor) const
{
- auto doc = qobject_cast<TextEditor::TextDocument *>(editor->document());
- if (!doc)
- return false;
- return clientSupportsDocumentSymbols(LanguageClientManager::clientForDocument(doc), doc);
+ if (auto doc = qobject_cast<TextEditor::TextDocument *>(editor->document())) {
+ if (Client *client = LanguageClientManager::clientForDocument(doc))
+ return client->supportsDocumentSymbols(doc);
+ }
+ return false;
}
TextEditor::IOutlineWidget *LanguageClientOutlineWidgetFactory::createWidget(Core::IEditor *editor)
{
auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor);
QTC_ASSERT(textEditor, return nullptr);
- Client *client = LanguageClientManager::clientForDocument(textEditor->textDocument());
- if (!client || !clientSupportsDocumentSymbols(client, textEditor->textDocument()))
- return nullptr;
- return new LanguageClientOutlineWidget(client, textEditor);
+ if (Client *client = LanguageClientManager::clientForDocument(textEditor->textDocument())) {
+ if (client->supportsDocumentSymbols(textEditor->textDocument()))
+ return new LanguageClientOutlineWidget(client, textEditor);
+ }
+ return nullptr;
}
class OutlineComboBox : public Utils::TreeViewComboBox
{
+ Q_DECLARE_TR_FUNCTIONS(LanguageClient::OutlineComboBox)
public:
OutlineComboBox(Client *client, TextEditor::BaseTextEditor *editor);
@@ -339,16 +390,12 @@ private:
const DocumentUri m_uri;
};
-Utils::TreeViewComboBox *LanguageClientOutlineWidgetFactory::createComboBox(Client *client,
- Core::IEditor *editor)
+Utils::TreeViewComboBox *LanguageClientOutlineWidgetFactory::createComboBox(
+ Client *client, TextEditor::BaseTextEditor *editor)
{
- auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor);
- QTC_ASSERT(textEditor, return nullptr);
- TextEditor::TextDocument *document = textEditor->textDocument();
- if (!client || !clientSupportsDocumentSymbols(client, document))
- return nullptr;
-
- return new OutlineComboBox(client, textEditor);
+ if (client && client->supportsDocumentSymbols(editor->textDocument()))
+ return new OutlineComboBox(client, editor);
+ return nullptr;
}
OutlineComboBox::OutlineComboBox(Client *client, TextEditor::BaseTextEditor *editor)
@@ -376,8 +423,10 @@ OutlineComboBox::OutlineComboBox(Client *client, TextEditor::BaseTextEditor *edi
sortAction->setChecked(sorted);
addAction(sortAction);
- connect(client->documentSymbolCache(), &DocumentSymbolCache::gotSymbols,
- this, &OutlineComboBox::updateModel);
+ connect(client->documentSymbolCache(),
+ &DocumentSymbolCache::gotSymbols,
+ this,
+ &OutlineComboBox::updateModel);
connect(client, &Client::documentUpdated, this, &OutlineComboBox::documentUpdated);
connect(m_editorWidget, &TextEditor::TextEditorWidget::cursorPositionChanged,
this, &OutlineComboBox::updateEntry);
diff --git a/src/plugins/languageclient/languageclientoutline.h b/src/plugins/languageclient/languageclientoutline.h
index fe7741a07b9..f397fe701b9 100644
--- a/src/plugins/languageclient/languageclientoutline.h
+++ b/src/plugins/languageclient/languageclientoutline.h
@@ -27,7 +27,10 @@
#include <texteditor/ioutlinewidget.h>
-namespace TextEditor { class TextDocument; }
+namespace TextEditor {
+class TextDocument;
+class BaseTextEditor;
+} // namespace TextEditor
namespace Utils { class TreeViewComboBox; }
namespace LanguageClient {
@@ -39,9 +42,7 @@ class LanguageClientOutlineWidgetFactory : public TextEditor::IOutlineWidgetFact
public:
using IOutlineWidgetFactory::IOutlineWidgetFactory;
- static Utils::TreeViewComboBox *createComboBox(Client *client, Core::IEditor *editor);
- static bool clientSupportsDocumentSymbols(const Client *client,
- const TextEditor::TextDocument *doc);
+ static Utils::TreeViewComboBox *createComboBox(Client *client, TextEditor::BaseTextEditor *editor);
// IOutlineWidgetFactory interface
public:
bool supportsEditor(Core::IEditor *editor) const override;
diff --git a/src/plugins/languageclient/languageclientplugin.cpp b/src/plugins/languageclient/languageclientplugin.cpp
index c8b4d134a0e..526e255e314 100644
--- a/src/plugins/languageclient/languageclientplugin.cpp
+++ b/src/plugins/languageclient/languageclientplugin.cpp
@@ -41,6 +41,7 @@ static LanguageClientPlugin *m_instance = nullptr;
LanguageClientPlugin::LanguageClientPlugin()
{
m_instance = this;
+ qRegisterMetaType<LanguageServerProtocol::JsonRpcMessage>();
}
LanguageClientPlugin::~LanguageClientPlugin()
@@ -87,7 +88,7 @@ ExtensionSystem::IPlugin::ShutdownFlag LanguageClientPlugin::aboutToShutdown()
QTC_ASSERT(LanguageClientManager::instance(),
return ExtensionSystem::IPlugin::SynchronousShutdown);
connect(LanguageClientManager::instance(), &LanguageClientManager::shutdownFinished,
- this, &ExtensionSystem::IPlugin::asynchronousShutdownFinished);
+ this, &ExtensionSystem::IPlugin::asynchronousShutdownFinished, Qt::QueuedConnection);
return ExtensionSystem::IPlugin::AsynchronousShutdown;
}
diff --git a/src/plugins/languageclient/languageclientquickfix.cpp b/src/plugins/languageclient/languageclientquickfix.cpp
index cf9f7196d0c..e65ba296b18 100644
--- a/src/plugins/languageclient/languageclientquickfix.cpp
+++ b/src/plugins/languageclient/languageclientquickfix.cpp
@@ -30,7 +30,6 @@
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/genericproposal.h>
-#include <texteditor/codeassist/iassistprocessor.h>
#include <texteditor/quickfix.h>
@@ -56,39 +55,17 @@ void CodeActionQuickFixOperation::perform()
m_client->executeCommand(*command);
}
-class CommandQuickFixOperation : public QuickFixOperation
-{
-public:
- CommandQuickFixOperation(const Command &command, Client *client)
- : m_command(command)
- , m_client(client)
- { setDescription(command.title()); }
- void perform() override
- {
- if (m_client)
- m_client->executeCommand(m_command);
- }
+CommandQuickFixOperation::CommandQuickFixOperation(const Command &command, Client *client)
+ : m_command(command)
+ , m_client(client)
+{ setDescription(command.title()); }
-private:
- Command m_command;
- QPointer<Client> m_client;
-};
-class LanguageClientQuickFixAssistProcessor : public IAssistProcessor
+void CommandQuickFixOperation::perform()
{
-public:
- explicit LanguageClientQuickFixAssistProcessor(Client *client) : m_client(client) {}
- bool running() override { return m_currentRequest.has_value(); }
- IAssistProposal *perform(const AssistInterface *interface) override;
- void cancel() override;
-
-private:
- void handleCodeActionResponse(const CodeActionRequest::Response &response);
-
- QSharedPointer<const AssistInterface> m_assistInterface;
- Client *m_client = nullptr; // not owned
- Utils::optional<MessageId> m_currentRequest;
-};
+ if (m_client)
+ m_client->executeCommand(m_command);
+}
IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInterface *interface)
{
@@ -96,12 +73,13 @@ IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInte
CodeActionParams params;
params.setContext({});
- QTextCursor cursor(interface->textDocument());
- cursor.setPosition(interface->position());
- if (cursor.atBlockEnd() || cursor.atBlockStart())
- cursor.select(QTextCursor::LineUnderCursor);
- else
- cursor.select(QTextCursor::WordUnderCursor);
+ QTextCursor cursor = interface->cursor();
+ if (!cursor.hasSelection()) {
+ if (cursor.atBlockEnd() || cursor.atBlockStart())
+ cursor.select(QTextCursor::LineUnderCursor);
+ else
+ cursor.select(QTextCursor::WordUnderCursor);
+ }
if (!cursor.hasSelection())
cursor.select(QTextCursor::LineUnderCursor);
Range range(cursor);
@@ -126,32 +104,37 @@ IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInte
void LanguageClientQuickFixAssistProcessor::cancel()
{
if (running()) {
- m_client->cancelRequest(m_currentRequest.value());
+ m_client->cancelRequest(*m_currentRequest);
m_client->removeAssistProcessor(this);
m_currentRequest.reset();
}
}
-void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(
- const CodeActionRequest::Response &response)
+void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(const CodeActionRequest::Response &response)
{
m_currentRequest.reset();
if (const Utils::optional<CodeActionRequest::Response::Error> &error = response.error())
m_client->log(*error);
- QuickFixOperations ops;
- if (const Utils::optional<CodeActionResult> &_result = response.result()) {
- const CodeActionResult &result = _result.value();
- if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&result)) {
- for (const Utils::variant<Command, CodeAction> &item : *list) {
- if (auto action = Utils::get_if<CodeAction>(&item))
- ops << new CodeActionQuickFixOperation(*action, m_client);
- else if (auto command = Utils::get_if<Command>(&item))
- ops << new CommandQuickFixOperation(*command, m_client);
- }
+ m_client->removeAssistProcessor(this);
+ GenericProposal *proposal = nullptr;
+ if (const Utils::optional<CodeActionResult> &result = response.result())
+ proposal = handleCodeActionResult(*result);
+ setAsyncProposalAvailable(proposal);
+}
+
+GenericProposal *LanguageClientQuickFixAssistProcessor::handleCodeActionResult(const CodeActionResult &result)
+{
+ if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&result)) {
+ QuickFixOperations ops;
+ for (const Utils::variant<Command, CodeAction> &item : *list) {
+ if (auto action = Utils::get_if<CodeAction>(&item))
+ ops << new CodeActionQuickFixOperation(*action, m_client);
+ else if (auto command = Utils::get_if<Command>(&item))
+ ops << new CommandQuickFixOperation(*command, m_client);
}
+ return GenericProposal::createProposal(m_assistInterface.data(), ops);
}
- m_client->removeAssistProcessor(this);
- setAsyncProposalAvailable(GenericProposal::createProposal(m_assistInterface.data(), ops));
+ return nullptr;
}
LanguageClientQuickFixProvider::LanguageClientQuickFixProvider(Client *client)
diff --git a/src/plugins/languageclient/languageclientquickfix.h b/src/plugins/languageclient/languageclientquickfix.h
index 955f12bc87e..8d961fa440c 100644
--- a/src/plugins/languageclient/languageclientquickfix.h
+++ b/src/plugins/languageclient/languageclientquickfix.h
@@ -28,12 +28,18 @@
#include "languageclient_global.h"
#include <texteditor/codeassist/iassistprovider.h>
+#include <texteditor/codeassist/iassistprocessor.h>
#include <texteditor/quickfix.h>
#include <languageserverprotocol/languagefeatures.h>
#include <QPointer>
+namespace TextEditor {
+class IAssistProposal;
+class GenericProposal;
+} // namespace TextEditor
+
namespace LanguageClient {
class Client;
@@ -49,6 +55,17 @@ private:
QPointer<Client> m_client;
};
+class LANGUAGECLIENT_EXPORT CommandQuickFixOperation : public TextEditor::QuickFixOperation
+{
+public:
+ CommandQuickFixOperation(const LanguageServerProtocol::Command &command, Client *client);
+ void perform() override;
+
+private:
+ LanguageServerProtocol::Command m_command;
+ QPointer<Client> m_client;
+};
+
class LANGUAGECLIENT_EXPORT LanguageClientQuickFixProvider : public TextEditor::IAssistProvider
{
public:
@@ -56,8 +73,35 @@ public:
IAssistProvider::RunType runType() const override;
TextEditor::IAssistProcessor *createProcessor(const TextEditor::AssistInterface *) const override;
+protected:
+ Client *client() const { return m_client; }
+
private:
Client *m_client = nullptr; // not owned
};
+class LANGUAGECLIENT_EXPORT LanguageClientQuickFixAssistProcessor
+ : public TextEditor::IAssistProcessor
+{
+public:
+ explicit LanguageClientQuickFixAssistProcessor(Client *client) : m_client(client) {}
+ bool running() override { return m_currentRequest.has_value(); }
+ TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override;
+ void cancel() override;
+
+protected:
+ void setOnlyKinds(const QList<LanguageServerProtocol::CodeActionKind> &only);
+ Client *client() { return m_client; }
+
+private:
+ void handleCodeActionResponse(
+ const LanguageServerProtocol::CodeActionRequest::Response &response);
+ virtual TextEditor::GenericProposal *handleCodeActionResult(
+ const LanguageServerProtocol::CodeActionResult &result);
+
+ QSharedPointer<const TextEditor::AssistInterface> m_assistInterface;
+ Client *m_client = nullptr; // not owned
+ Utils::optional<LanguageServerProtocol::MessageId> m_currentRequest;
+};
+
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientsettings.cpp b/src/plugins/languageclient/languageclientsettings.cpp
index d389f42fefb..737fe23b8f1 100644
--- a/src/plugins/languageclient/languageclientsettings.cpp
+++ b/src/plugins/languageclient/languageclientsettings.cpp
@@ -37,13 +37,16 @@
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
+#include <texteditor/plaintexteditorfactory.h>
+#include <texteditor/textmark.h>
+
#include <utils/algorithm.h>
-#include <utils/utilsicons.h>
#include <utils/delegates.h>
#include <utils/fancylineedit.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/jsontreeitem.h>
+#include <utils/macroexpander.h>
#include <utils/stringutils.h>
+#include <utils/utilsicons.h>
#include <utils/variablechooser.h>
#include <QBoxLayout>
@@ -75,6 +78,7 @@ constexpr char startupBehaviorKey[] = "startupBehavior";
constexpr char mimeTypeKey[] = "mimeType";
constexpr char filePatternKey[] = "filePattern";
constexpr char initializationOptionsKey[] = "initializationOptions";
+constexpr char configurationKey[] = "configuration";
constexpr char executableKey[] = "executable";
constexpr char argumentsKey[] = "arguments";
constexpr char settingsGroupKey[] = "LanguageClient";
@@ -110,7 +114,7 @@ public:
void reset(const QList<BaseSettings *> &settings);
QList<BaseSettings *> settings() const { return m_settings; }
int insertSettings(BaseSettings *settings);
- void enableSetting(const QString &id);
+ void enableSetting(const QString &id, bool enable = true);
QList<BaseSettings *> removed() const { return m_removed; }
BaseSettings *settingForIndex(const QModelIndex &index) const;
QModelIndex indexForSetting(BaseSettings *setting) const;
@@ -159,7 +163,7 @@ public:
QList<BaseSettings *> settings() const;
QList<BaseSettings *> changedSettings() const;
void addSettings(BaseSettings *settings);
- void enableSettings(const QString &id);
+ void enableSettings(const QString &id, bool enable = true);
private:
LanguageClientSettingsModel m_model;
@@ -323,7 +327,7 @@ void LanguageClientSettingsPage::apply()
LanguageClientManager::applySettings();
for (BaseSettings *setting : m_model.removed()) {
- for (Client *client : LanguageClientManager::clientForSetting(setting))
+ for (Client *client : LanguageClientManager::clientsForSetting(setting))
LanguageClientManager::shutdownClient(client);
}
@@ -364,9 +368,9 @@ void LanguageClientSettingsPage::addSettings(BaseSettings *settings)
m_changedSettings << settings->m_id;
}
-void LanguageClientSettingsPage::enableSettings(const QString &id)
+void LanguageClientSettingsPage::enableSettings(const QString &id, bool enable)
{
- m_model.enableSetting(id);
+ m_model.enableSetting(id, enable);
}
LanguageClientSettingsModel::~LanguageClientSettingsModel()
@@ -494,12 +498,14 @@ int LanguageClientSettingsModel::insertSettings(BaseSettings *settings)
return row;
}
-void LanguageClientSettingsModel::enableSetting(const QString &id)
+void LanguageClientSettingsModel::enableSetting(const QString &id, bool enable)
{
BaseSettings *setting = Utils::findOrDefault(m_settings, Utils::equal(&BaseSettings::m_id, id));
if (!setting)
return;
- setting->m_enabled = true;
+ if (setting->m_enabled == enable)
+ return;
+ setting->m_enabled = enable;
const QModelIndex &index = indexForSetting(setting);
if (index.isValid())
emit dataChanged(index, index, {Qt::CheckStateRole});
@@ -524,6 +530,16 @@ QJsonObject BaseSettings::initializationOptions() const
expand(m_initializationOptions).toUtf8()).object();
}
+QJsonValue BaseSettings::configuration() const
+{
+ const QJsonDocument document = QJsonDocument::fromJson(m_configuration.toUtf8());
+ if (document.isArray())
+ return document.array();
+ if (document.isObject())
+ return document.object();
+ return {};
+}
+
bool BaseSettings::applyFromSettingsWidget(QWidget *widget)
{
bool changed = false;
@@ -558,16 +574,16 @@ bool BaseSettings::isValid() const
return !m_name.isEmpty();
}
-Client *BaseSettings::createClient()
+Client *BaseSettings::createClient() const
{
- return createClient(nullptr);
+ return createClient(static_cast<ProjectExplorer::Project *>(nullptr));
}
-Client *BaseSettings::createClient(ProjectExplorer::Project *project)
+Client *BaseSettings::createClient(ProjectExplorer::Project *project) const
{
if (!isValid() || !m_enabled)
return nullptr;
- BaseClientInterface *interface = createInterfaceWithProject(project);
+ BaseClientInterface *interface = createInterface(project);
QTC_ASSERT(interface, return nullptr);
auto *client = createClient(interface);
client->setName(Utils::globalMacroExpander()->expand(m_name));
@@ -575,9 +591,15 @@ Client *BaseSettings::createClient(ProjectExplorer::Project *project)
client->setInitializationOptions(initializationOptions());
client->setActivateDocumentAutomatically(true);
client->setCurrentProject(project);
+ client->updateConfiguration(m_configuration);
return client;
}
+BaseClientInterface *BaseSettings::createInterface(ProjectExplorer::Project *) const
+{
+ return nullptr;
+}
+
Client *BaseSettings::createClient(BaseClientInterface *interface) const
{
return new Client(interface);
@@ -594,6 +616,7 @@ QVariantMap BaseSettings::toMap() const
map.insert(mimeTypeKey, m_languageFilter.mimeTypes);
map.insert(filePatternKey, m_languageFilter.filePattern);
map.insert(initializationOptionsKey, m_initializationOptions);
+ map.insert(configurationKey, m_configuration);
return map;
}
@@ -608,6 +631,7 @@ void BaseSettings::fromMap(const QVariantMap &map)
m_languageFilter.filePattern = map[filePatternKey].toStringList();
m_languageFilter.filePattern.removeAll(QString()); // remove empty entries
m_initializationOptions = map[initializationOptionsKey].toString();
+ m_configuration = map[configurationKey].toString();
}
static LanguageClientSettingsPage &settingsPage()
@@ -665,9 +689,9 @@ void LanguageClientSettings::addSettings(BaseSettings *settings)
settingsPage().addSettings(settings);
}
-void LanguageClientSettings::enableSettings(const QString &id)
+void LanguageClientSettings::enableSettings(const QString &id, bool enable)
{
- settingsPage().enableSettings(id);
+ settingsPage().enableSettings(id, enable);
}
void LanguageClientSettings::toSettings(QSettings *settings,
@@ -756,7 +780,7 @@ Utils::CommandLine StdIOSettings::command() const
return Utils::CommandLine(m_executable, arguments(), Utils::CommandLine::Raw);
}
-BaseClientInterface *StdIOSettings::createInterfaceWithProject(ProjectExplorer::Project *project) const
+BaseClientInterface *StdIOSettings::createInterface(ProjectExplorer::Project *project) const
{
auto interface = new StdIOClientInterface;
interface->setCommandLine(command());
@@ -1043,4 +1067,39 @@ bool LanguageFilter::operator!=(const LanguageFilter &other) const
return this->filePattern != other.filePattern || this->mimeTypes != other.mimeTypes;
}
+TextEditor::BaseTextEditor *jsonEditor()
+{
+ using namespace TextEditor;
+ BaseTextEditor *editor = PlainTextEditorFactory::createPlainTextEditor();
+ TextDocument *document = editor->textDocument();
+ TextEditorWidget *widget = editor->editorWidget();
+ widget->configureGenericHighlighter(Utils::mimeTypeForName("application/json"));
+ widget->setLineNumbersVisible(false);
+ widget->setMarksVisible(false);
+ widget->setRevisionsVisible(false);
+ widget->setCodeFoldingSupported(false);
+ QObject::connect(document, &TextDocument::contentsChanged, widget, [document](){
+ const Utils::Id jsonMarkId("LanguageClient.JsonTextMarkId");
+ qDeleteAll(
+ Utils::filtered(document->marks(), Utils::equal(&TextMark::category, jsonMarkId)));
+ const QString content = document->plainText().trimmed();
+ if (content.isEmpty())
+ return;
+ QJsonParseError error;
+ QJsonDocument::fromJson(content.toUtf8(), &error);
+ if (error.error == QJsonParseError::NoError)
+ return;
+ const Utils::OptionalLineColumn lineColumn
+ = Utils::Text::convertPosition(document->document(), error.offset);
+ if (!lineColumn.has_value())
+ return;
+ auto mark = new TextMark(Utils::FilePath(), lineColumn->line, jsonMarkId);
+ mark->setLineAnnotation(error.errorString());
+ mark->setColor(Utils::Theme::CodeModel_Error_TextMarkColor);
+ mark->setIcon(Utils::Icons::CODEMODEL_ERROR.icon());
+ document->addMark(mark);
+ });
+ return editor;
+}
+
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientsettings.h b/src/plugins/languageclient/languageclientsettings.h
index 95e17a9b5ae..bd48eb368bc 100644
--- a/src/plugins/languageclient/languageclientsettings.h
+++ b/src/plugins/languageclient/languageclientsettings.h
@@ -51,14 +51,16 @@ class FancyLineEdit;
namespace Core { class IDocument; }
namespace ProjectExplorer { class Project; }
+namespace TextEditor { class BaseTextEditor; }
namespace LanguageClient {
class Client;
class BaseClientInterface;
-struct LANGUAGECLIENT_EXPORT LanguageFilter
+class LANGUAGECLIENT_EXPORT LanguageFilter
{
+public:
QStringList mimeTypes;
QStringList filePattern;
bool isSupported(const Utils::FilePath &filePath, const QString &mimeType) const;
@@ -88,26 +90,23 @@ public:
StartBehavior m_startBehavior = RequiresFile;
LanguageFilter m_languageFilter;
QString m_initializationOptions;
+ QString m_configuration;
QJsonObject initializationOptions() const;
+ QJsonValue configuration() const;
virtual bool applyFromSettingsWidget(QWidget *widget);
virtual QWidget *createSettingsWidget(QWidget *parent = nullptr) const;
virtual BaseSettings *copy() const { return new BaseSettings(*this); }
virtual bool isValid() const;
- Client *createClient();
- Client *createClient(ProjectExplorer::Project *project);
+ Client *createClient() const;
+ Client *createClient(ProjectExplorer::Project *project) const;
virtual QVariantMap toMap() const;
virtual void fromMap(const QVariantMap &map);
protected:
- // TODO: remove in Qt Creator 6 and rename createInterfaceWithProject back to it
- virtual BaseClientInterface *createInterface() const { return nullptr; }
+ virtual BaseClientInterface *createInterface(ProjectExplorer::Project *) const;
virtual Client *createClient(BaseClientInterface *interface) const;
- virtual BaseClientInterface *createInterfaceWithProject(ProjectExplorer::Project *) const
- {
- return createInterface();
- }
BaseSettings(const BaseSettings &other) = default;
BaseSettings(BaseSettings &&other) = default;
@@ -137,7 +136,7 @@ public:
Utils::CommandLine command() const;
protected:
- BaseClientInterface *createInterfaceWithProject(ProjectExplorer::Project *project) const override;
+ BaseClientInterface *createInterface(ProjectExplorer::Project *project) const override;
StdIOSettings(const StdIOSettings &other) = default;
StdIOSettings(StdIOSettings &&other) = default;
@@ -167,7 +166,7 @@ public:
*/
static void registerClientType(const ClientType &type);
static void addSettings(BaseSettings *settings);
- static void enableSettings(const QString &id);
+ static void enableSettings(const QString &id, bool enable = true);
static void toSettings(QSettings *settings, const QList<BaseSettings *> &languageClientSettings);
static bool outlineComboBoxIsSorted();
@@ -215,4 +214,6 @@ private:
QLineEdit *m_arguments = nullptr;
};
+LANGUAGECLIENT_EXPORT TextEditor::BaseTextEditor *jsonEditor();
+
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientsymbolsupport.cpp b/src/plugins/languageclient/languageclientsymbolsupport.cpp
index 8199084c416..7e6dcdb6b2c 100644
--- a/src/plugins/languageclient/languageclientsymbolsupport.cpp
+++ b/src/plugins/languageclient/languageclientsymbolsupport.cpp
@@ -26,14 +26,16 @@
#include "languageclientsymbolsupport.h"
#include "client.h"
+#include "dynamiccapabilities.h"
#include "languageclientutils.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/searchresultwindow.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QFile>
+#include <QLabel>
using namespace LanguageServerProtocol;
@@ -69,20 +71,19 @@ static void sendTextDocumentPositionParamsRequest(Client *client,
sendMessage = Utils::get<bool>(*provider);
}
if (sendMessage)
- client->sendContent(request);
+ client->sendMessage(request);
}
static void handleGotoDefinitionResponse(const GotoDefinitionRequest::Response &response,
- Utils::ProcessLinkCallback callback,
+ Utils::LinkHandler callback,
Utils::optional<Utils::Link> linkUnderCursor)
{
- if (Utils::optional<GotoResult> _result = response.result()) {
- const GotoResult result = _result.value();
- if (Utils::holds_alternative<std::nullptr_t>(result)) {
+ if (Utils::optional<GotoResult> result = response.result()) {
+ if (Utils::holds_alternative<std::nullptr_t>(*result)) {
callback({});
- } else if (auto ploc = Utils::get_if<Location>(&result)) {
+ } else if (auto ploc = Utils::get_if<Location>(&*result)) {
callback(linkUnderCursor.value_or(ploc->toLink()));
- } else if (auto plloc = Utils::get_if<QList<Location>>(&result)) {
+ } else if (auto plloc = Utils::get_if<QList<Location>>(&*result)) {
if (!plloc->isEmpty())
callback(linkUnderCursor.value_or(plloc->value(0).toLink()));
else
@@ -104,7 +105,7 @@ static TextDocumentPositionParams generateDocPosParams(TextEditor::TextDocument
void SymbolSupport::findLinkAt(TextEditor::TextDocument *document,
const QTextCursor &cursor,
- Utils::ProcessLinkCallback callback,
+ Utils::LinkHandler callback,
const bool resolveTarget)
{
if (!m_client->reachable())
@@ -206,8 +207,7 @@ void SymbolSupport::handleFindReferencesResponse(const FindReferencesRequest::Re
if (result) {
Core::SearchResult *search = Core::SearchResultWindow::instance()->startNewSearch(
tr("Find References with %1 for:").arg(m_client->name()), "", wordUnderCursor);
- search->addResults(generateSearchResultItems(result.value()),
- Core::SearchResult::AddOrdered);
+ search->addResults(generateSearchResultItems(*result), Core::SearchResult::AddOrdered);
QObject::connect(search,
&Core::SearchResult::activated,
[](const Core::SearchResultItem &item) {
@@ -315,7 +315,7 @@ void SymbolSupport::requestPrepareRename(const TextDocumentPositionParams &param
}
}
});
- m_client->sendContent(request);
+ m_client->sendMessage(request);
}
void SymbolSupport::requestRename(const TextDocumentPositionParams &positionParams,
@@ -328,7 +328,7 @@ void SymbolSupport::requestRename(const TextDocumentPositionParams &positionPara
request.setResponseCallback([this, search](const RenameRequest::Response &response) {
handleRenameResponse(search, response);
});
- m_client->sendContent(request);
+ m_client->sendMessage(request);
search->setTextToReplace(newName);
search->popup();
}
@@ -421,7 +421,7 @@ void SymbolSupport::applyRename(const QList<Core::SearchResultItem> &checkedItem
}
for (auto it = editsForDocuments.begin(), end = editsForDocuments.end(); it != end; ++it)
- applyTextEdits(it.key(), it.value());
+ applyTextEdits(m_client, it.key(), it.value());
}
Core::Search::TextRange SymbolSupport::convertRange(const Range &range)
diff --git a/src/plugins/languageclient/languageclientsymbolsupport.h b/src/plugins/languageclient/languageclientsymbolsupport.h
index 6ba376a1d51..2959dbf50bf 100644
--- a/src/plugins/languageclient/languageclientsymbolsupport.h
+++ b/src/plugins/languageclient/languageclientsymbolsupport.h
@@ -51,7 +51,7 @@ public:
void findLinkAt(TextEditor::TextDocument *document,
const QTextCursor &cursor,
- Utils::ProcessLinkCallback callback,
+ Utils::LinkHandler callback,
const bool resolveTarget);
using ResultHandler = std::function<void(const QList<LanguageServerProtocol::Location> &)>;
diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp
index f0a2db61ffb..aa5d540f8da 100644
--- a/src/plugins/languageclient/languageclientutils.cpp
+++ b/src/plugins/languageclient/languageclientutils.cpp
@@ -88,17 +88,22 @@ bool applyTextDocumentEdit(const Client *client, const TextDocumentEdit &edit)
LanguageClientValue<int> version = edit.textDocument().version();
if (!version.isNull() && version.value(0) < client->documentVersion(filePath))
return false;
- return applyTextEdits(uri, edits);
+ return applyTextEdits(client, uri, edits);
}
-bool applyTextEdits(const DocumentUri &uri, const QList<TextEdit> &edits)
+bool applyTextEdits(const Client *client, const DocumentUri &uri, const QList<TextEdit> &edits)
{
if (edits.isEmpty())
return true;
- RefactoringChanges changes;
+ RefactoringChangesData * const backend = client->createRefactoringChangesBackend();
+ RefactoringChanges changes(backend);
RefactoringFilePtr file;
file = changes.file(uri.toFilePath());
file->setChangeSet(editsToChangeSet(edits, file->document()));
+ if (backend) {
+ for (const TextEdit &edit : edits)
+ file->appendIndentRange(convertRange(file->document(), edit.range()));
+ }
return file->apply();
}
@@ -130,7 +135,7 @@ bool applyWorkspaceEdit(const Client *client, const WorkspaceEdit &edit)
} else {
const WorkspaceEdit::Changes &changes = edit.changes().value_or(WorkspaceEdit::Changes());
for (auto it = changes.cbegin(); it != changes.cend(); ++it)
- result |= applyTextEdits(it.key(), it.value());
+ result |= applyTextEdits(client, it.key(), it.value());
return result;
}
return result;
@@ -144,7 +149,7 @@ QTextCursor endOfLineCursor(const QTextCursor &cursor)
}
void updateCodeActionRefactoringMarker(Client *client,
- const CodeAction &action,
+ const QList<CodeAction> &actions,
const DocumentUri &uri)
{
TextDocument* doc = TextDocument::textDocumentForFilePath(uri.toFilePath());
@@ -154,48 +159,60 @@ void updateCodeActionRefactoringMarker(Client *client,
if (editors.isEmpty())
return;
- const QList<Diagnostic> &diagnostics = action.diagnostics().value_or(QList<Diagnostic>());
+ QHash<int, RefactorMarker> markersAtBlock;
+ const auto addMarkerForCursor = [&](const CodeAction &action, const Range &range) {
+ const QTextCursor cursor = endOfLineCursor(range.start().toTextCursor(doc->document()));
+ const auto it = markersAtBlock.find(cursor.blockNumber());
+ if (it != markersAtBlock.end()) {
+ it->tooltip = LanguageClientManager::tr("Show available quick fixes");
+ it->callback = [cursor](TextEditorWidget *editor) {
+ editor->setTextCursor(cursor);
+ editor->invokeAssist(TextEditor::QuickFix);
+ };
+ return;
+ }
+ RefactorMarker marker;
+ marker.type = client->id();
+ marker.cursor = cursor;
+ if (action.isValid())
+ marker.tooltip = action.title();
+ if (action.edit()) {
+ marker.callback = [client, edit = action.edit()](const TextEditorWidget *) {
+ applyWorkspaceEdit(client, *edit);
+ };
+ } else if (action.command()) {
+ marker.callback = [command = action.command(),
+ client = QPointer(client)](const TextEditorWidget *) {
+ if (client)
+ client->executeCommand(*command);
+ };
+ }
+ markersAtBlock[cursor.blockNumber()] = marker;
+ };
- RefactorMarkers markers;
- RefactorMarker marker;
- marker.type = client->id();
- if (action.isValid())
- marker.tooltip = action.title();
- if (action.edit().has_value()) {
- WorkspaceEdit edit = action.edit().value();
- marker.callback = [client, edit](const TextEditorWidget *) {
- applyWorkspaceEdit(client, edit);
- };
- if (diagnostics.isEmpty()) {
- QList<TextEdit> edits;
- if (optional<QList<TextDocumentEdit>> documentChanges = edit.documentChanges()) {
- QList<TextDocumentEdit> changesForUri = Utils::filtered(
- documentChanges.value(), [uri](const TextDocumentEdit &edit) {
- return edit.textDocument().uri() == uri;
- });
- for (const TextDocumentEdit &edit : changesForUri)
- edits << edit.edits();
- } else if (optional<WorkspaceEdit::Changes> localChanges = edit.changes()) {
- edits = localChanges.value()[uri];
- }
- for (const TextEdit &edit : qAsConst(edits)) {
- marker.cursor = endOfLineCursor(edit.range().start().toTextCursor(doc->document()));
- markers << marker;
+ for (const CodeAction &action : actions) {
+ const QList<Diagnostic> &diagnostics = action.diagnostics().value_or(QList<Diagnostic>());
+ if (Utils::optional<WorkspaceEdit> edit = action.edit()) {
+ if (diagnostics.isEmpty()) {
+ QList<TextEdit> edits;
+ if (optional<QList<TextDocumentEdit>> documentChanges = edit->documentChanges()) {
+ QList<TextDocumentEdit> changesForUri = Utils::filtered(
+ *documentChanges, [uri](const TextDocumentEdit &edit) {
+ return edit.textDocument().uri() == uri;
+ });
+ for (const TextDocumentEdit &edit : changesForUri)
+ edits << edit.edits();
+ } else if (optional<WorkspaceEdit::Changes> localChanges = edit->changes()) {
+ edits = (*localChanges)[uri];
+ }
+ for (const TextEdit &edit : qAsConst(edits))
+ addMarkerForCursor(action, edit.range());
}
}
- } else if (action.command().has_value()) {
- const Command command = action.command().value();
- marker.callback = [command, client = QPointer<Client>(client)](const TextEditorWidget *) {
- if (client)
- client->executeCommand(command);
- };
- } else {
- return;
- }
- for (const Diagnostic &diagnostic : diagnostics) {
- marker.cursor = endOfLineCursor(diagnostic.range().start().toTextCursor(doc->document()));
- markers << marker;
+ for (const Diagnostic &diagnostic : diagnostics)
+ addMarkerForCursor(action, diagnostic.range());
}
+ const RefactorMarkers markers = markersAtBlock.values();
for (BaseTextEditor *editor : editors) {
if (TextEditorWidget *editorWidget = editor->editorWidget())
editorWidget->setRefactorMarkers(markers + editorWidget->refactorMarkers());
@@ -273,8 +290,8 @@ void updateEditorToolBar(Core::IEditor *editor)
});
}
- if (!extras->m_client || extras->m_client != client ||
- !LanguageClientOutlineWidgetFactory::clientSupportsDocumentSymbols(client, document)) {
+ if (!extras->m_client || !client || extras->m_client != client
+ || !client->supportsDocumentSymbols(document)) {
if (extras->m_outlineAction) {
widget->toolBar()->removeAction(extras->m_outlineAction);
delete extras->m_outlineAction;
@@ -283,10 +300,11 @@ void updateEditorToolBar(Core::IEditor *editor)
}
if (!extras->m_client) {
- if (QWidget *comboBox = LanguageClientOutlineWidgetFactory::createComboBox(client, editor)) {
+ QWidget *comboBox = LanguageClientOutlineWidgetFactory::createComboBox(client, textEditor);
+ if (comboBox) {
extras->m_client = client;
extras->m_outlineAction = widget->insertExtraToolBarWidget(TextEditorWidget::Left,
- comboBox);
+ comboBox);
}
}
}
diff --git a/src/plugins/languageclient/languageclientutils.h b/src/plugins/languageclient/languageclientutils.h
index c8120766077..24a13e6fbe9 100644
--- a/src/plugins/languageclient/languageclientutils.h
+++ b/src/plugins/languageclient/languageclientutils.h
@@ -51,14 +51,15 @@ Utils::ChangeSet editsToChangeSet(const QList<LanguageServerProtocol::TextEdit>
bool LANGUAGECLIENT_EXPORT applyWorkspaceEdit(const Client *client, const LanguageServerProtocol::WorkspaceEdit &edit);
bool LANGUAGECLIENT_EXPORT
applyTextDocumentEdit(const Client *client, const LanguageServerProtocol::TextDocumentEdit &edit);
-bool LANGUAGECLIENT_EXPORT applyTextEdits(const LanguageServerProtocol::DocumentUri &uri,
+bool LANGUAGECLIENT_EXPORT applyTextEdits(const Client *client,
+ const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::TextEdit> &edits);
void LANGUAGECLIENT_EXPORT applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator,
const LanguageServerProtocol::TextEdit &edit,
bool newTextIsSnippet = false);
void LANGUAGECLIENT_EXPORT
updateCodeActionRefactoringMarker(Client *client,
- const LanguageServerProtocol::CodeAction &action,
+ const QList<LanguageServerProtocol::CodeAction> &actions,
const LanguageServerProtocol::DocumentUri &uri);
void updateEditorToolBar(Core::IEditor *editor);
const QIcon LANGUAGECLIENT_EXPORT symbolIcon(int type);
diff --git a/src/plugins/languageclient/locatorfilter.cpp b/src/plugins/languageclient/locatorfilter.cpp
index 5ccc4d175a0..6dd843900da 100644
--- a/src/plugins/languageclient/locatorfilter.cpp
+++ b/src/plugins/languageclient/locatorfilter.cpp
@@ -25,6 +25,7 @@
#include "locatorfilter.h"
+#include "documentsymbolcache.h"
#include "languageclient_global.h"
#include "languageclientmanager.h"
#include "languageclientutils.h"
@@ -210,9 +211,9 @@ QList<Core::LocatorFilterEntry> DocumentLocatorFilter::matchesFor(
QTC_ASSERT(m_currentSymbols.has_value(), return {});
- if (auto list = Utils::get_if<QList<DocumentSymbol>>(&m_currentSymbols.value()))
+ if (auto list = Utils::get_if<QList<DocumentSymbol>>(&*m_currentSymbols))
return generateEntries(*list, entry);
- else if (auto list = Utils::get_if<QList<SymbolInformation>>(&m_currentSymbols.value()))
+ else if (auto list = Utils::get_if<QList<SymbolInformation>>(&*m_currentSymbols))
return generateEntries(*list, entry);
return {};
@@ -253,13 +254,13 @@ void WorkspaceLocatorFilter::prepareSearch(const QString &entry)
prepareSearch(entry, LanguageClientManager::clients(), false);
}
-void WorkspaceLocatorFilter::prepareSearch(const QString &entry, const QVector<Client *> &clients)
+void WorkspaceLocatorFilter::prepareSearch(const QString &entry, const QList<Client *> &clients)
{
prepareSearch(entry, clients, true);
}
void WorkspaceLocatorFilter::prepareSearch(const QString &entry,
- const QVector<Client *> &clients,
+ const QList<Client *> &clients,
bool force)
{
m_pendingRequests.clear();
@@ -288,7 +289,7 @@ void WorkspaceLocatorFilter::prepareSearch(const QString &entry,
handleResponse(client, response);
});
m_pendingRequests[client] = request.id();
- client->sendContent(request);
+ client->sendMessage(request);
}
}
diff --git a/src/plugins/languageclient/locatorfilter.h b/src/plugins/languageclient/locatorfilter.h
index c149fadcad0..72800b49ed7 100644
--- a/src/plugins/languageclient/locatorfilter.h
+++ b/src/plugins/languageclient/locatorfilter.h
@@ -33,6 +33,7 @@
#include <languageserverprotocol/languagefeatures.h>
#include <languageserverprotocol/workspace.h>
+#include <QPointer>
#include <QVector>
namespace Core { class IEditor; }
@@ -100,7 +101,7 @@ public:
/// request workspace symbols for all clients with enabled locator
void prepareSearch(const QString &entry) override;
/// force request workspace symbols for all given clients
- void prepareSearch(const QString &entry, const QVector<Client *> &clients);
+ void prepareSearch(const QString &entry, const QList<Client *> &clients);
QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
const QString &entry) override;
void accept(const Core::LocatorFilterEntry &selection,
@@ -117,7 +118,7 @@ protected:
void setMaxResultCount(qint64 limit) { m_maxResultCount = limit; }
private:
- void prepareSearch(const QString &entry, const QVector<Client *> &clients, bool force);
+ void prepareSearch(const QString &entry, const QList<Client *> &clients, bool force);
void handleResponse(Client *client,
const LanguageServerProtocol::WorkspaceSymbolRequest::Response &response);
diff --git a/src/plugins/languageclient/lspinspector.cpp b/src/plugins/languageclient/lspinspector.cpp
index e6e81a2a1f4..051e168f263 100644
--- a/src/plugins/languageclient/lspinspector.cpp
+++ b/src/plugins/languageclient/lspinspector.cpp
@@ -42,6 +42,7 @@
#include <QFormLayout>
#include <QGroupBox>
#include <QHeaderView>
+#include <QJsonDocument>
#include <QLabel>
#include <QListWidget>
#include <QPlainTextEdit>
@@ -120,8 +121,7 @@ public:
void clear();
private:
- QLabel *m_contentLength = nullptr;
- QLabel *m_mimeType = nullptr;
+ QTreeView *m_jsonTree = nullptr;
};
class LspCapabilitiesWidget : public QWidget
@@ -228,7 +228,7 @@ LspLogWidget::LspLogWidget()
setOrientation(Qt::Horizontal);
m_clientDetails = new MessageDetailWidget;
- m_clientDetails->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ m_clientDetails->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_clientDetails->setTitle(LspInspector::tr("Client Message"));
addWidget(m_clientDetails);
setStretchFactor(0, 1);
@@ -238,13 +238,13 @@ LspLogWidget::LspLogWidget()
m_messages->setModel(&m_model);
m_messages->setAlternatingRowColors(true);
m_model.setHeader({LspInspector::tr("Messages")});
- m_messages->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
+ m_messages->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
m_messages->setSelectionMode(QAbstractItemView::MultiSelection);
addWidget(m_messages);
setStretchFactor(1, 0);
m_serverDetails = new MessageDetailWidget;
- m_serverDetails->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ m_serverDetails->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_serverDetails->setTitle(LspInspector::tr("Server Message"));
addWidget(m_serverDetails);
setStretchFactor(2, 1);
@@ -258,8 +258,11 @@ LspLogWidget::LspLogWidget()
void LspLogWidget::currentMessageChanged(const QModelIndex &index)
{
m_messages->clearSelection();
- if (!index.isValid())
+ if (!index.isValid()) {
+ m_clientDetails->clear();
+ m_serverDetails->clear();
return;
+ }
LspLogMessage message = m_model.itemAt(index.row())->itemData;
if (message.sender == LspLogMessage::ClientMessage)
m_clientDetails->setMessage(message);
@@ -274,8 +277,6 @@ static bool matches(LspLogMessage::MessageSender sender,
{
if (message.sender != sender)
return false;
- if (message.message.mimeType != JsonRpcMessageHandler::jsonRpcMimeType())
- return false;
return message.id() == id;
}
@@ -322,7 +323,7 @@ void LspLogWidget::saveLog()
stream << (message.sender == LspLogMessage::ClientMessage ? QString{"Client"}
: QString{"Server"});
stream << '\n';
- stream << message.message.codec->toUnicode(message.message.content);
+ stream << QJsonDocument(message.message.toJsonObject()).toJson();
stream << "\n\n";
});
@@ -365,7 +366,7 @@ QWidget *LspInspector::createWidget(const QString &defaultClient)
void LspInspector::log(const LspLogMessage::MessageSender sender,
const QString &clientName,
- const BaseMessage &message)
+ const JsonRpcMessage &message)
{
std::list<LspLogMessage> &clientLog = m_logs[clientName];
while (clientLog.size() >= static_cast<std::size_t>(m_logSize))
@@ -510,50 +511,27 @@ LspCapabilitiesWidget *LspInspectorWidget::capabilities() const
MessageDetailWidget::MessageDetailWidget()
{
- auto layout = new QFormLayout;
+ auto layout = new QVBoxLayout;
setLayout(layout);
- m_contentLength = new QLabel;
- m_mimeType = new QLabel;
+ m_jsonTree = createJsonTreeView();
- layout->addRow("Content Length:", m_contentLength);
- layout->addRow("MIME Type:", m_mimeType);
+ layout->addWidget(m_jsonTree);
}
void MessageDetailWidget::setMessage(const LspLogMessage &message)
{
- m_contentLength->setText(QString::number(message.message.contentLength));
- m_mimeType->setText(QString::fromLatin1(message.message.mimeType));
-
- QWidget *newContentWidget = nullptr;
- if (message.message.mimeType == JsonRpcMessageHandler::jsonRpcMimeType()) {
- newContentWidget = createJsonTreeView("content", message.json());
- } else {
- auto edit = new QPlainTextEdit();
- edit->setReadOnly(true);
- edit->setPlainText(message.message.codec->toUnicode(message.message.content));
- newContentWidget = edit;
- }
- auto formLayout = static_cast<QFormLayout *>(layout());
- if (formLayout->rowCount() > 2)
- formLayout->removeRow(2);
- formLayout->setWidget(2, QFormLayout::SpanningRole, newContentWidget);
+ m_jsonTree->setModel(createJsonModel("content", message.message.toJsonObject()));
}
void MessageDetailWidget::clear()
{
- m_contentLength->setText({});
- m_mimeType->setText({});
- auto formLayout = static_cast<QFormLayout *>(layout());
- if (formLayout->rowCount() > 2)
- formLayout->removeRow(2);
+ m_jsonTree->setModel(createJsonModel("", QJsonObject()));
}
LspLogMessage::LspLogMessage() = default;
-LspLogMessage::LspLogMessage(MessageSender sender,
- const QTime &time,
- const LanguageServerProtocol::BaseMessage &message)
+LspLogMessage::LspLogMessage(MessageSender sender, const QTime &time, const JsonRpcMessage &message)
: sender(sender)
, time(time)
, message(message)
@@ -562,7 +540,7 @@ LspLogMessage::LspLogMessage(MessageSender sender,
MessageId LspLogMessage::id() const
{
if (!m_id.has_value())
- m_id = MessageId(json().value(idKey));
+ m_id = MessageId(message.toJsonObject().value(idKey));
return *m_id;
}
@@ -570,25 +548,10 @@ QString LspLogMessage::displayText() const
{
if (!m_displayText.has_value()) {
m_displayText = QString(time.toString("hh:mm:ss.zzz") + '\n');
- if (message.mimeType == JsonRpcMessageHandler::jsonRpcMimeType())
- m_displayText->append(json().value(QString{methodKey}).toString(id().toString()));
- else
- m_displayText->append(message.codec->toUnicode(message.content));
+ m_displayText->append(
+ message.toJsonObject().value(methodKey).toString(id().toString()));
}
return *m_displayText;
}
-QJsonObject &LspLogMessage::json() const
-{
- if (!m_json.has_value()) {
- if (message.mimeType == JsonRpcMessageHandler::jsonRpcMimeType()) {
- QString error;
- m_json = JsonRpcMessageHandler::toJsonObject(message.content, message.codec, error);
- } else {
- m_json = QJsonObject();
- }
- }
- return *m_json;
-}
-
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/lspinspector.h b/src/plugins/languageclient/lspinspector.h
index 6d3cb048e83..81eb16a2b75 100644
--- a/src/plugins/languageclient/lspinspector.h
+++ b/src/plugins/languageclient/lspinspector.h
@@ -45,18 +45,16 @@ public:
LspLogMessage();
LspLogMessage(MessageSender sender,
const QTime &time,
- const LanguageServerProtocol::BaseMessage &message);
+ const LanguageServerProtocol::JsonRpcMessage &message);
QTime time;
- LanguageServerProtocol::BaseMessage message;
+ LanguageServerProtocol::JsonRpcMessage message;
LanguageServerProtocol::MessageId id() const;
QString displayText() const;
- QJsonObject &json() const;
private:
mutable Utils::optional<LanguageServerProtocol::MessageId> m_id;
mutable Utils::optional<QString> m_displayText;
- mutable Utils::optional<QJsonObject> m_json;
};
struct Capabilities
@@ -76,7 +74,7 @@ public:
void log(const LspLogMessage::MessageSender sender,
const QString &clientName,
- const LanguageServerProtocol::BaseMessage &message);
+ const LanguageServerProtocol::JsonRpcMessage &message);
void clientInitialized(const QString &clientName,
const LanguageServerProtocol::ServerCapabilities &capabilities);
void updateCapabilities(const QString &clientName,
diff --git a/src/plugins/languageclient/semantichighlightsupport.cpp b/src/plugins/languageclient/semantichighlightsupport.cpp
index d6abceaba91..7fbf6645912 100644
--- a/src/plugins/languageclient/semantichighlightsupport.cpp
+++ b/src/plugins/languageclient/semantichighlightsupport.cpp
@@ -32,7 +32,7 @@
#include <texteditor/syntaxhighlighter.h>
#include <texteditor/texteditor.h>
#include <texteditor/texteditorsettings.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QTextDocument>
@@ -68,12 +68,16 @@ void SemanticTokenSupport::refresh()
void SemanticTokenSupport::reloadSemanticTokens(TextDocument *textDocument)
{
- reloadSemanticTokensImpl(textDocument);
+ if (m_client->reachable())
+ reloadSemanticTokensImpl(textDocument);
+ else
+ queueDocumentReload(textDocument);
}
void SemanticTokenSupport::reloadSemanticTokensImpl(TextDocument *textDocument,
int remainingRerequests)
{
+ m_docReloadQueue.remove(textDocument);
const SemanticRequestTypes supportedRequests = supportedSemanticRequests(textDocument);
if (supportedRequests.testFlag(SemanticRequestType::None))
return;
@@ -84,6 +88,7 @@ void SemanticTokenSupport::reloadSemanticTokensImpl(TextDocument *textDocument,
filePath,
documentVersion = m_client->documentVersion(filePath)](
const SemanticTokensFullRequest::Response &response) {
+ m_runningRequests.remove(filePath);
if (const auto error = response.error()) {
qCDebug(LOGLSPHIGHLIGHT)
<< "received error" << error->code() << error->message() << "for" << filePath;
@@ -116,13 +121,20 @@ void SemanticTokenSupport::reloadSemanticTokensImpl(TextDocument *textDocument,
request.setResponseCallback(responseCallback);
qCDebug(LOGLSPHIGHLIGHT) << "Requesting all tokens for" << filePath << "with version"
<< m_client->documentVersion(filePath);
- m_client->sendContent(request);
+ MessageId &id = m_runningRequests[filePath];
+ if (id.isValid())
+ m_client->cancelRequest(id);
+ id = request.id();
+ m_client->sendMessage(request);
}
}
void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument)
{
- updateSemanticTokensImpl(textDocument);
+ if (m_client->reachable())
+ updateSemanticTokensImpl(textDocument);
+ else
+ queueDocumentReload(textDocument);
}
void SemanticTokenSupport::updateSemanticTokensImpl(TextDocument *textDocument,
@@ -144,6 +156,7 @@ void SemanticTokenSupport::updateSemanticTokensImpl(TextDocument *textDocument,
request.setResponseCallback(
[this, filePath, documentVersion, remainingRerequests](
const SemanticTokensFullDeltaRequest::Response &response) {
+ m_runningRequests.remove(filePath);
if (const auto error = response.error()) {
qCDebug(LOGLSPHIGHLIGHT) << "received error" << error->code()
<< error->message() << "for" << filePath;
@@ -161,13 +174,33 @@ void SemanticTokenSupport::updateSemanticTokensImpl(TextDocument *textDocument,
});
qCDebug(LOGLSPHIGHLIGHT)
<< "Requesting delta for" << filePath << "with version" << documentVersion;
- m_client->sendContent(request);
+ MessageId &id = m_runningRequests[filePath];
+ if (id.isValid())
+ m_client->cancelRequest(id);
+ id = request.id();
+ m_client->sendMessage(request);
return;
}
}
reloadSemanticTokens(textDocument);
}
+void SemanticTokenSupport::queueDocumentReload(TextEditor::TextDocument *doc)
+{
+ if (m_docReloadQueue.contains(doc))
+ return;
+ m_docReloadQueue << doc;
+ connect(
+ m_client,
+ &Client::initialized,
+ this,
+ [this, doc = QPointer<TextDocument>(doc)]() {
+ if (doc)
+ reloadSemanticTokensImpl(doc);
+ },
+ Qt::QueuedConnection);
+}
+
void SemanticTokenSupport::clearHighlight(TextEditor::TextDocument *doc)
{
if (m_tokens.contains(doc->filePath())){
@@ -229,23 +262,24 @@ void SemanticTokenSupport::updateFormatHash()
continue;
TextStyle style;
switch (tokenType) {
+ case namespaceToken: style = C_NAMESPACE; break;
case typeToken: style = C_TYPE; break;
case classToken: style = C_TYPE; break;
+ case structToken: style = C_TYPE; break;
case enumMemberToken: style = C_ENUMERATION; break;
case typeParameterToken: style = C_FIELD; break;
case parameterToken: style = C_PARAMETER; break;
case variableToken: style = C_LOCAL; break;
case functionToken: style = C_FUNCTION; break;
case methodToken: style = C_FUNCTION; break;
- case macroToken: style = C_PREPROCESSOR; break;
+ case macroToken: style = C_MACRO; break;
case keywordToken: style = C_KEYWORD; break;
case commentToken: style = C_COMMENT; break;
case stringToken: style = C_STRING; break;
case numberToken: style = C_NUMBER; break;
case operatorToken: style = C_OPERATOR; break;
default:
- style = m_additionalTypeStyles.value(tokenType, C_TEXT);
- break;
+ continue;
}
int mainHashPart = tokenType << tokenTypeBitOffset;
m_formatHash[mainHashPart] = fontSettings.toTextCharFormat(style);
@@ -279,6 +313,11 @@ void SemanticTokenSupport::setAdditionalTokenTypeStyles(
m_additionalTypeStyles = typeStyles;
}
+void SemanticTokenSupport::clearTokens()
+{
+ m_tokens.clear();
+}
+
//void SemanticTokenSupport::setAdditionalTokenModifierStyles(
// const QHash<int, TextStyle> &modifierStyles)
//{
@@ -301,14 +340,15 @@ SemanticRequestTypes SemanticTokenSupport::supportedSemanticRequests(TextDocumen
};
const QString dynamicMethod = "textDocument/semanticTokens";
const DynamicCapabilities &dynamicCapabilities = m_client->dynamicCapabilities();
- if (auto registered = dynamicCapabilities.isRegistered(dynamicMethod);
- registered.has_value()) {
- if (!registered.value())
+ if (auto registered = dynamicCapabilities.isRegistered(dynamicMethod)) {
+ if (!*registered)
return SemanticRequestType::None;
return supportedRequests(dynamicCapabilities.option(dynamicMethod).toObject());
}
- if (m_client->capabilities().semanticTokensProvider().has_value())
- return supportedRequests(m_client->capabilities().semanticTokensProvider().value());
+ if (Utils::optional<SemanticTokensOptions> provider = m_client->capabilities()
+ .semanticTokensProvider()) {
+ return supportedRequests(*provider);
+ }
return SemanticRequestType::None;
}
@@ -317,8 +357,9 @@ void SemanticTokenSupport::handleSemanticTokens(const Utils::FilePath &filePath,
int documentVersion)
{
if (auto tokens = Utils::get_if<SemanticTokens>(&result)) {
+ const bool force = !m_tokens.contains(filePath);
m_tokens[filePath] = {*tokens, documentVersion};
- highlight(filePath);
+ highlight(filePath, force);
}
}
@@ -359,10 +400,9 @@ void SemanticTokenSupport::handleSemanticTokensDelta(
return;
for (const auto start = data.begin() + edit.start(); it < start; ++it)
newData.append(*it);
- const Utils::optional<QList<int>> editData = edit.data();
- if (editData.has_value()) {
- newData.append(editData.value());
- qCDebug(LOGLSPHIGHLIGHT) << edit.start() << edit.deleteCount() << editData.value();
+ if (const Utils::optional<QList<int>> editData = edit.data()) {
+ newData.append(*editData);
+ qCDebug(LOGLSPHIGHLIGHT) << edit.start() << edit.deleteCount() << *editData;
} else {
qCDebug(LOGLSPHIGHLIGHT) << edit.start() << edit.deleteCount();
}
diff --git a/src/plugins/languageclient/semantichighlightsupport.h b/src/plugins/languageclient/semantichighlightsupport.h
index 163f3fde888..d8314979111 100644
--- a/src/plugins/languageclient/semantichighlightsupport.h
+++ b/src/plugins/languageclient/semantichighlightsupport.h
@@ -32,6 +32,7 @@
#include <texteditor/semantichighlighter.h>
#include <texteditor/textdocument.h>
+#include <QSet>
#include <QTextCharFormat>
#include <functional>
@@ -71,6 +72,7 @@ public:
void clearHighlight(TextEditor::TextDocument *doc);
void rehighlight();
void setLegend(const LanguageServerProtocol::SemanticTokensLegend &legend);
+ void clearTokens();
void setTokenTypesMap(const QMap<QString, int> &tokenTypesMap);
void setTokenModifiersMap(const QMap<QString, int> &tokenModifiersMap);
@@ -85,6 +87,7 @@ public:
private:
void reloadSemanticTokensImpl(TextEditor::TextDocument *doc, int remainingRerequests = 3);
void updateSemanticTokensImpl(TextEditor::TextDocument *doc, int remainingRerequests = 3);
+ void queueDocumentReload(TextEditor::TextDocument *doc);
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(
TextEditor::TextDocument *document) const;
void handleSemanticTokens(const Utils::FilePath &filePath,
@@ -116,6 +119,8 @@ private:
SemanticTokensHandler m_tokensHandler;
QStringList m_tokenTypeStrings;
QStringList m_tokenModifierStrings;
+ QSet<TextEditor::TextDocument *> m_docReloadQueue;
+ QHash<Utils::FilePath, LanguageServerProtocol::MessageId> m_runningRequests;
};
} // namespace LanguageClient
diff --git a/src/plugins/macros/actionmacrohandler.cpp b/src/plugins/macros/actionmacrohandler.cpp
index 6238875b0d8..074f5458398 100644
--- a/src/plugins/macros/actionmacrohandler.cpp
+++ b/src/plugins/macros/actionmacrohandler.cpp
@@ -53,8 +53,8 @@ ActionMacroHandler::ActionMacroHandler()
this, &ActionMacroHandler::addCommand);
// Register all existing scriptable actions
- QList<Command *> commands = ActionManager::commands();
- foreach (Command *command, commands) {
+ const QList<Command *> commands = ActionManager::commands();
+ for (Command *command : commands) {
if (command->isScriptable())
registerCommand(command->id());
}
diff --git a/src/plugins/macros/macro.cpp b/src/plugins/macros/macro.cpp
index a102d10040d..eda04527ed9 100644
--- a/src/plugins/macros/macro.cpp
+++ b/src/plugins/macros/macro.cpp
@@ -143,7 +143,7 @@ bool Macro::save(const QString &fileName, QWidget *parent)
QDataStream stream(saver.file());
stream << d->version;
stream << d->description;
- foreach (const MacroEvent &event, d->events) {
+ for (const MacroEvent &event : qAsConst(d->events)) {
event.save(stream);
}
saver.setResult(&stream);
diff --git a/src/plugins/macros/macromanager.cpp b/src/plugins/macros/macromanager.cpp
index 0b757c41546..e7669f8cc3c 100644
--- a/src/plugins/macros/macromanager.cpp
+++ b/src/plugins/macros/macromanager.cpp
@@ -131,9 +131,9 @@ void MacroManagerPrivate::initialize()
const QDir dir(MacroManager::macrosDirectory());
QStringList filter;
filter << QLatin1String("*.") + QLatin1String(Constants::M_EXTENSION);
- QStringList files = dir.entryList(filter, QDir::Files);
+ const QStringList files = dir.entryList(filter, QDir::Files);
- foreach (const QString &name, files) {
+ for (const QString &name : files) {
QString fileName = dir.absolutePath() + QLatin1Char('/') + name;
auto macro = new Macro;
if (macro->loadHeader(fileName))
@@ -196,10 +196,11 @@ void MacroManagerPrivate::changeMacroDescription(Macro *macro, const QString &de
bool MacroManagerPrivate::executeMacro(Macro *macro)
{
bool error = !macro->load();
- foreach (const MacroEvent &macroEvent, macro->events()) {
+ const QList<MacroEvent> macroEvents = macro->events();
+ for (const MacroEvent &macroEvent : macroEvents) {
if (error)
break;
- foreach (IMacroHandler *handler, handlers) {
+ for (IMacroHandler *handler : qAsConst(handlers)) {
if (handler->canExecuteEvent(macroEvent)) {
if (!handler->executeEvent(macroEvent))
error = true;
@@ -255,8 +256,8 @@ MacroManager::MacroManager() :
MacroManager::~MacroManager()
{
// Cleanup macro
- QStringList macroList = d->macros.keys();
- foreach (const QString &name, macroList)
+ const QStringList macroList = d->macros.keys();
+ for (const QString &name : macroList)
d->removeMacro(name);
// Cleanup handlers
@@ -277,7 +278,7 @@ void MacroManager::startMacro()
Core::ActionManager::command(Constants::END_MACRO)->action()->setEnabled(true);
Core::ActionManager::command(Constants::EXECUTE_LAST_MACRO)->action()->setEnabled(false);
Core::ActionManager::command(Constants::SAVE_LAST_MACRO)->action()->setEnabled(false);
- foreach (IMacroHandler *handler, d->handlers)
+ for (IMacroHandler *handler : qAsConst(d->handlers))
handler->startRecording(d->currentMacro);
const QString endShortcut = Core::ActionManager::command(Constants::END_MACRO)
@@ -302,7 +303,7 @@ void MacroManager::endMacro()
Core::ActionManager::command(Constants::END_MACRO)->action()->setEnabled(false);
Core::ActionManager::command(Constants::EXECUTE_LAST_MACRO)->action()->setEnabled(true);
Core::ActionManager::command(Constants::SAVE_LAST_MACRO)->action()->setEnabled(true);
- foreach (IMacroHandler *handler, d->handlers)
+ for (IMacroHandler *handler : qAsConst(d->handlers))
handler->endRecordingMacro(d->currentMacro);
d->isRecording = false;
diff --git a/src/plugins/macros/macrooptionswidget.cpp b/src/plugins/macros/macrooptionswidget.cpp
index 0408dd9377b..d3815cff078 100644
--- a/src/plugins/macros/macrooptionswidget.cpp
+++ b/src/plugins/macros/macrooptionswidget.cpp
@@ -130,7 +130,7 @@ void MacroOptionsWidget::remove()
void MacroOptionsWidget::apply()
{
// Remove macro
- foreach (const QString &name, m_macroToRemove) {
+ for (const QString &name : qAsConst(m_macroToRemove)) {
MacroManager::instance()->deleteMacro(name);
m_macroToChange.remove(name);
}
diff --git a/src/plugins/mcusupport/CMakeLists.txt b/src/plugins/mcusupport/CMakeLists.txt
index 6d7602c2f0e..e3e202bcbda 100644
--- a/src/plugins/mcusupport/CMakeLists.txt
+++ b/src/plugins/mcusupport/CMakeLists.txt
@@ -12,12 +12,15 @@ add_qtc_plugin(McuSupport
mcusupportoptionspage.cpp mcusupportoptionspage.h
mcupackage.cpp mcupackage.h
mcutarget.cpp mcutarget.h
+ mcutargetfactorylegacy.cpp mcutargetfactorylegacy.h
+ mcutargetfactory.cpp mcutargetfactory.h
mcusupportplugin.cpp mcusupportplugin.h
mcusupportsdk.cpp mcusupportsdk.h
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
mcusupportversiondetection.cpp mcusupportversiondetection.h
- mcusupportcmakemapper.cpp mcusupportcmakemapper.h
mcutargetdescription.h
+ mcuhelpers.cpp mcuhelpers.h
+ settingshandler.cpp settingshandler.h
)
add_subdirectory(test)
diff --git a/src/plugins/mcusupport/mcuabstractpackage.h b/src/plugins/mcusupport/mcuabstractpackage.h
index e0499ef06fa..3f5a213bbd6 100644
--- a/src/plugins/mcusupport/mcuabstractpackage.h
+++ b/src/plugins/mcusupport/mcuabstractpackage.h
@@ -45,8 +45,11 @@ public:
ValidPackage
};
+ virtual ~McuAbstractPackage() = default;
+
virtual QString label() const = 0;
- virtual const QString &environmentVariableName() const = 0;
+ virtual QString cmakeVariableName() const = 0;
+ virtual QString environmentVariableName() const = 0;
virtual bool isAddToSystemPath() const = 0;
virtual void setVersions(const QStringList &) = 0;
@@ -54,6 +57,7 @@ public:
virtual Utils::FilePath path() const = 0;
virtual Utils::FilePath defaultPath() const = 0;
virtual Utils::FilePath detectionPath() const = 0;
+ virtual QString settingsKey() const = 0;
virtual void updateStatus() = 0;
virtual Status status() const = 0;
diff --git a/src/plugins/mcusupport/mcuabstracttargetfactory.h b/src/plugins/mcusupport/mcuabstracttargetfactory.h
new file mode 100644
index 00000000000..bc36a2c8b3f
--- /dev/null
+++ b/src/plugins/mcusupport/mcuabstracttargetfactory.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "mcusupport_global.h"
+
+#include <QHash>
+#include <QPair>
+
+#include <memory>
+
+namespace Utils {
+class FilePath;
+} // namespace Utils
+
+namespace McuSupport::Internal {
+
+namespace Sdk {
+struct McuTargetDescription;
+} //namespace Sdk
+
+class McuAbstractTargetFactory
+{
+public:
+ using Ptr = std::unique_ptr<McuAbstractTargetFactory>;
+ virtual ~McuAbstractTargetFactory() = default;
+
+ virtual QPair<Targets, Packages> createTargets(const Sdk::McuTargetDescription &,
+ const Utils::FilePath &qtForMcuPath)
+ = 0;
+ using AdditionalPackages
+ = QPair<QHash<QString, McuToolChainPackagePtr>, QHash<QString, McuPackagePtr>>;
+ virtual AdditionalPackages getAdditionalPackages() const { return {}; }
+}; // struct McuAbstractTargetFactory
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcuhelpers.cpp b/src/plugins/mcusupport/mcuhelpers.cpp
new file mode 100644
index 00000000000..e727f76d094
--- /dev/null
+++ b/src/plugins/mcusupport/mcuhelpers.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "mcuhelpers.h"
+#include "mcutargetdescription.h"
+
+#include <QRegularExpression>
+
+namespace McuSupport {
+
+Internal::McuTarget::OS deduceOperatingSystem(const Internal::Sdk::McuTargetDescription &desc)
+{
+ using OS = Internal::McuTarget::OS;
+ using TargetType = Internal::Sdk::McuTargetDescription::TargetType;
+ if (desc.platform.type == TargetType::Desktop)
+ return OS::Desktop;
+ else if (!desc.freeRTOS.envVar.isEmpty())
+ return OS::FreeRTOS;
+ return OS::BareMetal;
+}
+
+QString removeRtosSuffix(const QString &environmentVariable)
+{
+ static const QRegularExpression freeRtosSuffix{R"(_FREERTOS_\w+)"};
+ QString result = environmentVariable;
+ return result.replace(freeRtosSuffix, QString{});
+}
+
+} //namespace McuSupport
diff --git a/src/plugins/mcusupport/mcuhelpers.h b/src/plugins/mcusupport/mcuhelpers.h
new file mode 100644
index 00000000000..a97e536a9d9
--- /dev/null
+++ b/src/plugins/mcusupport/mcuhelpers.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "mcutarget.h"
+
+#include <QRegularExpression>
+
+namespace McuSupport {
+
+namespace Internal::Sdk {
+struct McuTargetDescription;
+}
+
+Internal::McuTarget::OS deduceOperatingSystem(const Internal::Sdk::McuTargetDescription &);
+QString removeRtosSuffix(const QString &environmentVariable);
+
+}; // namespace McuSupport
diff --git a/src/plugins/mcusupport/mcukitinformation.cpp b/src/plugins/mcusupport/mcukitinformation.cpp
index 2ab9af35d30..7c7bde5c7de 100644
--- a/src/plugins/mcusupport/mcukitinformation.cpp
+++ b/src/plugins/mcusupport/mcukitinformation.cpp
@@ -25,7 +25,10 @@
#include "mcukitinformation.h"
+#include <cmakeprojectmanager/cmakekitinformation.h>
#include <utils/qtcassert.h>
+#include <utils/algorithm.h>
+#include <utils/filepath.h>
using namespace ProjectExplorer;
@@ -57,31 +60,31 @@ McuDependenciesKitAspect::McuDependenciesKitAspect()
setPriority(28500);
}
-Tasks McuDependenciesKitAspect::validate(const Kit *k) const
+Tasks McuDependenciesKitAspect::validate(const Kit *kit) const
{
Tasks result;
- QTC_ASSERT(k, return result);
+ QTC_ASSERT(kit, return result);
- const QVariant checkFormat = k->value(McuDependenciesKitAspect::id());
- if (!checkFormat.isNull() && !checkFormat.canConvert(QVariant::List))
+ // check dependencies are defined properly for this kit
+ const QVariant checkFormat = kit->value(McuDependenciesKitAspect::id());
+ if (!checkFormat.isValid() || checkFormat.isNull())
+ return result;
+ if (!checkFormat.canConvert(QVariant::List))
return {BuildSystemTask(Task::Error, tr("The MCU dependencies setting value is invalid."))};
- const QVariant envStringList = k->value(EnvironmentKitAspect::id());
- if (!envStringList.isNull() && !envStringList.canConvert(QVariant::List))
- return {BuildSystemTask(Task::Error, tr("The environment setting value is invalid."))};
-
- const auto environment = Utils::NameValueDictionary(envStringList.toStringList());
- for (const auto &dependency : dependencies(k)) {
- if (!environment.hasKey(dependency.name)) {
- result << BuildSystemTask(Task::Warning,
- tr("Environment variable %1 not defined.")
- .arg(dependency.name));
+ // check paths defined in cmake variables for given dependencies exist
+ const auto cMakeEntries = Utils::NameValueDictionary(configuration(kit));
+ for (const auto &dependency: dependencies(kit)) {
+ auto givenPath = Utils::FilePath::fromString(cMakeEntries.value(dependency.name));
+ if (givenPath.isEmpty()) {
+ result << BuildSystemTask(Task::Warning, tr("CMake variable %1 not defined.").arg(
+ dependency.name));
} else {
- const auto path = Utils::FilePath::fromUserInput(environment.value(dependency.name)
- + "/" + dependency.value);
- if (!path.exists()) {
- result << BuildSystemTask(Task::Warning,
- tr("%1 not found.").arg(path.toUserOutput()));
+ const auto detectionPath = givenPath.resolvePath(dependency.value);
+ if (!detectionPath.exists()) {
+ result << BuildSystemTask(Task::Warning, tr("CMake variable %1: path %2 does not exist.").arg(
+ dependency.name,
+ detectionPath.toUserOutput()));
}
}
}
@@ -89,40 +92,40 @@ Tasks McuDependenciesKitAspect::validate(const Kit *k) const
return result;
}
-void McuDependenciesKitAspect::fix(Kit *k)
+void McuDependenciesKitAspect::fix(Kit *kit)
{
- QTC_ASSERT(k, return);
+ QTC_ASSERT(kit, return);
- const QVariant variant = k->value(McuDependenciesKitAspect::id());
+ const QVariant variant = kit->value(McuDependenciesKitAspect::id());
if (!variant.isNull() && !variant.canConvert(QVariant::List)) {
- qWarning("Kit \"%s\" has a wrong mcu dependencies value set.", qPrintable(k->displayName()));
- setDependencies(k, Utils::NameValueItems());
+ qWarning("Kit \"%s\" has a wrong mcu dependencies value set.", qPrintable(kit->displayName()));
+ setDependencies(kit, Utils::NameValueItems());
}
}
-KitAspectWidget *McuDependenciesKitAspect::createConfigWidget(Kit *k) const
+KitAspectWidget *McuDependenciesKitAspect::createConfigWidget(Kit *kit) const
{
- QTC_ASSERT(k, return nullptr);
- return new McuDependenciesKitAspectWidget(k, this);
+ QTC_ASSERT(kit, return nullptr);
+ return new McuDependenciesKitAspectWidget(kit, this);
}
-KitAspect::ItemList McuDependenciesKitAspect::toUserOutput(const Kit *k) const
+KitAspect::ItemList McuDependenciesKitAspect::toUserOutput(const Kit *kit) const
{
- Q_UNUSED(k)
+ Q_UNUSED(kit)
return {};
}
Utils::Id McuDependenciesKitAspect::id()
{
- return "PE.Profile.McuDependencies";
+ return "PE.Profile.McuCMakeDependencies";
}
-Utils::NameValueItems McuDependenciesKitAspect::dependencies(const Kit *k)
+Utils::NameValueItems McuDependenciesKitAspect::dependencies(const Kit *kit)
{
- if (k)
+ if (kit)
return Utils::NameValueItem::fromStringList(
- k->value(McuDependenciesKitAspect::id()).toStringList());
+ kit->value(McuDependenciesKitAspect::id()).toStringList());
return Utils::NameValueItems();
}
@@ -133,5 +136,14 @@ void McuDependenciesKitAspect::setDependencies(Kit *k, const Utils::NameValueIte
Utils::NameValueItem::toStringList(dependencies));
}
+Utils::NameValuePairs McuDependenciesKitAspect::configuration(const Kit *kit)
+{
+ using namespace CMakeProjectManager;
+ const auto config = CMakeConfigurationKitAspect::configuration(kit).toList();
+ return Utils::transform<Utils::NameValuePairs>(config, [](const CMakeConfigItem &it) {
+ return Utils::NameValuePair(QString::fromUtf8(it.key), QString::fromUtf8(it.value));
+ });
+}
+
} // namespace Internal
} // namespace McuSupport
diff --git a/src/plugins/mcusupport/mcukitinformation.h b/src/plugins/mcusupport/mcukitinformation.h
index 85c811ad668..516efa3af0f 100644
--- a/src/plugins/mcusupport/mcukitinformation.h
+++ b/src/plugins/mcusupport/mcukitinformation.h
@@ -37,16 +37,17 @@ class McuDependenciesKitAspect final : public ProjectExplorer::KitAspect
public:
McuDependenciesKitAspect();
- ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const override;
- void fix(ProjectExplorer::Kit *k) override;
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *kit) const override;
+ void fix(ProjectExplorer::Kit *kit) override;
- ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const override;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *kit) const override;
- ItemList toUserOutput(const ProjectExplorer::Kit *k) const override;
+ ItemList toUserOutput(const ProjectExplorer::Kit *kit) const override;
static Utils::Id id();
- static Utils::NameValueItems dependencies(const ProjectExplorer::Kit *k);
- static void setDependencies(ProjectExplorer::Kit *k, const Utils::NameValueItems &dependencies);
+ static Utils::NameValueItems dependencies(const ProjectExplorer::Kit *kit);
+ static void setDependencies(ProjectExplorer::Kit *kit, const Utils::NameValueItems &dependencies);
+ static Utils::NameValuePairs configuration(const ProjectExplorer::Kit *kit);
};
} // namespace Internal
diff --git a/src/plugins/mcusupport/mcukitmanager.cpp b/src/plugins/mcusupport/mcukitmanager.cpp
index a563a3828a3..7e6edff59ba 100644
--- a/src/plugins/mcusupport/mcukitmanager.cpp
+++ b/src/plugins/mcusupport/mcukitmanager.cpp
@@ -24,227 +24,330 @@
****************************************************************************/
#include "mcukitmanager.h"
+#include "mculegacyconstants.h"
#include "mcusupportoptions.h"
-#include "mcusupportconstants.h"
#include "mcukitinformation.h"
#include "mcupackage.h"
-#include "mcutarget.h"
+#include "mcusupportconstants.h"
#include "mcusupportplugin.h"
#include "mcusupportsdk.h"
+#include "mcutarget.h"
#include <cmakeprojectmanager/cmakekitinformation.h>
#include <cmakeprojectmanager/cmaketoolmanager.h>
#include <coreplugin/icore.h>
+
#include <debugger/debuggeritem.h>
#include <debugger/debuggeritemmanager.h>
#include <debugger/debuggerkitinformation.h>
-#include <utils/algorithm.h>
+
+#include <projectexplorer/projectexplorerconstants.h>
+
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtversionmanager.h>
+#include <utils/algorithm.h>
+
#include <QMessageBox>
#include <QPushButton>
+using CMakeProjectManager::CMakeConfig;
using CMakeProjectManager::CMakeConfigItem;
using CMakeProjectManager::CMakeConfigurationKitAspect;
using namespace ProjectExplorer;
using namespace Utils;
-namespace McuSupport {
-namespace Internal {
-namespace McuKitManager {
-
-static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change
+namespace McuSupport::Internal {
-static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage)
+// Utils for managing CMake Configurations
+static QMap<QByteArray, QByteArray> cMakeConfigToMap(const CMakeConfig &config)
{
- switch (tcPackage->toolchainType()) {
- case McuToolChainPackage::ToolChainType::Unsupported:
- return;
-
- case McuToolChainPackage::ToolChainType::GHS:
- case McuToolChainPackage::ToolChainType::GHSArm:
- return; // No Green Hills toolchain, because support for it is missing.
-
- case McuToolChainPackage::ToolChainType::IAR:
- case McuToolChainPackage::ToolChainType::KEIL:
- case McuToolChainPackage::ToolChainType::MSVC:
- case McuToolChainPackage::ToolChainType::GCC:
- case McuToolChainPackage::ToolChainType::ArmGcc:
- ToolChainKitAspect::setToolChain(k,
- tcPackage->toolChain(
- ProjectExplorer::Constants::C_LANGUAGE_ID));
- ToolChainKitAspect::setToolChain(k,
- tcPackage->toolChain(
- ProjectExplorer::Constants::CXX_LANGUAGE_ID));
- return;
-
- default:
- Q_UNREACHABLE();
+ QMap<QByteArray, QByteArray> map;
+ for (const auto &configItem : qAsConst(config.toList())) {
+ map.insert(configItem.key, configItem.value);
}
+ return map;
}
-
-static void setKitProperties(const QString &kitName,
- Kit *k,
- const McuTarget *mcuTarget,
- const FilePath &sdkPath)
+static CMakeConfig mapToCMakeConfig(const QMap<QByteArray, QByteArray> &map)
{
- using namespace Constants;
+ QList<CMakeConfigItem> asList;
+ for (auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it) {
+ asList.append(CMakeConfigItem(it->first, it->second));
+ }
- k->setUnexpandedDisplayName(kitName);
- k->setValue(KIT_MCUTARGET_VENDOR_KEY, mcuTarget->platform().vendor);
- k->setValue(KIT_MCUTARGET_MODEL_KEY, mcuTarget->platform().name);
- k->setValue(KIT_MCUTARGET_COLORDEPTH_KEY, mcuTarget->colorDepth());
- k->setValue(KIT_MCUTARGET_SDKVERSION_KEY, mcuTarget->qulVersion().toString());
- k->setValue(KIT_MCUTARGET_KITVERSION_KEY, KIT_VERSION);
- k->setValue(KIT_MCUTARGET_OS_KEY, static_cast<int>(mcuTarget->os()));
- k->setValue(KIT_MCUTARGET_TOOCHAIN_KEY, mcuTarget->toolChainPackage()->toolChainName());
- k->setAutoDetected(false);
- k->makeSticky();
- if (mcuTarget->toolChainPackage()->isDesktopToolchain())
- k->setDeviceTypeForIcon(DEVICE_TYPE);
- k->setValue(QtSupport::SuppliesQtQuickImportPath::id(), true);
- k->setValue(QtSupport::KitQmlImportPath::id(), sdkPath.pathAppended("include/qul").toVariant());
- k->setValue(QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), true);
- QSet<Id> irrelevant = {
- SysRootKitAspect::id(),
- QtSupport::SuppliesQtQuickImportPath::id(),
- QtSupport::KitQmlImportPath::id(),
- QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(),
- };
- if (!McuSupportOptions::kitsNeedQtVersion())
- irrelevant.insert(QtSupport::QtKitAspect::id());
- k->setIrrelevantAspects(irrelevant);
+ return CMakeConfig(asList);
}
+namespace McuKitManager {
-static void setKitDebugger(Kit *k, const McuToolChainPackage *tcPackage)
-{
- if (tcPackage->isDesktopToolchain()) {
- // Qt Creator seems to be smart enough to deduce the right Kit debugger from the ToolChain
- return;
- }
+static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change
- switch (tcPackage->toolchainType()) {
- case McuToolChainPackage::ToolChainType::Unsupported:
- case McuToolChainPackage::ToolChainType::GHS:
- case McuToolChainPackage::ToolChainType::GHSArm:
- case McuToolChainPackage::ToolChainType::IAR:
- return; // No Green Hills and IAR debugger, because support for it is missing.
-
- case McuToolChainPackage::ToolChainType::KEIL:
- case McuToolChainPackage::ToolChainType::MSVC:
- case McuToolChainPackage::ToolChainType::GCC:
- case McuToolChainPackage::ToolChainType::ArmGcc: {
- const QVariant debuggerId = tcPackage->debuggerId();
- if (debuggerId.isValid()) {
- Debugger::DebuggerKitAspect::setDebugger(k, debuggerId);
+class McuKitFactory
+{
+public:
+ static void setKitToolchains(Kit *k, const McuToolChainPackagePtr &tcPackage)
+ {
+ switch (tcPackage->toolchainType()) {
+ case McuToolChainPackage::ToolChainType::Unsupported:
+ return;
+
+ case McuToolChainPackage::ToolChainType::GHS:
+ case McuToolChainPackage::ToolChainType::GHSArm:
+ return; // No Green Hills toolchain, because support for it is missing.
+
+ case McuToolChainPackage::ToolChainType::IAR:
+ case McuToolChainPackage::ToolChainType::KEIL:
+ case McuToolChainPackage::ToolChainType::MSVC:
+ case McuToolChainPackage::ToolChainType::GCC:
+ case McuToolChainPackage::ToolChainType::ArmGcc:
+ ToolChainKitAspect::setToolChain(k,
+ tcPackage->toolChain(
+ ProjectExplorer::Constants::C_LANGUAGE_ID));
+ ToolChainKitAspect::setToolChain(k,
+ tcPackage->toolChain(
+ ProjectExplorer::Constants::CXX_LANGUAGE_ID));
+ return;
+
+ default:
+ Q_UNREACHABLE();
}
- return;
}
- default:
- Q_UNREACHABLE();
+ static void setKitProperties(Kit *k, const McuTarget *mcuTarget, const FilePath &sdkPath)
+ {
+ using namespace Constants;
+ const QString kitName{generateKitNameFromTarget(mcuTarget)};
+
+ k->setUnexpandedDisplayName(kitName);
+ k->setValue(KIT_MCUTARGET_VENDOR_KEY, mcuTarget->platform().vendor);
+ k->setValue(KIT_MCUTARGET_MODEL_KEY, mcuTarget->platform().name);
+ k->setValue(KIT_MCUTARGET_COLORDEPTH_KEY, mcuTarget->colorDepth());
+ k->setValue(KIT_MCUTARGET_SDKVERSION_KEY, mcuTarget->qulVersion().toString());
+ k->setValue(KIT_MCUTARGET_KITVERSION_KEY, KIT_VERSION);
+ k->setValue(KIT_MCUTARGET_OS_KEY, static_cast<int>(mcuTarget->os()));
+ k->setValue(KIT_MCUTARGET_TOOLCHAIN_KEY, mcuTarget->toolChainPackage()->toolChainName());
+ k->setAutoDetected(false);
+ k->makeSticky();
+ if (mcuTarget->toolChainPackage()->isDesktopToolchain())
+ k->setDeviceTypeForIcon(DEVICE_TYPE);
+ k->setValue(QtSupport::SuppliesQtQuickImportPath::id(), true);
+ k->setValue(QtSupport::KitQmlImportPath::id(), (sdkPath / "include/qul").toVariant());
+ k->setValue(QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), true);
+ QSet<Id> irrelevant = {
+ SysRootKitAspect::id(),
+ QtSupport::SuppliesQtQuickImportPath::id(),
+ QtSupport::KitQmlImportPath::id(),
+ QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(),
+ };
+ if (!McuSupportOptions::kitsNeedQtVersion())
+ irrelevant.insert(QtSupport::QtKitAspect::id());
+ k->setIrrelevantAspects(irrelevant);
}
-}
-static void setKitDevice(Kit *k, const McuTarget *mcuTarget)
-{
- // "Device Type" Desktop is the default. We use that for the Qt for MCUs Desktop Kit
- if (mcuTarget->toolChainPackage()->isDesktopToolchain())
- return;
+ static void setKitDebugger(Kit *k, const McuToolChainPackagePtr &tcPackage)
+ {
+ if (tcPackage->isDesktopToolchain()) {
+ // Qt Creator seems to be smart enough to deduce the right Kit debugger from the ToolChain
+ return;
+ }
- DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
-}
+ switch (tcPackage->toolchainType()) {
+ case McuToolChainPackage::ToolChainType::Unsupported:
+ case McuToolChainPackage::ToolChainType::GHS:
+ case McuToolChainPackage::ToolChainType::GHSArm:
+ case McuToolChainPackage::ToolChainType::IAR:
+ return; // No Green Hills and IAR debugger, because support for it is missing.
+
+ case McuToolChainPackage::ToolChainType::KEIL:
+ case McuToolChainPackage::ToolChainType::MSVC:
+ case McuToolChainPackage::ToolChainType::GCC:
+ case McuToolChainPackage::ToolChainType::ArmGcc: {
+ const QVariant debuggerId = tcPackage->debuggerId();
+ if (debuggerId.isValid()) {
+ Debugger::DebuggerKitAspect::setDebugger(k, debuggerId);
+ }
+ return;
+ }
-static void setKitDependencies(Kit *k,
- const McuTarget *mcuTarget,
- const McuAbstractPackage *qtForMCUsSdkPackage)
-{
- NameValueItems dependencies;
+ default:
+ Q_UNREACHABLE();
+ }
+ }
- auto processPackage = [&dependencies](const McuAbstractPackage *package) {
- if (!package->environmentVariableName().isEmpty())
- dependencies.append({package->environmentVariableName(),
- package->detectionPath().toUserOutput()});
- };
- for (auto package : mcuTarget->packages())
- processPackage(package);
- processPackage(qtForMCUsSdkPackage);
+ static void setKitDevice(Kit *k, const McuTarget *mcuTarget)
+ {
+ // "Device Type" Desktop is the default. We use that for the Qt for MCUs Desktop Kit
+ if (mcuTarget->toolChainPackage()->isDesktopToolchain())
+ return;
- McuDependenciesKitAspect::setDependencies(k, dependencies);
+ DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
+ }
- auto irrelevant = k->irrelevantAspects();
- irrelevant.insert(McuDependenciesKitAspect::id());
- k->setIrrelevantAspects(irrelevant);
-}
+ static void setKitDependencies(Kit *k,
+ const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdkPackage)
+ {
+ NameValueItems dependencies;
+
+ auto processPackage = [&dependencies](const McuPackagePtr &package) {
+ const auto cmakeVariableName = package->cmakeVariableName();
+ if (!cmakeVariableName.isEmpty())
+ dependencies.append({cmakeVariableName, package->detectionPath().toUserOutput()});
+ };
+ for (const auto &package : mcuTarget->packages())
+ processPackage(package);
+ processPackage(qtForMCUsSdkPackage);
+
+ McuDependenciesKitAspect::setDependencies(k, dependencies);
+
+ auto irrelevant = k->irrelevantAspects();
+ irrelevant.insert(McuDependenciesKitAspect::id());
+ k->setIrrelevantAspects(irrelevant);
+ }
-static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePath &qulDir)
-{
- using namespace CMakeProjectManager;
-
- CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
- // CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously
- if (mcuTarget->toolChainPackage()->toolchainType() != McuToolChainPackage::ToolChainType::GHS
- && mcuTarget->toolChainPackage()->toolchainType() != McuToolChainPackage::ToolChainType::GHSArm) {
- config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}"));
- config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}"));
+ static void setKitEnvironment(Kit *k,
+ const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdkPackage)
+ {
+ EnvironmentItems changes;
+ QStringList pathAdditions; // clazy:exclude=inefficient-qlist-soft
+
+ // The Desktop version depends on the Qt shared libs in Qul_DIR/bin.
+ // If CMake's fileApi is avaialble, we can rely on the "Add library search path to PATH"
+ // feature of the run configuration. Otherwise, we just prepend the path, here.
+ if (mcuTarget->toolChainPackage()->isDesktopToolchain()
+ && !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi())
+ pathAdditions.append((qtForMCUsSdkPackage->path() / "bin").toUserOutput());
+
+ auto processPackage = [&pathAdditions](const McuPackagePtr &package) {
+ if (package->isAddToSystemPath())
+ pathAdditions.append(package->path().toUserOutput());
+ };
+
+ for (const auto &package : mcuTarget->packages())
+ processPackage(package);
+ processPackage(qtForMCUsSdkPackage);
+
+ if (!pathAdditions.isEmpty()) {
+ const QString path = QLatin1String(HostOsInfo::isWindowsHost() ? "Path" : "PATH");
+ pathAdditions.append("${" + path + "}");
+ changes.append({path, pathAdditions.join(HostOsInfo::pathListSeparator())});
+ }
+
+ if (McuSupportOptions::kitsNeedQtVersion())
+ changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"});
+
+ EnvironmentKitAspect::setEnvironmentChanges(k, changes);
}
- if (!mcuTarget->toolChainPackage()->isDesktopToolchain()) {
- const FilePath cMakeToolchainFile = qulDir.pathAppended(
- "lib/cmake/Qul/toolchain/" + mcuTarget->toolChainPackage()->cmakeToolChainFileName());
+ static void setKitCMakeOptions(Kit *k,
+ const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdkPackage)
+ {
+ using namespace CMakeProjectManager;
+ auto configMap = cMakeConfigToMap(CMakeConfigurationKitAspect::configuration(k));
+
+ // CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously
+ if (mcuTarget->toolChainPackage()->toolchainType() != McuToolChainPackage::ToolChainType::GHS
+ && mcuTarget->toolChainPackage()->toolchainType()
+ != McuToolChainPackage::ToolChainType::GHSArm) {
+ configMap.insert("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}");
+ configMap.insert("CMAKE_C_COMPILER", "%{Compiler:Executable:C}");
+ }
+
+ if (!mcuTarget->toolChainPackage()->isDesktopToolchain()) {
+ const FilePath cMakeToolchainFile = mcuTarget->toolChainFilePackage()->path();
+
+ configMap.insert(Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE,
+ cMakeToolchainFile.toString().toUtf8());
+ if (!cMakeToolchainFile.exists()) {
+ printMessage(
+ McuTarget::tr(
+ "Warning for target %1: missing CMake toolchain file expected at %2.")
+ .arg(generateKitNameFromTarget(mcuTarget),
+ cMakeToolchainFile.toUserOutput()),
+ false);
+ }
+ }
- config.append(
- CMakeConfigItem("CMAKE_TOOLCHAIN_FILE", cMakeToolchainFile.toString().toUtf8()));
- if (!cMakeToolchainFile.exists()) {
+ const FilePath generatorsPath = qtForMCUsSdkPackage->path().pathAppended(
+ "/lib/cmake/Qul/QulGenerators.cmake");
+ configMap.insert("QUL_GENERATORS", generatorsPath.toString().toUtf8());
+ if (!generatorsPath.exists()) {
printMessage(McuTarget::tr(
- "Warning for target %1: missing CMake toolchain file expected at %2.")
- .arg(kitName(mcuTarget),
- cMakeToolchainFile.toUserOutput()),
+ "Warning for target %1: missing QulGenerators expected at %2.")
+ .arg(generateKitNameFromTarget(mcuTarget),
+ generatorsPath.toUserOutput()),
false);
}
- }
- const FilePath generatorsPath = qulDir.pathAppended("/lib/cmake/Qul/QulGenerators.cmake");
- config.append(CMakeConfigItem("QUL_GENERATORS", generatorsPath.toString().toUtf8()));
- if (!generatorsPath.exists()) {
- printMessage(McuTarget::tr("Warning for target %1: missing QulGenerators expected at %2.")
- .arg(kitName(mcuTarget), generatorsPath.toUserOutput()),
- false);
- }
+ configMap.insert("QUL_PLATFORM", mcuTarget->platform().name.toUtf8());
+
+ if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth)
+ configMap.insert("QUL_COLOR_DEPTH", QString::number(mcuTarget->colorDepth()).toLatin1());
+ if (McuSupportOptions::kitsNeedQtVersion())
+ configMap.insert("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}");
- config.append(CMakeConfigItem("QUL_PLATFORM", mcuTarget->platform().name.toUtf8()));
-
- if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth)
- config.append(CMakeConfigItem("QUL_COLOR_DEPTH",
- QString::number(mcuTarget->colorDepth()).toLatin1()));
- if (McuSupportOptions::kitsNeedQtVersion())
- config.append(CMakeConfigItem("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}"));
- CMakeConfigurationKitAspect::setConfiguration(k, config);
-
- if (HostOsInfo::isWindowsHost()) {
- auto type = mcuTarget->toolChainPackage()->toolchainType();
- if (type == McuToolChainPackage::ToolChainType::GHS || type == McuToolChainPackage::ToolChainType::GHSArm) {
- // See https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565802&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565802
- // and https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565803&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565803
- CMakeGeneratorKitAspect::setGenerator(k, "NMake Makefiles JOM");
+ if (HostOsInfo::isWindowsHost()) {
+ auto type = mcuTarget->toolChainPackage()->toolchainType();
+ if (type == McuToolChainPackage::ToolChainType::GHS
+ || type == McuToolChainPackage::ToolChainType::GHSArm) {
+ // See https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565802&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565802
+ // and https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565803&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565803
+ CMakeGeneratorKitAspect::setGenerator(k, "NMake Makefiles JOM");
+ }
}
+
+ auto processPackage = [&configMap](const McuPackagePtr &package) {
+ if (!package->cmakeVariableName().isEmpty())
+ configMap.insert(package->cmakeVariableName().toUtf8(),
+ package->path().toUserOutput().toUtf8());
+ };
+
+ for (auto package : mcuTarget->packages())
+ processPackage(package);
+ processPackage(qtForMCUsSdkPackage);
+
+ CMakeConfigurationKitAspect::setConfiguration(k, mapToCMakeConfig(configMap));
}
-}
-static void setKitQtVersionOptions(Kit *k)
+ static void setKitQtVersionOptions(Kit *k)
+ {
+ if (!McuSupportOptions::kitsNeedQtVersion())
+ QtSupport::QtKitAspect::setQtVersion(k, nullptr);
+ // else: auto-select a Qt version
+ }
+
+}; // class McuKitFactory
+
+// Construct kit
+Kit *newKit(const McuTarget *mcuTarget, const McuPackagePtr &qtForMCUsSdk)
{
- if (!McuSupportOptions::kitsNeedQtVersion())
- QtSupport::QtKitAspect::setQtVersion(k, nullptr);
- // else: auto-select a Qt version
+ const auto init = [&mcuTarget, qtForMCUsSdk](Kit *k) {
+ KitGuard kitGuard(k);
+
+ McuKitFactory::setKitProperties(k, mcuTarget, qtForMCUsSdk->path());
+ McuKitFactory::setKitDevice(k, mcuTarget);
+ McuKitFactory::setKitToolchains(k, mcuTarget->toolChainPackage());
+ McuKitFactory::setKitDebugger(k, mcuTarget->toolChainPackage());
+ McuKitFactory::setKitEnvironment(k, mcuTarget, qtForMCUsSdk);
+ McuKitFactory::setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk);
+ McuKitFactory::setKitDependencies(k, mcuTarget, qtForMCUsSdk);
+ McuKitFactory::setKitQtVersionOptions(k);
+
+ k->setup();
+ k->fix();
+ };
+
+ return KitManager::registerKit(init);
}
-QString kitName(const McuTarget *mcuTarget)
+// Kit Information
+QString generateKitNameFromTarget(const McuTarget *mcuTarget)
{
- const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage();
+ McuToolChainPackagePtr tcPkg = mcuTarget->toolChainPackage();
const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain()
? QString::fromLatin1(" (%1)").arg(
tcPkg->toolChainName().toUpper())
@@ -263,6 +366,36 @@ QString kitName(const McuTarget *mcuTarget)
compilerName);
}
+// Kit Information
+QVersionNumber kitQulVersion(const Kit *kit)
+{
+ return QVersionNumber::fromString(
+ kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString());
+}
+
+// Kit Information
+static FilePath kitDependencyPath(const Kit *kit, const QString &cmakeVariableName)
+{
+ const auto config = CMakeConfigurationKitAspect::configuration(kit).toList();
+ const auto keyName = cmakeVariableName.toUtf8();
+ for (const CMakeConfigItem &configItem : config) {
+ if (configItem.key == keyName)
+ return FilePath::fromUserInput(QString::fromUtf8(configItem.value));
+ }
+ return FilePath();
+}
+
+// Kit Information
+bool kitIsUpToDate(const Kit *kit,
+ const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdkPackage)
+{
+ return kitQulVersion(kit) == mcuTarget->qulVersion()
+ && kitDependencyPath(kit, qtForMCUsSdkPackage->cmakeVariableName()).toUserOutput()
+ == qtForMCUsSdkPackage->path().toUserOutput();
+}
+
+// Queries
QList<Kit *> existingKits(const McuTarget *mcuTarget)
{
using namespace Constants;
@@ -274,41 +407,42 @@ QList<Kit *> existingKits(const McuTarget *mcuTarget)
&& kit->value(KIT_MCUTARGET_COLORDEPTH_KEY) == mcuTarget->colorDepth()
&& kit->value(KIT_MCUTARGET_OS_KEY).toInt()
== static_cast<int>(mcuTarget->os())
- && kit->value(KIT_MCUTARGET_TOOCHAIN_KEY)
+ && kit->value(KIT_MCUTARGET_TOOLCHAIN_KEY)
== mcuTarget->toolChainPackage()->toolChainName()));
});
}
-QList<Kit *> matchingKits(const McuTarget *mcuTarget,
- const McuAbstractPackage *qtForMCUsSdkPackage)
+// Queries
+QList<Kit *> matchingKits(const McuTarget *mcuTarget, const McuPackagePtr &qtForMCUsSdkPackage)
{
- return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
+ return Utils::filtered(existingKits(mcuTarget), [&mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
return kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
});
}
-QList<Kit *> upgradeableKits(const McuTarget *mcuTarget,
- const McuAbstractPackage *qtForMCUsSdkPackage)
+// Queries
+QList<Kit *> upgradeableKits(const McuTarget *mcuTarget, const McuPackagePtr &qtForMCUsSdkPackage)
{
- return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
+ return Utils::filtered(existingKits(mcuTarget), [&mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
return !kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
});
}
+// Queries
QList<Kit *> kitsWithMismatchedDependencies(const McuTarget *mcuTarget)
{
- return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) {
- const auto environment = Utils::NameValueDictionary(
- Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit)));
- return Utils::anyOf(mcuTarget->packages(),
- [&environment](const McuAbstractPackage *package) {
- return !package->environmentVariableName().isEmpty()
- && environment.value(package->environmentVariableName())
- != package->path().toUserOutput();
- });
+ return Utils::filtered(existingKits(mcuTarget), [&mcuTarget](Kit *kit) {
+ const auto entries = Utils::NameValueDictionary(
+ McuDependenciesKitAspect::configuration(kit));
+ return Utils::anyOf(mcuTarget->packages(), [&entries](const McuPackagePtr &package) {
+ const QString cmakeVariableName = package->cmakeVariableName();
+ return !cmakeVariableName.isEmpty()
+ && entries.value(cmakeVariableName) != package->path().toUserOutput();
+ });
});
}
+// Queries
QList<Kit *> outdatedKits()
{
return Utils::filtered(KitManager::kits(), [](Kit *kit) {
@@ -317,63 +451,13 @@ QList<Kit *> outdatedKits()
});
}
-void removeOutdatedKits()
-{
- for (auto kit : outdatedKits())
- KitManager::deregisterKit(kit);
-}
-
-Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk)
-{
- const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) {
- KitGuard kitGuard(k);
-
- setKitProperties(kitName(mcuTarget), k, mcuTarget, qtForMCUsSdk->path());
- setKitDevice(k, mcuTarget);
- setKitToolchains(k, mcuTarget->toolChainPackage());
- setKitDebugger(k, mcuTarget->toolChainPackage());
- McuSupportOptions::setKitEnvironment(k, mcuTarget, qtForMCUsSdk);
- setKitDependencies(k, mcuTarget, qtForMCUsSdk);
- setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk->path());
- setKitQtVersionOptions(k);
-
- k->setup();
- k->fix();
- };
-
- return KitManager::registerKit(init);
-}
-
-QVersionNumber kitQulVersion(const Kit *kit)
-{
- return QVersionNumber::fromString(
- kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString());
-}
-
-static FilePath kitDependencyPath(const Kit *kit, const QString &variableName)
-{
- for (const NameValueItem &nameValueItem : EnvironmentKitAspect::environmentChanges(kit)) {
- if (nameValueItem.name == variableName)
- return FilePath::fromUserInput(nameValueItem.value);
- }
- return FilePath();
-}
-
-bool kitIsUpToDate(const Kit *kit,
- const McuTarget *mcuTarget,
- const McuAbstractPackage *qtForMCUsSdkPackage)
-{
- return kitQulVersion(kit) == mcuTarget->qulVersion()
- && kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput()
- == qtForMCUsSdkPackage->path().toUserOutput();
-}
-
-void createAutomaticKits()
+// Maintenance
+void createAutomaticKits(const SettingsHandler::Ptr &settingsHandler)
{
- auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
+ McuPackagePtr qtForMCUsPackage{Sdk::createQtForMCUsPackage(settingsHandler)};
- const auto createKits = [qtForMCUsPackage]() {
- if (McuSupportOptions::automaticKitCreationFromSettings()) {
+ const auto createKits = [qtForMCUsPackage, settingsHandler]() {
+ if (settingsHandler->isAutomaticKitCreationEnabled()) {
qtForMCUsPackage->updateStatus();
if (!qtForMCUsPackage->isValidStatus()) {
switch (qtForMCUsPackage->status()) {
@@ -385,16 +469,19 @@ void createAutomaticKits()
break;
}
case McuAbstractPackage::Status::InvalidPath: {
- printMessage(McuPackage::tr("Path %1 does not exist. Add the path in Tools > Options > "
- "Devices > MCU.")
+ printMessage(McuPackage::tr(
+ "Path %1 does not exist. Add the path in Edit > Preferences > "
+ "Devices > MCU.")
.arg(qtForMCUsPackage->path().toUserOutput()),
true);
break;
}
case McuAbstractPackage::Status::EmptyPath: {
- printMessage(McuPackage::tr("Missing %1. Add the path in Tools > Options > Devices > MCU.")
- .arg(qtForMCUsPackage->detectionPath().toUserOutput()),
- true);
+ printMessage(
+ McuPackage::tr(
+ "Missing %1. Add the path in Edit > Preferences > Devices > MCU.")
+ .arg(qtForMCUsPackage->detectionPath().toUserOutput()),
+ true);
return;
}
default:
@@ -404,60 +491,62 @@ void createAutomaticKits()
}
if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) {
- printMessage(McuPackage::tr("No CMake tool was detected. Add a CMake tool in Tools > Options > "
- "Kits > CMake."),
- true);
+ printMessage(
+ McuPackage::tr(
+ "No CMake tool was detected. Add a CMake tool in Edit > Preferences > "
+ "Kits > CMake."),
+ true);
return;
}
FilePath dir = qtForMCUsPackage->path();
- McuSdkRepository repo;
- Sdk::targetsAndPackages(dir, &repo);
+ McuSdkRepository repo{Sdk::targetsAndPackages(dir, settingsHandler)};
bool needsUpgrade = false;
for (const auto &target : qAsConst(repo.mcuTargets)) {
// if kit already exists, skip
- if (!matchingKits(target, qtForMCUsPackage).empty())
+ if (!matchingKits(target.get(), qtForMCUsPackage).empty())
continue;
- if (!upgradeableKits(target, qtForMCUsPackage).empty()) {
+ if (!upgradeableKits(target.get(), qtForMCUsPackage).empty()) {
// if kit exists but wrong version/path
needsUpgrade = true;
} else {
// if no kits for this target, create
if (target->isValid())
- newKit(target, qtForMCUsPackage);
+ newKit(target.get(), qtForMCUsPackage);
target->printPackageProblems();
}
}
-
- repo.deletePackagesAndTargets();
-
if (needsUpgrade)
- McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade();
+ McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(settingsHandler);
}
};
createKits();
- delete qtForMCUsPackage;
}
-void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption)
+// Maintenance
+// when the SDK version has changed, and the user has given permission
+// to upgrade, create new kits with current data, for the targets
+// for which kits already existed
+// function parameter is option to keep the old ones or delete them
+void upgradeKitsByCreatingNewPackage(const SettingsHandler::Ptr &settingsHandler,
+ UpgradeOption upgradeOption)
{
if (upgradeOption == UpgradeOption::Ignore)
return;
- auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
+ McuPackagePtr qtForMCUsPackage{Sdk::createQtForMCUsPackage(settingsHandler)};
auto dir = qtForMCUsPackage->path();
- McuSdkRepository repo;
- Sdk::targetsAndPackages(dir, &repo);
+ McuSdkRepository repo{Sdk::targetsAndPackages(dir, settingsHandler)};
for (const auto &target : qAsConst(repo.mcuTargets)) {
- if (!matchingKits(target, qtForMCUsPackage).empty())
+ if (!matchingKits(target.get(), qtForMCUsPackage).empty())
// already up-to-date
continue;
- const auto kits = upgradeableKits(target, qtForMCUsPackage);
+ const auto kits = upgradeableKits(target.get(), qtForMCUsPackage);
if (!kits.empty()) {
if (upgradeOption == UpgradeOption::Replace) {
for (auto existingKit : kits)
@@ -465,47 +554,63 @@ void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption)
}
if (target->isValid())
- newKit(target, qtForMCUsPackage);
+ newKit(target.get(), qtForMCUsPackage);
target->printPackageProblems();
}
}
-
- repo.deletePackagesAndTargets();
- delete qtForMCUsPackage;
}
+// Maintenance
+// when the user manually asks to upgrade a specific kit
+// button is available if SDK version changed
void upgradeKitInPlace(ProjectExplorer::Kit *kit,
- const McuTarget *mcuTarget,
- const McuAbstractPackage *qtForMCUsSdk)
+ const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdk)
{
- setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path());
- McuSupportOptions::setKitEnvironment(kit, mcuTarget, qtForMCUsSdk);
- setKitDependencies(kit, mcuTarget, qtForMCUsSdk);
+ McuKitFactory::setKitProperties(kit, mcuTarget, qtForMCUsSdk->path());
+ McuKitFactory::setKitEnvironment(kit, mcuTarget, qtForMCUsSdk);
+ McuKitFactory::setKitCMakeOptions(kit, mcuTarget, qtForMCUsSdk);
+ McuKitFactory::setKitDependencies(kit, mcuTarget, qtForMCUsSdk);
}
-void fixKitsDependencies()
+// Maintenance
+// If the user changed a path in the McuSupport plugin's UI
+// update the corresponding cmake variables in all existing kits
+void updatePathsInExistingKits(const SettingsHandler::Ptr &settingsHandler)
{
- auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
+ McuPackagePtr qtForMCUsPackage{Sdk::createQtForMCUsPackage(settingsHandler)};
FilePath dir = qtForMCUsPackage->path();
- McuSdkRepository repo;
- Sdk::targetsAndPackages(dir, &repo);
+ McuSdkRepository repo{Sdk::targetsAndPackages(dir, settingsHandler)};
for (const auto &target : qAsConst(repo.mcuTargets)) {
if (target->isValid()) {
- for (auto *kit : kitsWithMismatchedDependencies(target)) {
- McuSupportOptions::updateKitEnvironment(kit, target);
+ for (auto *kit : kitsWithMismatchedDependencies(target.get())) {
+ auto changes = cMakeConfigToMap(CMakeConfigurationKitAspect::configuration(kit));
+
+ const auto updateForPackage = [&changes](const McuPackagePtr &package) {
+ if (!package->cmakeVariableName().isEmpty() && package->isValidStatus()) {
+ changes.insert(package->cmakeVariableName().toUtf8(),
+ package->path().toUserOutput().toUtf8());
+ }
+ };
+
+ for (const auto &package : target->packages()) {
+ updateForPackage(package);
+ }
+ updateForPackage(qtForMCUsPackage);
+
+ CMakeConfigurationKitAspect::setConfiguration(kit,
+ CMakeProjectManager::CMakeConfig(
+ mapToCMakeConfig(changes)));
}
}
}
-
- repo.deletePackagesAndTargets();
- delete qtForMCUsPackage;
}
-/**
- * @brief Fix/update existing kits if needed
- */
-void fixExistingKits()
+// Maintenance
+// if we changed minor details in the kits across versions of QtCreator
+// this function updates those details in existing older kits
+void fixExistingKits(const SettingsHandler::Ptr &settingsHandler)
{
for (Kit *kit : KitManager::kits()) {
if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY))
@@ -558,24 +663,28 @@ void fixExistingKits()
}
// Fix kit dependencies for known targets
- auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
+ McuPackagePtr qtForMCUsPackage{Sdk::createQtForMCUsPackage(settingsHandler)};
qtForMCUsPackage->updateStatus();
if (qtForMCUsPackage->isValidStatus()) {
FilePath dir = qtForMCUsPackage->path();
- McuSdkRepository repo;
- Sdk::targetsAndPackages(dir, &repo);
+ McuSdkRepository repo{Sdk::targetsAndPackages(dir, settingsHandler)};
for (const auto &target : qAsConst(repo.mcuTargets))
- for (auto kit : existingKits(target)) {
+ for (auto kit : existingKits(target.get())) {
if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) {
- setKitDependencies(kit, target, qtForMCUsPackage);
+ McuKitFactory::setKitCMakeOptions(kit, target.get(), qtForMCUsPackage);
+ McuKitFactory::setKitDependencies(kit, target.get(), qtForMCUsPackage);
}
}
-
- repo.deletePackagesAndTargets();
}
- delete qtForMCUsPackage;
+}
+
+// Maintenance
+// removes kits with older schemes
+void removeOutdatedKits()
+{
+ for (auto kit : outdatedKits())
+ KitManager::deregisterKit(kit);
}
} // namespace McuKitManager
-} // namespace Internal
-} // namespace McuSupport
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcukitmanager.h b/src/plugins/mcusupport/mcukitmanager.h
index 1814fb26432..8cd5eea0b5d 100644
--- a/src/plugins/mcusupport/mcukitmanager.h
+++ b/src/plugins/mcusupport/mcukitmanager.h
@@ -25,62 +25,60 @@
#pragma once
-#include <utils/environmentfwd.h>
#include "mcusupport_global.h"
+#include "settingshandler.h"
+
+#include <utils/environmentfwd.h>
#include <QCoreApplication>
-#include <QObject>
-#include <QVector>
#include <QVersionNumber>
namespace ProjectExplorer {
class Kit;
} // namespace ProjectExplorer
-namespace McuSupport {
-namespace Internal {
+namespace McuSupport::Internal {
class McuAbstractPackage;
-class McuToolChainPackage;
class McuTarget;
-namespace McuKitManager
-{
- enum class UpgradeOption {
- Ignore,
- Keep,
- Replace
- };
-
- // Creating kits:
- ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk);
- void createAutomaticKits();
-
- // Querying the kits:
- QList<ProjectExplorer::Kit *> existingKits(const McuTarget *mcuTarget);
- QList<ProjectExplorer::Kit *> matchingKits(const McuTarget *mcuTarget,
- const McuAbstractPackage *qtForMCUsSdkPackage);
- QList<ProjectExplorer::Kit *> upgradeableKits(
- const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage);
- QList<ProjectExplorer::Kit *> kitsWithMismatchedDependencies(const McuTarget *mcuTarget);
-
- // Upgrading kits:
- void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption);
- void upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk);
-
- // Fixing kits:
- void fixKitsDependencies();
- void fixExistingKits();
-
- // Outdated kits:
- QList<ProjectExplorer::Kit *> outdatedKits();
- void removeOutdatedKits();
-
- // Querying kits:
- QString kitName(const McuTarget* mcuTarget);
- QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit);
- bool kitIsUpToDate(const ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage);
+namespace McuKitManager {
+enum class UpgradeOption { Ignore, Keep, Replace };
+
+// Kit Factory
+ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuPackagePtr &qtForMCUsSdk);
+
+// Kit information
+QString generateKitNameFromTarget(const McuTarget *mcuTarget);
+QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit);
+bool kitIsUpToDate(const ProjectExplorer::Kit *kit,
+ const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdkPackage);
+
+// Queries
+QList<ProjectExplorer::Kit *> existingKits(const McuTarget *mcuTarget);
+QList<ProjectExplorer::Kit *> matchingKits(const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdkPackage);
+QList<ProjectExplorer::Kit *> upgradeableKits(const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdkPackage);
+QList<ProjectExplorer::Kit *> kitsWithMismatchedDependencies(const McuTarget *mcuTarget);
+QList<ProjectExplorer::Kit *> outdatedKits();
+
+// Maintenance
+void createAutomaticKits(const SettingsHandler::Ptr &);
+void upgradeKitsByCreatingNewPackage(const SettingsHandler::Ptr &, UpgradeOption upgradeOption);
+void upgradeKitInPlace(ProjectExplorer::Kit *kit,
+ const McuTarget *mcuTarget,
+ const McuPackagePtr &qtForMCUsSdk);
+
+// Fixing kits:
+void updatePathsInExistingKits(const SettingsHandler::Ptr &);
+void fixExistingKits(const SettingsHandler::Ptr &);
+
+// Outdated kits:
+void removeOutdatedKits();
} // namespace McuKitManager
-} // namespace Internal
-} // namespace McuSupport
+} // namespace McuSupport::Internal
+
+Q_DECLARE_METATYPE(McuSupport::Internal::McuKitManager::UpgradeOption)
diff --git a/src/plugins/mcusupport/mculegacyconstants.h b/src/plugins/mcusupport/mculegacyconstants.h
new file mode 100644
index 00000000000..945996acc23
--- /dev/null
+++ b/src/plugins/mcusupport/mculegacyconstants.h
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+namespace McuSupport::Constants {
+
+const char QUL_TOOLCHAIN_CMAKE_DIR[] = "lib/cmake/Qul/toolchain/";
+const char QUL_ENV_VAR[] = "Qul_ROOT";
+
+} // namespace McuSupport::Constants
diff --git a/src/plugins/mcusupport/mcupackage.cpp b/src/plugins/mcusupport/mcupackage.cpp
index 53b5ccceb52..35c87fe2ba0 100644
--- a/src/plugins/mcusupport/mcupackage.cpp
+++ b/src/plugins/mcusupport/mcupackage.cpp
@@ -25,20 +25,21 @@
#include "mcupackage.h"
#include "mcusupportconstants.h"
-#include "mcusupportversiondetection.h"
#include "mcusupportsdk.h"
+#include "mcusupportversiondetection.h"
+#include "settingshandler.h"
#include <baremetal/baremetalconstants.h>
#include <coreplugin/icore.h>
+#include <debugger/debuggeritem.h>
+#include <debugger/debuggeritemmanager.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchainmanager.h>
#include <utils/algorithm.h>
#include <utils/infolabel.h>
#include <utils/pathchooser.h>
#include <utils/utilsicons.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/toolchain.h>
-#include <projectexplorer/toolchainmanager.h>
-#include <debugger/debuggeritem.h>
-#include <debugger/debuggeritemmanager.h>
#include <QDesktopServices>
#include <QGridLayout>
@@ -49,26 +50,30 @@ using namespace Utils;
namespace McuSupport::Internal {
-McuPackage::McuPackage(const QString &label,
+McuPackage::McuPackage(const SettingsHandler::Ptr &settingsHandler,
+ const QString &label,
const FilePath &defaultPath,
const FilePath &detectionPath,
const QString &settingsKey,
+ const QString &cmakeVarName,
const QString &envVarName,
const QString &downloadUrl,
const McuPackageVersionDetector *versionDetector,
const bool addToSystemPath,
const FilePath &relativePathModifier)
- : m_label(label)
- , m_defaultPath(Sdk::packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath))
+ : settingsHandler(settingsHandler)
+ , m_label(label)
+ , m_defaultPath(settingsHandler->getPath(settingsKey, QSettings::SystemScope, defaultPath))
, m_detectionPath(detectionPath)
, m_settingsKey(settingsKey)
, m_versionDetector(versionDetector)
, m_relativePathModifier(relativePathModifier)
+ , m_cmakeVariableName(cmakeVarName)
, m_environmentVariableName(envVarName)
, m_downloadUrl(downloadUrl)
, m_addToSystemPath(addToSystemPath)
{
- m_path = Sdk::packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath);
+ m_path = this->settingsHandler->getPath(settingsKey, QSettings::UserScope, m_defaultPath);
}
QString McuPackage::label() const
@@ -76,7 +81,17 @@ QString McuPackage::label() const
return m_label;
}
-const QString &McuPackage::environmentVariableName() const
+QString McuPackage::settingsKey() const
+{
+ return m_settingsKey;
+}
+
+QString McuPackage::cmakeVariableName() const
+{
+ return m_cmakeVariableName;
+}
+
+QString McuPackage::environmentVariableName() const
{
return m_environmentVariableName;
}
@@ -98,7 +113,7 @@ FilePath McuPackage::basePath() const
FilePath McuPackage::path() const
{
- return basePath().pathAppended(m_relativePathModifier.path()).absoluteFilePath();
+ return (basePath() / m_relativePathModifier.path()).absoluteFilePath().cleanPath();
}
FilePath McuPackage::defaultPath() const
@@ -121,10 +136,10 @@ void McuPackage::updatePath()
void McuPackage::updateStatus()
{
bool validPath = !m_path.isEmpty() && m_path.exists();
- const FilePath detectionPath = basePath().pathAppended(m_detectionPath.path());
+ const FilePath detectionPath = basePath() / m_detectionPath.path();
const bool validPackage = m_detectionPath.isEmpty() || detectionPath.exists();
m_detectedVersion = validPath && validPackage && m_versionDetector
- ? m_versionDetector->parseVersion(basePath().toString())
+ ? m_versionDetector->parseVersion(basePath())
: QString();
const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty()
|| m_versions.contains(m_detectedVersion);
@@ -148,7 +163,6 @@ bool McuPackage::isValidStatus() const
return m_status == Status::ValidPackage || m_status == Status::ValidPackageMismatchedVersion;
}
-
void McuPackage::updateStatusUi()
{
switch (m_status) {
@@ -216,22 +230,12 @@ QString McuPackage::statusText() const
bool McuPackage::writeToSettings() const
{
- const FilePath savedPath = Sdk::packagePathFromSettings(m_settingsKey,
- QSettings::UserScope,
- m_defaultPath);
- const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/'
- + QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey;
- Core::ICore::settings()->setValueWithDefault(key, m_path.toString(), m_defaultPath.toString());
-
- return savedPath != m_path;
+ return settingsHandler->write(m_settingsKey, m_path, m_defaultPath);
}
QWidget *McuPackage::widget()
{
- if (m_widget)
- return m_widget;
-
- m_widget = new QWidget;
+ auto *widget = new QWidget;
m_fileChooser = new PathChooser;
m_fileChooser->lineEdit()->setButtonIcon(FancyLineEdit::Right, Icons::RESET.icon());
m_fileChooser->lineEdit()->setButtonVisible(FancyLineEdit::Right, true);
@@ -239,7 +243,7 @@ QWidget *McuPackage::widget()
m_fileChooser->setFilePath(m_defaultPath);
});
- auto layout = new QGridLayout(m_widget);
+ auto layout = new QGridLayout(widget);
layout->setContentsMargins(0, 0, 0, 0);
m_infoLabel = new InfoLabel();
@@ -266,18 +270,27 @@ QWidget *McuPackage::widget()
});
updateStatus();
- return m_widget;
+ return widget;
}
-
-McuToolChainPackage::McuToolChainPackage(const QString &label,
+McuToolChainPackage::McuToolChainPackage(const SettingsHandler::Ptr &settingsHandler,
+ const QString &label,
const FilePath &defaultPath,
const FilePath &detectionPath,
const QString &settingsKey,
McuToolChainPackage::ToolChainType type,
+ const QString &cmakeVarName,
const QString &envVarName,
const McuPackageVersionDetector *versionDetector)
- : McuPackage(label, defaultPath, detectionPath, settingsKey, envVarName, {}, versionDetector)
+ : McuPackage(settingsHandler,
+ label,
+ defaultPath,
+ detectionPath,
+ settingsKey,
+ cmakeVarName,
+ envVarName,
+ {},
+ versionDetector)
, m_type(type)
{}
@@ -379,7 +392,7 @@ ToolChain *McuToolChainPackage::toolChain(Id language) const
case ToolChainType::GCC:
return gccToolChain(language);
case ToolChainType::IAR: {
- const FilePath compiler = path().pathAppended("/bin/iccarm").withExecutableSuffix();
+ const FilePath compiler = (path() / "/bin/iccarm").withExecutableSuffix();
return iarToolChain(compiler, language);
}
case ToolChainType::ArmGcc:
@@ -390,9 +403,9 @@ ToolChain *McuToolChainPackage::toolChain(Id language) const
const QLatin1String compilerName(
language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++");
const QString comp = QLatin1String(m_type == ToolChainType::ArmGcc ? "/bin/arm-none-eabi-%1"
- : "/bar/foo-keil-%1")
+ : "/bar/foo-keil-%1")
.arg(compilerName);
- const FilePath compiler = path().pathAppended(comp).withExecutableSuffix();
+ const FilePath compiler = (path() / comp).withExecutableSuffix();
return armGccToolChain(compiler, language);
}
@@ -419,11 +432,6 @@ QString McuToolChainPackage::toolChainName() const
}
}
-QString McuToolChainPackage::cmakeToolChainFileName() const
-{
- return toolChainName() + QLatin1String(".cmake");
-}
-
QVariant McuToolChainPackage::debuggerId() const
{
using namespace Debugger;
@@ -454,7 +462,7 @@ QVariant McuToolChainPackage::debuggerId() const
return QVariant();
}
- const FilePath command = path().pathAppended(sub).withExecutableSuffix();
+ const FilePath command = (path() / sub).withExecutableSuffix();
if (const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command)) {
return debugger->id();
}
@@ -466,5 +474,4 @@ QVariant McuToolChainPackage::debuggerId() const
return DebuggerItemManager::registerDebugger(newDebugger);
}
-
} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcupackage.h b/src/plugins/mcusupport/mcupackage.h
index 5a57fad9658..7316fbea151 100644
--- a/src/plugins/mcusupport/mcupackage.h
+++ b/src/plugins/mcusupport/mcupackage.h
@@ -26,6 +26,8 @@
#pragma once
#include "mcuabstractpackage.h"
+#include "mcusupportversiondetection.h"
+#include "settingshandler.h"
#include <utils/filepath.h>
@@ -53,11 +55,13 @@ class McuPackage : public McuAbstractPackage
Q_OBJECT
public:
- McuPackage(const QString &label,
+ McuPackage(const SettingsHandler::Ptr &settingsHandler,
+ const QString &label,
const Utils::FilePath &defaultPath,
const Utils::FilePath &detectionPath,
const QString &settingsKey,
- const QString &envVarName = {},
+ const QString &cmakeVarName,
+ const QString &envVarName,
const QString &downloadUrl = {},
const McuPackageVersionDetector *versionDetector = nullptr,
const bool addToPath = false,
@@ -66,7 +70,8 @@ public:
~McuPackage() override = default;
QString label() const override;
- const QString &environmentVariableName() const override;
+ QString cmakeVariableName() const override;
+ QString environmentVariableName() const override;
bool isAddToSystemPath() const override;
void setVersions(const QStringList &versions) override;
@@ -74,6 +79,7 @@ public:
Utils::FilePath path() const override;
Utils::FilePath defaultPath() const override;
Utils::FilePath detectionPath() const override;
+ QString settingsKey() const final;
void updateStatus() override;
Status status() const override;
@@ -88,7 +94,8 @@ private:
void updatePath();
void updateStatusUi();
- QWidget *m_widget = nullptr;
+ SettingsHandler::Ptr settingsHandler;
+
Utils::PathChooser *m_fileChooser = nullptr;
Utils::InfoLabel *m_infoLabel = nullptr;
@@ -96,12 +103,13 @@ private:
const Utils::FilePath m_defaultPath;
const Utils::FilePath m_detectionPath;
const QString m_settingsKey;
- const McuPackageVersionDetector *m_versionDetector;
+ QScopedPointer<const McuPackageVersionDetector> m_versionDetector;
Utils::FilePath m_path;
Utils::FilePath m_relativePathModifier; // relative path to m_path to be returned by path()
QString m_detectedVersion;
QStringList m_versions;
+ const QString m_cmakeVariableName;
const QString m_environmentVariableName;
const QString m_downloadUrl;
const bool m_addToSystemPath;
@@ -111,14 +119,17 @@ private:
class McuToolChainPackage : public McuPackage
{
+ Q_OBJECT
public:
enum class ToolChainType { IAR, KEIL, MSVC, GCC, ArmGcc, GHS, GHSArm, Unsupported };
- McuToolChainPackage(const QString &label,
+ McuToolChainPackage(const SettingsHandler::Ptr &settingsHandler,
+ const QString &label,
const Utils::FilePath &defaultPath,
const Utils::FilePath &detectionPath,
const QString &settingsKey,
ToolChainType toolchainType,
+ const QString &cmakeVarName = {},
const QString &envVarName = {},
const McuPackageVersionDetector *versionDetector = nullptr);
@@ -126,7 +137,6 @@ public:
bool isDesktopToolchain() const;
ProjectExplorer::ToolChain *toolChain(Utils::Id language) const;
QString toolChainName() const;
- QString cmakeToolChainFileName() const;
QVariant debuggerId() const;
private:
@@ -135,3 +145,5 @@ private:
} // namespace Internal
} // namespace McuSupport
+
+Q_DECLARE_METATYPE(McuSupport::Internal::McuToolChainPackage::ToolChainType)
diff --git a/src/plugins/mcusupport/mcusupport.qbs b/src/plugins/mcusupport/mcusupport.qbs
index 22adc0ff2af..5f3135214af 100644
--- a/src/plugins/mcusupport/mcusupport.qbs
+++ b/src/plugins/mcusupport/mcusupport.qbs
@@ -23,6 +23,10 @@ QtcPlugin {
"mcupackage.h",
"mcutarget.cpp",
"mcutarget.h",
+ "mcutargetfactory.cpp",
+ "mcutargetfactory.h",
+ "mcutargetfactorylegacy.cpp",
+ "mcutargetfactorylegacy.h",
"mcusupport.qrc",
"mcusupport_global.h",
"mcusupportconstants.h",
@@ -42,11 +46,13 @@ QtcPlugin {
"mcusupportrunconfiguration.h",
"mcusupportversiondetection.cpp",
"mcusupportversiondetection.h",
- "mcusupportcmakemapper.h",
- "mcusupportcmakemapper.cpp",
"mcutargetdescription.h",
"mcukitinformation.cpp",
- "mcukitinformation.h"
+ "mcukitinformation.h",
+ "mcuhelpers.cpp",
+ "mcuhelpers.h",
+ "settingshandler.h",
+ "settingshandler.cpp",
]
Group {
@@ -55,6 +61,7 @@ QtcPlugin {
prefix: "test/"
files: [
"packagemock.h",
+ "settingshandlermock.h",
"unittest.cpp", "unittest.h"
]
}
diff --git a/src/plugins/mcusupport/mcusupport_global.h b/src/plugins/mcusupport/mcusupport_global.h
index fd92f43c9c6..bb05bd0441d 100644
--- a/src/plugins/mcusupport/mcusupport_global.h
+++ b/src/plugins/mcusupport/mcusupport_global.h
@@ -25,6 +25,10 @@
#pragma once
+#include <QList>
+#include <QSet>
+#include <QSharedPointer>
+#include <QVersionNumber>
#include <QtGlobal>
#if defined(MCUSUPPORT_LIBRARY)
@@ -32,3 +36,20 @@
#else
#define MCUSUPPORTSHARED_EXPORT Q_DECL_IMPORT
#endif
+
+namespace McuSupport::Internal {
+
+class McuTarget;
+class McuAbstractPackage;
+class McuToolChainPackage;
+
+using McuPackagePtr = QSharedPointer<McuAbstractPackage>;
+using McuToolChainPackagePtr = QSharedPointer<McuToolChainPackage>;
+using McuTargetPtr = QSharedPointer<McuTarget>;
+
+static const QVersionNumber minimalVersion{2, 0, 0};
+static const QVersionNumber newVersion{2, 3};
+using Targets = QList<McuTargetPtr>;
+using Packages = QSet<McuPackagePtr>;
+
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcusupportcmakemapper.cpp b/src/plugins/mcusupport/mcusupportcmakemapper.cpp
deleted file mode 100644
index 7f69f4f6716..00000000000
--- a/src/plugins/mcusupport/mcusupportcmakemapper.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-#include "mcusupportcmakemapper.h"
-#include "utils/namevalueitem.h"
-
-#include <utils/algorithm.h>
-
-namespace {
-static const QHash<QString, QString> &envVarToCMakeVarMapping()
-{
- static const QHash<QString, QString> mapping = {
- {"EVK_MIMXRT1060_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"EVK_MIMXRT1064_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"EVK_MIMXRT595_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"EVK_MIMXRT1170_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"EVKB_IMXRT1050_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"STM32Cube_FW_F7_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"STM32Cube_FW_F4_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"STM32Cube_FW_L4_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"STM32Cube_FW_H7_SDK_PATH", "QUL_BOARD_SDK_DIR"},
- {"RGL_DIR", "QUL_BOARD_SDK_DIR"},
- {"TVII_GRAPHICS_DRIVER_DIR", "QUL_BOARD_SDK_DIR"},
- {"EK_RA6M3G_FSP_PATH", "QUL_BOARD_SDK_DIR"},
- {"ARMGCC_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
- {"IAR_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
- {"GHS_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
- {"GHS_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
- {"EVK_MIMXRT1170_FREERTOS_PATH", "FREERTOS_DIR"},
- {"IMXRT1050_FREERTOS_DIR", "FREERTOS_DIR"},
- {"IMXRT1064_FREERTOS_DIR", "FREERTOS_DIR"},
- {"IMXRT595_FREERTOS_DIR", "FREERTOS_DIR"},
- {"STM32F7_FREERTOS_DIR", "FREERTOS_DIR"},
- {"eFlashLoad_PATH", "eFlashLoad_PATH"},
- {"RenesasFlashProgrammer_PATH", "RENESAS_FLASH_PROGRAMMER_PATH"},
- {"MCUXpressoIDE_PATH", "MCUXPRESSO_IDE_PATH"},
- {"JLINK_PATH", "JLINK_PATH"},
- {"CYPRESS_AUTO_FLASH_UTILITY_DIR", "INFINEON_AUTO_FLASH_UTILITY_DIR"},
- {"EK_RA6M3G_E2_PROJECT_PATH", "EK_RA6M3G_E2_PROJECT_PATH"},
- };
- return mapping;
-}
-} // namespace
-
-QList<CMakeProjectManager::CMakeConfigItem> McuSupport::Internal::mapEnvVarsToQul2xCmakeVars(
- const Utils::EnvironmentItems &envVars)
-{
- const auto &mapping = envVarToCMakeVarMapping();
- auto cmakeVars
- = Utils::transform(envVars, [mapping](const Utils::EnvironmentItem &envVar) {
- return CMakeProjectManager::CMakeConfigItem(mapping.value(envVar.name, "").toUtf8(),
- envVar.value.toUtf8());
- }).toList();
-
- return Utils::filtered(cmakeVars, [](const CMakeProjectManager::CMakeConfigItem &item) {
- return !item.key.isEmpty();
- });
-}
diff --git a/src/plugins/mcusupport/mcusupportcmakemapper.h b/src/plugins/mcusupport/mcusupportcmakemapper.h
deleted file mode 100644
index f5da2092def..00000000000
--- a/src/plugins/mcusupport/mcusupportcmakemapper.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-#pragma once
-
-#include "cmakeprojectmanager/cmakeconfigitem.h"
-#include "utils/environmentfwd.h"
-
-namespace McuSupport {
-namespace Internal {
-QList<CMakeProjectManager::CMakeConfigItem> mapEnvVarsToQul2xCmakeVars(
- const Utils::EnvironmentItems &envVars);
-}
-} // namespace McuSupport
diff --git a/src/plugins/mcusupport/mcusupportconstants.h b/src/plugins/mcusupport/mcusupportconstants.h
index ec46414fb7f..8c707b28495 100644
--- a/src/plugins/mcusupport/mcusupportconstants.h
+++ b/src/plugins/mcusupport/mcusupportconstants.h
@@ -28,23 +28,27 @@
namespace McuSupport {
namespace Constants {
-const char DEVICE_TYPE[] = "McuSupport.DeviceType";
-const char DEVICE_ID[] = "McuSupport.Device";
-const char RUNCONFIGURATION[] = "McuSupport.RunConfiguration";
-const char SETTINGS_ID[] = "CC.McuSupport.Configuration";
+const char DEVICE_TYPE[]{"McuSupport.DeviceType"};
+const char DEVICE_ID[]{"McuSupport.Device"};
+const char RUNCONFIGURATION[]{"McuSupport.RunConfiguration"};
+const char SETTINGS_ID[]{"CC.McuSupport.Configuration"};
-const char KIT_MCUTARGET_VENDOR_KEY[] = "McuSupport.McuTargetVendor";
-const char KIT_MCUTARGET_MODEL_KEY[] = "McuSupport.McuTargetModel";
-const char KIT_MCUTARGET_SDKVERSION_KEY[] = "McuSupport.McuTargetSdkVersion";
-const char KIT_MCUTARGET_KITVERSION_KEY[] = "McuSupport.McuTargetKitVersion";
-const char KIT_MCUTARGET_COLORDEPTH_KEY[] = "McuSupport.McuTargetColorDepth";
-const char KIT_MCUTARGET_OS_KEY[] = "McuSupport.McuTargetOs";
-const char KIT_MCUTARGET_TOOCHAIN_KEY[] = "McuSupport.McuTargetToolchain";
+const char KIT_MCUTARGET_VENDOR_KEY[]{"McuSupport.McuTargetVendor"};
+const char KIT_MCUTARGET_MODEL_KEY[]{"McuSupport.McuTargetModel"};
+const char KIT_MCUTARGET_SDKVERSION_KEY[]{"McuSupport.McuTargetSdkVersion"};
+const char KIT_MCUTARGET_KITVERSION_KEY[]{"McuSupport.McuTargetKitVersion"};
+const char KIT_MCUTARGET_COLORDEPTH_KEY[]{"McuSupport.McuTargetColorDepth"};
+const char KIT_MCUTARGET_OS_KEY[]{"McuSupport.McuTargetOs"};
+const char KIT_MCUTARGET_TOOLCHAIN_KEY[]{"McuSupport.McuTargetToolchain"};
-const char SETTINGS_GROUP[] = "McuSupport";
-const char SETTINGS_KEY_PACKAGE_PREFIX[] = "Package_";
-const char SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK[] = "QtForMCUsSdk"; // Key known by SDK installer
-const char SETTINGS_KEY_AUTOMATIC_KIT_CREATION[] = "AutomaticKitCreation";
+const char SETTINGS_GROUP[]{"McuSupport"};
+const char SETTINGS_KEY_PACKAGE_PREFIX[]{"Package_"};
+const char SETTINGS_KEY_FREERTOS_PREFIX[]{"FreeRTOSSourcePackage_"};
+const char SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK[]{"QtForMCUsSdk"}; // Key known by SDK installer
+const char SETTINGS_KEY_AUTOMATIC_KIT_CREATION[]{"AutomaticKitCreation"};
+
+const char TOOLCHAIN_DIR_CMAKE_VARIABLE[]{"QUL_TARGET_TOOLCHAIN_DIR"};
+const char TOOLCHAIN_FILE_CMAKE_VARIABLE[]{"CMAKE_TOOLCHAIN_FILE"};
} // namespace Constants
} // namespace McuSupport
diff --git a/src/plugins/mcusupport/mcusupportdevice.cpp b/src/plugins/mcusupport/mcusupportdevice.cpp
index 46fb430ac22..876bddd06fd 100644
--- a/src/plugins/mcusupport/mcusupportdevice.cpp
+++ b/src/plugins/mcusupport/mcusupportdevice.cpp
@@ -26,7 +26,6 @@
#include "mcusupportdevice.h"
#include "mcusupportconstants.h"
-#include <projectexplorer/devicesupport/deviceprocess.h>
#include <projectexplorer/runcontrol.h>
using namespace ProjectExplorer;
diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp
index df06b96767e..647f441aefa 100644
--- a/src/plugins/mcusupport/mcusupportoptions.cpp
+++ b/src/plugins/mcusupport/mcusupportoptions.cpp
@@ -25,14 +25,14 @@
#include "mcusupportoptions.h"
-#include "mcupackage.h"
-#include "mcutarget.h"
-#include "mcukitmanager.h"
#include "mcukitinformation.h"
-#include "mcusupportcmakemapper.h"
+#include "mcukitmanager.h"
+#include "mcupackage.h"
#include "mcusupportconstants.h"
-#include "mcusupportsdk.h"
#include "mcusupportplugin.h"
+#include "mcusupportsdk.h"
+#include "mcutarget.h"
+#include "settingshandler.h"
#include <cmakeprojectmanager/cmakekitinformation.h>
#include <cmakeprojectmanager/cmaketoolmanager.h>
@@ -46,37 +46,21 @@
#include <QMessageBox>
#include <QPushButton>
-using CMakeProjectManager::CMakeConfigItem;
-using CMakeProjectManager::CMakeConfigurationKitAspect;
using namespace ProjectExplorer;
using namespace Utils;
-namespace McuSupport {
-namespace Internal {
-
-void McuSdkRepository::deletePackagesAndTargets()
-{
- qDeleteAll(packages);
- packages.clear();
- qDeleteAll(mcuTargets);
- mcuTargets.clear();
-}
+namespace McuSupport::Internal {
-McuSupportOptions::McuSupportOptions(QObject *parent)
+McuSupportOptions::McuSupportOptions(const SettingsHandler::Ptr &settingsHandler, QObject *parent)
: QObject(parent)
- , qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage())
+ , qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage(settingsHandler))
+ , settingsHandler(settingsHandler)
{
- connect(qtForMCUsSdkPackage,
+ connect(qtForMCUsSdkPackage.get(),
&McuAbstractPackage::changed,
this,
&McuSupportOptions::populatePackagesAndTargets);
- m_automaticKitCreation = automaticKitCreationFromSettings();
-}
-
-McuSupportOptions::~McuSupportOptions()
-{
- deletePackagesAndTargets();
- delete qtForMCUsSdkPackage;
+ m_automaticKitCreation = settingsHandler->isAutomaticKitCreationEnabled();
}
void McuSupportOptions::populatePackagesAndTargets()
@@ -84,12 +68,12 @@ void McuSupportOptions::populatePackagesAndTargets()
setQulDir(qtForMCUsSdkPackage->path());
}
-static FilePath qulDocsDir()
+FilePath McuSupportOptions::qulDocsDir() const
{
- const FilePath qulDir = McuSupportOptions::qulDirFromSettings();
+ const FilePath qulDir = qulDirFromSettings();
if (qulDir.isEmpty() || !qulDir.exists())
return {};
- const FilePath docsDir = qulDir.pathAppended("docs");
+ const FilePath docsDir = qulDir / "docs";
return docsDir.exists() ? docsDir : FilePath();
}
@@ -114,7 +98,7 @@ void McuSupportOptions::registerExamples()
auto examples = {std::make_pair(QStringLiteral("demos"), tr("Qt for MCUs Demos")),
std::make_pair(QStringLiteral("examples"), tr("Qt for MCUs Examples"))};
for (const auto &dir : examples) {
- const FilePath examplesDir = McuSupportOptions::qulDirFromSettings().pathAppended(dir.first);
+ const FilePath examplesDir = qulDirFromSettings() / dir.first;
if (!examplesDir.exists())
continue;
@@ -126,107 +110,35 @@ void McuSupportOptions::registerExamples()
const QVersionNumber &McuSupportOptions::minimalQulVersion()
{
- static const QVersionNumber v({2, 0});
- return v;
+ return minimalVersion;
+}
+
+bool McuSupportOptions::isLegacyVersion(const QVersionNumber &version)
+{
+ return version < newVersion;
}
void McuSupportOptions::setQulDir(const FilePath &dir)
{
- deletePackagesAndTargets();
qtForMCUsSdkPackage->updateStatus();
if (qtForMCUsSdkPackage->isValidStatus())
- Sdk::targetsAndPackages(dir, &sdkRepository);
+ sdkRepository = Sdk::targetsAndPackages(dir, settingsHandler);
+ else
+ sdkRepository = McuSdkRepository{};
for (const auto &package : qAsConst(sdkRepository.packages))
- connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::packagesChanged);
+ connect(package.get(),
+ &McuAbstractPackage::changed,
+ this,
+ &McuSupportOptions::packagesChanged);
emit packagesChanged();
}
-FilePath McuSupportOptions::qulDirFromSettings()
-{
- return Sdk::packagePathFromSettings(Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK,
- QSettings::UserScope, {});
-}
-
-void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems)
-{
- const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems);
- const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key);
-
- // First filter out all Qul2.x CMake vars
- auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit),
- [&](const auto &configItem) {
- return !cmakeVarNames.contains(configItem.key);
- });
- // Then append them with new values
- config.append(cmakeVars);
- CMakeConfigurationKitAspect::setConfiguration(kit, config);
-}
-
-static bool expectsCmakeVars(const McuTarget *mcuTarget)
-{
- return mcuTarget->qulVersion() >= QVersionNumber{2, 0};
-}
-
-void McuSupportOptions::setKitEnvironment(Kit *k,
- const McuTarget *mcuTarget,
- const McuAbstractPackage *qtForMCUsSdkPackage)
+FilePath McuSupportOptions::qulDirFromSettings() const
{
- EnvironmentItems changes;
- QStringList pathAdditions;
-
- // The Desktop version depends on the Qt shared libs in Qul_DIR/bin.
- // If CMake's fileApi is avaialble, we can rely on the "Add library search path to PATH"
- // feature of the run configuration. Otherwise, we just prepend the path, here.
- if (mcuTarget->toolChainPackage()->isDesktopToolchain()
- && !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi())
- pathAdditions.append(qtForMCUsSdkPackage->path().pathAppended("bin").toUserOutput());
-
- auto processPackage = [&pathAdditions, &changes](const McuAbstractPackage *package) {
- if (package->isAddToSystemPath())
- pathAdditions.append(package->path().toUserOutput());
- if (!package->environmentVariableName().isEmpty())
- changes.append({package->environmentVariableName(), package->path().toUserOutput()});
- };
- for (auto package : mcuTarget->packages())
- processPackage(package);
- processPackage(qtForMCUsSdkPackage);
-
- if (McuSupportOptions::kitsNeedQtVersion())
- changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"});
-
- // Hack, this problem should be solved in lower layer
- if (expectsCmakeVars(mcuTarget)) {
- McuSupportOptions::remapQul2xCmakeVars(k, changes);
- }
-
- EnvironmentKitAspect::setEnvironmentChanges(k, changes);
-}
-
-void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
-{
- EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(k);
- for (auto package : mcuTarget->packages()) {
- const QString varName = package->environmentVariableName();
- if (!varName.isEmpty() && package->isValidStatus()) {
- const int index = Utils::indexOf(changes, [varName](const EnvironmentItem &item) {
- return item.name == varName;
- });
- const EnvironmentItem item = {package->environmentVariableName(),
- package->path().toUserOutput()};
- if (index != -1)
- changes.replace(index, item);
- else
- changes.append(item);
- }
- }
-
- // Hack, this problem should be solved in lower layer
- if (expectsCmakeVars(mcuTarget)) {
- remapQul2xCmakeVars(k, changes);
- }
-
- EnvironmentKitAspect::setEnvironmentChanges(k, changes);
+ return settingsHandler->getPath(Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK,
+ QSettings::UserScope,
+ {});
}
McuKitManager::UpgradeOption McuSupportOptions::askForKitUpgrades()
@@ -250,23 +162,16 @@ McuKitManager::UpgradeOption McuSupportOptions::askForKitUpgrades()
return McuKitManager::UpgradeOption::Ignore;
}
-
-void McuSupportOptions::deletePackagesAndTargets()
-{
- sdkRepository.deletePackagesAndTargets();
-}
-
-
void McuSupportOptions::checkUpgradeableKits()
{
- if (!qtForMCUsSdkPackage->isValidStatus() || sdkRepository.mcuTargets.length() == 0)
+ if (!qtForMCUsSdkPackage->isValidStatus() || sdkRepository.mcuTargets.isEmpty())
return;
- if (Utils::anyOf(sdkRepository.mcuTargets, [this](const McuTarget *target) {
- return !McuKitManager::upgradeableKits(target, this->qtForMCUsSdkPackage).empty()
- && McuKitManager::matchingKits(target, this->qtForMCUsSdkPackage).empty();
+ if (Utils::anyOf(sdkRepository.mcuTargets, [this](const McuTargetPtr &target) {
+ return !McuKitManager::upgradeableKits(target.get(), this->qtForMCUsSdkPackage).empty()
+ && McuKitManager::matchingKits(target.get(), this->qtForMCUsSdkPackage).empty();
}))
- McuKitManager::upgradeKitsByCreatingNewPackage(askForKitUpgrades());
+ McuKitManager::upgradeKitsByCreatingNewPackage(settingsHandler, askForKitUpgrades());
}
bool McuSupportOptions::kitsNeedQtVersion()
@@ -276,7 +181,6 @@ bool McuSupportOptions::kitsNeedQtVersion()
return !HostOsInfo::isWindowsHost();
}
-
bool McuSupportOptions::automaticKitCreationEnabled() const
{
return m_automaticKitCreation;
@@ -287,22 +191,4 @@ void McuSupportOptions::setAutomaticKitCreationEnabled(const bool enabled)
m_automaticKitCreation = enabled;
}
-void McuSupportOptions::writeGeneralSettings() const
-{
- const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/'
- + QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION);
- QSettings *settings = Core::ICore::settings(QSettings::UserScope);
- settings->setValue(key, m_automaticKitCreation);
-}
-
-bool McuSupportOptions::automaticKitCreationFromSettings()
-{
- QSettings *settings = Core::ICore::settings(QSettings::UserScope);
- const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/'
- + QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION);
- const bool automaticKitCreation = settings->value(key, true).toBool();
- return automaticKitCreation;
-}
-
-} // namespace Internal
-} // namespace McuSupport
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h
index 04dbb24b6ae..0900fc3e0aa 100644
--- a/src/plugins/mcusupport/mcusupportoptions.h
+++ b/src/plugins/mcusupport/mcusupportoptions.h
@@ -25,12 +25,13 @@
#pragma once
-#include <utils/environmentfwd.h>
-#include "mcusupport_global.h"
#include "mcukitmanager.h"
+#include "mcusupport_global.h"
+#include "settingshandler.h"
+
+#include <utils/environmentfwd.h>
#include <QObject>
-#include <QVector>
#include <QVersionNumber>
QT_FORWARD_DECLARE_CLASS(QWidget)
@@ -50,42 +51,34 @@ namespace McuSupport {
namespace Internal {
class McuAbstractPackage;
-class McuToolChainPackage;
-class McuTarget;
-class McuSdkRepository
+class McuSdkRepository final
{
public:
- QVector<McuAbstractPackage *> packages;
- QVector<McuTarget *> mcuTargets;
-
- void deletePackagesAndTargets();
+ Targets mcuTargets;
+ Packages packages;
};
-class McuSupportOptions : public QObject
+class McuSupportOptions final : public QObject
{
Q_OBJECT
public:
- explicit McuSupportOptions(QObject *parent = nullptr);
- ~McuSupportOptions() override;
+ explicit McuSupportOptions(const SettingsHandler::Ptr &, QObject *parent = nullptr);
- McuAbstractPackage *qtForMCUsSdkPackage = nullptr;
+ McuPackagePtr qtForMCUsSdkPackage{nullptr};
McuSdkRepository sdkRepository;
void setQulDir(const Utils::FilePath &dir);
- static void setKitEnvironment(ProjectExplorer::Kit *,
- const McuTarget *,
- const McuAbstractPackage *);
- static void updateKitEnvironment(ProjectExplorer::Kit *, const McuTarget *);
- static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &);
- static Utils::FilePath qulDirFromSettings();
+ Utils::FilePath qulDirFromSettings() const;
+ Utils::FilePath qulDocsDir() const;
static McuKitManager::UpgradeOption askForKitUpgrades();
- static void registerQchFiles();
- static void registerExamples();
+ void registerQchFiles();
+ void registerExamples();
static const QVersionNumber &minimalQulVersion();
+ static bool isLegacyVersion(const QVersionNumber &version);
void checkUpgradeableKits();
void populatePackagesAndTargets();
@@ -94,16 +87,14 @@ public:
bool automaticKitCreationEnabled() const;
void setAutomaticKitCreationEnabled(const bool enabled);
- void writeGeneralSettings() const;
- static bool automaticKitCreationFromSettings();
+
private:
- void deletePackagesAndTargets();
+ SettingsHandler::Ptr settingsHandler;
bool m_automaticKitCreation = true;
signals:
void packagesChanged();
};
-
} // namespace Internal
} // namespace McuSupport
diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp
index 2b96f02ce74..386de01d286 100644
--- a/src/plugins/mcusupport/mcusupportoptionspage.cpp
+++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp
@@ -24,12 +24,13 @@
****************************************************************************/
#include "mcusupportoptionspage.h"
+#include "mcukitmanager.h"
#include "mcupackage.h"
-#include "mcutarget.h"
#include "mcusupportconstants.h"
#include "mcusupportoptions.h"
#include "mcusupportsdk.h"
-#include "mcukitmanager.h"
+#include "mcutarget.h"
+#include "settingshandler.h"
#include <cmakeprojectmanager/cmakeprojectconstants.h>
#include <cmakeprojectmanager/cmaketoolmanager.h>
@@ -51,19 +52,18 @@
#include <QPushButton>
#include <QVBoxLayout>
-namespace McuSupport {
-namespace Internal {
+namespace McuSupport::Internal {
class McuSupportOptionsWidget : public Core::IOptionsPageWidget
{
Q_DECLARE_TR_FUNCTIONS(McuSupport::Internal::McuSupportOptionsWidget)
public:
- McuSupportOptionsWidget();
+ McuSupportOptionsWidget(McuSupportOptions &, const SettingsHandler::Ptr &);
void updateStatus();
void showMcuTargetPackages();
- McuTarget *currentMcuTarget() const;
+ McuTargetPtr currentMcuTarget() const;
private:
void apply() final;
@@ -72,9 +72,10 @@ private:
void showEvent(QShowEvent *event) final;
QString m_armGccPath;
- McuSupportOptions m_options;
- QMap<McuPackage *, QWidget *> m_packageWidgets;
- QMap<McuTarget *, QWidget *> m_mcuTargetPacketWidgets;
+ McuSupportOptions &m_options;
+ SettingsHandler::Ptr m_settingsHandler;
+ QMap<McuPackagePtr, QWidget *> m_packageWidgets;
+ QMap<McuTargetPtr, QWidget *> m_mcuTargetPacketWidgets;
QFormLayout *m_packagesLayout = nullptr;
QGroupBox *m_qtForMCUsSdkGroupBox = nullptr;
QGroupBox *m_packagesGroupBox = nullptr;
@@ -89,7 +90,10 @@ private:
QPushButton *m_kitUpdatePushButton = nullptr;
};
-McuSupportOptionsWidget::McuSupportOptionsWidget()
+McuSupportOptionsWidget::McuSupportOptionsWidget(McuSupportOptions &options,
+ const SettingsHandler::Ptr &settingsHandler)
+ : m_options{options}
+ , m_settingsHandler(settingsHandler)
{
auto mainLayout = new QVBoxLayout(this);
@@ -123,7 +127,7 @@ McuSupportOptionsWidget::McuSupportOptionsWidget()
&QComboBox::currentTextChanged,
this,
&McuSupportOptionsWidget::showMcuTargetPackages);
- connect(m_options.qtForMCUsSdkPackage,
+ connect(m_options.qtForMCUsSdkPackage.get(),
&McuAbstractPackage::changed,
this,
&McuSupportOptionsWidget::populateMcuTargetsComboBox);
@@ -146,8 +150,7 @@ McuSupportOptionsWidget::McuSupportOptionsWidget()
m_kitAutomaticCreationCheckBox = new QCheckBox(
tr("Automatically create kits for all available targets on start"));
connect(m_kitAutomaticCreationCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
- m_options.setAutomaticKitCreationEnabled(
- state == Qt::CheckState::Checked);
+ m_options.setAutomaticKitCreationEnabled(state == Qt::CheckState::Checked);
});
mainLayout->addWidget(m_kitAutomaticCreationCheckBox);
}
@@ -162,15 +165,18 @@ McuSupportOptionsWidget::McuSupportOptionsWidget()
m_kitCreationPushButton = new QPushButton(tr("Create Kit"));
m_kitCreationPushButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
connect(m_kitCreationPushButton, &QPushButton::clicked, this, [this] {
- McuKitManager::newKit(currentMcuTarget(), m_options.qtForMCUsSdkPackage);
- McuSupportOptions::registerQchFiles();
+ McuKitManager::newKit(currentMcuTarget().get(), m_options.qtForMCUsSdkPackage);
+ m_options.registerQchFiles();
updateStatus();
});
m_kitUpdatePushButton = new QPushButton(tr("Update Kit"));
m_kitUpdatePushButton->setSizePolicy(m_kitCreationPushButton->sizePolicy());
connect(m_kitUpdatePushButton, &QPushButton::clicked, this, [this] {
- for (auto kit: McuKitManager::upgradeableKits(currentMcuTarget(), m_options.qtForMCUsSdkPackage))
- McuKitManager::upgradeKitInPlace(kit, currentMcuTarget(), m_options.qtForMCUsSdkPackage);
+ for (auto kit : McuKitManager::upgradeableKits(currentMcuTarget().get(),
+ m_options.qtForMCUsSdkPackage))
+ McuKitManager::upgradeKitInPlace(kit,
+ currentMcuTarget().get(),
+ m_options.qtForMCUsSdkPackage);
updateStatus();
});
vLayout->addWidget(m_kitCreationPushButton);
@@ -189,7 +195,7 @@ McuSupportOptionsWidget::McuSupportOptionsWidget()
void McuSupportOptionsWidget::updateStatus()
{
- const McuTarget *mcuTarget = currentMcuTarget();
+ const McuTargetPtr mcuTarget = currentMcuTarget();
const bool cMakeAvailable = !CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty();
@@ -220,11 +226,13 @@ void McuSupportOptionsWidget::updateStatus()
m_kitCreationPushButton->setVisible(mcuTargetValid);
m_kitUpdatePushButton->setVisible(mcuTargetValid);
if (mcuTargetValid) {
- const bool hasMatchingKits = !McuKitManager::matchingKits(
- mcuTarget, m_options.qtForMCUsSdkPackage).isEmpty();
- const bool hasUpgradeableKits = !hasMatchingKits &&
- !McuKitManager::upgradeableKits(
- mcuTarget, m_options.qtForMCUsSdkPackage).isEmpty();
+ const bool hasMatchingKits = !McuKitManager::matchingKits(mcuTarget.get(),
+ m_options.qtForMCUsSdkPackage)
+ .isEmpty();
+ const bool hasUpgradeableKits
+ = !hasMatchingKits
+ && !McuKitManager::upgradeableKits(mcuTarget.get(), m_options.qtForMCUsSdkPackage)
+ .isEmpty();
m_kitCreationPushButton->setEnabled(!hasMatchingKits);
m_kitUpdatePushButton->setEnabled(hasUpgradeableKits);
@@ -260,7 +268,7 @@ void McuSupportOptionsWidget::updateStatus()
void McuSupportOptionsWidget::showMcuTargetPackages()
{
- const McuTarget *mcuTarget = currentMcuTarget();
+ McuTargetPtr mcuTarget = currentMcuTarget();
if (!mcuTarget)
return;
@@ -270,9 +278,9 @@ void McuSupportOptionsWidget::showMcuTargetPackages()
row.fieldItem->widget()->hide();
}
- for (auto package : qAsConst(m_options.sdkRepository.packages)) {
+ for (const auto &package : qAsConst(m_options.sdkRepository.packages)) {
QWidget *packageWidget = package->widget();
- if (!mcuTarget->packages().contains(package))
+ if (!mcuTarget->packages().contains(package) || package->label().isEmpty())
continue;
m_packagesLayout->addRow(package->label(), packageWidget);
packageWidget->show();
@@ -281,12 +289,14 @@ void McuSupportOptionsWidget::showMcuTargetPackages()
updateStatus();
}
-McuTarget *McuSupportOptionsWidget::currentMcuTarget() const
+McuTargetPtr McuSupportOptionsWidget::currentMcuTarget() const
{
const int mcuTargetIndex = m_mcuTargetsComboBox->currentIndex();
- return (mcuTargetIndex == -1 || m_options.sdkRepository.mcuTargets.isEmpty())
- ? nullptr
- : m_options.sdkRepository.mcuTargets.at(mcuTargetIndex);
+ McuTargetPtr target{nullptr};
+ if (mcuTargetIndex != -1 && !m_options.sdkRepository.mcuTargets.isEmpty())
+ target = m_options.sdkRepository.mcuTargets.at(mcuTargetIndex);
+
+ return target;
}
void McuSupportOptionsWidget::showEvent(QShowEvent *event)
@@ -299,14 +309,14 @@ void McuSupportOptionsWidget::apply()
{
bool pathsChanged = false;
- m_options.writeGeneralSettings();
+ m_settingsHandler->setAutomaticKitCreation(m_options.automaticKitCreationEnabled());
pathsChanged |= m_options.qtForMCUsSdkPackage->writeToSettings();
for (auto package : qAsConst(m_options.sdkRepository.packages))
pathsChanged |= package->writeToSettings();
if (pathsChanged) {
m_options.checkUpgradeableKits();
- McuKitManager::fixKitsDependencies();
+ McuKitManager::updatePathsInExistingKits(m_settingsHandler);
}
}
@@ -315,19 +325,21 @@ void McuSupportOptionsWidget::populateMcuTargetsComboBox()
m_options.populatePackagesAndTargets();
m_mcuTargetsComboBox->clear();
m_mcuTargetsComboBox->addItems(
- Utils::transform<QStringList>(m_options.sdkRepository.mcuTargets, [](McuTarget *t) {
- return McuKitManager::kitName(t);
+ Utils::transform<QStringList>(m_options.sdkRepository.mcuTargets, [](const McuTargetPtr &t) {
+ return McuKitManager::generateKitNameFromTarget(t.get());
}));
updateStatus();
}
-McuSupportOptionsPage::McuSupportOptionsPage()
+McuSupportOptionsPage::McuSupportOptionsPage(McuSupportOptions &options,
+ const SettingsHandler::Ptr &settingsHandler)
{
setId(Utils::Id(Constants::SETTINGS_ID));
setDisplayName(McuSupportOptionsWidget::tr("MCU"));
setCategory(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY);
- setWidgetCreator([] { return new McuSupportOptionsWidget; });
+ setWidgetCreator([&options, &settingsHandler] {
+ return new McuSupportOptionsWidget(options, settingsHandler);
+ });
}
-} // namespace Internal
-} // namespace McuSupport
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcusupportoptionspage.h b/src/plugins/mcusupport/mcusupportoptionspage.h
index c7b2db6150c..442414119ed 100644
--- a/src/plugins/mcusupport/mcusupportoptionspage.h
+++ b/src/plugins/mcusupport/mcusupportoptionspage.h
@@ -25,15 +25,19 @@
#pragma once
+#include "settingshandler.h"
+
#include <coreplugin/dialogs/ioptionspage.h>
namespace McuSupport {
namespace Internal {
+class McuSupportOptions;
+
class McuSupportOptionsPage final : public Core::IOptionsPage
{
public:
- McuSupportOptionsPage();
+ McuSupportOptionsPage(McuSupportOptions &, const SettingsHandler::Ptr &);
};
} // namespace Internal
diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp
index f0778b04b24..903999a210c 100644
--- a/src/plugins/mcusupport/mcusupportplugin.cpp
+++ b/src/plugins/mcusupport/mcusupportplugin.cpp
@@ -25,10 +25,10 @@
#include "mcusupportplugin.h"
#include "mcukitinformation.h"
+#include "mcukitmanager.h"
#include "mcusupportconstants.h"
#include "mcusupportdevice.h"
#include "mcusupportoptions.h"
-#include "mcukitmanager.h"
#include "mcusupportoptionspage.h"
#include "mcusupportrunconfiguration.h"
@@ -44,6 +44,7 @@
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
#include <projectexplorer/kitmanager.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <utils/infobar.h>
@@ -52,6 +53,10 @@
using namespace Core;
using namespace ProjectExplorer;
+namespace {
+constexpr char setupMcuSupportKits[]{"SetupMcuSupportKits"};
+}
+
namespace McuSupport {
namespace Internal {
@@ -73,7 +78,9 @@ public:
RunWorkerFactory runWorkerFactory{makeFlashAndRunWorker(),
{ProjectExplorer::Constants::NORMAL_RUN_MODE},
{Constants::RUNCONFIGURATION}};
- McuSupportOptionsPage optionsPage;
+ SettingsHandler::Ptr m_settingsHandler{new SettingsHandler};
+ McuSupportOptions m_options{m_settingsHandler};
+ McuSupportOptionsPage optionsPage{m_options, m_settingsHandler};
McuDependenciesKitAspect environmentPathsKitAspect;
}; // class McuSupportPluginPrivate
@@ -93,8 +100,8 @@ bool McuSupportPlugin::initialize(const QStringList &arguments, QString *errorSt
setObjectName("McuSupportPlugin");
dd = new McuSupportPluginPrivate;
- McuSupportOptions::registerQchFiles();
- McuSupportOptions::registerExamples();
+ dd->m_options.registerQchFiles();
+ dd->m_options.registerExamples();
ProjectExplorer::JsonWizardFactory::addWizardPath(":/mcusupport/wizards/");
return true;
@@ -104,35 +111,34 @@ void McuSupportPlugin::extensionsInitialized()
{
ProjectExplorer::DeviceManager::instance()->addDevice(McuSupportDevice::create());
- connect(KitManager::instance(), &KitManager::kitsLoaded, []() {
+ connect(KitManager::instance(), &KitManager::kitsLoaded, [this]() {
McuKitManager::removeOutdatedKits();
- McuKitManager::createAutomaticKits();
- McuKitManager::fixExistingKits();
- McuSupportPlugin::askUserAboutMcuSupportKitsSetup();
+ McuKitManager::createAutomaticKits(dd->m_settingsHandler);
+ McuKitManager::fixExistingKits(dd->m_settingsHandler);
+ askUserAboutMcuSupportKitsSetup();
});
}
void McuSupportPlugin::askUserAboutMcuSupportKitsSetup()
{
- const char setupMcuSupportKits[] = "SetupMcuSupportKits";
-
if (!ICore::infoBar()->canInfoBeAdded(setupMcuSupportKits)
- || McuSupportOptions::qulDirFromSettings().isEmpty()
+ || dd->m_options.qulDirFromSettings().isEmpty()
|| !McuKitManager::existingKits(nullptr).isEmpty())
return;
Utils::InfoBarEntry info(setupMcuSupportKits,
tr("Create Kits for Qt for MCUs? "
- "To do it later, select Options > Devices > MCU."),
+ "To do it later, select Edit > Preferences > Devices > MCU."),
Utils::InfoBarEntry::GlobalSuppression::Enabled);
- info.addCustomButton(tr("Create Kits for Qt for MCUs"), [setupMcuSupportKits] {
+ // clazy:excludeall=connect-3arg-lambda
+ info.addCustomButton(tr("Create Kits for Qt for MCUs"), [] {
ICore::infoBar()->removeInfo(setupMcuSupportKits);
QTimer::singleShot(0, []() { ICore::showOptionsDialog(Constants::SETTINGS_ID); });
});
ICore::infoBar()->addInfo(info);
}
-void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade()
+void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(const SettingsHandler::Ptr &settingsHandler)
{
const char upgradeMcuSupportKits[] = "UpgradeMcuSupportKits";
@@ -142,18 +148,21 @@ void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade()
Utils::InfoBarEntry info(upgradeMcuSupportKits,
tr("New version of Qt for MCUs detected. Upgrade existing Kits?"),
Utils::InfoBarEntry::GlobalSuppression::Enabled);
- static McuKitManager::UpgradeOption selectedOption = McuKitManager::UpgradeOption::Keep;
+ using McuKitManager::UpgradeOption;
+ static UpgradeOption selectedOption = UpgradeOption::Keep;
+
+ const QList<Utils::InfoBarEntry::ComboInfo> infos
+ = {{tr("Create new kits"), QVariant::fromValue(UpgradeOption::Keep)},
+ {tr("Replace existing kits"), QVariant::fromValue(UpgradeOption::Replace)}};
- const QStringList options = { tr("Create new kits"), tr("Replace existing kits") };
- info.setComboInfo(options, [options](const QString &selected) {
- selectedOption = options.indexOf(selected) == 0 ? McuKitManager::UpgradeOption::Keep
- : McuKitManager::UpgradeOption::Replace;
+ info.setComboInfo(infos, [](const Utils::InfoBarEntry::ComboInfo &selected) {
+ selectedOption = selected.data.value<UpgradeOption>();
});
- info.addCustomButton(tr("Proceed"), [upgradeMcuSupportKits] {
+ info.addCustomButton(tr("Proceed"), [upgradeMcuSupportKits, settingsHandler] {
ICore::infoBar()->removeInfo(upgradeMcuSupportKits);
- QTimer::singleShot(0, []() {
- McuKitManager::upgradeKitsByCreatingNewPackage(selectedOption);
+ QTimer::singleShot(0, [settingsHandler]() {
+ McuKitManager::upgradeKitsByCreatingNewPackage(settingsHandler, selectedOption);
});
});
diff --git a/src/plugins/mcusupport/mcusupportplugin.h b/src/plugins/mcusupport/mcusupportplugin.h
index 21767a02f07..18195e6c05f 100644
--- a/src/plugins/mcusupport/mcusupportplugin.h
+++ b/src/plugins/mcusupport/mcusupportplugin.h
@@ -26,6 +26,7 @@
#pragma once
#include "mcusupport_global.h"
+#include "settingshandler.h"
#include <extensionsystem/iplugin.h>
@@ -44,8 +45,8 @@ public:
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final;
- static void askUserAboutMcuSupportKitsSetup();
- static void askUserAboutMcuSupportKitsUpgrade();
+ void askUserAboutMcuSupportKitsSetup();
+ static void askUserAboutMcuSupportKitsUpgrade(const SettingsHandler::Ptr &settingsHandler);
private:
QVector<QObject *> createTestObjects() const final;
diff --git a/src/plugins/mcusupport/mcusupportrunconfiguration.cpp b/src/plugins/mcusupport/mcusupportrunconfiguration.cpp
index 361fb09b899..2fe3f8b18d1 100644
--- a/src/plugins/mcusupport/mcusupportrunconfiguration.cpp
+++ b/src/plugins/mcusupport/mcusupportrunconfiguration.cpp
@@ -27,10 +27,7 @@
#include "mcusupportconstants.h"
#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/devicesupport/devicemanager.h>
-#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/project.h>
-#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <cmakeprojectmanager/cmakekitinformation.h>
@@ -91,15 +88,12 @@ public:
FlashAndRunWorker(RunControl *runControl)
: SimpleTargetRunner(runControl)
{
- setStarter([this, runControl] {
+ setStartModifier([this, runControl] {
const Target *target = runControl->target();
- Runnable r;
- r.command = {cmakeFilePath(target),
- runControl->runConfiguration()->aspect<StringAspect>()->value(),
- CommandLine::Raw};
- r.workingDirectory = target->activeBuildConfiguration()->buildDirectory();
- r.environment = target->activeBuildConfiguration()->environment();
- SimpleTargetRunner::doStart(r, {});
+ setCommandLine({cmakeFilePath(target), runControl->aspect<StringAspect>()->value,
+ CommandLine::Raw});
+ setWorkingDirectory(target->activeBuildConfiguration()->buildDirectory());
+ setEnvironment(target->activeBuildConfiguration()->environment());
});
}
};
diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp
index b32af50e5c7..b5ef907d8fe 100644
--- a/src/plugins/mcusupport/mcusupportsdk.cpp
+++ b/src/plugins/mcusupport/mcusupportsdk.cpp
@@ -24,14 +24,18 @@
****************************************************************************/
#include "mcusupportsdk.h"
+#include "mcuhelpers.h"
+#include "mcukitmanager.h"
+#include "mculegacyconstants.h"
#include "mcupackage.h"
-#include "mcutarget.h"
#include "mcusupportconstants.h"
#include "mcusupportoptions.h"
-#include "mcukitmanager.h"
+#include "mcusupportplugin.h"
#include "mcusupportversiondetection.h"
+#include "mcutarget.h"
#include "mcutargetdescription.h"
-#include "mcusupportplugin.h"
+#include "mcutargetfactory.h"
+#include "mcutargetfactorylegacy.h"
#include <baremetal/baremetalconstants.h>
#include <coreplugin/icore.h>
@@ -49,12 +53,18 @@
#include <QJsonObject>
#include <QVariant>
+#include <memory>
+
using namespace Utils;
namespace McuSupport {
namespace Internal {
namespace Sdk {
+namespace {
+const char CMAKE_ENTRIES[]{"cmakeEntries"};
+} // namespace
+
static FilePath findInProgramFiles(const QString &folder)
{
for (auto envVar : {"ProgramFiles", "ProgramFiles(x86)", "ProgramW6432"}) {
@@ -67,31 +77,143 @@ static FilePath findInProgramFiles(const QString &folder)
return {};
}
-McuPackage *createQtForMCUsPackage()
+McuPackagePtr createQtForMCUsPackage(const SettingsHandler::Ptr &settingsHandler)
{
- return new McuPackage(McuPackage::tr("Qt for MCUs SDK"),
- FileUtils::homePath(), // defaultPath
- FilePath("bin/qmltocpp").withExecutableSuffix(), // detectionPath
- Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK, // settingsKey
- QStringLiteral("Qul_DIR")); // envVarName
+ return McuPackagePtr{
+ new McuPackage(settingsHandler,
+ McuPackage::tr("Qt for MCUs SDK"),
+ FileUtils::homePath(), // defaultPath
+ FilePath("bin/qmltocpp").withExecutableSuffix(), // detectionPath
+ Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK, // settingsKey
+ QStringLiteral("Qul_ROOT"), // cmakeVarName
+ QStringLiteral("Qul_DIR"))}; // envVarName
}
-static McuToolChainPackage *createMsvcToolChainPackage()
+static McuPackageVersionDetector *generatePackageVersionDetector(const QString &envVar)
{
- return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::ToolChainType::MSVC);
+ if (envVar.startsWith("EVK"))
+ return new McuPackageXmlVersionDetector("*_manifest_*.xml", "ksdk", "version", ".*");
+
+ if (envVar.startsWith("STM32"))
+ return new McuPackageXmlVersionDetector("package.xml",
+ "PackDescription",
+ "Release",
+ R"(\b(\d+\.\d+\.\d+)\b)");
+
+ if (envVar.startsWith("RGL"))
+ return new McuPackageDirectoryVersionDetector("rgl_*_obj_*", R"(\d+\.\d+\.\w+)", false);
+
+ return nullptr;
}
-static McuToolChainPackage *createGccToolChainPackage()
+/// Create the McuPackage by checking the "boardSdk" property in the JSON file for the board.
+/// The name of the environment variable pointing to the the SDK for the board will be defined in the "envVar" property
+/// inside the "boardSdk".
+McuPackagePtr createBoardSdkPackage(const SettingsHandler::Ptr &settingsHandler,
+ const McuTargetDescription &desc)
{
- return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::ToolChainType::GCC);
+ const auto generateSdkName = [](const QString &envVar) {
+ qsizetype postfixPos = envVar.indexOf("_SDK_PATH");
+ if (postfixPos < 0) {
+ postfixPos = envVar.indexOf("_DIR");
+ }
+ const QString sdkName = postfixPos > 0 ? envVar.left(postfixPos) : envVar;
+ return QString{"MCU SDK (%1)"}.arg(sdkName);
+ };
+ const QString sdkName = desc.boardSdk.name.isEmpty() ? generateSdkName(desc.boardSdk.envVar)
+ : desc.boardSdk.name;
+
+ const FilePath defaultPath = [&] {
+ const auto envVar = desc.boardSdk.envVar.toLatin1();
+ if (qEnvironmentVariableIsSet(envVar))
+ return FilePath::fromUserInput(qEnvironmentVariable(envVar));
+ if (!desc.boardSdk.defaultPath.isEmpty()) {
+ FilePath defaultPath = FilePath::fromUserInput(QDir::rootPath()
+ + desc.boardSdk.defaultPath.toString());
+ if (defaultPath.exists())
+ return defaultPath;
+ }
+ return FilePath();
+ }();
+
+ const auto versionDetector = generatePackageVersionDetector(desc.boardSdk.envVar);
+
+ return McuPackagePtr{new McuPackage(settingsHandler,
+ sdkName,
+ defaultPath,
+ {}, // detection path
+ desc.boardSdk.envVar, // settings key
+ "QUL_BOARD_SDK_DIR", // cmake var
+ desc.boardSdk.envVar, // env var
+ {}, // download URL
+ versionDetector)};
}
-static McuToolChainPackage *createUnsupportedToolChainPackage()
+McuPackagePtr createFreeRTOSSourcesPackage(const SettingsHandler::Ptr &settingsHandler,
+ const QString &envVar,
+ const FilePath &boardSdkDir,
+ const FilePath &freeRTOSBoardSdkSubDir)
{
- return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::ToolChainType::Unsupported);
+ const QString envVarPrefix = removeRtosSuffix(envVar);
+
+ FilePath defaultPath;
+ if (qEnvironmentVariableIsSet(envVar.toLatin1()))
+ defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar.toLatin1()));
+ else if (!boardSdkDir.isEmpty() && !freeRTOSBoardSdkSubDir.isEmpty())
+ defaultPath = boardSdkDir / freeRTOSBoardSdkSubDir.toString();
+
+ return McuPackagePtr{
+ new McuPackage(settingsHandler,
+ QString::fromLatin1("FreeRTOS Sources (%1)").arg(envVarPrefix),
+ defaultPath,
+ {}, // detection path
+ QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}.append(envVarPrefix),
+ "FREERTOS_DIR", // cmake var
+ envVar, // env var
+ "https://freertos.org")}; // download url
}
-static McuToolChainPackage *createArmGccPackage()
+McuPackagePtr createUnsupportedToolChainFilePackage(const SettingsHandler::Ptr &settingsHandler,
+ const FilePath &qtForMCUSdkPath)
+{
+ const FilePath toolchainFilePath = qtForMCUSdkPath / Constants::QUL_TOOLCHAIN_CMAKE_DIR
+ / "unsupported.cmake";
+ return McuPackagePtr{new McuPackage(settingsHandler,
+ {},
+ toolchainFilePath,
+ {},
+ {},
+ Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE,
+ {})};
+}
+
+McuToolChainPackagePtr createUnsupportedToolChainPackage(const SettingsHandler::Ptr &settingsHandler)
+{
+ return McuToolChainPackagePtr{new McuToolChainPackage(
+ settingsHandler, {}, {}, {}, {}, McuToolChainPackage::ToolChainType::Unsupported)};
+}
+
+McuToolChainPackagePtr createMsvcToolChainPackage(const SettingsHandler::Ptr &settingsHandler)
+{
+ return McuToolChainPackagePtr{new McuToolChainPackage(settingsHandler,
+ {},
+ {},
+ {},
+ {},
+ McuToolChainPackage::ToolChainType::MSVC)};
+}
+
+McuToolChainPackagePtr createGccToolChainPackage(const SettingsHandler::Ptr &settingsHandler)
+{
+ return McuToolChainPackagePtr{new McuToolChainPackage(settingsHandler,
+ {},
+ {},
+ {},
+ {},
+ McuToolChainPackage::ToolChainType::GCC)};
+}
+
+McuToolChainPackagePtr createArmGccToolchainPackage(const SettingsHandler::Ptr &settingsHandler)
{
const char envVar[] = "ARMGCC_DIR";
@@ -115,16 +237,19 @@ static McuToolChainPackage *createArmGccPackage()
{"--version"},
"\\b(\\d+\\.\\d+\\.\\d+)\\b");
- return new McuToolChainPackage(McuPackage::tr("GNU Arm Embedded Toolchain"),
- defaultPath,
- detectionPath,
- "GNUArmEmbeddedToolchain", // settingsKey
- McuToolChainPackage::ToolChainType::ArmGcc,
- envVar,
- versionDetector);
+ return McuToolChainPackagePtr{
+ new McuToolChainPackage(settingsHandler,
+ McuPackage::tr("GNU Arm Embedded Toolchain"),
+ defaultPath,
+ detectionPath,
+ "GNUArmEmbeddedToolchain", // settingsKey
+ McuToolChainPackage::ToolChainType::ArmGcc, // toolchainType
+ Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE, // cmake var
+ envVar, // env var
+ versionDetector)};
}
-static McuToolChainPackage *createGhsToolchainPackage()
+McuToolChainPackagePtr createGhsToolchainPackage(const SettingsHandler::Ptr &settingsHandler)
{
const char envVar[] = "GHS_COMPILER_DIR";
@@ -135,16 +260,19 @@ static McuToolChainPackage *createGhsToolchainPackage()
{"-V"},
"\\bv(\\d+\\.\\d+\\.\\d+)\\b");
- return new McuToolChainPackage("Green Hills Compiler",
- defaultPath,
- FilePath("ccv850").withExecutableSuffix(), // detectionPath
- "GHSToolchain", // settingsKey
- McuToolChainPackage::ToolChainType::GHS,
- envVar,
- versionDetector);
+ return McuToolChainPackagePtr{
+ new McuToolChainPackage(settingsHandler,
+ "Green Hills Compiler",
+ defaultPath,
+ FilePath("ccv850").withExecutableSuffix(), // detectionPath
+ "GHSToolchain", // settingsKey
+ McuToolChainPackage::ToolChainType::GHS, // toolchainType
+ Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE, // cmake var
+ envVar, // env var
+ versionDetector)};
}
-static McuToolChainPackage *createGhsArmToolchainPackage()
+McuToolChainPackagePtr createGhsArmToolchainPackage(const SettingsHandler::Ptr &settingsHandler)
{
const char envVar[] = "GHS_ARM_COMPILER_DIR";
@@ -155,16 +283,19 @@ static McuToolChainPackage *createGhsArmToolchainPackage()
{"-V"},
"\\bv(\\d+\\.\\d+\\.\\d+)\\b");
- return new McuToolChainPackage("Green Hills Compiler for ARM",
- defaultPath,
- FilePath("cxarm").withExecutableSuffix(), // detectionPath
- "GHSArmToolchain", // settingsKey
- McuToolChainPackage::ToolChainType::GHSArm,
- envVar,
- versionDetector);
+ return McuToolChainPackagePtr{
+ new McuToolChainPackage(settingsHandler,
+ "Green Hills Compiler for ARM",
+ defaultPath,
+ FilePath("cxarm").withExecutableSuffix(), // detectionPath
+ "GHSArmToolchain", // settingsKey
+ McuToolChainPackage::ToolChainType::GHSArm, // toolchainType
+ Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE, // cmake var
+ envVar, // env var
+ versionDetector)};
}
-static McuToolChainPackage *createIarToolChainPackage()
+McuToolChainPackagePtr createIarToolChainPackage(const SettingsHandler::Ptr &settingsHandler)
{
const char envVar[] = "IAR_ARM_COMPILER_DIR";
@@ -188,42 +319,19 @@ static McuToolChainPackage *createIarToolChainPackage()
{"--version"},
"\\bV(\\d+\\.\\d+\\.\\d+)\\.\\d+\\b");
- return new McuToolChainPackage("IAR ARM Compiler",
- defaultPath,
- detectionPath,
- "IARToolchain", // settings key
- McuToolChainPackage::ToolChainType::IAR,
- envVar,
- versionDetector);
-}
-
-static McuPackage *createRGLPackage()
-{
- const char envVar[] = "RGL_DIR";
-
- FilePath defaultPath;
- if (qEnvironmentVariableIsSet(envVar)) {
- defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
- } else if (Utils::HostOsInfo::isWindowsHost()) {
- const FilePath rglPath = FilePath::fromString(QDir::rootPath())
- / "Renesas_Electronics/D1x_RGL";
- if (rglPath.exists()) {
- defaultPath = rglPath;
- const FilePaths subDirs = defaultPath.dirEntries(
- {{"rgl_ghs_D1Mx_*"}, QDir::Dirs | QDir::NoDotAndDotDot});
- if (subDirs.count() == 1)
- defaultPath = subDirs.first();
- }
- }
-
- return new McuPackage("Renesas Graphics Library",
- defaultPath,
- {}, // detection path
- "RGL",
- envVar);
+ return McuToolChainPackagePtr{
+ new McuToolChainPackage(settingsHandler,
+ "IAR ARM Compiler",
+ defaultPath,
+ detectionPath,
+ "IARToolchain", // settings key
+ McuToolChainPackage::ToolChainType::IAR, // toolchainType
+ Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE, // cmake var
+ envVar, // env var
+ versionDetector)};
}
-static McuPackage *createStm32CubeProgrammerPackage()
+static McuPackagePtr createStm32CubeProgrammerPackage(const SettingsHandler::Ptr &settingsHandler)
{
FilePath defaultPath;
const QString cubePath = "STMicroelectronics/STM32Cube/STM32CubeProgrammer";
@@ -237,27 +345,26 @@ static McuPackage *createStm32CubeProgrammerPackage()
defaultPath = programPath;
}
- const FilePath detectionPath = FilePath::fromString(
- QLatin1String(Utils::HostOsInfo::isWindowsHost()
- ? "/bin/STM32_Programmer_CLI.exe"
- : "/bin/STM32_Programmer.sh")
- );
-
- auto result
- = new McuPackage(McuPackage::tr("STM32CubeProgrammer"),
- defaultPath,
- detectionPath,
- "Stm32CubeProgrammer",
- {}, // env var
- "https://www.st.com/en/development-tools/stm32cubeprog.html", // download url
- nullptr, // version detector
- true, // add to path
- "/bin" // relative path modifier
- );
- return result;
+ const FilePath detectionPath = FilePath::fromString(
+ QLatin1String(Utils::HostOsInfo::isWindowsHost() ? "/bin/STM32_Programmer_CLI.exe"
+ : "/bin/STM32_Programmer.sh"));
+
+ return McuPackagePtr{
+ new McuPackage(settingsHandler,
+ McuPackage::tr("STM32CubeProgrammer"),
+ defaultPath,
+ detectionPath,
+ "Stm32CubeProgrammer",
+ {}, // cmake var
+ {}, // env var
+ "https://www.st.com/en/development-tools/stm32cubeprog.html", // download url
+ nullptr, // version detector
+ true, // add to path
+ "/bin" // relative path modifier
+ )};
}
-static McuPackage *createMcuXpressoIdePackage()
+static McuPackagePtr createMcuXpressoIdePackage(const SettingsHandler::Ptr &settingsHandler)
{
const char envVar[] = "MCUXpressoIDE_PATH";
@@ -280,15 +387,18 @@ static McuPackage *createMcuXpressoIdePackage()
defaultPath = programPath;
}
- return new McuPackage("MCUXpresso IDE",
- defaultPath,
- FilePath("ide/binaries/crt_emu_cm_redlink").withExecutableSuffix(), // detection path
- "MCUXpressoIDE", // settings key
- envVar,
- "https://www.nxp.com/mcuxpresso/ide"); // download url
+ return McuPackagePtr{new McuPackage(settingsHandler,
+ "MCUXpresso IDE",
+ defaultPath,
+ FilePath("ide/binaries/crt_emu_cm_redlink")
+ .withExecutableSuffix(), // detection path
+ "MCUXpressoIDE", // settings key
+ "MCUXPRESSO_IDE_PATH", // cmake var
+ envVar,
+ "https://www.nxp.com/mcuxpresso/ide")}; // download url
}
-static McuPackage *createCypressProgrammerPackage()
+static McuPackagePtr createCypressProgrammerPackage(const SettingsHandler::Ptr &settingsHandler)
{
const char envVar[] = "CYPRESS_AUTO_FLASH_UTILITY_DIR";
@@ -306,17 +416,18 @@ static McuPackage *createCypressProgrammerPackage()
}
}
- auto result = new McuPackage("Cypress Auto Flash Utility",
- defaultPath,
- FilePath("/bin/openocd").withExecutableSuffix(),
- "CypressAutoFlashUtil",
- envVar);
- return result;
+ return McuPackagePtr{new McuPackage(settingsHandler,
+ "Cypress Auto Flash Utility",
+ defaultPath,
+ FilePath("/bin/openocd").withExecutableSuffix(),
+ "CypressAutoFlashUtil", // settings key
+ "INFINEON_AUTO_FLASH_UTILITY_DIR", // cmake var
+ envVar)}; // env var
}
-static McuPackage *createRenesasProgrammerPackage()
+static McuPackagePtr createRenesasProgrammerPackage(const SettingsHandler::Ptr &settingsHandler)
{
- const char envVar[] = "RenesasFlashProgrammer_PATH";
+ const char envVar[] = "RENESAS_FLASH_PROGRAMMER_PATH";
FilePath defaultPath;
if (qEnvironmentVariableIsSet(envVar)) {
@@ -332,313 +443,121 @@ static McuPackage *createRenesasProgrammerPackage()
}
}
- auto result = new McuPackage("Renesas Flash Programmer",
- defaultPath,
- FilePath("rfp-cli").withExecutableSuffix(),
- "RenesasFlashProgrammer",
- envVar);
- return result;
+ return McuPackagePtr{new McuPackage(settingsHandler,
+ "Renesas Flash Programmer",
+ defaultPath,
+ FilePath("rfp-cli").withExecutableSuffix(),
+ "RenesasFlashProgrammer", // settings key
+ "RENESAS_FLASH_PROGRAMMER_PATH", // cmake var
+ envVar)}; // env var
}
-static McuPackageVersionDetector *generatePackageVersionDetector(QString envVar)
-{
- if (envVar.startsWith("EVK"))
- return new McuPackageXmlVersionDetector("*_manifest_*.xml", "ksdk", "version", ".*");
-
- if (envVar.startsWith("STM32"))
- return new McuPackageXmlVersionDetector("package.xml",
- "PackDescription",
- "Release",
- "\\b(\\d+\\.\\d+\\.\\d+)\\b");
- if (envVar.startsWith("RGL"))
- return new McuPackageDirectoryVersionDetector("rgl_*_obj_*", "\\d+\\.\\d+\\.\\w+", false);
-
- return nullptr;
-}
-
-/// Create the McuPackage by checking the "boardSdk" property in the JSON file for the board.
-/// The name of the environment variable pointing to the the SDK for the board will be defined in the "envVar" property
-/// inside the "boardSdk".
-static McuPackage *createBoardSdkPackage(const McuTargetDescription &desc)
-{
- const auto generateSdkName = [](const QString &envVar) {
- auto postfixPos = envVar.indexOf("_SDK_PATH");
- if (postfixPos < 0) {
- postfixPos = envVar.indexOf("_DIR");
- }
- auto sdkName = postfixPos > 0 ? envVar.left(postfixPos) : envVar;
- return QString::fromLatin1("MCU SDK (%1)").arg(sdkName);
- };
- const QString sdkName = desc.boardSdk.name.isEmpty() ? generateSdkName(desc.boardSdk.envVar)
- : desc.boardSdk.name;
-
- const FilePath defaultPath = [&] {
- const auto envVar = desc.boardSdk.envVar.toLatin1();
- if (qEnvironmentVariableIsSet(envVar))
- return FilePath::fromUserInput(qEnvironmentVariable(envVar));
- if (!desc.boardSdk.defaultPath.isEmpty()) {
- FilePath defaultPath = FilePath::fromUserInput(QDir::rootPath()
- + desc.boardSdk.defaultPath);
- if (defaultPath.exists())
- return defaultPath;
- }
- return FilePath();
- }();
-
- const auto versionDetector = generatePackageVersionDetector(desc.boardSdk.envVar);
-
- return new McuPackage(sdkName,
- defaultPath,
- {}, // detection path
- desc.boardSdk.envVar, // settings key
- desc.boardSdk.envVar, // env var
- {}, // download URL
- versionDetector);
-}
-
-static McuPackage *createFreeRTOSSourcesPackage(const QString &envVar,
- const FilePath &boardSdkDir,
- const QString &freeRTOSBoardSdkSubDir)
+static McuAbstractTargetFactory::Ptr createFactory(bool isLegacy,
+ const SettingsHandler::Ptr &settingsHandler,
+ const FilePath &qtMcuSdkPath)
{
- const QString envVarPrefix = envVar.chopped(int(strlen("_FREERTOS_DIR")));
-
- FilePath defaultPath;
- if (qEnvironmentVariableIsSet(envVar.toLatin1()))
- defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar.toLatin1()));
- else if (!boardSdkDir.isEmpty() && !freeRTOSBoardSdkSubDir.isEmpty())
- defaultPath = boardSdkDir / freeRTOSBoardSdkSubDir;
-
- return new McuPackage(QString::fromLatin1("FreeRTOS Sources (%1)").arg(envVarPrefix),
- defaultPath,
- {},
- QString::fromLatin1("FreeRTOSSourcePackage_%1").arg(envVarPrefix),
- envVar,
- "https://freertos.org");
+ McuAbstractTargetFactory::Ptr result;
+ if (isLegacy) {
+ static const QHash<QString, ToolchainCompilerCreator> toolchainCreators = {
+ {{"armgcc"},
+ {[settingsHandler] { return createArmGccToolchainPackage(settingsHandler); }}},
+ {{"greenhills"},
+ [settingsHandler] { return createGhsToolchainPackage(settingsHandler); }},
+ {{"iar"}, {[settingsHandler] { return createIarToolChainPackage(settingsHandler); }}},
+ {{"msvc"}, {[settingsHandler] { return createMsvcToolChainPackage(settingsHandler); }}},
+ {{"gcc"}, {[settingsHandler] { return createGccToolChainPackage(settingsHandler); }}},
+ {{"arm-greenhills"},
+ {[settingsHandler] { return createGhsArmToolchainPackage(settingsHandler); }}},
+ };
+
+ const FilePath toolchainFilePrefix = qtMcuSdkPath / Constants::QUL_TOOLCHAIN_CMAKE_DIR;
+ static const QHash<QString, McuPackagePtr> toolchainFiles = {
+ {{"armgcc"},
+ McuPackagePtr{new McuPackage{settingsHandler,
+ {},
+ toolchainFilePrefix / "armgcc.cmake",
+ {},
+ {},
+ Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE,
+ {}}}},
+
+ {{"iar"},
+ McuPackagePtr{new McuPackage{settingsHandler,
+ {},
+ toolchainFilePrefix / "iar.cmake",
+ {},
+ {},
+ Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE,
+ {}}}},
+ {"greenhills",
+ McuPackagePtr{new McuPackage{settingsHandler,
+ {},
+ toolchainFilePrefix / "ghs.cmake",
+ {},
+ {},
+ Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE,
+ {}}}},
+ {"arm-greenhills",
+ McuPackagePtr{new McuPackage{settingsHandler,
+ {},
+ toolchainFilePrefix / "arm-ghs.cmake",
+ {},
+ {},
+ Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE,
+ {}}}},
+ };
+
+ // Note: the vendor name (the key of the hash) is case-sensitive. It has to match the "platformVendor" key in the
+ // json file.
+ static const QHash<QString, McuPackagePtr> vendorPkgs = {
+ {{"ST"}, McuPackagePtr{createStm32CubeProgrammerPackage(settingsHandler)}},
+ {{"NXP"}, McuPackagePtr{createMcuXpressoIdePackage(settingsHandler)}},
+ {{"CYPRESS"}, McuPackagePtr{createCypressProgrammerPackage(settingsHandler)}},
+ {{"RENESAS"}, McuPackagePtr{createRenesasProgrammerPackage(settingsHandler)}},
+ };
+
+ result = std::make_unique<McuTargetFactoryLegacy>(toolchainCreators,
+ toolchainFiles,
+ vendorPkgs,
+ settingsHandler);
+ } else {
+ result = std::make_unique<McuTargetFactory>(settingsHandler);
+ }
+ return result;
}
-struct McuTargetFactory
+McuSdkRepository targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
+ const SettingsHandler::Ptr &settingsHandler,
+ const FilePath &qtForMCUSdkPath,
+ bool isLegacy)
{
- McuTargetFactory(const QHash<QString, McuToolChainPackage *> &tcPkgs,
- const QHash<QString, McuPackage *> &vendorPkgs)
- : tcPkgs(tcPkgs)
- , vendorPkgs(vendorPkgs)
- {}
-
- QVector<McuTarget *> createTargets(const McuTargetDescription &description)
- {
- auto qulVersion = QVersionNumber::fromString(description.qulVersion);
- if (qulVersion <= QVersionNumber({1, 3})) {
- if (description.platform.type == McuTargetDescription::TargetType::Desktop)
- return createDesktopTargetsLegacy(description);
-
- // There was a platform backends related refactoring in Qul 1.4
- // This requires different processing of McuTargetDescriptions
- return createMcuTargetsLegacy(description);
- }
- return createTargetsImpl(description);
+ Targets mcuTargets;
+ Packages mcuPackages;
+
+ McuAbstractTargetFactory::Ptr targetFactory = createFactory(isLegacy,
+ settingsHandler,
+ qtForMCUSdkPath);
+ for (const McuTargetDescription &desc : descriptions) {
+ auto [targets, packages] = targetFactory->createTargets(desc, qtForMCUSdkPath);
+ mcuTargets.append(targets);
+ mcuPackages.unite(packages);
}
- QVector<McuAbstractPackage *> getMcuPackages() const
- {
- QVector<McuAbstractPackage *> packages;
- for (auto *package : qAsConst(boardSdkPkgs))
- packages.append(package);
- for (auto *package : qAsConst(freeRTOSPkgs))
- packages.append(package);
- return packages;
- }
-
-protected:
- // Implementation for Qul version <= 1.3
- QVector<McuTarget *> createMcuTargetsLegacy(const McuTargetDescription &desc)
- {
- QVector<McuTarget *> mcuTargets;
- McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
- if (!tcPkg)
- tcPkg = createUnsupportedToolChainPackage();
- for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) {
- for (int colorDepth : desc.platform.colorDepths) {
- QVector<McuAbstractPackage *> required3rdPartyPkgs = {tcPkg};
- if (vendorPkgs.contains(desc.platform.vendor))
- required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
-
- FilePath boardSdkDefaultPath;
- if (!desc.boardSdk.envVar.isEmpty()) {
- if (!boardSdkPkgs.contains(desc.boardSdk.envVar)) {
- auto boardSdkPkg = desc.boardSdk.envVar != "RGL_DIR"
- ? createBoardSdkPackage(desc)
- : createRGLPackage();
- boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg);
- }
- auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar);
- boardSdkDefaultPath = boardSdkPkg->defaultPath();
- required3rdPartyPkgs.append(boardSdkPkg);
- }
- if (os == McuTarget::OS::FreeRTOS) {
- if (desc.freeRTOS.envVar.isEmpty()) {
- continue;
- } else {
- if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) {
- freeRTOSPkgs
- .insert(desc.freeRTOS.envVar,
- createFreeRTOSSourcesPackage(desc.freeRTOS.envVar,
- boardSdkDefaultPath,
- desc.freeRTOS.boardSdkSubDir));
- }
- required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOS.envVar));
- }
- }
-
- const auto platform = McuTarget::Platform{desc.platform.id,
- desc.platform.name,
- desc.platform.vendor};
- auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
- platform,
- os,
- required3rdPartyPkgs,
- tcPkg,
- desc.platform.colorDepths.count() > 1
- ? colorDepth
- : McuTarget::UnspecifiedColorDepth);
- mcuTargets.append(mcuTarget);
- }
+ if (isLegacy) {
+ auto [toolchainPkgs, vendorPkgs]{targetFactory->getAdditionalPackages()};
+ for (McuToolChainPackagePtr &package : toolchainPkgs) {
+ mcuPackages.insert(package);
}
- return mcuTargets;
- }
-
- QVector<McuTarget *> createDesktopTargetsLegacy(const McuTargetDescription &desc)
- {
- McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
- if (!tcPkg)
- tcPkg = createUnsupportedToolChainPackage();
- const auto platform = McuTarget::Platform{desc.platform.id,
- desc.platform.name,
- desc.platform.vendor};
- auto desktopTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
- platform,
- McuTarget::OS::Desktop,
- {},
- tcPkg);
- return {desktopTarget};
- }
-
- QVector<McuTarget *> createTargetsImpl(const McuTargetDescription &desc)
- {
- // OS deduction
- const auto os = [&] {
- if (desc.platform.type == McuTargetDescription::TargetType::Desktop)
- return McuTarget::OS::Desktop;
- else if (!desc.freeRTOS.envVar.isEmpty())
- return McuTarget::OS::FreeRTOS;
- return McuTarget::OS::BareMetal;
- }();
-
- QVector<McuTarget *> mcuTargets;
- McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
- if (tcPkg)
- tcPkg->setVersions(desc.toolchain.versions);
- else
- tcPkg = createUnsupportedToolChainPackage();
- for (int colorDepth : desc.platform.colorDepths) {
- QVector<McuAbstractPackage *> required3rdPartyPkgs;
- // Desktop toolchains don't need any additional settings
- if (tcPkg && !tcPkg->isDesktopToolchain()
- && tcPkg->toolchainType() != McuToolChainPackage::ToolChainType::Unsupported)
- required3rdPartyPkgs.append(tcPkg);
-
- // Add setting specific to platform IDE
- if (vendorPkgs.contains(desc.platform.vendor))
- required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
-
- // Board SDK specific settings
- FilePath boardSdkDefaultPath;
- if (!desc.boardSdk.envVar.isEmpty()) {
- if (!boardSdkPkgs.contains(desc.boardSdk.envVar)) {
- auto boardSdkPkg = createBoardSdkPackage(desc);
- boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg);
- }
- auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar);
- boardSdkPkg->setVersions(desc.boardSdk.versions);
- boardSdkDefaultPath = boardSdkPkg->defaultPath();
- required3rdPartyPkgs.append(boardSdkPkg);
- }
-
- // Free RTOS specific settings
- if (!desc.freeRTOS.envVar.isEmpty()) {
- if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) {
- freeRTOSPkgs.insert(desc.freeRTOS.envVar,
- createFreeRTOSSourcesPackage(desc.freeRTOS.envVar,
- boardSdkDefaultPath,
- desc.freeRTOS.boardSdkSubDir));
- }
- required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOS.envVar));
- }
-
- const McuTarget::Platform platform(
- {desc.platform.id, desc.platform.name, desc.platform.vendor});
- auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
- platform,
- os,
- required3rdPartyPkgs,
- tcPkg,
- colorDepth);
- mcuTargets.append(mcuTarget);
+ for (McuPackagePtr &package : vendorPkgs) {
+ mcuPackages.insert(package);
}
- return mcuTargets;
- }
-
-private:
- const QHash<QString, McuToolChainPackage *> &tcPkgs;
- const QHash<QString, McuPackage *> &vendorPkgs;
-
- QHash<QString, McuPackage *> boardSdkPkgs;
- QHash<QString, McuPackage *> freeRTOSPkgs;
-}; // struct McuTargetFactory
-
-QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
- QVector<McuAbstractPackage *> *packages)
-{
- const QHash<QString, McuToolChainPackage *> tcPkgs = {
- {{"armgcc"}, createArmGccPackage()},
- {{"greenhills"}, createGhsToolchainPackage()},
- {{"iar"}, createIarToolChainPackage()},
- {{"msvc"}, createMsvcToolChainPackage()},
- {{"gcc"}, createGccToolChainPackage()},
- {{"arm-greenhills"}, createGhsArmToolchainPackage()},
- };
-
- // Note: the vendor name (the key of the hash) is case-sensitive. It has to match the "platformVendor" key in the
- // json file.
- const QHash<QString, McuPackage *> vendorPkgs = {
- {{"ST"}, createStm32CubeProgrammerPackage()},
- {{"NXP"}, createMcuXpressoIdePackage()},
- {{"CYPRESS"}, createCypressProgrammerPackage()},
- {{"RENESAS"}, createRenesasProgrammerPackage()},
- };
-
- McuTargetFactory targetFactory(tcPkgs, vendorPkgs);
- QVector<McuTarget *> mcuTargets;
-
- for (const auto &desc : descriptions) {
- auto newTargets = targetFactory.createTargets(desc);
- mcuTargets.append(newTargets);
}
-
- packages->append(
- Utils::transform<QVector<McuAbstractPackage *>>(tcPkgs.values(),
- [&](McuToolChainPackage *tcPkg) {
- return tcPkg;
- }));
- for (auto *package : vendorPkgs)
- packages->append(package);
- packages->append(targetFactory.getMcuPackages());
-
- return mcuTargets;
+ return McuSdkRepository{mcuTargets, mcuPackages};
}
-Utils::FilePath kitsPath(const Utils::FilePath &dir)
+Utils::FilePath kitsPath(const Utils::FilePath &qtMcuSdkPath)
{
- return dir / "kits/";
+ return qtMcuSdkPath / "kits/";
}
static QFileInfoList targetDescriptionFiles(const Utils::FilePath &dir)
@@ -647,6 +566,29 @@ static QFileInfoList targetDescriptionFiles(const Utils::FilePath &dir)
return kitsDir.entryInfoList();
}
+static PackageDescription parsePackage(const QJsonObject &cmakeEntry)
+{
+ return {cmakeEntry["label"].toString(),
+ cmakeEntry["envVar"].toString(),
+ cmakeEntry["cmakeVar"].toString(),
+ cmakeEntry["description"].toString(),
+ cmakeEntry["setting"].toString(),
+ FilePath::fromString(cmakeEntry["defaultValue"].toString()),
+ FilePath::fromString(cmakeEntry["validation"].toString()),
+ {},
+ false};
+}
+
+static QList<PackageDescription> parsePackages(const QJsonArray &cmakeEntries)
+{
+ QList<PackageDescription> result;
+ for (const auto &cmakeEntryRef : cmakeEntries) {
+ const QJsonObject cmakeEntry{cmakeEntryRef.toObject()};
+ result.push_back(parsePackage(cmakeEntry));
+ }
+ return result;
+}
+
McuTargetDescription parseDescriptionJson(const QByteArray &data)
{
const QJsonDocument document = QJsonDocument::fromJson(data);
@@ -655,9 +597,18 @@ McuTargetDescription parseDescriptionJson(const QByteArray &data)
const QJsonObject platform = target.value("platform").toObject();
const QString compatVersion = target.value("compatVersion").toString();
const QJsonObject toolchain = target.value("toolchain").toObject();
+ const QJsonObject toolchainFile = toolchain.value("file").toObject();
+ const QJsonObject compiler = toolchain.value("compiler").toObject();
const QJsonObject boardSdk = target.value("boardSdk").toObject();
const QJsonObject freeRTOS = target.value("freeRTOS").toObject();
+ const PackageDescription toolchainPackage = parsePackage(compiler);
+ const PackageDescription toolchainFilePackage = parsePackage(toolchainFile);
+ const QList<PackageDescription> boardSDKEntries = parsePackages(
+ boardSdk.value(CMAKE_ENTRIES).toArray());
+ const QList<PackageDescription> freeRtosEntries = parsePackages(
+ freeRTOS.value(CMAKE_ENTRIES).toArray());
+
const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList();
const auto toolchainVersionsList = Utils::transform<QStringList>(toolchainVersions,
[&](const QVariant &version) {
@@ -676,41 +627,39 @@ McuTargetDescription parseDescriptionJson(const QByteArray &data)
});
const QString platformName = platform.value("platformName").toString();
- return {
- qulVersion,
- compatVersion,
- {
- platform.value("id").toString(),
- platformName,
- platform.value("vendor").toString(),
- colorDepthsVector,
- platformName == "Desktop" ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU,
- },
- {
- toolchain.value("id").toString(),
- toolchainVersionsList,
- },
- {
- boardSdk.value("name").toString(),
- boardSdk.value("defaultPath").toString(),
- boardSdk.value("envVar").toString(),
- boardSdkVersionsList,
- },
- {
- freeRTOS.value("envVar").toString(),
- freeRTOS.value("boardSdkSubDir").toString(),
- }
- };
+ return {qulVersion,
+ compatVersion,
+ {
+ platform.value("id").toString(),
+ platformName,
+ platform.value("vendor").toString(),
+ colorDepthsVector,
+ platformName == "Desktop" ? McuTargetDescription::TargetType::Desktop
+ : McuTargetDescription::TargetType::MCU,
+ },
+ {toolchain.value("id").toString(),
+ toolchainVersionsList,
+ toolchainPackage,
+ toolchainFilePackage},
+ {
+ boardSdk.value("name").toString(),
+ FilePath::fromString(boardSdk.value("defaultPath").toString()),
+ boardSdk.value("envVar").toString(),
+ boardSdkVersionsList,
+ boardSDKEntries,
+ },
+ {
+ freeRTOS.value("envVar").toString(),
+ FilePath::fromString(freeRTOS.value("boardSdkSubDir").toString()),
+ freeRtosEntries,
+ }};
}
// https://doc.qt.io/qtcreator/creator-developing-mcu.html#supported-qt-for-mcus-sdks
static const QString legacySupportVersionFor(const QString &sdkVersion)
{
- static const QHash<QString, QString> oldSdkQtcRequiredVersion = {
- {{"1.0"}, {"4.11.x"}},
- {{"1.1"}, {"4.12.0 or 4.12.1"}},
- {{"1.2"}, {"4.12.2 or 4.12.3"}}
- };
+ static const QHash<QString, QString> oldSdkQtcRequiredVersion
+ = {{{"1.0"}, {"4.11.x"}}, {{"1.1"}, {"4.12.0 or 4.12.1"}}, {{"1.2"}, {"4.12.2 or 4.12.3"}}};
if (oldSdkQtcRequiredVersion.contains(sdkVersion))
return oldSdkQtcRequiredVersion.value(sdkVersion);
@@ -720,11 +669,10 @@ static const QString legacySupportVersionFor(const QString &sdkVersion)
return QString();
}
-
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message)
{
const McuPackagePathVersionDetector versionDetector("(?<=\\bQtMCUs.)(\\d+\\.\\d+)");
- const QString sdkDetectedVersion = versionDetector.parseVersion(qulDir.toString());
+ const QString sdkDetectedVersion = versionDetector.parseVersion(qulDir);
const QString legacyVersion = legacySupportVersionFor(sdkDetectedVersion);
if (!legacyVersion.isEmpty()) {
@@ -740,11 +688,13 @@ bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message)
return false;
}
-void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo)
+McuSdkRepository targetsAndPackages(const Utils::FilePath &qtForMCUSdkPath,
+ const SettingsHandler::Ptr &settingsHandler)
{
QList<McuTargetDescription> descriptions;
+ bool isLegacy{false};
- auto descriptionFiles = targetDescriptionFiles(dir);
+ auto descriptionFiles = targetDescriptionFiles(qtForMCUSdkPath);
for (const QFileInfo &fileInfo : descriptionFiles) {
QFile file(fileInfo.absoluteFilePath());
if (!file.open(QFile::ReadOnly))
@@ -760,7 +710,11 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo)
false);
continue;
}
- if (QVersionNumber::fromString(desc.qulVersion) < McuSupportOptions::minimalQulVersion()) {
+
+ const auto qulVersion{QVersionNumber::fromString(desc.qulVersion)};
+ isLegacy = McuSupportOptions::isLegacyVersion(qulVersion);
+
+ if (qulVersion < McuSupportOptions::minimalQulVersion()) {
const QString legacyVersion = legacySupportVersionFor(desc.qulVersion);
const QString qtcSupportText
= !legacyVersion.isEmpty()
@@ -779,39 +733,30 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo)
// No valid description means invalid or old SDK installation.
if (descriptions.empty()) {
- if (kitsPath(dir).exists()) {
+ if (kitsPath(qtForMCUSdkPath).exists()) {
printMessage(McuTarget::tr("No valid kit descriptions found at %1.")
- .arg(kitsPath(dir).toUserOutput()),
+ .arg(kitsPath(qtForMCUSdkPath).toUserOutput()),
true);
- return;
+ return McuSdkRepository{};
} else {
QString deprecationMessage;
- if (checkDeprecatedSdkError(dir, deprecationMessage)) {
+ if (checkDeprecatedSdkError(qtForMCUSdkPath, deprecationMessage)) {
printMessage(deprecationMessage, true);
- return;
+ return McuSdkRepository{};
}
}
}
-
- repo->mcuTargets.append(targetsFromDescriptions(descriptions, &(repo->packages)));
+ McuSdkRepository repo = targetsFromDescriptions(descriptions,
+ settingsHandler,
+ qtForMCUSdkPath,
+ isLegacy);
// Keep targets sorted lexicographically
- std::sort(repo->mcuTargets.begin(),
- repo->mcuTargets.end(),
- [](const McuTarget *lhs, const McuTarget *rhs) {
- return McuKitManager::kitName(lhs) < McuKitManager::kitName(rhs);
- });
-}
-
-FilePath packagePathFromSettings(const QString &settingsKey,
- QSettings::Scope scope,
- const FilePath &defaultPath)
-{
- QSettings *settings = Core::ICore::settings(scope);
- const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/'
- + QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + settingsKey;
- const QString path = settings->value(key, defaultPath.toString()).toString();
- return FilePath::fromUserInput(path);
+ Utils::sort(repo.mcuTargets, [](const McuTargetPtr &lhs, const McuTargetPtr &rhs) {
+ return McuKitManager::generateKitNameFromTarget(lhs.get())
+ < McuKitManager::generateKitNameFromTarget(rhs.get());
+ });
+ return repo;
}
} // namespace Sdk
diff --git a/src/plugins/mcusupport/mcusupportsdk.h b/src/plugins/mcusupport/mcusupportsdk.h
index a79a7d90f10..6d1feddf7ac 100644
--- a/src/plugins/mcusupport/mcusupportsdk.h
+++ b/src/plugins/mcusupport/mcusupportsdk.h
@@ -25,40 +25,58 @@
#pragma once
-#include "utils/filepath.h"
+#include "mcusupport_global.h"
+#include "settingshandler.h"
-#include <QSettings>
-#include <QVector>
+#include <utils/filepath.h>
-namespace McuSupport {
-namespace Internal {
+namespace Utils {
+class FilePath;
+} // namespace Utils
+
+namespace McuSupport::Internal {
constexpr int MAX_COMPATIBILITY_VERSION{1};
-class McuSdkRepository;
class McuAbstractPackage;
class McuPackage;
+class McuSdkRepository;
class McuTarget;
+class McuToolChainPackage;
namespace Sdk {
struct McuTargetDescription;
-McuPackage *createQtForMCUsPackage();
+McuPackagePtr createQtForMCUsPackage(const SettingsHandler::Ptr &);
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message);
-void targetsAndPackages(const Utils::FilePath &qulDir, McuSdkRepository *repo);
+McuSdkRepository targetsAndPackages(const Utils::FilePath &qulDir, const SettingsHandler::Ptr &);
McuTargetDescription parseDescriptionJson(const QByteArray &);
-QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &,
- QVector<McuAbstractPackage *> *);
+McuSdkRepository targetsFromDescriptions(const QList<McuTargetDescription> &,
+ const SettingsHandler::Ptr &,
+ const Utils::FilePath &qtForMCUSdkPath,
+ bool isLegacy);
Utils::FilePath kitsPath(const Utils::FilePath &dir);
-Utils::FilePath packagePathFromSettings(const QString &settingsKey,
- QSettings::Scope scope,
- const Utils::FilePath &defaultPath);
+McuPackagePtr createUnsupportedToolChainFilePackage(const SettingsHandler::Ptr &,
+ const Utils::FilePath &qtMcuSdkPath);
+McuToolChainPackagePtr createUnsupportedToolChainPackage(const SettingsHandler::Ptr &);
+McuToolChainPackagePtr createIarToolChainPackage(const SettingsHandler::Ptr &);
+McuToolChainPackagePtr createGccToolChainPackage(const SettingsHandler::Ptr &);
+McuToolChainPackagePtr createArmGccToolchainPackage(const SettingsHandler::Ptr &);
+McuToolChainPackagePtr createMsvcToolChainPackage(const SettingsHandler::Ptr &);
+McuToolChainPackagePtr createGhsToolchainPackage(const SettingsHandler::Ptr &);
+McuToolChainPackagePtr createGhsArmToolchainPackage(const SettingsHandler::Ptr &);
+
+McuPackagePtr createBoardSdkPackage(const SettingsHandler::Ptr &, const McuTargetDescription &);
+McuPackagePtr createFreeRTOSSourcesPackage(const SettingsHandler::Ptr &settingsHandler,
+ const QString &envVar,
+ const Utils::FilePath &boardSdkDir,
+ const Utils::FilePath &freeRTOSBoardSdkSubDir);
+
} // namespace Sdk
-} // namespace Internal
-} // namespace McuSupport
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcusupportversiondetection.cpp b/src/plugins/mcusupport/mcusupportversiondetection.cpp
index 12bb7912e72..c7ae1518230 100644
--- a/src/plugins/mcusupport/mcusupportversiondetection.cpp
+++ b/src/plugins/mcusupport/mcusupportversiondetection.cpp
@@ -25,11 +25,11 @@
#include "mcusupportversiondetection.h"
-#include <utils/fileutils.h>
#include <utils/qtcprocess.h>
#include <QDir>
#include <QRegularExpression>
+#include <QXmlStreamReader>
namespace McuSupport {
namespace Internal {
@@ -46,19 +46,21 @@ QString matchRegExp(const QString &text, const QString &regExp)
McuPackageVersionDetector::McuPackageVersionDetector() {}
McuPackageExecutableVersionDetector::McuPackageExecutableVersionDetector(
- const Utils::FilePath &detectionPath, const QStringList &detectionArgs, const QString &detectionRegExp)
+ const Utils::FilePath &detectionPath,
+ const QStringList &detectionArgs,
+ const QString &detectionRegExp)
: McuPackageVersionDetector()
, m_detectionPath(detectionPath)
, m_detectionArgs(detectionArgs)
, m_detectionRegExp(detectionRegExp)
{}
-QString McuPackageExecutableVersionDetector::parseVersion(const QString &packagePath) const
+QString McuPackageExecutableVersionDetector::parseVersion(const Utils::FilePath &packagePath) const
{
if (m_detectionPath.isEmpty() || m_detectionRegExp.isEmpty())
return QString();
- const Utils::FilePath binaryPath = Utils::FilePath::fromString(packagePath).pathAppended(m_detectionPath.path());
+ const Utils::FilePath binaryPath = packagePath / m_detectionPath.path();
if (!binaryPath.exists())
return QString();
@@ -69,7 +71,7 @@ QString McuPackageExecutableVersionDetector::parseVersion(const QString &package
if (!binaryProcess.waitForStarted())
return QString();
binaryProcess.waitForFinished(execTimeout);
- if (binaryProcess.exitCode() == QProcess::ExitStatus::NormalExit) {
+ if (binaryProcess.exitStatus() == QProcess::NormalExit) {
const QString processOutput = QString::fromUtf8(
binaryProcess.readAllStandardOutput().append(binaryProcess.readAllStandardError()));
return matchRegExp(processOutput, m_detectionRegExp);
@@ -89,9 +91,9 @@ McuPackageXmlVersionDetector::McuPackageXmlVersionDetector(const QString &filePa
, m_versionRegExp(versionRegExp)
{}
-QString McuPackageXmlVersionDetector::parseVersion(const QString &packagePath) const
+QString McuPackageXmlVersionDetector::parseVersion(const Utils::FilePath &packagePath) const
{
- const auto files = QDir(packagePath, m_filePattern).entryInfoList();
+ const auto files = QDir(packagePath.toString(), m_filePattern).entryInfoList();
for (const auto &xmlFile : files) {
QFile sdkXmlFile = QFile(xmlFile.absoluteFilePath());
sdkXmlFile.open(QFile::OpenModeFlag::ReadOnly);
@@ -117,9 +119,9 @@ McuPackageDirectoryVersionDetector::McuPackageDirectoryVersionDetector(const QSt
, m_isFile(isFile)
{}
-QString McuPackageDirectoryVersionDetector::parseVersion(const QString &packagePath) const
+QString McuPackageDirectoryVersionDetector::parseVersion(const Utils::FilePath &packagePath) const
{
- const auto files = QDir(packagePath, m_filePattern)
+ const auto files = QDir(packagePath.toString(), m_filePattern)
.entryInfoList(m_isFile ? QDir::Filter::Files : QDir::Filter::Dirs);
for (const auto &entry : files) {
const QString matched = matchRegExp(entry.fileName(), m_versionRegExp);
@@ -133,11 +135,11 @@ McuPackagePathVersionDetector::McuPackagePathVersionDetector(const QString &vers
: m_versionRegExp(versionRegExp)
{}
-QString McuPackagePathVersionDetector::parseVersion(const QString &packagePath) const
+QString McuPackagePathVersionDetector::parseVersion(const Utils::FilePath &packagePath) const
{
- if (!Utils::FilePath::fromString(packagePath).exists())
+ if (!packagePath.exists())
return QString();
- return matchRegExp(packagePath, m_versionRegExp);
+ return matchRegExp(packagePath.toString(), m_versionRegExp);
}
} // namespace Internal
diff --git a/src/plugins/mcusupport/mcusupportversiondetection.h b/src/plugins/mcusupport/mcusupportversiondetection.h
index c5f25875d0d..76e88718dbb 100644
--- a/src/plugins/mcusupport/mcusupportversiondetection.h
+++ b/src/plugins/mcusupport/mcusupportversiondetection.h
@@ -25,19 +25,17 @@
#pragma once
-#include <QObject>
#include <utils/filepath.h>
+#include <QString>
-namespace McuSupport {
-namespace Internal {
+namespace McuSupport::Internal {
-class McuPackageVersionDetector : public QObject
+class McuPackageVersionDetector
{
- Q_OBJECT
public:
McuPackageVersionDetector();
virtual ~McuPackageVersionDetector() = default;
- virtual QString parseVersion(const QString &packagePath) const = 0;
+ virtual QString parseVersion(const Utils::FilePath &packagePath) const = 0;
};
// Get version from the output of an executable
@@ -47,7 +45,7 @@ public:
McuPackageExecutableVersionDetector(const Utils::FilePath &detectionPath,
const QStringList &detectionArgs,
const QString &detectionRegExp);
- QString parseVersion(const QString &packagePath) const final;
+ QString parseVersion(const Utils::FilePath &packagePath) const final;
private:
const Utils::FilePath m_detectionPath;
@@ -63,7 +61,7 @@ public:
const QString &elementName,
const QString &versionAttribute,
const QString &versionRegExp);
- QString parseVersion(const QString &packagePath) const final;
+ QString parseVersion(const Utils::FilePath &packagePath) const final;
private:
const QString m_filePattern;
@@ -79,7 +77,7 @@ public:
McuPackageDirectoryVersionDetector(const QString &filePattern,
const QString &versionRegExp,
const bool isFile);
- QString parseVersion(const QString &packagePath) const final;
+ QString parseVersion(const Utils::FilePath &packagePath) const final;
private:
const QString m_filePattern;
@@ -92,11 +90,10 @@ class McuPackagePathVersionDetector : public McuPackageVersionDetector
{
public:
McuPackagePathVersionDetector(const QString &versionRegExp);
- QString parseVersion(const QString &packagePath) const final;
+ QString parseVersion(const Utils::FilePath &packagePath) const final;
private:
const QString m_versionRegExp;
};
-} // namespace Internal
-} // namespace McuSupport
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcutarget.cpp b/src/plugins/mcusupport/mcutarget.cpp
index 28628eeca51..c21fc896ea2 100644
--- a/src/plugins/mcusupport/mcutarget.cpp
+++ b/src/plugins/mcusupport/mcutarget.cpp
@@ -24,8 +24,8 @@
****************************************************************************/
#include "mcutarget.h"
-#include "mcupackage.h"
#include "mcukitmanager.h"
+#include "mcupackage.h"
#include "mcusupportplugin.h"
#include <utils/algorithm.h>
@@ -37,40 +37,47 @@ namespace McuSupport::Internal {
McuTarget::McuTarget(const QVersionNumber &qulVersion,
const Platform &platform,
OS os,
- const QVector<McuAbstractPackage *> &packages,
- const McuToolChainPackage *toolChainPackage,
+ const Packages &packages,
+ const McuToolChainPackagePtr &toolChainPackage,
+ const McuPackagePtr &toolChainFilePackage,
int colorDepth)
: m_qulVersion(qulVersion)
, m_platform(platform)
, m_os(os)
, m_packages(packages)
, m_toolChainPackage(toolChainPackage)
+ , m_toolChainFilePackage(toolChainFilePackage)
, m_colorDepth(colorDepth)
{}
-const QVector<McuAbstractPackage *> &McuTarget::packages() const
+Packages McuTarget::packages() const
{
return m_packages;
}
-const McuToolChainPackage *McuTarget::toolChainPackage() const
+McuToolChainPackagePtr McuTarget::toolChainPackage() const
{
return m_toolChainPackage;
}
+McuPackagePtr McuTarget::toolChainFilePackage() const
+{
+ return m_toolChainFilePackage;
+}
+
McuTarget::OS McuTarget::os() const
{
return m_os;
}
-const McuTarget::Platform &McuTarget::platform() const
+McuTarget::Platform McuTarget::platform() const
{
return m_platform;
}
bool McuTarget::isValid() const
{
- return Utils::allOf(packages(), [](McuAbstractPackage *package) {
+ return Utils::allOf(packages(), [](const McuPackagePtr &package) {
package->updateStatus();
return package->isValidStatus();
});
@@ -82,20 +89,20 @@ void McuTarget::printPackageProblems() const
package->updateStatus();
if (!package->isValidStatus())
printMessage(tr("Error creating kit for target %1, package %2: %3")
- .arg(McuKitManager::kitName(this),
+ .arg(McuKitManager::generateKitNameFromTarget(this),
package->label(),
package->statusText()),
true);
if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion)
printMessage(tr("Warning creating kit for target %1, package %2: %3")
- .arg(McuKitManager::kitName(this),
+ .arg(McuKitManager::generateKitNameFromTarget(this),
package->label(),
package->statusText()),
false);
}
}
-const QVersionNumber &McuTarget::qulVersion() const
+QVersionNumber McuTarget::qulVersion() const
{
return m_qulVersion;
}
diff --git a/src/plugins/mcusupport/mcutarget.h b/src/plugins/mcusupport/mcutarget.h
index 7426f81e152..c2c43707a1f 100644
--- a/src/plugins/mcusupport/mcutarget.h
+++ b/src/plugins/mcusupport/mcutarget.h
@@ -25,6 +25,9 @@
#pragma once
+#include "mcupackage.h"
+#include "mcusupport_global.h"
+
#include <QObject>
#include <QVersionNumber>
@@ -37,10 +40,8 @@ class PathChooser;
class InfoLabel;
} // namespace Utils
-namespace McuSupport {
-namespace Internal {
+namespace McuSupport::Internal {
-class McuAbstractPackage;
class McuToolChainPackage;
class McuTarget : public QObject
@@ -62,14 +63,16 @@ public:
McuTarget(const QVersionNumber &qulVersion,
const Platform &platform,
OS os,
- const QVector<McuAbstractPackage *> &packages,
- const McuToolChainPackage *toolChainPackage,
+ const Packages &packages,
+ const McuToolChainPackagePtr &toolChainPackage,
+ const McuPackagePtr &toolChainFilePackage,
int colorDepth = UnspecifiedColorDepth);
- const QVersionNumber &qulVersion() const;
- const QVector<McuAbstractPackage *> &packages() const;
- const McuToolChainPackage *toolChainPackage() const;
- const Platform &platform() const;
+ QVersionNumber qulVersion() const;
+ Packages packages() const;
+ McuToolChainPackagePtr toolChainPackage() const;
+ McuPackagePtr toolChainFilePackage() const;
+ Platform platform() const;
OS os() const;
int colorDepth() const;
bool isValid() const;
@@ -79,11 +82,10 @@ private:
const QVersionNumber m_qulVersion;
const Platform m_platform;
const OS m_os;
- const QVector<McuAbstractPackage *> m_packages;
- const McuToolChainPackage *m_toolChainPackage;
+ const Packages m_packages;
+ McuToolChainPackagePtr m_toolChainPackage;
+ McuPackagePtr m_toolChainFilePackage;
const int m_colorDepth;
}; // class McuTarget
-
-} // namespace Internal
-} // namespace McuSupport
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcutargetdescription.h b/src/plugins/mcusupport/mcutargetdescription.h
index ab0699574ad..7f261a82176 100644
--- a/src/plugins/mcusupport/mcutargetdescription.h
+++ b/src/plugins/mcusupport/mcutargetdescription.h
@@ -25,19 +25,34 @@
#pragma once
+#include <utils/filepath.h>
#include <QString>
#include <QStringList>
#include <QVector>
+#include <QVersionNumber>
namespace McuSupport::Internal::Sdk {
+struct PackageDescription
+{
+ QString label;
+ QString envVar;
+ QString cmakeVar;
+ QString description;
+ QString setting;
+ Utils::FilePath defaultPath;
+ Utils::FilePath validationPath;
+ QList<QVersionNumber> versions;
+ bool shouldAddToSystemPath;
+}; //struct PackageDescription
+
struct McuTargetDescription
{
enum class TargetType { MCU, Desktop };
QString qulVersion;
QString compatVersion;
- struct
+ struct Platform
{
QString id;
QString name;
@@ -45,23 +60,29 @@ struct McuTargetDescription
QVector<int> colorDepths;
TargetType type;
} platform;
- struct
+ struct Toolchain
{
QString id;
QStringList versions;
+ PackageDescription compiler;
+ PackageDescription file;
} toolchain;
- struct
+ struct BoardSdk
{
QString name;
- QString defaultPath;
+ Utils::FilePath defaultPath;
QString envVar;
QStringList versions;
+ QList<PackageDescription> packages;
} boardSdk;
- struct
+ struct FreeRTOS
{
QString envVar;
- QString boardSdkSubDir;
+ Utils::FilePath boardSdkSubDir;
+ QList<PackageDescription> packages;
} freeRTOS;
};
} // namespace McuSupport::Internal::Sdk
+
+Q_DECLARE_METATYPE(McuSupport::Internal::Sdk::McuTargetDescription)
diff --git a/src/plugins/mcusupport/mcutargetfactory.cpp b/src/plugins/mcusupport/mcutargetfactory.cpp
new file mode 100644
index 00000000000..b1d5cc4be62
--- /dev/null
+++ b/src/plugins/mcusupport/mcutargetfactory.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "mcutargetfactory.h"
+#include "mcuhelpers.h"
+#include "mcupackage.h"
+#include "mcusupportconstants.h"
+#include "mcusupportversiondetection.h"
+#include "mcutarget.h"
+#include "mcutargetdescription.h"
+
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+#include <QVersionNumber>
+
+namespace McuSupport::Internal {
+
+using Sdk::McuTargetDescription;
+using Sdk::PackageDescription;
+
+bool isToolchainDescriptionValid(const McuTargetDescription::Toolchain &t)
+{
+ return !t.id.isEmpty() && !t.compiler.cmakeVar.isEmpty() && !t.file.cmakeVar.isEmpty();
+}
+
+bool isDesktopToolchain(McuToolChainPackage::ToolChainType type)
+{
+ return type == McuToolChainPackage::ToolChainType::MSVC
+ || type == McuToolChainPackage::ToolChainType::GCC;
+}
+
+const static QMap<QString, McuToolChainPackage::ToolChainType> toolchainTypeMapping{
+ {"iar", McuToolChainPackage::ToolChainType::IAR},
+ {"keil", McuToolChainPackage::ToolChainType::KEIL},
+ {"msvc", McuToolChainPackage::ToolChainType::MSVC},
+ {"gcc", McuToolChainPackage::ToolChainType::GCC},
+ {"armgcc", McuToolChainPackage::ToolChainType::ArmGcc},
+ {"ghs", McuToolChainPackage::ToolChainType::GHS},
+ {"ghsarm", McuToolChainPackage::ToolChainType::GHSArm},
+};
+
+McuTargetFactory::McuTargetFactory(const SettingsHandler::Ptr &settingsHandler)
+ : settingsHandler{settingsHandler}
+{}
+
+QPair<Targets, Packages> McuTargetFactory::createTargets(const McuTargetDescription &desc,
+ const Utils::FilePath & /*qtForMCUSdkPath*/)
+{
+ Targets mcuTargets;
+ Packages packages;
+
+ for (int colorDepth : desc.platform.colorDepths) {
+ const McuTarget::Platform platform(
+ {desc.platform.id, desc.platform.name, desc.platform.vendor});
+
+ auto *toolchain = createToolchain(desc.toolchain);
+ McuPackagePtr toolchainFile{createPackage(desc.toolchain.file)};
+ //Skip target with incorrect toolchain dir or toolchain file.
+ if (!toolchain || !toolchainFile)
+ continue;
+ Packages targetPackages = createPackages(desc);
+ packages.unite(targetPackages);
+ mcuTargets.append(McuTargetPtr{new McuTarget{QVersionNumber::fromString(desc.qulVersion),
+ platform,
+ deduceOperatingSystem(desc),
+ targetPackages,
+ McuToolChainPackagePtr{toolchain},
+ toolchainFile,
+ colorDepth}});
+ }
+ return {mcuTargets, packages};
+}
+
+QList<PackageDescription> aggregatePackageEntries(const McuTargetDescription &desc)
+{
+ QList<PackageDescription> result;
+ result.append(desc.boardSdk.packages);
+ result.append(desc.freeRTOS.packages);
+ return result;
+}
+
+Packages McuTargetFactory::createPackages(const McuTargetDescription &desc)
+{
+ Packages packages;
+ QList<PackageDescription> packageDescriptions = aggregatePackageEntries(desc);
+
+ for (const PackageDescription &pkgDesc : packageDescriptions) {
+ packages.insert(createPackage(pkgDesc));
+ }
+
+ return packages;
+}
+
+McuPackagePtr McuTargetFactory::createPackage(const PackageDescription &pkgDesc)
+{
+ return McuPackagePtr{new McuPackage{
+ settingsHandler,
+ pkgDesc.label,
+ pkgDesc.defaultPath,
+ pkgDesc.validationPath,
+ pkgDesc.setting,
+ pkgDesc.cmakeVar,
+ pkgDesc.envVar,
+ }};
+}
+
+McuToolChainPackage *McuTargetFactory::createToolchain(
+ const McuTargetDescription::Toolchain &toolchain)
+{
+ const PackageDescription compilerDescription{toolchain.compiler};
+
+ McuToolChainPackage::ToolChainType toolchainType
+ = toolchainTypeMapping.value(toolchain.id, McuToolChainPackage::ToolChainType::Unsupported);
+
+ if (isDesktopToolchain(toolchainType))
+ return new McuToolChainPackage{settingsHandler, {}, {}, {}, {}, toolchainType};
+ else if (!isToolchainDescriptionValid(toolchain))
+ toolchainType = McuToolChainPackage::ToolChainType::Unsupported;
+
+ return new McuToolChainPackage{
+ settingsHandler,
+ compilerDescription.label,
+ compilerDescription.defaultPath,
+ compilerDescription.validationPath,
+ compilerDescription.setting,
+ toolchainType,
+ compilerDescription.cmakeVar,
+ compilerDescription.envVar,
+ nullptr, // McuPackageVersionDetector
+ };
+}
+
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcutargetfactory.h b/src/plugins/mcusupport/mcutargetfactory.h
new file mode 100644
index 00000000000..56e99d58e6a
--- /dev/null
+++ b/src/plugins/mcusupport/mcutargetfactory.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "mcuabstracttargetfactory.h"
+#include "mcutargetdescription.h"
+#include "settingshandler.h"
+
+namespace McuSupport::Internal {
+
+namespace Sdk {
+struct PackageDescription;
+} // namespace Sdk
+
+class McuTargetFactory : public McuAbstractTargetFactory
+{
+public:
+ explicit McuTargetFactory(const SettingsHandler::Ptr &);
+ QPair<Targets, Packages> createTargets(const Sdk::McuTargetDescription &,
+ const Utils::FilePath &qtForMCUSdkPath) override;
+ Packages createPackages(const Sdk::McuTargetDescription &);
+ McuToolChainPackage *createToolchain(const Sdk::McuTargetDescription::Toolchain &);
+ McuPackagePtr createPackage(const Sdk::PackageDescription &);
+
+private:
+ SettingsHandler::Ptr settingsHandler;
+}; // struct McuTargetFactory
+
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcutargetfactorylegacy.cpp b/src/plugins/mcusupport/mcutargetfactorylegacy.cpp
new file mode 100644
index 00000000000..bddfe76f59a
--- /dev/null
+++ b/src/plugins/mcusupport/mcutargetfactorylegacy.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "mcutargetfactorylegacy.h"
+#include "mcuhelpers.h"
+#include "mcupackage.h"
+#include "mcusupportsdk.h"
+#include "mcusupportversiondetection.h"
+#include "mcutarget.h"
+#include "mcutargetdescription.h"
+
+#include <utils/fileutils.h>
+#include <QVersionNumber>
+
+namespace McuSupport::Internal {
+
+McuTargetFactoryLegacy::McuTargetFactoryLegacy(
+ const QHash<QString, ToolchainCompilerCreator> &toolchainCreators,
+ const QHash<QString, McuPackagePtr> &toolchainFiles,
+ const QHash<QString, McuPackagePtr> &vendorPkgs,
+ const SettingsHandler::Ptr &settingsHandler)
+ : toolchainCreators(toolchainCreators)
+ , toolchainFiles(toolchainFiles)
+ , vendorPkgs(vendorPkgs)
+ , settingsHandler(settingsHandler)
+{}
+
+QPair<Targets, Packages> McuTargetFactoryLegacy::createTargets(const Sdk::McuTargetDescription &desc,
+ const Utils::FilePath &qtForMcuPath)
+{
+ QHash<QString, McuPackagePtr> boardSdkPkgs;
+ QHash<QString, McuPackagePtr> freeRTOSPkgs;
+ Targets mcuTargets;
+ Packages packages;
+ McuToolChainPackagePtr toolchainPackage = getToolchainCompiler(desc.toolchain);
+ McuPackagePtr toolchainFilePackage = getToolchainFile(qtForMcuPath, desc.toolchain.id);
+ for (int colorDepth : desc.platform.colorDepths) {
+ Packages required3rdPartyPkgs;
+ // Desktop toolchains don't need any additional settings
+ if (toolchainPackage && !toolchainPackage->isDesktopToolchain()
+ && toolchainPackage->toolchainType()
+ != McuToolChainPackage::ToolChainType::Unsupported) {
+ required3rdPartyPkgs.insert(toolchainPackage);
+ }
+
+ // Add setting specific to platform IDE.
+ if (vendorPkgs.contains(desc.platform.vendor)) {
+ required3rdPartyPkgs.insert(vendorPkgs.value(desc.platform.vendor));
+ }
+
+ // Board SDK specific settings
+ Utils::FilePath boardSdkDefaultPath;
+ if (!desc.boardSdk.envVar.isEmpty()) {
+ if (!boardSdkPkgs.contains(desc.boardSdk.envVar)) {
+ McuPackagePtr boardSdkPkg{createBoardSdkPackage(settingsHandler, desc)};
+ boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg);
+ }
+ McuPackagePtr boardSdkPkg{boardSdkPkgs.value(desc.boardSdk.envVar)};
+ boardSdkPkg->setVersions(desc.boardSdk.versions);
+ boardSdkDefaultPath = boardSdkPkg->defaultPath();
+ required3rdPartyPkgs.insert(boardSdkPkg);
+ }
+
+ // Free RTOS specific settings.
+ if (!desc.freeRTOS.envVar.isEmpty()) {
+ if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) {
+ freeRTOSPkgs
+ .insert(desc.freeRTOS.envVar,
+ McuPackagePtr{
+ Sdk::createFreeRTOSSourcesPackage(settingsHandler,
+ desc.freeRTOS.envVar,
+ boardSdkDefaultPath,
+ desc.freeRTOS.boardSdkSubDir)});
+ }
+ required3rdPartyPkgs.insert(freeRTOSPkgs.value(desc.freeRTOS.envVar));
+ }
+
+ packages.unite(required3rdPartyPkgs);
+ const McuTarget::Platform platform(
+ {desc.platform.id, desc.platform.name, desc.platform.vendor});
+ mcuTargets.append(McuTargetPtr{new McuTarget{QVersionNumber::fromString(desc.qulVersion),
+ platform,
+ deduceOperatingSystem(desc),
+ required3rdPartyPkgs,
+ toolchainPackage,
+ toolchainFilePackage,
+ colorDepth}});
+ }
+ return {mcuTargets, packages};
+}
+
+McuAbstractTargetFactory::AdditionalPackages McuTargetFactoryLegacy::getAdditionalPackages() const
+{
+ return {{}, vendorPkgs};
+}
+
+McuToolChainPackagePtr McuTargetFactoryLegacy::getToolchainCompiler(
+ const Sdk::McuTargetDescription::Toolchain &desc) const
+{
+ auto compilerCreator = toolchainCreators.value(desc.id, [this] {
+ return McuToolChainPackagePtr{Sdk::createUnsupportedToolChainPackage(settingsHandler)};
+ });
+ McuToolChainPackagePtr toolchainPackage = compilerCreator();
+ toolchainPackage->setVersions(desc.versions);
+ return toolchainPackage;
+}
+
+McuPackagePtr McuTargetFactoryLegacy::getToolchainFile(const Utils::FilePath &qtForMCUSdkPath,
+ const QString &toolchainName) const
+{
+ if (McuPackagePtr toolchainFile = toolchainFiles.value(toolchainName); toolchainFile) {
+ return toolchainFile;
+ } else {
+ return McuPackagePtr{
+ Sdk::createUnsupportedToolChainFilePackage(settingsHandler, qtForMCUSdkPath)};
+ }
+}
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/mcutargetfactorylegacy.h b/src/plugins/mcusupport/mcutargetfactorylegacy.h
new file mode 100644
index 00000000000..9a08bff83d8
--- /dev/null
+++ b/src/plugins/mcusupport/mcutargetfactorylegacy.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "mcuabstracttargetfactory.h"
+#include "mcutargetdescription.h"
+#include "settingshandler.h"
+
+#include <functional>
+#include <QHash>
+#include <QPair>
+
+namespace McuSupport::Internal {
+
+class McuPackage;
+
+using ToolchainCompilerCreator = std::function<McuToolChainPackagePtr()>;
+
+class McuTargetFactoryLegacy : public McuAbstractTargetFactory
+{
+public:
+ McuTargetFactoryLegacy(const QHash<QString, ToolchainCompilerCreator> &toolchainCreators,
+ const QHash<QString, McuPackagePtr> &toolchainFiles,
+ const QHash<QString, McuPackagePtr> &vendorPkgs,
+ const SettingsHandler::Ptr &);
+
+ QPair<Targets, Packages> createTargets(const Sdk::McuTargetDescription &,
+ const Utils::FilePath &qtForMCUSdkPath) override;
+ AdditionalPackages getAdditionalPackages() const override;
+
+ McuToolChainPackagePtr getToolchainCompiler(const Sdk::McuTargetDescription::Toolchain &) const;
+ McuPackagePtr getToolchainFile(const Utils::FilePath &qtForMCUSdkPath,
+ const QString &toolchainName) const;
+
+private:
+ QHash<QString, ToolchainCompilerCreator> toolchainCreators;
+ const QHash<QString, McuPackagePtr> toolchainFiles;
+ const QHash<QString, McuPackagePtr> vendorPkgs;
+
+ SettingsHandler::Ptr settingsHandler;
+}; // struct McuTargetFactoryLegacy
+
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/settingshandler.cpp b/src/plugins/mcusupport/settingshandler.cpp
new file mode 100644
index 00000000000..4b2188150d6
--- /dev/null
+++ b/src/plugins/mcusupport/settingshandler.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "settingshandler.h"
+
+#include "mcusupportconstants.h"
+#include "mcusupportsdk.h"
+
+#include <coreplugin/icore.h>
+#include <utils/filepath.h>
+
+namespace McuSupport::Internal {
+
+using Utils::FilePath;
+
+namespace {
+const QString automaticKitCreationSettingsKey = QLatin1String(Constants::SETTINGS_GROUP) + '/'
+ + QLatin1String(
+ Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION);
+}
+
+static FilePath packagePathFromSettings(const QString &settingsKey,
+ QSettings &settings,
+ const FilePath &defaultPath)
+{
+ const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/'
+ + QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + settingsKey;
+ const QString path = settings.value(key, defaultPath.toUserOutput()).toString();
+ return FilePath::fromUserInput(path);
+}
+
+FilePath SettingsHandler::getPath(const QString &settingsKey,
+ QSettings::Scope scope,
+ const Utils::FilePath &defaultPath) const
+{
+ return packagePathFromSettings(settingsKey, *Core::ICore::settings(scope), defaultPath);
+}
+
+bool SettingsHandler::write(const QString &settingsKey,
+ const Utils::FilePath &path,
+ const Utils::FilePath &defaultPath) const
+{
+ const FilePath savedPath = packagePathFromSettings(settingsKey,
+ *Core::ICore::settings(QSettings::UserScope),
+ defaultPath);
+ const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/'
+ + QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + settingsKey;
+ Core::ICore::settings()->setValueWithDefault(key,
+ path.toUserOutput(),
+ defaultPath.toUserOutput());
+
+ return savedPath != path;
+}
+
+bool SettingsHandler::isAutomaticKitCreationEnabled() const
+{
+ QSettings *settings = Core::ICore::settings(QSettings::UserScope);
+ const bool automaticKitCreation = settings->value(automaticKitCreationSettingsKey, true).toBool();
+ return automaticKitCreation;
+}
+
+void SettingsHandler::setAutomaticKitCreation(bool isEnabled)
+{
+ QSettings *settings = Core::ICore::settings(QSettings::UserScope);
+ settings->setValue(automaticKitCreationSettingsKey, isEnabled);
+}
+
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/settingshandler.h b/src/plugins/mcusupport/settingshandler.h
new file mode 100644
index 00000000000..495716352ec
--- /dev/null
+++ b/src/plugins/mcusupport/settingshandler.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+#pragma once
+
+#include <QSettings>
+#include <QSharedPointer>
+#include <QString>
+
+namespace Utils {
+class FilePath;
+} //namespace Utils
+
+namespace McuSupport::Internal {
+
+class SettingsHandler
+{
+public:
+ using Ptr = QSharedPointer<SettingsHandler>;
+ virtual ~SettingsHandler() = default;
+ virtual Utils::FilePath getPath(const QString &settingsKey,
+ QSettings::Scope scope,
+ const Utils::FilePath &m_defaultPath) const;
+
+ virtual bool write(const QString &settingsKey,
+ const Utils::FilePath &path,
+ const Utils::FilePath &defaultPath) const;
+
+ virtual bool isAutomaticKitCreationEnabled() const;
+ void setAutomaticKitCreation(bool isEnabled);
+}; //class SettingsHandler
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/test/CMakeLists.txt b/src/plugins/mcusupport/test/CMakeLists.txt
index 8e693fd3e1e..2df4faa891d 100644
--- a/src/plugins/mcusupport/test/CMakeLists.txt
+++ b/src/plugins/mcusupport/test/CMakeLists.txt
@@ -6,7 +6,7 @@ if(TARGET Googletest)
CONDITION WITH_TESTS
DEPENDS Googletest
SOURCES
- unittest.h unittest.cpp packagemock.h
+ unittest.h unittest.cpp packagemock.h settingshandlermock.h
)
else()
message("Googletest target is missing")
diff --git a/src/plugins/mcusupport/test/armgcc_nxp_1050_json.h b/src/plugins/mcusupport/test/armgcc_nxp_1050_json.h
new file mode 100644
index 00000000000..a45175e93ec
--- /dev/null
+++ b/src/plugins/mcusupport/test/armgcc_nxp_1050_json.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+constexpr auto armgcc_nxp_1050_json = R"({
+ "qulVersion": "2.0.0",
+ "compatVersion": "1",
+ "platform": {
+ "id": "MIMXRT1050-EVK-FREERTOS",
+ "vendor": "NXP",
+ "colorDepths": [
+ 16
+ ],
+ "pathEntries": [],
+ "environmentEntries": [],
+ "cmakeEntries": [
+ {
+ "id": "Qul_DIR",
+ "label": "Qt for MCUs SDK",
+ "type": "path",
+ "cmakeVar": "Qul_ROOT",
+ "envVar": "Qul_DIR",
+ "optional": false
+ },
+ {
+ "id": "MCU_XPRESSO_PATH",
+ "label": "MCUXpresso IDE",
+ "type": "path",
+ "cmakeVar": "MCUXPRESSO_IDE_PATH",
+ "defaultValue": {
+ "windows": "$ROOT/nxp/MCUXpressoIDE*",
+ "unix": "/usr/local/mcuxpressoide/"
+ },
+ "optional": false
+ }
+ ]
+ },
+ "toolchain": {
+ "id": "armgcc",
+ "versions": [
+ "9.3.1"
+ ],
+ "compiler": {
+ "id": "ARMGCC_DIR",
+ "label": "GNU Arm Embedded Toolchain",
+ "cmakeVar": "QUL_TARGET_TOOLCHAIN_DIR",
+ "envVar": "ARMGCC_DIR",
+ "setting": "GNUArmEmbeddedToolchain",
+ "type": "path",
+ "optional": false
+ },
+ "file": {
+ "id": "ARMGCC_CMAKE_TOOLCHAIN_FILE",
+ "label": "CMake Toolchain File",
+ "cmakeVar": "CMAKE_TOOLCHAIN_FILE",
+ "type": "file",
+ "defaultValue": "/opt/qtformcu/2.2/lib/cmake/Qul/toolchain/armgcc.cmake",
+ "visible": false,
+ "optional": false
+ }
+ },
+ "boardSdk": {
+ "envVar": "EVKB_IMXRT1050_SDK_PATH",
+ "versions": [
+ "2.10.0"
+ ],
+ "cmakeEntries": [
+ {
+ "id": "NXP_SDK_DIR",
+ "label": "Board SDK for MIMXRT1050-EVK",
+ "cmakeVar": "QUL_BOARD_SDK_DIR",
+ "type": "path",
+ "optional": false
+ }
+ ]
+ },
+ "freeRTOS": {
+ "envVar": "IMXRT1050_FREERTOS_DIR",
+ "cmakeEntries": [
+ {
+ "id": "NXP_FREERTOS_DIR",
+ "label": "FreeRTOS SDK for MIMXRT1050-EVK",
+ "cmakeVar": "FREERTOS_DIR",
+ "defaultValue": "$QUL_BOARD_SDK_DIR/rtos/freertos/freertos_kernel",
+ "type": "path",
+ "optional": false
+ }
+ ]
+ }
+})";
diff --git a/src/plugins/mcusupport/test/armgcc_nxp_mimxrt1170_evk_freertos_json.h b/src/plugins/mcusupport/test/armgcc_nxp_mimxrt1170_evk_freertos_json.h
new file mode 100644
index 00000000000..b4057e84489
--- /dev/null
+++ b/src/plugins/mcusupport/test/armgcc_nxp_mimxrt1170_evk_freertos_json.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+constexpr auto armgcc_nxp_mimxrt1170_evk_freertos_json = R"({
+ "qulVersion": "2.1.5",
+ "compatVersion": "1",
+ "platform": {
+ "id": "MIMXRT1170-EVK-FREERTOS",
+ "vendor": "NXP",
+ "colorDepths": [
+ 32
+ ],
+ "pathEntries": [],
+ "environmentEntries": [],
+ "cmakeEntries": [
+ {
+ "id": "Qul_DIR",
+ "description": "Qt for MCUs SDK",
+ "type": "path",
+ "cmakeVar": "Qul_ROOT",
+ "optional": false
+ },
+ {
+ "id": "MCU_XPRESSO_PATH",
+ "description": "MCUXpresso IDE",
+ "type": "path",
+ "cmakeVar": "MCUXPRESSO_IDE_PATH",
+ "defaultValue": {
+ "windows": "$ROOT/nxp/MCUXpressoIDE*",
+ "unix": "/usr/local/mcuxpressoide/"
+ },
+ "optional": false
+ }
+ ]
+ },
+ "toolchain": {
+ "id": "armgcc",
+ "versions": [
+ "9.3.1"
+ ],
+ "compiler": {
+ "id": "ARMGCC_DIR",
+ "label": "GNU Arm Embedded Toolchain",
+ "description": "GNU Arm Embedded Toolchain",
+ "cmakeVar": "QUL_TARGET_TOOLCHAIN_DIR",
+ "envVar": "ARMGCC_DIR",
+ "setting": "GNUArmEmbeddedToolchain",
+ "type": "path",
+ "optional": false
+ },
+ "file": {
+ "id": "ARMGCC_CMAKE_TOOLCHAIN_FILE",
+ "label": "CMake Toolchain File",
+ "description": "CMake Toolchain File",
+ "cmakeVar": "CMAKE_TOOLCHAIN_FILE",
+ "type": "file",
+ "defaultValue": "/opt/qtformcu/2.2//lib/cmake/Qul/toolchain/armgcc.cmake",
+ "visible": false,
+ "optional": false
+ }
+ },
+ "boardSdk": {
+ "envVar": "EVK_MIMXRT1170_SDK_PATH",
+ "versions": [
+ "2.10.1"
+ ],
+ "cmakeEntries": [
+ {
+ "id": "NXP_SDK_DIR",
+ "description": "Board SDK for MIMXRT1170-EVK",
+ "cmakeVar": "QUL_BOARD_SDK_DIR",
+ "type": "path",
+ "optional": false
+ }
+ ]
+ },
+ "freeRTOS": {
+ "envVar": "EVK_MIMXRT1170_FREERTOS_PATH",
+ "cmakeEntries": [
+ {
+ "id": "NXP_FREERTOS_DIR",
+ "description": "FreeRTOS SDK for MIMXRT1170-EVK",
+ "cmakeVar": "FREERTOS_DIR",
+ "defaultValue": "$QUL_BOARD_SDK_DIR/rtos/freertos/freertos_kernel",
+ "type": "path",
+ "optional": false
+ }
+ ]
+ }
+})";
diff --git a/src/plugins/mcusupport/test/armgcc_stm32f769i_freertos_json.h b/src/plugins/mcusupport/test/armgcc_stm32f769i_freertos_json.h
new file mode 100644
index 00000000000..df260db98dc
--- /dev/null
+++ b/src/plugins/mcusupport/test/armgcc_stm32f769i_freertos_json.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+constexpr auto armgcc_stm32f769i_freertos_json = R"({
+ "qulVersion": "@CMAKE_PROJECT_VERSION@",
+ "compatVersion": "@COMPATIBILITY_VERSION@",
+ "platform": {
+ "id": "STM32F769I-DISCOVERY-FREERTOS",
+ "vendor": "ST",
+ "colorDepths": [
+ 32
+ ],
+ "pathEntries": [
+ {
+ "id": "STM32CubeProgrammer_PATH",
+ "id": "STM32CubeProgrammer_PATH",
+ "label": "STM32CubeProgrammer",
+ "type": "path",
+ "defaultValue": {
+ "windows": "$PROGRAMSANDFILES/STMicroelectronics/STM32Cube/STM32CubeProgrammer/",
+ "unix": "$HOME/STMicroelectronics/STM32Cube/STM32CubeProgrammer/"
+ },
+ "optional": false
+ }
+ ],
+ "environmentEntries": [],
+ "cmakeEntries": [
+ {
+ "id": "Qul_DIR",
+ "label": "Qt for MCUs SDK",
+ "type": "path",
+ "cmakeVar": "Qul_ROOT",
+ "optional": false
+ }
+ ]
+ },
+ "toolchain": {
+ "id": "armgcc",
+ "versions": [
+ "9.3.1"
+ ],
+ "compiler": {
+ "id": "ARMGCC_DIR",
+ "label": "GNU Arm Embedded Toolchain",
+ "cmakeVar": "QUL_TARGET_TOOLCHAIN_DIR",
+ "envVar": "ARMGCC_DIR",
+ "setting": "GNUArmEmbeddedToolchain",
+ "type": "path",
+ "optional": false
+ },
+ "file": {
+ "id": "ARMGCC_CMAKE_TOOLCHAIN_FILE",
+ "label": "CMake Toolchain File",
+ "cmakeVar": "CMAKE_TOOLCHAIN_FILE",
+ "type": "file",
+ "defaultValue": "/opt/qtformcu/2.2//lib/cmake/Qul/toolchain/armgcc.cmake",
+ "visible": false,
+ "optional": false
+ }
+ },
+ "boardSdk": {
+ "envVar": "STM32Cube_FW_F7_SDK_PATH",
+ "versions": [
+ "1.16.0"
+ ],
+ "cmakeEntries": [
+ {
+ "id": "ST_SDK_DIR",
+ "label": "Board SDK for STM32F769I-Discovery",
+ "cmakeVar": "QUL_BOARD_SDK_DIR",
+ "type": "path",
+ "optional": false
+ }
+ ]
+ },
+ "freeRTOS": {
+ "envVar": "STM32F7_FREERTOS_DIR",
+ "cmakeEntries": [
+ {
+ "id": "ST_FREERTOS_DIR",
+ "label": "FreeRTOS SDK for STM32F769I-Discovery",
+ "cmakeVar": "FREERTOS_DIR",
+ "defaultValue": "$QUL_BOARD_SDK_DIR/Middlewares/Third_Party/FreeRTOS/Source",
+ "type": "path",
+ "optional": false
+ }
+ ]
+ }
+})";
diff --git a/src/plugins/mcusupport/test/armgcc_stm32h750b_metal_json.h b/src/plugins/mcusupport/test/armgcc_stm32h750b_metal_json.h
new file mode 100644
index 00000000000..03545fb83c9
--- /dev/null
+++ b/src/plugins/mcusupport/test/armgcc_stm32h750b_metal_json.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+constexpr auto armgcc_stm32h750b_metal_json = R"({
+ "qulVersion": "2.0.0",
+ "compatVersion": "1",
+ "platform": {
+ "id": "STM32H750B-DISCOVERY-BAREMETAL",
+ "vendor": "ST",
+ "colorDepths": [
+ 32
+ ],
+ "pathEntries": [
+ {
+ "id": "STM32CubeProgrammer_PATH",
+ "label": "STM32CubeProgrammer",
+ "type": "path",
+ "defaultValue": {
+ "windows": "$PROGRAMSANDFILES/STMicroelectronics/STM32Cube/STM32CubeProgrammer/",
+ "unix": "$HOME/STMicroelectronics/STM32Cube/STM32CubeProgrammer/"
+ },
+ "optional": false
+ }
+ ],
+ "environmentEntries": [],
+ "cmakeEntries": [
+ {
+ "id": "Qul_DIR",
+ "label": "Qt for MCUs SDK",
+ "type": "path",
+ "cmakeVar": "Qul_ROOT",
+ "optional": false
+ }
+ ]
+ },
+ "toolchain": {
+ "id": "armgcc",
+ "versions": [
+ "9.3.1"
+ ],
+ "compiler": {
+ "id": "ARMGCC_DIR",
+ "label": "GNU Arm Embedded Toolchain",
+ "cmakeVar": "QUL_TARGET_TOOLCHAIN_DIR",
+ "envVar": "ARMGCC_DIR",
+ "setting": "GNUArmEmbeddedToolchain",
+ "type": "path",
+ "optional": false
+ },
+ "file" : {
+ "id": "ARMGCC_CMAKE_TOOLCHAIN_FILE",
+ "label": "CMake Toolchain File",
+ "cmakeVar": "CMAKE_TOOLCHAIN_FILE",
+ "type": "file",
+ "defaultValue": "/opt/qtformcu/2.2//lib/cmake/Qul/toolchain/armgcc.cmake",
+ "visible": false,
+ "optional": false
+ }
+ },
+ "boardSdk": {
+ "envVar": "STM32Cube_FW_H7_SDK_PATH",
+ "versions": [
+ "1.5.0"
+ ],
+ "cmakeEntries": [
+ {
+ "id": "ST_SDK_DIR",
+ "label": "Board SDK for STM32H750B-Discovery",
+ "cmakeVar": "QUL_BOARD_SDK_DIR",
+ "type": "path",
+ "optional": false
+ }
+ ]
+ }
+})";
diff --git a/src/plugins/mcusupport/test/gcc_desktop_json.h b/src/plugins/mcusupport/test/gcc_desktop_json.h
new file mode 100644
index 00000000000..f66e50d1bc5
--- /dev/null
+++ b/src/plugins/mcusupport/test/gcc_desktop_json.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+constexpr auto gcc_desktop_json = R"({
+ "qulVersion": "@CMAKE_PROJECT_VERSION@",
+ "compatVersion": "@COMPATIBILITY_VERSION@",
+ "platform": {
+ "id": "Qt",
+ "platformName": "Desktop",
+ "vendor": "Qt",
+ "colorDepths": [
+ 32
+ ],
+ "pathEntries": [
+ ],
+ "environmentEntries": [
+ ],
+ "cmakeEntries": [
+ {
+ "id": "Qul_DIR",
+ "label": "Qt for MCUs SDK",
+ "type": "path",
+ "cmakeVar": "Qul_ROOT",
+ "optional": false
+ }
+ ]
+ },
+ "toolchain": {
+ "id": "gcc"
+ }
+})";
diff --git a/src/plugins/mcusupport/test/ghs_rh850_d1m1a_baremetal_json.h b/src/plugins/mcusupport/test/ghs_rh850_d1m1a_baremetal_json.h
new file mode 100644
index 00000000000..3a46fe8e17a
--- /dev/null
+++ b/src/plugins/mcusupport/test/ghs_rh850_d1m1a_baremetal_json.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+constexpr auto ghs_rh850_d1m1a_baremetal_json = R"({
+ "qulVersion": "2.1.5",
+ "compatVersion": "1",
+ "platform": {
+ "id": "RH850-D1M1A-BAREMETAL",
+ "vendor": "RENESAS",
+ "colorDepths": [
+ 32
+ ],
+ "pathEntries": [],
+ "environmentEntries": [],
+ "cmakeEntries": [
+ {
+ "id": "Qul_DIR",
+ "description": "Qt for MCUs SDK",
+ "type": "path",
+ "cmakeVar": "Qul_ROOT",
+ "optional": false
+ }
+ ]
+ },
+ "toolchain": {
+ "id": "greenhills",
+ "versions": [
+ "2018.1.5"
+ ],
+ "compiler": {
+ "description": "Green Hills Compiler",
+ "cmakeVar": "QUL_TARGET_TOOLCHAIN_DIR",
+ "setting": "GHSToolchain",
+ "label": "Green Hills Compiler",
+ "type": "path",
+ "optional": false
+ },
+ "file": {
+ "description": "CMake Toolchain File",
+ "cmakeVar": "CMAKE_TOOLCHAIN_FILE",
+ "type": "file",
+ "defaultValue": "/opt/qtformcu/2.2/lib/cmake/Qul/toolchain/ghs.cmake",
+ "visible": false,
+ "optional": false
+ }
+ },
+ "boardSdk": {
+ "envVar": "RGL_DIR",
+ "versions": [
+ "2.0.0a"
+ ],
+ "cmakeEntries": [
+ {
+ "id": "RGL_DIR",
+ "description": "Renesas Graphics Library",
+ "cmakeVar": "QUL_BOARD_SDK_DIR",
+ "type": "path",
+ "defaultValue": "/Renesas_Electronics/D1x_RGL/rgl_ghs_D1Mx_obj_V.2.0.0a",
+ "optional": false
+ }
+ ]
+ }
+})";
diff --git a/src/plugins/mcusupport/test/iar_nxp_1064_json.h b/src/plugins/mcusupport/test/iar_nxp_1064_json.h
new file mode 100644
index 00000000000..35eb13517f3
--- /dev/null
+++ b/src/plugins/mcusupport/test/iar_nxp_1064_json.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+constexpr auto iar_nxp_1064_json = R"({
+ "compatVersion": "1",
+ "qulVersion": "2.0.0",
+ "boardSdk": {
+ "cmakeEntries": [
+ {
+ "cmakeVar": "QUL_BOARD_SDK_DIR",
+ "label": "Board SDK for MIMXRT1064-EVK",
+ "id": "NXP_SDK_DIR",
+ "optional": false,
+ "type": "path",
+ "versions": ["2.10.0"]
+ }
+ ],
+ "envVar": "EVK_MIMXRT1064_SDK_PATH",
+ "versions": ["2.10.0"]
+ },
+ "freeRTOS": {
+ "cmakeEntries": [
+ {
+ "envVar": "IMXRT1064_FREERTOS_DIR",
+ "cmakeVar": "FREERTOS_DIR",
+ "defaultValue": "$QUL_BOARD_SDK_DIR/rtos/freertos/freertos_kernel",
+ "label": "FreeRTOS Sources (IMXRT1064) ",
+ "label": "FreeRTOS SDK for MIMXRT1064-EVK",
+ "id": "NXP_FREERTOS_DIR",
+ "optional": false,
+ "type": "path"
+ }
+ ],
+ "envVar": "IMXRT1064_FREERTOS_DIR"
+ },
+ "platform": {
+ "cmakeEntries": [
+ {
+ "cmakeVar": "Qul_ROOT",
+ "label": "Qt for MCUs SDK",
+ "id": "Qul_DIR",
+ "optional": false,
+ "type": "path"
+ },
+ {
+ "cmakeVar": "MCUXPRESSO_IDE_PATH",
+ "defaultValue": {
+ "unix": "/usr/local/mcuxpressoide/",
+ "windows": "$ROOT/nxp/MCUXpressoIDE*"
+ }
+ }
+ ],
+ "colorDepths": [16],
+ "environmentEntries": [],
+ "id": "MIMXRT1064-EVK-FREERTOS",
+ "pathEntries": [],
+ "vendor": "NXP"
+ },
+ "toolchain": {
+ "id": "iar",
+ "versions": ["8.50.9"],
+ "compiler": {
+ "id": "IAR_DIR",
+ "cmakeVar": "QUL_TARGET_TOOLCHAIN_DIR",
+ "setting": "IARToolchain",
+ "envVar": "IAR_ARM_COMPILER_DIR",
+ "label": "IAR ARM Compiler",
+ "optional": false,
+ "type": "path"
+ },
+ "file": {
+ "id": "IAR_CMAKE_TOOLCHAIN_FILE",
+ "label": "CMake Toolchain File",
+ "cmakeVar": "CMAKE_TOOLCHAIN_FILE",
+ "type": "file",
+ "defaultValue": "/opt/qtformcu/2.2//lib/cmake/Qul/toolchain/iar.cmake",
+ "visible": false,
+ "optional": false
+ }
+ }
+})";
diff --git a/src/plugins/mcusupport/test/iar_stm32f469i_metal_json.h b/src/plugins/mcusupport/test/iar_stm32f469i_metal_json.h
new file mode 100644
index 00000000000..639ece61af2
--- /dev/null
+++ b/src/plugins/mcusupport/test/iar_stm32f469i_metal_json.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+constexpr auto iar_stm32f469i_metal_json = R"({
+ "qulVersion": "@CMAKE_PROJECT_VERSION@",
+ "compatVersion": "@COMPATIBILITY_VERSION@",
+ "platform": {
+ "id": "STM32F469I-DISCOVERY-BAREMETAL",
+ "vendor": "ST",
+ "colorDepths": [
+ 24
+ ],
+ "pathEntries": [
+ {
+ "id": "STM32CubeProgrammer_PATH",
+ "label": "STM32CubeProgrammer",
+ "type": "path",
+ "defaultValue": {
+ "windows": "$PROGRAMSANDFILES/STMicroelectronics/STM32Cube/STM32CubeProgrammer/",
+ "unix": "$HOME/STMicroelectronics/STM32Cube/STM32CubeProgrammer/"
+ },
+ "optional": false
+ }
+ ],
+ "environmentEntries": [],
+ "cmakeEntries": [
+ {
+ "id": "Qul_DIR",
+ "label": "Qt for MCUs SDK",
+ "type": "path",
+ "cmakeVar": "Qul_ROOT",
+ "optional": false
+ }
+ ]
+ },
+ "toolchain": {
+ "id": "iar",
+ "versions": [
+ "8.50.9"
+ ],
+ "compiler": {
+ "id": "IARToolchain",
+ "setting": "IARToolchain",
+ "envVar": "IAR_ARM_COMPILER_DIR",
+ "label": "IAR ARM Compiler",
+ "cmakeVar": "QUL_TARGET_TOOLCHAIN_DIR",
+ "type": "path",
+ "optional": false
+ },
+ "file": {
+ "id": "IAR_CMAKE_TOOLCHAIN_FILE",
+ "label": "CMake Toolchain File",
+ "cmakeVar": "CMAKE_TOOLCHAIN_FILE",
+ "type": "file",
+ "defaultValue": "/opt/qtformcu/2.2//lib/cmake/Qul/toolchain/iar.cmake",
+ "visible": false,
+ "optional": false
+ }
+ },
+ "boardSdk": {
+ "envVar": "STM32Cube_FW_F4_SDK_PATH",
+ "versions": [
+ "1.25.0"
+ ],
+ "cmakeEntries": [
+ {
+ "id": "ST_SDK_DIR",
+ "label": "Board SDK for STM32F469I-Discovery",
+ "cmakeVar": "QUL_BOARD_SDK_DIR",
+ "type": "path",
+ "optional": false
+ }
+ ]
+ }
+})";
diff --git a/src/plugins/mcusupport/test/nxp_1064_json.h b/src/plugins/mcusupport/test/nxp_1064_json.h
deleted file mode 100644
index 4e8f53afa96..00000000000
--- a/src/plugins/mcusupport/test/nxp_1064_json.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-constexpr auto nxp_1064_json = R"({
- "boardSdk": {
- "cmakeCacheEntries": [
- {
- "cmakeOptionName": "QUL_BOARD_SDK_DIR",
- "description": "Board SDK for MIMXRT1064-EVK",
- "id": "NXP_SDK_DIR",
- "optional": false,
- "type": "path"
- }
- ],
- "envVar": "EVK_MIMXRT1064_SDK_PATH",
- "versions": ["2.10.0"]
- },
- "compatVersion": "1",
- "freeRTOS": {
- "cmakeCacheEntries": [
- {
- "cmakeOptionName": "FREERTOS_DIR",
- "defaultValue": "$QUL_BOARD_SDK_DIR/rtos/freertos/freertos_kernel",
- "description": "FreeRTOS SDK for MIMXRT1064-EVK",
- "id": "NXP_FREERTOS_DIR",
- "optional": false,
- "type": "path"
- }
- ],
- "envVar": "IMXRT1064_FREERTOS_DIR"
- },
- "platform": {
- "cmakeCacheEntries": [
- {
- "cmakeOptionName": "Qul_ROOT",
- "description": "Qt for MCUs SDK",
- "id": "Qul_DIR",
- "optional": false,
- "type": "path"
- },
- {
- "cmakeOptionName": "MCUXPRESSO_IDE_PATH",
- "defaultValue": {
- "unix": "/usr/local/mcuxpressoide/",
- "windows": "$ROOT/nxp/MCUXpressoIDE*"
- }
- }
- ],
- "colorDepths": [16],
- "environmentEntries": [],
- "id": "MIMXRT1064-EVK-FREERTOS",
- "pathEntries": [],
- "vendor": "NXP"
- },
- "qulVersion": "2.0.0",
- "toolchain": {
- "cmakeCacheEntries": [
- {
- "cmakeOptionName": "QUL_TARGET_TOOLCHAIN_DIR",
- "description": "IAR ARM Compiler",
- "id": "IAR_DIR",
- "optional": false,
- "type": "path"
- }
- ],
- "id": "iar",
- "versions": ["8.50.9"]
- }
-})";
diff --git a/src/plugins/mcusupport/test/packagemock.h b/src/plugins/mcusupport/test/packagemock.h
index 2e41ef6550b..34157eb19b4 100644
--- a/src/plugins/mcusupport/test/packagemock.h
+++ b/src/plugins/mcusupport/test/packagemock.h
@@ -42,10 +42,12 @@ public:
MOCK_METHOD(Utils::FilePath, detectionPath, (), (const));
MOCK_METHOD(QString, statusText, (), (const));
MOCK_METHOD(void, updateStatus, ());
+ MOCK_METHOD(QString, settingsKey, (), (const));
MOCK_METHOD(Status, status, (), (const));
MOCK_METHOD(bool, isValidStatus, (), (const));
- MOCK_METHOD(const QString &, environmentVariableName, (), (const));
+ MOCK_METHOD(QString, cmakeVariableName, (), (const));
+ MOCK_METHOD(QString, environmentVariableName, (), (const));
MOCK_METHOD(bool, isAddToSystemPath, (), (const));
MOCK_METHOD(bool, writeToSettings, (), (const));
MOCK_METHOD(void, setVersions, (const QStringList &) );
diff --git a/src/plugins/mcusupport/test/settingshandlermock.h b/src/plugins/mcusupport/test/settingshandlermock.h
new file mode 100644
index 00000000000..ac48dd04dd2
--- /dev/null
+++ b/src/plugins/mcusupport/test/settingshandlermock.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+#pragma once
+
+#include "settingshandler.h"
+
+#include <gmock/gmock.h>
+#include <utils/filepath.h>
+
+namespace McuSupport::Internal {
+
+class SettingsHandlerMock : public SettingsHandler
+{
+public:
+ SettingsHandlerMock() = default;
+ ~SettingsHandlerMock() override = default;
+ MOCK_METHOD(Utils::FilePath,
+ getPath,
+ (const QString &, QSettings::Scope, const Utils::FilePath &),
+ (const, override));
+ MOCK_METHOD(bool,
+ write,
+ (const QString &, const Utils::FilePath &, const Utils::FilePath &),
+ (const, override));
+}; //class SettingsHandler
+} // namespace McuSupport::Internal
diff --git a/src/plugins/mcusupport/test/unittest.cpp b/src/plugins/mcusupport/test/unittest.cpp
index 62b8fd9c278..259ea35bf97 100644
--- a/src/plugins/mcusupport/test/unittest.cpp
+++ b/src/plugins/mcusupport/test/unittest.cpp
@@ -24,49 +24,642 @@
****************************************************************************/
#include "unittest.h"
-#include "mcutargetdescription.h"
+
+#include "armgcc_nxp_1050_json.h"
+#include "armgcc_nxp_mimxrt1170_evk_freertos_json.h"
+#include "armgcc_stm32f769i_freertos_json.h"
+#include "armgcc_stm32h750b_metal_json.h"
+#include "gcc_desktop_json.h"
+#include "ghs_rh850_d1m1a_baremetal_json.h"
+#include "iar_nxp_1064_json.h"
+#include "iar_stm32f469i_metal_json.h"
+
+#include "mcuhelpers.h"
#include "mcukitmanager.h"
-#include "nxp_1064_json.h"
-#include "utils/filepath.h"
+#include "mculegacyconstants.h"
+#include "mcusupportconstants.h"
+#include "mcusupportoptions.h"
+#include "mcusupportsdk.h"
+#include "mcusupportversiondetection.h"
+#include "mcutargetdescription.h"
+#include "mcutargetfactorylegacy.h"
+
+#include <baremetal/baremetalconstants.h>
#include <cmakeprojectmanager/cmakeconfigitem.h>
#include <cmakeprojectmanager/cmakekitinformation.h>
+#include <gmock/gmock-actions.h>
#include <gmock/gmock.h>
+
+#include <projectexplorer/customtoolchain.h>
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchainmanager.h>
+
+#include <utils/algorithm.h>
+#include <utils/filepath.h>
+
#include <QJsonArray>
#include <QJsonDocument>
+#include <QtTest>
+
+#include <algorithm>
namespace McuSupport::Internal::Test {
+namespace {
+const char empty[]{""};
+const char armGccDir[]{"/opt/armgcc"};
+const char armGccDirectorySetting[]{"GNUArmEmbeddedToolchain"};
+const char armGccEnvVar[]{"ARMGCC_DIR"};
+const char armGccLabel[]{"GNU Arm Embedded Toolchain"};
+const char armGccToolchainFilePath[]{"/opt/qtformcu/2.2/lib/cmake/Qul/toolchain/armgcc.cmake"};
+const char armGcc[]{"armgcc"};
+const char cmakeToolchainLabel[]{"CMake Toolchain File"};
+const char fallbackDir[]{"/abc/def/fallback"};
+const char freeRtosCMakeVar[]{"FREERTOS_DIR"};
+const char freeRtosDescription[]{"Freertos directory"};
+const char freeRtosEnvVar[]{"EVK_MIMXRT1170_FREERTOS_PATH"};
+const char freeRtosLabel[]{"FreeRTOS directory"};
+const char freeRtosPath[]{"/opt/freertos/default"};
+const char freeRtosSetting[]{"Freertos"};
+const char greenhillToolchainFilePath[]{"/opt/qtformcu/2.2/lib/cmake/Qul/toolchain/ghs.cmake"};
+const char greenhillCompilerDir[]{"/abs/ghs"};
+const char greenhillSetting[]{"GHSToolchain"};
+const char iarDir[]{"/opt/iar/compiler"};
+const char iarEnvVar[]{"IAR_ARM_COMPILER_DIR"};
+const char iarLabel[]{"IAR ARM Compiler"};
+const char iarSetting[]{"IARToolchain"};
+const char iarToolchainFilePath[]{"/opt/qtformcu/2.2/lib/cmake/Qul/toolchain/iar.cmake"};
+const char iar[]{"iar"};
+const char id[]{"target_id"};
+const char name[]{"target_name"};
+const char nxp1050FreeRtosEnvVar[]{"IMXRT1050_FREERTOS_DIR"};
+const char nxp1050[]{"IMXRT1050"};
+const char nxp1064FreeRtosEnvVar[]{"IMXRT1064_FREERTOS_DIR"};
+const char nxp1064[]{"IMXRT1064"};
+const char nxp1170FreeRtosEnvVar[]{"EVK_MIMXRT1170_FREERTOS_PATH"};
+const char nxp1170[]{"EVK_MIMXRT1170"};
+const char qtForMcuSdkPath[]{"/opt/qtformcu/2.2"};
+const char qulCmakeVar[]{"Qul_ROOT"};
+const char qulEnvVar[]{"Qul_DIR"};
+const char stm32f7FreeRtosEnvVar[]{"STM32F7_FREERTOS_DIR"};
+const char stm32f7[]{"STM32F7"};
+const char unsupported[]{"unsupported"};
+const char vendor[]{"target_vendor"};
+const QString settingsPrefix = QLatin1String(Constants::SETTINGS_GROUP) + '/'
+ + QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX);
+
+const QString unsupportedToolchainFilePath = QString{qtForMcuSdkPath}
+ + "/lib/cmake/Qul/toolchain/unsupported.cmake";
+
+const QStringList jsonFiles{QString::fromUtf8(armgcc_nxp_1050_json),
+ QString::fromUtf8(iar_nxp_1064_json)};
+
+const bool runLegacy{true};
+const int colorDepth{32};
+
+const Sdk::McuTargetDescription::Platform
+ platformDescription{id, "", "", {colorDepth}, Sdk::McuTargetDescription::TargetType::MCU};
+const Utils::Id cxxLanguageId{ProjectExplorer::Constants::CXX_LANGUAGE_ID};
+} // namespace
+
+using namespace Utils;
+
using CMakeProjectManager::CMakeConfigItem;
using CMakeProjectManager::CMakeConfigurationKitAspect;
using ProjectExplorer::EnvironmentKitAspect;
+using ProjectExplorer::Kit;
using ProjectExplorer::KitManager;
+using ProjectExplorer::ToolChain;
+using ProjectExplorer::ToolChainManager;
+
+using testing::_;
using testing::Return;
-using testing::ReturnRef;
-using Utils::FilePath;
+
+void verifyIarToolchain(const McuToolChainPackagePtr &iarToolchainPackage)
+{
+ ProjectExplorer::ToolChainFactory toolchainFactory;
+ Id iarId{BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID};
+ ToolChain *iarToolchain{toolchainFactory.createToolChain(iarId)};
+ iarToolchain->setLanguage(cxxLanguageId);
+ ToolChainManager::instance()->registerToolChain(iarToolchain);
+
+ QVERIFY(iarToolchainPackage != nullptr);
+ QCOMPARE(iarToolchainPackage->cmakeVariableName(), Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE);
+ QCOMPARE(iarToolchainPackage->environmentVariableName(), iarEnvVar);
+ QCOMPARE(iarToolchainPackage->isDesktopToolchain(), false);
+ QCOMPARE(iarToolchainPackage->toolChainName(), iar);
+ QCOMPARE(iarToolchainPackage->toolchainType(), McuToolChainPackage::ToolChainType::IAR);
+ QCOMPARE(iarToolchainPackage->label(), iarLabel);
+
+ iarToolchain = iarToolchainPackage->toolChain(cxxLanguageId);
+ QVERIFY(iarToolchain != nullptr);
+ QCOMPARE(iarToolchain->displayName(), "IAREW");
+ QCOMPARE(iarToolchain->detection(), ToolChain::UninitializedDetection);
+}
+
+void verifyArmGccToolchain(const McuToolChainPackagePtr &armGccPackage)
+{
+ //Fake register and fake detect compiler.
+ ProjectExplorer::ToolChainFactory toolchainFactory;
+ Id armGccId{ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID};
+
+ ToolChain *armToolchain{toolchainFactory.createToolChain(armGccId)};
+ armToolchain->setLanguage(cxxLanguageId);
+ ToolChainManager::instance()->registerToolChain(armToolchain);
+
+ QVERIFY(armGccPackage != nullptr);
+ QCOMPARE(armGccPackage->cmakeVariableName(), Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE);
+ QCOMPARE(armGccPackage->environmentVariableName(), armGccEnvVar);
+ QCOMPARE(armGccPackage->isDesktopToolchain(), false);
+ QCOMPARE(armGccPackage->toolChainName(), armGcc);
+ QCOMPARE(armGccPackage->toolchainType(), McuToolChainPackage::ToolChainType::ArmGcc);
+ QCOMPARE(armGccPackage->settingsKey(), armGccDirectorySetting);
+
+ // FIXME(piotr.mucko): Re-enable when toolchains retrieval from McuToolChainPackage is unified for arm and iar.
+ // armToolchain = armGccPackage->toolChain(cxxLanguageId);
+ // QVERIFY(armToolchain != nullptr);
+}
+
+void verifyGccToolchain(const McuToolChainPackagePtr &gccPackage)
+{
+ QVERIFY(gccPackage != nullptr);
+ QCOMPARE(gccPackage->cmakeVariableName(), "");
+ QCOMPARE(gccPackage->environmentVariableName(), "");
+ QCOMPARE(gccPackage->isDesktopToolchain(), true);
+ QCOMPARE(gccPackage->toolChainName(), unsupported);
+ QCOMPARE(gccPackage->toolchainType(), McuToolChainPackage::ToolChainType::GCC);
+}
+
+void verifyTargetToolchains(const Targets &targets,
+ const QString &toolchainFilePath,
+ const QString &compilerPath,
+ const QString &compilerSetting)
+{
+ QCOMPARE(targets.size(), 1);
+ const auto &target{targets.first()};
+
+ const auto toolchainFile{target->toolChainFilePackage()};
+ QVERIFY(toolchainFile);
+ QCOMPARE(toolchainFile->cmakeVariableName(), Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE);
+ QCOMPARE(toolchainFile->settingsKey(), empty);
+ QCOMPARE(toolchainFile->path().toString(), toolchainFilePath);
+
+ const auto toolchainCompiler{target->toolChainPackage()};
+ QVERIFY(toolchainCompiler);
+ QCOMPARE(toolchainCompiler->cmakeVariableName(), Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE);
+ QCOMPARE(toolchainCompiler->path().toString(), compilerPath);
+ QCOMPARE(toolchainCompiler->settingsKey(), compilerSetting);
+}
+
+McuSupportTest::McuSupportTest()
+ : targetFactory{settingsMockPtr}
+ , toolchainPackagePtr{new McuToolChainPackage{
+ settingsMockPtr,
+ {}, // label
+ {}, // defaultPath
+ {}, // detectionPath
+ {}, // settingsKey
+ McuToolChainPackage::ToolChainType::Unsupported, // toolchain type
+ {}, // cmake var name
+ {}}} // env var name
+ , armGccToolchainPackagePtr{new McuToolChainPackage{settingsMockPtr,
+ armGccLabel,
+ armGccDir,
+ {}, // validation path
+ armGccDirectorySetting,
+ McuToolChainPackage::ToolChainType::ArmGcc,
+ Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE,
+ armGccEnvVar}}
+ , iarToolchainPackagePtr{new McuToolChainPackage{settingsMockPtr,
+ iarLabel,
+ iarDir,
+ {}, // validation path
+ iarSetting,
+ McuToolChainPackage::ToolChainType::IAR,
+ Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE,
+ iarEnvVar}}
+ , platform{id, name, vendor}
+ , mcuTarget{currentQulVersion,
+ platform,
+ McuTarget::OS::FreeRTOS,
+ {sdkPackagePtr, freeRtosPackagePtr},
+ armGccToolchainPackagePtr,
+ armGccToolchainFilePackagePtr}
+{
+ testing::Mock::AllowLeak(settingsMockPtr.get());
+ testing::FLAGS_gmock_verbose = "error";
+}
void McuSupportTest::initTestCase()
{
- EXPECT_CALL(freeRtosPackage, environmentVariableName()).WillRepeatedly(ReturnRef(freeRtosEnvVar));
- EXPECT_CALL(freeRtosPackage, isValidStatus()).WillRepeatedly(Return(true));
- EXPECT_CALL(freeRtosPackage, path())
- .WillRepeatedly(Return(FilePath::fromString(defaultfreeRtosPath)));
+ targetDescription = Sdk::McuTargetDescription{
+ "2.0.1",
+ "2",
+ platformDescription,
+ Sdk::McuTargetDescription::Toolchain{},
+ Sdk::McuTargetDescription::BoardSdk{},
+ Sdk::McuTargetDescription::FreeRTOS{},
+ };
+
+ EXPECT_CALL(*freeRtosPackage, environmentVariableName())
+ .WillRepeatedly(Return(QString{freeRtosEnvVar}));
+ EXPECT_CALL(*freeRtosPackage, cmakeVariableName())
+ .WillRepeatedly(Return(QString{freeRtosCMakeVar}));
+ EXPECT_CALL(*freeRtosPackage, isValidStatus()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*freeRtosPackage, path()).WillRepeatedly(Return(FilePath::fromString(freeRtosPath)));
+ EXPECT_CALL(*freeRtosPackage, isAddToSystemPath()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*freeRtosPackage, detectionPath()).WillRepeatedly(Return(FilePath{}));
+
+ EXPECT_CALL(*sdkPackage, environmentVariableName()).WillRepeatedly(Return(QString{qulEnvVar}));
+ EXPECT_CALL(*sdkPackage, cmakeVariableName()).WillRepeatedly(Return(QString{qulCmakeVar}));
+ EXPECT_CALL(*sdkPackage, isValidStatus()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*sdkPackage, path()).WillRepeatedly(Return(FilePath::fromString(qtForMcuSdkPath)));
+ EXPECT_CALL(*sdkPackage, isAddToSystemPath()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*sdkPackage, detectionPath()).WillRepeatedly(Return(FilePath{}));
+
+ EXPECT_CALL(*armGccToolchainFilePackage, environmentVariableName())
+ .WillRepeatedly(Return(QString{QString{}}));
+ EXPECT_CALL(*armGccToolchainFilePackage, cmakeVariableName())
+ .WillRepeatedly(Return(QString{Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE}));
+ EXPECT_CALL(*armGccToolchainFilePackage, isValidStatus()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*armGccToolchainFilePackage, path())
+ .WillRepeatedly(Return(FilePath::fromString(armGccToolchainFilePath)));
+ EXPECT_CALL(*armGccToolchainFilePackage, isAddToSystemPath()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*armGccToolchainFilePackage, detectionPath()).WillRepeatedly(Return(FilePath{}));
+
+ ON_CALL(*settingsMockPtr, getPath)
+ .WillByDefault([](const QString &, QSettings::Scope, const FilePath &m_defaultPath) {
+ return m_defaultPath;
+ });
+}
+
+void McuSupportTest::init()
+{
+ qDebug() << __func__;
+}
+
+void McuSupportTest::cleanup()
+{
+ QVERIFY(testing::Mock::VerifyAndClearExpectations(settingsMockPtr.get()));
+ QVERIFY(testing::Mock::VerifyAndClearExpectations(freeRtosPackage));
+ QVERIFY(testing::Mock::VerifyAndClearExpectations(sdkPackage));
}
void McuSupportTest::test_parseBasicInfoFromJson()
{
- const auto description = Sdk::parseDescriptionJson(nxp_1064_json);
+ const auto description = Sdk::parseDescriptionJson(iar_nxp_1064_json);
QVERIFY(!description.freeRTOS.envVar.isEmpty());
QVERIFY(description.freeRTOS.boardSdkSubDir.isEmpty());
}
+void McuSupportTest::test_parseCmakeEntries()
+{
+ const auto description{Sdk::parseDescriptionJson(iar_nxp_1064_json)};
+
+ QVERIFY(!description.freeRTOS.packages.isEmpty());
+ auto &freeRtos = description.freeRTOS.packages[0];
+ QCOMPARE(freeRtos.envVar, nxp1064FreeRtosEnvVar);
+}
+
+void McuSupportTest::test_parseToolchainFromJSON_data()
+{
+ QTest::addColumn<QString>("json");
+ QTest::addColumn<QString>("environmentVariable");
+ QTest::addColumn<QString>("label");
+ QTest::addColumn<QString>("toolchainFile");
+ QTest::addColumn<QString>("id");
+
+ //TODO(me): Add ghs nxp 1064 nxp 1070.
+ QTest::newRow("armgcc_nxp_1050_json")
+ << armgcc_nxp_1050_json << armGccEnvVar << armGccLabel << armGccToolchainFilePath << armGcc;
+ QTest::newRow("armgcc_stm32f769i_freertos_json")
+ << armgcc_stm32f769i_freertos_json << armGccEnvVar << armGccLabel << armGccToolchainFilePath
+ << armGcc;
+
+ QTest::newRow("armgcc_stm32h750b_metal_json")
+ << armgcc_stm32h750b_metal_json << armGccEnvVar << armGccLabel << armGccToolchainFilePath
+ << armGcc;
+
+ QTest::newRow("armgcc_nxp_mimxrt1170_evk_freertos_json")
+ << armgcc_nxp_mimxrt1170_evk_freertos_json << armGccEnvVar << armGccLabel
+ << armGccToolchainFilePath << armGcc;
+
+ QTest::newRow("iar_stm32f469i_metal_json")
+ << iar_stm32f469i_metal_json << iarEnvVar << iarLabel << iarToolchainFilePath << iar;
+}
+
+void McuSupportTest::test_parseToolchainFromJSON()
+{
+ QFETCH(QString, json);
+ QFETCH(QString, environmentVariable);
+ QFETCH(QString, label);
+ QFETCH(QString, toolchainFile);
+ QFETCH(QString, id);
+ Sdk::McuTargetDescription description{Sdk::parseDescriptionJson(json.toLocal8Bit())};
+ QCOMPARE(description.toolchain.id, id);
+
+ const Sdk::PackageDescription &compilerPackage{description.toolchain.compiler};
+ QCOMPARE(compilerPackage.cmakeVar, Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE);
+ QCOMPARE(compilerPackage.envVar, environmentVariable);
+
+ const Sdk::PackageDescription &toolchainFilePackage{description.toolchain.file};
+ QCOMPARE(toolchainFilePackage.label, cmakeToolchainLabel);
+ QCOMPARE(toolchainFilePackage.envVar, QString{});
+ QCOMPARE(toolchainFilePackage.cmakeVar, Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE);
+ QCOMPARE(toolchainFilePackage.defaultPath.cleanPath().toString(), toolchainFile);
+}
+
+void McuSupportTest::test_legacy_createIarToolchain()
+{
+ McuToolChainPackagePtr iarToolchainPackage = Sdk::createIarToolChainPackage(settingsMockPtr);
+ verifyIarToolchain(iarToolchainPackage);
+}
+
+void McuSupportTest::test_createIarToolchain()
+{
+ const auto description = Sdk::parseDescriptionJson(iar_stm32f469i_metal_json);
+
+ McuToolChainPackagePtr iarToolchainPackage{targetFactory.createToolchain(description.toolchain)};
+ verifyIarToolchain(iarToolchainPackage);
+}
+
+void McuSupportTest::test_legacy_createDesktopGccToolchain()
+{
+ McuToolChainPackagePtr gccPackage = Sdk::createGccToolChainPackage(settingsMockPtr);
+ verifyGccToolchain(gccPackage);
+}
+
+void McuSupportTest::test_createDesktopGccToolchain()
+{
+ const auto description = Sdk::parseDescriptionJson(gcc_desktop_json);
+ McuToolChainPackagePtr gccPackage{targetFactory.createToolchain(description.toolchain)};
+ verifyGccToolchain(gccPackage);
+}
+
+void McuSupportTest::test_verifyManuallyCreatedArmGccToolchain()
+{
+ verifyArmGccToolchain(armGccToolchainPackagePtr);
+}
+
+void McuSupportTest::test_legacy_createArmGccToolchain()
+{
+ McuToolChainPackagePtr armGccPackage = Sdk::createArmGccToolchainPackage(settingsMockPtr);
+ verifyArmGccToolchain(armGccPackage);
+}
+
+void McuSupportTest::test_createArmGccToolchain_data()
+{
+ QTest::addColumn<QString>("json");
+ QTest::newRow("armgcc_nxp_1050_json") << armgcc_nxp_1050_json;
+ QTest::newRow("armgcc_stm32f769i_freertos_json") << armgcc_stm32f769i_freertos_json;
+ QTest::newRow("armgcc_stm32h750b_metal_json") << armgcc_stm32h750b_metal_json;
+ QTest::newRow("armgcc_nxp_mimxrt1170_evk_freertos_json")
+ << armgcc_nxp_mimxrt1170_evk_freertos_json;
+}
+
+void McuSupportTest::test_createArmGccToolchain()
+{
+ QFETCH(QString, json);
+
+ const auto description = Sdk::parseDescriptionJson(json.toLocal8Bit());
+ McuToolChainPackagePtr armGccPackage{targetFactory.createToolchain(description.toolchain)};
+ verifyArmGccToolchain(armGccPackage);
+}
+
+void McuSupportTest::test_mapParsedToolchainIdToCorrespondingType_data()
+{
+ QTest::addColumn<Sdk::McuTargetDescription>("description");
+ QTest::addColumn<McuToolChainPackage::ToolChainType>("toolchainType");
+
+ QTest::newRow("armgcc_stm32h750b") << Sdk::parseDescriptionJson(armgcc_stm32h750b_metal_json)
+ << McuToolChainPackage::ToolChainType::ArmGcc;
+ QTest::newRow("iar_nxp1064") << Sdk::parseDescriptionJson(iar_nxp_1064_json)
+ << McuToolChainPackage::ToolChainType::IAR;
+ QTest::newRow("iar_stm32f469i") << Sdk::parseDescriptionJson(iar_stm32f469i_metal_json)
+ << McuToolChainPackage::ToolChainType::IAR;
+}
+
+void McuSupportTest::test_mapParsedToolchainIdToCorrespondingType()
+{
+ QFETCH(Sdk::McuTargetDescription, description);
+ QFETCH(McuToolChainPackage::ToolChainType, toolchainType);
+
+ const McuToolChainPackage *toolchain{targetFactory.createToolchain(description.toolchain)};
+
+ QVERIFY(toolchain != nullptr);
+ QCOMPARE(toolchain->toolchainType(), toolchainType);
+}
+
+void McuSupportTest::test_legacy_createPackagesWithCorrespondingSettings_data()
+{
+ QTest::addColumn<QString>("json");
+ QTest::addColumn<QSet<QString>>("expectedSettings");
+
+ QSet<QString> commonSettings{{"CypressAutoFlashUtil"},
+ {"MCUXpressoIDE"},
+ {"RenesasFlashProgrammer"},
+ {"Stm32CubeProgrammer"}};
+
+ QTest::newRow("nxp1064") << iar_nxp_1064_json
+ << QSet<QString>{{"EVK_MIMXRT1064_SDK_PATH"},
+ {QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}
+ .append("IMXRT1064")},
+ "IARToolchain"}
+ .unite(commonSettings);
+ QTest::newRow("stm32f469i") << iar_stm32f469i_metal_json
+ << QSet<QString>{{"STM32Cube_FW_F4_SDK_PATH"}, "IARToolchain"}.unite(
+ commonSettings);
+ QTest::newRow("nxp1050") << armgcc_nxp_1050_json
+ << QSet<QString>{{"EVKB_IMXRT1050_SDK_PATH"},
+ {QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}
+ .append("IMXRT1050")},
+ "GNUArmEmbeddedToolchain"}
+ .unite(commonSettings);
+ QTest::newRow("stm32h750b") << armgcc_stm32h750b_metal_json
+ << QSet<QString>{{"STM32Cube_FW_H7_SDK_PATH"},
+ "GNUArmEmbeddedToolchain"}
+ .unite(commonSettings);
+ QTest::newRow("stm32f769i") << armgcc_stm32f769i_freertos_json
+ << QSet<QString>{{"STM32Cube_FW_F7_SDK_PATH"},
+ "GNUArmEmbeddedToolchain"}
+ .unite(commonSettings);
+
+ QTest::newRow("ghs_rh850_d1m1a_baremetal_json")
+ << ghs_rh850_d1m1a_baremetal_json << QSet<QString>{"GHSToolchain"}.unite(commonSettings);
+}
+
+void McuSupportTest::test_legacy_createPackagesWithCorrespondingSettings()
+{
+ QFETCH(QString, json);
+ const Sdk::McuTargetDescription description = Sdk::parseDescriptionJson(json.toLocal8Bit());
+ const auto [targets, packages]{
+ Sdk::targetsFromDescriptions({description}, settingsMockPtr, qtForMcuSdkPath, runLegacy)};
+ Q_UNUSED(targets);
+
+ QSet<QString> settings = transform<QSet<QString>>(packages, [](const auto &package) {
+ return package->settingsKey();
+ });
+ QFETCH(QSet<QString>, expectedSettings);
+ QVERIFY(settings.contains(expectedSettings));
+}
+
+void McuSupportTest::test_createFreeRtosPackageWithCorrectSetting_data()
+{
+ QTest::addColumn<QString>("freeRtosEnvVar");
+ QTest::addColumn<QString>("expectedSettingsKey");
+
+ QTest::newRow("nxp1050") << nxp1050FreeRtosEnvVar
+ << QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}.append(nxp1050);
+ QTest::newRow("nxp1064") << nxp1064FreeRtosEnvVar
+ << QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}.append(nxp1064);
+ QTest::newRow("nxp1170") << nxp1170FreeRtosEnvVar
+ << QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}.append(nxp1170);
+ QTest::newRow("stm32f7") << stm32f7FreeRtosEnvVar
+ << QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}.append(stm32f7);
+}
+
+void McuSupportTest::test_createFreeRtosPackageWithCorrectSetting()
+{
+ QFETCH(QString, freeRtosEnvVar);
+ QFETCH(QString, expectedSettingsKey);
+
+ McuPackagePtr package{
+ Sdk::createFreeRTOSSourcesPackage(settingsMockPtr, freeRtosEnvVar, FilePath{}, FilePath{})};
+ QVERIFY(package != nullptr);
+
+ QCOMPARE(package->settingsKey(), expectedSettingsKey);
+}
+
+void McuSupportTest::test_createTargets()
+{
+ Sdk::PackageDescription packageDescription{id,
+ nxp1064FreeRtosEnvVar,
+ freeRtosCMakeVar,
+ freeRtosSetting,
+ freeRtosDescription,
+ freeRtosPath,
+ "",
+ {},
+ true};
+ targetDescription.freeRTOS.packages.append(packageDescription);
+ targetDescription.toolchain.id = armGcc;
+
+ const auto [targets, packages]{targetFactory.createTargets(targetDescription, qtForMcuSdkPath)};
+ QVERIFY(!targets.empty());
+ const McuTargetPtr target{targets.at(0)};
+ QCOMPARE(target->colorDepth(), colorDepth);
+ const auto &tgtPackages{target->packages()};
+ QVERIFY(!tgtPackages.empty());
+
+ QVERIFY(anyOf(tgtPackages, [](const McuPackagePtr &pkg) {
+ return (pkg->environmentVariableName() == nxp1064FreeRtosEnvVar
+ && pkg->cmakeVariableName() == freeRtosCMakeVar && pkg->label() == id);
+ }));
+}
+
+void McuSupportTest::test_createPackages()
+{
+ Sdk::PackageDescription packageDescription{id,
+ nxp1064FreeRtosEnvVar,
+ freeRtosCMakeVar,
+ freeRtosLabel,
+ freeRtosSetting,
+ freeRtosPath,
+ "",
+ {},
+ true};
+ targetDescription.freeRTOS.packages.append(packageDescription);
+
+ const auto packages{targetFactory.createPackages(targetDescription)};
+ QVERIFY(!packages.empty());
+}
+
+void McuSupportTest::test_removeRtosSuffixFromEnvironmentVariable_data()
+{
+ QTest::addColumn<QString>("freeRtosEnvVar");
+ QTest::addColumn<QString>("expectedEnvVarWithoutSuffix");
+
+ QTest::newRow("nxp1050") << nxp1050FreeRtosEnvVar << nxp1050;
+ QTest::newRow("nxp1064") << nxp1064FreeRtosEnvVar << nxp1064;
+ QTest::newRow("nxp1170") << nxp1170FreeRtosEnvVar << nxp1170;
+ QTest::newRow("stm32f7") << stm32f7FreeRtosEnvVar << stm32f7;
+}
+
+void McuSupportTest::test_removeRtosSuffixFromEnvironmentVariable()
+{
+ QFETCH(QString, freeRtosEnvVar);
+ QFETCH(QString, expectedEnvVarWithoutSuffix);
+ QCOMPARE(removeRtosSuffix(freeRtosEnvVar), expectedEnvVarWithoutSuffix);
+}
+
+void McuSupportTest::test_twoDotOneUsesLegacyImplementation()
+{
+ QCOMPARE(McuSupportOptions::isLegacyVersion({2, 1}), true);
+ QCOMPARE(McuSupportOptions::isLegacyVersion({2, 0}), true);
+ QCOMPARE(McuSupportOptions::isLegacyVersion({2, 0, 0}), true);
+ QCOMPARE(McuSupportOptions::isLegacyVersion({2, 0, 1}), true);
+ QCOMPARE(McuSupportOptions::isLegacyVersion({2, 2, 0}), true);
+ QCOMPARE(McuSupportOptions::isLegacyVersion({2, 2, 1}), true);
+ QCOMPARE(McuSupportOptions::isLegacyVersion({2, 3, 0}), false);
+}
+void McuSupportTest::test_useFallbackPathForToolchainWhenPathFromSettingsIsNotAvailable()
+{
+ Sdk::PackageDescription compilerDescription{armGcc,
+ armGccEnvVar,
+ Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE,
+ armGcc,
+ armGccDirectorySetting,
+ fallbackDir,
+ {},
+ {},
+ false};
+ Sdk::McuTargetDescription::Toolchain toolchainDescription{armGcc, {}, compilerDescription, {}};
+
+ EXPECT_CALL(*settingsMockPtr, getPath(QString{armGccDirectorySetting}, _, FilePath{fallbackDir}))
+ .Times(2)
+ .WillRepeatedly(Return(FilePath{fallbackDir}));
+
+ McuToolChainPackage *toolchain = targetFactory.createToolchain(toolchainDescription);
+
+ QCOMPARE(toolchain->path().toString(), fallbackDir);
+}
+
+void McuSupportTest::test_usePathFromSettingsForToolchainPath()
+{
+ Sdk::PackageDescription compilerDescription{{},
+ armGccEnvVar,
+ Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE,
+ armGcc,
+ armGccDirectorySetting,
+ empty,
+ {},
+ {},
+ false};
+ Sdk::McuTargetDescription::Toolchain toolchainDescription{armGcc, {}, compilerDescription, {}};
+
+ EXPECT_CALL(*settingsMockPtr, getPath(QString{armGccDirectorySetting}, _, FilePath{empty}))
+ .Times(2)
+ .WillOnce(Return(FilePath{empty})) // system scope settings
+ .WillOnce(Return(FilePath{armGccDir})); // user scope settings
+
+ McuToolChainPackage *toolchain = targetFactory.createToolchain(toolchainDescription);
+ QCOMPARE(toolchain->path().toString(), armGccDir);
+}
+
void McuSupportTest::test_addNewKit()
{
+ const QString cmakeVar = "CMAKE_SDK";
+ EXPECT_CALL(*sdkPackage, cmakeVariableName()).WillRepeatedly(Return(cmakeVar));
+
auto &kitManager{*KitManager::instance()};
QSignalSpy kitAddedSpy(&kitManager, &KitManager::kitAdded);
- auto *newKit{McuKitManager::newKit(&mcuTarget, &freeRtosPackage)};
+ auto *newKit{McuKitManager::newKit(&mcuTarget, sdkPackagePtr)};
QVERIFY(newKit != nullptr);
QCOMPARE(kitAddedSpy.count(), 1);
@@ -75,25 +668,126 @@ void McuSupportTest::test_addNewKit()
QVERIFY(createdKit != nullptr);
QCOMPARE(createdKit, newKit);
- auto cmakeAspect{CMakeConfigurationKitAspect{}};
- QVERIFY(createdKit->hasValue(cmakeAspect.id()));
- QVERIFY(createdKit->value(cmakeAspect.id(), freeRtosCmakeVar).isValid());
+ const auto config = CMakeConfigurationKitAspect::configuration(newKit);
+ QVERIFY(config.size() > 0);
+ QVERIFY(
+ indexOf(config.toVector(),
+ [&cmakeVar](const CMakeConfigItem &item) { return item.key == cmakeVar.toUtf8(); })
+ != -1);
+}
+
+void McuSupportTest::test_getFullToolchainFilePathFromTarget()
+{
+ QCOMPARE(mcuTarget.toolChainFilePackage()->path().toUserOutput(),
+ armGccToolchainFilePackagePtr->path().toUserOutput());
+}
+
+void McuSupportTest::test_legacy_getPredefinedToolchainFilePackage()
+{
+ QHash<QString, ToolchainCompilerCreator> toolchainCreators{
+ {armGcc, [this] { return armGccToolchainPackagePtr; }}};
+ McuTargetFactoryLegacy legacyTargetFactory{toolchainCreators,
+ {{armGcc, armGccToolchainFilePackagePtr}},
+ {},
+ settingsMockPtr};
+ auto armToolchainFile = legacyTargetFactory.getToolchainFile(qtForMcuSdkPath, armGcc);
+ QVERIFY(armToolchainFile);
+ QCOMPARE(armToolchainFile, armGccToolchainFilePackagePtr);
+}
+
+void McuSupportTest::test_legacy_createUnsupportedToolchainFilePackage()
+{
+ QHash<QString, ToolchainCompilerCreator> toolchainCreators{
+ {armGcc, [this] { return armGccToolchainPackagePtr; }}};
+ McuTargetFactoryLegacy legacyTargetFactory{toolchainCreators,
+ {{armGcc, armGccToolchainFilePackagePtr}},
+ {},
+ settingsMockPtr};
+
+ auto unsupportedToolchainFile = legacyTargetFactory.getToolchainFile(qtForMcuSdkPath, iar);
+ QVERIFY(unsupportedToolchainFile);
+ QCOMPARE(unsupportedToolchainFile->path().toString(), unsupportedToolchainFilePath);
+ QCOMPARE(unsupportedToolchainFile->cmakeVariableName(),
+ Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE);
+}
+
+void McuSupportTest::test_legacy_createTargetWithToolchainPackages_data()
+{
+ QTest::addColumn<QString>("json");
+ QTest::addColumn<QString>("toolchainFilePath");
+ QTest::addColumn<QString>("compilerPath");
+ QTest::addColumn<QString>("compilerSetting");
+
+ QTest::newRow("nxp1050") << armgcc_nxp_1050_json << armGccToolchainFilePath << armGccDir
+ << armGccDirectorySetting;
+ QTest::newRow("stm32h750b") << armgcc_stm32h750b_metal_json << armGccToolchainFilePath
+ << armGccDir << armGccDirectorySetting;
+ QTest::newRow("stm32f769i") << armgcc_stm32f769i_freertos_json << armGccToolchainFilePath
+ << armGccDir << armGccDirectorySetting;
+ QTest::newRow("stm32f469i") << iar_stm32f469i_metal_json << iarToolchainFilePath << iarDir
+ << iarSetting;
+ QTest::newRow("nxp1064") << iar_nxp_1064_json << iarToolchainFilePath << iarDir << iarSetting;
+ QTest::newRow("nxp1064") << iar_nxp_1064_json << iarToolchainFilePath << iarDir << iarSetting;
+ QTest::newRow("ghs_rh850_d1m1a_baremetal_json")
+ << ghs_rh850_d1m1a_baremetal_json << greenhillToolchainFilePath << greenhillCompilerDir
+ << greenhillSetting;
+}
+
+void McuSupportTest::test_legacy_createTargetWithToolchainPackages()
+{
+ QFETCH(QString, json);
+ QFETCH(QString, toolchainFilePath);
+ QFETCH(QString, compilerPath);
+ QFETCH(QString, compilerSetting);
+
+ const Sdk::McuTargetDescription description = Sdk::parseDescriptionJson(json.toLocal8Bit());
+
+ EXPECT_CALL(*settingsMockPtr,
+ getPath(QString{Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK}, _, _))
+ .WillRepeatedly(Return(FilePath::fromString(qtForMcuSdkPath)));
+ EXPECT_CALL(*settingsMockPtr, getPath(compilerSetting, _, _))
+ .WillRepeatedly(Return(FilePath::fromString(compilerPath)));
+
+ const auto [targets, packages]{
+ Sdk::targetsFromDescriptions({description}, settingsMockPtr, qtForMcuSdkPath, runLegacy)};
+ Q_UNUSED(packages);
+
+ verifyTargetToolchains(targets, toolchainFilePath, compilerPath, compilerSetting);
+}
+
+void McuSupportTest::test_createTargetWithToolchainPackages_data()
+{
+ test_legacy_createTargetWithToolchainPackages_data();
}
-void McuSupportTest::test_addFreeRtosCmakeVarToKit()
+void McuSupportTest::test_createTargetWithToolchainPackages()
{
- McuSupportOptions::updateKitEnvironment(&kit, &mcuTarget);
+ QFETCH(QString, json);
+ QFETCH(QString, toolchainFilePath);
+ QFETCH(QString, compilerPath);
+ QFETCH(QString, compilerSetting);
+
+ EXPECT_CALL(*settingsMockPtr, getPath(compilerSetting, _, _))
+ .WillRepeatedly(Return(FilePath::fromString(compilerPath)));
+
+ const Sdk::McuTargetDescription description = Sdk::parseDescriptionJson(json.toLocal8Bit());
+ const auto [targets, packages]{
+ Sdk::targetsFromDescriptions({description}, settingsMockPtr, qtForMcuSdkPath, !runLegacy)};
+ Q_UNUSED(packages);
+
+ verifyTargetToolchains(targets, toolchainFilePath, compilerPath, compilerSetting);
+}
+
+void McuSupportTest::test_addToolchainFileInfoToKit()
+{
+ McuKitManager::upgradeKitInPlace(&kit, &mcuTarget, sdkPackagePtr);
- QVERIFY(kit.hasValue(EnvironmentKitAspect::id()));
QVERIFY(kit.isValid());
- QVERIFY(!kit.allKeys().empty());
+ QCOMPARE(kit.value(Constants::KIT_MCUTARGET_TOOLCHAIN_KEY).toString(), armGcc);
const auto &cmakeConfig{CMakeConfigurationKitAspect::configuration(&kit)};
- QCOMPARE(cmakeConfig.size(), 1);
-
- CMakeConfigItem expectedCmakeVar{freeRtosCmakeVar.toLocal8Bit(),
- FilePath::fromString(defaultfreeRtosPath).toUserOutput().toLocal8Bit()};
- QVERIFY(cmakeConfig.contains(expectedCmakeVar));
+ QVERIFY(!cmakeConfig.empty());
+ QCOMPARE(cmakeConfig.valueOf(Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE), armGccToolchainFilePath);
}
} // namespace McuSupport::Internal::Test
diff --git a/src/plugins/mcusupport/test/unittest.h b/src/plugins/mcusupport/test/unittest.h
index dcdb5370b2d..a9310f87107 100644
--- a/src/plugins/mcusupport/test/unittest.h
+++ b/src/plugins/mcusupport/test/unittest.h
@@ -25,59 +25,86 @@
#pragma once
-#include "mcupackage.h"
#include "mcutarget.h"
-#include "mcusupportoptions.h"
-#include "mcusupportplugin.h"
-#include "mcusupportsdk.h"
+#include "mcutargetfactory.h"
#include "packagemock.h"
+#include "settingshandlermock.h"
#include <projectexplorer/kit.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/projectexplorer.h>
-#include <utils/filepath.h>
-#include <utils/fileutils.h>
+
#include <QObject>
#include <QSignalSpy>
#include <QTest>
namespace McuSupport::Internal::Test {
-using ProjectExplorer::Kit;
-
class McuSupportTest : public QObject
{
Q_OBJECT
+public:
+ McuSupportTest();
+
private slots:
void initTestCase();
+ void init();
+ void cleanup();
- void test_addFreeRtosCmakeVarToKit();
void test_addNewKit();
void test_parseBasicInfoFromJson();
+ void test_parseCmakeEntries();
+ void test_parseToolchainFromJSON_data();
+ void test_parseToolchainFromJSON();
+ void test_mapParsedToolchainIdToCorrespondingType_data();
+ void test_mapParsedToolchainIdToCorrespondingType();
+ void test_legacy_createPackagesWithCorrespondingSettings();
+ void test_legacy_createPackagesWithCorrespondingSettings_data();
+ void test_legacy_createTargetWithToolchainPackages_data();
+ void test_legacy_createTargetWithToolchainPackages();
+ void test_createTargetWithToolchainPackages_data();
+ void test_createTargetWithToolchainPackages();
-private:
- QVersionNumber currentQulVersion{2, 0};
+ void test_createFreeRtosPackageWithCorrectSetting_data();
+ void test_createFreeRtosPackageWithCorrectSetting();
+ void test_createTargets();
+ void test_createPackages();
+ void test_legacy_createIarToolchain();
+ void test_createIarToolchain();
+ void test_legacy_createDesktopGccToolchain();
+ void test_createDesktopGccToolchain();
+ void test_verifyManuallyCreatedArmGccToolchain();
+ void test_legacy_createArmGccToolchain();
+ void test_createArmGccToolchain_data();
+ void test_createArmGccToolchain();
+ void test_removeRtosSuffixFromEnvironmentVariable_data();
+ void test_removeRtosSuffixFromEnvironmentVariable();
+ void test_useFallbackPathForToolchainWhenPathFromSettingsIsNotAvailable();
+ void test_usePathFromSettingsForToolchainPath();
- const QString id{"target_id"};
- const QString name{"target_name"};
- const QString vendor{"target_vendor"};
+ void test_twoDotOneUsesLegacyImplementation();
+ void test_addToolchainFileInfoToKit();
+ void test_getFullToolchainFilePathFromTarget();
+ void test_legacy_getPredefinedToolchainFilePackage();
+ void test_legacy_createUnsupportedToolchainFilePackage();
- const QString freeRtosEnvVar{"EVK_MIMXRT1170_FREERTOS_PATH"};
- const QString freeRtosCmakeVar{"FREERTOS_DIR"};
- const QString defaultfreeRtosPath{"/opt/freertos/default"};
-
- PackageMock freeRtosPackage;
- Kit kit;
-
- McuToolChainPackage toolchainPackage{{}, {}, {}, {}, {}};
- const McuTarget::Platform platform{id, name, vendor};
- McuTarget mcuTarget{currentQulVersion,
- platform,
- McuTarget::OS::FreeRTOS,
- {&freeRtosPackage},
- &toolchainPackage};
+private:
+ QVersionNumber currentQulVersion{2, 0};
+ PackageMock *freeRtosPackage{new PackageMock};
+ PackageMock *sdkPackage{new PackageMock};
+ McuPackagePtr freeRtosPackagePtr{freeRtosPackage};
+ McuPackagePtr sdkPackagePtr{sdkPackage};
+ QSharedPointer<SettingsHandlerMock> settingsMockPtr{new SettingsHandlerMock};
+ McuTargetFactory targetFactory;
+ Sdk::McuTargetDescription targetDescription;
+ McuToolChainPackagePtr toolchainPackagePtr;
+ McuToolChainPackagePtr armGccToolchainPackagePtr;
+ McuToolChainPackagePtr iarToolchainPackagePtr;
+ PackageMock *armGccToolchainFilePackage{new PackageMock};
+ McuPackagePtr armGccToolchainFilePackagePtr{armGccToolchainFilePackage};
+ McuTarget::Platform platform;
+ McuTarget mcuTarget;
+ ProjectExplorer::Kit kit;
}; // class McuSupportTest
} // namespace McuSupport::Internal::Test
diff --git a/src/plugins/mercurial/commiteditor.cpp b/src/plugins/mercurial/commiteditor.cpp
index 84abca39824..39a88cd294a 100644
--- a/src/plugins/mercurial/commiteditor.cpp
+++ b/src/plugins/mercurial/commiteditor.cpp
@@ -62,7 +62,7 @@ void CommitEditor::setFields(const QFileInfo &repositoryRoot, const QString &bra
QStringList shouldTrack;
- foreach (const VcsBaseClient::StatusItem &item, repoStatus) {
+ for (const VcsBaseClient::StatusItem &item : repoStatus) {
if (item.flags == QLatin1String("Untracked"))
shouldTrack.append(item.file);
else
@@ -71,8 +71,8 @@ void CommitEditor::setFields(const QFileInfo &repositoryRoot, const QString &bra
VcsBaseSubmitEditor::filterUntrackedFilesOfProject(fileModel->repositoryRoot(), &shouldTrack);
- foreach (const QString &track, shouldTrack) {
- foreach (const VcsBaseClient::StatusItem &item, repoStatus) {
+ for (const QString &track : qAsConst(shouldTrack)) {
+ for (const VcsBaseClient::StatusItem &item : repoStatus) {
if (item.file == track)
fileModel->addFile(item.file, item.flags, Unchecked);
}
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index b7093f4196f..ddf930ba1c6 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -36,6 +36,7 @@
#include <vcsbase/vcsbaseeditorconfig.h>
#include <vcsbase/vcsbasediffeditorcontroller.h>
+#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
@@ -102,8 +103,8 @@ bool MercurialClient::manifestSync(const FilePath &repository, const QString &re
const QDir repositoryDir(repository.toString());
const QFileInfo needle = QFileInfo(repositoryDir, relativeFilename);
- const QStringList files = proc.stdOut().split(QLatin1Char('\n'));
- foreach (const QString &fileName, files) {
+ const QStringList files = proc.cleanedStdOut().split(QLatin1Char('\n'));
+ for (const QString &fileName : files) {
const QFileInfo managedFile(repositoryDir, fileName);
if (needle == managedFile)
return true;
@@ -128,7 +129,7 @@ bool MercurialClient::synchronousClone(const FilePath &workingDirectory,
QStringList arguments(QLatin1String("init"));
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, arguments);
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return false;
// Then pull remote repository
@@ -136,7 +137,7 @@ bool MercurialClient::synchronousClone(const FilePath &workingDirectory,
arguments << QLatin1String("pull") << dstLocation;
QtcProcess proc1;
vcsSynchronousExec(proc1, workingDirectory, arguments, flags);
- if (proc1.result() != QtcProcess::FinishedWithSuccess)
+ if (proc1.result() != ProcessResult::FinishedWithSuccess)
return false;
// By now, there is no hgrc file -> create it
@@ -153,13 +154,13 @@ bool MercurialClient::synchronousClone(const FilePath &workingDirectory,
arguments << QLatin1String("update");
QtcProcess proc2;
vcsSynchronousExec(proc2, workingDirectory, arguments, flags);
- return proc2.result() == QtcProcess::FinishedWithSuccess;
+ return proc2.result() == ProcessResult::FinishedWithSuccess;
} else {
QStringList arguments(QLatin1String("clone"));
arguments << dstLocation << workingDirectory.parentDir().toString();
QtcProcess proc;
vcsSynchronousExec(proc, workingDirectory.parentDir(), arguments, flags);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
}
@@ -183,9 +184,9 @@ bool MercurialClient::synchronousPull(const FilePath &workingDir, const QString
command.addFlags(flags);
command.runCommand(proc, {vcsBinary(), args});
- const bool ok = proc.result() == QtcProcess::FinishedWithSuccess;
+ const bool ok = proc.result() == ProcessResult::FinishedWithSuccess;
- parsePullOutput(proc.stdOut().trimmed());
+ parsePullOutput(proc.cleanedStdOut().trimmed());
return ok;
}
@@ -224,23 +225,23 @@ QStringList MercurialClient::parentRevisionsSync(const FilePath &workingDirector
args << file;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, args);
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return QStringList();
/* Looks like: \code
changeset: 0:031a48610fba
user: ...
\endcode */
// Obtain first line and split by blank-delimited tokens
- const QStringList lines = proc.stdOut().split(QLatin1Char('\n'));
+ const QStringList lines = proc.cleanedStdOut().split(QLatin1Char('\n'));
if (lines.size() < 1) {
VcsOutputWindow::appendSilently(
- msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(proc.stdOut())));
+ msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(proc.cleanedStdOut())));
return QStringList();
}
QStringList changeSets = lines.front().simplified().split(QLatin1Char(' '));
if (changeSets.size() < 2) {
VcsOutputWindow::appendSilently(
- msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(proc.stdOut())));
+ msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(proc.cleanedStdOut())));
return QStringList();
}
// Remove revision numbers
@@ -267,9 +268,9 @@ QString MercurialClient::shortDescriptionSync(const FilePath &workingDirectory,
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, args);
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return revision;
- return stripLastNewline(proc.stdOut());
+ return stripLastNewline(proc.cleanedStdOut());
}
// Default format: "SHA1 (author summmary)"
@@ -287,7 +288,7 @@ bool MercurialClient::managesFile(const FilePath &workingDirectory, const QStrin
args << QLatin1String("status") << QLatin1String("--unknown") << fileName;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, args);
- return proc.stdOut().isEmpty();
+ return proc.cleanedStdOut().isEmpty();
}
void MercurialClient::incoming(const FilePath &repositoryRoot, const QString &repository)
diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp
index 12b8cb6a186..6cd0c778ec4 100644
--- a/src/plugins/mercurial/mercurialplugin.cpp
+++ b/src/plugins/mercurial/mercurialplugin.cpp
@@ -36,32 +36,32 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
-#include <coreplugin/documentmanager.h>
-#include <coreplugin/vcsmanager.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/documentmanager.h>
+#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
-#include <coreplugin/editormanager/editormanager.h>
-
#include <coreplugin/locator/commandlocator.h>
+#include <coreplugin/vcsmanager.h>
+#include <utils/commandline.h>
+#include <utils/environment.h>
#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
#include <vcsbase/basevcseditorfactory.h>
#include <vcsbase/basevcssubmiteditorfactory.h>
-#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseconstants.h>
-#include <vcsbase/vcsoutputwindow.h>
+#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcscommand.h>
+#include <vcsbase/vcsoutputwindow.h>
#include <QAction>
-#include <QMenu>
#include <QDebug>
-#include <QtGlobal>
#include <QDir>
-#include <QDialog>
#include <QFileDialog>
+#include <QMenu>
+#include <QtGlobal>
#ifdef WITH_TESTS
#include <QTest>
@@ -732,7 +732,7 @@ void MercurialPluginPrivate::updateActions(VcsBasePluginPrivate::ActionState as)
revertFile->setParameter(filename);
statusFile->setParameter(filename);
- foreach (QAction *repoAction, m_repositoryActionList)
+ for (QAction *repoAction : qAsConst(m_repositoryActionList))
repoAction->setEnabled(repoEnabled);
}
diff --git a/src/plugins/mesonprojectmanager/CMakeLists.txt b/src/plugins/mesonprojectmanager/CMakeLists.txt
index 5486bd44773..cea74e07510 100644
--- a/src/plugins/mesonprojectmanager/CMakeLists.txt
+++ b/src/plugins/mesonprojectmanager/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(MesonProjectManager
+ PLUGIN_CLASS MesonProjectPlugin
DEPENDS QmlJS
PLUGIN_DEPENDS Core CppEditor ProjectExplorer TextEditor QtSupport
SOURCES
@@ -82,7 +83,7 @@ add_qtc_plugin(MesonProjectManager
machinefiles/machinefilemanager.cpp
machinefiles/nativefilegenerator.h
machinefiles/nativefilegenerator.cpp
- resources.qrc
+ resources_meson.qrc
)
file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
@@ -90,6 +91,7 @@ file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_L
if(WITH_TESTS)
add_qtc_test(tst_mesonwrapper
+ EXCLUDE_FROM_PRECHECK
INCLUDES
BEFORE "."
DEPENDS
@@ -110,6 +112,7 @@ add_qtc_test(tst_mesonwrapper
)
add_qtc_test(tst_mesoninfoparser
+ EXCLUDE_FROM_PRECHECK
INCLUDES
BEFORE "."
DEPENDS
diff --git a/src/plugins/mesonprojectmanager/exewrappers/toolwrapper.cpp b/src/plugins/mesonprojectmanager/exewrappers/toolwrapper.cpp
index d13175f5f4f..48579c8d074 100644
--- a/src/plugins/mesonprojectmanager/exewrappers/toolwrapper.cpp
+++ b/src/plugins/mesonprojectmanager/exewrappers/toolwrapper.cpp
@@ -66,7 +66,7 @@ Version ToolWrapper::read_version(const Utils::FilePath &toolPath)
process.setCommand({ toolPath, { "--version" } });
process.start();
if (process.waitForFinished())
- return Version::fromString(process.stdOut());
+ return Version::fromString(process.cleanedStdOut());
}
return {};
}
diff --git a/src/plugins/mesonprojectmanager/mesonactionsmanager/mesonactionsmanager.cpp b/src/plugins/mesonprojectmanager/mesonactionsmanager/mesonactionsmanager.cpp
index 6d616b983c8..516e4404402 100644
--- a/src/plugins/mesonprojectmanager/mesonactionsmanager/mesonactionsmanager.cpp
+++ b/src/plugins/mesonprojectmanager/mesonactionsmanager/mesonactionsmanager.cpp
@@ -31,7 +31,9 @@
#include <project/mesonbuildsystem.h>
#include <project/projecttree/mesonprojectnodes.h>
+
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projecttree.h>
#include <utils/parameteraction.h>
diff --git a/src/plugins/mesonprojectmanager/mesonprojectmanager.qbs b/src/plugins/mesonprojectmanager/mesonprojectmanager.qbs
index 3a9ce46d718..2499ac3f9c0 100644
--- a/src/plugins/mesonprojectmanager/mesonprojectmanager.qbs
+++ b/src/plugins/mesonprojectmanager/mesonprojectmanager.qbs
@@ -78,7 +78,7 @@ Project {
"project/projecttree/mesonprojectnodes.h",
"project/projecttree/projecttree.cpp",
"project/projecttree/projecttree.h",
- "resources.qrc",
+ "resources_meson.qrc",
"settings/general/settings.cpp",
"settings/general/settings.h",
"settings/tools/kitaspect/mesontoolkitaspect.cpp",
diff --git a/src/plugins/mesonprojectmanager/mesonprojectplugin.cpp b/src/plugins/mesonprojectmanager/mesonprojectplugin.cpp
index bd2e120d513..ddfa6e4df04 100644
--- a/src/plugins/mesonprojectmanager/mesonprojectplugin.cpp
+++ b/src/plugins/mesonprojectmanager/mesonprojectplugin.cpp
@@ -25,11 +25,9 @@
#include "mesonprojectplugin.h"
-#include "exewrappers/mesonwrapper.h"
#include "machinefiles/machinefilemanager.h"
#include "mesonactionsmanager/mesonactionsmanager.h"
#include "project/mesonbuildconfiguration.h"
-#include "project/mesonbuildsystem.h"
#include "project/mesonproject.h"
#include "project/mesonrunconfiguration.h"
#include "project/ninjabuildstep.h"
@@ -39,8 +37,10 @@
#include "settings/tools/toolssettingsaccessor.h"
#include "settings/tools/toolssettingspage.h"
+#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/runcontrol.h>
@@ -84,6 +84,7 @@ private:
void saveAll()
{
m_toolsSettings.saveMesonTools(MesonTools::tools(), ICore::dialogParent());
+ Settings::instance()->writeSettings(ICore::settings());
}
};
@@ -101,6 +102,7 @@ bool MesonProjectPlugin::initialize(const QStringList & /*arguments*/, QString *
ProjectManager::registerProjectType<MesonProject>(Constants::Project::MIMETYPE);
FileIconProvider::registerIconOverlayForFilename(Constants::Icons::MESON, "meson.build");
FileIconProvider::registerIconOverlayForFilename(Constants::Icons::MESON, "meson_options.txt");
+ Settings::instance()->readSettings(ICore::settings());
return true;
}
diff --git a/src/plugins/mesonprojectmanager/project/mesonbuildconfiguration.cpp b/src/plugins/mesonprojectmanager/project/mesonbuildconfiguration.cpp
index b603f856b35..291d5f05dc9 100644
--- a/src/plugins/mesonprojectmanager/project/mesonbuildconfiguration.cpp
+++ b/src/plugins/mesonprojectmanager/project/mesonbuildconfiguration.cpp
@@ -83,9 +83,8 @@ FilePath MesonBuildConfiguration::shadowBuildDirectory(const FilePath &projectFi
return {};
const QString projectName = projectFilePath.parentDir().fileName();
- return BuildConfiguration::buildDirectoryFromTemplate(
- Project::projectDirectory(projectFilePath),
- projectFilePath, projectName, k, bcName, buildType, BuildConfiguration::ReplaceSpaces);
+ return buildDirectoryFromTemplate(Project::projectDirectory(projectFilePath), projectFilePath,
+ projectName, k, bcName, buildType, "meson");
}
ProjectExplorer::BuildSystem *MesonBuildConfiguration::buildSystem() const
diff --git a/src/plugins/mesonprojectmanager/project/mesonprocess.cpp b/src/plugins/mesonprojectmanager/project/mesonprocess.cpp
index 25b859ec730..f8561ecbee7 100644
--- a/src/plugins/mesonprojectmanager/project/mesonprocess.cpp
+++ b/src/plugins/mesonprojectmanager/project/mesonprocess.cpp
@@ -33,6 +33,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/taskhub.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <QLoggingCategory>
@@ -51,7 +52,7 @@ MesonProcess::MesonProcess()
}
bool MesonProcess::run(const Command &command,
- const Utils::Environment env,
+ const Environment &env,
const QString &projectName,
bool captureStdo)
{
@@ -96,58 +97,25 @@ void MesonProcess::setProgressValue(int p)
m_future.setProgressValue(p);
}
-void MesonProcess::handleProcessFinished(int code, QProcess::ExitStatus status)
+void MesonProcess::handleProcessDone()
{
+ if (m_process->result() != ProcessResult::FinishedWithSuccess) {
+ ProjectExplorer::TaskHub::addTask(ProjectExplorer::BuildSystemTask{
+ ProjectExplorer::Task::TaskType::Error, m_process->exitMessage()});
+ }
m_cancelTimer.stop();
m_stdo = m_process->readAllStandardOutput();
m_stderr = m_process->readAllStandardError();
- if (status == QProcess::NormalExit) {
+ if (m_process->exitStatus() == QProcess::NormalExit) {
m_future.setProgressValue(1);
m_future.reportFinished();
} else {
m_future.reportCanceled();
m_future.reportFinished();
}
- const QString elapsedTime = Utils::formatElapsedTime(m_elapsed.elapsed());
+ const QString elapsedTime = formatElapsedTime(m_elapsed.elapsed());
Core::MessageManager::writeSilently(elapsedTime);
- emit finished(code, status);
-}
-
-void MesonProcess::handleProcessError(QProcess::ProcessError error)
-{
- QString message;
- QString commandStr = m_currentCommand.toUserOutput();
- switch (error) {
- case QProcess::ProcessError::FailedToStart:
- message = tr("The process failed to start.")
- + tr("Either the "
- "invoked program \"%1\" is missing, or you may have insufficient "
- "permissions to invoke the program.")
- .arg(m_currentCommand.executable().toUserOutput());
- break;
- case QProcess::ProcessError::Crashed:
- message = tr("The process was ended forcefully.");
- break;
- case QProcess::ProcessError::Timedout:
- message = tr("Process timed out.");
- break;
- case QProcess::ProcessError::WriteError:
- message = tr("An error occurred when attempting to write "
- "to the process. For example, the process may not be running, "
- "or it may have closed its input channel.");
- break;
- case QProcess::ProcessError::ReadError:
- message = tr("An error occurred when attempting to read from "
- "the process. For example, the process may not be running.");
- break;
- case QProcess::ProcessError::UnknownError:
- message = tr("An unknown error in the process occurred.");
- break;
- }
- ProjectExplorer::TaskHub::addTask(
- ProjectExplorer::BuildSystemTask{ProjectExplorer::Task::TaskType::Error,
- QString("%1\n%2").arg(message).arg(commandStr)});
- handleProcessFinished(-1, QProcess::CrashExit);
+ emit finished(m_process->exitCode(), m_process->exitStatus());
}
void MesonProcess::checkForCancelled()
@@ -160,26 +128,16 @@ void MesonProcess::checkForCancelled()
}
void MesonProcess::setupProcess(const Command &command,
- const Utils::Environment env,
+ const Environment env,
bool captureStdo)
{
- if (m_process)
- disconnect(m_process.get());
- m_process = std::make_unique<Utils::QtcProcess>();
- connect(m_process.get(), &QtcProcess::finished, this, [this] {
- handleProcessFinished(m_process->exitCode(), m_process->exitStatus());
- });
- connect(m_process.get(), &QtcProcess::errorOccurred, this, &MesonProcess::handleProcessError);
+ m_process.reset(new QtcProcess);
+ connect(m_process.get(), &QtcProcess::done, this, &MesonProcess::handleProcessDone);
if (!captureStdo) {
- connect(m_process.get(),
- &QtcProcess::readyReadStandardOutput,
- this,
- &MesonProcess::processStandardOutput);
-
- connect(m_process.get(),
- &QtcProcess::readyReadStandardError,
- this,
- &MesonProcess::processStandardError);
+ connect(m_process.get(), &QtcProcess::readyReadStandardOutput,
+ this, &MesonProcess::processStandardOutput);
+ connect(m_process.get(), &QtcProcess::readyReadStandardError,
+ this, &MesonProcess::processStandardError);
}
m_process->setWorkingDirectory(command.workDir());
@@ -212,17 +170,15 @@ bool MesonProcess::sanityCheck(const Command &command) const
void MesonProcess::processStandardOutput()
{
- QTC_ASSERT(m_process, return );
- auto data = m_process->readAllStandardOutput();
+ const auto data = m_process->readAllStandardOutput();
Core::MessageManager::writeSilently(QString::fromLocal8Bit(data));
emit readyReadStandardOutput(data);
}
void MesonProcess::processStandardError()
{
- QTC_ASSERT(m_process, return );
-
Core::MessageManager::writeSilently(QString::fromLocal8Bit(m_process->readAllStandardError()));
}
+
} // namespace Internal
} // namespace MesonProjectManager
diff --git a/src/plugins/mesonprojectmanager/project/mesonprocess.h b/src/plugins/mesonprojectmanager/project/mesonprocess.h
index 9c5c6db9a97..d1ee043781c 100644
--- a/src/plugins/mesonprojectmanager/project/mesonprocess.h
+++ b/src/plugins/mesonprojectmanager/project/mesonprocess.h
@@ -27,9 +27,6 @@
#include "exewrappers/mesonwrapper.h"
-#include <utils/qtcprocess.h>
-
-#include <QBuffer>
#include <QByteArray>
#include <QElapsedTimer>
#include <QFutureInterface>
@@ -39,6 +36,8 @@
#include <memory>
+namespace Utils { class QtcProcess; }
+
namespace MesonProjectManager {
namespace Internal {
@@ -48,7 +47,7 @@ class MesonProcess final : public QObject
public:
MesonProcess();
bool run(const Command &command,
- const Utils::Environment env,
+ const Utils::Environment &env,
const QString &projectName,
bool captureStdo = false);
@@ -67,8 +66,7 @@ signals:
void readyReadStandardOutput(const QByteArray &data);
private:
- void handleProcessFinished(int code, QProcess::ExitStatus status);
- void handleProcessError(QProcess::ProcessError error);
+ void handleProcessDone();
void checkForCancelled();
void setupProcess(const Command &command, const Utils::Environment env, bool captureStdo);
diff --git a/src/plugins/mesonprojectmanager/project/mesonproject.cpp b/src/plugins/mesonprojectmanager/project/mesonproject.cpp
index aefc3f481d8..4b770f2793f 100644
--- a/src/plugins/mesonprojectmanager/project/mesonproject.cpp
+++ b/src/plugins/mesonprojectmanager/project/mesonproject.cpp
@@ -25,9 +25,7 @@
#include "mesonproject.h"
-#include "mesonbuildsystem.h"
#include "mesonpluginconstants.h"
-#include "exewrappers/mesontools.h"
#include "settings/tools/kitaspect/mesontoolkitaspect.h"
#include "settings/tools/kitaspect/ninjatoolkitaspect.h"
@@ -79,14 +77,5 @@ ProjectExplorer::DeploymentKnowledge MesonProject::deploymentKnowledge() const
return ProjectExplorer::DeploymentKnowledge::Bad;
}
-ProjectExplorer::MakeInstallCommand MesonProject::makeInstallCommand(
- const ProjectExplorer::Target *target, const QString &installRoot)
-{
- Q_UNUSED(target)
- Q_UNUSED(installRoot)
- // TODO in next releases
- return {};
-}
-
} // namespace Internal
} // namespace MesonProjectManager
diff --git a/src/plugins/mesonprojectmanager/project/mesonproject.h b/src/plugins/mesonprojectmanager/project/mesonproject.h
index 3842e1ce061..29920b03fa7 100644
--- a/src/plugins/mesonprojectmanager/project/mesonproject.h
+++ b/src/plugins/mesonprojectmanager/project/mesonproject.h
@@ -25,15 +25,12 @@
#pragma once
-#include "exewrappers/mesonwrapper.h"
#include "mesonprojectimporter.h"
#include <projectexplorer/project.h>
#include <projectexplorer/projectimporter.h>
#include <projectexplorer/task.h>
-#include <utils/fileutils.h>
-
namespace MesonProjectManager {
namespace Internal {
@@ -49,8 +46,6 @@ public:
private:
ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
- ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target,
- const QString &installRoot) override;
mutable std::unique_ptr<MesonProjectImporter> m_projectImporter;
};
diff --git a/src/plugins/mesonprojectmanager/project/mesonrunconfiguration.cpp b/src/plugins/mesonprojectmanager/project/mesonrunconfiguration.cpp
index a4590b41a1f..6fdcc4f9647 100644
--- a/src/plugins/mesonprojectmanager/project/mesonrunconfiguration.cpp
+++ b/src/plugins/mesonprojectmanager/project/mesonrunconfiguration.cpp
@@ -31,36 +31,36 @@
#include <projectexplorer/desktoprunconfiguration.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/localenvironmentaspect.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/target.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
+using namespace ProjectExplorer;
+
namespace MesonProjectManager {
namespace Internal {
-MesonRunConfiguration::MesonRunConfiguration(ProjectExplorer::Target *target, Utils::Id id)
- : ProjectExplorer::RunConfiguration{target, id}
+MesonRunConfiguration::MesonRunConfiguration(Target *target, Utils::Id id)
+ : RunConfiguration{target, id}
{
- auto envAspect = addAspect<ProjectExplorer::LocalEnvironmentAspect>(target);
+ auto envAspect = addAspect<LocalEnvironmentAspect>(target);
- addAspect<ProjectExplorer::ExecutableAspect>();
- addAspect<ProjectExplorer::ArgumentsAspect>();
- addAspect<ProjectExplorer::WorkingDirectoryAspect>();
- addAspect<ProjectExplorer::TerminalAspect>();
+ addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
+ addAspect<TerminalAspect>();
- auto libAspect = addAspect<ProjectExplorer::UseLibraryPathsAspect>();
- connect(libAspect,
- &ProjectExplorer::UseLibraryPathsAspect::changed,
- envAspect,
- &ProjectExplorer::EnvironmentAspect::environmentChanged);
+ auto libAspect = addAspect<UseLibraryPathsAspect>();
+ connect(libAspect, &UseLibraryPathsAspect::changed,
+ envAspect, &EnvironmentAspect::environmentChanged);
if (Utils::HostOsInfo::isMacHost()) {
- auto dyldAspect = addAspect<ProjectExplorer::UseDyldSuffixAspect>();
- connect(dyldAspect,
- &ProjectExplorer::UseLibraryPathsAspect::changed,
- envAspect,
- &ProjectExplorer::EnvironmentAspect::environmentChanged);
+ auto dyldAspect = addAspect<UseDyldSuffixAspect>();
+ connect(dyldAspect, &UseLibraryPathsAspect::changed,
+ envAspect, &EnvironmentAspect::environmentChanged);
envAspect->addModifier([dyldAspect](Utils::Environment &env) {
if (dyldAspect->value())
env.set(QLatin1String("DYLD_IMAGE_SUFFIX"), QLatin1String("_debug"));
@@ -68,17 +68,14 @@ MesonRunConfiguration::MesonRunConfiguration(ProjectExplorer::Target *target, Ut
}
envAspect->addModifier([this, libAspect](Utils::Environment &env) {
- ProjectExplorer::BuildTargetInfo bti = buildTargetInfo();
+ BuildTargetInfo bti = buildTargetInfo();
if (bti.runEnvModifier)
bti.runEnvModifier(env, libAspect->value());
});
setUpdater([this] { updateTargetInformation(); });
- connect(target,
- &ProjectExplorer::Target::buildSystemUpdated,
- this,
- &ProjectExplorer::RunConfiguration::update);
+ connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
}
void MesonRunConfiguration::updateTargetInformation()
@@ -86,13 +83,11 @@ void MesonRunConfiguration::updateTargetInformation()
if (!activeBuildSystem())
return;
- ProjectExplorer::BuildTargetInfo bti = buildTargetInfo();
- auto terminalAspect = aspect<ProjectExplorer::TerminalAspect>();
- terminalAspect->setUseTerminalHint(bti.usesTerminal);
- aspect<ProjectExplorer::ExecutableAspect>()->setExecutable(bti.targetFilePath);
- aspect<ProjectExplorer::WorkingDirectoryAspect>()->setDefaultWorkingDirectory(
- bti.workingDirectory);
- emit aspect<ProjectExplorer::LocalEnvironmentAspect>()->environmentChanged();
+ BuildTargetInfo bti = buildTargetInfo();
+ aspect<TerminalAspect>()->setUseTerminalHint(bti.usesTerminal);
+ aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
+ aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
+ emit aspect<LocalEnvironmentAspect>()->environmentChanged();
}
MesonRunConfigurationFactory::MesonRunConfigurationFactory()
diff --git a/src/plugins/mesonprojectmanager/project/mesonrunconfiguration.h b/src/plugins/mesonprojectmanager/project/mesonrunconfiguration.h
index 7e657201ca9..a31439883d2 100644
--- a/src/plugins/mesonprojectmanager/project/mesonrunconfiguration.h
+++ b/src/plugins/mesonprojectmanager/project/mesonrunconfiguration.h
@@ -25,9 +25,7 @@
#pragma once
-#include <projectexplorer/desktoprunconfiguration.h>
#include <projectexplorer/runconfiguration.h>
-#include <projectexplorer/target.h>
namespace MesonProjectManager {
namespace Internal {
diff --git a/src/plugins/mesonprojectmanager/project/ninjabuildstep.cpp b/src/plugins/mesonprojectmanager/project/ninjabuildstep.cpp
index 067e853a59e..76276a9a895 100644
--- a/src/plugins/mesonprojectmanager/project/ninjabuildstep.cpp
+++ b/src/plugins/mesonprojectmanager/project/ninjabuildstep.cpp
@@ -185,11 +185,6 @@ QString NinjaBuildStep::defaultBuildTarget() const
return {Constants::Targets::all};
}
-void NinjaBuildStep::doRun()
-{
- AbstractProcessStep::doRun();
-}
-
void NinjaBuildStep::setupOutputFormatter(Utils::OutputFormatter *formatter)
{
auto mesonOutputParser = new MesonOutputParser;
diff --git a/src/plugins/mesonprojectmanager/project/ninjabuildstep.h b/src/plugins/mesonprojectmanager/project/ninjabuildstep.h
index c4a6a81875b..d231c01af84 100644
--- a/src/plugins/mesonprojectmanager/project/ninjabuildstep.h
+++ b/src/plugins/mesonprojectmanager/project/ninjabuildstep.h
@@ -30,8 +30,6 @@
#include <projectexplorer/abstractprocessstep.h>
#include <projectexplorer/buildstep.h>
-#include <utils/qtcprocess.h>
-
namespace MesonProjectManager {
namespace Internal {
@@ -54,7 +52,6 @@ public:
private:
void update(bool parsingSuccessful);
- void doRun() override;
void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
QString defaultBuildTarget() const;
diff --git a/src/plugins/mesonprojectmanager/resources.qrc b/src/plugins/mesonprojectmanager/resources_meson.qrc
index eb7fd47f0de..eb7fd47f0de 100644
--- a/src/plugins/mesonprojectmanager/resources.qrc
+++ b/src/plugins/mesonprojectmanager/resources_meson.qrc
diff --git a/src/plugins/mesonprojectmanager/settings/general/settings.cpp b/src/plugins/mesonprojectmanager/settings/general/settings.cpp
index 03a9ed293a4..694f8b063bb 100644
--- a/src/plugins/mesonprojectmanager/settings/general/settings.cpp
+++ b/src/plugins/mesonprojectmanager/settings/general/settings.cpp
@@ -41,9 +41,12 @@ Settings::Settings()
autorunMeson.setLabelText(tr("Autorun Meson"));
autorunMeson.setToolTip(tr("Automatically run Meson when needed."));
- verboseNinja.setSettingsKey("meson.autorun");
+ verboseNinja.setSettingsKey("ninja.verbose");
verboseNinja.setLabelText(tr("Ninja verbose mode"));
verboseNinja.setToolTip(tr("Enables verbose mode by default when invoking Ninja."));
+
+ registerAspect(&autorunMeson);
+ registerAspect(&verboseNinja);
}
Settings *Settings::instance()
diff --git a/src/plugins/modeleditor/CMakeLists.txt b/src/plugins/modeleditor/CMakeLists.txt
index df35e771464..2667c790430 100644
--- a/src/plugins/modeleditor/CMakeLists.txt
+++ b/src/plugins/modeleditor/CMakeLists.txt
@@ -1,5 +1,4 @@
add_qtc_plugin(ModelEditor
- DEFINES MODELEDITOR_LIBRARY
DEPENDS Modeling Qt5::Core Qt5::Gui Qt5::Widgets
PLUGIN_DEPENDS Core CppEditor ProjectExplorer
SOURCES
diff --git a/src/plugins/modeleditor/classviewcontroller.cpp b/src/plugins/modeleditor/classviewcontroller.cpp
index cee051f4034..fdd4b2f0abd 100644
--- a/src/plugins/modeleditor/classviewcontroller.cpp
+++ b/src/plugins/modeleditor/classviewcontroller.cpp
@@ -76,7 +76,7 @@ void ClassViewController::appendClassDeclarationsFromSymbol(CPlusPlus::Symbol *s
int line, int column,
QSet<QString> *classNames)
{
- if (symbol->isClass()
+ if (symbol->asClass()
&& (line <= 0 || (symbol->line() == line && symbol->column() == column + 1)))
{
CPlusPlus::Overview overview;
@@ -87,7 +87,7 @@ void ClassViewController::appendClassDeclarationsFromSymbol(CPlusPlus::Symbol *s
classNames->insert(className);
}
- if (symbol->isScope()) {
+ if (symbol->asScope()) {
CPlusPlus::Scope *scope = symbol->asScope();
int total = scope->memberCount();
for (int i = 0; i < total; ++i) {
diff --git a/src/plugins/modeleditor/componentviewcontroller.cpp b/src/plugins/modeleditor/componentviewcontroller.cpp
index 1a3c4f0f0ac..11428e64de0 100644
--- a/src/plugins/modeleditor/componentviewcontroller.cpp
+++ b/src/plugins/modeleditor/componentviewcontroller.cpp
@@ -168,11 +168,12 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen
CppEditor::CppModelManager *cppModelManager = CppEditor::CppModelManager::instance();
CPlusPlus::Snapshot snapshot = cppModelManager->snapshot();
- QStringList filePaths = findFilePathOfComponent(component);
- foreach (const QString &filePath, filePaths) {
+ const QStringList filePaths = findFilePathOfComponent(component);
+ for (const QString &filePath : filePaths) {
CPlusPlus::Document::Ptr document = snapshot.document(filePath);
if (document) {
- foreach (const CPlusPlus::Document::Include &include, document->resolvedIncludes()) {
+ const QList<CPlusPlus::Document::Include> includes = document->resolvedIncludes();
+ for (const CPlusPlus::Document::Include &include : includes) {
QString includeFilePath = include.resolvedFileName();
// replace proxy header with real one
CPlusPlus::Document::Ptr includeDocument = snapshot.document(includeFilePath);
@@ -214,7 +215,8 @@ QStringList UpdateIncludeDependenciesVisitor::findFilePathOfComponent(const qmt:
}
QStringList bestFilePaths;
int maxPathLength = 1;
- foreach (const Node &node, m_filePaths.values(component->name())) {
+ const QList<Node> nodes = m_filePaths.values(component->name());
+ for (const Node &node : nodes) {
int i = elementPath.size() - 1;
int j = node.m_elementPath.size() - 1;
while (i >= 0 && j >= 0 && elementPath.at(i) == node.m_elementPath.at(j)) {
@@ -235,14 +237,16 @@ QStringList UpdateIncludeDependenciesVisitor::findFilePathOfComponent(const qmt:
void UpdateIncludeDependenciesVisitor::collectElementPaths(const ProjectExplorer::FolderNode *folderNode,
QMultiHash<QString, Node> *filePathsMap)
{
- foreach (const ProjectExplorer::FileNode *fileNode, folderNode->fileNodes()) {
+ const QList<ProjectExplorer::FileNode *> fileNodes = folderNode->fileNodes();
+ for (const ProjectExplorer::FileNode *fileNode : fileNodes) {
QString elementName = qmt::NameController::convertFileNameToElementName(fileNode->filePath().toString());
QFileInfo fileInfo = fileNode->filePath().toFileInfo();
QString nodePath = fileInfo.path();
QStringList elementsPath = qmt::NameController::buildElementsPath(nodePath, false);
filePathsMap->insert(elementName, Node(fileNode->filePath().toString(), elementsPath));
}
- foreach (const ProjectExplorer::FolderNode *subNode, folderNode->folderNodes())
+ const QList<ProjectExplorer::FolderNode *> subNodes = folderNode->folderNodes();
+ for (const ProjectExplorer::FolderNode *subNode : subNodes)
collectElementPaths(subNode, filePathsMap);
}
diff --git a/src/plugins/modeleditor/elementtasks.cpp b/src/plugins/modeleditor/elementtasks.cpp
index 82cad867fd5..0672d7d43d2 100644
--- a/src/plugins/modeleditor/elementtasks.cpp
+++ b/src/plugins/modeleditor/elementtasks.cpp
@@ -114,9 +114,9 @@ bool ElementTasks::hasClassDefinition(const qmt::MElement *element) const
return false;
QFutureInterface<Core::LocatorFilterEntry> dummyInterface;
- QList<Core::LocatorFilterEntry> matches = classesFilter->matchesFor(dummyInterface,
- qualifiedClassName);
- foreach (const Core::LocatorFilterEntry &entry, matches) {
+ const QList<Core::LocatorFilterEntry> matches
+ = classesFilter->matchesFor(dummyInterface, qualifiedClassName);
+ for (const Core::LocatorFilterEntry &entry : matches) {
CppEditor::IndexItem::Ptr info = qvariant_cast<CppEditor::IndexItem::Ptr>(entry.internalData);
if (info->scopedSymbolName() != qualifiedClassName)
continue;
@@ -151,8 +151,9 @@ void ElementTasks::openClassDefinition(const qmt::MElement *element)
return;
QFutureInterface<Core::LocatorFilterEntry> dummyInterface;
- QList<Core::LocatorFilterEntry> matches = classesFilter->matchesFor(dummyInterface, qualifiedClassName);
- foreach (const Core::LocatorFilterEntry &entry, matches) {
+ const QList<Core::LocatorFilterEntry> matches
+ = classesFilter->matchesFor(dummyInterface, qualifiedClassName);
+ for (const Core::LocatorFilterEntry &entry : matches) {
CppEditor::IndexItem::Ptr info = qvariant_cast<CppEditor::IndexItem::Ptr>(entry.internalData);
if (info->scopedSymbolName() != qualifiedClassName)
continue;
diff --git a/src/plugins/modeleditor/modeleditor.cpp b/src/plugins/modeleditor/modeleditor.cpp
index 286e5b560f0..9c641ddb171 100644
--- a/src/plugins/modeleditor/modeleditor.cpp
+++ b/src/plugins/modeleditor/modeleditor.cpp
@@ -745,7 +745,8 @@ void ModelEditor::updateSelectedArea(SelectedArea selectedArea)
if (hasSelection) {
qmt::DSelection selection = documentController->diagramsManager()->diagramSceneModel(activeDiagram)->selectedElements();
if (!selection.isEmpty()) {
- foreach (qmt::DSelection::Index index, selection.indices()) {
+ const QList<qmt::DSelection::Index> indexes = selection.indices();
+ for (qmt::DSelection::Index index : indexes) {
qmt::DElement *diagramElement = documentController->diagramController()->findElement(index.elementKey(), activeDiagram);
if (diagramElement)
propertiesDiagramElements.append(diagramElement);
@@ -765,9 +766,9 @@ void ModelEditor::updateSelectedArea(SelectedArea selectedArea)
canPaste = hasSingleSelection && !modelsManager->isModelClipboardEmpty();
canSelectAll = activeDiagram && !activeDiagram->diagramElements().isEmpty();
canExportDiagram = activeDiagram != nullptr;
- QModelIndexList indexes = d->modelTreeView->selectedSourceModelIndexes();
+ const QModelIndexList indexes = d->modelTreeView->selectedSourceModelIndexes();
if (!indexes.isEmpty()) {
- foreach (const QModelIndex &propertiesIndex, indexes) {
+ for (const QModelIndex &propertiesIndex : indexes) {
if (propertiesIndex.isValid()) {
qmt::MElement *modelElement = documentController->treeModel()->element(propertiesIndex);
if (modelElement)
@@ -1065,7 +1066,7 @@ void ModelEditor::initToolbars()
QList<qmt::Toolbar> toolbars = stereotypeController->toolbars();
std::stable_sort(toolbars.begin(), toolbars.end(),
[=](const qmt::Toolbar &lhs, const qmt::Toolbar &rhs) { return lhs.priority() > rhs.priority(); });
- foreach (const qmt::Toolbar &toolbar, toolbars) {
+ for (const qmt::Toolbar &toolbar : qAsConst(toolbars)) {
QWidget *toolBar = toolBars.value(toolbar.id());
QLayout *toolBarLayout = nullptr;
if (!toolBar) {
@@ -1081,7 +1082,8 @@ void ModelEditor::initToolbars()
toolBarLayout = toolBar->layout();
QMT_ASSERT(toolBarLayout, continue);
}
- foreach (const qmt::Toolbar::Tool &tool, toolbar.tools()) {
+ const QList<qmt::Toolbar::Tool> tools = toolbar.tools();
+ for (const qmt::Toolbar::Tool &tool : tools) {
switch (tool.m_toolType) {
case qmt::Toolbar::TooltypeTool:
{
@@ -1193,7 +1195,7 @@ void ModelEditor::initToolbars()
// add stretch to all layouts and calculate width of tool bar
int maxWidth = 48;
- foreach (QWidget *toolBar, toolBars) {
+ for (QWidget *toolBar : qAsConst(toolBars)) {
QMT_ASSERT(toolBar, continue);
auto layout = qobject_cast<QBoxLayout *>(toolBar->layout());
QMT_ASSERT(layout, continue);
@@ -1442,13 +1444,14 @@ void ModelEditor::synchronizeDiagramWithBrowser()
if (currentDiagram()) {
bool done = false;
qmt::DocumentController *documentController = d->document->documentController();
- QModelIndexList indexes = d->modelTreeView->selectedSourceModelIndexes();
+ const QModelIndexList indexes = d->modelTreeView->selectedSourceModelIndexes();
if (!indexes.isEmpty()) {
- foreach (const QModelIndex &index, indexes) {
+ for (const QModelIndex &index : indexes) {
if (index.isValid()) {
qmt::MElement *modelElement = documentController->treeModel()->element(index);
if (modelElement) {
- foreach (qmt::DElement *diagramElement, currentDiagram()->diagramElements()) {
+ const QList<qmt::DElement *> diagramElements = currentDiagram()->diagramElements();
+ for (qmt::DElement *diagramElement : diagramElements) {
if (diagramElement->modelUid() == modelElement->uid()) {
// disconnect temporarily avoiding double update of properties Ui
disconnect(documentController->diagramsManager(), &qmt::DiagramsManager::diagramSelectionChanged,
@@ -1479,7 +1482,8 @@ void ModelEditor::synchronizeBrowserWithDiagram(const qmt::MDiagram *diagram)
qmt::DocumentController *documentController = d->document->documentController();
qmt::DSelection selection = documentController->diagramsManager()->diagramSceneModel(diagram)->selectedElements();
if (!selection.isEmpty()) {
- foreach (qmt::DSelection::Index index, selection.indices()) {
+ const QList<qmt::DSelection::Index> indexes = selection.indices();
+ for (qmt::DSelection::Index index : indexes) {
qmt::DElement *diagramElement = documentController->diagramController()->findElement(index.elementKey(), diagram);
if (diagramElement) {
qmt::MElement *modelElement = documentController->modelController()->findElement(diagramElement->modelUid());
diff --git a/src/plugins/modeleditor/modeleditor_global.h b/src/plugins/modeleditor/modeleditor_global.h
index 0327c570e36..5fdca6f4040 100644
--- a/src/plugins/modeleditor/modeleditor_global.h
+++ b/src/plugins/modeleditor/modeleditor_global.h
@@ -29,6 +29,8 @@
#if defined(MODELEDITOR_LIBRARY)
# define MODELEDITOR_EXPORT Q_DECL_EXPORT
+#elif defined(MODELEDITOR_STATIC_LIBRARY)
+# define MODELEDITOR_EXPORT
#else
# define MODELEDITOR_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/modeleditor/modelindexer.cpp b/src/plugins/modeleditor/modelindexer.cpp
index d05cf9ecb3d..322a873f86b 100644
--- a/src/plugins/modeleditor/modelindexer.cpp
+++ b/src/plugins/modeleditor/modelindexer.cpp
@@ -43,10 +43,9 @@
#include <projectexplorer/session.h>
#include <projectexplorer/projectnodes.h>
-#include <utils/mimetypes/mimetype.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/qtcassert.h>
+#include <utils/mimeutils.h>
#include <utils/porting.h>
+#include <utils/qtcassert.h>
#include <QQueue>
#include <QMutex>
@@ -432,13 +431,15 @@ void ModelIndexer::scanProject(ProjectExplorer::Project *project)
}
// remove deleted files from indexed models
- foreach (const QString &file, d->indexedModels.keys()) {
+ const QStringList files = d->indexedModels.keys();
+ for (const QString &file : files) {
if (!filesSet.contains(QueuedFile(file, project)))
removeModelFile(file, project);
}
// remove deleted files from indexed diagrams
- foreach (const QString &file, d->indexedDiagramReferences.keys()) {
+ const QStringList deletedFiles = d->indexedDiagramReferences.keys();
+ for (const QString &file : deletedFiles) {
if (!filesSet.contains(QueuedFile(file, project)))
removeDiagramReferenceFile(file, project);
}
@@ -469,11 +470,13 @@ QString ModelIndexer::findFirstModel(ProjectExplorer::FolderNode *folderNode,
{
if (!mimeType.isValid())
return QString();
- foreach (ProjectExplorer::FileNode *fileNode, folderNode->fileNodes()) {
+ const QList<ProjectExplorer::FileNode *> fileNodes = folderNode->fileNodes();
+ for (const ProjectExplorer::FileNode *fileNode : fileNodes) {
if (mimeType.suffixes().contains(fileNode->filePath().completeSuffix()))
return fileNode->filePath().toString();
}
- foreach (ProjectExplorer::FolderNode *subFolderNode, folderNode->folderNodes()) {
+ const QList<ProjectExplorer::FolderNode *> subFolderNodes = folderNode->folderNodes();
+ for (ProjectExplorer::FolderNode *subFolderNode : subFolderNodes) {
QString modelFileName = findFirstModel(subFolderNode, mimeType);
if (!modelFileName.isEmpty())
return modelFileName;
diff --git a/src/plugins/modeleditor/modelsmanager.cpp b/src/plugins/modeleditor/modelsmanager.cpp
index a4a2a1e3da5..09375871765 100644
--- a/src/plugins/modeleditor/modelsmanager.cpp
+++ b/src/plugins/modeleditor/modelsmanager.cpp
@@ -167,7 +167,7 @@ void ModelsManager::releaseModel(ExtDocumentController *documentController)
void ModelsManager::openDiagram(const qmt::Uid &modelUid, const qmt::Uid &diagramUid)
{
- foreach (const ManagedModel &managedModel, d->managedModels) {
+ for (const ManagedModel &managedModel : qAsConst(d->managedModels)) {
if (managedModel.m_documentController->projectController()->project()->uid() == modelUid) {
qmt::MDiagram *diagram = managedModel.m_documentController->modelController()->findObject<qmt::MDiagram>(diagramUid);
QMT_ASSERT(diagram, continue);
@@ -230,7 +230,7 @@ void ModelsManager::onAboutToShowContextMenu(ProjectExplorer::Node *node)
{
bool canOpenDiagram = false;
- foreach (const ManagedModel &managedModel, d->managedModels) {
+ for (const ManagedModel &managedModel : qAsConst(d->managedModels)) {
if (managedModel.m_documentController->pxNodeController()->hasDiagramForExplorerNode(node)) {
canOpenDiagram = true;
break;
@@ -248,7 +248,7 @@ void ModelsManager::onOpenDiagramFromProjectExplorer()
{
if (ProjectExplorer::ProjectTree::currentNode() == d->contextMenuOwnerNode) {
qmt::MDiagram *diagram = nullptr;
- foreach (const ManagedModel &managedModel, d->managedModels) {
+ for (const ManagedModel &managedModel : qAsConst(d->managedModels)) {
if ((diagram = managedModel.m_documentController->pxNodeController()->findDiagramForExplorerNode(d->contextMenuOwnerNode))) {
openDiagram(managedModel.m_documentController, diagram);
break;
@@ -267,7 +267,7 @@ void ModelsManager::onOpenDefaultModel(const qmt::Uid &modelUid)
void ModelsManager::openDiagram(ExtDocumentController *documentController,
qmt::MDiagram *diagram)
{
- foreach (const ManagedModel &managedModel, d->managedModels) {
+ for (const ManagedModel &managedModel : qAsConst(d->managedModels)) {
if (managedModel.m_documentController == documentController) {
Core::IEditor *editor = Core::EditorManager::activateEditorForDocument(managedModel.m_modelDocument);
if (auto modelEditor = qobject_cast<ModelEditor *>(editor)) {
diff --git a/src/plugins/modeleditor/modelutilities.cpp b/src/plugins/modeleditor/modelutilities.cpp
index 58c8d7d851d..2232d837df1 100644
--- a/src/plugins/modeleditor/modelutilities.cpp
+++ b/src/plugins/modeleditor/modelutilities.cpp
@@ -74,7 +74,7 @@ bool ModelUtilities::haveDependency(const qmt::MObject *source,
bool ModelUtilities::haveDependency(const qmt::MObject *source,
const QList<qmt::MPackage *> &targets)
{
- foreach (const qmt::MPackage *target, targets) {
+ for (const qmt::MPackage *target : targets) {
if (haveDependency(source, target))
return true;
}
diff --git a/src/plugins/modeleditor/pxnodecontroller.cpp b/src/plugins/modeleditor/pxnodecontroller.cpp
index fba2f1c8cab..5761b727152 100644
--- a/src/plugins/modeleditor/pxnodecontroller.cpp
+++ b/src/plugins/modeleditor/pxnodecontroller.cpp
@@ -156,11 +156,12 @@ void PxNodeController::addFileSystemEntry(const QString &filePath, int line, int
auto menu = new QMenu;
menu->addAction(new MenuAction(tr("Add Component %1").arg(elementName), elementName,
MenuAction::TYPE_ADD_COMPONENT, menu));
- QStringList classNames = Utils::toList(d->classViewController->findClassDeclarations(filePath, line, column));
+ const QStringList classNames = Utils::toList(
+ d->classViewController->findClassDeclarations(filePath, line, column));
if (!classNames.empty()) {
menu->addSeparator();
int index = 0;
- foreach (const QString &className, classNames) {
+ for (const QString &className : classNames) {
auto action = new MenuAction(tr("Add Class %1").arg(className), elementName,
MenuAction::TYPE_ADD_CLASS, index, menu);
action->className = className;
diff --git a/src/plugins/nim/editor/nimtexteditorwidget.cpp b/src/plugins/nim/editor/nimtexteditorwidget.cpp
index 7ec1791c962..8f0c517ac71 100644
--- a/src/plugins/nim/editor/nimtexteditorwidget.cpp
+++ b/src/plugins/nim/editor/nimtexteditorwidget.cpp
@@ -60,7 +60,7 @@ NimTextEditorWidget::NimTextEditorWidget(QWidget *parent)
setLanguageSettingsId(Nim::Constants::C_NIMLANGUAGE_ID);
}
-void NimTextEditorWidget::findLinkAt(const QTextCursor &c, Utils::ProcessLinkCallback &&processLinkCallback, bool /*resolveTarget*/, bool /*inNextSplit*/)
+void NimTextEditorWidget::findLinkAt(const QTextCursor &c, const Utils::LinkHandler &processLinkCallback, bool /*resolveTarget*/, bool /*inNextSplit*/)
{
const Utils::FilePath &path = textDocument()->filePath();
@@ -90,7 +90,7 @@ void NimTextEditorWidget::findLinkAt(const QTextCursor &c, Utils::ProcessLinkCal
m_callback(Utils::Link());
m_dirtyFile = std::move(dirtyFile);
- m_callback = std::move(processLinkCallback);
+ m_callback = processLinkCallback;
m_request = std::move(request);
QObject::connect(m_request.get(), &NimSuggestClientRequest::finished, this, &NimTextEditorWidget::onFindLinkFinished);
diff --git a/src/plugins/nim/editor/nimtexteditorwidget.h b/src/plugins/nim/editor/nimtexteditorwidget.h
index 8cbc207ebc1..097e81507ca 100644
--- a/src/plugins/nim/editor/nimtexteditorwidget.h
+++ b/src/plugins/nim/editor/nimtexteditorwidget.h
@@ -36,13 +36,13 @@ public:
NimTextEditorWidget(QWidget* parent = nullptr);
protected:
- void findLinkAt(const QTextCursor &, Utils::ProcessLinkCallback &&processLinkCallback, bool resolveTarget, bool inNextSplit);
+ void findLinkAt(const QTextCursor &, const Utils::LinkHandler &processLinkCallback, bool resolveTarget, bool inNextSplit);
private:
void onFindLinkFinished();
std::shared_ptr<Nim::Suggest::NimSuggestClientRequest> m_request;
- Utils::ProcessLinkCallback m_callback;
+ Utils::LinkHandler m_callback;
std::unique_ptr<QTemporaryFile> m_dirtyFile;
};
diff --git a/src/plugins/nim/nimplugin.cpp b/src/plugins/nim/nimplugin.cpp
index 4bd3a326dd6..418032f6e90 100644
--- a/src/plugins/nim/nimplugin.cpp
+++ b/src/plugins/nim/nimplugin.cpp
@@ -27,7 +27,6 @@
#include "nimconstants.h"
#include "editor/nimeditorfactory.h"
-#include "editor/nimhighlighter.h"
#include "project/nimblerunconfiguration.h"
#include "project/nimblebuildconfiguration.h"
#include "project/nimbuildconfiguration.h"
@@ -45,10 +44,13 @@
#include "suggest/nimsuggestcache.h"
#include <coreplugin/fileiconprovider.h>
+
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
-#include <projectexplorer/toolchainmanager.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/taskhub.h>
+#include <projectexplorer/toolchainmanager.h>
+
#include <texteditor/snippets/snippetprovider.h>
using namespace Utils;
diff --git a/src/plugins/nim/project/nimblebuildstep.cpp b/src/plugins/nim/project/nimblebuildstep.cpp
index b242d2128c7..c871926a0a2 100644
--- a/src/plugins/nim/project/nimblebuildstep.cpp
+++ b/src/plugins/nim/project/nimblebuildstep.cpp
@@ -55,14 +55,13 @@ private:
NimbleBuildStep::NimbleBuildStep(BuildStepList *parentList, Id id)
: AbstractProcessStep(parentList, id)
{
- auto arguments = addAspect<ArgumentsAspect>();
+ auto arguments = addAspect<ArgumentsAspect>(macroExpander());
arguments->setSettingsKey(Constants::C_NIMBLEBUILDSTEP_ARGUMENTS);
arguments->setResetter([this] { return defaultArguments(); });
arguments->setArguments(defaultArguments());
setCommandLineProvider([this, arguments] {
- return CommandLine(Nim::nimblePathFromKit(kit()),
- {"build", arguments->arguments(macroExpander())});
+ return CommandLine(Nim::nimblePathFromKit(kit()), {"build", arguments->arguments()});
});
setWorkingDirectoryProvider([this] { return project()->projectDirectory(); });
setEnvironmentModifier([this](Environment &env) {
diff --git a/src/plugins/nim/project/nimblebuildsystem.cpp b/src/plugins/nim/project/nimblebuildsystem.cpp
index 7a2a642eebc..634012cb42f 100644
--- a/src/plugins/nim/project/nimblebuildsystem.cpp
+++ b/src/plugins/nim/project/nimblebuildsystem.cpp
@@ -63,7 +63,7 @@ static std::vector<NimbleTask> parseTasks(const FilePath &nimblePath, const File
std::vector<NimbleTask> result;
if (process.exitCode() != 0) {
- TaskHub::addTask(Task(Task::Error, process.stdOut(), {}, -1, Constants::C_NIMPARSE_ID));
+ TaskHub::addTask(Task(Task::Error, process.cleanedStdOut(), {}, -1, Constants::C_NIMPARSE_ID));
return result;
}
@@ -91,7 +91,7 @@ static NimbleMetadata parseMetadata(const FilePath &nimblePath, const FilePath &
NimbleMetadata result = {};
if (process.exitCode() != 0) {
- TaskHub::addTask(Task(Task::Error, process.stdOut(), {}, -1, Constants::C_NIMPARSE_ID));
+ TaskHub::addTask(Task(Task::Error, process.cleanedStdOut(), {}, -1, Constants::C_NIMPARSE_ID));
return result;
}
const QList<QByteArray> &lines = linesFromProcessOutput(&process);
diff --git a/src/plugins/nim/project/nimblerunconfiguration.cpp b/src/plugins/nim/project/nimblerunconfiguration.cpp
index 1dcd9315ac2..9364192d049 100644
--- a/src/plugins/nim/project/nimblerunconfiguration.cpp
+++ b/src/plugins/nim/project/nimblerunconfiguration.cpp
@@ -25,11 +25,11 @@
#include "nimblerunconfiguration.h"
-#include "nimblebuildsystem.h"
+#include "nimbuildsystem.h"
#include "nimconstants.h"
-#include "nimbleproject.h"
#include <projectexplorer/localenvironmentaspect.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
@@ -51,10 +51,10 @@ public:
NimbleRunConfiguration(Target *target, Utils::Id id)
: RunConfiguration(target, id)
{
- addAspect<LocalEnvironmentAspect>(target);
- addAspect<ExecutableAspect>();
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ auto envAspect = addAspect<LocalEnvironmentAspect>(target);
+ addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
addAspect<TerminalAspect>();
setUpdater([this] {
@@ -89,9 +89,11 @@ public:
NimbleTestConfiguration(ProjectExplorer::Target *target, Utils::Id id)
: RunConfiguration(target, id)
{
- addAspect<ExecutableAspect>()->setExecutable(Nim::nimblePathFromKit(target->kit()));
- addAspect<ArgumentsAspect>()->setArguments("test");
- addAspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(project()->projectDirectory());
+ addAspect<ExecutableAspect>(target, ExecutableAspect::BuildDevice)
+ ->setExecutable(Nim::nimblePathFromKit(target->kit()));
+ addAspect<ArgumentsAspect>(macroExpander())->setArguments("test");
+ addAspect<WorkingDirectoryAspect>(macroExpander(), nullptr)
+ ->setDefaultWorkingDirectory(project()->projectDirectory());
addAspect<TerminalAspect>();
setDisplayName(tr("Nimble Test"));
diff --git a/src/plugins/nim/project/nimbuildconfiguration.cpp b/src/plugins/nim/project/nimbuildconfiguration.cpp
index e27b1374f24..37b2e0d9ef1 100644
--- a/src/plugins/nim/project/nimbuildconfiguration.cpp
+++ b/src/plugins/nim/project/nimbuildconfiguration.cpp
@@ -39,7 +39,6 @@
#include <projectexplorer/target.h>
#include <utils/aspects.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
using namespace ProjectExplorer;
@@ -54,7 +53,7 @@ static FilePath defaultBuildDirectory(const Kit *k,
{
return BuildConfiguration::buildDirectoryFromTemplate(
projectFilePath.parentDir(), projectFilePath, projectFilePath.baseName(),
- k, bc, buildType);
+ k, bc, buildType, "nim");
}
NimBuildConfiguration::NimBuildConfiguration(Target *target, Utils::Id id)
diff --git a/src/plugins/nim/project/nimrunconfiguration.cpp b/src/plugins/nim/project/nimrunconfiguration.cpp
index ef3e478b857..af6fb6713f2 100644
--- a/src/plugins/nim/project/nimrunconfiguration.cpp
+++ b/src/plugins/nim/project/nimrunconfiguration.cpp
@@ -49,10 +49,10 @@ public:
NimRunConfiguration(Target *target, Utils::Id id)
: RunConfiguration(target, id)
{
- addAspect<LocalEnvironmentAspect>(target);
- addAspect<ExecutableAspect>();
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ auto envAspect = addAspect<LocalEnvironmentAspect>(target);
+ addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
addAspect<TerminalAspect>();
setDisplayName(tr("Current Build Target"));
diff --git a/src/plugins/nim/settings/nimcodestylepreferencesfactory.cpp b/src/plugins/nim/settings/nimcodestylepreferencesfactory.cpp
index f84a7f0bf97..0d5b5c9c4b1 100644
--- a/src/plugins/nim/settings/nimcodestylepreferencesfactory.cpp
+++ b/src/plugins/nim/settings/nimcodestylepreferencesfactory.cpp
@@ -59,9 +59,10 @@ TextEditor::ICodeStylePreferences *NimCodeStylePreferencesFactory::createCodeSty
return new TextEditor::SimpleCodeStylePreferences();
}
-QWidget *NimCodeStylePreferencesFactory::createEditor(TextEditor::ICodeStylePreferences *preferences,
- ProjectExplorer::Project *project,
- QWidget *parent) const
+TextEditor::CodeStyleEditorWidget *NimCodeStylePreferencesFactory::createEditor(
+ TextEditor::ICodeStylePreferences *preferences,
+ ProjectExplorer::Project *project,
+ QWidget *parent) const
{
Q_UNUSED(project)
auto result = new NimCodeStylePreferencesWidget(preferences, parent);
diff --git a/src/plugins/nim/settings/nimcodestylepreferencesfactory.h b/src/plugins/nim/settings/nimcodestylepreferencesfactory.h
index 157700574cc..774e2c4e587 100644
--- a/src/plugins/nim/settings/nimcodestylepreferencesfactory.h
+++ b/src/plugins/nim/settings/nimcodestylepreferencesfactory.h
@@ -39,9 +39,9 @@ public:
Utils::Id languageId() override;
QString displayName() override;
TextEditor::ICodeStylePreferences *createCodeStyle() const override;
- QWidget *createEditor(TextEditor::ICodeStylePreferences *settings,
- ProjectExplorer::Project *project,
- QWidget *parent) const override;
+ TextEditor::CodeStyleEditorWidget *createEditor(TextEditor::ICodeStylePreferences *settings,
+ ProjectExplorer::Project *project,
+ QWidget *parent) const override;
TextEditor::Indenter *createIndenter(QTextDocument *doc) const override;
QString snippetProviderGroupId() const override;
QString previewText() const override;
diff --git a/src/plugins/nim/settings/nimcodestylepreferenceswidget.cpp b/src/plugins/nim/settings/nimcodestylepreferenceswidget.cpp
index b4e735ff48d..8c984bcd344 100644
--- a/src/plugins/nim/settings/nimcodestylepreferenceswidget.cpp
+++ b/src/plugins/nim/settings/nimcodestylepreferenceswidget.cpp
@@ -44,7 +44,7 @@ using namespace TextEditor;
namespace Nim {
NimCodeStylePreferencesWidget::NimCodeStylePreferencesWidget(ICodeStylePreferences *preferences, QWidget *parent)
- : QWidget(parent)
+ : TextEditor::CodeStyleEditorWidget(parent)
, m_preferences(preferences)
, m_ui(new Ui::NimCodeStylePreferencesWidget())
{
diff --git a/src/plugins/nim/settings/nimcodestylepreferenceswidget.h b/src/plugins/nim/settings/nimcodestylepreferenceswidget.h
index 963ff9738b4..51b0a2b5901 100644
--- a/src/plugins/nim/settings/nimcodestylepreferenceswidget.h
+++ b/src/plugins/nim/settings/nimcodestylepreferenceswidget.h
@@ -26,6 +26,7 @@
#pragma once
#include <QWidget>
+#include <texteditor/icodestylepreferencesfactory.h>
namespace TextEditor {
class ICodeStylePreferences;
@@ -36,7 +37,7 @@ namespace Nim {
namespace Ui { class NimCodeStylePreferencesWidget; }
-class NimCodeStylePreferencesWidget : public QWidget
+class NimCodeStylePreferencesWidget : public TextEditor::CodeStyleEditorWidget
{
Q_OBJECT
diff --git a/src/plugins/nim/suggest/nimsuggest.cpp b/src/plugins/nim/suggest/nimsuggest.cpp
index e51efea0545..fc12c160233 100644
--- a/src/plugins/nim/suggest/nimsuggest.cpp
+++ b/src/plugins/nim/suggest/nimsuggest.cpp
@@ -32,8 +32,7 @@ NimSuggest::NimSuggest(QObject *parent)
: QObject(parent)
{
connect(&m_server, &NimSuggestServer::started, this, &NimSuggest::onServerStarted);
- connect(&m_server, &NimSuggestServer::crashed, this, &NimSuggest::onServerCrashed);
- connect(&m_server, &NimSuggestServer::finished, this, &NimSuggest::onServerFinished);
+ connect(&m_server, &NimSuggestServer::done, this, &NimSuggest::onServerDone);
connect(&m_client, &NimSuggestClient::disconnected, this, &NimSuggest::onClientDisconnected);
connect(&m_client, &NimSuggestClient::connected, this, &NimSuggest::onClientConnected);
@@ -134,14 +133,13 @@ void NimSuggest::disconnectClient()
void NimSuggest::stopServer()
{
- m_server.kill();
+ m_server.stop();
}
void NimSuggest::startServer()
{
- if (!m_projectFile.isEmpty() && !m_executablePath.isEmpty()) {
+ if (!m_projectFile.isEmpty() && !m_executablePath.isEmpty())
m_server.start(m_executablePath, m_projectFile);
- }
}
void NimSuggest::onServerStarted()
@@ -150,18 +148,13 @@ void NimSuggest::onServerStarted()
connectClient();
}
-void NimSuggest::onServerCrashed()
+void NimSuggest::onServerDone()
{
setServerReady(false);
disconnectClient();
restart();
}
-void NimSuggest::onServerFinished()
-{
- onServerCrashed();
-}
-
void NimSuggest::onClientConnected()
{
setClientReady(true);
diff --git a/src/plugins/nim/suggest/nimsuggest.h b/src/plugins/nim/suggest/nimsuggest.h
index 5043455cec3..48190496ab2 100644
--- a/src/plugins/nim/suggest/nimsuggest.h
+++ b/src/plugins/nim/suggest/nimsuggest.h
@@ -75,8 +75,7 @@ private:
void startServer();
void onServerStarted();
- void onServerCrashed();
- void onServerFinished();
+ void onServerDone();
void onClientConnected();
void onClientDisconnected();
diff --git a/src/plugins/nim/suggest/server.cpp b/src/plugins/nim/suggest/server.cpp
index d1eb036f022..e55151afbe8 100644
--- a/src/plugins/nim/suggest/server.cpp
+++ b/src/plugins/nim/suggest/server.cpp
@@ -32,17 +32,11 @@ namespace Suggest {
NimSuggestServer::NimSuggestServer(QObject *parent) : QObject(parent)
{
- connect(&m_process, &QtcProcess::finished, this, &NimSuggestServer::onFinished);
- connect(&m_process, &QtcProcess::started, this, &NimSuggestServer::onStarted);
+ connect(&m_process, &QtcProcess::done, this, &NimSuggestServer::onDone);
connect(&m_process, &QtcProcess::readyReadStandardOutput, this,
&NimSuggestServer::onStandardOutputAvailable);
}
-NimSuggestServer::~NimSuggestServer()
-{
- kill();
-}
-
QString NimSuggestServer::executablePath() const
{
return m_executablePath;
@@ -61,7 +55,7 @@ bool NimSuggestServer::start(const QString &executablePath,
return false;
}
- m_port = 0;
+ stop();
m_executablePath = executablePath;
m_projectFilePath = projectFilePath;
m_process.setCommand({FilePath::fromString(executablePath), {"--epc", m_projectFilePath}});
@@ -69,11 +63,9 @@ bool NimSuggestServer::start(const QString &executablePath,
return true;
}
-void NimSuggestServer::kill()
+void NimSuggestServer::stop()
{
- disconnect(&m_process, &QtcProcess::finished, this, &NimSuggestServer::onFinished);
- m_process.kill();
- m_process.waitForFinished();
+ m_process.close();
clearState();
}
@@ -87,15 +79,10 @@ QString NimSuggestServer::projectFilePath() const
return m_projectFilePath;
}
-void NimSuggestServer::onStarted()
-{
- m_started = true;
-}
-
void NimSuggestServer::onStandardOutputAvailable()
{
- if (m_started && !m_portAvailable) {
- auto output = QString::fromUtf8(m_process.readAllStandardOutput());
+ if (!m_portAvailable) {
+ const QString output = QString::fromUtf8(m_process.readAllStandardOutput());
m_port = static_cast<uint16_t>(output.toUInt());
m_portAvailable = true;
emit started();
@@ -104,19 +91,14 @@ void NimSuggestServer::onStandardOutputAvailable()
}
}
-void NimSuggestServer::onFinished()
+void NimSuggestServer::onDone()
{
clearState();
-
- if (m_process.exitCode() == QProcess::ExitStatus::CrashExit)
- emit crashed();
- else
- emit finished();
+ emit done();
}
void NimSuggestServer::clearState()
{
- m_started = false;
m_portAvailable = false;
m_port = 0;
}
diff --git a/src/plugins/nim/suggest/server.h b/src/plugins/nim/suggest/server.h
index 53f0590288a..4d3a5857ef0 100644
--- a/src/plugins/nim/suggest/server.h
+++ b/src/plugins/nim/suggest/server.h
@@ -40,10 +40,9 @@ class NimSuggestServer : public QObject
public:
NimSuggestServer(QObject *parent = nullptr);
- ~NimSuggestServer();
bool start(const QString &executablePath, const QString &projectFilePath);
- void kill();
+ void stop();
quint16 port() const;
QString executablePath() const;
@@ -51,16 +50,13 @@ public:
signals:
void started();
- void finished();
- void crashed();
+ void done();
private:
- void onStarted();
void onStandardOutputAvailable();
- void onFinished();
+ void onDone();
void clearState();
- bool m_started = false;
bool m_portAvailable = false;
Utils::QtcProcess m_process;
quint16 m_port = 0;
diff --git a/src/plugins/perforce/perforcechecker.cpp b/src/plugins/perforce/perforcechecker.cpp
index bebb86768d8..8ce4f04d395 100644
--- a/src/plugins/perforce/perforcechecker.cpp
+++ b/src/plugins/perforce/perforcechecker.cpp
@@ -41,8 +41,7 @@ namespace Internal {
PerforceChecker::PerforceChecker(QObject *parent) : QObject(parent)
{
- connect(&m_process, &QtcProcess::errorOccurred, this, &PerforceChecker::slotError);
- connect(&m_process, &QtcProcess::finished, this, &PerforceChecker::slotFinished);
+ connect(&m_process, &QtcProcess::done, this, &PerforceChecker::slotDone);
}
PerforceChecker::~PerforceChecker()
@@ -108,45 +107,31 @@ void PerforceChecker::slotTimeOut()
if (!isRunning())
return;
m_timedOut = true;
- m_process.stopProcess();
+ m_process.stop();
+ m_process.waitForFinished();
emitFailed(tr("\"%1\" timed out after %2 ms.").arg(m_binary.toUserOutput()).arg(m_timeOutMS));
}
-void PerforceChecker::slotError(QProcess::ProcessError error)
+void PerforceChecker::slotDone()
{
if (m_timedOut)
return;
- switch (error) {
- case QProcess::FailedToStart:
+ if (m_process.error() == QProcess::FailedToStart) {
emitFailed(tr("Unable to launch \"%1\": %2").
arg(m_binary.toUserOutput(), m_process.errorString()));
- break;
- case QProcess::Crashed: // Handled elsewhere
- case QProcess::Timedout:
- break;
- case QProcess::ReadError:
- case QProcess::WriteError:
- case QProcess::UnknownError:
- m_process.stopProcess();
- break;
- }
-}
-
-void PerforceChecker::slotFinished()
-{
- if (m_timedOut)
return;
+ }
switch (m_process.exitStatus()) {
case QProcess::CrashExit:
emitFailed(tr("\"%1\" crashed.").arg(m_binary.toUserOutput()));
break;
case QProcess::NormalExit:
if (m_process.exitCode()) {
- const QString stdErr = m_process.stdErr();
+ const QString stdErr = m_process.cleanedStdErr();
emitFailed(tr("\"%1\" terminated with exit code %2: %3").
arg(m_binary.toUserOutput()).arg(m_process.exitCode()).arg(stdErr));
} else {
- parseOutput(m_process.stdOut());
+ parseOutput(m_process.cleanedStdOut());
}
break;
}
diff --git a/src/plugins/perforce/perforcechecker.h b/src/plugins/perforce/perforcechecker.h
index 6d8dd09146d..42d312bc8c5 100644
--- a/src/plugins/perforce/perforcechecker.h
+++ b/src/plugins/perforce/perforcechecker.h
@@ -59,8 +59,7 @@ signals:
void failed(const QString &errorMessage);
private:
- void slotError(QProcess::ProcessError error);
- void slotFinished();
+ void slotDone();
void slotTimeOut();
void emitFailed(const QString &);
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index cd340be879c..84ecf557214 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -45,6 +45,7 @@
#include <texteditor/textdocument.h>
+#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
@@ -723,7 +724,8 @@ void PerforcePluginPrivate::printOpenedFileList()
QString errorMessage;
QString mapped;
const QChar delimiter = QLatin1Char('#');
- foreach (const QString &line, perforceResponse.stdOut.split(QLatin1Char('\n'))) {
+ const QStringList lines = perforceResponse.stdOut.split(QLatin1Char('\n'));
+ for (const QString &line : lines) {
mapped.clear();
const int delimiterPos = line.indexOf(delimiter);
if (delimiterPos > 0)
@@ -786,9 +788,9 @@ void PerforcePluginPrivate::startSubmitProject()
return;
}
- QStringList filesLines = filesResult.stdOut.split(QLatin1Char('\n'));
+ const QStringList filesLines = filesResult.stdOut.split(QLatin1Char('\n'));
QStringList depotFileNames;
- foreach (const QString &line, filesLines) {
+ for (const QString &line : filesLines) {
depotFileNames.append(line.left(line.lastIndexOf(QRegularExpression("#[0-9]+\\s-\\s"))));
}
if (depotFileNames.isEmpty()) {
@@ -1270,28 +1272,28 @@ PerforceResponse PerforcePluginPrivate::synchronousProcess(const FilePath &worki
}
process.setTimeOutMessageBoxEnabled(true);
process.setCommand({m_settings.p4BinaryPath.filePath(), args});
- process.runBlocking(QtcProcess::WithEventLoop);
+ process.runBlocking(EventLoopMode::On);
PerforceResponse response;
response.error = true;
response.exitCode = process.exitCode();
- response.stdErr = process.stdErr();
- response.stdOut = process.stdOut();
+ response.stdErr = process.cleanedStdErr();
+ response.stdOut = process.cleanedStdOut();
switch (process.result()) {
- case QtcProcess::FinishedWithSuccess:
+ case ProcessResult::FinishedWithSuccess:
response.error = false;
break;
- case QtcProcess::FinishedWithError:
+ case ProcessResult::FinishedWithError:
response.message = msgExitCode(process.exitCode());
response.error = !(flags & IgnoreExitCode);
break;
- case QtcProcess::TerminatedAbnormally:
+ case ProcessResult::TerminatedAbnormally:
response.message = msgCrash();
break;
- case QtcProcess::StartFailed:
+ case ProcessResult::StartFailed:
response.message = msgNotStarted(m_settings.p4BinaryPath.value());
break;
- case QtcProcess::Hang:
+ case ProcessResult::Hang:
response.message = msgCrash();
break;
}
@@ -1327,7 +1329,8 @@ PerforceResponse PerforcePluginPrivate::fullySynchronousProcess(const FilePath &
QByteArray stdErr;
const int timeOutS = (flags & LongTimeOut) ? m_settings.longTimeOutS() : m_settings.timeOutS.value();
if (!process.readDataFromProcess(timeOutS, &stdOut, &stdErr, true)) {
- process.stopProcess();
+ process.stop();
+ process.waitForFinished();
response.error = true;
response.message = msgTimeout(timeOutS);
return response;
diff --git a/src/plugins/perforce/perforcesettings.cpp b/src/plugins/perforce/perforcesettings.cpp
index 614fc07ad26..c58dc117b52 100644
--- a/src/plugins/perforce/perforcesettings.cpp
+++ b/src/plugins/perforce/perforcesettings.cpp
@@ -240,7 +240,7 @@ PerforceSettingsPage::PerforceSettingsPage(PerforceSettings *settings)
auto errorLabel = new QLabel;
auto testButton = new QPushButton(PerforceSettings::tr("Test"));
- connect(testButton, &QPushButton::clicked, this, [this, settings, errorLabel, testButton] {
+ connect(testButton, &QPushButton::clicked, this, [settings, errorLabel, testButton] {
testButton->setEnabled(false);
auto checker = new PerforceChecker(errorLabel);
checker->setUseOverideCursor(true);
diff --git a/src/plugins/perforce/perforcesubmiteditor.cpp b/src/plugins/perforce/perforcesubmiteditor.cpp
index 115be50ad6f..a26d71ee8b9 100644
--- a/src/plugins/perforce/perforcesubmiteditor.cpp
+++ b/src/plugins/perforce/perforcesubmiteditor.cpp
@@ -125,7 +125,7 @@ void PerforceSubmitEditor::updateFields()
lines = m_entries.value(QLatin1String("Files")).split(newLine);
// split up "file#add" and store complete spec line as user data
- foreach (const QString &specLine, lines) {
+ for (const QString &specLine : qAsConst(lines)) {
const QStringList list = specLine.split(QLatin1Char('#'));
if (list.size() == 2) {
const QString file = list.at(0).trimmed();
diff --git a/src/plugins/perfprofiler/perfconfigwidget.cpp b/src/plugins/perfprofiler/perfconfigwidget.cpp
index b58900c5d60..f52bebc4852 100644
--- a/src/plugins/perfprofiler/perfconfigwidget.cpp
+++ b/src/plugins/perfprofiler/perfconfigwidget.cpp
@@ -29,7 +29,7 @@
#include <coreplugin/messagebox.h>
-#include <projectexplorer/devicesupport/deviceprocess.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/runcontrol.h>
@@ -43,7 +43,9 @@
#include <QHeaderView>
#include <QMessageBox>
#include <QMetaEnum>
+#include <QPushButton>
#include <QStyledItemDelegate>
+#include <QTableView>
using namespace Utils;
@@ -124,6 +126,8 @@ PerfConfigWidget::PerfConfigWidget(PerfSettings *settings, QWidget *parent)
}.attachTo(this);
}
+PerfConfigWidget::~PerfConfigWidget() = default;
+
void PerfConfigWidget::setTarget(ProjectExplorer::Target *target)
{
ProjectExplorer::IDevice::ConstPtr device;
@@ -140,17 +144,10 @@ void PerfConfigWidget::setTarget(ProjectExplorer::Target *target)
QTC_ASSERT(device, return);
QTC_CHECK(!m_process || m_process->state() == QProcess::NotRunning);
- m_process.reset(device->createProcess(nullptr));
- if (!m_process) {
- useTracePointsButton->setEnabled(false);
- return;
- }
-
- connect(m_process.get(), &ProjectExplorer::DeviceProcess::finished,
- this, &PerfConfigWidget::handleProcessFinished);
-
- connect(m_process.get(), &ProjectExplorer::DeviceProcess::errorOccurred,
- this, &PerfConfigWidget::handleProcessError);
+ m_process.reset(new QtcProcess);
+ m_process->setCommand({device->filePath("perf"), {"probe", "-l"}});
+ connect(m_process.get(), &QtcProcess::done,
+ this, &PerfConfigWidget::handleProcessDone);
useTracePointsButton->setEnabled(true);
}
@@ -173,15 +170,20 @@ void PerfConfigWidget::readTracePoints()
messageBox.setText(tr("Replace events with trace points read from the device?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
if (messageBox.exec() == QMessageBox::Yes) {
- ProjectExplorer::Runnable runnable;
- runnable.command = {"perf", {"probe", "-l"}};
- m_process->start(runnable);
+ m_process->start();
useTracePointsButton->setEnabled(false);
}
}
-void PerfConfigWidget::handleProcessFinished()
+void PerfConfigWidget::handleProcessDone()
{
+ if (m_process->error() == QProcess::FailedToStart) {
+ Core::AsynchronousMessageBox::warning(
+ tr("Cannot List Trace Points"),
+ tr("\"perf probe -l\" failed to start. Is perf installed?"));
+ useTracePointsButton->setEnabled(true);
+ return;
+ }
const QList<QByteArray> lines =
m_process->readAllStandardOutput().append(m_process->readAllStandardError())
.split('\n');
@@ -218,16 +220,6 @@ void PerfConfigWidget::handleProcessFinished()
useTracePointsButton->setEnabled(true);
}
-void PerfConfigWidget::handleProcessError(QProcess::ProcessError error)
-{
- if (error == QProcess::FailedToStart) {
- Core::AsynchronousMessageBox::warning(
- tr("Cannot List Trace Points"),
- tr("\"perf probe -l\" failed to start. Is perf installed?"));
- useTracePointsButton->setEnabled(true);
- }
-}
-
QWidget *SettingsDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
diff --git a/src/plugins/perfprofiler/perfconfigwidget.h b/src/plugins/perfprofiler/perfconfigwidget.h
index bb4795a7910..bac4993dec1 100644
--- a/src/plugins/perfprofiler/perfconfigwidget.h
+++ b/src/plugins/perfprofiler/perfconfigwidget.h
@@ -29,10 +29,14 @@
#include <coreplugin/dialogs/ioptionspage.h>
-#include <projectexplorer/devicesupport/deviceprocess.h>
+#include <QProcess>
-#include <QPushButton>
-#include <QTableView>
+QT_BEGIN_NAMESPACE
+class QPushButton;
+class QTableView;
+QT_END_NAMESPACE
+
+namespace Utils { class QtcProcess; }
namespace PerfProfiler {
namespace Internal {
@@ -42,6 +46,7 @@ class PerfConfigWidget : public Core::IOptionsPageWidget
Q_OBJECT
public:
explicit PerfConfigWidget(PerfSettings *settings, QWidget *parent = nullptr);
+ ~PerfConfigWidget();
void updateUi();
void setTarget(ProjectExplorer::Target *target);
@@ -51,11 +56,10 @@ private:
void apply() final;
void readTracePoints();
- void handleProcessFinished();
- void handleProcessError(QProcess::ProcessError error);
+ void handleProcessDone();
PerfSettings *m_settings;
- std::unique_ptr<ProjectExplorer::DeviceProcess> m_process;
+ std::unique_ptr<Utils::QtcProcess> m_process;
QTableView *eventsView;
QPushButton *useTracePointsButton;
diff --git a/src/plugins/perfprofiler/perfprofiler_global.h b/src/plugins/perfprofiler/perfprofiler_global.h
index 9f12da9189a..74f3557449d 100644
--- a/src/plugins/perfprofiler/perfprofiler_global.h
+++ b/src/plugins/perfprofiler/perfprofiler_global.h
@@ -29,6 +29,8 @@
#if defined(PERFPROFILER_LIBRARY)
# define PERFPROFILER_EXPORT Q_DECL_EXPORT
+#elif defined(PERFPROFILER_STATIC_LIBRARY)
+# define PERFPROFILER_EXPORT
#else
# define PERFPROFILER_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/perfprofiler/perfprofilerplugin.cpp b/src/plugins/perfprofiler/perfprofilerplugin.cpp
index c12742f113f..b9dab22afa7 100644
--- a/src/plugins/perfprofiler/perfprofilerplugin.cpp
+++ b/src/plugins/perfprofiler/perfprofilerplugin.cpp
@@ -24,12 +24,10 @@
****************************************************************************/
#include "perfoptionspage.h"
-#include "perfprofilerconstants.h"
#include "perfprofilerplugin.h"
#include "perfprofilerruncontrol.h"
#include "perfprofilertool.h"
#include "perfrunconfigurationaspect.h"
-#include "perftimelinemodelmanager.h"
#if WITH_TESTS
//# include "tests/perfprofilertracefile_test.h" // FIXME has to be rewritten
@@ -44,8 +42,10 @@
#include <coreplugin/icore.h>
#include <debugger/analyzer/analyzermanager.h>
#include <extensionsystem/pluginmanager.h>
+
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
diff --git a/src/plugins/perfprofiler/perfprofilerruncontrol.cpp b/src/plugins/perfprofiler/perfprofilerruncontrol.cpp
index 684918bb6a8..e84836e0b8f 100644
--- a/src/plugins/perfprofiler/perfprofilerruncontrol.cpp
+++ b/src/plugins/perfprofiler/perfprofilerruncontrol.cpp
@@ -23,20 +23,18 @@
**
****************************************************************************/
-#include "perfdatareader.h"
-#include "perfprofilerconstants.h"
#include "perfprofilerruncontrol.h"
+
+#include "perfdatareader.h"
#include "perfprofilertool.h"
#include "perfrunconfigurationaspect.h"
#include "perfsettings.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
-#include <projectexplorer/devicesupport/deviceprocess.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
-#include <ssh/sshconnection.h>
#include <utils/qtcprocess.h>
#include <QAction>
@@ -116,46 +114,39 @@ public:
{
setId("LocalPerfRecordWorker");
- auto perfAspect = static_cast<PerfRunConfigurationAspect *>(runControl->aspect(Constants::PerfSettingsId));
+ auto perfAspect = runControl->aspect<PerfRunConfigurationAspect>();
QTC_ASSERT(perfAspect, return);
- PerfSettings *settings = static_cast<PerfSettings *>(perfAspect->currentSettings());
+ PerfSettings *settings = static_cast<PerfSettings *>(perfAspect->currentSettings);
QTC_ASSERT(settings, return);
m_perfRecordArguments = settings->perfRecordArguments();
}
void start() override
{
- m_process = device()->createProcess(this);
- if (!m_process) {
- reportFailure(tr("Could not start device process."));
- return;
- }
+ m_process = new QtcProcess(this);
- connect(m_process, &DeviceProcess::started, this, &RunWorker::reportStarted);
- connect(m_process, &DeviceProcess::finished, this, &RunWorker::reportStopped);
- connect(m_process, &DeviceProcess::errorOccurred, [this](QProcess::ProcessError e) {
+ connect(m_process, &QtcProcess::started, this, &RunWorker::reportStarted);
+ connect(m_process, &QtcProcess::done, this, [this] {
// The terminate() below will frequently lead to QProcess::Crashed. We're not interested
// in that. FailedToStart is the only actual failure.
- if (e == QProcess::FailedToStart) {
- QString msg = tr("Perf Process Failed to Start");
- QMessageBox::warning(Core::ICore::dialogParent(),
- msg, tr("Make sure that you are running a recent Linux kernel and "
- "that the \"perf\" utility is available."));
+ if (m_process->error() == QProcess::FailedToStart) {
+ const QString msg = tr("Perf Process Failed to Start");
+ QMessageBox::warning(Core::ICore::dialogParent(), msg,
+ tr("Make sure that you are running a recent Linux kernel and "
+ "that the \"perf\" utility is available."));
reportFailure(msg);
+ return;
}
+ reportStopped();
});
- Runnable perfRunnable = runnable();
-
- QStringList arguments;
- arguments << "record";
- arguments += m_perfRecordArguments;
- arguments << "-o" << "-" << "--" << perfRunnable.command.executable().toString()
- << ProcessArgs::splitArgs(perfRunnable.command.arguments(), OsTypeLinux);
+ CommandLine cmd({device()->filePath("perf"), {"record"}});
+ cmd.addArgs(m_perfRecordArguments);
+ cmd.addArgs({"-o", "-", "--"});
+ cmd.addCommandLineAsArgs(runControl()->commandLine(), CommandLine::Raw);
- perfRunnable.command.setExecutable("perf");
- perfRunnable.command.setArguments(ProcessArgs::joinArgs(arguments, OsTypeLinux));
- m_process->start(perfRunnable);
+ m_process->setCommand(cmd);
+ m_process->start();
}
void stop() override
@@ -164,10 +155,10 @@ public:
m_process->terminate();
}
- DeviceProcess *recorder() { return m_process; }
+ QtcProcess *recorder() { return m_process; }
private:
- QPointer<DeviceProcess> m_process;
+ QPointer<QtcProcess> m_process;
QStringList m_perfRecordArguments;
};
@@ -216,12 +207,12 @@ void PerfProfilerRunner::start()
PerfDataReader *reader = m_perfParserWorker->reader();
if (auto prw = qobject_cast<LocalPerfRecordWorker *>(m_perfRecordWorker)) {
// That's the local case.
- DeviceProcess *recorder = prw->recorder();
- connect(recorder, &DeviceProcess::readyReadStandardError, this, [this, recorder] {
+ QtcProcess *recorder = prw->recorder();
+ connect(recorder, &QtcProcess::readyReadStandardError, this, [this, recorder] {
appendMessage(QString::fromLocal8Bit(recorder->readAllStandardError()),
Utils::StdErrFormat);
});
- connect(recorder, &DeviceProcess::readyReadStandardOutput, this, [this, reader, recorder] {
+ connect(recorder, &QtcProcess::readyReadStandardOutput, this, [this, reader, recorder] {
if (!reader->feedParser(recorder->readAllStandardOutput()))
reportFailure(tr("Failed to transfer Perf data to perfparser."));
});
diff --git a/src/plugins/perfprofiler/perfprofilertool.cpp b/src/plugins/perfprofiler/perfprofilertool.cpp
index 78f79b46718..6a19ccdeda4 100644
--- a/src/plugins/perfprofiler/perfprofilertool.cpp
+++ b/src/plugins/perfprofiler/perfprofilertool.cpp
@@ -26,9 +26,7 @@
#include "perfconfigwidget.h"
#include "perfloaddialog.h"
#include "perfprofilerplugin.h"
-#include "perfprofilerruncontrol.h"
#include "perfprofilertool.h"
-#include "perfrunconfigurationaspect.h"
#include "perfsettings.h"
#include "perftracepointdialog.h"
@@ -39,15 +37,20 @@
#include <coreplugin/imode.h>
#include <coreplugin/messagebox.h>
#include <coreplugin/modemanager.h>
+
#include <debugger/analyzer/analyzerconstants.h>
#include <debugger/analyzer/analyzermanager.h>
#include <debugger/debuggericons.h>
+
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
+
#include <qtsupport/qtkitinformation.h>
+
#include <utils/algorithm.h>
#include <utils/fancymainwindow.h>
#include <utils/utilsicons.h>
diff --git a/src/plugins/perfprofiler/perftracepointdialog.cpp b/src/plugins/perfprofiler/perftracepointdialog.cpp
index 3bb2197ea58..e0db48cc4cf 100644
--- a/src/plugins/perfprofiler/perftracepointdialog.cpp
+++ b/src/plugins/perfprofiler/perftracepointdialog.cpp
@@ -35,9 +35,8 @@
#include <projectexplorer/target.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
-#include <QVBoxLayout>
-#include <QHBoxLayout>
#include <QPushButton>
#include <QTimer>
@@ -81,15 +80,7 @@ PerfTracePointDialog::PerfTracePointDialog() :
? QLatin1String("pkexec") : QLatin1String("n.a."));
}
-PerfTracePointDialog::~PerfTracePointDialog()
-{
- if (m_process && m_process->state() != QProcess::NotRunning) {
- DeviceProcess *process = m_process.release();
- connect(process, &DeviceProcess::finished, process, &QObject::deleteLater);
- process->kill();
- QTimer::singleShot(10000, process, &QObject::deleteLater);
- }
-}
+PerfTracePointDialog::~PerfTracePointDialog() = default;
void PerfTracePointDialog::runScript()
{
@@ -98,58 +89,38 @@ void PerfTracePointDialog::runScript()
m_ui->privilegesChooser->setEnabled(false);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
- m_process.reset(m_device->createProcess(this));
+ m_process.reset(new QtcProcess(this));
+ m_process->setWriteData(m_ui->textEdit->toPlainText().toUtf8());
+ m_ui->textEdit->clear();
- Runnable runnable;
const QString elevate = m_ui->privilegesChooser->currentText();
if (elevate != QLatin1String("n.a."))
- runnable.command = {FilePath::fromString(elevate), {"sh"}};
+ m_process->setCommand({m_device->filePath(elevate), {"sh"}});
else
- runnable.command = {"sh", {}};
-
- connect(m_process.get(), &DeviceProcess::started,
- this, &PerfTracePointDialog::feedScriptToProcess);
+ m_process->setCommand({m_device->filePath("sh"), {}});
- connect(m_process.get(), &DeviceProcess::finished,
- this, &PerfTracePointDialog::handleProcessFinished);
-
- connect(m_process.get(), &DeviceProcess::errorOccurred,
- this, &PerfTracePointDialog::handleProcessError);
-
- m_process->start(runnable);
+ connect(m_process.get(), &QtcProcess::done, this, &PerfTracePointDialog::handleProcessDone);
+ m_process->start();
}
-void PerfTracePointDialog::feedScriptToProcess()
+void PerfTracePointDialog::handleProcessDone()
{
- m_process->write(m_ui->textEdit->toPlainText().toUtf8());
- m_ui->textEdit->clear();
-}
-
-void PerfTracePointDialog::handleProcessFinished()
-{
- if (m_process->exitCode() != 0) {
- m_ui->label->setText(tr("Failed to create trace points."));
+ const QProcess::ProcessError error = m_process->error();
+ QString message;
+ if (error == QProcess::FailedToStart) {
+ message = tr("Failed to run trace point script: %1").arg(error);
+ } else if ((m_process->exitStatus() == QProcess::CrashExit) || (m_process->exitCode() != 0)) {
+ message = tr("Failed to create trace points.");
} else {
- m_ui->label->setText(tr("Created trace points for: %1")
- .arg(QString::fromUtf8(
- m_process->readAllStandardOutput().trimmed()
- .replace('\n', ", "))));
+ message = tr("Created trace points for: %1").arg(QString::fromUtf8(
+ m_process->readAllStandardOutput().trimmed().replace('\n', ", ")));
}
+ m_ui->label->setText(message);
m_ui->textEdit->setHtml(QString::fromUtf8(m_process->readAllStandardError()));
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
}
-void PerfTracePointDialog::handleProcessError(QProcess::ProcessError error)
-{
- if (error == QProcess::FailedToStart) {
- m_ui->label->setText(tr("Failed to run trace point script: %1").arg(error));
- m_ui->textEdit->setText(QString::fromUtf8(m_process->readAllStandardError()));
- m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
- m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
- }
-}
-
void PerfTracePointDialog::accept()
{
if (m_process) {
diff --git a/src/plugins/perfprofiler/perftracepointdialog.h b/src/plugins/perfprofiler/perftracepointdialog.h
index ca5d4e2ae52..ce275b8cd34 100644
--- a/src/plugins/perfprofiler/perftracepointdialog.h
+++ b/src/plugins/perfprofiler/perftracepointdialog.h
@@ -25,14 +25,12 @@
#pragma once
-#include <projectexplorer/devicesupport/deviceprocess.h>
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
#include <QDialog>
-#include <QTextEdit>
-#include <QLabel>
-#include <QDialogButtonBox>
-#include <QComboBox>
+#include <QProcess>
+
+namespace Utils { class QtcProcess; }
namespace PerfProfiler {
namespace Internal {
@@ -49,14 +47,12 @@ public:
private:
void runScript();
- void feedScriptToProcess();
- void handleProcessFinished();
- void handleProcessError(QProcess::ProcessError error);
+ void handleProcessDone();
void finish();
Ui::PerfTracePointDialog *m_ui;
- ProjectExplorer::IDevice::ConstPtr m_device;
- std::unique_ptr<ProjectExplorer::DeviceProcess> m_process;
+ ProjectExplorer::IDeviceConstPtr m_device;
+ std::unique_ptr<Utils::QtcProcess> m_process;
void accept() final;
void reject() final;
diff --git a/src/plugins/perfprofiler/tracepoints.sh b/src/plugins/perfprofiler/tracepoints.sh
index 1352c4dd324..989e5004bf5 100644
--- a/src/plugins/perfprofiler/tracepoints.sh
+++ b/src/plugins/perfprofiler/tracepoints.sh
@@ -49,8 +49,20 @@ match_tracepoints() {
BASE="perfprofiler_${MACHINE}_${NAME}"
RETURN=`perf probe -l "${BASE}_ret" | awk '{print $3}'`
+ if [ -z "$RETURN" ]; then
+ RETURN=`perf probe -l "${BASE}_ret__return" | awk '{print $3}'`
+ fi
+
+ CHECK=
+ for RET in $RETURN; do
+ if [ -n "$CHECK" ]; then
+ CHECK="$CHECK && "
+ fi
+ CHECK="$CHECK\$3 != \"$RET\""
+ done
+
ENTRY=`echo ${RETURN} | awk '{sub(/%return/, ""); print $1}'`
- BAD=`perf probe -l "${BASE}*" | awk '{ if ($3 != "'$RETURN'" && $3 != "'$ENTRY'") { print $1 } }'`
+ BAD=`perf probe -l "${BASE}*" | awk '{ if ('"$CHECK"' && $3 != "'$ENTRY'") { print $1 } }'`
for PROBE in $BAD; do
perf probe -d $PROBE
done
@@ -121,7 +133,7 @@ set_tracepoint() {
}
HOST_MACHINE=`uname -m`
-find /lib -name libc.so.6 | while read LIBC; do
+find /lib/ -name libc.so.6 | while read LIBC; do
echo $LIBC | awk -F '/' '{print $(NF-1)}' | while IFS='-' read MACHINE KERNEL SYSTEM; do
if [ "$MACHINE" = "lib" ]; then MACHINE=$HOST_MACHINE; fi
>&2 echo "</pre><h3>Removing old trace points for $MACHINE</h3><pre>"
diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs
index 504a47a1669..d46294e16cb 100644
--- a/src/plugins/plugins.qbs
+++ b/src/plugins/plugins.qbs
@@ -20,6 +20,7 @@ Project {
"clearcase/clearcase.qbs",
"cmakeprojectmanager/cmakeprojectmanager.qbs",
"mesonprojectmanager/mesonprojectmanager.qbs",
+ "coco/coco.qbs",
"compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.qbs",
"conan/conan.qbs",
"coreplugin/coreplugin.qbs",
@@ -39,6 +40,7 @@ Project {
"emacskeys/emacskeys.qbs",
"genericprojectmanager/genericprojectmanager.qbs",
"git/git.qbs",
+ "gitlab/gitlab.qbs",
"glsleditor/glsleditor.qbs",
"helloworld/helloworld.qbs",
"help/help.qbs",
@@ -80,7 +82,6 @@ Project {
"valgrind/valgrind.qbs",
"vcsbase/vcsbase.qbs",
"webassembly/webassembly.qbs",
- "welcome/welcome.qbs",
- "winrt/winrt.qbs"
+ "welcome/welcome.qbs"
].concat(project.additionalPlugins)
}
diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt
index a123b7a1170..23f8e926372 100644
--- a/src/plugins/projectexplorer/CMakeLists.txt
+++ b/src/plugins/projectexplorer/CMakeLists.txt
@@ -1,5 +1,5 @@
add_qtc_plugin(ProjectExplorer
- DEPENDS QtcSsh Qt5::Qml
+ DEPENDS Qt5::Qml
PLUGIN_DEPENDS Core TextEditor
PLUGIN_TEST_DEPENDS GenericProjectManager
SOURCES
@@ -9,7 +9,6 @@ add_qtc_plugin(ProjectExplorer
addrunconfigdialog.cpp addrunconfigdialog.h
allprojectsfilter.cpp allprojectsfilter.h
allprojectsfind.cpp allprojectsfind.h
- applicationlauncher.cpp applicationlauncher.h
appoutputpane.cpp appoutputpane.h
baseprojectwizarddialog.cpp baseprojectwizarddialog.h
buildaspects.cpp buildaspects.h
@@ -49,26 +48,28 @@ add_qtc_plugin(ProjectExplorer
desktoprunconfiguration.cpp desktoprunconfiguration.h
devicesupport/desktopdevice.cpp devicesupport/desktopdevice.h
devicesupport/desktopdevicefactory.cpp devicesupport/desktopdevicefactory.h
- devicesupport/desktopdeviceprocess.cpp devicesupport/desktopdeviceprocess.h
devicesupport/desktopprocesssignaloperation.cpp devicesupport/desktopprocesssignaloperation.h
devicesupport/devicecheckbuildstep.cpp devicesupport/devicecheckbuildstep.h
devicesupport/devicefactoryselectiondialog.cpp devicesupport/devicefactoryselectiondialog.h devicesupport/devicefactoryselectiondialog.ui
+ devicesupport/devicefilesystemmodel.cpp devicesupport/devicefilesystemmodel.h
devicesupport/devicemanager.cpp devicesupport/devicemanager.h
devicesupport/devicemanagermodel.cpp devicesupport/devicemanagermodel.h
- devicesupport/deviceprocess.cpp devicesupport/deviceprocess.h
devicesupport/deviceprocessesdialog.cpp devicesupport/deviceprocessesdialog.h
devicesupport/deviceprocesslist.cpp devicesupport/deviceprocesslist.h
devicesupport/devicesettingspage.cpp devicesupport/devicesettingspage.h
devicesupport/devicesettingswidget.cpp devicesupport/devicesettingswidget.h devicesupport/devicesettingswidget.ui
devicesupport/devicetestdialog.cpp devicesupport/devicetestdialog.h devicesupport/devicetestdialog.ui
devicesupport/deviceusedportsgatherer.cpp devicesupport/deviceusedportsgatherer.h
+ devicesupport/filetransfer.cpp devicesupport/filetransfer.h
+ devicesupport/filetransferinterface.h
devicesupport/idevice.cpp devicesupport/idevice.h
devicesupport/idevicefactory.cpp devicesupport/idevicefactory.h
+ devicesupport/idevicefwd.h
devicesupport/idevicewidget.h
devicesupport/localprocesslist.cpp devicesupport/localprocesslist.h
- devicesupport/sshdeviceprocess.cpp devicesupport/sshdeviceprocess.h
- devicesupport/sshdeviceprocess.cpp devicesupport/sshdeviceprocess.h
devicesupport/sshdeviceprocesslist.cpp devicesupport/sshdeviceprocesslist.h
+ devicesupport/sshparameters.cpp devicesupport/sshparameters.h
+ devicesupport/sshsettings.cpp devicesupport/sshsettings.h
devicesupport/sshsettingspage.cpp devicesupport/sshsettingspage.h
editorconfiguration.cpp editorconfiguration.h
editorsettingspropertiespage.cpp editorsettingspropertiespage.h editorsettingspropertiespage.ui
@@ -144,6 +145,7 @@ add_qtc_plugin(ProjectExplorer
projectmodels.cpp projectmodels.h
projectnodes.cpp projectnodes.h
projectpanelfactory.cpp projectpanelfactory.h
+ projectsettingswidget.cpp projectsettingswidget.h
projecttree.cpp projecttree.h
projecttreewidget.cpp projecttreewidget.h
projectwelcomepage.cpp projectwelcomepage.h
@@ -155,6 +157,7 @@ add_qtc_plugin(ProjectExplorer
runconfigurationaspects.cpp runconfigurationaspects.h
runcontrol.cpp runcontrol.h
runsettingspropertiespage.cpp runsettingspropertiespage.h
+ sanitizerparser.cpp sanitizerparser.h
selectablefilesmodel.cpp selectablefilesmodel.h
session.cpp session.h
sessiondialog.cpp sessiondialog.h sessiondialog.ui
@@ -181,6 +184,7 @@ add_qtc_plugin(ProjectExplorer
userfileaccessor.cpp userfileaccessor.h
vcsannotatetaskhandler.cpp vcsannotatetaskhandler.h
waitforstopdialog.cpp waitforstopdialog.h
+ windebuginterface.cpp windebuginterface.h
xcodebuildparser.cpp xcodebuildparser.h
)
@@ -189,8 +193,8 @@ extend_qtc_plugin(ProjectExplorer
DEFINES "PROJECT_USER_FILE_EXTENSION=${PROJECT_USER_FILE_EXTENSION}"
)
-if (TARGET libclang)
- set(CLANG_BINDIR "$<TARGET_FILE_DIR:libclang>")
+if (TARGET clangd)
+ set(CLANG_BINDIR "$<TARGET_FILE_DIR:clangd>")
endif()
extend_qtc_plugin(ProjectExplorer
DEFINES "CLANG_BINDIR=\"${CLANG_BINDIR}\""
@@ -198,7 +202,6 @@ extend_qtc_plugin(ProjectExplorer
extend_qtc_plugin(ProjectExplorer
CONDITION WIN32
- SOURCES windebuginterface.cpp windebuginterface.h
DEFINES UNICODE _UNICODE
)
diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index fb9df9ef78b..ea8e0fb77aa 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -606,7 +606,8 @@ Abi Abi::abiFromTargetTriplet(const QString &triple)
} else if (p == "mingw32" || p == "win32"
|| p == "mingw32msvc" || p == "msys"
|| p == "cygwin" || p == "windows") {
- arch = X86Architecture;
+ if (arch == UnknownArchitecture)
+ arch = X86Architecture;
os = WindowsOS;
flavor = WindowsMSysFlavor;
format = PEFormat;
@@ -1196,8 +1197,14 @@ Abis Abi::abisOfBinary(const Utils::FilePath &path)
offset += fileLength.toInt() + 60 /* header */;
tmp.append(abiOf(data.mid(toSkip)));
- if (tmp.isEmpty() && fileName == "/0 ")
+ if (tmp.isEmpty() && fileName == "/0 ") {
tmp = parseCoffHeader(data.mid(toSkip, 20)); // This might be windws...
+ if (tmp.isEmpty()) {
+ // Qt 6.2 static builds have the coff headers for both MSVC and MinGW at offset 66
+ toSkip = 66 + fileNameOffset;
+ tmp = parseCoffHeader(data.mid(toSkip, 20));
+ }
+ }
if (!tmp.isEmpty() && tmp.at(0).binaryFormat() != MachOFormat)
break;
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index 7c20ca27a7d..f1013efa1d7 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -208,7 +208,6 @@ void AbstractProcessStep::doRun()
CommandLine::Raw);
if (!effectiveCommand.executable().isExecutableFile()) {
processStartupFailed();
- finish(false);
return;
}
@@ -216,7 +215,7 @@ void AbstractProcessStep::doRun()
? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale());
d->stderrStream = std::make_unique<QTextDecoder>(QTextCodec::codecForLocale());
- d->m_process.reset(new QtcProcess());
+ d->m_process.reset(new QtcProcess);
d->m_process->setUseCtrlCStub(HostOsInfo::isWindowsHost());
d->m_process->setWorkingDirectory(wd);
// Enforce PWD in the environment because some build tools use that.
@@ -233,14 +232,12 @@ void AbstractProcessStep::doRun()
this, &AbstractProcessStep::processReadyReadStdOutput);
connect(d->m_process.get(), &QtcProcess::readyReadStandardError,
this, &AbstractProcessStep::processReadyReadStdError);
- connect(d->m_process.get(), &QtcProcess::finished,
+ connect(d->m_process.get(), &QtcProcess::done,
this, &AbstractProcessStep::slotProcessFinished);
d->m_process->start();
if (!d->m_process->waitForStarted()) {
- processStartupFailed();
d->m_process.reset();
- finish(false);
return;
}
processStarted();
@@ -281,14 +278,13 @@ void AbstractProcessStep::setupProcessParameters(ProcessParameters *params) cons
void AbstractProcessStep::Private::cleanUp(int exitCode, QProcess::ExitStatus status)
{
- // The process has finished, leftover data is read in processFinished
+ // The process has finished, leftover data was read in slotProcessFinished
q->processFinished(exitCode, status);
- const bool returnValue = q->processSucceeded(exitCode, status)
- || m_ignoreReturnValue;
+ const bool returnValue = q->processSucceeded(exitCode, status) || m_ignoreReturnValue;
- m_process.reset();
+ if (m_process)
+ m_process.release()->deleteLater();
- // Report result
q->finish(returnValue);
}
@@ -315,7 +311,7 @@ void AbstractProcessStep::processStarted()
void AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus status)
{
- QString command = d->m_param.effectiveCommand().toUserOutput();
+ const QString command = d->m_param.effectiveCommand().toUserOutput();
if (status == QProcess::NormalExit && exitCode == 0) {
emit addOutput(tr("The process \"%1\" exited normally.").arg(command),
BuildStep::OutputFormat::NormalMessage);
@@ -344,6 +340,7 @@ void AbstractProcessStep::processStartupFailed()
QString err = d->m_process ? d->m_process->errorString() : QString();
if (!err.isEmpty())
emit addOutput(err, OutputFormat::ErrorMessage);
+ finish(false);
}
/*!
@@ -400,6 +397,10 @@ void AbstractProcessStep::finish(bool success)
void AbstractProcessStep::slotProcessFinished()
{
QTC_ASSERT(d->m_process.get(), return);
+ if (d->m_process->error() == QProcess::FailedToStart) {
+ processStartupFailed();
+ return;
+ }
stdError(d->stderrStream->toUnicode(d->m_process->readAllStandardError()));
stdOutput(d->stdoutStream->toUnicode(d->m_process->readAllStandardOutput()));
d->cleanUp(d->m_process->exitCode(), d->m_process->exitStatus());
diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp
index 657097d1a85..d84a8849e35 100644
--- a/src/plugins/projectexplorer/allprojectsfind.cpp
+++ b/src/plugins/projectexplorer/allprojectsfind.cpp
@@ -81,7 +81,7 @@ Utils::FileIterator *AllProjectsFind::filesForProjects(const QStringList &nameFi
Utils::filterFilesFunction(nameFilters, exclusionFilters);
const QMap<QString, QTextCodec *> openEditorEncodings = TextDocument::openedTextDocumentEncodings();
QMap<QString, QTextCodec *> encodings;
- foreach (const Project *project, projects) {
+ for (const Project *project : projects) {
const EditorConfiguration *config = project->editorConfiguration();
QTextCodec *projectCodec = config->useGlobalSettings()
? Core::EditorManager::defaultTextCodec()
diff --git a/src/plugins/projectexplorer/applicationlauncher.cpp b/src/plugins/projectexplorer/applicationlauncher.cpp
deleted file mode 100644
index ab685ae8cbd..00000000000
--- a/src/plugins/projectexplorer/applicationlauncher.cpp
+++ /dev/null
@@ -1,481 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "applicationlauncher.h"
-#ifdef Q_OS_WIN
-#include "windebuginterface.h"
-#include <qt_windows.h>
-#endif
-
-#include <coreplugin/icore.h>
-
-#include <utils/fileutils.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-
-#include "devicesupport/deviceprocess.h"
-#include "projectexplorer.h"
-#include "projectexplorersettings.h"
-#include "runcontrol.h"
-
-#include <QTextCodec>
-#include <QTimer>
-
-/*!
- \class ProjectExplorer::ApplicationLauncher
-
- \brief The ApplicationLauncher class is the application launcher of the
- ProjectExplorer plugin.
-
- Encapsulates processes running in a console or as GUI processes,
- captures debug output of GUI processes on Windows (outputDebugString()).
-
- \sa Utils::QtcProcess
-*/
-
-using namespace Utils;
-
-namespace ProjectExplorer {
-
-using namespace Internal;
-
-namespace Internal {
-
-class ApplicationLauncherPrivate : public QObject
-{
-public:
- enum State { Inactive, Run };
- explicit ApplicationLauncherPrivate(ApplicationLauncher *parent);
- ~ApplicationLauncherPrivate() override { setFinished(); }
-
- void start(const Runnable &runnable, const IDevice::ConstPtr &device, bool local);
- void stop();
-
- // Local
- void handleProcessStarted();
- void localProcessError(QProcess::ProcessError error);
- void readLocalStandardOutput();
- void readLocalStandardError();
- void cannotRetrieveLocalDebugOutput();
- void checkLocalDebugOutput(qint64 pid, const QString &message);
- void localProcessDone(int, QProcess::ExitStatus);
- qint64 applicationPID() const;
- bool isLocalRunning() const;
-
- // Remote
- void doReportError(const QString &message,
- QProcess::ProcessError error = QProcess::FailedToStart);
- void handleRemoteStderr();
- void handleRemoteStdout();
- void handleApplicationFinished();
- void setFinished();
- void handleApplicationError(QProcess::ProcessError error);
-
-public:
- ApplicationLauncher *q;
-
- bool m_isLocal = true;
- bool m_runAsRoot = false;
-
- // Local
- std::unique_ptr<QtcProcess> m_localProcess;
- bool m_useTerminal = false;
- QProcess::ProcessChannelMode m_processChannelMode;
- // Keep track whether we need to emit a finished signal
- bool m_processRunning = false;
-
- QTextCodec *m_outputCodec;
- QTextCodec::ConverterState m_outputCodecState;
- QTextCodec::ConverterState m_errorCodecState;
-
- qint64 m_listeningPid = 0;
-
- // Remote
- DeviceProcess *m_deviceProcess = nullptr;
- QString m_remoteErrorString;
- QProcess::ProcessError m_remoteError = QProcess::UnknownError;
- QProcess::ExitStatus m_remoteExitStatus = QProcess::CrashExit;
- State m_state = Inactive;
- bool m_stopRequested = false;
-};
-
-} // Internal
-
-static QProcess::ProcessChannelMode defaultProcessChannelMode()
-{
- return ProjectExplorerPlugin::appOutputSettings().mergeChannels
- ? QProcess::MergedChannels : QProcess::SeparateChannels;
-}
-
-ApplicationLauncherPrivate::ApplicationLauncherPrivate(ApplicationLauncher *parent)
- : q(parent)
- , m_processChannelMode(defaultProcessChannelMode())
- , m_outputCodec(QTextCodec::codecForLocale())
-{
-#ifdef Q_OS_WIN
- connect(WinDebugInterface::instance(), &WinDebugInterface::cannotRetrieveDebugOutput,
- this, &ApplicationLauncherPrivate::cannotRetrieveLocalDebugOutput);
- connect(WinDebugInterface::instance(), &WinDebugInterface::debugOutput,
- this, &ApplicationLauncherPrivate::checkLocalDebugOutput);
-#endif
-}
-
-ApplicationLauncher::ApplicationLauncher(QObject *parent) : QObject(parent),
- d(std::make_unique<ApplicationLauncherPrivate>(this))
-{
-}
-
-ApplicationLauncher::~ApplicationLauncher() = default;
-
-void ApplicationLauncher::setProcessChannelMode(QProcess::ProcessChannelMode mode)
-{
- d->m_processChannelMode = mode;
-}
-
-void ApplicationLauncher::setUseTerminal(bool on)
-{
- d->m_useTerminal = on;
-}
-
-void ApplicationLauncher::setRunAsRoot(bool on)
-{
- d->m_runAsRoot = on;
-}
-
-void ApplicationLauncher::stop()
-{
- d->stop();
-}
-
-void ApplicationLauncherPrivate::stop()
-{
- if (m_isLocal) {
- if (!isLocalRunning())
- return;
- QTC_ASSERT(m_localProcess, return);
- m_localProcess->stopProcess();
- localProcessDone(0, QProcess::CrashExit);
- } else {
- if (m_stopRequested)
- return;
- m_stopRequested = true;
- m_remoteExitStatus = QProcess::CrashExit;
- emit q->appendMessage(ApplicationLauncher::tr("User requested stop. Shutting down..."),
- Utils::NormalMessageFormat);
- switch (m_state) {
- case Run:
- m_deviceProcess->terminate();
- break;
- case Inactive:
- break;
- }
- }
-}
-
-bool ApplicationLauncher::isRunning() const
-{
- return d->isLocalRunning();
-}
-
-bool ApplicationLauncher::isLocal() const
-{
- return d->m_isLocal;
-}
-
-bool ApplicationLauncherPrivate::isLocalRunning() const
-{
- if (!m_localProcess)
- return false;
- return m_localProcess->state() != QProcess::NotRunning;
-}
-
-ProcessHandle ApplicationLauncher::applicationPID() const
-{
- return ProcessHandle(d->applicationPID());
-}
-
-qint64 ApplicationLauncherPrivate::applicationPID() const
-{
- if (!isLocalRunning())
- return 0;
-
- return m_localProcess->processId();
-}
-
-QString ApplicationLauncher::errorString() const
-{
- if (d->m_isLocal)
- return d->m_localProcess ? d->m_localProcess->errorString() : QString();
- return d->m_remoteErrorString;
-}
-
-QProcess::ProcessError ApplicationLauncher::processError() const
-{
- if (d->m_isLocal)
- return d->m_localProcess ? d->m_localProcess->error() : QProcess::UnknownError;
- return d->m_remoteError;
-}
-
-void ApplicationLauncherPrivate::localProcessError(QProcess::ProcessError error)
-{
- // TODO: why below handlings are different?
- if (m_useTerminal) {
- emit q->appendMessage(m_localProcess->errorString(), ErrorMessageFormat);
- if (m_processRunning && m_localProcess->processId() == 0) {
- m_processRunning = false;
- emit q->processExited(-1, QProcess::NormalExit);
- }
- } else {
- QString error;
- QProcess::ExitStatus status = QProcess::NormalExit;
- switch (m_localProcess->error()) {
- case QProcess::FailedToStart:
- error = ApplicationLauncher::tr("Failed to start program. Path or permissions wrong?");
- break;
- case QProcess::Crashed:
- status = QProcess::CrashExit;
- break;
- default:
- error = ApplicationLauncher::tr("Some error has occurred while running the program.");
- }
- if (!error.isEmpty())
- emit q->appendMessage(error, ErrorMessageFormat);
- if (m_processRunning && !isLocalRunning()) {
- m_processRunning = false;
- emit q->processExited(-1, status);
- }
- }
- emit q->error(error);
-}
-
-void ApplicationLauncherPrivate::readLocalStandardOutput()
-{
- const QByteArray data = m_localProcess->readAllStandardOutput();
- const QString msg = m_outputCodec->toUnicode(
- data.constData(), data.length(), &m_outputCodecState);
- emit q->appendMessage(msg, StdOutFormat, false);
-}
-
-void ApplicationLauncherPrivate::readLocalStandardError()
-{
- const QByteArray data = m_localProcess->readAllStandardError();
- const QString msg = m_outputCodec->toUnicode(
- data.constData(), data.length(), &m_errorCodecState);
- emit q->appendMessage(msg, StdErrFormat, false);
-}
-
-void ApplicationLauncherPrivate::cannotRetrieveLocalDebugOutput()
-{
-#ifdef Q_OS_WIN
- disconnect(WinDebugInterface::instance(), nullptr, this, nullptr);
- emit q->appendMessage(ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput(), ErrorMessageFormat);
-#endif
-}
-
-void ApplicationLauncherPrivate::checkLocalDebugOutput(qint64 pid, const QString &message)
-{
- if (m_listeningPid == pid)
- emit q->appendMessage(message, DebugFormat);
-}
-
-void ApplicationLauncherPrivate::localProcessDone(int exitCode, QProcess::ExitStatus status)
-{
- QTimer::singleShot(100, this, [this, exitCode, status]() {
- m_listeningPid = 0;
- emit q->processExited(exitCode, status);
- });
-}
-
-QString ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput()
-{
- return tr("Cannot retrieve debugging output.") + QLatin1Char('\n');
-}
-
-void ApplicationLauncherPrivate::handleProcessStarted()
-{
- m_listeningPid = applicationPID();
- emit q->processStarted();
-}
-
-void ApplicationLauncher::start(const Runnable &runnable)
-{
- d->start(runnable, IDevice::ConstPtr(), true);
-}
-
-void ApplicationLauncher::start(const Runnable &runnable, const IDevice::ConstPtr &device)
-{
- d->start(runnable, device, false);
-}
-
-void ApplicationLauncherPrivate::start(const Runnable &runnable, const IDevice::ConstPtr &device, bool local)
-{
- m_isLocal = local;
-
- if (m_isLocal) {
- const QtcProcess::TerminalMode terminalMode = m_useTerminal
- ? QtcProcess::TerminalOn : QtcProcess::TerminalOff;
- m_localProcess.reset(new QtcProcess(terminalMode, this));
- m_localProcess->setProcessChannelMode(m_processChannelMode);
-
- if (m_processChannelMode == QProcess::SeparateChannels) {
- connect(m_localProcess.get(), &QtcProcess::readyReadStandardError,
- this, &ApplicationLauncherPrivate::readLocalStandardError);
- }
- if (!m_useTerminal) {
- connect(m_localProcess.get(), &QtcProcess::readyReadStandardOutput,
- this, &ApplicationLauncherPrivate::readLocalStandardOutput);
- }
-
- connect(m_localProcess.get(), &QtcProcess::started,
- this, &ApplicationLauncherPrivate::handleProcessStarted);
- connect(m_localProcess.get(), &QtcProcess::finished, this, [this] {
- localProcessDone(m_localProcess->exitCode(), m_localProcess->exitStatus());
- });
- connect(m_localProcess.get(), &QtcProcess::errorOccurred,
- this, &ApplicationLauncherPrivate::localProcessError);
-
-
- // Work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch' ...)
- const FilePath fixedPath = runnable.workingDirectory.normalizedPathName();
- m_localProcess->setWorkingDirectory(fixedPath);
-
- Environment env = runnable.environment;
- if (m_runAsRoot)
- RunControl::provideAskPassEntry(env);
-
- m_localProcess->setEnvironment(env);
-
- m_processRunning = true;
- #ifdef Q_OS_WIN
- if (!WinDebugInterface::instance()->isRunning())
- WinDebugInterface::instance()->start(); // Try to start listener again...
- #endif
-
- CommandLine cmdLine = runnable.command;
-
- if (HostOsInfo::isMacHost()) {
- CommandLine disclaim(Core::ICore::libexecPath("disclaim"));
- disclaim.addCommandLineAsArgs(cmdLine);
- cmdLine = disclaim;
- }
-
- m_localProcess->setRunAsRoot(m_runAsRoot);
- m_localProcess->setCommand(cmdLine);
- m_localProcess->start();
- } else {
- QTC_ASSERT(m_state == Inactive, return);
-
- m_state = Run;
- if (!device) {
- doReportError(ApplicationLauncher::tr("Cannot run: No device."));
- setFinished();
- return;
- }
-
- if (!device->canCreateProcess()) {
- doReportError(ApplicationLauncher::tr("Cannot run: Device is not able to create processes."));
- setFinished();
- return;
- }
-
- if (!device->isEmptyCommandAllowed() && runnable.command.isEmpty()) {
- doReportError(ApplicationLauncher::tr("Cannot run: No command given."));
- setFinished();
- return;
- }
-
- m_stopRequested = false;
- m_remoteExitStatus = QProcess::NormalExit;
-
- m_deviceProcess = device->createProcess(this);
- m_deviceProcess->setRunInTerminal(m_useTerminal);
- connect(m_deviceProcess, &DeviceProcess::started,
- q, &ApplicationLauncher::processStarted);
- connect(m_deviceProcess, &DeviceProcess::readyReadStandardOutput,
- this, &ApplicationLauncherPrivate::handleRemoteStdout);
- connect(m_deviceProcess, &DeviceProcess::readyReadStandardError,
- this, &ApplicationLauncherPrivate::handleRemoteStderr);
- connect(m_deviceProcess, &DeviceProcess::errorOccurred,
- this, &ApplicationLauncherPrivate::handleApplicationError);
- connect(m_deviceProcess, &DeviceProcess::finished,
- this, &ApplicationLauncherPrivate::handleApplicationFinished);
- m_deviceProcess->start(runnable);
- }
-}
-
-void ApplicationLauncherPrivate::handleApplicationError(QProcess::ProcessError error)
-{
- if (error == QProcess::FailedToStart) {
- doReportError(ApplicationLauncher::tr("Application failed to start: %1")
- .arg(m_deviceProcess->errorString()));
- setFinished();
- }
-}
-
-void ApplicationLauncherPrivate::setFinished()
-{
- if (m_state == Inactive)
- return;
-
- int exitCode = 0;
- if (m_deviceProcess)
- exitCode = m_deviceProcess->exitCode();
-
- m_state = Inactive;
- emit q->processExited(exitCode, m_remoteExitStatus);
-}
-
-void ApplicationLauncherPrivate::handleApplicationFinished()
-{
- QTC_ASSERT(m_state == Run, return);
-
- if (m_deviceProcess->exitStatus() == QProcess::CrashExit)
- doReportError(m_deviceProcess->errorString(), QProcess::Crashed);
- setFinished();
-}
-
-void ApplicationLauncherPrivate::handleRemoteStdout()
-{
- QTC_ASSERT(m_state == Run, return);
- const QByteArray output = m_deviceProcess->readAllStandardOutput();
- emit q->appendMessage(QString::fromUtf8(output), Utils::StdOutFormat, false);
-}
-
-void ApplicationLauncherPrivate::handleRemoteStderr()
-{
- QTC_ASSERT(m_state == Run, return);
- const QByteArray output = m_deviceProcess->readAllStandardError();
- emit q->appendMessage(QString::fromUtf8(output), Utils::StdErrFormat, false);
-}
-
-void ApplicationLauncherPrivate::doReportError(const QString &message, QProcess::ProcessError error)
-{
- m_remoteErrorString = message;
- m_remoteError = error;
- m_remoteExitStatus = QProcess::CrashExit;
- emit q->error(error);
-}
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/applicationlauncher.h b/src/plugins/projectexplorer/applicationlauncher.h
deleted file mode 100644
index 86b9c6f3cf3..00000000000
--- a/src/plugins/projectexplorer/applicationlauncher.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "projectexplorer_export.h"
-
-#include "devicesupport/idevice.h"
-
-#include <utils/outputformat.h>
-#include <utils/processhandle.h>
-
-#include <QProcess>
-
-#include <memory>
-
-namespace Utils { class ProcessHandle; }
-
-namespace ProjectExplorer {
-
-class Runnable;
-namespace Internal { class ApplicationLauncherPrivate; }
-
-// Documentation inside.
-class PROJECTEXPLORER_EXPORT ApplicationLauncher : public QObject
-{
- Q_OBJECT
-
-public:
- explicit ApplicationLauncher(QObject *parent = nullptr);
- ~ApplicationLauncher() override;
-
- void setProcessChannelMode(QProcess::ProcessChannelMode mode);
- void setUseTerminal(bool on);
- void setRunAsRoot(bool on);
- void start(const Runnable &runnable);
- void start(const Runnable &runnable, const IDevice::ConstPtr &device);
- void stop();
- bool isRunning() const;
- Utils::ProcessHandle applicationPID() const;
- bool isLocal() const;
-
- QString errorString() const;
- QProcess::ProcessError processError() const;
-
- static QString msgWinCannotRetrieveDebuggingOutput();
-
-signals:
- void appendMessage(const QString &message, Utils::OutputFormat format, bool appendNewLine = true);
- void processStarted();
- void processExited(int exitCode, QProcess::ExitStatus exitStatus);
- void error(QProcess::ProcessError error);
-
-private:
- std::unique_ptr<Internal::ApplicationLauncherPrivate> d;
-};
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp
index 9fc9562355e..413895ae92f 100644
--- a/src/plugins/projectexplorer/appoutputpane.cpp
+++ b/src/plugins/projectexplorer/appoutputpane.cpp
@@ -44,6 +44,7 @@
#include <extensionsystem/invoker.h>
#include <extensionsystem/pluginmanager.h>
+
#include <utils/algorithm.h>
#include <utils/outputformatter.h>
#include <utils/qtcassert.h>
@@ -66,11 +67,20 @@
static Q_LOGGING_CATEGORY(appOutputLog, "qtc.projectexplorer.appoutput", QtWarningMsg);
-using namespace ProjectExplorer;
-using namespace ProjectExplorer::Internal;
+using namespace Utils;
-const char OPTIONS_PAGE_ID[] = "B.ProjectExplorer.AppOutputOptions";
+namespace ProjectExplorer {
+namespace Internal {
+const char OPTIONS_PAGE_ID[] = "B.ProjectExplorer.AppOutputOptions";
+const char SETTINGS_KEY[] = "ProjectExplorer/AppOutput/Zoom";
+const char C_APP_OUTPUT[] = "ProjectExplorer.ApplicationOutput";
+const char POP_UP_FOR_RUN_OUTPUT_KEY[] = "ProjectExplorer/Settings/ShowRunOutput";
+const char POP_UP_FOR_DEBUG_OUTPUT_KEY[] = "ProjectExplorer/Settings/ShowDebugOutput";
+const char CLEAN_OLD_OUTPUT_KEY[] = "ProjectExplorer/Settings/CleanOldAppOutput";
+const char MERGE_CHANNELS_KEY[] = "ProjectExplorer/Settings/MergeStdErrAndStdOut";
+const char WRAP_OUTPUT_KEY[] = "ProjectExplorer/Settings/WrapAppOutput";
+const char MAX_LINES_KEY[] = "ProjectExplorer/Settings/MaxAppOutputLines";
static QObject *debuggerPlugin()
{
@@ -84,20 +94,6 @@ static QString msgAttachDebuggerTooltip(const QString &handleDescription = QStri
AppOutputPane::tr("Attach debugger to %1").arg(handleDescription);
}
-namespace {
-const char SETTINGS_KEY[] = "ProjectExplorer/AppOutput/Zoom";
-const char C_APP_OUTPUT[] = "ProjectExplorer.ApplicationOutput";
-const char POP_UP_FOR_RUN_OUTPUT_KEY[] = "ProjectExplorer/Settings/ShowRunOutput";
-const char POP_UP_FOR_DEBUG_OUTPUT_KEY[] = "ProjectExplorer/Settings/ShowDebugOutput";
-const char CLEAN_OLD_OUTPUT_KEY[] = "ProjectExplorer/Settings/CleanOldAppOutput";
-const char MERGE_CHANNELS_KEY[] = "ProjectExplorer/Settings/MergeStdErrAndStdOut";
-const char WRAP_OUTPUT_KEY[] = "ProjectExplorer/Settings/WrapAppOutput";
-const char MAX_LINES_KEY[] = "ProjectExplorer/Settings/MaxAppOutputLines";
-}
-
-namespace ProjectExplorer {
-namespace Internal {
-
class TabWidget : public QTabWidget
{
Q_OBJECT
@@ -174,7 +170,7 @@ AppOutputPane::AppOutputPane() :
m_formatterWidget(new QWidget),
m_handler(new ShowOutputTaskHandler(this,
tr("Show &App Output"),
- tr("Show the output that generated this issue in the Application Output pane."),
+ tr("Show the output that generated this issue in Application Output."),
tr("A")))
{
ExtensionSystem::PluginManager::addObject(m_handler);
@@ -405,19 +401,20 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
connect(rc, &RunControl::applicationProcessHandleChanged,
this, &AppOutputPane::enableDefaultButtons);
connect(rc, &RunControl::appendMessage,
- this, [this, rc](const QString &out, Utils::OutputFormat format) {
+ this, [this, rc](const QString &out, OutputFormat format) {
appendMessage(rc, out, format);
});
// First look if we can reuse a tab
- const Runnable thisRunnable = rc->runnable();
+ const CommandLine thisCommand = rc->commandLine();
+ const FilePath thisWorkingDirectory = rc->workingDirectory();
+ const Environment thisEnvironment = rc->environment();
const int tabIndex = Utils::indexOf(m_runControlTabs, [&](const RunControlTab &tab) {
if (!tab.runControl || tab.runControl->isRunning())
return false;
- const Runnable otherRunnable = tab.runControl->runnable();
- return thisRunnable.command == otherRunnable.command
- && thisRunnable.workingDirectory == otherRunnable.workingDirectory
- && thisRunnable.environment == otherRunnable.environment;
+ return thisCommand == tab.runControl->commandLine()
+ && thisWorkingDirectory == tab.runControl->workingDirectory()
+ && thisEnvironment == tab.runControl->environment();
});
if (tabIndex != -1) {
RunControlTab &tab = m_runControlTabs[tabIndex];
@@ -440,7 +437,7 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
}
// Create new
static int counter = 0;
- Utils::Id contextId = Utils::Id(C_APP_OUTPUT).withSuffix(counter++);
+ Id contextId = Id(C_APP_OUTPUT).withSuffix(counter++);
Core::Context context(contextId);
Core::OutputWindow *ow = new Core::OutputWindow(context, SETTINGS_KEY, m_tabWidget);
ow->setWindowTitle(tr("Application Output Window"));
@@ -493,19 +490,19 @@ void AppOutputPane::updateFromSettings()
}
}
-void AppOutputPane::appendMessage(RunControl *rc, const QString &out, Utils::OutputFormat format)
+void AppOutputPane::appendMessage(RunControl *rc, const QString &out, OutputFormat format)
{
const int index = indexOf(rc);
if (index != -1) {
Core::OutputWindow *window = m_runControlTabs.at(index).window;
QString stringToWrite;
- if (format == Utils::NormalMessageFormat || format == Utils::ErrorMessageFormat) {
+ if (format == NormalMessageFormat || format == ErrorMessageFormat) {
stringToWrite = QTime::currentTime().toString();
stringToWrite += ": ";
}
stringToWrite += out;
window->appendMessage(stringToWrite, format);
- if (format != Utils::NormalMessageFormat) {
+ if (format != NormalMessageFormat) {
RunControlTab &tab = m_runControlTabs[index];
switch (tab.behaviorOnOutput) {
case AppOutputPaneMode::FlashOnOutput:
@@ -537,7 +534,7 @@ const bool kWrapOutputDefault = true;
void AppOutputPane::storeSettings() const
{
- Utils::QtcSettings *const s = Core::ICore::settings();
+ QtcSettings *const s = Core::ICore::settings();
s->setValueWithDefault(POP_UP_FOR_RUN_OUTPUT_KEY,
int(m_settings.runOutputMode),
int(kRunOutputModeDefault));
@@ -609,8 +606,10 @@ void AppOutputPane::stopRunControl()
QTC_ASSERT(rc, return);
if (rc->isRunning()) {
- if (optionallyPromptToStop(rc))
+ if (optionallyPromptToStop(rc)) {
rc->initiateStop();
+ enableButtons(rc);
+ }
} else {
QTC_CHECK(false);
rc->forceStop();
@@ -713,7 +712,7 @@ void AppOutputPane::enableButtons(const RunControl *rc)
m_stopAction->setEnabled(isRunning);
if (isRunning && debuggerPlugin() && rc->applicationProcessHandle().isValid()) {
m_attachButton->setEnabled(true);
- Utils::ProcessHandle h = rc->applicationProcessHandle();
+ ProcessHandle h = rc->applicationProcessHandle();
QString tip = h.isValid() ? RunControl::tr("PID %1").arg(h.pid())
: RunControl::tr("Invalid");
m_attachButton->setToolTip(msgAttachDebuggerTooltip(tip));
@@ -801,14 +800,12 @@ void AppOutputPane::slotRunControlFinished2(RunControl *sender)
ProjectExplorerPlugin::updateRunActions();
-#ifdef Q_OS_WIN
const bool isRunning = Utils::anyOf(m_runControlTabs, [](const RunControlTab &rt) {
return rt.runControl && rt.runControl->isRunning();
});
- if (!isRunning)
- WinDebugInterface::instance()->stop();
-#endif
+ if (!isRunning)
+ WinDebugInterface::stop();
}
bool AppOutputPane::canNext() const
@@ -874,8 +871,8 @@ public:
maxCharsLayout->addWidget(new QLabel(parts.at(1).trimmed()));
maxCharsLayout->addStretch(1);
const auto outputModeLayout = new QFormLayout;
- outputModeLayout->addRow(tr("Open pane on output when running:"), &m_runOutputModeComboBox);
- outputModeLayout->addRow(tr("Open pane on output when debugging:"),
+ outputModeLayout->addRow(tr("Open Application Output when running:"), &m_runOutputModeComboBox);
+ outputModeLayout->addRow(tr("Open Application Output when debugging:"),
&m_debugOutputModeComboBox);
layout->addLayout(outputModeLayout);
layout->addLayout(maxCharsLayout);
diff --git a/src/plugins/projectexplorer/buildaspects.cpp b/src/plugins/projectexplorer/buildaspects.cpp
index e89aaf50ef8..845d1230aff 100644
--- a/src/plugins/projectexplorer/buildaspects.cpp
+++ b/src/plugins/projectexplorer/buildaspects.cpp
@@ -31,6 +31,7 @@
#include <coreplugin/fileutils.h>
+#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/infolabel.h>
#include <utils/layoutbuilder.h>
diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp
index 630925db048..0a5abd65d19 100644
--- a/src/plugins/projectexplorer/buildconfiguration.cpp
+++ b/src/plugins/projectexplorer/buildconfiguration.cpp
@@ -47,12 +47,13 @@
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
+#include <projectexplorer/devicesupport/idevice.h>
+
#include <utils/algorithm.h>
#include <utils/detailswidget.h>
-#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/mimetypes/mimetype.h>
#include <utils/layoutbuilder.h>
+#include <utils/macroexpander.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/variablechooser.h>
@@ -200,7 +201,6 @@ BuildConfiguration::BuildConfiguration(Target *target, Utils::Id id)
tr("Variables in the build configuration's environment"),
[this](const QString &var) { return environment().expandedValueForKey(var); });
- updateCacheAndEmitEnvironmentChanged();
connect(Core::ICore::instance(), &Core::ICore::systemEnvironmentChanged,
this, &BuildConfiguration::updateCacheAndEmitEnvironmentChanged);
connect(target, &Target::kitChanged,
@@ -284,13 +284,15 @@ void BuildConfiguration::addConfigWidgets(const std::function<void(NamedWidget *
adder(new Internal::BuildStepListWidget(buildSteps()));
adder(new Internal::BuildStepListWidget(cleanSteps()));
- QList<NamedWidget *> subConfigWidgets = createSubConfigWidgets();
- foreach (NamedWidget *subConfigWidget, subConfigWidgets)
+ const QList<NamedWidget *> subConfigWidgets = createSubConfigWidgets();
+ for (NamedWidget *subConfigWidget : subConfigWidgets)
adder(subConfigWidget);
}
void BuildConfiguration::doInitialize(const BuildInfo &info)
{
+ updateCacheAndEmitEnvironmentChanged();
+
setDisplayName(info.displayName);
setDefaultDisplayName(info.displayName);
setBuildDirectory(info.buildDirectory);
@@ -303,8 +305,6 @@ void BuildConfiguration::doInitialize(const BuildInfo &info)
for (Utils::Id id : qAsConst(d->m_initialCleanSteps))
d->m_cleanSteps.appendStep(id);
- acquaintAspects();
-
if (d->m_initializer)
d->m_initializer(info);
}
@@ -489,8 +489,10 @@ void BuildConfiguration::setBuildDirectorySettingsKey(const QString &key)
Environment BuildConfiguration::baseEnvironment() const
{
Environment result;
- if (useSystemEnvironment())
- result = Environment::systemEnvironment();
+ if (useSystemEnvironment()) {
+ ProjectExplorer::IDevice::ConstPtr devicePtr = BuildDeviceKitAspect::device(kit());
+ result = devicePtr ? devicePtr->systemEnvironment() : Environment::systemEnvironment();
+ }
addToEnvironment(result);
kit()->addToBuildEnvironment(result);
result.modify(project()->additionalEnvironment());
@@ -608,7 +610,7 @@ FilePath BuildConfiguration::buildDirectoryFromTemplate(const FilePath &projectD
const Kit *kit,
const QString &bcName,
BuildType buildType,
- SpaceHandling spaceHandling)
+ const QString &buildSystem)
{
MacroExpander exp;
@@ -634,6 +636,10 @@ FilePath BuildConfiguration::buildDirectoryFromTemplate(const FilePath &projectD
QCoreApplication::translate(
"ProjectExplorer", "Name of the project's active build configuration"),
[bcName] { return bcName; });
+ exp.registerVariable("BuildSystem:Name",
+ QCoreApplication::translate(
+ "ProjectExplorer", "Name of the project's active build system"),
+ [buildSystem] { return buildSystem; });
exp.registerVariable("CurrentBuild:Type",
QCoreApplication::translate("ProjectExplorer", "Type of current build"),
[buildType] { return buildTypeName(buildType); }, false);
@@ -647,8 +653,7 @@ FilePath BuildConfiguration::buildDirectoryFromTemplate(const FilePath &projectD
qCDebug(bcLog) << "build dir template:" << buildDir;
buildDir = exp.expand(buildDir);
qCDebug(bcLog) << "expanded build:" << buildDir;
- if (spaceHandling == ReplaceSpaces)
- buildDir.replace(" ", "-");
+ buildDir.replace(" ", "-");
return projectDir.resolvePath(buildDir);
}
@@ -792,7 +797,6 @@ BuildConfiguration *BuildConfigurationFactory::restore(Target *parent, const QVa
if (!id.name().startsWith(factory->m_buildConfigId.name()))
continue;
BuildConfiguration *bc = factory->m_creator(parent);
- bc->acquaintAspects();
QTC_ASSERT(bc, return nullptr);
if (!bc->fromMap(map)) {
delete bc;
diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h
index d3df3e21ea4..32b505f3ba5 100644
--- a/src/plugins/projectexplorer/buildconfiguration.h
+++ b/src/plugins/projectexplorer/buildconfiguration.h
@@ -30,7 +30,7 @@
#include "task.h"
#include <utils/environment.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
namespace Utils { class MacroExpander; }
@@ -110,14 +110,13 @@ public:
static QString buildTypeName(BuildType type);
- enum SpaceHandling { KeepSpace, ReplaceSpaces };
static Utils::FilePath buildDirectoryFromTemplate(const Utils::FilePath &projectDir,
const Utils::FilePath &mainFilePath,
const QString &projectName,
const Kit *kit,
const QString &bcName,
BuildType buildType,
- SpaceHandling spaceHandling = ReplaceSpaces);
+ const QString &buildSystem);
bool isActive() const;
diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp
index 4dc482c4f7d..41e27da1f23 100644
--- a/src/plugins/projectexplorer/buildmanager.cpp
+++ b/src/plugins/projectexplorer/buildmanager.cpp
@@ -30,6 +30,7 @@
#include "buildsystem.h"
#include "compileoutputwindow.h"
#include "deployconfiguration.h"
+#include "devicesupport/devicemanager.h"
#include "kit.h"
#include "kitinformation.h"
#include "project.h"
@@ -46,7 +47,9 @@
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
+
#include <extensionsystem/pluginmanager.h>
+
#include <utils/algorithm.h>
#include <utils/outputformatter.h>
#include <utils/runextensions.h>
@@ -117,7 +120,8 @@ static int queue(const QList<Project *> &projects, const QList<Id> &stepIds,
return projects.contains(rc->project());
case StopBeforeBuild::SameBuildDir:
return Utils::contains(projects, [rc, configSelection](Project *p) {
- IDevice::ConstPtr device = rc->runnable().device;
+ const FilePath executable = rc->commandLine().executable();
+ IDevice::ConstPtr device = DeviceManager::deviceForPath(executable);
for (const Target * const t : targetsForSelection(p, configSelection)) {
if (device.isNull())
device = DeviceKitAspect::device(t->kit());
@@ -125,7 +129,7 @@ static int queue(const QList<Project *> &projects, const QList<Id> &stepIds,
continue;
for (const BuildConfiguration * const bc
: buildConfigsForSelection(t, configSelection)) {
- if (rc->runnable().command.executable().isChildOf(bc->buildDirectory()))
+ if (executable.isChildOf(bc->buildDirectory()))
return true;
}
}
@@ -155,7 +159,7 @@ static int queue(const QList<Project *> &projects, const QList<Id> &stepIds,
}
if (stopThem) {
- foreach (RunControl *rc, toStop)
+ for (RunControl *rc : toStop)
rc->initiateStop();
WaitForStopDialog dialog(toStop);
@@ -170,18 +174,18 @@ static int queue(const QList<Project *> &projects, const QList<Id> &stepIds,
QList<BuildStepList *> stepLists;
QStringList preambleMessage;
- foreach (Project *pro, projects) {
+ for (const Project *pro : projects) {
if (pro && pro->needsConfiguration()) {
preambleMessage.append(
BuildManager::tr("The project %1 is not configured, skipping it.")
.arg(pro->displayName()) + QLatin1Char('\n'));
}
}
- foreach (Id id, stepIds) {
+ for (const Id id : stepIds) {
const bool isBuild = id == Constants::BUILDSTEPS_BUILD;
const bool isClean = id == Constants::BUILDSTEPS_CLEAN;
const bool isDeploy = id == Constants::BUILDSTEPS_DEPLOY;
- foreach (Project *pro, projects) {
+ for (const Project *pro : projects) {
if (!pro || pro->needsConfiguration())
continue;
BuildStepList *bsl = nullptr;
@@ -224,6 +228,7 @@ public:
QStringList m_stepNames;
int m_progress = 0;
int m_maxProgress = 0;
+ bool m_poppedUpTaskWindow = false;
bool m_running = false;
bool m_isDeploying = false;
// is set to true while canceling, so that nextBuildStep knows that the BuildStep finished because of canceling
@@ -485,6 +490,10 @@ void BuildManager::updateTaskCount()
{
const int errors = getErrorTaskCount();
ProgressManager::setApplicationLabel(errors > 0 ? QString::number(errors) : QString());
+ if (errors > 0 && !d->m_poppedUpTaskWindow) {
+ showTaskWindow();
+ d->m_poppedUpTaskWindow = true;
+ }
}
void BuildManager::finish()
@@ -512,6 +521,7 @@ void BuildManager::clearBuildQueue()
d->m_buildQueue.clear();
d->m_enabledState.clear();
d->m_running = false;
+ d->m_poppedUpTaskWindow = false;
d->m_isDeploying = false;
d->m_previousBuildStepProject = nullptr;
d->m_currentBuildStep = nullptr;
@@ -748,6 +758,7 @@ void BuildManager::nextStep()
d->m_currentBuildStep->run();
} else {
d->m_running = false;
+ d->m_poppedUpTaskWindow = false;
d->m_isDeploying = false;
d->m_previousBuildStepProject = nullptr;
d->m_progressFutureInterface->reportFinished();
diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp
index 94bdf78accc..ff3102c7ead 100644
--- a/src/plugins/projectexplorer/buildstep.cpp
+++ b/src/plugins/projectexplorer/buildstep.cpp
@@ -33,6 +33,7 @@
#include "project.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
+#include "sanitizerparser.h"
#include "target.h"
#include <utils/algorithm.h>
@@ -113,7 +114,7 @@
\fn void ProjectExplorer::BuildStep::addOutput(const QString &string, ProjectExplorer::BuildStep::OutputFormat format,
ProjectExplorer::BuildStep::OutputNewlineSetting newlineSetting = DoAppendNewline) const
- The \a string is added to the generated output, usually in the output pane.
+ The \a string is added to the generated output, usually in the output.
It should be in plain text, with the format in the parameter.
*/
@@ -283,6 +284,7 @@ void BuildStep::setupOutputFormatter(OutputFormatter *formatter)
formatter->addLineParser(parser);
}
+ formatter->addLineParser(new Internal::SanitizerParser);
formatter->setForwardStdOutToStdError(buildConfiguration()->parseStdOut());
}
Utils::FileInProjectFinder fileFinder;
diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp
index 0a60422dbb1..82248bedc8a 100644
--- a/src/plugins/projectexplorer/buildsteplist.cpp
+++ b/src/plugins/projectexplorer/buildsteplist.cpp
@@ -25,11 +25,9 @@
#include "buildsteplist.h"
-#include "buildconfiguration.h"
#include "buildmanager.h"
#include "buildstep.h"
-#include "deployconfiguration.h"
-#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
#include "target.h"
#include <utils/algorithm.h>
@@ -131,6 +129,11 @@ bool BuildStepList::fromMap(const QVariantMap &map)
}
bool handled = false;
Utils::Id stepId = idFromMap(bsData);
+
+ // pre-8.0 compat
+ if (stepId == "RemoteLinux.CheckForFreeDiskSpaceStep")
+ continue;
+
for (BuildStepFactory *factory : factories) {
if (factory->stepId() == stepId) {
if (factory->canHandle(this)) {
@@ -196,7 +199,7 @@ void BuildStepList::moveStepUp(int position)
emit stepMoved(position, position - 1);
}
-BuildStep *BuildStepList::at(int position)
+BuildStep *BuildStepList::at(int position) const
{
return m_steps.at(position);
}
diff --git a/src/plugins/projectexplorer/buildsteplist.h b/src/plugins/projectexplorer/buildsteplist.h
index 49c0f8b206b..4d55a4a023f 100644
--- a/src/plugins/projectexplorer/buildsteplist.h
+++ b/src/plugins/projectexplorer/buildsteplist.h
@@ -49,7 +49,7 @@ public:
QList<BuildStep *> steps() const;
- template <class BS> BS *firstOfType() {
+ template <class BS> BS *firstOfType() const {
BS *bs = nullptr;
for (int i = 0; i < count(); ++i) {
bs = qobject_cast<BS *>(at(i));
@@ -76,7 +76,7 @@ public:
bool removeStep(int position);
void moveStepUp(int position);
- BuildStep *at(int position);
+ BuildStep *at(int position) const;
Target *target() { return m_target; }
diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp
index 424b49d802c..930416f3bef 100644
--- a/src/plugins/projectexplorer/buildsystem.cpp
+++ b/src/plugins/projectexplorer/buildsystem.cpp
@@ -34,8 +34,12 @@
#include <coreplugin/messagemanager.h>
#include <coreplugin/outputwindow.h>
+
#include <projectexplorer/buildaspects.h>
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/makestep.h>
+#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QTimer>
@@ -253,6 +257,22 @@ bool BuildSystem::supportsAction(Node *, ProjectAction, const Node *) const
return false;
}
+MakeInstallCommand BuildSystem::makeInstallCommand(const FilePath &installRoot) const
+{
+ QTC_ASSERT(target()->project()->hasMakeInstallEquivalent(), return {});
+
+ BuildStepList *buildSteps = buildConfiguration()->buildSteps();
+ QTC_ASSERT(buildSteps, return {});
+
+ MakeInstallCommand cmd;
+ if (const auto makeStep = buildSteps->firstOfType<MakeStep>()) {
+ cmd.command.setExecutable(makeStep->makeExecutable());
+ cmd.command.addArg("install");
+ cmd.command.addArg("INSTALL_ROOT=" + installRoot.nativePath());
+ }
+ return cmd;
+}
+
FilePaths BuildSystem::filesGeneratedFrom(const FilePath &sourceFile) const
{
Q_UNUSED(sourceFile)
diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h
index 263738d8e45..38945b46153 100644
--- a/src/plugins/projectexplorer/buildsystem.h
+++ b/src/plugins/projectexplorer/buildsystem.h
@@ -29,7 +29,7 @@
#include "buildtargetinfo.h"
#include "project.h"
-#include "treescanner.h"
+#include "projectnodes.h"
#include <QObject>
@@ -40,6 +40,7 @@ class CommandLine;
namespace ProjectExplorer {
class BuildConfiguration;
+class BuildStepList;
class Node;
struct TestCaseInfo
@@ -103,6 +104,8 @@ public:
virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const;
virtual QString name() const = 0;
+ virtual MakeInstallCommand makeInstallCommand(const Utils::FilePath &installRoot) const;
+
virtual Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const;
virtual QVariant additionalData(Utils::Id id) const;
diff --git a/src/plugins/projectexplorer/buildtargetinfo.h b/src/plugins/projectexplorer/buildtargetinfo.h
index 7b5ef1984bb..0592393fb20 100644
--- a/src/plugins/projectexplorer/buildtargetinfo.h
+++ b/src/plugins/projectexplorer/buildtargetinfo.h
@@ -27,9 +27,8 @@
#include "projectexplorer_export.h"
-#include <utils/algorithm.h>
#include <utils/environment.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <utils/porting.h>
#include <QList>
diff --git a/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp b/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
index 7abca7b0834..b31388b9f0c 100644
--- a/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
@@ -34,9 +34,11 @@ using namespace TextEditor;
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
-CodeStyleSettingsWidget::CodeStyleSettingsWidget(Project *project) : QWidget(), m_project(project)
+CodeStyleSettingsWidget::CodeStyleSettingsWidget(Project *project) : ProjectSettingsWidget(), m_project(project)
{
m_ui.setupUi(this);
+ setUseGlobalSettingsCheckBoxVisible(false);
+ setUseGlobalSettingsLabelVisible(false);
const EditorConfiguration *config = m_project->editorConfiguration();
diff --git a/src/plugins/projectexplorer/codestylesettingspropertiespage.h b/src/plugins/projectexplorer/codestylesettingspropertiespage.h
index 7ab03ff7ac6..e4ab5e1121c 100644
--- a/src/plugins/projectexplorer/codestylesettingspropertiespage.h
+++ b/src/plugins/projectexplorer/codestylesettingspropertiespage.h
@@ -26,6 +26,7 @@
#pragma once
#include "ui_codestylesettingspropertiespage.h"
+#include <projectexplorer/projectsettingswidget.h>
namespace ProjectExplorer {
class EditorConfiguration;
@@ -33,7 +34,7 @@ class Project;
namespace Internal {
-class CodeStyleSettingsWidget : public QWidget
+class CodeStyleSettingsWidget : public ProjectSettingsWidget
{
Q_OBJECT
public:
diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp
index abb6736a955..151f69ff3db 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.cpp
+++ b/src/plugins/projectexplorer/compileoutputwindow.cpp
@@ -118,7 +118,7 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
m_handler = new ShowOutputTaskHandler(this,
tr("Show Compile &Output"),
- tr("Show the output that generated this issue in the Compile Output pane."),
+ tr("Show the output that generated this issue in Compile Output."),
tr("O"));
ExtensionSystem::PluginManager::addObject(m_handler);
setupContext(C_COMPILE_OUTPUT, m_outputWindow);
@@ -283,7 +283,7 @@ public:
const CompileOutputSettings &settings = BuildManager::compileOutputSettings();
m_wrapOutputCheckBox.setText(tr("Word-wrap output"));
m_wrapOutputCheckBox.setChecked(settings.wrapOutput);
- m_popUpCheckBox.setText(tr("Open pane when building"));
+ m_popUpCheckBox.setText(tr("Open Compile Output when building"));
m_popUpCheckBox.setChecked(settings.popUp);
m_maxCharsBox.setMaximum(100000000);
m_maxCharsBox.setValue(settings.maxCharCount);
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
index 80678ba841e..8804965a479 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
@@ -25,8 +25,8 @@
#include "customexecutablerunconfiguration.h"
-#include "devicesupport/devicemanager.h"
#include "localenvironmentaspect.h"
+#include "projectexplorerconstants.h"
#include "target.h"
using namespace Utils;
@@ -41,20 +41,20 @@ CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *targe
: CustomExecutableRunConfiguration(target, CUSTOM_EXECUTABLE_RUNCONFIG_ID)
{}
-CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target, Utils::Id id)
+CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
auto envAspect = addAspect<LocalEnvironmentAspect>(target);
- auto exeAspect = addAspect<ExecutableAspect>();
+ auto exeAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::HostDevice);
exeAspect->setSettingsKey("ProjectExplorer.CustomExecutableRunConfiguration.Executable");
exeAspect->setDisplayStyle(StringAspect::PathChooserDisplay);
exeAspect->setHistoryCompleter("Qt.CustomExecutable.History");
exeAspect->setExpectedKind(PathChooser::ExistingCommand);
exeAspect->setEnvironmentChange(EnvironmentChange::fromFixedEnvironment(envAspect->environment()));
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
addAspect<TerminalAspect>();
connect(envAspect, &EnvironmentAspect::environmentChanged, this, [exeAspect, envAspect] {
@@ -82,7 +82,6 @@ Runnable CustomExecutableRunConfiguration::runnable() const
r.command = commandLine();
r.environment = aspect<EnvironmentAspect>()->environment();
r.workingDirectory = workingDirectory;
- r.device = DeviceManager::defaultDesktopDevice();
if (!r.command.isEmpty()) {
const FilePath expanded = macroExpander()->expand(r.command.executable());
diff --git a/src/plugins/projectexplorer/customparser.cpp b/src/plugins/projectexplorer/customparser.cpp
index b3006f4ba04..0c69ced3941 100644
--- a/src/plugins/projectexplorer/customparser.cpp
+++ b/src/plugins/projectexplorer/customparser.cpp
@@ -30,6 +30,7 @@
#include "task.h"
#include <coreplugin/icore.h>
+#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QCheckBox>
@@ -182,6 +183,7 @@ CustomParsersAspect::CustomParsersAspect(Target *target)
setId("CustomOutputParsers");
setSettingsKey("CustomOutputParsers");
setDisplayName(tr("Custom Output Parsers"));
+ addDataExtractor(this, &CustomParsersAspect::parsers, &Data::parsers);
setConfigWidgetCreator([this] {
const auto widget = new Internal::CustomParsersSelectionWidget;
widget->setSelectedParsers(m_parsers);
@@ -225,11 +227,6 @@ CustomParser *CustomParser::createFromId(Utils::Id id)
return nullptr;
}
-Utils::Id CustomParser::id()
-{
- return Utils::Id("ProjectExplorer.OutputParser.Custom");
-}
-
OutputLineParser::Result CustomParser::handleLine(const QString &line, OutputFormat type)
{
const CustomParserExpression::CustomParserChannel channel = type == StdErrFormat
@@ -288,7 +285,7 @@ public:
const auto layout = new QVBoxLayout(this);
const auto explanatoryLabel = new QLabel(tr(
"Custom output parsers scan command line output for user-provided error patterns<br>"
- "in order to create entries in the issues pane.<br>"
+ "to create entries in Issues.<br>"
"The parsers can be configured <a href=\"dummy\">here</a>."));
layout->addWidget(explanatoryLabel);
connect(explanatoryLabel, &QLabel::linkActivated, [] {
diff --git a/src/plugins/projectexplorer/customparser.h b/src/plugins/projectexplorer/customparser.h
index b0df82c3f92..a99ae18dbb2 100644
--- a/src/plugins/projectexplorer/customparser.h
+++ b/src/plugins/projectexplorer/customparser.h
@@ -100,7 +100,12 @@ public:
CustomParsersAspect(Target *target);
void setParsers(const QList<Utils::Id> &parsers) { m_parsers = parsers; }
- const QList<Utils::Id> parsers() const { return m_parsers; }
+ QList<Utils::Id> parsers() const { return m_parsers; }
+
+ struct Data : BaseAspect::Data
+ {
+ QList<Utils::Id> parsers;
+ };
private:
void fromMap(const QVariantMap &map) override;
@@ -119,7 +124,6 @@ public:
void setSettings(const CustomParserSettings &settings);
static CustomParser *createFromId(Utils::Id id);
- static Utils::Id id();
private:
Result handleLine(const QString &line, Utils::OutputFormat type) override;
diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp
index 9ead29bf35e..8ed88ea7593 100644
--- a/src/plugins/projectexplorer/customtoolchain.cpp
+++ b/src/plugins/projectexplorer/customtoolchain.cpp
@@ -139,7 +139,8 @@ ToolChain::BuiltInHeaderPathsRunner CustomToolChain::createBuiltInHeaderPathsRun
const HeaderPaths builtInHeaderPaths = m_builtInHeaderPaths;
// This runner must be thread-safe!
- return [builtInHeaderPaths](const QStringList &cxxFlags, const QString &, const QString &) {
+ return [builtInHeaderPaths](const QStringList &cxxFlags, const FilePath &sysRoot, const QString &) {
+ Q_UNUSED(sysRoot)
HeaderPaths flagHeaderPaths;
for (const QString &cxxFlag : cxxFlags) {
if (cxxFlag.startsWith(QLatin1String("-I")))
@@ -264,47 +265,6 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
setMkspecs(data.value(QLatin1String(mkspecsKeyC)).toString());
setOutputParserId(Utils::Id::fromSetting(data.value(QLatin1String(outputParserKeyC))));
- // Restore Pre-4.13 settings.
- if (outputParserId() == Internal::CustomParser::id()) {
- CustomParserSettings customParserSettings;
- customParserSettings.error.setPattern(
- data.value("ProjectExplorer.CustomToolChain.ErrorPattern").toString());
- customParserSettings.error.setFileNameCap(
- data.value("ProjectExplorer.CustomToolChain.ErrorLineNumberCap").toInt());
- customParserSettings.error.setLineNumberCap(
- data.value("ProjectExplorer.CustomToolChain.ErrorFileNameCap").toInt());
- customParserSettings.error.setMessageCap(
- data.value("ProjectExplorer.CustomToolChain.ErrorMessageCap").toInt());
- customParserSettings.error.setChannel(
- static_cast<CustomParserExpression::CustomParserChannel>(
- data.value("ProjectExplorer.CustomToolChain.ErrorChannel").toInt()));
- customParserSettings.error.setExample(
- data.value("ProjectExplorer.CustomToolChain.ErrorExample").toString());
- customParserSettings.warning.setPattern(
- data.value("ProjectExplorer.CustomToolChain.WarningPattern").toString());
- customParserSettings.warning.setFileNameCap(
- data.value("ProjectExplorer.CustomToolChain.WarningLineNumberCap").toInt());
- customParserSettings.warning.setLineNumberCap(
- data.value("ProjectExplorer.CustomToolChain.WarningFileNameCap").toInt());
- customParserSettings.warning.setMessageCap(
- data.value("ProjectExplorer.CustomToolChain.WarningMessageCap").toInt());
- customParserSettings.warning.setChannel(
- static_cast<CustomParserExpression::CustomParserChannel>(
- data.value("ProjectExplorer.CustomToolChain.WarningChannel").toInt()));
- customParserSettings.warning.setExample(
- data.value("ProjectExplorer.CustomToolChain.WarningExample").toString());
- if (!customParserSettings.error.pattern().isEmpty()
- || !customParserSettings.error.pattern().isEmpty()) {
- // Found custom parser in old settings, move to new place.
- customParserSettings.id = Utils::Id::fromString(QUuid::createUuid().toString());
- setOutputParserId(customParserSettings.id);
- customParserSettings.displayName = tr("Parser for toolchain %1").arg(displayName());
- QList<CustomParserSettings> settings = ProjectExplorerPlugin::customParsers();
- settings << customParserSettings;
- ProjectExplorerPlugin::setCustomParsers(settings);
- }
- }
-
return true;
}
diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp
index b6fb74e0e79..59fc2af090b 100644
--- a/src/plugins/projectexplorer/customwizard/customwizard.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp
@@ -171,7 +171,8 @@ BaseFileWizard *CustomWizard::create(QWidget *parent, const WizardDialogParamete
wizard->setPage(parameters()->firstPageId, customPage);
else
wizard->addPage(customPage);
- foreach (QWizardPage *ep, wizard->extensionPages())
+ const QList<QWizardPage *> pages = wizard->extensionPages();
+ for (QWizardPage *ep : pages)
wizard->addPage(ep);
if (CustomWizardPrivate::verbose)
qDebug() << "initWizardDialog" << wizard << wizard->pageIds();
@@ -228,7 +229,8 @@ static bool createFile(CustomWizardFile cwFile,
template <class WizardPage>
WizardPage *findWizardPage(const QWizard *w)
{
- foreach (int pageId, w->pageIds())
+ const QList<int> ids = w->pageIds();
+ for (const int pageId : ids)
if (auto wp = qobject_cast<WizardPage *>(w->page(pageId)))
return wp;
return nullptr;
diff --git a/src/plugins/projectexplorer/customwizard/customwizardpage.cpp b/src/plugins/projectexplorer/customwizard/customwizardpage.cpp
index aac22467508..2851c4b740d 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardpage.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardpage.cpp
@@ -96,7 +96,7 @@ CustomWizardFieldPage::CustomWizardFieldPage(const QSharedPointer<CustomWizardCo
m_formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
if (debug)
qDebug() << Q_FUNC_INFO << parameters->fields.size();
- foreach (const CustomWizardField &f, parameters->fields)
+ for (const CustomWizardField &f : qAsConst(parameters->fields))
addField(f);
vLayout->addLayout(m_formLayout);
m_errorLabel->setVisible(false);
@@ -371,7 +371,7 @@ bool CustomWizardFieldPage::validatePage()
{
clearError();
// Check line edits with validators
- foreach (const LineEditData &led, m_lineEdits) {
+ for (const LineEditData &led : qAsConst(m_lineEdits)) {
if (const QValidator *val = led.lineEdit->validator()) {
int pos = 0;
QString text = led.lineEdit->text();
@@ -399,7 +399,7 @@ QMap<QString, QString> CustomWizardFieldPage::replacementMap(const QWizard *w,
const FieldList &f)
{
QMap<QString, QString> fieldReplacementMap = ctx->baseReplacements;
- foreach (const Internal::CustomWizardField &field, f) {
+ for (const Internal::CustomWizardField &field : f) {
const QString value = w->field(field.name).toString();
fieldReplacementMap.insert(field.name, value);
}
diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
index 5edaf059198..a3efdeedb40 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
@@ -30,7 +30,7 @@
#include <cppeditor/cppeditorconstants.h>
#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/templateengine.h>
@@ -176,7 +176,7 @@ bool CustomWizardValidationRule::validateRules(const QList<CustomWizardValidatio
if (rules.isEmpty())
return true;
QJSEngine engine;
- foreach (const CustomWizardValidationRule &rule, rules)
+ for (const CustomWizardValidationRule &rule : rules)
if (!rule.validate(engine, replacementMap)) {
*errorMessage = rule.message;
CustomWizardContext::replaceFields(replacementMap, errorMessage);
@@ -302,7 +302,7 @@ static bool parseCustomProjectElement(QXmlStreamReader &reader,
static inline QMap<QString, QString> attributesToStringMap(const QXmlStreamAttributes &attributes)
{
QMap<QString, QString> rc;
- foreach (const QXmlStreamAttribute &attribute, attributes)
+ for (const QXmlStreamAttribute &attribute : attributes)
rc.insert(attribute.name().toString(), attribute.value().toString());
return rc;
}
@@ -452,9 +452,9 @@ static inline IWizardFactory::WizardKind kindAttribute(const QXmlStreamReader &r
static inline QSet<Id> readRequiredFeatures(const QXmlStreamReader &reader)
{
QString value = reader.attributes().value(QLatin1String(featuresRequiredC)).toString();
- QStringList stringList = value.split(QLatin1Char(','), Qt::SkipEmptyParts);
+ const QStringList stringList = value.split(QLatin1Char(','), Qt::SkipEmptyParts);
QSet<Id> features;
- foreach (const QString &string, stringList)
+ for (const QString &string : stringList)
features |= Id::fromString(string);
return features;
}
@@ -708,7 +708,7 @@ static inline QString passThrough(const QString &in) { return in; }
static inline QString headerGuard(const QString &in)
{
QString result;
- foreach (const QChar c, in) {
+ for (const QChar c : in) {
if (c.isLetterOrNumber())
result.append(c.toUpper());
else
@@ -721,7 +721,7 @@ static inline QString structName(const QString &in)
{
bool capNeeded = true;
QString result;
- foreach (const QChar c, in) {
+ for (const QChar c : in) {
if (c.isLetterOrNumber()) {
if (capNeeded) {
result.append(c.toUpper());
diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
index d2170775b6c..c5f801cc8e4 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
@@ -99,7 +99,7 @@ static bool
// Arguments: Prepend 'dryrun'. Do field replacement to actual
// argument value to expand via temporary file if specified
CustomWizardContext::TemporaryFilePtrList temporaryFiles;
- foreach (const GeneratorScriptArgument &argument, argumentsIn) {
+ for (const GeneratorScriptArgument &argument : argumentsIn) {
QString value = argument.value;
const bool nonEmptyReplacements
= argument.flags & GeneratorScriptArgument::WriteFile ?
@@ -115,10 +115,10 @@ static bool
qDebug("In %s, running:\n%s\n", qPrintable(workingDirectory.toUserOutput()),
qPrintable(cmd.toUserOutput()));
process.setCommand(cmd);
- process.runBlocking(QtcProcess::WithEventLoop);
- if (process.result() != Utils::QtcProcess::FinishedWithSuccess) {
+ process.runBlocking(EventLoopMode::On);
+ if (process.result() != Utils::ProcessResult::FinishedWithSuccess) {
*errorMessage = QString("Generator script failed: %1").arg(process.exitMessage());
- const QString stdErr = process.stdErr();
+ const QString stdErr = process.cleanedStdErr();
if (!stdErr.isEmpty()) {
errorMessage->append(QLatin1Char('\n'));
errorMessage->append(stdErr);
@@ -126,7 +126,7 @@ static bool
return false;
}
if (stdOut) {
- *stdOut = process.stdOut();
+ *stdOut = process.cleanedStdOut();
if (CustomWizard::verbose())
qDebug("Output: '%s'\n", qPrintable(*stdOut));
}
@@ -155,7 +155,8 @@ Core::GeneratedFiles
Core::GeneratedFiles files;
// Parse the output consisting of lines with ',' separated tokens.
// (file name + attributes matching those of the <file> element)
- foreach (const QString &line, stdOut.split(QLatin1Char('\n'))) {
+ const QStringList lines = stdOut.split(QLatin1Char('\n'));
+ for (const QString &line : lines) {
const QString trimmed = line.trimmed();
if (!trimmed.isEmpty()) {
Core::GeneratedFile file;
@@ -187,7 +188,7 @@ Core::GeneratedFiles
if (CustomWizard::verbose()) {
QDebug nospace = qDebug().nospace();
nospace << script << " generated:\n";
- foreach (const Core::GeneratedFile &f, files)
+ for (const Core::GeneratedFile &f : qAsConst(files))
nospace << ' ' << f.path() << f.attributes() << '\n';
}
return files;
diff --git a/src/plugins/projectexplorer/dependenciespanel.cpp b/src/plugins/projectexplorer/dependenciespanel.cpp
index 94ccadbd57e..b5ec18b984c 100644
--- a/src/plugins/projectexplorer/dependenciespanel.cpp
+++ b/src/plugins/projectexplorer/dependenciespanel.cpp
@@ -210,10 +210,12 @@ void DependenciesView::updateSizeHint()
// DependenciesWidget
//
-DependenciesWidget::DependenciesWidget(Project *project, QWidget *parent) : QWidget(parent),
+DependenciesWidget::DependenciesWidget(Project *project, QWidget *parent) : ProjectSettingsWidget(parent),
m_project(project),
m_model(new DependenciesModel(project, this))
{
+ setUseGlobalSettingsCheckBoxVisible(false);
+ setUseGlobalSettingsLabelVisible(false);
auto vbox = new QVBoxLayout(this);
vbox->setContentsMargins(0, 0, 0, 0);
m_detailsContainer = new Utils::DetailsWidget(this);
diff --git a/src/plugins/projectexplorer/dependenciespanel.h b/src/plugins/projectexplorer/dependenciespanel.h
index b1e4d78f59a..73f864a854b 100644
--- a/src/plugins/projectexplorer/dependenciespanel.h
+++ b/src/plugins/projectexplorer/dependenciespanel.h
@@ -25,8 +25,9 @@
#pragma once
-#include <QAbstractListModel>
+#include <projectexplorer/projectsettingswidget.h>
+#include <QAbstractListModel>
#include <QTreeView>
QT_BEGIN_NAMESPACE
@@ -81,7 +82,7 @@ private:
QSize m_sizeHint;
};
-class DependenciesWidget : public QWidget
+class DependenciesWidget : public ProjectSettingsWidget
{
Q_OBJECT
diff --git a/src/plugins/projectexplorer/deployconfiguration.cpp b/src/plugins/projectexplorer/deployconfiguration.cpp
index df10a323101..c0f3a8d1924 100644
--- a/src/plugins/projectexplorer/deployconfiguration.cpp
+++ b/src/plugins/projectexplorer/deployconfiguration.cpp
@@ -26,14 +26,16 @@
#include "deployconfiguration.h"
#include "buildsteplist.h"
-#include "buildconfiguration.h"
#include "deploymentdataview.h"
#include "kitinformation.h"
#include "project.h"
-#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
#include "target.h"
#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+#include <QDebug>
using namespace Utils;
@@ -44,7 +46,7 @@ const char BUILD_STEP_LIST_PREFIX[] = "ProjectExplorer.BuildConfiguration.BuildS
const char USES_DEPLOYMENT_DATA[] = "ProjectExplorer.DeployConfiguration.CustomDataEnabled";
const char DEPLOYMENT_DATA[] = "ProjectExplorer.DeployConfiguration.CustomData";
-DeployConfiguration::DeployConfiguration(Target *target, Utils::Id id)
+DeployConfiguration::DeployConfiguration(Target *target, Id id)
: ProjectConfiguration(target, id),
m_stepList(this, Constants::BUILDSTEPS_DEPLOY)
{
@@ -135,7 +137,7 @@ DeployConfigurationFactory::~DeployConfigurationFactory()
g_deployConfigurationFactories.removeOne(this);
}
-Utils::Id DeployConfigurationFactory::creationId() const
+Id DeployConfigurationFactory::creationId() const
{
return m_deployConfigBaseId;
}
@@ -176,7 +178,7 @@ void DeployConfigurationFactory::setUseDeploymentDataView()
};
}
-void DeployConfigurationFactory::setConfigBaseId(Utils::Id deployConfigBaseId)
+void DeployConfigurationFactory::setConfigBaseId(Id deployConfigBaseId)
{
m_deployConfigBaseId = deployConfigBaseId;
}
@@ -210,7 +212,7 @@ DeployConfiguration *DeployConfigurationFactory::clone(Target *parent,
DeployConfiguration *DeployConfigurationFactory::restore(Target *parent, const QVariantMap &map)
{
- const Utils::Id id = idFromMap(map);
+ const Id id = idFromMap(map);
DeployConfigurationFactory *factory = Utils::findOrDefault(g_deployConfigurationFactories,
[parent, id](DeployConfigurationFactory *f) {
if (!f->canHandle(parent))
diff --git a/src/plugins/projectexplorer/deploymentdata.h b/src/plugins/projectexplorer/deploymentdata.h
index 9a5ae43a633..22bfc4bae57 100644
--- a/src/plugins/projectexplorer/deploymentdata.h
+++ b/src/plugins/projectexplorer/deploymentdata.h
@@ -28,6 +28,7 @@
#include "deployablefile.h"
#include "projectexplorer_export.h"
+#include <utils/commandline.h>
#include <utils/environment.h>
#include <QList>
@@ -39,8 +40,7 @@ enum class DeploymentKnowledge { Perfect, Approximative, Bad };
class PROJECTEXPLORER_EXPORT MakeInstallCommand
{
public:
- Utils::FilePath command;
- QStringList arguments;
+ Utils::CommandLine command;
Utils::Environment environment;
};
diff --git a/src/plugins/projectexplorer/deploymentdataview.cpp b/src/plugins/projectexplorer/deploymentdataview.cpp
index 689c351125f..3e586938e7f 100644
--- a/src/plugins/projectexplorer/deploymentdataview.cpp
+++ b/src/plugins/projectexplorer/deploymentdataview.cpp
@@ -84,11 +84,10 @@ public:
bool isEditable = false;
};
-
DeploymentDataView::DeploymentDataView(DeployConfiguration *dc)
{
auto model = new TreeModel<DeploymentDataItem>(this);
- model->setHeader({tr("Local File Path"), tr("Remote Directory")});
+ model->setHeader({tr("Source File Path"), tr("Target Directory")});
auto view = new QTreeView(this);
view->setMinimumSize(QSize(100, 100));
diff --git a/src/plugins/projectexplorer/desktoprunconfiguration.cpp b/src/plugins/projectexplorer/desktoprunconfiguration.cpp
index d0ab573b06f..ab5322647cb 100644
--- a/src/plugins/projectexplorer/desktoprunconfiguration.cpp
+++ b/src/plugins/projectexplorer/desktoprunconfiguration.cpp
@@ -27,7 +27,7 @@
#include "buildsystem.h"
#include "localenvironmentaspect.h"
-#include "project.h"
+#include "projectexplorerconstants.h"
#include "runconfigurationaspects.h"
#include "target.h"
@@ -68,9 +68,9 @@ DesktopRunConfiguration::DesktopRunConfiguration(Target *target, Id id, Kind kin
{
auto envAspect = addAspect<LocalEnvironmentAspect>(target);
- addAspect<ExecutableAspect>();
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
addAspect<TerminalAspect>();
auto libAspect = addAspect<UseLibraryPathsAspect>();
diff --git a/src/plugins/projectexplorer/desktoprunconfiguration.h b/src/plugins/projectexplorer/desktoprunconfiguration.h
index 446186e8035..a8d21eb9ec3 100644
--- a/src/plugins/projectexplorer/desktoprunconfiguration.h
+++ b/src/plugins/projectexplorer/desktoprunconfiguration.h
@@ -25,8 +25,7 @@
#pragma once
-#include "runconfigurationaspects.h"
-#include "runcontrol.h"
+#include "runconfiguration.h"
namespace ProjectExplorer {
namespace Internal {
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
index 87efde505e9..64e9556995d 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
@@ -24,7 +24,6 @@
****************************************************************************/
#include "desktopdevice.h"
-#include "desktopdeviceprocess.h"
#include "deviceprocesslist.h"
#include "localprocesslist.h"
#include "desktopprocesssignaloperation.h"
@@ -34,12 +33,10 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runcontrol.h>
-#include <ssh/sshconnection.h>
-
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/portlist.h>
-#include <utils/stringutils.h>
+#include <utils/qtcprocess.h>
#include <utils/url.h>
#include <QCoreApplication>
@@ -97,11 +94,6 @@ DeviceProcessList *DesktopDevice::createProcessListModel(QObject *parent) const
return new Internal::LocalProcessList(sharedFromThis(), parent);
}
-DeviceProcess *DesktopDevice::createProcess(QObject *parent) const
-{
- return new Internal::DesktopDeviceProcess(sharedFromThis(), parent);
-}
-
DeviceProcessSignalOperation::Ptr DesktopDevice::signalOperation() const
{
return DeviceProcessSignalOperation::Ptr(new DesktopProcessSignalOperation());
@@ -123,43 +115,29 @@ DeviceEnvironmentFetcher::Ptr DesktopDevice::environmentFetcher() const
return DeviceEnvironmentFetcher::Ptr(new DesktopDeviceEnvironmentFetcher());
}
-class DesktopPortsGatheringMethod : public PortsGatheringMethod
+PortsGatheringMethod DesktopDevice::portsGatheringMethod() const
{
- CommandLine commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const override
- {
- // We might encounter the situation that protocol is given IPv6
- // but the consumer of the free port information decides to open
- // an IPv4(only) port. As a result the next IPv6 scan will
- // report the port again as open (in IPv6 namespace), while the
- // same port in IPv4 namespace might still be blocked, and
- // re-use of this port fails.
- // GDBserver behaves exactly like this.
-
- Q_UNUSED(protocol)
-
- if (HostOsInfo::isWindowsHost() || HostOsInfo::isMacHost())
- return {"netstat", {"-a", "-n"}};
- if (HostOsInfo::isLinuxHost())
- return {"/bin/sh", {"-c", "cat /proc/net/tcp*"}};
- return {};
- }
+ return {
+ [this](QAbstractSocket::NetworkLayerProtocol protocol) -> CommandLine {
+ // We might encounter the situation that protocol is given IPv6
+ // but the consumer of the free port information decides to open
+ // an IPv4(only) port. As a result the next IPv6 scan will
+ // report the port again as open (in IPv6 namespace), while the
+ // same port in IPv4 namespace might still be blocked, and
+ // re-use of this port fails.
+ // GDBserver behaves exactly like this.
- QList<Utils::Port> usedPorts(const QByteArray &output) const override
- {
- QList<Utils::Port> ports;
- const QList<QByteArray> lines = output.split('\n');
- for (const QByteArray &line : lines) {
- const Port port(Utils::parseUsedPortFromNetstatOutput(line));
- if (port.isValid() && !ports.contains(port))
- ports.append(port);
- }
- return ports;
- }
-};
+ Q_UNUSED(protocol)
-PortsGatheringMethod::Ptr DesktopDevice::portsGatheringMethod() const
-{
- return DesktopPortsGatheringMethod::Ptr(new DesktopPortsGatheringMethod);
+ if (HostOsInfo::isWindowsHost() || HostOsInfo::isMacHost())
+ return {filePath("netstat"), {"-a", "-n"}};
+ if (HostOsInfo::isLinuxHost())
+ return {filePath("/bin/sh"), {"-c", "cat /proc/net/tcp*"}};
+ return {};
+ },
+
+ &Port::parseFromNetstatOutput
+ };
}
QUrl DesktopDevice::toolControlChannel(const ControlChannelHint &) const
@@ -201,6 +179,12 @@ bool DesktopDevice::setPermissions(const FilePath &filePath, QFile::Permissions
return filePath.setPermissions(permissions);
}
+FilePath DesktopDevice::mapToGlobalPath(const Utils::FilePath &pathOnDevice) const
+{
+ QTC_CHECK(!pathOnDevice.needsDevice());
+ return pathOnDevice;
+}
+
Environment DesktopDevice::systemEnvironment() const
{
return Environment::systemEnvironment();
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h
index 06502c559d6..37dc326a989 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopdevice.h
+++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.h
@@ -48,9 +48,7 @@ public:
bool canAutoDetectPorts() const override;
bool canCreateProcessModel() const override;
DeviceProcessList *createProcessListModel(QObject *parent) const override;
- bool canCreateProcess() const override { return true; }
- ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const override;
- DeviceProcess *createProcess(QObject *parent) const override;
+ ProjectExplorer::PortsGatheringMethod portsGatheringMethod() const override;
DeviceProcessSignalOperation::Ptr signalOperation() const override;
DeviceEnvironmentFetcher::Ptr environmentFetcher() const override;
QUrl toolControlChannel(const ControlChannelHint &) const override;
@@ -81,6 +79,7 @@ public:
qint64 fileSize(const Utils::FilePath &filePath) const override;
QFile::Permissions permissions(const Utils::FilePath &filePath) const override;
bool setPermissions(const Utils::FilePath &filePath, QFile::Permissions) const override;
+ Utils::FilePath mapToGlobalPath(const Utils::FilePath &pathOnDevice) const override;
protected:
DesktopDevice();
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp
deleted file mode 100644
index c2106967f77..00000000000
--- a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "desktopdeviceprocess.h"
-
-#include "idevice.h"
-#include "../runcontrol.h"
-
-#include <utils/environment.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-
-using namespace Utils;
-
-namespace ProjectExplorer {
-namespace Internal {
-
-DesktopDeviceProcess::DesktopDeviceProcess(const QSharedPointer<const IDevice> &device,
- QObject *parent)
- : DeviceProcess(device, ProcessMode::Writer, parent)
-{
-}
-
-void DesktopDeviceProcess::start(const Runnable &runnable)
-{
- QTC_ASSERT(state() == QProcess::NotRunning, return);
- if (runnable.environment.size())
- setEnvironment(runnable.environment);
- setWorkingDirectory(runnable.workingDirectory);
- setCommand(runnable.command);
- QtcProcess::start();
-}
-
-void DesktopDeviceProcess::interrupt()
-{
- device()->signalOperation()->interruptProcess(processId());
-}
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.h b/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.h
deleted file mode 100644
index ed926112a2d..00000000000
--- a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "deviceprocess.h"
-
-#include <utils/qtcprocess.h>
-
-namespace ProjectExplorer {
-namespace Internal {
-
-class DesktopDeviceProcess : public DeviceProcess
-{
- Q_OBJECT
-
-public:
- DesktopDeviceProcess(const QSharedPointer<const IDevice> &device, QObject *parent = nullptr);
-
- void start(const Runnable &runnable) override;
- void interrupt() override;
-};
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp
index 5a1d0f94277..7057987e896 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp
+++ b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp
@@ -25,12 +25,11 @@
#include "desktopprocesssignaloperation.h"
-#include "localprocesslist.h"
-
#include <app/app_version.h>
#include <utils/winutils.h>
#include <utils/fileutils.h>
+#include <utils/processinfo.h>
#include <QCoreApplication>
#include <QDir>
@@ -46,6 +45,8 @@
#include <signal.h>
#endif // else Q_OS_WIN
+using namespace Utils;
+
namespace ProjectExplorer {
void DesktopProcessSignalOperation::killProcess(qint64 pid)
@@ -57,9 +58,10 @@ void DesktopProcessSignalOperation::killProcess(qint64 pid)
void DesktopProcessSignalOperation::killProcess(const QString &filePath)
{
m_errorMessage.clear();
- foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
- if (process.cmdLine == filePath)
- killProcessSilently(process.pid);
+ const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
+ for (const ProcessInfo &processInfo : processInfoList) {
+ if (processInfo.commandLine == filePath)
+ killProcessSilently(processInfo.processId);
}
emit finished(m_errorMessage);
}
@@ -74,9 +76,10 @@ void DesktopProcessSignalOperation::interruptProcess(qint64 pid)
void DesktopProcessSignalOperation::interruptProcess(const QString &filePath)
{
m_errorMessage.clear();
- foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
- if (process.cmdLine == filePath)
- interruptProcessSilently(process.pid);
+ const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
+ for (const ProcessInfo &processInfo : processInfoList) {
+ if (processInfo.commandLine == filePath)
+ interruptProcessSilently(processInfo.processId);
}
emit finished(m_errorMessage);
}
@@ -105,7 +108,7 @@ void DesktopProcessSignalOperation::killProcessSilently(qint64 pid)
|PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
if (const HANDLE handle = OpenProcess(rights, FALSE, DWORD(pid))) {
if (!TerminateProcess(handle, UINT(-1)))
- appendMsgCannotKill(pid, Utils::winErrorMessage(GetLastError()));
+ appendMsgCannotKill(pid, winErrorMessage(GetLastError()));
CloseHandle(handle);
} else {
appendMsgCannotKill(pid, tr("Cannot open process."));
@@ -123,10 +126,10 @@ void DesktopProcessSignalOperation::interruptProcessSilently(qint64 pid)
#ifdef Q_OS_WIN
enum SpecialInterrupt { NoSpecialInterrupt, Win32Interrupt, Win64Interrupt };
- bool is64BitSystem = Utils::is64BitWindowsSystem();
+ bool is64BitSystem = is64BitWindowsSystem();
SpecialInterrupt si = NoSpecialInterrupt;
if (is64BitSystem)
- si = Utils::is64BitWindowsBinary(m_debuggerCommand) ? Win64Interrupt : Win32Interrupt;
+ si = is64BitWindowsBinary(m_debuggerCommand) ? Win64Interrupt : Win32Interrupt;
/*
Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a
32 bit application inside a 64 bit environment.
@@ -164,18 +167,18 @@ GDB 32bit | Api | Api | N/A | Win32
inferior = OpenProcess(rights, FALSE, pid);
if (inferior == NULL) {
appendMsgCannotInterrupt(pid, tr("Cannot open process: %1")
- + Utils::winErrorMessage(GetLastError()));
+ + winErrorMessage(GetLastError()));
break;
}
- bool creatorIs64Bit = Utils::is64BitWindowsBinary(
- Utils::FilePath::fromUserInput(QCoreApplication::applicationFilePath()));
+ bool creatorIs64Bit = is64BitWindowsBinary(
+ FilePath::fromUserInput(QCoreApplication::applicationFilePath()));
if (!is64BitSystem
|| si == NoSpecialInterrupt
|| (si == Win64Interrupt && creatorIs64Bit)
|| (si == Win32Interrupt && !creatorIs64Bit)) {
if (!DebugBreakProcess(inferior)) {
appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed:")
- + QLatin1Char(' ') + Utils::winErrorMessage(GetLastError()));
+ + QLatin1Char(' ') + winErrorMessage(GetLastError()));
}
} else if (si == Win32Interrupt || si == Win64Interrupt) {
QString executable = QCoreApplication::applicationDirPath();
diff --git a/src/plugins/projectexplorer/devicesupport/devicefilesystemmodel.cpp b/src/plugins/projectexplorer/devicesupport/devicefilesystemmodel.cpp
new file mode 100644
index 00000000000..3fa987f2b0a
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/devicefilesystemmodel.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "devicefilesystemmodel.h"
+
+#include <projectexplorer/devicesupport/idevice.h>
+#include <utils/futuresynchronizer.h>
+#include <utils/qtcassert.h>
+#include <utils/runextensions.h>
+#include <utils/utilsicons.h>
+
+#include <QFutureWatcher>
+#include <QIcon>
+#include <QList>
+#include <QScopeGuard>
+#include <QSet>
+
+using namespace Utils;
+
+namespace ProjectExplorer {
+namespace Internal {
+
+enum class FileType {
+ File,
+ Dir,
+// Link,
+ Other
+};
+
+
+class RemoteDirNode;
+class RemoteFileNode
+{
+public:
+ virtual ~RemoteFileNode() = default;
+
+ FilePath m_filePath;
+ FileType m_fileType = FileType::File;
+ RemoteDirNode *m_parent = nullptr;
+};
+
+class RemoteDirNode : public RemoteFileNode
+{
+public:
+ RemoteDirNode() { m_fileType = FileType::Dir; }
+ ~RemoteDirNode() { qDeleteAll(m_children); }
+
+ enum { Initial, Fetching, Finished } m_state = Initial;
+ QList<RemoteFileNode *> m_children;
+};
+
+static RemoteFileNode *indexToFileNode(const QModelIndex &index)
+{
+ return static_cast<RemoteFileNode *>(index.internalPointer());
+}
+
+static RemoteDirNode *indexToDirNode(const QModelIndex &index)
+{
+ RemoteFileNode * const fileNode = indexToFileNode(index);
+ QTC_CHECK(fileNode);
+ return dynamic_cast<RemoteDirNode *>(fileNode);
+}
+
+using ResultType = QList<QPair<FilePath, FileType>>;
+
+class DeviceFileSystemModelPrivate
+{
+public:
+ IDevice::ConstPtr m_device;
+ std::unique_ptr<RemoteDirNode> m_rootNode;
+ QSet<QFutureWatcher<ResultType> *> m_watchers;
+ FutureSynchronizer m_futureSynchronizer;
+};
+
+} // namespace Internal
+
+using namespace Internal;
+
+DeviceFileSystemModel::DeviceFileSystemModel(QObject *parent)
+ : QAbstractItemModel(parent), d(new DeviceFileSystemModelPrivate)
+{
+ d->m_futureSynchronizer.setCancelOnWait(true);
+}
+
+DeviceFileSystemModel::~DeviceFileSystemModel()
+{
+ qDeleteAll(d->m_watchers);
+ delete d;
+}
+
+void DeviceFileSystemModel::setDevice(const IDevice::ConstPtr &device)
+{
+ d->m_device = device;
+}
+
+bool DeviceFileSystemModel::canFetchMore(const QModelIndex &parent) const
+{
+ if (!parent.isValid()) {
+ return !d->m_rootNode.get();
+ }
+
+ RemoteDirNode * const dirNode = indexToDirNode(parent);
+ if (!dirNode)
+ return false;
+ if (dirNode->m_state == RemoteDirNode::Initial)
+ return true;
+ return false;
+}
+
+void DeviceFileSystemModel::fetchMore(const QModelIndex &parent)
+{
+ if (!parent.isValid()) {
+ beginInsertRows(QModelIndex(), 0, 0);
+ QTC_CHECK(!d->m_rootNode);
+ d->m_rootNode.reset(new RemoteDirNode);
+ d->m_rootNode->m_filePath = d->m_device->rootPath();
+ endInsertRows();
+ return;
+ }
+ RemoteDirNode * const dirNode = indexToDirNode(parent);
+ if (!dirNode)
+ return;
+ if (dirNode->m_state != RemoteDirNode::Initial)
+ return;
+ collectEntries(dirNode->m_filePath, dirNode);
+ dirNode->m_state = RemoteDirNode::Fetching;
+}
+
+bool DeviceFileSystemModel::hasChildren(const QModelIndex &parent) const
+{
+ if (!parent.isValid())
+ return true;
+
+ RemoteDirNode * const dirNode = indexToDirNode(parent);
+ if (!dirNode)
+ return false;
+ if (dirNode->m_state == RemoteDirNode::Initial)
+ return true;
+ return dirNode->m_children.size();
+}
+
+int DeviceFileSystemModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return 2; // type + name
+}
+
+QVariant DeviceFileSystemModel::data(const QModelIndex &index, int role) const
+{
+ const RemoteFileNode * const node = indexToFileNode(index);
+ QTC_ASSERT(node, return QVariant());
+ if (index.column() == 0 && role == Qt::DecorationRole) {
+ if (node->m_fileType == FileType::File)
+ return Utils::Icons::UNKNOWN_FILE.icon();
+ if (node->m_fileType == FileType::Dir)
+ return Utils::Icons::DIR.icon();
+ return Utils::Icons::HELP.icon(); // Shows a question mark.
+ }
+ if (index.column() == 1) {
+ if (role == Qt::DisplayRole) {
+ if (node->m_filePath == d->m_device->rootPath())
+ return QString("/");
+ return node->m_filePath.fileName();
+ }
+ if (role == PathRole)
+ return node->m_filePath.toString();
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags DeviceFileSystemModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::NoItemFlags;
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+QVariant DeviceFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation != Qt::Horizontal)
+ return QVariant();
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ if (section == 0)
+ return tr("File Type");
+ if (section == 1)
+ return tr("File Name");
+ return QVariant();
+}
+
+QModelIndex DeviceFileSystemModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (row < 0 || row >= rowCount(parent) || column < 0 || column >= columnCount(parent))
+ return QModelIndex();
+ if (!d->m_rootNode)
+ return QModelIndex();
+ if (!parent.isValid())
+ return createIndex(row, column, d->m_rootNode.get());
+ const RemoteDirNode * const parentNode = indexToDirNode(parent);
+ QTC_ASSERT(parentNode, return QModelIndex());
+ QTC_ASSERT(row < parentNode->m_children.count(), return QModelIndex());
+ RemoteFileNode * const childNode = parentNode->m_children.at(row);
+ return createIndex(row, column, childNode);
+}
+
+QModelIndex DeviceFileSystemModel::parent(const QModelIndex &child) const
+{
+ if (!child.isValid()) // Don't assert on this, since the model tester tries it.
+ return QModelIndex();
+
+ const RemoteFileNode * const childNode = indexToFileNode(child);
+ QTC_ASSERT(childNode, return QModelIndex());
+ if (childNode == d->m_rootNode.get())
+ return QModelIndex();
+ RemoteDirNode * const parentNode = childNode->m_parent;
+ if (parentNode == d->m_rootNode.get())
+ return createIndex(0, 0, d->m_rootNode.get());
+ const RemoteDirNode * const grandParentNode = parentNode->m_parent;
+ QTC_ASSERT(grandParentNode, return QModelIndex());
+ return createIndex(grandParentNode->m_children.indexOf(parentNode), 0, parentNode);
+}
+
+static FileType fileType(const FilePath &path)
+{
+ if (path.isDir())
+ return FileType::Dir;
+ if (path.isFile())
+ return FileType::File;
+ return FileType::Other;
+}
+
+static void dirEntries(QFutureInterface<ResultType> &futureInterface, const FilePath &dir)
+{
+ const QList<FilePath> entries = dir.dirEntries(QDir::NoFilter);
+ ResultType result;
+ for (const FilePath &entry : entries) {
+ if (futureInterface.isCanceled())
+ return;
+ result.append(qMakePair(entry, fileType(entry)));
+ }
+ futureInterface.reportResult(result);
+}
+
+int DeviceFileSystemModel::rowCount(const QModelIndex &parent) const
+{
+ if (!d->m_rootNode)
+ return 0;
+ if (!parent.isValid())
+ return 1;
+ if (parent.column() != 0)
+ return 0;
+ RemoteDirNode * const dirNode = indexToDirNode(parent);
+ if (!dirNode)
+ return 0;
+ return dirNode->m_children.count();
+}
+
+void DeviceFileSystemModel::collectEntries(const FilePath &filePath, RemoteDirNode *parentNode)
+{
+ // Destructor of this will delete working watchers, as they are children of this.
+ QFutureWatcher<ResultType> *watcher = new QFutureWatcher<ResultType>(this);
+ auto future = runAsync(dirEntries, filePath);
+ d->m_futureSynchronizer.addFuture(future);
+ connect(watcher, &QFutureWatcher<ResultType>::finished, this, [this, watcher, parentNode] {
+ auto cleanup = qScopeGuard([watcher, this] {
+ d->m_watchers.remove(watcher);
+ watcher->deleteLater();
+ });
+
+ QTC_ASSERT(parentNode->m_state == RemoteDirNode::Fetching, return);
+ parentNode->m_state = RemoteDirNode::Finished;
+
+ const ResultType entries = watcher->result();
+ if (entries.isEmpty())
+ return;
+
+ const int row = parentNode->m_parent
+ ? parentNode->m_parent->m_children.indexOf(parentNode) : 0;
+ const QModelIndex parentIndex = createIndex(row, 0, parentNode);
+ beginInsertRows(parentIndex, 0, entries.count() - 1);
+
+ for (const QPair<FilePath, FileType> &entry : entries) {
+ RemoteFileNode *childNode = nullptr;
+ if (entry.second == FileType::Dir)
+ childNode = new RemoteDirNode;
+ else
+ childNode = new RemoteFileNode;
+ childNode->m_filePath = entry.first;
+ childNode->m_fileType = entry.second;
+ childNode->m_parent = parentNode;
+ parentNode->m_children.append(childNode);
+ }
+ endInsertRows();
+ });
+ d->m_watchers.insert(watcher);
+ watcher->setFuture(future);
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/devicefilesystemmodel.h b/src/plugins/projectexplorer/devicesupport/devicefilesystemmodel.h
new file mode 100644
index 00000000000..f9fb3ea9df7
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/devicefilesystemmodel.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "../projectexplorer_export.h"
+#include "idevicefwd.h"
+
+#include <QAbstractItemModel>
+
+namespace Utils { class FilePath; }
+
+namespace ProjectExplorer {
+
+namespace Internal {
+class DeviceFileSystemModelPrivate;
+class RemoteDirNode;
+}
+
+// Very simple read-only model. Symbolic links are not followed.
+class PROJECTEXPLORER_EXPORT DeviceFileSystemModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ explicit DeviceFileSystemModel(QObject *parent = nullptr);
+ ~DeviceFileSystemModel();
+
+ void setDevice(const IDeviceConstPtr &device);
+
+ // Use this to get the full path of a file or directory.
+ static const int PathRole = Qt::UserRole;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+private:
+ bool canFetchMore(const QModelIndex &parent) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ void fetchMore(const QModelIndex &parent) override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+ bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
+ QModelIndex parent(const QModelIndex &child) const override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ void collectEntries(const Utils::FilePath &filePath, Internal::RemoteDirNode *parentNode);
+
+ Internal::DeviceFileSystemModelPrivate * const d;
+};
+
+} // namespace ProjectExplorer;
diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
index 2f33c106d7e..deb96f14291 100644
--- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
@@ -32,6 +32,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
+#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/persistentsettings.h>
#include <utils/portlist.h>
@@ -519,12 +520,6 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
return device->symLinkTarget(filePath);
};
- deviceHooks.mapToGlobalPath = [](const FilePath &filePath) {
- auto device = DeviceManager::deviceForPath(filePath);
- QTC_ASSERT(device, return FilePath{});
- return device->mapToGlobalPath(filePath);
- };
-
deviceHooks.mapToDevicePath = [](const FilePath &filePath) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return QString{});
@@ -600,15 +595,20 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
return device->bytesAvailable(filePath);
};
+ deviceHooks.deviceDisplayName = [](const FilePath &filePath) {
+ auto device = DeviceManager::deviceForPath(filePath);
+ QTC_ASSERT(device, return QString());
+ return device->displayName();
+ };
+
FileUtils::setDeviceFileHooks(deviceHooks);
DeviceProcessHooks processHooks;
- processHooks.startProcessHook = [](QtcProcess &process) {
- FilePath filePath = process.commandLine().executable();
+ processHooks.processImplHook = [](const FilePath &filePath) -> ProcessInterface * {
auto device = DeviceManager::deviceForPath(filePath);
- QTC_ASSERT(device, return);
- device->runProcess(process);
+ QTC_ASSERT(device, return nullptr);
+ return device->createProcessInterface();
};
processHooks.systemEnvironmentForBinary = [](const FilePath &filePath) {
diff --git a/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h
index 3144896cda0..2f5813ecc50 100644
--- a/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h
+++ b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h
@@ -26,12 +26,14 @@
#pragma once
#include "../projectexplorer_export.h"
-#include "idevice.h"
+#include "idevicefwd.h"
#include <QAbstractListModel>
#include <memory>
+namespace Utils { class Id; }
+
namespace ProjectExplorer {
namespace Internal { class DeviceManagerModelPrivate; }
class IDevice;
@@ -47,9 +49,9 @@ public:
void setFilter(const QList<Utils::Id> &filter);
void setTypeFilter(Utils::Id type);
- IDevice::ConstPtr device(int pos) const;
+ IDeviceConstPtr device(int pos) const;
Utils::Id deviceId(int pos) const;
- int indexOf(IDevice::ConstPtr dev) const;
+ int indexOf(IDeviceConstPtr dev) const;
int indexForId(Utils::Id id) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -62,7 +64,7 @@ private:
void handleDeviceListChanged();
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- bool matchesTypeFilter(const IDevice::ConstPtr &dev) const;
+ bool matchesTypeFilter(const IDeviceConstPtr &dev) const;
const std::unique_ptr<Internal::DeviceManagerModelPrivate> d;
};
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocess.cpp
deleted file mode 100644
index 84c692e5a47..00000000000
--- a/src/plugins/projectexplorer/devicesupport/deviceprocess.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "deviceprocess.h"
-
-#include "idevice.h"
-
-#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
-
-using namespace Utils;
-
-namespace ProjectExplorer {
-
-DeviceProcess::DeviceProcess(const IDevice::ConstPtr &device,
- const QtcProcess::Setup &setup,
- QObject *parent)
- : QtcProcess(setup, parent), m_device(device)
-{
-}
-
-IDevice::ConstPtr DeviceProcess::device() const
-{
- return m_device;
-}
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocess.h b/src/plugins/projectexplorer/devicesupport/deviceprocess.h
deleted file mode 100644
index 215b26879b4..00000000000
--- a/src/plugins/projectexplorer/devicesupport/deviceprocess.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "../projectexplorer_export.h"
-
-#include <utils/qtcprocess.h>
-
-#include <QSharedPointer>
-#include <QStringList>
-
-namespace ProjectExplorer {
-
-class IDevice;
-class Runnable;
-
-class PROJECTEXPLORER_EXPORT DeviceProcess : public Utils::QtcProcess
-{
- Q_OBJECT
-public:
- using Utils::QtcProcess::start;
- virtual void start(const Runnable &runnable) = 0;
-
- void setRunInTerminal(bool term) { m_runInTerminal = term; }
- bool runInTerminal() const { return m_runInTerminal; }
-
-protected:
- explicit DeviceProcess(const QSharedPointer<const IDevice> &device,
- const Utils::QtcProcess::Setup &setup,
- QObject *parent = nullptr);
-
- QSharedPointer<const IDevice> device() const;
-
-private:
- const QSharedPointer<const IDevice> m_device;
- bool m_runInTerminal = false;
-};
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp
index bef4f16974c..17eb79ac9e2 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp
+++ b/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp
@@ -25,11 +25,13 @@
#include "deviceprocessesdialog.h"
#include "deviceprocesslist.h"
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitchooser.h>
#include <projectexplorer/kitinformation.h>
#include <utils/fancylineedit.h>
#include <utils/itemviews.h>
+#include <utils/processinfo.h>
#include <utils/qtcassert.h>
#include <QDialogButtonBox>
@@ -99,10 +101,10 @@ public:
void handleProcessListUpdated();
void handleProcessKilled();
void updateButtons();
- DeviceProcessItem selectedProcess() const;
+ ProcessInfo selectedProcess() const;
QDialog *q;
- DeviceProcessList *processList;
+ std::unique_ptr<DeviceProcessList> processList;
ProcessListFilterModel proxyModel;
QLabel *kitLabel;
KitChooser *kitChooser;
@@ -126,8 +128,6 @@ DeviceProcessesDialogPrivate::DeviceProcessesDialogPrivate(KitChooser *chooser,
q->setWindowTitle(DeviceProcessesDialog::tr("List of Processes"));
q->setMinimumHeight(500);
- processList = nullptr;
-
processFilterLineEdit = new FancyLineEdit(q);
processFilterLineEdit->setPlaceholderText(DeviceProcessesDialog::tr("Filter"));
processFilterLineEdit->setFocus(Qt::TabFocusReason);
@@ -206,21 +206,20 @@ DeviceProcessesDialogPrivate::DeviceProcessesDialogPrivate(KitChooser *chooser,
void DeviceProcessesDialogPrivate::setDevice(const IDevice::ConstPtr &device)
{
- delete processList;
- processList = nullptr;
+ processList.reset();
proxyModel.setSourceModel(nullptr);
if (!device)
return;
- processList = device->createProcessListModel();
+ processList.reset(device->createProcessListModel());
QTC_ASSERT(processList, return);
proxyModel.setSourceModel(processList->model());
- connect(processList, &DeviceProcessList::error,
+ connect(processList.get(), &DeviceProcessList::error,
this, &DeviceProcessesDialogPrivate::handleRemoteError);
- connect(processList, &DeviceProcessList::processListUpdated,
+ connect(processList.get(), &DeviceProcessList::processListUpdated,
this, &DeviceProcessesDialogPrivate::handleProcessListUpdated);
- connect(processList, &DeviceProcessList::processKilled,
+ connect(processList.get(), &DeviceProcessList::processKilled,
this, &DeviceProcessesDialogPrivate::handleProcessKilled, Qt::QueuedConnection);
updateButtons();
@@ -279,11 +278,11 @@ void DeviceProcessesDialogPrivate::updateButtons()
errorText->setVisible(!errorText->document()->isEmpty());
}
-DeviceProcessItem DeviceProcessesDialogPrivate::selectedProcess() const
+ProcessInfo DeviceProcessesDialogPrivate::selectedProcess() const
{
const QModelIndexList indexes = procView->selectionModel()->selectedIndexes();
if (indexes.empty() || !processList)
- return DeviceProcessItem();
+ return ProcessInfo();
return processList->at(proxyModel.mapToSource(indexes.first()).row());
}
@@ -352,7 +351,7 @@ void DeviceProcessesDialog::showAllDevices()
d->updateDevice();
}
-DeviceProcessItem DeviceProcessesDialog::currentProcess() const
+ProcessInfo DeviceProcessesDialog::currentProcess() const
{
return d->selectedProcess();
}
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.h b/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.h
index 7876bf6edd3..08f10bc27d9 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.h
+++ b/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.h
@@ -27,15 +27,16 @@
#include "../projectexplorer_export.h"
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
#include <QDialog>
#include <memory>
+namespace Utils { class ProcessInfo; }
+
namespace ProjectExplorer {
-class DeviceProcessItem;
class KitChooser;
namespace Internal { class DeviceProcessesDialogPrivate; }
@@ -50,9 +51,9 @@ public:
void addAcceptButton(const QString &label);
void addCloseButton();
- void setDevice(const IDevice::ConstPtr &device);
+ void setDevice(const IDeviceConstPtr &device);
void showAllDevices();
- DeviceProcessItem currentProcess() const;
+ Utils::ProcessInfo currentProcess() const;
KitChooser *kitChooser() const;
void logMessage(const QString &line);
DeviceProcessesDialog(KitChooser *chooser, QWidget *parent);
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp
index b54b0baddb0..bdb2159e074 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp
+++ b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp
@@ -24,11 +24,11 @@
****************************************************************************/
#include "deviceprocesslist.h"
-#include "localprocesslist.h"
+#include "idevice.h"
+#include <utils/processinfo.h>
#include <utils/qtcassert.h>
#include <utils/treemodel.h>
-#include <utils/fileutils.h>
using namespace Utils;
@@ -40,12 +40,12 @@ enum State { Inactive, Listing, Killing };
class DeviceProcessTreeItem : public TreeItem
{
public:
- DeviceProcessTreeItem(const DeviceProcessItem &p, Qt::ItemFlags f) : process(p), fl(f) {}
+ DeviceProcessTreeItem(const ProcessInfo &p, Qt::ItemFlags f) : process(p), fl(f) {}
QVariant data(int column, int role) const final;
Qt::ItemFlags flags(int) const final { return fl; }
- DeviceProcessItem process;
+ ProcessInfo process;
Qt::ItemFlags fl;
};
@@ -88,14 +88,14 @@ void DeviceProcessList::update()
doUpdate();
}
-void DeviceProcessList::reportProcessListUpdated(const QList<DeviceProcessItem> &processes)
+void DeviceProcessList::reportProcessListUpdated(const QList<ProcessInfo> &processes)
{
QTC_ASSERT(d->state == Listing, return);
setFinished();
d->model.clear();
- for (const DeviceProcessItem &process : processes) {
+ for (const ProcessInfo &process : processes) {
Qt::ItemFlags fl;
- if (process.pid != d->ownPid)
+ if (process.processId != d->ownPid)
fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
d->model.rootItem()->appendChild(new DeviceProcessTreeItem(process, fl));
}
@@ -125,7 +125,7 @@ void DeviceProcessList::reportProcessKilled()
emit processKilled();
}
-DeviceProcessItem DeviceProcessList::at(int row) const
+ProcessInfo DeviceProcessList::at(int row) const
{
return d->model.rootItem()->childAt(row)->process;
}
@@ -139,9 +139,9 @@ QVariant DeviceProcessTreeItem::data(int column, int role) const
{
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
if (column == 0)
- return process.pid ? process.pid : QVariant();
+ return process.processId ? process.processId : QVariant();
else
- return process.cmdLine;
+ return process.commandLine;
}
return QVariant();
}
@@ -163,18 +163,4 @@ void DeviceProcessList::reportError(const QString &message)
emit error(message);
}
-QList<DeviceProcessItem> DeviceProcessList::localProcesses()
-{
- return LocalProcessList::getLocalProcesses();
-}
-
-bool DeviceProcessItem::operator <(const DeviceProcessItem &other) const
-{
- if (pid != other.pid)
- return pid < other.pid;
- if (exe != other.exe)
- return exe < other.exe;
- return cmdLine < other.cmdLine;
-}
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h
index bd39744e36c..53be4410263 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h
+++ b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h
@@ -25,44 +25,35 @@
#pragma once
-#include "idevice.h"
+#include "../projectexplorer_export.h"
+#include "idevicefwd.h"
#include <QAbstractItemModel>
#include <QList>
#include <memory>
+namespace Utils { class ProcessInfo; }
+
namespace ProjectExplorer {
namespace Internal { class DeviceProcessListPrivate; }
-class PROJECTEXPLORER_EXPORT DeviceProcessItem
-{
-public:
- bool operator<(const DeviceProcessItem &other) const;
-
- qint64 pid = 0;
- QString cmdLine;
- QString exe;
-};
-
class PROJECTEXPLORER_EXPORT DeviceProcessList : public QObject
{
Q_OBJECT
public:
- DeviceProcessList(const IDevice::ConstPtr &device, QObject *parent = nullptr);
+ DeviceProcessList(const IDeviceConstPtr &device, QObject *parent = nullptr);
~DeviceProcessList() override;
void update();
void killProcess(int row);
void setOwnPid(qint64 pid);
- DeviceProcessItem at(int row) const;
+ Utils::ProcessInfo at(int row) const;
QAbstractItemModel *model() const;
- static QList<DeviceProcessItem> localProcesses();
-
signals:
void processListUpdated();
void error(const QString &errorMsg);
@@ -71,13 +62,13 @@ signals:
protected:
void reportError(const QString &message);
void reportProcessKilled();
- void reportProcessListUpdated(const QList<DeviceProcessItem> &processes);
+ void reportProcessListUpdated(const QList<Utils::ProcessInfo> &processes);
- IDevice::ConstPtr device() const;
+ IDeviceConstPtr device() const;
private:
virtual void doUpdate() = 0;
- virtual void doKillProcess(const DeviceProcessItem &process) = 0;
+ virtual void doKillProcess(const Utils::ProcessInfo &process) = 0;
void setFinished();
diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
index 13892ceb3b1..fb7ccf70460 100644
--- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
@@ -153,9 +153,9 @@ void DeviceSettingsWidget::addDevice()
m_deviceManager->addDevice(device);
m_ui->removeConfigButton->setEnabled(true);
m_ui->configurationComboBox->setCurrentIndex(m_deviceManagerModel->indexOf(device));
+ saveSettings();
if (device->hasDeviceTester())
testDevice();
- saveSettings();
}
void DeviceSettingsWidget::removeDevice()
diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
index 4514d624f09..d2cb58603b6 100644
--- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
+++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
@@ -25,7 +25,7 @@
#pragma once
-#include "idevice.h"
+#include "idevicefwd.h"
#include <QList>
#include <QString>
@@ -38,7 +38,6 @@ class QPushButton;
QT_END_NAMESPACE
namespace ProjectExplorer {
-class IDevice;
class DeviceManager;
class DeviceManagerModel;
class IDeviceWidget;
@@ -71,7 +70,7 @@ private:
void initGui();
void displayCurrent();
void setDeviceInfoWidgetsEnabled(bool enable);
- IDevice::ConstPtr currentDevice() const;
+ IDeviceConstPtr currentDevice() const;
int currentIndex() const;
void clearDetails();
QString parseTestOutput();
diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
index 567cf5d41f5..ead3e521ba4 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
+++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
@@ -23,19 +23,17 @@
**
****************************************************************************/
-#include "deviceprocess.h"
#include "deviceusedportsgatherer.h"
-#include <ssh/sshconnection.h>
+#include "sshparameters.h"
+#include <projectexplorer/devicesupport/idevice.h>
#include <utils/port.h>
#include <utils/portlist.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/url.h>
-#include <QPointer>
-
-using namespace QSsh;
using namespace Utils;
namespace ProjectExplorer {
@@ -44,12 +42,12 @@ namespace Internal {
class DeviceUsedPortsGathererPrivate
{
public:
- QPointer<DeviceProcess> process;
+ std::unique_ptr<QtcProcess> process;
QList<Port> usedPorts;
QByteArray remoteStdout;
QByteArray remoteStderr;
IDevice::ConstPtr device;
- PortsGatheringMethod::Ptr portsGatheringMethod;
+ PortsGatheringMethod portsGatheringMethod;
};
} // namespace Internal
@@ -72,32 +70,33 @@ void DeviceUsedPortsGatherer::start(const IDevice::ConstPtr &device)
QTC_ASSERT(d->device, emit error("No device given"); return);
d->portsGatheringMethod = d->device->portsGatheringMethod();
- QTC_ASSERT(d->portsGatheringMethod, emit error("Not implemented"); return);
+ QTC_ASSERT(d->portsGatheringMethod.commandLine, emit error("Not implemented"); return);
+ QTC_ASSERT(d->portsGatheringMethod.parsePorts, emit error("Not implemented"); return);
const QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::AnyIPProtocol;
- d->process = d->device->createProcess(this);
-
- connect(d->process.data(), &DeviceProcess::finished,
- this, &DeviceUsedPortsGatherer::handleProcessFinished);
- connect(d->process.data(), &DeviceProcess::errorOccurred,
- this, &DeviceUsedPortsGatherer::handleProcessError);
- connect(d->process.data(), &DeviceProcess::readyReadStandardOutput,
- this, &DeviceUsedPortsGatherer::handleRemoteStdOut);
- connect(d->process.data(), &DeviceProcess::readyReadStandardError,
- this, &DeviceUsedPortsGatherer::handleRemoteStdErr);
-
- Runnable runnable;
- runnable.command = d->portsGatheringMethod->commandLine(protocol);
- d->process->start(runnable);
+
+ d->process.reset(new QtcProcess);
+ d->process->setCommand(d->portsGatheringMethod.commandLine(protocol));
+
+ connect(d->process.get(), &QtcProcess::done,
+ this, &DeviceUsedPortsGatherer::handleProcessDone);
+ connect(d->process.get(), &QtcProcess::readyReadStandardOutput,
+ this, [this] { d->remoteStdout += d->process->readAllStandardOutput(); });
+ connect(d->process.get(), &QtcProcess::readyReadStandardError,
+ this, [this] { d->remoteStderr += d->process->readAllStandardError(); });
+
+
+ d->process->start();
}
void DeviceUsedPortsGatherer::stop()
{
d->remoteStdout.clear();
d->remoteStderr.clear();
- if (d->process)
- disconnect(d->process.data(), nullptr, this, nullptr);
- d->process.clear();
+ if (d->process) {
+ d->process->disconnect();
+ d->process.release()->deleteLater();
+ }
}
Port DeviceUsedPortsGatherer::getNextFreePort(PortList *freePorts) const
@@ -118,27 +117,24 @@ QList<Port> DeviceUsedPortsGatherer::usedPorts() const
void DeviceUsedPortsGatherer::setupUsedPorts()
{
d->usedPorts.clear();
- const QList<Port> usedPorts = d->portsGatheringMethod->usedPorts(d->remoteStdout);
- foreach (const Port port, usedPorts) {
+ const QList<Port> usedPorts = d->portsGatheringMethod.parsePorts(d->remoteStdout);
+ for (const Port port : usedPorts) {
if (d->device->freePorts().contains(port))
d->usedPorts << port;
}
emit portListReady();
}
-void DeviceUsedPortsGatherer::handleProcessError()
-{
- emit error(tr("Connection error: %1").arg(d->process->errorString()));
- stop();
-}
-
-void DeviceUsedPortsGatherer::handleProcessFinished()
+void DeviceUsedPortsGatherer::handleProcessDone()
{
- if (!d->process)
+ if (d->process->error() != QProcess::UnknownError) {
+ emit error(tr("Connection error: %1").arg(d->process->errorString()));
+ stop();
return;
+ }
+
QString errMsg;
- QProcess::ExitStatus exitStatus = d->process->exitStatus();
- switch (exitStatus) {
+ switch (d->process->exitStatus()) {
case QProcess::CrashExit:
errMsg = tr("Remote process crashed: %1").arg(d->process->errorString());
break;
@@ -163,18 +159,6 @@ void DeviceUsedPortsGatherer::handleProcessFinished()
stop();
}
-void DeviceUsedPortsGatherer::handleRemoteStdOut()
-{
- if (d->process)
- d->remoteStdout += d->process->readAllStandardOutput();
-}
-
-void DeviceUsedPortsGatherer::handleRemoteStdErr()
-{
- if (d->process)
- d->remoteStderr += d->process->readAllStandardError();
-}
-
// PortGatherer
PortsGatherer::PortsGatherer(RunControl *runControl)
diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
index da3f866ae29..acc9367488b 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
+++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
@@ -25,7 +25,7 @@
#pragma once
-#include "idevice.h"
+#include "idevicefwd.h"
#include <projectexplorer/runcontrol.h>
@@ -46,7 +46,7 @@ public:
DeviceUsedPortsGatherer(QObject *parent = nullptr);
~DeviceUsedPortsGatherer() override;
- void start(const IDevice::ConstPtr &device);
+ void start(const IDeviceConstPtr &device);
void stop();
Utils::Port getNextFreePort(Utils::PortList *freePorts) const; // returns -1 if no more are left
QList<Utils::Port> usedPorts() const;
@@ -56,11 +56,7 @@ signals:
void portListReady();
private:
- void handleRemoteStdOut();
- void handleRemoteStdErr();
- void handleProcessError();
- void handleProcessFinished();
-
+ void handleProcessDone();
void setupUsedPorts();
Internal::DeviceUsedPortsGathererPrivate * const d;
diff --git a/src/plugins/projectexplorer/devicesupport/filetransfer.cpp b/src/plugins/projectexplorer/devicesupport/filetransfer.cpp
new file mode 100644
index 00000000000..e16db6bc08b
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/filetransfer.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "filetransfer.h"
+
+#include "devicemanager.h"
+#include "idevice.h"
+
+#include <utils/processinterface.h>
+#include <utils/qtcassert.h>
+
+#include <QProcess>
+
+using namespace Utils;
+
+namespace ProjectExplorer {
+
+FileTransferDirection FileToTransfer::direction() const
+{
+ if (m_source.needsDevice() == m_target.needsDevice())
+ return FileTransferDirection::Invalid;
+ return m_source.needsDevice() ? FileTransferDirection::Download : FileTransferDirection::Upload;
+}
+
+QString FileTransferSetupData::defaultRsyncFlags()
+{
+ return "-av";
+}
+
+static FileTransferDirection transferDirection(const FilesToTransfer &files)
+{
+ if (files.isEmpty())
+ return FileTransferDirection::Invalid;
+
+ const FileTransferDirection direction = files.first().direction();
+ for (const FileToTransfer &file : files) {
+ if (file.direction() != direction)
+ return FileTransferDirection::Invalid;
+ }
+ return direction;
+}
+
+static const FilePath &remoteFile(FileTransferDirection direction, const FileToTransfer &file)
+{
+ return direction == FileTransferDirection::Upload ? file.m_target : file.m_source;
+}
+
+static bool isSameDevice(const FilePath &first, const FilePath &second)
+{
+ return (first.scheme() == second.scheme()) && (first.host() == second.host());
+}
+
+static IDeviceConstPtr matchedDevice(FileTransferDirection direction, const FilesToTransfer &files)
+{
+ if (files.isEmpty())
+ return {};
+ const FilePath &filePath = remoteFile(direction, files.first());
+ for (const FileToTransfer &file : files) {
+ if (!isSameDevice(filePath, remoteFile(direction, file)))
+ return {};
+ }
+ return DeviceManager::deviceForPath(filePath);
+}
+
+void FileTransferInterface::startFailed(const QString &errorString)
+{
+ emit done({0, QProcess::NormalExit, QProcess::FailedToStart, errorString});
+}
+
+class FileTransferPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ void test(const ProjectExplorer::IDeviceConstPtr &onDevice);
+ void start();
+ void stop();
+
+ FileTransferSetupData m_setup;
+
+signals:
+ void progress(const QString &progressMessage);
+ void done(const ProcessResultData &resultData);
+
+private:
+ void startFailed(const QString &errorString);
+ void run(const FileTransferSetupData &setup, const IDeviceConstPtr &device);
+
+ std::unique_ptr<FileTransferInterface> m_transfer;
+};
+
+void FileTransferPrivate::test(const IDeviceConstPtr &onDevice)
+{
+ if (!onDevice)
+ return startFailed(tr("No device set for test transfer."));
+
+ run({{}, m_setup.m_method, m_setup.m_rsyncFlags}, onDevice);
+}
+
+void FileTransferPrivate::start()
+{
+ if (m_setup.m_files.isEmpty())
+ return startFailed(tr("No files to transfer."));
+
+ const FileTransferDirection direction = transferDirection(m_setup.m_files);
+ if (direction == FileTransferDirection::Invalid)
+ return startFailed(tr("Mixing different types of transfer in one go."));
+
+ const IDeviceConstPtr device = matchedDevice(direction, m_setup.m_files);
+ if (!device)
+ return startFailed(tr("Trying to transfer into / from not matching device."));
+
+ run(m_setup, device);
+}
+
+void FileTransferPrivate::stop()
+{
+ if (!m_transfer)
+ return;
+ m_transfer->disconnect();
+ m_transfer.release()->deleteLater();
+}
+
+void FileTransferPrivate::run(const FileTransferSetupData &setup, const IDeviceConstPtr &device)
+{
+ stop();
+
+ m_transfer.reset(device->createFileTransferInterface(setup));
+ QTC_ASSERT(m_transfer, startFailed(tr("Missing transfer implementation.")); return);
+
+ m_transfer->setParent(this);
+ connect(m_transfer.get(), &FileTransferInterface::progress,
+ this, &FileTransferPrivate::progress);
+ connect(m_transfer.get(), &FileTransferInterface::done,
+ this, &FileTransferPrivate::done);
+ m_transfer->start();
+}
+
+void FileTransferPrivate::startFailed(const QString &errorString)
+{
+ emit done({0, QProcess::NormalExit, QProcess::FailedToStart, errorString});
+}
+
+FileTransfer::FileTransfer()
+ : d(new FileTransferPrivate)
+{
+ d->setParent(this);
+ connect(d, &FileTransferPrivate::progress, this, &FileTransfer::progress);
+ connect(d, &FileTransferPrivate::done, this, &FileTransfer::done);
+}
+
+FileTransfer::~FileTransfer()
+{
+ stop();
+ delete d;
+}
+
+void FileTransfer::setFilesToTransfer(const FilesToTransfer &files)
+{
+ d->m_setup.m_files = files;
+}
+
+void FileTransfer::setTransferMethod(FileTransferMethod method)
+{
+ d->m_setup.m_method = method;
+}
+
+void FileTransfer::setRsyncFlags(const QString &flags)
+{
+ d->m_setup.m_rsyncFlags = flags;
+}
+
+void FileTransfer::test(const ProjectExplorer::IDeviceConstPtr &onDevice)
+{
+ d->test(onDevice);
+}
+
+FileTransferMethod FileTransfer::transferMethod() const
+{
+ return d->m_setup.m_method;
+}
+
+void FileTransfer::start()
+{
+ d->start();
+}
+
+void FileTransfer::stop()
+{
+ d->stop();
+}
+
+QString FileTransfer::transferMethodName(FileTransferMethod method)
+{
+ switch (method) {
+ case FileTransferMethod::Sftp: return FileTransfer::tr("sftp");
+ case FileTransferMethod::Rsync: return FileTransfer::tr("rsync");
+ }
+ QTC_CHECK(false);
+ return {};
+}
+
+} // namespace ProjectExplorer
+
+#include "filetransfer.moc"
diff --git a/src/plugins/projectexplorer/devicesupport/filetransfer.h b/src/plugins/projectexplorer/devicesupport/filetransfer.h
new file mode 100644
index 00000000000..a40de415ded
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/filetransfer.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "../projectexplorer_export.h"
+#include "filetransferinterface.h"
+#include "idevicefwd.h"
+
+namespace Utils { class ProcessResultData; }
+
+namespace ProjectExplorer {
+
+class FileTransferPrivate;
+
+class PROJECTEXPLORER_EXPORT FileTransfer : public QObject
+{
+ Q_OBJECT
+
+public:
+ FileTransfer();
+ ~FileTransfer();
+
+ void setFilesToTransfer(const FilesToTransfer &files);
+ void setTransferMethod(FileTransferMethod method);
+ void setRsyncFlags(const QString &flags);
+
+ FileTransferMethod transferMethod() const;
+
+ void test(const ProjectExplorer::IDeviceConstPtr &onDevice);
+ void start();
+ void stop();
+
+ static QString transferMethodName(FileTransferMethod method);
+
+signals:
+ void progress(const QString &progressMessage);
+ void done(const Utils::ProcessResultData &resultData);
+
+private:
+ FileTransferPrivate *d;
+};
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/filetransferinterface.h b/src/plugins/projectexplorer/devicesupport/filetransferinterface.h
new file mode 100644
index 00000000000..530f2868c7d
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/filetransferinterface.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "../projectexplorer_export.h"
+
+#include <utils/filepath.h>
+
+namespace Utils { class ProcessResultData; }
+
+namespace ProjectExplorer {
+
+enum class FileTransferDirection {
+ Invalid,
+ Upload,
+ Download
+};
+
+enum class FileTransferMethod {
+ Sftp,
+ Rsync,
+ Default = Sftp
+};
+
+class PROJECTEXPLORER_EXPORT FileToTransfer
+{
+public:
+ Utils::FilePath m_source;
+ Utils::FilePath m_target;
+
+ FileTransferDirection direction() const;
+};
+
+using FilesToTransfer = QList<FileToTransfer>;
+
+class PROJECTEXPLORER_EXPORT FileTransferSetupData
+{
+public:
+ FilesToTransfer m_files; // When empty, do test instead of a real transfer
+ FileTransferMethod m_method = FileTransferMethod::Default;
+ QString m_rsyncFlags = defaultRsyncFlags();
+
+ static QString defaultRsyncFlags();
+};
+
+class PROJECTEXPLORER_EXPORT FileTransferInterface : public QObject
+{
+ Q_OBJECT
+
+signals:
+ void progress(const QString &progressMessage);
+ void done(const Utils::ProcessResultData &resultData);
+
+protected:
+ FileTransferInterface(const FileTransferSetupData &setupData)
+ : m_setup(setupData) {}
+
+ void startFailed(const QString &errorString);
+
+ const FileTransferSetupData m_setup;
+
+private:
+ FileTransferInterface() = delete;
+
+ virtual void start() = 0;
+
+ friend class FileTransferPrivate;
+};
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp
index 4977cafac41..f7ca5633bb7 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp
@@ -25,16 +25,15 @@
#include "idevice.h"
-#include "devicemanager.h"
+#include "sshparameters.h"
+
#include "deviceprocesslist.h"
#include "idevicefactory.h"
#include "../kit.h"
#include "../kitinformation.h"
-#include "../runconfiguration.h"
#include <coreplugin/icore.h>
-#include <ssh/sshconnection.h>
#include <utils/displayname.h>
#include <utils/icon.h>
#include <utils/portlist.h>
@@ -45,6 +44,7 @@
#include <QStandardPaths>
#include <QDateTime>
+#include <QReadWriteLock>
#include <QString>
#include <QUuid>
@@ -129,8 +129,8 @@ const char HostKeyCheckingKey[] = "HostKeyChecking";
const char DebugServerKey[] = "DebugServerKey";
const char QmlRuntimeKey[] = "QmlsceneKey";
-using AuthType = QSsh::SshConnectionParameters::AuthenticationType;
-const AuthType DefaultAuthType = QSsh::SshConnectionParameters::AuthenticationTypeAll;
+using AuthType = SshParameters::AuthenticationType;
+const AuthType DefaultAuthType = SshParameters::AuthenticationTypeAll;
const IDevice::MachineType DefaultMachineType = IDevice::Hardware;
const int DefaultTimeout = 10;
@@ -151,7 +151,8 @@ public:
OsType osType = OsTypeOther;
int version = 0; // This is used by devices that have been added by the SDK.
- QSsh::SshConnectionParameters sshParameters;
+ QReadWriteLock lock; // Currently used to protect sshParameters only
+ SshParameters sshParameters;
PortList freePorts;
FilePath debugServerPath;
FilePath debugDumperPath = Core::ICore::resourcePath("debugger/");
@@ -211,7 +212,17 @@ bool IDevice::isAnyUnixDevice() const
FilePath IDevice::mapToGlobalPath(const FilePath &pathOnDevice) const
{
- return pathOnDevice;
+ if (pathOnDevice.needsDevice()) {
+ // Already correct form, only sanity check it's ours...
+ QTC_CHECK(handlesFile(pathOnDevice));
+ return pathOnDevice;
+ }
+ // match DeviceManager::deviceForPath
+ FilePath result;
+ result.setPath(pathOnDevice.path());
+ result.setScheme("device");
+ result.setHost(id().toString());
+ return result;
}
QString IDevice::mapToDevicePath(const FilePath &globalPath) const
@@ -219,9 +230,15 @@ QString IDevice::mapToDevicePath(const FilePath &globalPath) const
return globalPath.path();
}
+FilePath IDevice::filePath(const QString &pathOnDevice) const
+{
+ return mapToGlobalPath(FilePath::fromString(pathOnDevice));
+}
+
bool IDevice::handlesFile(const FilePath &filePath) const
{
- Q_UNUSED(filePath);
+ if (filePath.scheme() == "device" && filePath.host() == id().toString())
+ return true;
return false;
}
@@ -422,10 +439,18 @@ bool IDevice::setPermissions(const FilePath &filePath, QFile::Permissions) const
return false;
}
-void IDevice::runProcess(QtcProcess &process) const
+ProcessInterface *IDevice::createProcessInterface() const
+{
+ QTC_CHECK(false);
+ return nullptr;
+}
+
+FileTransferInterface *IDevice::createFileTransferInterface(
+ const FileTransferSetupData &setup) const
{
- Q_UNUSED(process);
+ Q_UNUSED(setup)
QTC_CHECK(false);
+ return nullptr;
}
Environment IDevice::systemEnvironment() const
@@ -558,11 +583,6 @@ const QList<IDevice::DeviceAction> IDevice::deviceActions() const
return d->deviceActions;
}
-PortsGatheringMethod::Ptr IDevice::portsGatheringMethod() const
-{
- return PortsGatheringMethod::Ptr();
-}
-
DeviceProcessList *IDevice::createProcessListModel(QObject *parent) const
{
Q_UNUSED(parent)
@@ -581,12 +601,6 @@ OsType IDevice::osType() const
return d->osType;
}
-DeviceProcess *IDevice::createProcess(QObject * /* parent */) const
-{
- QTC_CHECK(false);
- return nullptr;
-}
-
DeviceEnvironmentFetcher::Ptr IDevice::environmentFetcher() const
{
return DeviceEnvironmentFetcher::Ptr();
@@ -629,6 +643,7 @@ void IDevice::fromMap(const QVariantMap &map)
d->id = newId();
d->origin = static_cast<Origin>(map.value(QLatin1String(OriginKey), ManuallyAdded).toInt());
+ QWriteLocker locker(&d->lock);
d->sshParameters.setHost(map.value(QLatin1String(HostKey)).toString());
d->sshParameters.setPort(map.value(QLatin1String(SshPortKey), 22).toInt());
d->sshParameters.setUserName(map.value(QLatin1String(UserNameKey)).toString());
@@ -636,16 +651,16 @@ void IDevice::fromMap(const QVariantMap &map)
// Pre-4.9, the authentication enum used to have more values
const int storedAuthType = map.value(QLatin1String(AuthKey), DefaultAuthType).toInt();
const bool outdatedAuthType = storedAuthType
- > QSsh::SshConnectionParameters::AuthenticationTypeSpecificKey;
+ > SshParameters::AuthenticationTypeSpecificKey;
d->sshParameters.authenticationType = outdatedAuthType
- ? QSsh::SshConnectionParameters::AuthenticationTypeAll
+ ? SshParameters::AuthenticationTypeAll
: static_cast<AuthType>(storedAuthType);
d->sshParameters.privateKeyFile =
FilePath::fromVariant(map.value(QLatin1String(KeyFileKey), defaultPrivateKeyFilePath()));
d->sshParameters.timeout = map.value(QLatin1String(TimeoutKey), DefaultTimeout).toInt();
- d->sshParameters.hostKeyCheckingMode = static_cast<QSsh::SshHostKeyCheckingMode>
- (map.value(QLatin1String(HostKeyCheckingKey), QSsh::SshHostKeyCheckingNone).toInt());
+ d->sshParameters.hostKeyCheckingMode = static_cast<SshHostKeyCheckingMode>
+ (map.value(QLatin1String(HostKeyCheckingKey), SshHostKeyCheckingNone).toInt());
QString portsSpec = map.value(PortsSpecKey).toString();
if (portsSpec.isEmpty())
@@ -673,6 +688,7 @@ QVariantMap IDevice::toMap() const
map.insert(QLatin1String(IdKey), d->id.toSetting());
map.insert(QLatin1String(OriginKey), d->origin);
+ QReadLocker locker(&d->lock);
map.insert(QLatin1String(MachineTypeKey), d->machineType);
map.insert(QLatin1String(HostKey), d->sshParameters.host());
map.insert(QLatin1String(SshPortKey), d->sshParameters.port());
@@ -721,20 +737,23 @@ QString IDevice::deviceStateToString() const
}
}
-QSsh::SshConnectionParameters IDevice::sshParameters() const
+SshParameters IDevice::sshParameters() const
{
+ QReadLocker locker(&d->lock);
return d->sshParameters;
}
-void IDevice::setSshParameters(const QSsh::SshConnectionParameters &sshParameters)
+void IDevice::setSshParameters(const SshParameters &sshParameters)
{
+ QWriteLocker locker(&d->lock);
d->sshParameters = sshParameters;
}
QUrl IDevice::toolControlChannel(const ControlChannelHint &) const
{
QUrl url;
- url.setScheme(Utils::urlTcpScheme());
+ url.setScheme(urlTcpScheme());
+ QReadLocker locker(&d->lock);
url.setHost(d->sshParameters.host());
return url;
}
@@ -759,6 +778,15 @@ void IDevice::setMachineType(MachineType machineType)
d->machineType = machineType;
}
+FilePath IDevice::rootPath() const
+{
+ FilePath root;
+ root.setScheme("device");
+ root.setHost(id().toString());
+ root.setPath("/");
+ return root;
+}
+
FilePath IDevice::debugServerPath() const
{
return d->debugServerPath;
@@ -774,7 +802,7 @@ FilePath IDevice::debugDumperPath() const
return d->debugDumperPath;
}
-void IDevice::setDebugDumperPath(const Utils::FilePath &path)
+void IDevice::setDebugDumperPath(const FilePath &path)
{
d->debugDumperPath = path;
}
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h
index 9090500f493..22e125ddd9d 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.h
+++ b/src/plugins/projectexplorer/devicesupport/idevice.h
@@ -26,6 +26,7 @@
#pragma once
#include "../projectexplorer_export.h"
+#include "idevicefwd.h"
#include <utils/id.h>
#include <utils/filepath.h>
@@ -46,22 +47,23 @@ QT_BEGIN_NAMESPACE
class QWidget;
QT_END_NAMESPACE
-namespace QSsh { class SshConnectionParameters; }
-
namespace Utils {
class CommandLine;
class Environment;
class Icon;
class PortList;
class Port;
+class ProcessInterface;
class QtcProcess;
} // Utils
namespace ProjectExplorer {
-class DeviceProcess;
class DeviceProcessList;
+class FileTransferInterface;
+class FileTransferSetupData;
class Kit;
+class SshParameters;
class Task;
namespace Internal { class IDevicePrivate; }
@@ -108,14 +110,11 @@ protected:
explicit DeviceEnvironmentFetcher();
};
-class PROJECTEXPLORER_EXPORT PortsGatheringMethod
+class PROJECTEXPLORER_EXPORT PortsGatheringMethod final
{
public:
- using Ptr = QSharedPointer<const PortsGatheringMethod>;
-
- virtual ~PortsGatheringMethod() = default;
- virtual Utils::CommandLine commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const = 0;
- virtual QList<Utils::Port> usedPorts(const QByteArray &commandOutput) const = 0;
+ std::function<Utils::CommandLine(QAbstractSocket::NetworkLayerProtocol protocol)> commandLine;
+ std::function<QList<Utils::Port>(const QByteArray &commandOutput)> parsePorts;
};
// See cpp file for documentation.
@@ -123,8 +122,8 @@ class PROJECTEXPLORER_EXPORT IDevice : public QEnableSharedFromThis<IDevice>
{
friend class Internal::IDevicePrivate;
public:
- using Ptr = QSharedPointer<IDevice>;
- using ConstPtr = QSharedPointer<const IDevice>;
+ using Ptr = IDevicePtr;
+ using ConstPtr = IDeviceConstPtr;
template <class ...Args> using Continuation = std::function<void(Args...)>;
enum Origin { ManuallyAdded, AutoDetected };
@@ -174,14 +173,12 @@ public:
// Devices that can auto detect ports need not return a ports gathering method. Such devices can
// obtain a free port on demand. eg: Desktop device.
virtual bool canAutoDetectPorts() const { return false; }
- virtual PortsGatheringMethod::Ptr portsGatheringMethod() const;
+ virtual PortsGatheringMethod portsGatheringMethod() const { return {}; }
virtual bool canCreateProcessModel() const { return false; }
virtual DeviceProcessList *createProcessListModel(QObject *parent = nullptr) const;
virtual bool hasDeviceTester() const { return false; }
virtual DeviceTester *createDeviceTester() const;
- virtual bool canCreateProcess() const { return false; }
- virtual DeviceProcess *createProcess(QObject *parent) const;
virtual DeviceProcessSignalOperation::Ptr signalOperation() const = 0;
virtual DeviceEnvironmentFetcher::Ptr environmentFetcher() const;
@@ -196,8 +193,8 @@ public:
static QString defaultPrivateKeyFilePath();
static QString defaultPublicKeyFilePath();
- QSsh::SshConnectionParameters sshParameters() const;
- void setSshParameters(const QSsh::SshConnectionParameters &sshParameters);
+ SshParameters sshParameters() const;
+ void setSshParameters(const SshParameters &sshParameters);
enum ControlChannelHint { QmlControlChannel };
virtual QUrl toolControlChannel(const ControlChannelHint &) const;
@@ -208,6 +205,9 @@ public:
MachineType machineType() const;
void setMachineType(MachineType machineType);
+ Utils::FilePath rootPath() const;
+ Utils::FilePath filePath(const QString &pathOnDevice) const;
+
Utils::FilePath debugServerPath() const;
void setDebugServerPath(const Utils::FilePath &path);
@@ -266,7 +266,9 @@ public:
virtual QDateTime lastModified(const Utils::FilePath &filePath) const;
virtual QFile::Permissions permissions(const Utils::FilePath &filePath) const;
virtual bool setPermissions(const Utils::FilePath &filePath, QFile::Permissions) const;
- virtual void runProcess(Utils::QtcProcess &process) const;
+ virtual Utils::ProcessInterface *createProcessInterface() const;
+ virtual FileTransferInterface *createFileTransferInterface(
+ const FileTransferSetupData &setup) const;
virtual Utils::Environment systemEnvironment() const;
virtual qint64 fileSize(const Utils::FilePath &filePath) const;
virtual qint64 bytesAvailable(const Utils::FilePath &filePath) const;
diff --git a/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp b/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp
index 1ff8498d3eb..b12b0cae935 100644
--- a/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp
@@ -25,6 +25,7 @@
#include "idevicefactory.h"
+#include <projectexplorer/devicesupport/idevice.h>
#include <utils/algorithm.h>
#include <utils/icon.h>
#include <utils/qtcassert.h>
diff --git a/src/plugins/projectexplorer/devicesupport/idevicefactory.h b/src/plugins/projectexplorer/devicesupport/idevicefactory.h
index 59034aaef5f..1d2e07e8480 100644
--- a/src/plugins/projectexplorer/devicesupport/idevicefactory.h
+++ b/src/plugins/projectexplorer/devicesupport/idevicefactory.h
@@ -25,12 +25,15 @@
#pragma once
-#include "idevice.h"
+#include "idevicefwd.h"
#include <projectexplorer/projectexplorer_export.h>
+#include <utils/id.h>
#include <QIcon>
#include <QVariantMap>
+namespace Utils { class FilePath; }
+
namespace ProjectExplorer {
class PROJECTEXPLORER_EXPORT IDeviceFactory
@@ -43,8 +46,8 @@ public:
QString displayName() const { return m_displayName; }
QIcon icon() const { return m_icon; }
bool canCreate() const;
- IDevice::Ptr construct() const;
- IDevice::Ptr create() const;
+ IDevicePtr construct() const;
+ IDevicePtr create() const;
virtual bool canRestore(const QVariantMap &) const { return true; }
@@ -57,16 +60,16 @@ protected:
void setDisplayName(const QString &displayName);
void setIcon(const QIcon &icon);
- void setCombinedIcon(const Utils::FilePath &small, const Utils::FilePath &large);
- void setConstructionFunction(const std::function<IDevice::Ptr ()> &constructor);
- void setCreator(const std::function<IDevice::Ptr()> &creator);
+ void setCombinedIcon(const Utils::FilePath &smallIcon, const Utils::FilePath &largeIcon);
+ void setConstructionFunction(const std::function<IDevicePtr ()> &constructor);
+ void setCreator(const std::function<IDevicePtr()> &creator);
private:
- std::function<IDevice::Ptr()> m_creator;
+ std::function<IDevicePtr()> m_creator;
const Utils::Id m_deviceType;
QString m_displayName;
QIcon m_icon;
- std::function<IDevice::Ptr()> m_constructor;
+ std::function<IDevicePtr()> m_constructor;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/idevicefwd.h b/src/plugins/projectexplorer/devicesupport/idevicefwd.h
new file mode 100644
index 00000000000..e4d0a1bf08b
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/idevicefwd.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtGlobal>
+
+QT_BEGIN_NAMESPACE
+template <class T>
+class QSharedPointer;
+QT_END_NAMESPACE
+
+namespace ProjectExplorer {
+
+class IDevice;
+
+using IDevicePtr = QSharedPointer<IDevice>;
+using IDeviceConstPtr = QSharedPointer<const IDevice>;
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/idevicewidget.h b/src/plugins/projectexplorer/devicesupport/idevicewidget.h
index ef02ef847fe..8af4f37af21 100644
--- a/src/plugins/projectexplorer/devicesupport/idevicewidget.h
+++ b/src/plugins/projectexplorer/devicesupport/idevicewidget.h
@@ -25,7 +25,7 @@
#pragma once
-#include "idevice.h"
+#include "idevicefwd.h"
#include <projectexplorer/projectexplorer_export.h>
#include <QWidget>
@@ -40,14 +40,14 @@ public:
virtual void updateDeviceFromUi() = 0;
protected:
- explicit IDeviceWidget(const IDevice::Ptr &device) :
+ explicit IDeviceWidget(const IDevicePtr &device) :
m_device(device)
{ }
- IDevice::Ptr device() const { return m_device; }
+ IDevicePtr device() const { return m_device; }
private:
- IDevice::Ptr m_device;
+ IDevicePtr m_device;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
index 1579b2cc9fe..14b09034f5c 100644
--- a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
+++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
@@ -25,204 +25,43 @@
#include "localprocesslist.h"
-#include <utils/qtcprocess.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <utils/processinfo.h>
-#include <QLibrary>
#include <QTimer>
-#ifdef Q_OS_UNIX
-#include <QDir>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
+#if defined(Q_OS_UNIX)
#include <unistd.h>
-#endif
-
-#ifdef Q_OS_WIN
+#elif defined(Q_OS_WIN)
#include <windows.h>
-#include <utils/winutils.h>
-#include <tlhelp32.h>
-#include <psapi.h>
#endif
+using namespace Utils;
+
namespace ProjectExplorer {
namespace Internal {
-#ifdef Q_OS_WIN
-
-LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent)
- : DeviceProcessList(device, parent)
-{
- setOwnPid(GetCurrentProcessId());
-}
-
-QList<DeviceProcessItem> LocalProcessList::getLocalProcesses()
-{
- QList<DeviceProcessItem> processes;
-
- PROCESSENTRY32 pe;
- pe.dwSize = sizeof(PROCESSENTRY32);
- HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if (snapshot == INVALID_HANDLE_VALUE)
- return processes;
-
- for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) {
- DeviceProcessItem p;
- p.pid = pe.th32ProcessID;
- // Image has the absolute path, but can fail.
- const QString image = Utils::imageName(pe.th32ProcessID);
- p.exe = p.cmdLine = image.isEmpty() ?
- QString::fromWCharArray(pe.szExeFile) :
- image;
- processes << p;
- }
- CloseHandle(snapshot);
- return processes;
-}
-
-#endif //Q_OS_WIN
-
-#ifdef Q_OS_UNIX
LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcessList(device, parent)
{
+#if defined(Q_OS_UNIX)
setOwnPid(getpid());
+#elif defined(Q_OS_WIN)
+ setOwnPid(GetCurrentProcessId());
+#endif
}
-static bool isUnixProcessId(const QString &procname)
-{
- for (int i = 0; i != procname.size(); ++i)
- if (!procname.at(i).isDigit())
- return false;
- return true;
-}
-
-// Determine UNIX processes by reading "/proc". Default to ps if
-// it does not exist
-
-static const char procDirC[] = "/proc/";
-
-static QList<DeviceProcessItem> getLocalProcessesUsingProc(const QDir &procDir)
-{
- QList<DeviceProcessItem> processes;
- const QString procDirPath = QLatin1String(procDirC);
- const QStringList procIds = procDir.entryList();
- foreach (const QString &procId, procIds) {
- if (!isUnixProcessId(procId))
- continue;
- DeviceProcessItem proc;
- proc.pid = procId.toInt();
- const QString root = procDirPath + procId;
-
- QFile exeFile(root + QLatin1String("/exe"));
- proc.exe = exeFile.symLinkTarget();
-
- QFile cmdLineFile(root + QLatin1String("/cmdline"));
- if (cmdLineFile.open(QIODevice::ReadOnly)) { // process may have exited
- QList<QByteArray> tokens = cmdLineFile.readAll().split('\0');
- if (!tokens.isEmpty()) {
- if (proc.exe.isEmpty())
- proc.exe = QString::fromLocal8Bit(tokens.front());
- foreach (const QByteArray &t, tokens) {
- if (!proc.cmdLine.isEmpty())
- proc.cmdLine.append(QLatin1Char(' '));
- proc.cmdLine.append(QString::fromLocal8Bit(t));
- }
- }
- }
-
- if (proc.exe.isEmpty()) {
- QFile statFile(root + QLatin1String("/stat"));
- if (!statFile.open(QIODevice::ReadOnly)) {
- const QStringList data = QString::fromLocal8Bit(statFile.readAll()).split(QLatin1Char(' '));
- if (data.size() < 2)
- continue;
- proc.exe = data.at(1);
- proc.cmdLine = data.at(1); // PPID is element 3
- if (proc.exe.startsWith(QLatin1Char('(')) && proc.exe.endsWith(QLatin1Char(')'))) {
- proc.exe.truncate(proc.exe.size() - 1);
- proc.exe.remove(0, 1);
- }
- }
- }
- if (!proc.exe.isEmpty())
- processes.push_back(proc);
- }
- return processes;
-}
-
-// Determine UNIX processes by running ps
-static QMap<qint64, QString> getLocalProcessDataUsingPs(const QString &column)
-{
- QMap<qint64, QString> result;
- Utils::QtcProcess psProcess;
- psProcess.setCommand({"ps", {"-e", "-o", "pid," + column}});
- psProcess.start();
- if (psProcess.waitForStarted()) {
- QByteArray output;
- if (psProcess.readDataFromProcess(30, &output, nullptr, false)) {
- // Split "457 /Users/foo.app arg1 arg2"
- const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
- const int lineCount = lines.size();
- const QChar blank = QLatin1Char(' ');
- for (int l = 1; l < lineCount; l++) { // Skip header
- const QString line = lines.at(l).trimmed();
- const int pidSep = line.indexOf(blank);
- const qint64 pid = line.left(pidSep).toLongLong();
- result[pid] = line.mid(pidSep + 1);
- }
- }
- }
- return result;
-}
-
-static QList<DeviceProcessItem> getLocalProcessesUsingPs()
-{
- QList<DeviceProcessItem> processes;
-
- // cmdLines are full command lines, usually with absolute path,
- // exeNames only the file part of the executable's path.
- const QMap<qint64, QString> exeNames = getLocalProcessDataUsingPs("comm");
- const QMap<qint64, QString> cmdLines = getLocalProcessDataUsingPs("args");
-
- for (auto it = exeNames.begin(), end = exeNames.end(); it != end; ++it) {
- const qint64 pid = it.key();
- if (pid <= 0)
- continue;
- const QString cmdLine = cmdLines.value(pid);
- if (cmdLines.isEmpty())
- continue;
- const QString exeName = it.value();
- if (exeName.isEmpty())
- continue;
- const int pos = cmdLine.indexOf(exeName);
- if (pos == -1)
- continue;
- processes.append({pid, cmdLine, cmdLine.left(pos + exeName.size())});
- }
-
- return processes;
-}
-
-QList<DeviceProcessItem> LocalProcessList::getLocalProcesses()
-{
- const QDir procDir = QDir(QLatin1String(procDirC));
- return procDir.exists() ? getLocalProcessesUsingProc(procDir) : getLocalProcessesUsingPs();
-}
-
-#endif // QT_OS_UNIX
-
-void LocalProcessList::doKillProcess(const DeviceProcessItem &process)
+void LocalProcessList::doKillProcess(const ProcessInfo &processInfo)
{
DeviceProcessSignalOperation::Ptr signalOperation = device()->signalOperation();
connect(signalOperation.data(), &DeviceProcessSignalOperation::finished,
this, &LocalProcessList::reportDelayedKillStatus);
- signalOperation->killProcess(process.pid);
+ signalOperation->killProcess(processInfo.processId);
}
void LocalProcessList::handleUpdate()
{
- reportProcessListUpdated(getLocalProcesses());
+ reportProcessListUpdated(ProcessInfo::processInfoList());
}
void LocalProcessList::doUpdate()
diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.h b/src/plugins/projectexplorer/devicesupport/localprocesslist.h
index 8e100868495..fbfd5e6368a 100644
--- a/src/plugins/projectexplorer/devicesupport/localprocesslist.h
+++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.h
@@ -35,13 +35,11 @@ class LocalProcessList : public DeviceProcessList
Q_OBJECT
public:
- explicit LocalProcessList(const IDevice::ConstPtr &device, QObject *parent = nullptr);
-
- static QList<DeviceProcessItem> getLocalProcesses();
+ explicit LocalProcessList(const IDeviceConstPtr &device, QObject *parent = nullptr);
private:
void doUpdate() override;
- void doKillProcess(const DeviceProcessItem &process) override;
+ void doKillProcess(const Utils::ProcessInfo &process) override;
private:
void handleUpdate();
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
deleted file mode 100644
index bf265b0258f..00000000000
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
+++ /dev/null
@@ -1,359 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshdeviceprocess.h"
-
-#include "idevice.h"
-#include "../runcontrol.h"
-
-#include <coreplugin/icore.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshconnectionmanager.h>
-#include <ssh/sshremoteprocess.h>
-#include <utils/environment.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-
-#include <QString>
-#include <QTimer>
-
-using namespace Utils;
-
-namespace ProjectExplorer {
-
-enum class Signal { Interrupt, Terminate, Kill };
-
-class SshDeviceProcess::SshDeviceProcessPrivate
-{
-public:
- SshDeviceProcessPrivate(SshDeviceProcess *q) : q(q) {}
-
- SshDeviceProcess * const q;
- bool ignoreSelfSignals = true;
- QSsh::SshConnection *connection = nullptr;
- QSsh::SshRemoteProcessPtr remoteProcess;
- Runnable runnable;
- QString errorMessage;
- QProcess::ExitStatus exitStatus = QProcess::NormalExit;
- DeviceProcessSignalOperation::Ptr killOperation;
- QTimer killTimer;
- enum State { Inactive, Connecting, Connected, ProcessRunning } state = Inactive;
-
- void setState(State newState);
- void doSignal(Signal signal);
-
- QString displayName() const
- {
- return runnable.extraData.value("Ssh.X11ForwardToDisplay").toString();
- }
-};
-
-SshDeviceProcess::SshDeviceProcess(const IDevice::ConstPtr &device, QObject *parent)
- : DeviceProcess(device, QtcProcess::TerminalOn, parent),
- d(std::make_unique<SshDeviceProcessPrivate>(this))
-{
- // Hack: we rely on fact that below slots were called before any other external slots connected
- // to this instance signals. That's why we don't re-emit them from inside our handlers since
- // these signal will reach all other external slots anyway after our handlers are done.
- connect(this, &QtcProcess::started, this, [this] {
- if (!d->ignoreSelfSignals)
- handleProcessStarted();
- });
- connect(this, &QtcProcess::finished, this, [this] {
- if (!d->ignoreSelfSignals)
- handleProcessFinished(QtcProcess::errorString());
- });
- connect(&d->killTimer, &QTimer::timeout, this, &SshDeviceProcess::handleKillOperationTimeout);
-}
-
-SshDeviceProcess::~SshDeviceProcess()
-{
- d->setState(SshDeviceProcessPrivate::Inactive);
-}
-
-void SshDeviceProcess::start(const Runnable &runnable)
-{
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::Inactive, return);
- QTC_ASSERT(runInTerminal() || !runnable.command.isEmpty(), return);
- d->setState(SshDeviceProcessPrivate::Connecting);
-
- d->errorMessage.clear();
- d->exitStatus = QProcess::NormalExit;
- d->runnable = runnable;
- QSsh::SshConnectionParameters params = device()->sshParameters();
- params.x11DisplayName = d->displayName();
- d->connection = QSsh::SshConnectionManager::acquireConnection(params);
- connect(d->connection, &QSsh::SshConnection::errorOccurred,
- this, &SshDeviceProcess::handleConnectionError);
- connect(d->connection, &QSsh::SshConnection::disconnected,
- this, &SshDeviceProcess::handleDisconnected);
- if (d->connection->state() == QSsh::SshConnection::Connected) {
- handleConnected();
- } else {
- connect(d->connection, &QSsh::SshConnection::connected,
- this, &SshDeviceProcess::handleConnected);
- if (d->connection->state() == QSsh::SshConnection::Unconnected)
- d->connection->connectToHost();
- }
-}
-
-void SshDeviceProcess::interrupt()
-{
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::ProcessRunning, return);
- d->doSignal(Signal::Interrupt);
-}
-
-void SshDeviceProcess::terminate()
-{
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::ProcessRunning, return);
- d->doSignal(Signal::Terminate);
-}
-
-void SshDeviceProcess::kill()
-{
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::ProcessRunning, return);
- d->doSignal(Signal::Kill);
-}
-
-QProcess::ProcessState SshDeviceProcess::state() const
-{
- switch (d->state) {
- case SshDeviceProcessPrivate::Inactive:
- return QProcess::NotRunning;
- case SshDeviceProcessPrivate::Connecting:
- case SshDeviceProcessPrivate::Connected:
- return QProcess::Starting;
- case SshDeviceProcessPrivate::ProcessRunning:
- return QProcess::Running;
- default:
- QTC_CHECK(false);
- return QProcess::NotRunning;
- }
-}
-
-QProcess::ExitStatus SshDeviceProcess::exitStatus() const
-{
- return d->exitStatus == QProcess::NormalExit && exitCode() != 255
- ? QProcess::NormalExit : QProcess::CrashExit;
-}
-
-int SshDeviceProcess::exitCode() const
-{
- return runInTerminal() ? QtcProcess::exitCode() : d->remoteProcess->exitCode();
-}
-
-QString SshDeviceProcess::errorString() const
-{
- return d->errorMessage;
-}
-
-QByteArray SshDeviceProcess::readAllStandardOutput()
-{
- return d->remoteProcess.get() ? d->remoteProcess->readAllStandardOutput() : QByteArray();
-}
-
-QByteArray SshDeviceProcess::readAllStandardError()
-{
- return d->remoteProcess.get() ? d->remoteProcess->readAllStandardError() : QByteArray();
-}
-
-qint64 SshDeviceProcess::processId() const
-{
- return 0;
-}
-
-void SshDeviceProcess::handleConnected()
-{
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::Connecting, return);
- d->setState(SshDeviceProcessPrivate::Connected);
-
- d->remoteProcess = runInTerminal() && d->runnable.command.isEmpty()
- ? d->connection->createRemoteShell()
- : d->connection->createRemoteProcess(fullCommandLine(d->runnable));
- const QString display = d->displayName();
- if (!display.isEmpty())
- d->remoteProcess->requestX11Forwarding(display);
- d->ignoreSelfSignals = !runInTerminal();
- if (runInTerminal()) {
- setAbortOnMetaChars(false);
- setCommand(d->remoteProcess->fullLocalCommandLine(true));
- QtcProcess::start();
- } else {
- connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::started,
- this, &SshDeviceProcess::handleProcessStarted);
- connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::done,
- this, &SshDeviceProcess::handleProcessFinished);
- connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::readyReadStandardOutput,
- this, &QtcProcess::readyReadStandardOutput);
- connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::readyReadStandardError,
- this, &QtcProcess::readyReadStandardError);
- d->remoteProcess->start();
- }
-}
-
-void SshDeviceProcess::handleConnectionError()
-{
- QTC_ASSERT(d->state != SshDeviceProcessPrivate::Inactive, return);
-
- d->errorMessage = d->connection->errorString();
- handleDisconnected();
-}
-
-void SshDeviceProcess::handleDisconnected()
-{
- QTC_ASSERT(d->state != SshDeviceProcessPrivate::Inactive, return);
- const SshDeviceProcessPrivate::State oldState = d->state;
- d->setState(SshDeviceProcessPrivate::Inactive);
- switch (oldState) {
- case SshDeviceProcessPrivate::Connecting:
- case SshDeviceProcessPrivate::Connected:
- emit errorOccurred(QProcess::FailedToStart);
- break;
- case SshDeviceProcessPrivate::ProcessRunning:
- d->exitStatus = QProcess::CrashExit;
- emit finished();
- default:
- break;
- }
-}
-
-void SshDeviceProcess::handleProcessStarted()
-{
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::Connected, return);
-
- d->setState(SshDeviceProcessPrivate::ProcessRunning);
- if (d->ignoreSelfSignals)
- emit started();
-}
-
-void SshDeviceProcess::handleProcessFinished(const QString &error)
-{
- d->errorMessage = error;
- if (d->killOperation && error.isEmpty())
- d->errorMessage = tr("The process was ended forcefully.");
- d->setState(SshDeviceProcessPrivate::Inactive);
- if (d->ignoreSelfSignals)
- emit finished();
-}
-
-void SshDeviceProcess::handleKillOperationFinished(const QString &errorMessage)
-{
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::ProcessRunning, return);
- if (errorMessage.isEmpty()) // Process will finish as expected; nothing to do here.
- return;
-
- d->exitStatus = QProcess::CrashExit; // Not entirely true, but it will get the message across.
- d->errorMessage = tr("Failed to kill remote process: %1").arg(errorMessage);
- d->setState(SshDeviceProcessPrivate::Inactive);
- emit finished();
-}
-
-void SshDeviceProcess::handleKillOperationTimeout()
-{
- d->exitStatus = QProcess::CrashExit; // Not entirely true, but it will get the message across.
- d->errorMessage = tr("Timeout waiting for remote process to finish.");
- d->setState(SshDeviceProcessPrivate::Inactive);
- emit finished();
-}
-
-QString SshDeviceProcess::fullCommandLine(const Runnable &runnable) const
-{
- QString cmdLine = runnable.command.executable().toString();
- // FIXME: That quotes wrongly.
- if (!runnable.command.arguments().isEmpty())
- cmdLine.append(QLatin1Char(' ')).append(runnable.command.arguments());
- return cmdLine;
-}
-
-void SshDeviceProcess::SshDeviceProcessPrivate::doSignal(Signal signal)
-{
- if (runnable.command.isEmpty())
- return;
- switch (state) {
- case SshDeviceProcessPrivate::Inactive:
- QTC_ASSERT(false, return);
- break;
- case SshDeviceProcessPrivate::Connecting:
- errorMessage = tr("Terminated by request.");
- setState(SshDeviceProcessPrivate::Inactive);
- emit q->errorOccurred(QProcess::FailedToStart);
- break;
- case SshDeviceProcessPrivate::Connected:
- case SshDeviceProcessPrivate::ProcessRunning:
- DeviceProcessSignalOperation::Ptr signalOperation = q->device()->signalOperation();
- const qint64 processId = q->processId();
- if (signal == Signal::Interrupt) {
- if (processId != 0)
- signalOperation->interruptProcess(processId);
- else
- signalOperation->interruptProcess(runnable.command.executable().toString());
- } else {
- if (killOperation) // We are already in the process of killing the app.
- return;
- killOperation = signalOperation;
- connect(signalOperation.data(), &DeviceProcessSignalOperation::finished, q,
- &SshDeviceProcess::handleKillOperationFinished);
- killTimer.start(5000);
- if (processId != 0)
- signalOperation->killProcess(processId);
- else
- signalOperation->killProcess(runnable.command.executable().toString());
- }
- break;
- }
-}
-
-void SshDeviceProcess::SshDeviceProcessPrivate::setState(SshDeviceProcess::SshDeviceProcessPrivate::State newState)
-{
- if (state == newState)
- return;
-
- state = newState;
- if (state != Inactive)
- return;
-
- if (killOperation) {
- killOperation->disconnect(q);
- killOperation.clear();
- if (q->runInTerminal())
- QMetaObject::invokeMethod(q, &QtcProcess::stopProcess, Qt::QueuedConnection);
- }
- killTimer.stop();
- if (remoteProcess)
- remoteProcess->disconnect(q);
- if (connection) {
- connection->disconnect(q);
- QSsh::SshConnectionManager::releaseConnection(connection);
- connection = nullptr;
- }
-}
-
-qint64 SshDeviceProcess::write(const QByteArray &data)
-{
- QTC_ASSERT(!runInTerminal(), return -1);
- return d->remoteProcess->write(data);
-}
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h
deleted file mode 100644
index 0980d530bcf..00000000000
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "deviceprocess.h"
-
-#include <memory>
-
-namespace ProjectExplorer {
-
-class Runnable;
-
-class PROJECTEXPLORER_EXPORT SshDeviceProcess : public DeviceProcess
-{
- Q_OBJECT
-public:
- explicit SshDeviceProcess(const QSharedPointer<const IDevice> &device, QObject *parent = nullptr);
- ~SshDeviceProcess() override;
-
- void start(const Runnable &runnable) override;
- void interrupt() override;
- void terminate() override;
- void kill() override;
-
- QProcess::ProcessState state() const override;
- QProcess::ExitStatus exitStatus() const override;
- int exitCode() const override;
- QString errorString() const override;
-
- QByteArray readAllStandardOutput() override;
- QByteArray readAllStandardError() override;
-
- qint64 write(const QByteArray &data) override;
-
-private:
- void handleConnected();
- void handleConnectionError();
- void handleDisconnected();
- void handleProcessStarted();
- void handleProcessFinished(const QString &error);
- void handleKillOperationFinished(const QString &errorMessage);
- void handleKillOperationTimeout();
-
- virtual QString fullCommandLine(const Runnable &runnable) const;
- virtual qint64 processId() const;
-
- class SshDeviceProcessPrivate;
- friend class SshDeviceProcessPrivate;
- const std::unique_ptr<SshDeviceProcessPrivate> d;
-};
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
index 32d58dc5dce..da69611151f 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
@@ -24,71 +24,61 @@
****************************************************************************/
#include "sshdeviceprocesslist.h"
-
#include "idevice.h"
-#include <ssh/sshremoteprocessrunner.h>
+#include <utils/processinfo.h>
#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
+#include <utils/qtcprocess.h>
-using namespace QSsh;
+using namespace Utils;
namespace ProjectExplorer {
-class SshDeviceProcessList::SshDeviceProcessListPrivate
+class SshDeviceProcessListPrivate
{
public:
- SshRemoteProcessRunner process;
- DeviceProcessSignalOperation::Ptr signalOperation;
+ QtcProcess m_process;
+ DeviceProcessSignalOperation::Ptr m_signalOperation;
};
SshDeviceProcessList::SshDeviceProcessList(const IDevice::ConstPtr &device, QObject *parent) :
DeviceProcessList(device, parent), d(std::make_unique<SshDeviceProcessListPrivate>())
{
+ connect(&d->m_process, &QtcProcess::done, this, &SshDeviceProcessList::handleProcessDone);
}
SshDeviceProcessList::~SshDeviceProcessList() = default;
void SshDeviceProcessList::doUpdate()
{
- connect(&d->process, &SshRemoteProcessRunner::connectionError,
- this, &SshDeviceProcessList::handleConnectionError);
- connect(&d->process, &SshRemoteProcessRunner::processClosed,
- this, &SshDeviceProcessList::handleListProcessFinished);
- d->process.run(listProcessesCommandLine(), device()->sshParameters());
+ d->m_process.close();
+ d->m_process.setCommand({device()->filePath("/bin/sh"), {"-c", listProcessesCommandLine()}});
+ d->m_process.start();
}
-void SshDeviceProcessList::doKillProcess(const DeviceProcessItem &process)
+void SshDeviceProcessList::doKillProcess(const ProcessInfo &process)
{
- d->signalOperation = device()->signalOperation();
- QTC_ASSERT(d->signalOperation, return);
- connect(d->signalOperation.data(), &DeviceProcessSignalOperation::finished,
+ d->m_signalOperation = device()->signalOperation();
+ QTC_ASSERT(d->m_signalOperation, return);
+ connect(d->m_signalOperation.data(), &DeviceProcessSignalOperation::finished,
this, &SshDeviceProcessList::handleKillProcessFinished);
- d->signalOperation->killProcess(process.pid);
-}
-
-void SshDeviceProcessList::handleConnectionError()
-{
- setFinished();
- reportError(tr("Connection failure: %1").arg(d->process.lastConnectionErrorString()));
+ d->m_signalOperation->killProcess(process.processId);
}
-void SshDeviceProcessList::handleListProcessFinished(const QString &error)
+void SshDeviceProcessList::handleProcessDone()
{
- setFinished();
- if (!error.isEmpty()) {
- handleProcessError(error);
- return;
- }
- if (d->process.processExitCode() == 0) {
- const QByteArray remoteStdout = d->process.readAllStandardOutput();
- const QString stdoutString
- = QString::fromUtf8(remoteStdout.data(), remoteStdout.count());
- reportProcessListUpdated(buildProcessList(stdoutString));
+ if (d->m_process.result() == ProcessResult::FinishedWithSuccess) {
+ reportProcessListUpdated(buildProcessList(d->m_process.cleanedStdOut()));
} else {
- handleProcessError(tr("Process listing command failed with exit code %1.")
- .arg(d->process.processExitCode()));
+ const QString errorMessage = d->m_process.exitStatus() == QProcess::NormalExit
+ ? tr("Process listing command failed with exit code %1.").arg(d->m_process.exitCode())
+ : d->m_process.errorString();
+ const QString stdErr = d->m_process.cleanedStdErr();
+ const QString fullMessage = stdErr.isEmpty()
+ ? errorMessage : errorMessage + '\n' + tr("Remote stderr was: %1").arg(stdErr);
+ reportError(fullMessage);
}
+ setFinished();
}
void SshDeviceProcessList::handleKillProcessFinished(const QString &errorString)
@@ -100,21 +90,12 @@ void SshDeviceProcessList::handleKillProcessFinished(const QString &errorString)
setFinished();
}
-void SshDeviceProcessList::handleProcessError(const QString &errorMessage)
-{
- QString fullMessage = errorMessage;
- const QByteArray remoteStderr = d->process.readAllStandardError();
- if (!remoteStderr.isEmpty())
- fullMessage += QLatin1Char('\n') + tr("Remote stderr was: %1").arg(QString::fromUtf8(remoteStderr));
- reportError(fullMessage);
-}
-
void SshDeviceProcessList::setFinished()
{
- d->process.disconnect(this);
- if (d->signalOperation) {
- d->signalOperation->disconnect(this);
- d->signalOperation.clear();
+ d->m_process.close();
+ if (d->m_signalOperation) {
+ d->m_signalOperation->disconnect(this);
+ d->m_signalOperation.clear();
}
}
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h
index 60937e65cc0..b13f5d11569 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h
@@ -31,28 +31,27 @@
namespace ProjectExplorer {
+class SshDeviceProcessListPrivate;
+
class PROJECTEXPLORER_EXPORT SshDeviceProcessList : public DeviceProcessList
{
Q_OBJECT
public:
- explicit SshDeviceProcessList(const IDevice::ConstPtr &device, QObject *parent = nullptr);
+ explicit SshDeviceProcessList(const IDeviceConstPtr &device, QObject *parent = nullptr);
~SshDeviceProcessList() override;
private:
- void handleConnectionError();
- void handleListProcessFinished(const QString &error);
+ void handleProcessDone();
void handleKillProcessFinished(const QString &errorString);
virtual QString listProcessesCommandLine() const = 0;
- virtual QList<DeviceProcessItem> buildProcessList(const QString &listProcessesReply) const = 0;
+ virtual QList<Utils::ProcessInfo> buildProcessList(const QString &listProcessesReply) const = 0;
void doUpdate() override;
- void doKillProcess(const DeviceProcessItem &process) override;
+ void doKillProcess(const Utils::ProcessInfo &process) override;
- void handleProcessError(const QString &errorMessage);
void setFinished();
- class SshDeviceProcessListPrivate;
const std::unique_ptr<SshDeviceProcessListPrivate> d;
};
diff --git a/src/plugins/projectexplorer/devicesupport/sshparameters.cpp b/src/plugins/projectexplorer/devicesupport/sshparameters.cpp
new file mode 100644
index 00000000000..90d650c1016
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/sshparameters.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sshparameters.h"
+
+#include "sshsettings.h"
+
+#include <utils/environment.h>
+#include <utils/fileutils.h>
+#include <utils/hostosinfo.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+
+#include <QDebug>
+
+#include <memory>
+
+using namespace Utils;
+
+namespace ProjectExplorer {
+
+SshParameters::SshParameters()
+{
+ url.setPort(0);
+}
+
+QStringList SshParameters::connectionOptions(const FilePath &binary) const
+{
+ QString hostKeyCheckingString;
+ switch (hostKeyCheckingMode) {
+ case SshHostKeyCheckingNone:
+ case SshHostKeyCheckingAllowNoMatch:
+ // There is "accept-new" as well, but only since 7.6.
+ hostKeyCheckingString = "no";
+ break;
+ case SshHostKeyCheckingStrict:
+ hostKeyCheckingString = "yes";
+ break;
+ }
+
+ QStringList args{"-o", "StrictHostKeyChecking=" + hostKeyCheckingString,
+ "-o", "Port=" + QString::number(port())};
+
+ if (!userName().isEmpty())
+ args << "-o" << "User=" + userName();
+
+ const bool keyOnly = authenticationType == SshParameters::AuthenticationTypeSpecificKey;
+ if (keyOnly)
+ args << "-o" << "IdentitiesOnly=yes" << "-i" << privateKeyFile.path();
+
+ const QString batchModeEnabled = (keyOnly || SshSettings::askpassFilePath().isEmpty())
+ ? QLatin1String("yes") : QLatin1String("no");
+ args << "-o" << "BatchMode=" + batchModeEnabled;
+
+ const bool isWindows = HostOsInfo::isWindowsHost()
+ && binary.toString().toLower().contains("/system32/");
+ const bool useTimeout = (timeout != 0) && !isWindows;
+ if (useTimeout)
+ args << "-o" << "ConnectTimeout=" + QString::number(timeout);
+
+ return args;
+}
+
+bool SshParameters::setupSshEnvironment(QtcProcess *process)
+{
+ Environment env = process->controlEnvironment();
+ if (!env.isValid())
+ env = Environment::systemEnvironment();
+ const bool hasDisplay = env.hasKey("DISPLAY") && (env.value("DISPLAY") != QString(":0"));
+ if (SshSettings::askpassFilePath().exists()) {
+ env.set("SSH_ASKPASS", SshSettings::askpassFilePath().toUserOutput());
+
+ // OpenSSH only uses the askpass program if DISPLAY is set, regardless of the platform.
+ if (!env.hasKey("DISPLAY"))
+ env.set("DISPLAY", ":0");
+ }
+ process->setEnvironment(env);
+
+ // Otherwise, ssh will ignore SSH_ASKPASS and read from /dev/tty directly.
+ process->setDisableUnixTerminal();
+ return hasDisplay;
+}
+
+
+static inline bool equals(const SshParameters &p1, const SshParameters &p2)
+{
+ return p1.url == p2.url
+ && p1.authenticationType == p2.authenticationType
+ && p1.privateKeyFile == p2.privateKeyFile
+ && p1.hostKeyCheckingMode == p2.hostKeyCheckingMode
+ && p1.x11DisplayName == p2.x11DisplayName
+ && p1.timeout == p2.timeout;
+}
+
+bool operator==(const SshParameters &p1, const SshParameters &p2)
+{
+ return equals(p1, p2);
+}
+
+bool operator!=(const SshParameters &p1, const SshParameters &p2)
+{
+ return !equals(p1, p2);
+}
+
+#ifdef WITH_TESTS
+namespace SshTest {
+const QString getHostFromEnvironment()
+{
+ const QString host = QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_HOST"));
+ if (host.isEmpty() && qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS"))
+ return QString("127.0.0.1");
+ return host;
+}
+
+quint16 getPortFromEnvironment()
+{
+ const int port = qEnvironmentVariableIntValue("QTC_SSH_TEST_PORT");
+ return port != 0 ? quint16(port) : 22;
+}
+
+const QString getUserFromEnvironment()
+{
+ return QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_USER"));
+}
+
+const QString getKeyFileFromEnvironment()
+{
+ const FilePath defaultKeyFile = FileUtils::homePath() / ".ssh/id_rsa";
+ const QString keyFile = QString::fromLocal8Bit(qgetenv("QTC_SSH_TEST_KEYFILE"));
+ if (keyFile.isEmpty()) {
+ if (qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS"))
+ return defaultKeyFile.toString();
+ }
+ return keyFile;
+}
+
+const QString userAtHost()
+{
+ QString userMidFix = getUserFromEnvironment();
+ if (!userMidFix.isEmpty())
+ userMidFix.append('@');
+ return userMidFix + getHostFromEnvironment();
+}
+
+SshParameters getParameters()
+{
+ SshParameters params;
+ if (!qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS")) {
+ params.setUserName(getUserFromEnvironment());
+ params.privateKeyFile = FilePath::fromUserInput(getKeyFileFromEnvironment());
+ }
+ params.setHost(getHostFromEnvironment());
+ params.setPort(getPortFromEnvironment());
+ params.timeout = 10;
+ params.authenticationType = !params.privateKeyFile.isEmpty()
+ ? SshParameters::AuthenticationTypeSpecificKey
+ : SshParameters::AuthenticationTypeAll;
+ return params;
+}
+
+bool checkParameters(const SshParameters &params)
+{
+ if (qEnvironmentVariableIsSet("QTC_SSH_TEST_DEFAULTS"))
+ return true;
+ if (params.host().isEmpty()) {
+ qWarning("No hostname provided. Set QTC_SSH_TEST_HOST.");
+ return false;
+ }
+ if (params.userName().isEmpty())
+ qWarning("No user name provided - test may fail with empty default. Set QTC_SSH_TEST_USER.");
+ if (params.privateKeyFile.isEmpty()) {
+ qWarning("No key file provided. Set QTC_SSH_TEST_KEYFILE.");
+ return false;
+ }
+ return true;
+}
+
+void printSetupHelp()
+{
+ qInfo() << "\n\n"
+ "In order to run this test properly it requires some setup (example for fedora):\n"
+ "1. Run a server on the host to connect to:\n"
+ " systemctl start sshd\n"
+ "2. Create your own ssh key (needed only once). For fedora it needs ecdsa type:\n"
+ " ssh-keygen -t ecdsa\n"
+ "3. Make your public key known to the server (needed only once):\n"
+ " ssh-copy-id -i [full path to your public key] [user@host]\n"
+ "4. Set the env variables before executing test:\n"
+ " QTC_SSH_TEST_HOST=127.0.0.1\n"
+ " QTC_SSH_TEST_KEYFILE=[full path to your private key]\n"
+ " QTC_SSH_TEST_USER=[your user name]\n";
+}
+
+} // namespace SshTest
+#endif
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/sshparameters.h b/src/plugins/projectexplorer/devicesupport/sshparameters.h
new file mode 100644
index 00000000000..abf94883bdc
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/sshparameters.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "../projectexplorer_export.h"
+
+#include <utils/filepath.h>
+
+#include <QUrl>
+
+namespace Utils { class QtcProcess; }
+
+namespace ProjectExplorer {
+
+enum SshHostKeyCheckingMode {
+ SshHostKeyCheckingNone,
+ SshHostKeyCheckingStrict,
+ SshHostKeyCheckingAllowNoMatch,
+};
+
+class PROJECTEXPLORER_EXPORT SshParameters
+{
+public:
+ enum AuthenticationType {
+ AuthenticationTypeAll,
+ AuthenticationTypeSpecificKey,
+ };
+
+ SshParameters();
+
+ QString host() const { return url.host(); }
+ quint16 port() const { return url.port(); }
+ QString userName() const { return url.userName(); }
+ QString userAtHost() const { return userName().isEmpty() ? host() : userName() + '@' + host(); }
+ void setHost(const QString &host) { url.setHost(host); }
+ void setPort(int port) { url.setPort(port); }
+ void setUserName(const QString &name) { url.setUserName(name); }
+
+ QStringList connectionOptions(const Utils::FilePath &binary) const;
+
+ QUrl url;
+ Utils::FilePath privateKeyFile;
+ QString x11DisplayName;
+ int timeout = 0; // In seconds.
+ AuthenticationType authenticationType = AuthenticationTypeAll;
+ SshHostKeyCheckingMode hostKeyCheckingMode = SshHostKeyCheckingAllowNoMatch;
+
+ static bool setupSshEnvironment(Utils::QtcProcess *process);
+};
+
+PROJECTEXPLORER_EXPORT bool operator==(const SshParameters &p1, const SshParameters &p2);
+PROJECTEXPLORER_EXPORT bool operator!=(const SshParameters &p1, const SshParameters &p2);
+
+#ifdef WITH_TESTS
+namespace SshTest {
+const QString PROJECTEXPLORER_EXPORT getHostFromEnvironment();
+quint16 PROJECTEXPLORER_EXPORT getPortFromEnvironment();
+const QString PROJECTEXPLORER_EXPORT getUserFromEnvironment();
+const QString PROJECTEXPLORER_EXPORT getKeyFileFromEnvironment();
+const PROJECTEXPLORER_EXPORT QString userAtHost();
+SshParameters PROJECTEXPLORER_EXPORT getParameters();
+bool PROJECTEXPLORER_EXPORT checkParameters(const SshParameters &params);
+void PROJECTEXPLORER_EXPORT printSetupHelp();
+} // namespace SshTest
+#endif
+
+} // namespace ProjectExplorer
+
+Q_DECLARE_METATYPE(ProjectExplorer::SshParameters::AuthenticationType)
diff --git a/src/plugins/projectexplorer/devicesupport/sshsettings.cpp b/src/plugins/projectexplorer/devicesupport/sshsettings.cpp
new file mode 100644
index 00000000000..d0f93e2fb7e
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/sshsettings.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sshsettings.h"
+
+#include <utils/environment.h>
+#include <utils/hostosinfo.h>
+
+#include <QReadWriteLock>
+#include <QSettings>
+
+using namespace Utils;
+
+namespace ProjectExplorer {
+namespace Internal {
+
+struct SshSettings
+{
+ bool useConnectionSharing = !HostOsInfo::isWindowsHost();
+ int connectionSharingTimeOutInMinutes = 10;
+ FilePath sshFilePath;
+ FilePath sftpFilePath;
+ FilePath askpassFilePath;
+ FilePath keygenFilePath;
+ ProjectExplorer::SshSettings::SearchPathRetriever searchPathRetriever = [] { return FilePaths(); };
+ QReadWriteLock lock;
+};
+
+} // namespace Internal
+
+Q_GLOBAL_STATIC(Internal::SshSettings, sshSettings)
+
+class AccessSettingsGroup
+{
+public:
+ AccessSettingsGroup(QSettings *settings) : m_settings(settings)
+ {
+ settings->beginGroup("SshSettings");
+ }
+ ~AccessSettingsGroup() { m_settings->endGroup(); }
+private:
+ QSettings * const m_settings;
+};
+
+static QString connectionSharingKey() { return QString("UseConnectionSharing"); }
+static QString connectionSharingTimeoutKey() { return QString("ConnectionSharingTimeout"); }
+static QString sshFilePathKey() { return QString("SshFilePath"); }
+static QString sftpFilePathKey() { return QString("SftpFilePath"); }
+static QString askPassFilePathKey() { return QString("AskpassFilePath"); }
+static QString keygenFilePathKey() { return QString("KeygenFilePath"); }
+
+void SshSettings::loadSettings(QSettings *settings)
+{
+ QWriteLocker locker(&sshSettings->lock);
+ AccessSettingsGroup g(settings);
+ QVariant value = settings->value(connectionSharingKey());
+ if (value.isValid() && !HostOsInfo::isWindowsHost())
+ sshSettings->useConnectionSharing = value.toBool();
+ value = settings->value(connectionSharingTimeoutKey());
+ if (value.isValid())
+ sshSettings->connectionSharingTimeOutInMinutes = value.toInt();
+ sshSettings->sshFilePath = FilePath::fromString(settings->value(sshFilePathKey()).toString());
+ sshSettings->sftpFilePath = FilePath::fromString(settings->value(sftpFilePathKey()).toString());
+ sshSettings->askpassFilePath = FilePath::fromString(
+ settings->value(askPassFilePathKey()).toString());
+ sshSettings->keygenFilePath = FilePath::fromString(
+ settings->value(keygenFilePathKey()).toString());
+}
+
+void SshSettings::storeSettings(QSettings *settings)
+{
+ QReadLocker locker(&sshSettings->lock);
+ AccessSettingsGroup g(settings);
+ settings->setValue(connectionSharingKey(), sshSettings->useConnectionSharing);
+ settings->setValue(connectionSharingTimeoutKey(),
+ sshSettings->connectionSharingTimeOutInMinutes);
+ settings->setValue(sshFilePathKey(), sshSettings->sshFilePath.toString());
+ settings->setValue(sftpFilePathKey(), sshSettings->sftpFilePath.toString());
+ settings->setValue(askPassFilePathKey(), sshSettings->askpassFilePath.toString());
+ settings->setValue(keygenFilePathKey(), sshSettings->keygenFilePath.toString());
+}
+
+void SshSettings::setConnectionSharingEnabled(bool share)
+{
+ QWriteLocker locker(&sshSettings->lock);
+ sshSettings->useConnectionSharing = share;
+}
+bool SshSettings::connectionSharingEnabled()
+{
+ QReadLocker locker(&sshSettings->lock);
+ return sshSettings->useConnectionSharing;
+}
+
+void SshSettings::setConnectionSharingTimeout(int timeInMinutes)
+{
+ QWriteLocker locker(&sshSettings->lock);
+ sshSettings->connectionSharingTimeOutInMinutes = timeInMinutes;
+}
+int SshSettings::connectionSharingTimeout()
+{
+ QReadLocker locker(&sshSettings->lock);
+ return sshSettings->connectionSharingTimeOutInMinutes;
+}
+
+// Keep read locker locked while calling this method
+static FilePath filePathValue(const FilePath &value, const QStringList &candidateFileNames)
+{
+ if (!value.isEmpty())
+ return value;
+ const QList<FilePath> additionalSearchPaths = sshSettings->searchPathRetriever();
+ for (const QString &candidate : candidateFileNames) {
+ const FilePath filePath = Environment::systemEnvironment()
+ .searchInPath(candidate, additionalSearchPaths);
+ if (!filePath.isEmpty())
+ return filePath;
+ }
+ return FilePath();
+}
+
+// Keep read locker locked while calling this method
+static FilePath filePathValue(const FilePath &value, const QString &candidateFileName)
+{
+ return filePathValue(value, QStringList(candidateFileName));
+}
+
+void SshSettings::setSshFilePath(const FilePath &ssh)
+{
+ QWriteLocker locker(&sshSettings->lock);
+ sshSettings->sshFilePath = ssh;
+}
+
+FilePath SshSettings::sshFilePath()
+{
+ QReadLocker locker(&sshSettings->lock);
+ return filePathValue(sshSettings->sshFilePath, "ssh");
+}
+
+void SshSettings::setSftpFilePath(const FilePath &sftp)
+{
+ QWriteLocker locker(&sshSettings->lock);
+ sshSettings->sftpFilePath = sftp;
+}
+
+FilePath SshSettings::sftpFilePath()
+{
+ QReadLocker locker(&sshSettings->lock);
+ return filePathValue(sshSettings->sftpFilePath, "sftp");
+}
+
+void SshSettings::setAskpassFilePath(const FilePath &askPass)
+{
+ QWriteLocker locker(&sshSettings->lock);
+ sshSettings->askpassFilePath = askPass;
+}
+
+FilePath SshSettings::askpassFilePath()
+{
+ QReadLocker locker(&sshSettings->lock);
+ FilePath candidate;
+ candidate = sshSettings->askpassFilePath;
+ if (candidate.isEmpty())
+ candidate = FilePath::fromString(Environment::systemEnvironment().value("SSH_ASKPASS"));
+ return filePathValue(candidate, QStringList{"qtc-askpass", "ssh-askpass"});
+}
+
+void SshSettings::setKeygenFilePath(const FilePath &keygen)
+{
+ QWriteLocker locker(&sshSettings->lock);
+ sshSettings->keygenFilePath = keygen;
+}
+
+FilePath SshSettings::keygenFilePath()
+{
+ QReadLocker locker(&sshSettings->lock);
+ return filePathValue(sshSettings->keygenFilePath, "ssh-keygen");
+}
+
+void SshSettings::setExtraSearchPathRetriever(const SearchPathRetriever &pathRetriever)
+{
+ QWriteLocker locker(&sshSettings->lock);
+ sshSettings->searchPathRetriever = pathRetriever;
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/sshsettings.h b/src/plugins/projectexplorer/devicesupport/sshsettings.h
new file mode 100644
index 00000000000..74d246cbb7b
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/sshsettings.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "../projectexplorer_export.h"
+
+#include <utils/fileutils.h>
+
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+QT_END_NAMESPACE
+
+namespace ProjectExplorer {
+
+class PROJECTEXPLORER_EXPORT SshSettings
+{
+public:
+ static void loadSettings(QSettings *settings);
+ static void storeSettings(QSettings *settings);
+
+ static void setConnectionSharingEnabled(bool share);
+ static bool connectionSharingEnabled();
+
+ static void setConnectionSharingTimeout(int timeInMinutes);
+ static int connectionSharingTimeout();
+
+ static void setSshFilePath(const Utils::FilePath &ssh);
+ static Utils::FilePath sshFilePath();
+
+ static void setSftpFilePath(const Utils::FilePath &sftp);
+ static Utils::FilePath sftpFilePath();
+
+ static void setAskpassFilePath(const Utils::FilePath &askPass);
+ static Utils::FilePath askpassFilePath();
+
+ static void setKeygenFilePath(const Utils::FilePath &keygen);
+ static Utils::FilePath keygenFilePath();
+
+ using SearchPathRetriever = std::function<Utils::FilePaths()>;
+ static void setExtraSearchPathRetriever(const SearchPathRetriever &pathRetriever);
+};
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp b/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp
index 288a5f9cb42..451ec0328f2 100644
--- a/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp
@@ -24,10 +24,10 @@
****************************************************************************/
#include "sshsettingspage.h"
+#include "sshsettings.h"
#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorerconstants.h>
-#include <ssh/sshsettings.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>
@@ -36,7 +36,6 @@
#include <QFormLayout>
#include <QSpinBox>
-using namespace QSsh;
using namespace Utils;
namespace ProjectExplorer {
diff --git a/src/plugins/projectexplorer/editorconfiguration.cpp b/src/plugins/projectexplorer/editorconfiguration.cpp
index 286e8cf201d..7102d87c7f6 100644
--- a/src/plugins/projectexplorer/editorconfiguration.cpp
+++ b/src/plugins/projectexplorer/editorconfiguration.cpp
@@ -282,7 +282,8 @@ void EditorConfiguration::setUseGlobalSettings(bool use)
{
d->m_useGlobal = use;
d->m_defaultCodeStyle->setCurrentDelegate(use ? TextEditorSettings::codeStyle() : nullptr);
- foreach (Core::IEditor *editor, Core::DocumentModel::editorsForOpenedDocuments()) {
+ const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForOpenedDocuments();
+ for (Core::IEditor *editor : editors) {
if (auto widget = TextEditorWidget::fromEditor(editor)) {
Project *project = SessionManager::projectForFile(editor->document()->filePath());
if (project && project->editorConfiguration() == this)
@@ -403,16 +404,16 @@ void EditorConfiguration::slotAboutToRemoveProject(Project *project)
if (project->editorConfiguration() != this)
return;
- foreach (BaseTextEditor *editor, d->m_editors)
+ for (BaseTextEditor *editor : qAsConst(d->m_editors))
deconfigureEditor(editor);
}
-TabSettings actualTabSettings(const QString &fileName,
+TabSettings actualTabSettings(const Utils::FilePath &file,
const TextDocument *baseTextdocument)
{
if (baseTextdocument)
return baseTextdocument->tabSettings();
- if (Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(fileName)))
+ if (Project *project = SessionManager::projectForFile(file))
return project->editorConfiguration()->codeStyle()->tabSettings();
return TextEditorSettings::codeStyle()->tabSettings();
}
diff --git a/src/plugins/projectexplorer/editorconfiguration.h b/src/plugins/projectexplorer/editorconfiguration.h
index fb9561d90a4..fef5e68466c 100644
--- a/src/plugins/projectexplorer/editorconfiguration.h
+++ b/src/plugins/projectexplorer/editorconfiguration.h
@@ -49,7 +49,9 @@ class StorageSettings;
class BehaviorSettings;
class ExtraEncodingSettings;
class MarginSettings;
-}
+} // namespace TextEditor
+
+namespace Utils { class FilePath; }
namespace ProjectExplorer {
@@ -118,6 +120,6 @@ private:
// the file belongs to and return the project settings. If the file doesn't belong to any
// project return the global settings.
PROJECTEXPLORER_EXPORT TextEditor::TabSettings actualTabSettings(
- const QString &fileName, const TextEditor::TextDocument *baseTextDocument);
+ const Utils::FilePath &file, const TextEditor::TextDocument *baseTextDocument);
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/editorsettingspropertiespage.cpp b/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
index 2ed5d783763..b985a254836 100644
--- a/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
@@ -27,6 +27,7 @@
#include "editorconfiguration.h"
#include "project.h"
+#include <texteditor/texteditorconstants.h>
#include <texteditor/behaviorsettings.h>
#include <texteditor/extraencodingsettings.h>
#include <texteditor/marginsettings.h>
@@ -38,18 +39,20 @@
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
-EditorSettingsWidget::EditorSettingsWidget(Project *project) : QWidget(), m_project(project)
+EditorSettingsWidget::EditorSettingsWidget(Project *project) : ProjectSettingsWidget(), m_project(project)
{
m_ui.setupUi(this);
+ setGlobalSettingsId(TextEditor::Constants::TEXT_EDITOR_BEHAVIOR_SETTINGS);
const EditorConfiguration *config = m_project->editorConfiguration();
settingsToUi(config);
- globalSettingsActivated(config->useGlobalSettings() ? 0 : 1);
+ globalSettingsActivated(config->useGlobalSettings());
+ setUseGlobalSettings(config->useGlobalSettings());
-
- connect(m_ui.globalSelector, QOverload<int>::of(&QComboBox::activated),
+ connect(this, &ProjectSettingsWidget::useGlobalSettingsChanged,
this, &EditorSettingsWidget::globalSettingsActivated);
+
connect(m_ui.restoreButton, &QAbstractButton::clicked,
this, &EditorSettingsWidget::restoreDefaultValues);
@@ -78,7 +81,6 @@ void EditorSettingsWidget::settingsToUi(const EditorConfiguration *config)
m_ui.useIndenter->setChecked(config->marginSettings().m_useIndenter);
m_ui.wrapColumn->setValue(config->marginSettings().m_marginColumn);
m_ui.behaviorSettingsWidget->setCodeStyle(config->codeStyle());
- m_ui.globalSelector->setCurrentIndex(config->useGlobalSettings() ? 0 : 1);
m_ui.behaviorSettingsWidget->setAssignedCodec(config->textCodec());
m_ui.behaviorSettingsWidget->setAssignedTypingSettings(config->typingSettings());
m_ui.behaviorSettingsWidget->setAssignedStorageSettings(config->storageSettings());
@@ -86,9 +88,8 @@ void EditorSettingsWidget::settingsToUi(const EditorConfiguration *config)
m_ui.behaviorSettingsWidget->setAssignedExtraEncodingSettings(config->extraEncodingSettings());
}
-void EditorSettingsWidget::globalSettingsActivated(int index)
+void EditorSettingsWidget::globalSettingsActivated(bool useGlobal)
{
- const bool useGlobal = !index;
m_ui.displaySettings->setEnabled(!useGlobal);
m_ui.behaviorSettingsWidget->setActive(!useGlobal);
m_ui.restoreButton->setEnabled(!useGlobal);
diff --git a/src/plugins/projectexplorer/editorsettingspropertiespage.h b/src/plugins/projectexplorer/editorsettingspropertiespage.h
index 6f3fdb9670b..a153ce8d44a 100644
--- a/src/plugins/projectexplorer/editorsettingspropertiespage.h
+++ b/src/plugins/projectexplorer/editorsettingspropertiespage.h
@@ -26,6 +26,7 @@
#pragma once
#include "ui_editorsettingspropertiespage.h"
+#include <projectexplorer/projectsettingswidget.h>
namespace ProjectExplorer {
class EditorConfiguration;
@@ -33,14 +34,14 @@ class Project;
namespace Internal {
-class EditorSettingsWidget : public QWidget
+class EditorSettingsWidget : public ProjectSettingsWidget
{
Q_OBJECT
public:
explicit EditorSettingsWidget(Project *project);
private:
- void globalSettingsActivated(int index);
+ void globalSettingsActivated(bool useGlobal);
void restoreDefaultValues();
void settingsToUi(const EditorConfiguration *config);
diff --git a/src/plugins/projectexplorer/editorsettingspropertiespage.ui b/src/plugins/projectexplorer/editorsettingspropertiespage.ui
index 092249ed998..0bcc6bff562 100644
--- a/src/plugins/projectexplorer/editorsettingspropertiespage.ui
+++ b/src/plugins/projectexplorer/editorsettingspropertiespage.ui
@@ -6,56 +6,19 @@
<rect>
<x>0</x>
<y>0</y>
- <width>401</width>
+ <width>601</width>
<height>173</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
- <property name="margin">
- <number>0</number>
- </property>
<item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Editor settings:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="globalSelector">
- <item>
- <property name="text">
- <string>Global</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Custom</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="0" column="2">
<widget class="QPushButton" name="restoreButton">
<property name="text">
<string>Restore Global</string>
</property>
</widget>
</item>
- <item row="0" column="3">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>3</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="0" colspan="4">
+ <item row="1" column="0" colspan="3">
<widget class="QGroupBox" name="displaySettings">
<property name="enabled">
<bool>false</bool>
@@ -107,9 +70,6 @@
</layout>
</widget>
</item>
- <item row="2" column="0" colspan="4">
- <widget class="TextEditor::BehaviorSettingsWidget" name="behaviorSettingsWidget" native="true"/>
- </item>
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
@@ -123,6 +83,22 @@
</property>
</spacer>
</item>
+ <item row="2" column="0" colspan="3">
+ <widget class="TextEditor::BehaviorSettingsWidget" name="behaviorSettingsWidget" native="true"/>
+ </item>
+ <item row="0" column="2">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>3</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
</widget>
<customwidgets>
diff --git a/src/plugins/projectexplorer/environmentaspect.cpp b/src/plugins/projectexplorer/environmentaspect.cpp
index d34b32170fc..7d19fafc7b2 100644
--- a/src/plugins/projectexplorer/environmentaspect.cpp
+++ b/src/plugins/projectexplorer/environmentaspect.cpp
@@ -28,6 +28,7 @@
#include "environmentaspectwidget.h"
#include "target.h"
+#include <utils/algorithm.h>
#include <utils/qtcassert.h>
using namespace Utils;
@@ -46,6 +47,7 @@ EnvironmentAspect::EnvironmentAspect()
setDisplayName(tr("Environment"));
setId("EnvironmentAspect");
setConfigWidgetCreator([this] { return new EnvironmentAspectWidget(this); });
+ addDataExtractor(this, &EnvironmentAspect::environment, &Data::environment);
}
int EnvironmentAspect::baseEnvironmentBase() const
diff --git a/src/plugins/projectexplorer/environmentaspect.h b/src/plugins/projectexplorer/environmentaspect.h
index 79c1d622e85..8e1095738ff 100644
--- a/src/plugins/projectexplorer/environmentaspect.h
+++ b/src/plugins/projectexplorer/environmentaspect.h
@@ -70,6 +70,11 @@ public:
bool isLocal() const { return m_isLocal; }
+ struct Data : BaseAspect::Data
+ {
+ Utils::Environment environment;
+ };
+
signals:
void baseEnvironmentChanged();
void userEnvironmentChangesChanged(const Utils::EnvironmentItems &diff);
diff --git a/src/plugins/projectexplorer/environmentaspectwidget.cpp b/src/plugins/projectexplorer/environmentaspectwidget.cpp
index 280cc5ac9da..be332b289ff 100644
--- a/src/plugins/projectexplorer/environmentaspectwidget.cpp
+++ b/src/plugins/projectexplorer/environmentaspectwidget.cpp
@@ -41,9 +41,8 @@ namespace ProjectExplorer {
// EnvironmentAspectWidget:
// --------------------------------------------------------------------
-EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect, QWidget *additionalWidget) :
- m_aspect(aspect),
- m_additionalWidget(additionalWidget)
+EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect)
+ : m_aspect(aspect)
{
QTC_CHECK(m_aspect);
@@ -52,10 +51,10 @@ EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect, QWid
topLayout->setContentsMargins(0, 0, 0, 25);
auto baseEnvironmentWidget = new QWidget;
- auto baseLayout = new QHBoxLayout(baseEnvironmentWidget);
- baseLayout->setContentsMargins(0, 0, 0, 0);
+ m_baseLayout = new QHBoxLayout(baseEnvironmentWidget);
+ m_baseLayout->setContentsMargins(0, 0, 0, 0);
auto label = new QLabel(tr("Base environment for this run configuration:"), this);
- baseLayout->addWidget(label);
+ m_baseLayout->addWidget(label);
m_baseEnvironmentComboBox = new QComboBox;
for (const QString &displayName : m_aspect->displayNames())
@@ -67,10 +66,8 @@ EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect, QWid
connect(m_baseEnvironmentComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &EnvironmentAspectWidget::baseEnvironmentSelected);
- baseLayout->addWidget(m_baseEnvironmentComboBox);
- baseLayout->addStretch(10);
- if (additionalWidget)
- baseLayout->addWidget(additionalWidget);
+ m_baseLayout->addWidget(m_baseEnvironmentComboBox);
+ m_baseLayout->addStretch(10);
const EnvironmentWidget::Type widgetType = aspect->isLocal()
? EnvironmentWidget::TypeLocal : EnvironmentWidget::TypeRemote;
@@ -92,14 +89,9 @@ EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect, QWid
this, &EnvironmentAspectWidget::environmentChanged);
}
-EnvironmentAspect *EnvironmentAspectWidget::aspect() const
+void EnvironmentAspectWidget::addWidget(QWidget *widget)
{
- return m_aspect;
-}
-
-QWidget *EnvironmentAspectWidget::additionalWidget() const
-{
- return m_additionalWidget;
+ m_baseLayout->addWidget(widget);
}
void EnvironmentAspectWidget::baseEnvironmentSelected(int idx)
diff --git a/src/plugins/projectexplorer/environmentaspectwidget.h b/src/plugins/projectexplorer/environmentaspectwidget.h
index 44acee2f616..9c30c373c7a 100644
--- a/src/plugins/projectexplorer/environmentaspectwidget.h
+++ b/src/plugins/projectexplorer/environmentaspectwidget.h
@@ -37,6 +37,7 @@
QT_BEGIN_NAMESPACE
class QComboBox;
+class QHBoxLayout;
QT_END_NAMESPACE
namespace Utils { class DetailsWidget; }
@@ -50,12 +51,12 @@ class PROJECTEXPLORER_EXPORT EnvironmentAspectWidget : public QWidget
Q_OBJECT
public:
- explicit EnvironmentAspectWidget(EnvironmentAspect *aspect, QWidget *additionalWidget = nullptr);
+ explicit EnvironmentAspectWidget(EnvironmentAspect *aspect);
- virtual EnvironmentAspect *aspect() const;
+protected:
+ EnvironmentAspect *aspect() const { return m_aspect; }
EnvironmentWidget *envWidget() const { return m_environmentWidget; }
-
- QWidget *additionalWidget() const;
+ void addWidget(QWidget *widget);
private:
void baseEnvironmentSelected(int idx);
@@ -66,8 +67,7 @@ private:
EnvironmentAspect *m_aspect;
bool m_ignoreChange = false;
-
- QWidget *m_additionalWidget = nullptr;
+ QHBoxLayout *m_baseLayout = nullptr;
QComboBox *m_baseEnvironmentComboBox = nullptr;
EnvironmentWidget *m_environmentWidget = nullptr;
};
diff --git a/src/plugins/projectexplorer/environmentwidget.cpp b/src/plugins/projectexplorer/environmentwidget.cpp
index 72acba403f5..69b0cd61d63 100644
--- a/src/plugins/projectexplorer/environmentwidget.cpp
+++ b/src/plugins/projectexplorer/environmentwidget.cpp
@@ -395,7 +395,7 @@ void EnvironmentWidget::updateSummaryText()
Utils::EnvironmentItem::sort(&list);
QString text;
- foreach (const Utils::EnvironmentItem &item, list) {
+ for (const Utils::EnvironmentItem &item : qAsConst(list)) {
if (item.name != Utils::EnvironmentModel::tr("<VARIABLE>")) {
if (!d->m_baseEnvironmentText.isEmpty() || !text.isEmpty())
text.append(QLatin1String("<br>"));
diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp
index 36a8d68b889..ded77e903d7 100644
--- a/src/plugins/projectexplorer/extracompiler.cpp
+++ b/src/plugins/projectexplorer/extracompiler.cpp
@@ -426,11 +426,8 @@ void ProcessExtraCompiler::runInThread(
if (process.waitForFinished(200))
break;
- if (futureInterface.isCanceled()) {
- process.kill();
- process.waitForFinished();
+ if (futureInterface.isCanceled())
return;
- }
futureInterface.reportResult(handleProcessFinished(&process));
}
diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp
index 4ec61aeef6b..36076e8e764 100644
--- a/src/plugins/projectexplorer/gccparser.cpp
+++ b/src/plugins/projectexplorer/gccparser.cpp
@@ -126,8 +126,8 @@ void GccParser::createOrAmendTask(
// If a "required from here" line is present, it is almost always the cause of the problem,
// so that's where we should go when the issue is double-clicked.
- if ((originalLine.endsWith("required from here") || originalLine.endsWith("requested here"))
- && !file.isEmpty() && line > 0) {
+ if ((originalLine.endsWith("required from here") || originalLine.endsWith("requested here")
+ || originalLine.endsWith("note: here")) && !file.isEmpty() && line > 0) {
m_requiredFromHereFound = true;
m_currentTask.setFile(file);
m_currentTask.line = line;
@@ -1398,6 +1398,39 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
FilePath::fromUserInput("tst_addresscache.cpp"), 79, 13, {})}
<< QString();
+ QTest::newRow(R"("note: here")")
+ << QString(
+ "In file included from qmlprofilerstatisticsmodel.h:31,\n"
+ " from qmlprofilerstatisticsmodel.cpp:26:\n"
+ "qmlprofilerstatisticsmodel.cpp: In member function ‘virtual QVariant QmlProfiler::QmlProfilerStatisticsModel::data(const QModelIndex&, int) const’:\n"
+ "qtcassert.h:43:34: warning: this statement may fall through [-Wimplicit-fallthrough=]\n"
+ " 43 | #define QTC_ASSERT(cond, action) if (Q_LIKELY(cond)) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0)\n"
+ " | ^~\n"
+ "qtcassert.h:43:34: note: in definition of macro ‘QTC_ASSERT’\n"
+ " 43 | #define QTC_ASSERT(cond, action) if (Q_LIKELY(cond)) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0)\n"
+ " | ^~\n"
+ "qmlprofilerstatisticsmodel.cpp:365:5: note: here\n"
+ " 365 | default:\n"
+ " | ^~~~~~~")
+ << OutputParserTester::STDERR
+ << QString() << QString()
+ << Tasks{compileTask(Task::Warning,
+ "this statement may fall through [-Wimplicit-fallthrough=]\n"
+ "In file included from qmlprofilerstatisticsmodel.h:31,\n"
+ " from qmlprofilerstatisticsmodel.cpp:26:\n"
+ "qmlprofilerstatisticsmodel.cpp: In member function ‘virtual QVariant QmlProfiler::QmlProfilerStatisticsModel::data(const QModelIndex&, int) const’:\n"
+ "qtcassert.h:43:34: warning: this statement may fall through [-Wimplicit-fallthrough=]\n"
+ " 43 | #define QTC_ASSERT(cond, action) if (Q_LIKELY(cond)) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0)\n"
+ " | ^~\n"
+ "qtcassert.h:43:34: note: in definition of macro ‘QTC_ASSERT’\n"
+ " 43 | #define QTC_ASSERT(cond, action) if (Q_LIKELY(cond)) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0)\n"
+ " | ^~\n"
+ "qmlprofilerstatisticsmodel.cpp:365:5: note: here\n"
+ " 365 | default:\n"
+ " | ^~~~~~~",
+ FilePath::fromUserInput("qmlprofilerstatisticsmodel.cpp"), 365, 5, {})}
+ << QString();
+
QTest::newRow("cc1plus")
<< QString(
"cc1plus: error: one or more PCH files were found, but they were invalid\n"
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index 666ef9624eb..b3c827041f9 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -27,6 +27,7 @@
#include "abiwidget.h"
#include "clangparser.h"
+#include "devicesupport/idevice.h"
#include "gccparser.h"
#include "linuxiccparser.h"
#include "projectmacro.h"
@@ -125,18 +126,18 @@ using namespace Internal;
// Helpers:
// --------------------------------------------------------------------------
-static const char compilerPlatformCodeGenFlagsKeyC[] = "ProjectExplorer.GccToolChain.PlatformCodeGenFlags";
-static const char compilerPlatformLinkerFlagsKeyC[] = "ProjectExplorer.GccToolChain.PlatformLinkerFlags";
-static const char targetAbiKeyC[] = "ProjectExplorer.GccToolChain.TargetAbi";
-static const char originalTargetTripleKeyC[] = "ProjectExplorer.GccToolChain.OriginalTargetTriple";
-static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis";
-static const char parentToolChainIdKeyC[] = "ProjectExplorer.ClangToolChain.ParentToolChainId";
-static const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+|clang(?:\\+\\+)?)(?:-([\\d.]+))?$";
+const char compilerPlatformCodeGenFlagsKeyC[] = "ProjectExplorer.GccToolChain.PlatformCodeGenFlags";
+const char compilerPlatformLinkerFlagsKeyC[] = "ProjectExplorer.GccToolChain.PlatformLinkerFlags";
+const char targetAbiKeyC[] = "ProjectExplorer.GccToolChain.TargetAbi";
+const char originalTargetTripleKeyC[] = "ProjectExplorer.GccToolChain.OriginalTargetTriple";
+const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis";
+const char parentToolChainIdKeyC[] = "ProjectExplorer.ClangToolChain.ParentToolChainId";
+const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+|clang(?:\\+\\+)?)(?:-([\\d.]+))?$";
-static QByteArray runGcc(const FilePath &gcc, const QStringList &arguments, const Environment &env)
+static QString runGcc(const FilePath &gcc, const QStringList &arguments, const Environment &env)
{
if (!gcc.isExecutableFile())
- return QByteArray();
+ return {};
QtcProcess cpp;
Environment environment(env);
@@ -146,14 +147,14 @@ static QByteArray runGcc(const FilePath &gcc, const QStringList &arguments, cons
cpp.setTimeoutS(10);
cpp.setCommand({gcc, arguments});
cpp.runBlocking();
- if (cpp.result() != QtcProcess::FinishedWithSuccess || cpp.exitCode() != 0) {
+ if (cpp.result() != ProcessResult::FinishedWithSuccess || cpp.exitCode() != 0) {
Core::MessageManager::writeFlashing({"Compiler feature detection failure!",
cpp.exitMessage(),
- QString::fromUtf8(cpp.allRawOutput())});
- return QByteArray();
+ cpp.allOutput()});
+ return {};
}
- return cpp.allOutput().toUtf8();
+ return cpp.allOutput();
}
static ProjectExplorer::Macros gccPredefinedMacros(const FilePath &gcc,
@@ -163,7 +164,7 @@ static ProjectExplorer::Macros gccPredefinedMacros(const FilePath &gcc,
QStringList arguments = args;
arguments << "-";
- ProjectExplorer::Macros predefinedMacros = Macro::toMacros(runGcc(gcc, arguments, env));
+ ProjectExplorer::Macros predefinedMacros = Macro::toMacros(runGcc(gcc, arguments, env).toUtf8());
// Sanity check in case we get an error message instead of real output:
QTC_CHECK(predefinedMacros.isEmpty()
|| predefinedMacros.front().type == ProjectExplorer::MacroType::Define);
@@ -188,7 +189,7 @@ HeaderPaths GccToolChain::gccHeaderPaths(const FilePath &gcc,
{
HeaderPaths builtInHeaderPaths;
QByteArray line;
- QByteArray data = runGcc(gcc, arguments, env);
+ QByteArray data = runGcc(gcc, arguments, env).toUtf8();
QBuffer cpp(&data);
cpp.open(QIODevice::ReadOnly);
while (cpp.canReadLine()) {
@@ -276,7 +277,7 @@ static GccToolChain::DetectedAbisResult guessGccAbi(const FilePath &path,
QStringList arguments = extraArgs;
arguments << "-dumpmachine";
- QString machine = QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed();
+ QString machine = runGcc(path, arguments, env).trimmed().section('\n', 0, 0, QString::SectionSkipEmpty);
if (machine.isEmpty()) {
// ICC does not implement the -dumpmachine option on macOS.
if (HostOsInfo::isMacHost() && (path.fileName() == "icc" || path.fileName() == "icpc"))
@@ -292,7 +293,7 @@ static QString gccVersion(const FilePath &path,
{
QStringList arguments = extraArgs;
arguments << "-dumpversion";
- return QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed();
+ return runGcc(path, arguments, env).trimmed();
}
static FilePath gccInstallDir(const FilePath &compiler,
@@ -301,7 +302,7 @@ static FilePath gccInstallDir(const FilePath &compiler,
{
QStringList arguments = extraArgs;
arguments << "-print-search-dirs";
- QString output = QString::fromLocal8Bit(runGcc(compiler, arguments, env)).trimmed();
+ QString output = runGcc(compiler, arguments, env).trimmed();
// Expected output looks like this:
// install: /usr/lib/gcc/x86_64-linux-gnu/7/
// ...
@@ -441,23 +442,21 @@ static QStringList filteredFlags(const QStringList &allFlags, bool considerSysro
} else if (a == "-arch") {
if (++i < allFlags.length() && !filtered.contains(a))
filtered << a << allFlags.at(i);
+ } else if (a == "-Xclang") {
+ filtered << a;
} else if ((considerSysroot && (a == "--sysroot" || a == "-isysroot"))
|| a == "-D" || a == "-U"
|| a == "-gcc-toolchain" || a == "-target" || a == "-mllvm" || a == "-isystem") {
if (++i < allFlags.length())
filtered << a << allFlags.at(i);
- } else if (a.startsWith("-m") || a == "-Os" || a == "-O0" || a == "-O1" || a == "-O2"
- || a == "-O3" || a == "-ffinite-math-only" || a == "-fshort-double"
- || a == "-fshort-wchar" || a == "-fsignaling-nans" || a == "-fno-inline"
- || a == "-fno-exceptions" || a == "-fstack-protector"
- || a == "-fstack-protector-all" || a == "-fsanitize=address"
- || a == "-fno-rtti" || a.startsWith("-std=") || a.startsWith("-stdlib=")
+ } else if (a.startsWith("-m") || a.startsWith("-f") || a.startsWith("-O")
+ || a.startsWith("-std=") || a.startsWith("-stdlib=")
|| a.startsWith("-specs=") || a == "-ansi" || a == "-undef"
- || a.startsWith("-D") || a.startsWith("-U") || a == "-fopenmp"
- || a == "-Wno-deprecated" || a == "-fPIC" || a == "-fpic" || a == "-fPIE"
- || a == "-fpie" || a.startsWith("-stdlib=") || a.startsWith("-B")
+ || a.startsWith("-D") || a.startsWith("-U")
+ || a.startsWith("-stdlib=") || a.startsWith("-B")
|| a.startsWith("--target=")
|| (a.startsWith("-isystem") && a.length() > 8)
+ || a == "-Wno-deprecated"
|| a == "-nostdinc" || a == "-nostdinc++") {
filtered << a;
}
@@ -525,7 +524,7 @@ Utils::LanguageExtensions GccToolChain::languageExtensions(const QStringList &cx
LanguageExtensions extensions = defaultLanguageExtensions();
const QStringList allCxxflags = m_platformCodeGenFlags + cxxflags; // add only cxxflags is empty?
- foreach (const QString &flag, allCxxflags) {
+ for (const QString &flag : allCxxflags) {
if (flag.startsWith("-std=")) {
const QByteArray std = flag.mid(5).toLatin1();
if (std.startsWith("gnu"))
@@ -552,7 +551,8 @@ WarningFlags GccToolChain::warningFlags(const QStringList &cflags) const
| WarningFlags::SignedComparison | WarningFlags::UninitializedVars);
WarningFlags groupWextra(WarningFlags::Extra | WarningFlags::IgnoredQualifiers | WarningFlags::UnusedParams);
- foreach (const QString &flag, cflags) {
+ for (int end = cflags.size(), i = 0; i != end; ++i) {
+ const QString &flag = cflags[i];
if (flag == "--all-warnings")
flags |= groupWall;
else if (flag == "--extra-warnings")
@@ -592,15 +592,15 @@ QStringList GccToolChain::includedFiles(const QStringList &flags, const QString
}
QStringList GccToolChain::gccPrepareArguments(const QStringList &flags,
- const QString &sysRoot,
+ const FilePath &sysRoot,
const QStringList &platformCodeGenFlags,
- Utils::Id languageId,
+ Id languageId,
OptionsReinterpreter reinterpretOptions)
{
QStringList arguments;
const bool hasKitSysroot = !sysRoot.isEmpty();
if (hasKitSysroot)
- arguments.append(QString::fromLatin1("--sysroot=%1").arg(sysRoot));
+ arguments.append(QString("--sysroot=%1").arg(sysRoot.nativePath()));
QStringList allFlags;
allFlags << platformCodeGenFlags << flags;
@@ -625,7 +625,7 @@ HeaderPaths GccToolChain::builtInHeaderPaths(const Utils::Environment &env,
Utils::Id languageId,
ExtraHeaderPathsFunction extraHeaderPathsFunction,
const QStringList &flags,
- const QString &sysRoot,
+ const Utils::FilePath &sysRoot,
const QString &originalTargetTriple)
{
QStringList arguments = gccPrepareArguments(flags,
@@ -673,7 +673,7 @@ ToolChain::BuiltInHeaderPathsRunner GccToolChain::createBuiltInHeaderPathsRunner
headerCache = headerPathsCache(),
languageId = language(),
extraHeaderPathsFunction = m_extraHeaderPathsFunction](const QStringList &flags,
- const QString &sysRoot,
+ const FilePath &sysRoot,
const QString &) {
return builtInHeaderPaths(fullEnv,
compilerCommand,
@@ -1207,10 +1207,16 @@ Toolchains GccToolChainFactory::autoDetectToolchains(
|| compilerPath.toString().contains("ccache")) {
existingTcMatches = existingCommand == compilerPath;
} else {
- existingTcMatches = Environment::systemEnvironment().isSameExecutable(
- existingCommand.toString(), compilerPath.toString())
- || (HostOsInfo::isWindowsHost() && existingCommand.toFileInfo().size()
- == compilerPath.toFileInfo().size());
+ existingTcMatches = Environment::systemEnvironment()
+ .isSameExecutable(existingCommand.toString(),
+ compilerPath.toString());
+ if (!existingTcMatches
+ && HostOsInfo::isWindowsHost()
+ && !existingCommand.needsDevice()
+ && !compilerPath.needsDevice()) {
+ existingTcMatches = existingCommand.toFileInfo().size()
+ == compilerPath.toFileInfo().size();
+ }
}
if (existingTcMatches) {
if (existingTc->typeId() == requiredTypeId && (!checker || checker(existingTc))
@@ -1289,8 +1295,8 @@ public:
layout->setContentsMargins(0, 0, 0, 0);
m_tripleLineEdit.setEnabled(false);
m_overrideCheckBox.setText(tr("Override for code model"));
- m_overrideCheckBox.setToolTip(tr("Check this button in the rare case that the code model\n"
- "fails because clang does not understand the target architecture."));
+ m_overrideCheckBox.setToolTip(tr("Enable in the rare case that the code model\n"
+ "fails because Clang does not understand the target architecture."));
layout->addWidget(&m_tripleLineEdit, 1);
layout->addWidget(&m_overrideCheckBox);
layout->addStretch(1);
@@ -1439,8 +1445,7 @@ void GccToolChainConfigWidget::handleCompilerCommandChange()
Abis abiList;
if (!path.isEmpty()) {
- QFileInfo fi(path.toFileInfo());
- haveCompiler = fi.isExecutable() && fi.isFile();
+ haveCompiler = path.isExecutableFile();
}
if (haveCompiler) {
Environment env = path.deviceEnvironment();
@@ -1572,6 +1577,27 @@ ClangToolChain::~ClangToolChain()
QObject::disconnect(m_mingwToolchainAddedConnection);
}
+bool ClangToolChain::matchesCompilerCommand(const Utils::FilePath &command,
+ const Utils::Environment &env) const
+{
+ if (!m_resolvedCompilerCommand) {
+ m_resolvedCompilerCommand = FilePath();
+ if (HostOsInfo::isMacHost()
+ && compilerCommand().parentDir() == FilePath::fromString("/usr/bin")) {
+ std::unique_ptr<QtcProcess> xcrun(new QtcProcess);
+ xcrun->setCommand({"/usr/bin/xcrun", {"-f", compilerCommand().fileName()}});
+ xcrun->runBlocking();
+ const FilePath output = FilePath::fromString(xcrun->cleanedStdOut().trimmed());
+ if (output.isExecutableFile() && output != compilerCommand())
+ m_resolvedCompilerCommand = output;
+ }
+ }
+ if (!m_resolvedCompilerCommand->isEmpty()
+ && env.isSameExecutable(m_resolvedCompilerCommand->toString(), command.toString()))
+ return true;
+ return GccToolChain::matchesCompilerCommand(command, env);
+}
+
static FilePath mingwAwareMakeCommand(const Environment &environment)
{
const QStringList makes
@@ -1606,7 +1632,8 @@ LanguageExtensions ClangToolChain::languageExtensions(const QStringList &cxxflag
WarningFlags ClangToolChain::warningFlags(const QStringList &cflags) const
{
WarningFlags flags = GccToolChain::warningFlags(cflags);
- foreach (const QString &flag, cflags) {
+ for (int end = cflags.size(), i = 0; i != end; ++i) {
+ const QString &flag = cflags[i];
if (flag == "-Wdocumentation")
flags |= WarningFlags::Documentation;
if (flag == "-Wno-documentation")
@@ -1680,7 +1707,7 @@ ToolChain::BuiltInHeaderPathsRunner ClangToolChain::createBuiltInHeaderPathsRunn
headerCache = headerPathsCache(),
languageId = language(),
extraHeaderPathsFunction = m_extraHeaderPathsFunction](const QStringList &flags,
- const QString &sysRoot,
+ const FilePath &sysRoot,
const QString &target) {
return builtInHeaderPaths(fullEnv,
compilerCommand,
diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h
index 7bd83d0a1b2..980ea3fb8b7 100644
--- a/src/plugins/projectexplorer/gcctoolchain.h
+++ b/src/plugins/projectexplorer/gcctoolchain.h
@@ -33,6 +33,7 @@
#include "headerpath.h"
#include <utils/fileutils.h>
+#include <utils/optional.h>
#include <functional>
#include <memory>
@@ -150,7 +151,7 @@ protected:
Utils::Id languageId,
ExtraHeaderPathsFunction extraHeaderPathsFunction,
const QStringList &flags,
- const QString &sysRoot,
+ const Utils::FilePath &sysRoot,
const QString &originalTargetTriple);
static HeaderPaths gccHeaderPaths(const Utils::FilePath &gcc,
@@ -174,7 +175,7 @@ protected:
private:
void updateSupportedAbis() const;
static QStringList gccPrepareArguments(const QStringList &flags,
- const QString &sysRoot,
+ const Utils::FilePath &sysRoot,
const QStringList &platformCodeGenFlags,
Utils::Id languageId,
OptionsReinterpreter reinterpretOptions);
@@ -211,6 +212,10 @@ public:
explicit ClangToolChain(Utils::Id typeId);
~ClangToolChain() override;
+ bool matchesCompilerCommand(
+ const Utils::FilePath &command,
+ const Utils::Environment &env = Utils::Environment::systemEnvironment()) const override;
+
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
@@ -237,6 +242,9 @@ protected:
void syncAutodetectedWithParentToolchains();
private:
+ // "resolved" on macOS from /usr/bin/clang(++) etc to <DeveloperDir>/usr/bin/clang(++)
+ // which is used for comparison with matchesCompileCommand
+ mutable Utils::optional<Utils::FilePath> m_resolvedCompilerCommand;
QByteArray m_parentToolChainId;
QMetaObject::Connection m_mingwToolchainAddedConnection;
QMetaObject::Connection m_thisToolchainRemovedConnection;
diff --git a/src/plugins/projectexplorer/gnumakeparser.cpp b/src/plugins/projectexplorer/gnumakeparser.cpp
index 1bf71ee7602..74c5dd6ef52 100644
--- a/src/plugins/projectexplorer/gnumakeparser.cpp
+++ b/src/plugins/projectexplorer/gnumakeparser.cpp
@@ -370,7 +370,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing()
FilePaths searchDirs = childParser->searchDirectories();
// add extra directories:
- foreach (const QString &dir, extraSearchDirs)
+ for (const QString &dir : qAsConst(extraSearchDirs))
testbench.addSearchDir(FilePath::fromString(dir));
testbench.testParsing(input, inputChannel,
@@ -379,13 +379,13 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing()
// make sure we still have all the original dirs
FilePaths newSearchDirs = tester->directories;
- foreach (const FilePath &dir, searchDirs) {
+ for (const FilePath &dir : qAsConst(searchDirs)) {
QVERIFY(newSearchDirs.contains(dir));
newSearchDirs.removeOne(dir);
}
// make sure we have all additional dirs:
- foreach (const QString &dir, additionalSearchDirs) {
+ for (const QString &dir : qAsConst(additionalSearchDirs)) {
const FilePath fp = FilePath::fromString(dir);
QVERIFY(newSearchDirs.contains(fp));
newSearchDirs.removeOne(fp);
diff --git a/src/plugins/projectexplorer/journaldwatcher.cpp b/src/plugins/projectexplorer/journaldwatcher.cpp
index 5e5acddc224..e823c64cb80 100644
--- a/src/plugins/projectexplorer/journaldwatcher.cpp
+++ b/src/plugins/projectexplorer/journaldwatcher.cpp
@@ -212,7 +212,7 @@ void JournaldWatcher::handleEntry()
if (logEntry.isEmpty())
break;
- foreach (const JournaldWatcherPrivate::SubscriberInformation &info, d->m_subscriptions)
+ for (const JournaldWatcherPrivate::SubscriberInformation &info: qAsConst(d->m_subscriptions))
info.subscription(logEntry);
}
}
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
index d226f6fc894..56c3617ce00 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
@@ -345,6 +345,13 @@ QVariant JsonFieldPage::value(const QString &key)
return w->value(key);
}
+JsonFieldPage::Field *JsonFieldPage::jsonField(const QString &name)
+{
+ return Utils::findOr(m_fields, nullptr, [&name](Field *f) {
+ return f->name() == name;
+ });
+}
+
QWidget *JsonFieldPage::Field::widget() const
{
return d->m_widget;
@@ -1265,7 +1272,11 @@ void ComboBoxField::initializeData(MacroExpander *expander)
ListField::initializeData(expander);
// refresh also the current text of the combobox
auto w = qobject_cast<QComboBox *>(widget());
- w->setCurrentIndex(selectionModel()->currentIndex().row());
+ const int row = selectionModel()->currentIndex().row();
+ if (row < w->count() && row > 0)
+ w->setCurrentIndex(row);
+ else
+ w->setCurrentIndex(0);
}
QVariant ComboBoxField::toSettings() const
@@ -1379,8 +1390,8 @@ void JsonFieldPage::registerFieldFactory(const QString &id, const JsonFieldPage:
bool JsonFieldPage::setup(const QVariant &data)
{
QString errorMessage;
- QList<QVariant> fieldList = JsonWizardFactory::objectOrList(data, &errorMessage);
- foreach (const QVariant &field, fieldList) {
+ const QList<QVariant> fieldList = JsonWizardFactory::objectOrList(data, &errorMessage);
+ for (const QVariant &field : fieldList) {
Field *f = JsonFieldPage::Field::parse(field, &errorMessage);
if (!f)
continue;
@@ -1403,7 +1414,7 @@ bool JsonFieldPage::isComplete() const
bool result = true;
bool hasErrorMessage = false;
- foreach (Field *f, m_fields) {
+ for (Field *f : qAsConst(m_fields)) {
f->adjustState(m_expander);
if (!f->validate(m_expander, &message)) {
if (!message.isEmpty()) {
@@ -1423,13 +1434,13 @@ bool JsonFieldPage::isComplete() const
void JsonFieldPage::initializePage()
{
- foreach (Field *f, m_fields)
+ for (Field *f : qAsConst(m_fields))
f->initialize(m_expander);
}
void JsonFieldPage::cleanupPage()
{
- foreach (Field *f, m_fields)
+ for (Field *f : qAsConst(m_fields))
f->cleanup(m_expander);
}
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.h b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.h
index 8ee07366879..27362ca9842 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.h
+++ b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.h
@@ -29,7 +29,6 @@
#include <utils/pathchooser.h>
#include <utils/wizardpage.h>
-#include <utils/algorithm.h>
#include <QRegularExpression>
#include <QVariant>
@@ -143,11 +142,7 @@ public:
QVariant value(const QString &key);
public:
- Field *jsonField(const QString &name) {
- return Utils::findOr(m_fields, nullptr, [&name](Field *f) {
- return f->name() == name;
- });
- }
+ Field *jsonField(const QString &name);
private:
static QHash<QString, FieldFactory> m_factories;
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage_p.h b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage_p.h
index db8a1b06fb7..17904cfd1b4 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage_p.h
+++ b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage_p.h
@@ -27,6 +27,7 @@
#include "jsonfieldpage.h"
+#include <utils/fileutils.h>
#include <utils/pathchooser.h>
#include <QWidget>
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp
index 75c2daf7164..5ddb908baef 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp
@@ -35,7 +35,7 @@
#include <utils/algorithm.h>
#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
using namespace Core;
@@ -112,10 +112,8 @@ void JsonKitsPage::setupProjectFiles(const JsonWizard::GeneratorFiles &files)
{
for (const JsonWizard::GeneratorFile &f : files) {
if (f.file.attributes() & GeneratedFile::OpenProjectAttribute) {
- const QFileInfo fi(f.file.path());
- const QString path = fi.absoluteFilePath();
- Project *project = ProjectManager::openProject(Utils::mimeTypeForFile(fi),
- Utils::FilePath::fromString(path));
+ Project *project = ProjectManager::openProject(Utils::mimeTypeForFile(f.file.filePath()),
+ f.file.filePath().absoluteFilePath());
if (project) {
if (setupProject(project))
project->saveSettings();
@@ -132,7 +130,7 @@ QSet<Id> JsonKitsPage::evaluate(const QVector<JsonKitsPage::ConditionalFeature>
return Id::fromStringList(defaultSet.toStringList());
QSet<Id> features;
- foreach (const ConditionalFeature &f, list) {
+ for (const ConditionalFeature &f : list) {
if (JsonWizard::boolFromVariant(f.condition, wiz->expander()))
features.insert(Id::fromString(wiz->expander()->expand(f.feature)));
}
@@ -154,7 +152,8 @@ QVector<JsonKitsPage::ConditionalFeature> JsonKitsPage::parseFeatures(const QVar
return result;
}
- foreach (const QVariant &element, data.toList()) {
+ const QList<QVariant> elements = data.toList();
+ for (const QVariant &element : elements) {
if (element.type() == QVariant::String) {
result.append({ element.toString(), QVariant(true) });
} else if (element.type() == QVariant::Map) {
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp
index db390130ff7..49926602131 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp
@@ -195,7 +195,7 @@ JsonWizard::GeneratorFiles JsonWizard::generateFileList()
if (m_files.isEmpty() && errorMessage.isEmpty()) {
emit preGenerateFiles();
- foreach (JsonWizardGenerator *gen, m_generators) {
+ for (JsonWizardGenerator *gen : qAsConst(m_generators)) {
Core::GeneratedFiles tmp = gen->fileList(&m_expander, stringValue(QStringLiteral("WizardDir")),
targetPath, &errorMessage);
if (!errorMessage.isEmpty())
@@ -261,7 +261,7 @@ QList<JsonWizard::OptionDefinition> JsonWizard::parseOptions(const QVariant &v,
QList<JsonWizard::OptionDefinition> result;
if (!v.isNull()) {
const QVariantList optList = JsonWizardFactory::objectOrList(v, errorMessage);
- foreach (const QVariant &o, optList) {
+ for (const QVariant &o : optList) {
QVariantMap optionObject = o.toMap();
JsonWizard::OptionDefinition odef;
odef.m_key = optionObject.value(QLatin1String("key")).toString();
@@ -331,7 +331,8 @@ void JsonWizard::removeAttributeFromAllFiles(Core::GeneratedFile::Attribute a)
QHash<QString, QVariant> JsonWizard::variables() const
{
QHash<QString, QVariant> result = Wizard::variables();
- foreach (const QByteArray &p, dynamicPropertyNames()) {
+ const QList<QByteArray> properties = dynamicPropertyNames();
+ for (const QByteArray &p : properties) {
QString key = QString::fromUtf8(p);
result.insert(key, value(key));
}
@@ -442,7 +443,7 @@ void JsonWizard::openFiles(const JsonWizard::GeneratorFiles &files)
{
QString errorMessage;
bool openedSomething = false;
- foreach (const JsonWizard::GeneratorFile &f, files) {
+ for (const JsonWizard::GeneratorFile &f : files) {
const Core::GeneratedFile &file = f.file;
if (!QFileInfo::exists(file.path())) {
errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizard",
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
index 705e51aa66d..8a87218b7b7 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
@@ -40,6 +40,7 @@
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
+#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/wizard.h>
@@ -112,7 +113,8 @@ static QString supportedTypeIds(const QList<T *> &factories)
{
QStringList tmp;
for (const T *f : factories) {
- foreach (Id i, f->supportedIds())
+ const QList<Id> ids = f->supportedIds();
+ for (const Id i : ids)
tmp.append(i.toString());
}
return tmp.join(QLatin1String("', '"));
@@ -166,7 +168,8 @@ QVariantMap JsonWizardFactory::loadDefaultValues(const QString &fileName)
}
QList <Core::IWizardFactory *> result;
- foreach (const Utils::FilePath &path, searchPaths()) {
+ const Utils::FilePaths paths = searchPaths();
+ for (const Utils::FilePath &path : paths) {
if (path.isEmpty())
continue;
@@ -247,18 +250,8 @@ QVariant JsonWizardFactory::mergeDataValueMaps(const QVariant &valueMap, const Q
{
QVariantMap retVal;
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- const QVariantMap &map = defaultValueMap.toMap();
- for (auto it = map.begin(), end = map.end(); it != end; ++it)
- retVal.insert(it.key(), it.value());
-
- const QVariantMap &map2 = valueMap.toMap();
- for (auto it = map2.begin(), end = map2.end(); it != end; ++it)
- retVal.insert(it.key(), it.value());
-#else
retVal.insert(defaultValueMap.toMap());
retVal.insert(valueMap.toMap());
-#endif
return retVal;
}
@@ -412,7 +405,8 @@ QList<Core::IWizardFactory *> JsonWizardFactory::createWizardFactories()
const QString wizardFileName = QLatin1String(WIZARD_FILE);
QList <Core::IWizardFactory *> result;
- foreach (const FilePath &path, searchPaths()) {
+ const Utils::FilePaths paths = searchPaths();
+ for (const Utils::FilePath &path : paths) {
if (path.isEmpty())
continue;
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp
index 982356adc7a..1f5e16a0f77 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp
@@ -49,11 +49,11 @@ bool JsonWizardFileGenerator::setup(const QVariant &data, QString *errorMessage)
{
QTC_ASSERT(errorMessage && errorMessage->isEmpty(), return false);
- QVariantList list = JsonWizardFactory::objectOrList(data, errorMessage);
+ const QVariantList list = JsonWizardFactory::objectOrList(data, errorMessage);
if (list.isEmpty())
return false;
- foreach (const QVariant &d, list) {
+ for (const QVariant &d : list) {
if (d.type() != QVariant::Map) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
"Files data list entry is not an object.");
@@ -117,7 +117,7 @@ Core::GeneratedFile JsonWizardFileGenerator::generateFile(const File &file,
// evaluate file options once:
QHash<QString, QString> options;
- foreach (const JsonWizard::OptionDefinition &od, file.options) {
+ for (const JsonWizard::OptionDefinition &od : qAsConst(file.options)) {
if (od.condition(*expander))
options.insert(od.key(), od.value(*expander));
}
@@ -195,7 +195,7 @@ Core::GeneratedFiles JsonWizardFileGenerator::fileList(Utils::MacroExpander *exp
const QSet<QString> knownFiles = Utils::transform<QSet>(fileList, &File::target);
- foreach (const File &dir, dirList) {
+ for (const File &dir : qAsConst(dirList)) {
QDir sourceDir(dir.source);
QDirIterator it(dir.source, QDir::NoDotAndDotDot | QDir::Files| QDir::Hidden,
QDirIterator::Subdirectories);
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp
index a49b01fd48a..624583f6dcb 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp
@@ -42,9 +42,9 @@
#include <texteditor/textindenter.h>
#include <utils/algorithm.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/stringutils.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
#include <QCoreApplication>
#include <QDebug>
@@ -86,7 +86,7 @@ bool JsonWizardGenerator::formatFile(const JsonWizard *wizard, GeneratedFile *fi
if (file->isBinary() || file->contents().isEmpty())
return true; // nothing to do
- Id languageId = TextEditorSettings::languageId(Utils::mimeTypeForFile(file->path()).name());
+ Id languageId = TextEditorSettings::languageId(Utils::mimeTypeForFile(file->filePath()).name());
if (!languageId.isValid())
return true; // don't modify files like *.ui, *.pro
@@ -99,7 +99,7 @@ bool JsonWizardGenerator::formatFile(const JsonWizard *wizard, GeneratedFile *fi
Indenter *indenter = nullptr;
if (factory) {
indenter = factory->createIndenter(&doc);
- indenter->setFileName(Utils::FilePath::fromString(file->path()));
+ indenter->setFileName(file->filePath());
}
if (!indenter)
indenter = new TextIndenter(&doc);
@@ -161,7 +161,7 @@ JsonWizardGenerator::OverwriteResult JsonWizardGenerator::promptForOverwrite(Jso
QStringList existingFiles;
bool oddStuffFound = false;
- foreach (const JsonWizard::GeneratorFile &f, *files) {
+ for (const JsonWizard::GeneratorFile &f : qAsConst(*files)) {
const QFileInfo fi(f.file.path());
if (fi.exists()
&& !(f.file.attributes() & GeneratedFile::ForceOverwrite)
@@ -176,7 +176,7 @@ JsonWizardGenerator::OverwriteResult JsonWizardGenerator::promptForOverwrite(Jso
// Format a file list message as ( "<file1> [readonly], <file2> [folder]").
const QString commonExistingPath = Utils::commonPath(existingFiles);
QString fileNamesMsgPart;
- foreach (const QString &fileName, existingFiles) {
+ for (const QString &fileName : qAsConst(existingFiles)) {
const QFileInfo fi(fileName);
if (fi.exists()) {
if (!fileNamesMsgPart.isEmpty())
@@ -210,7 +210,7 @@ JsonWizardGenerator::OverwriteResult JsonWizardGenerator::promptForOverwrite(Jso
// Scripts cannot handle overwrite
overwriteDialog.setFiles(existingFiles);
- foreach (const JsonWizard::GeneratorFile &file, *files)
+ for (const JsonWizard::GeneratorFile &file : qAsConst(*files))
if (!file.generator->canKeepExistingFiles())
overwriteDialog.setFileEnabled(file.file.path(), false);
if (overwriteDialog.exec() != QDialog::Accepted)
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp
index c0349814e0a..3a0c30ab892 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp
@@ -80,7 +80,7 @@ bool FieldPageFactory::validateData(Utils::Id typeId, const QVariant &data, QStr
{
QTC_ASSERT(canCreate(typeId), return false);
- QList<QVariant> list = JsonWizardFactory::objectOrList(data, errorMessage);
+ const QList<QVariant> list = JsonWizardFactory::objectOrList(data, errorMessage);
if (list.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizard",
"When parsing fields of page \"%1\": %2")
@@ -88,7 +88,7 @@ bool FieldPageFactory::validateData(Utils::Id typeId, const QVariant &data, QStr
return false;
}
- foreach (const QVariant &v, list) {
+ for (const QVariant &v : list) {
JsonFieldPage::Field *field = JsonFieldPage::Field::parse(v, errorMessage);
if (!field)
return false;
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp
index 51ffd37b91c..528110e8799 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp
@@ -25,18 +25,15 @@
#include "jsonwizardscannergenerator.h"
-#include "../projectexplorer.h"
#include "../projectmanager.h"
-#include "jsonwizard.h"
-#include "jsonwizardfactory.h"
#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
-#include <utils/fileutils.h>
-#include <utils/qtcassert.h>
+#include <utils/filepath.h>
#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
+#include <utils/qtcassert.h>
#include <QCoreApplication>
#include <QDir>
@@ -61,8 +58,8 @@ bool JsonWizardScannerGenerator::setup(const QVariant &data, QString *errorMessa
QVariantMap gen = data.toMap();
m_binaryPattern = gen.value(QLatin1String("binaryPattern")).toString();
- QStringList patterns = gen.value(QLatin1String("subdirectoryPatterns")).toStringList();
- foreach (const QString pattern, patterns) {
+ const QStringList patterns = gen.value(QLatin1String("subdirectoryPatterns")).toStringList();
+ for (const QString &pattern : patterns) {
QRegularExpression regexp(pattern);
if (!regexp.isValid()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::Internal::JsonWizard",
@@ -104,7 +101,8 @@ Core::GeneratedFiles JsonWizardScannerGenerator::fileList(Utils::MacroExpander *
for (auto it = result.begin(); it != result.end(); ++it) {
const QString relPath = project.relativeFilePath(it->path());
it->setBinary(binaryPattern.match(relPath).hasMatch());
- bool found = ProjectManager::canOpenProjectForMimeType(Utils::mimeTypeForFile(relPath));
+ bool found = ProjectManager::canOpenProjectForMimeType(Utils::mimeTypeForFile(
+ Utils::FilePath::fromString(relPath)));
if (found) {
it->setAttributes(it->attributes() | Core::GeneratedFile::OpenProjectAttribute);
minDepth = std::min(minDepth, getDepth(it->path()));
@@ -126,7 +124,7 @@ Core::GeneratedFiles JsonWizardScannerGenerator::fileList(Utils::MacroExpander *
bool JsonWizardScannerGenerator::matchesSubdirectoryPattern(const QString &path)
{
- foreach (const QRegularExpression &regexp, m_subDirectoryExpressions) {
+ for (const QRegularExpression &regexp : qAsConst(m_subDirectoryExpressions)) {
if (regexp.match(path).hasMatch())
return true;
}
@@ -141,9 +139,9 @@ Core::GeneratedFiles JsonWizardScannerGenerator::scan(const QString &dir, const
if (!directory.exists())
return result;
- QFileInfoList entries = directory.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot,
- QDir::DirsLast | QDir::Name);
- foreach (const QFileInfo &fi, entries) {
+ const QFileInfoList entries = directory.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot,
+ QDir::DirsLast | QDir::Name);
+ for (const QFileInfo &fi : entries) {
const QString relativePath = base.relativeFilePath(fi.absoluteFilePath());
if (fi.isDir() && matchesSubdirectoryPattern(relativePath)) {
result += scan(fi.absoluteFilePath(), base);
diff --git a/src/plugins/projectexplorer/kit.cpp b/src/plugins/projectexplorer/kit.cpp
index 114e6e25512..42f74c77f9f 100644
--- a/src/plugins/projectexplorer/kit.cpp
+++ b/src/plugins/projectexplorer/kit.cpp
@@ -25,6 +25,7 @@
#include "kit.h"
+#include "devicesupport/idevice.h"
#include "devicesupport/idevicefactory.h"
#include "kitinformation.h"
#include "kitmanager.h"
@@ -189,12 +190,12 @@ Kit::Kit(const QVariantMap &data) :
for (QVariantMap::ConstIterator it = extra.constBegin(); it != cend; ++it)
d->m_data.insert(Id::fromString(it.key()), it.value());
- QStringList mutableInfoList = data.value(QLatin1String(MUTABLE_INFO_KEY)).toStringList();
- foreach (const QString &mutableInfo, mutableInfoList)
+ const QStringList mutableInfoList = data.value(QLatin1String(MUTABLE_INFO_KEY)).toStringList();
+ for (const QString &mutableInfo : mutableInfoList)
d->m_mutable.insert(Id::fromString(mutableInfo));
- QStringList stickyInfoList = data.value(QLatin1String(STICKY_INFO_KEY)).toStringList();
- foreach (const QString &stickyInfo, stickyInfoList)
+ const QStringList stickyInfoList = data.value(QLatin1String(STICKY_INFO_KEY)).toStringList();
+ for (const QString &stickyInfo : stickyInfoList)
d->m_sticky.insert(Id::fromString(stickyInfo));
}
@@ -337,7 +338,8 @@ QString Kit::fileSystemFriendlyName() const
QString name = customFileSystemFriendlyName();
if (name.isEmpty())
name = FileUtils::qmakeFriendlyName(displayName());
- foreach (Kit *i, KitManager::kits()) {
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *i : kits) {
if (i == this)
continue;
if (name == FileUtils::qmakeFriendlyName(i->displayName())) {
@@ -536,12 +538,12 @@ QVariantMap Kit::toMap() const
data.insert(DEVICE_TYPE_FOR_ICON_KEY, d->m_deviceTypeForIcon.toSetting());
QStringList mutableInfo;
- foreach (Id id, d->m_mutable)
+ for (const Id id : qAsConst(d->m_mutable))
mutableInfo << id.toString();
data.insert(QLatin1String(MUTABLE_INFO_KEY), mutableInfo);
QStringList stickyInfo;
- foreach (Id id, d->m_sticky)
+ for (const Id id : qAsConst(d->m_sticky))
stickyInfo << id.toString();
data.insert(QLatin1String(STICKY_INFO_KEY), stickyInfo);
@@ -574,14 +576,16 @@ void Kit::addToRunEnvironment(Environment &env) const
Environment Kit::buildEnvironment() const
{
- Environment env = Environment::systemEnvironment(); // FIXME: Use build device
+ IDevice::ConstPtr device = BuildDeviceKitAspect::device(this);
+ Environment env = device ? device->systemEnvironment() : Environment::systemEnvironment();
addToBuildEnvironment(env);
return env;
}
Environment Kit::runEnvironment() const
{
- Environment env = Environment::systemEnvironment(); // FIXME: Use run device
+ IDevice::ConstPtr device = DeviceKitAspect::device(this);
+ Environment env = device ? device->systemEnvironment() : Environment::systemEnvironment();
addToRunEnvironment(env);
return env;
}
@@ -607,7 +611,7 @@ QString Kit::toHtml(const Tasks &additional, const QString &extraText) const
if (!isValid() || hasWarning() || !additional.isEmpty())
str << "<p>" << ProjectExplorer::toHtml(additional + validate()) << "</p>";
- str << "<table>";
+ str << "<dl style=\"white-space:pre\">";
for (KitAspect *aspect : KitManager::kitAspects()) {
const KitAspect::ItemList list = aspect->toUserOutput(this);
for (const KitAspect::Item &j : list) {
@@ -619,10 +623,11 @@ QString Kit::toHtml(const Tasks &additional, const QString &extraText) const
contents = contents.mid(0, pos);
contents += "&lt;...&gt;";
}
- str << "<tr><td><b>" << j.first << ":</b></td><td>" << contents << "</td></tr>";
+ str << "<dt style=\"font-weight:bold\">" << j.first
+ << ":</dt><dd>" << contents << "</dd>";
}
}
- str << "</table></body></html>";
+ str << "</dl></body></html>";
return result;
}
diff --git a/src/plugins/projectexplorer/kitchooser.cpp b/src/plugins/projectexplorer/kitchooser.cpp
index 8b6b6ecb053..531e904b7f0 100644
--- a/src/plugins/projectexplorer/kitchooser.cpp
+++ b/src/plugins/projectexplorer/kitchooser.cpp
@@ -127,8 +127,8 @@ void KitChooser::populate()
m_hasStartupKit = true;
}
}
-
- foreach (Kit *kit, KitManager::sortKits(KitManager::kits())) {
+ const QList<Kit *> kits = KitManager::sortKits(KitManager::kits());
+ for (Kit *kit : kits) {
if (m_kitPredicate(kit)) {
m_chooser->addItem(kitText(kit), kit->id().toSetting());
const int pos = m_chooser->count() - 1;
diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp
index acf153ddfaa..a39c091dba3 100644
--- a/src/plugins/projectexplorer/kitinformation.cpp
+++ b/src/plugins/projectexplorer/kitinformation.cpp
@@ -30,6 +30,7 @@
#include "devicesupport/devicemanager.h"
#include "devicesupport/devicemanagermodel.h"
#include "devicesupport/idevicefactory.h"
+#include "devicesupport/sshparameters.h"
#include "projectexplorerconstants.h"
#include "kit.h"
#include "toolchain.h"
@@ -37,8 +38,6 @@
#include <docker/dockerconstants.h>
-#include <ssh/sshconnection.h>
-
#include <utils/algorithm.h>
#include <utils/elidinglabel.h>
#include <utils/environment.h>
@@ -269,7 +268,8 @@ private:
void refresh() override
{
m_ignoreChanges = true;
- foreach (Utils::Id l, m_languageComboboxMap.keys()) {
+ const QList<Utils::Id> keys = m_languageComboboxMap.keys();
+ for (const Utils::Id l : keys) {
const Toolchains ltcList
= ToolChainManager::toolchains(Utils::equal(&ToolChain::language, l));
@@ -277,7 +277,7 @@ private:
cb->clear();
cb->addItem(tr("<No compiler>"), QByteArray());
- foreach (ToolChain *tc, ltcList)
+ for (ToolChain *tc : ltcList)
cb->addItem(tc->displayName(), tc->id());
cb->setEnabled(cb->count() > 1 && !m_isReadOnly);
@@ -290,7 +290,8 @@ private:
void makeReadOnly() override
{
m_isReadOnly = true;
- foreach (Utils::Id l, m_languageComboboxMap.keys()) {
+ const QList<Utils::Id> keys = m_languageComboboxMap.keys();
+ for (const Utils::Id l : keys) {
m_languageComboboxMap.value(l)->setEnabled(false);
}
}
@@ -347,7 +348,8 @@ static QMap<Utils::Id, QByteArray> defaultToolChainIds()
QMap<Utils::Id, QByteArray> toolChains;
const Abi abi = Abi::hostAbi();
const Toolchains tcList = ToolChainManager::toolchains(Utils::equal(&ToolChain::targetAbi, abi));
- foreach (Utils::Id l, ToolChainManager::allLanguages()) {
+ const QList<Utils::Id> languages = ToolChainManager::allLanguages();
+ for (Utils::Id l : languages) {
ToolChain *tc = Utils::findOrDefault(tcList, Utils::equal(&ToolChain::language, l));
toolChains.insert(l, tc ? tc->id() : QByteArray());
}
@@ -374,7 +376,7 @@ Tasks ToolChainKitAspect::validate(const Kit *k) const
result << BuildSystemTask(Task::Warning, ToolChainKitAspect::msgNoToolChainInTarget());
} else {
QSet<Abi> targetAbis;
- foreach (ToolChain *tc, tcList) {
+ for (const ToolChain *tc : tcList) {
targetAbis.insert(tc->targetAbi());
result << tc->validateKit(k);
}
@@ -454,7 +456,8 @@ void ToolChainKitAspect::upgrade(Kit *k)
void ToolChainKitAspect::fix(Kit *k)
{
QTC_ASSERT(ToolChainManager::isLoaded(), return);
- foreach (const Utils::Id& l, ToolChainManager::allLanguages()) {
+ const QList<Utils::Id> languages = ToolChainManager::allLanguages();
+ for (const Utils::Id l : languages) {
const QByteArray tcId = toolChainId(k, l);
if (!tcId.isEmpty() && !ToolChainManager::findToolChain(tcId)) {
qWarning("Tool chain set up in kit \"%s\" for \"%s\" not found.",
@@ -701,11 +704,11 @@ void ToolChainKitAspect::clearToolChain(Kit *k, Id language)
Abi ToolChainKitAspect::targetAbi(const Kit *k)
{
- QList<ToolChain *> tcList = toolChains(k);
+ const QList<ToolChain *> tcList = toolChains(k);
// Find the best possible ABI for all the tool chains...
Abi cxxAbi;
QHash<Abi, int> abiCount;
- foreach (ToolChain *tc, tcList) {
+ for (ToolChain *tc : tcList) {
Abi ta = tc->targetAbi();
if (tc->language() == Id(Constants::CXX_LANGUAGE_ID))
cxxAbi = tc->targetAbi();
@@ -739,7 +742,8 @@ QString ToolChainKitAspect::msgNoToolChainInTarget()
void ToolChainKitAspect::kitsWereLoaded()
{
- foreach (Kit *k, KitManager::kits())
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits)
fix(k);
connect(ToolChainManager::instance(), &ToolChainManager::toolChainRemoved,
@@ -759,7 +763,8 @@ void ToolChainKitAspect::toolChainUpdated(ToolChain *tc)
void ToolChainKitAspect::toolChainRemoved(ToolChain *tc)
{
Q_UNUSED(tc)
- foreach (Kit *k, KitManager::kits())
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits)
fix(k);
}
@@ -1105,9 +1110,17 @@ void DeviceKitAspect::setDeviceId(Kit *k, Utils::Id id)
k->setValue(DeviceKitAspect::id(), id.toSetting());
}
+FilePath DeviceKitAspect::deviceFilePath(const Kit *k, const QString &pathOnDevice)
+{
+ if (IDevice::ConstPtr dev = device(k))
+ return dev->filePath(pathOnDevice);
+ return FilePath::fromString(pathOnDevice);
+}
+
void DeviceKitAspect::kitsWereLoaded()
{
- foreach (Kit *k, KitManager::kits())
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits)
fix(k);
DeviceManager *dm = DeviceManager::instance();
@@ -1124,7 +1137,8 @@ void DeviceKitAspect::kitsWereLoaded()
void DeviceKitAspect::deviceUpdated(Utils::Id id)
{
- foreach (Kit *k, KitManager::kits()) {
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits) {
if (deviceId(k) == id)
notifyAboutUpdate(k);
}
@@ -1137,7 +1151,8 @@ void DeviceKitAspect::kitUpdated(Kit *k)
void DeviceKitAspect::devicesChanged()
{
- foreach (Kit *k, KitManager::kits())
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits)
setup(k); // Set default device if necessary
}
@@ -1346,7 +1361,8 @@ void BuildDeviceKitAspect::setDeviceId(Kit *k, Utils::Id id)
void BuildDeviceKitAspect::kitsWereLoaded()
{
- foreach (Kit *k, KitManager::kits())
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits)
fix(k);
DeviceManager *dm = DeviceManager::instance();
@@ -1363,7 +1379,8 @@ void BuildDeviceKitAspect::kitsWereLoaded()
void BuildDeviceKitAspect::deviceUpdated(Utils::Id id)
{
- foreach (Kit *k, KitManager::kits()) {
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits) {
if (deviceId(k) == id)
notifyAboutUpdate(k);
}
@@ -1376,7 +1393,8 @@ void BuildDeviceKitAspect::kitUpdated(Kit *k)
void BuildDeviceKitAspect::devicesChanged()
{
- foreach (Kit *k, KitManager::kits())
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits)
setup(k); // Set default device if necessary
}
diff --git a/src/plugins/projectexplorer/kitinformation.h b/src/plugins/projectexplorer/kitinformation.h
index 5675b02c062..a925d84ba47 100644
--- a/src/plugins/projectexplorer/kitinformation.h
+++ b/src/plugins/projectexplorer/kitinformation.h
@@ -26,7 +26,7 @@
#pragma once
#include "abi.h"
-#include "devicesupport/idevice.h"
+#include "devicesupport/idevicefwd.h"
#include "kitmanager.h"
#include "kit.h"
@@ -157,10 +157,11 @@ public:
void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const override;
static Utils::Id id();
- static IDevice::ConstPtr device(const Kit *k);
+ static IDeviceConstPtr device(const Kit *k);
static Utils::Id deviceId(const Kit *k);
- static void setDevice(Kit *k, IDevice::ConstPtr dev);
+ static void setDevice(Kit *k, IDeviceConstPtr dev);
static void setDeviceId(Kit *k, Utils::Id dataId);
+ static Utils::FilePath deviceFilePath(const Kit *k, const QString &pathOnDevice);
private:
QVariant defaultValue(const Kit *k) const;
@@ -194,13 +195,13 @@ public:
void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const override;
static Utils::Id id();
- static IDevice::ConstPtr device(const Kit *k);
+ static IDeviceConstPtr device(const Kit *k);
static Utils::Id deviceId(const Kit *k);
- static void setDevice(Kit *k, IDevice::ConstPtr dev);
+ static void setDevice(Kit *k, IDeviceConstPtr dev);
static void setDeviceId(Kit *k, Utils::Id dataId);
private:
- static IDevice::ConstPtr defaultDevice();
+ static IDeviceConstPtr defaultDevice();
void kitsWereLoaded();
void deviceUpdated(Utils::Id dataId);
diff --git a/src/plugins/projectexplorer/kitmanager.cpp b/src/plugins/projectexplorer/kitmanager.cpp
index e67bbe71d25..93bfe31ae43 100644
--- a/src/plugins/projectexplorer/kitmanager.cpp
+++ b/src/plugins/projectexplorer/kitmanager.cpp
@@ -309,7 +309,18 @@ void KitManager::restoreKits()
}
static const auto isHostKit = [](const Kit *kit) {
- return kitMatchesAbiList(kit, {Abi::hostAbi()});
+ const Abi hostAbi = Abi::hostAbi();
+ if (HostOsInfo::isMacHost() && hostAbi.architecture() == Abi::ArmArchitecture) {
+ const Abi x86Abi(Abi::X86Architecture,
+ hostAbi.os(),
+ hostAbi.osFlavor(),
+ hostAbi.binaryFormat(),
+ hostAbi.wordWidth());
+
+ return kitMatchesAbiList(kit, {hostAbi, x86Abi});
+ }
+
+ return kitMatchesAbiList(kit, {hostAbi});
};
static const auto deviceTypeForKit = [](const Kit *kit) {
@@ -438,7 +449,8 @@ void KitManager::saveKits()
data.insert(QLatin1String(KIT_FILE_VERSION_KEY), 1);
int count = 0;
- foreach (Kit *k, kits()) {
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits) {
QVariantMap tmp = k->toMap();
if (tmp.isEmpty())
continue;
diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
index 778beb52c8c..d2a1c701a8b 100644
--- a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
+++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
@@ -68,7 +68,7 @@ KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
- QLabel *label = new QLabel(tr("Name:"));
+ auto label = new QLabel(tr("Name:"));
label->setToolTip(tr("Kit name and icon."));
QString toolTip =
@@ -81,15 +81,15 @@ KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
Q_ASSERT(fileSystemFriendlyNameRegexp.isValid());
m_fileSystemFriendlyNameLineEdit->setValidator(new QRegularExpressionValidator(fileSystemFriendlyNameRegexp, m_fileSystemFriendlyNameLineEdit));
- label = new QLabel(tr("File system name:"));
- label->setToolTip(toolTip);
+ auto fsLabel = new QLabel(tr("File system name:"));
+ fsLabel->setToolTip(toolTip);
connect(m_fileSystemFriendlyNameLineEdit, &QLineEdit::textChanged,
this, &KitManagerConfigWidget::setFileSystemFriendlyName);
using namespace Layouting;
Grid {
AlignAsFormLabel(label), m_nameEdit, m_iconButton, Break(),
- AlignAsFormLabel(label), m_fileSystemFriendlyNameLineEdit
+ AlignAsFormLabel(fsLabel), m_fileSystemFriendlyNameLineEdit
}.attachTo(this);
m_iconButton->setToolTip(tr("Kit icon."));
@@ -243,7 +243,7 @@ void KitManagerConfigWidget::setHasUniqueName(bool unique)
void KitManagerConfigWidget::makeStickySubWidgetsReadOnly()
{
- foreach (KitAspectWidget *w, m_widgets) {
+ for (KitAspectWidget *w : qAsConst(m_widgets)) {
if (w->kit()->isSticky(w->kitInformation()->id()))
w->makeReadOnly();
}
@@ -354,7 +354,7 @@ void KitManagerConfigWidget::workingCopyWasUpdated(Kit *k)
k->fix();
m_fixingKit = false;
- foreach (KitAspectWidget *w, m_widgets)
+ for (KitAspectWidget *w : qAsConst(m_widgets))
w->refresh();
m_cachedDisplayName.clear();
@@ -382,7 +382,7 @@ void KitManagerConfigWidget::kitWasUpdated(Kit *k)
void KitManagerConfigWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event)
- foreach (KitAspectWidget *widget, m_widgets)
+ for (KitAspectWidget *widget : qAsConst(m_widgets))
widget->refresh();
}
diff --git a/src/plugins/projectexplorer/kitmodel.cpp b/src/plugins/projectexplorer/kitmodel.cpp
index 0bb09cf951e..ed3604fa247 100644
--- a/src/plugins/projectexplorer/kitmodel.cpp
+++ b/src/plugins/projectexplorer/kitmodel.cpp
@@ -113,7 +113,8 @@ KitModel::KitModel(QBoxLayout *parentLayout, QObject *parent)
rootItem()->appendChild(m_autoRoot);
rootItem()->appendChild(m_manualRoot);
- foreach (Kit *k, KitManager::sortKits(KitManager::kits()))
+ const QList<Kit *> kits = KitManager::sortKits(KitManager::kits());
+ for (Kit *k : kits)
addKit(k);
changeDefaultKit();
@@ -193,7 +194,8 @@ void KitModel::apply()
});
// Remove unused kits:
- foreach (KitNode *n, m_toRemoveList)
+ const QList<KitNode *> removeList = m_toRemoveList;
+ for (KitNode *n : removeList)
n->widget->removeKit();
emit layoutChanged(); // Force update.
@@ -310,7 +312,7 @@ void KitModel::updateKit(Kit *)
void KitModel::removeKit(Kit *k)
{
QList<KitNode *> nodes = m_toRemoveList;
- foreach (KitNode *n, nodes) {
+ for (KitNode *n : qAsConst(nodes)) {
if (n->widget->configures(k)) {
m_toRemoveList.removeOne(n);
if (m_defaultNode == n)
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index 6a4b2264880..a1095773b4c 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -23,16 +23,17 @@
**
****************************************************************************/
+#include "miniprojecttargetselector.h"
+
#include "buildconfiguration.h"
#include "buildmanager.h"
#include "deployconfiguration.h"
#include "kit.h"
#include "kitmanager.h"
-#include "miniprojecttargetselector.h"
+#include "project.h"
#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
#include "projectexplorericons.h"
-#include "project.h"
-#include "projectmodels.h"
#include "runconfiguration.h"
#include "session.h"
#include "target.h"
@@ -44,25 +45,26 @@
#include <utils/styledbar.h>
#include <utils/stylehelper.h>
#include <utils/theme/theme.h>
+#include <utils/treemodel.h>
#include <utils/utilsicons.h>
-#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/icore.h>
#include <coreplugin/modemanager.h>
+#include <QAction>
#include <QGuiApplication>
-#include <QTimer>
-#include <QLayout>
+#include <QItemDelegate>
+#include <QKeyEvent>
#include <QLabel>
+#include <QLayout>
#include <QList>
#include <QListWidget>
-#include <QStatusBar>
-#include <QKeyEvent>
#include <QPainter>
#include <QPixmap>
+#include <QStatusBar>
#include <QStyleFactory>
-#include <QAction>
-#include <QItemDelegate>
+#include <QTimer>
using namespace Utils;
@@ -634,7 +636,7 @@ private:
setKit(m_kit);
} else {
// Refresh all widgets if the number of mutable settings did not change
- foreach (KitAspectWidget *w, m_widgets)
+ for (KitAspectWidget *w : qAsConst(m_widgets))
w->refresh();
}
}
@@ -1001,7 +1003,8 @@ void MiniProjectTargetSelector::projectAdded(Project *project)
connect(project, &Project::removedTarget,
this, &MiniProjectTargetSelector::handleRemovalOfTarget);
- foreach (Target *t, project->targets())
+ const QList<Target *> targets = project->targets();
+ for (Target *t : targets)
addedTarget(t);
updateProjectListVisible();
@@ -1018,7 +1021,8 @@ void MiniProjectTargetSelector::projectRemoved(Project *project)
disconnect(project, &Project::removedTarget,
this, &MiniProjectTargetSelector::handleRemovalOfTarget);
- foreach (Target *t, project->targets())
+ const QList<Target *> targets = project->targets();
+ for (Target *t : targets)
removedTarget(t);
updateProjectListVisible();
@@ -1165,9 +1169,11 @@ void MiniProjectTargetSelector::updateTargetListVisible()
void MiniProjectTargetSelector::updateBuildListVisible()
{
int maxCount = 0;
- for (Project *p : SessionManager::projects())
- foreach (Target *t, p->targets())
+ for (Project *p : SessionManager::projects()) {
+ const QList<Target *> targets = p->targets();
+ for (Target *t : targets)
maxCount = qMax(t->buildConfigurations().size(), maxCount);
+ }
bool visible = maxCount > 1;
m_listWidgets[BUILD]->setVisible(visible);
@@ -1179,9 +1185,11 @@ void MiniProjectTargetSelector::updateBuildListVisible()
void MiniProjectTargetSelector::updateDeployListVisible()
{
int maxCount = 0;
- for (Project *p : SessionManager::projects())
- foreach (Target *t, p->targets())
+ for (Project *p : SessionManager::projects()) {
+ const QList<Target *> targets = p->targets();
+ for (Target *t : targets)
maxCount = qMax(t->deployConfigurations().size(), maxCount);
+ }
bool visible = maxCount > 1;
m_listWidgets[DEPLOY]->setVisible(visible);
@@ -1193,9 +1201,11 @@ void MiniProjectTargetSelector::updateDeployListVisible()
void MiniProjectTargetSelector::updateRunListVisible()
{
int maxCount = 0;
- for (Project *p : SessionManager::projects())
- foreach (Target *t, p->targets())
+ for (Project *p : SessionManager::projects()) {
+ const QList<Target *> targets = p->targets();
+ for (Target *t : targets)
maxCount = qMax(t->runConfigurations().size(), maxCount);
+ }
bool visible = maxCount > 1;
m_listWidgets[RUN]->setVisible(visible);
@@ -1221,7 +1231,8 @@ void MiniProjectTargetSelector::changeStartupProject(Project *project)
if (project) {
QList<QObject *> list;
- foreach (Target *t, project->targets())
+ const QList<Target *> targets = project->targets();
+ for (Target *t : targets)
list.append(t);
m_listWidgets[TARGET]->setProjectConfigurations(list, project->activeTarget());
} else {
diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp
index df9a21660fb..890b4a4e532 100644
--- a/src/plugins/projectexplorer/msvcparser.cpp
+++ b/src/plugins/projectexplorer/msvcparser.cpp
@@ -69,16 +69,21 @@ using namespace ProjectExplorer;
// nmake/jom messages.
static Task handleNmakeJomMessage(const QString &line)
{
+ Task::TaskType type = Task::Unknown;
int matchLength = 0;
- if (line.startsWith("Error:"))
+ if (line.startsWith("Error:")) {
matchLength = 6;
- else if (line.startsWith("Warning:"))
+ type = Task::Error;
+ } else if (line.startsWith("Warning:")) {
matchLength = 8;
-
- if (!matchLength)
+ type = Task::Warning;
+ } else {
return {};
+ }
- return CompileTask(Task::Error, line.mid(matchLength).trimmed());
+ CompileTask task(type, line.mid(matchLength).trimmed());
+ task.details << line;
+ return std::move(task);
}
static Task::TaskType taskType(const QString &category)
@@ -139,6 +144,7 @@ OutputLineParser::Result MsvcParser::handleLine(const QString &line, OutputForma
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2);
m_lastTask = CompileTask(Task::Unknown, description, filePath, lineNo);
+ m_lastTask.details << line;
m_lines = 1;
return {Status::InProgress, linkSpecs};
}
@@ -173,17 +179,16 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
[](int total, const QString &line) { return total + line.length() + 1;});
for (LinkSpec &ls : linkSpecs)
ls.startPos += offset;
- m_linkSpecs << linkSpecs;
- m_lastTask.details.append(line);
++m_lines;
} else {
flush();
m_lastTask = CompileTask(taskType(match.captured(2)),
match.captured(3) + match.captured(4).trimmed(), // description
filePath, position.second);
- m_linkSpecs << linkSpecs;
m_lines = 1;
}
+ m_linkSpecs << linkSpecs;
+ m_lastTask.details.append(line);
return {Status::InProgress, linkSpecs};
}
@@ -196,6 +201,8 @@ void MsvcParser::flush()
if (m_lastTask.isNull())
return;
+ if (m_lastTask.details.count() == 1)
+ m_lastTask.details.clear();
setDetailsFormat(m_lastTask, m_linkSpecs);
Task t = m_lastTask;
m_lastTask.clear();
@@ -476,6 +483,7 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< (Tasks()
<< compileTask(Task::Error,
"C2440: 'initializing' : cannot convert from 'int' to 'std::_Tree<_Traits>::iterator'\n"
+ "..\\untitled\\main.cpp(19) : error C2440: 'initializing' : cannot convert from 'int' to 'std::_Tree<_Traits>::iterator'\n"
" with\n"
" [\n"
" _Traits=std::_Tmap_traits<int,double,std::less<int>,std::allocator<std::pair<const int,double>>,false>\n"
@@ -484,7 +492,7 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
FilePath::fromUserInput("..\\untitled\\main.cpp"),
19,
QVector<QTextLayout::FormatRange>()
- << formatRange(85, 247)))
+ << formatRange(85, 365)))
<< "";
QTest::newRow("Linker error 1")
@@ -545,6 +553,7 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
FilePath::fromUserInput("c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE\\xutility"), 2212)
<< compileTask(Task::Unknown,
"see reference to function template instantiation '_OutIt std::copy<const unsigned char*,unsigned short*>(_InIt,_InIt,_OutIt)' being compiled\n"
+ " symbolgroupvalue.cpp(2314) : see reference to function template instantiation '_OutIt std::copy<const unsigned char*,unsigned short*>(_InIt,_InIt,_OutIt)' being compiled\n"
" with\n"
" [\n"
" _OutIt=unsigned short *,\n"
@@ -553,7 +562,7 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
FilePath::fromUserInput("symbolgroupvalue.cpp"),
2314,
QVector<QTextLayout::FormatRange>()
- << formatRange(141, 109)))
+ << formatRange(141, 287)))
<< "";
QTest::newRow("Ambiguous symbol")
@@ -588,11 +597,12 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< "" << ""
<< Tasks{compileTask(Task::Error,
"C2733: 'func': second C linkage of overloaded function not allowed\n"
+ "main.cpp(7): error C2733: 'func': second C linkage of overloaded function not allowed\n"
"main.cpp(6): note: see declaration of 'func'",
FilePath::fromUserInput("main.cpp"),
7,
QVector<QTextLayout::FormatRange>()
- << formatRange(67, 44))}
+ << formatRange(67, 130))}
<< "";
QTest::newRow("cyrillic warning") // QTCREATORBUG-20297
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index 13a945a2807..7ab685bdfc9 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -31,7 +31,6 @@
#include "projectexplorerconstants.h"
#include "projectexplorersettings.h"
#include "taskhub.h"
-#include "toolchainmanager.h"
#include <coreplugin/icore.h>
@@ -106,7 +105,10 @@ const MsvcPlatform platforms[]
{MsvcToolChain::amd64_arm, "amd64_arm", "/bin/amd64_arm", "vcvarsamd64_arm.bat"},
{MsvcToolChain::amd64_x86, "amd64_x86", "/bin/amd64_x86", "vcvarsamd64_x86.bat"},
{MsvcToolChain::x86_arm64, "x86_arm64", "/bin/x86_arm64", "vcvarsx86_arm64.bat"},
- {MsvcToolChain::amd64_arm64, "amd64_arm64", "/bin/amd64_arm64", "vcvarsamd64_arm64.bat"}};
+ {MsvcToolChain::amd64_arm64, "amd64_arm64", "/bin/amd64_arm64", "vcvarsamd64_arm64.bat"},
+ {MsvcToolChain::arm64, "arm64", "/bin/arm64", "vcvarsarm64.bat"},
+ {MsvcToolChain::arm64_x86, "arm64_x86", "/bin/arm64_x86", "vcvarsarm64_x86.bat"},
+ {MsvcToolChain::arm64_amd64, "arm64_amd64", "/bin/arm64_amd64", "vcvarsarm64_amd64.bat"}};
static QList<const MsvcToolChain *> g_availableMsvcToolchains;
@@ -147,6 +149,9 @@ static bool hostPrefersPlatform(MsvcToolChain::Platform platform)
|| platform == MsvcToolChain::x86_arm64;
case HostOsInfo::HostArchitectureArm:
return platform == MsvcToolChain::arm;
+ case HostOsInfo::HostArchitectureArm64:
+ return platform == MsvcToolChain::arm64
+ || platform == MsvcToolChain::arm64_x86 || platform == MsvcToolChain::arm64_amd64;
case HostOsInfo::HostArchitectureItanium:
return platform == MsvcToolChain::ia64;
default:
@@ -158,12 +163,23 @@ static bool hostSupportsPlatform(MsvcToolChain::Platform platform)
{
if (hostPrefersPlatform(platform))
return true;
+
+ switch (HostOsInfo::hostArchitecture()) {
// The x86 host toolchains are not the preferred toolchains on amd64 but they are still
// supported by that host
- return HostOsInfo::hostArchitecture() == HostOsInfo::HostArchitectureAMD64
- && (platform == MsvcToolChain::x86 || platform == MsvcToolChain::x86_amd64
+ case HostOsInfo::HostArchitectureAMD64:
+ return platform == MsvcToolChain::x86 || platform == MsvcToolChain::x86_amd64
|| platform == MsvcToolChain::x86_ia64 || platform == MsvcToolChain::x86_arm
- || platform == MsvcToolChain::x86_arm64);
+ || platform == MsvcToolChain::x86_arm64;
+ // The Arm64 host can run the cross-compilers via emulation of x86 and amd64
+ case HostOsInfo::HostArchitectureArm64:
+ return platform == MsvcToolChain::x86_arm || platform == MsvcToolChain::x86_arm64
+ || platform == MsvcToolChain::amd64_arm || platform == MsvcToolChain::amd64_arm64
+ || platform == MsvcToolChain::x86 || platform == MsvcToolChain::x86_amd64
+ || platform == MsvcToolChain::amd64 || platform == MsvcToolChain::amd64_x86;
+ default:
+ return false;
+ }
}
static QString fixRegistryPath(const QString &path)
@@ -265,27 +281,27 @@ static QVector<VisualStudioInstallation> detectVisualStudioFromVsWhere(const QSt
{"-products", "*", "-prerelease", "-legacy", "-format", "json", "-utf8"}});
vsWhereProcess.runBlocking();
switch (vsWhereProcess.result()) {
- case QtcProcess::FinishedWithSuccess:
+ case ProcessResult::FinishedWithSuccess:
break;
- case QtcProcess::StartFailed:
+ case ProcessResult::StartFailed:
qWarning().noquote() << QDir::toNativeSeparators(vswhere) << "could not be started.";
return installations;
- case QtcProcess::FinishedWithError:
+ case ProcessResult::FinishedWithError:
qWarning().noquote().nospace() << QDir::toNativeSeparators(vswhere)
<< " finished with exit code "
<< vsWhereProcess.exitCode() << ".";
return installations;
- case QtcProcess::TerminatedAbnormally:
+ case ProcessResult::TerminatedAbnormally:
qWarning().noquote().nospace()
<< QDir::toNativeSeparators(vswhere) << " crashed. Exit code: " << vsWhereProcess.exitCode();
return installations;
- case QtcProcess::Hang:
+ case ProcessResult::Hang:
qWarning().noquote() << QDir::toNativeSeparators(vswhere) << "did not finish in" << timeoutS
<< "seconds.";
return installations;
}
- QByteArray output = vsWhereProcess.stdOut().toUtf8();
+ QByteArray output = vsWhereProcess.cleanedStdOut().toUtf8();
QJsonParseError error;
const QJsonDocument doc = QJsonDocument::fromJson(output, &error);
if (error.error != QJsonParseError::NoError || doc.isNull()) {
@@ -340,7 +356,8 @@ static QVector<VisualStudioInstallation> detectVisualStudioFromRegistry()
#endif
QSettings vsRegistry(keyRoot + QStringLiteral("VS7"), QSettings::NativeFormat);
QScopedPointer<QSettings> vcRegistry;
- foreach (const QString &vsName, vsRegistry.allKeys()) {
+ const QStringList keys = vsRegistry.allKeys();
+ for (const QString &vsName : keys) {
const QVersionNumber version = QVersionNumber::fromString(vsName);
if (!version.isNull()) {
const QString installationPath = fixRegistryPath(vsRegistry.value(vsName).toString());
@@ -382,6 +399,7 @@ static unsigned char wordWidthForPlatform(MsvcToolChain::Platform platform)
case ProjectExplorer::Internal::MsvcToolChain::x86_arm:
case ProjectExplorer::Internal::MsvcToolChain::amd64_arm:
case ProjectExplorer::Internal::MsvcToolChain::amd64_x86:
+ case ProjectExplorer::Internal::MsvcToolChain::arm64_x86:
return 32;
case ProjectExplorer::Internal::MsvcToolChain::amd64:
case ProjectExplorer::Internal::MsvcToolChain::x86_amd64:
@@ -389,6 +407,8 @@ static unsigned char wordWidthForPlatform(MsvcToolChain::Platform platform)
case ProjectExplorer::Internal::MsvcToolChain::x86_ia64:
case ProjectExplorer::Internal::MsvcToolChain::amd64_arm64:
case ProjectExplorer::Internal::MsvcToolChain::x86_arm64:
+ case ProjectExplorer::Internal::MsvcToolChain::arm64:
+ case ProjectExplorer::Internal::MsvcToolChain::arm64_amd64:
return 64;
}
@@ -402,12 +422,15 @@ static Abi::Architecture archForPlatform(MsvcToolChain::Platform platform)
case ProjectExplorer::Internal::MsvcToolChain::amd64:
case ProjectExplorer::Internal::MsvcToolChain::x86_amd64:
case ProjectExplorer::Internal::MsvcToolChain::amd64_x86:
+ case ProjectExplorer::Internal::MsvcToolChain::arm64_x86:
+ case ProjectExplorer::Internal::MsvcToolChain::arm64_amd64:
return Abi::X86Architecture;
case ProjectExplorer::Internal::MsvcToolChain::arm:
case ProjectExplorer::Internal::MsvcToolChain::x86_arm:
case ProjectExplorer::Internal::MsvcToolChain::amd64_arm:
case ProjectExplorer::Internal::MsvcToolChain::x86_arm64:
case ProjectExplorer::Internal::MsvcToolChain::amd64_arm64:
+ case ProjectExplorer::Internal::MsvcToolChain::arm64:
return Abi::ArmArchitecture;
case ProjectExplorer::Internal::MsvcToolChain::ia64:
case ProjectExplorer::Internal::MsvcToolChain::x86_ia64:
@@ -652,10 +675,10 @@ Macros MsvcToolChain::msvcPredefinedMacros(const QStringList &cxxflags,
arguments << toProcess << QLatin1String("/EP") << saver.filePath().toUserOutput();
cpp.setCommand({binary, arguments});
cpp.runBlocking();
- if (cpp.result() != QtcProcess::FinishedWithSuccess)
+ if (cpp.result() != ProcessResult::FinishedWithSuccess)
return predefinedMacros;
- const QStringList output = Utils::filtered(cpp.stdOut().split('\n'),
+ const QStringList output = Utils::filtered(cpp.cleanedStdOut().split('\n'),
[](const QString &s) { return s.startsWith('V'); });
for (const QString &line : output)
predefinedMacros.append(Macro::fromKeyValue(line.mid(1)));
@@ -901,34 +924,18 @@ QStringList MsvcToolChain::suggestedMkspecList() const
case Abi::WindowsMsvc2013Flavor:
return {"win32-msvc",
"win32-msvc2013",
- "winphone-arm-msvc2013",
- "winphone-x86-msvc2013",
- "winrt-arm-msvc2013",
- "winrt-x86-msvc2013",
- "winrt-x64-msvc2013",
"win32-msvc2012",
"win32-msvc2010"};
case Abi::WindowsMsvc2015Flavor:
return {"win32-msvc",
- "win32-msvc2015",
- "winphone-arm-msvc2015",
- "winphone-x86-msvc2015",
- "winrt-arm-msvc2015",
- "winrt-x86-msvc2015",
- "winrt-x64-msvc2015"};
+ "win32-msvc2015"};
case Abi::WindowsMsvc2017Flavor:
return {"win32-msvc",
- "win32-msvc2017",
- "winrt-arm-msvc2017",
- "winrt-x86-msvc2017",
- "winrt-x64-msvc2017"};
+ "win32-msvc2017",};
case Abi::WindowsMsvc2019Flavor:
return {"win32-msvc",
"win32-msvc2019",
- "win32-arm64-msvc",
- "winrt-arm-msvc2019",
- "winrt-x86-msvc2019",
- "winrt-x64-msvc2019"};
+ "win32-arm64-msvc"};
case Abi::WindowsMsvc2022Flavor:
return {"win32-msvc",
"win32-msvc2022",
@@ -1079,7 +1086,7 @@ Utils::LanguageExtensions MsvcToolChain::languageExtensions(const QStringList &c
WarningFlags MsvcToolChain::warningFlags(const QStringList &cflags) const
{
WarningFlags flags = WarningFlags::NoWarnings;
- foreach (QString flag, cflags) {
+ for (QString flag : cflags) {
if (!flag.isEmpty() && flag[0] == QLatin1Char('-'))
flag[0] = QLatin1Char('/');
@@ -1135,7 +1142,7 @@ ToolChain::BuiltInHeaderPathsRunner MsvcToolChain::createBuiltInHeaderPathsRunne
Utils::Environment fullEnv = env;
addToEnvironment(fullEnv);
- return [this, fullEnv](const QStringList &, const QString &, const QString &) {
+ return [this, fullEnv](const QStringList &, const FilePath &, const QString &) {
QMutexLocker locker(&m_headerPathsMutex);
const auto envList = fullEnv.toStringList();
const auto it = m_headerPathsPerEnv.constFind(envList);
@@ -1149,7 +1156,7 @@ ToolChain::BuiltInHeaderPathsRunner MsvcToolChain::createBuiltInHeaderPathsRunne
void MsvcToolChain::addToEnvironment(Utils::Environment &env) const
{
// We cache the full environment (incoming + modifications by setup script).
- if (!m_resultEnvironment.size() || env != m_lastEnvironment) {
+ if (!m_resultEnvironment.isValid() || env != m_lastEnvironment) {
qCDebug(Log) << "addToEnvironment: " << displayName();
m_lastEnvironment = env;
m_resultEnvironment = readEnvironmentSetting(env);
@@ -1329,6 +1336,9 @@ MsvcToolChainConfigWidget::MsvcToolChainConfigWidget(ToolChain *tc)
m_varsBatArchCombo->addItem("amd64_arm64", MsvcToolChain::amd64_arm64);
m_varsBatArchCombo->addItem("ia64", MsvcToolChain::ia64);
m_varsBatArchCombo->addItem("x86_ia64", MsvcToolChain::x86_ia64);
+ m_varsBatArchCombo->addItem("arm64", MsvcToolChain::arm64);
+ m_varsBatArchCombo->addItem("arm64_x86", MsvcToolChain::arm64_x86);
+ m_varsBatArchCombo->addItem("arm64_amd64", MsvcToolChain::arm64_amd64);
m_varsBatArgumentsEdit->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
m_varsBatArgumentsEdit->setToolTip(tr("Additional arguments for the vcvarsall.bat call"));
hLayout->addWidget(m_varsBatPathCombo);
@@ -1555,11 +1565,11 @@ static QVersionNumber clangClVersion(const FilePath &clangClPath)
QtcProcess clangClProcess;
clangClProcess.setCommand({clangClPath, {"--version"}});
clangClProcess.runBlocking();
- if (clangClProcess.result() != QtcProcess::FinishedWithSuccess)
+ if (clangClProcess.result() != ProcessResult::FinishedWithSuccess)
return {};
const QRegularExpressionMatch match = QRegularExpression(
QStringLiteral("clang version (\\d+(\\.\\d+)+)"))
- .match(clangClProcess.stdOut());
+ .match(clangClProcess.cleanedStdOut());
if (!match.hasMatch())
return {};
return QVersionNumber::fromString(match.captured(1));
@@ -1780,7 +1790,7 @@ Macros ClangClToolChain::msvcPredefinedMacros(const QStringList &cxxflags,
arguments.append("-");
cpp.setCommand({compilerCommand(), arguments});
cpp.runBlocking();
- if (cpp.result() != Utils::QtcProcess::FinishedWithSuccess) {
+ if (cpp.result() != ProcessResult::FinishedWithSuccess) {
// Show the warning but still parse the output.
QTC_CHECK(false && "clang-cl exited with non-zero code.");
}
@@ -1924,7 +1934,8 @@ Toolchains MsvcToolChainFactory::autoDetect(const ToolchainDetector &detector) c
const QString defaultSdkPath = sdkRegistry.value(QLatin1String("CurrentInstallFolder"))
.toString();
if (!defaultSdkPath.isEmpty()) {
- foreach (const QString &sdkKey, sdkRegistry.childGroups()) {
+ const QStringList groups = sdkRegistry.childGroups();
+ for (const QString &sdkKey : groups) {
const QString name = sdkRegistry.value(sdkKey + QLatin1String("/ProductName")).toString();
const QString folder = sdkRegistry.value(sdkKey + QLatin1String("/InstallationFolder"))
.toString();
@@ -1943,6 +1954,7 @@ Toolchains MsvcToolChainFactory::autoDetect(const ToolchainDetector &detector) c
{MsvcToolChain::x86, "x86"},
{MsvcToolChain::amd64, "x64"},
{MsvcToolChain::ia64, "ia64"},
+ {MsvcToolChain::arm64, "arm64"},
};
for (const auto &platform : platforms) {
tmp.append(findOrCreateToolchains(detector,
@@ -1960,7 +1972,7 @@ Toolchains MsvcToolChainFactory::autoDetect(const ToolchainDetector &detector) c
results = tmp + results;
else
results += tmp;
- } // foreach
+ } // for
}
// 2) Installed MSVCs
@@ -1978,9 +1990,13 @@ Toolchains MsvcToolChainFactory::autoDetect(const ToolchainDetector &detector) c
MsvcToolChain::x86_arm64,
MsvcToolChain::amd64_arm64,
MsvcToolChain::ia64,
- MsvcToolChain::x86_ia64};
+ MsvcToolChain::x86_ia64,
+ MsvcToolChain::arm64,
+ MsvcToolChain::arm64_x86,
+ MsvcToolChain::arm64_amd64};
- foreach (const VisualStudioInstallation &i, detectVisualStudio()) {
+ const QVector<VisualStudioInstallation> studios = detectVisualStudio();
+ for (const VisualStudioInstallation &i : studios) {
for (MsvcToolChain::Platform platform : platforms) {
const bool toolchainInstalled
= QFileInfo(vcVarsBatFor(i.vcVarsPath, platform, i.version)).isFile();
@@ -2123,13 +2139,13 @@ Utils::optional<QString> MsvcToolChain::generateEnvironmentSettings(const Utils:
// Windows SDK setup scripts require command line switches for environment expansion.
CommandLine cmd(cmdPath, {"/E:ON", "/V:ON", "/c", saver.filePath().toUserOutput()});
qCDebug(Log) << "readEnvironmentSetting: " << call << cmd.toUserOutput()
- << " Env: " << runEnv.size();
+ << " Env: " << runEnv.toStringList().size();
run.setCodec(QTextCodec::codecForName("UTF-8"));
run.setCommand(cmd);
run.runBlocking();
- if (run.result() != QtcProcess::FinishedWithSuccess) {
- const QString message = !run.stdErr().isEmpty() ? run.stdErr() : run.exitMessage();
+ if (run.result() != ProcessResult::FinishedWithSuccess) {
+ const QString message = !run.cleanedStdErr().isEmpty() ? run.cleanedStdErr() : run.exitMessage();
qWarning().noquote() << message;
QString command = QDir::toNativeSeparators(batchFile);
if (!batchArgs.isEmpty())
@@ -2141,7 +2157,7 @@ Utils::optional<QString> MsvcToolChain::generateEnvironmentSettings(const Utils:
}
// The SDK/MSVC scripts do not return exit codes != 0. Check on stdout.
- const QString stdOut = run.stdOut();
+ const QString stdOut = run.cleanedStdOut();
//
// Now parse the file to get the environment settings
@@ -2159,7 +2175,8 @@ Utils::optional<QString> MsvcToolChain::generateEnvironmentSettings(const Utils:
const QString output = stdOut.mid(start, end - start);
- foreach (const QString &line, output.split(QLatin1String("\n"))) {
+ const QStringList lines = output.split(QLatin1String("\n"));
+ for (const QString &line : lines) {
const int pos = line.indexOf('=');
if (pos > 0) {
const QString varName = line.mid(0, pos);
diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h
index 56c926141c5..05090e721b5 100644
--- a/src/plugins/projectexplorer/msvctoolchain.h
+++ b/src/plugins/projectexplorer/msvctoolchain.h
@@ -28,7 +28,6 @@
#include "abi.h"
#include "abiwidget.h"
#include "toolchain.h"
-#include "toolchaincache.h"
#include "toolchainconfigwidget.h"
#include <QFutureWatcher>
@@ -58,7 +57,7 @@ class MsvcToolChain : public ToolChain
public:
enum Type { WindowsSDK, VS };
enum Platform { x86, amd64, x86_amd64, ia64, x86_ia64, arm, x86_arm, amd64_arm, amd64_x86,
- x86_arm64, amd64_arm64 };
+ x86_arm64, amd64_arm64, arm64, arm64_x86, arm64_amd64 };
explicit MsvcToolChain(Utils::Id typeId);
~MsvcToolChain() override;
diff --git a/src/plugins/projectexplorer/namedwidget.cpp b/src/plugins/projectexplorer/namedwidget.cpp
index 9aed84c73a3..5afca483151 100644
--- a/src/plugins/projectexplorer/namedwidget.cpp
+++ b/src/plugins/projectexplorer/namedwidget.cpp
@@ -28,7 +28,7 @@
namespace ProjectExplorer {
NamedWidget::NamedWidget(const QString &displayName, QWidget *parent)
- : QWidget(parent), m_displayName(displayName)
+ : ProjectSettingsWidget(parent), m_displayName(displayName)
{
}
diff --git a/src/plugins/projectexplorer/namedwidget.h b/src/plugins/projectexplorer/namedwidget.h
index b1e80111e2d..6cc3aae174c 100644
--- a/src/plugins/projectexplorer/namedwidget.h
+++ b/src/plugins/projectexplorer/namedwidget.h
@@ -26,12 +26,13 @@
#pragma once
#include "projectexplorer_export.h"
+#include "projectsettingswidget.h"
#include <QWidget>
namespace ProjectExplorer {
-class PROJECTEXPLORER_EXPORT NamedWidget : public QWidget
+class PROJECTEXPLORER_EXPORT NamedWidget : public ProjectSettingsWidget
{
public:
explicit NamedWidget(const QString &displayName, QWidget *parent = nullptr);
diff --git a/src/plugins/projectexplorer/outputparser_test.cpp b/src/plugins/projectexplorer/outputparser_test.cpp
index 8cbfb4108a8..5cdf5c9924f 100644
--- a/src/plugins/projectexplorer/outputparser_test.cpp
+++ b/src/plugins/projectexplorer/outputparser_test.cpp
@@ -60,6 +60,8 @@ void OutputParserTester::testParsing(const QString &lines,
const QString &childStdErrLines,
const QString &outputLines)
{
+ for (Utils::OutputLineParser * const parser : lineParsers())
+ parser->skipFileExistsCheck();
const auto terminator = new TestTerminator(this);
if (!lineParsers().isEmpty())
terminator->setRedirectionDetector(lineParsers().constLast());
diff --git a/src/plugins/projectexplorer/panelswidget.cpp b/src/plugins/projectexplorer/panelswidget.cpp
index b18c799dd10..8ab4d01a738 100644
--- a/src/plugins/projectexplorer/panelswidget.cpp
+++ b/src/plugins/projectexplorer/panelswidget.cpp
@@ -25,11 +25,14 @@
#include "panelswidget.h"
+#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
#include <utils/styledbar.h>
#include <utils/stylehelper.h>
#include <utils/theme/theme.h>
+#include <QCheckBox>
+#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QScrollArea>
@@ -41,7 +44,7 @@ namespace ProjectExplorer {
namespace {
const int ABOVE_HEADING_MARGIN = 10;
-const int ABOVE_CONTENTS_MARGIN = 4;
+const int CONTENTS_MARGIN = 5;
const int BELOW_CONTENTS_MARGIN = 16;
}
@@ -85,7 +88,16 @@ PanelsWidget::PanelsWidget(QWidget *parent) : QWidget(parent)
PanelsWidget::PanelsWidget(const QString &displayName, QWidget *widget)
: PanelsWidget(nullptr)
{
- addPropertiesPanel(displayName, widget);
+ addPropertiesPanel(displayName);
+ addWidget(widget);
+}
+
+PanelsWidget::PanelsWidget(const QString &displayName, ProjectSettingsWidget *widget)
+ : PanelsWidget(nullptr)
+{
+ addPropertiesPanel(displayName);
+ addGlobalSettingsProperties(widget);
+ addWidget(widget);
}
PanelsWidget::~PanelsWidget() = default;
@@ -102,7 +114,7 @@ PanelsWidget::~PanelsWidget() = default;
* | widget |
* +------------+ BELOW_CONTENTS_MARGIN
*/
-void PanelsWidget::addPropertiesPanel(const QString &displayName, QWidget *widget)
+void PanelsWidget::addPropertiesPanel(const QString &displayName)
{
// name:
auto nameLabel = new QLabel(m_root);
@@ -120,11 +132,60 @@ void PanelsWidget::addPropertiesPanel(const QString &displayName, QWidget *widge
line->setForegroundRole(QPalette::Midlight);
line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
m_layout->addWidget(line);
+}
- // add the widget:
- widget->setContentsMargins(0, ABOVE_CONTENTS_MARGIN, 0, BELOW_CONTENTS_MARGIN);
+void PanelsWidget::addWidget(QWidget *widget)
+{
+ widget->setContentsMargins(0, CONTENTS_MARGIN, 0, BELOW_CONTENTS_MARGIN);
widget->setParent(m_root);
m_layout->addWidget(widget);
}
+void PanelsWidget::addGlobalSettingsProperties(ProjectSettingsWidget *widget)
+{
+ if (!widget->isUseGlobalSettingsCheckBoxVisible() && !widget->isUseGlobalSettingsLabelVisible())
+ return;
+ m_layout->setContentsMargins(0, 0, 0, 0);
+ const auto useGlobalSettingsCheckBox = new QCheckBox;
+ useGlobalSettingsCheckBox->setChecked(widget->useGlobalSettings());
+ useGlobalSettingsCheckBox->setEnabled(widget->isUseGlobalSettingsCheckBoxEnabled());
+
+ const QString labelText = widget->isUseGlobalSettingsCheckBoxVisible()
+ ? QStringLiteral("Use <a href=\"dummy\">global settings</a>")
+ : QStringLiteral("<a href=\"dummy\">Global settings</a>");
+ const auto settingsLabel = new QLabel(labelText);
+ settingsLabel->setEnabled(widget->isUseGlobalSettingsCheckBoxEnabled());
+
+ const auto horizontalLayout = new QHBoxLayout;
+ horizontalLayout->setContentsMargins(0, CONTENTS_MARGIN, 0, CONTENTS_MARGIN);
+ horizontalLayout->setSpacing(CONTENTS_MARGIN);
+
+ if (widget->isUseGlobalSettingsCheckBoxVisible()) {
+ horizontalLayout->addWidget(useGlobalSettingsCheckBox);
+
+ connect(widget, &ProjectSettingsWidget::useGlobalSettingsCheckBoxEnabledChanged,
+ this, [useGlobalSettingsCheckBox, settingsLabel](bool enabled) {
+ useGlobalSettingsCheckBox->setEnabled(enabled);
+ settingsLabel->setEnabled(enabled);
+ });
+ connect(useGlobalSettingsCheckBox, &QCheckBox::stateChanged,
+ widget, &ProjectSettingsWidget::setUseGlobalSettings);
+ connect(widget, &ProjectSettingsWidget::useGlobalSettingsChanged,
+ useGlobalSettingsCheckBox, &QCheckBox::setChecked);
+ }
+
+ if (widget->isUseGlobalSettingsLabelVisible()) {
+ horizontalLayout->addWidget(settingsLabel);
+ connect(settingsLabel, &QLabel::linkActivated, this, [widget] {
+ Core::ICore::showOptionsDialog(widget->globalSettingsId());
+ });
+ }
+ horizontalLayout->addStretch(1);
+ m_layout->addLayout(horizontalLayout);
+
+ auto separator = new QFrame(m_root);
+ separator->setFrameShape(QFrame::HLine);
+ m_layout->addWidget(separator);
+}
+
} // ProjectExplorer
diff --git a/src/plugins/projectexplorer/panelswidget.h b/src/plugins/projectexplorer/panelswidget.h
index b213f2191b9..5c6691d802a 100644
--- a/src/plugins/projectexplorer/panelswidget.h
+++ b/src/plugins/projectexplorer/panelswidget.h
@@ -26,6 +26,7 @@
#pragma once
#include "projectexplorer_export.h"
+#include "projectsettingswidget.h"
#include <QWidget>
@@ -42,9 +43,12 @@ class PROJECTEXPLORER_EXPORT PanelsWidget : public QWidget
public:
explicit PanelsWidget(QWidget *parent = nullptr);
PanelsWidget(const QString &displayName, QWidget *widget);
+ PanelsWidget(const QString &displayName, ProjectSettingsWidget *widget);
~PanelsWidget() override;
- void addPropertiesPanel(const QString &displayName, QWidget *widget);
+ void addPropertiesPanel(const QString &displayName);
+ void addGlobalSettingsProperties(ProjectSettingsWidget *widget);
+ void addWidget(QWidget *widget);
static int constexpr PanelVMargin = 14;
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index 9ffd402d3ed..bc19d3b1614 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -32,11 +32,10 @@
#include "editorconfiguration.h"
#include "kit.h"
#include "kitinformation.h"
-#include "makestep.h"
#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
#include "projectnodes.h"
#include "runconfiguration.h"
-#include "runcontrol.h"
#include "session.h"
#include "target.h"
#include "taskhub.h"
@@ -56,6 +55,7 @@
#include <utils/algorithm.h>
#include <utils/environment.h>
+#include <utils/fileutils.h>
#include <utils/macroexpander.h>
#include <utils/pointeralgorithm.h>
#include <utils/qtcassert.h>
@@ -454,7 +454,8 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
newBc->setBuildDirectory(BuildConfiguration::buildDirectoryFromTemplate(
project->projectDirectory(), project->projectFilePath(),
project->displayName(), newTarget->kit(),
- sourceBc->displayName(), sourceBc->buildType()));
+ sourceBc->displayName(), sourceBc->buildType(),
+ sourceBc->buildSystem()->name()));
newTarget->addBuildConfiguration(newBc);
if (sourceTarget->activeBuildConfiguration() == sourceBc)
SessionManager::setActiveBuildConfiguration(newTarget, newBc, SetActive::NoCascade);
@@ -970,18 +971,6 @@ bool Project::hasMakeInstallEquivalent() const
return d->m_hasMakeInstallEquivalent;
}
-MakeInstallCommand Project::makeInstallCommand(const Target *target, const QString &installRoot)
-{
- QTC_ASSERT(hasMakeInstallEquivalent(), return MakeInstallCommand());
- MakeInstallCommand cmd;
- if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) {
- if (const auto makeStep = bc->buildSteps()->firstOfType<MakeStep>())
- cmd.command = makeStep->makeExecutable();
- }
- cmd.arguments << "install" << ("INSTALL_ROOT=" + QDir::toNativeSeparators(installRoot));
- return cmd;
-}
-
void Project::setup(const QList<BuildInfo> &infoList)
{
std::vector<std::unique_ptr<Target>> toRegister;
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index 22495aa47a1..eaeebb100ff 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -33,9 +33,8 @@
#include <coreplugin/idocument.h>
#include <utils/environmentfwd.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
-#include <QObject>
#include <QFileSystemModel>
#include <functional>
@@ -149,7 +148,6 @@ public:
virtual DeploymentKnowledge deploymentKnowledge() const { return DeploymentKnowledge::Bad; }
bool hasMakeInstallEquivalent() const;
- virtual MakeInstallCommand makeInstallCommand(const Target *target, const QString &installRoot);
void setup(const QList<BuildInfo> &infoList);
Utils::MacroExpander *macroExpander() const;
diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp
index 0b9559a90b6..7fee92127b0 100644
--- a/src/plugins/projectexplorer/projectconfiguration.cpp
+++ b/src/plugins/projectexplorer/projectconfiguration.cpp
@@ -28,6 +28,7 @@
#include "kitinformation.h"
#include "target.h"
+#include <projectexplorer/devicesupport/idevice.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -134,23 +135,11 @@ bool ProjectConfiguration::fromMap(const QVariantMap &map)
return true;
}
-Utils::BaseAspect *ProjectConfiguration::aspect(Utils::Id id) const
+BaseAspect *ProjectConfiguration::aspect(Id id) const
{
return m_aspects.aspect(id);
}
-void ProjectConfiguration::acquaintAspects()
-{
- for (Utils::BaseAspect *aspect : m_aspects)
- aspect->acquaintSiblings(m_aspects);
-}
-
-void ProjectConfiguration::doPostInit()
-{
- for (const std::function<void()> &postInit : qAsConst(m_postInit))
- postInit();
-}
-
FilePath ProjectConfiguration::mapFromBuildDeviceToGlobalPath(const FilePath &path) const
{
IDevice::ConstPtr dev = BuildDeviceKitAspect::device(kit());
@@ -158,9 +147,9 @@ FilePath ProjectConfiguration::mapFromBuildDeviceToGlobalPath(const FilePath &pa
return dev->mapToGlobalPath(path);
}
-Utils::Id ProjectExplorer::idFromMap(const QVariantMap &map)
+Id ProjectExplorer::idFromMap(const QVariantMap &map)
{
- return Utils::Id::fromSetting(map.value(QLatin1String(CONFIGURATION_ID_KEY)));
+ return Id::fromSetting(map.value(QLatin1String(CONFIGURATION_ID_KEY)));
}
QString ProjectConfiguration::expandedDisplayName() const
diff --git a/src/plugins/projectexplorer/projectconfiguration.h b/src/plugins/projectexplorer/projectconfiguration.h
index 9263804c56a..44658b1b489 100644
--- a/src/plugins/projectexplorer/projectconfiguration.h
+++ b/src/plugins/projectexplorer/projectconfiguration.h
@@ -87,13 +87,8 @@ public:
Utils::BaseAspect *aspect(Utils::Id id) const;
template <typename T> T *aspect() const { return m_aspects.aspect<T>(); }
- void acquaintAspects();
-
Utils::FilePath mapFromBuildDeviceToGlobalPath(const Utils::FilePath &path) const;
- void addPostInit(const std::function<void()> &fixup) { m_postInit.append(fixup); }
- void doPostInit();
-
signals:
void displayNameChanged();
void toolTipChanged();
@@ -106,7 +101,6 @@ private:
const Utils::Id m_id;
Utils::DisplayName m_displayName;
QString m_toolTip;
- QList<std::function<void()>> m_postInit;
};
// helper function:
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index a8182c56bf3..27bdbcd8400 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -27,7 +27,6 @@
#include "appoutputpane.h"
#include "buildpropertiessettings.h"
-#include "buildsteplist.h"
#include "buildsystem.h"
#include "compileoutputwindow.h"
#include "configtaskhandler.h"
@@ -48,7 +47,6 @@
#include "appoutputpane.h"
#include "buildconfiguration.h"
#include "buildmanager.h"
-#include "buildsettingspropertiespage.h"
#include "codestylesettingspropertiespage.h"
#include "copytaskhandler.h"
#include "currentprojectfilter.h"
@@ -60,6 +58,7 @@
#include "devicesupport/desktopdevicefactory.h"
#include "devicesupport/devicemanager.h"
#include "devicesupport/devicesettingspage.h"
+#include "devicesupport/sshsettings.h"
#include "devicesupport/sshsettingspage.h"
#include "editorsettingspropertiespage.h"
#include "filesinallprojectsfind.h"
@@ -86,21 +85,22 @@
#include "projectwindow.h"
#include "removetaskhandler.h"
#include "runconfigurationaspects.h"
-#include "runsettingspropertiespage.h"
+#include "sanitizerparser.h"
#include "selectablefilesmodel.h"
#include "session.h"
#include "sessiondialog.h"
#include "showineditortaskhandler.h"
#include "simpleprojectwizard.h"
#include "target.h"
-#include "targetsettingspanel.h"
#include "taskhub.h"
#include "toolchainmanager.h"
#include "toolchainoptionspage.h"
#include "vcsannotatetaskhandler.h"
+#ifdef Q_OS_WIN
#include "windebuginterface.h"
#include "msvctoolchain.h"
+#endif
#include "projecttree.h"
#include "projectwelcomepage.h"
@@ -130,8 +130,6 @@
#include <coreplugin/vcsmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshsettings.h>
#include <texteditor/findinfiles.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditorconstants.h>
@@ -139,13 +137,14 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/parameteraction.h>
#include <utils/processhandle.h>
#include <utils/proxyaction.h>
#include <utils/qtcassert.h>
#include <utils/removefiledialog.h>
#include <utils/stringutils.h>
+#include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h>
#include <QAction>
@@ -334,7 +333,8 @@ static bool canOpenTerminalWithRunEnv(const Project *project, const ProjectNode
const RunConfiguration * const runConfig = runConfigForNode(target, node);
if (!runConfig)
return false;
- IDevice::ConstPtr device = runConfig->runnable().device;
+ IDevice::ConstPtr device
+ = DeviceManager::deviceForPath(runConfig->runnable().command.executable());
if (!device)
device = DeviceKitAspect::device(target->kit());
return device && device->canOpenTerminal();
@@ -394,6 +394,8 @@ class ProjectEnvironmentWidget : public NamedWidget
public:
explicit ProjectEnvironmentWidget(Project *project) : NamedWidget(tr("Project Environment"))
{
+ setUseGlobalSettingsCheckBoxVisible(false);
+ setUseGlobalSettingsLabelVisible(false);
const auto vbox = new QVBoxLayout(this);
vbox->setContentsMargins(0, 0, 0, 0);
const auto envWidget = new EnvironmentWidget(this, EnvironmentWidget::TypeLocal);
@@ -418,6 +420,42 @@ protected:
void restoreState(const QJsonObject &object) override;
};
+class RunConfigurationLocatorFilter : public Core::ILocatorFilter
+{
+public:
+ RunConfigurationLocatorFilter();
+
+ void prepareSearch(const QString &entry) override;
+ QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
+ const QString &entry) override;
+
+private:
+ void targetListUpdated();
+ QList<Core::LocatorFilterEntry> m_result;
+};
+
+class RunRunConfigurationLocatorFilter final : public RunConfigurationLocatorFilter
+{
+public:
+ RunRunConfigurationLocatorFilter();
+
+ void accept(const Core::LocatorFilterEntry &selection,
+ QString *newText,
+ int *selectionStart,
+ int *selectionLength) const final;
+};
+
+class SwitchToRunConfigurationLocatorFilter final : public RunConfigurationLocatorFilter
+{
+public:
+ SwitchToRunConfigurationLocatorFilter();
+
+ void accept(const Core::LocatorFilterEntry &selection,
+ QString *newText,
+ int *selectionStart,
+ int *selectionLength) const final;
+};
+
class ProjectExplorerPluginPrivate : public QObject
{
Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::ProjectExplorerPlugin)
@@ -498,7 +536,7 @@ public:
void checkForShutdown();
void timerEvent(QTimerEvent *) override;
- QList<QPair<QString, QString> > recentProjects() const;
+ RecentProjectsEntries recentProjects() const;
void extendFolderNavigationWidgetFactory();
@@ -584,7 +622,7 @@ public:
int m_shutdownWatchDogId = -1;
QHash<QString, std::function<Project *(const FilePath &)>> m_projectCreators;
- QList<QPair<QString, QString> > m_recentProjects; // pair of filename, displayname
+ RecentProjectsEntries m_recentProjects; // pair of filename, displayname
static const int m_maxRecentProjects = 25;
QString m_lastOpenDirectory;
@@ -652,6 +690,8 @@ public:
AllProjectsFilter m_allProjectsFilter;
CurrentProjectFilter m_currentProjectFilter;
AllProjectFilesFilter m_allProjectDirectoriesFilter;
+ RunRunConfigurationLocatorFilter m_runConfigurationLocatorFilter;
+ SwitchToRunConfigurationLocatorFilter m_switchRunConfigurationLocatorFilter;
ProcessStepFactory m_processStepFactory;
@@ -697,6 +737,7 @@ public:
cmakeRunConfigFactory.runConfigurationId()}
};
+ SanitizerOutputFormatterFactory sanitizerFormatterFactory;
};
static ProjectExplorerPlugin *m_instance = nullptr;
@@ -1174,9 +1215,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd->m_sessionManagerAction = new QAction(tr("&Manage..."), this);
dd->m_sessionMenu->addAction(dd->m_sessionManagerAction);
dd->m_sessionMenu->addSeparator();
+ cmd = ActionManager::registerAction(dd->m_sessionManagerAction,
+ "ProjectExplorer.ManageSessions");
cmd->setDefaultKeySequence(QKeySequence());
-
// unload action
dd->m_unloadAction = new ParameterAction(tr("Close Project"), tr("Close Pro&ject \"%1\""),
ParameterAction::AlwaysEnabled, this);
@@ -1681,7 +1723,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
if (tmp < 0 || tmp > int(StopBeforeBuild::SameApp))
tmp = int(defaultSettings.stopBeforeBuild);
dd->m_projectExplorerSettings.stopBeforeBuild = StopBeforeBuild(tmp);
- dd->m_projectExplorerSettings.terminalMode = static_cast<TerminalMode>(
+ dd->m_projectExplorerSettings.terminalMode = static_cast<Internal::TerminalMode>(
s->value(Constants::TERMINAL_MODE_SETTINGS_KEY, int(defaultSettings.terminalMode)).toInt());
dd->m_projectExplorerSettings.closeSourceFilesWithProject
= s->value(Constants::CLOSE_FILES_WITH_PROJECT_SETTINGS_KEY,
@@ -2207,8 +2249,10 @@ void ProjectExplorerPlugin::extensionsInitialized()
dd->m_projectFilterString = filterStrings.join(filterSeparator);
BuildManager::extensionsInitialized();
+ TaskHub::addCategory(Constants::TASK_CATEGORY_SANITIZER,
+ tr("Sanitizer", "Category for sanitizer issues listed under 'Issues'"));
- QSsh::SshSettings::loadSettings(Core::ICore::settings());
+ SshSettings::loadSettings(Core::ICore::settings());
const auto searchPathRetriever = [] {
FilePaths searchPaths = {Core::ICore::libexecPath()};
if (HostOsInfo::isWindowsHost()) {
@@ -2227,7 +2271,7 @@ void ProjectExplorerPlugin::extensionsInitialized()
}
return searchPaths;
};
- QSsh::SshSettings::setExtraSearchPathRetriever(searchPathRetriever);
+ SshSettings::setExtraSearchPathRetriever(searchPathRetriever);
const auto parseIssuesAction = new QAction(tr("Parse Build Output..."), this);
ActionContainer *mtools = ActionManager::actionContainer(Core::Constants::M_TOOLS);
@@ -2279,6 +2323,11 @@ ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown()
return AsynchronousShutdown;
}
+QVector<QObject *> ProjectExplorerPlugin::createTestObjects() const
+{
+ return SanitizerParser::createTestObjects();
+}
+
void ProjectExplorerPlugin::showSessionManager()
{
dd->showSessionManager();
@@ -2357,7 +2406,7 @@ void ProjectExplorerPluginPrivate::savePersistentSettings()
QStringList fileNames;
QStringList displayNames;
- QList<QPair<QString, QString> >::const_iterator it, end;
+ RecentProjectsEntries::const_iterator it, end;
end = dd->m_recentProjects.constEnd();
for (it = dd->m_recentProjects.constBegin(); it != end; ++it) {
fileNames << (*it).first;
@@ -2562,12 +2611,12 @@ void ProjectExplorerPluginPrivate::determineSessionToRestoreAtStartup()
// Process command line arguments first:
const bool lastSessionArg = m_instance->pluginSpec()->arguments().contains("-lastsession");
m_sessionToRestoreAtStartup = lastSessionArg ? SessionManager::startupSession() : QString();
- QStringList arguments = ExtensionSystem::PluginManager::arguments();
+ const QStringList arguments = ExtensionSystem::PluginManager::arguments();
if (!lastSessionArg) {
QStringList sessions = SessionManager::sessions();
// We have command line arguments, try to find a session in them
// Default to no session loading
- foreach (const QString &arg, arguments) {
+ for (const QString &arg : arguments) {
if (sessions.contains(arg)) {
// Session argument
m_sessionToRestoreAtStartup = arg;
@@ -2684,7 +2733,7 @@ void ProjectExplorerPluginPrivate::executeRunConfiguration(RunConfiguration *run
}
auto runControl = new RunControl(runMode);
- runControl->setRunConfiguration(runConfiguration);
+ runControl->copyDataFromRunConfiguration(runConfiguration);
// A user needed interaction may have cancelled the run
// (by example asking for a process pid or server url).
@@ -2782,9 +2831,9 @@ void ProjectExplorerPluginPrivate::buildQueueFinished(bool success)
doUpdateRunActions();
}
-QList<QPair<QString, QString> > ProjectExplorerPluginPrivate::recentProjects() const
+RecentProjectsEntries ProjectExplorerPluginPrivate::recentProjects() const
{
- return Utils::filtered(dd->m_recentProjects, [](const QPair<QString, QString> &p) {
+ return Utils::filtered(dd->m_recentProjects, [](const RecentProjectsEntry &p) {
return QFileInfo(p.first).isFile();
});
}
@@ -3045,7 +3094,7 @@ static QPair<bool, QString> subprojectEnabledState(const Project *pro)
result.first = true;
const QList<Project *> &projects = SessionManager::projectOrder(pro);
- foreach (Project *project, projects) {
+ for (const Project *project : projects) {
if (project && project->activeTarget()
&& project->activeTarget()->activeBuildConfiguration()
&& !project->activeTarget()->activeBuildConfiguration()->isEnabled()) {
@@ -3198,12 +3247,13 @@ void ProjectExplorerPlugin::runRunConfiguration(RunConfiguration *rc,
dd->doUpdateRunActions();
}
-QList<QPair<Runnable, ProcessHandle>> ProjectExplorerPlugin::runningRunControlProcesses()
+QList<QPair<CommandLine, ProcessHandle>> ProjectExplorerPlugin::runningRunControlProcesses()
{
- QList<QPair<Runnable, ProcessHandle>> processes;
- foreach (RunControl *rc, allRunControls()) {
+ QList<QPair<CommandLine, ProcessHandle>> processes;
+ const QList<RunControl *> runControls = allRunControls();
+ for (RunControl *rc : runControls) {
if (rc->isRunning())
- processes << qMakePair(rc->runnable(), rc->applicationProcessHandle());
+ processes << qMakePair(rc->commandLine(), rc->applicationProcessHandle());
}
return processes;
}
@@ -3368,7 +3418,7 @@ void ProjectExplorerPluginPrivate::addToRecentProjects(const QString &fileName,
return;
QString prettyFileName(QDir::toNativeSeparators(fileName));
- QList<QPair<QString, QString> >::iterator it;
+ RecentProjectsEntries::iterator it;
for (it = m_recentProjects.begin(); it != m_recentProjects.end();)
if ((*it).first == prettyFileName)
it = m_recentProjects.erase(it);
@@ -3397,13 +3447,13 @@ void ProjectExplorerPluginPrivate::updateUnloadProjectMenu()
void ProjectExplorerPluginPrivate::updateRecentProjectMenu()
{
- using StringPairListConstIterator = QList<QPair<QString, QString> >::const_iterator;
+ using StringPairListConstIterator = RecentProjectsEntries::const_iterator;
ActionContainer *aci = ActionManager::actionContainer(Constants::M_RECENTPROJECTS);
QMenu *menu = aci->menu();
menu->clear();
int acceleratorKey = 1;
- auto projects = recentProjects();
+ const RecentProjectsEntries projects = recentProjects();
//projects (ignore sessions, they used to be in this list)
const StringPairListConstIterator end = projects.constEnd();
for (StringPairListConstIterator it = projects.constBegin(); it != end; ++it, ++acceleratorKey) {
@@ -3452,7 +3502,7 @@ void ProjectExplorerPluginPrivate::removeFromRecentProjects(const QString &fileN
const QString &displayName)
{
QTC_ASSERT(!fileName.isEmpty() && !displayName.isEmpty(), return);
- QTC_CHECK(m_recentProjects.removeOne(QPair<QString, QString>(fileName, displayName)));
+ QTC_CHECK(m_recentProjects.removeOne(RecentProjectsEntry(fileName, displayName)));
}
void ProjectExplorerPluginPrivate::invalidateProject(Project *project)
@@ -3528,7 +3578,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions(Node *currentNode)
m_runActionContextMenu->setData(QVariant::fromValue(runConfigs.first()));
} else if (runConfigs.count() > 1) {
runMenu->menu()->menuAction()->setVisible(true);
- foreach (RunConfiguration *rc, runConfigs) {
+ for (RunConfiguration *rc : qAsConst(runConfigs)) {
auto *act = new QAction(runMenu->menu());
act->setData(QVariant::fromValue(rc));
act->setText(tr("Run %1").arg(rc->displayName()));
@@ -3887,7 +3937,7 @@ void ProjectExplorerPluginPrivate::openTerminalHereWithRunEnv()
QTC_ASSERT(runConfig, return);
const Runnable runnable = runConfig->runnable();
- IDevice::ConstPtr device = runnable.device;
+ IDevice::ConstPtr device = DeviceManager::deviceForPath(runnable.command.executable());
if (!device)
device = DeviceKitAspect::device(target->kit());
QTC_ASSERT(device && device->canOpenTerminal(), return);
@@ -4302,7 +4352,7 @@ OutputWindow *ProjectExplorerPlugin::buildSystemOutput()
return dd->m_proWindow->buildSystemOutput();
}
-QList<QPair<QString, QString> > ProjectExplorerPlugin::recentProjects()
+RecentProjectsEntries ProjectExplorerPlugin::recentProjects()
{
return dd->recentProjects();
}
@@ -4371,4 +4421,106 @@ void AllProjectFilesFilter::restoreState(const QJsonObject &object)
DirectoryFilter::restoreState(withoutDirectories);
}
+RunConfigurationLocatorFilter::RunConfigurationLocatorFilter()
+{
+ connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
+ this, &RunConfigurationLocatorFilter::targetListUpdated);
+
+ targetListUpdated();
+}
+
+void RunConfigurationLocatorFilter::prepareSearch(const QString &entry)
+{
+ m_result.clear();
+ const Target *target = SessionManager::startupTarget();
+ if (!target)
+ return;
+ for (auto rc : target->runConfigurations()) {
+ if (rc->displayName().contains(entry, Qt::CaseInsensitive)) {
+ Core::LocatorFilterEntry filterEntry(this, rc->displayName(), {});
+ m_result.append(filterEntry);
+ }
+ }
+}
+
+QList<Core::LocatorFilterEntry> RunConfigurationLocatorFilter::matchesFor(
+ QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
+{
+ Q_UNUSED(future)
+ Q_UNUSED(entry)
+ return m_result;
+}
+
+void RunConfigurationLocatorFilter::targetListUpdated()
+{
+ setEnabled(SessionManager::startupProject()); // at least one project opened
+}
+
+static RunConfiguration *runConfigurationForDisplayName(const QString &displayName)
+{
+ const Project *project = SessionManager::instance()->startupProject();
+ if (!project)
+ return nullptr;
+ const QList<RunConfiguration *> runconfigs = project->activeTarget()->runConfigurations();
+ return Utils::findOrDefault(runconfigs, [displayName](RunConfiguration *rc) {
+ return rc->displayName() == displayName;
+ });
+}
+
+RunRunConfigurationLocatorFilter::RunRunConfigurationLocatorFilter()
+{
+ setId("Run run configuration");
+ setDisplayName(ProjectExplorerPluginPrivate::tr("Run run configuration"));
+ setDescription(ProjectExplorerPluginPrivate::tr("Run a run configuration of the current "
+ "active project"));
+ setDefaultShortcutString("rr");
+ setPriority(Medium);
+}
+
+void RunRunConfigurationLocatorFilter::accept(const LocatorFilterEntry &selection, QString *newText,
+ int *selectionStart, int *selectionLength) const
+{
+ Q_UNUSED(newText)
+ Q_UNUSED(selectionStart)
+ Q_UNUSED(selectionLength)
+
+ RunConfiguration *toStart = runConfigurationForDisplayName(selection.displayName);
+ if (!toStart)
+ return;
+ if (!BuildManager::isBuilding(toStart->project()))
+ ProjectExplorerPlugin::runRunConfiguration(toStart, Constants::NORMAL_RUN_MODE, true);
+}
+
+SwitchToRunConfigurationLocatorFilter::SwitchToRunConfigurationLocatorFilter()
+{
+ setId("Switch run configuration");
+ setDisplayName(ProjectExplorerPluginPrivate::tr("Switch run configuration"));
+ setDescription(ProjectExplorerPluginPrivate::tr("Switch active run configuration"));
+ setDefaultShortcutString("sr");
+ setPriority(Medium);
+}
+
+void SwitchToRunConfigurationLocatorFilter::accept(const LocatorFilterEntry &selection,
+ QString *newText, int *selectionStart,
+ int *selectionLength) const
+{
+ Q_UNUSED(newText)
+ Q_UNUSED(selectionStart)
+ Q_UNUSED(selectionLength)
+
+ RunConfiguration *toSwitchTo = runConfigurationForDisplayName(selection.displayName);
+ if (!toSwitchTo)
+ return;
+
+ SessionManager::startupTarget()->setActiveRunConfiguration(toSwitchTo);
+ QTimer::singleShot(200, this, [displayName = selection.displayName](){
+ if (auto ks = ICore::mainWindow()->findChild<QWidget *>("KitSelector.Button")) {
+ Utils::ToolTip::show(ks->mapToGlobal(QPoint{25, 25}),
+ ProjectExplorerPluginPrivate::tr(
+ "Switched run configuration to\n%1").arg(displayName),
+ ICore::dialogParent());
+ }
+ });
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index 9333367d592..563a380b1bb 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -64,6 +64,9 @@ class MiniProjectTargetSelector;
class ProjectExplorerSettings;
}
+using RecentProjectsEntry = QPair<QString, QString>;
+using RecentProjectsEntries = QList<RecentProjectsEntry>;
+
class PROJECTEXPLORER_EXPORT ProjectExplorerPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -131,6 +134,7 @@ public:
void extensionsInitialized() override;
void restoreKits();
ShutdownFlag aboutToShutdown() override;
+ QVector<QObject *> createTestObjects() const override;
static void setProjectExplorerSettings(const Internal::ProjectExplorerSettings &pes);
static const Internal::ProjectExplorerSettings &projectExplorerSettings();
@@ -153,14 +157,14 @@ public:
static void renameFile(Node *node, const QString &newFilePath);
static QStringList projectFilePatterns();
static bool isProjectFile(const Utils::FilePath &filePath);
- static QList<QPair<QString, QString> > recentProjects();
+ static RecentProjectsEntries recentProjects();
static bool canRunStartupProject(Utils::Id runMode, QString *whyNot = nullptr);
static void runProject(Project *pro, Utils::Id, const bool forceSkipDeploy = false);
static void runStartupProject(Utils::Id runMode, bool forceSkipDeploy = false);
static void runRunConfiguration(RunConfiguration *rc, Utils::Id runMode,
const bool forceSkipDeploy = false);
- static QList<QPair<Runnable, Utils::ProcessHandle>> runningRunControlProcesses();
+ static QList<QPair<Utils::CommandLine, Utils::ProcessHandle>> runningRunControlProcesses();
static QList<RunControl *> allRunControls();
static void addExistingFiles(FolderNode *folderNode, const Utils::FilePaths &filePaths);
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index 69baa7acc75..1843cf63719 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -6,7 +6,6 @@ Project {
QtcPlugin {
Depends { name: "Qt"; submodules: ["widgets", "xml", "network", "qml"] }
Depends { name: "Aggregation" }
- Depends { name: "QtcSsh" }
Depends { name: "Utils" }
Depends { name: "Core" }
@@ -27,7 +26,6 @@ Project {
"addrunconfigdialog.cpp", "addrunconfigdialog.h",
"allprojectsfilter.cpp", "allprojectsfilter.h",
"allprojectsfind.cpp", "allprojectsfind.h",
- "applicationlauncher.cpp", "applicationlauncher.h",
"appoutputpane.cpp", "appoutputpane.h",
"baseprojectwizarddialog.cpp", "baseprojectwizarddialog.h",
"buildaspects.cpp", "buildaspects.h",
@@ -121,6 +119,7 @@ Project {
"projectmodels.cpp", "projectmodels.h",
"projectnodes.cpp", "projectnodes.h",
"projectpanelfactory.cpp", "projectpanelfactory.h",
+ "projectsettingswidget.cpp", "projectsettingswidget.h",
"projecttree.cpp",
"projecttree.h",
"projecttreewidget.cpp", "projecttreewidget.h",
@@ -132,6 +131,7 @@ Project {
"runcontrol.cpp", "runcontrol.h",
"runconfigurationaspects.cpp", "runconfigurationaspects.h",
"runsettingspropertiespage.cpp", "runsettingspropertiespage.h",
+ "sanitizerparser.cpp", "sanitizerparser.h",
"selectablefilesmodel.cpp", "selectablefilesmodel.h",
"session.cpp", "session.h",
"sessionmodel.cpp", "sessionmodel.h",
@@ -158,6 +158,7 @@ Project {
"userfileaccessor.cpp", "userfileaccessor.h",
"vcsannotatetaskhandler.cpp", "vcsannotatetaskhandler.h",
"waitforstopdialog.cpp", "waitforstopdialog.h",
+ "windebuginterface.cpp", "windebuginterface.h",
"xcodebuildparser.cpp", "xcodebuildparser.h"
]
}
@@ -209,22 +210,25 @@ Project {
"desktopdevicefactory.cpp", "desktopdevicefactory.h",
"devicecheckbuildstep.cpp", "devicecheckbuildstep.h",
"devicefactoryselectiondialog.cpp", "devicefactoryselectiondialog.h", "devicefactoryselectiondialog.ui",
+ "devicefilesystemmodel.cpp", "devicefilesystemmodel.h",
"devicemanager.cpp", "devicemanager.h",
"devicemanagermodel.cpp", "devicemanagermodel.h",
- "deviceprocess.cpp", "deviceprocess.h",
"deviceprocessesdialog.cpp", "deviceprocessesdialog.h",
"deviceprocesslist.cpp", "deviceprocesslist.h",
"devicesettingspage.cpp", "devicesettingspage.h",
"devicesettingswidget.cpp", "devicesettingswidget.h", "devicesettingswidget.ui",
"devicetestdialog.cpp", "devicetestdialog.h", "devicetestdialog.ui",
"deviceusedportsgatherer.cpp", "deviceusedportsgatherer.h",
+ "filetransfer.cpp", "filetransfer.h",
+ "filetransferinterface.h",
"idevice.cpp", "idevice.h",
"idevicefactory.cpp", "idevicefactory.h",
+ "idevicefwd.h",
"idevicewidget.h",
- "desktopdeviceprocess.cpp", "desktopdeviceprocess.h",
"localprocesslist.cpp", "localprocesslist.h",
- "sshdeviceprocess.cpp", "sshdeviceprocess.h",
"sshdeviceprocesslist.cpp", "sshdeviceprocesslist.h",
+ "sshparameters.cpp", "sshparameters.h",
+ "sshsettings.cpp", "sshsettings.h",
"sshsettingspage.cpp", "sshsettingspage.h",
"desktopprocesssignaloperation.cpp", "desktopprocesssignaloperation.h"
]
@@ -242,8 +246,6 @@ Project {
files: [
"msvctoolchain.cpp",
"msvctoolchain.h",
- "windebuginterface.cpp",
- "windebuginterface.h",
]
}
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index fcc2db0072b..94cba518594 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -131,6 +131,7 @@ const char TASK_CATEGORY_COMPILE[] = "Task.Category.Compile";
const char TASK_CATEGORY_BUILDSYSTEM[] = "Task.Category.Buildsystem";
const char TASK_CATEGORY_DEPLOYMENT[] = "Task.Category.Deploy";
const char TASK_CATEGORY_AUTOTEST[] = "Task.Category.Autotest";
+const char TASK_CATEGORY_SANITIZER[] = "Task.Category.Analyzer";
// Wizard categories
const char QT_PROJECT_WIZARD_CATEGORY[] = "H.Project";
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp
index 52b20b3ad08..692e1da7e3a 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.cpp
+++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp
@@ -24,34 +24,36 @@
****************************************************************************/
#include "projectfilewizardextension.h"
-#include "projectexplorer.h"
-#include "session.h"
+
+#include "editorconfiguration.h"
+#include "project.h"
+#include "projectexplorerconstants.h"
#include "projectnodes.h"
#include "projecttree.h"
+#include "projecttree.h"
#include "projectwizardpage.h"
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-#include <utils/stringutils.h>
+#include "session.h"
#include <coreplugin/icore.h>
-#include <projectexplorer/editorconfiguration.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projecttree.h>
+
#include <texteditor/icodestylepreferences.h>
#include <texteditor/icodestylepreferencesfactory.h>
#include <texteditor/storagesettings.h>
#include <texteditor/tabsettings.h>
#include <texteditor/texteditorsettings.h>
#include <texteditor/textindenter.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <QPointer>
+#include <utils/algorithm.h>
+#include <utils/mimeutils.h>
+#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
+
#include <QDebug>
#include <QFileInfo>
-#include <QTextDocument>
-#include <QTextCursor>
#include <QMessageBox>
+#include <QPointer>
+#include <QTextCursor>
+#include <QTextDocument>
using namespace TextEditor;
using namespace Core;
@@ -76,7 +78,6 @@ using namespace Utils;
enum { debugExtension = 0 };
namespace ProjectExplorer {
-
namespace Internal {
// --------- ProjectWizardContext
@@ -244,7 +245,7 @@ void ProjectFileWizardExtension::applyCodeStyle(GeneratedFile *file) const
if (file->isBinary() || file->contents().isEmpty())
return; // nothing to do
- Id languageId = TextEditorSettings::languageId(Utils::mimeTypeForFile(file->path()).name());
+ Id languageId = TextEditorSettings::languageId(Utils::mimeTypeForFile(file->filePath()).name());
if (!languageId.isValid())
return; // don't modify files like *.ui *.pro
diff --git a/src/plugins/projectexplorer/projectimporter.cpp b/src/plugins/projectexplorer/projectimporter.cpp
index e69a1413612..e51aaa2c968 100644
--- a/src/plugins/projectexplorer/projectimporter.cpp
+++ b/src/plugins/projectexplorer/projectimporter.cpp
@@ -82,7 +82,8 @@ ProjectImporter::ProjectImporter(const Utils::FilePath &path) : m_projectPath(pa
ProjectImporter::~ProjectImporter()
{
- foreach (Kit *k, KitManager::kits())
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *k : kits)
removeProject(k);
}
@@ -134,7 +135,7 @@ const QList<BuildInfo> ProjectImporter::import(const Utils::FilePath &importPath
}
qCDebug(log) << "Looking for kits";
- foreach (void *data, dataList) {
+ for (void *data : qAsConst(dataList)) {
QTC_ASSERT(data, continue);
QList<Kit *> kitList;
const QList<Kit *> tmp
@@ -149,7 +150,7 @@ const QList<BuildInfo> ProjectImporter::import(const Utils::FilePath &importPath
qCDebug(log) << " " << tmp.count() << "matching kits found.";
}
- foreach (Kit *k, kitList) {
+ for (Kit *k : qAsConst(kitList)) {
qCDebug(log) << "Creating buildinfos for kit" << k->displayName();
const QList<BuildInfo> infoList = buildInfoList(data);
if (infoList.isEmpty()) {
@@ -167,7 +168,7 @@ const QList<BuildInfo> ProjectImporter::import(const Utils::FilePath &importPath
}
}
- foreach (auto *dd, dataList)
+ for (void *dd : qAsConst(dataList))
deleteDirectoryData(dd);
dataList.clear();
@@ -189,7 +190,7 @@ Target *ProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
activeTarget = possibleTargets.at(0);
bool pickedFallback = false;
- foreach (Target *t, possibleTargets) {
+ for (Target *t : possibleTargets) {
if (t->kit() == KitManager::defaultKit())
return t;
if (pickedFallback)
@@ -234,12 +235,13 @@ void ProjectImporter::makePersistent(Kit *k) const
k->removeKey(KIT_TEMPORARY_NAME);
k->removeKey(KIT_FINAL_NAME);
- foreach (const TemporaryInformationHandler &tih, m_temporaryHandlers) {
+ for (const TemporaryInformationHandler &tih : qAsConst(m_temporaryHandlers)) {
const Utils::Id fid = fullId(tih.id);
const QVariantList temporaryValues = k->value(fid).toList();
// Mark permanent in all other kits:
- foreach (Kit *ok, KitManager::kits()) {
+ const QList<Kit *> kits = KitManager::kits();
+ for (Kit *ok : kits) {
if (ok == k || !ok->hasValue(fid))
continue;
const QVariantList otherTemporaryValues
@@ -258,7 +260,7 @@ void ProjectImporter::makePersistent(Kit *k) const
void ProjectImporter::cleanupKit(Kit *k) const
{
QTC_ASSERT(k, return);
- foreach (const TemporaryInformationHandler &tih, m_temporaryHandlers) {
+ for (const TemporaryInformationHandler &tih : qAsConst(m_temporaryHandlers)) {
const Utils::Id fid = fullId(tih.id);
const QVariantList temporaryValues
= Utils::filtered(k->value(fid).toList(), [fid, k](const QVariant &v) {
@@ -412,9 +414,7 @@ ProjectImporter::findOrCreateToolChains(const ToolChainDescription &tcd) const
{
ToolChainData result;
result.tcs = ToolChainManager::toolchains([&tcd](const ToolChain *tc) {
- return tc->language() == tcd.language &&
- Utils::Environment::systemEnvironment().isSameExecutable(
- tc->compilerCommand().toString(), tcd.compilerPath.toString());
+ return tc->language() == tcd.language && tc->matchesCompilerCommand(tcd.compilerPath);
});
for (const ToolChain *tc : qAsConst(result.tcs)) {
const QByteArray tcId = tc->id();
diff --git a/src/plugins/projectexplorer/projectmacro.cpp b/src/plugins/projectexplorer/projectmacro.cpp
index 4a6ca945c97..5692382aa88 100644
--- a/src/plugins/projectexplorer/projectmacro.cpp
+++ b/src/plugins/projectexplorer/projectmacro.cpp
@@ -63,16 +63,6 @@ QByteArray Macro::toByteArray(const Macros &macros)
return text;
}
-QByteArray Macro::toByteArray(const QVector<Macros> &macrosVector)
-{
- QByteArray text;
-
- for (const Macros &macros : macrosVector)
- text += toByteArray(macros);
-
- return text;
-}
-
Macros Macro::toMacros(const QByteArray &text)
{
return tokensLinesToMacros(tokenizeLines(splitLines(text)));
diff --git a/src/plugins/projectexplorer/projectmacro.h b/src/plugins/projectexplorer/projectmacro.h
index 0cdef8fee3e..059f630841e 100644
--- a/src/plugins/projectexplorer/projectmacro.h
+++ b/src/plugins/projectexplorer/projectmacro.h
@@ -61,7 +61,6 @@ public:
QByteArray toByteArray() const;
static QByteArray toByteArray(const Macros &macros);
- static QByteArray toByteArray(const QVector<Macros> &macross);
static Macros toMacros(const QByteArray &text);
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index 7b6866f92a6..61dfff43d05 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -39,8 +39,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/mimetypes/mimetype.h>
+#include <utils/mimeutils.h>
#include <utils/pointeralgorithm.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
@@ -89,7 +88,7 @@ static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder,
parts[0].prepend('/');
ProjectExplorer::FolderNode *parent = folder;
- foreach (const QString &part, parts) {
+ for (const QString &part : qAsConst(parts)) {
path = path.pathAppended(part);
// Find folder in subFolders
FolderNode *next = parent->folderNode(path);
@@ -353,7 +352,8 @@ FilePath Node::pathOrDirectory(bool dir) const
} else {
// Otherwise we figure out a commonPath from the subfolders
QStringList list;
- foreach (FolderNode *f, folder->folderNodes())
+ const QList<FolderNode *> folders = folder->folderNodes();
+ for (FolderNode *f : folders)
list << f->filePath().toString() + QLatin1Char('/');
location = FilePath::fromString(Utils::commonPath(list));
}
@@ -1094,4 +1094,28 @@ QIcon DirectoryIcon::icon() const
return icon;
}
+ResourceFileNode::ResourceFileNode(const FilePath &filePath, const QString &qrcPath, const QString &displayName)
+ : FileNode(filePath, FileNode::fileTypeForFileName(filePath))
+ , m_qrcPath(qrcPath)
+ , m_displayName(displayName)
+{
+}
+
+QString ResourceFileNode::displayName() const
+{
+ return m_displayName;
+}
+
+QString ResourceFileNode::qrcPath() const
+{
+ return m_qrcPath;
+}
+
+bool ResourceFileNode::supportsAction(ProjectAction action, const Node *node) const
+{
+ if (action == HidePathActions)
+ return false;
+ return parentFolderNode()->supportsAction(action, node);
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index c5cd68a4c53..9e2e4e9474d 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -464,6 +464,20 @@ private:
Project *m_project;
};
+class PROJECTEXPLORER_EXPORT ResourceFileNode : public ProjectExplorer::FileNode
+{
+public:
+ ResourceFileNode(const Utils::FilePath &filePath, const QString &qrcPath, const QString &displayName);
+
+ QString displayName() const override;
+ QString qrcPath() const;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
+
+private:
+ QString m_qrcPath;
+ QString m_displayName;
+};
+
} // namespace ProjectExplorer
Q_DECLARE_METATYPE(ProjectExplorer::Node *)
diff --git a/src/plugins/projectexplorer/projectnodeshelper.h b/src/plugins/projectexplorer/projectnodeshelper.h
index 6e159571517..f1517906fd3 100644
--- a/src/plugins/projectexplorer/projectnodeshelper.h
+++ b/src/plugins/projectexplorer/projectnodeshelper.h
@@ -31,7 +31,7 @@
#include <coreplugin/vcsmanager.h>
#include <utils/algorithm.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
namespace ProjectExplorer {
@@ -40,9 +40,8 @@ QList<FileNode *> scanForFiles(QFutureInterface<Result> &future,
const Utils::FilePath &directory,
const std::function<FileNode *(const Utils::FilePath &)> factory);
-// IMPLEMENTATION:
-
namespace Internal {
+
template<typename Result>
QList<FileNode *> scanForFilesRecursively(
QFutureInterface<Result> &future,
diff --git a/src/plugins/projectexplorer/projectpanelfactory.cpp b/src/plugins/projectexplorer/projectpanelfactory.cpp
index 5dca1340b1e..e96dbfdbc41 100644
--- a/src/plugins/projectexplorer/projectpanelfactory.cpp
+++ b/src/plugins/projectexplorer/projectpanelfactory.cpp
@@ -28,6 +28,8 @@
#include "project.h"
#include "projectwindow.h"
+#include <utils/layoutbuilder.h>
+
using namespace ProjectExplorer::Internal;
using namespace Utils;
@@ -90,7 +92,7 @@ void ProjectPanelFactory::setId(Utils::Id id)
m_id = id;
}
-QWidget *ProjectPanelFactory::createWidget(Project *project) const
+ProjectSettingsWidget *ProjectPanelFactory::createWidget(Project *project) const
{
return m_widgetCreator(project);
}
diff --git a/src/plugins/projectexplorer/projectpanelfactory.h b/src/plugins/projectexplorer/projectpanelfactory.h
index d1eb6500309..f5d68f8bf4d 100644
--- a/src/plugins/projectexplorer/projectpanelfactory.h
+++ b/src/plugins/projectexplorer/projectpanelfactory.h
@@ -27,8 +27,7 @@
#include "projectexplorer_export.h"
-#include "panelswidget.h"
-#include "projectwindow.h"
+#include "projectsettingswidget.h"
#include <utils/id.h>
#include <utils/treemodel.h>
@@ -57,7 +56,7 @@ public:
// interface for users of ProjectPanelFactory
bool supports(Project *project);
- using WidgetCreator = std::function<QWidget *(Project *)>;
+ using WidgetCreator = std::function<ProjectSettingsWidget *(Project *)>;
// interface for "implementations" of ProjectPanelFactory
// by default all projects are supported, only set a custom supports function
@@ -73,7 +72,7 @@ public:
Utils::TreeItem *createPanelItem(Project *project);
void setCreateWidgetFunction(const WidgetCreator &createWidgetFunction);
- QWidget *createWidget(Project *project) const;
+ ProjectSettingsWidget *createWidget(Project *project) const;
private:
friend class ProjectExplorerPlugin;
diff --git a/src/plugins/projectexplorer/projectsettingswidget.cpp b/src/plugins/projectexplorer/projectsettingswidget.cpp
new file mode 100644
index 00000000000..c7d9e07ce3f
--- /dev/null
+++ b/src/plugins/projectexplorer/projectsettingswidget.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "projectsettingswidget.h"
+
+namespace ProjectExplorer {
+
+ProjectSettingsWidget::ProjectSettingsWidget(QWidget *parent)
+ : QWidget(parent)
+{}
+
+void ProjectSettingsWidget::setUseGlobalSettings(bool useGlobalSettings)
+{
+ if (m_useGlobalSettings == useGlobalSettings)
+ return;
+ m_useGlobalSettings = useGlobalSettings;
+ emit useGlobalSettingsChanged(useGlobalSettings);
+}
+
+bool ProjectSettingsWidget::useGlobalSettings() const
+{
+ return m_useGlobalSettings;
+}
+
+void ProjectSettingsWidget::setUseGlobalSettingsCheckBoxEnabled(bool enabled)
+{
+ if (m_useGlobalSettingsCheckBoxEnabled == enabled)
+ return;
+ m_useGlobalSettingsCheckBoxEnabled = enabled;
+ emit useGlobalSettingsCheckBoxEnabledChanged(enabled);
+}
+
+bool ProjectSettingsWidget::isUseGlobalSettingsCheckBoxEnabled() const
+{
+ return m_useGlobalSettingsCheckBoxEnabled;
+}
+
+bool ProjectSettingsWidget::isUseGlobalSettingsCheckBoxVisible() const
+{
+ return m_useGlobalSettingsCheckBoxVisibleVisible;
+}
+
+void ProjectSettingsWidget::setUseGlobalSettingsCheckBoxVisible(bool visible)
+{
+ m_useGlobalSettingsCheckBoxVisibleVisible = visible;
+}
+
+bool ProjectSettingsWidget::isUseGlobalSettingsLabelVisible() const
+{
+ return m_useGlobalSettingsLabelVisibleVisible;
+}
+
+void ProjectSettingsWidget::setUseGlobalSettingsLabelVisible(bool visible)
+{
+ m_useGlobalSettingsLabelVisibleVisible = visible;
+}
+
+Utils::Id ProjectSettingsWidget::globalSettingsId() const
+{
+ return m_globalSettingsId;
+}
+
+void ProjectSettingsWidget::setGlobalSettingsId(Utils::Id globalId)
+{
+ m_globalSettingsId = globalId;
+}
+
+} // ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectsettingswidget.h b/src/plugins/projectexplorer/projectsettingswidget.h
new file mode 100644
index 00000000000..edc7a59c17b
--- /dev/null
+++ b/src/plugins/projectexplorer/projectsettingswidget.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "projectexplorer_export.h"
+
+#include <utils/id.h>
+
+#include <QWidget>
+
+namespace ProjectExplorer {
+
+class PROJECTEXPLORER_EXPORT ProjectSettingsWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit ProjectSettingsWidget(QWidget *parent = nullptr);
+
+ void setUseGlobalSettings(bool useGlobalSettings);
+ bool useGlobalSettings() const;
+
+ void setUseGlobalSettingsCheckBoxEnabled(bool enadled);
+ bool isUseGlobalSettingsCheckBoxEnabled() const;
+
+ bool isUseGlobalSettingsCheckBoxVisible() const;
+ bool isUseGlobalSettingsLabelVisible() const;
+ Utils::Id globalSettingsId() const;
+
+protected:
+ void setUseGlobalSettingsCheckBoxVisible(bool visible);
+ void setUseGlobalSettingsLabelVisible(bool visible);
+ void setGlobalSettingsId(Utils::Id globalId);
+
+signals:
+ void useGlobalSettingsChanged(bool useGlobalSettings);
+ void useGlobalSettingsCheckBoxEnabledChanged(bool enadled);
+
+private:
+ bool m_useGlobalSettings = true;
+ bool m_useGlobalSettingsCheckBoxEnabled = true;
+ bool m_useGlobalSettingsCheckBoxVisibleVisible = true;
+ bool m_useGlobalSettingsLabelVisibleVisible = true;
+ Utils::Id m_globalSettingsId;
+};
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp
index ee040d5a37f..9f9a35322a5 100644
--- a/src/plugins/projectexplorer/projecttree.cpp
+++ b/src/plugins/projectexplorer/projecttree.cpp
@@ -52,7 +52,9 @@
#include <QMenu>
#include <QTimer>
-namespace { const char EXTERNAL_FILE_WARNING[] = "ExternalFile"; }
+namespace {
+const char EXTERNAL_OR_GENERATED_FILE_WARNING[] = "ExternalOrGeneratedFile";
+}
using namespace Utils;
@@ -192,7 +194,7 @@ void ProjectTree::updateFromNode(Node *node)
project = SessionManager::startupProject();
setCurrent(node, project);
- foreach (ProjectTreeWidget *widget, m_projectTreeWidgets)
+ for (ProjectTreeWidget *widget : qAsConst(m_projectTreeWidgets))
widget->sync(node);
}
@@ -214,14 +216,20 @@ void ProjectTree::setCurrent(Node *node, Project *project)
}
if (Core::IDocument *document = Core::EditorManager::currentDocument()) {
- if (node) {
- disconnect(document, &Core::IDocument::changed,
- this, &ProjectTree::updateExternalFileWarning);
- document->infoBar()->removeInfo(EXTERNAL_FILE_WARNING);
- } else {
+ if (!node) {
connect(document, &Core::IDocument::changed,
this, &ProjectTree::updateExternalFileWarning,
Qt::UniqueConnection);
+ } else if (node->isGenerated()) {
+ connect(document, &Core::IDocument::changed,
+ this, &ProjectTree::updateGeneratedFileWarning,
+ Qt::UniqueConnection);
+ } else {
+ disconnect(document, &Core::IDocument::changed,
+ this, &ProjectTree::updateExternalFileWarning);
+ disconnect(document, &Core::IDocument::changed,
+ this, &ProjectTree::updateGeneratedFileWarning);
+ document->infoBar()->removeInfo(EXTERNAL_OR_GENERATED_FILE_WARNING);
}
}
@@ -304,18 +312,18 @@ void ProjectTree::changeProjectRootDirectory()
m_currentProject->changeRootProjectDirectory();
}
-void ProjectTree::updateExternalFileWarning()
+void ProjectTree::updateFileWarning(const QString &text)
{
auto document = qobject_cast<Core::IDocument *>(sender());
if (!document || document->filePath().isEmpty())
return;
Utils::InfoBar *infoBar = document->infoBar();
- Utils::Id externalFileId(EXTERNAL_FILE_WARNING);
+ Utils::Id infoId(EXTERNAL_OR_GENERATED_FILE_WARNING);
if (!document->isModified()) {
- infoBar->removeInfo(externalFileId);
+ infoBar->removeInfo(infoId);
return;
}
- if (!infoBar->canInfoBeAdded(externalFileId))
+ if (!infoBar->canInfoBeAdded(infoId))
return;
const FilePath fileName = document->filePath();
const QList<Project *> projects = SessionManager::projects();
@@ -335,9 +343,17 @@ void ProjectTree::updateExternalFileWarning()
}
}
infoBar->addInfo(
- Utils::InfoBarEntry(externalFileId,
- tr("<b>Warning:</b> This file is outside the project directory."),
- Utils::InfoBarEntry::GlobalSuppression::Enabled));
+ Utils::InfoBarEntry(infoId, text, Utils::InfoBarEntry::GlobalSuppression::Enabled));
+}
+
+void ProjectTree::updateExternalFileWarning()
+{
+ updateFileWarning(tr("<b>Warning:</b> This file is outside the project directory."));
+}
+
+void ProjectTree::updateGeneratedFileWarning()
+{
+ updateFileWarning(tr("<b>Warning:</b> This file is generated."));
}
bool ProjectTree::hasFocus(ProjectTreeWidget *widget)
diff --git a/src/plugins/projectexplorer/projecttree.h b/src/plugins/projectexplorer/projecttree.h
index 3947666d3a6..c09d3591561 100644
--- a/src/plugins/projectexplorer/projecttree.h
+++ b/src/plugins/projectexplorer/projecttree.h
@@ -132,7 +132,9 @@ private:
void updateFromFocus();
+ void updateFileWarning(const QString &text);
void updateExternalFileWarning();
+ void updateGeneratedFileWarning();
static bool hasFocus(Internal::ProjectTreeWidget *widget);
Internal::ProjectTreeWidget *currentWidget() const;
void hideContextMenu();
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index 6c5b70718ce..31f3cb0f7c8 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -25,12 +25,12 @@
#include "projecttreewidget.h"
-#include "projectexplorer.h"
-#include "projectnodes.h"
#include "project.h"
-#include "session.h"
+#include "projectexplorerconstants.h"
#include "projectmodels.h"
+#include "projectnodes.h"
#include "projecttree.h"
+#include "session.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
@@ -44,19 +44,19 @@
#include <utils/algorithm.h>
#include <utils/navigationtreeview.h>
#include <utils/progressindicator.h>
+#include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h>
+#include <QAction>
#include <QApplication>
+#include <QLineEdit>
+#include <QMenu>
+#include <QPainter>
#include <QSettings>
-
#include <QStyledItemDelegate>
-#include <QVBoxLayout>
#include <QToolButton>
-#include <QPainter>
-#include <QAction>
-#include <QLineEdit>
-#include <QMenu>
+#include <QVBoxLayout>
#include <memory>
@@ -326,7 +326,7 @@ int ProjectTreeWidget::expandedCount(Node *node)
return 0;
int count = 0;
- foreach (ProjectTreeWidget *tree, m_projectTreeWidgets) {
+ for (ProjectTreeWidget *tree : qAsConst(m_projectTreeWidgets)) {
QModelIndex idx = index;
while (idx.isValid() && idx != tree->m_view->rootIndex()) {
if (!tree->m_view->isExpanded(idx))
@@ -469,11 +469,11 @@ void ProjectTreeWidget::editCurrentItem()
const Node *node = m_model->nodeForIndex(currentIndex);
if (!node)
return;
- auto *editor = qobject_cast<QLineEdit*>(m_view->indexWidget(currentIndex));
+ auto editor = qobject_cast<QLineEdit *>(m_view->indexWidget(currentIndex));
if (!editor)
return;
- const int dotIndex = Utils::FilePath::fromString(editor->text()).completeBaseName().length();
+ const int dotIndex = FilePath::fromString(editor->text()).completeBaseName().length();
if (dotIndex > 0)
editor->setSelection(0, dotIndex);
}
diff --git a/src/plugins/projectexplorer/projecttreewidget.h b/src/plugins/projectexplorer/projecttreewidget.h
index 7b3c53c84fa..b891d86b34c 100644
--- a/src/plugins/projectexplorer/projecttreewidget.h
+++ b/src/plugins/projectexplorer/projecttreewidget.h
@@ -25,15 +25,12 @@
#pragma once
-#include "expanddata.h"
-
#include <coreplugin/inavigationwidgetfactory.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <QWidget>
#include <QModelIndex>
-#include <QSet>
QT_FORWARD_DECLARE_CLASS(QTreeView)
diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp
index 2382103d910..1c882eec664 100644
--- a/src/plugins/projectexplorer/projectwelcomepage.cpp
+++ b/src/plugins/projectexplorer/projectwelcomepage.cpp
@@ -78,15 +78,14 @@ ProjectModel::ProjectModel(QObject *parent)
int ProjectModel::rowCount(const QModelIndex &) const
{
- return ProjectExplorerPlugin::recentProjects().count();
+ return m_projects.count();
}
QVariant ProjectModel::data(const QModelIndex &index, int role) const
{
- const QList<QPair<QString, QString> > recentProjects = ProjectExplorerPlugin::recentProjects();
- if (recentProjects.count() <= index.row())
+ if (m_projects.count() <= index.row())
return {};
- QPair<QString, QString> data = recentProjects.at(index.row());
+ RecentProjectsEntry data = m_projects.at(index.row());
switch (role) {
case Qt::DisplayRole:
return data.second;
@@ -120,6 +119,7 @@ QHash<int, QByteArray> ProjectModel::roleNames() const
void ProjectModel::resetProjects()
{
beginResetModel();
+ m_projects = ProjectExplorerPlugin::recentProjects();
endResetModel();
}
diff --git a/src/plugins/projectexplorer/projectwelcomepage.h b/src/plugins/projectexplorer/projectwelcomepage.h
index f56b220529d..dca26f3e6b3 100644
--- a/src/plugins/projectexplorer/projectwelcomepage.h
+++ b/src/plugins/projectexplorer/projectwelcomepage.h
@@ -25,6 +25,8 @@
#pragma once
+#include "projectexplorer.h"
+
#include <coreplugin/iwelcomepage.h>
#include <QAbstractListModel>
@@ -49,6 +51,9 @@ public:
public slots:
void resetProjects();
+
+private:
+ RecentProjectsEntries m_projects;
};
class ProjectWelcomePage : public Core::IWelcomePage
diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp
index 8c9d3a64619..ebf6f59f78b 100644
--- a/src/plugins/projectexplorer/projectwindow.cpp
+++ b/src/plugins/projectexplorer/projectwindow.cpp
@@ -26,15 +26,16 @@
#include "projectwindow.h"
#include "buildinfo.h"
-#include "projectexplorerconstants.h"
#include "kit.h"
#include "kitmanager.h"
#include "kitoptionspage.h"
#include "panelswidget.h"
#include "project.h"
#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
#include "projectimporter.h"
#include "projectpanelfactory.h"
+#include "projectsettingswidget.h"
#include "session.h"
#include "target.h"
#include "targetsettingspanel.h"
@@ -100,52 +101,48 @@ private:
QPointer<QWidget> m_toolBar;
QPointer<FancyLineEdit> m_filterOutputLineEdit;
- QAction *m_clear;
- QAction *m_filterActionRegexp;
- QAction *m_filterActionCaseSensitive;
- QAction *m_invertFilterAction;
- QAction *m_zoomIn;
- QAction *m_zoomOut;
+ QAction m_clear;
+ QAction m_filterActionRegexp;
+ QAction m_filterActionCaseSensitive;
+ QAction m_invertFilterAction;
+ QAction m_zoomIn;
+ QAction m_zoomOut;
};
BuildSystemOutputWindow::BuildSystemOutputWindow()
: OutputWindow(Context(kBuildSystemOutputContext), "ProjectsMode.BuildSystemOutput.Zoom")
- , m_clear(new QAction)
{
setReadOnly(true);
Command *clearCommand = ActionManager::command(Core::Constants::OUTPUTPANE_CLEAR);
- m_clear->setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
- m_clear->setText(clearCommand->action()->text());
- ActionManager::registerAction(m_clear,
+ m_clear.setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
+ m_clear.setText(clearCommand->action()->text());
+ ActionManager::registerAction(&m_clear,
Core::Constants::OUTPUTPANE_CLEAR,
Context(kBuildSystemOutputContext));
- connect(m_clear, &QAction::triggered, this, [this] { clear(); });
+ connect(&m_clear, &QAction::triggered, this, &OutputWindow::clear);
- m_filterActionRegexp = new QAction(this);
- m_filterActionRegexp->setCheckable(true);
- m_filterActionRegexp->setText(ProjectWindow::tr("Use Regular Expressions"));
- connect(m_filterActionRegexp, &QAction::toggled, this, &BuildSystemOutputWindow::updateFilter);
- Core::ActionManager::registerAction(m_filterActionRegexp,
+ m_filterActionRegexp.setCheckable(true);
+ m_filterActionRegexp.setText(ProjectWindow::tr("Use Regular Expressions"));
+ connect(&m_filterActionRegexp, &QAction::toggled, this, &BuildSystemOutputWindow::updateFilter);
+ Core::ActionManager::registerAction(&m_filterActionRegexp,
kRegExpActionId,
Context(Constants::C_PROJECTEXPLORER));
- m_filterActionCaseSensitive = new QAction(this);
- m_filterActionCaseSensitive->setCheckable(true);
- m_filterActionCaseSensitive->setText(ProjectWindow::tr("Case Sensitive"));
- connect(m_filterActionCaseSensitive,
+ m_filterActionCaseSensitive.setCheckable(true);
+ m_filterActionCaseSensitive.setText(ProjectWindow::tr("Case Sensitive"));
+ connect(&m_filterActionCaseSensitive,
&QAction::toggled,
this,
&BuildSystemOutputWindow::updateFilter);
- Core::ActionManager::registerAction(m_filterActionCaseSensitive,
+ Core::ActionManager::registerAction(&m_filterActionCaseSensitive,
kCaseSensitiveActionId,
Context(Constants::C_PROJECTEXPLORER));
- m_invertFilterAction = new QAction(this);
- m_invertFilterAction->setCheckable(true);
- m_invertFilterAction->setText(ProjectWindow::tr("Show Non-matching Lines"));
- connect(m_invertFilterAction, &QAction::toggled, this, &BuildSystemOutputWindow::updateFilter);
- Core::ActionManager::registerAction(m_invertFilterAction,
+ m_invertFilterAction.setCheckable(true);
+ m_invertFilterAction.setText(ProjectWindow::tr("Show Non-matching Lines"));
+ connect(&m_invertFilterAction, &QAction::toggled, this, &BuildSystemOutputWindow::updateFilter);
+ Core::ActionManager::registerAction(&m_invertFilterAction,
kInvertActionId,
Context(Constants::C_PROJECTEXPLORER));
@@ -155,17 +152,15 @@ BuildSystemOutputWindow::BuildSystemOutputWindow()
[this] { setBaseFont(TextEditor::TextEditorSettings::fontSettings().font()); });
setBaseFont(TextEditor::TextEditorSettings::fontSettings().font());
- m_zoomIn = new QAction;
- m_zoomIn->setIcon(Utils::Icons::PLUS_TOOLBAR.icon());
- connect(m_zoomIn, &QAction::triggered, this, [this] { zoomIn(); });
- ActionManager::registerAction(m_zoomIn,
+ m_zoomIn.setIcon(Utils::Icons::PLUS_TOOLBAR.icon());
+ connect(&m_zoomIn, &QAction::triggered, this, [this] { zoomIn(); });
+ ActionManager::registerAction(&m_zoomIn,
Core::Constants::ZOOM_IN,
Context(kBuildSystemOutputContext));
- m_zoomOut = new QAction;
- m_zoomOut->setIcon(Utils::Icons::MINUS.icon());
- connect(m_zoomOut, &QAction::triggered, this, [this] { zoomOut(); });
- ActionManager::registerAction(m_zoomOut,
+ m_zoomOut.setIcon(Utils::Icons::MINUS.icon());
+ connect(&m_zoomOut, &QAction::triggered, this, [this] { zoomOut(); });
+ ActionManager::registerAction(&m_zoomOut,
Core::Constants::ZOOM_OUT,
Context(kBuildSystemOutputContext));
}
@@ -175,8 +170,8 @@ QWidget *BuildSystemOutputWindow::toolBar()
if (!m_toolBar) {
m_toolBar = new StyledBar(this);
auto clearButton = new CommandButton(Core::Constants::OUTPUTPANE_CLEAR);
- clearButton->setDefaultAction(m_clear);
- clearButton->setToolTipBase(m_clear->text());
+ clearButton->setDefaultAction(&m_clear);
+ clearButton->setToolTipBase(m_clear.text());
m_filterOutputLineEdit = new FancyLineEdit;
m_filterOutputLineEdit->setButtonVisible(FancyLineEdit::Left, true);
@@ -200,9 +195,9 @@ QWidget *BuildSystemOutputWindow::toolBar()
});
auto zoomInButton = new CommandButton(Core::Constants::ZOOM_IN);
- zoomInButton->setDefaultAction(m_zoomIn);
+ zoomInButton->setDefaultAction(&m_zoomIn);
auto zoomOutButton = new CommandButton(Core::Constants::ZOOM_OUT);
- zoomOutButton->setDefaultAction(m_zoomOut);
+ zoomOutButton->setDefaultAction(&m_zoomOut);
auto layout = new QHBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
@@ -222,10 +217,10 @@ void BuildSystemOutputWindow::updateFilter()
if (!m_filterOutputLineEdit)
return;
updateFilterProperties(m_filterOutputLineEdit->text(),
- m_filterActionCaseSensitive->isChecked() ? Qt::CaseSensitive
+ m_filterActionCaseSensitive.isChecked() ? Qt::CaseSensitive
: Qt::CaseInsensitive,
- m_filterActionRegexp->isChecked(),
- m_invertFilterAction->isChecked());
+ m_filterActionRegexp.isChecked(),
+ m_invertFilterAction.isChecked());
}
// Standard third level for the generic case: i.e. all except for the Build/Run page
@@ -261,7 +256,7 @@ QVariant MiscSettingsPanelItem::data(int column, int role) const
if (role == PanelWidgetRole) {
if (!m_widget) {
- QWidget *widget = m_factory->createWidget(m_project);
+ ProjectSettingsWidget *widget = m_factory->createWidget(m_project);
m_widget = new PanelsWidget(m_factory->displayName(), widget);
m_widget->setFocusProxy(widget);
}
@@ -304,7 +299,8 @@ public:
: m_project(project)
{
QTC_ASSERT(m_project, return);
- foreach (ProjectPanelFactory *factory, ProjectPanelFactory::factories())
+ const QList<ProjectPanelFactory *> factories = ProjectPanelFactory::factories();
+ for (ProjectPanelFactory *factory : factories)
appendChild(new MiscSettingsPanelItem(factory, project));
}
diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp
index 10ad1b66ddd..5a6c3380e72 100644
--- a/src/plugins/projectexplorer/projectwizardpage.cpp
+++ b/src/plugins/projectexplorer/projectwizardpage.cpp
@@ -96,7 +96,7 @@ AddNewTree::AddNewTree(FolderNode *node, QList<AddNewTree *> children, const QSt
{
if (node)
m_toolTip = node->directory().toString();
- foreach (AddNewTree *child, children)
+ for (AddNewTree *child : qAsConst(children))
appendChild(child);
}
@@ -108,7 +108,7 @@ AddNewTree::AddNewTree(FolderNode *node, QList<AddNewTree *> children,
{
if (node)
m_toolTip = node->directory().toString();
- foreach (AddNewTree *child, children)
+ for (AddNewTree *child : qAsConst(children))
appendChild(child);
}
@@ -259,7 +259,8 @@ static AddNewTree *buildAddFilesTree(FolderNode *root, const FilePaths &files,
Node *contextNode, BestNodeSelector *selector)
{
QList<AddNewTree *> children;
- foreach (FolderNode *fn, root->folderNodes()) {
+ const QList<FolderNode *> folderNodes = root->folderNodes();
+ for (FolderNode *fn : folderNodes) {
AddNewTree *child = buildAddFilesTree(fn, files, contextNode, selector);
if (child)
children.append(child);
@@ -388,7 +389,8 @@ void ProjectWizardPage::initializeVersionControls()
}
} else {
// Create
- foreach (IVersionControl *vc, VcsManager::versionControls()) {
+ const QList<IVersionControl *> versionControls = VcsManager::versionControls();
+ for (IVersionControl *vc : versionControls) {
if (vc->supportsOperation(IVersionControl::CreateRepositoryOperation)) {
versionControlChoices.append(vc->displayName());
m_activeVersionControls.append(vc);
@@ -427,7 +429,7 @@ bool ProjectWizardPage::runVersionControl(const QList<GeneratedFile> &files, QSt
}
// Add files if supported.
if (versionControl->supportsOperation(IVersionControl::AddOperation)) {
- foreach (const GeneratedFile &generatedFile, files) {
+ for (const GeneratedFile &generatedFile : files) {
if (!versionControl->vcsAdd(generatedFile.filePath())) {
*errorMessage = tr("Failed to add \"%1\" to the version control system.").arg(generatedFile.path());
return false;
@@ -545,7 +547,7 @@ void ProjectWizardPage::setFiles(const QStringList &fileNames)
}
);
- foreach (const QString &f, formattedFiles)
+ for (const QString &f : qAsConst(formattedFiles))
str << QDir::toNativeSeparators(f) << '\n';
str << "</pre>";
diff --git a/src/plugins/projectexplorer/rawprojectpart.cpp b/src/plugins/projectexplorer/rawprojectpart.cpp
index 35e96b75d87..b222610446d 100644
--- a/src/plugins/projectexplorer/rawprojectpart.cpp
+++ b/src/plugins/projectexplorer/rawprojectpart.cpp
@@ -29,7 +29,6 @@
#include "buildconfiguration.h"
#include "kitinformation.h"
#include "project.h"
-#include "projectexplorerconstants.h"
#include "target.h"
#include <utils/algorithm.h>
@@ -165,7 +164,7 @@ KitInfo::KitInfo(Kit *kit)
}
// Sysroot
- sysRootPath = SysRootKitAspect::sysRoot(kit).toString();
+ sysRootPath = SysRootKitAspect::sysRoot(kit);
}
bool KitInfo::isValid() const
@@ -174,7 +173,7 @@ bool KitInfo::isValid() const
}
ToolChainInfo::ToolChainInfo(const ToolChain *toolChain,
- const QString &sysRootPath,
+ const Utils::FilePath &sysRootPath,
const Utils::Environment &env)
{
if (toolChain) {
diff --git a/src/plugins/projectexplorer/rawprojectpart.h b/src/plugins/projectexplorer/rawprojectpart.h
index 3bf7d31b906..569e2fd8af9 100644
--- a/src/plugins/projectexplorer/rawprojectpart.h
+++ b/src/plugins/projectexplorer/rawprojectpart.h
@@ -138,7 +138,7 @@ public:
Utils::QtMajorVersion projectPartQtVersion = Utils::QtMajorVersion::None;
- QString sysRootPath;
+ Utils::FilePath sysRootPath;
};
class PROJECTEXPLORER_EXPORT ToolChainInfo
@@ -146,7 +146,7 @@ class PROJECTEXPLORER_EXPORT ToolChainInfo
public:
ToolChainInfo() = default;
ToolChainInfo(const ProjectExplorer::ToolChain *toolChain,
- const QString &sysRootPath,
+ const Utils::FilePath &sysRootPath,
const Utils::Environment &env);
bool isValid() const { return type.isValid(); }
@@ -161,7 +161,7 @@ public:
Utils::FilePath installDir;
QStringList extraCodeModelFlags;
- QString sysRootPath; // For headerPathsRunner.
+ Utils::FilePath sysRootPath; // For headerPathsRunner.
ProjectExplorer::ToolChain::BuiltInHeaderPathsRunner headerPathsRunner;
ProjectExplorer::ToolChain::MacroInspectionRunner macroInspectionRunner;
};
diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp
index 430eadb8dae..f1e2d92c839 100644
--- a/src/plugins/projectexplorer/runconfiguration.cpp
+++ b/src/plugins/projectexplorer/runconfiguration.cpp
@@ -25,7 +25,6 @@
#include "runconfiguration.h"
-#include "abi.h"
#include "buildconfiguration.h"
#include "buildsystem.h"
#include "environmentaspect.h"
@@ -33,12 +32,18 @@
#include "kitinformation.h"
#include "project.h"
#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
#include "projectnodes.h"
#include "runconfigurationaspects.h"
#include "runcontrol.h"
#include "session.h"
#include "target.h"
-#include "toolchain.h"
+
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
@@ -49,9 +54,6 @@
#include <utils/utilsicons.h>
#include <utils/variablechooser.h>
-#include <coreplugin/icontext.h>
-#include <coreplugin/icore.h>
-
#include <QDir>
#include <QFormLayout>
#include <QHash>
@@ -93,7 +95,10 @@ void ISettingsAspect::setConfigWidgetCreator(const ConfigWidgetCreator &configWi
//
///////////////////////////////////////////////////////////////////////
-GlobalOrProjectAspect::GlobalOrProjectAspect() = default;
+GlobalOrProjectAspect::GlobalOrProjectAspect()
+{
+ addDataExtractor(this, &GlobalOrProjectAspect::currentSettings, &Data::currentSettings);
+}
GlobalOrProjectAspect::~GlobalOrProjectAspect()
{
@@ -212,14 +217,10 @@ RunConfiguration::RunConfiguration(Target *target, Utils::Id id)
executable = executableAspect->executable();
QString arguments;
if (const auto argumentsAspect = aspect<ArgumentsAspect>())
- arguments = argumentsAspect->arguments(macroExpander());
+ arguments = argumentsAspect->arguments();
+
return CommandLine{executable, arguments, CommandLine::Raw};
};
-
- addPostInit([this] {
- if (const auto wdAspect = aspect<WorkingDirectoryAspect>())
- wdAspect->setMacroExpander(&m_expander);
- });
}
RunConfiguration::~RunConfiguration() = default;
@@ -264,14 +265,22 @@ void RunConfiguration::addAspectFactory(const AspectFactory &aspectFactory)
theAspectFactories.push_back(aspectFactory);
}
-QMap<Utils::Id, QVariantMap> RunConfiguration::aspectData() const
+QMap<Utils::Id, QVariantMap> RunConfiguration::settingsData() const
{
QMap<Utils::Id, QVariantMap> data;
- for (BaseAspect *aspect : qAsConst(m_aspects))
+ for (BaseAspect *aspect : m_aspects)
aspect->toActiveMap(data[aspect->id()]);
return data;
}
+AspectContainerData RunConfiguration::aspectData() const
+{
+ AspectContainerData data;
+ for (BaseAspect *aspect : m_aspects)
+ data.append(aspect->extractData());
+ return data;
+}
+
BuildSystem *RunConfiguration::activeBuildSystem() const
{
return target()->buildSystem();
@@ -573,8 +582,6 @@ RunConfiguration *RunConfigurationFactory::create(Target *target) const
for (const RunConfiguration::AspectFactory &factory : theAspectFactories)
rc->m_aspects.registerAspect(factory(target));
- rc->acquaintAspects();
- rc->doPostInit();
return rc;
}
diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h
index fe0ebb530be..318fafae329 100644
--- a/src/plugins/projectexplorer/runconfiguration.h
+++ b/src/plugins/projectexplorer/runconfiguration.h
@@ -26,9 +26,7 @@
#pragma once
#include "buildtargetinfo.h"
-#include "devicesupport/idevice.h"
#include "projectconfiguration.h"
-#include "projectexplorerconstants.h"
#include "task.h"
#include <utils/aspects.h>
@@ -105,6 +103,11 @@ public:
ISettingsAspect *globalSettings() const { return m_globalSettings; }
ISettingsAspect *currentSettings() const;
+ struct Data : Utils::BaseAspect::Data
+ {
+ ISettingsAspect *currentSettings = nullptr;
+ };
+
protected:
friend class RunConfiguration;
void fromMap(const QVariantMap &map) override;
@@ -163,7 +166,8 @@ public:
addAspectFactory([](Target *target) { return new T(target); });
}
- QMap<Utils::Id, QVariantMap> aspectData() const;
+ QMap<Utils::Id, QVariantMap> settingsData() const; // FIXME: Merge into aspectData?
+ Utils::AspectContainerData aspectData() const;
void update();
@@ -276,3 +280,5 @@ private:
};
} // namespace ProjectExplorer
+
+Q_DECLARE_METATYPE(ProjectExplorer::ISettingsAspect *);
diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp
index 2291a86fbda..eefe7ac4116 100644
--- a/src/plugins/projectexplorer/runconfigurationaspects.cpp
+++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp
@@ -25,13 +25,17 @@
#include "runconfigurationaspects.h"
+#include "devicesupport/devicemanager.h"
+#include "devicesupport/idevice.h"
#include "environmentaspect.h"
-#include "project.h"
+#include "kitinformation.h"
#include "projectexplorer.h"
#include "projectexplorersettings.h"
-#include "runconfiguration.h"
#include "target.h"
+#include <coreplugin/icore.h>
+
+#include <utils/algorithm.h>
#include <utils/detailsbutton.h>
#include <utils/fancylineedit.h>
#include <utils/layoutbuilder.h>
@@ -40,11 +44,13 @@
#include <utils/utilsicons.h>
#include <QCheckBox>
+#include <QComboBox>
#include <QLabel>
#include <QLineEdit>
#include <QFormLayout>
#include <QPlainTextEdit>
#include <QToolButton>
+#include <QPushButton>
using namespace Utils;
@@ -65,6 +71,8 @@ TerminalAspect::TerminalAspect()
setDisplayName(tr("Terminal"));
setId("TerminalAspect");
setSettingsKey("RunConfiguration.UseTerminal");
+ addDataExtractor(this, &TerminalAspect::useTerminal, &Data::useTerminal);
+ addDataExtractor(this, &TerminalAspect::isUserSet, &Data::isUserSet);
calculateUseTerminal();
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
this, &TerminalAspect::calculateUseTerminal);
@@ -162,7 +170,9 @@ bool TerminalAspect::isUserSet() const
working directory for running the executable.
*/
-WorkingDirectoryAspect::WorkingDirectoryAspect()
+WorkingDirectoryAspect::WorkingDirectoryAspect(const MacroExpander *expander,
+ EnvironmentAspect *envAspect)
+ : m_envAspect(envAspect), m_macroExpander(expander)
{
setDisplayName(tr("Working Directory"));
setId("WorkingDirectoryAspect");
@@ -205,11 +215,6 @@ void WorkingDirectoryAspect::addToLayout(LayoutBuilder &builder)
builder.addItems({tr("Working directory:"), m_chooser.data(), m_resetButton.data()});
}
-void WorkingDirectoryAspect::acquaintSiblings(const AspectContainer &siblings)
-{
- m_envAspect = siblings.aspect<EnvironmentAspect>();
-}
-
void WorkingDirectoryAspect::resetPath()
{
m_chooser->setFilePath(m_defaultWorkingDirectory);
@@ -293,11 +298,6 @@ void WorkingDirectoryAspect::setDefaultWorkingDirectory(const FilePath &defaultW
}
}
-void WorkingDirectoryAspect::setMacroExpander(MacroExpander *macroExpander)
-{
- m_macroExpander = macroExpander;
-}
-
/*!
\internal
*/
@@ -315,11 +315,15 @@ PathChooser *WorkingDirectoryAspect::pathChooser() const
arguments for an executable.
*/
-ArgumentsAspect::ArgumentsAspect()
+ArgumentsAspect::ArgumentsAspect(const MacroExpander *macroExpander)
+ : m_macroExpander(macroExpander)
{
setDisplayName(tr("Arguments"));
setId("ArgumentsAspect");
setSettingsKey("RunConfiguration.Arguments");
+
+ addDataExtractor(this, &ArgumentsAspect::arguments, &Data::arguments);
+
m_labelText = tr("Command line arguments:");
}
@@ -328,14 +332,14 @@ ArgumentsAspect::ArgumentsAspect()
Macros in the value are expanded using \a expander.
*/
-QString ArgumentsAspect::arguments(const MacroExpander *expander) const
+QString ArgumentsAspect::arguments() const
{
- QTC_ASSERT(expander, return m_arguments);
+ QTC_ASSERT(m_macroExpander, return m_arguments);
if (m_currentlyExpanding)
return m_arguments;
m_currentlyExpanding = true;
- const QString expanded = expander->expandProcessArgs(m_arguments);
+ const QString expanded = m_macroExpander->expandProcessArgs(m_arguments);
m_currentlyExpanding = false;
return expanded;
}
@@ -509,36 +513,49 @@ void ArgumentsAspect::addToLayout(LayoutBuilder &builder)
by the build system's parsing results with an optional manual override.
*/
-ExecutableAspect::ExecutableAspect()
+ExecutableAspect::ExecutableAspect(Target *target, ExecutionDeviceSelector selector)
+ : m_target(target), m_selector(selector)
{
setDisplayName(tr("Executable"));
setId("ExecutableAspect");
- setExecutablePathStyle(HostOsInfo::hostOs());
+ addDataExtractor(this, &ExecutableAspect::executable, &Data::executable);
+
m_executable.setPlaceHolderText(tr("<unknown>"));
m_executable.setLabelText(tr("Executable:"));
m_executable.setDisplayStyle(StringAspect::LabelDisplay);
- connect(&m_executable, &StringAspect::changed,
- this, &ExecutableAspect::changed);
+ updateDevice();
+
+ connect(&m_executable, &StringAspect::changed, this, &ExecutableAspect::changed);
}
/*!
\internal
*/
+
+static IDevice::ConstPtr executionDevice(Target *target,
+ ExecutableAspect::ExecutionDeviceSelector selector)
+{
+ if (target) {
+ if (selector == ExecutableAspect::RunDevice)
+ return DeviceKitAspect::device(target->kit());
+ if (selector == ExecutableAspect::BuildDevice)
+ return BuildDeviceKitAspect::device(target->kit());
+ }
+ return DeviceManager::defaultDesktopDevice();
+}
+
ExecutableAspect::~ExecutableAspect()
{
delete m_alternativeExecutable;
m_alternativeExecutable = nullptr;
}
-/*!
- Sets the display style of the paths to the default used on \a osType,
- backslashes on Windows, forward slashes elsewhere.
-
- \sa Utils::StringAspect::setDisplayFilter()
-*/
-void ExecutableAspect::setExecutablePathStyle(OsType osType)
+void ExecutableAspect::updateDevice()
{
+ const IDevice::ConstPtr dev = executionDevice(m_target, m_selector);
+ const OsType osType = dev ? dev->osType() : HostOsInfo::hostOs();
+
m_executable.setDisplayFilter([osType](const QString &pathName) {
return OsSpecificAspects::pathWithNativeSeparators(osType, pathName);
});
@@ -623,10 +640,14 @@ void ExecutableAspect::makeOverridable(const QString &overridingKey, const QStri
*/
FilePath ExecutableAspect::executable() const
{
- if (m_alternativeExecutable && m_alternativeExecutable->isChecked())
- return m_alternativeExecutable->filePath();
+ FilePath exe = m_alternativeExecutable && m_alternativeExecutable->isChecked()
+ ? m_alternativeExecutable->filePath()
+ : m_executable.filePath();
+
+ if (const IDevice::ConstPtr dev = executionDevice(m_target, m_selector))
+ exe = dev->filePath(exe.path());
- return m_executable.filePath();
+ return exe;
}
/*!
@@ -760,4 +781,117 @@ RunAsRootAspect::RunAsRootAspect()
setLabel(tr("Run as root user"), LabelPlacement::AtCheckBox);
}
+Interpreter::Interpreter()
+ : id(QUuid::createUuid().toString())
+{}
+
+Interpreter::Interpreter(const QString &_id,
+ const QString &_name,
+ const FilePath &_command,
+ bool _autoDetected)
+ : id(_id)
+ , name(_name)
+ , command(_command)
+ , autoDetected(_autoDetected)
+{}
+
+/*!
+ \class ProjectExplorer::InterpreterAspect
+ \inmodule QtCreator
+
+ \brief The InterpreterAspect class lets a user specify an interpreter
+ to use with files or projects using an interpreted language.
+*/
+
+InterpreterAspect::InterpreterAspect()
+{
+ addDataExtractor(this, &InterpreterAspect::currentInterpreter, &Data::interpreter);
+}
+
+Interpreter InterpreterAspect::currentInterpreter() const
+{
+ return Utils::findOrDefault(m_interpreters, Utils::equal(&Interpreter::id, m_currentId));
+}
+
+void InterpreterAspect::updateInterpreters(const QList<Interpreter> &interpreters)
+{
+ m_interpreters = interpreters;
+ if (m_comboBox)
+ updateComboBox();
+}
+
+void InterpreterAspect::setDefaultInterpreter(const Interpreter &interpreter)
+{
+ m_defaultId = interpreter.id;
+ if (m_currentId.isEmpty())
+ m_currentId = m_defaultId;
+}
+
+void InterpreterAspect::setCurrentInterpreter(const Interpreter &interpreter)
+{
+ m_currentId = interpreter.id;
+ emit changed();
+}
+
+void InterpreterAspect::fromMap(const QVariantMap &map)
+{
+ m_currentId = map.value(settingsKey(), m_defaultId).toString();
+}
+
+void InterpreterAspect::toMap(QVariantMap &map) const
+{
+ if (m_currentId != m_defaultId)
+ saveToMap(map, m_currentId, QString(), settingsKey());
+}
+
+void InterpreterAspect::addToLayout(LayoutBuilder &builder)
+{
+ if (QTC_GUARD(m_comboBox.isNull()))
+ m_comboBox = new QComboBox;
+
+ updateComboBox();
+ connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &InterpreterAspect::updateCurrentInterpreter);
+
+ auto manageButton = new QPushButton(tr("Manage..."));
+ connect(manageButton, &QPushButton::clicked, [this] {
+ Core::ICore::showOptionsDialog(m_settingsDialogId);
+ });
+
+ builder.addItems({tr("Interpreter"), m_comboBox.data(), manageButton});
+}
+
+void InterpreterAspect::updateCurrentInterpreter()
+{
+ const int index = m_comboBox->currentIndex();
+ if (index < 0)
+ return;
+ QTC_ASSERT(index < m_interpreters.size(), return);
+ m_currentId = m_interpreters[index].id;
+ m_comboBox->setToolTip(m_interpreters[index].command.toUserOutput());
+ emit changed();
+}
+
+void InterpreterAspect::updateComboBox()
+{
+ int currentIndex = -1;
+ int defaultIndex = -1;
+ const QString currentId = m_currentId;
+ m_comboBox->clear();
+ for (const Interpreter &interpreter : qAsConst(m_interpreters)) {
+ int index = m_comboBox->count();
+ m_comboBox->addItem(interpreter.name);
+ m_comboBox->setItemData(index, interpreter.command.toUserOutput(), Qt::ToolTipRole);
+ if (interpreter.id == currentId)
+ currentIndex = index;
+ if (interpreter.id == m_defaultId)
+ defaultIndex = index;
+ }
+ if (currentIndex >= 0)
+ m_comboBox->setCurrentIndex(currentIndex);
+ else if (defaultIndex >= 0)
+ m_comboBox->setCurrentIndex(defaultIndex);
+ updateCurrentInterpreter();
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/runconfigurationaspects.h b/src/plugins/projectexplorer/runconfigurationaspects.h
index 1f8a6933fb6..f9524a3c6a1 100644
--- a/src/plugins/projectexplorer/runconfigurationaspects.h
+++ b/src/plugins/projectexplorer/runconfigurationaspects.h
@@ -33,6 +33,7 @@
QT_BEGIN_NAMESPACE
class QCheckBox;
+class QComboBox;
class QPlainTextEdit;
class QToolButton;
QT_END_NAMESPACE
@@ -41,6 +42,8 @@ namespace Utils { class ExpandButton; }
namespace ProjectExplorer {
+class ProjectConfiguration;
+
class PROJECTEXPLORER_EXPORT TerminalAspect : public Utils::BaseAspect
{
Q_OBJECT
@@ -55,6 +58,12 @@ public:
bool isUserSet() const;
+ struct Data : BaseAspect::Data
+ {
+ bool useTerminal;
+ bool isUserSet;
+ };
+
private:
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
@@ -72,16 +81,15 @@ class PROJECTEXPLORER_EXPORT WorkingDirectoryAspect : public Utils::BaseAspect
Q_OBJECT
public:
- WorkingDirectoryAspect();
+ explicit WorkingDirectoryAspect(const Utils::MacroExpander *expander,
+ EnvironmentAspect *envAspect);
void addToLayout(Utils::LayoutBuilder &builder) override;
- void acquaintSiblings(const Utils::AspectContainer &) override;
Utils::FilePath workingDirectory() const;
Utils::FilePath defaultWorkingDirectory() const;
Utils::FilePath unexpandedWorkingDirectory() const;
void setDefaultWorkingDirectory(const Utils::FilePath &defaultWorkingDirectory);
- void setMacroExpander(Utils::MacroExpander *macroExpander);
Utils::PathChooser *pathChooser() const;
private:
@@ -95,7 +103,7 @@ private:
Utils::FilePath m_defaultWorkingDirectory;
QPointer<Utils::PathChooser> m_chooser;
QPointer<QToolButton> m_resetButton;
- Utils::MacroExpander *m_macroExpander = nullptr;
+ const Utils::MacroExpander *m_macroExpander = nullptr;
};
class PROJECTEXPLORER_EXPORT ArgumentsAspect : public Utils::BaseAspect
@@ -103,11 +111,11 @@ class PROJECTEXPLORER_EXPORT ArgumentsAspect : public Utils::BaseAspect
Q_OBJECT
public:
- ArgumentsAspect();
+ explicit ArgumentsAspect(const Utils::MacroExpander *macroExpander);
void addToLayout(Utils::LayoutBuilder &builder) override;
- QString arguments(const Utils::MacroExpander *expander) const;
+ QString arguments() const;
QString unexpandedArguments() const;
void setArguments(const QString &arguments);
@@ -115,6 +123,11 @@ public:
void setResetter(const std::function<QString()> &resetter);
void resetArguments();
+ struct Data : BaseAspect::Data
+ {
+ QString arguments;
+ };
+
private:
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
@@ -130,6 +143,7 @@ private:
bool m_multiLine = false;
mutable bool m_currentlyExpanding = false;
std::function<QString()> m_resetter;
+ const Utils::MacroExpander *m_macroExpander = nullptr;
};
class PROJECTEXPLORER_EXPORT UseLibraryPathsAspect : public Utils::BoolAspect
@@ -161,7 +175,9 @@ class PROJECTEXPLORER_EXPORT ExecutableAspect : public Utils::BaseAspect
Q_OBJECT
public:
- ExecutableAspect();
+ enum ExecutionDeviceSelector { HostDevice, BuildDevice, RunDevice };
+
+ explicit ExecutableAspect(Target *target, ExecutionDeviceSelector selector);
~ExecutableAspect() override;
Utils::FilePath executable() const;
@@ -172,21 +188,28 @@ public:
void addToLayout(Utils::LayoutBuilder &builder) override;
void setLabelText(const QString &labelText);
void setPlaceHolderText(const QString &placeHolderText);
- void setExecutablePathStyle(Utils::OsType osType);
void setHistoryCompleter(const QString &historyCompleterKey);
void setExpectedKind(const Utils::PathChooser::Kind expectedKind);
void setEnvironmentChange(const Utils::EnvironmentChange &change);
void setDisplayStyle(Utils::StringAspect::DisplayStyle style);
+ struct Data : BaseAspect::Data
+ {
+ Utils::FilePath executable;
+ };
+
protected:
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
private:
QString executableText() const;
+ void updateDevice();
Utils::StringAspect m_executable;
Utils::StringAspect *m_alternativeExecutable = nullptr;
+ Target *m_target = nullptr;
+ ExecutionDeviceSelector m_selector = RunDevice;
};
class PROJECTEXPLORER_EXPORT SymbolFileAspect : public Utils::StringAspect
@@ -197,4 +220,61 @@ public:
SymbolFileAspect() = default;
};
+class PROJECTEXPLORER_EXPORT Interpreter
+{
+public:
+ Interpreter();
+ Interpreter(const QString &id,
+ const QString &name,
+ const Utils::FilePath &command,
+ bool autoDetected = true);
+
+ inline bool operator==(const Interpreter &other) const
+ {
+ return id == other.id && name == other.name && command == other.command;
+ }
+
+ QString id;
+ QString name;
+ Utils::FilePath command;
+ bool autoDetected = true;
+};
+
+class PROJECTEXPLORER_EXPORT InterpreterAspect : public Utils::BaseAspect
+{
+ Q_OBJECT
+
+public:
+ InterpreterAspect();
+
+ Interpreter currentInterpreter() const;
+ void updateInterpreters(const QList<Interpreter> &interpreters);
+ void setDefaultInterpreter(const Interpreter &interpreter);
+ void setCurrentInterpreter(const Interpreter &interpreter);
+ void setSettingsDialogId(Utils::Id id) { m_settingsDialogId = id; }
+
+ void fromMap(const QVariantMap &) override;
+ void toMap(QVariantMap &) const override;
+ void addToLayout(Utils::LayoutBuilder &builder) override;
+
+ struct Data : Utils::BaseAspect::Data { Interpreter interpreter; };
+
+private:
+ void updateCurrentInterpreter();
+ void updateComboBox();
+ QList<Interpreter> m_interpreters;
+ QPointer<QComboBox> m_comboBox;
+ QString m_defaultId;
+ QString m_currentId;
+ Utils::Id m_settingsDialogId;
+};
+
+class PROJECTEXPLORER_EXPORT MainScriptAspect : public Utils::StringAspect
+{
+ Q_OBJECT
+
+public:
+ MainScriptAspect() = default;
+};
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp
index 883760dfda0..4a6539befff 100644
--- a/src/plugins/projectexplorer/runcontrol.cpp
+++ b/src/plugins/projectexplorer/runcontrol.cpp
@@ -25,47 +25,57 @@
#include "runcontrol.h"
-#include "devicesupport/desktopdevice.h"
-#include "abi.h"
#include "buildconfiguration.h"
#include "customparser.h"
-#include "environmentaspect.h"
+#include "devicesupport/desktopdevice.h"
+#include "devicesupport/devicemanager.h"
+#include "devicesupport/idevice.h"
+#include "devicesupport/sshsettings.h"
#include "kitinformation.h"
#include "project.h"
#include "projectexplorer.h"
+#include "projectexplorersettings.h"
#include "runconfigurationaspects.h"
+#include "runcontrol.h"
#include "session.h"
#include "target.h"
-#include "toolchain.h"
+#include "windebuginterface.h"
+
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
#include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
#include <utils/detailswidget.h>
#include <utils/fileinprojectfinder.h>
+#include <utils/fileutils.h>
#include <utils/outputformatter.h>
+#include <utils/processinterface.h>
+#include <utils/processinterface.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/utilsicons.h>
#include <utils/variablechooser.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
-#include <ssh/sshsettings.h>
-
#include <QDir>
#include <QFormLayout>
#include <QHash>
-#include <QPushButton>
-#include <QTimer>
#include <QLoggingCategory>
+#include <QPushButton>
#include <QSettings>
+#include <QTextCodec>
+#include <QTimer>
+
#if defined (WITH_JOURNALD)
#include "journaldwatcher.h"
#endif
-using namespace Utils;
using namespace ProjectExplorer::Internal;
+using namespace Utils;
namespace {
static Q_LOGGING_CATEGORY(statesLog, "qtc.projectmanager.states", QtWarningMsg)
@@ -301,8 +311,39 @@ static QString stateName(RunControlState s)
# undef SN
}
-class RunControlPrivate : public QObject
+class RunControlPrivateData
+{
+public:
+ QString displayName;
+ Runnable runnable;
+ IDevice::ConstPtr device;
+ Utils::Icon icon;
+ const MacroExpander *macroExpander = nullptr;
+ AspectContainerData aspectData;
+ QString buildKey;
+ QMap<Utils::Id, QVariantMap> settingsData;
+ Utils::Id runConfigId;
+ BuildTargetInfo buildTargetInfo;
+ FilePath buildDirectory;
+ Environment buildEnvironment;
+ Kit *kit = nullptr; // Not owned.
+ QPointer<Target> target; // Not owned.
+ QPointer<Project> project; // Not owned.
+ std::function<bool(bool*)> promptToStop;
+ std::vector<RunWorkerFactory> m_factories;
+
+ // A handle to the actual application process.
+ Utils::ProcessHandle applicationProcessHandle;
+
+ RunControlState state = RunControlState::Initialized;
+
+ QList<QPointer<RunWorker>> m_workers;
+};
+
+class RunControlPrivate : public QObject, public RunControlPrivateData
{
+ Q_OBJECT
+
public:
RunControlPrivate(RunControl *parent, Utils::Id mode)
: q(parent), runMode(mode)
@@ -319,6 +360,8 @@ public:
m_workers.clear();
}
+ void copyData(RunControlPrivateData *other) { RunControlPrivateData::operator=(*other); }
+
Q_ENUM(RunControlState)
void checkState(RunControlState expectedState);
@@ -344,32 +387,7 @@ public:
bool supportsReRunning() const;
RunControl *q;
- QString displayName;
- Runnable runnable;
- IDevice::ConstPtr device;
Utils::Id runMode;
- Utils::Icon icon;
- const MacroExpander *macroExpander = nullptr;
- QPointer<RunConfiguration> runConfiguration; // Not owned. Avoid use.
- QString buildKey;
- QMap<Utils::Id, QVariantMap> settingsData;
- Utils::Id runConfigId;
- BuildTargetInfo buildTargetInfo;
- BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
- FilePath buildDirectory;
- Environment buildEnvironment;
- Kit *kit = nullptr; // Not owned.
- QPointer<Target> target; // Not owned.
- QPointer<Project> project; // Not owned.
- std::function<bool(bool*)> promptToStop;
- std::vector<RunWorkerFactory> m_factories;
-
- // A handle to the actual application process.
- Utils::ProcessHandle applicationProcessHandle;
-
- RunControlState state = RunControlState::Initialized;
-
- QList<QPointer<RunWorker>> m_workers;
};
} // Internal
@@ -381,16 +399,21 @@ RunControl::RunControl(Utils::Id mode) :
{
}
-void RunControl::setRunConfiguration(RunConfiguration *runConfig)
+void RunControl::copyDataFromRunControl(RunControl *runControl)
+{
+ QTC_ASSERT(runControl, return);
+ d->copyData(runControl->d.get());
+}
+
+void RunControl::copyDataFromRunConfiguration(RunConfiguration *runConfig)
{
QTC_ASSERT(runConfig, return);
- QTC_CHECK(!d->runConfiguration);
- d->runConfiguration = runConfig;
d->runConfigId = runConfig->id();
d->runnable = runConfig->runnable();
d->displayName = runConfig->expandedDisplayName();
d->buildKey = runConfig->buildKey();
- d->settingsData = runConfig->aspectData();
+ d->settingsData = runConfig->settingsData();
+ d->aspectData = runConfig->aspectData();
setTarget(runConfig->target());
@@ -407,7 +430,6 @@ void RunControl::setTarget(Target *target)
d->buildTargetInfo = target->buildTarget(d->buildKey);
if (auto bc = target->activeBuildConfiguration()) {
- d->buildType = bc->buildType();
d->buildDirectory = bc->buildDirectory();
d->buildEnvironment = bc->environment();
}
@@ -424,8 +446,8 @@ void RunControl::setKit(Kit *kit)
d->kit = kit;
d->macroExpander = kit->macroExpander();
- if (d->runnable.device)
- setDevice(d->runnable.device);
+ if (!d->runnable.command.isEmpty())
+ setDevice(DeviceManager::deviceForPath(d->runnable.command.executable()));
else
setDevice(DeviceKitAspect::device(kit));
}
@@ -857,9 +879,8 @@ void RunControlPrivate::showError(const QString &msg)
void RunControl::setupFormatter(OutputFormatter *formatter) const
{
QList<Utils::OutputLineParser *> parsers = OutputFormatterFactory::createFormatters(target());
- if (const auto customParsersAspect
- = (runConfiguration() ? runConfiguration()->aspect<CustomParsersAspect>() : nullptr)) {
- for (const Utils::Id id : customParsersAspect->parsers()) {
+ if (const auto customParsersAspect = aspect<CustomParsersAspect>()) {
+ for (const Id id : qAsConst(customParsersAspect->parsers)) {
if (CustomParser * const parser = CustomParser::createFromId(id))
parsers << parser;
}
@@ -883,13 +904,50 @@ const Runnable &RunControl::runnable() const
return d->runnable;
}
-void RunControl::setRunnable(const Runnable &runnable)
+const CommandLine &RunControl::commandLine() const
+{
+ return d->runnable.command;
+}
+
+void RunControl::setCommandLine(const CommandLine &command)
+{
+ d->runnable.command = command;
+}
+
+const FilePath &RunControl::workingDirectory() const
+{
+ return d->runnable.workingDirectory;
+}
+
+void RunControl::setWorkingDirectory(const FilePath &workingDirectory)
+{
+ d->runnable.workingDirectory = workingDirectory;
+}
+
+const Environment &RunControl::environment() const
+{
+ return d->runnable.environment;
+}
+
+void RunControl::setEnvironment(const Environment &environment)
+{
+ d->runnable.environment = environment;
+}
+
+const QVariantHash &RunControl::extraData() const
{
- d->runnable = runnable;
+ return d->runnable.extraData;
+}
+
+void RunControl::setExtraData(const QVariantHash &extraData)
+{
+ d->runnable.extraData = extraData;
}
QString RunControl::displayName() const
{
+ if (d->displayName.isEmpty())
+ return d->runnable.command.executable().toUserOutput();
return d->displayName;
}
@@ -913,11 +971,6 @@ IDevice::ConstPtr RunControl::device() const
return d->device;
}
-RunConfiguration *RunControl::runConfiguration() const
-{
- return d->runConfiguration.data();
-}
-
Target *RunControl::target() const
{
return d->target;
@@ -938,24 +991,24 @@ const MacroExpander *RunControl::macroExpander() const
return d->macroExpander;
}
-BaseAspect *RunControl::aspect(Utils::Id id) const
+const BaseAspect::Data *RunControl::aspect(Id instanceId) const
{
- return d->runConfiguration ? d->runConfiguration->aspect(id) : nullptr;
+ return d->aspectData.aspect(instanceId);
}
-QVariantMap RunControl::settingsData(Utils::Id id) const
+const BaseAspect::Data *RunControl::aspect(BaseAspect::Data::ClassId classId) const
{
- return d->settingsData.value(id);
+ return d->aspectData.aspect(classId);
}
-QString RunControl::buildKey() const
+QVariantMap RunControl::settingsData(Id id) const
{
- return d->buildKey;
+ return d->settingsData.value(id);
}
-BuildConfiguration::BuildType RunControl::buildType() const
+QString RunControl::buildKey() const
{
- return d->buildType;
+ return d->buildKey;
}
FilePath RunControl::buildDirectory() const
@@ -1099,7 +1152,7 @@ bool RunControl::showPromptToStopDialog(const QString &title,
void RunControl::provideAskPassEntry(Environment &env)
{
if (env.value("SUDO_ASKPASS").isEmpty()) {
- const FilePath askpass = QSsh::SshSettings::askpassFilePath();
+ const FilePath askpass = SshSettings::askpassFilePath();
if (askpass.exists())
env.set("SUDO_ASKPASS", askpass.toUserOutput());
}
@@ -1143,8 +1196,8 @@ void RunControlPrivate::checkState(RunControlState expectedState)
void RunControlPrivate::setState(RunControlState newState)
{
if (!isAllowedTransition(state, newState))
- qDebug() << "Invalid run control state transition from " << stateName(state)
- << " to " << stateName(newState);
+ qDebug() << "Invalid run control state transition from" << stateName(state)
+ << "to" << stateName(newState);
state = newState;
@@ -1174,97 +1227,345 @@ void RunControlPrivate::debugMessage(const QString &msg)
qCDebug(statesLog()) << msg;
}
-// SimpleTargetRunner
-SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
- : RunWorker(runControl)
+// SimpleTargetRunnerPrivate
+
+namespace Internal {
+
+class SimpleTargetRunnerPrivate : public QObject
{
- setId("SimpleTargetRunner");
- if (auto terminalAspect = runControl->aspect<TerminalAspect>())
- m_useTerminal = terminalAspect->useTerminal();
- if (auto runAsRootAspect = runControl->aspect<RunAsRootAspect>())
- m_runAsRoot = runAsRootAspect->value();
+ Q_OBJECT
+
+public:
+ explicit SimpleTargetRunnerPrivate(SimpleTargetRunner *parent);
+ ~SimpleTargetRunnerPrivate() override;
+
+ void start();
+ void stop();
+
+ Utils::ProcessHandle applicationPID() const;
+
+ enum State { Inactive, Run };
+
+ void handleStandardOutput();
+ void handleStandardError();
+ void handleDone();
+
+ // Local
+ qint64 privateApplicationPID() const;
+ bool isRunning() const;
+
+ SimpleTargetRunner *q = nullptr;
+
+ bool m_runAsRoot = false;
+
+ QtcProcess m_process;
+
+ QTextCodec *m_outputCodec = nullptr;
+ QTextCodec::ConverterState m_outputCodecState;
+ QTextCodec::ConverterState m_errorCodecState;
+
+ State m_state = Inactive;
+ bool m_stopRequested = false;
+
+ Utils::CommandLine m_command;
+ Utils::FilePath m_workingDirectory;
+ Utils::Environment m_environment;
+ QVariantHash m_extraData;
+
+ ProcessResultData m_resultData;
+
+ std::function<void()> m_startModifier;
+
+ bool m_stopReported = false;
+ bool m_stopForced = false;
+
+ void forwardStarted();
+ void forwardDone();
+};
+
+} // Internal
+
+static QProcess::ProcessChannelMode defaultProcessChannelMode()
+{
+ return ProjectExplorerPlugin::appOutputSettings().mergeChannels
+ ? QProcess::MergedChannels : QProcess::SeparateChannels;
}
-void SimpleTargetRunner::start()
+SimpleTargetRunnerPrivate::SimpleTargetRunnerPrivate(SimpleTargetRunner *parent)
+ : q(parent)
{
- if (m_starter)
- m_starter();
- else
- doStart(runControl()->runnable(), runControl()->device());
+ m_process.setProcessChannelMode(defaultProcessChannelMode());
+ connect(&m_process, &QtcProcess::started, this, &SimpleTargetRunnerPrivate::forwardStarted);
+ connect(&m_process, &QtcProcess::done, this, &SimpleTargetRunnerPrivate::handleDone);
+ connect(&m_process, &QtcProcess::readyReadStandardError,
+ this, &SimpleTargetRunnerPrivate::handleStandardError);
+ connect(&m_process, &QtcProcess::readyReadStandardOutput,
+ this, &SimpleTargetRunnerPrivate::handleStandardOutput);
+
+ if (WinDebugInterface::instance()) {
+ connect(WinDebugInterface::instance(), &WinDebugInterface::cannotRetrieveDebugOutput,
+ this, [this] {
+ disconnect(WinDebugInterface::instance(), nullptr, this, nullptr);
+ q->appendMessage(tr("Cannot retrieve debugging output.")
+ + QLatin1Char('\n'), ErrorMessageFormat);
+ });
+
+ connect(WinDebugInterface::instance(), &WinDebugInterface::debugOutput,
+ this, [this](qint64 pid, const QString &message) {
+ if (privateApplicationPID() == pid)
+ q->appendMessage(message, DebugFormat);
+ });
+ }
}
-void SimpleTargetRunner::doStart(const Runnable &runnable, const IDevice::ConstPtr &device)
+SimpleTargetRunnerPrivate::~SimpleTargetRunnerPrivate()
{
- m_stopForced = false;
- m_stopReported = false;
- m_launcher.disconnect(this);
- m_launcher.setUseTerminal(m_useTerminal);
- m_launcher.setRunAsRoot(m_runAsRoot);
+ if (m_state == Run)
+ forwardDone();
+}
- const bool isDesktop = device.isNull() || device.dynamicCast<const DesktopDevice>();
- const QString msg = RunControl::tr("Starting %1...").arg(runnable.command.toUserOutput());
- appendMessage(msg, Utils::NormalMessageFormat);
+void SimpleTargetRunnerPrivate::stop()
+{
+ m_resultData.m_exitStatus = QProcess::CrashExit;
- connect(&m_launcher, &ApplicationLauncher::processExited,
- this, [this, runnable](int exitCode, QProcess::ExitStatus status) {
- if (m_stopReported)
+ const bool isLocal = !m_command.executable().needsDevice();
+ if (isLocal) {
+ if (!isRunning())
return;
- const QString msg = (status == QProcess::CrashExit)
- ? tr("%1 crashed.") : tr("%2 exited with code %1").arg(exitCode);
- const QString displayName = runnable.command.executable().toUserOutput();
- appendMessage(msg.arg(displayName), Utils::NormalMessageFormat);
- m_stopReported = true;
- reportStopped();
- });
-
- connect(&m_launcher, &ApplicationLauncher::error,
- this, [this, runnable](QProcess::ProcessError error) {
- if (m_stopReported)
+ m_process.stop();
+ m_process.waitForFinished();
+ QTimer::singleShot(100, this, [this] { forwardDone(); });
+ } else {
+ if (m_stopRequested)
return;
- if (error == QProcess::Timedout)
- return; // No actual change on the process side.
- const QString msg = m_stopForced ? tr("The process was ended forcefully.")
- : userMessageForProcessError(error, runnable.command.executable());
- appendMessage(msg, Utils::NormalMessageFormat);
- m_stopReported = true;
- reportStopped();
- });
+ m_stopRequested = true;
+ q->appendMessage(tr("User requested stop. Shutting down..."), NormalMessageFormat);
+ switch (m_state) {
+ case Run:
+ m_process.stop();
+ m_process.waitForFinished();
+ break;
+ case Inactive:
+ break;
+ }
+ }
+}
- connect(&m_launcher, &ApplicationLauncher::appendMessage, this, &RunWorker::appendMessage);
+bool SimpleTargetRunnerPrivate::isRunning() const
+{
+ return m_process.state() != QProcess::NotRunning;
+}
- if (isDesktop) {
- connect(&m_launcher, &ApplicationLauncher::processStarted, this, [this] {
- // Console processes only know their pid after being started
- ProcessHandle pid = m_launcher.applicationPID();
- runControl()->setApplicationProcessHandle(pid);
- pid.activate();
- reportStarted();
- });
+qint64 SimpleTargetRunnerPrivate::privateApplicationPID() const
+{
+ if (!isRunning())
+ return 0;
- if (runnable.command.isEmpty()) {
- reportFailure(RunControl::tr("No executable specified."));
- } else {
- m_launcher.start(runnable);
+ return m_process.processId();
+}
+
+void SimpleTargetRunnerPrivate::handleDone()
+{
+ m_resultData = m_process.resultData();
+ QTC_ASSERT(m_state == Run, forwardDone(); return);
+
+ m_state = Inactive;
+ forwardDone();
+}
+
+void SimpleTargetRunnerPrivate::handleStandardOutput()
+{
+ const QByteArray data = m_process.readAllStandardOutput();
+ const QString msg = m_outputCodec->toUnicode(
+ data.constData(), data.length(), &m_outputCodecState);
+ q->appendMessageChunk(msg, StdOutFormat);
+}
+
+void SimpleTargetRunnerPrivate::handleStandardError()
+{
+ const QByteArray data = m_process.readAllStandardError();
+ const QString msg = m_outputCodec->toUnicode(
+ data.constData(), data.length(), &m_errorCodecState);
+ q->appendMessageChunk(msg, StdErrFormat);
+}
+
+void SimpleTargetRunnerPrivate::start()
+{
+ const bool isLocal = !m_command.executable().needsDevice();
+
+ CommandLine cmdLine = m_command;
+ Environment env = m_environment;
+
+ m_resultData = {};
+ QTC_ASSERT(m_state == Inactive, return);
+
+ if (isLocal) {
+ if (m_runAsRoot)
+ RunControl::provideAskPassEntry(env);
+
+ WinDebugInterface::startIfNeeded();
+
+ if (HostOsInfo::isMacHost()) {
+ CommandLine disclaim(Core::ICore::libexecPath("disclaim"));
+ disclaim.addCommandLineAsArgs(cmdLine);
+ cmdLine = disclaim;
}
- } else {
- connect(&m_launcher, &ApplicationLauncher::processStarted, this, &RunWorker::reportStarted);
- m_launcher.start(runnable, device);
+ m_process.setRunAsRoot(m_runAsRoot);
}
+
+ const IDevice::ConstPtr device = DeviceManager::deviceForPath(m_command.executable());
+ if (device && !device->isEmptyCommandAllowed() && m_command.isEmpty()) {
+ m_resultData.m_errorString = tr("Cannot run: No command given.");
+ m_resultData.m_error = QProcess::FailedToStart;
+ m_resultData.m_exitStatus = QProcess::CrashExit;
+ forwardDone();
+ return;
+ }
+
+ m_stopRequested = false;
+
+ m_process.setCommand(cmdLine);
+ m_process.setEnvironment(env);
+ m_process.setExtraData(m_extraData);
+
+ m_state = Run;
+ m_process.setWorkingDirectory(m_workingDirectory);
+
+ if (isLocal)
+ m_outputCodec = QTextCodec::codecForLocale();
+ else
+ m_outputCodec = QTextCodec::codecForName("utf8");
+
+ m_process.start();
+}
+
+
+/*!
+ \class ProjectExplorer::SimpleTargetRunner
+
+ \brief The SimpleTargetRunner class is the application launcher of the
+ ProjectExplorer plugin.
+
+ Encapsulates processes running in a console or as GUI processes,
+ captures debug output of GUI processes on Windows (outputDebugString()).
+
+ \sa Utils::QtcProcess
+*/
+
+SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
+ : RunWorker(runControl), d(new Internal::SimpleTargetRunnerPrivate(this))
+{
+ setId("SimpleTargetRunner");
+}
+
+SimpleTargetRunner::~SimpleTargetRunner() = default;
+
+void SimpleTargetRunnerPrivate::forwardDone()
+{
+ if (m_stopReported)
+ return;
+ const QString executable = m_command.executable().displayName();
+ QString msg = tr("%1 exited with code %2").arg(executable).arg(m_resultData.m_exitCode);
+ if (m_resultData.m_exitStatus == QProcess::CrashExit)
+ msg = tr("%1 crashed.").arg(executable);
+ else if (m_stopForced)
+ msg = tr("The process was ended forcefully.");
+ else if (m_resultData.m_error != QProcess::UnknownError)
+ msg = RunWorker::userMessageForProcessError(m_resultData.m_error, m_command.executable());
+ q->appendMessage(msg, NormalMessageFormat);
+ m_stopReported = true;
+ q->reportStopped();
+}
+
+void SimpleTargetRunnerPrivate::forwardStarted()
+{
+ const bool isDesktop = !m_command.executable().needsDevice();
+ if (isDesktop) {
+ // Console processes only know their pid after being started
+ ProcessHandle pid{privateApplicationPID()};
+ q->runControl()->setApplicationProcessHandle(pid);
+ pid.activate();
+ }
+
+ q->reportStarted();
+}
+
+void SimpleTargetRunner::start()
+{
+ d->m_command = runControl()->commandLine();
+ d->m_workingDirectory = runControl()->workingDirectory();
+ d->m_environment = runControl()->environment();
+ d->m_extraData = runControl()->extraData();
+
+ if (d->m_startModifier)
+ d->m_startModifier();
+
+ bool useTerminal = false;
+ if (auto terminalAspect = runControl()->aspect<TerminalAspect>())
+ useTerminal = terminalAspect->useTerminal;
+
+ bool runAsRoot = false;
+ if (auto runAsRootAspect = runControl()->aspect<RunAsRootAspect>())
+ runAsRoot = runAsRootAspect->value;
+
+ d->m_stopForced = false;
+ d->m_stopReported = false;
+ d->disconnect(this);
+ d->m_process.setTerminalMode(useTerminal ? Utils::TerminalMode::On : Utils::TerminalMode::Off);
+ d->m_runAsRoot = runAsRoot;
+
+ const QString msg = RunControl::tr("Starting %1...").arg(d->m_command.displayName());
+ appendMessage(msg, NormalMessageFormat);
+
+ const bool isDesktop = !d->m_command.executable().needsDevice();
+ if (isDesktop && d->m_command.isEmpty()) {
+ reportFailure(RunControl::tr("No executable specified."));
+ return;
+ }
+ d->start();
}
void SimpleTargetRunner::stop()
{
- m_stopForced = true;
- m_launcher.stop();
+ d->m_stopForced = true;
+ d->stop();
+}
+
+void SimpleTargetRunner::setStartModifier(const std::function<void ()> &startModifier)
+{
+ d->m_startModifier = startModifier;
+}
+
+CommandLine SimpleTargetRunner::commandLine() const
+{
+ return d->m_command;
+}
+
+void SimpleTargetRunner::setCommandLine(const Utils::CommandLine &commandLine)
+{
+ d->m_command = commandLine;
}
-void SimpleTargetRunner::setStarter(const std::function<void ()> &starter)
+void SimpleTargetRunner::setEnvironment(const Environment &environment)
{
- m_starter = starter;
+ d->m_environment = environment;
}
+void SimpleTargetRunner::setWorkingDirectory(const FilePath &workingDirectory)
+{
+ d->m_workingDirectory = workingDirectory;
+}
+
+void SimpleTargetRunner::forceRunOnHost()
+{
+ const FilePath executable = d->m_command.executable();
+ if (executable.needsDevice()) {
+ QTC_CHECK(false);
+ d->m_command.setExecutable(FilePath::fromString(executable.path()));
+ }
+}
// RunWorkerPrivate
@@ -1462,22 +1763,22 @@ void RunWorker::reportFailure(const QString &msg)
* Appends a message in the specified \a format to
* the owning RunControl's \uicontrol{Application Output} pane.
*/
-void RunWorker::appendMessage(const QString &msg, OutputFormat format, bool appendNewLine)
+void RunWorker::appendMessage(const QString &msg, OutputFormat format)
{
- if (!appendNewLine || msg.endsWith('\n'))
+ if (msg.endsWith('\n'))
emit d->runControl->appendMessage(msg, format);
else
emit d->runControl->appendMessage(msg + '\n', format);
}
-IDevice::ConstPtr RunWorker::device() const
+void RunWorker::appendMessageChunk(const QString &msg, OutputFormat format)
{
- return d->runControl->device();
+ emit d->runControl->appendMessage(msg, format);
}
-const Runnable &RunWorker::runnable() const
+IDevice::ConstPtr RunWorker::device() const
{
- return d->runControl->runnable();
+ return d->runControl->device();
}
void RunWorker::addStartDependency(RunWorker *dependency)
@@ -1585,11 +1886,6 @@ void RunWorker::stop()
reportStopped();
}
-QString Runnable::displayName() const
-{
- return command.executable().toString();
-}
-
// OutputFormatterFactory
static QList<OutputFormatterFactory *> g_outputFormatterFactories;
@@ -1618,3 +1914,5 @@ void OutputFormatterFactory::setFormatterCreator(const FormatterCreator &creator
}
} // namespace ProjectExplorer
+
+#include "runcontrol.moc"
diff --git a/src/plugins/projectexplorer/runcontrol.h b/src/plugins/projectexplorer/runcontrol.h
index c1ab5d67813..0ff9b8778e9 100644
--- a/src/plugins/projectexplorer/runcontrol.h
+++ b/src/plugins/projectexplorer/runcontrol.h
@@ -25,33 +25,29 @@
#pragma once
-#include "applicationlauncher.h"
-#include "buildconfiguration.h"
-#include "devicesupport/idevice.h"
-#include "projectexplorerconstants.h"
+#include "devicesupport/idevicefwd.h"
#include "runconfiguration.h"
+#include <utils/commandline.h>
#include <utils/environment.h>
+#include <utils/outputformatter.h>
#include <utils/processhandle.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-#include <utils/icon.h>
#include <QHash>
+#include <QProcess> // FIXME: Remove
#include <QVariant>
#include <functional>
#include <memory>
namespace Utils {
+class Icon;
class MacroExpander;
class OutputLineParser;
-class OutputFormatter;
} // Utils
namespace ProjectExplorer {
-class GlobalOrProjectAspect;
-class Node;
class RunConfiguration;
class RunControl;
class Target;
@@ -59,6 +55,7 @@ class Target;
namespace Internal {
class RunControlPrivate;
class RunWorkerPrivate;
+class SimpleTargetRunnerPrivate;
} // Internal
@@ -70,11 +67,7 @@ public:
Utils::CommandLine command;
Utils::FilePath workingDirectory;
Utils::Environment environment;
- IDevice::ConstPtr device; // Override the kit's device. Keep unset by default.
- QHash<Utils::Id, QVariant> extraData;
-
- // FIXME: Not necessarily a display name
- QString displayName() const;
+ QVariantHash extraData;
};
class PROJECTEXPLORER_EXPORT RunWorker : public QObject
@@ -99,9 +92,9 @@ public:
QVariant recordedData(const QString &channel) const;
// Part of read-only interface of RunControl for convenience.
- void appendMessage(const QString &msg, Utils::OutputFormat format, bool appendNewLine = true);
- IDevice::ConstPtr device() const;
- const Runnable &runnable() const;
+ void appendMessage(const QString &msg, Utils::OutputFormat format);
+ void appendMessageChunk(const QString &msg, Utils::OutputFormat format);
+ IDeviceConstPtr device() const;
// States
void initiateStart();
@@ -193,10 +186,12 @@ public:
explicit RunControl(Utils::Id mode);
~RunControl() override;
- void setRunConfiguration(RunConfiguration *runConfig);
void setTarget(Target *target);
void setKit(Kit *kit);
+ void copyDataFromRunConfiguration(RunConfiguration *runConfig);
+ void copyDataFromRunControl(RunControl *runControl);
+
void initiateStart();
void initiateReStart();
void initiateStop();
@@ -208,7 +203,7 @@ public:
bool supportsReRunning() const;
- virtual QString displayName() const;
+ QString displayName() const;
void setDisplayName(const QString &displayName);
bool isRunning() const;
@@ -221,21 +216,21 @@ public:
Utils::ProcessHandle applicationProcessHandle() const;
void setApplicationProcessHandle(const Utils::ProcessHandle &handle);
- IDevice::ConstPtr device() const;
+ IDeviceConstPtr device() const;
- RunConfiguration *runConfiguration() const; // FIXME: Remove.
// FIXME: Try to cut down to amount of functions.
Target *target() const;
Project *project() const;
Kit *kit() const;
const Utils::MacroExpander *macroExpander() const;
- Utils::BaseAspect *aspect(Utils::Id id) const;
- template <typename T> T *aspect() const {
- return runConfiguration() ? runConfiguration()->aspect<T>() : nullptr;
+
+ const Utils::BaseAspect::Data *aspect(Utils::Id instanceId) const;
+ const Utils::BaseAspect::Data *aspect(Utils::BaseAspect::Data::ClassId classId) const;
+ template <typename T> const typename T::Data *aspect() const {
+ return dynamic_cast<const typename T::Data *>(aspect(&T::staticMetaObject));
}
QString buildKey() const;
- BuildConfiguration::BuildType buildType() const;
Utils::FilePath buildDirectory() const;
Utils::Environment buildEnvironment() const;
@@ -248,7 +243,18 @@ public:
Utils::Id runMode() const;
const Runnable &runnable() const;
- void setRunnable(const Runnable &runnable);
+
+ const Utils::CommandLine &commandLine() const;
+ void setCommandLine(const Utils::CommandLine &command);
+
+ const Utils::FilePath &workingDirectory() const;
+ void setWorkingDirectory(const Utils::FilePath &workingDirectory);
+
+ const Utils::Environment &environment() const;
+ void setEnvironment(const Utils::Environment &environment);
+
+ const QVariantHash &extraData() const;
+ void setExtraData(const QVariantHash &extraData);
static bool showPromptToStopDialog(const QString &title, const QString &text,
const QString &stopButtonText = QString(),
@@ -271,7 +277,7 @@ signals:
void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
private:
- void setDevice(const IDevice::ConstPtr &device);
+ void setDevice(const IDeviceConstPtr &device);
friend class RunWorker;
friend class Internal::RunWorkerPrivate;
@@ -291,24 +297,27 @@ class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public RunWorker
public:
explicit SimpleTargetRunner(RunControl *runControl);
+ ~SimpleTargetRunner() override;
protected:
- void setStarter(const std::function<void()> &starter);
- void doStart(const Runnable &runnable, const IDevice::ConstPtr &device);
+ void setStartModifier(const std::function<void()> &startModifier);
+
+ Utils::CommandLine commandLine() const;
+ void setCommandLine(const Utils::CommandLine &commandLine);
+
+ void setEnvironment(const Utils::Environment &environment);
+ void setWorkingDirectory(const Utils::FilePath &workingDirectory);
+
+ void forceRunOnHost();
private:
void start() final;
void stop() final;
const Runnable &runnable() const = delete;
+ void setRunnable(const Runnable &) = delete;
- ApplicationLauncher m_launcher;
- std::function<void()> m_starter;
-
- bool m_stopReported = false;
- bool m_useTerminal = false;
- bool m_runAsRoot = false;
- bool m_stopForced = false;
+ const std::unique_ptr<Internal::SimpleTargetRunnerPrivate> d;
};
class PROJECTEXPLORER_EXPORT OutputFormatterFactory
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
index 5c1d68d40bf..546c215b345 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
@@ -447,7 +447,8 @@ QString RunSettingsWidget::uniqueDCName(const QString &name)
QString result = name.trimmed();
if (!result.isEmpty()) {
QStringList dcNames;
- foreach (DeployConfiguration *dc, m_target->deployConfigurations()) {
+ const QList<DeployConfiguration *> configurations = m_target->deployConfigurations();
+ for (DeployConfiguration *dc : configurations) {
if (dc == m_target->activeDeployConfiguration())
continue;
dcNames.append(dc->displayName());
@@ -462,7 +463,8 @@ QString RunSettingsWidget::uniqueRCName(const QString &name)
QString result = name.trimmed();
if (!result.isEmpty()) {
QStringList rcNames;
- foreach (RunConfiguration *rc, m_target->runConfigurations()) {
+ const QList<RunConfiguration *> configurations = m_target->runConfigurations();
+ for (RunConfiguration *rc : configurations) {
if (rc == m_target->activeRunConfiguration())
continue;
rcNames.append(rc->displayName());
diff --git a/src/plugins/projectexplorer/sanitizerparser.cpp b/src/plugins/projectexplorer/sanitizerparser.cpp
new file mode 100644
index 00000000000..4a68e9a44db
--- /dev/null
+++ b/src/plugins/projectexplorer/sanitizerparser.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sanitizerparser.h"
+
+#include "projectexplorerconstants.h"
+
+#include <QRegularExpression>
+
+#include <iterator>
+#include <numeric>
+
+#ifdef WITH_TESTS
+#include <QTest>
+#include "outputparser_test.h"
+#endif
+
+using namespace Utils;
+
+namespace ProjectExplorer::Internal {
+
+OutputLineParser::Result SanitizerParser::handleLine(const QString &line, OutputFormat format)
+{
+ if (format != OutputFormat::StdErrFormat)
+ return Status::NotHandled;
+
+ // Non-regex shortcut for the common case.
+ if (m_id == 0 && !line.startsWith('='))
+ return Status::NotHandled;
+
+ static const QRegularExpression idPattern(R"(^==(?<id>\d+)==ERROR: (?<desc>.*)$)");
+ const QRegularExpressionMatch match = idPattern.match(line);
+ if (!match.hasMatch())
+ return m_id == 0 ? Status::NotHandled : handleContinuation(line);
+
+ QTC_ASSERT(m_id == 0, flush());
+ m_id = match.captured("id").toULongLong();
+ QTC_ASSERT(m_id != 0, return Status::NotHandled);
+ const QString description = match.captured("desc");
+ m_task = Task(Task::Error, description, {}, 0, Constants::TASK_CATEGORY_SANITIZER);
+ m_task.details << line;
+ return Status::InProgress;
+}
+
+OutputLineParser::Result SanitizerParser::handleContinuation(const QString &line)
+{
+ m_task.details << line;
+
+ if (line == QString("==%1==ABORTING").arg(m_id)) {
+ flush();
+ return Status::Done;
+ }
+
+ // Locations are either source files with line and sometimes column, or binaries with
+ // a hex offset.
+ static const QString filePathPattern = R"((?<file>(?:[A-Za-z]:)?[\/\\][^:]+))";
+ static const QString numberSuffixPatternTemplate = R"(:(?<%1>\d+))";
+ static const QString lineSuffixPattern = numberSuffixPatternTemplate.arg("line");
+ static const QString columnSuffixPattern = numberSuffixPatternTemplate.arg("column");
+ static const QString offsetSuffixPattern = R"(\+0x[[:xdigit:]]+)";
+ static const QString locationPatternString = QString(R"(%1(?:(?:%2(%3)?)|%4))")
+ .arg(filePathPattern, lineSuffixPattern, columnSuffixPattern, offsetSuffixPattern);
+ static const QRegularExpression filePattern(locationPatternString);
+
+ LinkSpecs linkSpecs;
+ const QString summaryPrefix = "SUMMARY: ";
+ if (line.startsWith(summaryPrefix)) {
+ static const QRegularExpression summaryPatternWithFile(QString(
+ R"(^%1(?<desc>.*?) at %2.*$)").arg(summaryPrefix, locationPatternString));
+ const QRegularExpressionMatch summaryMatch = summaryPatternWithFile.match(line);
+ if (summaryMatch.hasMatch()) {
+ m_task.summary = summaryMatch.captured("desc");
+ const FilePath file = absoluteFilePath(FilePath::fromUserInput(
+ summaryMatch.captured("file")));
+ if (fileExists(file)) {
+ m_task.file = file;
+ m_task.line = summaryMatch.captured("line").toInt();
+ m_task.column = summaryMatch.captured("column").toInt();
+ addLinkSpecForAbsoluteFilePath(linkSpecs, file, m_task.line, summaryMatch, "file");
+ addLinkSpecs(linkSpecs);
+ }
+ } else {
+ m_task.summary = line.mid(summaryPrefix.length());
+ }
+ flush();
+ return {Status::Done, linkSpecs};
+ }
+ const QRegularExpressionMatch fileMatch = filePattern.match(line);
+ if (fileMatch.hasMatch()) {
+ const FilePath file = absoluteFilePath(FilePath::fromUserInput(fileMatch.captured("file")));
+ if (fileExists(file)) {
+ addLinkSpecForAbsoluteFilePath(linkSpecs, file, fileMatch.captured("line").toInt(),
+ fileMatch, "file");
+ addLinkSpecs(linkSpecs);
+ }
+ }
+ return {Status::InProgress, linkSpecs};
+}
+
+void SanitizerParser::addLinkSpecs(const LinkSpecs &linkSpecs)
+{
+ LinkSpecs adaptedLinkSpecs = linkSpecs;
+ const int offset = std::accumulate(m_task.details.cbegin(), m_task.details.cend() - 1,
+ 0, [](int total, const QString &line) { return total + line.length() + 1;});
+ for (LinkSpec &ls : adaptedLinkSpecs)
+ ls.startPos += offset;
+ m_linkSpecs << adaptedLinkSpecs;
+}
+
+void SanitizerParser::flush()
+{
+ if (m_task.isNull())
+ return;
+
+ setDetailsFormat(m_task, m_linkSpecs);
+ static const int maxLen = 50;
+ if (m_task.details.length() > maxLen) {
+ auto cutOffIt = std::next(m_task.details.begin(), maxLen);
+ cutOffIt = m_task.details.insert(cutOffIt, "...");
+ m_task.details.erase(std::next(cutOffIt), std::prev(m_task.details.end()));
+ }
+ scheduleTask(m_task, m_task.details.count());
+ m_task.clear();
+ m_linkSpecs.clear();
+ m_id = 0;
+}
+
+#ifdef WITH_TESTS
+class SanitizerParserTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testParser_data()
+ {
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<Tasks >("tasks");
+ QTest::addColumn<QString>("childStdErrLines");
+
+ const QString odrInput = R"(=================================================================
+==3792966==ERROR: AddressSanitizer: odr-violation (0x55f0cfaeddc0):
+ [1] size=16 'lre_id_continue_table_ascii' /sda/home/christian/dev/qbs/master/src/src/shared/quickjs/libregexp.c:193:16
+ [2] size=16 'lre_id_continue_table_ascii' /sda/home/christian/dev/qbs/master/src/src/shared/quickjs/libregexp.c:193:16
+These globals were registered at these points:
+ [1]:
+ #0 0x7fc07337a3d9 in __asan_register_globals /usr/src/debug/gcc/libsanitizer/asan/asan_globals.cpp:341
+ #1 0x55f0cfa986f2 in _sub_I_00099_1 (/sda/home/christian/dev/qbs/master/qtc_System_with_local_compiler_Debug/install-root/usr/local/bin/tst_language+0x2756f2)
+ #2 0x7fc07198943a in __libc_start_main@GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d43a)
+
+ [2]:
+ #0 0x7fc07337a3d9 in __asan_register_globals /usr/src/debug/gcc/libsanitizer/asan/asan_globals.cpp:341
+ #1 0x7fc072f456b7 in _sub_I_00099_1 (/sda/home/christian/dev/qbs/master/qtc_System_with_local_compiler_Debug/install-root/usr/local/bin/../lib/libqbscore.so.1.22+0xb926b7)
+ #2 0x7fc073d5cedd in call_init (/lib64/ld-linux-x86-64.so.2+0x5edd)
+
+==3792966==HINT: if you don't care about these errors you may set ASAN_OPTIONS=detect_odr_violation=0
+SUMMARY: AddressSanitizer: odr-violation: global 'lre_id_continue_table_ascii' at /sda/home/christian/dev/qbs/master/src/src/shared/quickjs/libregexp.c:193:16
+==3792966==ABORTING)";
+ const QStringList odrNonMatchedLines{
+ "=================================================================",
+ "==3792966==ABORTING"};
+ Task odrTask(Task::Error,
+ QString("AddressSanitizer: odr-violation: global 'lre_id_continue_table_ascii'")
+ + R"(
+==3792966==ERROR: AddressSanitizer: odr-violation (0x55f0cfaeddc0):
+ [1] size=16 'lre_id_continue_table_ascii' /sda/home/christian/dev/qbs/master/src/src/shared/quickjs/libregexp.c:193:16
+ [2] size=16 'lre_id_continue_table_ascii' /sda/home/christian/dev/qbs/master/src/src/shared/quickjs/libregexp.c:193:16
+These globals were registered at these points:
+ [1]:
+ #0 0x7fc07337a3d9 in __asan_register_globals /usr/src/debug/gcc/libsanitizer/asan/asan_globals.cpp:341
+ #1 0x55f0cfa986f2 in _sub_I_00099_1 (/sda/home/christian/dev/qbs/master/qtc_System_with_local_compiler_Debug/install-root/usr/local/bin/tst_language+0x2756f2)
+ #2 0x7fc07198943a in __libc_start_main@GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d43a)
+
+ [2]:
+ #0 0x7fc07337a3d9 in __asan_register_globals /usr/src/debug/gcc/libsanitizer/asan/asan_globals.cpp:341
+ #1 0x7fc072f456b7 in _sub_I_00099_1 (/sda/home/christian/dev/qbs/master/qtc_System_with_local_compiler_Debug/install-root/usr/local/bin/../lib/libqbscore.so.1.22+0xb926b7)
+ #2 0x7fc073d5cedd in call_init (/lib64/ld-linux-x86-64.so.2+0x5edd)
+
+==3792966==HINT: if you don't care about these errors you may set ASAN_OPTIONS=detect_odr_violation=0
+SUMMARY: AddressSanitizer: odr-violation: global 'lre_id_continue_table_ascii' at /sda/home/christian/dev/qbs/master/src/src/shared/quickjs/libregexp.c:193:16)",
+ FilePath::fromUserInput("/sda/home/christian/dev/qbs/master/src/src/shared/quickjs/libregexp.c"),
+ 193, Constants::TASK_CATEGORY_SANITIZER);
+ odrTask.column = 16;
+ QTest::newRow("odr violation")
+ << odrInput
+ << QList<Task>{odrTask}
+ << (odrNonMatchedLines.join('\n') + "\n");
+
+ const QString leakInput = R"(
+==61167==ERROR: LeakSanitizer: detected memory leaks
+
+Direct leak of 19 byte(s) in 1 object(s) allocated from:
+ #0 0x7eff1fd87667 in __interceptor_malloc (/lib64/libasan.so.6+0xb0667)
+ #1 0x741c95 in mutt_mem_malloc mutt/memory.c:95
+ #2 0x48f089 in get_hostname /home/mutt/work/neo/init.c:343
+ #3 0x49259e in mutt_init /home/mutt/work/neo/init.c:929
+ #4 0x4a4caa in main /home/mutt/work/neo/main.c:665
+ #5 0x7eff1ea1c041 in __libc_start_main ../csu/libc-start.c:308
+
+SUMMARY: AddressSanitizer: 19 byte(s) leaked in 1 allocation(s).)";
+ const QString leakNonMatchedLines = "\n";
+ const Task leakTask(Task::Error,
+ QString("AddressSanitizer: 19 byte(s) leaked in 1 allocation(s).") + leakInput,
+ {}, -1, Constants::TASK_CATEGORY_SANITIZER);
+ QTest::newRow("leak") << leakInput << QList<Task>{leakTask} << leakNonMatchedLines;
+ }
+
+ void testParser()
+ {
+ OutputParserTester testbench;
+ testbench.setLineParsers({new SanitizerParser});
+ QFETCH(QString, input);
+ QFETCH(Tasks, tasks);
+ QFETCH(QString, childStdErrLines);
+ testbench.testParsing(input, OutputParserTester::STDERR, tasks, {}, childStdErrLines, {});
+ }
+};
+#endif
+
+QVector<QObject *> SanitizerParser::createTestObjects()
+{
+#ifdef WITH_TESTS
+ return {new SanitizerParserTest};
+#endif
+ return {};
+}
+
+SanitizerOutputFormatterFactory::SanitizerOutputFormatterFactory()
+{
+ setFormatterCreator([](Target *) -> QList<OutputLineParser *> {return {new SanitizerParser}; });
+}
+
+} // namespace ProjectExplorer::Internal
+
+#ifdef WITH_TESTS
+#include <sanitizerparser.moc>
+#endif
diff --git a/src/plugins/projectexplorer/sanitizerparser.h b/src/plugins/projectexplorer/sanitizerparser.h
new file mode 100644
index 00000000000..1cb9674fcce
--- /dev/null
+++ b/src/plugins/projectexplorer/sanitizerparser.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "ioutputparser.h"
+#include "runcontrol.h"
+#include "task.h"
+
+#include <QObject>
+#include <QVector>
+
+namespace ProjectExplorer::Internal {
+
+class SanitizerParser : public OutputTaskParser
+{
+public:
+ static QVector<QObject *> createTestObjects();
+
+private:
+ Result handleLine(const QString &line, Utils::OutputFormat format) override;
+ void flush() override;
+
+ Result handleContinuation(const QString &line);
+ void addLinkSpecs(const LinkSpecs &linkSpecs);
+
+ Task m_task;
+ LinkSpecs m_linkSpecs;
+ quint64 m_id = 0;
+};
+
+class SanitizerOutputFormatterFactory : public ProjectExplorer::OutputFormatterFactory
+{
+public:
+ SanitizerOutputFormatterFactory();
+};
+
+} // namespace ProjectExplorer::Internal
+
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
index c03baf88482..9f9ee8810a4 100644
--- a/src/plugins/projectexplorer/session.cpp
+++ b/src/plugins/projectexplorer/session.cpp
@@ -31,6 +31,7 @@
#include "kit.h"
#include "project.h"
#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
#include "projectnodes.h"
#include "target.h"
@@ -51,7 +52,6 @@
#include <QDebug>
#include <QDir>
#include <QFileInfo>
-
#include <QMessageBox>
#include <QPushButton>
@@ -96,8 +96,8 @@ public:
QStringList dependenciesOrder() const;
void dependencies(const QString &proName, QStringList &result) const;
- static QString windowTitleAddition(const QString &filePath);
- static QString sessionTitle(const QString &filePath);
+ static QString windowTitleAddition(const FilePath &filePath);
+ static QString sessionTitle(const FilePath &filePath);
bool hasProjects() const { return !m_projects.isEmpty(); }
@@ -118,7 +118,7 @@ public:
PersistentSettingsWriter *m_writer = nullptr;
private:
- static QString locationInProject(const QString &filePath);
+ static QString locationInProject(const FilePath &filePath);
};
static SessionManager *m_instance = nullptr;
@@ -192,7 +192,8 @@ bool SessionManagerPrivate::recursiveDependencyCheck(const QString &newDep, cons
if (newDep == checkDep)
return false;
- foreach (const QString &dependency, m_depMap.value(checkDep)) {
+ const QStringList depList = m_depMap.value(checkDep);
+ for (const QString &dependency : depList) {
if (!recursiveDependencyCheck(newDep, dependency))
return false;
}
@@ -213,7 +214,7 @@ QList<Project *> SessionManager::dependencies(const Project *project)
const QStringList proDeps = d->m_depMap.value(proName);
QList<Project *> projects;
- foreach (const QString &dep, proDeps) {
+ for (const QString &dep : proDeps) {
const Utils::FilePath fn = Utils::FilePath::fromString(dep);
Project *pro = Utils::findOrDefault(d->m_projects, [&fn](Project *p) { return p->projectFilePath() == fn; });
if (pro)
@@ -522,7 +523,8 @@ bool SessionManager::save()
while (i != d->m_depMap.constEnd()) {
QString key = i.key();
QStringList values;
- foreach (const QString &value, i.value())
+ const QStringList valueList = i.value();
+ for (const QString &value : valueList)
values << value;
depMap.insert(key, values);
++i;
@@ -587,16 +589,16 @@ QStringList SessionManagerPrivate::dependencies(const QString &proName) const
void SessionManagerPrivate::dependencies(const QString &proName, QStringList &result) const
{
- QStringList depends = m_depMap.value(proName);
+ const QStringList depends = m_depMap.value(proName);
- foreach (const QString &dep, depends)
+ for (const QString &dep : depends)
dependencies(dep, result);
if (!result.contains(proName))
result.append(proName);
}
-QString SessionManagerPrivate::sessionTitle(const QString &filePath)
+QString SessionManagerPrivate::sessionTitle(const FilePath &filePath)
{
if (SessionManager::isDefaultSession(d->m_sessionName)) {
if (filePath.isEmpty()) {
@@ -614,18 +616,17 @@ QString SessionManagerPrivate::sessionTitle(const QString &filePath)
return QString();
}
-QString SessionManagerPrivate::locationInProject(const QString &filePath) {
- const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(filePath));
+QString SessionManagerPrivate::locationInProject(const FilePath &filePath) {
+ const Project *project = SessionManager::projectForFile(filePath);
if (!project)
return QString();
- const Utils::FilePath file = Utils::FilePath::fromString(filePath);
- const Utils::FilePath parentDir = file.parentDir();
+ const FilePath parentDir = filePath.parentDir();
if (parentDir == project->projectDirectory())
return "@ " + project->displayName();
- if (file.isChildOf(project->projectDirectory())) {
- const Utils::FilePath dirInProject = parentDir.relativeChildPath(project->projectDirectory());
+ if (filePath.isChildOf(project->projectDirectory())) {
+ const FilePath dirInProject = parentDir.relativeChildPath(project->projectDirectory());
return "(" + dirInProject.toUserOutput() + " @ " + project->displayName() + ")";
}
@@ -635,9 +636,9 @@ QString SessionManagerPrivate::locationInProject(const QString &filePath) {
return "(" + parentDir.toUserOutput() + " @ " + project->displayName() + ")";
}
-QString SessionManagerPrivate::windowTitleAddition(const QString &filePath)
+QString SessionManagerPrivate::windowTitleAddition(const FilePath &filePath)
{
- return locationInProject(filePath);
+ return filePath.isEmpty() ? QString() : locationInProject(filePath);
}
QStringList SessionManagerPrivate::dependenciesOrder() const
@@ -668,7 +669,7 @@ QStringList SessionManagerPrivate::dependenciesOrder() const
// remove the handled projects from the dependency lists
// of the remaining unordered projects
for (int i = 0; i < unordered.count(); ++i) {
- foreach (const QString &pro, ordered) {
+ for (const QString &pro : qAsConst(ordered)) {
QStringList depList = unordered.at(i).second;
depList.removeAll(pro);
unordered[i].second = depList;
@@ -689,7 +690,7 @@ QList<Project *> SessionManager::projectOrder(const Project *project)
else
pros = d->dependenciesOrder();
- foreach (const QString &proFile, pros) {
+ for (const QString &proFile : qAsConst(pros)) {
for (Project *pro : projects()) {
if (pro->projectFilePath().toString() == proFile) {
result << pro;
@@ -725,9 +726,11 @@ void SessionManager::configureEditor(IEditor *editor, const QString &fileName)
void SessionManager::configureEditors(Project *project)
{
- foreach (IDocument *document, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents) {
if (project->isKnownFile(document->filePath())) {
- foreach (IEditor *editor, DocumentModel::editorsForDocument(document)) {
+ const QList<IEditor *> editors = DocumentModel::editorsForDocument(document);
+ for (IEditor *editor : editors) {
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) {
project->editorConfiguration()->configureEditor(textEditor);
}
@@ -892,7 +895,7 @@ bool SessionManager::cloneSession(const QString &original, const QString &clone)
void SessionManagerPrivate::restoreValues(const PersistentSettingsReader &reader)
{
const QStringList keys = reader.restoreValue(QLatin1String("valueKeys")).toStringList();
- foreach (const QString &key, keys) {
+ for (const QString &key : keys) {
QVariant value = reader.restoreValue(QLatin1String("value-") + key);
m_values.insert(key, value);
}
@@ -905,7 +908,8 @@ void SessionManagerPrivate::restoreDependencies(const PersistentSettingsReader &
while (i != depMap.constEnd()) {
const QString &key = i.key();
QStringList values;
- foreach (const QString &value, i.value().toStringList())
+ const QStringList valueList = i.value().toStringList();
+ for (const QString &value : valueList)
values << value;
m_depMap.insert(key, values);
++i;
@@ -973,7 +977,8 @@ void SessionManagerPrivate::restoreProjects(const FilePaths &fileList)
ProjectExplorerPlugin::OpenProjectResult result = ProjectExplorerPlugin::openProjects(fileList);
if (!result)
ProjectExplorerPlugin::showOpenProjectError(result);
- foreach (Project *p, result.projects())
+ const QList<Project *> projects = result.projects();
+ for (const Project *p : projects)
m_failedProjects.removeAll(p->projectFilePath());
}
}
diff --git a/src/plugins/projectexplorer/simpleprojectwizard.cpp b/src/plugins/projectexplorer/simpleprojectwizard.cpp
index 82a30658aa3..c893cb6a490 100644
--- a/src/plugins/projectexplorer/simpleprojectwizard.cpp
+++ b/src/plugins/projectexplorer/simpleprojectwizard.cpp
@@ -42,7 +42,7 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/filewizardpage.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/wizard.h>
#include <QApplication>
@@ -170,7 +170,7 @@ SimpleProjectWizard::SimpleProjectWizard()
setSupportedProjectTypes({QmakeProjectManager::Constants::QMAKEPROJECT_ID,
CMakeProjectManager::Constants::CMAKE_PROJECT_ID});
setIcon(ProjectExplorer::Icons::WIZARD_IMPORT_AS_PROJECT.icon());
- setDisplayName(tr("Import as qmake or cmake Project (Limited Functionality)"));
+ setDisplayName(tr("Import as qmake or CMake Project (Limited Functionality)"));
setId("Z.DummyProFile");
setDescription(tr("Imports existing projects that do not use qmake, CMake, Qbs, Meson, or Autotools.<p>"
"This creates a project file that allows you to use %1 as a code editor "
@@ -224,7 +224,7 @@ GeneratedFiles generateQmakeFiles(const SimpleProjectWizardDialog *wizard,
for (const FilePath &fileName : wizard->selectedFiles()) {
QString source = dir.relativeFilePath(fileName.toString());
- MimeType mimeType = Utils::mimeTypeForFile(fileName.toFileInfo());
+ MimeType mimeType = Utils::mimeTypeForFile(fileName);
if (mimeType.matchesName("text/x-chdr") || mimeType.matchesName("text/x-c++hdr"))
proHeaders += " $$PWD/" + source + " \\\n";
else
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index 7d9d9c180b5..964461bfb5a 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -621,28 +621,28 @@ void Target::updateDefaultBuildConfigurations()
void Target::updateDefaultDeployConfigurations()
{
- QList<DeployConfigurationFactory *> dcFactories = DeployConfigurationFactory::find(this);
+ const QList<DeployConfigurationFactory *> dcFactories = DeployConfigurationFactory::find(this);
if (dcFactories.isEmpty()) {
qWarning("No deployment configuration factory found for target id '%s'.", qPrintable(id().toString()));
return;
}
QList<Utils::Id> dcIds;
- foreach (DeployConfigurationFactory *dcFactory, dcFactories)
+ for (const DeployConfigurationFactory *dcFactory : dcFactories)
dcIds.append(dcFactory->creationId());
- QList<DeployConfiguration *> dcList = deployConfigurations();
+ const QList<DeployConfiguration *> dcList = deployConfigurations();
QList<Utils::Id> toCreate = dcIds;
- foreach (DeployConfiguration *dc, dcList) {
+ for (DeployConfiguration *dc : dcList) {
if (dcIds.contains(dc->id()))
toCreate.removeOne(dc->id());
else
removeDeployConfiguration(dc);
}
- foreach (Utils::Id id, toCreate) {
- foreach (DeployConfigurationFactory *dcFactory, dcFactories) {
+ for (Utils::Id id : qAsConst(toCreate)) {
+ for (DeployConfigurationFactory *dcFactory : dcFactories) {
if (dcFactory->creationId() == id) {
DeployConfiguration *dc = dcFactory->create(this);
if (dc) {
@@ -680,7 +680,7 @@ void Target::updateDefaultRunConfigurations()
// that produce already existing RCs
QList<RunConfiguration *> toRemove;
QList<RunConfigurationCreationInfo> existing;
- foreach (RunConfiguration *rc, existingConfigured) {
+ for (RunConfiguration *rc : qAsConst(existingConfigured)) {
bool present = false;
for (const RunConfigurationCreationInfo &item : creators) {
QString buildKey = rc->buildKey();
@@ -697,7 +697,7 @@ void Target::updateDefaultRunConfigurations()
bool removeExistingUnconfigured = false;
if (ProjectExplorerPlugin::projectExplorerSettings().automaticallyCreateRunConfigurations) {
// Create new "automatic" RCs and put them into newConfigured/newUnconfigured
- foreach (const RunConfigurationCreationInfo &item, creators) {
+ for (const RunConfigurationCreationInfo &item : creators) {
if (item.creationMode == RunConfigurationCreationInfo::ManualCreationOnly)
continue;
bool exists = false;
@@ -735,14 +735,14 @@ void Target::updateDefaultRunConfigurations()
}
// Do actual changes:
- foreach (RunConfiguration *rc, newConfigured)
+ for (RunConfiguration *rc : qAsConst(newConfigured))
addRunConfiguration(rc);
- foreach (RunConfiguration *rc, newUnconfigured)
+ for (RunConfiguration *rc : qAsConst(newUnconfigured))
addRunConfiguration(rc);
// Generate complete list of RCs to remove later:
QList<RunConfiguration *> removalList;
- foreach (RunConfiguration *rc, toRemove) {
+ for (RunConfiguration *rc : qAsConst(toRemove)) {
removalList << rc;
existingConfigured.removeOne(rc); // make sure to also remove them from existingConfigured!
}
@@ -778,7 +778,7 @@ void Target::updateDefaultRunConfigurations()
}
// Remove the RCs that are no longer needed:
- foreach (RunConfiguration *rc, removalList)
+ for (RunConfiguration *rc : qAsConst(removalList))
removeRunConfiguration(rc);
}
@@ -803,11 +803,6 @@ QVariant Target::additionalData(Utils::Id id) const
return {};
}
-MakeInstallCommand Target::makeInstallCommand(const QString &installRoot) const
-{
- return project()->makeInstallCommand(this, installRoot);
-}
-
MacroExpander *Target::macroExpander() const
{
return &d->m_macroExpander;
diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h
index 12cf80d01aa..b1ff67c2d2f 100644
--- a/src/plugins/projectexplorer/target.h
+++ b/src/plugins/projectexplorer/target.h
@@ -25,9 +25,12 @@
#pragma once
-#include "projectconfiguration.h"
#include "projectexplorer_export.h"
+#include <utils/id.h>
+
+#include <QObject>
+
#include <memory>
QT_FORWARD_DECLARE_CLASS(QIcon)
@@ -41,7 +44,6 @@ class BuildSystem;
class DeployConfiguration;
class DeploymentData;
class Kit;
-class MakeInstallCommand;
class Project;
class ProjectConfigurationModel;
class RunConfiguration;
@@ -114,7 +116,6 @@ public:
void setNamedSettings(const QString &name, const QVariant &value);
QVariant additionalData(Utils::Id id) const;
- MakeInstallCommand makeInstallCommand(const QString &installRoot) const;
Utils::MacroExpander *macroExpander() const;
diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp
index 95dacf0a623..53514032a39 100644
--- a/src/plugins/projectexplorer/targetsettingspanel.cpp
+++ b/src/plugins/projectexplorer/targetsettingspanel.cpp
@@ -289,7 +289,8 @@ public:
case Qt::DecorationRole: {
const Kit *k = KitManager::kit(m_kitId);
- QTC_ASSERT(k, return QVariant());
+ if (!k)
+ break;
if (m_kitErrorsForProject)
return kitIconWithOverlay(*k, IconOverlay::Error);
if (!isEnabled())
@@ -317,7 +318,8 @@ public:
case Qt::ToolTipRole: {
Kit *k = KitManager::kit(m_kitId);
- QTC_ASSERT(k, return QVariant());
+ if (!k)
+ break;
const QString extraText = [this]() {
if (m_kitErrorsForProject)
return QString("<h3>" + tr("Kit is unsuited for project") + "</h3>");
diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp
index a46424798dc..0c86b06000a 100644
--- a/src/plugins/projectexplorer/targetsetuppage.cpp
+++ b/src/plugins/projectexplorer/targetsetuppage.cpp
@@ -138,11 +138,15 @@ public:
verticalLayout->setContentsMargins(0, 0, 0, 0);
verticalLayout->addWidget(scrollArea);
+ auto horizontalLayout = new QHBoxLayout;
+ horizontalLayout->addWidget(allKitsCheckBox);
+ horizontalLayout->addSpacing(10);
+ horizontalLayout->addWidget(kitFilterLineEdit);
+
auto verticalLayout_2 = new QVBoxLayout(setupTargetPage);
verticalLayout_2->addWidget(headerLabel);
- verticalLayout_2->addWidget(kitFilterLineEdit);
+ verticalLayout_2->addLayout(horizontalLayout);
verticalLayout_2->addWidget(noValidKitLabel);
- verticalLayout_2->addWidget(allKitsCheckBox);
verticalLayout_2->addWidget(centralWidget);
verticalLayout_2->addWidget(scrollAreaWidget);
@@ -550,7 +554,7 @@ void TargetSetupPage::doInitializePage()
void TargetSetupPage::showEvent(QShowEvent *event)
{
WizardPage::showEvent(event);
- setFocus(); // Ensure "Configure Project" gets triggered on <Return>
+ m_ui->kitFilterLineEdit->setFocus(); // Ensure "Configure Project" gets triggered on <Return>
}
void TargetSetupPage::changeAllKitsSelections()
diff --git a/src/plugins/projectexplorer/targetsetupwidget.cpp b/src/plugins/projectexplorer/targetsetupwidget.cpp
index 2982ed9ad64..91814cdc05f 100644
--- a/src/plugins/projectexplorer/targetsetupwidget.cpp
+++ b/src/plugins/projectexplorer/targetsetupwidget.cpp
@@ -375,7 +375,7 @@ QPair<Task::TaskType, QString> TargetSetupWidget::findIssues(const BuildInfo &in
QString text;
Task::TaskType highestType = Task::Unknown;
- foreach (const Task &t, issues) {
+ for (const Task &t : qAsConst(issues)) {
if (!text.isEmpty())
text.append(QLatin1String("<br>"));
// set severity:
diff --git a/src/plugins/projectexplorer/taskhub.cpp b/src/plugins/projectexplorer/taskhub.cpp
index ec402ad03bf..d8962d8fc9c 100644
--- a/src/plugins/projectexplorer/taskhub.cpp
+++ b/src/plugins/projectexplorer/taskhub.cpp
@@ -153,11 +153,18 @@ void TaskHub::addTask(Task::TaskType type, const QString &description, Utils::Id
void TaskHub::addTask(Task task)
{
+ if (QThread::currentThread() != qApp->thread()) {
+ QMetaObject::invokeMethod(qApp, [task = std::move(task)] {
+ TaskHub::addTask(task);
+ });
+
+ return;
+ }
+
QTC_ASSERT(m_registeredCategories.contains(task.category), return);
QTC_ASSERT(!task.description().isEmpty(), return);
QTC_ASSERT(!task.isNull(), return);
QTC_ASSERT(task.m_mark.isNull(), return);
- QTC_ASSERT(QThread::currentThread() == qApp->thread(), return);
if (task.file.isEmpty() || task.line <= 0)
task.line = -1;
diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp
index 36b6c942a1f..3d58e7a6874 100644
--- a/src/plugins/projectexplorer/taskmodel.cpp
+++ b/src/plugins/projectexplorer/taskmodel.cpp
@@ -97,7 +97,7 @@ Tasks TaskModel::tasks(Utils::Id categoryId) const
return m_tasks;
Tasks taskList;
- foreach (const Task &t, m_tasks) {
+ for (const Task &t : qAsConst(m_tasks)) {
if (t.category == categoryId)
taskList.append(t);
}
diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp
index 5e446246b15..9530ccbb81f 100644
--- a/src/plugins/projectexplorer/taskwindow.cpp
+++ b/src/plugins/projectexplorer/taskwindow.cpp
@@ -641,7 +641,8 @@ void TaskWindow::updateCategoriesMenu()
const QList<Utils::Id> filteredCategories = d->m_filter->filteredCategories();
QMap<QString, Utils::Id> nameToIds;
- foreach (Utils::Id categoryId, d->m_model->categoryIds())
+ const QList<Utils::Id> ids = d->m_model->categoryIds();
+ for (const Utils::Id categoryId : ids)
nameToIds.insert(d->m_model->categoryDisplayName(categoryId), categoryId);
const NameToIdsConstIt cend = nameToIds.constEnd();
diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp
index 945835fa4ff..32d39fc0806 100644
--- a/src/plugins/projectexplorer/toolchain.cpp
+++ b/src/plugins/projectexplorer/toolchain.cpp
@@ -26,6 +26,7 @@
#include "toolchain.h"
#include "abi.h"
+#include "devicesupport/idevice.h"
#include "headerpath.h"
#include "projectexplorerconstants.h"
#include "toolchainmanager.h"
@@ -342,6 +343,11 @@ void ToolChain::setCompilerCommand(const FilePath &command)
toolChainUpdated();
}
+bool ToolChain::matchesCompilerCommand(const Utils::FilePath &command, const Environment &env) const
+{
+ return env.isSameExecutable(compilerCommand().toString(), command.toString());
+}
+
void ToolChain::setCompilerCommandKey(const QString &commandKey)
{
d->m_compilerCommandKey = commandKey;
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index 133b9d39e36..1b6ed3e7a2b 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -28,7 +28,7 @@
#include "projectexplorer_export.h"
#include "abi.h"
-#include "devicesupport/idevice.h"
+#include "devicesupport/idevicefwd.h"
#include "headerpath.h"
#include "projectmacro.h"
#include "task.h"
@@ -147,7 +147,7 @@ public:
// A BuiltInHeaderPathsRunner is created in the ui thread and runs in another thread.
using BuiltInHeaderPathsRunner = std::function<HeaderPaths(
- const QStringList &cxxflags, const QString &sysRoot, const QString &originalTargetTriple)>;
+ const QStringList &cxxflags, const Utils::FilePath &sysRoot, const QString &originalTargetTriple)>;
virtual BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(const Utils::Environment &env) const = 0;
virtual void addToEnvironment(Utils::Environment &env) const = 0;
virtual Utils::FilePath makeCommand(const Utils::Environment &env) const = 0;
@@ -156,6 +156,9 @@ public:
virtual Utils::FilePath compilerCommand() const; // FIXME: De-virtualize.
void setCompilerCommand(const Utils::FilePath &command);
+ virtual bool matchesCompilerCommand(
+ const Utils::FilePath &command,
+ const Utils::Environment &env = Utils::Environment::systemEnvironment()) const;
virtual QList<Utils::OutputLineParser *> createOutputParsers() const = 0;
@@ -251,14 +254,14 @@ class PROJECTEXPLORER_EXPORT ToolchainDetector
{
public:
ToolchainDetector(const Toolchains &alreadyKnown,
- const IDevice::ConstPtr &device,
+ const IDeviceConstPtr &device,
const Utils::FilePaths &searchPaths);
bool isBadToolchain(const Utils::FilePath &toolchain) const;
void addBadToolchain(const Utils::FilePath &toolchain) const;
const Toolchains alreadyKnown;
- const IDevice::ConstPtr device;
+ const IDeviceConstPtr device;
const Utils::FilePaths searchPaths; // If empty use device path and/or magic.
};
diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp
index 012800a18eb..1e5dc4ce5cf 100644
--- a/src/plugins/projectexplorer/toolchainmanager.cpp
+++ b/src/plugins/projectexplorer/toolchainmanager.cpp
@@ -220,7 +220,7 @@ bool ToolChainManager::registerToolChain(ToolChain *tc)
if (d->m_toolChains.contains(tc))
return true;
- foreach (ToolChain *current, d->m_toolChains) {
+ for (const ToolChain *current : qAsConst(d->m_toolChains)) {
if (*tc == *current && !tc->isAutoDetected())
return false;
QTC_ASSERT(current->id() != tc->id(), return false);
diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp
index 1690c29e69d..b8dccb01998 100644
--- a/src/plugins/projectexplorer/toolchainoptionspage.cpp
+++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp
@@ -96,12 +96,17 @@ public:
font.setBold(changed);
return font;
}
- case Qt::ToolTipRole:
- if (!toolChain->isValid())
- return ToolChainOptionsPage::tr("This toolchain is invalid.");
- return ToolChainOptionsPage::tr("<nobr><b>ABI:</b> %1").arg(
- changed ? ToolChainOptionsPage::tr("not up-to-date")
- : toolChain->targetAbi().toString());
+ case Qt::ToolTipRole: {
+ QString toolTip;
+ if (toolChain->isValid()) {
+ toolTip = ToolChainOptionsPage::tr("<nobr><b>ABI:</b> %1").arg(
+ changed ? ToolChainOptionsPage::tr("not up-to-date")
+ : toolChain->targetAbi().toString());
+ } else {
+ toolTip = ToolChainOptionsPage::tr("This toolchain is invalid.");
+ }
+ return QVariant("<div style=\"white-space:pre\">" + toolTip + "</div>");
+ }
case Qt::DecorationRole:
return column == 0 && !toolChain->isValid()
? Utils::Icons::CRITICAL.icon() : QVariant();
@@ -165,7 +170,8 @@ public:
{ProjectExplorer::Constants::msgAutoDetectedToolTip()});
auto manualRoot = new StaticTreeItem(ProjectExplorer::Constants::msgManual());
- foreach (const Utils::Id &l, ToolChainManager::allLanguages()) {
+ const QList<Utils::Id> languages = ToolChainManager::allLanguages();
+ for (const Utils::Id &l : languages) {
const QString dn = ToolChainManager::displayNameOfLanguageId(l);
auto autoNode = new StaticTreeItem(dn);
auto manualNode = new StaticTreeItem(dn);
@@ -191,7 +197,7 @@ public:
m_addButton = new QPushButton(ToolChainOptionsPage::tr("Add"), this);
auto addMenu = new QMenu;
- foreach (ToolChainFactory *factory, m_factories) {
+ for (ToolChainFactory *factory : qAsConst(m_factories)) {
QList<Utils::Id> languages = factory->supportedLanguages();
if (languages.isEmpty())
continue;
@@ -203,7 +209,7 @@ public:
return ToolChainManager::displayNameOfLanguageId(l1) < ToolChainManager::displayNameOfLanguageId(l2);
});
auto subMenu = addMenu->addMenu(factory->displayName());
- foreach (const Utils::Id &l, languages)
+ for (const Utils::Id &l : qAsConst(languages))
subMenu->addAction(createAction(ToolChainManager::displayNameOfLanguageId(l), factory, l));
}
}
@@ -357,27 +363,24 @@ ToolChainTreeItem *ToolChainOptionsWidget::insertToolChain(ToolChain *tc, bool c
void ToolChainOptionsWidget::addToolChain(ToolChain *tc)
{
- foreach (ToolChainTreeItem *n, m_toAddList) {
- if (n->toolChain == tc) {
- // do not delete n: Still used elsewhere!
- m_toAddList.removeOne(n);
- return;
- }
+ if (Utils::eraseOne(m_toAddList, [tc](const ToolChainTreeItem *item) {
+ return item->toolChain == tc; })) {
+ // do not delete here!
+ return;
}
insertToolChain(tc);
-
updateState();
}
void ToolChainOptionsWidget::removeToolChain(ToolChain *tc)
{
- foreach (ToolChainTreeItem *n, m_toRemoveList) {
- if (n->toolChain == tc) {
- m_toRemoveList.removeOne(n);
- delete n;
- return;
- }
+ if (auto it = std::find_if(m_toRemoveList.begin(), m_toRemoveList.end(),
+ [tc](const ToolChainTreeItem *item) { return item->toolChain == tc; });
+ it != m_toRemoveList.end()) {
+ m_toRemoveList.erase(it);
+ delete *it;
+ return;
}
StaticTreeItem *parent = parentForToolChain(tc);
@@ -451,13 +454,14 @@ void ToolChainOptionsWidget::apply()
{
// Remove unused tool chains:
QList<ToolChainTreeItem *> nodes = m_toRemoveList;
- foreach (ToolChainTreeItem *n, nodes)
+ for (const ToolChainTreeItem *n : qAsConst(nodes))
ToolChainManager::deregisterToolChain(n->toolChain);
Q_ASSERT(m_toRemoveList.isEmpty());
// Update tool chains:
- foreach (const Utils::Id &l, m_languageMap.keys()) {
+ const QList<Utils::Id> languages = m_languageMap.keys();
+ for (const Utils::Id &l : languages) {
const QPair<StaticTreeItem *, StaticTreeItem *> autoAndManual = m_languageMap.value(l);
for (StaticTreeItem *parent : {autoAndManual.first, autoAndManual.second}) {
for (TreeItem *item : *parent) {
@@ -474,12 +478,13 @@ void ToolChainOptionsWidget::apply()
// Add new (and already updated) tool chains
QStringList removedTcs;
nodes = m_toAddList;
- foreach (ToolChainTreeItem *n, nodes) {
+ for (const ToolChainTreeItem *n : qAsConst(nodes)) {
if (!ToolChainManager::registerToolChain(n->toolChain))
removedTcs << n->toolChain->displayName();
}
//
- foreach (ToolChainTreeItem *n, m_toAddList)
+ const QList<ToolChainTreeItem *> toAddList = m_toAddList;
+ for (ToolChainTreeItem *n : toAddList)
markForRemoval(n);
qDeleteAll(m_toAddList);
diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
index 4db892b391e..c4fa29466a2 100644
--- a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
+++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
@@ -25,6 +25,7 @@
#include "toolchainsettingsaccessor.h"
+#include "projectexplorerconstants.h"
#include "toolchain.h"
#include <coreplugin/icore.h>
@@ -56,9 +57,9 @@ public:
// Helpers:
// --------------------------------------------------------------------
-static const char TOOLCHAIN_DATA_KEY[] = "ToolChain.";
-static const char TOOLCHAIN_COUNT_KEY[] = "ToolChain.Count";
-static const char TOOLCHAIN_FILENAME[] = "toolchains.xml";
+const char TOOLCHAIN_DATA_KEY[] = "ToolChain.";
+const char TOOLCHAIN_COUNT_KEY[] = "ToolChain.Count";
+const char TOOLCHAIN_FILENAME[] = "toolchains.xml";
struct ToolChainOperations
{
@@ -80,7 +81,7 @@ static Toolchains autoDetectToolChains(const ToolchainDetector &detector)
static Toolchains makeUniqueByEqual(const Toolchains &a)
{
Toolchains result;
- foreach (ToolChain *tc, a) {
+ for (ToolChain *tc : a) {
if (!Utils::contains(result, [tc](ToolChain *rtc) { return *tc == *rtc; }))
result.append(tc);
}
@@ -211,8 +212,11 @@ Toolchains ToolChainSettingsAccessor::restoreToolChains(QWidget *parent) const
const ToolChainOperations ops = mergeToolChainLists(systemFileTcs, userFileTcs, autodetectedTcs);
// Process ops:
- for (ToolChain *tc : ops.toDemote)
- tc->setDetection(ToolChain::ManualDetection);
+ for (ToolChain *tc : ops.toDemote) {
+ // FIXME: We currently only demote local toolchains, as they are not redetected.
+ if (tc->detectionSource().isEmpty())
+ tc->setDetection(ToolChain::ManualDetection);
+ }
qDeleteAll(ops.toDelete);
@@ -281,8 +285,6 @@ Toolchains ToolChainSettingsAccessor::toolChains(const QVariantMap &data) const
#ifdef WITH_TESTS
#include "projectexplorer.h"
-#include "headerpath.h"
-
#include "abi.h"
#include "toolchainconfigwidget.h"
diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.h b/src/plugins/projectexplorer/toolchainsettingsaccessor.h
index 80d3f90fd6d..9f12bc182a2 100644
--- a/src/plugins/projectexplorer/toolchainsettingsaccessor.h
+++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.h
@@ -29,8 +29,6 @@
#include <QList>
-#include <memory>
-
namespace ProjectExplorer {
class ToolChain;
diff --git a/src/plugins/projectexplorer/treescanner.h b/src/plugins/projectexplorer/treescanner.h
index 26992448928..73b39a4792e 100644
--- a/src/plugins/projectexplorer/treescanner.h
+++ b/src/plugins/projectexplorer/treescanner.h
@@ -28,8 +28,8 @@
#include "projectexplorer_export.h"
#include "projectnodes.h"
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
+#include <utils/mimeutils.h>
#include <QObject>
#include <QFuture>
diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp
index 39749ba5a34..173153a2e6e 100644
--- a/src/plugins/projectexplorer/userfileaccessor.cpp
+++ b/src/plugins/projectexplorer/userfileaccessor.cpp
@@ -704,8 +704,8 @@ QVariantMap UserFileVersion16Upgrader::upgrade(const QVariantMap &data)
NamePolicy policy = oldSteps.size() > 1 ? RenameBuildConfiguration : KeepName;
- foreach (const QVariantMap &oldBuildConfiguration, oldBuildConfigurations) {
- foreach (const OldStepMaps &oldStep, oldSteps) {
+ for (const QVariantMap &oldBuildConfiguration : qAsConst(oldBuildConfigurations)) {
+ for (const OldStepMaps &oldStep : qAsConst(oldSteps)) {
QVariantMap newBuildConfiguration = insertSteps(oldBuildConfiguration, oldStep, policy);
if (!newBuildConfiguration.isEmpty())
newBuildConfigurations.append(newBuildConfiguration);
@@ -735,7 +735,7 @@ QVariant UserFileVersion17Upgrader::process(const QVariant &entry)
switch (entry.type()) {
case QVariant::List: {
QVariantList result;
- foreach (const QVariant &item, entry.toList())
+ for (const QVariant &item : entry.toList())
result.append(process(item));
return result;
}
diff --git a/src/plugins/projectexplorer/waitforstopdialog.cpp b/src/plugins/projectexplorer/waitforstopdialog.cpp
index f2d3abb1521..0b825492dcf 100644
--- a/src/plugins/projectexplorer/waitforstopdialog.cpp
+++ b/src/plugins/projectexplorer/waitforstopdialog.cpp
@@ -35,8 +35,8 @@
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
-WaitForStopDialog::WaitForStopDialog(QList<ProjectExplorer::RunControl *> runControls) :
- m_runControls(runControls)
+WaitForStopDialog::WaitForStopDialog(const QList<ProjectExplorer::RunControl *> &runControls)
+ : m_runControls(runControls)
{
setWindowTitle(tr("Waiting for Applications to Stop"));
@@ -53,7 +53,7 @@ WaitForStopDialog::WaitForStopDialog(QList<ProjectExplorer::RunControl *> runCon
updateProgressText();
- foreach (RunControl *rc, runControls)
+ for (const RunControl *rc : runControls)
connect(rc, &RunControl::stopped, this, &WaitForStopDialog::runControlFinished);
m_timer.start();
diff --git a/src/plugins/projectexplorer/waitforstopdialog.h b/src/plugins/projectexplorer/waitforstopdialog.h
index 2a1d0e32137..602b1812025 100644
--- a/src/plugins/projectexplorer/waitforstopdialog.h
+++ b/src/plugins/projectexplorer/waitforstopdialog.h
@@ -42,7 +42,7 @@ class WaitForStopDialog : public QDialog
{
Q_OBJECT
public:
- explicit WaitForStopDialog(QList<ProjectExplorer::RunControl *> runControls);
+ explicit WaitForStopDialog(const QList<ProjectExplorer::RunControl *> &runControls);
bool canceled();
private:
diff --git a/src/plugins/projectexplorer/windebuginterface.cpp b/src/plugins/projectexplorer/windebuginterface.cpp
index e9fdb939a5c..59091e8ebcd 100644
--- a/src/plugins/projectexplorer/windebuginterface.cpp
+++ b/src/plugins/projectexplorer/windebuginterface.cpp
@@ -56,9 +56,9 @@ WinDebugInterface *WinDebugInterface::instance()
bool WinDebugInterface::stop()
{
- if (!m_waitHandles[TerminateEventHandle])
+ if (!m_instance->m_waitHandles[TerminateEventHandle])
return false;
- SetEvent(m_waitHandles[TerminateEventHandle]);
+ SetEvent(m_instance->m_waitHandles[TerminateEventHandle]);
return true;
}
@@ -198,6 +198,12 @@ void WinDebugInterface::dispatchDebugOutput()
emit _q_debugOutputReady();
}
+void WinDebugInterface::startIfNeeded()
+{
+ if (!m_instance->isRunning())
+ m_instance->start();
+}
+
} // namespace Internal
} // namespace ProjectExplorer
@@ -222,6 +228,10 @@ void WinDebugInterface::emitReadySignal() { }
void WinDebugInterface::dispatchDebugOutput() { }
+bool WinDebugInterface::stop() { return false; }
+
+void WinDebugInterface::startIfNeeded() { }
+
} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/windebuginterface.h b/src/plugins/projectexplorer/windebuginterface.h
index e4593940384..61bd0498216 100644
--- a/src/plugins/projectexplorer/windebuginterface.h
+++ b/src/plugins/projectexplorer/windebuginterface.h
@@ -45,7 +45,8 @@ public:
static WinDebugInterface *instance();
- bool stop();
+ static bool stop();
+ static void startIfNeeded();
signals:
void debugOutput(qint64 pid, const QString &message);
diff --git a/src/plugins/projectexplorer/xcodebuildparser.h b/src/plugins/projectexplorer/xcodebuildparser.h
index f7197322acc..e528edd5a9f 100644
--- a/src/plugins/projectexplorer/xcodebuildparser.h
+++ b/src/plugins/projectexplorer/xcodebuildparser.h
@@ -27,7 +27,6 @@
#include "projectexplorer_export.h"
#include "ioutputparser.h"
-#include "devicesupport/idevice.h"
#include <QRegularExpression>
#include <QStringList>
diff --git a/src/plugins/python/CMakeLists.txt b/src/plugins/python/CMakeLists.txt
index 42984eb91ee..a508e14ddc8 100644
--- a/src/plugins/python/CMakeLists.txt
+++ b/src/plugins/python/CMakeLists.txt
@@ -2,6 +2,10 @@ add_qtc_plugin(Python
DEPENDS QmlJS
PLUGIN_DEPENDS Core LanguageClient ProjectExplorer TextEditor
SOURCES
+ pipsupport.cpp pipsupport.h
+ pyside.cpp pyside.h
+ pysidebuildconfiguration.cpp pysidebuildconfiguration.h
+ pysideuicextracompiler.cpp pysideuicextracompiler.h
python.qrc
pythonconstants.h
pythoneditor.cpp pythoneditor.h
diff --git a/src/plugins/python/pipsupport.cpp b/src/plugins/python/pipsupport.cpp
new file mode 100644
index 00000000000..3d479f871ba
--- /dev/null
+++ b/src/plugins/python/pipsupport.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pipsupport.h"
+
+#include "pythonproject.h"
+#include "pythonrunconfiguration.h"
+#include "pythonsettings.h"
+
+#include <coreplugin/messagemanager.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/target.h>
+
+#include <utils/algorithm.h>
+#include <utils/mimeutils.h>
+#include <utils/qtcprocess.h>
+
+using namespace Utils;
+
+namespace Python {
+namespace Internal {
+
+static constexpr char pipInstallTaskId[] = "Python::pipInstallTask";
+
+PipInstallTask::PipInstallTask(const FilePath &python)
+ : m_python(python)
+{
+ connect(&m_process, &QtcProcess::done, this, &PipInstallTask::handleDone);
+ connect(&m_process, &QtcProcess::readyReadStandardError, this, &PipInstallTask::handleError);
+ connect(&m_process, &QtcProcess::readyReadStandardOutput, this, &PipInstallTask::handleOutput);
+ connect(&m_killTimer, &QTimer::timeout, this, &PipInstallTask::cancel);
+ connect(&m_watcher, &QFutureWatcher<void>::canceled, this, &PipInstallTask::cancel);
+ m_watcher.setFuture(m_future.future());
+}
+
+void PipInstallTask::setPackage(const PipPackage &package)
+{
+ m_package = package;
+}
+
+void PipInstallTask::run()
+{
+ if (m_package.packageName.isEmpty()) {
+ emit finished(false);
+ return;
+ }
+ const QString taskTitle = tr("Install %1").arg(m_package.displayName);
+ Core::ProgressManager::addTask(m_future.future(), taskTitle, pipInstallTaskId);
+ QString package = m_package.packageName;
+ if (!m_package.version.isEmpty())
+ package += "==" + m_package.version;
+ QStringList arguments = {"-m", "pip", "install", package};
+
+ // add --user to global pythons, but skip it for venv pythons
+ if (!QDir(m_python.parentDir().toString()).exists("activate"))
+ arguments << "--user";
+
+ m_process.setCommand({m_python, arguments});
+ m_process.start();
+
+ Core::MessageManager::writeDisrupting(
+ tr("Running \"%1\" to install %2.")
+ .arg(m_process.commandLine().toUserOutput(), m_package.displayName));
+
+ m_killTimer.setSingleShot(true);
+ m_killTimer.start(5 /*minutes*/ * 60 * 1000);
+}
+
+void PipInstallTask::cancel()
+{
+ m_process.stop();
+ m_process.waitForFinished();
+ Core::MessageManager::writeFlashing(
+ tr("The %1 installation was canceled by %2.")
+ .arg(m_package.displayName, m_killTimer.isActive() ? tr("user") : tr("time out")));
+}
+
+void PipInstallTask::handleDone()
+{
+ m_future.reportFinished();
+ const bool success = m_process.result() == ProcessResult::FinishedWithSuccess;
+ if (!success) {
+ Core::MessageManager::writeFlashing(tr("Installing the %1 failed with exit code %2")
+ .arg(m_package.displayName).arg(m_process.exitCode()));
+ }
+ emit finished(success);
+}
+
+void PipInstallTask::handleOutput()
+{
+ const QString &stdOut = QString::fromLocal8Bit(m_process.readAllStandardOutput().trimmed());
+ if (!stdOut.isEmpty())
+ Core::MessageManager::writeSilently(stdOut);
+}
+
+void PipInstallTask::handleError()
+{
+ const QString &stdErr = QString::fromLocal8Bit(m_process.readAllStandardError().trimmed());
+ if (!stdErr.isEmpty())
+ Core::MessageManager::writeSilently(stdErr);
+}
+
+PipPackageInfo PipPackage::info(const FilePath &python) const
+{
+ PipPackageInfo result;
+
+ QtcProcess pip;
+ pip.setCommand(CommandLine(python, {"-m", "pip", "show", "-f", packageName}));
+ pip.runBlocking();
+ QString fieldName;
+ QStringList data;
+ const QString pipOutput = pip.allOutput();
+ for (const QString &line : pipOutput.split('\n')) {
+ if (line.isEmpty())
+ continue;
+ if (line.front().isSpace()) {
+ data.append(line.trimmed());
+ } else {
+ result.parseField(fieldName, data);
+ if (auto colonPos = line.indexOf(':'); colonPos >= 0) {
+ fieldName = line.left(colonPos);
+ data = QStringList(line.mid(colonPos + 1).trimmed());
+ } else {
+ fieldName.clear();
+ data.clear();
+ }
+ }
+ }
+ result.parseField(fieldName, data);
+ return result;
+}
+
+void PipPackageInfo::parseField(const QString &field, const QStringList &data)
+{
+ if (field.isEmpty())
+ return;
+ if (field == "Name") {
+ name = data.value(0);
+ } else if (field == "Version") {
+ version = data.value(0);
+ } else if (field == "Summary") {
+ summary = data.value(0);
+ } else if (field == "Home-page") {
+ homePage = QUrl(data.value(0));
+ } else if (field == "Author") {
+ author = data.value(0);
+ } else if (field == "Author-email") {
+ authorEmail = data.value(0);
+ } else if (field == "License") {
+ license = data.value(0);
+ } else if (field == "Location") {
+ location = FilePath::fromUserInput(data.value(0)).normalizedPathName();
+ } else if (field == "Requires") {
+ requiresPackage = data.value(0).split(',', Qt::SkipEmptyParts);
+ } else if (field == "Required-by") {
+ requiredByPackage = data.value(0).split(',', Qt::SkipEmptyParts);
+ } else if (field == "Files") {
+ for (const QString &fileName : data) {
+ if (!fileName.isEmpty())
+ files.append(FilePath::fromUserInput(fileName.trimmed()));
+ }
+ }
+}
+
+} // namespace Internal
+} // namespace Python
diff --git a/src/plugins/python/pipsupport.h b/src/plugins/python/pipsupport.h
new file mode 100644
index 00000000000..9aeded08ab0
--- /dev/null
+++ b/src/plugins/python/pipsupport.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/filepath.h>
+#include <utils/qtcprocess.h>
+
+#include <QFutureWatcher>
+#include <QTimer>
+
+namespace Python {
+namespace Internal {
+
+class PipPackageInfo;
+
+class PipPackage
+{
+public:
+ explicit PipPackage(const QString &packageName = {},
+ const QString &displayName = {},
+ const QString &version = {})
+ : packageName(packageName)
+ , displayName(displayName.isEmpty() ? packageName : displayName)
+ , version(version)
+ {}
+ QString packageName;
+ QString displayName;
+ QString version;
+
+ PipPackageInfo info(const Utils::FilePath &python) const;
+};
+
+class PipPackageInfo
+{
+public:
+ QString name;
+ QString version;
+ QString summary;
+ QUrl homePage;
+ QString author;
+ QString authorEmail;
+ QString license;
+ Utils::FilePath location;
+ QStringList requiresPackage;
+ QStringList requiredByPackage;
+ Utils::FilePaths files;
+
+ void parseField(const QString &field, const QStringList &value);
+};
+
+class PipInstallTask : public QObject
+{
+ Q_OBJECT
+public:
+ explicit PipInstallTask(const Utils::FilePath &python);
+ void setPackage(const PipPackage &package);
+ void run();
+
+signals:
+ void finished(bool success);
+
+private:
+ void cancel();
+ void handleDone();
+ void handleOutput();
+ void handleError();
+
+ const Utils::FilePath m_python;
+ PipPackage m_package;
+ Utils::QtcProcess m_process;
+ QFutureInterface<void> m_future;
+ QFutureWatcher<void> m_watcher;
+ QTimer m_killTimer;
+};
+
+} // namespace Internal
+} // namespace Python
diff --git a/src/plugins/python/pyside.cpp b/src/plugins/python/pyside.cpp
new file mode 100644
index 00000000000..2bdfebc2783
--- /dev/null
+++ b/src/plugins/python/pyside.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pyside.h"
+
+#include "pythonconstants.h"
+#include "pythonplugin.h"
+#include "pythonproject.h"
+#include "pythonrunconfiguration.h"
+#include "pythonsettings.h"
+#include "pythonutils.h"
+
+#include <coreplugin/icore.h>
+
+#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/target.h>
+
+#include <texteditor/textdocument.h>
+
+#include <utils/algorithm.h>
+#include <utils/infobar.h>
+#include <utils/runextensions.h>
+
+#include <QRegularExpression>
+#include <QTextCursor>
+
+using namespace Utils;
+using namespace ProjectExplorer;
+
+namespace Python {
+namespace Internal {
+
+static constexpr char installPySideInfoBarId[] = "Python::InstallPySide";
+
+PySideInstaller *PySideInstaller::instance()
+{
+ static PySideInstaller *instance = new PySideInstaller;
+ return instance;
+}
+
+void PySideInstaller::checkPySideInstallation(const FilePath &python,
+ TextEditor::TextDocument *document)
+{
+ document->infoBar()->removeInfo(installPySideInfoBarId);
+ const QString pySide = importedPySide(document->plainText());
+ if (pySide == "PySide2" || pySide == "PySide6")
+ instance()->runPySideChecker(python, pySide, document);
+}
+
+bool PySideInstaller::missingPySideInstallation(const FilePath &pythonPath,
+ const QString &pySide)
+{
+ QTC_ASSERT(!pySide.isEmpty(), return false);
+ static QMap<FilePath, QSet<QString>> pythonWithPyside;
+ if (pythonWithPyside[pythonPath].contains(pySide))
+ return false;
+
+ QtcProcess pythonProcess;
+ pythonProcess.setCommand({pythonPath, {"-c", "import " + pySide}});
+ pythonProcess.runBlocking();
+ const bool missing = pythonProcess.result() != ProcessResult::FinishedWithSuccess;
+ if (!missing)
+ pythonWithPyside[pythonPath].insert(pySide);
+ return missing;
+}
+
+QString PySideInstaller::importedPySide(const QString &text)
+{
+ static QRegularExpression importScanner("^\\s*(import|from)\\s+(PySide\\d)",
+ QRegularExpression::MultilineOption);
+ const QRegularExpressionMatch match = importScanner.match(text);
+ return match.captured(2);
+}
+
+PySideInstaller::PySideInstaller()
+ : QObject(PythonPlugin::instance())
+{}
+
+void PySideInstaller::installPyside(const Utils::FilePath &python,
+ const QString &pySide,
+ TextEditor::TextDocument *document)
+{
+ document->infoBar()->removeInfo(installPySideInfoBarId);
+
+ auto install = new PipInstallTask(python);
+ connect(install, &PipInstallTask::finished, install, &QObject::deleteLater);
+ connect(install, &PipInstallTask::finished, this, [=](bool success){
+ if (success)
+ emit pySideInstalled(python, pySide);
+ });
+ install->setPackage(PipPackage(pySide));
+ install->run();
+}
+
+void PySideInstaller::changeInterpreter(const QString &interpreterId,
+ RunConfiguration *runConfig)
+{
+ if (runConfig) {
+ if (auto aspect = runConfig->aspect<InterpreterAspect>())
+ aspect->setCurrentInterpreter(PythonSettings::interpreter(interpreterId));
+ }
+}
+
+void PySideInstaller::handlePySideMissing(const FilePath &python,
+ const QString &pySide,
+ TextEditor::TextDocument *document)
+{
+ if (!document || !document->infoBar()->canInfoBeAdded(installPySideInfoBarId))
+ return;
+ const QString message = tr("%1 installation missing for %2 (%3)")
+ .arg(pySide, pythonName(python), python.toUserOutput());
+ InfoBarEntry info(installPySideInfoBarId, message, InfoBarEntry::GlobalSuppression::Enabled);
+ auto installCallback = [=]() { installPyside(python, pySide, document); };
+ const QString installTooltip = tr("Install %1 for %2 using pip package installer.")
+ .arg(pySide, python.toUserOutput());
+ info.addCustomButton(tr("Install"), installCallback, installTooltip);
+
+ if (PythonProject *project = pythonProjectForFile(document->filePath())) {
+ if (ProjectExplorer::Target *target = project->activeTarget()) {
+ auto runConfiguration = target->activeRunConfiguration();
+ if (runConfiguration->id() == Constants::C_PYTHONRUNCONFIGURATION_ID) {
+ const QList<InfoBarEntry::ComboInfo> interpreters = Utils::transform(
+ PythonSettings::interpreters(), [](const Interpreter &interpreter) {
+ return InfoBarEntry::ComboInfo{interpreter.name, interpreter.id};
+ });
+ auto interpreterChangeCallback =
+ [=, rc = QPointer<RunConfiguration>(runConfiguration)](
+ const InfoBarEntry::ComboInfo &info) {
+ changeInterpreter(info.data.toString(), rc);
+ };
+
+ auto interpreterAspect = runConfiguration->aspect<InterpreterAspect>();
+ QTC_ASSERT(interpreterAspect, return);
+ const QString id = interpreterAspect->currentInterpreter().id;
+ const auto isCurrentInterpreter = Utils::equal(&InfoBarEntry::ComboInfo::data,
+ QVariant(id));
+ const QString switchTooltip = tr("Switch the Python interpreter for %1")
+ .arg(runConfiguration->displayName());
+ info.setComboInfo(interpreters,
+ interpreterChangeCallback,
+ switchTooltip,
+ Utils::indexOf(interpreters, isCurrentInterpreter));
+ }
+ }
+ }
+ document->infoBar()->addInfo(info);
+}
+
+void PySideInstaller::runPySideChecker(const Utils::FilePath &python,
+ const QString &pySide,
+ TextEditor::TextDocument *document)
+{
+ using CheckPySideWatcher = QFutureWatcher<bool>;
+
+ QPointer<CheckPySideWatcher> watcher = new CheckPySideWatcher();
+
+ // cancel and delete watcher after a 10 second timeout
+ QTimer::singleShot(10000, this, [watcher]() {
+ if (watcher) {
+ watcher->cancel();
+ watcher->deleteLater();
+ }
+ });
+ connect(watcher,
+ &CheckPySideWatcher::resultReadyAt,
+ this,
+ [=, document = QPointer<TextEditor::TextDocument>(document)]() {
+ if (watcher->result())
+ handlePySideMissing(python, pySide, document);
+ watcher->deleteLater();
+ });
+ watcher->setFuture(
+ Utils::runAsync(&missingPySideInstallation, python, pySide));
+}
+
+} // namespace Internal
+} // namespace Python
diff --git a/src/plugins/python/pyside.h b/src/plugins/python/pyside.h
new file mode 100644
index 00000000000..d396c726b4a
--- /dev/null
+++ b/src/plugins/python/pyside.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "pipsupport.h"
+
+#include <utils/filepath.h>
+
+#include <QCoreApplication>
+#include <QTextDocument>
+
+namespace TextEditor { class TextDocument; }
+namespace ProjectExplorer { class RunConfiguration; }
+
+namespace Python {
+namespace Internal {
+
+class PySideInstaller : public QObject
+{
+ Q_OBJECT
+
+public:
+ static PySideInstaller *instance();
+ static void checkPySideInstallation(const Utils::FilePath &python,
+ TextEditor::TextDocument *document);
+
+
+signals:
+ void pySideInstalled(const Utils::FilePath &python, const QString &pySide);
+
+private:
+ PySideInstaller();
+
+ void installPyside(const Utils::FilePath &python,
+ const QString &pySide, TextEditor::TextDocument *document);
+ void changeInterpreter(const QString &interpreterId, ProjectExplorer::RunConfiguration *runConfig);
+ void handlePySideMissing(const Utils::FilePath &python,
+ const QString &pySide,
+ TextEditor::TextDocument *document);
+
+ void runPySideChecker(const Utils::FilePath &python,
+ const QString &pySide,
+ TextEditor::TextDocument *document);
+ static bool missingPySideInstallation(const Utils::FilePath &python, const QString &pySide);
+ static QString importedPySide(const QString &text);
+
+ QHash<Utils::FilePath, QList<TextEditor::TextDocument *>> m_infoBarEntries;
+};
+
+} // namespace Internal
+} // namespace Python
diff --git a/src/plugins/python/pysidebuildconfiguration.cpp b/src/plugins/python/pysidebuildconfiguration.cpp
new file mode 100644
index 00000000000..2e2540755c0
--- /dev/null
+++ b/src/plugins/python/pysidebuildconfiguration.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pysidebuildconfiguration.h"
+
+#include "pipsupport.h"
+#include "pythonconstants.h"
+#include "pythonproject.h"
+#include "pythonrunconfiguration.h"
+#include "pythonsettings.h"
+
+#include <projectexplorer/buildinfo.h>
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/environmentaspect.h>
+#include <projectexplorer/processparameters.h>
+#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/target.h>
+#include <utils/commandline.h>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace Python {
+namespace Internal {
+
+constexpr char pySideBuildStep[] = "Python.PysideBuildStep";
+
+PySideBuildConfigurationFactory::PySideBuildConfigurationFactory()
+{
+ registerBuildConfiguration<PySideBuildConfiguration>("Python.PySideBuildConfiguration");
+ setSupportedProjectType(PythonProjectId);
+ setSupportedProjectMimeTypeName(Constants::C_PY_MIMETYPE);
+ setBuildGenerator([](const Kit *, const FilePath &projectPath, bool) {
+ BuildInfo info;
+ info.displayName = "build";
+ info.typeName = "build";
+ info.buildDirectory = projectPath.parentDir();
+ return QList<BuildInfo>{info};
+ });
+}
+
+PySideBuildStepFactory::PySideBuildStepFactory()
+{
+ registerStep<PySideBuildStep>(pySideBuildStep);
+ setSupportedProjectType(PythonProjectId);
+ setDisplayName(tr("Run PySide6 project tool"));
+ setFlags(BuildStepInfo::UniqueStep);
+}
+
+PySideBuildStep::PySideBuildStep(BuildStepList *bsl, Id id)
+ : AbstractProcessStep(bsl, id)
+{
+ m_pysideProject = addAspect<StringAspect>();
+ m_pysideProject->setSettingsKey("Python.PySideProjectTool");
+ m_pysideProject->setLabelText(tr("PySide project tool:"));
+ m_pysideProject->setToolTip(tr("Enter location of PySide project tool."));
+ m_pysideProject->setDisplayStyle(StringAspect::PathChooserDisplay);
+ m_pysideProject->setExpectedKind(PathChooser::Command);
+ m_pysideProject->setHistoryCompleter("Python.PySideProjectTool.History");
+
+ const FilePath pySideProjectPath = Environment::systemEnvironment().searchInPath(
+ "pyside6-project");
+ if (pySideProjectPath.isExecutableFile())
+ m_pysideProject->setFilePath(pySideProjectPath);
+
+ setCommandLineProvider([this] { return CommandLine(m_pysideProject->filePath(), {"build"}); });
+ setWorkingDirectoryProvider([this] { return target()->project()->projectDirectory(); });
+ setEnvironmentModifier([this](Environment &env) {
+ env.prependOrSetPath(m_pysideProject->filePath().parentDir());
+ });
+}
+
+void PySideBuildStep::updatePySideProjectPath(const Utils::FilePath &pySideProjectPath)
+{
+ m_pysideProject->setFilePath(pySideProjectPath);
+}
+
+void PySideBuildStep::doRun()
+{
+ if (processParameters()->effectiveCommand().isExecutableFile())
+ AbstractProcessStep::doRun();
+ else
+ emit finished(true);
+}
+
+PySideBuildConfiguration::PySideBuildConfiguration(Target *target, Id id)
+ : BuildConfiguration(target, id)
+{
+ setConfigWidgetDisplayName(PySideBuildConfigurationFactory::tr("General"));
+
+ setInitializer([this](const BuildInfo &) {
+ buildSteps()->appendStep(pySideBuildStep);
+ updateCacheAndEmitEnvironmentChanged();
+ });
+
+ updateCacheAndEmitEnvironmentChanged();
+}
+
+} // namespace Internal
+} // namespace Python
diff --git a/src/plugins/python/pysidebuildconfiguration.h b/src/plugins/python/pysidebuildconfiguration.h
new file mode 100644
index 00000000000..3a199f25388
--- /dev/null
+++ b/src/plugins/python/pysidebuildconfiguration.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectexplorer/abstractprocessstep.h>
+#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/buildstep.h>
+
+namespace Python {
+namespace Internal {
+
+class PySideBuildConfiguration : public ProjectExplorer::BuildConfiguration
+{
+public:
+ PySideBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id);
+};
+
+class PySideBuildConfigurationFactory : public ProjectExplorer::BuildConfigurationFactory
+{
+ Q_DECLARE_TR_FUNCTIONS(Python::Internal::PySideBuildConfigurationFactory)
+public:
+ PySideBuildConfigurationFactory();
+};
+
+class PySideBuildStep : public ProjectExplorer::AbstractProcessStep
+{
+ Q_OBJECT
+public:
+ PySideBuildStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
+ void updatePySideProjectPath(const Utils::FilePath &pySideProjectPath);
+
+private:
+ Utils::StringAspect *m_pysideProject;
+
+private:
+ void doRun() override;
+};
+
+class PySideBuildStepFactory : public ProjectExplorer::BuildStepFactory
+{
+ Q_DECLARE_TR_FUNCTIONS(Python::Internal::PySideBuildStepFactory)
+public:
+ PySideBuildStepFactory();
+};
+
+} // namespace Internal
+} // namespace Python
diff --git a/src/plugins/python/pysideuicextracompiler.cpp b/src/plugins/python/pysideuicextracompiler.cpp
new file mode 100644
index 00000000000..b8a2f99ecd9
--- /dev/null
+++ b/src/plugins/python/pysideuicextracompiler.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pysideuicextracompiler.h"
+
+#include <utils/qtcprocess.h>
+
+using namespace ProjectExplorer;
+
+namespace Python {
+namespace Internal {
+
+PySideUicExtraCompiler::PySideUicExtraCompiler(const Utils::FilePath &pySideUic,
+ const Project *project,
+ const Utils::FilePath &source,
+ const Utils::FilePaths &targets,
+ QObject *parent)
+ : ProcessExtraCompiler(project, source, targets, parent)
+ , m_pySideUic(pySideUic)
+{
+}
+
+Utils::FilePath PySideUicExtraCompiler::pySideUicPath() const
+{
+ return m_pySideUic;
+}
+
+Utils::FilePath PySideUicExtraCompiler::command() const
+{
+ return m_pySideUic;
+}
+
+FileNameToContentsHash PySideUicExtraCompiler::handleProcessFinished(
+ Utils::QtcProcess *process)
+{
+ FileNameToContentsHash result;
+ if (process->exitStatus() != QProcess::NormalExit && process->exitCode() != 0)
+ return result;
+
+ const Utils::FilePaths targetList = targets();
+ if (targetList.size() != 1)
+ return result;
+ // As far as I can discover in the UIC sources, it writes out local 8-bit encoding. The
+ // conversion below is to normalize both the encoding, and the line terminators.
+ result[targetList.first()] = QString::fromLocal8Bit(process->readAllStandardOutput()).toUtf8();
+ return result;
+}
+
+} // namespace Internal
+} // namespace Python
diff --git a/src/plugins/python/pysideuicextracompiler.h b/src/plugins/python/pysideuicextracompiler.h
new file mode 100644
index 00000000000..202f2a5d71b
--- /dev/null
+++ b/src/plugins/python/pysideuicextracompiler.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectexplorer/extracompiler.h>
+
+namespace Python {
+namespace Internal {
+
+class PySideUicExtraCompiler : public ProjectExplorer::ProcessExtraCompiler
+{
+public:
+ PySideUicExtraCompiler(const Utils::FilePath &pySideUic,
+ const ProjectExplorer::Project *project,
+ const Utils::FilePath &source,
+ const Utils::FilePaths &targets,
+ QObject *parent = nullptr);
+
+ Utils::FilePath pySideUicPath() const;
+
+private:
+ Utils::FilePath command() const override;
+ ProjectExplorer::FileNameToContentsHash handleProcessFinished(
+ Utils::QtcProcess *process) override;
+
+ Utils::FilePath m_pySideUic;
+};
+
+} // namespace Internal
+} // namespace Python
diff --git a/src/plugins/python/python.qbs b/src/plugins/python/python.qbs
index 14ec87b08fe..0f6de6c58e2 100644
--- a/src/plugins/python/python.qbs
+++ b/src/plugins/python/python.qbs
@@ -17,6 +17,14 @@ QtcPlugin {
Group {
name: "General"
files: [
+ "pipsupport.cpp",
+ "pipsupport.h",
+ "pyside.cpp",
+ "pyside.h",
+ "pysidebuildconfiguration.cpp",
+ "pysidebuildconfiguration.h",
+ "pysideuicextracompiler.cpp",
+ "pysideuicextracompiler.h",
"python.qrc",
"pythonconstants.h",
"pythoneditor.cpp",
diff --git a/src/plugins/python/pythonconstants.h b/src/plugins/python/pythonconstants.h
index 8d392acd204..28d062d029f 100644
--- a/src/plugins/python/pythonconstants.h
+++ b/src/plugins/python/pythonconstants.h
@@ -31,10 +31,13 @@ namespace Python {
namespace Constants {
const char C_PYTHONEDITOR_ID[] = "PythonEditor.PythonEditor";
+const char C_PYTHONRUNCONFIGURATION_ID[] = "PythonEditor.RunConfiguration.";
+
const char C_EDITOR_DISPLAY_NAME[] =
QT_TRANSLATE_NOOP("OpenWith::Editors", "Python Editor");
const char C_PYTHONOPTIONS_PAGE_ID[] = "PythonEditor.OptionsPage";
+const char C_PYLSCONFIGURATION_PAGE_ID[] = "PythonEditor.PythonLanguageServerConfiguration";
const char C_PYTHON_SETTINGS_CATEGORY[] = "P.Python";
const char PYTHON_OPEN_REPL[] = "Python.OpenRepl";
@@ -47,6 +50,7 @@ const char PYLS_SETTINGS_ID[] = "Python.PyLSSettingsID";
* MIME type
******************************************************************************/
const char C_PY_MIMETYPE[] = "text/x-python";
+const char C_PY3_MIMETYPE[] = "text/x-python3";
const char C_PY_MIME_ICON[] = "text-x-python";
} // namespace Constants
diff --git a/src/plugins/python/pythoneditor.cpp b/src/plugins/python/pythoneditor.cpp
index c3e9ec0c51c..2a6c0d094cb 100644
--- a/src/plugins/python/pythoneditor.cpp
+++ b/src/plugins/python/pythoneditor.cpp
@@ -24,9 +24,12 @@
****************************************************************************/
#include "pythoneditor.h"
+
+#include "pyside.h"
#include "pythonconstants.h"
#include "pythonhighlighter.h"
#include "pythonindenter.h"
+#include "pythonlanguageclient.h"
#include "pythonsettings.h"
#include "pythonutils.h"
@@ -102,6 +105,36 @@ static QWidget *createEditorWidget()
return widget;
}
+class PythonDocument : public TextEditor::TextDocument
+{
+public:
+ PythonDocument() : TextEditor::TextDocument(Constants::C_PYTHONEDITOR_ID)
+ {
+ connect(PythonSettings::instance(),
+ &PythonSettings::pylsEnabledChanged,
+ this,
+ [this](const bool enabled) {
+ if (!enabled)
+ return;
+ const Utils::FilePath &python = detectPython(filePath());
+ if (python.exists())
+ PyLSConfigureAssistant::openDocumentWithPython(python, this);
+ });
+ connect(this, &PythonDocument::openFinishedSuccessfully,
+ this, &PythonDocument::checkForPyls);
+ }
+
+ void checkForPyls()
+ {
+ const Utils::FilePath &python = detectPython(filePath());
+ if (!python.exists())
+ return;
+
+ PyLSConfigureAssistant::openDocumentWithPython(python, this);
+ PySideInstaller::checkPySideInstallation(python, this);
+ }
+};
+
PythonEditorFactory::PythonEditorFactory()
{
registerReplAction(this);
@@ -116,7 +149,7 @@ PythonEditorFactory::PythonEditorFactory()
| TextEditor::TextEditorActionHandler::UnCollapseAll
| TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor);
- setDocumentCreator([] { return new TextEditor::TextDocument(Constants::C_PYTHONEDITOR_ID); });
+ setDocumentCreator([]() { return new PythonDocument; });
setEditorWidgetCreator(createEditorWidget);
setIndenterCreator([](QTextDocument *doc) { return new PythonIndenter(doc); });
setSyntaxHighlighterCreator([] { return new PythonHighlighter; });
diff --git a/src/plugins/python/pythonlanguageclient.cpp b/src/plugins/python/pythonlanguageclient.cpp
index 86906317ea9..e621cd6283b 100644
--- a/src/plugins/python/pythonlanguageclient.cpp
+++ b/src/plugins/python/pythonlanguageclient.cpp
@@ -25,69 +25,67 @@
#include "pythonlanguageclient.h"
+#include "pipsupport.h"
+#include "pysideuicextracompiler.h"
#include "pythonconstants.h"
#include "pythonplugin.h"
+#include "pythonproject.h"
+#include "pythonrunconfiguration.h"
#include "pythonsettings.h"
#include "pythonutils.h"
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
-
+#include <languageclient/languageclientinterface.h>
#include <languageclient/languageclientmanager.h>
-
+#include <languageserverprotocol/textsynchronization.h>
+#include <languageserverprotocol/workspace.h>
+#include <projectexplorer/extracompiler.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/target.h>
#include <texteditor/textdocument.h>
-
+#include <texteditor/texteditor.h>
#include <utils/infobar.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/variablechooser.h>
+#include <QCheckBox>
#include <QComboBox>
#include <QFutureWatcher>
#include <QGridLayout>
+#include <QGroupBox>
+#include <QJsonDocument>
+#include <QPushButton>
#include <QRegularExpression>
#include <QTimer>
using namespace LanguageClient;
+using namespace LanguageServerProtocol;
+using namespace ProjectExplorer;
using namespace Utils;
namespace Python {
namespace Internal {
-static constexpr char startPylsInfoBarId[] = "Python::StartPyls";
static constexpr char installPylsInfoBarId[] = "Python::InstallPyls";
-static constexpr char enablePylsInfoBarId[] = "Python::EnablePyls";
-static constexpr char installPylsTaskId[] = "Python::InstallPylsTask";
-struct PythonLanguageServerState
+class PythonLanguageServerState
{
+public:
enum {
CanNotBeInstalled,
CanBeInstalled,
- AlreadyInstalled,
- AlreadyConfigured,
- ConfiguredButDisabled
+ AlreadyInstalled
} state;
FilePath pylsModulePath;
};
-static QString pythonName(const FilePath &pythonPath)
+static QHash<FilePath, PyLSClient*> &pythonClients()
{
- static QHash<FilePath, QString> nameForPython;
- if (!pythonPath.exists())
- return {};
- QString name = nameForPython.value(pythonPath);
- if (name.isEmpty()) {
- QtcProcess pythonProcess;
- pythonProcess.setTimeoutS(2);
- pythonProcess.setCommand({pythonPath, {"--version"}});
- pythonProcess.runBlocking();
- if (pythonProcess.result() != QtcProcess::FinishedWithSuccess)
- return {};
- name = pythonProcess.allOutput().trimmed();
- nameForPython[pythonPath] = name;
- }
- return name;
+ static QHash<FilePath, PyLSClient*> clients;
+ return clients;
}
FilePath getPylsModulePath(CommandLine pylsCommand)
@@ -129,29 +127,11 @@ FilePath getPylsModulePath(CommandLine pylsCommand)
return {};
}
-QList<const StdIOSettings *> configuredPythonLanguageServer()
-{
- using namespace LanguageClient;
- QList<const StdIOSettings *> result;
- for (const BaseSettings *setting : LanguageClientManager::currentSettings()) {
- if (setting->m_languageFilter.isSupported("foo.py", Constants::C_PY_MIMETYPE))
- result << dynamic_cast<const StdIOSettings *>(setting);
- }
- return result;
-}
-
static PythonLanguageServerState checkPythonLanguageServer(const FilePath &python)
{
using namespace LanguageClient;
const CommandLine pythonLShelpCommand(python, {"-m", "pylsp", "-h"});
const FilePath &modulePath = getPylsModulePath(pythonLShelpCommand);
- for (const StdIOSettings *serverSetting : configuredPythonLanguageServer()) {
- if (modulePath == getPylsModulePath(serverSetting->command())) {
- return {serverSetting->m_enabled ? PythonLanguageServerState::AlreadyConfigured
- : PythonLanguageServerState::ConfiguredButDisabled,
- FilePath()};
- }
- }
QtcProcess pythonProcess;
pythonProcess.setCommand(pythonLShelpCommand);
@@ -167,256 +147,161 @@ static PythonLanguageServerState checkPythonLanguageServer(const FilePath &pytho
return {PythonLanguageServerState::CanNotBeInstalled, FilePath()};
}
-class PyLSSettingsWidget : public QWidget
+
+class PyLSInterface : public StdIOClientInterface
{
- Q_DECLARE_TR_FUNCTIONS(PyLSSettingsWidget)
public:
- PyLSSettingsWidget(const PyLSSettings *settings, QWidget *parent)
- : QWidget(parent)
- , m_name(new QLineEdit(settings->m_name, this))
- , m_interpreter(new QComboBox(this))
- {
- int row = 0;
- auto *mainLayout = new QGridLayout;
- mainLayout->addWidget(new QLabel(tr("Name:")), row, 0);
- mainLayout->addWidget(m_name, row, 1);
- auto chooser = new VariableChooser(this);
- chooser->addSupportedWidget(m_name);
-
- mainLayout->addWidget(new QLabel(tr("Python:")), ++row, 0);
- QString settingsId = settings->interpreterId();
- if (settingsId.isEmpty())
- settingsId = PythonSettings::defaultInterpreter().id;
- updateInterpreters(PythonSettings::interpreters(), settingsId);
- mainLayout->addWidget(m_interpreter, row, 1);
- setLayout(mainLayout);
-
- connect(PythonSettings::instance(),
- &PythonSettings::interpretersChanged,
- this,
- &PyLSSettingsWidget::updateInterpreters);
- }
+ PyLSInterface()
+ : m_extraPythonPath("QtCreator-pyls-XXXXXX")
+ { }
- void updateInterpreters(const QList<Interpreter> &interpreters, const QString &defaultId)
+ TemporaryDirectory m_extraPythonPath;
+protected:
+ void startImpl() override
{
- QString currentId = interpreterId();
- if (currentId.isEmpty())
- currentId = defaultId;
- m_interpreter->clear();
- for (const Interpreter &interpreter : interpreters) {
- if (!interpreter.command.exists())
- continue;
- const QString name = QString(interpreter.name + " (%1)")
- .arg(interpreter.command.toUserOutput());
- m_interpreter->addItem(name, interpreter.id);
- if (!currentId.isEmpty() && currentId == interpreter.id)
- m_interpreter->setCurrentIndex(m_interpreter->count() - 1);
+ if (!m_cmd.executable().needsDevice()) {
+ // todo check where to put this tempdir in remote setups
+ Environment env = Environment::systemEnvironment();
+ env.appendOrSet("PYTHONPATH",
+ m_extraPythonPath.path().toString(),
+ OsSpecificAspects::pathListSeparator(env.osType()));
+ setEnvironment(env);
}
+ StdIOClientInterface::startImpl();
}
-
- QString name() const { return m_name->text(); }
- QString interpreterId() const { return m_interpreter->currentData().toString(); }
-
-private:
- QLineEdit *m_name = nullptr;
- QComboBox *m_interpreter = nullptr;
};
-PyLSSettings::PyLSSettings()
+PyLSClient *clientForPython(const FilePath &python)
{
- m_settingsTypeId = Constants::PYLS_SETTINGS_ID;
- m_name = "Python Language Server";
- m_startBehavior = RequiresFile;
- m_languageFilter.mimeTypes = QStringList(Constants::C_PY_MIMETYPE);
- m_arguments = "-m pylsp";
+ if (auto client = pythonClients()[python])
+ return client;
+ auto interface = new PyLSInterface;
+ interface->setCommandLine(CommandLine(python, {"-m", "pylsp"}));
+ auto client = new PyLSClient(interface);
+ client->setName(PyLSClient::tr("Python Language Server (%1)").arg(python.toUserOutput()));
+ client->setActivateDocumentAutomatically(true);
+ client->updateConfiguration();
+ LanguageFilter filter;
+ filter.mimeTypes = QStringList() << Constants::C_PY_MIMETYPE << Constants::C_PY3_MIMETYPE;
+ client->setSupportedLanguage(filter);
+ client->start();
+ pythonClients()[python] = client;
+ return client;
}
-bool PyLSSettings::isValid() const
+PyLSClient::PyLSClient(PyLSInterface *interface)
+ : Client(interface)
+ , m_extraCompilerOutputDir(interface->m_extraPythonPath.path())
{
- return !m_interpreterId.isEmpty() && StdIOSettings::isValid();
-}
-
-static const char interpreterKey[] = "interpreter";
+ connect(this, &Client::initialized, this, &PyLSClient::updateConfiguration);
+ connect(PythonSettings::instance(), &PythonSettings::pylsConfigurationChanged,
+ this, &PyLSClient::updateConfiguration);
+ connect(PythonSettings::instance(), &PythonSettings::pylsEnabledChanged,
+ this, [this](const bool enabled){
+ if (!enabled)
+ LanguageClientManager::shutdownClient(this);
+ });
-QVariantMap PyLSSettings::toMap() const
-{
- QVariantMap map = StdIOSettings::toMap();
- map.insert(interpreterKey, m_interpreterId);
- return map;
}
-void PyLSSettings::fromMap(const QVariantMap &map)
+PyLSClient::~PyLSClient()
{
- StdIOSettings::fromMap(map);
- setInterpreter(map[interpreterKey].toString());
+ pythonClients().remove(pythonClients().key(this));
}
-bool PyLSSettings::applyFromSettingsWidget(QWidget *widget)
+void PyLSClient::updateConfiguration()
{
- bool changed = false;
- auto pylswidget = static_cast<PyLSSettingsWidget *>(widget);
-
- changed |= m_name != pylswidget->name();
- m_name = pylswidget->name();
-
- changed |= m_interpreterId != pylswidget->interpreterId();
- setInterpreter(pylswidget->interpreterId());
-
- return changed;
+ const auto doc = QJsonDocument::fromJson(PythonSettings::pyLSConfiguration().toUtf8());
+ if (doc.isArray())
+ Client::updateConfiguration(doc.array());
+ else if (doc.isObject())
+ Client::updateConfiguration(doc.object());
}
-QWidget *PyLSSettings::createSettingsWidget(QWidget *parent) const
+void PyLSClient::openDocument(TextEditor::TextDocument *document)
{
- return new PyLSSettingsWidget(this, parent);
+ using namespace LanguageServerProtocol;
+ if (reachable()) {
+ const FilePath documentPath = document->filePath();
+ if (PythonProject *project = pythonProjectForFile(documentPath)) {
+ if (Target *target = project->activeTarget()) {
+ if (auto rc = qobject_cast<PythonRunConfiguration *>(target->activeRunConfiguration()))
+ updateExtraCompilers(project, rc->extraCompilers());
+ }
+ } else if (isSupportedDocument(document)) {
+ const FilePath workspacePath = documentPath.parentDir();
+ if (!m_extraWorkspaceDirs.contains(workspacePath)) {
+ WorkspaceFoldersChangeEvent event;
+ event.setAdded({WorkSpaceFolder(DocumentUri::fromFilePath(workspacePath),
+ workspacePath.fileName())});
+ DidChangeWorkspaceFoldersParams params;
+ params.setEvent(event);
+ DidChangeWorkspaceFoldersNotification change(params);
+ sendMessage(change);
+ m_extraWorkspaceDirs.append(workspacePath);
+ }
+ }
+ }
+ Client::openDocument(document);
}
-BaseSettings *PyLSSettings::copy() const
+void PyLSClient::projectClosed(ProjectExplorer::Project *project)
{
- return new PyLSSettings(*this);
+ for (ProjectExplorer::ExtraCompiler *compiler : m_extraCompilers.value(project))
+ closeExtraCompiler(compiler);
+ Client::projectClosed(project);
}
-void PyLSSettings::setInterpreter(const QString &interpreterId)
+void PyLSClient::updateExtraCompilers(ProjectExplorer::Project *project,
+ const QList<PySideUicExtraCompiler *> &extraCompilers)
{
- m_interpreterId = interpreterId;
- if (m_interpreterId.isEmpty())
- return;
- Interpreter interpreter = Utils::findOrDefault(PythonSettings::interpreters(),
- Utils::equal(&Interpreter::id, interpreterId));
- m_executable = interpreter.command;
+ auto oldCompilers = m_extraCompilers.take(project);
+ for (PySideUicExtraCompiler *extraCompiler : extraCompilers) {
+ QTC_ASSERT(extraCompiler->targets().size() == 1 , continue);
+ int index = oldCompilers.indexOf(extraCompiler);
+ if (index < 0) {
+ m_extraCompilers[project] << extraCompiler;
+ connect(extraCompiler,
+ &ExtraCompiler::contentsChanged,
+ this,
+ [this, extraCompiler](const FilePath &file) {
+ updateExtraCompilerContents(extraCompiler, file);
+ });
+ if (extraCompiler->isDirty())
+ static_cast<ExtraCompiler *>(extraCompiler)->run();
+ } else {
+ m_extraCompilers[project] << oldCompilers.takeAt(index);
+ }
+ }
+ for (ProjectExplorer::ExtraCompiler *compiler : oldCompilers)
+ closeExtraCompiler(compiler);
}
-Client *PyLSSettings::createClient(BaseClientInterface *interface) const
+void PyLSClient::updateExtraCompilerContents(ExtraCompiler *compiler, const FilePath &file)
{
- return new Client(interface);
-}
+ const QString text = QString::fromUtf8(compiler->content(file));
+ const FilePath target = m_extraCompilerOutputDir.pathAppended(file.fileName());
-PyLSConfigureAssistant *PyLSConfigureAssistant::instance()
-{
- static auto *instance = new PyLSConfigureAssistant(PythonPlugin::instance());
- return instance;
+ target.writeFileContents(compiler->content(file));
}
-const StdIOSettings *PyLSConfigureAssistant::languageServerForPython(const FilePath &python)
+void PyLSClient::closeExtraCompiler(ProjectExplorer::ExtraCompiler *compiler)
{
- return findOrDefault(configuredPythonLanguageServer(),
- [pythonModulePath = getPylsModulePath(
- CommandLine(python, {"-m", "pylsp"}))](const StdIOSettings *setting) {
- return getPylsModulePath(setting->command()) == pythonModulePath;
- });
+ const FilePath file = compiler->targets().first();
+ m_extraCompilerOutputDir.pathAppended(file.fileName()).removeFile();
+ compiler->disconnect(this);
}
-static Client *registerLanguageServer(const FilePath &python)
+PyLSClient *PyLSClient::clientForPython(const FilePath &python)
{
- Interpreter interpreter = Utils::findOrDefault(PythonSettings::interpreters(),
- Utils::equal(&Interpreter::command, python));
- StdIOSettings *settings = nullptr;
- if (!interpreter.id.isEmpty()) {
- auto *pylsSettings = new PyLSSettings();
- pylsSettings->setInterpreter(interpreter.id);
- settings = pylsSettings;
- } else {
- // cannot find a matching interpreter in settings for the python path add a generic server
- auto *settings = new StdIOSettings();
- settings->m_executable = python;
- settings->m_arguments = "-m pylsp";
- settings->m_languageFilter.mimeTypes = QStringList(Constants::C_PY_MIMETYPE);
- }
- settings->m_name = PyLSConfigureAssistant::tr("Python Language Server (%1)")
- .arg(pythonName(python));
- LanguageClientManager::registerClientSettings(settings);
- Client *client = LanguageClientManager::clientForSetting(settings).value(0);
- PyLSConfigureAssistant::updateEditorInfoBars(python, client);
- return client;
+ return pythonClients()[python];
}
-class PythonLSInstallHelper : public QObject
+PyLSConfigureAssistant *PyLSConfigureAssistant::instance()
{
- Q_OBJECT
-public:
- PythonLSInstallHelper(const FilePath &python, QPointer<TextEditor::TextDocument> document)
- : m_python(python)
- , m_document(document)
- {
- m_watcher.setFuture(m_future.future());
- }
-
- void run()
- {
- Core::ProgressManager::addTask(m_future.future(), "Install PyLS", installPylsTaskId);
- connect(&m_process, &QtcProcess::finished, this, &PythonLSInstallHelper::installFinished);
- connect(&m_process,
- &QtcProcess::readyReadStandardError,
- this,
- &PythonLSInstallHelper::errorAvailable);
- connect(&m_process,
- &QtcProcess::readyReadStandardOutput,
- this,
- &PythonLSInstallHelper::outputAvailable);
-
- connect(&m_killTimer, &QTimer::timeout, this, &PythonLSInstallHelper::cancel);
- connect(&m_watcher, &QFutureWatcher<void>::canceled, this, &PythonLSInstallHelper::cancel);
-
- QStringList arguments = {"-m", "pip", "install", "python-lsp-server[all]"};
-
- // add --user to global pythons, but skip it for venv pythons
- if (!QDir(m_python.parentDir().toString()).exists("activate"))
- arguments << "--user";
-
- m_process.setCommand({m_python, arguments});
- m_process.start();
-
- Core::MessageManager::writeDisrupting(
- tr("Running \"%1\" to install Python language server.")
- .arg(m_process.commandLine().toUserOutput()));
-
- m_killTimer.setSingleShot(true);
- m_killTimer.start(5 /*minutes*/ * 60 * 1000);
- }
-
-private:
- void cancel()
- {
- m_process.stopProcess();
- Core::MessageManager::writeFlashing(
- tr("The Python language server installation was canceled by %1.")
- .arg(m_killTimer.isActive() ? tr("user") : tr("time out")));
- }
-
- void installFinished()
- {
- m_future.reportFinished();
- if (m_process.result() == QtcProcess::FinishedWithSuccess) {
- if (Client *client = registerLanguageServer(m_python))
- LanguageClientManager::openDocumentWithClient(m_document, client);
- } else {
- Core::MessageManager::writeFlashing(
- tr("Installing the Python language server failed with exit code %1")
- .arg(m_process.exitCode()));
- }
- deleteLater();
- }
-
- void outputAvailable()
- {
- const QString &stdOut = QString::fromLocal8Bit(m_process.readAllStandardOutput().trimmed());
- if (!stdOut.isEmpty())
- Core::MessageManager::writeSilently(stdOut);
- }
-
- void errorAvailable()
- {
- const QString &stdErr = QString::fromLocal8Bit(m_process.readAllStandardError().trimmed());
- if (!stdErr.isEmpty())
- Core::MessageManager::writeSilently(stdErr);
- }
-
- QFutureInterface<void> m_future;
- QFutureWatcher<void> m_watcher;
- QtcProcess m_process;
- QTimer m_killTimer;
- const FilePath m_python;
- QPointer<TextEditor::TextDocument> m_document;
-};
+ static auto *instance = new PyLSConfigureAssistant(PythonPlugin::instance());
+ return instance;
+}
void PyLSConfigureAssistant::installPythonLanguageServer(const FilePath &python,
QPointer<TextEditor::TextDocument> document)
@@ -428,55 +313,38 @@ void PyLSConfigureAssistant::installPythonLanguageServer(const FilePath &python,
for (TextEditor::TextDocument *additionalDocument : m_infoBarEntries[python])
additionalDocument->infoBar()->removeInfo(installPylsInfoBarId);
- auto install = new PythonLSInstallHelper(python, document);
- install->run();
-}
+ auto install = new PipInstallTask(python);
-static void setupPythonLanguageServer(const FilePath &python,
- QPointer<TextEditor::TextDocument> document)
-{
- document->infoBar()->removeInfo(startPylsInfoBarId);
- if (Client *client = registerLanguageServer(python))
- LanguageClientManager::openDocumentWithClient(document, client);
-}
-
-static void enablePythonLanguageServer(const FilePath &python,
- QPointer<TextEditor::TextDocument> document)
-{
- document->infoBar()->removeInfo(enablePylsInfoBarId);
- if (const StdIOSettings *setting = PyLSConfigureAssistant::languageServerForPython(python)) {
- LanguageClientManager::enableClientSettings(setting->m_id);
- if (const StdIOSettings *setting = PyLSConfigureAssistant::languageServerForPython(python)) {
- if (Client *client = LanguageClientManager::clientForSetting(setting).value(0)) {
- LanguageClientManager::openDocumentWithClient(document, client);
- PyLSConfigureAssistant::updateEditorInfoBars(python, client);
+ connect(install, &PipInstallTask::finished, this, [=](const bool success) {
+ if (success) {
+ if (document) {
+ if (PyLSClient *client = clientForPython(python))
+ LanguageClientManager::openDocumentWithClient(document, client);
}
}
- }
+ install->deleteLater();
+ });
+
+ install->setPackage(PipPackage{"python-lsp-server[all]", "Python Language Server"});
+ install->run();
}
-void PyLSConfigureAssistant::documentOpened(Core::IDocument *document)
+void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
+ TextEditor::TextDocument *document)
{
- auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
- if (!textDocument || textDocument->mimeType() != Constants::C_PY_MIMETYPE)
+ if (!PythonSettings::pylsEnabled())
return;
- const FilePath &python = detectPython(textDocument->filePath());
- if (!python.exists())
+ if (auto client = pythonClients().value(python)) {
+ LanguageClientManager::openDocumentWithClient(document, client);
return;
+ }
- instance()->openDocumentWithPython(python, textDocument);
-}
-
-void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
- TextEditor::TextDocument *document)
-{
using CheckPylsWatcher = QFutureWatcher<PythonLanguageServerState>;
-
QPointer<CheckPylsWatcher> watcher = new CheckPylsWatcher();
// cancel and delete watcher after a 10 second timeout
- QTimer::singleShot(10000, this, [watcher]() {
+ QTimer::singleShot(10000, instance(), [watcher]() {
if (watcher) {
watcher->cancel();
watcher->deleteLater();
@@ -485,11 +353,11 @@ void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
connect(watcher,
&CheckPylsWatcher::resultReadyAt,
- this,
+ instance(),
[=, document = QPointer<TextEditor::TextDocument>(document)]() {
if (!document || !watcher)
return;
- handlePyLSState(python, watcher->result(), document);
+ instance()->handlePyLSState(python, watcher->result(), document);
watcher->deleteLater();
});
watcher->setFuture(Utils::runAsync(&checkPythonLanguageServer, python));
@@ -501,19 +369,12 @@ void PyLSConfigureAssistant::handlePyLSState(const FilePath &python,
{
if (state.state == PythonLanguageServerState::CanNotBeInstalled)
return;
- if (state.state == PythonLanguageServerState::AlreadyConfigured) {
- if (const StdIOSettings *setting = languageServerForPython(python)) {
- if (Client *client = LanguageClientManager::clientForSetting(setting).value(0))
- LanguageClientManager::openDocumentWithClient(document, client);
- }
- return;
- }
resetEditorInfoBar(document);
Utils::InfoBar *infoBar = document->infoBar();
if (state.state == PythonLanguageServerState::CanBeInstalled
&& infoBar->canInfoBeAdded(installPylsInfoBarId)) {
- auto message = tr("Install and set up Python language server (PyLS) for %1 (%2). "
+ auto message = tr("Install Python language server (PyLS) for %1 (%2). "
"The language server provides Python specific completion and annotation.")
.arg(pythonName(python), python.toUserOutput());
Utils::InfoBarEntry info(installPylsInfoBarId,
@@ -523,27 +384,9 @@ void PyLSConfigureAssistant::handlePyLSState(const FilePath &python,
[=]() { installPythonLanguageServer(python, document); });
infoBar->addInfo(info);
m_infoBarEntries[python] << document;
- } else if (state.state == PythonLanguageServerState::AlreadyInstalled
- && infoBar->canInfoBeAdded(startPylsInfoBarId)) {
- auto message = tr("Found a Python language server for %1 (%2). "
- "Set it up for this document?")
- .arg(pythonName(python), python.toUserOutput());
- Utils::InfoBarEntry info(startPylsInfoBarId,
- message,
- Utils::InfoBarEntry::GlobalSuppression::Enabled);
- info.addCustomButton(tr("Set Up"), [=]() { setupPythonLanguageServer(python, document); });
- infoBar->addInfo(info);
- m_infoBarEntries[python] << document;
- } else if (state.state == PythonLanguageServerState::ConfiguredButDisabled
- && infoBar->canInfoBeAdded(enablePylsInfoBarId)) {
- auto message = tr("Enable Python language server for %1 (%2)?")
- .arg(pythonName(python), python.toUserOutput());
- Utils::InfoBarEntry info(enablePylsInfoBarId,
- message,
- Utils::InfoBarEntry::GlobalSuppression::Enabled);
- info.addCustomButton(tr("Enable"), [=]() { enablePythonLanguageServer(python, document); });
- infoBar->addInfo(info);
- m_infoBarEntries[python] << document;
+ } else if (state.state == PythonLanguageServerState::AlreadyInstalled) {
+ if (auto client = clientForPython(python))
+ LanguageClientManager::openDocumentWithClient(document, client);
}
}
@@ -560,10 +403,7 @@ void PyLSConfigureAssistant::resetEditorInfoBar(TextEditor::TextDocument *docume
{
for (QList<TextEditor::TextDocument *> &documents : m_infoBarEntries)
documents.removeAll(document);
- Utils::InfoBar *infoBar = document->infoBar();
- infoBar->removeInfo(installPylsInfoBarId);
- infoBar->removeInfo(startPylsInfoBarId);
- infoBar->removeInfo(enablePylsInfoBarId);
+ document->infoBar()->removeInfo(installPylsInfoBarId);
}
PyLSConfigureAssistant::PyLSConfigureAssistant(QObject *parent)
@@ -582,5 +422,3 @@ PyLSConfigureAssistant::PyLSConfigureAssistant(QObject *parent)
} // namespace Internal
} // namespace Python
-
-#include "pythonlanguageclient.moc"
diff --git a/src/plugins/python/pythonlanguageclient.h b/src/plugins/python/pythonlanguageclient.h
index 67e0e5f104d..c58103c5fbf 100644
--- a/src/plugins/python/pythonlanguageclient.h
+++ b/src/plugins/python/pythonlanguageclient.h
@@ -26,40 +26,48 @@
#pragma once
#include <utils/fileutils.h>
+#include <utils/temporarydirectory.h>
#include <languageclient/client.h>
#include <languageclient/languageclientsettings.h>
namespace Core { class IDocument; }
-namespace LanguageClient { class Client; }
+namespace ProjectExplorer { class ExtraCompiler; }
namespace TextEditor { class TextDocument; }
namespace Python {
namespace Internal {
-class Interpreter;
-struct PythonLanguageServerState;
+class PySideUicExtraCompiler;
+class PythonLanguageServerState;
+class PyLSInterface;
-class PyLSSettings : public LanguageClient::StdIOSettings
+class PyLSClient : public LanguageClient::Client
{
+ Q_OBJECT
public:
- PyLSSettings();
+ explicit PyLSClient(PyLSInterface *interface);
+ ~PyLSClient();
+
+ void openDocument(TextEditor::TextDocument *document) override;
+ void projectClosed(ProjectExplorer::Project *project) override;
- QString interpreterId() const { return m_interpreterId; }
- void setInterpreter(const QString &interpreterId);
+ void updateExtraCompilers(ProjectExplorer::Project *project,
+ const QList<PySideUicExtraCompiler *> &extraCompilers);
- bool isValid() const final;
- QVariantMap toMap() const final;
- void fromMap(const QVariantMap &map) final;
- bool applyFromSettingsWidget(QWidget *widget) final;
- QWidget *createSettingsWidget(QWidget *parent) const final;
- LanguageClient::BaseSettings *copy() const final;
- LanguageClient::Client *createClient(LanguageClient::BaseClientInterface *interface) const final;
+ static PyLSClient *clientForPython(const Utils::FilePath &python);
+ void updateConfiguration();
private:
- QString m_interpreterId;
+ void updateExtraCompilerContents(ProjectExplorer::ExtraCompiler *compiler,
+ const Utils::FilePath &file);
+ void closeExtraDoc(const Utils::FilePath &file);
+ void closeExtraCompiler(ProjectExplorer::ExtraCompiler *compiler);
- PyLSSettings(const PyLSSettings &other) = default;
+ Utils::FilePaths m_extraWorkspaceDirs;
+ Utils::FilePath m_extraCompilerOutputDir;
+
+ QHash<ProjectExplorer::Project *, QList<ProjectExplorer::ExtraCompiler *>> m_extraCompilers;
};
class PyLSConfigureAssistant : public QObject
@@ -68,12 +76,10 @@ class PyLSConfigureAssistant : public QObject
public:
static PyLSConfigureAssistant *instance();
- static const LanguageClient::StdIOSettings *languageServerForPython(
- const Utils::FilePath &python);
- static void documentOpened(Core::IDocument *document);
- static void updateEditorInfoBars(const Utils::FilePath &python, LanguageClient::Client *client);
-
- void openDocumentWithPython(const Utils::FilePath &python, TextEditor::TextDocument *document);
+ static void updateEditorInfoBars(const Utils::FilePath &python,
+ LanguageClient::Client *client);
+ static void openDocumentWithPython(const Utils::FilePath &python,
+ TextEditor::TextDocument *document);
private:
explicit PyLSConfigureAssistant(QObject *parent);
diff --git a/src/plugins/python/pythonplugin.cpp b/src/plugins/python/pythonplugin.cpp
index 15b656b2e43..cfdd61fdf8a 100644
--- a/src/plugins/python/pythonplugin.cpp
+++ b/src/plugins/python/pythonplugin.cpp
@@ -25,9 +25,8 @@
#include "pythonplugin.h"
-#include "pythonconstants.h"
+#include "pysidebuildconfiguration.h"
#include "pythoneditor.h"
-#include "pythonlanguageclient.h"
#include "pythonproject.h"
#include "pythonsettings.h"
#include "pythonrunconfiguration.h"
@@ -36,6 +35,7 @@
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/localenvironmentaspect.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/taskhub.h>
@@ -61,6 +61,8 @@ public:
PythonEditorFactory editorFactory;
PythonOutputFormatterFactory outputFormatterFactory;
PythonRunConfigurationFactory runConfigFactory;
+ PySideBuildStepFactory buildStepFactory;
+ PySideBuildConfigurationFactory buildConfigFactory;
RunWorkerFactory runWorkerFactory{
RunWorkerFactory::make<SimpleTargetRunner>(),
@@ -72,10 +74,6 @@ public:
PythonPlugin::PythonPlugin()
{
m_instance = this;
-
- LanguageClient::LanguageClientSettings::registerClientType({Constants::PYLS_SETTINGS_ID,
- tr("Python Language Server"),
- []() { return new PyLSSettings; }});
}
PythonPlugin::~PythonPlugin()
@@ -111,9 +109,6 @@ void PythonPlugin::extensionsInitialized()
Core::FileIconProvider::registerIconOverlayForSuffix(imageFile, "py");
TaskHub::addCategory(PythonErrorTaskCategory, "Python", true);
-
- connect(Core::EditorManager::instance(), &Core::EditorManager::documentOpened,
- this, &PyLSConfigureAssistant::documentOpened);
}
} // namespace Internal
diff --git a/src/plugins/python/pythonproject.cpp b/src/plugins/python/pythonproject.cpp
index c373b08ac11..7d0fc27f0f5 100644
--- a/src/plugins/python/pythonproject.cpp
+++ b/src/plugins/python/pythonproject.cpp
@@ -48,7 +48,9 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <utils/algorithm.h>
#include <utils/fileutils.h>
+#include <utils/mimeutils.h>
using namespace Core;
using namespace ProjectExplorer;
@@ -220,7 +222,6 @@ PythonProject::PythonProject(const FilePath &fileName)
setProjectLanguages(Context(ProjectExplorer::Constants::PYTHON_LANGUAGE_ID));
setDisplayName(fileName.completeBaseName());
- setNeedsBuildConfigurations(false);
setBuildSystemCreator([](Target *t) { return new PythonBuildSystem(t); });
}
@@ -242,7 +243,6 @@ static FileType getFileType(const FilePath &f)
void PythonBuildSystem::triggerParsing()
{
ParseGuard guard = guardParsingRun();
-
parse();
const QDir baseDir(projectDirectory().toString());
@@ -255,11 +255,14 @@ void PythonBuildSystem::triggerParsing()
const FileType fileType = getFileType(filePath);
newRoot->addNestedNode(std::make_unique<PythonFileNode>(filePath, displayName, fileType));
- if (fileType == FileType::Source) {
+ const MimeType mt = mimeTypeForFile(filePath, MimeMatchMode::MatchExtension);
+ if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE)) {
BuildTargetInfo bti;
+ bti.displayName = displayName;
bti.buildKey = f;
bti.targetFilePath = filePath;
bti.projectFilePath = projectFilePath();
+ bti.isQtcRunnable = filePath.fileName() == "main.py";
appTargets.append(bti);
}
}
diff --git a/src/plugins/python/pythonrunconfiguration.cpp b/src/plugins/python/pythonrunconfiguration.cpp
index 4c49a46eb2b..5f63c19091f 100644
--- a/src/plugins/python/pythonrunconfiguration.cpp
+++ b/src/plugins/python/pythonrunconfiguration.cpp
@@ -25,6 +25,9 @@
#include "pythonrunconfiguration.h"
+#include "pyside.h"
+#include "pysidebuildconfiguration.h"
+#include "pysideuicextracompiler.h"
#include "pythonconstants.h"
#include "pythonlanguageclient.h"
#include "pythonproject.h"
@@ -35,6 +38,7 @@
#include <languageclient/languageclientmanager.h>
+#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/localenvironmentaspect.h>
#include <projectexplorer/runconfigurationaspects.h>
@@ -134,125 +138,27 @@ private:
////////////////////////////////////////////////////////////////
-class InterpreterAspect : public BaseAspect
-{
- Q_OBJECT
-
-public:
- InterpreterAspect() = default;
-
- Interpreter currentInterpreter() const;
- void updateInterpreters(const QList<Interpreter> &interpreters);
- void setDefaultInterpreter(const Interpreter &interpreter) { m_defaultId = interpreter.id; }
-
- void fromMap(const QVariantMap &) override;
- void toMap(QVariantMap &) const override;
- void addToLayout(LayoutBuilder &builder) override;
-
-private:
- void updateCurrentInterpreter();
- void updateComboBox();
- QList<Interpreter> m_interpreters;
- QPointer<QComboBox> m_comboBox;
- QString m_defaultId;
- QString m_currentId;
-};
-
-Interpreter InterpreterAspect::currentInterpreter() const
-{
- return Utils::findOrDefault(m_interpreters, Utils::equal(&Interpreter::id, m_currentId));
-}
-
-void InterpreterAspect::updateInterpreters(const QList<Interpreter> &interpreters)
-{
- m_interpreters = interpreters;
- if (m_comboBox)
- updateComboBox();
-}
-
-void InterpreterAspect::fromMap(const QVariantMap &map)
-{
- m_currentId = map.value(settingsKey(), m_defaultId).toString();
-}
-
-void InterpreterAspect::toMap(QVariantMap &map) const
-{
- saveToMap(map, m_currentId, QString(), settingsKey());
-}
-
-void InterpreterAspect::addToLayout(LayoutBuilder &builder)
-{
- if (QTC_GUARD(m_comboBox.isNull()))
- m_comboBox = new QComboBox;
-
- updateComboBox();
- connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
- this, &InterpreterAspect::updateCurrentInterpreter);
-
- auto manageButton = new QPushButton(tr("Manage..."));
- connect(manageButton, &QPushButton::clicked, []() {
- Core::ICore::showOptionsDialog(Constants::C_PYTHONOPTIONS_PAGE_ID);
- });
-
- builder.addItems({tr("Interpreter"), m_comboBox.data(), manageButton});
-}
-
-void InterpreterAspect::updateCurrentInterpreter()
-{
- const int index = m_comboBox->currentIndex();
- if (index < 0)
- return;
- QTC_ASSERT(index < m_interpreters.size(), return);
- m_currentId = m_interpreters[index].id;
- m_comboBox->setToolTip(m_interpreters[index].command.toUserOutput());
- emit changed();
-}
-
-void InterpreterAspect::updateComboBox()
-{
- int currentIndex = -1;
- int defaultIndex = -1;
- const QString currentId = m_currentId;
- m_comboBox->clear();
- for (const Interpreter &interpreter : qAsConst(m_interpreters)) {
- int index = m_comboBox->count();
- m_comboBox->addItem(interpreter.name);
- m_comboBox->setItemData(index, interpreter.command.toUserOutput(), Qt::ToolTipRole);
- if (interpreter.id == currentId)
- currentIndex = index;
- if (interpreter.id == m_defaultId)
- defaultIndex = index;
- }
- if (currentIndex >= 0)
- m_comboBox->setCurrentIndex(currentIndex);
- else if (defaultIndex >= 0)
- m_comboBox->setCurrentIndex(defaultIndex);
- updateCurrentInterpreter();
-}
-
-class MainScriptAspect : public StringAspect
-{
- Q_OBJECT
-
-public:
- MainScriptAspect() = default;
-};
-
-PythonRunConfiguration::PythonRunConfiguration(Target *target, Utils::Id id)
+PythonRunConfiguration::PythonRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
auto interpreterAspect = addAspect<InterpreterAspect>();
interpreterAspect->setSettingsKey("PythonEditor.RunConfiguation.Interpreter");
+ interpreterAspect->setSettingsDialogId(Constants::C_PYTHONOPTIONS_PAGE_ID);
+
connect(interpreterAspect, &InterpreterAspect::changed,
- this, &PythonRunConfiguration::updateLanguageServer);
+ this, &PythonRunConfiguration::currentInterpreterChanged);
connect(PythonSettings::instance(), &PythonSettings::interpretersChanged,
interpreterAspect, &InterpreterAspect::updateInterpreters);
- QList<Interpreter> interpreters = PythonSettings::detectPythonVenvs(project()->projectDirectory());
- aspect<InterpreterAspect>()->updateInterpreters(PythonSettings::interpreters());
- aspect<InterpreterAspect>()->setDefaultInterpreter(
- interpreters.isEmpty() ? PythonSettings::defaultInterpreter() : interpreters.first());
+ QList<Interpreter> interpreters = PythonSettings::detectPythonVenvs(
+ project()->projectDirectory());
+ interpreterAspect->updateInterpreters(PythonSettings::interpreters());
+ Interpreter defaultInterpreter = interpreters.isEmpty() ? PythonSettings::defaultInterpreter()
+ : interpreters.first();
+ if (!defaultInterpreter.command.isExecutableFile())
+ defaultInterpreter = PythonSettings::interpreters().value(0);
+ interpreterAspect->setDefaultInterpreter(defaultInterpreter);
auto bufferedAspect = addAspect<BoolAspect>();
bufferedAspect->setSettingsKey("PythonEditor.RunConfiguation.Buffered");
@@ -267,17 +173,17 @@ PythonRunConfiguration::PythonRunConfiguration(Target *target, Utils::Id id)
addAspect<LocalEnvironmentAspect>(target);
- auto argumentsAspect = addAspect<ArgumentsAspect>();
+ auto argumentsAspect = addAspect<ArgumentsAspect>(macroExpander());
- addAspect<WorkingDirectoryAspect>();
+ addAspect<WorkingDirectoryAspect>(macroExpander(), nullptr);
addAspect<TerminalAspect>();
- setCommandLineGetter([this, bufferedAspect, interpreterAspect, argumentsAspect] {
+ setCommandLineGetter([bufferedAspect, interpreterAspect, argumentsAspect, scriptAspect] {
CommandLine cmd{interpreterAspect->currentInterpreter().command};
if (!bufferedAspect->value())
cmd.addArg("-u");
- cmd.addArg(mainScript());
- cmd.addArgs(argumentsAspect->arguments(macroExpander()), CommandLine::Raw);
+ cmd.addArg(scriptAspect->filePath().fileName());
+ cmd.addArgs(argumentsAspect->arguments(), CommandLine::Raw);
return cmd;
});
@@ -290,45 +196,133 @@ PythonRunConfiguration::PythonRunConfiguration(Target *target, Utils::Id id)
});
connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
+ connect(target, &Target::buildSystemUpdated, this, &PythonRunConfiguration::updateExtraCompilers);
+ currentInterpreterChanged();
+
+ setRunnableModifier([](Runnable &r) {
+ r.workingDirectory = r.workingDirectory.onDevice(r.command.executable());
+ });
+
+ connect(PySideInstaller::instance(), &PySideInstaller::pySideInstalled, this,
+ [this](const FilePath &python) {
+ if (python == aspect<InterpreterAspect>()->currentInterpreter().command)
+ checkForPySide(python);
+ });
}
-void PythonRunConfiguration::updateLanguageServer()
+PythonRunConfiguration::~PythonRunConfiguration()
{
- using namespace LanguageClient;
+ qDeleteAll(m_extraCompilers);
+}
- const FilePath python(FilePath::fromUserInput(interpreter()));
+void PythonRunConfiguration::checkForPySide(const FilePath &python)
+{
+ BuildStepList *buildSteps = target()->activeBuildConfiguration()->buildSteps();
+
+ Utils::FilePath pySideProjectPath;
+ m_pySideUicPath.clear();
+ const PipPackage pySide6Package("PySide6");
+ const PipPackageInfo info = pySide6Package.info(python);
+
+ for (const FilePath &file : qAsConst(info.files)) {
+ if (file.fileName() == HostOsInfo::withExecutableSuffix("pyside6-project")) {
+ pySideProjectPath = info.location.resolvePath(file);
+ pySideProjectPath = pySideProjectPath.cleanPath();
+ if (!m_pySideUicPath.isEmpty())
+ break;
+ } else if (file.fileName() == HostOsInfo::withExecutableSuffix("pyside6-uic")) {
+ m_pySideUicPath = info.location.resolvePath(file);
+ m_pySideUicPath = m_pySideUicPath.cleanPath();
+ if (!pySideProjectPath.isEmpty())
+ break;
+ }
+ }
- for (FilePath &file : project()->files(Project::AllFiles)) {
- if (auto document = TextEditor::TextDocument::textDocumentForFilePath(file)) {
- if (document->mimeType() == Constants::C_PY_MIMETYPE)
- PyLSConfigureAssistant::instance()->openDocumentWithPython(python, document);
+ // Workaround that pip might return an incomplete file list on windows
+ if (HostOsInfo::isWindowsHost() && !python.needsDevice()
+ && !info.location.isEmpty() && m_pySideUicPath.isEmpty()) {
+ // Scripts is next to the site-packages install dir for user installations
+ FilePath scripts = info.location.parentDir().pathAppended("Scripts");
+ if (!scripts.exists()) {
+ // in global/venv installations Scripts is next to Lib/site-packages
+ scripts = info.location.parentDir().parentDir().pathAppended("Scripts");
}
+ auto userInstalledPySideTool = [&](const QString &toolName) {
+ const FilePath tool = scripts.pathAppended(HostOsInfo::withExecutableSuffix(toolName));
+ return tool.isExecutableFile() ? tool : FilePath();
+ };
+ m_pySideUicPath = userInstalledPySideTool("pyside6-uic");
+ if (pySideProjectPath.isEmpty())
+ pySideProjectPath = userInstalledPySideTool("pyside6-project");
}
-}
-bool PythonRunConfiguration::supportsDebugger() const
-{
- return true;
+ updateExtraCompilers();
+
+ if (auto pySideBuildStep = buildSteps->firstOfType<PySideBuildStep>())
+ pySideBuildStep->updatePySideProjectPath(pySideProjectPath);
}
-QString PythonRunConfiguration::mainScript() const
+void PythonRunConfiguration::currentInterpreterChanged()
{
- return aspect<MainScriptAspect>()->value();
+ const FilePath python = aspect<InterpreterAspect>()->currentInterpreter().command;
+ checkForPySide(python);
+
+ for (FilePath &file : project()->files(Project::AllFiles)) {
+ if (auto document = TextEditor::TextDocument::textDocumentForFilePath(file)) {
+ if (document->mimeType() == Constants::C_PY_MIMETYPE
+ || document->mimeType() == Constants::C_PY3_MIMETYPE) {
+ PyLSConfigureAssistant::openDocumentWithPython(python, document);
+ PySideInstaller::checkPySideInstallation(python, document);
+ }
+ }
+ }
}
-QString PythonRunConfiguration::arguments() const
+QList<PySideUicExtraCompiler *> PythonRunConfiguration::extraCompilers() const
{
- return aspect<ArgumentsAspect>()->arguments(macroExpander());
+ return m_extraCompilers;
}
-QString PythonRunConfiguration::interpreter() const
+void PythonRunConfiguration::updateExtraCompilers()
{
- return aspect<InterpreterAspect>()->currentInterpreter().command.toString();
+ QList<PySideUicExtraCompiler *> oldCompilers = m_extraCompilers;
+ m_extraCompilers.clear();
+
+ if (m_pySideUicPath.isExecutableFile()) {
+ auto uiMatcher = [](const ProjectExplorer::Node *node) {
+ if (const ProjectExplorer::FileNode *fileNode = node->asFileNode())
+ return fileNode->fileType() == ProjectExplorer::FileType::Form;
+ return false;
+ };
+ const FilePaths uiFiles = project()->files(uiMatcher);
+ for (const FilePath &uiFile : uiFiles) {
+ Utils::FilePath generated = uiFile.parentDir();
+ generated = generated.pathAppended("/ui_" + uiFile.baseName() + ".py");
+ int index = Utils::indexOf(oldCompilers, [&](PySideUicExtraCompiler *oldCompiler) {
+ return oldCompiler->pySideUicPath() == m_pySideUicPath
+ && oldCompiler->project() == project() && oldCompiler->source() == uiFile
+ && oldCompiler->targets() == Utils::FilePaths{generated};
+ });
+ if (index < 0) {
+ m_extraCompilers << new PySideUicExtraCompiler(m_pySideUicPath,
+ project(),
+ uiFile,
+ {generated},
+ this);
+ } else {
+ m_extraCompilers << oldCompilers.takeAt(index);
+ }
+ }
+ }
+ const FilePath python = aspect<InterpreterAspect>()->currentInterpreter().command;
+ if (auto client = PyLSClient::clientForPython(python))
+ client->updateExtraCompilers(project(), m_extraCompilers);
+ qDeleteAll(oldCompilers);
}
PythonRunConfigurationFactory::PythonRunConfigurationFactory()
{
- registerRunConfiguration<PythonRunConfiguration>("PythonEditor.RunConfiguration.");
+ registerRunConfiguration<PythonRunConfiguration>(Constants::C_PYTHONRUNCONFIGURATION_ID);
addSupportedProjectType(PythonProjectId);
}
@@ -343,5 +337,3 @@ PythonOutputFormatterFactory::PythonOutputFormatterFactory()
} // namespace Internal
} // namespace Python
-
-#include "pythonrunconfiguration.moc"
diff --git a/src/plugins/python/pythonrunconfiguration.h b/src/plugins/python/pythonrunconfiguration.h
index ffdf4a4d27c..89bddac83e2 100644
--- a/src/plugins/python/pythonrunconfiguration.h
+++ b/src/plugins/python/pythonrunconfiguration.h
@@ -31,25 +31,23 @@
namespace Python {
namespace Internal {
+class PySideUicExtraCompiler;
+
class PythonRunConfiguration : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
-
- Q_PROPERTY(bool supportsDebugger READ supportsDebugger)
- Q_PROPERTY(QString interpreter READ interpreter)
- Q_PROPERTY(QString mainScript READ mainScript)
- Q_PROPERTY(QString arguments READ arguments)
-
public:
PythonRunConfiguration(ProjectExplorer::Target *target, Utils::Id id);
- QString interpreter() const;
+ ~PythonRunConfiguration() override;
+ void currentInterpreterChanged();
+ QList<PySideUicExtraCompiler *> extraCompilers() const;
private:
- void updateLanguageServer();
+ void checkForPySide(const Utils::FilePath &python);
+ void updateExtraCompilers();
+ Utils::FilePath m_pySideUicPath;
- bool supportsDebugger() const;
- QString mainScript() const;
- QString arguments() const;
+ QList<PySideUicExtraCompiler *> m_extraCompilers;
};
class PythonRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp
index 314b3dc3ad5..8f7537c8b77 100644
--- a/src/plugins/python/pythonsettings.cpp
+++ b/src/plugins/python/pythonsettings.cpp
@@ -26,10 +26,16 @@
#include "pythonsettings.h"
#include "pythonconstants.h"
+#include "pythonplugin.h"
#include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/icore.h>
-
+#include <extensionsystem/pluginmanager.h>
+#include <languageclient/languageclient_global.h>
+#include <languageclient/languageclientsettings.h>
+#include <languageclient/languageclientmanager.h>
+#include <texteditor/textdocument.h>
+#include <texteditor/texteditor.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/detailswidget.h>
@@ -39,6 +45,7 @@
#include <utils/pathchooser.h>
#include <utils/qtcprocess.h>
#include <utils/treemodel.h>
+#include <utils/utilsicons.h>
#include <QDir>
#include <QLabel>
@@ -48,21 +55,57 @@
#include <QStackedWidget>
#include <QTreeView>
#include <QWidget>
+#include <QVBoxLayout>
+#include <QGroupBox>
+#include <QCheckBox>
+#include <QJsonDocument>
+#include <QJsonObject>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+using namespace Layouting;
namespace Python {
namespace Internal {
-using namespace Utils;
-using namespace Layouting;
+static Interpreter createInterpreter(const FilePath &python,
+ const QString &defaultName,
+ bool windowedSuffix = false)
+{
+ Interpreter result;
+ result.id = QUuid::createUuid().toString();
+ result.command = python;
+
+ QtcProcess pythonProcess;
+ pythonProcess.setProcessChannelMode(QProcess::MergedChannels);
+ pythonProcess.setTimeoutS(1);
+ pythonProcess.setCommand({python, {"--version"}});
+ pythonProcess.runBlocking();
+ if (pythonProcess.result() == ProcessResult::FinishedWithSuccess)
+ result.name = pythonProcess.cleanedStdOut().trimmed();
+ if (result.name.isEmpty())
+ result.name = defaultName;
+ if (windowedSuffix)
+ result.name += " (Windowed)";
+ QDir pythonDir(python.parentDir().toString());
+ if (pythonDir.exists() && pythonDir.exists("activate") && pythonDir.cdUp())
+ result.name += QString(" (%1 Virtual Environment)").arg(pythonDir.dirName());
+
+ return result;
+}
class InterpreterDetailsWidget : public QWidget
{
+ Q_OBJECT
public:
InterpreterDetailsWidget()
: m_name(new QLineEdit)
- , m_executable(new Utils::PathChooser())
+ , m_executable(new PathChooser())
{
- m_executable->setExpectedKind(Utils::PathChooser::ExistingCommand);
+ m_executable->setExpectedKind(PathChooser::ExistingCommand);
+
+ connect(m_name, &QLineEdit::textChanged, this, &InterpreterDetailsWidget::changed);
+ connect(m_executable, &PathChooser::filePathChanged, this, &InterpreterDetailsWidget::changed);
Form {
PythonSettings::tr("Name:"), m_name, Break(),
@@ -72,23 +115,30 @@ public:
void updateInterpreter(const Interpreter &interpreter)
{
+ QSignalBlocker blocker(this); // do not emit changed when we change the controls here
+ m_currentInterpreter = interpreter;
m_name->setText(interpreter.name);
m_executable->setFilePath(interpreter.command);
- m_currentId = interpreter.id;
}
Interpreter toInterpreter()
{
- return {m_currentId, m_name->text(), m_executable->filePath()};
+ m_currentInterpreter.command = m_executable->filePath();
+ m_currentInterpreter.name = m_name->text();
+ return m_currentInterpreter;
}
QLineEdit *m_name = nullptr;
PathChooser *m_executable = nullptr;
- QString m_currentId;
+ Interpreter m_currentInterpreter;
+
+signals:
+ void changed();
};
class InterpreterOptionsWidget : public QWidget
{
+ Q_DECLARE_TR_FUNCTIONS(Python::Internal::InterpreterOptionsWidget)
public:
InterpreterOptionsWidget(const QList<Interpreter> &interpreters,
const QString &defaultInterpreter);
@@ -101,26 +151,46 @@ private:
InterpreterDetailsWidget *m_detailsWidget = nullptr;
QPushButton *m_deleteButton = nullptr;
QPushButton *m_makeDefaultButton = nullptr;
+ QPushButton *m_cleanButton = nullptr;
QString m_defaultId;
void currentChanged(const QModelIndex &index, const QModelIndex &previous);
+ void detailsChanged();
+ void updateCleanButton();
void addItem();
void deleteItem();
void makeDefault();
+ void cleanUp();
};
InterpreterOptionsWidget::InterpreterOptionsWidget(const QList<Interpreter> &interpreters, const QString &defaultInterpreter)
: m_detailsWidget(new InterpreterDetailsWidget())
, m_defaultId(defaultInterpreter)
{
- m_model.setDataAccessor([this](const Interpreter &interpreter, int, int role) -> QVariant {
- if (role == Qt::DisplayRole)
+ m_model.setDataAccessor([this](const Interpreter &interpreter, int column, int role) -> QVariant {
+ switch (role) {
+ case Qt::DisplayRole:
return interpreter.name;
- if (role == Qt::FontRole) {
+ case Qt::FontRole: {
QFont f = font();
f.setBold(interpreter.id == m_defaultId);
return f;
}
+ case Qt::ToolTipRole:
+ if (interpreter.command.isEmpty())
+ return tr("Executable is empty.");
+ if (!interpreter.command.exists())
+ return tr("%1 does not exist.").arg(interpreter.command.toUserOutput());
+ if (!interpreter.command.isExecutableFile())
+ return tr("%1 is not an executable file.").arg(interpreter.command.toUserOutput());
+ break;
+ case Qt::DecorationRole:
+ if (column == 0 && !interpreter.command.isExecutableFile())
+ return Utils::Icons::CRITICAL.icon();
+ break;
+ default:
+ break;
+ }
return {};
});
m_model.setAllData(interpreters);
@@ -145,12 +215,24 @@ InterpreterOptionsWidget::InterpreterOptionsWidget(const QList<Interpreter> &int
m_makeDefaultButton->setEnabled(false);
connect(m_makeDefaultButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::makeDefault);
+ m_cleanButton = new QPushButton(PythonSettings::tr("&Clean Up"));
+ connect(m_cleanButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::cleanUp);
+ m_cleanButton->setToolTip(
+ PythonSettings::tr("Remove all Python interpreters without a valid executable."));
+
+ updateCleanButton();
+
m_detailsWidget->hide();
+ connect(m_detailsWidget,
+ &InterpreterDetailsWidget::changed,
+ this,
+ &InterpreterOptionsWidget::detailsChanged);
Column buttons {
addButton,
m_deleteButton,
m_makeDefaultButton,
+ m_cleanButton,
Stretch()
};
@@ -162,12 +244,6 @@ InterpreterOptionsWidget::InterpreterOptionsWidget(const QList<Interpreter> &int
void InterpreterOptionsWidget::apply()
{
- const QModelIndex &index = m_view.currentIndex();
- if (index.isValid()) {
- m_model.itemAt(index.row())->itemData = m_detailsWidget->toInterpreter();
- emit m_model.dataChanged(index, index);
- }
-
QList<Interpreter> interpreters;
for (const TreeItem *treeItem : m_model)
interpreters << static_cast<const ListItem<Interpreter> *>(treeItem)->itemData;
@@ -190,12 +266,30 @@ void InterpreterOptionsWidget::currentChanged(const QModelIndex &index, const QM
m_makeDefaultButton->setEnabled(index.isValid());
}
+void InterpreterOptionsWidget::detailsChanged()
+{
+ const QModelIndex &index = m_view.currentIndex();
+ if (index.isValid()) {
+ m_model.itemAt(index.row())->itemData = m_detailsWidget->toInterpreter();
+ emit m_model.dataChanged(index, index);
+ }
+ updateCleanButton();
+}
+
+void InterpreterOptionsWidget::updateCleanButton()
+{
+ m_cleanButton->setEnabled(Utils::anyOf(m_model.allData(), [](const Interpreter &interpreter) {
+ return !interpreter.command.isExecutableFile();
+ }));
+}
+
void InterpreterOptionsWidget::addItem()
{
const QModelIndex &index = m_model.indexForItem(
- m_model.appendItem({QUuid::createUuid().toString(), QString("Python"), FilePath()}));
+ m_model.appendItem({QUuid::createUuid().toString(), QString("Python"), FilePath(), false}));
QTC_ASSERT(index.isValid(), return);
m_view.setCurrentIndex(index);
+ updateCleanButton();
}
void InterpreterOptionsWidget::deleteItem()
@@ -203,6 +297,7 @@ void InterpreterOptionsWidget::deleteItem()
const QModelIndex &index = m_view.currentIndex();
if (index.isValid())
m_model.destroyItem(m_model.itemAt(index.row()));
+ updateCleanButton();
}
class InterpreterOptionsPage : public Core::IOptionsPage
@@ -274,35 +369,216 @@ static bool alreadyRegistered(const QList<Interpreter> &pythons, const FilePath
});
}
-Interpreter::Interpreter(const FilePath &python, const QString &defaultName, bool windowedSuffix)
- : id(QUuid::createUuid().toString())
- , command(python)
+static InterpreterOptionsPage &interpreterOptionsPage()
{
- QtcProcess pythonProcess;
- pythonProcess.setProcessChannelMode(QProcess::MergedChannels);
- pythonProcess.setTimeoutS(1);
- pythonProcess.setCommand({python, {"--version"}});
- pythonProcess.runBlocking();
- if (pythonProcess.result() == QtcProcess::FinishedWithSuccess)
- name = pythonProcess.stdOut().trimmed();
- if (name.isEmpty())
- name = defaultName;
- if (windowedSuffix)
- name += " (Windowed)";
- QDir pythonDir(python.parentDir().toString());
- if (pythonDir.exists() && pythonDir.exists("activate") && pythonDir.cdUp())
- name += QString(" (%1 Virtual Environment)").arg(pythonDir.dirName());
+ static InterpreterOptionsPage page;
+ return page;
}
-Interpreter::Interpreter(const QString &_id, const QString &_name, const FilePath &_command)
- : id(_id)
- , name(_name)
- , command(_command)
-{}
+static const QStringList &plugins()
+{
+ static const QStringList plugins{"flake8",
+ "jedi_completion",
+ "jedi_definition",
+ "jedi_hover",
+ "jedi_references",
+ "jedi_signature_help",
+ "jedi_symbols",
+ "mccabe",
+ "pycodestyle",
+ "pydocstyle",
+ "pyflakes",
+ "pylint",
+ "rope_completion",
+ "yapf"};
+ return plugins;
+}
-static InterpreterOptionsPage &interpreterOptionsPage()
+class PyLSConfigureWidget : public QWidget
{
- static InterpreterOptionsPage page;
+public:
+ PyLSConfigureWidget()
+ : m_editor(LanguageClient::jsonEditor())
+ , m_advancedLabel(new QLabel)
+ , m_pluginsGroup(new QGroupBox(PythonSettings::tr("Plugins:")))
+ , m_mainGroup(new QGroupBox(PythonSettings::tr("Use Python Language Server")))
+
+ {
+ m_mainGroup->setCheckable(true);
+
+ auto mainGroupLayout = new QVBoxLayout;
+
+ auto pluginsLayout = new QVBoxLayout;
+ m_pluginsGroup->setLayout(pluginsLayout);
+ m_pluginsGroup->setFlat(true);
+ for (const QString &plugin : plugins()) {
+ auto checkBox = new QCheckBox(plugin, this);
+ connect(checkBox, &QCheckBox::clicked, this, [this, plugin, checkBox]() {
+ updatePluginEnabled(checkBox->checkState(), plugin);
+ });
+ m_checkBoxes[plugin] = checkBox;
+ pluginsLayout->addWidget(checkBox);
+ }
+
+ mainGroupLayout->addWidget(m_pluginsGroup);
+
+ const QString labelText = PythonSettings::tr(
+ "For a complete list of available options, consult the <a "
+ "href=\"https://github.com/python-lsp/python-lsp-server/blob/develop/"
+ "CONFIGURATION.md\">Python LSP Server configuration documentation</a>.");
+
+ m_advancedLabel->setText(labelText);
+ m_advancedLabel->setOpenExternalLinks(true);
+ mainGroupLayout->addWidget(m_advancedLabel);
+ mainGroupLayout->addWidget(m_editor->editorWidget(), 1);
+
+ setAdvanced(false);
+
+ mainGroupLayout->addStretch();
+
+ auto advanced = new QCheckBox(PythonSettings::tr("Advanced"));
+ advanced->setChecked(false);
+
+ connect(advanced,
+ &QCheckBox::toggled,
+ this,
+ &PyLSConfigureWidget::setAdvanced);
+
+ mainGroupLayout->addWidget(advanced);
+
+ m_mainGroup->setLayout(mainGroupLayout);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(m_mainGroup);
+ setLayout(mainLayout);
+ }
+
+ void initialize(bool enabled, const QString &configuration)
+ {
+ m_editor->textDocument()->setPlainText(configuration);
+ m_mainGroup->setChecked(enabled);
+ updateCheckboxes();
+ }
+
+ void apply()
+ {
+ PythonSettings::setPylsEnabled(m_mainGroup->isChecked());
+ PythonSettings::setPyLSConfiguration(m_editor->textDocument()->plainText());
+ }
+private:
+ void setAdvanced(bool advanced)
+ {
+ m_editor->editorWidget()->setVisible(advanced);
+ m_advancedLabel->setVisible(advanced);
+ m_pluginsGroup->setVisible(!advanced);
+ updateCheckboxes();
+ }
+
+ void updateCheckboxes()
+ {
+ const QJsonDocument document = QJsonDocument::fromJson(
+ m_editor->textDocument()->plainText().toUtf8());
+ if (document.isObject()) {
+ const QJsonObject pluginsObject
+ = document.object()["pylsp"].toObject()["plugins"].toObject();
+ for (const QString &plugin : plugins()) {
+ auto checkBox = m_checkBoxes[plugin];
+ if (!checkBox)
+ continue;
+ const QJsonValue enabled = pluginsObject[plugin].toObject()["enabled"];
+ if (!enabled.isBool())
+ checkBox->setCheckState(Qt::PartiallyChecked);
+ else
+ checkBox->setCheckState(enabled.toBool(false) ? Qt::Checked : Qt::Unchecked);
+ }
+ }
+ }
+
+ void updatePluginEnabled(Qt::CheckState check, const QString &plugin)
+ {
+ if (check == Qt::PartiallyChecked)
+ return;
+ QJsonDocument document = QJsonDocument::fromJson(
+ m_editor->textDocument()->plainText().toUtf8());
+ QJsonObject config;
+ if (!document.isNull())
+ config = document.object();
+ QJsonObject pylsp = config["pylsp"].toObject();
+ QJsonObject plugins = pylsp["plugins"].toObject();
+ QJsonObject pluginValue = plugins[plugin].toObject();
+ pluginValue.insert("enabled", check == Qt::Checked);
+ plugins.insert(plugin, pluginValue);
+ pylsp.insert("plugins", plugins);
+ config.insert("pylsp", pylsp);
+ document.setObject(config);
+ m_editor->textDocument()->setPlainText(QString::fromUtf8(document.toJson()));
+ }
+
+ QMap<QString, QCheckBox *> m_checkBoxes;
+ TextEditor::BaseTextEditor *m_editor = nullptr;
+ QLabel *m_advancedLabel = nullptr;
+ QGroupBox *m_pluginsGroup = nullptr;
+ QGroupBox *m_mainGroup = nullptr;
+};
+
+
+class PyLSOptionsPage : public Core::IOptionsPage
+{
+public:
+ PyLSOptionsPage();
+
+ bool enabled() const { return m_enabled; }
+ void setEnabled(bool enabled);
+
+ void setConfiguration(const QString &configuration) { m_configuration = configuration; }
+ QString configuration() const { return m_configuration; }
+
+ QWidget *widget() override;
+ void apply() override;
+ void finish() override;
+
+private:
+ QPointer<PyLSConfigureWidget> m_widget;
+ bool m_enabled = true;
+ QString m_configuration;
+};
+
+PyLSOptionsPage::PyLSOptionsPage()
+{
+ setId(Constants::C_PYLSCONFIGURATION_PAGE_ID);
+ setDisplayName(PythonSettings::tr("Language Server Configuration"));
+ setCategory(Constants::C_PYTHON_SETTINGS_CATEGORY);
+}
+
+QWidget *PyLSOptionsPage::widget()
+{
+ if (!m_widget) {
+ m_widget = new PyLSConfigureWidget();
+ m_widget->initialize(m_enabled, m_configuration);
+ }
+ return m_widget;
+}
+
+void PyLSOptionsPage::apply()
+{
+ if (m_widget)
+ m_widget->apply();
+}
+
+void PyLSOptionsPage::finish()
+{
+ delete m_widget;
+ m_widget = nullptr;
+}
+
+void PyLSOptionsPage::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+}
+
+static PyLSOptionsPage &pylspOptionsPage()
+{
+ static PyLSOptionsPage page;
return page;
}
@@ -320,46 +596,144 @@ void InterpreterOptionsWidget::makeDefault()
}
}
+void InterpreterOptionsWidget::cleanUp()
+{
+ m_model.destroyItems(
+ [](const Interpreter &interpreter) { return !interpreter.command.isExecutableFile(); });
+ updateCleanButton();
+}
+
constexpr char settingsGroupKey[] = "Python";
constexpr char interpreterKey[] = "Interpeter";
constexpr char defaultKey[] = "DefaultInterpeter";
+constexpr char pylsEnabledKey[] = "PylsEnabled";
+constexpr char pylsConfigurationKey[] = "PylsConfiguration";
struct SavedSettings
{
QList<Interpreter> pythons;
QString defaultId;
+ QString pylsConfiguration;
+ bool pylsEnabled = true;
};
+static QString defaultPylsConfiguration()
+{
+ static QJsonObject configuration;
+ if (configuration.isEmpty()) {
+ QJsonObject enabled;
+ enabled.insert("enabled", true);
+ QJsonObject disabled;
+ disabled.insert("enabled", false);
+ QJsonObject plugins;
+ plugins.insert("flake8", disabled);
+ plugins.insert("jedi_completion", enabled);
+ plugins.insert("jedi_definition", enabled);
+ plugins.insert("jedi_hover", enabled);
+ plugins.insert("jedi_references", enabled);
+ plugins.insert("jedi_signature_help", enabled);
+ plugins.insert("jedi_symbols", enabled);
+ plugins.insert("mccabe", disabled);
+ plugins.insert("pycodestyle", disabled);
+ plugins.insert("pydocstyle", disabled);
+ plugins.insert("pyflakes", enabled);
+ plugins.insert("pylint", disabled);
+ plugins.insert("rope_completion", enabled);
+ plugins.insert("yapf", enabled);
+ QJsonObject pylsp;
+ pylsp.insert("plugins", plugins);
+ configuration.insert("pylsp", pylsp);
+ }
+ return QString::fromUtf8(QJsonDocument(configuration).toJson());
+}
+
+static void disableOutdatedPylsNow()
+{
+ using namespace LanguageClient;
+ const QList<BaseSettings *>
+ settings = LanguageClientSettings::pageSettings();
+ for (const BaseSettings *setting : settings) {
+ if (setting->m_settingsTypeId != LanguageClient::Constants::LANGUAGECLIENT_STDIO_SETTINGS_ID)
+ continue;
+ auto stdioSetting = static_cast<const StdIOSettings *>(setting);
+ if (stdioSetting->arguments().startsWith("-m pyls")
+ && stdioSetting->m_languageFilter.isSupported("foo.py", Constants::C_PY_MIMETYPE)) {
+ LanguageClientManager::enableClientSettings(stdioSetting->m_id, false);
+ }
+ }
+}
+
+static void disableOutdatedPyls()
+{
+ using namespace ExtensionSystem;
+ if (PluginManager::isInitializationDone()) {
+ disableOutdatedPylsNow();
+ } else {
+ QObject::connect(PluginManager::instance(), &PluginManager::initializationDone,
+ PythonPlugin::instance(), &disableOutdatedPylsNow);
+ }
+}
+
static SavedSettings fromSettings(QSettings *settings)
{
- QList<Interpreter> pythons;
+ SavedSettings result;
settings->beginGroup(settingsGroupKey);
const QVariantList interpreters = settings->value(interpreterKey).toList();
+ QList<Interpreter> oldSettings;
for (const QVariant &interpreterVar : interpreters) {
auto interpreterList = interpreterVar.toList();
- if (interpreterList.size() != 3)
+ const Interpreter interpreter{interpreterList.value(0).toString(),
+ interpreterList.value(1).toString(),
+ FilePath::fromVariant(interpreterList.value(2)),
+ interpreterList.value(3, true).toBool()};
+ if (interpreterList.size() == 3)
+ oldSettings << interpreter;
+ else if (interpreterList.size() == 4)
+ result.pythons << interpreter;
+ }
+
+ for (const Interpreter &interpreter : qAsConst(oldSettings)) {
+ if (Utils::anyOf(result.pythons, Utils::equal(&Interpreter::id, interpreter.id)))
continue;
- pythons << Interpreter{interpreterList.value(0).toString(),
- interpreterList.value(1).toString(),
- FilePath::fromVariant(interpreterList.value(2))};
+ result.pythons << interpreter;
}
- const QString defaultId = settings->value(defaultKey).toString();
+ result.pythons = Utils::filtered(result.pythons, [](const Interpreter &interpreter){
+ return !interpreter.autoDetected || interpreter.command.isExecutableFile();
+ });
+ result.defaultId = settings->value(defaultKey).toString();
+
+ QVariant pylsEnabled = settings->value(pylsEnabledKey);
+ if (pylsEnabled.isNull())
+ disableOutdatedPyls();
+ else
+ result.pylsEnabled = pylsEnabled.toBool();
+ const QVariant pylsConfiguration = settings->value(pylsConfigurationKey);
+ if (!pylsConfiguration.isNull())
+ result.pylsConfiguration = pylsConfiguration.toString();
+ else
+ result.pylsConfiguration = defaultPylsConfiguration();
settings->endGroup();
-
- return {pythons, defaultId};
+ return result;
}
static void toSettings(QSettings *settings, const SavedSettings &savedSettings)
{
settings->beginGroup(settingsGroupKey);
- const QVariantList interpretersVar
- = Utils::transform(savedSettings.pythons, [](const Interpreter &interpreter) {
- return QVariant({interpreter.id, interpreter.name, interpreter.command.toVariant()});
- });
+ QVariantList interpretersVar;
+ for (const Interpreter &interpreter : savedSettings.pythons) {
+ QVariantList interpreterVar{interpreter.id,
+ interpreter.name,
+ interpreter.command.toVariant()};
+ interpretersVar.append(QVariant(interpreterVar)); // old settings
+ interpreterVar.append(interpreter.autoDetected);
+ interpretersVar.append(QVariant(interpreterVar)); // new settings
+ }
settings->setValue(interpreterKey, interpretersVar);
settings->setValue(defaultKey, savedSettings.defaultId);
+ settings->setValue(pylsConfigurationKey, savedSettings.pylsConfiguration);
+ settings->setValue(pylsEnabledKey, savedSettings.pylsEnabled);
settings->endGroup();
}
@@ -393,10 +767,10 @@ static void addPythonsFromRegistry(QList<Interpreter> &pythons)
const FilePath &path = FilePath::fromUserInput(regVal.toString());
const FilePath python = path.pathAppended("python").withExecutableSuffix();
if (python.exists() && !alreadyRegistered(pythons, python))
- pythons << Interpreter(python, "Python " + versionGroup);
+ pythons << createInterpreter(python, "Python " + versionGroup);
const FilePath pythonw = path.pathAppended("pythonw").withExecutableSuffix();
if (pythonw.exists() && !alreadyRegistered(pythons, pythonw))
- pythons << Interpreter(pythonw, "Python " + versionGroup, true);
+ pythons << createInterpreter(pythonw, "Python " + versionGroup, true);
}
pythonRegistry.endGroup();
}
@@ -412,11 +786,11 @@ static void addPythonsFromPath(QList<Interpreter> &pythons)
if (executable.toFileInfo().size() == 0)
continue;
if (executable.exists() && !alreadyRegistered(pythons, executable))
- pythons << Interpreter(executable, "Python from Path");
+ pythons << createInterpreter(executable, "Python from Path");
}
for (const FilePath &executable : env.findAllInPath("pythonw")) {
if (executable.exists() && !alreadyRegistered(pythons, executable))
- pythons << Interpreter(executable, "Python from Path", true);
+ pythons << createInterpreter(executable, "Python from Path", true);
}
} else {
const QStringList filters = {"python",
@@ -428,7 +802,7 @@ static void addPythonsFromPath(QList<Interpreter> &pythons)
for (const QFileInfo &fi : dir.entryInfoList(filters)) {
const FilePath executable = Utils::FilePath::fromFileInfo(fi);
if (executable.exists() && !alreadyRegistered(pythons, executable))
- pythons << Interpreter(executable, "Python from Path");
+ pythons << createInterpreter(executable, "Python from Path");
}
}
}
@@ -457,6 +831,9 @@ void PythonSettings::init()
settingsInstance = new PythonSettings();
const SavedSettings &settings = fromSettings(Core::ICore::settings());
+ pylspOptionsPage().setConfiguration(settings.pylsConfiguration);
+ pylspOptionsPage().setEnabled(settings.pylsEnabled);
+
QList<Interpreter> pythons = settings.pythons;
if (HostOsInfo::isWindowsHost())
@@ -479,6 +856,34 @@ void PythonSettings::setInterpreter(const QList<Interpreter> &interpreters, cons
saveSettings();
}
+void PythonSettings::setPyLSConfiguration(const QString &configuration)
+{
+ if (configuration == pylspOptionsPage().configuration())
+ return;
+ pylspOptionsPage().setConfiguration(configuration);
+ saveSettings();
+ emit instance()->pylsConfigurationChanged(configuration);
+}
+
+void PythonSettings::setPylsEnabled(const bool &enabled)
+{
+ if (enabled == pylspOptionsPage().enabled())
+ return;
+ pylspOptionsPage().setEnabled(enabled);
+ saveSettings();
+ emit instance()->pylsEnabledChanged(enabled);
+}
+
+bool PythonSettings::pylsEnabled()
+{
+ return pylspOptionsPage().enabled();
+}
+
+QString PythonSettings::pyLSConfiguration()
+{
+ return pylspOptionsPage().configuration();
+}
+
void PythonSettings::addInterpreter(const Interpreter &interpreter, bool isDefault)
{
interpreterOptionsPage().addInterpreter(interpreter);
@@ -514,7 +919,7 @@ QList<Interpreter> PythonSettings::detectPythonVenvs(const FilePath &path)
= Utils::findOrDefault(PythonSettings::interpreters(),
Utils::equal(&Interpreter::command, python));
if (interpreter.command.isEmpty()) {
- interpreter = Interpreter(python, defaultName);
+ interpreter = createInterpreter(python, defaultName);
PythonSettings::addInterpreter(interpreter);
}
result << interpreter;
@@ -525,7 +930,7 @@ QList<Interpreter> PythonSettings::detectPythonVenvs(const FilePath &path)
dir.cdUp();
}
}
- } while (dir.cdUp());
+ } while (dir.cdUp() && !(dir.isRoot() && Utils::HostOsInfo::isAnyUnixHost()));
}
return result;
}
@@ -534,7 +939,9 @@ void PythonSettings::saveSettings()
{
const QList<Interpreter> &interpreters = interpreterOptionsPage().interpreters();
const QString defaultId = interpreterOptionsPage().defaultInterpreter().id;
- toSettings(Core::ICore::settings(), {interpreters, defaultId});
+ const QString pylsConfiguration = pylspOptionsPage().configuration();
+ const bool pylsEnabled = pylspOptionsPage().enabled();
+ toSettings(Core::ICore::settings(), {interpreters, defaultId, pylsConfiguration, pylsEnabled});
if (QTC_GUARD(settingsInstance))
emit settingsInstance->interpretersChanged(interpreters, defaultId);
}
@@ -549,6 +956,12 @@ Interpreter PythonSettings::defaultInterpreter()
return interpreterOptionsPage().defaultInterpreter();
}
+Interpreter PythonSettings::interpreter(const QString &interpreterId)
+{
+ const QList<Interpreter> interpreters = PythonSettings::interpreters();
+ return Utils::findOrDefault(interpreters, Utils::equal(&Interpreter::id, interpreterId));
+}
+
} // namespace Internal
} // namespace Python
diff --git a/src/plugins/python/pythonsettings.h b/src/plugins/python/pythonsettings.h
index 0ef6c62a0ff..94b9cc819a5 100644
--- a/src/plugins/python/pythonsettings.h
+++ b/src/plugins/python/pythonsettings.h
@@ -25,6 +25,8 @@
#pragma once
+#include <projectexplorer/runconfigurationaspects.h>
+
#include <utils/fileutils.h>
#include <utils/optional.h>
@@ -33,43 +35,31 @@
namespace Python {
namespace Internal {
-class Interpreter
-{
-public:
- Interpreter() = default;
- Interpreter(const Utils::FilePath &python,
- const QString &defaultName,
- bool windowedSuffix = false);
- Interpreter(const QString &id,
- const QString &name,
- const Utils::FilePath &command);
-
- inline bool operator==(const Interpreter &other) const
- {
- return id == other.id && name == other.name && command == other.command;
- }
-
- QString id = QUuid::createUuid().toString();
- QString name;
- Utils::FilePath command;
-};
-
class PythonSettings : public QObject
{
Q_OBJECT
public:
static void init();
+ using Interpreter = ProjectExplorer::Interpreter;
+
static QList<Interpreter> interpreters();
static Interpreter defaultInterpreter();
+ static Interpreter interpreter(const QString &interpreterId);
static void setInterpreter(const QList<Interpreter> &interpreters, const QString &defaultId);
static void addInterpreter(const Interpreter &interpreter, bool isDefault = false);
+ static void setPyLSConfiguration(const QString &configuration);
+ static bool pylsEnabled();
+ static void setPylsEnabled(const bool &enabled);
+ static QString pyLSConfiguration();
static PythonSettings *instance();
static QList<Interpreter> detectPythonVenvs(const Utils::FilePath &path);
signals:
void interpretersChanged(const QList<Interpreter> &interpreters, const QString &defaultId);
+ void pylsConfigurationChanged(const QString &configuration);
+ void pylsEnabledChanged(const bool enabled);
private:
PythonSettings();
diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp
index 8902ec48ed0..ebc2a695f7b 100644
--- a/src/plugins/python/pythonutils.cpp
+++ b/src/plugins/python/pythonutils.cpp
@@ -36,9 +36,10 @@
#include <projectexplorer/target.h>
#include <utils/algorithm.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcprocess.h>
+using namespace ProjectExplorer;
using namespace Utils;
namespace Python {
@@ -46,36 +47,51 @@ namespace Internal {
FilePath detectPython(const FilePath &documentPath)
{
- FilePath python;
-
- PythonProject *project = documentPath.isEmpty()
- ? nullptr
- : qobject_cast<PythonProject *>(
- ProjectExplorer::SessionManager::projectForFile(documentPath));
+ Project *project = documentPath.isEmpty() ? nullptr
+ : SessionManager::projectForFile(documentPath);
if (!project)
- project = qobject_cast<PythonProject *>(ProjectExplorer::SessionManager::startupProject());
+ project = SessionManager::startupProject();
+
+ Environment env = Environment::systemEnvironment();
if (project) {
if (auto target = project->activeTarget()) {
- if (auto runConfig = qobject_cast<PythonRunConfiguration *>(
- target->activeRunConfiguration())) {
- python = FilePath::fromString(runConfig->interpreter());
+ if (auto runConfig = target->activeRunConfiguration()) {
+ if (auto interpreter = runConfig->aspect<InterpreterAspect>())
+ return interpreter->currentInterpreter().command;
+ if (auto environmentAspect = runConfig->aspect<EnvironmentAspect>())
+ env = environmentAspect->environment();
}
}
}
// check whether this file is inside a python virtual environment
- QList<Interpreter> venvInterpreters = PythonSettings::detectPythonVenvs(documentPath);
- if (!python.exists())
- python = venvInterpreters.value(0).command;
+ const QList<Interpreter> venvInterpreters = PythonSettings::detectPythonVenvs(documentPath);
+ if (!venvInterpreters.isEmpty())
+ return venvInterpreters.first().command;
+
+ auto defaultInterpreter = PythonSettings::defaultInterpreter().command;
+ if (defaultInterpreter.exists())
+ return defaultInterpreter;
+
+ auto pythonFromPath = [=](const QString toCheck) {
+ for (const FilePath &python : env.findAllInPath(toCheck)) {
+ // Windows creates empty redirector files that may interfere
+ if (python.exists() && python.osType() == OsTypeWindows && python.fileSize() != 0)
+ return python;
+ }
+ return FilePath();
+ };
- if (!python.exists())
- python = PythonSettings::defaultInterpreter().command;
+ const FilePath fromPath3 = pythonFromPath("python3");
+ if (fromPath3.exists())
+ return fromPath3;
- if (!python.exists() && !PythonSettings::interpreters().isEmpty())
- python = PythonSettings::interpreters().constFirst().command;
+ const FilePath fromPath = pythonFromPath("python");
+ if (fromPath.exists())
+ return fromPath;
- return python;
+ return PythonSettings::interpreters().value(0).command;
}
static QStringList replImportArgs(const FilePath &pythonFile, ReplType type)
@@ -99,7 +115,7 @@ void openPythonRepl(QObject *parent, const FilePath &file, ReplType type)
{
static const auto workingDir = [](const FilePath &file) {
if (file.isEmpty()) {
- if (ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject())
+ if (Project *project = SessionManager::startupProject())
return project->projectDirectory();
return FilePath::fromString(QDir::currentPath());
}
@@ -107,24 +123,54 @@ void openPythonRepl(QObject *parent, const FilePath &file, ReplType type)
};
const auto args = QStringList{"-i"} + replImportArgs(file, type);
- auto process = new QtcProcess(QtcProcess::TerminalOn, parent);
+ auto process = new QtcProcess(parent);
+ process->setTerminalMode(TerminalMode::On);
const FilePath pythonCommand = detectPython(file);
process->setCommand({pythonCommand, args});
process->setWorkingDirectory(workingDir(file));
const QString commandLine = process->commandLine().toUserOutput();
- QObject::connect(process,
- &QtcProcess::errorOccurred,
- process,
- [process, commandLine] {
- Core::MessageManager::writeDisrupting(
- QCoreApplication::translate("Python",
- "Failed to run Python (%1): \"%2\".")
- .arg(commandLine, process->errorString()));
- process->deleteLater();
- });
- QObject::connect(process, &QtcProcess::finished, process, &QObject::deleteLater);
+ QObject::connect(process, &QtcProcess::done, process, [process, commandLine] {
+ if (process->error() != QProcess::UnknownError) {
+ Core::MessageManager::writeDisrupting(QCoreApplication::translate("Python",
+ (process->error() == QProcess::FailedToStart)
+ ? "Failed to run Python (%1): \"%2\"."
+ : "Error while running Python (%1): \"%2\".")
+ .arg(commandLine, process->errorString()));
+ }
+ process->deleteLater();
+ });
process->start();
}
+QString pythonName(const FilePath &pythonPath)
+{
+ static QHash<FilePath, QString> nameForPython;
+ if (!pythonPath.exists())
+ return {};
+ QString name = nameForPython.value(pythonPath);
+ if (name.isEmpty()) {
+ QtcProcess pythonProcess;
+ pythonProcess.setTimeoutS(2);
+ pythonProcess.setCommand({pythonPath, {"--version"}});
+ pythonProcess.runBlocking();
+ if (pythonProcess.result() != ProcessResult::FinishedWithSuccess)
+ return {};
+ name = pythonProcess.allOutput().trimmed();
+ nameForPython[pythonPath] = name;
+ }
+ return name;
+}
+
+PythonProject *pythonProjectForFile(const FilePath &pythonFile)
+{
+ for (Project *project : SessionManager::projects()) {
+ if (auto pythonProject = qobject_cast<PythonProject *>(project)) {
+ if (pythonProject->isKnownFile(pythonFile))
+ return pythonProject;
+ }
+ }
+ return nullptr;
+}
+
} // namespace Internal
} // namespace Python
diff --git a/src/plugins/python/pythonutils.h b/src/plugins/python/pythonutils.h
index c33bf456cac..4ca5ea37a01 100644
--- a/src/plugins/python/pythonutils.h
+++ b/src/plugins/python/pythonutils.h
@@ -25,7 +25,7 @@
#pragma once
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
namespace Python {
namespace Internal {
@@ -33,6 +33,10 @@ namespace Internal {
enum class ReplType { Unmodified, Import, ImportToplevel };
void openPythonRepl(QObject *parent, const Utils::FilePath &file, ReplType type);
Utils::FilePath detectPython(const Utils::FilePath &documentPath);
+QString pythonName(const Utils::FilePath &pythonPath);
+
+class PythonProject;
+PythonProject *pythonProjectForFile(const Utils::FilePath &pythonFile);
} // namespace Internal
} // namespace Python
diff --git a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp
index 19bfdc27b0a..98d04e76a50 100644
--- a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp
+++ b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp
@@ -31,6 +31,7 @@
#include <coreplugin/messagemanager.h>
#include <baremetal/baremetalconstants.h>
#include <projectexplorer/abi.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/gcctoolchain.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
@@ -45,7 +46,6 @@
#include <ios/iosconstants.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
-#include <winrt/winrtconstants.h>
#include <QDir>
#include <QFileInfo>
@@ -60,7 +60,6 @@ using namespace Constants;
namespace Internal {
using namespace ProjectExplorer::Constants;
using namespace Ios::Constants;
-using namespace WinRt::Internal::Constants;
static QString extractToolchainPrefix(QString *compilerName)
{
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
index be80dfcb7f1..22403395dd1 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
@@ -46,7 +46,6 @@
#include <qtsupport/qtkitinformation.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -66,7 +65,7 @@ static FilePath defaultBuildDirectory(const FilePath &projectFilePath, const Kit
const QString projectName = projectFilePath.completeBaseName();
return BuildConfiguration::buildDirectoryFromTemplate(
Project::projectDirectory(projectFilePath),
- projectFilePath, projectName, k, bcName, buildType);
+ projectFilePath, projectName, k, bcName, buildType, "qbs");
}
// ---------------------------------------------------------------------------
@@ -132,13 +131,11 @@ QbsBuildConfiguration::QbsBuildConfiguration(Target *target, Utils::Id id)
connect(separateDebugInfoAspect, &SeparateDebugInfoAspect::changed,
this, &QbsBuildConfiguration::qbsConfigurationChanged);
- const auto qmlDebuggingAspect = addAspect<QtSupport::QmlDebuggingAspect>();
- qmlDebuggingAspect->setKit(target->kit());
+ const auto qmlDebuggingAspect = addAspect<QtSupport::QmlDebuggingAspect>(this);
connect(qmlDebuggingAspect, &QtSupport::QmlDebuggingAspect::changed,
this, &QbsBuildConfiguration::qbsConfigurationChanged);
- const auto qtQuickCompilerAspect = addAspect<QtSupport::QtQuickCompilerAspect>();
- qtQuickCompilerAspect->setKit(target->kit());
+ const auto qtQuickCompilerAspect = addAspect<QtSupport::QtQuickCompilerAspect>(this);
connect(qtQuickCompilerAspect, &QtSupport::QtQuickCompilerAspect::changed,
this, &QbsBuildConfiguration::qbsConfigurationChanged);
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
index 20249d09ed0..3350fb6fd8a 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
@@ -41,6 +41,7 @@
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtversionmanager.h>
+#include <utils/algorithm.h>
#include <utils/aspects.h>
#include <utils/layoutbuilder.h>
#include <utils/macroexpander.h>
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
index 8a78718cf54..1ce9752f9f4 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.cpp
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -561,7 +561,7 @@ void QbsBuildSystem::handleQbsParsingDone(bool success)
m_qbsUpdateFutureInterface->reportCanceled();
}
- delete m_qbsProjectParser;
+ m_qbsProjectParser->deleteLater();
m_qbsProjectParser = nullptr;
m_qbsUpdateFutureInterface->reportFinished();
delete m_qbsUpdateFutureInterface;
diff --git a/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp b/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
index 5873728a3bc..ee7fb37ed15 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
@@ -25,7 +25,6 @@
#include "qbsprojectimporter.h"
-#include "qbsbuildconfiguration.h"
#include "qbspmlogging.h"
#include "qbssession.h"
@@ -39,7 +38,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>
#include <qtsupport/qtkitinformation.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <utils/hostosinfo.h>
#include <QFileInfo>
@@ -90,7 +89,7 @@ static FilePath buildDir(const FilePath &projectFilePath, const Kit *k)
const QString projectName = projectFilePath.completeBaseName();
return BuildConfiguration::buildDirectoryFromTemplate(
Project::projectDirectory(projectFilePath),
- projectFilePath, projectName, k, QString(), BuildConfiguration::Unknown);
+ projectFilePath, projectName, k, QString(), BuildConfiguration::Unknown, "qbs");
}
static bool hasBuildGraph(const QString &dir)
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager_global.h b/src/plugins/qbsprojectmanager/qbsprojectmanager_global.h
index 7b53f201e3d..607a1ef255c 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager_global.h
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager_global.h
@@ -29,6 +29,8 @@
#if defined(QBSPROJECTMANAGER_LIBRARY)
# define QBSPROJECTMANAGER_EXPORT Q_DECL_EXPORT
+#elif defined(QBSPROJECTMANAGER_STATIC_LIBRARY)
+# define QBSPROJECTMANAGER_EXPORT
#else
# define QBSPROJECTMANAGER_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/qbsprojectmanager/qbssession.cpp b/src/plugins/qbsprojectmanager/qbssession.cpp
index 8739bed7b3b..746fd515bf4 100644
--- a/src/plugins/qbsprojectmanager/qbssession.cpp
+++ b/src/plugins/qbsprojectmanager/qbssession.cpp
@@ -34,6 +34,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/taskhub.h>
#include <utils/algorithm.h>
+#include <utils/environment.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -169,8 +170,11 @@ void QbsSession::initialize()
{
Environment env = Environment::systemEnvironment();
env.set("QT_FORCE_STDERR_LOGGING", "1");
+
d->packetReader = new PacketReader(this);
- d->qbsProcess = new QtcProcess(ProcessMode::Writer, this);
+
+ d->qbsProcess = new QtcProcess(this);
+ d->qbsProcess->setProcessMode(ProcessMode::Writer);
d->qbsProcess->setEnvironment(env);
connect(d->qbsProcess, &QtcProcess::readyReadStandardOutput, this, [this] {
d->packetReader->handleData(d->qbsProcess->readAllStandardOutput());
@@ -178,31 +182,16 @@ void QbsSession::initialize()
connect(d->qbsProcess, &QtcProcess::readyReadStandardError, this, [this] {
qCDebug(qbsPmLog) << "[qbs stderr]: " << d->qbsProcess->readAllStandardError();
});
- connect(d->qbsProcess, &QtcProcess::errorOccurred, this, [this](QProcess::ProcessError e) {
- d->eventLoop.exit(1);
- if (state() == State::ShuttingDown || state() == State::Inactive)
- return;
- switch (e) {
- case QProcess::FailedToStart:
+ connect(d->qbsProcess, &QtcProcess::done, this, [this] {
+ if (d->qbsProcess->result() == ProcessResult::StartFailed) {
+ d->eventLoop.exit(1);
setError(Error::QbsFailedToStart);
- break;
- case QProcess::WriteError:
- case QProcess::ReadError:
- setError(Error::ProtocolError);
- break;
- case QProcess::Crashed:
- case QProcess::Timedout:
- case QProcess::UnknownError:
- break;
+ return;
}
- });
- connect(d->qbsProcess, &QtcProcess::finished, this, [this] {
d->qbsProcess->deleteLater();
- switch (state()) {
+ switch (d->state) {
case State::Inactive:
- break;
- case State::ShuttingDown:
- setInactive();
+ QTC_CHECK(false);
break;
case State::Active:
setError(Error::QbsQuit);
@@ -211,7 +200,6 @@ void QbsSession::initialize()
setError(Error::ProtocolError);
break;
}
- d->qbsProcess = nullptr;
});
connect(d->packetReader, &PacketReader::errorOccurred, this, [this](const QString &msg) {
qCDebug(qbsPmLog) << "session error" << msg;
@@ -230,8 +218,8 @@ void QbsSession::initialize()
void QbsSession::sendQuitPacket()
{
- d->qbsProcess->write(Packet::createPacket(QJsonObject{qMakePair(QString("type"),
- QJsonValue("quit"))}));
+ d->qbsProcess->writeRaw(Packet::createPacket(QJsonObject{qMakePair(QString("type"),
+ QJsonValue("quit"))}));
}
QbsSession::~QbsSession()
@@ -240,21 +228,15 @@ QbsSession::~QbsSession()
d->packetReader->disconnect(this);
if (d->qbsProcess) {
d->qbsProcess->disconnect(this);
- quit();
- if (d->qbsProcess->state() == QProcess::Running && !d->qbsProcess->waitForFinished(10000))
- d->qbsProcess->terminate();
- if (d->qbsProcess->state() == QProcess::Running && !d->qbsProcess->waitForFinished(10000))
- d->qbsProcess->kill();
- d->qbsProcess->waitForFinished(1000);
+ if (d->qbsProcess->state() == QProcess::Running) {
+ sendQuitPacket();
+ d->qbsProcess->waitForFinished(10000);
+ }
+ delete d->qbsProcess;
}
delete d;
}
-QbsSession::State QbsSession::state() const
-{
- return d->state;
-}
-
optional<QbsSession::Error> QbsSession::lastError() const
{
return d->lastError;
@@ -304,14 +286,6 @@ void QbsSession::cancelCurrentJob()
sendRequest(QJsonObject{qMakePair(QString("type"), QJsonValue("cancel-job"))});
}
-void QbsSession::quit()
-{
- if (d->state == State::ShuttingDown || d->state == State::Inactive)
- return;
- d->state = State::ShuttingDown;
- sendQuitPacket();
-}
-
void QbsSession::requestFilesGeneratedFrom(const QHash<QString, QStringList> &sourceFilesPerProduct)
{
QJsonObject request;
@@ -561,7 +535,7 @@ void QbsSession::sendRequestNow(const QJsonObject &request)
{
QTC_ASSERT(d->state == State::Active, return);
if (!request.isEmpty())
- d->qbsProcess->write(Packet::createPacket(request));
+ d->qbsProcess->writeRaw(Packet::createPacket(request));
}
ErrorInfo QbsSession::getErrorInfo(const QJsonObject &packet)
diff --git a/src/plugins/qbsprojectmanager/qbssession.h b/src/plugins/qbsprojectmanager/qbssession.h
index 8829085f9df..b3901cbf2cd 100644
--- a/src/plugins/qbsprojectmanager/qbssession.h
+++ b/src/plugins/qbsprojectmanager/qbssession.h
@@ -121,17 +121,15 @@ public:
explicit QbsSession(QObject *parent = nullptr);
~QbsSession() override;
- enum class State { Initializing, Active, ShuttingDown, Inactive };
+ enum class State { Initializing, Active, Inactive };
enum class Error { QbsFailedToStart, QbsQuit, ProtocolError, VersionMismatch };
- State state() const;
Utils::optional<Error> lastError() const;
static QString errorString(Error error);
QJsonObject projectData() const;
void sendRequest(const QJsonObject &request);
void cancelCurrentJob();
- void quit();
void requestFilesGeneratedFrom(const QHash<QString, QStringList> &sourceFilesPerProduct);
QStringList filesGeneratedFrom(const QString &sourceFile) const;
FileChangeResult addFiles(const QStringList &files, const QString &product,
diff --git a/src/plugins/qmakeprojectmanager/externaleditors.cpp b/src/plugins/qmakeprojectmanager/externaleditors.cpp
index 6d5893e6701..9d22c2ad0cf 100644
--- a/src/plugins/qmakeprojectmanager/externaleditors.cpp
+++ b/src/plugins/qmakeprojectmanager/externaleditors.cpp
@@ -170,8 +170,11 @@ bool ExternalQtEditor::getEditorLaunchData(const Utils::FilePath &filePath,
qtVersionsToCheck = Utils::filteredUnique(qtVersionsToCheck); // can still contain nullptr
data->binary = findFirstCommand(qtVersionsToCheck, m_commandForQtVersion);
// fallback
- if (data->binary.isEmpty())
- data->binary = Utils::QtcProcess::locateBinary(m_commandForQtVersion(nullptr));
+ if (data->binary.isEmpty()) {
+ const QString path = qEnvironmentVariable("PATH");
+ data->binary = Utils::QtcProcess::locateBinary(path, m_commandForQtVersion(nullptr));
+ }
+
if (data->binary.isEmpty()) {
*errorMessage = msgAppNotFound(id().toString());
return false;
@@ -272,12 +275,7 @@ bool DesignerExternalEditor::startEditor(const Utils::FilePath &filePath, QStrin
m_processCache.insert(binary, socket);
auto mapSlot = [this, binary] { processTerminated(binary); };
connect(socket, &QAbstractSocket::disconnected, this, mapSlot);
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- const auto errorOccurred = QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error);
-#else
- const auto errorOccurred = &QAbstractSocket::errorOccurred;
-#endif
- connect(socket, errorOccurred, this, mapSlot);
+ connect(socket, &QAbstractSocket::errorOccurred, this, mapSlot);
}
return true;
}
diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp
index be1c5f9dd26..ecb3bfbda78 100644
--- a/src/plugins/qmakeprojectmanager/profileeditor.cpp
+++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp
@@ -62,7 +62,7 @@ class ProFileEditorWidget : public TextEditorWidget
{
private:
void findLinkAt(const QTextCursor &,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool resolveTarget = true,
bool inNextSplit = false) override;
void contextMenuEvent(QContextMenuEvent *) override;
@@ -125,7 +125,7 @@ QString ProFileEditorWidget::checkForPrfFile(const QString &baseName) const
}
void ProFileEditorWidget::findLinkAt(const QTextCursor &cursor,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const LinkHandler &processLinkCallback,
bool /*resolveTarget*/,
bool /*inNextSplit*/)
{
diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
index 018b4c339f1..675b272085c 100644
--- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
@@ -56,10 +56,8 @@
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtversionmanager.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/qtcassert.h>
#include <QDebug>
#include <QInputDialog>
@@ -105,8 +103,8 @@ FilePath QmakeBuildConfiguration::shadowBuildDirectory(const FilePath &proFilePa
return {};
const QString projectName = proFilePath.completeBaseName();
- return BuildConfiguration::buildDirectoryFromTemplate(
- Project::projectDirectory(proFilePath), proFilePath, projectName, k, suffix, buildType);
+ return buildDirectoryFromTemplate(Project::projectDirectory(proFilePath), proFilePath,
+ projectName, k, suffix, buildType, "qmake");
}
const char BUILD_CONFIGURATION_KEY[] = "Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration";
@@ -191,16 +189,14 @@ QmakeBuildConfiguration::QmakeBuildConfiguration(Target *target, Utils::Id id)
qmakeBuildSystem()->scheduleUpdateAllNowOrLater();
});
- const auto qmlDebuggingAspect = addAspect<QmlDebuggingAspect>();
- qmlDebuggingAspect->setKit(target->kit());
+ const auto qmlDebuggingAspect = addAspect<QmlDebuggingAspect>(this);
connect(qmlDebuggingAspect, &QmlDebuggingAspect::changed, this, [this] {
emit qmlDebuggingChanged();
emit qmakeBuildConfigurationChanged();
qmakeBuildSystem()->scheduleUpdateAllNowOrLater();
});
- const auto qtQuickCompilerAspect = addAspect<QtQuickCompilerAspect>();
- qtQuickCompilerAspect->setKit(target->kit());
+ const auto qtQuickCompilerAspect = addAspect<QtQuickCompilerAspect>(this);
connect(qtQuickCompilerAspect, &QtQuickCompilerAspect::changed, this, [this] {
emit useQtQuickCompilerChanged();
emit qmakeBuildConfigurationChanged();
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
index da52070931a..7c2f3b5e7b6 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
@@ -28,6 +28,7 @@
#include "qmakeproject.h"
#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.h b/src/plugins/qmakeprojectmanager/qmakenodes.h
index 798a813dad6..59e49f467ae 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.h
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.h
@@ -31,9 +31,8 @@
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/projectnodes.h>
-namespace Utils { class FilePath; }
-
namespace QmakeProjectManager {
+
class QmakeProFileNode;
class QmakeProject;
diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
index 8ae6a7cf1e5..10fc625d562 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
@@ -179,7 +179,8 @@ static void createTree(QmakeBuildSystem *buildSystem,
vfolder->setIcon(fileTypes.at(i).icon);
vfolder->setDisplayName(fileTypes.at(i).typeName);
vfolder->setAddFileFilter(fileTypes.at(i).addFileFilter);
- vfolder->setIsSourcesOrHeaders(type == FileType::Source || type == FileType::Header);
+ vfolder->setIsSourcesOrHeaders(type == FileType::Source || type == FileType::Header
+ || type == FileType::Form);
if (type == FileType::Resource) {
for (const auto &file : newFilePaths) {
diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
index 0931743f9b4..d5dc6a91e79 100644
--- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
@@ -27,7 +27,6 @@
#include "qmakeproject.h"
#include "qmakeprojectmanagerconstants.h"
-#include "qmakebuildconfiguration.h"
#include <android/androidconstants.h>
#include <coreplugin/documentmanager.h>
@@ -46,17 +45,18 @@
#include <texteditor/tabsettings.h>
#include <texteditor/texteditorsettings.h>
+#include <utils/QtConcurrentTools>
#include <utils/algorithm.h>
#include <utils/filesystemwatcher.h>
+#include <utils/mimeutils.h>
#include <utils/qtcprocess.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/stringutils.h>
#include <utils/temporarydirectory.h>
-#include <utils/QtConcurrentTools>
#include <QLoggingCategory>
#include <QMessageBox>
#include <QTextCodec>
+#include <QXmlStreamWriter>
using namespace Core;
using namespace ProjectExplorer;
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
index c77f468ae23..bff8df79024 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
@@ -1390,7 +1390,7 @@ void QmakeBuildSystem::testToolChain(ToolChain *tc, const FilePath &path) const
const Utils::FilePath expected = tc->compilerCommand();
Environment env = buildConfiguration()->environment();
- if (env.isSameExecutable(path.toString(), expected.toString()))
+ if (tc->matchesCompilerCommand(expected, env))
return;
const QPair<Utils::FilePath, Utils::FilePath> pair = qMakePair(expected, path);
if (m_toolChainWarnings.contains(pair))
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager_global.h b/src/plugins/qmakeprojectmanager/qmakeprojectmanager_global.h
index 7dee97cb25f..d5d64f69f71 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager_global.h
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager_global.h
@@ -29,6 +29,8 @@
#if defined(QMAKEPROJECTMANAGER_LIBRARY)
# define QMAKEPROJECTMANAGER_EXPORT Q_DECL_EXPORT
+#elif defined(QMAKEPROJECTMANAGER_STATIC_LIBRARY)
+# define QMAKEPROJECTMANAGER_EXPORT
#else
# define QMAKEPROJECTMANAGER_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
index 3268d16a529..2393251ae02 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
@@ -38,7 +38,6 @@
#include "qmakeproject.h"
#include "externaleditors.h"
#include "qmakekitinformation.h"
-#include "profilehighlighter.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -56,6 +55,7 @@
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectexplorericons.h>
#include <texteditor/texteditor.h>
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h
index 68255197dd0..5b3176b9b72 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h
@@ -27,12 +27,7 @@
#include <extensionsystem/iplugin.h>
-namespace ProjectExplorer { class Project; }
-
namespace QmakeProjectManager {
-
-class QmakeProFileNode;
-
namespace Internal {
class QmakeProjectManagerPlugin final : public ExtensionSystem::IPlugin
diff --git a/src/plugins/qmakeprojectmanager/qmakesettings.cpp b/src/plugins/qmakeprojectmanager/qmakesettings.cpp
index 12886c1486d..8102ce10818 100644
--- a/src/plugins/qmakeprojectmanager/qmakesettings.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakesettings.cpp
@@ -29,8 +29,11 @@
#include <projectexplorer/projectexplorerconstants.h>
+#include <utils/hostosinfo.h>
#include <utils/layoutbuilder.h>
+#include <QXmlStreamWriter>
+
using namespace Utils;
namespace QmakeProjectManager {
diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp
index 65e3f379403..7b6eddc5670 100644
--- a/src/plugins/qmakeprojectmanager/qmakestep.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp
@@ -25,7 +25,6 @@
#include "qmakestep.h"
-#include "qmakemakestep.h"
#include "qmakebuildconfiguration.h"
#include "qmakekitinformation.h"
#include "qmakenodes.h"
@@ -39,8 +38,10 @@
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/gnumakeparser.h>
+#include <projectexplorer/makestep.h>
#include <projectexplorer/processparameters.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h>
@@ -89,7 +90,7 @@ QMakeStep::QMakeStep(BuildStepList *bsl, Id id)
m_buildType->addOption(tr("Debug"));
m_buildType->addOption(tr("Release"));
- m_userArgs = addAspect<ArgumentsAspect>();
+ m_userArgs = addAspect<ArgumentsAspect>(macroExpander());
m_userArgs->setSettingsKey(QMAKE_ARGUMENTS_KEY);
m_userArgs->setLabelText(tr("Additional arguments:"));
@@ -469,7 +470,7 @@ QStringList QMakeStep::parserArguments()
QString QMakeStep::userArguments() const
{
- return m_userArgs->arguments(macroExpander());
+ return m_userArgs->arguments();
}
QString QMakeStep::mkspec() const
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index bd55391a314..8b0081b1d89 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -9,7 +9,6 @@ add_qtc_plugin(QmlDesigner
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
Qt5::QuickWidgets Qt5::CorePrivate Sqlite Qt5::Xml Qt5::Svg
DEFINES
- DESIGNER_CORE_LIBRARY
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
SHARE_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../../../share/qtcreator/qmldesigner"
PUBLIC_INCLUDES
@@ -27,15 +26,8 @@ add_qtc_plugin(QmlDesigner
designmodewidget.cpp designmodewidget.h
documentmanager.cpp documentmanager.h
documentwarningwidget.cpp documentwarningwidget.h
- checkablefiletreeitem.cpp checkablefiletreeitem.h
- cmakegeneratordialog.cpp cmakegeneratordialog.h
- cmakegeneratordialogtreemodel.cpp cmakegeneratordialogtreemodel.h
- cmakeprojectconverter.cpp cmakeprojectconverter.h
- cmakeprojectconverterdialog.cpp cmakeprojectconverterdialog.h
dynamiclicensecheck.h
generateresource.cpp generateresource.h
- generatecmakelists.cpp generatecmakelists.h
- generatecmakelistsconstants.h
openuiqmlfiledialog.cpp openuiqmlfiledialog.h openuiqmlfiledialog.ui
qmldesignerconstants.h
qmldesignericons.h
@@ -46,7 +38,6 @@ add_qtc_plugin(QmlDesigner
designermcumanager.cpp designermcumanager.h
richtexteditordialog.cpp richtexteditordialog.h
editorproxy.cpp editorproxy.h
- boilerplate.qrc
EXPLICIT_MOC
components/propertyeditor/propertyeditorvalue.h
components/connectioneditor/connectionviewwidget.h
@@ -59,7 +50,16 @@ add_qtc_plugin(QmlDesigner
include(qmldesignercore.cmake)
extend_with_qmldesigner_core(QmlDesigner)
+if (QTC_STATIC_BUILD AND TARGET QmlDesigner)
+ get_target_property(_designerType Qt5::Designer TYPE)
+ if (${_designerType} STREQUAL "STATIC_LIBRARY")
+ extend_qtc_target(QmlDesigner PUBLIC_DEFINES QT_DESIGNER_STATIC)
+ endif()
+ extend_qtc_target(QmlDesigner PUBLIC_DEPENDS TextEditor)
+endif()
+
add_qtc_plugin(assetexporterplugin
+ PLUGIN_CLASS AssetExporterPlugin
CONDITION TARGET QmlDesigner
DEPENDS Core ProjectExplorer QmlDesigner Utils Qt5::Qml Qt5::QuickPrivate
PUBLIC_INCLUDES assetexporterplugin
@@ -81,6 +81,7 @@ add_qtc_plugin(assetexporterplugin
)
add_qtc_plugin(componentsplugin
+ PLUGIN_CLASS ComponentsPlugin
CONDITION TARGET QmlDesigner
DEPENDS Core QmlDesigner Utils Qt5::Qml
DEFINES COMPONENTS_LIBRARY
@@ -96,6 +97,7 @@ add_qtc_plugin(componentsplugin
)
add_qtc_plugin(qmlpreviewplugin
+ PLUGIN_CLASS QmlPreviewWidgetPlugin
CONDITION TARGET QmlDesigner
DEPENDS Core ProjectExplorer QmlDesigner Utils Qt5::Qml
SOURCES
@@ -106,6 +108,7 @@ add_qtc_plugin(qmlpreviewplugin
)
add_qtc_plugin(qtquickplugin
+ PLUGIN_CLASS QtQuickPlugin
CONDITION TARGET QmlDesigner
DEPENDS Core QmlDesigner Utils Qt5::Qml
DEFINES QTQUICK_LIBRARY
@@ -335,7 +338,7 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components
- SOURCES resources/resources.qrc
+ SOURCES resources/resources_qmldesigner_components.qrc
)
extend_qtc_plugin(QmlDesigner
@@ -494,7 +497,7 @@ extend_qtc_plugin(QmlDesigner
easingcurve.cpp easingcurve.h
easingcurvedialog.cpp easingcurvedialog.h
preseteditor.cpp preseteditor.h
- setframevaluedialog.cpp setframevaluedialog.h setframevaluedialog.ui
+ setframevaluedialog.cpp setframevaluedialog.h
splineeditor.cpp splineeditor.h
timeline.qrc
timelineabstracttool.cpp timelineabstracttool.h
diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp
index 7809b57e71b..c7e4408cb14 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp
@@ -105,7 +105,7 @@ void AssetExporterPlugin::onExport()
void AssetExporterPlugin::addActions()
{
- auto exportAction = new QAction(tr("Export Components"));
+ auto exportAction = new QAction(tr("Export Components"), this);
exportAction->setToolTip(tr("Export components in the current project."));
connect(exportAction, &QAction::triggered, this, &AssetExporterPlugin::onExport);
Core::Command *cmd = Core::ActionManager::registerAction(exportAction, Constants::EXPORT_QML);
diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs
index 031b0977bc5..a8bc03685f3 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs
+++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs
@@ -2,13 +2,14 @@ import qbs
QtcProduct {
name: "assetexporterplugin"
+ condition: QmlDesigner.present
type: ["dynamiclibrary"]
installDir: qtc.ide_plugin_path + '/' + installDirName
property string installDirName: qbs.targetOS.contains("macos") ? "QmlDesigner" : "qmldesigner"
Depends { name: "Core" }
Depends { name: "ProjectExplorer" }
- Depends { name: "QmlDesigner" }
+ Depends { name: "QmlDesigner"; required: false }
Depends { name: "Utils" }
Depends {
name: "Qt"
diff --git a/src/plugins/qmldesigner/checkablefiletreeitem.cpp b/src/plugins/qmldesigner/checkablefiletreeitem.cpp
deleted file mode 100644
index 42a788b8d69..00000000000
--- a/src/plugins/qmldesigner/checkablefiletreeitem.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "checkablefiletreeitem.h"
-
-using namespace Utils;
-
-namespace QmlDesigner {
-
-CheckableFileTreeItem::CheckableFileTreeItem(const FilePath &filePath)
- :QStandardItem(filePath.toString())
-{
- Qt::ItemFlags itemFlags = flags();
- if (!isDir())
- itemFlags |= Qt::ItemIsUserCheckable;
- itemFlags &= ~(Qt::ItemIsEditable | Qt::ItemIsSelectable);
- setFlags(itemFlags);
-}
-
-const FilePath CheckableFileTreeItem::toFilePath() const
-{
- return FilePath::fromString(text());
-}
-
-bool CheckableFileTreeItem::isFile() const
-{
- return FilePath::fromString(text()).isFile();
-}
-
-bool CheckableFileTreeItem::isDir() const
-{
- return FilePath::fromString(text()).isDir();
-}
-
-void CheckableFileTreeItem::setChecked(bool checked)
-{
- this->checked = checked;
-}
-
-bool CheckableFileTreeItem::isChecked() const
-{
- return this->checked;
-}
-
-} //QmlDesigner
diff --git a/src/plugins/qmldesigner/checkablefiletreeitem.h b/src/plugins/qmldesigner/checkablefiletreeitem.h
deleted file mode 100644
index d7762a88043..00000000000
--- a/src/plugins/qmldesigner/checkablefiletreeitem.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#ifndef CHECKABLEFILETREEITEM_H
-#define CHECKABLEFILETREEITEM_H
-
-#include <utils/fileutils.h>
-
-#include <QStandardItem>
-
-namespace QmlDesigner {
-
-class CheckableFileTreeItem : public QStandardItem
-{
-public:
- explicit CheckableFileTreeItem(const Utils::FilePath &text = Utils::FilePath());
-
- const Utils::FilePath toFilePath() const;
- bool isFile() const;
- bool isDir() const;
-
- bool isChecked() const;
- void setChecked(bool checked);
-
-private:
- bool checked;
-};
-
-} //QmlDesigner
-
-#endif // CHECKABLEFILETREEITEM_H
diff --git a/src/plugins/qmldesigner/cmakegeneratordialog.cpp b/src/plugins/qmldesigner/cmakegeneratordialog.cpp
deleted file mode 100644
index 19edd3e30a6..00000000000
--- a/src/plugins/qmldesigner/cmakegeneratordialog.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cmakegeneratordialog.h"
-#include "cmakegeneratordialogtreemodel.h"
-#include "generatecmakelistsconstants.h"
-
-#include <utils/utilsicons.h>
-#include <utils/detailswidget.h>
-
-#include <QDialogButtonBox>
-#include <QPushButton>
-#include <QLayout>
-#include <QLabel>
-
-#include <QSplitter>
-
-using namespace Utils;
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-
-CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePaths &files)
- : QDialog(),
- m_rootDir(rootDir),
- m_files(files)
-{
- setWindowTitle(QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "Select Files to Generate"));
-
- QLabel *mainLabel = new QLabel(QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "Start CMakeFiles.txt generation"),
- this);
- mainLabel->setMargin(30);
-
- QVBoxLayout *dialogLayout = new QVBoxLayout(this);
- dialogLayout->addWidget(mainLabel);
- dialogLayout->addWidget(createDetailsWidget());
- dialogLayout->addWidget(createButtons());
- setLayout(dialogLayout);
-
- setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- setMaximumHeight(layout()->totalSizeHint().height());
-
- refreshNotificationText();
-}
-
-QTreeView* CmakeGeneratorDialog::createFileTree()
-{
- m_model = new CMakeGeneratorDialogTreeModel(m_rootDir, m_files, this);
-
- QTreeView *tree = new QTreeView(this);
- tree->setModel(m_model);
- tree->expandAll();
- tree->setHeaderHidden(true);
-
- return tree;
-}
-
-QWidget* CmakeGeneratorDialog::createDetailsWidget()
-{
- QTreeView* tree = createFileTree();
-
- m_notifications = new QTextEdit(this);
- m_warningIcon = Utils::Icons::WARNING.pixmap();
-
- QSplitter *advancedInnerWidget = new QSplitter(this);
- advancedInnerWidget->addWidget(tree);
- advancedInnerWidget->addWidget(m_notifications);
- advancedInnerWidget->setStretchFactor(0, 2);
- advancedInnerWidget->setStretchFactor(1, 1);
- advancedInnerWidget->setOrientation(Qt::Vertical);
- advancedInnerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::MinimumExpanding);
-
- DetailsWidget *advancedWidget = new DetailsWidget(this);
- advancedWidget->setMinimumWidth(600);
- advancedWidget->setWidget(advancedInnerWidget);
- advancedWidget->setSummaryText(QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "Advanced Options"));
- connect(advancedWidget, &DetailsWidget::expanded, this, &CmakeGeneratorDialog::advancedVisibilityChanged);
-
- return advancedWidget;
-}
-
-QWidget* CmakeGeneratorDialog::createButtons()
-{
- QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
- auto *okButton = buttons->button(QDialogButtonBox::Ok);
- okButton->setDefault(true);
-
- connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(m_model, &CMakeGeneratorDialogTreeModel::checkedStateChanged, this, &CmakeGeneratorDialog::refreshNotificationText);
-
- return buttons;
-}
-
-FilePaths CmakeGeneratorDialog::getFilePaths()
-{
- FilePaths paths;
-
- QList<CheckableFileTreeItem*> items = m_model->checkedItems();
- for (CheckableFileTreeItem *item: items) {
- paths.append(FilePath::fromString(item->text()));
- }
-
- return paths;
-}
-
-const QString FILE_CREATE_NOTIFICATION = QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "File %1 will be created.\n");
-const QString FILE_OVERWRITE_NOTIFICATION = QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "File %1 will be overwritten.\n");
-
-void CmakeGeneratorDialog::refreshNotificationText()
-{
- QTextDocument *document = m_notifications->document();
- document->clear();
- document->addResource(QTextDocument::ImageResource, QUrl("cmakegendialog://warningicon"), m_warningIcon);
-
- QTextCursor cursor = m_notifications->textCursor();
- QTextImageFormat iformat;
- iformat.setName("cmakegendialog://warningicon");
-
- QList<CheckableFileTreeItem*> nodes = m_model->items();
-
- for (CheckableFileTreeItem *node : nodes) {
- if (!m_files.contains(node->toFilePath()))
- continue;
-
- if (!node->toFilePath().exists() && node->isChecked()) {
- QString relativePath = QString(node->toFilePath().toString()).remove(m_rootDir.toString()+'/');
- cursor.insertText(QString(FILE_CREATE_NOTIFICATION).arg(relativePath));
- }
- }
-
- if (!document->toPlainText().isEmpty())
- cursor.insertBlock();
-
- for (CheckableFileTreeItem *node : nodes) {
- if (!m_files.contains(node->toFilePath()))
- continue;
-
- if (node->toFilePath().exists() && node->isChecked()) {
- QString relativePath = node->toFilePath().relativePath(m_rootDir).toString();
- cursor.insertImage(iformat);
- cursor.insertText(QString(FILE_OVERWRITE_NOTIFICATION).arg(relativePath));
- }
- }
-}
-
-void CmakeGeneratorDialog::advancedVisibilityChanged(bool visible)
-{
- if (visible) {
- setMaximumHeight(QWIDGETSIZE_MAX);
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- }
- else {
- setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- int height = layout()->totalSizeHint().height();
- setMaximumHeight(height);
- resize(width(), height);
- }
-}
-
-} //GenerateCmake
-} //QmlDesigner
diff --git a/src/plugins/qmldesigner/cmakegeneratordialog.h b/src/plugins/qmldesigner/cmakegeneratordialog.h
deleted file mode 100644
index f7c9984bcbf..00000000000
--- a/src/plugins/qmldesigner/cmakegeneratordialog.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-
-#ifndef CMAKEGENERATORDIALOG_H
-#define CMAKEGENERATORDIALOG_H
-
-#include "cmakegeneratordialogtreemodel.h"
-
-#include <utils/fileutils.h>
-
-#include <QDialog>
-#include <QTextEdit>
-#include <QTreeView>
-#include <QLabel>
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-
-class CmakeGeneratorDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- CmakeGeneratorDialog(const Utils::FilePath &rootDir, const Utils::FilePaths &files);
- Utils::FilePaths getFilePaths();
-
-public slots:
- void refreshNotificationText();
- void advancedVisibilityChanged(bool visible);
-
-private:
- QTreeView* createFileTree();
- QWidget* createDetailsWidget();
- QWidget* createButtons();
-
-private:
- CMakeGeneratorDialogTreeModel *m_model;
- QTextEdit *m_notifications;
- QVariant m_warningIcon;
- Utils::FilePath m_rootDir;
- Utils::FilePaths m_files;
-};
-
-} //GenerateCmake
-} //QmlDesigner
-
-#endif // CMAKEGENERATORDIALOG_H
diff --git a/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.cpp b/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.cpp
deleted file mode 100644
index 28a318dcf05..00000000000
--- a/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cmakegeneratordialogtreemodel.h"
-#include "generatecmakelistsconstants.h"
-#include "checkablefiletreeitem.h"
-
-#include <utils/utilsicons.h>
-
-using namespace Utils;
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-
-CMakeGeneratorDialogTreeModel::CMakeGeneratorDialogTreeModel(const FilePath &rootDir,
- const FilePaths &files, QObject *parent)
- :QStandardItemModel(parent),
- rootDir(rootDir),
- m_icons(new QFileIconProvider())
-{
- createNodes(files, invisibleRootItem());
-}
-
-CMakeGeneratorDialogTreeModel::~CMakeGeneratorDialogTreeModel()
-{
- delete m_icons;
-}
-
-QVariant CMakeGeneratorDialogTreeModel::data(const QModelIndex &index, int role) const
-{
- if (index.isValid()) {
- const CheckableFileTreeItem *node = constNodeForIndex(index);
- if (role == Qt::CheckStateRole) {
- if (!node->isDir())
- return node->isChecked() ? Qt::Checked : Qt::Unchecked;
- return {};
- }
- else if (role == Qt::DisplayRole) {
- FilePath fullPath = node->toFilePath();
- return QVariant(fullPath.fileName());
- }
- else if (role == Qt::DecorationRole) {
- if (node->isFile())
- return Utils::Icons::WARNING.icon();
- if (node->isDir())
- return m_icons->icon(QFileIconProvider::Folder);
- else
- return Utils::Icons::NEWFILE.icon();
- }
- else if (role == Qt::ToolTipRole) {
- if (node->isFile())
- return QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "This file already exists and will be overwritten.");
- if (!node->toFilePath().exists())
- return QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "This file or folder will be created.");
- }
- }
-
- return QStandardItemModel::data(index, role);
-}
-
-bool CMakeGeneratorDialogTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- if (index.isValid()) {
- CheckableFileTreeItem *node = nodeForIndex(index);
- if (role == Qt::CheckStateRole) {
- node->setChecked(value.value<bool>());
- emit checkedStateChanged(node);
- return true;
- }
- }
-
- return QStandardItemModel::setData(index, value, role);;
-}
-
-const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::items() const
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- QList<QStandardItem*> standardItems = findItems("*", Qt::MatchWildcard | Qt::MatchRecursive);
-#else
- QList<QStandardItem*> standardItems = findItems(".*", Qt::MatchRegularExpression | Qt::MatchRecursive);
-#endif
- QList<CheckableFileTreeItem*> checkableItems;
- for (QStandardItem *item : standardItems)
- checkableItems.append(static_cast<CheckableFileTreeItem*>(item));
-
- return checkableItems;
-}
-
-const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::checkedItems() const
-{
- QList<CheckableFileTreeItem*> allItems = items();
-
- QList<CheckableFileTreeItem*> checkedItems;
- for (CheckableFileTreeItem *item : allItems) {
- if (item->isChecked())
- checkedItems.append(item);
- }
-
- return checkedItems;
-}
-
-bool CMakeGeneratorDialogTreeModel::checkedByDefault(const Utils::FilePath &file) const
-{
- if (file.exists()) {
- QString relativePath = file.relativeChildPath(rootDir).toString();
- if (relativePath.compare(QmlDesigner::GenerateCmake::Constants::FILENAME_CMAKELISTS) == 0)
- return false;
- if (relativePath.endsWith(QmlDesigner::GenerateCmake::Constants::FILENAME_CMAKELISTS)
- && relativePath.length() > QString(QmlDesigner::GenerateCmake::Constants::FILENAME_CMAKELISTS).length())
- return true;
- if (relativePath.compare(QmlDesigner::GenerateCmake::Constants::FILENAME_MODULES) == 0)
- return true;
- if (relativePath.compare(
- FilePath::fromString(QmlDesigner::GenerateCmake::Constants::DIRNAME_CPP)
- .pathAppended(QmlDesigner::GenerateCmake::Constants::FILENAME_MAINCPP_HEADER)
- .toString())
- == 0)
- return true;
- }
-
- return !file.exists();
-}
-
-void CMakeGeneratorDialogTreeModel::createNodes(const FilePaths &candidates, QStandardItem *parent)
-{
- if (!parent)
- return;
-
- CheckableFileTreeItem *checkParent = dynamic_cast<CheckableFileTreeItem*>(parent);
- FilePath thisDir = (parent == invisibleRootItem()) ? rootDir : checkParent->toFilePath();
-
- for (const FilePath &file : candidates) {
- if (file.parentDir() == thisDir) {
- CheckableFileTreeItem *fileNode = new CheckableFileTreeItem(file);
- fileNode->setChecked(checkedByDefault(file));
- if (!file.exists())
- fileNode->setChecked(true);
- parent->appendRow(fileNode);
- }
- }
-
- FilePaths directSubDirs;
- for (const FilePath &file : candidates) {
- FilePath dir = file.parentDir();
- if (dir.parentDir() == thisDir && !directSubDirs.contains(dir))
- directSubDirs.append(dir);
- }
-
- for (const FilePath &subDir : directSubDirs) {
- CheckableFileTreeItem *dirNode = new CheckableFileTreeItem(subDir);
- parent->appendRow(dirNode);
-
- FilePaths subDirCandidates;
- for (const FilePath &file : candidates)
- if (file.isChildOf(subDir))
- subDirCandidates.append(file);
-
- createNodes(subDirCandidates, dirNode);
- }
-}
-
-const CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::constNodeForIndex(const QModelIndex &index) const
-{
- const QStandardItem *parent = static_cast<const QStandardItem*>(index.internalPointer());
- const QStandardItem *item = parent->child(index.row(), index.column());
- return static_cast<const CheckableFileTreeItem*>(item);
-}
-
-CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::nodeForIndex(const QModelIndex &index)
-{
- QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer());
- QStandardItem *item = parent->child(index.row(), index.column());
- return static_cast<CheckableFileTreeItem*>(item);
-}
-
-} //GenerateCmake
-} //QmlDesigner
diff --git a/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.h b/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.h
deleted file mode 100644
index 79f358a801f..00000000000
--- a/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#ifndef CMAKEGENERATORDIALOGTREEMODEL_H
-#define CMAKEGENERATORDIALOGTREEMODEL_H
-
-#include "checkablefiletreeitem.h"
-
-#include <QFileIconProvider>
-#include <QStandardItemModel>
-
-#include <utils/fileutils.h>
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-
-class CMakeGeneratorDialogTreeModel : public QStandardItemModel
-{
- Q_OBJECT
-
-public:
- CMakeGeneratorDialogTreeModel(const Utils::FilePath &rootDir,
- const Utils::FilePaths &files, QObject *parent = nullptr);
- ~CMakeGeneratorDialogTreeModel();
-
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
-
- const QList<CheckableFileTreeItem*> items() const;
- const QList<CheckableFileTreeItem*> checkedItems() const;
- const CheckableFileTreeItem* constNodeForIndex(const QModelIndex &index) const;
- CheckableFileTreeItem* nodeForIndex(const QModelIndex &index);
-
-signals:
- void checkedStateChanged(CheckableFileTreeItem *item);
-
-protected:
- bool checkedByDefault(const Utils::FilePath &file) const;
- Utils::FilePath rootDir;
-
-private:
- void createNodes(const Utils::FilePaths &candidates, QStandardItem *parent);
-
- QFileIconProvider* m_icons;
-};
-
-} //GenerateCmake
-} //QmlDesigner
-
-
-#endif // CMAKEGENERATORDIALOGTREEMODEL_H
diff --git a/src/plugins/qmldesigner/cmakeprojectconverter.cpp b/src/plugins/qmldesigner/cmakeprojectconverter.cpp
deleted file mode 100644
index 9d1320438db..00000000000
--- a/src/plugins/qmldesigner/cmakeprojectconverter.cpp
+++ /dev/null
@@ -1,440 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-#include "cmakeprojectconverter.h"
-#include "cmakeprojectconverterdialog.h"
-#include "generatecmakelists.h"
-#include "generatecmakelistsconstants.h"
-
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/icore.h>
-
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/session.h>
-#include <projectexplorer/target.h>
-
-#include <QAction>
-#include <QMessageBox>
-#include <QRegularExpression>
-
-using namespace Utils;
-using namespace QmlDesigner::GenerateCmake::Constants;
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-
-const QString MENU_ITEM_CONVERT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
- "Export as Latest Project Format");
-const QString ERROR_TITLE = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
- "Creating Project");
-const QString SUCCESS_TITLE = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
- "Creating Project");
-const QString ERROR_TEXT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
- "Creating project failed.\n%1");
-const QString SUCCESS_TEXT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
- "Creating project succeeded.");
-
-void CmakeProjectConverter::generateMenuEntry()
-{
- Core::ActionContainer *menu =
- Core::ActionManager::actionContainer(Core::Constants::M_FILE);
- auto action = new QAction(MENU_ITEM_CONVERT);
- QObject::connect(action, &QAction::triggered, CmakeProjectConverter::onConvertProject);
- Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.ConvertToCmakeProject");
- menu->addAction(cmd, Core::Constants::G_FILE_EXPORT);
-
- action->setEnabled(isProjectConvertable(ProjectExplorer::SessionManager::startupProject()));
- QObject::connect(ProjectExplorer::SessionManager::instance(),
- &ProjectExplorer::SessionManager::startupProjectChanged, [action]() {
- action->setEnabled(isProjectConvertable(ProjectExplorer::SessionManager::startupProject()));
- });
-}
-
-bool CmakeProjectConverter::isProjectConvertable(const ProjectExplorer::Project *project)
-{
- if (!project)
- return false;
-
- return !isProjectCurrentFormat(project);
-}
-
-const QStringList sanityCheckFiles({FILENAME_CMAKELISTS,
- FILENAME_MODULES,
- FILENAME_MAINQML,
- QString(DIRNAME_CONTENT)+'/'+FILENAME_CMAKELISTS,
- QString(DIRNAME_IMPORT)+'/'+FILENAME_CMAKELISTS,
- QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP,
- QString(DIRNAME_CPP)+'/'+FILENAME_ENV_HEADER,
- QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP_HEADER
- });
-
-bool CmakeProjectConverter::isProjectCurrentFormat(const ProjectExplorer::Project *project)
-{
- const QmlProjectManager::QmlProject *qmlprj = qobject_cast<const QmlProjectManager::QmlProject*>(project);
-
- if (!qmlprj)
- return false;
-
- FilePath rootDir = qmlprj->rootProjectDirectory();
- for (const QString &file : sanityCheckFiles)
- if (!rootDir.pathAppended(file).exists())
- return false;
-
- return true;
-}
-
-void CmakeProjectConverter::onConvertProject()
-{
- ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
- const QmlProjectManager::QmlProject *qmlProject =
- qobject_cast<const QmlProjectManager::QmlProject*>(project);
- if (qmlProject) {
- CmakeProjectConverterDialog dialog(qmlProject);
- if (dialog.exec()) {
- FilePath newProjectPath = dialog.newPath();
- CmakeProjectConverter converter;
- converter.convertProject(qmlProject, newProjectPath);
- }
- }
-}
-
-bool CmakeProjectConverter::convertProject(const QmlProjectManager::QmlProject *project,
- const FilePath &targetDir)
-{
- m_converterObjects.clear();
- m_projectDir = project->projectDirectory();
- m_newProjectDir = targetDir;
- m_project = project;
-
- m_rootDirFiles = QStringList(FILENAME_FILTER_QMLPROJECT);
- const QString confFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!confFile.isEmpty())
- m_rootDirFiles.append(confFile);
-
- bool retVal = prepareAndExecute();
-
- if (retVal) {
- QMessageBox::information(Core::ICore::dialogParent(), SUCCESS_TITLE, SUCCESS_TEXT);
- ProjectExplorer::ProjectExplorerPlugin::OpenProjectResult result
- = ProjectExplorer::ProjectExplorerPlugin::openProject(newProjectFile());
- if (!result)
- ProjectExplorer::ProjectExplorerPlugin::showOpenProjectError(result);
- }
- else {
- QMessageBox::critical(Core::ICore::dialogParent(), ERROR_TITLE, ERROR_TEXT.arg(m_errorText));
- }
-
- return retVal;
-}
-
-bool CmakeProjectConverter::prepareAndExecute()
-{
- GenerateCmake::CmakeFileGenerator cmakeGenerator;
-
- if (!performSanityCheck())
- return false;
- if (!prepareBaseDirectoryStructure())
- return false;
- if (!prepareCopy())
- return false;
- if (!createPreparedProject())
- return false;
- if (!cmakeGenerator.prepare(m_newProjectDir, false))
- return false;
- if (!cmakeGenerator.execute())
- return false;
- if (!modifyNewFiles())
- return false;
-
- return true;
-}
-
-bool CmakeProjectConverter::isFileBlacklisted(const Utils::FilePath &file) const
-{
- if (!file.fileName().compare(FILENAME_CMAKELISTS))
- return true;
- if (!file.suffix().compare(FILENAME_SUFFIX_QMLPROJECT))
- return true;
- if (!file.suffix().compare(FILENAME_SUFFIX_USER))
- return true;
- if (m_rootDirFiles.contains(file.fileName()))
- return true;
-
- return false;
-}
-
-bool CmakeProjectConverter::isDirBlacklisted(const Utils::FilePath &dir) const
-{
- if (!dir.isDir())
- return true;
-
- return false;
-}
-
-const QString ERROR_CANNOT_WRITE_DIR = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
- "Unable to write to directory\n%1.");
-
-bool CmakeProjectConverter::performSanityCheck()
-{
- if (!m_newProjectDir.parentDir().isWritableDir()) {
- m_errorText = ERROR_CANNOT_WRITE_DIR.arg(m_newProjectDir.parentDir().toString());
- return false;
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareBaseDirectoryStructure()
-{
- addDirectory(m_newProjectDir);
- addDirectory(contentDir());
- addDirectory(sourceDir());
- addDirectory(importDir());
- addDirectory(assetDir());
- addDirectory(assetImportDir());
- addFile(contentDir().pathAppended(FILENAME_APPMAINQML));
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopy()
-{
- FilePaths rootFiles = m_projectDir.dirEntries({m_rootDirFiles, QDir::Files});
- for (const FilePath &file : rootFiles) {
- addFile(file, m_newProjectDir.pathAppended(file.fileName()));
- }
-
- prepareCopyDirFiles(m_projectDir, contentDir());
-
- FilePaths subDirs = m_projectDir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot);
- for (FilePath &subDir : subDirs) {
- if (subDir.fileName() == DIRNAME_IMPORT) {
- prepareCopyDirTree(subDir, importDir());
- }
- else if (subDir.fileName() == DIRNAME_CPP) {
- prepareCopyDirTree(subDir, sourceDir());
- }
- else if (subDir.fileName() == DIRNAME_ASSET) {
- prepareCopyDirTree(subDir, assetDir());
- }
- else if (subDir.fileName() == DIRNAME_ASSETIMPORT) {
- prepareCopyDirTree(subDir, assetImportDir());
- }
- else {
- prepareCopyDirTree(subDir, contentDir().pathAppended(subDir.fileName()));
- }
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopyDirFiles(const FilePath &dir, const FilePath &targetDir)
-{
- FilePaths dirFiles = dir.dirEntries(QDir::Files);
- for (FilePath file : dirFiles) {
- if (!isFileBlacklisted(file))
- addFile(file, targetDir.pathAppended(file.fileName()));
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopyDirTree(const FilePath &dir, const FilePath &targetDir)
-{
- prepareCopyDirFiles(dir, targetDir);
- FilePaths subDirs = dir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot);
- for (FilePath &subDir : subDirs) {
- if (isDirBlacklisted(subDir))
- continue;
- addDirectory(targetDir.pathAppended(subDir.fileName()));
- prepareCopyDirFiles(subDir, targetDir.pathAppended(subDir.fileName()));
- prepareCopyDirTree(subDir, targetDir.pathAppended(subDir.fileName()));
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::addDirectory(const Utils::FilePath &target)
-{
- return addObject(ProjectConverterObjectType::Directory, FilePath(), target);
-}
-
-bool CmakeProjectConverter::addFile(const Utils::FilePath &target)
-{
- return addFile(FilePath(), target);
-}
-
-bool CmakeProjectConverter::addFile(const Utils::FilePath &original, const Utils::FilePath &target)
-{
- addDirectory(target.parentDir());
- return addObject(ProjectConverterObjectType::File, original, target);
-}
-
-bool CmakeProjectConverter::addObject(ProjectConverterObjectType type,
- const Utils::FilePath &original, const Utils::FilePath &target)
-{
- if (target.isChildOf(m_projectDir))
- return false;
-
- if (!target.isChildOf(m_newProjectDir) &&
- ((type == ProjectConverterObjectType::Directory) && (target != m_newProjectDir))) {
- return false;
- }
-
- for (ProjectConverterObject &o : m_converterObjects) {
- if (o.target == target)
- return false;
- }
-
- ProjectConverterObject object;
- object.type = type;
- object.target = target;
- object.original = original;
-
- m_converterObjects.append(object);
-
- return true;
-}
-
-bool CmakeProjectConverter::createPreparedProject()
-{
- for (ProjectConverterObject &pco : m_converterObjects) {
- if (pco.type == ProjectConverterObjectType::Directory) {
- pco.target.createDir();
- }
- else if (pco.type == ProjectConverterObjectType::File) {
- if (pco.original.isEmpty()) {
- QFile newFile(pco.target.toString());
- newFile.open(QIODevice::WriteOnly);
- newFile.close();
- }
- else {
- pco.original.copyFile(pco.target);
- }
- }
- }
-
- return true;
-}
-
-const FilePath CmakeProjectConverter::contentDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_CONTENT);
-}
-
-const FilePath CmakeProjectConverter::sourceDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_CPP);
-}
-
-const FilePath CmakeProjectConverter::importDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_IMPORT);
-}
-
-const FilePath CmakeProjectConverter::assetDir() const
-{
- return contentDir().pathAppended(DIRNAME_ASSET);
-}
-
-const FilePath CmakeProjectConverter::assetImportDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_ASSETIMPORT);
-}
-
-const FilePath CmakeProjectConverter::newProjectFile() const
-{
- return m_newProjectDir.pathAppended(m_project->projectFilePath().fileName());
-}
-
-const FilePath CmakeProjectConverter::projectMainFile() const
-{
- auto *target = m_project->activeTarget();
- if (target && target->buildSystem()) {
- auto buildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
- if (buildSystem) {
- return buildSystem->mainFilePath();
- }
- }
- return {};
-}
-
-const QString CmakeProjectConverter::projectMainClass() const
-{
- return projectMainFile().baseName();
-}
-
-bool CmakeProjectConverter::modifyNewFiles()
-{
- return modifyAppMainQml() && modifyProjectFile();
-}
-
-const char APPMAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectappmainqml.tpl";
-
-bool CmakeProjectConverter::modifyAppMainQml()
-{
- QString appMainQmlPath = contentDir().pathAppended(FILENAME_APPMAINQML).toString();
- QFile appMainQml(appMainQmlPath);
- appMainQml.open(QIODevice::ReadWrite);
- if (!appMainQml.isOpen())
- return false;
-
- QString templateContent = GenerateCmake::readTemplate(APPMAIN_QMLFILE_TEMPLATE_PATH);
- QString appMainQmlContent = templateContent.arg(projectMainClass());
-
- appMainQml.reset();
- appMainQml.write(appMainQmlContent.toUtf8());
- appMainQml.close();
-
- return true;
-}
-
-bool CmakeProjectConverter::modifyProjectFile()
-{
- QString projectFileName = m_project->projectFilePath().fileName();
- FilePath projectFilePath = m_newProjectDir.pathAppended(projectFileName);
- QFile projectFile(projectFilePath.toString());
- projectFile.open(QIODevice::ReadOnly);
- if (!projectFile.isOpen())
- return false;
- QString projectFileContent = QString::fromUtf8(projectFile.readAll());
- projectFile.close();
-
- const QRegularExpression mainFilePattern("^\\s*mainFile:\\s*\".*\"", QRegularExpression::MultilineOption);
- const QString mainFileString(" mainFile: \"content/App.qml\"");
-
- projectFileContent.replace(mainFilePattern, mainFileString);
-
- projectFile.open(QIODevice::WriteOnly|QIODevice::Truncate);
- if (!projectFile.isOpen())
- return false;
- projectFile.write(projectFileContent.toUtf8());
- projectFile.close();
-
- return true;
-}
-
-} //GenerateCmake
-} //QmlDesigner
diff --git a/src/plugins/qmldesigner/cmakeprojectconverter.h b/src/plugins/qmldesigner/cmakeprojectconverter.h
deleted file mode 100644
index c5f4361cb11..00000000000
--- a/src/plugins/qmldesigner/cmakeprojectconverter.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#ifndef CMAKEPROJECTCONVERTER_H
-#define CMAKEPROJECTCONVERTER_H
-
-#include <utils/fileutils.h>
-#include <qmlprojectmanager/qmlproject.h>
-
-namespace QmlDesigner {
-
-namespace GenerateCmake {
-
-enum ProjectConverterObjectType {
- File,
- Directory
-};
-
-struct ProjectConverterObject {
- ProjectConverterObjectType type;
- Utils::FilePath target;
- Utils::FilePath original;
-};
-
-class CmakeProjectConverter {
-
-public:
- bool convertProject(const QmlProjectManager::QmlProject *project,
- const Utils::FilePath &targetDir);
- static void generateMenuEntry();
- static void onConvertProject();
- static bool isProjectConvertable(const ProjectExplorer::Project *project);
- static bool isProjectCurrentFormat(const ProjectExplorer::Project *project);
-
-private:
- bool prepareAndExecute();
- bool isFileBlacklisted(const Utils::FilePath &file) const;
- bool isDirBlacklisted(const Utils::FilePath &dir) const;
- bool performSanityCheck();
- bool prepareBaseDirectoryStructure();
- bool prepareCopyDirFiles(const Utils::FilePath &dir, const Utils::FilePath &targetDir);
- bool prepareCopyDirTree(const Utils::FilePath &dir, const Utils::FilePath &targetDir);
- bool prepareCopy();
- bool addDirectory(const Utils::FilePath &target);
- bool addFile(const Utils::FilePath &target);
- bool addFile(const Utils::FilePath &original, const Utils::FilePath &target);
- bool addObject(ProjectConverterObjectType type,
- const Utils::FilePath &original, const Utils::FilePath &target);
- bool createPreparedProject();
-
- const Utils::FilePath contentDir() const;
- const Utils::FilePath sourceDir() const;
- const Utils::FilePath importDir() const;
- const Utils::FilePath assetDir() const;
- const Utils::FilePath assetImportDir() const;
- const Utils::FilePath newProjectFile() const;
-
- const QString environmentVariable(const QString &key) const;
- const Utils::FilePath projectMainFile() const;
- const QString projectMainClass() const;
- bool modifyNewFiles();
- bool modifyAppMainQml();
- bool modifyProjectFile();
-
-private:
- QList<ProjectConverterObject> m_converterObjects;
- QStringList m_rootDirFiles;
- Utils::FilePath m_projectDir;
- Utils::FilePath m_newProjectDir;
- const QmlProjectManager::QmlProject *m_project;
- QString m_errorText;
-};
-
-} //GenerateCmake
-} //QmlDesigner
-
-#endif // CMAKEPROJECTCONVERTER_H
diff --git a/src/plugins/qmldesigner/cmakeprojectconverterdialog.cpp b/src/plugins/qmldesigner/cmakeprojectconverterdialog.cpp
deleted file mode 100644
index 1c15043779c..00000000000
--- a/src/plugins/qmldesigner/cmakeprojectconverterdialog.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cmakeprojectconverterdialog.h"
-
-#include <coreplugin/documentmanager.h>
-
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QFormLayout>
-#include <QGroupBox>
-#include <QLabel>
-#include <QLayout>
-#include <QPushButton>
-#include <QRegularExpression>
-
-using namespace Utils;
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-
-const QRegularExpression projectNameRegexp("^(?!(import))(?!(QtQml))(?!(QtQuick))(?:[A-Z][a-zA-Z0-9-_]*)$");
-
-static bool projectNameValidationFunction(FancyLineEdit *editor, QString *)
-{
- return editor->text().count(projectNameRegexp);
-}
-
-static bool dirValidationFunction(FancyLineEdit *editor, QString *)
-{
- return FilePath::fromString(editor->text()).isWritableDir();
-}
-
-const QString EXPLANATION_TEXT = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "This process creates a copy of the existing project. The new project's folder structure is adjusted for CMake build process and necessary related new files are generated.\n\nThe new project can be opened in Qt Creator using the main CMakeLists.txt file.");
-
-const QString PROJECT_NAME_LABEL = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Name:");
-
-const QString PARENT_DIR_LABEL = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Create in:");
-
-CmakeProjectConverterDialog::CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject)
- : QDialog()
-{
- const FilePath defaultDir = Core::DocumentManager::projectsDirectory();
- const QString defaultName = uniqueProjectName(defaultDir, oldProject->displayName());
-
- QLabel *mainLabel = new QLabel(EXPLANATION_TEXT, this);
- mainLabel->setWordWrap(true);
-
- mainLabel->setMargin(20);
- mainLabel->setMinimumWidth(600);
-
- m_errorLabel = new InfoLabel();
- m_errorLabel->setType(InfoLabel::InfoType::None);
-
- m_nameEditor = new FancyLineEdit();
- m_nameEditor->setValidationFunction(projectNameValidationFunction);
- m_nameEditor->setText(defaultName);
-
- m_dirSelector = new PathChooser();
- m_dirSelector->setExpectedKind(PathChooser::Directory);
- m_dirSelector->setValidationFunction(dirValidationFunction);
- m_dirSelector->setPath(defaultDir.toString());
-
- QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
- m_okButton = buttons->button(QDialogButtonBox::Ok);
- m_okButton->setDefault(true);
-
- connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(m_nameEditor, &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged);
- connect(m_dirSelector->lineEdit(), &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged);
-
- QGroupBox *form = new QGroupBox();
- QFormLayout *formLayout = new QFormLayout(form);
- formLayout->addRow(PROJECT_NAME_LABEL, m_nameEditor);
- formLayout->addRow(PARENT_DIR_LABEL, m_dirSelector);
-
- QVBoxLayout *dialogLayout = new QVBoxLayout(this);
- dialogLayout->addWidget(mainLabel);
- dialogLayout->addWidget(form);
- dialogLayout->addWidget(m_errorLabel);
- dialogLayout->addWidget(buttons);
-
- pathValidChanged();
-}
-
-void CmakeProjectConverterDialog::pathValidChanged()
-{
- bool valid = isValid();
-
- if (valid) {
- m_newProjectDir = FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text());
- }
- else {
- m_newProjectDir = FilePath();
- }
-
- const QString error = errorText();
- m_errorLabel->setType(error.isEmpty() ? InfoLabel::None : InfoLabel::Warning);
- m_errorLabel->setText(error);
- m_okButton->setEnabled(valid);
-}
-
-const FilePath CmakeProjectConverterDialog::newPath() const
-{
- return m_newProjectDir;
-}
-
-const QStringList blackListedStarts = {"import","QtQml","QtQuick"};
-
-const QString CmakeProjectConverterDialog::startsWithBlacklisted(const QString &text) const
-{
- for (const QString &badWord : blackListedStarts) {
- if (text.startsWith(badWord))
- return badWord;
- }
-
- return {};
-}
-
-const QString ERROR_TEXT_NAME_EMPTY = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Name is empty.");
-const QString ERROR_TEXT_NAME_BAD_START = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Name must not start with \"%1\".");
-const QString ERROR_TEXT_NAME_LOWERCASE_START = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Name must begin with a capital letter");
-const QString ERROR_TEXT_NAME_BAD_CHARACTERS = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Name must contain only letters, numbers or characters - _.");
-
-const QString ERROR_DIR_NOT_DIR = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Target is not a directory.");
-const QString ERROR_DIR_NOT_WRITABLE = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Cannot write to target directory.");
-const QString ERROR_DIR_EXISTS = QCoreApplication::translate(
- "QmlDesigner::CmakeProjectConverterDialog",
- "Project directory already exists.");
-
-const QString CmakeProjectConverterDialog::errorText() const
-{
- QString text;
-
- if (!m_nameEditor->isValid()) {
- QString name = m_nameEditor->text();
-
- if (name.isEmpty())
- return ERROR_TEXT_NAME_EMPTY;
-
- const QString badStart = startsWithBlacklisted(text);
- if (!badStart.isEmpty())
- return ERROR_TEXT_NAME_BAD_START.arg(badStart);
-
- if (name[0].isLower())
- return ERROR_TEXT_NAME_LOWERCASE_START;
-
- return ERROR_TEXT_NAME_BAD_CHARACTERS;
-
- }
-
- if (!m_dirSelector->isValid()) {
- FilePath path = m_dirSelector->filePath();
- if (!path.isDir())
- return ERROR_DIR_NOT_DIR;
- if (!path.isWritableDir())
- return ERROR_DIR_NOT_WRITABLE;
- }
-
- if (FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text()).exists())
- return ERROR_DIR_EXISTS;
-
-
- return text;
-}
-
-const QString CmakeProjectConverterDialog::uniqueProjectName(const FilePath &dir, const QString &oldName) const
-{
- for (unsigned i = 0; ; ++i) {
- QString name = oldName;
- if (i)
- name += QString::number(i);
- if (!dir.pathAppended(name).exists())
- return name;
- }
- return oldName;
-}
-
-bool CmakeProjectConverterDialog::isValid()
-{
- FilePath newPath = FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text());
- return m_dirSelector->isValid() && m_nameEditor->isValid() && !newPath.exists();
-}
-
-} //GenerateCmake
-} //QmlDesigner
diff --git a/src/plugins/qmldesigner/cmakeprojectconverterdialog.h b/src/plugins/qmldesigner/cmakeprojectconverterdialog.h
deleted file mode 100644
index a3143de7cd8..00000000000
--- a/src/plugins/qmldesigner/cmakeprojectconverterdialog.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-
-#ifndef CMAKEPROJECTCONVERTERDIALOG_H
-#define CMAKEPROJECTCONVERTERDIALOG_H
-
-#include <qmlprojectmanager/qmlproject.h>
-#include <utils/fancylineedit.h>
-#include <utils/filepath.h>
-#include <utils/infolabel.h>
-#include <utils/pathchooser.h>
-
-#include <QDialog>
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-
-class CmakeProjectConverterDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject);
- const Utils::FilePath newPath() const;
-
-public slots:
- void pathValidChanged();
-
-private:
- const QString startsWithBlacklisted(const QString &text) const;
- const QString errorText() const;
- const QString uniqueProjectName(const Utils::FilePath &dir, const QString &oldName) const;
- bool isValid();
-
-private:
- Utils::FilePath m_newProjectDir;
- Utils::FancyLineEdit *m_nameEditor;
- Utils::PathChooser *m_dirSelector;
- Utils::InfoLabel *m_errorLabel;
- QPushButton *m_okButton;
-};
-
-} //GenerateCmake
-} //Qmldesigner
-
-#endif // CMAKEPROJECTCONVERTERDIALOG_H
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp
index 390eca63653..d222f2cacc8 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp
@@ -84,12 +84,7 @@ WidgetInfo AssetsLibraryView::widgetInfo()
imageCacheData()->synchronousFontImageCache};
}
- return createWidgetInfo(m_widget.data(),
- new WidgetInfo::ToolBarWidgetDefaultFactory<AssetsLibraryWidget>(m_widget.data()),
- "Assets",
- WidgetInfo::LeftPane,
- 0,
- tr("Assets"));
+ return createWidgetInfo(m_widget.data(), "Assets", WidgetInfo::LeftPane, 0, tr("Assets"));
}
void AssetsLibraryView::modelAttached(Model *model)
diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp
index 5b9c54b4d41..6cf747e9d5d 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp
+++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp
@@ -103,7 +103,7 @@ TextEditor::AssistInterface *BindingEditorWidget::createAssistInterface(
{
Q_UNUSED(assistKind)
return new QmlJSEditor::QmlJSCompletionAssistInterface(
- document(), position(), Utils::FilePath(),
+ textCursor(), Utils::FilePath(),
assistReason, qmljsdocument->semanticInfo());
}
diff --git a/src/plugins/qmldesigner/components/componentcore/addsignalhandlerdialog.cpp b/src/plugins/qmldesigner/components/componentcore/addsignalhandlerdialog.cpp
index d6f4871dfa4..2974bea53e9 100644
--- a/src/plugins/qmldesigner/components/componentcore/addsignalhandlerdialog.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/addsignalhandlerdialog.cpp
@@ -73,7 +73,7 @@ bool checkForPropertyChanges(const QString &signal)
void AddSignalHandlerDialog::updateComboBox()
{
m_ui->comboBox->clear();
- foreach (const QString &signal, m_signals) {
+ for (const QString &signal : qAsConst(m_signals)) {
if (m_ui->all->isChecked()) {
m_ui->comboBox->addItem(signal);
} else if (m_ui->properties->isChecked()) {
diff --git a/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp b/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
index 86f96cb1aa8..728c6574cdd 100644
--- a/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
@@ -39,7 +39,9 @@ static QString styleConfigFileName(const QString &qmlFileName)
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(Utils::FilePath::fromString(qmlFileName));
if (currentProject) {
- foreach (const Utils::FilePath &fileName, currentProject->files(ProjectExplorer::Project::SourceFiles))
+ const QList<Utils::FilePath> fileNames = currentProject->files(
+ ProjectExplorer::Project::SourceFiles);
+ for (const Utils::FilePath &fileName : fileNames)
if (fileName.endsWith("qtquickcontrols2.conf"))
return fileName.toString();
}
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index a0bd7a23896..8dc52ad6303 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -129,11 +129,13 @@ void DesignerActionManager::polishActions() const
Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR);
Core::Context qmlDesignerEditor3DContext(Constants::C_QMLEDITOR3D);
Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR);
+ Core::Context qmlDesignerMaterialBrowserContext(Constants::C_QMLMATERIALBROWSER);
Core::Context qmlDesignerUIContext;
qmlDesignerUIContext.add(qmlDesignerFormEditorContext);
qmlDesignerUIContext.add(qmlDesignerEditor3DContext);
qmlDesignerUIContext.add(qmlDesignerNavigatorContext);
+ qmlDesignerUIContext.add(qmlDesignerMaterialBrowserContext);
for (auto *action : actions) {
if (!action->menuId().isEmpty()) {
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
index 65da49ed6b5..db85dcb0ad0 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
@@ -178,7 +178,8 @@ void DesignerActionManagerView::setupContext(SelectionContext::UpdateMode update
}
SelectionContext selectionContext(this);
selectionContext.setUpdateMode(updateMode);
- foreach (ActionInterface* action, m_designerActionManager.designerActions()) {
+ const QList<ActionInterface *> actions = m_designerActionManager.designerActions();
+ for (ActionInterface *action : actions) {
action->currentContextChanged(selectionContext);
}
m_setupContextDirty = false;
diff --git a/src/plugins/qmldesigner/components/componentcore/findimplementation.cpp b/src/plugins/qmldesigner/components/componentcore/findimplementation.cpp
index d0a1bca4fd6..3a9e81eef9e 100644
--- a/src/plugins/qmldesigner/components/componentcore/findimplementation.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/findimplementation.cpp
@@ -290,8 +290,8 @@ QList<QmlJSEditor::FindReferences::Usage> FindImplementation::run(const QString
FindImplementationVisitor visitor(document, context);
- FindImplementationVisitor::Results results = visitor(typeName, itemName, targetValue);
- foreach (const SourceLocation &location, results) {
+ const FindImplementationVisitor::Results results = visitor(typeName, itemName, targetValue);
+ for (const SourceLocation &location : results) {
usages.append(QmlJSEditor::FindReferences::Usage(fileName,
matchingLine(location.offset, document->source()),
location.startLine, location.startColumn - 1, location.length));
diff --git a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
index 439faec59d1..b44c4daf670 100644
--- a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
@@ -103,7 +103,7 @@ static int lowerBound(int i)
static inline QPointF getUpperLeftPosition(const QList<ModelNode> &modelNodeList)
{
QPointF postion(std::numeric_limits<qreal>::max(), std::numeric_limits<qreal>::max());
- foreach (const ModelNode &modelNode, modelNodeList) {
+ for (const ModelNode &modelNode : modelNodeList) {
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
QmlItemNode qmlIitemNode = QmlItemNode(modelNode);
if (qmlIitemNode.instancePosition().x() < postion.x())
@@ -122,18 +122,20 @@ static void setUpperLeftPostionToNode(const ModelNode &layoutNode, const QList<M
layoutNode.variantProperty("y").setValue(qRound(upperLeftPosition.y()));
}
-void LayoutInGridLayout::reparentToNodeAndRemovePositionForModelNodes(const ModelNode &parentModelNode,
- const QList<ModelNode> &modelNodeList)
+void LayoutInGridLayout::reparentToNodeAndRemovePositionForModelNodes(
+ const ModelNode &parentModelNode, const QList<ModelNode> &modelNodeList)
{
- foreach (ModelNode modelNode, modelNodeList) {
+ for (ModelNode modelNode : modelNodeList) {
reparentTo(modelNode, parentModelNode);
modelNode.removeProperty("x");
modelNode.removeProperty("y");
- foreach (const VariantProperty &variantProperty, modelNode.variantProperties()) {
+ const QList<VariantProperty> variantProperties = modelNode.variantProperties();
+ for (const VariantProperty &variantProperty : variantProperties) {
if (variantProperty.name().contains("anchors."))
modelNode.removeProperty(variantProperty.name());
}
- foreach (const BindingProperty &bindingProperty, modelNode.bindingProperties()) {
+ const QList<BindingProperty> bindingProperties = modelNode.bindingProperties();
+ for (const BindingProperty &bindingProperty : bindingProperties) {
if (bindingProperty.name().contains("anchors."))
modelNode.removeProperty(bindingProperty.name());
}
@@ -142,7 +144,7 @@ void LayoutInGridLayout::reparentToNodeAndRemovePositionForModelNodes(const Mode
void LayoutInGridLayout::setSizeAsPreferredSize(const QList<ModelNode> &modelNodeList)
{
- foreach (ModelNode modelNode, modelNodeList) {
+ for (ModelNode modelNode : modelNodeList) {
if (modelNode.hasVariantProperty("width")) {
modelNode.variantProperty("Layout.preferredWidth").setValue(modelNode.variantProperty("width").value());
modelNode.removeProperty("width");
@@ -249,7 +251,8 @@ int LayoutInGridLayout::rowCount() const
void LayoutInGridLayout::collectItemNodes()
{
- foreach (const ModelNode &modelNode, m_selectionContext.selectedModelNodes()) {
+ const QList<ModelNode> modelNodes = m_selectionContext.selectedModelNodes();
+ for (const ModelNode &modelNode : modelNodes) {
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
QmlItemNode itemNode = modelNode;
if (itemNode.instanceSize().width() > 0
@@ -267,7 +270,7 @@ void LayoutInGridLayout::collectItemNodes()
void LayoutInGridLayout::collectOffsets()
{
//We collect all different x and y offsets that define the cells
- foreach (const QmlItemNode &qmlItemNode, m_qmlItemNodes) {
+ for (const QmlItemNode &qmlItemNode : qAsConst(m_qmlItemNodes)) {
int x = qRound((qmlItemNode.instancePosition().x()));
m_xTopOffsets.append(x);
x = qRound((qmlItemNode.instancePosition().x() + lowerBound(qmlItemNode.instanceBoundingRect().width())));
@@ -303,7 +306,7 @@ void LayoutInGridLayout::calculateGridOffsets()
int heightTolerance = defaultHeightTolerance;
//The tolerance cannot be bigger then the size of an item
- foreach (const auto &qmlItemNode, m_qmlItemNodes) {
+ for (const auto &qmlItemNode : qAsConst(m_qmlItemNodes)) {
widthTolerance = qMin(qmlItemNode.instanceSize().toSize().width() - 1, widthTolerance);
heightTolerance = qMin(qmlItemNode.instanceSize().toSize().height() - 1, heightTolerance);
}
@@ -340,7 +343,7 @@ void LayoutInGridLayout::removeEmtpyRowsAndColumns()
m_columns = QVector<bool>(columnCount());
m_columns.fill(false);
- foreach (const auto &qmlItemNode, m_qmlItemNodes) {
+ for (const auto &qmlItemNode : qAsConst(m_qmlItemNodes)) {
int xCell = getCell(m_xTopOffsets, qmlItemNode.instancePosition().x());
int yCell = getCell(m_yTopOffsets, qmlItemNode.instancePosition().y());
@@ -372,7 +375,7 @@ void LayoutInGridLayout::initializeCells()
void LayoutInGridLayout::markUsedCells()
{
//We mark cells which are covered by items with true
- foreach (const auto &qmlItemNode, m_qmlItemNodes) {
+ for (const auto &qmlItemNode : qAsConst(m_qmlItemNodes)) {
int xCell = getCell(m_xTopOffsets, qmlItemNode.instancePosition().x());
int yCell = getCell(m_yTopOffsets, qmlItemNode.instancePosition().y());
@@ -391,7 +394,7 @@ void LayoutInGridLayout::fillEmptyCells()
//Cells which are not covered by items and are not marked as true have to be filled with a "spacer" item
m_layoutedNodes = m_selectionContext.selectedModelNodes();
- foreach (const QmlItemNode &itemNode, m_qmlItemNodes) {
+ for (const auto &itemNode : qAsConst(m_qmlItemNodes)) {
m_layoutedNodes.append(itemNode);
}
@@ -431,7 +434,7 @@ void LayoutInGridLayout::setSpanning(const ModelNode &layoutNode)
layoutNode.variantProperty("columns").setValue(columnCount());
layoutNode.variantProperty("rows").setValue(rowCount());
- foreach (const ModelNode &modelNode, m_layoutedNodes) {
+ for (const ModelNode &modelNode : qAsConst(m_layoutedNodes)) {
QmlItemNode qmlItemNode(modelNode);
int xCell = getCell(m_xTopOffsets, qmlItemNode.instancePosition().x());
int yCell = getCell(m_yTopOffsets, qmlItemNode.instancePosition().y());
@@ -461,7 +464,7 @@ void LayoutInGridLayout::setSpanning(const ModelNode &layoutNode)
void LayoutInGridLayout::removeSpacersBySpanning(QList<ModelNode> &nodes)
{
- foreach (const ModelNode &node, m_spacerNodes) {
+ for (const ModelNode &node : qAsConst(m_spacerNodes)) {
if (int index = nodes.indexOf(node)) {
ModelNode before = nodes.at(index -1);
if (m_spacerNodes.contains(before)) {
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu.cpp
index c0dea6b3c5b..2df447f0dae 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu.cpp
@@ -41,19 +41,18 @@ ModelNodeContextMenu::ModelNodeContextMenu(AbstractView *view) :
{
}
-static QSet<ActionInterface* > findMembers(QSet<ActionInterface* > actionInterface,
- const QByteArray &category)
+static QSet<ActionInterface *> findMembers(const QSet<ActionInterface *> actionInterface,
+ const QByteArray &category)
{
- QSet<ActionInterface* > ret;
+ QSet<ActionInterface *> ret;
- foreach (ActionInterface* factory, actionInterface) {
- if (factory->category() == category)
- ret.insert(factory);
- }
- return ret;
+ for (ActionInterface *factory : actionInterface) {
+ if (factory->category() == category)
+ ret.insert(factory);
+ }
+ return ret;
}
-
void populateMenu(QSet<ActionInterface* > &actionInterfaces,
const QByteArray &category,
QMenu* menu,
@@ -68,7 +67,7 @@ void populateMenu(QSet<ActionInterface* > &actionInterfaces,
return l->priority() > r->priority();
});
- foreach (ActionInterface* actionInterface, matchingFactoriesList) {
+ for (ActionInterface* actionInterface : qAsConst(matchingFactoriesList)) {
if (actionInterface->type() == ActionInterface::ContextMenu) {
actionInterface->currentContextChanged(selectionContext);
QMenu *newMenu = actionInterface->action()->menu();
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
index 975a59d478d..19c83ac7801 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
@@ -54,7 +54,7 @@ static inline bool itemsHaveSameParent(const QList<ModelNode> &siblingList)
if (!parent.isValid())
return false;
- foreach (const ModelNode &node, siblingList) {
+ for (const ModelNode &node : siblingList) {
QmlItemNode currentItem(node);
if (!currentItem.isValid())
return false;
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index 11e052b1dd3..068e9cf2fd8 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -115,7 +115,7 @@ static inline void reparentTo(const ModelNode &node, const QmlItemNode &parent)
static inline QPointF getUpperLeftPosition(const QList<ModelNode> &modelNodeList)
{
QPointF postion(std::numeric_limits<qreal>::max(), std::numeric_limits<qreal>::max());
- foreach (const ModelNode &modelNode, modelNodeList) {
+ for (const ModelNode &modelNode : modelNodeList) {
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
QmlItemNode qmlIitemNode = QmlItemNode(modelNode);
if (qmlIitemNode.instancePosition().x() < postion.x())
@@ -152,7 +152,8 @@ void deSelect(const SelectionContext &selectionState)
{
if (selectionState.view()) {
QList<ModelNode> selectedNodes = selectionState.view()->selectedModelNodes();
- foreach (const ModelNode &node, selectionState.selectedModelNodes()) {
+ const QList<ModelNode> nodes = selectionState.selectedModelNodes();
+ for (const ModelNode &node : nodes) {
if (selectedNodes.contains(node))
selectedNodes.removeAll(node);
}
@@ -311,7 +312,8 @@ void resetSize(const SelectionContext &selectionState)
return;
selectionState.view()->executeInTransaction("DesignerActionManager|resetSize",[selectionState](){
- foreach (ModelNode node, selectionState.selectedModelNodes()) {
+ const QList<ModelNode> nodes = selectionState.selectedModelNodes();
+ for (const ModelNode &node : nodes) {
QmlItemNode itemNode(node);
if (itemNode.isValid()) {
itemNode.removeProperty("width");
@@ -327,7 +329,8 @@ void resetPosition(const SelectionContext &selectionState)
return;
selectionState.view()->executeInTransaction("DesignerActionManager|resetPosition",[selectionState](){
- foreach (ModelNode node, selectionState.selectedModelNodes()) {
+ const QList<ModelNode> nodes = selectionState.selectedModelNodes();
+ for (const ModelNode &node : nodes) {
QmlItemNode itemNode(node);
if (itemNode.isValid()) {
itemNode.removeProperty("x");
@@ -600,8 +603,8 @@ static void addSignal(const QString &typeName, const QString &itemId, const QStr
signalHandlerName = "on" + toUpper(signalName).toUtf8();
else
signalHandlerName = itemId.toUtf8() + ".on" + toUpper(signalName).toUtf8();
-
- foreach (const ModelNode &modelNode, rewriterView.allModelNodes()) {
+ const QList<ModelNode> nodes = rewriterView.allModelNodes();
+ for (const ModelNode &modelNode : nodes) {
if (modelNode.type() == typeName.toUtf8()) {
modelNode.signalHandlerProperty(signalHandlerName).setSource(QLatin1String("{\n}"));
}
@@ -612,7 +615,7 @@ static QStringList cleanSignalNames(const QStringList &input)
{
QStringList output;
- foreach (const QString &signal, input)
+ for (const QString &signal : input)
if (!signal.startsWith(QLatin1String("__")) && !output.contains(signal))
output.append(signal);
@@ -625,11 +628,13 @@ static QStringList getSortedSignalNameList(const ModelNode &modelNode)
QStringList signalNames;
if (metaInfo.isValid()) {
- foreach (const PropertyName &signalName, sortedPropertyNameList(metaInfo.signalNames()))
+ const PropertyNameList signalNameList = sortedPropertyNameList(metaInfo.signalNames());
+ for (const PropertyName &signalName : signalNameList)
if (!signalName.contains("Changed"))
signalNames.append(QString::fromUtf8(signalName));
- foreach (const PropertyName &propertyName, sortedPropertyNameList(metaInfo.propertyNames()))
+ const PropertyNameList propertyNameList = sortedPropertyNameList(metaInfo.propertyNames());
+ for (const PropertyName &propertyName : propertyNameList)
if (!propertyName.contains("."))
signalNames.append(QString::fromUtf8(propertyName + "Changed"));
}
@@ -741,7 +746,8 @@ void removeLayout(const SelectionContext &selectionContext)
return;
selectionContext.view()->executeInTransaction("DesignerActionManager|removeLayout", [selectionContext, &layoutItem, parent](){
- foreach (const ModelNode &modelNode, selectionContext.currentSingleSelectedNode().directSubModelNodes()) {
+ const QList<ModelNode> modelNodes = selectionContext.currentSingleSelectedNode().directSubModelNodes();
+ for (const ModelNode &modelNode : modelNodes) {
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
QmlItemNode qmlItem(modelNode);
diff --git a/src/plugins/qmldesigner/components/componentcore/theme.h b/src/plugins/qmldesigner/components/componentcore/theme.h
index d8853cc7906..7707cdeb12b 100644
--- a/src/plugins/qmldesigner/components/componentcore/theme.h
+++ b/src/plugins/qmldesigner/components/componentcore/theme.h
@@ -130,6 +130,8 @@ public:
listView,
lockOff,
lockOn,
+ materialPreviewEnvironment,
+ materialPreviewModel,
mergeCells,
minus,
mirror,
diff --git a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp
index 402023b8289..7528daa5608 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp
@@ -105,7 +105,8 @@ void BackendModel::resetModel()
}
if (rootNode.isValid()) {
- foreach (const AbstractProperty &property ,rootNode.properties())
+ const QList<AbstractProperty> properties = rootNode.properties();
+ for (const AbstractProperty &property : properties)
if (property.isDynamic() && !simpleTypes.contains(property.dynamicTypeName())) {
NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo(property.dynamicTypeName());
@@ -147,7 +148,8 @@ QStringList BackendModel::possibleCppTypes() const
QStringList list;
if (rewriterView) {
- foreach (const QmlTypeData &cppTypeData, rewriterView->getQMLTypes())
+ const QList<QmlTypeData> cppTypes = rewriterView->getQMLTypes();
+ for (const QmlTypeData &cppTypeData : cppTypes)
list.append(cppTypeData.typeName);
}
diff --git a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
index 9de20eb74d9..03c08f96c46 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
@@ -139,7 +139,8 @@ QStringList BindingModel::possibleTargetProperties(const BindingProperty &bindin
if (metaInfo.isValid()) {
QStringList possibleProperties;
- foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
+ const QList<PropertyName> propertyNames = metaInfo.propertyNames();
+ for (const PropertyName &propertyName : propertyNames) {
if (metaInfo.propertyIsWritable(propertyName))
possibleProperties << QString::fromUtf8(propertyName);
}
@@ -232,7 +233,8 @@ static PropertyName unusedProperty(const ModelNode &modelNode)
{
PropertyName propertyName = "none";
if (modelNode.metaInfo().isValid()) {
- foreach (const PropertyName &propertyName, modelNode.metaInfo().propertyNames()) {
+ const QList<PropertyName> propertyNames = modelNode.metaInfo().propertyNames();
+ for (const PropertyName &propertyName : propertyNames) {
if (modelNode.metaInfo().propertyIsWritable(propertyName) && !modelNode.hasProperty(propertyName))
return propertyName;
}
@@ -305,7 +307,8 @@ void BindingModel::updateBindingProperty(int rowNumber)
void BindingModel::addModelNode(const ModelNode &modelNode)
{
- foreach (const BindingProperty &bindingProperty, modelNode.bindingProperties()) {
+ const QList<BindingProperty> bindingProperties = modelNode.bindingProperties();
+ for (const BindingProperty &bindingProperty : bindingProperties) {
addBindingProperty(bindingProperty);
}
}
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
index 6737d66d18d..b174cafe6db 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
@@ -35,6 +35,10 @@
#include <nodeabstractproperty.h>
#include <variantproperty.h>
#include <signalhandlerproperty.h>
+#include <qmldesignerplugin.h>
+#include <viewmanager.h>
+
+#include <utils/qtcassert.h>
#include <QTableView>
@@ -112,7 +116,7 @@ void ConnectionView::propertiesRemoved(const QList<AbstractProperty> &propertyLi
void ConnectionView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList)
{
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
if (property.isBindingProperty()) {
bindingModel()->bindingRemoved(property.toBindingProperty());
dynamicPropertiesModel()->bindingRemoved(property.toBindingProperty());
@@ -127,7 +131,7 @@ void ConnectionView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &p
void ConnectionView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
AbstractView::PropertyChangeFlags /*propertyChange*/)
{
- foreach (const VariantProperty &variantProperty, propertyList) {
+ for (const VariantProperty &variantProperty : propertyList) {
if (variantProperty.isDynamic())
dynamicPropertiesModel()->variantPropertyChanged(variantProperty);
if (variantProperty.isDynamic() && variantProperty.parentModelNode().isRootNode())
@@ -141,7 +145,7 @@ void ConnectionView::variantPropertiesChanged(const QList<VariantProperty> &prop
void ConnectionView::bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
AbstractView::PropertyChangeFlags /*propertyChange*/)
{
- foreach (const BindingProperty &bindingProperty, propertyList) {
+ for (const BindingProperty &bindingProperty : propertyList) {
bindingModel()->bindingChanged(bindingProperty);
if (bindingProperty.isDynamic())
dynamicPropertiesModel()->bindingPropertyChanged(bindingProperty);
@@ -207,11 +211,10 @@ void ConnectionView::importsChanged(const QList<Import> & /*addedImports*/, cons
WidgetInfo ConnectionView::widgetInfo()
{
return createWidgetInfo(m_connectionViewWidget.data(),
- new WidgetInfo::ToolBarWidgetDefaultFactory<ConnectionViewWidget>(connectionViewWidget()),
QLatin1String("ConnectionView"),
WidgetInfo::LeftPane,
0,
- tr("Connection View"));
+ tr("Connections"));
}
bool ConnectionView::hasWidget() const
@@ -269,6 +272,25 @@ BackendModel *ConnectionView::backendModel() const
return m_backendModel;
}
+ConnectionView *ConnectionView::instance()
+{
+
+ static ConnectionView *s_instance = nullptr;
+
+ if (s_instance)
+ return s_instance;
+
+ const auto views = QmlDesignerPlugin::instance()->viewManager().views();
+ for (auto *view : views) {
+ ConnectionView *myView = qobject_cast<ConnectionView*>(view);
+ if (myView)
+ s_instance = myView;
+ }
+
+ QTC_ASSERT(s_instance, return nullptr);
+ return s_instance;
+}
+
} // namesapce Internal
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.h b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
index fb934ba3855..7bf3064f830 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
@@ -83,13 +83,14 @@ public:
QTableView *dynamicPropertiesTableView() const;
QTableView *backendView() const;
-protected:
+ DynamicPropertiesModel *dynamicPropertiesModel() const;
+
ConnectionViewWidget *connectionViewWidget() const;
ConnectionModel *connectionModel() const;
BindingModel *bindingModel() const;
- DynamicPropertiesModel *dynamicPropertiesModel() const;
BackendModel *backendModel() const;
+ static ConnectionView *instance();
private: //variables
QPointer<ConnectionViewWidget> m_connectionViewWidget;
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
index de64139cb91..dc230ef86c1 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
@@ -70,7 +70,7 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) :
editorForDynamic();
- setWindowTitle(tr("Connections", "Title of connection view"));
+ setWindowTitle(tr("Connections", "Title of connections window"));
ui->setupUi(this);
QStyle *style = QStyleFactory::create("fusion");
@@ -81,9 +81,9 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) :
ui->tabBar->setUsesScrollButtons(true);
ui->tabBar->setElideMode(Qt::ElideRight);
- ui->tabBar->addTab(tr("Connections", "Title of connection view"));
- ui->tabBar->addTab(tr("Bindings", "Title of connection view"));
- ui->tabBar->addTab(tr("Properties", "Title of dynamic properties view"));
+ ui->tabBar->addTab(tr("Connections", "Title of connection tab"));
+ ui->tabBar->addTab(tr("Bindings", "Title of connection tab"));
+ ui->tabBar->addTab(tr("Properties", "Title of dynamic properties tab"));
const Qt::Alignment headerAlignment = Qt::AlignLeft | Qt::AlignVCenter;
ui->connectionView->horizontalHeader()->setDefaultAlignment(headerAlignment);
diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
index db81f1bb7d8..e7252a24994 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
@@ -62,22 +62,6 @@ QString idOrTypeNameForNode(const QmlDesigner::ModelNode &modelNode)
return idLabel;
}
-QmlDesigner::PropertyName unusedProperty(const QmlDesigner::ModelNode &modelNode)
-{
- QmlDesigner::PropertyName propertyName = "property";
- int i = 0;
- if (modelNode.metaInfo().isValid()) {
- while (true) {
- const QmlDesigner::PropertyName currentPropertyName = propertyName + QString::number(i).toLatin1();
- if (!modelNode.hasProperty(currentPropertyName) && !modelNode.metaInfo().hasProperty(currentPropertyName))
- return currentPropertyName;
- i++;
- }
- }
-
- return propertyName;
-}
-
QVariant convertVariantForTypeName(const QVariant &variant, const QmlDesigner::TypeName &typeName)
{
QVariant returnValue = variant;
@@ -119,6 +103,22 @@ namespace QmlDesigner {
namespace Internal {
+QmlDesigner::PropertyName DynamicPropertiesModel::unusedProperty(const QmlDesigner::ModelNode &modelNode)
+{
+ QmlDesigner::PropertyName propertyName = "property";
+ int i = 0;
+ if (modelNode.metaInfo().isValid()) {
+ while (true) {
+ const QmlDesigner::PropertyName currentPropertyName = propertyName + QString::number(i).toLatin1();
+ if (!modelNode.hasProperty(currentPropertyName) && !modelNode.metaInfo().hasProperty(currentPropertyName))
+ return currentPropertyName;
+ i++;
+ }
+ }
+
+ return propertyName;
+}
+
DynamicPropertiesModel::DynamicPropertiesModel(ConnectionView *parent)
: QStandardItemModel(parent)
, m_connectionView(parent)
@@ -298,6 +298,9 @@ AbstractProperty DynamicPropertiesModel::abstractPropertyForRow(int rowNumber) c
const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
+ if (!connectionView()->isAttached())
+ return AbstractProperty();
+
ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
if (modelNode.isValid())
@@ -345,7 +348,8 @@ QStringList DynamicPropertiesModel::possibleTargetProperties(const BindingProper
if (metaInfo.isValid()) {
QStringList possibleProperties;
- foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
+ const QList<PropertyName> propertyNames = metaInfo.propertyNames();
+ for (const PropertyName &propertyName : propertyNames) {
if (metaInfo.propertyIsWritable(propertyName))
possibleProperties << QString::fromUtf8(propertyName);
}
@@ -401,7 +405,8 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper
if (metaInfo.isValid()) {
QStringList possibleProperties;
- foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
+ const QList<PropertyName> propertyNames = metaInfo.propertyNames();
+ for (const PropertyName &propertyName : propertyNames) {
if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check
possibleProperties << QString::fromUtf8(propertyName);
}
@@ -415,16 +420,18 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper
void DynamicPropertiesModel::deleteDynamicPropertyByRow(int rowNumber)
{
- BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
- if (bindingProperty.isValid()) {
- bindingProperty.parentModelNode().removeProperty(bindingProperty.name());
- }
+ connectionView()->executeInTransaction("DynamicPropertiesModel::deleteDynamicPropertyByRow", [this, rowNumber]() {
+ BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
+ if (bindingProperty.isValid()) {
+ bindingProperty.parentModelNode().removeProperty(bindingProperty.name());
+ }
- VariantProperty variantProperty = variantPropertyForRow(rowNumber);
+ VariantProperty variantProperty = variantPropertyForRow(rowNumber);
- if (variantProperty.isValid()) {
- variantProperty.parentModelNode().removeProperty(variantProperty.name());
- }
+ if (variantProperty.isValid()) {
+ variantProperty.parentModelNode().removeProperty(variantProperty.name());
+ }
+ });
resetModel();
}
@@ -504,12 +511,14 @@ void DynamicPropertiesModel::updateVariantProperty(int rowNumber)
void DynamicPropertiesModel::addModelNode(const ModelNode &modelNode)
{
- foreach (const BindingProperty &bindingProperty, modelNode.bindingProperties()) {
+ const QList<BindingProperty> bindingProperties = modelNode.bindingProperties();
+ for (const BindingProperty &bindingProperty : bindingProperties) {
if (bindingProperty.isDynamic())
addBindingProperty(bindingProperty);
}
- foreach (const VariantProperty &variantProperty, modelNode.variantProperties()) {
+ const QList<VariantProperty> variantProperties = modelNode.variantProperties();
+ for (const VariantProperty &variantProperty : variantProperties) {
if (variantProperty.isDynamic())
addVariantProperty(variantProperty);
}
diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h
index 3b7d0cf4231..a5b674c1f8a 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h
@@ -69,6 +69,8 @@ public:
BindingProperty replaceVariantWithBinding(const PropertyName &name, bool copyValue = false);
void resetProperty(const PropertyName &name);
+ QmlDesigner::PropertyName unusedProperty(const QmlDesigner::ModelNode &modelNode);
+
protected:
void addProperty(const QVariant &propertyValue,
const QString &propertyType,
diff --git a/src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp b/src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp
index 3e910638daf..36e577d38d7 100644
--- a/src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp
@@ -36,14 +36,16 @@
namespace QmlDesigner {
AnimationCurve::AnimationCurve()
- : m_fromData(false)
+ : m_type(AnimationCurve::ValueType::Undefined)
+ , m_fromData(false)
, m_minY(std::numeric_limits<double>::max())
, m_maxY(std::numeric_limits<double>::lowest())
, m_frames()
{}
-AnimationCurve::AnimationCurve(const std::vector<Keyframe> &frames)
- : m_fromData(false)
+AnimationCurve::AnimationCurve(AnimationCurve::ValueType type, const std::vector<Keyframe> &frames)
+ : m_type(type)
+ , m_fromData(false)
, m_minY(std::numeric_limits<double>::max())
, m_maxY(std::numeric_limits<double>::lowest())
, m_frames(frames)
@@ -51,8 +53,13 @@ AnimationCurve::AnimationCurve(const std::vector<Keyframe> &frames)
analyze();
}
-AnimationCurve::AnimationCurve(const QEasingCurve &easing, const QPointF &start, const QPointF &end)
- : m_fromData(true)
+AnimationCurve::AnimationCurve(
+ AnimationCurve::ValueType type,
+ const QEasingCurve &easing,
+ const QPointF &start,
+ const QPointF &end)
+ : m_type(type)
+ , m_fromData(true)
, m_minY(std::numeric_limits<double>::max())
, m_maxY(std::numeric_limits<double>::lowest())
, m_frames()
@@ -117,6 +124,11 @@ bool AnimationCurve::hasUnified() const
return false;
}
+AnimationCurve::ValueType AnimationCurve::valueType() const
+{
+ return m_type;
+}
+
double AnimationCurve::minimumTime() const
{
if (!m_frames.empty())
diff --git a/src/plugins/qmldesigner/components/curveeditor/animationcurve.h b/src/plugins/qmldesigner/components/curveeditor/animationcurve.h
index ba39ecd3471..1c51d05d806 100644
--- a/src/plugins/qmldesigner/components/curveeditor/animationcurve.h
+++ b/src/plugins/qmldesigner/components/curveeditor/animationcurve.h
@@ -40,11 +40,17 @@ class CurveSegment;
class AnimationCurve
{
public:
+ using ValueType = Keyframe::ValueType;
+
AnimationCurve();
- AnimationCurve(const std::vector<Keyframe> &frames);
+ AnimationCurve(ValueType type, const std::vector<Keyframe> &frames);
- AnimationCurve(const QEasingCurve &easing, const QPointF &start, const QPointF &end);
+ AnimationCurve(
+ ValueType type,
+ const QEasingCurve &easing,
+ const QPointF &start,
+ const QPointF &end);
bool isEmpty() const;
@@ -54,6 +60,8 @@ public:
bool hasUnified() const;
+ ValueType valueType() const;
+
double minimumTime() const;
double maximumTime() const;
@@ -93,6 +101,8 @@ public:
private:
void analyze();
+ ValueType m_type;
+
bool m_fromData;
double m_minY;
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp
index 217e0e0eb76..29e88e2581d 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp
@@ -42,6 +42,7 @@ namespace QmlDesigner {
CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
: QWidget(parent)
, m_infoText(nullptr)
+ , m_statusLine(nullptr)
, m_toolbar(new CurveEditorToolBar(model, this))
, m_tree(new TreeView(model, this))
, m_view(new GraphicsView(model, this))
@@ -61,10 +62,13 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
area->setWidget(splitter);
area->setWidgetResizable(true);
+ m_statusLine = new QLabel();
+
auto *box = new QVBoxLayout;
box->addWidget(m_infoText);
box->addWidget(m_toolbar);
box->addWidget(area);
+ box->addWidget(m_statusLine);
setLayout(box);
connect(m_toolbar, &CurveEditorToolBar::defaultClicked, [this]() {
@@ -89,9 +93,11 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
m_view->viewport()->update();
});
- connect(
- m_toolbar, &CurveEditorToolBar::currentFrameChanged,
- model, &CurveEditorModel::commitCurrentFrame);
+ connect(m_toolbar, &CurveEditorToolBar::currentFrameChanged, [this, model](int frame) {
+ model->setCurrentFrame(frame);
+ updateStatusLine();
+ m_view->viewport()->update();
+ });
connect(
m_view, &GraphicsView::currentFrameChanged,
@@ -106,6 +112,8 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
auto updateTimeline = [this, model](bool validTimeline) {
if (validTimeline) {
+ updateStatusLine();
+ m_view->setCurrentFrame(m_view->model()->currentFrame(), false);
m_toolbar->updateBoundsSilent(model->minimumTime(), model->maximumTime());
m_toolbar->show();
m_tree->show();
@@ -119,6 +127,8 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
}
};
connect(model, &CurveEditorModel::timelineChanged, this, updateTimeline);
+
+ connect(model, &CurveEditorModel::setStatusLineMsg, m_statusLine, &QLabel::setText);
}
bool CurveEditor::dragging() const
@@ -153,4 +163,11 @@ void CurveEditor::hideEvent(QHideEvent *event)
QWidget::hideEvent(event);
}
+void CurveEditor::updateStatusLine()
+{
+ int currentFrame = m_view->model()->currentFrame();
+ QString currentText = QString("Playhead frame %1").arg(currentFrame);
+ m_statusLine->setText(currentText);
+}
+
} // End namespace QmlDesigner.
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditor.h b/src/plugins/qmldesigner/components/curveeditor/curveeditor.h
index 9d1a6f68f94..2265c5538f8 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditor.h
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditor.h
@@ -59,8 +59,12 @@ protected:
void hideEvent(QHideEvent *event) override;
private:
+ void updateStatusLine();
+
QLabel *m_infoText;
+ QLabel *m_statusLine;
+
CurveEditorToolBar *m_toolbar;
TreeView *m_tree;
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp
index 43776718174..fb60298e612 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp
@@ -44,12 +44,18 @@ namespace QmlDesigner {
CurveEditorModel::CurveEditorModel(QObject *parent)
: TreeModel(parent)
, m_hasTimeline(false)
+ , m_currentFrame(0)
, m_minTime(CurveEditorStyle::defaultTimeMin)
, m_maxTime(CurveEditorStyle::defaultTimeMax)
{}
CurveEditorModel::~CurveEditorModel() {}
+int CurveEditorModel::currentFrame() const
+{
+ return m_currentFrame;
+}
+
double CurveEditorModel::minimumTime() const
{
return m_minTime;
@@ -102,6 +108,7 @@ void CurveEditorModel::setTimeline(const QmlDesigner::QmlTimeline &timeline)
m_hasTimeline = timeline.isValid();
if (m_hasTimeline) {
+ m_currentFrame = static_cast<int>(timeline.currentKeyframe());
m_minTime = timeline.startKeyframe();
m_maxTime = timeline.endKeyframe();
std::vector<TreeItem *> items;
@@ -116,8 +123,8 @@ void CurveEditorModel::setTimeline(const QmlDesigner::QmlTimeline &timeline)
void CurveEditorModel::setCurrentFrame(int frame)
{
- if (graphicsView())
- graphicsView()->setCurrentFrame(frame, false);
+ m_currentFrame = frame;
+ emit commitCurrentFrame(m_currentFrame);
}
void CurveEditorModel::setMinimumTime(double time)
@@ -262,7 +269,7 @@ TreeItem *CurveEditorModel::createTopLevelItem(const QmlDesigner::QmlTimeline &t
AnimationCurve curve = createAnimationCurve(grp);
if (!curve.isEmpty()) {
QString name = QString::fromUtf8(grp.propertyName());
- auto propertyItem = new PropertyTreeItem(name, curve, typeFrom(grp));
+ auto propertyItem = new PropertyTreeItem(name, curve);
QmlDesigner::ModelNode target = grp.modelNode();
if (target.hasAuxiliaryData("locked"))
@@ -288,7 +295,7 @@ AnimationCurve CurveEditorModel::createAnimationCurve(const QmlDesigner::QmlTime
{
switch (typeFrom(group)) {
case PropertyTreeItem::ValueType::Bool:
- return createDoubleCurve(group);
+ return createBooleanCurve(group);
case PropertyTreeItem::ValueType::Integer:
return createDoubleCurve(group);
@@ -346,7 +353,13 @@ std::vector<Keyframe> resolveSmallCurves(const std::vector<Keyframe> &frames)
continue;
}
#endif
- AnimationCurve acurve(curve, previous.position(), frame.position());
+ // This is just a temporary curve. ValueType does not matter
+ AnimationCurve acurve(
+ AnimationCurve::ValueType::Undefined,
+ curve,
+ previous.position(),
+ frame.position());
+
previous.setRightHandle(acurve.keyframeAt(0).rightHandle());
out.push_back(acurve.keyframeAt(1));
continue;
@@ -357,6 +370,17 @@ std::vector<Keyframe> resolveSmallCurves(const std::vector<Keyframe> &frames)
return out;
}
+
+AnimationCurve CurveEditorModel::createBooleanCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group)
+{
+ std::vector<Keyframe> keyframes = createKeyframes(group.keyframePositions());
+
+ for (auto& keyframe : keyframes)
+ keyframe.setInterpolation(Keyframe::Interpolation::Step);
+
+ return AnimationCurve(typeFrom(group), keyframes);
+}
+
AnimationCurve CurveEditorModel::createDoubleCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group)
{
std::vector<Keyframe> keyframes = createKeyframes(group.keyframePositions());
@@ -374,7 +398,7 @@ AnimationCurve CurveEditorModel::createDoubleCurve(const QmlDesigner::QmlTimelin
}
}
- return AnimationCurve(keyframes);
+ return AnimationCurve(typeFrom(group), keyframes);
}
} // End namespace QmlDesigner.
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h
index 041642aa610..aa804058c64 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h
@@ -48,6 +48,8 @@ class CurveEditorModel : public TreeModel
Q_OBJECT
signals:
+ void setStatusLineMsg(const QString& msg);
+
void commitCurrentFrame(int frame);
void commitStartFrame(int frame);
@@ -63,6 +65,8 @@ public:
~CurveEditorModel() override;
+ int currentFrame() const;
+
double minimumTime() const;
double maximumTime() const;
@@ -92,10 +96,14 @@ private:
AnimationCurve createAnimationCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
+ AnimationCurve createBooleanCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
+
AnimationCurve createDoubleCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
bool m_hasTimeline = false;
+ int m_currentFrame = 0;
+
double m_minTime = 0.;
double m_maxTime = 0.;
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
index 7421d7b6658..5368512d315 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
@@ -35,6 +35,7 @@
#include <variantproperty.h>
#include <qmlstate.h>
#include <qmltimeline.h>
+#include <nodelistproperty.h>
#include <cmath>
@@ -69,8 +70,7 @@ bool CurveEditorView::hasWidget() const
WidgetInfo CurveEditorView::widgetInfo()
{
- return createWidgetInfo(
- m_editor, nullptr, "CurveEditorId", WidgetInfo::BottomPane, 0, tr("Curve Editor"));
+ return createWidgetInfo(m_editor, "CurveEditorId", WidgetInfo::BottomPane, 0, tr("Curves"));
}
void CurveEditorView::modelAttached(Model *model)
@@ -215,6 +215,9 @@ void CurveEditorView::propertiesRemoved(const QList<AbstractProperty> &propertyL
QmlTimeline CurveEditorView::activeTimeline() const
{
+ if (!isAttached())
+ return {};
+
QmlModelState state = currentState();
if (state.isBaseState()) {
for (const ModelNode &node : allModelNodesOfType("QtQuick.Timeline.Timeline")) {
@@ -335,42 +338,56 @@ void commitAuxiliaryData(ModelNode &node, TreeItem *item)
void CurveEditorView::commitKeyframes(TreeItem *item)
{
+ if (!isAttached())
+ return;
+
if (auto *nitem = item->asNodeItem()) {
ModelNode node = modelNodeForId(nitem->name());
commitAuxiliaryData(node, item);
} else if (auto *pitem = item->asPropertyItem()) {
QmlTimeline currentTimeline = activeTimeline();
+ if (!currentTimeline.isValid())
+ return;
+
QmlTimelineKeyframeGroup group = timelineKeyframeGroup(currentTimeline, pitem);
if (group.isValid()) {
ModelNode groupNode = group.modelNode();
commitAuxiliaryData(groupNode, item);
- auto replaceKeyframes = [&group, pitem, this]() {
+ auto replaceKeyframes = [&group, pitem, this]() mutable {
m_block = true;
- for (auto frame : group.keyframes())
+
+ for (auto& frame : group.keyframes())
frame.destroy();
- Keyframe previous;
- for (auto &&frame : pitem->curve().keyframes()) {
- QPointF pos = frame.position();
- group.setValue(QVariant(pos.y()), pos.x());
-
- if (previous.isValid()) {
- if (frame.interpolation() == Keyframe::Interpolation::Bezier ||
- frame.interpolation() == Keyframe::Interpolation::Step ) {
- CurveSegment segment(previous, frame);
- if (segment.isValid())
- attachEasingCurve(group, pos.x(), segment.easingCurve());
- } else if (frame.interpolation() == Keyframe::Interpolation::Easing) {
- QVariant data = frame.data();
- if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
- attachEasingCurve(group, pos.x(), data.value<QEasingCurve>());
+ AnimationCurve curve = pitem->curve();
+ if (curve.valueType() == AnimationCurve::ValueType::Bool) {
+ for (const auto& frame : curve.keyframes()) {
+ QPointF pos = frame.position();
+ group.setValue(QVariant(pos.y()), pos.x());
+ }
+ } else {
+ Keyframe previous;
+ for (const auto& frame : curve.keyframes()) {
+ QPointF pos = frame.position();
+ group.setValue(QVariant(pos.y()), pos.x());
+
+ if (previous.isValid()) {
+ if (frame.interpolation() == Keyframe::Interpolation::Bezier ||
+ frame.interpolation() == Keyframe::Interpolation::Step ) {
+ CurveSegment segment(previous, frame);
+ if (segment.isValid())
+ attachEasingCurve(group, pos.x(), segment.easingCurve());
+ } else if (frame.interpolation() == Keyframe::Interpolation::Easing) {
+ QVariant data = frame.data();
+ if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
+ attachEasingCurve(group, pos.x(), data.value<QEasingCurve>());
+ }
}
+ previous = frame;
}
-
- previous = frame;
}
m_block = false;
};
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp
index f8587df06fe..cb6811c9750 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp
@@ -85,7 +85,7 @@ void ColorControl::mouseReleaseEvent(QMouseEvent *event)
event->accept();
- if (color != m_color) {
+ if (color.isValid() && color != m_color) {
m_color = color;
update();
emit valueChanged();
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp
index 0b7ab9d391d..5b053099763 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp
@@ -37,22 +37,11 @@
namespace QmlDesigner {
-CurveItem::CurveItem(QGraphicsItem *parent)
- : CurveEditorItem(parent)
- , m_id(0)
- , m_style()
- , m_type(PropertyTreeItem::ValueType::Undefined)
- , m_component(PropertyTreeItem::Component::Generic)
- , m_transform()
- , m_keyframes()
- , m_itemDirty(false)
-{}
-
CurveItem::CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem *parent)
: CurveEditorItem(parent)
, m_id(id)
, m_style()
- , m_type(PropertyTreeItem::ValueType::Undefined)
+ , m_type(curve.valueType())
, m_component(PropertyTreeItem::Component::Generic)
, m_transform()
, m_keyframes()
@@ -235,14 +224,16 @@ PropertyTreeItem::Component CurveItem::component() const
return m_component;
}
-AnimationCurve CurveItem::curve() const
+AnimationCurve CurveItem::curve(bool remap) const
{
std::vector<Keyframe> frames;
frames.reserve(m_keyframes.size());
+
+ bool map = (m_type == AnimationCurve::ValueType::Bool) && remap;
for (auto *frameItem : m_keyframes)
- frames.push_back(frameItem->keyframe());
+ frames.push_back(frameItem->keyframe(map));
- return AnimationCurve(frames);
+ return AnimationCurve(m_type, frames);
}
AnimationCurve CurveItem::resolvedCurve() const
@@ -278,11 +269,13 @@ std::vector<AnimationCurve> CurveItem::curves() const
Keyframe previous = tmp.back();
if (tmp.size() >= 2)
- out.push_back(AnimationCurve(tmp));
+ out.push_back(AnimationCurve(m_type, tmp));
- out.push_back(AnimationCurve(current.data().value<QEasingCurve>(),
- previous.position(),
- current.position()));
+ out.push_back(AnimationCurve(
+ m_type,
+ current.data().value<QEasingCurve>(),
+ previous.position(),
+ current.position()));
tmp.clear();
tmp.push_back(current);
@@ -293,7 +286,7 @@ std::vector<AnimationCurve> CurveItem::curves() const
}
if (!tmp.empty())
- out.push_back(AnimationCurve(tmp));
+ out.push_back(AnimationCurve(m_type, tmp));
return out;
}
@@ -384,7 +377,7 @@ void CurveItem::setDirty(bool dirty)
void CurveItem::setHandleVisibility(bool visible)
{
- for (auto frame : qAsConst(m_keyframes))
+ for (auto *frame : qAsConst(m_keyframes))
frame->setHandleVisibility(visible);
}
@@ -402,7 +395,7 @@ void CurveItem::setCurve(const AnimationCurve &curve)
{
freeClear(m_keyframes);
- for (const auto &frame : curve.keyframes()) {
+ for (const auto& frame : curve.keyframes()) {
auto *item = new KeyframeItem(frame, this);
item->setLocked(locked());
item->setComponentTransform(m_transform);
@@ -419,7 +412,7 @@ QRectF CurveItem::setComponentTransform(const QTransform &transform)
{
prepareGeometryChange();
m_transform = transform;
- for (auto frame : qAsConst(m_keyframes))
+ for (auto *frame : qAsConst(m_keyframes))
frame->setComponentTransform(transform);
return boundingRect();
@@ -438,6 +431,14 @@ void CurveItem::setInterpolation(Keyframe::Interpolation interpolation)
if (m_keyframes.empty())
return;
+ if (m_type == AnimationCurve::ValueType::Bool) {
+ if (interpolation != Keyframe::Interpolation::Step) {
+ interpolation = Keyframe::Interpolation::Step;
+ QString msg("Warning: Curves of type bool can only be step-interpolated!");
+ emit curveMessage(msg);
+ }
+ }
+
KeyframeItem *prevItem = m_keyframes[0];
for (int i = 1; i < m_keyframes.size(); ++i) {
KeyframeItem *currItem = m_keyframes[i];
@@ -454,7 +455,7 @@ void CurveItem::setInterpolation(Keyframe::Interpolation interpolation)
prevItem = currItem;
}
setDirty(false);
- emit curveChanged(id(), curve());
+ emit curveChanged(id(), curve(true));
}
void CurveItem::setDefaultInterpolation()
@@ -466,7 +467,7 @@ void CurveItem::setDefaultInterpolation()
if (frame->selected())
frame->setDefaultInterpolation();
}
- emit curveChanged(id(), curve());
+ emit curveChanged(id(), curve(true));
}
void CurveItem::toggleUnified()
@@ -478,12 +479,13 @@ void CurveItem::toggleUnified()
if (frame->selected())
frame->toggleUnified();
}
- emit curveChanged(id(), curve());
+ emit curveChanged(id(), curve(true));
}
void CurveItem::connect(GraphicsScene *scene)
{
QObject::connect(this, &CurveItem::curveChanged, scene, &GraphicsScene::curveChanged);
+ QObject::connect(this, &CurveItem::curveMessage, scene, &GraphicsScene::curveMessage);
QObject::connect(this, &CurveItem::keyframeMoved, scene, &GraphicsScene::keyframeMoved);
QObject::connect(this, &CurveItem::handleMoved, scene, &GraphicsScene::handleMoved);
@@ -498,7 +500,7 @@ void CurveItem::insertKeyframeByTime(double time)
acurve.insert(time);
setCurve(acurve);
- emit curveChanged(id(), curve());
+ emit curveChanged(id(), curve(true));
}
void CurveItem::deleteSelectedKeyframes()
@@ -516,7 +518,14 @@ void CurveItem::deleteSelectedKeyframes()
markDirty();
- emit curveChanged(id(), curve());
+ emit curveChanged(id(), curve(true));
+}
+
+void CurveItem::remapValue(double min, double max)
+{
+ for (auto *frameItem : qAsConst(m_keyframes)) {
+ frameItem->remapValue(min, max);
+ }
}
void CurveItem::markDirty()
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h b/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h
index 5a2f363df7f..c6bdc6d3d4c 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h
@@ -46,6 +46,8 @@ class CurveItem : public CurveEditorItem
Q_OBJECT
signals:
+ void curveMessage(const QString& msg);
+
void curveChanged(unsigned int id, const AnimationCurve &curve);
void keyframeMoved(KeyframeItem *item, const QPointF &direction);
@@ -53,8 +55,6 @@ signals:
void handleMoved(KeyframeItem *frame, HandleItem::Slot slot, double angle, double deltaLength);
public:
- CurveItem(QGraphicsItem *parent = nullptr);
-
CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem *parent = nullptr);
~CurveItem() override;
@@ -93,7 +93,7 @@ public:
PropertyTreeItem::Component component() const;
- AnimationCurve curve() const;
+ AnimationCurve curve(bool remap = false) const;
AnimationCurve resolvedCurve() const;
@@ -135,6 +135,8 @@ public:
void deleteSelectedKeyframes();
+ void remapValue(double min, double max);
+
private:
void markDirty();
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp
index 9eda7f8934b..3506aab811c 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp
@@ -426,7 +426,7 @@ void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
if (curve->isDirty()) {
m_dirty = true;
curve->setDirty(false);
- emit curveChanged(curve->id(), curve->curve());
+ emit curveChanged(curve->id(), curve->curve(true));
}
}
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h
index 2e6bc3b080d..58738d116b1 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h
@@ -41,6 +41,8 @@ class GraphicsScene : public QGraphicsScene
Q_OBJECT
signals:
+ void curveMessage(const QString& msg);
+
void curveChanged(unsigned int id, const AnimationCurve &curve);
public:
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp
index 5b4e6e3cfbc..8ab71ace978 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp
@@ -83,6 +83,8 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
connect(&m_dialog, &CurveEditorStyleDialog::styleChanged, this, &GraphicsView::setStyle);
+ connect(m_scene, &GraphicsScene::curveMessage, m_model, &CurveEditorModel::setStatusLineMsg);
+
auto itemSlot = [this](unsigned int id, const AnimationCurve &curve) {
m_model->setCurve(id, curve);
applyZoom(m_zoomX, m_zoomY);
@@ -560,7 +562,14 @@ void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
scrollContent(mapTimeToX(deltaTransformed.x()), mapValueToY(deltaTransformed.y()));
}
+ for (auto *curve : m_scene->curves()) {
+ if (curve->valueType() == AnimationCurve::ValueType::Bool) {
+ curve->remapValue(minValue, maxValue);
+ }
+ }
+
m_scene->doNotMoveItems(false);
+ this->update();
}
void GraphicsView::drawGrid(QPainter *painter)
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp
index ef0a886d523..0dbb2d125f0 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp
@@ -27,7 +27,10 @@
#include "curveitem.h"
#include "handleitem.h"
+#include <QApplication>
#include <QPainter>
+#include <qnamespace.h>
+#include <QGraphicsSceneMouseEvent>
#include <cmath>
@@ -103,8 +106,16 @@ void KeyframeItem::lockedCallback()
KeyframeItem::~KeyframeItem() {}
-Keyframe KeyframeItem::keyframe() const
+Keyframe KeyframeItem::keyframe(bool remap) const
{
+ if (remap) {
+ auto frame = m_frame;
+ auto pos = frame.position();
+ auto center = m_min + ((m_max - m_min) / 2.0);
+ pos.ry() = pos.y() > center ? 1.0 : 0.0;
+ frame.setPosition(pos);
+ return frame;
+ }
return m_frame;
}
@@ -350,6 +361,18 @@ void KeyframeItem::moveHandle(HandleItem::Slot slot, double deltaAngle, double d
emit redrawCurve();
}
+void KeyframeItem::remapValue(double min, double max)
+{
+ auto center = m_min + ((m_max - m_min) / 2.0);
+ auto pos = m_frame.position();
+ pos.ry() = pos.y() > center ? max : min;
+ m_frame.setPosition(pos);
+
+ m_max = max;
+ m_min = min;
+ setKeyframe(m_frame);
+}
+
void KeyframeItem::updateHandle(HandleItem *handle, bool emitChanged)
{
bool ok = false;
@@ -422,8 +445,10 @@ QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons
if (curveItem->valueType() == PropertyTreeItem::ValueType::Integer)
position.setY(std::round(position.y()));
- else if (curveItem->valueType() == PropertyTreeItem::ValueType::Bool)
- position.setY(position.y() > 0.5 ? 1.0 : 0.0);
+ else if (curveItem->valueType() == PropertyTreeItem::ValueType::Bool) {
+ double center = m_min + ((m_max - m_min) / 2.0);
+ position.setY(position.y() > center ? m_max : m_min);
+ }
if (!legalLeft() || !legalRight()) {
return QVariant(m_transform.map(position));
@@ -431,10 +456,22 @@ QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons
lseg.moveRightTo(position);
rseg.moveLeftTo(position);
- if (legalLeft() && legalRight())
- m_validPos = position;
-
- return QVariant(m_transform.map(m_validPos));
+ if (legalLeft() && legalRight()) {
+ if (qApp->keyboardModifiers().testFlag(Qt::ShiftModifier) && m_validPos.has_value()) {
+ if (m_firstPos) {
+ auto firstToNow = QLineF(*m_firstPos, position);
+ if (std::abs(firstToNow.dx()) > std::abs(firstToNow.dy()))
+ m_validPos = QPointF(position.x(), m_firstPos->y());
+ else
+ m_validPos = QPointF(m_firstPos->x(), position.y());
+ }
+
+ } else {
+ m_validPos = position;
+ }
+ }
+
+ return QVariant(m_transform.map(*m_validPos));
}
}
}
@@ -444,6 +481,11 @@ QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons
void KeyframeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
+ bool ok;
+ m_firstPos = m_transform.inverted(&ok).map(event->scenePos());
+ if (!ok)
+ m_firstPos = Utils::nullopt;
+
SelectableItem::mousePressEvent(event);
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(parentItem()))
curveItem->setHandleVisibility(false);
@@ -451,6 +493,7 @@ void KeyframeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
void KeyframeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
+ m_firstPos = Utils::nullopt;
SelectableItem::mouseReleaseEvent(event);
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(parentItem()))
curveItem->setHandleVisibility(true);
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h b/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h
index 3e566c84b74..c7bfa02cd18 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h
@@ -30,6 +30,8 @@
#include "keyframe.h"
#include "selectableitem.h"
+#include <utils/optional.h>
+
#include <QGraphicsObject>
namespace QmlDesigner {
@@ -64,7 +66,7 @@ public:
void lockedCallback() override;
- Keyframe keyframe() const;
+ Keyframe keyframe(bool remap = false) const;
bool isUnified() const;
@@ -106,6 +108,8 @@ public:
void moveHandle(HandleItem::Slot slot, double deltaAngle, double deltaLength);
+ void remapValue(double min, double max);
+
protected:
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
@@ -131,9 +135,13 @@ private:
HandleItem *m_right;
- QPointF m_validPos;
+ Utils::optional< QPointF > m_firstPos;
+ Utils::optional< QPointF > m_validPos;
bool m_visibleOverride = true;
+
+ double m_min = 0.0;
+ double m_max = 1.0;
};
} // End namespace QmlDesigner.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp
index c4b6845f51f..91e6dbd6604 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp
@@ -84,7 +84,6 @@ CurveItem *TreeModel::curveItem(TreeItem *item)
{
if (auto *pti = item->asPropertyItem()) {
auto *citem = new CurveItem(pti->id(), pti->curve());
- citem->setValueType(pti->valueType());
citem->setComponent(pti->component());
citem->setLocked(pti->locked() || item->implicitlyLocked());
citem->setPinned(pti->pinned() || item->implicitlyPinned());
diff --git a/src/plugins/qmldesigner/components/curveeditor/keyframe.h b/src/plugins/qmldesigner/components/curveeditor/keyframe.h
index fd3c2cb88bc..2757d229f58 100644
--- a/src/plugins/qmldesigner/components/curveeditor/keyframe.h
+++ b/src/plugins/qmldesigner/components/curveeditor/keyframe.h
@@ -35,6 +35,7 @@ namespace QmlDesigner {
class Keyframe
{
public:
+ enum class ValueType { Undefined, Bool, Integer, Double };
enum class Interpolation { Undefined, Step, Linear, Bezier, Easing };
Keyframe();
diff --git a/src/plugins/qmldesigner/components/curveeditor/treeitem.cpp b/src/plugins/qmldesigner/components/curveeditor/treeitem.cpp
index 0b90d7d83b0..495b3750c8c 100644
--- a/src/plugins/qmldesigner/components/curveeditor/treeitem.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/treeitem.cpp
@@ -321,11 +321,9 @@ std::vector<PropertyTreeItem *> NodeTreeItem::properties() const
return out;
}
-PropertyTreeItem::PropertyTreeItem(const QString &name,
- const AnimationCurve &curve,
- const ValueType &type)
+PropertyTreeItem::PropertyTreeItem(const QString &name, const AnimationCurve &curve)
: TreeItem(name)
- , m_type(type)
+ , m_type(curve.valueType())
, m_component(Component::Generic)
, m_curve(curve)
{}
diff --git a/src/plugins/qmldesigner/components/curveeditor/treeitem.h b/src/plugins/qmldesigner/components/curveeditor/treeitem.h
index 60538778092..bf76d43706b 100644
--- a/src/plugins/qmldesigner/components/curveeditor/treeitem.h
+++ b/src/plugins/qmldesigner/components/curveeditor/treeitem.h
@@ -151,15 +151,10 @@ class PropertyTreeItem : public TreeItem
public:
enum class Component { Generic, R, G, B, A, X, Y, Z, W };
- enum class ValueType {
- Undefined,
- Bool,
- Integer,
- Double,
- };
+ using ValueType = AnimationCurve::ValueType;
public:
- PropertyTreeItem(const QString &name, const AnimationCurve &curve, const ValueType &type);
+ PropertyTreeItem(const QString &name, const AnimationCurve &curve);
PropertyTreeItem *asPropertyItem() override;
diff --git a/src/plugins/qmldesigner/components/debugview/debugview.cpp b/src/plugins/qmldesigner/components/debugview/debugview.cpp
index 831170d3026..c32edec724d 100644
--- a/src/plugins/qmldesigner/components/debugview/debugview.cpp
+++ b/src/plugins/qmldesigner/components/debugview/debugview.cpp
@@ -90,12 +90,12 @@ void DebugView::importsChanged(const QList<Import> &addedImports, const QList<Im
if (isDebugViewEnabled()) {
QString message;
message += QString("added imports:") += lineBreak;
- foreach (const Import &import, addedImports) {
+ for (const Import &import : addedImports) {
message += import.toImportString() += lineBreak;
}
message += QString("removed imports:") += lineBreak;
- foreach (const Import &import, removedImports) {
+ for (const Import &import : removedImports) {
message += import.toImportString() += lineBreak;
}
@@ -128,7 +128,8 @@ void DebugView::nodeAboutToBeRemoved(const ModelNode &removedNode)
QString string;
message.setString(&string);
message << removedNode << lineBreak;
- foreach (const ModelNode &modelNode, removedNode.allSubModelNodes()) {
+ const QList<ModelNode> modelNodes = removedNode.allSubModelNodes();
+ for (const ModelNode &modelNode : modelNodes) {
message << "child node:" << modelNode << lineBreak;
}
@@ -194,7 +195,7 @@ void DebugView::variantPropertiesChanged(const QList<VariantProperty> &propertyL
QTextStream message;
QString string;
message.setString(&string);
- foreach (const VariantProperty &property, propertyList) {
+ for (const VariantProperty &property : propertyList) {
message << property;
}
log("::variantPropertiesChanged:", string);
@@ -208,7 +209,7 @@ void DebugView::bindingPropertiesChanged(const QList<BindingProperty> &propertyL
QTextStream message;
QString string;
message.setString(&string);
- foreach (const BindingProperty &property, propertyList) {
+ for (const BindingProperty &property : propertyList) {
message << property;
}
log("::Binding properties changed:", string);
@@ -221,7 +222,7 @@ void DebugView::signalHandlerPropertiesChanged(const QVector<SignalHandlerProper
QTextStream message;
QString string;
message.setString(&string);
- foreach (const SignalHandlerProperty &property, propertyList) {
+ for (const SignalHandlerProperty &property : propertyList) {
message << property;
}
log("::signalHandlerPropertiesChanged:", string);
@@ -244,7 +245,7 @@ void DebugView::rootNodeTypeChanged(const QString &type, int majorVersion, int m
void DebugView::selectedNodesChanged(const QList<ModelNode> &selectedNodes /*selectedNodeList*/,
const QList<ModelNode> & /*lastSelectedNodeList*/)
{
- foreach (const ModelNode &selectedNode, selectedNodes) {
+ for (const ModelNode &selectedNode : selectedNodes) {
QTextStream message;
QString string;
message.setString(&string);
@@ -307,7 +308,7 @@ void DebugView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
QTextStream message;
QString string;
message.setString(&string);
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
message << property;
}
log("::propertiesRemoved:", string);
@@ -336,11 +337,11 @@ void DebugView::documentMessagesChanged(const QList<DocumentMessage> &errors, co
QString string;
message.setString(&string);
- foreach (const DocumentMessage &error, errors) {
+ for (const DocumentMessage &error : errors) {
message << error.toString();
}
- foreach (const DocumentMessage &warning, warnings) {
+ for (const DocumentMessage &warning : warnings) {
message << warning.toString();
}
@@ -362,7 +363,7 @@ void DebugView::rewriterEndTransaction()
WidgetInfo DebugView::widgetInfo()
{
- return createWidgetInfo(m_debugViewWidget.data(), nullptr, QStringLiteral("DebugView"), WidgetInfo::LeftPane, 0, tr("Debug View"));
+ return createWidgetInfo(m_debugViewWidget.data(), QStringLiteral("DebugView"), WidgetInfo::LeftPane, 0, tr("Debug View"));
}
bool DebugView::hasWidget() const
@@ -382,7 +383,7 @@ void DebugView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyNam
using Pair = QPair<ModelNode, PropertyName>;
- foreach (const Pair &pair, propertyList) {
+ for (const Pair &pair : propertyList) {
message << pair.first;
message << lineBreak;
message << pair.second;
@@ -403,7 +404,7 @@ void DebugView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
QString string;
message.setString(&string);
- foreach (const ModelNode &modelNode, completedNodeList) {
+ for (const ModelNode &modelNode : completedNodeList) {
message << modelNode << lineBreak;
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
message << "parent: " << QmlItemNode(modelNode).instanceParent() << lineBreak;
@@ -421,7 +422,8 @@ void DebugView::instanceInformationsChanged(const QMultiHash<ModelNode, Informat
QString string;
message.setString(&string);
- foreach (const ModelNode &modelNode, informationChangedHash.keys()) {
+ const QList<ModelNode> modelNodes = informationChangedHash.keys();
+ for (const ModelNode &modelNode : modelNodes) {
message << modelNode;
message << informationChangedHash.value(modelNode);
}
@@ -446,7 +448,7 @@ void DebugView::instancesChildrenChanged(const QVector<ModelNode> & nodeList)
QString string;
message.setString(&string);
- foreach (const ModelNode &modelNode, nodeList) {
+ for (const ModelNode &modelNode : nodeList) {
message << modelNode << lineBreak;
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
message << "parent: " << QmlItemNode(modelNode).instanceParent() << lineBreak;
@@ -466,11 +468,11 @@ void DebugView::customNotification(const AbstractView *view, const QString &iden
message << view;
message << identifier;
- foreach (const ModelNode &node, nodeList) {
+ for (const ModelNode &node : nodeList) {
message << node;
}
- foreach (const QVariant &variant, data) {
+ for (const QVariant &variant : data) {
message << variant.toString();
}
diff --git a/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp b/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp
index 3d7a9207c08..40d5ca4084b 100644
--- a/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp
@@ -23,8 +23,6 @@
**
****************************************************************************/
-#pragma once
-
#include <QColorDialog>
#include <utils/qtcassert.h>
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
index aa76d58370d..f848b58b3f0 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
@@ -77,7 +77,7 @@ WidgetInfo Edit3DView::widgetInfo()
if (!m_edit3DWidget)
createEdit3DWidget();
- return createWidgetInfo(m_edit3DWidget.data(), nullptr, "Editor3D", WidgetInfo::CentralPane, 0, tr("3D Editor"), DesignerWidgetFlags::IgnoreErrors);
+ return createWidgetInfo(m_edit3DWidget.data(), "Editor3D", WidgetInfo::CentralPane, 0, tr("3D"), DesignerWidgetFlags::IgnoreErrors);
}
Edit3DWidget *Edit3DView::edit3DWidget() const
@@ -210,8 +210,6 @@ void Edit3DView::modelAttached(Model *model)
void Edit3DView::modelAboutToBeDetached(Model *model)
{
- QTC_ASSERT(edit3DWidget()->canvas(), return);
-
// Hide the canvas when model is detached (i.e. changing documents)
if (edit3DWidget() && edit3DWidget()->canvas()) {
m_canvasCache.insert(model, edit3DWidget()->canvas()->renderImage());
@@ -241,6 +239,16 @@ void Edit3DView::customNotification(const AbstractView *view, const QString &ide
resetPuppet();
}
+void Edit3DView::modelAtPosReady(const ModelNode &modelNode)
+{
+ if (!m_droppedMaterial.isValid() || !modelNode.isValid())
+ return;
+
+ executeInTransaction(__FUNCTION__, [&] {
+ assignMaterialTo3dModel(modelNode, m_droppedMaterial);
+ });
+}
+
void Edit3DView::sendInputEvent(QInputEvent *e) const
{
if (nodeInstanceView())
@@ -330,6 +338,21 @@ Edit3DAction *Edit3DView::createResetColorAction()
tooltip);
}
+Edit3DAction *Edit3DView::createSyncBackgroundColorAction()
+{
+ QString description = QCoreApplication::translate("SyncEdit3DColorAction",
+ "Use Scene Environment Color");
+ QString tooltip = QCoreApplication::translate("SyncEdit3DColorAction",
+ "Sets the 3D Editor to use the Scene Environment "
+ "color as background color.");
+
+ return new Edit3DAction(
+ QmlDesigner::Constants::EDIT3D_EDIT_SYNC_BACKGROUND_COLOR, View3DActionCommand::SyncBackgroundColor,
+ description,
+ {}, true, false, {}, {}, {},
+ tooltip);
+}
+
void Edit3DView::createEdit3DActions()
{
m_selectionModeAction
@@ -561,6 +584,7 @@ void Edit3DView::createEdit3DActions()
m_backgroundColorActions << createSelectBackgrounColorAction();
m_backgroundColorActions << createGridColorSelectionAction();
+ m_backgroundColorActions << createSyncBackgroundColorAction();
m_backgroundColorActions << createResetColorAction();
}
@@ -607,5 +631,10 @@ void Edit3DView::addQuick3DImport()
tr("Could not add QtQuick3D import to project."));
}
+void Edit3DView::dropMaterial(const ModelNode &matNode, const QPointF &pos)
+{
+ m_droppedMaterial = matNode;
+ QmlDesignerPlugin::instance()->viewManager().nodeInstanceView()->view3DAction({View3DActionCommand::GetModelAtPos, pos});
}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
index b817c20d1a4..8b242058efb 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
@@ -64,6 +64,7 @@ public:
void modelAboutToBeDetached(Model *model) override;
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
+ void modelAtPosReady(const ModelNode &modelNode) override;
void sendInputEvent(QInputEvent *e) const;
void edit3DViewResized(const QSize &size) const;
@@ -78,8 +79,7 @@ public:
void setSeeker(SeekerSlider *slider);
void addQuick3DImport();
-
-protected:
+ void dropMaterial(const ModelNode &matNode, const QPointF &pos);
private:
void createEdit3DWidget();
@@ -88,6 +88,7 @@ private:
Edit3DAction *createSelectBackgrounColorAction();
Edit3DAction *createGridColorSelectionAction();
Edit3DAction *createResetColorAction();
+ Edit3DAction *createSyncBackgroundColorAction();
QPointer<Edit3DWidget> m_edit3DWidget;
QVector<Edit3DAction *> m_leftActions;
@@ -118,6 +119,7 @@ private:
SeekerSlider *m_seeker = nullptr;
int particlemode;
ModelCache<QImage> m_canvasCache;
+ ModelNode m_droppedMaterial;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
index afa05dd67e2..a6672b9f164 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
@@ -242,12 +242,28 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
- if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
+ if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData())
+ || dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
dragEnterEvent->acceptProposedAction();
+ }
}
void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
{
+ // handle dropping materials
+ if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
+ QByteArray data = dropEvent->mimeData()->data(Constants::MIME_TYPE_MATERIAL);
+ QDataStream stream(data);
+ qint32 internalId;
+ stream >> internalId;
+ ModelNode matNode = m_view->modelNodeForInternalId(internalId);
+
+ if (matNode.isValid())
+ m_view->dropMaterial(matNode, dropEvent->position());
+ return;
+ }
+
+ // handle dropping external assets
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
QHash<QString, QStringList> addedAssets = actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
diff --git a/src/plugins/qmldesigner/components/eventlist/eventlist.h b/src/plugins/qmldesigner/components/eventlist/eventlist.h
index 72f951c0393..8dfbed6e42d 100644
--- a/src/plugins/qmldesigner/components/eventlist/eventlist.h
+++ b/src/plugins/qmldesigner/components/eventlist/eventlist.h
@@ -25,9 +25,9 @@
#pragma once
#include "modelnode.h"
-#include "utils/fileutils.h"
-#include <unordered_set>
+#include <utils/filepath.h>
+
#include <QDialog>
QT_FORWARD_DECLARE_CLASS(QStandardItemModel)
diff --git a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp
index d24ff3a35b4..9f24e7d0e9f 100644
--- a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp
@@ -75,7 +75,7 @@ QList<FormEditorItem *> AbstractFormEditorTool::toFormEditorItemList(const QList
{
QList<FormEditorItem *> formEditorItemList;
- foreach (QGraphicsItem *graphicsItem, itemList) {
+ for (QGraphicsItem *graphicsItem : itemList) {
auto formEditorItem = qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
if (formEditorItem)
formEditorItemList.append(formEditorItem);
@@ -105,7 +105,7 @@ bool AbstractFormEditorTool::topSelectedItemIsMovable(const QList<QGraphicsItem*
{
QList<ModelNode> selectedNodes = view()->selectedModelNodes();
- foreach (QGraphicsItem *item, itemList) {
+ for (QGraphicsItem *item : itemList) {
FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
if (formEditorItem
&& selectedNodes.contains(formEditorItem->qmlItemNode())
@@ -116,7 +116,7 @@ bool AbstractFormEditorTool::topSelectedItemIsMovable(const QList<QGraphicsItem*
return true;
}
- foreach (QGraphicsItem *item, itemList) {
+ for (QGraphicsItem *item : itemList) {
FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
if (formEditorItem
&& formEditorItem->qmlItemNode().isValid()
@@ -163,7 +163,7 @@ bool AbstractFormEditorTool::topItemIsResizeHandle(const QList<QGraphicsItem*> &
QGraphicsItem *AbstractFormEditorTool::topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList)
{
- foreach (QGraphicsItem *item, itemList) {
+ for (QGraphicsItem *item : itemList) {
if (item->flags().testFlag(QGraphicsItem::ItemIsMovable))
return item;
}
@@ -173,7 +173,7 @@ QGraphicsItem *AbstractFormEditorTool::topMovableGraphicsItem(const QList<QGraph
FormEditorItem *AbstractFormEditorTool::topMovableFormEditorItem(const QList<QGraphicsItem*> &itemList, bool selectOnlyContentItems)
{
- foreach (QGraphicsItem *item, itemList) {
+ for (QGraphicsItem *item : itemList) {
FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
if (formEditorItem
&& formEditorItem->qmlItemNode().isValid()
@@ -221,7 +221,7 @@ QList<FormEditorItem *> AbstractFormEditorTool::filterSelectedModelNodes(const Q
{
QList<FormEditorItem *> filteredItemList;
- foreach (FormEditorItem *item, itemList) {
+ for (FormEditorItem *item : itemList) {
if (view()->isSelectedModelNode(item->qmlItemNode()))
filteredItemList.append(item);
}
@@ -266,7 +266,7 @@ void AbstractFormEditorTool::mousePressEvent(const QList<QGraphicsItem*> & /*ite
static bool containsItemNode(const QList<QGraphicsItem*> & itemList, const QmlItemNode &itemNode)
{
- foreach (QGraphicsItem *item, itemList) {
+ for (QGraphicsItem *item : itemList) {
FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
if (formEditorItem && formEditorItem->qmlItemNode() == itemNode)
return true;
@@ -340,7 +340,7 @@ Snapper::Snapping AbstractFormEditorTool::generateUseSnapping(Qt::KeyboardModifi
static bool isNotAncestorOfItemInList(FormEditorItem *formEditorItem, const QList<FormEditorItem*> &itemList)
{
- foreach (FormEditorItem *item, itemList) {
+ for (FormEditorItem *item : itemList) {
if (item
&& item->qmlItemNode().isValid()
&& item->qmlItemNode().isAncestorOf(formEditorItem->qmlItemNode()))
@@ -352,7 +352,7 @@ static bool isNotAncestorOfItemInList(FormEditorItem *formEditorItem, const QLis
FormEditorItem *AbstractFormEditorTool::containerFormEditorItem(const QList<QGraphicsItem *> &itemUnderMouseList, const QList<FormEditorItem *> &selectedItemList) const
{
- foreach (QGraphicsItem* item, itemUnderMouseList) {
+ for (QGraphicsItem* item : itemUnderMouseList) {
FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
if (formEditorItem
&& !selectedItemList.contains(formEditorItem)
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp b/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp
index 81bd86e1f64..5c634a773e5 100644
--- a/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp
@@ -121,7 +121,7 @@ void AnchorIndicator::setItems(const QList<FormEditorItem *> &itemList)
void AnchorIndicator::updateItems(const QList<FormEditorItem *> &itemList)
{
- foreach (FormEditorItem *formEditorItem, itemList) {
+ for (FormEditorItem *formEditorItem : itemList) {
if (formEditorItem == m_formEditorItem) {
QmlItemNode sourceQmlItemNode = m_formEditorItem->qmlItemNode();
if (!sourceQmlItemNode.modelNode().isRootNode()) {
diff --git a/src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp b/src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp
index 238a13eac0a..416042f085c 100644
--- a/src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp
@@ -144,7 +144,7 @@ void BindingIndicator::setItems(const QList<FormEditorItem *> &itemList)
void BindingIndicator::updateItems(const QList<FormEditorItem *> &itemList)
{
- foreach (FormEditorItem *formEditorItem, itemList) {
+ for (FormEditorItem *formEditorItem : itemList) {
if (formEditorItem == m_formEditorItem) {
const QmlItemNode qmlItemNode = m_formEditorItem->qmlItemNode();
diff --git a/src/plugins/qmldesigner/components/formeditor/contentnoteditableindicator.cpp b/src/plugins/qmldesigner/components/formeditor/contentnoteditableindicator.cpp
index 4c96433e5be..935340996ff 100644
--- a/src/plugins/qmldesigner/components/formeditor/contentnoteditableindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/contentnoteditableindicator.cpp
@@ -48,7 +48,7 @@ ContentNotEditableIndicator::~ContentNotEditableIndicator()
void ContentNotEditableIndicator::clear()
{
- foreach (const EntryPair &entryPair, m_entryList) {
+ for (const EntryPair &entryPair : qAsConst(m_entryList)) {
delete entryPair.second;
entryPair.first->blurContent(false);
}
@@ -71,23 +71,25 @@ void ContentNotEditableIndicator::updateItems(const QList<FormEditorItem *> &ite
{
QSet<FormEditorItem*> affectedFormEditorItemItems;
affectedFormEditorItemItems.unite(Utils::toSet(itemList));
- foreach (FormEditorItem *formEditorItem, itemList)
+ for (FormEditorItem *formEditorItem : itemList)
affectedFormEditorItemItems.unite(Utils::toSet(formEditorItem->offspringFormEditorItems()));
- foreach (const EntryPair &entryPair, m_entryList) {
- foreach (FormEditorItem *formEditorItem, affectedFormEditorItemItems) {
- if (formEditorItem == entryPair.first) {
- QRectF boundingRectangleInSceneSpace = formEditorItem->qmlItemNode().instanceSceneTransform().mapRect(formEditorItem->qmlItemNode().instanceBoundingRect());
- entryPair.second->setRect(boundingRectangleInSceneSpace);
- entryPair.second->update();
- }
- }
+ for (const EntryPair &entryPair : qAsConst(m_entryList)) {
+ for (FormEditorItem *formEditorItem : qAsConst(affectedFormEditorItemItems)) {
+ if (formEditorItem == entryPair.first) {
+ QRectF boundingRectangleInSceneSpace
+ = formEditorItem->qmlItemNode().instanceSceneTransform().mapRect(
+ formEditorItem->qmlItemNode().instanceBoundingRect());
+ entryPair.second->setRect(boundingRectangleInSceneSpace);
+ entryPair.second->update();
+ }
+ }
}
}
void ContentNotEditableIndicator::addAddiationEntries(const QList<FormEditorItem *> &itemList)
{
- foreach (FormEditorItem *formEditorItem, itemList) {
+ for (FormEditorItem *formEditorItem : itemList) {
const ModelNode modelNode = formEditorItem->qmlItemNode().modelNode();
if (modelNode.metaInfo().isValid() && modelNode.metaInfo().isSubclassOf("QtQuick.Loader")) {
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
index dea52631d85..5beb60a98e5 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp
@@ -79,7 +79,8 @@ void FormEditorScene::setupScene()
void FormEditorScene::resetScene()
{
- foreach (QGraphicsItem *item, m_manipulatorLayerItem->childItems()) {
+ const QList<QGraphicsItem *> items = m_manipulatorLayerItem->childItems();
+ for (QGraphicsItem *item : items) {
removeItem(item);
delete item;
}
@@ -116,7 +117,8 @@ QList<FormEditorItem*> FormEditorScene::allFormEditorItems() const
void FormEditorScene::updateAllFormEditorItems()
{
- foreach (FormEditorItem *item, allFormEditorItems())
+ const QList<FormEditorItem *> items = allFormEditorItems();
+ for (FormEditorItem *item : items)
item->update();
}
@@ -134,8 +136,8 @@ AbstractFormEditorTool* FormEditorScene::currentTool() const
FormEditorItem* FormEditorScene::calulateNewParent(FormEditorItem *formEditorItem)
{
if (formEditorItem->qmlItemNode().isValid()) {
- QList<QGraphicsItem *> list = items(formEditorItem->qmlItemNode().instanceBoundingRect().center());
- foreach (QGraphicsItem *graphicsItem, list) {
+ const QList<QGraphicsItem *> list = items(formEditorItem->qmlItemNode().instanceBoundingRect().center());
+ for (QGraphicsItem *graphicsItem : list) {
if (qgraphicsitem_cast<FormEditorItem*>(graphicsItem) &&
graphicsItem->collidesWithItem(formEditorItem, Qt::ContainsItemShape))
return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
@@ -229,7 +231,7 @@ QList<QGraphicsItem *> FormEditorScene::removeLayerItems(const QList<QGraphicsIt
{
QList<QGraphicsItem *> itemListWithoutLayerItems;
- foreach (QGraphicsItem *item, itemList)
+ for (QGraphicsItem *item : itemList)
if (item != manipulatorLayerItem() && item != formLayerItem())
itemListWithoutLayerItems.append(item);
@@ -422,16 +424,17 @@ void FormEditorScene::clearFormEditorItems()
const QList<FormEditorItem*> formEditorItems = Utils::filtered(formEditorItemsTransformed,
[](FormEditorItem *item) { return item; });
- foreach (FormEditorItem *item, formEditorItems)
+ for (FormEditorItem *item : formEditorItems)
item->setParentItem(nullptr);
- foreach (FormEditorItem *item, formEditorItems)
+ for (FormEditorItem *item : formEditorItems)
delete item;
}
void FormEditorScene::highlightBoundingRect(FormEditorItem *highlighItem)
{
- foreach (FormEditorItem *item, allFormEditorItems()) {
+ QList<FormEditorItem *> items = allFormEditorItems();
+ for (FormEditorItem *item : items) {
if (item == highlighItem)
item->setHighlightBoundingRect(true);
else
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
index dc499c03b9b..42ecfc06792 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
@@ -166,8 +166,8 @@ void FormEditorView::setupFormEditorItemTree(const QmlItemNode &qmlItemNode)
static void deleteWithoutChildren(const QList<FormEditorItem*> &items)
{
- foreach (FormEditorItem *item, items) {
- foreach (QGraphicsItem *child, item->childItems()) {
+ for (const FormEditorItem *item : items) {
+ for (QGraphicsItem *child : item->childItems()) {
child->setParentItem(item->scene()->rootFormEditorItem());
}
delete item;
@@ -286,11 +286,9 @@ void FormEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
void FormEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
{
- foreach (FormEditorItem *item, m_scene->allFormEditorItems()) {
+ const QList<FormEditorItem *> items = m_scene->allFormEditorItems();
+ for (FormEditorItem *item : items) {
item->setParentItem(nullptr);
- }
-
- foreach (FormEditorItem *item, m_scene->allFormEditorItems()) {
m_scene->removeItemFromHash(item);
delete item;
}
@@ -309,11 +307,12 @@ void FormEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVer
void FormEditorView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
{
QList<FormEditorItem*> removedItems;
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
if (property.isNodeAbstractProperty()) {
NodeAbstractProperty nodeAbstractProperty = property.toNodeAbstractProperty();
- foreach (const ModelNode &modelNode, nodeAbstractProperty.allSubNodes()) {
+ const QList<ModelNode> modelNodes = nodeAbstractProperty.allSubNodes();
+ for (const ModelNode &modelNode : modelNodes) {
const QmlItemNode qmlItemNode(modelNode);
if (qmlItemNode.isValid()){
@@ -362,7 +361,7 @@ WidgetInfo FormEditorView::widgetInfo()
if (!m_formEditorWidget)
createFormEditorWidget();
- return createWidgetInfo(m_formEditorWidget.data(), nullptr, "FormEditor", WidgetInfo::CentralPane, 0, tr("Form Editor"), DesignerWidgetFlags::IgnoreErrors);
+ return createWidgetInfo(m_formEditorWidget.data(), "FormEditor", WidgetInfo::CentralPane, 0, tr("2D"), DesignerWidgetFlags::IgnoreErrors);
}
FormEditorWidget *FormEditorView::formEditorWidget()
diff --git a/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp b/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp
index a16ca4b54dd..9daf5cd98e4 100644
--- a/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/itemutilfunctions.cpp
@@ -32,11 +32,11 @@ namespace QmlDesigner {
class FormEditorItem;
-QRectF boundingRectForItemList(QList<FormEditorItem*> itemList)
+QRectF boundingRectForItemList(const QList<FormEditorItem*> itemList)
{
QRectF boundingRect;
- foreach (FormEditorItem *item, itemList)
+ for (FormEditorItem *item : itemList)
{
boundingRect = boundingRect.united(item->mapToScene(item->qmlItemNode().instanceBoundingRect()).boundingRect());
}
diff --git a/src/plugins/qmldesigner/components/formeditor/layeritem.cpp b/src/plugins/qmldesigner/components/formeditor/layeritem.cpp
index 5be1d109266..0752450fd87 100644
--- a/src/plugins/qmldesigner/components/formeditor/layeritem.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/layeritem.cpp
@@ -69,8 +69,8 @@ QList<QGraphicsItem*> LayerItem::findAllChildItems(const QGraphicsItem *item) co
{
QList<QGraphicsItem*> itemList(item->childItems());
- foreach (QGraphicsItem *childItem, item->childItems())
- itemList += findAllChildItems(childItem);
+ for (int end = itemList.length(), i = 0; i < end; ++i)
+ itemList += findAllChildItems(itemList.at(i));
return itemList;
}
diff --git a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
index 9bf0d3fc511..0969776a028 100644
--- a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
@@ -88,7 +88,7 @@ void MoveManipulator::synchronizeParent(const QList<FormEditorItem*> &itemList,
{
bool snapperUpdated = false;
- foreach (FormEditorItem *item, itemList) {
+ for (FormEditorItem *item : itemList) {
if (m_itemList.contains(item)) {
QmlItemNode parentItemNode = QmlItemNode(parentNode);
if (parentItemNode.isValid()) {
@@ -111,7 +111,7 @@ void MoveManipulator::synchronizeInstanceParent(const QList<FormEditorItem*> &it
bool MoveManipulator::itemsCanReparented() const
{
- foreach (FormEditorItem* item, m_itemList) {
+ for (FormEditorItem* item : qAsConst(m_itemList)) {
if (item
&& item->qmlItemNode().isValid()
&& !item->qmlItemNode().instanceCanReparent())
@@ -123,7 +123,7 @@ bool MoveManipulator::itemsCanReparented() const
void MoveManipulator::setDirectUpdateInNodeInstances(bool directUpdate)
{
- foreach (FormEditorItem* item, m_itemList) {
+ for (FormEditorItem* item : qAsConst(m_itemList)) {
if (item && item->qmlItemNode().isValid())
item->qmlItemNode().nodeInstance().setDirectUpdate(directUpdate);
}
@@ -136,7 +136,7 @@ void MoveManipulator::begin(const QPointF &beginPoint)
m_snapper.updateSnappingLines(m_itemList);
- foreach (FormEditorItem* item, m_itemList) {
+ for (FormEditorItem* item : qAsConst(m_itemList)) {
if (item && item->qmlItemNode().isValid()) {
QTransform fromItemToSceneTransform = item->qmlItemNode().instanceSceneTransform();
m_beginItemRectInSceneSpaceHash.insert(item, fromItemToSceneTransform.mapRect(item->qmlItemNode().instanceBoundingRect()));
@@ -144,14 +144,14 @@ void MoveManipulator::begin(const QPointF &beginPoint)
}
QTransform fromContentItemToSceneTransform = m_snapper.containerFormEditorItem()->qmlItemNode().instanceSceneContentItemTransform();
- foreach (FormEditorItem* item, m_itemList) {
+ for (FormEditorItem* item : qAsConst(m_itemList)) {
if (item && item->qmlItemNode().isValid()) {
QPointF positionInScenesSpace = fromContentItemToSceneTransform.map(item->instancePosition());
m_beginPositionInSceneSpaceHash.insert(item, positionInScenesSpace);
}
}
- foreach (FormEditorItem* item, m_itemList) {
+ for (FormEditorItem* item : qAsConst(m_itemList)) {
if (item && item->qmlItemNode().isValid()) {
QmlAnchors anchors(item->qmlItemNode().anchors());
m_beginTopMarginHash.insert(item, anchors.instanceMargin(AnchorLineTop));
@@ -278,7 +278,7 @@ void MoveManipulator::update(const QPointF& updatePoint, Snapper::Snapping useSn
generateSnappingLines(tanslatedBoundingRects(m_beginItemRectInSceneSpaceHash, offsetVector, fromSceneToItemTransform));
}
- foreach (FormEditorItem* item, m_itemList) {
+ for (FormEditorItem* item : qAsConst(m_itemList)) {
QPointF positionInContainerSpace(fromSceneToContentItemTransform.map(m_beginPositionInSceneSpaceHash.value(item)) + offsetVector);
if (!item || !item->qmlItemNode().isValid())
@@ -363,7 +363,7 @@ void MoveManipulator::reparentTo(FormEditorItem *newParent, ReparentFlag flag)
else
parentProperty = parentItemNode.nodeAbstractProperty("data");
- foreach (FormEditorItem* item, m_itemList) {
+ for (FormEditorItem* item : qAsConst(m_itemList)) {
if (!item || !item->qmlItemNode().isValid())
continue;
@@ -372,7 +372,7 @@ void MoveManipulator::reparentTo(FormEditorItem *newParent, ReparentFlag flag)
}
- foreach (const ModelNode &nodeToReparented, nodeReparentVector)
+ for (const ModelNode &nodeToReparented : qAsConst(nodeReparentVector))
parentProperty.reparentHere(nodeToReparented);
synchronizeParent(m_itemList, parentProperty.parentModelNode());
@@ -393,7 +393,7 @@ void MoveManipulator::end()
void MoveManipulator::end(Snapper::Snapping useSnapping)
{
if (useSnapping == Snapper::UseSnappingAndAnchoring) {
- foreach (FormEditorItem *formEditorItem, m_itemList)
+ for (FormEditorItem* formEditorItem : qAsConst(m_itemList))
m_snapper.adjustAnchoringOfItem(formEditorItem);
}
@@ -402,7 +402,7 @@ void MoveManipulator::end(Snapper::Snapping useSnapping)
void MoveManipulator::moveBy(double deltaX, double deltaY)
{
- foreach (FormEditorItem* item, m_itemList) {
+ for (FormEditorItem* item : qAsConst(m_itemList)) {
if (!item || !item->qmlItemNode().isValid())
continue;
@@ -444,14 +444,14 @@ void MoveManipulator::endRewriterTransaction()
void MoveManipulator::setOpacityForAllElements(qreal opacity)
{
- foreach (FormEditorItem* item, m_itemList)
+ for (FormEditorItem* item : qAsConst(m_itemList))
item->setOpacity(opacity);
}
void MoveManipulator::deleteSnapLines()
{
if (m_layerItem) {
- foreach (QGraphicsItem *item, m_graphicsLineList) {
+ for (QGraphicsItem *item : qAsConst(m_graphicsLineList)) {
m_layerItem->scene()->removeItem(item);
delete item;
}
diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.cpp b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
index a383a746590..81cbc8273e3 100644
--- a/src/plugins/qmldesigner/components/formeditor/movetool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
@@ -271,7 +271,7 @@ void MoveTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList, QGra
void MoveTool::itemsAboutToRemoved(const QList<FormEditorItem*> &removedItemList)
{
- foreach (FormEditorItem* removedItem, removedItemList)
+ for (FormEditorItem* removedItem : removedItemList)
m_movingItems.removeOne(removedItem);
}
@@ -304,7 +304,7 @@ bool MoveTool::haveSameParent(const QList<FormEditorItem*> &itemList)
return false;
QGraphicsItem *firstParent = itemList.constFirst()->parentItem();
- foreach (FormEditorItem* item, itemList)
+ for (FormEditorItem* item : itemList)
{
if (firstParent != item->parentItem())
return false;
@@ -316,7 +316,7 @@ bool MoveTool::haveSameParent(const QList<FormEditorItem*> &itemList)
bool MoveTool::isAncestorOfAllItems(FormEditorItem* maybeAncestorItem,
const QList<FormEditorItem*> &itemList)
{
- foreach (FormEditorItem* item, itemList)
+ for (FormEditorItem* item : itemList)
{
if (!maybeAncestorItem->isAncestorOf(item) && item != maybeAncestorItem)
return false;
@@ -332,7 +332,7 @@ FormEditorItem* MoveTool::ancestorIfOtherItemsAreChild(const QList<FormEditorIte
return nullptr;
- foreach (FormEditorItem* item, itemList)
+ for (FormEditorItem* item : itemList)
{
if (isAncestorOfAllItems(item, itemList))
return item;
diff --git a/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp b/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp
index 47066dd3d24..235a97cefd3 100644
--- a/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/onedimensionalcluster.cpp
@@ -69,7 +69,7 @@ double OneDimensionalCluster::constFirst() const
QList<OneDimensionalCluster> OneDimensionalCluster::createOneDimensionalClusterList(const QList<double> & oneDimensionalCoordinateList)
{
QList<OneDimensionalCluster> oneDimensionalClusterList;
- foreach (double coordinate, oneDimensionalCoordinateList)
+ for (double coordinate : oneDimensionalCoordinateList)
{
QList<double> initialList;
initialList.append(coordinate);
@@ -134,7 +134,7 @@ QList<double> OneDimensionalCluster::reduceLines(const QList<double> & oneDimens
clusterList = reduceOneDimensionalClusterList(clusterList, maximumDistance);
QList<double> lineList;
- foreach (const OneDimensionalCluster &cluster, clusterList)
+ for (const OneDimensionalCluster &cluster : qAsConst(clusterList))
lineList.append(cluster.constFirst());
return lineList;
diff --git a/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp b/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp
index ad5f2feffff..cdb56ae044f 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/resizeindicator.cpp
@@ -71,7 +71,7 @@ void ResizeIndicator::setItems(const QList<FormEditorItem*> &itemList)
{
clear();
- foreach (FormEditorItem* item, itemList) {
+ for (FormEditorItem* item : itemList) {
if (item && itemIsResizable(item->qmlItemNode())) {
ResizeController controller(m_layerItem, item);
m_itemControllerHash.insert(item, controller);
@@ -81,7 +81,7 @@ void ResizeIndicator::setItems(const QList<FormEditorItem*> &itemList)
void ResizeIndicator::updateItems(const QList<FormEditorItem*> &itemList)
{
- foreach (FormEditorItem* item, itemList) {
+ for (FormEditorItem* item : itemList) {
if (m_itemControllerHash.contains(item)) {
if (!item || !itemIsResizable(item->qmlItemNode())) {
m_itemControllerHash.take(item);
diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
index 8907aab2bce..65c454fbe6a 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
@@ -628,7 +628,7 @@ bool ResizeManipulator::isInvalidSize(const QSizeF & size)
void ResizeManipulator::deleteSnapLines()
{
if (m_layerItem) {
- foreach (QGraphicsItem *item, m_graphicsLineList) {
+ for (QGraphicsItem *item : qAsConst(m_graphicsLineList)) {
m_layerItem->scene()->removeItem(item);
delete item;
}
diff --git a/src/plugins/qmldesigner/components/formeditor/rotationmanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/rotationmanipulator.cpp
index a7dbe75418b..6d7b054d0f6 100644
--- a/src/plugins/qmldesigner/components/formeditor/rotationmanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/rotationmanipulator.cpp
@@ -220,7 +220,7 @@ void RotationManipulator::end()
void RotationManipulator::deleteSnapLines()
{
if (m_layerItem) {
- foreach (QGraphicsItem *item, m_graphicsLineList) {
+ for (QGraphicsItem *item : qAsConst(m_graphicsLineList)) {
m_layerItem->scene()->removeItem(item);
delete item;
}
diff --git a/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp
index fa399f8860a..0327bb882cc 100644
--- a/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/rubberbandselectionmanipulator.cpp
@@ -51,7 +51,7 @@ void RubberBandSelectionManipulator::clear()
FormEditorItem *RubberBandSelectionManipulator::topFormEditorItem(const QList<QGraphicsItem*> &itemList)
{
- foreach (QGraphicsItem *item, itemList) {
+ for (QGraphicsItem *item : itemList) {
FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
if (formEditorItem)
diff --git a/src/plugins/qmldesigner/components/formeditor/seekerslider.cpp b/src/plugins/qmldesigner/components/formeditor/seekerslider.cpp
index c4659dcd651..e4fab1cde10 100644
--- a/src/plugins/qmldesigner/components/formeditor/seekerslider.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/seekerslider.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "seekerslider.h"
+
#include <utils/icon.h>
#include <QStyleOption>
diff --git a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp
index 02f3ce9ee66..382d9cc9163 100644
--- a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp
@@ -54,7 +54,7 @@ SelectionIndicator::~SelectionIndicator()
void SelectionIndicator::show()
{
- foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash)
+ for (QGraphicsPolygonItem *item : qAsConst(m_indicatorShapeHash))
item->show();
if (m_labelItem)
m_labelItem->show();
@@ -62,7 +62,7 @@ void SelectionIndicator::show()
void SelectionIndicator::hide()
{
- foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash)
+ for (QGraphicsPolygonItem *item : qAsConst(m_indicatorShapeHash))
item->hide();
if (m_labelItem)
m_labelItem->hide();
@@ -71,7 +71,7 @@ void SelectionIndicator::hide()
void SelectionIndicator::clear()
{
if (m_layerItem) {
- foreach (QGraphicsItem *item, m_indicatorShapeHash) {
+ for (QGraphicsPolygonItem *item : qAsConst(m_indicatorShapeHash)) {
m_layerItem->scene()->removeItem(item);
delete item;
}
@@ -102,7 +102,7 @@ void SelectionIndicator::setItems(const QList<FormEditorItem*> &itemList)
static QColor selectionColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_FormEditorSelectionColor);
- foreach (FormEditorItem *item, itemList) {
+ for (FormEditorItem *item : itemList) {
if (!item->qmlItemNode().isValid())
continue;
@@ -178,7 +178,7 @@ void SelectionIndicator::setItems(const QList<FormEditorItem*> &itemList)
void SelectionIndicator::updateItems(const QList<FormEditorItem*> &itemList)
{
- foreach (FormEditorItem *item, itemList) {
+ for (FormEditorItem *item : itemList) {
if (m_indicatorShapeHash.contains(item)) {
QGraphicsPolygonItem *indicatorGraphicsItem = m_indicatorShapeHash.value(item);
indicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpaceForItem(item, m_layerItem.data()));
@@ -207,7 +207,7 @@ void SelectionIndicator::setCursor(const QCursor &cursor)
{
m_cursor = cursor;
- foreach (QGraphicsItem *item, m_indicatorShapeHash)
+ for (QGraphicsItem *item : qAsConst(m_indicatorShapeHash))
item->setCursor(cursor);
}
diff --git a/src/plugins/qmldesigner/components/formeditor/snapper.cpp b/src/plugins/qmldesigner/components/formeditor/snapper.cpp
index 361a8a46b42..312b2751c1a 100644
--- a/src/plugins/qmldesigner/components/formeditor/snapper.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/snapper.cpp
@@ -453,7 +453,7 @@ static QLineF mergedHorizontalLine(const QList<QLineF> &lineList)
double minimumX = std::numeric_limits<double>::max();
double maximumX = std::numeric_limits<double>::min();
- foreach (const QLineF &line, lineList) {
+ for (const QLineF &line : lineList) {
minimumX = qMin(minimumX, double(line.x1()));
minimumX = qMin(minimumX, double(line.x2()));
maximumX = qMax(maximumX, double(line.x1()));
@@ -471,7 +471,7 @@ static QLineF mergedVerticalLine(const QList<QLineF> &lineList)
double minimumY = std::numeric_limits<double>::max();
double maximumY = std::numeric_limits<double>::min();
- foreach (const QLineF &line, lineList) {
+ for (const QLineF &line : lineList) {
minimumY = qMin(minimumY, double(line.y1()));
minimumY = qMin(minimumY, double(line.y2()));
maximumY = qMax(maximumY, double(line.y1()));
@@ -705,13 +705,13 @@ QList<QGraphicsItem*> Snapper::generateSnappingLines(const QList<QRectF> &boundi
{
QList<QGraphicsItem*> graphicsItemList;
QList<QLineF> lineList;
- foreach (const QRectF &boundingRect, boundingRectList) {
+ for (const QRectF &boundingRect : boundingRectList) {
QList<QRectF> snappedBoundingRectList;
lineList += mergedHorizontalLines(horizontalSnappedLines(boundingRect, &snappedBoundingRectList));
lineList += mergedVerticalLines(verticalSnappedLines(boundingRect, &snappedBoundingRectList));
}
- foreach (const QLineF &line, lineList) {
+ for (const QLineF &line : qAsConst(lineList)) {
QLineF lineInTransformationSpace = transform.map(line);
auto lineItem = new QGraphicsLineItem(lineInTransformationSpace, layerItem);
lineItem->setZValue(40);
diff --git a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp
index 45d71cb9b18..6658a846a45 100644
--- a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp
@@ -99,7 +99,8 @@ void SnappingLineCreator::generateLines(const QList<FormEditorItem*> &exceptionL
addLines(containerBoundingRectInTransformationSpace, m_formEditorItem);
}
- foreach (FormEditorItem *item, m_formEditorItem->childFormEditorItems()) {
+ const QList<FormEditorItem *> items = m_formEditorItem->childFormEditorItems();
+ for (FormEditorItem *item : items) {
if (!item || !item->qmlItemNode().isValid())
continue;
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
index 25b468fe23a..155e700b178 100644
--- a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
@@ -70,7 +70,7 @@ static QStringList arrayToStringList(const QByteArray &byteArray)
static QByteArray stringListToArray(const QStringList &stringList)
{
QString str;
- foreach (const QString &subString, stringList)
+ for (const QString &subString : stringList)
str += subString + QLatin1Char('\n');
return str.toUtf8();
}
@@ -83,7 +83,7 @@ void DesignDocumentView::toClipboard() const
data->setText(toText());
QStringList imports;
- foreach (const Import &import, model()->imports())
+ for (const Import &import : model()->imports())
imports.append(import.toImportString());
data->setData(QLatin1String("QmlDesigner::imports"), stringListToArray(imports));
@@ -95,7 +95,7 @@ void DesignDocumentView::fromClipboard()
QClipboard *clipboard = QApplication::clipboard();
fromText(clipboard->text());
QStringList imports = arrayToStringList(clipboard->mimeData()->data(QLatin1String("QmlDesigner::imports")));
-// foreach (const QString &importString, imports) {
+// for (const QString &importString, imports) {
// Import import(Import::createLibraryImport();
// model()->addImport(import); //### imports
// }
@@ -109,7 +109,7 @@ QString DesignDocumentView::toText() const
QPlainTextEdit textEdit;
QString imports;
- foreach (const Import &import, model()->imports()) {
+ for (const Import &import : model()->imports()) {
if (import.isFileImport())
imports += QStringLiteral("import ") + QStringLiteral("\"") + import.file() + QStringLiteral("\"")+ QStringLiteral(";\n");
else
@@ -215,10 +215,11 @@ void DesignDocumentView::copyModelNodes(const QList<ModelNode> &nodesToCopy)
if (selectedNodes.isEmpty())
return;
- foreach (const ModelNode &node, selectedNodes) {
- foreach (const ModelNode &node2, selectedNodes) {
- if (node.isAncestorOf(node2))
- selectedNodes.removeAll(node2);
+ QList<ModelNode> nodeList = selectedNodes;
+ for (int end = nodeList.length(), i = 0; i < end; ++i) {
+ for (int j = 0; j < end; ++j) {
+ if (nodeList.at(i).isAncestorOf(nodeList.at(j)))
+ selectedNodes.removeAll(nodeList.at(j));
}
}
@@ -238,14 +239,13 @@ void DesignDocumentView::copyModelNodes(const QList<ModelNode> &nodesToCopy)
view.toClipboard();
} else { // multi items selected
-
- foreach (ModelNode node, view.rootModelNode().directSubModelNodes()) {
+ for (ModelNode node : view.rootModelNode().directSubModelNodes()) {
node.destroy();
}
view.changeRootNodeType("QtQuick.Rectangle", 2, 0);
view.rootModelNode().setIdWithRefactoring("__multi__selection__");
- foreach (const ModelNode &selectedNode, selectedNodes) {
+ for (const ModelNode &selectedNode : qAsConst(selectedNodes)) {
ModelNode newNode(view.insertModel(selectedNode));
view.rootModelNode().nodeListProperty("data").reparentHere(newNode);
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui
index 34a6ef66ccb..081bc36a3d3 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui
@@ -55,7 +55,7 @@
<item>
<widget class="QPushButton" name="advancedSettingsButton">
<property name="text">
- <string>Show All Settings</string>
+ <string>Show All Options</string>
</property>
</widget>
</item>
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
index 76795d2817e..d1232432524 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
@@ -307,7 +307,10 @@ void ItemLibraryModel::setSearchText(const QString &searchText)
m_searchText = lowerSearchText;
bool changed = false;
- updateVisibility(&changed);
+ if (updateVisibility(&changed); changed) {
+ beginResetModel();
+ endResetModel();
+ }
selectImportFirstVisibleCategory();
}
@@ -591,11 +594,6 @@ void ItemLibraryModel::updateVisibility(bool *changed)
if (!m_searchText.isEmpty() && hasVisibleItems && !import->importExpanded())
import->setImportExpanded();
}
-
- if (changed) {
- beginResetModel();
- endResetModel();
- }
}
void ItemLibraryModel::addRoleNames()
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
index 5ad81ef9a20..2149049b004 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
@@ -64,12 +64,7 @@ WidgetInfo ItemLibraryView::widgetInfo()
if (m_widget.isNull())
m_widget = new ItemLibraryWidget{m_imageCache};
- return createWidgetInfo(m_widget.data(),
- new WidgetInfo::ToolBarWidgetDefaultFactory<ItemLibraryWidget>(m_widget.data()),
- "Components",
- WidgetInfo::LeftPane,
- 0,
- tr("Components"));
+ return createWidgetInfo(m_widget.data(), "Components", WidgetInfo::LeftPane, 0, tr("Components"));
}
void ItemLibraryView::modelAttached(Model *model)
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index 109078e1561..e1911036b53 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -143,7 +143,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
, m_itemsWidget(new QQuickWidget(this))
, m_imageCache{imageCache}
{
- m_compressionTimer.setInterval(200);
+ m_compressionTimer.setInterval(1000);
m_compressionTimer.setSingleShot(true);
ItemLibraryModel::registerQmlTypes();
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
index 49f313534d1..4027a1c75ae 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
@@ -24,9 +24,13 @@
****************************************************************************/
#include "materialbrowsermodel.h"
-#include "variantproperty.h"
+
+#include <bindingproperty.h>
#include <designmodewidget.h>
#include <qmldesignerplugin.h>
+#include <qmlobjectnode.h>
+#include "variantproperty.h"
+#include "utils/qtcassert.h"
namespace QmlDesigner {
@@ -46,24 +50,27 @@ int MaterialBrowserModel::rowCount(const QModelIndex &) const
QVariant MaterialBrowserModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() >= m_materialList.count()) {
- qWarning() << Q_FUNC_INFO << "invalid index requested";
- return {};
- }
+ QTC_ASSERT(index.isValid() && index.row() < m_materialList.count(), return {});
+ QTC_ASSERT(roleNames().contains(role), return {});
- if (roleNames().value(role) == "materialName") {
+ QByteArray roleName = roleNames().value(role);
+ if (roleName == "materialName") {
QVariant objName = m_materialList.at(index.row()).variantProperty("objectName").value();
return objName.isValid() ? objName : "";
}
- if (roleNames().value(role) == "materialInternalId")
+ if (roleName == "materialInternalId")
return m_materialList.at(index.row()).internalId();
- if (roleNames().value(role) == "materialVisible")
+ if (roleName == "materialVisible")
return isMaterialVisible(index.row());
- if (!roleNames().contains(role))
- qWarning() << Q_FUNC_INFO << "invalid role requested";
+ if (roleName == "materialType") {
+ QString matType = QString::fromLatin1(m_materialList.at(index.row()).type());
+ if (matType.startsWith("QtQuick3D."))
+ matType.remove("QtQuick3D.");
+ return matType;
+ }
return {};
}
@@ -82,12 +89,57 @@ bool MaterialBrowserModel::isValidIndex(int idx) const
return idx > -1 && idx < rowCount();
}
+/**
+ * @brief Loads and parses propertyGroups.json from QtQuick3D module's designer folder
+ *
+ * propertyGroups.json contains lists of QtQuick3D objects' properties grouped by sections
+ *
+ * @param path path to propertyGroups.json file
+ */
+void MaterialBrowserModel::loadPropertyGroups(const QString &path)
+{
+ bool ok = true;
+
+ if (m_propertyGroupsObj.isEmpty()) {
+ QFile matPropsFile(path);
+
+ if (!matPropsFile.open(QIODevice::ReadOnly)) {
+ qWarning("Couldn't open propertyGroups.json");
+ ok = false;
+ }
+
+ if (ok) {
+ QJsonDocument matPropsJsonDoc = QJsonDocument::fromJson(matPropsFile.readAll());
+ if (matPropsJsonDoc.isNull()) {
+ qWarning("Invalid propertyGroups.json file");
+ ok = false;
+ } else {
+ m_propertyGroupsObj = matPropsJsonDoc.object();
+ }
+ }
+ }
+
+ m_defaultMaterialSections.clear();
+ m_principledMaterialSections.clear();
+ m_customMaterialSections.clear();
+ if (ok) {
+ m_defaultMaterialSections.append(m_propertyGroupsObj.value("DefaultMaterial").toObject().keys());
+ m_principledMaterialSections.append(m_propertyGroupsObj.value("PrincipledMaterial").toObject().keys());
+
+ QStringList customMatSections = m_propertyGroupsObj.value("CustomMaterial").toObject().keys();
+ if (customMatSections.size() > 1) // as of now custom material has only 1 section, so we don't add it
+ m_customMaterialSections.append(customMatSections);
+ }
+ emit materialSectionsChanged();
+}
+
QHash<int, QByteArray> MaterialBrowserModel::roleNames() const
{
static const QHash<int, QByteArray> roles {
{Qt::UserRole + 1, "materialName"},
{Qt::UserRole + 2, "materialInternalId"},
{Qt::UserRole + 3, "materialVisible"},
+ {Qt::UserRole + 4, "materialType"}
};
return roles;
}
@@ -120,6 +172,34 @@ void MaterialBrowserModel::setHasModelSelection(bool b)
emit hasModelSelectionChanged();
}
+bool MaterialBrowserModel::hasMaterialRoot() const
+{
+ return m_hasMaterialRoot;
+}
+
+void MaterialBrowserModel::setHasMaterialRoot(bool b)
+{
+ if (m_hasMaterialRoot == b)
+ return;
+
+ m_hasMaterialRoot = b;
+ emit hasMaterialRootChanged();
+}
+
+QString MaterialBrowserModel::copiedMaterialType() const
+{
+ return m_copiedMaterialType;
+}
+
+void MaterialBrowserModel::setCopiedMaterialType(const QString &matType)
+{
+ if (matType == m_copiedMaterialType)
+ return;
+
+ m_copiedMaterialType = matType;
+ emit copiedMaterialTypeChanged();
+}
+
QList<ModelNode> MaterialBrowserModel::materials() const
{
return m_materialList;
@@ -201,6 +281,12 @@ void MaterialBrowserModel::removeMaterial(const ModelNode &material)
}
}
+void MaterialBrowserModel::deleteSelectedMaterial()
+{
+ if (isValidIndex(m_selectedIndex))
+ m_materialList[m_selectedIndex].destroy();
+}
+
void MaterialBrowserModel::updateSelectedMaterial()
{
selectMaterial(m_selectedIndex, true);
@@ -256,6 +342,42 @@ void MaterialBrowserModel::duplicateMaterial(int idx)
emit duplicateMaterialTriggered(m_materialList.at(idx));
}
+void MaterialBrowserModel::copyMaterialProperties(int idx, const QString &section)
+{
+ ModelNode mat = m_materialList.at(idx);
+ QString matType = QString::fromLatin1(mat.type());
+
+ if (matType.startsWith("QtQuick3D."))
+ matType.remove("QtQuick3D.");
+
+ setCopiedMaterialType(matType);
+ m_allPropsCopied = section == "All";
+
+ if (m_allPropsCopied || m_propertyGroupsObj.empty()) {
+ m_copiedMaterialProps = mat.properties();
+ } else {
+ QJsonObject propsSpecObj = m_propertyGroupsObj.value(m_copiedMaterialType).toObject();
+ if (propsSpecObj.contains(section)) { // should always be true
+ m_copiedMaterialProps.clear();
+ const QJsonArray propNames = propsSpecObj.value(section).toArray();
+ for (const QJsonValueRef &propName : propNames)
+ m_copiedMaterialProps.append(mat.property(propName.toString().toLatin1()));
+
+ if (section == "Base") { // add QtQuick3D.Material base props as well
+ QJsonObject propsMatObj = m_propertyGroupsObj.value("Material").toObject();
+ const QJsonArray propNames = propsMatObj.value("Base").toArray();
+ for (const QJsonValueRef &propName : propNames)
+ m_copiedMaterialProps.append(mat.property(propName.toString().toLatin1()));
+ }
+ }
+ }
+}
+
+void MaterialBrowserModel::pasteMaterialProperties(int idx)
+{
+ emit pasteMaterialPropertiesTriggered(m_materialList.at(idx), m_copiedMaterialProps, m_allPropsCopied);
+}
+
void MaterialBrowserModel::deleteMaterial(int idx)
{
m_materialList[idx].destroy();
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
index 73e6b2f99c6..5f38e7488eb 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
@@ -25,7 +25,9 @@
#pragma once
+#include "qjsonobject.h"
#include <modelnode.h>
+#include <qmlobjectnode.h>
#include <QAbstractListModel>
#include <QObject>
@@ -41,6 +43,11 @@ class MaterialBrowserModel : public QAbstractListModel
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged)
+ Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged)
+ Q_PROPERTY(QString copiedMaterialType READ copiedMaterialType WRITE setCopiedMaterialType NOTIFY copiedMaterialTypeChanged)
+ Q_PROPERTY(QStringList defaultMaterialSections MEMBER m_defaultMaterialSections NOTIFY materialSectionsChanged)
+ Q_PROPERTY(QStringList principledMaterialSections MEMBER m_principledMaterialSections NOTIFY materialSectionsChanged)
+ Q_PROPERTY(QStringList customMaterialSections MEMBER m_customMaterialSections NOTIFY materialSectionsChanged)
public:
MaterialBrowserModel(QObject *parent = nullptr);
@@ -58,18 +65,28 @@ public:
bool hasModelSelection() const;
void setHasModelSelection(bool b);
+ bool hasMaterialRoot() const;
+ void setHasMaterialRoot(bool b);
+
+ QString copiedMaterialType() const;
+ void setCopiedMaterialType(const QString &matType);
+
QList<ModelNode> materials() const;
void setMaterials(const QList<ModelNode> &materials, bool hasQuick3DImport);
void removeMaterial(const ModelNode &material);
+ void deleteSelectedMaterial();
void updateMaterialName(const ModelNode &material);
void updateSelectedMaterial();
int materialIndex(const ModelNode &material) const;
ModelNode materialAt(int idx) const;
+ void loadPropertyGroups(const QString &path);
void resetModel();
Q_INVOKABLE void selectMaterial(int idx, bool force = false);
Q_INVOKABLE void duplicateMaterial(int idx);
+ Q_INVOKABLE void copyMaterialProperties(int idx, const QString &section);
+ Q_INVOKABLE void pasteMaterialProperties(int idx);
Q_INVOKABLE void deleteMaterial(int idx);
Q_INVOKABLE void renameMaterial(int idx, const QString &newName);
Q_INVOKABLE void addNewMaterial();
@@ -80,11 +97,17 @@ signals:
void isEmptyChanged();
void hasQuick3DImportChanged();
void hasModelSelectionChanged();
+ void hasMaterialRootChanged();
+ void copiedMaterialTypeChanged();
+ void materialSectionsChanged();
void selectedIndexChanged(int idx);
void renameMaterialTriggered(const QmlDesigner::ModelNode &material, const QString &newName);
void applyToSelectedTriggered(const QmlDesigner::ModelNode &material, bool add = false);
void addNewMaterialTriggered();
void duplicateMaterialTriggered(const QmlDesigner::ModelNode &material);
+ void pasteMaterialPropertiesTriggered(const QmlDesigner::ModelNode &material,
+ const QList<QmlDesigner::AbstractProperty> &props,
+ bool all);
private:
bool isMaterialVisible(int idx) const;
@@ -92,12 +115,20 @@ private:
QString m_searchText;
QList<ModelNode> m_materialList;
+ QStringList m_defaultMaterialSections;
+ QStringList m_principledMaterialSections;
+ QStringList m_customMaterialSections;
+ QList<AbstractProperty> m_copiedMaterialProps;
QHash<qint32, int> m_materialIndexHash; // internalId -> index
+ QJsonObject m_propertyGroupsObj;
int m_selectedIndex = 0;
bool m_isEmpty = true;
bool m_hasQuick3DImport = false;
bool m_hasModelSelection = false;
+ bool m_hasMaterialRoot = false;
+ bool m_allPropsCopied = true;
+ QString m_copiedMaterialType;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
index d85e8239c12..0d05b12d6a1 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
@@ -24,12 +24,17 @@
****************************************************************************/
#include "materialbrowserview.h"
+
+#include "bindingproperty.h"
#include "materialbrowserwidget.h"
#include "materialbrowsermodel.h"
#include "nodeabstractproperty.h"
+#include "nodemetainfo.h"
#include "qmlobjectnode.h"
#include "variantproperty.h"
+
#include <coreplugin/icore.h>
+#include <designmodecontext.h>
#include <nodeinstanceview.h>
#include <qmldesignerconstants.h>
@@ -39,7 +44,6 @@ namespace QmlDesigner {
MaterialBrowserView::MaterialBrowserView(QObject *parent)
: AbstractView(parent)
-
{}
MaterialBrowserView::~MaterialBrowserView()
@@ -53,7 +57,11 @@ bool MaterialBrowserView::hasWidget() const
WidgetInfo MaterialBrowserView::widgetInfo()
{
if (m_widget.isNull()) {
- m_widget = new MaterialBrowserWidget;
+ m_widget = new MaterialBrowserWidget(this);
+
+ auto matEditorContext = new Internal::MaterialBrowserContext(m_widget.data());
+ Core::ICore::addContextObject(matEditorContext);
+
MaterialBrowserModel *matBrowserModel = m_widget->materialBrowserModel().data();
// custom notifications below are sent to the MaterialEditor
@@ -81,10 +89,35 @@ WidgetInfo MaterialBrowserView::widgetInfo()
[&] (const ModelNode &material) {
emitCustomNotification("duplicate_material", {material});
});
+
+ connect(matBrowserModel, &MaterialBrowserModel::pasteMaterialPropertiesTriggered, this,
+ [&] (const ModelNode &material, const QList<AbstractProperty> &props, bool all) {
+ QmlObjectNode mat(material);
+ executeInTransaction(__FUNCTION__, [&] {
+ if (all) { // all material properties copied
+ // remove current properties
+ const PropertyNameList propNames = material.propertyNames();
+ for (const PropertyName &propName : propNames) {
+ if (propName != "objectName")
+ mat.removeProperty(propName);
+ }
+ }
+
+ // apply pasted properties
+ for (const AbstractProperty &prop : props) {
+ if (prop.name() == "objectName")
+ continue;
+
+ if (prop.isVariantProperty())
+ mat.setVariantProperty(prop.name(), prop.toVariantProperty().value());
+ else if (prop.isBindingProperty())
+ mat.setBindingProperty(prop.name(), prop.toBindingProperty().expression());
+ }
+ });
+ });
}
return createWidgetInfo(m_widget.data(),
- new WidgetInfo::ToolBarWidgetDefaultFactory<MaterialBrowserWidget>(m_widget.data()),
"MaterialBrowser",
WidgetInfo::LeftPane,
0,
@@ -95,7 +128,12 @@ void MaterialBrowserView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
+ QString matPropsPath = model->metaInfo("QtQuick3D.Material").importDirectoryPath()
+ + "/designer/propertyGroups.json";
+ m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath);
+
m_widget->clearSearchFilter();
+ m_widget->materialBrowserModel()->setHasMaterialRoot(rootModelNode().isSubclassOf("QtQuick3D.Material"));
m_hasQuick3DImport = model->hasImport("QtQuick3D");
// Project load is already very busy and may even trigger puppet reset, so let's wait a moment
@@ -131,7 +169,7 @@ void MaterialBrowserView::refreshModel(bool updateImages)
bool MaterialBrowserView::isMaterial(const ModelNode &node) const
{
- if (!node.isValid() || node.isComponent())
+ if (!node.isValid())
return false;
return node.isSubclassOf("QtQuick3D.Material");
@@ -139,6 +177,8 @@ bool MaterialBrowserView::isMaterial(const ModelNode &node) const
void MaterialBrowserView::modelAboutToBeDetached(Model *model)
{
+ m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport);
+
AbstractView::modelAboutToBeDetached(model);
}
@@ -283,6 +323,12 @@ void MaterialBrowserView::customNotification(const AbstractView *view, const QSt
int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first());
if (idx != -1)
m_widget->materialBrowserModel()->selectMaterial(idx);
+ } else if (identifier == "refresh_material_browser") {
+ QTimer::singleShot(0, this, [this]() {
+ refreshModel(true);
+ });
+ } else if (identifier == "delete_selected_material") {
+ m_widget->materialBrowserModel()->deleteSelectedMaterial();
}
}
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
index 3982d534546..71ddd1aca7f 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
@@ -25,6 +25,7 @@
#include "materialbrowserwidget.h"
#include "materialbrowsermodel.h"
+#include "materialbrowserview.h"
#include <theme.h>
@@ -130,14 +131,20 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
return QObject::eventFilter(obj, event);
}
-MaterialBrowserWidget::MaterialBrowserWidget()
- : m_materialBrowserModel(new MaterialBrowserModel(this))
+MaterialBrowserWidget::MaterialBrowserWidget(MaterialBrowserView *view)
+ : m_materialBrowserView(view)
+ , m_materialBrowserModel(new MaterialBrowserModel(this))
, m_quickWidget(new QQuickWidget(this))
, m_previewImageProvider(new PreviewImageProvider())
{
setWindowTitle(tr("Material Browser", "Title of material browser widget"));
setMinimumWidth(120);
+ Core::Context context(Constants::C_QMLMATERIALBROWSER);
+ m_context = new Core::IContext(this);
+ m_context->setContext(context);
+ m_context->setWidget(this);
+
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
@@ -164,6 +171,8 @@ MaterialBrowserWidget::MaterialBrowserWidget()
m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F8), this);
connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &MaterialBrowserWidget::reloadQmlSource);
+ QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_MATERIALBROWSER_TIME);
+
reloadQmlSource();
}
@@ -180,6 +189,14 @@ QList<QToolButton *> MaterialBrowserWidget::createToolBarWidgets()
return {};
}
+void MaterialBrowserWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
+{
+ if (m_materialBrowserView)
+ m_materialBrowserView->contextHelp(callback);
+ else
+ callback({});
+}
+
void MaterialBrowserWidget::handleSearchfilterChanged(const QString &filterText)
{
if (filterText != m_filterText) {
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
index 30f9d05b509..9c08f21f9af 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
@@ -25,20 +25,19 @@
#pragma once
-#include "itemlibraryinfo.h"
-#include "import.h"
#include "modelnode.h"
-#include <utils/fancylineedit.h>
+#include <coreplugin/icontext.h>
#include <utils/dropsupport.h>
+#include <utils/fancylineedit.h>
-#include <QFrame>
-#include <QToolButton>
#include <QFileIconProvider>
-#include <QQuickWidget>
+#include <QFrame>
+#include <QPointF>
#include <QQmlPropertyMap>
+#include <QQuickWidget>
#include <QTimer>
-#include <QPointF>
+#include <QToolButton>
#include <memory>
@@ -49,6 +48,7 @@ QT_END_NAMESPACE
namespace QmlDesigner {
+class MaterialBrowserView;
class MaterialBrowserModel;
class PreviewImageProvider;
@@ -57,10 +57,11 @@ class MaterialBrowserWidget : public QFrame
Q_OBJECT
public:
- MaterialBrowserWidget();
+ MaterialBrowserWidget(MaterialBrowserView *view);
~MaterialBrowserWidget() = default;
QList<QToolButton *> createToolBarWidgets();
+ void contextHelp(const Core::IContext::HelpCallback &callback) const;
static QString qmlSourcesPath();
void clearSearchFilter();
@@ -80,11 +81,13 @@ private:
void reloadQmlSource();
void updateSearch();
+ QPointer<MaterialBrowserView> m_materialBrowserView;
QPointer<MaterialBrowserModel> m_materialBrowserModel;
QScopedPointer<QQuickWidget> m_quickWidget;
QShortcut *m_qmlSourceUpdateShortcut = nullptr;
PreviewImageProvider *m_previewImageProvider = nullptr;
+ Core::IContext *m_context = nullptr;
QString m_filterText;
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp
index 435c5318979..31105e84dc0 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp
@@ -32,6 +32,7 @@
#include <qmlmodelnodeproxy.h>
#include <qmlobjectnode.h>
#include <qmltimeline.h>
+#include <documentmanager.h>
#include <coreplugin/messagebox.h>
#include <utils/algorithm.h>
@@ -47,12 +48,24 @@
namespace QmlDesigner {
-MaterialEditorContextObject::MaterialEditorContextObject(QObject *parent)
+MaterialEditorContextObject::MaterialEditorContextObject(QQmlContext *context, QObject *parent)
: QObject(parent)
+ , m_qmlContext(context)
{
qmlRegisterUncreatableType<MaterialEditorContextObject>("ToolBarAction", 1, 0, "ToolBarAction", "Enum type");
}
+QQmlComponent *MaterialEditorContextObject::specificQmlComponent()
+{
+ if (m_specificQmlComponent)
+ return m_specificQmlComponent;
+
+ m_specificQmlComponent = new QQmlComponent(m_qmlContext->engine(), this);
+ m_specificQmlComponent->setData(m_specificQmlData.toUtf8(), QUrl::fromLocalFile("specifics.qml"));
+
+ return m_specificQmlComponent;
+}
+
QString MaterialEditorContextObject::convertColorToString(const QVariant &color)
{
QString colorString;
@@ -158,8 +171,10 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName)
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Ok);
- if (msgBox.exec() == QMessageBox::Cancel)
+ if (msgBox.exec() == QMessageBox::Cancel) {
+ updatePossibleTypeIndex();
return;
+ }
for (const auto &p : std::as_const(incompatibleProperties))
m_selectedMaterial.removeProperty(p);
@@ -233,6 +248,20 @@ void MaterialEditorContextObject::setHasQuick3DImport(bool b)
emit hasQuick3DImportChanged();
}
+bool MaterialEditorContextObject::hasMaterialRoot() const
+{
+ return m_hasMaterialRoot;
+}
+
+void MaterialEditorContextObject::setHasMaterialRoot(bool b)
+{
+ if (b == m_hasMaterialRoot)
+ return;
+
+ m_hasMaterialRoot = b;
+ emit hasMaterialRootChanged();
+}
+
bool MaterialEditorContextObject::hasModelSelection() const
{
return m_hasModelSelection;
@@ -261,6 +290,20 @@ void MaterialEditorContextObject::setSpecificsUrl(const QUrl &newSpecificsUrl)
emit specificsUrlChanged();
}
+void MaterialEditorContextObject::setSpecificQmlData(const QString &newSpecificQmlData)
+{
+ if (newSpecificQmlData == m_specificQmlData)
+ return;
+
+ m_specificQmlData = newSpecificQmlData;
+
+ delete m_specificQmlComponent;
+ m_specificQmlComponent = nullptr;
+
+ emit specificQmlComponentChanged();
+ emit specificQmlDataChanged();
+}
+
void MaterialEditorContextObject::setStateName(const QString &newStateName)
{
if (newStateName == m_stateName)
@@ -279,6 +322,23 @@ void MaterialEditorContextObject::setAllStateNames(const QStringList &allStates)
emit allStateNamesChanged();
}
+void MaterialEditorContextObject::setPossibleTypes(const QStringList &types)
+{
+ if (types == m_possibleTypes)
+ return;
+
+ m_possibleTypes = types;
+ emit possibleTypesChanged();
+
+ updatePossibleTypeIndex();
+}
+
+void MaterialEditorContextObject::setCurrentType(const QString &type)
+{
+ m_currentType = type.split('.').last();
+ updatePossibleTypeIndex();
+}
+
void MaterialEditorContextObject::setIsBaseState(bool newIsBaseState)
{
if (newIsBaseState == m_isBaseState)
@@ -325,6 +385,20 @@ void MaterialEditorContextObject::setHasAliasExport(bool hasAliasExport)
emit hasAliasExportChanged();
}
+void MaterialEditorContextObject::updatePossibleTypeIndex()
+{
+ int newIndex = -1;
+ if (!m_currentType.isEmpty())
+ newIndex = m_possibleTypes.indexOf(m_currentType);
+
+ // Emit valid possible type index change even if the index doesn't change, as currentIndex on
+ // QML side will change to default internally if model is updated
+ if (m_possibleTypeIndex != -1 || m_possibleTypeIndex != newIndex) {
+ m_possibleTypeIndex = newIndex;
+ emit possibleTypeIndexChanged();
+ }
+}
+
void MaterialEditorContextObject::hideCursor()
{
if (QApplication::overrideCursor())
@@ -389,4 +463,10 @@ bool MaterialEditorContextObject::isBlocked(const QString &propName) const
return false;
}
+void MaterialEditorContextObject::goIntoComponent()
+{
+ QTC_ASSERT(m_model, return);
+ DocumentManager::goIntoComponent(m_selectedMaterial);
+}
+
} // QmlDesigner
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h
index 54d72171a56..07ce582d443 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h
@@ -43,9 +43,13 @@ class MaterialEditorContextObject : public QObject
Q_OBJECT
Q_PROPERTY(QUrl specificsUrl READ specificsUrl WRITE setSpecificsUrl NOTIFY specificsUrlChanged)
+ Q_PROPERTY(QString specificQmlData READ specificQmlData WRITE setSpecificQmlData NOTIFY specificQmlDataChanged)
+ Q_PROPERTY(QQmlComponent *specificQmlComponent READ specificQmlComponent NOTIFY specificQmlComponentChanged)
Q_PROPERTY(QString stateName READ stateName WRITE setStateName NOTIFY stateNameChanged)
Q_PROPERTY(QStringList allStateNames READ allStateNames WRITE setAllStateNames NOTIFY allStateNamesChanged)
+ Q_PROPERTY(QStringList possibleTypes READ possibleTypes WRITE setPossibleTypes NOTIFY possibleTypesChanged)
+ Q_PROPERTY(int possibleTypeIndex READ possibleTypeIndex NOTIFY possibleTypeIndexChanged)
Q_PROPERTY(bool isBaseState READ isBaseState WRITE setIsBaseState NOTIFY isBaseStateChanged)
Q_PROPERTY(bool selectionChanged READ selectionChanged WRITE setSelectionChanged NOTIFY selectionChangedChanged)
@@ -56,15 +60,20 @@ class MaterialEditorContextObject : public QObject
Q_PROPERTY(bool hasActiveTimeline READ hasActiveTimeline NOTIFY hasActiveTimelineChanged)
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged)
+ Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged)
Q_PROPERTY(QQmlPropertyMap *backendValues READ backendValues WRITE setBackendValues NOTIFY backendValuesChanged)
public:
- MaterialEditorContextObject(QObject *parent = nullptr);
+ MaterialEditorContextObject(QQmlContext *context, QObject *parent = nullptr);
QUrl specificsUrl() const { return m_specificsUrl; }
+ QString specificQmlData() const {return m_specificQmlData; }
+ QQmlComponent *specificQmlComponent();
QString stateName() const { return m_stateName; }
QStringList allStateNames() const { return m_allStateNames; }
+ QStringList possibleTypes() const { return m_possibleTypes; }
+ int possibleTypeIndex() const { return m_possibleTypeIndex; }
bool isBaseState() const { return m_isBaseState; }
bool selectionChanged() const { return m_selectionChanged; }
@@ -86,6 +95,7 @@ public:
Q_INVOKABLE QStringList allStatesForId(const QString &id);
Q_INVOKABLE bool isBlocked(const QString &propName) const;
+ Q_INVOKABLE void goIntoComponent();
enum ToolBarAction {
ApplyToSelected = 0,
@@ -105,6 +115,9 @@ public:
bool hasQuick3DImport() const;
void setHasQuick3DImport(bool b);
+ bool hasMaterialRoot() const;
+ void setHasMaterialRoot(bool b);
+
bool hasModelSelection() const;
void setHasModelSelection(bool b);
@@ -113,8 +126,11 @@ public:
void setSelectedMaterial(const ModelNode &matNode);
void setSpecificsUrl(const QUrl &newSpecificsUrl);
+ void setSpecificQmlData(const QString &newSpecificQmlData);
void setStateName(const QString &newStateName);
void setAllStateNames(const QStringList &allStates);
+ void setPossibleTypes(const QStringList &types);
+ void setCurrentType(const QString &type);
void setIsBaseState(bool newIsBaseState);
void setSelectionChanged(bool newSelectionChanged);
void setBackendValues(QQmlPropertyMap *newBackendValues);
@@ -125,8 +141,12 @@ public:
signals:
void specificsUrlChanged();
+ void specificQmlDataChanged();
+ void specificQmlComponentChanged();
void stateNameChanged();
void allStateNamesChanged();
+ void possibleTypesChanged();
+ void possibleTypeIndexChanged();
void isBaseStateChanged();
void selectionChangedChanged();
void backendValuesChanged();
@@ -134,18 +154,26 @@ signals:
void hasAliasExportChanged();
void hasActiveTimelineChanged();
void hasQuick3DImportChanged();
+ void hasMaterialRootChanged();
void hasModelSelectionChanged();
private:
+ void updatePossibleTypeIndex();
+
QUrl m_specificsUrl;
+ QString m_specificQmlData;
+ QQmlComponent *m_specificQmlComponent = nullptr;
+ QQmlContext *m_qmlContext = nullptr;
QString m_stateName;
QStringList m_allStateNames;
+ QStringList m_possibleTypes;
+ int m_possibleTypeIndex = -1;
+ QString m_currentType;
int m_majorVersion = 1;
QQmlPropertyMap *m_backendValues = nullptr;
- QQmlComponent *m_qmlComponent = nullptr;
Model *m_model = nullptr;
QPoint m_lastPos;
@@ -155,6 +183,7 @@ private:
bool m_aliasExport = false;
bool m_hasActiveTimeline = false;
bool m_hasQuick3DImport = false;
+ bool m_hasMaterialRoot = false;
bool m_hasModelSelection = false;
ModelNode m_selectedMaterial;
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp
index 7c5d8436226..588d62f892e 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp
@@ -102,7 +102,7 @@ public:
MaterialEditorQmlBackend::MaterialEditorQmlBackend(MaterialEditorView *materialEditor)
: m_view(new QQuickWidget)
, m_materialEditorTransaction(new MaterialEditorTransaction(materialEditor))
- , m_contextObject(new MaterialEditorContextObject())
+ , m_contextObject(new MaterialEditorContextObject(m_view->rootContext()))
, m_materialEditorImageProvider(new MaterialEditorImageProvider())
{
m_view->setResizeMode(QQuickWidget::SizeRootObjectToView);
@@ -125,18 +125,6 @@ PropertyName MaterialEditorQmlBackend::auxNamePostFix(const PropertyName &proper
return propertyName + "__AUX";
}
-QVariant MaterialEditorQmlBackend::properDefaultAuxiliaryProperties(const QmlObjectNode &qmlObjectNode,
- const PropertyName &propertyName)
-{
- const ModelNode node = qmlObjectNode.modelNode();
- const PropertyName auxName = propertyName;
-
- if (node.hasAuxiliaryData(auxName))
- return node.auxiliaryData(auxName);
-
- return {};
-}
-
void MaterialEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode,
const PropertyName &name,
const QVariant &value,
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h
index 3cfdbc9bd88..503f4a2667c 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h
@@ -79,7 +79,6 @@ private:
const PropertyName &name, const QVariant &value,
MaterialEditorView *materialEditor);
PropertyName auxNamePostFix(const PropertyName &propertyName);
- QVariant properDefaultAuxiliaryProperties(const QmlObjectNode &qmlObjectNode, const PropertyName &propertyName);
QQuickWidget *m_view = nullptr;
Internal::QmlAnchorBindingProxy m_backendAnchorBinding;
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
index d86ef1463bf..1a3ab43763a 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
@@ -31,18 +31,17 @@
#include "materialeditortransaction.h"
#include "assetslibrarywidget.h"
-#include <qmldesignerconstants.h>
-#include <qmltimeline.h>
+#include <bindingproperty.h>
+#include <metainfo.h>
+#include <nodeinstanceview.h>
+#include <nodelistproperty.h>
#include <nodemetainfo.h>
#include <nodeproperty.h>
-#include <nodelistproperty.h>
-#include <nodeinstanceview.h>
-#include <metainfo.h>
-
#include <rewritingexception.h>
#include <variantproperty.h>
-
-#include <bindingproperty.h>
+#include <qmldesignerconstants.h>
+#include <qmldesignerplugin.h>
+#include <qmltimeline.h>
#include <theme.h>
@@ -52,6 +51,7 @@
#include <qmldesignerplugin.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
+#include <propertyeditorqmlbackend.h>
#include <QApplication>
#include <QDebug>
@@ -63,6 +63,7 @@
#include <QStackedWidget>
#include <QShortcut>
#include <QTimer>
+#include <QColorDialog>
namespace QmlDesigner {
@@ -83,9 +84,14 @@ MaterialEditorView::MaterialEditorView(QWidget *parent)
}
});
+ m_typeUpdateTimer.setSingleShot(true);
+ m_typeUpdateTimer.setInterval(500);
+ connect(&m_typeUpdateTimer, &QTimer::timeout, this, &MaterialEditorView::updatePossibleTypes);
+
m_stackedWidget->setStyleSheet(Theme::replaceCssColors(
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
m_stackedWidget->setMinimumWidth(250);
+ QmlDesignerPlugin::trackWidgetFocusTime(m_stackedWidget, Constants::EVENT_MATERIALEDITOR_TIME);
}
MaterialEditorView::~MaterialEditorView()
@@ -419,12 +425,15 @@ void MaterialEditorView::handleToolBarAction(int action)
if (!model())
break;
executeInTransaction("MaterialEditorView:handleToolBarAction", [&] {
+ ModelNode matLib = materialLibraryNode();
+ if (!matLib.isValid())
+ return;
+
NodeMetaInfo metaInfo = model()->metaInfo("QtQuick3D.DefaultMaterial");
ModelNode newMatNode = createModelNode("QtQuick3D.DefaultMaterial", metaInfo.majorVersion(),
metaInfo.minorVersion());
renameMaterial(newMatNode, "New Material");
-
- materialLibraryNode().defaultNodeListProperty().reparentHere(newMatNode);
+ matLib.defaultNodeListProperty().reparentHere(newMatNode);
});
break;
}
@@ -442,18 +451,110 @@ void MaterialEditorView::handleToolBarAction(int action)
}
}
+void MaterialEditorView::handlePreviewEnvChanged(const QString &envAndValue)
+{
+ if (envAndValue.isEmpty() || m_initializingPreviewData)
+ return;
+
+ QTC_ASSERT(m_hasQuick3DImport, return);
+ QTC_ASSERT(model(), return);
+ QTC_ASSERT(model()->nodeInstanceView(), return);
+
+ QStringList parts = envAndValue.split('=');
+ QString env = parts[0];
+ QString value;
+ if (parts.size() > 1)
+ value = parts[1];
+
+ PropertyName matPrevEnvAuxProp("matPrevEnv");
+ PropertyName matPrevEnvValueAuxProp("matPrevEnvValue");
+
+ auto renderPreviews = [=](const QString &auxEnv, const QString &auxValue) {
+ rootModelNode().setAuxiliaryData(matPrevEnvAuxProp, auxEnv);
+ rootModelNode().setAuxiliaryData(matPrevEnvValueAuxProp, auxValue);
+ QTimer::singleShot(0, this, &MaterialEditorView::requestPreviewRender);
+ emitCustomNotification("refresh_material_browser", {});
+ };
+
+ if (env == "Color") {
+ m_colorDialog.clear();
+
+ // Store color to separate property to persist selection over non-color env changes
+ PropertyName colorAuxProp("matPrevColor");
+ QString oldColor = rootModelNode().auxiliaryData(colorAuxProp).toString();
+ QString oldEnv = rootModelNode().auxiliaryData(matPrevEnvAuxProp).toString();
+ QString oldValue = rootModelNode().auxiliaryData(matPrevEnvValueAuxProp).toString();
+
+ m_colorDialog = new QColorDialog(Core::ICore::dialogParent());
+ m_colorDialog->setModal(true);
+ m_colorDialog->setAttribute(Qt::WA_DeleteOnClose);
+ m_colorDialog->setCurrentColor(QColor(oldColor));
+ m_colorDialog->show();
+
+ QObject::connect(m_colorDialog, &QColorDialog::currentColorChanged,
+ m_colorDialog, [=](const QColor &color) {
+ renderPreviews(env, color.name());
+ });
+
+ QObject::connect(m_colorDialog, &QColorDialog::colorSelected,
+ m_colorDialog, [=](const QColor &color) {
+ renderPreviews(env, color.name());
+ rootModelNode().setAuxiliaryData(colorAuxProp, color.name());
+ });
+
+ QObject::connect(m_colorDialog, &QColorDialog::rejected,
+ m_colorDialog, [=]() {
+ renderPreviews(oldEnv, oldValue);
+ initPreviewData();
+ });
+ return;
+ }
+ renderPreviews(env, value);
+}
+
+void MaterialEditorView::handlePreviewModelChanged(const QString &modelStr)
+{
+ if (modelStr.isEmpty() || m_initializingPreviewData)
+ return;
+
+ QTC_ASSERT(m_hasQuick3DImport, return);
+ QTC_ASSERT(model(), return);
+ QTC_ASSERT(model()->nodeInstanceView(), return);
+
+ rootModelNode().setAuxiliaryData("matPrevModel", modelStr);
+
+ QTimer::singleShot(0, this, &MaterialEditorView::requestPreviewRender);
+ emitCustomNotification("refresh_material_browser", {});
+}
+
void MaterialEditorView::setupQmlBackend()
{
QUrl qmlPaneUrl;
QUrl qmlSpecificsUrl;
+ QString specificQmlData;
+ QString currentTypeName;
if (m_selectedMaterial.isValid() && m_hasQuick3DImport) {
qmlPaneUrl = QUrl::fromLocalFile(materialEditorResourcesPath() + "/MaterialEditorPane.qml");
+ TypeName diffClassName;
NodeMetaInfo metaInfo = m_selectedMaterial.metaInfo();
- QDir importDir(metaInfo.importDirectoryPath() + Constants::QML_DESIGNER_SUBFOLDER);
- QString typeName = QString::fromUtf8(metaInfo.typeName().split('.').constLast());
- qmlSpecificsUrl = QUrl::fromLocalFile(importDir.absoluteFilePath(typeName + "Specifics.qml"));
+ if (metaInfo.isValid()) {
+ diffClassName = metaInfo.typeName();
+ const QList<NodeMetaInfo> hierarchy = metaInfo.classHierarchy();
+ for (const NodeMetaInfo &metaInfo : hierarchy) {
+ if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsUrl))
+ break;
+ qmlSpecificsUrl = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName()
+ + "Specifics", metaInfo);
+ diffClassName = metaInfo.typeName();
+ }
+ }
+ if (metaInfo.isValid() && diffClassName != m_selectedMaterial.type()) {
+ specificQmlData = PropertyEditorQmlBackend::templateGeneration(
+ metaInfo, model()->metaInfo(diffClassName), m_selectedMaterial);
+ }
+ currentTypeName = QString::fromLatin1(m_selectedMaterial.type());
} else {
qmlPaneUrl = QUrl::fromLocalFile(materialEditorResourcesPath() + "/EmptyMaterialEditorPane.qml");
}
@@ -472,17 +573,29 @@ void MaterialEditorView::setupQmlBackend()
currentQmlBackend->setSource(qmlPaneUrl);
- QObject::connect(currentQmlBackend->widget()->rootObject(), SIGNAL(toolBarAction(int)),
+ QObject *rootObj = currentQmlBackend->widget()->rootObject();
+ QObject::connect(rootObj, SIGNAL(toolBarAction(int)),
this, SLOT(handleToolBarAction(int)));
+ QObject::connect(rootObj, SIGNAL(previewEnvChanged(QString)),
+ this, SLOT(handlePreviewEnvChanged(QString)));
+ QObject::connect(rootObj, SIGNAL(previewModelChanged(QString)),
+ this, SLOT(handlePreviewModelChanged(QString)));
} else {
currentQmlBackend->setup(m_selectedMaterial, currentStateName, qmlSpecificsUrl, this);
}
+ currentQmlBackend->widget()->installEventFilter(this);
currentQmlBackend->contextObject()->setHasQuick3DImport(m_hasQuick3DImport);
-
- m_stackedWidget->setCurrentWidget(currentQmlBackend->widget());
+ currentQmlBackend->contextObject()->setHasMaterialRoot(m_hasMaterialRoot);
+ currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
+ currentQmlBackend->contextObject()->setCurrentType(currentTypeName);
m_qmlBackEnd = currentQmlBackend;
+
+ delayedTypeUpdate();
+ initPreviewData();
+
+ m_stackedWidget->setCurrentWidget(m_qmlBackEnd->widget());
}
void MaterialEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value)
@@ -528,6 +641,75 @@ bool MaterialEditorView::noValidSelection() const
return !QmlObjectNode::isValidQmlObjectNode(m_selectedMaterial);
}
+void MaterialEditorView::initPreviewData()
+{
+ if (model() && m_qmlBackEnd) {
+ QString env = rootModelNode().auxiliaryData("matPrevEnv").toString();
+ QString envValue = rootModelNode().auxiliaryData("matPrevEnvValue").toString();
+ QString modelStr = rootModelNode().auxiliaryData("matPrevModel").toString();
+ if (!envValue.isEmpty() && env != "Color" && env != "Default") {
+ env += '=';
+ env += envValue;
+ }
+ if (env.isEmpty())
+ env = "Default";
+ if (modelStr.isEmpty())
+ modelStr = "#Sphere";
+ m_initializingPreviewData = true;
+ QMetaObject::invokeMethod(m_qmlBackEnd->widget()->rootObject(),
+ "initPreviewData",
+ Q_ARG(QVariant, env), Q_ARG(QVariant, modelStr));
+ m_initializingPreviewData = false;
+ }
+}
+
+void MaterialEditorView::delayedTypeUpdate()
+{
+ m_typeUpdateTimer.start();
+}
+
+static Import entryToImport(const ItemLibraryEntry &entry)
+{
+ if (entry.majorVersion() == -1 && entry.minorVersion() == -1)
+ return Import::createFileImport(entry.requiredImport());
+ return Import::createLibraryImport(entry.requiredImport(),
+ QString::number(entry.majorVersion()) + QLatin1Char('.') +
+ QString::number(entry.minorVersion()));
+}
+
+void MaterialEditorView::updatePossibleTypes()
+{
+ QTC_ASSERT(model(), return);
+
+ if (!m_qmlBackEnd)
+ return;
+
+ // Ensure basic types are always first
+ static const QStringList basicTypes {"DefaultMaterial", "PrincipledMaterial", "CustomMaterial"};
+ QStringList allTypes = basicTypes;
+
+ const QList<ItemLibraryEntry> itemLibEntries = m_itemLibraryInfo->entries();
+ for (const ItemLibraryEntry &entry : itemLibEntries) {
+ NodeMetaInfo metaInfo = model()->metaInfo(entry.typeName());
+ bool valid = metaInfo.isValid()
+ && (metaInfo.majorVersion() >= entry.majorVersion()
+ || metaInfo.majorVersion() < 0);
+ if (valid && metaInfo.isSubclassOf("QtQuick3D.Material")) {
+ bool addImport = entry.requiredImport().isEmpty();
+ if (!addImport) {
+ Import import = entryToImport(entry);
+ addImport = model()->hasImport(import, true, true);
+ }
+ if (addImport) {
+ QString typeName = QString::fromLatin1(entry.typeName().split('.').last());
+ if (!allTypes.contains(typeName))
+ allTypes.append(typeName);
+ }
+ }
+ }
+ m_qmlBackEnd->contextObject()->setPossibleTypes(allTypes);
+}
+
void MaterialEditorView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
@@ -535,11 +717,27 @@ void MaterialEditorView::modelAttached(Model *model)
m_locked = true;
m_hasQuick3DImport = model->hasImport("QtQuick3D");
+ m_hasMaterialRoot = rootModelNode().isSubclassOf("QtQuick3D.Material");
- // Creating the material library node on model attach causes errors as long as the type information
- // not complete yet, so we keep checking until type info is complete.
- if (m_hasQuick3DImport)
+ if (m_hasMaterialRoot) {
+ m_selectedMaterial = rootModelNode();
+ } else if (m_hasQuick3DImport) {
+ // Creating the material library node on model attach causes errors as long as the type
+ // information is not complete yet, so we keep checking until type info is complete.
m_ensureMatLibTimer.start(500);
+ }
+
+ if (m_itemLibraryInfo.data() != model->metaInfo().itemLibraryInfo()) {
+ if (m_itemLibraryInfo) {
+ disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
+ this, &MaterialEditorView::delayedTypeUpdate);
+ }
+ m_itemLibraryInfo = model->metaInfo().itemLibraryInfo();
+ if (m_itemLibraryInfo) {
+ connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
+ this, &MaterialEditorView::delayedTypeUpdate);
+ }
+ }
if (!m_setupCompleted) {
reloadQml();
@@ -647,7 +845,11 @@ bool MaterialEditorView::hasWidget() const
WidgetInfo MaterialEditorView::widgetInfo()
{
- return createWidgetInfo(m_stackedWidget, nullptr, "MaterialEditor", WidgetInfo::RightPane, 0, tr("Material Editor"));
+ return createWidgetInfo(m_stackedWidget,
+ "MaterialEditor",
+ WidgetInfo::RightPane,
+ 0,
+ tr("Material Editor"));
}
void MaterialEditorView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
@@ -700,10 +902,20 @@ void MaterialEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
m_locked = false;
}
-void MaterialEditorView::nodeTypeChanged(const ModelNode &node, const TypeName &, int, int)
+void MaterialEditorView::nodeTypeChanged(const ModelNode &node, const TypeName &typeName, int, int)
{
- if (node == m_selectedMaterial)
+ if (node == m_selectedMaterial) {
+ m_qmlBackEnd->contextObject()->setCurrentType(QString::fromLatin1(typeName));
delayedResetView();
+ }
+}
+
+void MaterialEditorView::rootNodeTypeChanged(const QString &type, int, int)
+{
+ if (rootModelNode() == m_selectedMaterial) {
+ m_qmlBackEnd->contextObject()->setCurrentType(type);
+ delayedResetView();
+ }
}
void MaterialEditorView::modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap)
@@ -749,6 +961,10 @@ void MaterialEditorView::duplicateMaterial(const ModelNode &material)
QmlObjectNode sourceMat(material);
executeInTransaction(__FUNCTION__, [&] {
+ ModelNode matLib = materialLibraryNode();
+ if (!matLib.isValid())
+ return;
+
// create the duplicate material
NodeMetaInfo metaInfo = model()->metaInfo(matType);
QmlObjectNode duplicateMat = createModelNode(matType, metaInfo.majorVersion(), metaInfo.minorVersion());
@@ -770,7 +986,7 @@ void MaterialEditorView::duplicateMaterial(const ModelNode &material)
duplicateMat.setBindingProperty(prop.name(), prop.toBindingProperty().expression());
}
- materialLibraryNode().defaultNodeListProperty().reparentHere(duplicateMat);
+ matLib.defaultNodeListProperty().reparentHere(duplicateMat);
});
}
@@ -780,8 +996,10 @@ void MaterialEditorView::customNotification(const AbstractView *view, const QStr
Q_UNUSED(view)
if (identifier == "selected_material_changed") {
- m_selectedMaterial = nodeList.first();
- QTimer::singleShot(0, this, &MaterialEditorView::resetView);
+ if (!m_hasMaterialRoot) {
+ m_selectedMaterial = nodeList.first();
+ QTimer::singleShot(0, this, &MaterialEditorView::resetView);
+ }
} else if (identifier == "apply_to_selected_triggered") {
applyMaterialToSelectedModels(nodeList.first(), data.first().toBool());
} else if (identifier == "rename_material") {
@@ -840,6 +1058,15 @@ void MaterialEditorView::setValue(const QmlObjectNode &qmlObjectNode, const Prop
m_locked = false;
}
+bool MaterialEditorView::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::FocusOut) {
+ if (m_qmlBackEnd && m_qmlBackEnd->widget() == obj)
+ QMetaObject::invokeMethod(m_qmlBackEnd->widget()->rootObject(), "closeContextMenu");
+ }
+ return QObject::eventFilter(obj, event);
+}
+
void MaterialEditorView::reloadQml()
{
m_qmlBackendHash.clear();
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h
index ff734ed30b8..e631ae9ca8a 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h
@@ -26,13 +26,17 @@
#pragma once
#include <abstractview.h>
+#include <itemlibraryinfo.h>
+
#include <QHash>
+#include <QPointer>
#include <QTimer>
QT_BEGIN_NAMESPACE
class QShortcut;
class QStackedWidget;
class QTimer;
+class QColorDialog;
QT_END_NAMESPACE
namespace QmlDesigner {
@@ -68,6 +72,7 @@ public:
void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList) override;
void nodeTypeChanged(const ModelNode& node, const TypeName &type, int majorVersion, int minorVersion) override;
+ void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap) override;
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier,
@@ -87,10 +92,13 @@ public:
public slots:
void handleToolBarAction(int action);
+ void handlePreviewEnvChanged(const QString &envAndValue);
+ void handlePreviewModelChanged(const QString &modelStr);
protected:
void timerEvent(QTimerEvent *event) override;
void setValue(const QmlObjectNode &fxObjectNode, const PropertyName &name, const QVariant &value);
+ bool eventFilter(QObject *obj, QEvent *event) override;
private:
static QString materialEditorResourcesPath();
@@ -113,8 +121,13 @@ private:
bool noValidSelection() const;
+ void initPreviewData();
+ void delayedTypeUpdate();
+ void updatePossibleTypes();
+
ModelNode m_selectedMaterial;
QTimer m_ensureMatLibTimer;
+ QTimer m_typeUpdateTimer;
QShortcut *m_updateShortcut = nullptr;
int m_timerId = 0;
QStackedWidget *m_stackedWidget = nullptr;
@@ -124,6 +137,11 @@ private:
bool m_locked = false;
bool m_setupCompleted = false;
bool m_hasQuick3DImport = false;
+ bool m_hasMaterialRoot = false;
+ bool m_initializingPreviewData = false;
+
+ QPointer<QColorDialog> m_colorDialog;
+ QPointer<ItemLibraryInfo> m_itemLibraryInfo;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index f8d5c884fbd..cc3934b6289 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -134,7 +134,6 @@ WidgetInfo NavigatorView::widgetInfo()
setupWidget();
return createWidgetInfo(m_widget.data(),
- new WidgetInfo::ToolBarWidgetDefaultFactory<NavigatorWidget>(m_widget.data()),
QStringLiteral("Navigator"),
WidgetInfo::LeftPane,
0,
diff --git a/src/plugins/qmldesigner/components/pathtool/pathitem.cpp b/src/plugins/qmldesigner/components/pathtool/pathitem.cpp
index 47df2b3e9fd..6a43508bde8 100644
--- a/src/plugins/qmldesigner/components/pathtool/pathitem.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathitem.cpp
@@ -134,17 +134,17 @@ void PathItem::writePathToProperty()
ModelNode pathNode = pathModelNode(formEditorItem());
- pathNode.view()->executeInTransaction("PathItem::writePathToProperty", [this, &pathNode](){
+ pathNode.view()->executeInTransaction("PathItem::writePathToProperty", [this, &pathNode]() {
QList<ModelNode> pathSegmentNodes = pathNode.nodeListProperty("pathElements").toModelNodeList();
- foreach (ModelNode pathSegment, pathSegmentNodes)
+ for (ModelNode pathSegment : pathSegmentNodes)
pathSegment.destroy();
if (!m_cubicSegments.isEmpty()) {
pathNode.variantProperty("startX").setValue(m_cubicSegments.constFirst().firstControlPoint().coordinate().x());
pathNode.variantProperty("startY").setValue(m_cubicSegments.constFirst().firstControlPoint().coordinate().y());
- foreach (const CubicSegment &cubicSegment, m_cubicSegments) {
+ for (const CubicSegment &cubicSegment : qAsConst(m_cubicSegments)) {
writePathAttributes(pathNode, cubicSegment.attributes());
writePathPercent(pathNode, cubicSegment.percent());
@@ -171,7 +171,7 @@ void PathItem::writePathAsCubicSegmentsOnly()
QList<ModelNode> pathSegmentNodes = pathNode.nodeListProperty("pathElements").toModelNodeList();
- foreach (ModelNode pathSegment, pathSegmentNodes)
+ for (ModelNode pathSegment : pathSegmentNodes)
pathSegment.destroy();
if (!m_cubicSegments.isEmpty()) {
@@ -179,7 +179,7 @@ void PathItem::writePathAsCubicSegmentsOnly()
pathNode.variantProperty("startY").setValue(m_cubicSegments.constFirst().firstControlPoint().coordinate().y());
- foreach (const CubicSegment &cubicSegment, m_cubicSegments) {
+ for (const CubicSegment &cubicSegment : qAsConst(m_cubicSegments)) {
writePathAttributes(pathNode, cubicSegment.attributes());
writePathPercent(pathNode, cubicSegment.percent());
writeCubicPath(pathNode, cubicSegment);
@@ -234,7 +234,7 @@ static void drawCubicSegments(const QList<CubicSegment> &cubicSegments, QPainter
QPainterPath curvePainterPath(cubicSegments.constFirst().firstControlPoint().coordinate());
- foreach (const CubicSegment &cubicSegment, cubicSegments)
+ for (const CubicSegment &cubicSegment : cubicSegments)
addCubicSegmentToPainterPath(cubicSegment, curvePainterPath);
painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
@@ -269,7 +269,7 @@ static void drawControlLines(const QList<CubicSegment> &cubicSegments, QPainter
painter->save();
painter->setRenderHint(QPainter::Antialiasing, false);
- foreach (const CubicSegment &cubicSegment, cubicSegments)
+ for (const CubicSegment &cubicSegment : cubicSegments)
drawControlLine(cubicSegment, painter);
painter->restore();
@@ -313,7 +313,7 @@ static void drawControlPoints(const QList<ControlPoint> &controlPoints, const QL
{
painter->save();
- foreach (const ControlPoint &controlPoint, controlPoints)
+ for (const ControlPoint &controlPoint : controlPoints)
drawControlPoint(controlPoint, selectionPoints, painter);
painter->restore();
@@ -337,7 +337,7 @@ static void drawPostionOverlays(const QList<SelectionPoint> &selectedPoints, QPa
painter->setFont(font);
painter->setPen(QColor(0, 0, 0));
- foreach (const SelectionPoint &selectedPoint, selectedPoints)
+ for (const SelectionPoint &selectedPoint : selectedPoints)
drawPositionOverlay(selectedPoint.controlPoint, painter);
painter->restore();
@@ -465,7 +465,7 @@ static QRectF boundingRectForPath(const QList<ControlPoint> &controlPoints)
double yMinimum = 0.;
double yMaximum = 0.;
- foreach (const ControlPoint & controlPoint, controlPoints) {
+ for (const ControlPoint & controlPoint : controlPoints) {
xMinimum = qMin(xMinimum, controlPoint.coordinate().x());
xMaximum = qMax(xMaximum, controlPoint.coordinate().x());
yMinimum = qMin(yMinimum, controlPoint.coordinate().y());
@@ -507,7 +507,8 @@ void PathItem::readControlPoints()
QMap<QString, QVariant> actualAttributes;
double percent = -1.0;
- foreach (const ModelNode &childNode, pathNode.nodeListProperty("pathElements").toModelNodeList()) {
+ const QList<ModelNode> childNodes = pathNode.nodeListProperty("pathElements").toModelNodeList();
+ for (const ModelNode &childNode : childNodes) {
if (childNode.type() == "QtQuick.PathAttribute") {
actualAttributes.insert(childNode.variantProperty("name").value().toString(), childNode.variantProperty("value").value());
@@ -554,7 +555,7 @@ static CubicSegment getMinimumDistanceSegment(const QPointF &pickPoint, const QL
CubicSegment minimumDistanceSegment;
double actualMinimumDistance = maximumDistance;
- foreach (const CubicSegment &cubicSegment, cubicSegments) {
+ for (const CubicSegment &cubicSegment : cubicSegments) {
double tSegment = 0.;
double cubicSegmentMinimumDistance = cubicSegment.minimumDistance(pickPoint, tSegment);
if (cubicSegmentMinimumDistance < actualMinimumDistance) {
@@ -689,7 +690,7 @@ const QList<ControlPoint> PathItem::controlPoints() const
if (!m_cubicSegments.isEmpty())
controlPointList.append(m_cubicSegments.constFirst().firstControlPoint());
- foreach (const CubicSegment &cubicSegment, m_cubicSegments) {
+ for (const CubicSegment &cubicSegment : qAsConst(m_cubicSegments)) {
controlPointList.append(cubicSegment.secondControlPoint());
controlPointList.append(cubicSegment.thirdControlPoint());
controlPointList.append(cubicSegment.fourthControlPoint());
@@ -703,7 +704,7 @@ const QList<ControlPoint> PathItem::controlPoints() const
bool hasLineOrQuadPathElements(const QList<ModelNode> &modelNodes)
{
- foreach (const ModelNode &modelNode, modelNodes) {
+ for (const ModelNode &modelNode : modelNodes) {
if (modelNode.type() == "QtQuick.PathLine"
|| modelNode.type() == "QtQuick.PathQuad")
return true;
@@ -752,7 +753,7 @@ static bool controlPointIsNearMousePosition(const ControlPoint &controlPoint, co
static bool controlPointsAreNearMousePosition(const QList<ControlPoint> &controlPoints, const QPointF &mousePosition)
{
- foreach (const ControlPoint &controlPoint, controlPoints) {
+ for (const ControlPoint &controlPoint : controlPoints) {
if (controlPointIsNearMousePosition(controlPoint, mousePosition))
return true;
}
@@ -762,7 +763,7 @@ static bool controlPointsAreNearMousePosition(const QList<ControlPoint> &control
static ControlPoint pickControlPoint(const QList<ControlPoint> &controlPoints, const QPointF &mousePosition)
{
- foreach (const ControlPoint &controlPoint, controlPoints) {
+ for (const ControlPoint &controlPoint : controlPoints) {
if (controlPointIsNearMousePosition(controlPoint, mousePosition))
return controlPoint;
}
@@ -837,7 +838,7 @@ void PathItem::updatePathModelNodes(const QList<SelectionPoint> &changedPoints)
RewriterTransaction rewriterTransaction =
formEditorItem()->qmlItemNode().view()->beginRewriterTransaction(QByteArrayLiteral("PathItem::createCubicSegmentContextMenu"));
- foreach (SelectionPoint changedPoint, changedPoints)
+ for (SelectionPoint changedPoint : changedPoints)
changedPoint.controlPoint.updateModelNode();
rewriterTransaction.commit();
@@ -923,7 +924,7 @@ QList<CubicSegment> cubicSegmentsContainingControlPoint(const ControlPoint &cont
{
QList<CubicSegment> cubicSegmentsHasControlPoint;
- foreach (const CubicSegment &cubicSegment, allCubicSegments) {
+ for (const CubicSegment &cubicSegment : allCubicSegments) {
if (cubicSegment.controlPoints().contains(controlPoint))
cubicSegmentsHasControlPoint.append(cubicSegment);
}
diff --git a/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp b/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp
index 6df69762334..7d09958bd3c 100644
--- a/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp
@@ -119,13 +119,13 @@ QList<ControlPoint> PathSelectionManipulator::allControlPoints()
{
QList<ControlPoint> controlPoints;
- foreach (const SelectionPoint &selectionPoint, m_singleSelectedPoints)
+ for (const SelectionPoint &selectionPoint : qAsConst(m_singleSelectedPoints))
controlPoints.append(selectionPoint.controlPoint);
- foreach (const SelectionPoint &selectionPoint, m_automaticallyAddedSinglePoints)
+ for (const SelectionPoint &selectionPoint : qAsConst(m_automaticallyAddedSinglePoints))
controlPoints.append(selectionPoint.controlPoint);
- foreach (const SelectionPoint &selectionPoint, m_multiSelectedPoints)
+ for (const SelectionPoint &selectionPoint : qAsConst(m_multiSelectedPoints))
controlPoints.append(selectionPoint.controlPoint);
return controlPoints;
@@ -155,7 +155,8 @@ void PathSelectionManipulator::updateMultiSelection(const QPointF &updatePoint)
QRectF selectionRect(m_startPoint, updatePoint);
- foreach (const ControlPoint &controlPoint, m_pathItem->controlPoints()) {
+ const QList<ControlPoint> controlPoints = m_pathItem->controlPoints();
+ for (const ControlPoint &controlPoint : controlPoints) {
if (selectionRect.contains(controlPoint.coordinate()))
addMultiSelectionControlPoint(controlPoint);
}
@@ -236,7 +237,7 @@ QPointF manipulatedVector(const QPointF &vector, Qt::KeyboardModifiers keyboardM
static void moveControlPoints(const QList<SelectionPoint> &movePoints, const QPointF &offsetVector)
{
- foreach (SelectionPoint movePoint, movePoints)
+ for (SelectionPoint movePoint : movePoints)
movePoint.controlPoint.setCoordinate(movePoint.startPosition + offsetVector);
}
@@ -266,11 +267,11 @@ bool PathSelectionManipulator::isMoving() const
void PathSelectionManipulator::updateMultiSelectedStartPoint()
{
- QList<SelectionPoint> oldSelectionPoints = m_multiSelectedPoints;
+ const QList<SelectionPoint> oldSelectionPoints = m_multiSelectedPoints;
m_multiSelectedPoints.clear();
- foreach (SelectionPoint selectionPoint, oldSelectionPoints) {
+ for (SelectionPoint selectionPoint : oldSelectionPoints) {
selectionPoint.startPosition = selectionPoint.controlPoint.coordinate();
m_multiSelectedPoints.append(selectionPoint);
}
diff --git a/src/plugins/qmldesigner/components/pathtool/pathtool.cpp b/src/plugins/qmldesigner/components/pathtool/pathtool.cpp
index 88fdd70f5f3..52976bc0e9c 100644
--- a/src/plugins/qmldesigner/components/pathtool/pathtool.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathtool.cpp
@@ -277,7 +277,7 @@ void PathTool::instancesParentChanged(const QList<FormEditorItem *> & /*itemLis
void PathTool::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > &propertyList)
{
using ModelNodePropertyNamePair = QPair<ModelNode, PropertyName>;
- foreach (const ModelNodePropertyNamePair &propertyPair, propertyList) {
+ for (const ModelNodePropertyNamePair &propertyPair : propertyList) {
if (propertyPair.first == m_pathItem->formEditorItem()->qmlItemNode().modelNode()
&& propertyPair.second == "path")
m_pathItem->updatePath();
diff --git a/src/plugins/qmldesigner/components/pathtool/pathtoolview.cpp b/src/plugins/qmldesigner/components/pathtool/pathtoolview.cpp
index ea1e28832ad..063b2f7f19f 100644
--- a/src/plugins/qmldesigner/components/pathtool/pathtoolview.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathtoolview.cpp
@@ -78,7 +78,7 @@ bool variantPropertyInEditedPath(const VariantProperty &variantProperty, const M
bool changesEditedPath(const QList<VariantProperty> &propertyList, const ModelNode &editingPathViewModelNode)
{
- foreach (const VariantProperty variantProperty, propertyList) {
+ for (const VariantProperty &variantProperty : propertyList) {
if (variantPropertyInEditedPath(variantProperty, editingPathViewModelNode))
return true;
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
index 18fcba3efc2..0777773400b 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
@@ -65,6 +65,9 @@ void FileResourcesModel::setModelNodeBackend(const QVariant &modelNodeBackend)
if (backendObjectCasted) {
QmlDesigner::Model *model = backendObjectCasted->qmlObjectNode().modelNode().model();
+ if (!model)
+ return;
+
m_docPath = QDir{QFileInfo{model->fileUrl().toLocalFile()}.absolutePath()};
m_path = QUrl::fromLocalFile(
QmlDesigner::DocumentManager::currentProjectDirPath().toFileInfo().absoluteFilePath());
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
index d00957fa8cf..c3e201bf1d9 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
@@ -79,7 +79,7 @@ QmlJS::SimpleReaderNode::Ptr templateConfiguration()
QStringList variantToStringList(const QVariant &variant) {
QStringList stringList;
- foreach (const QVariant &singleValue, variant.toList())
+ for (const QVariant &singleValue : variant.toList())
stringList << singleValue.toString();
return stringList;
@@ -415,7 +415,8 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
if (propertyEditorBenchmark().isInfoEnabled())
time.start();
- foreach (const PropertyName &propertyName, qmlObjectNode.modelNode().metaInfo().propertyNames())
+ const QList<PropertyName> propertyNames = qmlObjectNode.modelNode().metaInfo().propertyNames();
+ for (const PropertyName &propertyName : propertyNames)
createPropertyEditorValue(qmlObjectNode, propertyName, qmlObjectNode.instanceValue(propertyName), propertyEditor);
setupLayoutAttachedProperties(qmlObjectNode, propertyEditor);
@@ -513,7 +514,8 @@ void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl
{
NodeMetaInfo metaInfo = propertyEditor->model()->metaInfo(typeName);
- foreach (const PropertyName &propertyName, metaInfo.propertyNames())
+ const QList<PropertyName> propertyNames = metaInfo.propertyNames();
+ for (const PropertyName &propertyName : propertyNames)
setupPropertyEditorValue(propertyName, propertyEditor, QString::fromUtf8(metaInfo.propertyTypeName(propertyName)));
auto valueObject = qobject_cast<PropertyEditorValue *>(variantToQObject(
@@ -903,7 +905,8 @@ void PropertyEditorQmlBackend::setValueforAuxiliaryProperties(const QmlObjectNod
QUrl PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo, TypeName &className)
{
if (metaInfo.isValid()) {
- foreach (const NodeMetaInfo &info, metaInfo.classHierarchy()) {
+ const QList<NodeMetaInfo> hierarchy = metaInfo.classHierarchy();
+ for (const NodeMetaInfo &info : hierarchy) {
QUrl fileUrl = fileToUrl(locateQmlFile(info, QString::fromUtf8(qmlFileName(info))));
if (fileUrl.isValid()) {
className = info.typeName();
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
index fd568911abc..c68db4c57f7 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
@@ -643,10 +643,10 @@ void PropertyEditorNodeWrapper::remove()
}
m_modelNode = QmlDesigner::ModelNode();
- foreach (const QString &propertyName, m_valuesPropertyMap.keys())
+ const QStringList propertyNames = m_valuesPropertyMap.keys();
+ for (const QString &propertyName : propertyNames)
m_valuesPropertyMap.clear(propertyName);
- foreach (QObject *object, m_valuesPropertyMap.children())
- delete object;
+ qDeleteAll(m_valuesPropertyMap.children());
emit propertiesChanged();
emit existsChanged();
}
@@ -676,12 +676,13 @@ void PropertyEditorNodeWrapper::setup()
Q_ASSERT(m_editorValue->modelNode().isValid());
if ((m_editorValue->modelNode().isValid() && m_modelNode.isValid())) {
QmlDesigner::QmlObjectNode qmlObjectNode(m_modelNode);
- foreach ( const QString &propertyName, m_valuesPropertyMap.keys())
+ const QStringList propertyNames = m_valuesPropertyMap.keys();
+ for (const QString &propertyName : propertyNames)
m_valuesPropertyMap.clear(propertyName);
- foreach (QObject *object, m_valuesPropertyMap.children())
- delete object;
+ qDeleteAll(m_valuesPropertyMap.children());
- foreach (const QmlDesigner::PropertyName &propertyName, m_modelNode.metaInfo().propertyNames()) {
+ const QList<QmlDesigner::PropertyName> propertyNameList = m_modelNode.metaInfo().propertyNames();
+ for (const QmlDesigner::PropertyName &propertyName : propertyNameList) {
if (qmlObjectNode.isValid()) {
auto valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
valueObject->setName(propertyName);
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
index 4ae156dc921..af96ddd5813 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
@@ -187,4 +187,3 @@ private:
QML_DECLARE_TYPE(PropertyEditorValue)
QML_DECLARE_TYPE(PropertyEditorNodeWrapper)
-QML_DECLARE_TYPE(QQmlPropertyMap)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
index b516bba9c95..fb1be16dc73 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
@@ -46,6 +46,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
#include <utils/fileutils.h>
+#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
@@ -463,7 +464,8 @@ void PropertyEditorView::setupQmlBackend()
TypeName diffClassName;
if (commonAncestor.isValid()) {
diffClassName = commonAncestor.typeName();
- foreach (const NodeMetaInfo &metaInfo, commonAncestor.classHierarchy()) {
+ const QList<NodeMetaInfo> hierarchy = commonAncestor.classHierarchy();
+ for (const NodeMetaInfo &metaInfo : hierarchy) {
if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsFile))
break;
qmlSpecificsFile = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName() + "Specifics", metaInfo);
@@ -640,7 +642,7 @@ void PropertyEditorView::propertiesRemoved(const QList<AbstractProperty>& proper
if (noValidSelection())
return;
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
ModelNode node(property.parentModelNode());
if (node.isRootNode() && !m_selectedNode.isRootNode())
@@ -678,7 +680,7 @@ void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>&
if (noValidSelection())
return;
- foreach (const VariantProperty &property, propertyList) {
+ for (const VariantProperty &property : propertyList) {
ModelNode node(property.parentModelNode());
if (propertyIsAttachedLayoutProperty(property.name()))
@@ -701,7 +703,7 @@ void PropertyEditorView::bindingPropertiesChanged(const QList<BindingProperty>&
if (noValidSelection())
return;
- foreach (const BindingProperty &property, propertyList) {
+ for (const BindingProperty &property : propertyList) {
ModelNode node(property.parentModelNode());
if (property.isAliasExport())
@@ -790,7 +792,7 @@ bool PropertyEditorView::hasWidget() const
WidgetInfo PropertyEditorView::widgetInfo()
{
- return createWidgetInfo(m_stackedWidget, nullptr, QStringLiteral("Properties"), WidgetInfo::RightPane, 0, tr("Properties"));
+ return createWidgetInfo(m_stackedWidget, QStringLiteral("Properties"), WidgetInfo::RightPane, 0, tr("Properties"));
}
void PropertyEditorView::currentStateChanged(const ModelNode &node)
@@ -809,7 +811,7 @@ void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
m_locked = true;
using ModelNodePropertyPair = QPair<ModelNode, PropertyName>;
- foreach (const ModelNodePropertyPair &propertyPair, propertyList) {
+ for (const ModelNodePropertyPair &propertyPair : propertyList) {
const ModelNode modelNode = propertyPair.first;
const QmlObjectNode qmlObjectNode(modelNode);
const PropertyName propertyName = propertyPair.second;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp
index 2664f2c7a90..fd16a282920 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp
@@ -592,11 +592,11 @@ QStringList QmlAnchorBindingProxy::possibleTargetItems() const
itemList.removeOne(m_qmlItemNode);
//We currently have no instanceChildren().
//So we double check here if the instanceParents are equal.
- foreach (const QmlItemNode &node, itemList)
+ for (const QmlItemNode &node : qAsConst(itemList))
if (node.isValid() && (node.instanceParent().modelNode() != m_qmlItemNode.instanceParent().modelNode()))
itemList.removeAll(node);
- foreach (const QmlItemNode &itemNode, itemList) {
+ for (const QmlItemNode &itemNode : qAsConst(itemList)) {
if (itemNode.isValid() && !itemNode.id().isEmpty())
stringList.append(itemNode.id());
}
diff --git a/src/plugins/qmldesigner/components/resources/resources.qrc b/src/plugins/qmldesigner/components/resources/resources_qmldesigner_components.qrc
index d24fa1ca06a..d24fa1ca06a 100644
--- a/src/plugins/qmldesigner/components/resources/resources.qrc
+++ b/src/plugins/qmldesigner/components/resources/resources_qmldesigner_components.qrc
diff --git a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp
index 5121de76853..2841d566164 100644
--- a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp
+++ b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp
@@ -546,7 +546,7 @@ void RichTextEditor::setupFontActions()
w->setEditable(true);
const QList<int> standardSizes = QFontDatabase::standardSizes();
- foreach (int size, standardSizes)
+ for (const int size : standardSizes)
w->addItem(QString::number(size));
w->setCurrentText(QString::number(ui->textEdit->currentCharFormat().font().pointSize()));
connect(w, &QComboBox::textActivated, [this](const QString &p) {
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
index 2d96d01a9dc..0d8d39936bd 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
@@ -65,7 +65,7 @@ QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &par
int internalNodeId = 0;
if (row > 0 && row < rowCount() - 1) // first and last rows are base state, add state
- internalNodeId = m_statesEditorView->rootModelNode().nodeListProperty("states").at(row - 1).internalId();
+ internalNodeId = m_statesEditorView->acitveStatesGroupNode().nodeListProperty("states").at(row - 1).internalId();
return hasIndex(row, column, parent) ? createIndex(row, column, internalNodeId) : QModelIndex();
}
@@ -75,10 +75,10 @@ int StatesEditorModel::rowCount(const QModelIndex &parent) const
if (parent.isValid() || m_statesEditorView.isNull() || !m_statesEditorView->model())
return 0;
- if (!m_statesEditorView->rootModelNode().hasNodeListProperty("states"))
+ if (!m_statesEditorView->acitveStatesGroupNode().hasNodeListProperty("states"))
return 2; // base state + add new state
- return m_statesEditorView->rootModelNode().nodeListProperty("states").count() + 2; // 2 = base state + add new state
+ return m_statesEditorView->acitveStatesGroupNode().nodeListProperty("states").count() + 2; // 2 = base state + add new state
}
void StatesEditorModel::reset()
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
index cf1f3771412..eefde504948 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
@@ -77,7 +77,7 @@ WidgetInfo StatesEditorView::widgetInfo()
if (!m_statesEditorWidget)
m_statesEditorWidget = new StatesEditorWidget(this, m_statesEditorModel.data());
- return createWidgetInfo(m_statesEditorWidget.data(), nullptr, QLatin1String("StatesEditor"), WidgetInfo::BottomPane, 0, tr("States"));
+ return createWidgetInfo(m_statesEditorWidget.data(), QLatin1String("StatesEditor"), WidgetInfo::BottomPane, 0, tr("States"));
}
void StatesEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
@@ -85,6 +85,20 @@ void StatesEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorV
checkForStatesAvailability();
}
+ModelNode StatesEditorView::acitveStatesGroupNode() const
+{
+ return m_activeStatesGroupNode;
+}
+
+void StatesEditorView::setAcitveStatesGroupNode(const ModelNode &modelNode)
+{
+ if (m_activeStatesGroupNode == modelNode)
+ return;
+
+ m_activeStatesGroupNode = modelNode;
+ resetModel();
+}
+
void StatesEditorView::removeState(int nodeId)
{
try {
@@ -193,12 +207,12 @@ void StatesEditorView::createNewState()
void StatesEditorView::addState()
{
// can happen when root node is e.g. a ListModel
- if (!QmlVisualNode::isValidQmlVisualNode(rootModelNode()))
+ if (!QmlVisualNode::isValidQmlVisualNode(acitveStatesGroupNode()))
return;
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED);
- QStringList modelStateNames = rootStateGroup().names();
+ QStringList modelStateNames = activeStateGroup().names();
QString newStateName;
int index = 1;
@@ -209,9 +223,9 @@ void StatesEditorView::addState()
}
executeInTransaction("addState", [this, newStateName]() {
- rootModelNode().validId();
+ acitveStatesGroupNode().validId();
- ModelNode newState = rootStateGroup().addState(newStateName);
+ ModelNode newState = activeStateGroup().addState(newStateName);
setCurrentState(newState);
});
}
@@ -244,7 +258,7 @@ void StatesEditorView::duplicateCurrentState()
newName = newName.left(match.capturedStart());
int i = 1;
- QStringList stateNames = rootStateGroup().names();
+ QStringList stateNames = activeStateGroup().names();
while (stateNames.contains(newName + QString::number(i)))
i++;
const QString newStateName = newName + QString::number(i);
@@ -258,7 +272,7 @@ void StatesEditorView::duplicateCurrentState()
void StatesEditorView::checkForStatesAvailability()
{
if (m_statesEditorWidget) {
- const bool isVisual = QmlVisualNode::isValidQmlVisualNode(rootModelNode());
+ const bool isVisual = QmlVisualNode::isValidQmlVisualNode(acitveStatesGroupNode());
m_statesEditorWidget->showAddNewStatesButton(isVisual);
}
}
@@ -277,17 +291,17 @@ QmlModelState StatesEditorView::baseState() const
return QmlModelState::createBaseState(this);
}
-QmlModelStateGroup StatesEditorView::rootStateGroup() const
+QmlModelStateGroup StatesEditorView::activeStateGroup() const
{
- return QmlModelStateGroup(rootModelNode());
+ return QmlModelStateGroup(acitveStatesGroupNode());
}
bool StatesEditorView::validStateName(const QString &name) const
{
if (name == tr("base state"))
return false;
- QList<QmlModelState> modelStates = rootStateGroup().allStates();
- foreach (const QmlModelState &state, modelStates) {
+ const QList<QmlModelState> modelStates = activeStateGroup().allStates();
+ for (const QmlModelState &state : modelStates) {
if (state.name() == name)
return false;
}
@@ -392,8 +406,8 @@ void StatesEditorView::resetDefaultState()
auto guard = qScopeGuard([&]() { m_block = false; });
try {
- if (rootModelNode().hasProperty("state"))
- rootModelNode().removeProperty("state");
+ if (acitveStatesGroupNode().hasProperty("state"))
+ acitveStatesGroupNode().removeProperty("state");
} catch (const RewritingException &e) {
e.showException();
@@ -402,7 +416,7 @@ void StatesEditorView::resetDefaultState()
bool StatesEditorView::hasDefaultState() const
{
- return rootModelNode().hasProperty("state");
+ return acitveStatesGroupNode().hasProperty("state");
}
void StatesEditorView::setAnnotation(int internalNodeId)
@@ -475,6 +489,8 @@ void StatesEditorView::modelAttached(Model *model)
Q_ASSERT(model);
AbstractView::modelAttached(model);
+ m_activeStatesGroupNode = rootModelNode();
+
if (m_statesEditorWidget)
m_statesEditorWidget->setNodeInstanceView(nodeInstanceView());
@@ -491,7 +507,7 @@ void StatesEditorView::modelAboutToBeDetached(Model *model)
void StatesEditorView::propertiesRemoved(const QList<AbstractProperty>& propertyList)
{
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
if (property.name() == "states" && property.parentModelNode().isRootNode())
resetModel();
if (property.name() == "when" && QmlModelState::isValidQmlModelState(property.parentModelNode()))
@@ -548,7 +564,7 @@ void StatesEditorView::bindingPropertiesChanged(const QList<BindingProperty> &pr
{
Q_UNUSED(propertyChange)
- foreach (const BindingProperty &property, propertyList) {
+ for (const BindingProperty &property : propertyList) {
if (property.name() == "when" && QmlModelState::isValidQmlModelState(property.parentModelNode()))
resetModel();
}
@@ -588,12 +604,12 @@ void StatesEditorView::instancesPreviewImageChanged(const QVector<ModelNode> &no
int minimumIndex = 10000;
int maximumIndex = -1;
- foreach (const ModelNode &node, nodeList) {
+ for (const ModelNode &node : nodeList) {
if (node.isRootNode()) {
minimumIndex = qMin(minimumIndex, 0);
maximumIndex = qMax(maximumIndex, 0);
} else {
- int index = rootStateGroup().allStates().indexOf(QmlModelState(node)) + 1;
+ int index = activeStateGroup().allStates().indexOf(QmlModelState(node)) + 1;
if (index > 0) {
minimumIndex = qMin(minimumIndex, index);
maximumIndex = qMax(maximumIndex, index);
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
index 71a82711eaa..1ee8144a2bb 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
@@ -55,7 +55,7 @@ public:
QString currentStateName() const;
void setCurrentState(const QmlModelState &state);
QmlModelState baseState() const;
- QmlModelStateGroup rootStateGroup() const;
+ QmlModelStateGroup activeStateGroup() const;
// AbstractView
void modelAttached(Model *model) override;
@@ -87,6 +87,10 @@ public:
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
+ ModelNode acitveStatesGroupNode() const;
+ void setAcitveStatesGroupNode(const ModelNode &modelNode);
+
+
public slots:
void synchonizeCurrentStateFromWidget();
void createNewState();
@@ -105,6 +109,7 @@ private:
int m_lastIndex;
bool m_block = false;
QPointer<AnnotationEditor> m_editor;
+ ModelNode m_activeStatesGroupNode;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
index 7add0cd8e26..30375f9fc04 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
@@ -52,6 +52,7 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsreformatter.h>
#include <utils/changeset.h>
+#include <utils/qtcassert.h>
#include <QDebug>
#include <QPair>
@@ -145,7 +146,7 @@ void TextEditorView::nodeReparented(const ModelNode &/*node*/, const NodeAbstrac
WidgetInfo TextEditorView::widgetInfo()
{
- return createWidgetInfo(m_widget, nullptr, "TextEditor", WidgetInfo::CentralPane, 0, tr("Text Editor"), DesignerWidgetFlags::IgnoreErrors);
+ return createWidgetInfo(m_widget, "TextEditor", WidgetInfo::CentralPane, 0, tr("Code"), DesignerWidgetFlags::IgnoreErrors);
}
void TextEditorView::contextHelp(const Core::IContext::HelpCallback &callback) const
@@ -258,12 +259,7 @@ void TextEditorView::gotoCursorPosition(int line, int column)
void TextEditorView::reformatFile()
{
- int oldLine = -1;
-
- if (m_widget)
- oldLine = m_widget->currentLine();
-
- QByteArray editorState = m_widget->textEditor()->saveState();
+ QTC_ASSERT(!m_widget.isNull(), return);
auto document =
qobject_cast<QmlJSEditor::QmlJSEditorDocument *>(Core::EditorManager::currentDocument());
@@ -292,16 +288,21 @@ void TextEditorView::reformatFile()
return;
const QString &newText = QmlJS::reformat(currentDocument);
- QTextCursor tc(document->document());
+ if (currentDocument->source() == newText)
+ return;
+
+ QTextCursor tc = m_widget->textEditor()->textCursor();
+ int pos = m_widget->textEditor()->textCursor().position();
Utils::ChangeSet changeSet;
changeSet.replace(0, document->plainText().length(), newText);
- changeSet.apply(&tc);
- m_widget->textEditor()->restoreState(editorState);
+ tc.beginEditBlock();
+ changeSet.apply(&tc);
+ tc.setPosition(pos);
+ tc.endEditBlock();
- if (m_widget)
- m_widget->gotoCursorPosition(oldLine, 0);
+ m_widget->textEditor()->setTextCursor(tc);
}
}
diff --git a/src/plugins/qmldesigner/components/texttool/texttool.cpp b/src/plugins/qmldesigner/components/texttool/texttool.cpp
index a8b5ac044ae..8b271a7f701 100644
--- a/src/plugins/qmldesigner/components/texttool/texttool.cpp
+++ b/src/plugins/qmldesigner/components/texttool/texttool.cpp
@@ -240,7 +240,7 @@ void TextTool::instancesParentChanged(const QList<FormEditorItem *> & /*itemLis
void TextTool::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > &propertyList)
{
using ModelNodePropertyNamePair = QPair<ModelNode, PropertyName>;
- foreach (const ModelNodePropertyNamePair &propertyPair, propertyList) {
+ for (const ModelNodePropertyNamePair &propertyPair : propertyList) {
if (propertyPair.first == textItem()->formEditorItem()->qmlItemNode().modelNode()
&& propertyPair.second == "text")
textItem()->updateText();
diff --git a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
index ad4d02df891..60553dc6202 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
@@ -24,47 +24,147 @@
****************************************************************************/
#include "setframevaluedialog.h"
-#include "ui_setframevaluedialog.h"
+#include "timelinecontrols.h"
-#include <QtGui/qvalidator.h>
+#include <QDoubleSpinBox>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QMetaType>
+#include <QDialogButtonBox>
+#include <qnamespace.h>
+
+#include <limits>
namespace QmlDesigner {
SetFrameValueDialog::SetFrameValueDialog(qreal frame, const QVariant &value,
const QString &propertyName, QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::SetFrameValueDialog)
+ : QDialog(parent, Qt::Tool)
+ , m_valueGetter()
+ , m_valueType(value.metaType())
+ , m_frameControl(new QSpinBox)
{
- ui->setupUi(this);
setWindowTitle(tr("Edit Keyframe"));
- setFixedSize(size());
- ui->lineEditFrame->setValidator(new QIntValidator(0, 99999, this));
- auto dv = new QDoubleValidator(this);
- dv->setDecimals(2);
- ui->lineEditValue->setValidator(dv);
+ auto frameLabelString = QString(tr("Frame"));
+ auto labelWidth = fontMetrics().boundingRect(frameLabelString).width();
+ if (auto tmp = fontMetrics().boundingRect(propertyName).width(); tmp > labelWidth)
+ labelWidth = tmp;
+
+ auto *frameLabel = new QLabel(frameLabelString);
+ frameLabel->setAlignment(Qt::AlignRight);
+ frameLabel->setFixedWidth(labelWidth);
+
+ auto *valueLabel = new QLabel(propertyName);
+ valueLabel->setAlignment(Qt::AlignRight);
+ valueLabel->setFixedWidth(labelWidth);
+
+ m_frameControl->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
+ m_frameControl->setValue(static_cast<int>(frame));
+ m_frameControl->setAlignment(Qt::AlignRight);
+
+ auto* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ auto* frameRow = new QHBoxLayout;
+ frameRow->addWidget(frameLabel);
+ frameRow->addWidget(m_frameControl);
- QLocale l;
- ui->lineEditFrame->setText(l.toString(qRound(frame)));
- ui->lineEditValue->setText(l.toString(value.toDouble(), 'f', 2));
- ui->labelValue->setText(propertyName);
+ auto* valueRow = new QHBoxLayout;
+ valueRow->addWidget(valueLabel);
+ valueRow->addWidget(createValueControl(value));
+
+ auto* hbox = new QVBoxLayout;
+ hbox->addLayout(frameRow);
+ hbox->addLayout(valueRow);
+ hbox->addStretch();
+ hbox->addWidget(buttons);
+
+ setLayout(hbox);
}
SetFrameValueDialog::~SetFrameValueDialog()
-{
- delete ui;
-}
+{ }
qreal SetFrameValueDialog::frame() const
{
- QLocale l;
- return l.toDouble(ui->lineEditFrame->text());
+ return static_cast<qreal>(m_frameControl->value());
}
QVariant SetFrameValueDialog::value() const
{
- QLocale l;
- return QVariant(l.toDouble(ui->lineEditValue->text()));
+ if (m_valueGetter)
+ return m_valueGetter();
+ return QVariant(m_valueType);
+}
+
+QWidget* SetFrameValueDialog::createValueControl(const QVariant& value)
+{
+ m_valueType = value.metaType();
+
+ switch (value.metaType().id())
+ {
+
+ case QMetaType::QColor: {
+ auto* widget = new ColorControl(value.value<QColor>());
+ m_valueGetter = [widget]() { return widget->value(); };
+ return widget;
+ }
+
+ case QMetaType::Bool: {
+ auto* widget = new QCheckBox;
+ widget->setChecked(value.toBool());
+ m_valueGetter = [widget]() { return widget->isChecked(); };
+ return widget;
+ }
+
+ case QMetaType::Int: {
+ auto* widget = new QSpinBox;
+ widget->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
+ widget->setAlignment(Qt::AlignRight);
+ widget->setValue(value.toInt());
+ m_valueGetter = [widget]() { return widget->value(); };
+ return widget;
+ }
+
+ case QMetaType::UInt: {
+ auto* widget = new QSpinBox;
+ widget->setRange(0, std::numeric_limits<int>::max());
+ widget->setAlignment(Qt::AlignRight);
+ widget->setValue(value.toUInt());
+ m_valueGetter = [widget]() { return static_cast<unsigned int>(widget->value()); };
+ return widget;
+ }
+
+ case QMetaType::Float: {
+ auto* widget = new QDoubleSpinBox;
+ widget->setRange(std::numeric_limits<float>::min(), std::numeric_limits<float>::max());
+ widget->setAlignment(Qt::AlignRight);
+ widget->setValue(value.toFloat());
+ m_valueGetter = [widget]() { return static_cast<float>(widget->value()); };
+ return widget;
+ }
+
+ case QMetaType::Double:
+ [[fallthrough]];
+
+ default: {
+ auto* widget = new QDoubleSpinBox;
+ widget->setRange(std::numeric_limits<double>::min(), std::numeric_limits<double>::max());
+ widget->setAlignment(Qt::AlignRight);
+ widget->setValue(value.toDouble());
+ m_valueGetter = [widget]() { return widget->value(); };
+ return widget;
+ }
+
+ }
+
+ m_valueGetter = nullptr;
+ return nullptr;
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h
index 799e3fadc52..e2ca6e39010 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h
@@ -27,14 +27,10 @@
#include <QDialog>
-QT_FORWARD_DECLARE_CLASS(QLineEdit)
+QT_FORWARD_DECLARE_CLASS(QSpinBox)
namespace QmlDesigner {
-namespace Ui {
-class SetFrameValueDialog;
-}
-
class SetFrameValueDialog : public QDialog
{
Q_OBJECT
@@ -48,7 +44,12 @@ public:
QVariant value() const;
private:
- Ui::SetFrameValueDialog *ui;
+ QWidget* createValueControl(const QVariant& value);
+
+ std::function<QVariant(void)> m_valueGetter;
+
+ QMetaType m_valueType;
+ QSpinBox *m_frameControl;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
deleted file mode 100644
index 8a3ba3c99cb..00000000000
--- a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QmlDesigner::SetFrameValueDialog</class>
- <widget class="QDialog" name="QmlDesigner::SetFrameValueDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>212</width>
- <height>148</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Dialog</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="labelFrame">
- <property name="text">
- <string>Frame</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0" colspan="2">
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="lineEditFrame"/>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="lineEditValue"/>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="labelValue">
- <property name="text">
- <string>Value</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>QmlDesigner::SetFrameValueDialog</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>248</x>
- <y>254</y>
- </hint>
- <hint type="destinationlabel">
- <x>157</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>QmlDesigner::SetFrameValueDialog</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
- </hint>
- <hint type="destinationlabel">
- <x>286</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- </connections>
-</ui>
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp
index 185b12ea422..f417d5dad06 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp
@@ -191,7 +191,7 @@ void ColorControl::mouseReleaseEvent(QMouseEvent *event)
event->accept();
- if (color != m_color) {
+ if (color.isValid() && color != m_color) {
m_color = color;
update();
emit valueChanged();
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp
index db9e8a8ef64..e3bcef39424 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp
@@ -50,16 +50,7 @@ TimelineForm::TimelineForm(QWidget *parent)
connect(ui->expressionBindingLineEdit, &QLineEdit::editingFinished, [this]() {
QTC_ASSERT(m_timeline.isValid(), return );
-
- static QString lastString;
-
const QString bindingText = ui->expressionBindingLineEdit->text();
-
- if (bindingText == lastString)
- return;
-
- lastString = bindingText;
-
if (bindingText.isEmpty()) {
ui->animation->setChecked(true);
try {
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
index 2acf6601ab7..8511ebcfaf6 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
@@ -444,10 +444,12 @@ void TimelineGraphicsScene::invalidateHeightForTarget(const ModelNode &target)
void TimelineGraphicsScene::invalidateScene()
{
- ModelNode node = timelineView()->modelNodeForId(
- timelineWidget()->toolBar()->currentTimelineId());
- setTimeline(QmlTimeline(node));
- invalidateScrollbar();
+ if (timelineView()->isAttached()) {
+ ModelNode node = timelineView()->modelNodeForId(
+ timelineWidget()->toolBar()->currentTimelineId());
+ setTimeline(QmlTimeline(node));
+ invalidateScrollbar();
+ }
}
void TimelineGraphicsScene::invalidateScrollbar()
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp
index 7272735be24..f83033c15d6 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp
@@ -670,7 +670,6 @@ TimelineWidget *TimelineView::createWidget()
WidgetInfo TimelineView::widgetInfo()
{
return createWidgetInfo(createWidget(),
- nullptr,
QStringLiteral("Timelines"),
WidgetInfo::BottomPane,
0,
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp
index ceed4831791..81f45e5e0cc 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp
@@ -625,6 +625,7 @@ void TimelineWidget::showEvent(QShowEvent *event)
m_timelineView->setEnabled(true);
graphicsScene()->setWidth(m_graphicsView->viewport()->width());
+ graphicsScene()->invalidateScene();
graphicsScene()->invalidateLayout();
graphicsScene()->invalidate();
graphicsScene()->onShow();
diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
index 14c5eb6e953..09e9b9f05a3 100644
--- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
+++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
@@ -332,11 +332,10 @@ TransitionEditorWidget *TransitionEditorView::createWidget()
WidgetInfo TransitionEditorView::widgetInfo()
{
return createWidgetInfo(createWidget(),
- nullptr,
"TransitionEditor",
WidgetInfo::BottomPane,
0,
- tr("Transition Editor"));
+ tr("Transitions"));
}
void TransitionEditorView::openSettingsDialog()
diff --git a/src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs b/src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs
index 84adc2b5304..520e533af5b 100644
--- a/src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs
+++ b/src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs
@@ -2,12 +2,13 @@ import qbs
QtcProduct {
name: "componentsplugin"
+ condition: QmlDesigner.present
type: ["dynamiclibrary"]
installDir: qtc.ide_plugin_path + '/' + installDirName
property string installDirName: qbs.targetOS.contains("macos") ? "QmlDesigner" : "qmldesigner"
Depends { name: "Core" }
- Depends { name: "QmlDesigner" }
+ Depends { name: "QmlDesigner"; required: false }
Depends { name: "Utils" }
Depends { name: "Qt.qml" }
diff --git a/src/plugins/qmldesigner/componentsplugin/entertabdesigneraction.cpp b/src/plugins/qmldesigner/componentsplugin/entertabdesigneraction.cpp
index 7973bf565c0..0dccf93d2f1 100644
--- a/src/plugins/qmldesigner/componentsplugin/entertabdesigneraction.cpp
+++ b/src/plugins/qmldesigner/componentsplugin/entertabdesigneraction.cpp
@@ -86,7 +86,8 @@ void EnterTabDesignerAction::updateContext()
&& selectedModelNode.metaInfo().isSubclassOf("QtQuick.Controls.TabView")) {
const NodeAbstractProperty defaultProperty = selectedModelNode.defaultNodeAbstractProperty();
- foreach (const QmlDesigner::ModelNode &childModelNode, defaultProperty.directSubNodes()) {
+ const QList<QmlDesigner::ModelNode> childModelNodes = defaultProperty.directSubNodes();
+ for (const QmlDesigner::ModelNode &childModelNode : childModelNodes) {
createActionForTab(childModelNode);
}
}
diff --git a/src/plugins/qmldesigner/componentsplugin/tabviewindexmodel.cpp b/src/plugins/qmldesigner/componentsplugin/tabviewindexmodel.cpp
index ab5c831baef..225ab5e7442 100644
--- a/src/plugins/qmldesigner/componentsplugin/tabviewindexmodel.cpp
+++ b/src/plugins/qmldesigner/componentsplugin/tabviewindexmodel.cpp
@@ -61,10 +61,11 @@ void TabViewIndexModel::setupModel()
if (m_modelNode.isValid()
&& m_modelNode.metaInfo().isValid()
&& m_modelNode.metaInfo().isSubclassOf("QtQuick.Controls.TabView")) {
-
- foreach (const QmlDesigner::ModelNode &childModelNode, m_modelNode.defaultNodeAbstractProperty().directSubNodes()) {
+ const QList<QmlDesigner::ModelNode> childModelNodes
+ = m_modelNode.defaultNodeAbstractProperty().directSubNodes();
+ for (const QmlDesigner::ModelNode &childModelNode : childModelNodes) {
if (childModelNode.metaInfo().isValid()
- && childModelNode.metaInfo().isSubclassOf("QtQuick.Controls.Tab")) {
+ && childModelNode.metaInfo().isSubclassOf("QtQuick.Controls.Tab")) {
QmlDesigner::QmlItemNode itemNode(childModelNode);
if (itemNode.isValid()) {
m_tabViewIndexModel.append(itemNode.instanceValue("title").toString());
diff --git a/src/plugins/qmldesigner/designercore/filemanager/addpropertyvisitor.cpp b/src/plugins/qmldesigner/designercore/filemanager/addpropertyvisitor.cpp
index 47a7af5fc3b..baa6dcdcf2b 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/addpropertyvisitor.cpp
+++ b/src/plugins/qmldesigner/designercore/filemanager/addpropertyvisitor.cpp
@@ -155,8 +155,14 @@ void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializ
Q_ASSERT(!"unknown property type");
}
- if (!m_dynamicTypeName.isEmpty())
- newPropertyTemplate.prepend(QStringLiteral("property %1 ").arg(QString::fromUtf8(m_dynamicTypeName)));
+ if (!m_dynamicTypeName.isEmpty()) {
+ if (m_dynamicTypeName == "signal") {
+ newPropertyTemplate = "signal %1%2";
+ } else {
+ newPropertyTemplate.prepend(
+ QStringLiteral("property %1 ").arg(QString::fromUtf8(m_dynamicTypeName)));
+ }
+ }
if (isOneLiner) {
if (needsPreceedingSemicolon)
diff --git a/src/plugins/qmldesigner/designercore/filemanager/changepropertyvisitor.cpp b/src/plugins/qmldesigner/designercore/filemanager/changepropertyvisitor.cpp
index c76b67dceb9..caaab23e654 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/changepropertyvisitor.cpp
+++ b/src/plugins/qmldesigner/designercore/filemanager/changepropertyvisitor.cpp
@@ -137,7 +137,14 @@ void ChangePropertyVisitor::replaceMemberValue(UiObjectMember *propertyMember, b
startOffset = arrayBinding->lbracketToken.offset;
endOffset = arrayBinding->rbracketToken.end();
} else if (auto publicMember = AST::cast<UiPublicMember*>(propertyMember)) {
- if (publicMember->statement) {
+ if (publicMember->type == AST::UiPublicMember::Signal) {
+ startOffset = publicMember->firstSourceLocation().offset;
+ if (publicMember->semicolonToken.isValid())
+ endOffset = publicMember->semicolonToken.end();
+ else
+ endOffset = publicMember->lastSourceLocation().end();
+ replacement.prepend(QStringLiteral("signal %1 ").arg(publicMember->name));
+ } else if (publicMember->statement) {
startOffset = publicMember->statement->firstSourceLocation().offset;
if (publicMember->semicolonToken.isValid())
endOffset = publicMember->semicolonToken.end();
diff --git a/src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.cpp b/src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.cpp
index 82e4c15ef41..f4efd646231 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.cpp
+++ b/src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.cpp
@@ -40,7 +40,8 @@ FirstDefinitionFinder::FirstDefinitionFinder(const QString &text):
if (!ok) {
qDebug() << text;
- foreach (const QmlJS::DiagnosticMessage &message, m_doc->diagnosticMessages())
+ const QList<QmlJS::DiagnosticMessage> messages = m_doc->diagnosticMessages();
+ for (const QmlJS::DiagnosticMessage &message : messages)
qDebug() << message.message;
}
diff --git a/src/plugins/qmldesigner/designercore/include/abstractproperty.h b/src/plugins/qmldesigner/designercore/include/abstractproperty.h
index cb717664454..5eae8de3028 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractproperty.h
@@ -51,6 +51,7 @@ class QMLDESIGNERCORE_EXPORT NodeAbstractProperty;
class QMLDESIGNERCORE_EXPORT BindingProperty;
class QMLDESIGNERCORE_EXPORT NodeProperty;
class QMLDESIGNERCORE_EXPORT SignalHandlerProperty;
+class QMLDESIGNERCORE_EXPORT SignalDeclarationProperty;
class QmlObjectNode;
@@ -88,6 +89,7 @@ public:
BindingProperty toBindingProperty() const;
NodeProperty toNodeProperty() const;
SignalHandlerProperty toSignalHandlerProperty() const;
+ SignalDeclarationProperty toSignalDeclarationProperty() const;
bool isVariantProperty() const;
bool isNodeListProperty() const;
@@ -95,6 +97,7 @@ public:
bool isBindingProperty() const;
bool isNodeProperty() const;
bool isSignalHandlerProperty() const;
+ bool isSignalDeclarationProperty() const;
bool isDynamic() const;
TypeName dynamicTypeName() const;
diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h
index 6971f5f39ed..994caaa7ec4 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractview.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractview.h
@@ -70,30 +70,6 @@ enum DesignerWidgetFlags {
class WidgetInfo {
public:
- class ToolBarWidgetFactoryInterface {
- public:
- ToolBarWidgetFactoryInterface() = default;
-
- virtual QList<QToolButton*> createToolBarWidgets() = 0;
-
- virtual ~ToolBarWidgetFactoryInterface() = default;
- };
-
- template <class T>
- class ToolBarWidgetDefaultFactory : public ToolBarWidgetFactoryInterface {
- public:
- ToolBarWidgetDefaultFactory(T *t ) : m_t(t)
- {}
-
- QList<QToolButton*> createToolBarWidgets() override
- {
- return m_t->createToolBarWidgets();
- }
-
- private:
- T * m_t;
- };
-
enum PlacementHint {
NoPane,
LeftPane,
@@ -108,7 +84,6 @@ public:
QWidget *widget = nullptr;
int placementPriority;
PlacementHint placementHint;
- ToolBarWidgetFactoryInterface *toolBarWidgetFactory = nullptr;
DesignerWidgetFlags widgetFlags = DesignerWidgetFlags::DisableOnError;
};
@@ -137,12 +112,13 @@ public:
ModelNode createModelNode(const TypeName &typeName);
ModelNode createModelNode(const TypeName &typeName,
- int majorVersion,
- int minorVersion,
- const PropertyListType &propertyList = PropertyListType(),
- const PropertyListType &auxPropertyList = PropertyListType(),
- const QString &nodeSource = QString(),
- ModelNode::NodeSourceType nodeSourceType = ModelNode::NodeWithoutSource);
+ int majorVersion,
+ int minorVersion,
+ const PropertyListType &propertyList = PropertyListType(),
+ const PropertyListType &auxPropertyList = PropertyListType(),
+ const QString &nodeSource = {},
+ ModelNode::NodeSourceType nodeSourceType = ModelNode::NodeWithoutSource,
+ const QString &behaviorPropertyName = {});
ModelNode rootModelNode() const;
ModelNode rootModelNode();
@@ -190,6 +166,7 @@ public:
void emitUpdateActiveScene3D(const QVariantMap &sceneState);
void emitModelNodelPreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
void emitImport3DSupportChanged(const QVariantMap &supportMap);
+ void emitModelAtPosResult(const ModelNode &modelNode);
void sendTokenToInstances(const QString &token, int number, const QVector<ModelNode> &nodeVector);
@@ -208,6 +185,7 @@ public:
virtual void bindingPropertiesAboutToBeChanged(const QList<BindingProperty> &propertyList);
virtual void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
virtual void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty>& propertyList, PropertyChangeFlags propertyChange);
+ virtual void signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty>& propertyList, PropertyChangeFlags propertyChange);
virtual void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion);
virtual void nodeTypeChanged(const ModelNode& node, const TypeName &type, int majorVersion, int minorVersion);
@@ -254,6 +232,7 @@ public:
virtual void renderImage3DChanged(const QImage &image);
virtual void updateActiveScene3D(const QVariantMap &sceneState);
virtual void updateImport3DSupport(const QVariantMap &supportMap);
+ virtual void modelAtPosReady(const ModelNode &modelNode);
virtual void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
virtual void dragStarted(QMimeData *mimeData);
@@ -318,7 +297,6 @@ protected:
void setModel(Model * model);
void removeModel();
static WidgetInfo createWidgetInfo(QWidget *widget = nullptr,
- WidgetInfo::ToolBarWidgetFactoryInterface *toolBarWidgetFactory = nullptr,
const QString &uniqueId = QString(),
WidgetInfo::PlacementHint placementHint = WidgetInfo::NoPane,
int placementPriority = 0,
diff --git a/src/plugins/qmldesigner/designercore/include/forwardview.h b/src/plugins/qmldesigner/designercore/include/forwardview.h
index 5b46204091f..6ca882e756a 100644
--- a/src/plugins/qmldesigner/designercore/include/forwardview.h
+++ b/src/plugins/qmldesigner/designercore/include/forwardview.h
@@ -92,14 +92,14 @@ template <class ViewType>
void ForwardView<ViewType>::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->modelAttached(model);
}
template <class ViewType>
void ForwardView<ViewType>::modelAboutToBeDetached(Model *model)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->modelAboutToBeDetached(model);
AbstractView::modelAboutToBeDetached(model);
@@ -108,35 +108,35 @@ void ForwardView<ViewType>::modelAboutToBeDetached(Model *model)
template <class ViewType>
void ForwardView<ViewType>::nodeCreated(const ModelNode &createdNode)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->nodeCreated(ModelNode(createdNode, view.data()));
}
template <class ViewType>
void ForwardView<ViewType>::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->nodeAboutToBeRemoved(ModelNode(removedNode, view.data()));
}
template <class ViewType>
void ForwardView<ViewType>::nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->nodeRemoved(ModelNode(removedNode, view.data()), NodeAbstractProperty(parentProperty, view.data()), propertyChange);
}
template <class ViewType>
void ForwardView<ViewType>::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, PropertyChangeFlags propertyChange)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->nodeReparented(ModelNode(node, view.data()), NodeAbstractProperty(newPropertyParent, view.data()), NodeAbstractProperty(oldPropertyParent, view.data()), propertyChange);
}
template <class ViewType>
void ForwardView<ViewType>::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->nodeIdChanged(ModelNode(node, view.data()), newId, oldId);
}
@@ -145,7 +145,7 @@ static QList<T> adjustedList(const QList<T>& oldList, AbstractView *view)
{
QList<T> newList;
- foreach (const T &item, oldList)
+ for (const T &item : oldList)
{
newList.append(T(item, view));
}
@@ -156,41 +156,41 @@ static QList<T> adjustedList(const QList<T>& oldList, AbstractView *view)
template <class ViewType>
void ForwardView<ViewType>::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->propertiesAboutToBeRemoved(adjustedList(propertyList, view.data()));
}
template <class ViewType>
void ForwardView<ViewType>::propertiesRemoved(const QList<AbstractProperty>& propertyList)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->propertiesRemoved(adjustedList(propertyList, view.data()));
}
template <class ViewType>
void ForwardView<ViewType>::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->variantPropertiesChanged(adjustedList(propertyList, view.data()), propertyChange);
}
template <class ViewType>
void ForwardView<ViewType>::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->bindingPropertiesChanged(adjustedList(propertyList, view.data()), propertyChange);
}
void ForwardView::signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &propertyList, AbstractView::PropertyChangeFlags propertyChange)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->signalHandlerPropertiesChanged(adjustedList(propertyList, view.data()), propertyChange);
}
template <class ViewType>
void ForwardView<ViewType>::rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->rootNodeTypeChanged(type, majorVersion, minorVersion);
}
@@ -198,7 +198,7 @@ template <class ViewType>
void ForwardView<ViewType>::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->selectedNodesChanged(adjustedList(selectedNodeList, view.data()), adjustedList(lastSelectedNodeList, view.data()));
}
@@ -207,21 +207,21 @@ void ForwardView<ViewType>::fileUrlChanged(const QUrl &oldUrl, const QUrl &newUr
{
AbstractView::fileUrlChanged(oldUrl, newUrl);
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->fileUrlChanged(oldUrl, newUrl);
}
template<class ViewType>
void ForwardView<ViewType>::nodeOrderChanged(const NodeListProperty &listProperty)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->nodeOrderChanged(NodeListProperty(listProperty, view.data()));
}
template <class ViewType>
void ForwardView<ViewType>::importChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->importChanged(addedImport, removedImport);
}
@@ -230,7 +230,7 @@ void ForwardView<ViewType>::importRemoved(const Import &import)
{
AbstractView::importRemoved(import);
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->importRemoved(import);
}
@@ -239,14 +239,14 @@ void ForwardView<ViewType>::auxiliaryDataChanged(const ModelNode &node, const Pr
{
AbstractView::auxiliaryDataChanged(node, name, data);
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->auxiliaryDataChanged(ModelNode(node, view.data()), name, data);
}
template <class ViewType>
void ForwardView<ViewType>::scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList)
{
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
view->scriptFunctionsChanged(node, scriptFunctionList);
}
@@ -267,7 +267,7 @@ QList<ViewType*> ForwardView<ViewType>::viewList() const
{
QList<ViewType*> newList;
- foreach (const ViewTypePointer &view, m_targetViewList)
+ for (const ViewTypePointer &view : qAsConst(m_targetViewList))
newList.append(view.data());
return newList;
diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h
index 92884a9710e..003c732c80c 100644
--- a/src/plugins/qmldesigner/designercore/include/modelnode.h
+++ b/src/plugins/qmldesigner/designercore/include/modelnode.h
@@ -51,6 +51,7 @@ class AbstractProperty;
class BindingProperty;
class VariantProperty;
class SignalHandlerProperty;
+class SignalDeclarationProperty;
class Model;
class AbstractView;
class NodeListProperty;
@@ -128,6 +129,7 @@ public:
VariantProperty variantProperty(const PropertyName &name) const;
BindingProperty bindingProperty(const PropertyName &name) const;
SignalHandlerProperty signalHandlerProperty(const PropertyName &name) const;
+ SignalDeclarationProperty signalDeclarationProperty(const PropertyName &name) const;
NodeListProperty nodeListProperty(const PropertyName &name) const;
NodeProperty nodeProperty(const PropertyName &name) const;
NodeAbstractProperty nodeAbstractProperty(const PropertyName &name) const;
@@ -238,6 +240,7 @@ public:
bool isComponent() const;
bool isSubclassOf(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1) const;
QIcon typeIcon() const;
+ QString behaviorPropertyName() const;
friend void swap(ModelNode &first, ModelNode &second) noexcept
{
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
index 62efb225d44..d6e30746661 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
@@ -39,7 +39,6 @@
#include <QElapsedTimer>
#include <QHash>
#include <QImage>
-#include <QPointer>
#include <QRectF>
#include <QTime>
#include <QTimer>
diff --git a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h
index 552095a8d6d..d46e099b98c 100644
--- a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h
+++ b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h
@@ -30,9 +30,9 @@
// Unnecessary since core isn't a dll any more.
-#if defined(DESIGNER_CORE_LIBRARY)
+#if defined(QMLDESIGNER_LIBRARY)
#define QMLDESIGNERCORE_EXPORT Q_DECL_EXPORT
-#elif defined(DESIGNER_STATIC_CORE_LIBRARY)
+#elif defined(QMLDESIGNER_STATIC_LIBRARY)
#define QMLDESIGNERCORE_EXPORT
#else
#define QMLDESIGNERCORE_EXPORT Q_DECL_IMPORT
diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h
index 4e099290cd0..c01bbcc499f 100644
--- a/src/plugins/qmldesigner/designercore/include/rewriterview.h
+++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h
@@ -87,6 +87,7 @@ public:
void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange) override;
void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange) override;
void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty>& propertyList,PropertyChangeFlags propertyChange) override;
+ void signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty>& propertyList, PropertyChangeFlags propertyChange) override;
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent,
const NodeAbstractProperty &oldPropertyParent,
AbstractView::PropertyChangeFlags propertyChange) override;
diff --git a/src/plugins/qmldesigner/designercore/include/signalhandlerproperty.h b/src/plugins/qmldesigner/designercore/include/signalhandlerproperty.h
index 07e48decadc..1f6656e4a70 100644
--- a/src/plugins/qmldesigner/designercore/include/signalhandlerproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/signalhandlerproperty.h
@@ -30,7 +30,7 @@
namespace QmlDesigner {
-class QMLDESIGNERCORE_EXPORT SignalHandlerProperty : public QmlDesigner::AbstractProperty
+class QMLDESIGNERCORE_EXPORT SignalHandlerProperty : public AbstractProperty
{
friend ModelNode;
friend Internal::ModelPrivate;
@@ -50,4 +50,21 @@ protected:
SignalHandlerProperty(const PropertyName &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
};
+class QMLDESIGNERCORE_EXPORT SignalDeclarationProperty : public AbstractProperty
+{
+ friend ModelNode;
+ friend Internal::ModelPrivate;
+ friend AbstractProperty;
+
+public:
+ void setSignature(const QString &source);
+ QString signature() const;
+
+ SignalDeclarationProperty();
+ SignalDeclarationProperty(const SignalDeclarationProperty &property, AbstractView *view);
+
+protected:
+ SignalDeclarationProperty(const PropertyName &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
+};
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/viewmanager.h b/src/plugins/qmldesigner/designercore/include/viewmanager.h
index 1be785655a2..4a0748f2691 100644
--- a/src/plugins/qmldesigner/designercore/include/viewmanager.h
+++ b/src/plugins/qmldesigner/designercore/include/viewmanager.h
@@ -106,6 +106,7 @@ public:
void disableStandardViews();
void enableStandardViews();
+ QList<AbstractView *> views() const;
private: // functions
Q_DISABLE_COPY(ViewManager)
@@ -123,7 +124,6 @@ private: // functions
void switchStateEditorViewToBaseState();
void switchStateEditorViewToSavedState();
- QList<AbstractView *> views() const;
QList<AbstractView *> standardViews() const;
private: // variables
diff --git a/src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp
index eb994376ea0..5b22c6c55e4 100644
--- a/src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp
@@ -146,11 +146,6 @@ void ConnectionManager::closeSocketsAndKillProcesses()
connection.socket->abort();
}
- if (connection.qmlPuppetProcess) {
- QTimer::singleShot(3000, connection.qmlPuppetProcess.get(), &QProcess::terminate);
- QTimer::singleShot(6000, connection.qmlPuppetProcess.get(), &QProcess::kill);
- }
-
connection.clear();
}
}
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
index 01ed33ea495..1fcdd9285f6 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
@@ -174,7 +174,8 @@ QString NodeInstanceServerProxy::qrcMappingString() const
using StringPair = QPair<QString, QString>;
- foreach (const StringPair &pair, rewriterView->qrcMapping()) {
+ const QSet<QPair<QString, QString>> &pairs = rewriterView->qrcMapping();
+ for (const StringPair &pair : pairs) {
if (!mappingString.isEmpty())
mappingString.append(QLatin1String(";"));
mappingString.append(pair.first);
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 3498e749266..1a703463ccf 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -484,7 +484,7 @@ void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>&
QList<ModelNode> nodeList;
QList<AbstractProperty> nonNodePropertyList;
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
if (property.isNodeAbstractProperty())
nodeList.append(property.toNodeAbstractProperty().allSubNodes());
else
@@ -499,7 +499,7 @@ void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>&
m_nodeInstanceServer->removeSharedMemory(createRemoveSharedMemoryCommand("Image", nodeList));
m_nodeInstanceServer->removeProperties(createRemovePropertiesCommand(nonNodePropertyList));
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
const PropertyName &name = property.name();
if (name == "anchors.fill") {
resetHorizontalAnchors(property.parentModelNode());
@@ -527,13 +527,14 @@ void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>&
}
}
- foreach (const ModelNode &node, nodeList)
+ for (const ModelNode &node : qAsConst(nodeList))
removeInstanceNodeRelationship(node);
}
void NodeInstanceView::removeInstanceAndSubInstances(const ModelNode &node)
{
- foreach (const ModelNode &subNode, node.allSubModelNodes()) {
+ const QList<ModelNode> subNodes = node.allSubModelNodes();
+ for (const ModelNode &subNode : subNodes) {
if (hasInstanceForModelNode(subNode))
removeInstanceNodeRelationship(subNode);
}
@@ -636,7 +637,8 @@ void NodeInstanceView::nodeOrderChanged(const NodeListProperty &listProperty)
if (hasInstanceForModelNode(containerNode))
containerInstanceId = instanceForModelNode(containerNode).instanceId();
- foreach (const ModelNode &node, listProperty.toModelNodeList()) {
+ const QList<ModelNode> nodes = listProperty.toModelNodeList();
+ for (const ModelNode &node : nodes) {
qint32 instanceId = -1;
if (hasInstanceForModelNode(node)) {
instanceId = instanceForModelNode(node).instanceId();
@@ -658,7 +660,8 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
const QVariant &value)
{
QTC_ASSERT(m_nodeInstanceServer, return);
- const bool forceAuxChange = name == "invisible" || name == "locked" || name == "rotBlocked@Internal";
+ const bool forceAuxChange = name == "invisible" || name == "locked"
+ || name == "rotBlocked@Internal" || name.startsWith("matPrev");
if (((node.isRootNode() && (name == "width" || name == "height")) || forceAuxChange)
|| name.endsWith(PropertyName("@NodeInstance"))) {
if (hasInstanceForModelNode(node)) {
@@ -848,11 +851,11 @@ NodeInstance NodeInstanceView::activeStateInstance() const
void NodeInstanceView::updateChildren(const NodeAbstractProperty &newPropertyParent)
{
- QVector<ModelNode> childNodeVector = newPropertyParent.directSubNodes().toVector();
+ const QVector<ModelNode> childNodeVector = newPropertyParent.directSubNodes().toVector();
qint32 parentInstanceId = newPropertyParent.parentModelNode().internalId();
- foreach (const ModelNode &childNode, childNodeVector) {
+ for (const ModelNode &childNode : childNodeVector) {
qint32 instanceId = childNode.internalId();
if (hasInstanceForId(instanceId)) {
NodeInstance instance = instanceForId(instanceId);
@@ -882,7 +885,7 @@ void NodeInstanceView::updatePosition(const QList<VariantProperty> &propertyList
{
QMultiHash<ModelNode, InformationName> informationChangeHash;
- foreach (const VariantProperty &variantProperty, propertyList) {
+ for (const VariantProperty &variantProperty : propertyList) {
if (variantProperty.name() == "x") {
const ModelNode modelNode = variantProperty.parentModelNode();
if (!currentState().isBaseState() && QmlPropertyChanges::isValidQmlPropertyChanges(modelNode)) {
@@ -957,7 +960,8 @@ void NodeInstanceView::removeRecursiveChildRelationship(const ModelNode &removed
// instanceForNode(removedNode).setId(QString());
// }
- foreach (const ModelNode &childNode, removedNode.directSubModelNodes())
+ const QList<ModelNode> nodes = removedNode.directSubModelNodes();
+ for (const ModelNode &childNode : nodes)
removeRecursiveChildRelationship(childNode);
removeInstanceNodeRelationship(removedNode);
@@ -974,7 +978,7 @@ QRectF NodeInstanceView::sceneRect() const
QList<ModelNode> filterNodesForSkipItems(const QList<ModelNode> &nodeList)
{
QList<ModelNode> filteredNodeList;
- foreach (const ModelNode &node, nodeList) {
+ for (const ModelNode &node : nodeList) {
if (isSkippedNode(node))
continue;
@@ -984,6 +988,18 @@ QList<ModelNode> filterNodesForSkipItems(const QList<ModelNode> &nodeList)
return filteredNodeList;
}
+bool parentIsBehavior(ModelNode node)
+{
+ while (node.isValid() && !node.isRootNode()) {
+ if (!node.behaviorPropertyName().isEmpty())
+ return true;
+
+ node = node.parentProperty().parentModelNode();
+ }
+
+ return false;
+}
+
CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
{
QList<ModelNode> nodeList = allModelNodes();
@@ -1047,7 +1063,8 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
nodeMetaType,
nodeFlags);
- instanceContainerList.append(container);
+ if (!parentIsBehavior(instance.modelNode()))
+ instanceContainerList.append(container);
}
QVector<ReparentContainer> reparentContainerList;
@@ -1181,7 +1198,7 @@ ClearSceneCommand NodeInstanceView::createClearSceneCommand() const
CompleteComponentCommand NodeInstanceView::createComponentCompleteCommand(const QList<NodeInstance> &instanceList) const
{
QVector<qint32> containerList;
- foreach (const NodeInstance &instance, instanceList) {
+ for (const NodeInstance &instance : instanceList) {
if (instance.instanceId() >= 0)
containerList.append(instance.instanceId());
}
@@ -1192,7 +1209,7 @@ CompleteComponentCommand NodeInstanceView::createComponentCompleteCommand(const
ComponentCompletedCommand NodeInstanceView::createComponentCompletedCommand(const QList<NodeInstance> &instanceList) const
{
QVector<qint32> containerList;
- foreach (const NodeInstance &instance, instanceList) {
+ for (const NodeInstance &instance : instanceList) {
if (instance.instanceId() >= 0)
containerList.append(instance.instanceId());
}
@@ -1203,7 +1220,7 @@ ComponentCompletedCommand NodeInstanceView::createComponentCompletedCommand(cons
CreateInstancesCommand NodeInstanceView::createCreateInstancesCommand(const QList<NodeInstance> &instanceList) const
{
QVector<InstanceContainer> containerList;
- foreach (const NodeInstance &instance, instanceList) {
+ for (const NodeInstance &instance : instanceList) {
InstanceContainer::NodeSourceType nodeSourceType = static_cast<InstanceContainer::NodeSourceType>(instance.modelNode().nodeSourceType());
InstanceContainer::NodeMetaType nodeMetaType = InstanceContainer::ObjectMetaType;
@@ -1233,7 +1250,7 @@ CreateInstancesCommand NodeInstanceView::createCreateInstancesCommand(const QLis
ReparentInstancesCommand NodeInstanceView::createReparentInstancesCommand(const QList<NodeInstance> &instanceList) const
{
QVector<ReparentContainer> containerList;
- foreach (const NodeInstance &instance, instanceList) {
+ for (const NodeInstance &instance : instanceList) {
if (instance.modelNode().hasParentProperty()) {
NodeAbstractProperty parentProperty = instance.modelNode().parentProperty();
ReparentContainer container(instance.instanceId(), -1, PropertyName(), instanceForModelNode(parentProperty.parentModelNode()).instanceId(), parentProperty.name());
@@ -1277,7 +1294,7 @@ ChangeValuesCommand NodeInstanceView::createChangeValueCommand(const QList<Varia
const bool reflectionFlag = m_puppetTransaction.isValid() && (!currentTimeline().isValid() || !currentTimeline().isRecording());
- foreach (const VariantProperty &property, propertyList) {
+ for (const VariantProperty &property : propertyList) {
ModelNode node = property.parentModelNode();
if (node.isValid() && hasInstanceForModelNode(node)) {
NodeInstance instance = instanceForModelNode(node);
@@ -1327,7 +1344,7 @@ ChangeIdsCommand NodeInstanceView::createChangeIdsCommand(const QList<NodeInstan
RemoveInstancesCommand NodeInstanceView::createRemoveInstancesCommand(const QList<ModelNode> &nodeList) const
{
QVector<qint32> idList;
- foreach (const ModelNode &node, nodeList) {
+ for (const ModelNode &node : nodeList) {
if (node.isValid() && hasInstanceForModelNode(node)) {
NodeInstance instance = instanceForModelNode(node);
@@ -1342,7 +1359,7 @@ RemoveInstancesCommand NodeInstanceView::createRemoveInstancesCommand(const QLis
ChangeSelectionCommand NodeInstanceView::createChangeSelectionCommand(const QList<ModelNode> &nodeList) const
{
QVector<qint32> idList;
- foreach (const ModelNode &node, nodeList) {
+ for (const ModelNode &node : nodeList) {
if (node.isValid() && hasInstanceForModelNode(node)) {
NodeInstance instance = instanceForModelNode(node);
@@ -1368,7 +1385,7 @@ RemovePropertiesCommand NodeInstanceView::createRemovePropertiesCommand(const QL
{
QVector<PropertyAbstractContainer> containerList;
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
ModelNode node = property.parentModelNode();
if (node.isValid() && hasInstanceForModelNode(node)) {
NodeInstance instance = instanceForModelNode(node);
@@ -1390,7 +1407,7 @@ RemoveSharedMemoryCommand NodeInstanceView::createRemoveSharedMemoryCommand(cons
{
QVector<qint32> keyNumberVector;
- foreach (const ModelNode &modelNode, nodeList)
+ for (const ModelNode &modelNode : nodeList)
keyNumberVector.append(modelNode.internalId());
return RemoveSharedMemoryCommand(sharedMemoryTypeName, keyNumberVector);
@@ -1403,7 +1420,8 @@ void NodeInstanceView::valuesChanged(const ValuesChangedCommand &command)
QList<QPair<ModelNode, PropertyName> > valuePropertyChangeList;
- foreach (const PropertyValueContainer &container, command.valueChanges()) {
+ const QVector<PropertyValueContainer> containers = command.valueChanges();
+ for (const PropertyValueContainer &container : containers) {
if (hasInstanceForId(container.instanceId())) {
NodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
@@ -1451,7 +1469,8 @@ void NodeInstanceView::pixmapChanged(const PixmapChangedCommand &command)
QSet<ModelNode> renderImageChangeSet;
- foreach (const ImageContainer &container, command.images()) {
+ const QVector<ImageContainer> containers = command.images();
+ for (const ImageContainer &container : containers) {
if (hasInstanceForId(container.instanceId())) {
NodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
@@ -1471,7 +1490,7 @@ QMultiHash<ModelNode, InformationName> NodeInstanceView::informationChanged(cons
{
QMultiHash<ModelNode, InformationName> informationChangeHash;
- foreach (const InformationContainer &container, containerVector) {
+ for (const InformationContainer &container : containerVector) {
if (hasInstanceForId(container.instanceId())) {
NodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
@@ -1529,7 +1548,8 @@ void NodeInstanceView::statePreviewImagesChanged(const StatePreviewImageChangedC
QVector<ModelNode> previewImageChangeVector;
- foreach (const ImageContainer &container, command.previews()) {
+ const QVector<ImageContainer> containers = command.previews();
+ for (const ImageContainer &container : containers) {
if (container.keyNumber() == -1) {
m_baseStatePreviewImage = container.image();
if (!container.image().isNull())
@@ -1553,7 +1573,8 @@ void NodeInstanceView::componentCompleted(const ComponentCompletedCommand &comma
QVector<ModelNode> nodeVector;
- foreach (const qint32 &instanceId, command.instances()) {
+ const QVector<qint32> instances = command.instances();
+ for (const qint32 &instanceId : instances) {
if (hasModelNodeForInternalId(instanceId))
nodeVector.append(modelNodeForInternalId(instanceId));
}
@@ -1571,7 +1592,8 @@ void NodeInstanceView::childrenChanged(const ChildrenChangedCommand &command)
QVector<ModelNode> childNodeVector;
- foreach (qint32 instanceId, command.childrenInstances()) {
+ const QVector<qint32> instances = command.childrenInstances();
+ for (const qint32 &instanceId : instances) {
if (hasInstanceForId(instanceId)) {
NodeInstance instance = instanceForId(instanceId);
if (instance.parentId() == -1 || !instance.directUpdates())
@@ -1596,7 +1618,8 @@ void NodeInstanceView::token(const TokenCommand &command)
QVector<ModelNode> nodeVector;
- foreach (const qint32 &instanceId, command.instances()) {
+ const QVector<qint32> instances = command.instances();
+ for (const qint32 &instanceId : instances) {
if (hasModelNodeForInternalId(instanceId))
nodeVector.append(modelNodeForInternalId(instanceId));
}
@@ -1611,7 +1634,8 @@ void NodeInstanceView::debugOutput(const DebugOutputCommand & command)
emitDocumentMessage(command.text());
} else {
QVector<qint32> instanceIdsWithChangedErrors;
- foreach (qint32 instanceId, command.instanceIds()) {
+ const QVector<qint32> instanceIds = command.instanceIds();
+ for (const qint32 &instanceId : instanceIds) {
NodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
if (instance.setError(command.text()))
@@ -1627,7 +1651,7 @@ void NodeInstanceView::debugOutput(const DebugOutputCommand & command)
void NodeInstanceView::sendToken(const QString &token, int number, const QVector<ModelNode> &nodeVector)
{
QVector<qint32> instanceIdVector;
- foreach (const ModelNode &node, nodeVector)
+ for (const ModelNode &node : nodeVector)
instanceIdVector.append(node.internalId());
m_nodeInstanceServer->token(TokenCommand(token, number, instanceIdVector));
@@ -1636,7 +1660,8 @@ void NodeInstanceView::sendToken(const QString &token, int number, const QVector
void NodeInstanceView::selectionChanged(const ChangeSelectionCommand &command)
{
clearSelectedModelNodes();
- foreach (const qint32 &instanceId, command.instanceIds()) {
+ const QVector<qint32> instanceIds = command.instanceIds();
+ for (const qint32 &instanceId : instanceIds) {
if (hasModelNodeForInternalId(instanceId))
selectModelNode(modelNodeForInternalId(instanceId));
}
@@ -1680,6 +1705,10 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand
} else if (command.type() == PuppetToCreatorCommand::Import3DSupport) {
const QVariantMap supportMap = qvariant_cast<QVariantMap>(command.data());
emitImport3DSupportChanged(supportMap);
+ } else if (command.type() == PuppetToCreatorCommand::ModelAtPos) {
+ ModelNode modelNode = modelNodeForInternalId(command.data().toUInt());
+ if (modelNode.isValid())
+ emitModelAtPosResult(modelNode);
}
}
@@ -2024,14 +2053,12 @@ void NodeInstanceView::handleQsbProcessExit(Utils::QtcProcess *qsbProcess, const
{
--m_remainingQsbTargets;
- QString errStr = qsbProcess->errorString();
- QByteArray stdErrStr = qsbProcess->readAllStandardError();
+ const QString errStr = qsbProcess->errorString();
+ const QByteArray stdErrStr = qsbProcess->readAllStandardError();
if (!errStr.isEmpty() || !stdErrStr.isEmpty()) {
- Core::MessageManager::writeSilently(
- QCoreApplication::translate("QmlDesigner::NodeInstanceView",
- "Failed to generate QSB file for: %1")
- .arg(shader));
+ Core::MessageManager::writeSilently(QCoreApplication::translate(
+ "QmlDesigner::NodeInstanceView", "Failed to generate QSB file for: %1").arg(shader));
if (!errStr.isEmpty())
Core::MessageManager::writeSilently(errStr);
if (!stdErrStr.isEmpty())
@@ -2126,27 +2153,13 @@ void NodeInstanceView::handleShaderChanges()
QStringList args = baseArgs;
args.append(outPath.toString());
args.append(shader);
- auto qsbProcess = new Utils::QtcProcess;
+ auto qsbProcess = new Utils::QtcProcess(this);
+ connect(qsbProcess, &Utils::QtcProcess::done, this, [this, qsbProcess, shader] {
+ handleQsbProcessExit(qsbProcess, shader);
+ });
qsbProcess->setWorkingDirectory(srcPath);
qsbProcess->setCommand({m_qsbPath, args});
qsbProcess->start();
-
- if (!qsbProcess->waitForStarted()) {
- handleQsbProcessExit(qsbProcess, shader);
- continue;
- }
-
- if (qsbProcess->state() == QProcess::Running) {
- connect(qsbProcess, &Utils::QtcProcess::finished,
- [thisView = QPointer<NodeInstanceView>(this), qsbProcess, shader]() {
- if (thisView)
- thisView->handleQsbProcessExit(qsbProcess, shader);
- else
- qsbProcess->deleteLater();
- });
- } else {
- handleQsbProcessExit(qsbProcess, shader);
- }
}
}
diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
index 7d4beeacd8d..f2baf9c9844 100644
--- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
@@ -132,8 +132,9 @@ QDateTime PuppetCreator::puppetSourceLastModified() const
};
QDateTime lastModified;
- foreach (const QString directoryPath, sourceDirectoryPaths) {
- foreach (const QFileInfo fileEntry, QDir(directoryPath).entryInfoList()) {
+ for (const QString &directoryPath : sourceDirectoryPaths) {
+ const QFileInfoList fileEntrys = QDir(directoryPath).entryInfoList();
+ for (const QFileInfo &fileEntry : fileEntrys) {
const QDateTime filePathLastModified = fileEntry.lastModified();
if (lastModified < filePathLastModified)
lastModified = filePathLastModified;
diff --git a/src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h b/src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h
index b03c86f772b..9274f916b83 100644
--- a/src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h
+++ b/src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h
@@ -41,10 +41,7 @@ public:
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
process,
&QProcess::deleteLater);
-
- process->terminate();
-
- process->deleteLater();
+ process->kill();
}
};
diff --git a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
index 806d37c99bd..e274a6126fa 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
@@ -289,7 +289,7 @@ QList<ItemLibraryEntry> ItemLibraryInfo::entriesForType(const QByteArray &typeNa
{
QList<ItemLibraryEntry> entries;
- foreach (const ItemLibraryEntry &entry, m_nameToEntryHash) {
+ for (const ItemLibraryEntry &entry : qAsConst(m_nameToEntryHash)) {
if (entry.typeName() == typeName)
entries += entry;
}
@@ -315,7 +315,7 @@ static inline QString keyForEntry(const ItemLibraryEntry &entry)
void ItemLibraryInfo::addEntries(const QList<ItemLibraryEntry> &entries, bool overwriteDuplicate)
{
- foreach (const ItemLibraryEntry &entry, entries) {
+ for (const ItemLibraryEntry &entry : entries) {
const QString key = keyForEntry(entry);
if (!overwriteDuplicate && m_nameToEntryHash.contains(key))
throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
index 322adb7b4cf..3891a8d65e7 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
@@ -115,10 +115,10 @@ void MetaInfoPrivate::parseItemLibraryDescriptions()
{
#ifndef QMLDESIGNER_TEST
Internal::WidgetPluginManager pluginManager;
- foreach (const QString &pluginDir, m_q->s_pluginDirs)
+ for (const QString &pluginDir : qAsConst(m_q->s_pluginDirs))
pluginManager.addPath(pluginDir);
- QList<IWidgetPlugin *> widgetPluginList = pluginManager.instances();
- foreach (IWidgetPlugin *plugin, widgetPluginList) {
+ const QList<IWidgetPlugin *> widgetPluginList = pluginManager.instances();
+ for (IWidgetPlugin *plugin : widgetPluginList) {
Internal::MetaInfoReader reader(*m_q);
try {
reader.readMetaInfoFile(plugin->metaInfo());
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index 5e34593cc34..ba975889528 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -82,6 +82,15 @@ using PropertyInfo = QPair<PropertyName, TypeName>;
QVector<PropertyInfo> getObjectTypes(const ObjectValue *ov, const ContextPtr &context, bool local = false, int rec = 0);
+
+static QByteArray getUnqualifiedName(const QByteArray &name)
+{
+ const QList<QByteArray> nameComponents = name.split('.');
+ if (nameComponents.size() < 2)
+ return name;
+ return nameComponents.constLast();
+}
+
static TypeName resolveTypeName(const ASTPropertyReference *ref, const ContextPtr &context, QVector<PropertyInfo> &dotProperties)
{
TypeName type = "unknown";
@@ -140,7 +149,8 @@ static QString qualifiedTypeNameForContext(const ObjectValue *objectValue,
QStringList packages;
if (const CppComponentValue *cppComponent = value_cast<CppComponentValue>(objectValue)) {
QString className = cppComponent->className();
- foreach (const LanguageUtils::FakeMetaObject::Export &e, cppComponent->metaObject()->exports()) {
+ const QList<LanguageUtils::FakeMetaObject::Export> &exports = cppComponent->metaObject()->exports();
+ for (const LanguageUtils::FakeMetaObject::Export &e : exports) {
if (e.type == className)
packages << e.package;
if (e.package == CppQmlTypes::cppPackage)
@@ -160,7 +170,7 @@ static QString qualifiedTypeNameForContext(const ObjectValue *objectValue,
CoreImport cImport = dep.coreImport(objectValue->originId());
if (!cImport.valid())
break;
- foreach (const Export &e, cImport.possibleExports) {
+ for (const Export &e : qAsConst(cImport.possibleExports)) {
if (e.pathRequired.isEmpty() || vContext.paths.contains(e.pathRequired)) {
switch (e.exportName.type) {
case ImportType::Library:
@@ -185,7 +195,7 @@ static QString qualifiedTypeNameForContext(const ObjectValue *objectValue,
// remove the search path prefix.
// this means that the same relative path wrt. different import paths will clash
QString filePath = e.exportName.path();
- foreach (const QString &path, vContext.paths) {
+ for (const QString &path : qAsConst(vContext.paths)) {
if (filePath.startsWith(path) && filePath.size() > path.size()
&& filePath.at(path.size()) == QLatin1Char('/'))
{
@@ -260,7 +270,7 @@ static QString qualifiedTypeNameForContext(const ObjectValue *objectValue,
};
if (!possibleLibraries.isEmpty()) {
if (hasQtQuick) {
- foreach (const QString &libImport, possibleLibraries)
+ for (const QString &libImport : qAsConst(possibleLibraries))
if (!libImport.startsWith(QLatin1String("QtQuick")))
possibleLibraries.removeAll(libImport);
}
@@ -362,7 +372,8 @@ static inline bool isValueType(const TypeName &type)
"vector2d",
"vector3d",
"vector4d",
- "font"});
+ "font",
+ "QQuickIcon"});
return objectValuesList.contains(type);
}
@@ -379,7 +390,8 @@ static inline bool isValueType(const QString &type)
"vector2d",
"vector3d",
"vector4d",
- "font"});
+ "font",
+ "QQuickIcon"});
return objectValuesList.contains(type);
}
@@ -456,8 +468,8 @@ QVector<PropertyInfo> getQmlTypes(const CppComponentValue *objectValue, const Co
//dot property
const CppComponentValue * qmlValue = value_cast<CppComponentValue>(objectValue->lookupMember(nameAsString, context));
if (qmlValue) {
- QVector<PropertyInfo> dotProperties = getQmlTypes(qmlValue, context, false, rec + 1);
- foreach (const PropertyInfo &propertyInfo, dotProperties) {
+ const QVector<PropertyInfo> dotProperties = getQmlTypes(qmlValue, context, false, rec + 1);
+ for (const PropertyInfo &propertyInfo : dotProperties) {
const PropertyName dotName = name + '.' + propertyInfo.first;
const TypeName type = propertyInfo.second;
propertyList.append({dotName, type});
@@ -467,8 +479,8 @@ QVector<PropertyInfo> getQmlTypes(const CppComponentValue *objectValue, const Co
if (isValueType(objectValue->propertyType(nameAsString))) {
const ObjectValue *dotObjectValue = value_cast<ObjectValue>(objectValue->lookupMember(nameAsString, context));
if (dotObjectValue) {
- QVector<PropertyInfo> dotProperties = getObjectTypes(dotObjectValue, context, false, rec + 1);
- foreach (const PropertyInfo &propertyInfo, dotProperties) {
+ const QVector<PropertyInfo> dotProperties = getObjectTypes(dotObjectValue, context, false, rec + 1);
+ for (const PropertyInfo &propertyInfo : dotProperties) {
const PropertyName dotName = name + '.' + propertyInfo.first;
const TypeName type = propertyInfo.second;
propertyList.append({dotName, type});
@@ -786,22 +798,49 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
} else {
m_isFileComponent = true;
const Imports *imports = context()->imports(document());
- const ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data());
+ const ImportInfo importInfo = imports->info(lookupNameComponent().constLast(),
+ context().data());
+
if (importInfo.isValid()) {
if (importInfo.type() == ImportType::Library) {
m_majorVersion = importInfo.version().majorVersion();
m_minorVersion = importInfo.version().minorVersion();
}
- bool prepandName = (importInfo.type() == ImportType::Library || importInfo.type() == ImportType::Directory)
- && !m_qualfiedTypeName.contains('.');
+ bool prepandName = (importInfo.type() == ImportType::Library
+ || importInfo.type() == ImportType::Directory)
+ && !m_qualfiedTypeName.contains('.');
if (prepandName)
- m_qualfiedTypeName.prepend(importInfo.name().toUtf8() + '.');
+ m_qualfiedTypeName.prepend(importInfo.name().toUtf8() + '.');
}
}
m_objectValue = objectValue;
m_defaultPropertyName = context()->defaultPropertyName(objectValue).toUtf8();
m_isValid = true;
setupPrototypes();
+ } else {
+ // Special case for aliased types for the rewriter
+
+ const Imports *imports = context()->imports(document());
+ const ImportInfo importInfo = imports->info(QString::fromUtf8(m_qualfiedTypeName),
+ context().data());
+ if (importInfo.isValid()) {
+ if (importInfo.type() == ImportType::Library) {
+ m_majorVersion = importInfo.version().majorVersion();
+ m_minorVersion = importInfo.version().minorVersion();
+ }
+
+ m_qualfiedTypeName = getUnqualifiedName(m_qualfiedTypeName);
+
+ bool prepandName = (importInfo.type() == ImportType::Library
+ || importInfo.type() == ImportType::Directory);
+ if (prepandName)
+ m_qualfiedTypeName.prepend(importInfo.name().toUtf8() + '.');
+ }
+
+ m_objectValue = getObjectValue();
+ m_defaultPropertyName = context()->defaultPropertyName(objectValue).toUtf8();
+ m_isValid = true;
+ setupPrototypes();
}
}
}
@@ -825,7 +864,7 @@ const CppComponentValue *NodeMetaInfoPrivate::getCppComponentValue() const
const QmlJS::Imports *importsPtr = context()->imports(document());
if (importsPtr) {
const QList<QmlJS::Import> &imports = importsPtr->all();
- foreach (const QmlJS::Import &import, imports) {
+ for (const QmlJS::Import &import : imports) {
if (import.info.path() != QString::fromUtf8(module))
continue;
const Value *lookupResult = import.object->lookupMember(QString::fromUtf8(type), context());
@@ -846,9 +885,11 @@ const CppComponentValue *NodeMetaInfoPrivate::getCppComponentValue() const
const CppComponentValue *cppValue = context()->valueOwner()->cppQmlTypes().objectByCppName(QString::fromUtf8(type));
if (cppValue) {
- foreach (const LanguageUtils::FakeMetaObject::Export &exportValue, cppValue->metaObject()->exports()) {
+ const QList<LanguageUtils::FakeMetaObject::Export> exports = cppValue->metaObject()->exports();
+ for (const LanguageUtils::FakeMetaObject::Export &exportValue : exports) {
if (exportValue.package.toUtf8() != "<cpp>") {
- foreach (const QmlJS::Import &import, context()->imports(document())->all()) {
+ const QList<QmlJS::Import> imports = context()->imports(document())->all();
+ for (const QmlJS::Import &import : imports) {
if (import.info.path() != exportValue.package)
continue;
const Value *lookupResult = import.object->lookupMember(exportValue.type, context());
@@ -884,14 +925,14 @@ const Document *NodeMetaInfoPrivate::document() const
void NodeMetaInfoPrivate::setupLocalPropertyInfo(const QVector<PropertyInfo> &localPropertyInfos)
{
- foreach (const PropertyInfo &propertyInfo, localPropertyInfos) {
+ for (const PropertyInfo &propertyInfo : localPropertyInfos) {
m_localProperties.append(propertyInfo.first);
}
}
void NodeMetaInfoPrivate::setupPropertyInfo(const QVector<PropertyInfo> &propertyInfos)
{
- foreach (const PropertyInfo &propertyInfo, propertyInfos) {
+ for (const PropertyInfo &propertyInfo : propertyInfos) {
if (!m_properties.contains(propertyInfo.first)) {
m_properties.append(propertyInfo.first);
m_propertyTypes.append(propertyInfo.second);
@@ -1028,14 +1069,6 @@ bool NodeMetaInfoPrivate::isPropertyEnum(const PropertyName &propertyName) const
return qmlObjectValue->getEnum(QString::fromUtf8(propertyType(propertyName))).isValid();
}
-static QByteArray getUnqualifiedName(const QByteArray &name)
-{
- const QList<QByteArray> nameComponents = name.split('.');
- if (nameComponents.size() < 2)
- return name;
- return nameComponents.constLast();
-}
-
static QByteArray getPackage(const QByteArray &name)
{
QList<QByteArray> nameComponents = name.split('.');
@@ -1197,7 +1230,8 @@ QString NodeMetaInfoPrivate::importDirectoryPath() const
return importInfo.path();
} else if (importInfo.type() == ImportType::Library) {
if (modelManager) {
- foreach (const QString &importPath, model()->importPaths()) {
+ const QStringList importPaths = model()->importPaths();
+ for (const QString &importPath : importPaths) {
const QString targetPath = QDir(importPath).filePath(importInfo.path());
if (QDir(targetPath).exists())
return targetPath;
@@ -1271,7 +1305,7 @@ void NodeMetaInfoPrivate::setupPrototypes()
return;
}
- foreach (const ObjectValue *ov, objects) {
+ for (const ObjectValue *ov : qAsConst(objects)) {
TypeDescription description;
description.className = ov->className();
description.minorVersion = -1;
@@ -1301,7 +1335,8 @@ void NodeMetaInfoPrivate::setupPrototypes()
} else {
bool found = false;
if (cppExport.isValid()) {
- foreach (const LanguageUtils::FakeMetaObject::Export &exportValue, qmlValue->metaObject()->exports()) {
+ const QList<LanguageUtils::FakeMetaObject::Export> exports = qmlValue->metaObject()->exports();
+ for (const LanguageUtils::FakeMetaObject::Export &exportValue : exports) {
if (exportValue.package.toUtf8() != "<cpp>") {
found = true;
description.className = exportValue.package + '.' + exportValue.type;
@@ -1612,7 +1647,8 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
if (m_privateData->prototypeCacheNegatives().contains(Internal::stringIdentifier(type, majorVersion, minorVersion)))
return false; //take a shortcut - optimization
- foreach (const NodeMetaInfo &superClass, superClasses()) {
+ const QList<NodeMetaInfo> superClassList = superClasses();
+ for (const NodeMetaInfo &superClass : superClassList) {
if (superClass.m_privateData->cleverCheckType(type)
&& superClass.availableInVersion(majorVersion, minorVersion)) {
m_privateData->prototypeCachePositives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion));
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index 342e0a65fb6..5ece130a573 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -173,7 +173,7 @@ void SubComponentManager::parseDirectories()
for (const auto &assetPath : assetPaths)
parseDirectory(assetPath);
- foreach (const Import &import, m_imports) {
+ for (const Import &import : qAsConst(m_imports)) {
if (import.isFileImport()) {
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
if (dirInfo.exists() && dirInfo.isDir()) {
@@ -184,7 +184,8 @@ void SubComponentManager::parseDirectories()
QString url = import.url();
url.replace(QLatin1Char('.'), QLatin1Char('/'));
QFileInfo dirInfo = QFileInfo(url);
- foreach (const QString &path, importPaths()) {
+ const QStringList paths = importPaths();
+ for (const QString &path : paths) {
QString fullUrl = path + QLatin1Char('/') + url;
dirInfo = QFileInfo(fullUrl);
@@ -222,7 +223,8 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
designerDir.setNameFilters(filter);
QStringList metaFiles = designerDir.entryList(QDir::Files);
- foreach (const QFileInfo &metaInfoFile, designerDir.entryInfoList(QDir::Files)) {
+ const QFileInfoList metaInfoList = designerDir.entryInfoList(QDir::Files);
+ for (const QFileInfo &metaInfoFile : metaInfoList) {
if (model() && model()->metaInfo().itemLibraryInfo()) {
Internal::MetaInfoReader reader(model()->metaInfo());
reader.setQualifcation(qualification);
@@ -250,7 +252,8 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
QFileInfoList monitoredList = watchedFiles(canonicalDirPath);
QFileInfoList newList;
- foreach (const QFileInfo &qmlFile, dir.entryInfoList()) {
+ const QFileInfoList qmlFileList = dir.entryInfoList();
+ for (const QFileInfo &qmlFile : qmlFileList) {
if (QFileInfo(m_filePath.toLocalFile()) == qmlFile) {
// do not parse main file
continue;
@@ -279,7 +282,8 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
continue;
}
if (oldFileInfo < newFileInfo) {
- foreach (const QString &qualifier, m_dirToQualifier.value(canonicalDirPath))
+ const QString qualifiers = m_dirToQualifier.value(canonicalDirPath);
+ for (const QChar &qualifier : qualifiers)
unregisterQmlFile(oldFileInfo, qualifier);
m_watcher.removePath(oldFileInfo.filePath());
++oldIter;
@@ -291,7 +295,8 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
}
while (oldIter != monitoredList.constEnd()) {
- foreach (const QString &qualifier, m_dirToQualifier.value(canonicalDirPath))
+ const QString qualifiers = m_dirToQualifier.value(canonicalDirPath);
+ for (const QChar &qualifier : qualifiers)
unregisterQmlFile(*oldIter, qualifier);
++oldIter;
}
@@ -315,7 +320,8 @@ void SubComponentManager::parseFile(const QString &canonicalFilePath, bool addTo
const QFileInfo fi(canonicalFilePath);
const QString dir = fi.path();
- foreach (const QString &qualifier, m_dirToQualifier.values(dir)) {
+ const QStringList qualifiers = m_dirToQualifier.values(dir);
+ for (const QString &qualifier : qualifiers) {
registerQmlFile(fi, qualifier, addToLibrary);
}
registerQmlFile(fi, qualification, addToLibrary);
@@ -331,7 +337,8 @@ QFileInfoList SubComponentManager::watchedFiles(const QString &canonicalDirPath)
{
QFileInfoList files;
- foreach (const QString &monitoredFile, m_watcher.files()) {
+ const QStringList monitoredFiles = m_watcher.files();
+ for (const QString &monitoredFile : monitoredFiles) {
QFileInfo fileInfo(monitoredFile);
if (fileInfo.dir().absolutePath() == canonicalDirPath)
files.append(fileInfo);
diff --git a/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
index 4b2ff2f39cc..de1753e2590 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
@@ -203,6 +203,19 @@ SignalHandlerProperty AbstractProperty::toSignalHandlerProperty() const
return SignalHandlerProperty();
}
+SignalDeclarationProperty AbstractProperty::toSignalDeclarationProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ SignalDeclarationProperty propertyNode(name(), internalNode(), model(), view());
+
+ if (propertyNode.isSignalDeclarationProperty())
+ return propertyNode;
+
+ return SignalDeclarationProperty();
+}
+
NodeListProperty AbstractProperty::toNodeListProperty() const
{
if (!isValid())
@@ -307,6 +320,18 @@ bool AbstractProperty::isSignalHandlerProperty() const
return false;
}
+bool AbstractProperty::isSignalDeclarationProperty() const
+{
+ if (!isValid())
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
+
+ if (internalNode()->hasProperty(name())) {
+ Q_ASSERT(internalNode()->property(name()));
+ return internalNode()->property(name())->isSignalDeclarationProperty();
+ }
+
+ return false;
+}
bool AbstractProperty::isBindingProperty() const
{
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index 046572d7140..8bf0e4347f2 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -97,14 +97,15 @@ ModelNode AbstractView::createModelNode(const TypeName &typeName)
}
ModelNode AbstractView::createModelNode(const TypeName &typeName,
- int majorVersion,
- int minorVersion,
- const QList<QPair<PropertyName, QVariant> > &propertyList,
- const QList<QPair<PropertyName, QVariant> > &auxPropertyList,
- const QString &nodeSource,
- ModelNode::NodeSourceType nodeSourceType)
+ int majorVersion,
+ int minorVersion,
+ const QList<QPair<PropertyName, QVariant>> &propertyList,
+ const QList<QPair<PropertyName, QVariant>> &auxPropertyList,
+ const QString &nodeSource,
+ ModelNode::NodeSourceType nodeSourceType,
+ const QString &behaviorPropertyName)
{
- return ModelNode(model()->d->createNode(typeName, majorVersion, minorVersion, propertyList, auxPropertyList, nodeSource, nodeSourceType), model(), this);
+ return ModelNode(model()->d->createNode(typeName, majorVersion, minorVersion, propertyList, auxPropertyList, nodeSource, nodeSourceType, behaviorPropertyName), model(), this);
}
@@ -139,7 +140,6 @@ void AbstractView::removeModel()
}
WidgetInfo AbstractView::createWidgetInfo(QWidget *widget,
- WidgetInfo::ToolBarWidgetFactoryInterface *toolBarWidgetFactory,
const QString &uniqueId,
WidgetInfo::PlacementHint placementHint,
int placementPriority,
@@ -149,7 +149,6 @@ WidgetInfo AbstractView::createWidgetInfo(QWidget *widget,
WidgetInfo widgetInfo;
widgetInfo.widget = widget;
- widgetInfo.toolBarWidgetFactory = toolBarWidgetFactory;
widgetInfo.uniqueId = uniqueId;
widgetInfo.placementHint = placementHint;
widgetInfo.placementPriority = placementPriority;
@@ -352,6 +351,10 @@ void AbstractView::signalHandlerPropertiesChanged(const QVector<SignalHandlerPro
{
}
+void AbstractView::signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty>& /*propertyList*/, PropertyChangeFlags /*propertyChange*/)
+{
+}
+
void AbstractView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
{
}
@@ -405,6 +408,9 @@ void AbstractView::updateImport3DSupport(const QVariantMap & /*supportMap*/)
{
}
+// a Quick3DModel that is picked at the requested position in the 3D Editor
+void AbstractView::modelAtPosReady(const ModelNode & /*modelNode*/) {}
+
void AbstractView::modelNodePreviewPixmapChanged(const ModelNode & /*node*/, const QPixmap & /*pixmap*/)
{
}
@@ -796,6 +802,12 @@ void AbstractView::emitImport3DSupportChanged(const QVariantMap &supportMap)
model()->d->notifyImport3DSupportChanged(supportMap);
}
+void AbstractView::emitModelAtPosResult(const ModelNode &modelNode)
+{
+ if (model())
+ model()->d->notifyModelAtPosResult(modelNode);
+}
+
void AbstractView::emitRewriterEndTransaction()
{
if (model())
@@ -822,7 +834,7 @@ void AbstractView::changeRootNodeType(const TypeName &type, int majorVersion, in
void AbstractView::ensureMaterialLibraryNode()
{
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
- if (matLib.isValid())
+ if (matLib.isValid() || rootModelNode().isSubclassOf("QtQuick3D.Material"))
return;
// Create material library node
@@ -851,13 +863,11 @@ void AbstractView::ensureMaterialLibraryNode()
}
// Returns ModelNode for project's material library.
+// Since this calls ensureMaterialLibraryNode(), it should only be called within a transaction.
ModelNode AbstractView::materialLibraryNode()
{
ensureMaterialLibraryNode();
-
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
- QTC_ASSERT(matLib.isValid(), return {});
-
return matLib;
}
@@ -939,7 +949,8 @@ QmlTimeline AbstractView::currentTimeline() const
static int getMinorVersionFromImport(const Model *model)
{
- foreach (const Import &import, model->imports()) {
+ const QList<Import> imports = model->imports();
+ for (const Import &import : imports) {
if (import.isLibraryImport() && import.url() == "QtQuick") {
const QString versionString = import.version();
if (versionString.contains(".")) {
@@ -954,7 +965,8 @@ static int getMinorVersionFromImport(const Model *model)
static int getMajorVersionFromImport(const Model *model)
{
- foreach (const Import &import, model->imports()) {
+ const QList<Import> imports = model->imports();
+ for (const Import &import : imports) {
if (import.isLibraryImport() && import.url() == QStringLiteral("QtQuick")) {
const QString versionString = import.version();
if (versionString.contains(QStringLiteral("."))) {
@@ -984,7 +996,8 @@ static int getMajorVersionFromNode(const ModelNode &modelNode)
static int getMinorVersionFromNode(const ModelNode &modelNode)
{
if (modelNode.metaInfo().isValid()) {
- foreach (const NodeMetaInfo &info, modelNode.metaInfo().classHierarchy()) {
+ const QList<NodeMetaInfo> infos = modelNode.metaInfo().classHierarchy();
+ for (const NodeMetaInfo &info : infos) {
if (info.typeName() == "QtQuick.QtObject" || info.typeName() == "QtQuick.Item")
return info.minorVersion();
}
diff --git a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
index 4639fd101c3..bc87c7c7e10 100644
--- a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
+++ b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
@@ -28,12 +28,12 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/parser/qmljsast_p.h>
#include <qmljstools/qmljsindenter.h>
+#include <qmljstools/qmljscodestylepreferences.h>
#include <qmljseditor/qmljseditordocument.h>
#include <qmljseditor/qmljscomponentfromobjectdef.h>
#include <qmljseditor/qmljscompletionassist.h>
#include <qmljstools/qmljstoolssettings.h>
#include <texteditor/tabsettings.h>
-#include <texteditor/simplecodestylepreferences.h>
#include <utils/changeset.h>
#include <typeinfo>
@@ -95,8 +95,9 @@ bool BaseTextEditModifier::renameId(const QString &oldId, const QString &newId)
if (auto document = qobject_cast<QmlJSEditor::QmlJSEditorDocument *>(
m_textEdit->textDocument())) {
Utils::ChangeSet changeSet;
- foreach (const QmlJS::SourceLocation &loc,
- document->semanticInfo().idLocations.value(oldId)) {
+ const QList<QmlJS::SourceLocation> locations = document->semanticInfo()
+ .idLocations.value(oldId);
+ for (const QmlJS::SourceLocation &loc : locations) {
changeSet.replace(loc.begin(), loc.end(), newId);
}
QTextCursor tc = textCursor();
diff --git a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
index f08c3962ae7..d75147f9b3e 100644
--- a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
@@ -142,9 +142,9 @@ ModelNode BindingProperty::resolveToModelNode() const
static inline QStringList commaSeparatedSimplifiedStringList(const QString &string)
{
- QStringList stringList = string.split(QStringLiteral(","));
+ const QStringList stringList = string.split(QStringLiteral(","));
QStringList simpleList;
- foreach (const QString &simpleString, stringList)
+ for (const QString &simpleString : stringList)
simpleList.append(simpleString.simplified());
return simpleList;
}
@@ -190,8 +190,8 @@ QList<ModelNode> BindingProperty::resolveToModelNodeList() const
QString string = expression();
string.chop(1);
string.remove(0, 1);
- QStringList simplifiedList = commaSeparatedSimplifiedStringList(string);
- foreach (const QString &nodeId, simplifiedList) {
+ const QStringList simplifiedList = commaSeparatedSimplifiedStringList(string);
+ for (const QString &nodeId : simplifiedList) {
if (view()->hasId(nodeId))
returnList.append(view()->modelNodeForId(nodeId));
}
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode.cpp b/src/plugins/qmldesigner/designercore/model/internalnode.cpp
index d2edc4e64cb..3d29c24cb1f 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnode.cpp
@@ -215,6 +215,15 @@ InternalSignalHandlerProperty::Pointer InternalNode::signalHandlerProperty(const
return InternalSignalHandlerProperty::Pointer();
}
+InternalSignalDeclarationProperty::Pointer InternalNode::signalDeclarationProperty(const PropertyName &name) const
+{
+ InternalProperty::Pointer property = m_namePropertyHash.value(name);
+ if (property->isSignalDeclarationProperty())
+ return property.staticCast<InternalSignalDeclarationProperty>();
+
+ return InternalSignalDeclarationProperty::Pointer();
+}
+
InternalVariantProperty::Pointer InternalNode::variantProperty(const PropertyName &name) const
{
InternalProperty::Pointer property = m_namePropertyHash.value(name);
@@ -236,6 +245,12 @@ void InternalNode::addSignalHandlerProperty(const PropertyName &name)
m_namePropertyHash.insert(name, newProperty);
}
+void InternalNode::addSignalDeclarationProperty(const PropertyName &name)
+{
+ InternalProperty::Pointer newProperty(InternalSignalDeclarationProperty::create(name, internalPointer()));
+ m_namePropertyHash.insert(name, newProperty);
+}
+
InternalNodeListProperty::Pointer InternalNode::nodeListProperty(const PropertyName &name) const
{
InternalProperty::Pointer property = m_namePropertyHash.value(name);
@@ -311,7 +326,8 @@ QList<InternalProperty::Pointer> InternalNode::propertyList() const
QList<InternalNodeAbstractProperty::Pointer> InternalNode::nodeAbstractPropertyList() const
{
QList<InternalNodeAbstractProperty::Pointer> abstractPropertyList;
- foreach (const InternalProperty::Pointer &property, propertyList()) {
+ const QList<InternalProperty::Pointer> properties = propertyList();
+ for (const InternalProperty::Pointer &property : properties) {
if (property->isNodeAbstractProperty())
abstractPropertyList.append(property->toNodeAbstractProperty());
}
@@ -323,7 +339,8 @@ QList<InternalNodeAbstractProperty::Pointer> InternalNode::nodeAbstractPropertyL
QList<InternalNode::Pointer> InternalNode::allSubNodes() const
{
QList<InternalNode::Pointer> nodeList;
- foreach (const InternalNodeAbstractProperty::Pointer &property, nodeAbstractPropertyList()) {
+ const QList<InternalNodeAbstractProperty::Pointer> properties = nodeAbstractPropertyList();
+ for (const InternalNodeAbstractProperty::Pointer &property : properties) {
nodeList.append(property->allSubNodes());
}
@@ -333,7 +350,8 @@ QList<InternalNode::Pointer> InternalNode::allSubNodes() const
QList<InternalNode::Pointer> InternalNode::allDirectSubNodes() const
{
QList<InternalNode::Pointer> nodeList;
- foreach (const InternalNodeAbstractProperty::Pointer &property, nodeAbstractPropertyList()) {
+ const QList<InternalNodeAbstractProperty::Pointer> properties = nodeAbstractPropertyList();
+ for (const InternalNodeAbstractProperty::Pointer &property : properties) {
nodeList.append(property->directSubNodes());
}
@@ -386,5 +404,15 @@ void InternalNode::setNodeSourceType(int i)
m_nodeSourceType = i;
}
+QString InternalNode::behaviorPropertyName() const
+{
+ return m_behaviorPropertyName;
+}
+
+void InternalNode::setBehaviorPropertyName(const QString &name)
+{
+ m_behaviorPropertyName = name;
+}
+
}
}
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode_p.h b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
index 8770763b4e3..04f0de41450 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode_p.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
@@ -92,6 +92,7 @@ public:
InternalProperty::Pointer property(const PropertyName &name) const;
InternalBindingProperty::Pointer bindingProperty(const PropertyName &name) const;
InternalSignalHandlerProperty::Pointer signalHandlerProperty(const PropertyName &name) const;
+ InternalSignalDeclarationProperty::Pointer signalDeclarationProperty(const PropertyName &name) const;
InternalVariantProperty::Pointer variantProperty(const PropertyName &name) const;
InternalNodeListProperty::Pointer nodeListProperty(const PropertyName &name) const;
InternalNodeAbstractProperty::Pointer nodeAbstractProperty(const PropertyName &name) const;
@@ -99,11 +100,11 @@ public:
void addBindingProperty(const PropertyName &name);
void addSignalHandlerProperty(const PropertyName &name);
+ void addSignalDeclarationProperty(const PropertyName &name);
void addNodeListProperty(const PropertyName &name);
void addVariantProperty(const PropertyName &name);
void addNodeProperty(const PropertyName &name, const TypeName &dynamicTypeName);
-
PropertyNameList propertyNameList() const;
bool hasProperties() const;
@@ -125,6 +126,9 @@ public:
int nodeSourceType() const;
void setNodeSourceType(int i);
+ QString behaviorPropertyName() const;
+ void setBehaviorPropertyName(const QString &name);
+
protected:
Pointer internalPointer() const;
void setInternalWeakPointer(const Pointer &pointer);
@@ -151,6 +155,8 @@ private:
QString m_nodeSource;
int m_nodeSourceType = 0;
+
+ QString m_behaviorPropertyName;
};
Utils::QHashValueType qHash(const InternalNodePointer& node);
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
index 97c191e35c5..b320eb24a05 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
@@ -99,7 +99,7 @@ void InternalNodeListProperty::slide(int from, int to)
QList<InternalNode::Pointer> InternalNodeListProperty::allSubNodes() const
{
QList<InternalNode::Pointer> nodeList;
- foreach (const InternalNode::Pointer &childNode, m_nodeList) {
+ for (const InternalNode::Pointer &childNode : qAsConst(m_nodeList)) {
nodeList.append(childNode->allSubNodes());
nodeList.append(childNode);
}
diff --git a/src/plugins/qmldesigner/designercore/model/internalproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
index df2e2a22756..24730c74cc1 100644
--- a/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
@@ -107,6 +107,11 @@ bool InternalProperty::isSignalHandlerProperty() const
return false;
}
+bool InternalProperty::isSignalDeclarationProperty() const
+{
+ return false;
+}
+
QSharedPointer<InternalVariantProperty> InternalProperty::toVariantProperty() const
{
@@ -143,6 +148,12 @@ QSharedPointer<InternalSignalHandlerProperty> InternalProperty::toSignalHandlerP
return internalPointer().staticCast<InternalSignalHandlerProperty>();
}
+QSharedPointer<InternalSignalDeclarationProperty> InternalProperty::toSignalDeclarationProperty() const
+{
+ Q_ASSERT(internalPointer().dynamicCast<InternalSignalDeclarationProperty>());
+ return internalPointer().staticCast<InternalSignalDeclarationProperty>();
+}
+
void InternalProperty::remove()
{
propertyOwner()->removeProperty(name());
diff --git a/src/plugins/qmldesigner/designercore/model/internalproperty.h b/src/plugins/qmldesigner/designercore/model/internalproperty.h
index cf10f8ef7d9..97136d3c86e 100644
--- a/src/plugins/qmldesigner/designercore/model/internalproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalproperty.h
@@ -36,6 +36,7 @@ namespace Internal {
class InternalBindingProperty;
class InternalSignalHandlerProperty;
+class InternalSignalDeclarationProperty;
class InternalVariantProperty;
class InternalNodeListProperty;
class InternalNodeProperty;
@@ -62,6 +63,7 @@ public:
virtual bool isNodeProperty() const;
virtual bool isNodeAbstractProperty() const;
virtual bool isSignalHandlerProperty() const;
+ virtual bool isSignalDeclarationProperty() const;
QSharedPointer<InternalBindingProperty> toBindingProperty() const;
QSharedPointer<InternalVariantProperty> toVariantProperty() const;
@@ -69,6 +71,7 @@ public:
QSharedPointer<InternalNodeProperty> toNodeProperty() const;
QSharedPointer<InternalNodeAbstractProperty> toNodeAbstractProperty() const;
QSharedPointer<InternalSignalHandlerProperty> toSignalHandlerProperty() const;
+ QSharedPointer<InternalSignalDeclarationProperty> toSignalDeclarationProperty() const;
InternalNodePointer propertyOwner() const;
diff --git a/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp
index 08ce26a4c83..e7905e8e864 100644
--- a/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp
@@ -63,5 +63,42 @@ bool InternalSignalHandlerProperty::isSignalHandlerProperty() const
return true;
}
+InternalSignalDeclarationProperty::Pointer InternalSignalDeclarationProperty::create(const PropertyName &name, const InternalNodePointer &propertyOwner)
+{
+ auto newPointer(new InternalSignalDeclarationProperty(name, propertyOwner));
+ InternalSignalDeclarationProperty::Pointer smartPointer(newPointer);
+
+ newPointer->setInternalWeakPointer(smartPointer);
+
+ newPointer->setDynamicTypeName("signal");
+
+ return smartPointer;
+}
+
+bool InternalSignalDeclarationProperty::isValid() const
+{
+ return InternalProperty::isValid() && isSignalDeclarationProperty();
+}
+
+QString InternalSignalDeclarationProperty::signature() const
+{
+ return m_signature;
+}
+
+void InternalSignalDeclarationProperty::setSignature(const QString &signature)
+{
+ m_signature = signature;
+}
+
+bool InternalSignalDeclarationProperty::isSignalDeclarationProperty() const
+{
+ return true;
+}
+
+InternalSignalDeclarationProperty::InternalSignalDeclarationProperty(const PropertyName &name, const InternalNodePointer &propertyOwner)
+ : InternalProperty(name, propertyOwner)
+{
+}
+
} // namespace Internal
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h b/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h
index 9ecf424a544..c3f7f62e8ae 100644
--- a/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h
@@ -51,5 +51,26 @@ private:
QString m_source;
};
+class InternalSignalDeclarationProperty : public InternalProperty
+{
+public:
+ using Pointer = QSharedPointer<InternalSignalDeclarationProperty>;
+
+ static Pointer create(const PropertyName &name, const InternalNodePointer &propertyOwner);
+
+ bool isValid() const override;
+
+ QString signature() const;
+ void setSignature(const QString &source);
+
+ bool isSignalDeclarationProperty() const override;
+
+protected:
+ InternalSignalDeclarationProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
+
+private:
+ QString m_signature;
+};
+
} // namespace Internal
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index 47ce515f9e2..d2277dec3ae 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -97,9 +97,11 @@ ModelPrivate::ModelPrivate(Model *model)
0,
PropertyListType(),
PropertyListType(),
- QString(),
+ {},
ModelNode::NodeWithoutSource,
+ {},
true);
+
m_currentStateNode = m_rootInternalNode;
m_currentTimelineNode = m_rootInternalNode;
}
@@ -250,6 +252,7 @@ InternalNodePointer ModelPrivate::createNode(const TypeName &typeName,
const QList<QPair<PropertyName, QVariant>> &auxPropertyList,
const QString &nodeSource,
ModelNode::NodeSourceType nodeSourceType,
+ const QString &behaviorPropertyName,
bool isRootNode)
{
if (typeName.isEmpty())
@@ -263,6 +266,8 @@ InternalNodePointer ModelPrivate::createNode(const TypeName &typeName,
InternalNodePointer newNode = InternalNode::create(typeName, majorVersion, minorVersion, internalId);
newNode->setNodeSourceType(nodeSourceType);
+ newNode->setBehaviorPropertyName(behaviorPropertyName);
+
using PropertyPair = QPair<PropertyName, QVariant>;
for (const PropertyPair &propertyPair : propertyList) {
@@ -400,9 +405,13 @@ void ModelPrivate::notifyNodeInstanceViewLast(Callable call)
resetModel = true;
}
- for (QPointer<AbstractView> view : enabledViews()) {
- if (!view->isBlockingNotifications())
- call(view.data());
+ for (const QPointer<AbstractView> &view : enabledViews()) {
+ try {
+ if (!view->isBlockingNotifications())
+ call(view.data());
+ } catch (const Exception &e) {
+ e.showException(tr("Exception thrown by view %1.").arg(view->widgetInfo().tabName));
+ }
}
if (nodeInstanceView() && !nodeInstanceView()->isBlockingNotifications())
@@ -429,7 +438,7 @@ void ModelPrivate::notifyNormalViewsLast(Callable call)
if (nodeInstanceView() && !nodeInstanceView()->isBlockingNotifications())
call(nodeInstanceView());
- for (QPointer<AbstractView> view : enabledViews()) {
+ for (const QPointer<AbstractView> &view : enabledViews()) {
if (!view->isBlockingNotifications())
call(view.data());
}
@@ -441,7 +450,7 @@ void ModelPrivate::notifyNormalViewsLast(Callable call)
template<typename Callable>
void ModelPrivate::notifyInstanceChanges(Callable call)
{
- for (QPointer<AbstractView> view : enabledViews()) {
+ for (const QPointer<AbstractView> &view : enabledViews()) {
if (!view->isBlockingNotifications())
call(view.data());
}
@@ -589,6 +598,11 @@ void ModelPrivate::notifyImport3DSupportChanged(const QVariantMap &supportMap)
notifyInstanceChanges([&](AbstractView *view) { view->updateImport3DSupport(supportMap); });
}
+void ModelPrivate::notifyModelAtPosResult(const ModelNode &modelNode)
+{
+ notifyInstanceChanges([&](AbstractView *view) { view->modelAtPosReady(modelNode); });
+}
+
void ModelPrivate::notifyDragStarted(QMimeData *mimeData)
{
notifyInstanceChanges([&](AbstractView *view) { view->dragStarted(mimeData); });
@@ -833,6 +847,22 @@ void ModelPrivate::notifySignalHandlerPropertiesChanged(
});
}
+void ModelPrivate::notifySignalDeclarationPropertiesChanged(
+ const QVector<InternalSignalDeclarationPropertyPointer> &internalPropertyList,
+ AbstractView::PropertyChangeFlags propertyChange)
+{
+ notifyNodeInstanceViewLast([&](AbstractView *view) {
+ QVector<SignalDeclarationProperty> propertyList;
+ for (const InternalSignalDeclarationPropertyPointer &signalHandlerProperty : internalPropertyList) {
+ propertyList.append(SignalDeclarationProperty(signalHandlerProperty->name(),
+ signalHandlerProperty->propertyOwner(),
+ m_model,
+ view));
+ }
+ view->signalDeclarationPropertiesChanged(propertyList, propertyChange);
+ });
+}
+
void ModelPrivate::notifyScriptFunctionsChanged(const InternalNodePointer &node,
const QStringList &scriptFunctionList)
{
@@ -1090,6 +1120,19 @@ void ModelPrivate::setSignalHandlerProperty(const InternalNodePointer &node, con
notifySignalHandlerPropertiesChanged({signalHandlerProperty}, propertyChange);
}
+void ModelPrivate::setSignalDeclarationProperty(const InternalNodePointer &node, const PropertyName &name, const QString &signature)
+{
+ AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
+ if (!node->hasProperty(name)) {
+ node->addSignalDeclarationProperty(name);
+ propertyChange = AbstractView::PropertiesAdded;
+ }
+
+ InternalSignalDeclarationPropertyPointer signalDeclarationProperty = node->signalDeclarationProperty(name);
+ signalDeclarationProperty->setSignature(signature);
+ notifySignalDeclarationPropertiesChanged({signalDeclarationProperty}, propertyChange);
+}
+
void ModelPrivate::setVariantProperty(const InternalNodePointer &node, const PropertyName &name, const QVariant &value)
{
AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
@@ -1390,14 +1433,18 @@ void Model::changeImports(const QList<Import> &importsToBeAdded,
void Model::setPossibleImports(const QList<Import> &possibleImports)
{
- d->m_possibleImportList = possibleImports;
- d->notifyPossibleImportsChanged(possibleImports);
+ if (d->m_possibleImportList != possibleImports) {
+ d->m_possibleImportList = possibleImports;
+ d->notifyPossibleImportsChanged(possibleImports);
+ }
}
void Model::setUsedImports(const QList<Import> &usedImports)
{
- d->m_usedImportList = usedImports;
- d->notifyUsedImportsChanged(usedImports);
+ if (d->m_usedImportList != usedImports) {
+ d->m_usedImportList = usedImports;
+ d->notifyUsedImportsChanged(usedImports);
+ }
}
static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion)
diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h
index 09595670534..98be8a135fc 100644
--- a/src/plugins/qmldesigner/designercore/model/model_p.h
+++ b/src/plugins/qmldesigner/designercore/model/model_p.h
@@ -53,6 +53,7 @@ class InternalNode;
class InternalProperty;
class InternalBindingProperty;
class InternalSignalHandlerProperty;
+class InternalSignalDeclarationProperty;
class InternalVariantProperty;
class InternalNodeAbstractProperty;
class InternalNodeListProperty;
@@ -61,6 +62,7 @@ using InternalNodePointer = QSharedPointer<InternalNode>;
using InternalPropertyPointer = QSharedPointer<InternalProperty>;
using InternalBindingPropertyPointer = QSharedPointer<InternalBindingProperty>;
using InternalSignalHandlerPropertyPointer = QSharedPointer<InternalSignalHandlerProperty>;
+using InternalSignalDeclarationPropertyPointer = QSharedPointer<InternalSignalDeclarationProperty>;
using InternalVariantPropertyPointer = QSharedPointer<InternalVariantProperty>;
using InternalNodeAbstractPropertyPointer = QSharedPointer<InternalNodeAbstractProperty>;
using InternalNodeListPropertyPointer = QSharedPointer<InternalNodeListProperty>;
@@ -103,6 +105,7 @@ public:
const QList<QPair<PropertyName, QVariant> > &auxPropertyList,
const QString &nodeSource,
ModelNode::NodeSourceType nodeSourceType,
+ const QString &behaviorPropertyName,
bool isRootNode = false);
@@ -153,6 +156,7 @@ public:
const QList<InternalBindingPropertyPointer> &internalPropertyList);
void notifyBindingPropertiesChanged(const QList<InternalBindingPropertyPointer> &internalPropertyList, AbstractView::PropertyChangeFlags propertyChange);
void notifySignalHandlerPropertiesChanged(const QVector<InternalSignalHandlerPropertyPointer> &propertyList, AbstractView::PropertyChangeFlags propertyChange);
+ void notifySignalDeclarationPropertiesChanged(const QVector<InternalSignalDeclarationPropertyPointer> &propertyList, AbstractView::PropertyChangeFlags propertyChange);
void notifyVariantPropertiesChanged(const InternalNodePointer &node, const PropertyNameList &propertyNameList, AbstractView::PropertyChangeFlags propertyChange);
void notifyScriptFunctionsChanged(const InternalNodePointer &node, const QStringList &scriptFunctionList);
@@ -182,6 +186,7 @@ public:
void notifyUpdateActiveScene3D(const QVariantMap &sceneState);
void notifyModelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
void notifyImport3DSupportChanged(const QVariantMap &supportMap);
+ void notifyModelAtPosResult(const ModelNode &modelNode);
void notifyDragStarted(QMimeData *mimeData);
void notifyDragEnded();
@@ -219,6 +224,7 @@ public:
void setBindingProperty(const InternalNodePointer &node, const PropertyName &name, const QString &expression);
void setSignalHandlerProperty(const InternalNodePointer &node, const PropertyName &name, const QString &source);
+ void setSignalDeclarationProperty(const InternalNodePointer &node, const PropertyName &name, const QString &signature);
void setVariantProperty(const InternalNodePointer &node, const PropertyName &name, const QVariant &value);
void setDynamicVariantProperty(const InternalNodePointer &node, const PropertyName &name, const TypeName &propertyType, const QVariant &value);
void setDynamicBindingProperty(const InternalNodePointer &node, const PropertyName &name, const TypeName &dynamicPropertyType, const QString &expression);
diff --git a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
index df1939cc4bb..d2f4200e02d 100644
--- a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
@@ -62,7 +62,8 @@ static QString fixExpression(const QString &expression, const QHash<QString, QSt
static void syncVariantProperties(ModelNode &outputNode, const ModelNode &inputNode)
{
- foreach (const VariantProperty &property, inputNode.variantProperties()) {
+ const QList<VariantProperty> propertyies = inputNode.variantProperties();
+ for (const VariantProperty &property : propertyies) {
if (property.isDynamic()) {
outputNode.variantProperty(property.name()).
setDynamicTypeNameAndValue(property.dynamicTypeName(), property.value());
@@ -81,14 +82,16 @@ static void syncAuxiliaryProperties(ModelNode &outputNode, const ModelNode &inpu
static void syncBindingProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash)
{
- foreach (const BindingProperty &bindingProperty, inputNode.bindingProperties()) {
+ const QList<BindingProperty> propertyies = inputNode.bindingProperties();
+ for (const BindingProperty &bindingProperty : propertyies) {
outputNode.bindingProperty(bindingProperty.name()).setExpression(fixExpression(bindingProperty.expression(), idRenamingHash));
}
}
static void syncSignalHandlerProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash)
{
- foreach (const SignalHandlerProperty &signalProperty, inputNode.signalProperties()) {
+ const QList<SignalHandlerProperty> propertyies = inputNode.signalProperties();
+ for (const SignalHandlerProperty &signalProperty : propertyies) {
outputNode.signalHandlerProperty(signalProperty.name()).setSource(fixExpression(signalProperty.source(), idRenamingHash));
}
}
@@ -119,7 +122,8 @@ static void splitIdInBaseNameAndNumber(const QString &id, QString *baseId, int *
static void setupIdRenamingHash(const ModelNode &modelNode, QHash<QString, QString> &idRenamingHash, AbstractView *view)
{
- foreach (const ModelNode &node, modelNode.allSubModelNodesAndThisNode()) {
+ const QList<ModelNode> nodes = modelNode.allSubModelNodesAndThisNode();
+ for (const ModelNode &node : nodes) {
if (!node.id().isEmpty()) {
QString newId = node.id();
QString baseId;
@@ -141,7 +145,8 @@ static void syncNodeProperties(ModelNode &outputNode, const ModelNode &inputNode
const QHash<QString, QString> &idRenamingHash,
AbstractView *view, const MergePredicate &mergePredicate)
{
- foreach (const NodeProperty &nodeProperty, inputNode.nodeProperties()) {
+ const QList<NodeProperty> propertyies = inputNode.nodeProperties();
+ for (const NodeProperty &nodeProperty : propertyies) {
ModelNode node = nodeProperty.modelNode();
if (!mergePredicate(node))
continue;
@@ -154,8 +159,10 @@ static void syncNodeListProperties(ModelNode &outputNode, const ModelNode &input
const QHash<QString, QString> &idRenamingHash,
AbstractView *view, const MergePredicate &mergePredicate)
{
- foreach (const NodeListProperty &nodeListProperty, inputNode.nodeListProperties()) {
- foreach (const ModelNode &node, nodeListProperty.toModelNodeList()) {
+ const QList<NodeListProperty> propertyies = inputNode.nodeListProperties();
+ for (const NodeListProperty &nodeListProperty : propertyies) {
+ const QList<ModelNode> nodes = nodeListProperty.toModelNodeList();
+ for (const ModelNode &node : nodes) {
if (!mergePredicate(node))
continue;
ModelNode newNode = createNodeFromNode(node, idRenamingHash, view, mergePredicate);
@@ -191,7 +198,7 @@ ModelNode ModelMerger::insertModel(const ModelNode &modelNode, const MergePredic
QList<Import> newImports;
- foreach (const Import &import, modelNode.model()->imports()) {
+ for (const Import &import : modelNode.model()->imports()) {
if (!view()->model()->hasImport(import, true, true))
newImports.append(import);
}
@@ -216,7 +223,8 @@ void ModelMerger::replaceModel(const ModelNode &modelNode, const MergePredicate
view()->executeInTransaction("ModelMerger::replaceModel", [this, modelNode, &predicate](){
ModelNode rootNode(view()->rootModelNode());
- foreach (const PropertyName &propertyName, rootNode.propertyNames())
+ const QList<PropertyName> propertyNames = rootNode.propertyNames();
+ for (const PropertyName &propertyName : propertyNames)
rootNode.removeProperty(propertyName);
QHash<QString, QString> idRenamingHash;
diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
index fe3d0cf1e1b..b61aa9ecd63 100644
--- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
@@ -197,7 +197,8 @@ static bool isIdToAvoid(const QString& id)
"shaderInfo",
"sprite",
"spriteSequence",
- "baseState"
+ "baseState",
+ "rect"
};
return ids.contains(id);
@@ -486,6 +487,13 @@ SignalHandlerProperty ModelNode::signalHandlerProperty(const PropertyName &name)
return SignalHandlerProperty(name, m_internalNode, model(), view());
}
+SignalDeclarationProperty ModelNode::signalDeclarationProperty(const PropertyName &name) const
+{
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ return SignalDeclarationProperty(name, m_internalNode, model(), view());
+}
/*!
\brief Returns a NodeProperty
@@ -595,7 +603,8 @@ QList<AbstractProperty> ModelNode::properties() const
QList<AbstractProperty> propertyList;
- foreach (const PropertyName &propertyName, internalNode()->propertyNameList()) {
+ const QList<PropertyName> propertyNames = internalNode()->propertyNameList();
+ for (const PropertyName &propertyName : propertyNames) {
AbstractProperty property(propertyName, internalNode(), model(), view());
propertyList.append(property);
}
@@ -614,7 +623,8 @@ QList<VariantProperty> ModelNode::variantProperties() const
{
QList<VariantProperty> propertyList;
- foreach (const AbstractProperty &abstractProperty, properties())
+ const QList<AbstractProperty> abstractProperties = properties();
+ for (const AbstractProperty &abstractProperty : abstractProperties)
if (abstractProperty.isVariantProperty())
propertyList.append(abstractProperty.toVariantProperty());
return propertyList;
@@ -624,7 +634,8 @@ QList<NodeAbstractProperty> ModelNode::nodeAbstractProperties() const
{
QList<NodeAbstractProperty> propertyList;
- foreach (const AbstractProperty &nodeAbstractProperty, properties())
+ const QList<AbstractProperty> abstractProperties = properties();
+ for (const AbstractProperty &nodeAbstractProperty : abstractProperties)
if (nodeAbstractProperty.isNodeAbstractProperty())
propertyList.append(nodeAbstractProperty.toNodeAbstractProperty());
return propertyList;
@@ -634,7 +645,8 @@ QList<NodeProperty> ModelNode::nodeProperties() const
{
QList<NodeProperty> propertyList;
- foreach (const AbstractProperty &nodeProperty, properties())
+ const QList<AbstractProperty> abstractProperties = properties();
+ for (const AbstractProperty &nodeProperty : abstractProperties)
if (nodeProperty.isNodeProperty())
propertyList.append(nodeProperty.toNodeProperty());
return propertyList;
@@ -644,7 +656,8 @@ QList<NodeListProperty> ModelNode::nodeListProperties() const
{
QList<NodeListProperty> propertyList;
- foreach (const AbstractProperty &nodeListProperty, properties())
+ const QList<AbstractProperty> abstractProperties = properties();
+ for (const AbstractProperty &nodeListProperty : abstractProperties)
if (nodeListProperty.isNodeListProperty())
propertyList.append(nodeListProperty.toNodeListProperty());
return propertyList;
@@ -661,7 +674,8 @@ QList<BindingProperty> ModelNode::bindingProperties() const
{
QList<BindingProperty> propertyList;
- foreach (const AbstractProperty &bindingProperty, properties())
+ const QList<AbstractProperty> abstractProperties = properties();
+ for (const AbstractProperty &bindingProperty : abstractProperties)
if (bindingProperty.isBindingProperty())
propertyList.append(bindingProperty.toBindingProperty());
return propertyList;
@@ -671,7 +685,8 @@ QList<SignalHandlerProperty> ModelNode::signalProperties() const
{
QList<SignalHandlerProperty> propertyList;
- foreach (const AbstractProperty &property, properties())
+ const QList<AbstractProperty> abstractProperties = properties();
+ for (const AbstractProperty &property : abstractProperties)
if (property.isSignalHandlerProperty())
propertyList.append(property.toSignalHandlerProperty());
return propertyList;
@@ -1428,4 +1443,12 @@ QIcon ModelNode::typeIcon() const
return QIcon(QStringLiteral(":/ItemLibrary/images/item-invalid-icon.png"));
}
+QString ModelNode::behaviorPropertyName() const
+{
+ if (m_internalNode.isNull())
+ return {};
+
+ return m_internalNode->behaviorPropertyName();
+}
+
}
diff --git a/src/plugins/qmldesigner/designercore/model/modelnodepositionrecalculator.cpp b/src/plugins/qmldesigner/designercore/model/modelnodepositionrecalculator.cpp
index e70103807e7..6f02b52cb8e 100644
--- a/src/plugins/qmldesigner/designercore/model/modelnodepositionrecalculator.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelnodepositionrecalculator.cpp
@@ -46,7 +46,7 @@ void ModelNodePositionRecalculator::moved(const TextModifier::MoveInfo &moveInfo
const int prefixLength = moveInfo.prefixToInsert.length();
const int suffixLength = moveInfo.suffixToInsert.length();
- foreach (const ModelNode &node, m_nodesToTrack) {
+ for (const ModelNode &node : qAsConst(m_nodesToTrack)) {
const int nodeLocation = m_positionStore->nodeOffset(node);
if (nodeLocation == ModelNodePositionStorage::INVALID_LOCATION)
@@ -89,7 +89,7 @@ void ModelNodePositionRecalculator::replaced(int offset, int oldLength, int newL
if (growth == 0)
return;
- foreach (const ModelNode &node, m_nodesToTrack) {
+ for (const ModelNode &node : qAsConst(m_nodesToTrack)) {
const int nodeLocation = m_positionStore->nodeOffset(node);
if (nodeLocation == ModelNodePositionStorage::INVALID_LOCATION)
diff --git a/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp b/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp
index 14badab2bf6..6469dd6a04a 100644
--- a/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp
@@ -73,7 +73,7 @@ void ModelToTextMerger::nodeRemoved(const ModelNode &removedNode, const NodeAbst
void ModelToTextMerger::propertiesRemoved(const QList<AbstractProperty>& propertyList)
{
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
// Default property that has actual binding/value should be removed
if (isInHierarchy(property) && (!property.isDefaultProperty()
|| property.isBindingProperty()
@@ -87,7 +87,7 @@ void ModelToTextMerger::propertiesRemoved(const QList<AbstractProperty>& propert
void ModelToTextMerger::propertiesChanged(const QList<AbstractProperty>& propertyList, PropertyChangeFlags propertyChange)
{
const TextEditor::TabSettings tabSettings = m_rewriterView->textModifier()->tabSettings();
- foreach (const AbstractProperty &property, propertyList) {
+ for (const AbstractProperty &property : propertyList) {
ModelNode containedModelNode;
const QString propertyTextValue = QmlTextGenerator(propertyOrder(),
@@ -320,7 +320,7 @@ void ModelToTextMerger::reindent(const QMap<int, int> &dirtyAreas) const
Utils::sort(offsets);
TextModifier *textModifier = m_rewriterView->textModifier();
- foreach (const int offset, offsets) {
+ for (const int offset : qAsConst(offsets)) {
const int length = dirtyAreas[offset];
textModifier->indent(offset, length);
}
@@ -356,6 +356,8 @@ QmlRefactoring::PropertyType ModelToTextMerger::propertyType(const AbstractPrope
return QmlRefactoring::ObjectBinding;
else if (property.isVariantProperty())
return QmlRefactoring::ScriptBinding;
+ else if (property.isSignalDeclarationProperty())
+ return QmlRefactoring::ScriptBinding;
Q_ASSERT(false); //Cannot convert property type
return QmlRefactoring::Invalid;
@@ -415,7 +417,7 @@ void ModelToTextMerger::dumpRewriteActions(const QString &msg)
if (DebugRewriteActions) {
qDebug() << "---->" << qPrintable(msg);
- foreach (RewriteAction *action, m_rewriteActions) {
+ for (RewriteAction *action : qAsConst(m_rewriteActions)) {
qDebug() << "-----" << qPrintable(action->info());
}
diff --git a/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
index 512f37722a9..91cc2f79fed 100644
--- a/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
@@ -76,7 +76,7 @@ Internal::InternalNodeListPropertyPointer &NodeListProperty::internalNodeListPro
static QList<ModelNode> internalNodesToModelNodes(const QList<Internal::InternalNode::Pointer> &inputList, Model* model, AbstractView *view)
{
QList<ModelNode> modelNodeList;
- foreach (const Internal::InternalNode::Pointer &internalNode, inputList) {
+ for (const Internal::InternalNode::Pointer &internalNode : inputList) {
modelNodeList.append(ModelNode(internalNode, model, view));
}
return modelNodeList;
@@ -102,7 +102,8 @@ QList<QmlObjectNode> NodeListProperty::toQmlObjectNodeList() const
QList<QmlObjectNode> qmlObjectNodeList;
- foreach (const ModelNode &modelNode, toModelNodeList())
+ const QList<ModelNode> modelNodeList = toModelNodeList();
+ for (const ModelNode &modelNode : modelNodeList)
qmlObjectNodeList.append(QmlObjectNode(modelNode));
return qmlObjectNodeList;
diff --git a/src/plugins/qmldesigner/designercore/model/propertyparser.cpp b/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
index eab05e0adc4..21fcc0fa566 100644
--- a/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
+++ b/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
@@ -249,14 +249,11 @@ QVariant read(int variantType, const QString &str)
if (str == "false")
return false;
- auto tmp = QVariant(str);
- conversionOk = tmp.isValid();
- value = QVariant(tmp);
-
- if (tmp.canConvert(QMetaType::Double))
- value.convert(QMetaType::Double);
- else if (tmp.canConvert(QMetaType::QColor))
- value.convert(QMetaType::QColor);
+ if (auto f = QVariant(str).toDouble(&conversionOk); conversionOk)
+ return f;
+ else if (auto c = colorFromString(str, &conversionOk); conversionOk)
+ return c;
+
break;
}
case QMetaType::QPoint:
diff --git a/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp b/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
index ba821dd788b..77e73f45e99 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
@@ -190,7 +190,7 @@ bool detectHorizontalCycle(const ModelNode &node, QList<ModelNode> knownNodeList
static const PropertyNameList validAnchorLines({"right", "left", "horizontalCenter"});
static const PropertyNameList anchorNames({"anchors.right", "anchors.left", "anchors.horizontalCenter"});
- foreach (const PropertyName &anchorName, anchorNames) {
+ for (const PropertyName &anchorName : anchorNames) {
if (node.hasBindingProperty(anchorName)) {
AbstractProperty targetProperty = node.bindingProperty(anchorName).resolveToProperty();
if (targetProperty.isValid()) {
@@ -205,7 +205,7 @@ bool detectHorizontalCycle(const ModelNode &node, QList<ModelNode> knownNodeList
}
static const PropertyNameList anchorShortcutNames({"anchors.fill", "anchors.centerIn"});
- foreach (const PropertyName &anchorName, anchorShortcutNames) {
+ for (const PropertyName &anchorName : anchorShortcutNames) {
if (node.hasBindingProperty(anchorName)) {
ModelNode targetNode = node.bindingProperty(anchorName).resolveToModelNode();
@@ -230,7 +230,7 @@ bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
static const PropertyNameList validAnchorLines({"top", "bottom", "verticalCenter", "baseline"});
static const PropertyNameList anchorNames({"anchors.top", "anchors.bottom", "anchors.verticalCenter", "anchors.baseline"});
- foreach (const PropertyName &anchorName, anchorNames) {
+ for (const PropertyName &anchorName : anchorNames) {
if (node.hasBindingProperty(anchorName)) {
AbstractProperty targetProperty = node.bindingProperty(anchorName).resolveToProperty();
if (targetProperty.isValid()) {
@@ -245,7 +245,7 @@ bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
}
static const PropertyNameList anchorShortcutNames({"anchors.fill", "anchors.centerIn"});
- foreach (const PropertyName &anchorName, anchorShortcutNames) {
+ for (const PropertyName &anchorName : anchorShortcutNames) {
if (node.hasBindingProperty(anchorName)) {
ModelNode targetNode = node.bindingProperty(anchorName).resolveToModelNode();
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index 844240f0b92..6580c4005ba 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -201,7 +201,8 @@ QList<QmlItemNode> QmlItemNode::children() const
childrenList.append(modelNode().nodeListProperty("children").toModelNodeList());
if (modelNode().hasNodeListProperty("data")) {
- foreach (const ModelNode &node, modelNode().nodeListProperty("data").toModelNodeList()) {
+ const QList<ModelNode> nodes = modelNode().nodeListProperty("data").toModelNodeList();
+ for (const ModelNode &node : nodes) {
if (QmlItemNode::isValidQmlItemNode(node))
childrenList.append(node);
}
@@ -221,7 +222,8 @@ QList<QmlObjectNode> QmlItemNode::resources() const
resourcesList.append(modelNode().nodeListProperty("resources").toModelNodeList());
if (modelNode().hasNodeListProperty("data")) {
- foreach (const ModelNode &node, modelNode().nodeListProperty("data").toModelNodeList()) {
+ const QList<ModelNode> nodes = modelNode().nodeListProperty("data").toModelNodeList();
+ for (const ModelNode &node : nodes) {
if (!QmlItemNode::isValidQmlItemNode(node))
resourcesList.append(node);
}
@@ -489,7 +491,7 @@ QList<ModelNode> toModelNodeList(const QList<QmlItemNode> &qmlItemNodeList)
{
QList<ModelNode> modelNodeList;
- foreach (const QmlItemNode &qmlItemNode, qmlItemNodeList)
+ for (const QmlItemNode &qmlItemNode : qmlItemNodeList)
modelNodeList.append(qmlItemNode.modelNode());
return modelNodeList;
diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
index 2445042fbb5..5e137b06b87 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
@@ -394,7 +394,9 @@ static void removeAliasExports(const QmlObjectNode &node)
if (hasAliasExport)
rootNode.removeProperty(propertyName);
- foreach (const ModelNode &childNode, node.modelNode().directSubModelNodes()) {
+
+ const QList<ModelNode> nodes = node.modelNode().directSubModelNodes();
+ for (const ModelNode &childNode : nodes) {
removeAliasExports(childNode);
}
@@ -508,7 +510,8 @@ QList<QmlModelState> QmlObjectNode::allAffectingStates() const
QList<QmlModelState> returnList;
- foreach (const QmlModelState &state, allDefinedStates()) {
+ const QList<QmlModelState> states = allDefinedStates();
+ for (const QmlModelState &state : states) {
if (state.affectsModelNode(modelNode()))
returnList.append(state);
}
@@ -525,7 +528,8 @@ QList<QmlModelStateOperation> QmlObjectNode::allAffectingStatesOperations() cons
throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
QList<QmlModelStateOperation> returnList;
- foreach (const QmlModelState &state, allDefinedStates()) {
+ const QList<QmlModelState> states = allDefinedStates();
+ for (const QmlModelState &state : states) {
if (state.affectsModelNode(modelNode()))
returnList.append(state.stateOperations(modelNode()));
}
@@ -540,7 +544,8 @@ static QList<QmlVisualNode> allQmlVisualNodesRecursive(const QmlItemNode &qmlIte
if (qmlItemNode.isValid()) {
qmlVisualNodeList.append(qmlItemNode);
- foreach (const ModelNode &modelNode, qmlItemNode.modelNode().directSubModelNodes()) {
+ const QList<ModelNode> nodes = qmlItemNode.modelNode().directSubModelNodes();
+ for (const ModelNode &modelNode : nodes) {
if (QmlVisualNode::isValidQmlVisualNode(modelNode))
qmlVisualNodeList.append(allQmlVisualNodesRecursive(modelNode));
}
@@ -601,7 +606,7 @@ QList<ModelNode> toModelNodeList(const QList<QmlObjectNode> &qmlObjectNodeList)
{
QList<ModelNode> modelNodeList;
- foreach (const QmlObjectNode &qmlObjectNode, qmlObjectNodeList)
+ for (const QmlObjectNode &qmlObjectNode : qmlObjectNodeList)
modelNodeList.append(qmlObjectNode.modelNode());
return modelNodeList;
@@ -611,7 +616,7 @@ QList<QmlObjectNode> toQmlObjectNodeList(const QList<ModelNode> &modelNodeList)
{
QList<QmlObjectNode> qmlObjectNodeList;
- foreach (const ModelNode &modelNode, modelNodeList) {
+ for (const ModelNode &modelNode : modelNodeList) {
if (QmlObjectNode::isValidQmlObjectNode(modelNode))
qmlObjectNodeList.append(modelNode);
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmlstate.cpp b/src/plugins/qmldesigner/designercore/model/qmlstate.cpp
index 70bb2719383..f08d36d8503 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlstate.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlstate.cpp
@@ -52,7 +52,9 @@ QmlPropertyChanges QmlModelState::propertyChanges(const ModelNode &node)
{
if (!isBaseState()) {
addChangeSetIfNotExists(node);
- foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+
+ const QList<ModelNode> nodes = modelNode().nodeListProperty("changes").toModelNodeList();
+ for (const ModelNode &childNode : nodes) {
//### exception if not valid QmlModelStateOperation
if (QmlPropertyChanges::isValidQmlPropertyChanges(childNode)
&& QmlPropertyChanges(childNode).target().isValid()
@@ -69,7 +71,8 @@ QList<QmlModelStateOperation> QmlModelState::stateOperations(const ModelNode &no
QList<QmlModelStateOperation> returnList;
if (!isBaseState() && modelNode().hasNodeListProperty("changes")) {
- foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ const QList<ModelNode> nodes = modelNode().nodeListProperty("changes").toModelNodeList();
+ for (const ModelNode &childNode : nodes) {
if (QmlModelStateOperation::isValidQmlModelStateOperation(childNode)) {
QmlModelStateOperation stateOperation(childNode);
ModelNode targetNode = stateOperation.target();
@@ -87,7 +90,8 @@ QList<QmlPropertyChanges> QmlModelState::propertyChanges() const
QList<QmlPropertyChanges> returnList;
if (!isBaseState() && modelNode().hasNodeListProperty("changes")) {
- foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ const QList<ModelNode> nodes = modelNode().nodeListProperty("changes").toModelNodeList();
+ for (const ModelNode &childNode : nodes) {
//### exception if not valid QmlModelStateOperation
if (QmlPropertyChanges::isValidQmlPropertyChanges(childNode))
returnList.append(QmlPropertyChanges(childNode));
@@ -101,7 +105,8 @@ QList<QmlPropertyChanges> QmlModelState::propertyChanges() const
bool QmlModelState::hasPropertyChanges(const ModelNode &node) const
{
if (!isBaseState() && modelNode().hasNodeListProperty("changes")) {
- foreach (const QmlPropertyChanges &changeSet, propertyChanges()) {
+ const QList<QmlPropertyChanges> changes = propertyChanges();
+ for (const QmlPropertyChanges &changeSet : changes) {
if (changeSet.target().isValid() && changeSet.target() == node)
return true;
}
@@ -113,7 +118,8 @@ bool QmlModelState::hasPropertyChanges(const ModelNode &node) const
bool QmlModelState::hasStateOperation(const ModelNode &node) const
{
if (!isBaseState()) {
- foreach (const QmlModelStateOperation &stateOperation, stateOperations()) {
+ const QList<QmlModelStateOperation> operations = stateOperations();
+ for (const QmlModelStateOperation &stateOperation : operations) {
if (stateOperation.target() == node)
return true;
}
@@ -127,7 +133,8 @@ QList<QmlModelStateOperation> QmlModelState::stateOperations() const
QList<QmlModelStateOperation> returnList;
if (!isBaseState() && modelNode().hasNodeListProperty("changes")) {
- foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ const QList<ModelNode> nodes = modelNode().nodeListProperty("changes").toModelNodeList();
+ for (const ModelNode &childNode : nodes) {
//### exception if not valid QmlModelStateOperation
if (QmlModelStateOperation::isValidQmlModelStateOperation(childNode))
returnList.append(QmlModelStateOperation(childNode));
@@ -203,7 +210,8 @@ QList<QmlObjectNode> QmlModelState::allAffectedNodes() const
{
QList<QmlObjectNode> returnList;
- foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ const QList<ModelNode> nodes = modelNode().nodeListProperty("changes").toModelNodeList();
+ for (const ModelNode &childNode : nodes) {
if (QmlModelStateOperation::isValidQmlModelStateOperation(childNode) &&
!returnList.contains(QmlModelStateOperation(childNode).target()))
returnList.append(QmlModelStateOperation(childNode).target());
@@ -271,11 +279,14 @@ QmlModelState QmlModelState::duplicate(const QString &name) const
// QmlModelState newState(stateGroup().addState(name));
QmlModelState newState(createQmlState(view(), {{PropertyName("name"), QVariant(name)}}));
- foreach (const ModelNode &childNode, modelNode().nodeListProperty("changes").toModelNodeList()) {
+ const QList<ModelNode> nodes = modelNode().nodeListProperty("changes").toModelNodeList();
+ for (const ModelNode &childNode : nodes) {
ModelNode newModelNode(view()->createModelNode(childNode.type(), childNode.majorVersion(), childNode.minorVersion()));
- foreach (const BindingProperty &bindingProperty, childNode.bindingProperties())
+ const QList<BindingProperty> bindingProperties = childNode.bindingProperties();
+ for (const BindingProperty &bindingProperty : bindingProperties)
newModelNode.bindingProperty(bindingProperty.name()).setExpression(bindingProperty.expression());
- foreach (const VariantProperty &variantProperty, childNode.variantProperties())
+ const QList<VariantProperty> variantProperties = childNode.variantProperties();
+ for (const VariantProperty &variantProperty : variantProperties)
newModelNode.variantProperty(variantProperty.name()).setValue(variantProperty.value());
newState.modelNode().nodeListProperty("changes").reparentHere(newModelNode);
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
index 51cb503d81e..296b965548f 100644
--- a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
@@ -101,6 +101,8 @@ QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDept
return property.toBindingProperty().expression();
} else if (property.isSignalHandlerProperty()) {
return property.toSignalHandlerProperty().source();
+ } else if (property.isSignalDeclarationProperty()) {
+ return property.toSignalDeclarationProperty().signature();
} else if (property.isNodeProperty()) {
return toQml(property.toNodeProperty().modelNode(), indentDepth);
} else if (property.isNodeListProperty()) {
@@ -200,7 +202,7 @@ QString QmlTextGenerator::toQml(const ModelNode &node, int indentDepth) const
QString alias;
if (!url.isEmpty()) {
- foreach (const Import &import, node.model()->imports()) {
+ for (const Import &import : node.model()->imports()) {
if (import.url() == url) {
alias = import.alias();
break;
@@ -218,6 +220,10 @@ QString QmlTextGenerator::toQml(const ModelNode &node, int indentDepth) const
result = alias + '.';
result += type;
+ if (!node.behaviorPropertyName().isEmpty()) {
+ result += " on " + node.behaviorPropertyName();
+ }
+
result += QStringLiteral(" {\n");
const int propertyIndentDepth = indentDepth + m_tabSettings.m_indentSize;
@@ -236,7 +242,7 @@ QString QmlTextGenerator::propertiesToQml(const ModelNode &node, int indentDepth
PropertyNameList nodePropertyNames = node.propertyNames();
bool addToTop = true;
- foreach (const PropertyName &propertyName, m_propertyOrder) {
+ for (const PropertyName &propertyName : qAsConst(m_propertyOrder)) {
if (propertyName == "id") {
// the model handles the id property special, so:
if (!node.id().isEmpty()) {
@@ -262,7 +268,7 @@ QString QmlTextGenerator::propertiesToQml(const ModelNode &node, int indentDepth
}
}
- foreach (const PropertyName &propertyName, nodePropertyNames) {
+ for (const PropertyName &propertyName : qAsConst(nodePropertyNames)) {
bottomPart.prepend(propertyToQml(node.property(propertyName), indentDepth));
}
@@ -284,6 +290,10 @@ QString QmlTextGenerator::propertyToQml(const AbstractProperty &property, int in
+ QString::fromUtf8(property.name())
+ QStringLiteral(": ")
+ toQml(property, indentDepth);
+ }
+ if (property.isSignalDeclarationProperty()) {
+ result = m_tabSettings.indentationString(0, indentDepth, 0) + "signal" + " "
+ + QString::fromUtf8(property.name()) + " " + toQml(property, indentDepth);
} else {
result = m_tabSettings.indentationString(0, indentDepth, 0)
+ QString::fromUtf8(property.name())
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp b/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
index 38e9427892e..6b6f1f8a886 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
@@ -276,7 +276,7 @@ bool RemoveNodeRewriteAction::execute(QmlRefactoring &refactoring, ModelNodePosi
QString RemoveNodeRewriteAction::info() const
{
- return QLatin1String("RemoveNodeRewriteAction");
+ return QLatin1String("RemoveNodeRewriteAction") + QString::number(m_node.internalId());
}
bool RemovePropertyRewriteAction::execute(QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore)
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
index 0662da4e86a..abdba538232 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
@@ -102,7 +102,7 @@ void RewriteActionCompressor::compressImports(QList<RewriteAction *> &actions) c
}
}
- foreach (RewriteAction *action, actionsToRemove) {
+ for (RewriteAction *action : qAsConst(actionsToRemove)) {
actions.removeOne(action);
delete action;
}
@@ -128,7 +128,7 @@ void RewriteActionCompressor::compressRereparentActions(QList<RewriteAction *> &
}
}
- foreach (RewriteAction *action, actionsToRemove) {
+ for (RewriteAction *action : qAsConst(actionsToRemove)) {
actions.removeOne(action);
delete action;
}
@@ -147,7 +147,7 @@ void RewriteActionCompressor::compressReparentIntoSamePropertyActions(QList<Rewr
}
}
- foreach (RewriteAction *action, actionsToRemove) {
+ for (RewriteAction *action : qAsConst(actionsToRemove)) {
actions.removeOne(action);
delete action;
}
@@ -231,7 +231,7 @@ void RewriteActionCompressor::compressAddEditRemoveNodeActions(QList<RewriteActi
}
}
- foreach (RewriteAction *action, actionsToRemove) {
+ for (RewriteAction *action : qAsConst(actionsToRemove)) {
actions.removeOne(action);
delete action;
}
@@ -281,7 +281,7 @@ void RewriteActionCompressor::compressPropertyActions(QList<RewriteAction *> &ac
}
}
- foreach (RewriteAction *action, actionsToRemove){
+ for (RewriteAction *action : qAsConst(actionsToRemove)) {
actions.removeOne(action);
delete action;
}
@@ -330,13 +330,13 @@ void RewriteActionCompressor::compressAddEditActions(
}
}
- foreach (RewriteAction *action, actionsToRemove){
+ for (RewriteAction *action : qAsConst(actionsToRemove)) {
actions.removeOne(action);
delete action;
}
QmlTextGenerator gen(m_propertyOrder, tabSettings);
- foreach (RewriteAction *action, dirtyActions) {
+ for (RewriteAction *action : qAsConst(dirtyActions)) {
RewriteAction *newAction = nullptr;
if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
newAction = new AddPropertyRewriteAction(addAction->property(),
@@ -401,7 +401,7 @@ void RewriteActionCompressor::compressAddReparentActions(QList<RewriteAction *>
}
}
- foreach (RewriteAction *action, actionsToRemove){
+ for (RewriteAction *action : qAsConst(actionsToRemove)) {
actions.removeOne(action);
delete action;
}
diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
index 79ef6a64345..909c6483b1e 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
@@ -88,6 +88,7 @@ RewriterView::RewriterView(DifferenceHandling differenceHandling, QObject *paren
m_textToModelMerger(new Internal::TextToModelMerger(this))
{
m_amendTimer.setSingleShot(true);
+
m_amendTimer.setInterval(800);
connect(&m_amendTimer, &QTimer::timeout, this, &RewriterView::amendQmlText);
@@ -220,7 +221,7 @@ void RewriterView::variantPropertiesChanged(const QList<VariantProperty>& proper
return;
QList<AbstractProperty> usefulPropertyList;
- foreach (const VariantProperty &property, propertyList)
+ for (const VariantProperty &property : propertyList)
usefulPropertyList.append(property);
modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange);
@@ -236,7 +237,7 @@ void RewriterView::bindingPropertiesChanged(const QList<BindingProperty>& proper
return;
QList<AbstractProperty> usefulPropertyList;
- foreach (const BindingProperty &property, propertyList)
+ for (const BindingProperty &property : propertyList)
usefulPropertyList.append(property);
modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange);
@@ -252,7 +253,23 @@ void RewriterView::signalHandlerPropertiesChanged(const QVector<SignalHandlerPro
return;
QList<AbstractProperty> usefulPropertyList;
- foreach (const SignalHandlerProperty &property, propertyList)
+ for (const SignalHandlerProperty &property : propertyList)
+ usefulPropertyList.append(property);
+
+ modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange);
+
+ if (!isModificationGroupActive())
+ applyChanges();
+}
+
+void RewriterView::signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty> &propertyList, PropertyChangeFlags propertyChange)
+{
+ Q_ASSERT(textModifier());
+ if (textToModelMerger()->isActive())
+ return;
+
+ QList<AbstractProperty> usefulPropertyList;
+ for (const SignalDeclarationProperty &property : propertyList)
usefulPropertyList.append(property);
modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange);
@@ -275,10 +292,10 @@ void RewriterView::nodeReparented(const ModelNode &node, const NodeAbstractPrope
void RewriterView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
{
- foreach (const Import &import, addedImports)
+ for (const Import &import : addedImports)
importAdded(import);
- foreach (const Import &import, removedImports)
+ for (const Import &import : removedImports)
importRemoved(import);
}
@@ -290,7 +307,7 @@ void RewriterView::importAdded(const Import &import)
return;
if (import.url() == QLatin1String("Qt")) {
- foreach (const Import &import, model()->imports()) {
+ for (const Import &import : model()->imports()) {
if (import.url() == QLatin1String("QtQuick"))
return; //QtQuick magic we do not have to add an import for Qt
}
@@ -519,6 +536,10 @@ void RewriterView::applyChanges()
void RewriterView::amendQmlText()
{
+
+ if (!model()->rewriterView())
+ return;
+
emitCustomNotification(StartRewriterAmend);
const QString newQmlText = m_textModifier->text();
@@ -785,7 +806,7 @@ QMap<ModelNode, QString> RewriterView::extractText(const QList<ModelNode> &nodes
QmlDesigner::ASTObjectTextExtractor extract(m_textModifier->text());
QMap<ModelNode, QString> result;
- foreach (const ModelNode &node, nodes) {
+ for (const ModelNode &node : nodes) {
const int nodeLocation = m_positionStorage->nodeOffset(node);
if (nodeLocation == ModelNodePositionStorage::INVALID_LOCATION)
@@ -981,7 +1002,7 @@ QString RewriterView::convertTypeToImportAlias(const QString &type) const
QString alias;
if (!url.isEmpty()) {
- foreach (const Import &import, model()->imports()) {
+ for (const Import &import : model()->imports()) {
if (import.url() == url) {
alias = import.alias();
break;
@@ -1011,7 +1032,7 @@ QString RewriterView::pathForImport(const Import &import)
QmlJS::ImportInfo importInfo;
- foreach (const QmlJS::Import &qmljsImport, imports->all()) {
+ for (const QmlJS::Import &qmljsImport : imports->all()) {
if (qmljsImport.info.name() == importStr)
importInfo = qmljsImport.info;
}
diff --git a/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp b/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
index d8d7e2c9359..d2e5e6dbc51 100644
--- a/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
@@ -107,4 +107,57 @@ PropertyName SignalHandlerProperty::prefixRemoved(const PropertyName &propertyNa
return nameAsString.toLatin1();
}
+SignalDeclarationProperty::SignalDeclarationProperty() = default;
+
+SignalDeclarationProperty::SignalDeclarationProperty(const SignalDeclarationProperty &property,
+ AbstractView *view)
+ : AbstractProperty(property.name(), property.internalNode(), property.model(), view)
+{}
+
+SignalDeclarationProperty::SignalDeclarationProperty(
+ const PropertyName &propertyName,
+ const Internal::InternalNodePointer &internalNode,
+ Model *model,
+ AbstractView *view)
+ : AbstractProperty(propertyName, internalNode, model, view)
+{
+}
+
+void SignalDeclarationProperty::setSignature(const QString &signature)
+{
+ Internal::WriteLocker locker(model());
+ if (!isValid())
+ throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (name() == "id") { // the ID for a node is independent of the state, so it has to be set with ModelNode::setId
+ throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, name());
+ }
+
+ if (signature.isEmpty())
+ throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name());
+
+ if (internalNode()->hasProperty(name())) { //check if oldValue != value
+ Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
+ if (internalProperty->isSignalDeclarationProperty()
+ && internalProperty->toSignalDeclarationProperty()->signature() == signature)
+
+ return;
+ }
+
+ if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isSignalDeclarationProperty())
+ privateModel()->removeProperty(internalNode()->property(name()));
+
+ privateModel()->setSignalDeclarationProperty(internalNode(), name(), signature);
+}
+
+QString SignalDeclarationProperty::signature() const
+{
+
+ if (internalNode()->hasProperty(name())
+ && internalNode()->property(name())->isSignalDeclarationProperty())
+ return internalNode()->signalDeclarationProperty(name())->signature();
+
+ return QString();
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 176e0717ff9..6e7884fca29 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -40,6 +40,7 @@
#include "propertyparser.h"
#include "rewriterview.h"
#include "variantproperty.h"
+#include <rewritingexception.h>
#include <enumeration.h>
@@ -434,13 +435,14 @@ class ReadingContext
{
public:
ReadingContext(const Snapshot &snapshot, const Document::Ptr &doc,
- const ViewerContext &vContext)
+ const ViewerContext &vContext, Model *model)
: m_doc(doc)
, m_context(
Link(snapshot, vContext, ModelManagerInterface::instance()->builtins(doc))
(doc, &m_diagnosticLinkMessages))
, m_scopeChain(doc, m_context)
, m_scopeBuilder(&m_scopeChain)
+ , m_model(model)
{
}
@@ -506,6 +508,38 @@ public:
typeName.prepend(name + QLatin1Char('.'));
}
}
+
+ {
+ TypeName fullTypeName;
+ for (AST::UiQualifiedId *iter = astTypeNode; iter; iter = iter->next)
+ if (!iter->name.isEmpty())
+ fullTypeName += iter->name.toUtf8() + '.';
+
+ if (fullTypeName.endsWith('.'))
+ fullTypeName.chop(1);
+
+ NodeMetaInfo metaInfo = m_model->metaInfo(fullTypeName);
+
+ bool ok = metaInfo.typeName() == typeName.toUtf8()
+ && metaInfo.majorVersion() == majorVersion
+ && metaInfo.minorVersion() == minorVersion;
+
+
+ if (!ok) {
+ qDebug() << Q_FUNC_INFO;
+ qDebug() << astTypeNode->name.toString() << typeName;
+ qDebug() << metaInfo.isValid() << metaInfo.typeName();
+ qDebug() << metaInfo.directSuperClass().typeName();
+
+ if (!typeName.startsWith("...") && m_model == m_model->metaInfoProxyModel()
+ && metaInfo.isValid())
+ throw RewritingException(__LINE__, __FUNCTION__, __FILE__, "test", "test");
+ }
+
+ typeName = QString::fromUtf8(metaInfo.typeName());
+ majorVersion = metaInfo.majorVersion();
+ minorVersion = metaInfo.minorVersion();
+ }
}
/// When something is changed here, also change Check::checkScopeObjectMember in
@@ -758,6 +792,7 @@ private:
ContextPtr m_context;
ScopeChain m_scopeChain;
ScopeBuilder m_scopeBuilder;
+ Model *m_model;
};
} // namespace Internal
@@ -824,7 +859,7 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc,
}
}
- foreach (const Import &import, existingImports)
+ for (const Import &import : qAsConst(existingImports))
differenceHandler.importAbsentInQMl(import);
}
@@ -878,7 +913,7 @@ static bool isBlacklistImport(const ImportKey &importKey, Model *model)
static QHash<QString, ImportKey> filterPossibleImportKeys(const QSet<ImportKey> &possibleImportKeys, Model *model)
{
QHash<QString, ImportKey> filteredPossibleImportKeys;
- foreach (const ImportKey &importKey, possibleImportKeys) {
+ for (const ImportKey &importKey : possibleImportKeys) {
if (isLatestImportVersion(importKey, filteredPossibleImportKeys) && !isBlacklistImport(importKey, model))
filteredPossibleImportKeys.insert(importKey.path(), importKey);
}
@@ -888,7 +923,7 @@ static QHash<QString, ImportKey> filterPossibleImportKeys(const QSet<ImportKey>
static void removeUsedImports(QHash<QString, ImportKey> &filteredPossibleImportKeys, const QList<QmlJS::Import> &usedImports)
{
- foreach (const QmlJS::Import &import, usedImports)
+ for (const QmlJS::Import &import : usedImports)
filteredPossibleImportKeys.remove(import.info.path());
}
@@ -1064,7 +1099,8 @@ Document::MutablePtr TextToModelMerger::createParsedDocument(const QUrl &url, co
if (!doc->isParsedCorrectly()) {
if (errors) {
- foreach (const QmlJS::DiagnosticMessage &message, doc->diagnosticMessages())
+ const QList<QmlJS::DiagnosticMessage> messages = doc->diagnosticMessages();
+ for (const QmlJS::DiagnosticMessage &message : messages)
errors->append(DocumentMessage(message, QUrl::fromLocalFile(doc->fileName())));
}
return Document::MutablePtr();
@@ -1121,7 +1157,7 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
m_vContext = ModelManagerInterface::instance()->projectVContext(Dialect::Qml, m_document);
- ReadingContext ctxt(snapshot, m_document, m_vContext);
+ ReadingContext ctxt(snapshot, m_document, m_vContext, m_rewriterView->model());
m_scopeChain = QSharedPointer<const ScopeChain>(
new ScopeChain(ctxt.scopeChain()));
@@ -1182,6 +1218,15 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
ReadingContext *context,
DifferenceHandler &differenceHandler)
{
+ auto binding = AST::cast<AST::UiObjectBinding *>(astNode);
+
+ const bool hasOnToken = binding && binding->hasOnToken;
+
+ QString onTokenProperty;
+
+ if (hasOnToken)
+ onTokenProperty = toString(binding->qualifiedId);
+
AST::UiQualifiedId *astObjectType = qualifiedTypeNameId(astNode);
AST::UiObjectInitializer *astInitializer = initializerOfObject(astNode);
@@ -1218,10 +1263,10 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
bool isImplicitComponent = modelNode.hasParentProperty() && propertyIsComponentType(modelNode.parentProperty(), typeName, modelNode.model());
-
- if (modelNode.type() != typeName //If there is no valid parentProperty //the node has just been created. The type is correct then.
- || modelNode.majorVersion() != majorVersion
- || modelNode.minorVersion() != minorVersion) {
+ if (modelNode.type()
+ != typeName //If there is no valid parentProperty //the node has just been created. The type is correct then.
+ || modelNode.majorVersion() != majorVersion || modelNode.minorVersion() != minorVersion
+ || modelNode.behaviorPropertyName() != onTokenProperty) {
const bool isRootNode = m_rewriterView->rootModelNode() == modelNode;
differenceHandler.typeDiffers(isRootNode, modelNode, typeName,
majorVersion, minorVersion,
@@ -1275,12 +1320,12 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
} else if (auto def = AST::cast<AST::UiObjectDefinition *>(member)) {
const QString &name = def->qualifiedTypeNameId->name.toString();
if (name.isEmpty() || !name.at(0).isUpper()) {
- QStringList props = syncGroupedProperties(modelNode,
- name,
- def->initializer->members,
- context,
- differenceHandler);
- foreach (const QString &prop, props)
+ const QStringList props = syncGroupedProperties(modelNode,
+ name,
+ def->initializer->members,
+ context,
+ differenceHandler);
+ for (const QString &prop : props)
modelPropertyNames.remove(prop.toUtf8());
} else {
defaultPropertyItems.append(member);
@@ -1288,7 +1333,8 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
} else if (auto binding = AST::cast<AST::UiObjectBinding *>(member)) {
const QString astPropertyName = toString(binding->qualifiedId);
if (binding->hasOnToken) {
- // skip value sources
+ // Store Behaviours in the default property
+ defaultPropertyItems.append(member);
} else {
const Value *propertyType = nullptr;
const ObjectValue *containingObject = nullptr;
@@ -1313,8 +1359,21 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
} else if (auto script = AST::cast<AST::UiScriptBinding *>(member)) {
modelPropertyNames.remove(syncScriptBinding(modelNode, QString(), script, context, differenceHandler));
} else if (auto property = AST::cast<AST::UiPublicMember *>(member)) {
- if (property->type == AST::UiPublicMember::Signal)
- continue; // QML designer doesn't support this yet.
+ if (property->type == AST::UiPublicMember::Signal) {
+ const QStringView astName = property->name;
+ AbstractProperty modelProperty = modelNode.property(astName.toUtf8());
+ QString signature = "()";
+ if (property->parameters) {
+ signature = "("
+ + textAt(context->doc(),
+ property->parameters->firstSourceLocation(),
+ property->parameters->lastSourceLocation())
+ + ")";
+ }
+
+ syncSignalDeclarationProperty(modelProperty, signature, differenceHandler);
+ continue; // Done
+ }
const QStringView astName = property->name;
QString astValue;
@@ -1370,7 +1429,7 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
}
}
- foreach (const PropertyName &modelPropertyName, modelPropertyNames) {
+ for (const PropertyName &modelPropertyName : qAsConst(modelPropertyNames)) {
AbstractProperty modelProperty = modelNode.property(modelPropertyName);
// property deleted.
@@ -1649,6 +1708,19 @@ void TextToModelMerger::syncVariantProperty(AbstractProperty &modelProperty,
}
}
+void TextToModelMerger::syncSignalDeclarationProperty(AbstractProperty &modelProperty,
+ const QString &signature,
+ DifferenceHandler &differenceHandler)
+{
+ if (modelProperty.isSignalDeclarationProperty()) {
+ SignalDeclarationProperty signalHandlerProperty = modelProperty.toSignalDeclarationProperty();
+ if (signalHandlerProperty.signature() != signature)
+ differenceHandler.signalDeclarationSignatureDiffer(signalHandlerProperty, signature);
+ } else {
+ differenceHandler.shouldBeSignalDeclarationProperty(modelProperty, signature);
+ }
+}
+
void TextToModelMerger::syncNodeListProperty(NodeListProperty &modelListProperty,
const QList<AST::UiObjectMember *> arrayMembers,
ReadingContext *context,
@@ -1684,6 +1756,13 @@ ModelNode TextToModelMerger::createModelNode(const TypeName &typeName,
{
QString nodeSource;
+ auto binding = AST::cast<AST::UiObjectBinding *>(astNode);
+
+ const bool hasOnToken = binding && binding->hasOnToken;
+
+ QString onTokenProperty;
+ if (hasOnToken)
+ onTokenProperty = toString(binding->qualifiedId);
AST::UiQualifiedId *astObjectType = qualifiedTypeNameId(astNode);
@@ -1715,7 +1794,8 @@ ModelNode TextToModelMerger::createModelNode(const TypeName &typeName,
PropertyListType(),
PropertyListType(),
nodeSource,
- nodeSourceType);
+ nodeSourceType,
+ onTokenProperty);
syncNode(newNode, astNode, context, differenceHandler);
return newNode;
@@ -1782,6 +1862,13 @@ void ModelValidator::signalHandlerSourceDiffer(SignalHandlerProperty &modelPrope
QTC_ASSERT(compareJavaScriptExpression(modelProperty.source(), javascript), return);
}
+void ModelValidator::signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty, const QString &signature)
+{
+ Q_UNUSED(modelProperty)
+ Q_UNUSED(signature)
+ QTC_ASSERT(compareJavaScriptExpression(modelProperty.signature(), signature), return);
+}
+
void ModelValidator::shouldBeSignalHandlerProperty(AbstractProperty &modelProperty, const QString & /*javascript*/)
{
Q_UNUSED(modelProperty)
@@ -1789,6 +1876,13 @@ void ModelValidator::shouldBeSignalHandlerProperty(AbstractProperty &modelProper
Q_ASSERT(0);
}
+void ModelValidator::shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty, const QString & /*javascript*/)
+{
+ Q_UNUSED(modelProperty)
+ Q_ASSERT(modelProperty.isSignalDeclarationProperty());
+ Q_ASSERT(0);
+}
+
void ModelValidator::shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<AST::UiObjectMember *> /*arrayMembers*/,
ReadingContext * /*context*/)
@@ -1937,6 +2031,11 @@ void ModelAmender::signalHandlerSourceDiffer(SignalHandlerProperty &modelPropert
modelProperty.setSource(javascript);
}
+void ModelAmender::signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty, const QString &signature)
+{
+ modelProperty.setSignature(signature);
+}
+
void ModelAmender::shouldBeSignalHandlerProperty(AbstractProperty &modelProperty, const QString &javascript)
{
ModelNode theNode = modelProperty.parentModelNode();
@@ -1944,6 +2043,13 @@ void ModelAmender::shouldBeSignalHandlerProperty(AbstractProperty &modelProperty
newModelProperty.setSource(javascript);
}
+void ModelAmender::shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty, const QString &signature)
+{
+ ModelNode theNode = modelProperty.parentModelNode();
+ SignalDeclarationProperty newModelProperty = theNode.signalDeclarationProperty(modelProperty.name());
+ newModelProperty.setSignature(signature);
+}
+
void ModelAmender::shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<AST::UiObjectMember *> arrayMembers,
ReadingContext *context)
@@ -2150,7 +2256,8 @@ void TextToModelMerger::clearImplicitComponent(const ModelNode &node)
void TextToModelMerger::collectLinkErrors(QList<DocumentMessage> *errors, const ReadingContext &ctxt)
{
- foreach (const QmlJS::DiagnosticMessage &diagnosticMessage, ctxt.diagnosticLinkMessages()) {
+ const QList<QmlJS::DiagnosticMessage> diagnosticMessages = ctxt.diagnosticLinkMessages();
+ for (const QmlJS::DiagnosticMessage &diagnosticMessage : diagnosticMessages) {
if (diagnosticMessage.kind == QmlJS::Severity::ReadingTypeInfoWarning)
m_rewriterView->setIncompleteTypeInformation(true);
@@ -2166,7 +2273,7 @@ void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
}
bool hasQtQuick = false;
- foreach (const QmlDesigner::Import &import, m_rewriterView->model()->imports()) {
+ for (const QmlDesigner::Import &import : m_rewriterView->model()->imports()) {
if (import.isLibraryImport() && import.url() == QStringLiteral("QtQuick")) {
if (supportedQtQuickVersion(import.version())) {
@@ -2229,7 +2336,8 @@ void TextToModelMerger::collectSemanticErrorsAndWarnings(QList<DocumentMessage>
check.disableMessage(StaticAnalysis::ErrCouldNotResolvePrototype);
check.disableMessage(StaticAnalysis::ErrCouldNotResolvePrototypeOf);
- foreach (StaticAnalysis::Type type, StaticAnalysis::Message::allMessageTypes()) {
+ const QList<StaticAnalysis::Type> types = StaticAnalysis::Message::allMessageTypes();
+ for (StaticAnalysis::Type type : types) {
StaticAnalysis::PrototypeMessageData prototypeMessageData = StaticAnalysis::Message::prototypeForMessageType(type);
if (prototypeMessageData.severity == Severity::MaybeWarning
|| prototypeMessageData.severity == Severity::Warning) {
@@ -2240,7 +2348,8 @@ void TextToModelMerger::collectSemanticErrorsAndWarnings(QList<DocumentMessage>
check.enableQmlDesignerChecks();
QUrl fileNameUrl = QUrl::fromLocalFile(m_document->fileName());
- foreach (const StaticAnalysis::Message &message, check()) {
+ const QList<StaticAnalysis::Message> messages = check();
+ for (const StaticAnalysis::Message &message : messages) {
if (message.severity == Severity::Error) {
if (message.type == StaticAnalysis::ErrUnknownComponent)
warnings->append(DocumentMessage(message.toDiagnosticMessage(), fileNameUrl));
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
index ed48d4ebc8f..82fd8a16614 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
@@ -107,6 +107,9 @@ public:
const QList<QmlJS::AST::UiObjectMember *> &arrayMembers,
ReadingContext *context,
DifferenceHandler &differenceHandler);
+ void syncSignalDeclarationProperty(AbstractProperty &modelProperty,
+ const QString &signature,
+ DifferenceHandler &differenceHandler);
void syncVariantProperty(AbstractProperty &modelProperty,
const QVariant &astValue,
const TypeName &astType,
@@ -187,11 +190,15 @@ public:
const TypeName &astType) = 0;
virtual void signalHandlerSourceDiffer(SignalHandlerProperty &modelProperty,
const QString &javascript) = 0;
+ virtual void signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty,
+ const QString &signature) = 0;
virtual void shouldBeBindingProperty(AbstractProperty &modelProperty,
const QString &javascript,
const TypeName &astType) = 0;
virtual void shouldBeSignalHandlerProperty(AbstractProperty &modelProperty,
const QString &javascript) = 0;
+ virtual void shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty,
+ const QString &signature) = 0;
virtual void shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<QmlJS::AST::UiObjectMember *> arrayMembers,
ReadingContext *context) = 0;
@@ -241,6 +248,10 @@ public:
const TypeName &astType) override;
void signalHandlerSourceDiffer(SignalHandlerProperty &modelProperty,
const QString &javascript) override;
+ void signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty,
+ const QString &signature) override;
+ void shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty,
+ const QString &signature) override;
void shouldBeSignalHandlerProperty(AbstractProperty &modelProperty,
const QString &javascript) override;
void shouldBeNodeListProperty(AbstractProperty &modelProperty,
@@ -290,6 +301,10 @@ public:
const TypeName &astType) override;
void signalHandlerSourceDiffer(SignalHandlerProperty &modelProperty,
const QString &javascript) override;
+ void signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty,
+ const QString &signature) override;
+ void shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty,
+ const QString &signature) override;
void shouldBeSignalHandlerProperty(AbstractProperty &modelProperty,
const QString &javascript) override;
void shouldBeNodeListProperty(AbstractProperty &modelProperty,
diff --git a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
index 2896c1571db..d1b53b05ae2 100644
--- a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
@@ -348,7 +348,8 @@ QList<WidgetInfo> ViewManager::widgetInfos() const
QWidget *ViewManager::widget(const QString &uniqueId) const
{
- foreach (const WidgetInfo &widgetInfo, widgetInfos()) {
+ const QList<WidgetInfo> widgetInfoList = widgetInfos();
+ for (const WidgetInfo &widgetInfo : widgetInfoList) {
if (widgetInfo.uniqueId == uniqueId)
return widgetInfo.widget;
}
diff --git a/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp b/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp
index 9b319a814d1..401efad5993 100644
--- a/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp
+++ b/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp
@@ -162,7 +162,7 @@ void WidgetPluginPath::ensureLoaded()
const QStringList libraryFiles = libraryFilePaths(m_path);
if (debug)
qDebug() << "Checking " << libraryFiles.size() << " plugins " << m_path.absolutePath();
- foreach (const QString &libFile, libraryFiles)
+ for (const QString &libFile : libraryFiles)
m_plugins.push_back(WidgetPluginData(libFile));
m_loaded = true;
}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp
index c8281b328d6..7c39d24fd1a 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp
@@ -25,7 +25,7 @@
#include "projectstoragesqlitefunctionregistry.h"
-#include <sqlite3.h>
+#include "sqlite.h"
namespace QmlDesigner {
diff --git a/src/plugins/qmldesigner/designmodecontext.cpp b/src/plugins/qmldesigner/designmodecontext.cpp
index a0cb0cf4072..442b8b90536 100644
--- a/src/plugins/qmldesigner/designmodecontext.cpp
+++ b/src/plugins/qmldesigner/designmodecontext.cpp
@@ -28,6 +28,7 @@
#include "designmodewidget.h"
#include "formeditorwidget.h"
#include "edit3dwidget.h"
+#include "materialbrowserwidget.h"
#include "navigatorwidget.h"
#include "texteditorwidget.h"
@@ -70,6 +71,18 @@ void Editor3DContext::contextHelp(const HelpCallback &callback) const
qobject_cast<Edit3DWidget *>(m_widget)->contextHelp(callback);
}
+MaterialBrowserContext::MaterialBrowserContext(QWidget *widget)
+ : IContext(widget)
+{
+ setWidget(widget);
+ setContext(Core::Context(Constants::C_QMLMATERIALBROWSER, Constants::C_QT_QUICK_TOOLS_MENU));
+}
+
+void MaterialBrowserContext::contextHelp(const HelpCallback &callback) const
+{
+ qobject_cast<MaterialBrowserWidget *>(m_widget)->contextHelp(callback);
+}
+
NavigatorContext::NavigatorContext(QWidget *widget)
: IContext(widget)
{
diff --git a/src/plugins/qmldesigner/designmodecontext.h b/src/plugins/qmldesigner/designmodecontext.h
index b30430b5eeb..fdf5beeecef 100644
--- a/src/plugins/qmldesigner/designmodecontext.h
+++ b/src/plugins/qmldesigner/designmodecontext.h
@@ -60,6 +60,15 @@ public:
void contextHelp(const Core::IContext::HelpCallback &callback) const override;
};
+class MaterialBrowserContext : public Core::IContext
+{
+ Q_OBJECT
+
+public:
+ MaterialBrowserContext(QWidget *widget);
+ void contextHelp(const Core::IContext::HelpCallback &callback) const override;
+};
+
class NavigatorContext : public Core::IContext
{
Q_OBJECT
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index 51dbd58c990..c5c20a7f83f 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -110,37 +110,6 @@ QList<QToolButton *> ItemLibrarySideBarItem::createToolBarWidgets()
return qobject_cast<ItemLibraryWidget*>(widget())->createToolBarWidgets();
}
-class DesignerSideBarItem : public Core::SideBarItem
-{
-public:
- explicit DesignerSideBarItem(QWidget *widget, WidgetInfo::ToolBarWidgetFactoryInterface *createToolBarWidgets, const QString &id);
- ~DesignerSideBarItem() override;
-
- QList<QToolButton *> createToolBarWidgets() override;
-
-private:
- WidgetInfo::ToolBarWidgetFactoryInterface *m_toolBarWidgetFactory;
-
-};
-
-DesignerSideBarItem::DesignerSideBarItem(QWidget *widget, WidgetInfo::ToolBarWidgetFactoryInterface *toolBarWidgetFactory, const QString &id)
- : Core::SideBarItem(widget, id) , m_toolBarWidgetFactory(toolBarWidgetFactory)
-{
-}
-
-DesignerSideBarItem::~DesignerSideBarItem()
-{
- delete m_toolBarWidgetFactory;
-}
-
-QList<QToolButton *> DesignerSideBarItem::createToolBarWidgets()
-{
- if (m_toolBarWidgetFactory)
- return m_toolBarWidgetFactory->createToolBarWidgets();
-
- return QList<QToolButton *>();
-}
-
// ---------- DesignModeWidget
DesignModeWidget::DesignModeWidget()
: m_toolBar(new Core::EditorToolBar(this))
@@ -286,6 +255,8 @@ void DesignModeWidget::setup()
// First get all navigation views
QList<Core::INavigationWidgetFactory *> factories = Core::INavigationWidgetFactory::allNavigationFactories();
+ QList<Core::Command*> viewCommands;
+
for (Core::INavigationWidgetFactory *factory : factories) {
Core::NavigationView navigationView;
navigationView.widget = nullptr;
@@ -335,7 +306,7 @@ void DesignModeWidget::setup()
actionToggle.withSuffix(uniqueId + "Widget"),
designContext);
command->setAttribute(Core::Command::CA_Hide);
- mviews->addAction(command);
+ viewCommands.append(command);
}
}
@@ -358,7 +329,7 @@ void DesignModeWidget::setup()
actionToggle.withSuffix(widgetInfo.uniqueId + "Widget"),
designContext);
command->setAttribute(Core::Command::CA_Hide);
- mviews->addAction(command);
+ viewCommands.append(command);
}
// Finally the output pane
@@ -367,7 +338,7 @@ void DesignModeWidget::setup()
auto outputPanePlaceholder = new Core::OutputPanePlaceHolder(Core::Constants::MODE_DESIGN);
m_outputPaneDockWidget = new ADS::DockWidget(uniqueId);
m_outputPaneDockWidget->setWidget(outputPanePlaceholder);
- m_outputPaneDockWidget->setWindowTitle(tr("Output Pane"));
+ m_outputPaneDockWidget->setWindowTitle(tr("Output"));
m_dockManager->addDockWidget(ADS::NoDockWidgetArea, m_outputPaneDockWidget);
// Set unique id as object name
@@ -378,12 +349,19 @@ void DesignModeWidget::setup()
actionToggle.withSuffix("OutputPaneWidget"),
designContext);
command->setAttribute(Core::Command::CA_Hide);
- mviews->addAction(command);
+ viewCommands.append(command);
connect(outputPanePlaceholder, &Core::OutputPanePlaceHolder::visibilityChangeRequested,
m_outputPaneDockWidget, &ADS::DockWidget::toggleView);
}
+ std::sort(viewCommands.begin(), viewCommands.end(), [](Core::Command *first, Core::Command *second){
+ return first->description() < second->description();
+ });
+
+ for (Core::Command *command : viewCommands)
+ mviews->addAction(command);
+
// Create toolbars
auto toolBar = new QToolBar();
@@ -412,19 +390,26 @@ void DesignModeWidget::setup()
m_dockManager->initialize();
+ // Hide all floating widgets if the initial mode isn't design mode
+ if (Core::ModeManager::instance()->currentModeId() != Core::Constants::MODE_DESIGN) {
+ for (auto &floatingWidget : m_dockManager->floatingWidgets())
+ floatingWidget->hide();
+ }
+
connect(Core::ModeManager::instance(),
&Core::ModeManager::currentModeChanged,
this,
- [this](Utils::Id mode, Utils::Id oldMode) {
+ [this](Utils::Id mode, Utils::Id previousMode) {
if (mode == Core::Constants::MODE_DESIGN) {
m_dockManager->reloadActiveWorkspace();
m_dockManager->setModeChangeState(false);
}
- if (oldMode == Core::Constants::MODE_DESIGN && mode != Core::Constants::MODE_DESIGN) {
+ if (previousMode == Core::Constants::MODE_DESIGN
+ && mode != Core::Constants::MODE_DESIGN) {
m_dockManager->save();
m_dockManager->setModeChangeState(true);
- for (auto floatingWidget : m_dockManager->floatingWidgets())
+ for (auto &floatingWidget : m_dockManager->floatingWidgets())
floatingWidget->hide();
}
});
diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp
index 453dd96232a..65235aca914 100644
--- a/src/plugins/qmldesigner/documentmanager.cpp
+++ b/src/plugins/qmldesigner/documentmanager.cpp
@@ -67,7 +67,8 @@ static inline QHash<PropertyName, QVariant> getProperties(const ModelNode &node)
{
QHash<PropertyName, QVariant> propertyHash;
if (QmlObjectNode::isValidQmlObjectNode(node)) {
- foreach (const AbstractProperty &abstractProperty, node.properties()) {
+ const QList<AbstractProperty> abstractProperties = node.properties();
+ for (const AbstractProperty &abstractProperty : abstractProperties) {
if (abstractProperty.isVariantProperty()
|| (abstractProperty.isBindingProperty()
&& !abstractProperty.name().contains("anchors.")))
@@ -91,9 +92,10 @@ static inline QHash<PropertyName, QVariant> getProperties(const ModelNode &node)
static inline void applyProperties(ModelNode &node, const QHash<PropertyName, QVariant> &propertyHash)
{
- QHash<PropertyName, QVariant> auxiliaryData = node.auxiliaryData();
+ const QHash<PropertyName, QVariant> auxiliaryData = node.auxiliaryData();
- foreach (const PropertyName &propertyName, auxiliaryData.keys()) {
+ const QList<PropertyName> propertyNames = auxiliaryData.keys();
+ for (const PropertyName &propertyName : propertyNames) {
if (node.hasAuxiliaryData(propertyName))
node.setAuxiliaryData(propertyName, QVariant());
}
@@ -281,7 +283,7 @@ bool DocumentManager::hasCurrentDesignDocument() const
void DocumentManager::removeEditors(const QList<Core::IEditor *> &editors)
{
- foreach (Core::IEditor *editor, editors)
+ for (Core::IEditor *editor : editors)
delete m_designDocumentHash.take(editor).data();
}
diff --git a/src/plugins/qmldesigner/dynamiclicensecheck.h b/src/plugins/qmldesigner/dynamiclicensecheck.h
index 8ddcf55a15e..197f5da4152 100644
--- a/src/plugins/qmldesigner/dynamiclicensecheck.h
+++ b/src/plugins/qmldesigner/dynamiclicensecheck.h
@@ -44,7 +44,7 @@ enum FoundLicense {
};
namespace Internal {
-ExtensionSystem::IPlugin *licenseCheckerPlugin()
+inline ExtensionSystem::IPlugin *licenseCheckerPlugin()
{
const ExtensionSystem::PluginSpec *pluginSpec = Utils::findOrDefault(
ExtensionSystem::PluginManager::plugins(),
@@ -56,8 +56,7 @@ ExtensionSystem::IPlugin *licenseCheckerPlugin()
}
} // namespace Internal
-
-FoundLicense checkLicense()
+inline FoundLicense checkLicense()
{
static FoundLicense license = noLicense;
@@ -89,7 +88,7 @@ FoundLicense checkLicense()
return community;
}
-QString licensee()
+inline QString licensee()
{
if (auto plugin = Internal::licenseCheckerPlugin()) {
QString retVal;
diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp
deleted file mode 100644
index a585f2d2d40..00000000000
--- a/src/plugins/qmldesigner/generatecmakelists.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "generatecmakelists.h"
-#include "generatecmakelistsconstants.h"
-#include "cmakegeneratordialog.h"
-
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
-
-#include <projectexplorer/buildsystem.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/runcontrol.h>
-#include <projectexplorer/session.h>
-#include <projectexplorer/target.h>
-
-#include <qmlprojectmanager/qmlproject.h>
-#include <qmlprojectmanager/qmlprojectmanagerconstants.h>
-#include <qmlprojectmanager/qmlmainfileaspect.h>
-
-#include <utils/fileutils.h>
-
-#include <QAction>
-#include <QMessageBox>
-#include <QtConcurrent>
-#include <QRegularExpression>
-#include <QStringList>
-#include <QTextStream>
-
-using namespace Utils;
-using namespace QmlDesigner::GenerateCmake::Constants;
-
-namespace QmlDesigner {
-
-namespace GenerateCmake {
-
-bool operator==(const GeneratableFile &left, const GeneratableFile &right)
-{
- return (left.filePath == right.filePath && left.content == right.content);
-}
-
-enum ProjectDirectoryError {
- NoError = 0,
- MissingContentDir = 1<<1,
- MissingImportDir = 1<<2,
- MissingAssetDir = 1<<3,
- MissingAssetImportDir = 1<<4,
- MissingCppDir = 1<<5,
- MissingMainCMake = 1<<6,
- MissingMainQml = 1<<7,
- MissingAppMainQml = 1<<8,
- MissingQmlModules = 1<<9,
- MissingMainCpp = 1<<10,
- MissingMainCppHeader = 1<<11,
- MissingEnvHeader = 1<<12
-};
-
-const QString MENU_ITEM_GENERATE = QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "Generate CMake Build Files");
-
-void generateMenuEntry()
-{
- Core::ActionContainer *menu =
- Core::ActionManager::actionContainer(Core::Constants::M_FILE);
- auto action = new QAction(MENU_ITEM_GENERATE);
- QObject::connect(action, &QAction::triggered, GenerateCmake::onGenerateCmakeLists);
- Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.CreateCMakeLists");
- menu->addAction(cmd, Core::Constants::G_FILE_EXPORT);
-
- action->setEnabled(ProjectExplorer::SessionManager::startupProject() != nullptr);
- QObject::connect(ProjectExplorer::SessionManager::instance(),
- &ProjectExplorer::SessionManager::startupProjectChanged, [action]() {
- action->setEnabled(ProjectExplorer::SessionManager::startupProject() != nullptr);
- });
-}
-
-void onGenerateCmakeLists()
-{
- FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory();
-
- int projectDirErrors = isProjectCorrectlyFormed(rootDir);
- if (projectDirErrors != NoError) {
- showProjectDirErrorDialog(projectDirErrors);
- if (isErrorFatal(projectDirErrors))
- return;
- }
-
- CmakeFileGenerator cmakeGen;
- cmakeGen.prepare(rootDir);
-
- FilePaths allFiles;
- for (const GeneratableFile &file: cmakeGen.fileQueue().queuedFiles())
- allFiles.append(file.filePath);
-
- CmakeGeneratorDialog dialog(rootDir, allFiles);
- if (dialog.exec()) {
- FilePaths confirmedFiles = dialog.getFilePaths();
- cmakeGen.filterFileQueue(confirmedFiles);
- cmakeGen.execute();
- }
-}
-
-bool isErrorFatal(int error)
-{
- if (error & MissingContentDir ||
- error & MissingImportDir ||
- error & MissingCppDir ||
- error & MissingAppMainQml)
- return true;
-
- return false;
-}
-
-int isProjectCorrectlyFormed(const FilePath &rootDir)
-{
- int errors = NoError;
-
- if (!rootDir.pathAppended(DIRNAME_CONTENT).exists())
- errors |= MissingContentDir;
- if (!rootDir.pathAppended(DIRNAME_CONTENT).pathAppended(FILENAME_APPMAINQML).exists())
- errors |= MissingAppMainQml;
-
- if (!rootDir.pathAppended(DIRNAME_IMPORT).exists())
- errors |= MissingImportDir;
- if (!rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists())
- errors |= MissingAssetImportDir;
-
- if (!rootDir.pathAppended(DIRNAME_CPP).exists())
- errors |= MissingCppDir;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP).exists())
- errors |= MissingMainCpp;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP_HEADER).exists())
- errors |= MissingMainCppHeader;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_ENV_HEADER).exists())
- errors |= MissingEnvHeader;
-
- if (!rootDir.pathAppended(FILENAME_CMAKELISTS).exists())
- errors |= MissingMainCMake;
- if (!rootDir.pathAppended(FILENAME_MODULES).exists())
- errors |= MissingQmlModules;
- if (!rootDir.pathAppended(FILENAME_MAINQML).exists())
- errors |= MissingMainQml;
-
- return errors;
-}
-
-const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1");
-//const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
-// "The project is not properly structured for automatically generating CMake files.\n\nThe following files or directories are missing and may be created:\n\n%1");
-const QString WARNING_TITLE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
- "Cannot Generate CMake Files");
-//const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
-// "Problems with Generating CMake Files");
-
-void showProjectDirErrorDialog(int error)
-{
- bool isFatal = isErrorFatal(error);
-
- if (isFatal) {
- QString fatalList;
-
- if (error & MissingContentDir)
- fatalList.append(QString(DIRNAME_CONTENT) + "\n");
- if (error & MissingAppMainQml)
- fatalList.append(QString(DIRNAME_CONTENT)
- + QDir::separator()
- + QString(FILENAME_APPMAINQML)
- + "\n");
- if (error & MissingCppDir)
- fatalList.append(QString(DIRNAME_CPP) + "\n");
- if (error & MissingImportDir)
- fatalList.append(QString(DIRNAME_IMPORT) + "\n");
-
- QMessageBox::critical(nullptr,
- WARNING_TITLE_FATAL,
- WARNING_MISSING_STRUCTURE_FATAL.arg(fatalList));
- }
-}
-
-bool FileQueue::queueFile(const FilePath &filePath, const QString &fileContent)
-{
- GeneratableFile file;
- file.filePath = filePath;
- file.content = fileContent;
- file.fileExists = filePath.exists();
- m_queuedFiles.append(file);
-
- return true;
-}
-
-const QVector<GeneratableFile> FileQueue::queuedFiles() const
-{
- return m_queuedFiles;
-}
-
-bool FileQueue::writeQueuedFiles()
-{
- for (GeneratableFile &file: m_queuedFiles)
- if (!writeFile(file))
- return false;
-
- return true;
-}
-
-bool FileQueue::writeFile(const GeneratableFile &file)
-{
- QFile fileHandle(file.filePath.toString());
- fileHandle.open(QIODevice::WriteOnly);
- QTextStream stream(&fileHandle);
- stream << file.content;
- fileHandle.close();
-
- return true;
-}
-
-void FileQueue::filterFiles(const Utils::FilePaths keepFiles)
-{
- QtConcurrent::blockingFilter(m_queuedFiles, [keepFiles](const GeneratableFile &qf) {
- return keepFiles.contains(qf.filePath);
- });
-}
-
-QString readTemplate(const QString &templatePath)
-{
- QFile templatefile(templatePath);
- templatefile.open(QIODevice::ReadOnly);
- QTextStream stream(&templatefile);
- QString content = stream.readAll();
- templatefile.close();
-
- return content;
-}
-
-const QString projectEnvironmentVariable(const QString &key)
-{
- QString value = {};
-
- auto *target = ProjectExplorer::SessionManager::startupProject()->activeTarget();
- if (target && target->buildSystem()) {
- auto buildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
- if (buildSystem) {
- auto envItems = buildSystem->environment();
- auto confEnv = std::find_if(envItems.begin(), envItems.end(),
- [key](NameValueItem &item){return item.name == key;});
- if (confEnv != envItems.end())
- value = confEnv->value;
- }
- }
- return value;
-}
-
-const QDir::Filters FILES_ONLY = QDir::Files;
-const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
-
-const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl";
-const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl";
-
-bool CmakeFileGenerator::prepare(const FilePath &rootDir, bool checkFileBelongs)
-{
- m_checkFileIsInProject = checkFileBelongs;
-
- FilePath contentDir = rootDir.pathAppended(DIRNAME_CONTENT);
- FilePath importDir = rootDir.pathAppended(DIRNAME_IMPORT);
- FilePath assetImportDir = rootDir.pathAppended(DIRNAME_ASSETIMPORT);
-
- generateModuleCmake(contentDir);
- generateImportCmake(importDir);
- generateImportCmake(assetImportDir);
- generateMainCmake(rootDir);
- generateEntryPointFiles(rootDir);
-
- return true;
-}
-
-const FileQueue CmakeFileGenerator::fileQueue() const
-{
- return m_fileQueue;
-}
-
-void CmakeFileGenerator::filterFileQueue(const Utils::FilePaths &keepFiles)
-{
- m_fileQueue.filterFiles(keepFiles);
-}
-
-bool CmakeFileGenerator::execute()
-{
- return m_fileQueue.writeQueuedFiles();
-}
-
-const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n";
-const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
-
-void CmakeFileGenerator::generateMainCmake(const FilePath &rootDir)
-{
- //TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all.
- QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
- QString appName = projectName + "App";
-
- QString fileSection = "";
- const QString qtcontrolsConfFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!qtcontrolsConfFile.isEmpty())
- fileSection = QString(" FILES\n %1").arg(qtcontrolsConfFile);
-
- QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH)
- .arg(appName)
- .arg(fileSection);
-
- queueCmakeFile(rootDir, cmakeFileContent);
-
- QString subdirIncludes;
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_CONTENT));
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_IMPORT));
- if (rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists())
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_ASSETIMPORT));
-
- QString modulesAsPlugins;
- for (const QString &moduleName : m_moduleNames)
- modulesAsPlugins.append(" " + moduleName + "plugin\n");
-
- QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH)
- .arg(appName)
- .arg(subdirIncludes)
- .arg(modulesAsPlugins);
-
- m_fileQueue.queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent);
-}
-
-void CmakeFileGenerator::generateImportCmake(const FilePath &dir, const QString &modulePrefix)
-{
- if (!dir.exists())
- return;
-
- QString fileContent;
-
- fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
- FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirs) {
- if (isDirBlacklisted(subDir))
- continue;
- if (getDirectoryTreeQmls(subDir).isEmpty() && getDirectoryTreeResources(subDir).isEmpty())
- continue;
- fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
- QString prefix = modulePrefix.isEmpty() ?
- modulePrefix % subDir.fileName() :
- QString(modulePrefix + '.') + subDir.fileName();
- if (getDirectoryQmls(subDir).isEmpty()) {
- generateImportCmake(subDir, prefix);
- } else {
- generateModuleCmake(subDir, prefix);
- }
- }
-
- queueCmakeFile(dir, fileContent);
-}
-
-const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
-const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
-const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
-
-void CmakeFileGenerator::generateModuleCmake(const FilePath &dir, const QString &uri)
-{
- QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
-
- QString singletonContent;
- FilePaths qmldirFileList = dir.dirEntries({QStringList(FILENAME_QMLDIR), FILES_ONLY});
- if (!qmldirFileList.isEmpty()) {
- QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
- for (QString &singleton : singletons) {
- singletonContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true"));
- }
- }
-
- QStringList qmlFileList = getDirectoryTreeQmls(dir);
- QString qmlFiles;
- for (QString &qmlFile : qmlFileList)
- qmlFiles.append(QString(" %1\n").arg(qmlFile));
-
- QStringList resourceFileList = getDirectoryTreeResources(dir);
- QString resourceFiles;
- for (QString &resourceFile : resourceFileList)
- resourceFiles.append(QString(" %1\n").arg(resourceFile));
-
- QString moduleContent;
- if (!qmlFiles.isEmpty()) {
- moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFiles));
- }
- if (!resourceFiles.isEmpty()) {
- moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
- }
-
- QString moduleUri = uri.isEmpty() ?
- dir.fileName() :
- uri;
-
- QString moduleName = QString(moduleUri).replace('.', '_');
- m_moduleNames.append(moduleName);
-
- QString fileContent;
- fileContent.append(fileTemplate.arg(singletonContent, moduleName, moduleUri, moduleContent));
- queueCmakeFile(dir, fileContent);
-}
-
-QStringList CmakeFileGenerator::getSingletonsFromQmldirFile(const FilePath &filePath)
-{
- QStringList singletons;
- QFile f(filePath.toString());
- f.open(QIODevice::ReadOnly);
- QTextStream stream(&f);
-
- while (!stream.atEnd()) {
- QString line = stream.readLine();
- if (line.startsWith("singleton", Qt::CaseInsensitive)) {
- QStringList tokenizedLine = line.split(QRegularExpression("\\s+"));
- QString fileName = tokenizedLine.last();
- if (fileName.endsWith(".qml", Qt::CaseInsensitive)) {
- singletons.append(fileName);
- }
- }
- }
-
- f.close();
-
- return singletons;
-}
-
-QStringList CmakeFileGenerator::getDirectoryQmls(const FilePath &dir)
-{
- QStringList moduleFiles;
-
- const QStringList qmlFilesOnly(FILENAME_FILTER_QML);
- FilePaths allFiles = dir.dirEntries({qmlFilesOnly, FILES_ONLY});
- for (FilePath &file : allFiles) {
- if (includeFile(file)) {
- moduleFiles.append(file.fileName());
- }
- }
-
- return moduleFiles;
-}
-
-QStringList CmakeFileGenerator::getDirectoryResources(const FilePath &dir)
-{
- QStringList moduleFiles;
-
- FilePaths allFiles = dir.dirEntries(FILES_ONLY);
- for (FilePath &file : allFiles) {
- if (!file.fileName().endsWith(".qml", Qt::CaseInsensitive) &&
- includeFile(file)) {
- moduleFiles.append(file.fileName());
- }
- }
-
- return moduleFiles;
-}
-
-QStringList CmakeFileGenerator::getDirectoryTreeQmls(const FilePath &dir)
-{
- QStringList qmlFileList;
-
- qmlFileList.append(getDirectoryQmls(dir));
-
- FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirsList) {
- if (isDirBlacklisted(subDir))
- continue;
- QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir);
- for (QString &qmlFile : subDirQmlFiles) {
- qmlFileList.append(subDir.fileName().append('/').append(qmlFile));
- }
- }
-
- return qmlFileList;
-}
-
-QStringList CmakeFileGenerator::getDirectoryTreeResources(const FilePath &dir)
-{
- QStringList resourceFileList;
-
- resourceFileList.append(getDirectoryResources(dir));
-
- FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirsList) {
- if (isDirBlacklisted(subDir))
- continue;
- QStringList subDirResources = getDirectoryTreeResources(subDir);
- for (QString &resource : subDirResources) {
- resourceFileList.append(subDir.fileName().append('/').append(resource));
- }
-
- }
-
- return resourceFileList;
-}
-
-void CmakeFileGenerator::queueCmakeFile(const FilePath &dir, const QString &content)
-{
- FilePath filePath = dir.pathAppended(FILENAME_CMAKELISTS);
- m_fileQueue.queueFile(filePath, content);
-}
-
-bool CmakeFileGenerator::isFileBlacklisted(const QString &fileName)
-{
- return (!fileName.compare(FILENAME_QMLDIR) ||
- !fileName.compare(FILENAME_CMAKELISTS));
-}
-
-bool CmakeFileGenerator::isDirBlacklisted(const FilePath &dir)
-{
- return (!dir.fileName().compare(DIRNAME_DESIGNER));
-}
-
-bool CmakeFileGenerator::includeFile(const FilePath &filePath)
-{
- if (m_checkFileIsInProject) {
- ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
- if (!project->isKnownFile(filePath))
- return false;
- }
-
- return !isFileBlacklisted(filePath.fileName());
-}
-
-
-bool CmakeFileGenerator::generateEntryPointFiles(const FilePath &dir)
-{
- const QString qtcontrolsConf = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!qtcontrolsConf.isEmpty())
- m_resourceFileLocations.append(qtcontrolsConf);
-
- bool cppOk = generateMainCpp(dir);
- bool qmlOk = generateMainQml(dir);
-
- return cppOk && qmlOk;
-}
-
-const char MAIN_CPPFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
-const char MAIN_CPPFILE_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
-const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n";
-const char ENV_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl";
-const char ENV_HEADER_VARIABLE_LINE[] = " qputenv(\"%1\", \"%2\");\n";
-
-bool CmakeFileGenerator::generateMainCpp(const FilePath &dir)
-{
- FilePath srcDir = dir.pathAppended(DIRNAME_CPP);
-
- QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH);
- FilePath cppFilePath = srcDir.pathAppended(FILENAME_MAINCPP);
- bool cppOk = m_fileQueue.queueFile(cppFilePath, cppContent);
-
- QString modulesAsPlugins;
- for (const QString &moduleName : m_moduleNames)
- modulesAsPlugins.append(
- QString(MAIN_CPPFILE_HEADER_PLUGIN_LINE).arg(moduleName + "Plugin"));
-
- QString headerContent = GenerateCmake::readTemplate(MAIN_CPPFILE_HEADER_TEMPLATE_PATH)
- .arg(modulesAsPlugins);
- FilePath headerFilePath = srcDir.pathAppended(FILENAME_MAINCPP_HEADER);
- bool pluginHeaderOk = m_fileQueue.queueFile(headerFilePath, headerContent);
-
- bool envHeaderOk = true;
- QString environment;
- auto *target = ProjectExplorer::SessionManager::startupProject()->activeTarget();
- if (target && target->buildSystem()) {
- auto buildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
- if (buildSystem) {
- for (EnvironmentItem &envItem : buildSystem->environment()) {
- QString key = envItem.name;
- QString value = envItem.value;
- if (isFileResource(value))
- value.prepend(":/");
- environment.append(QString(ENV_HEADER_VARIABLE_LINE).arg(key).arg(value));
- }
- QString envHeaderContent = GenerateCmake::readTemplate(ENV_HEADER_TEMPLATE_PATH)
- .arg(environment);
- FilePath envHeaderPath = srcDir.pathAppended(FILENAME_ENV_HEADER);
- envHeaderOk = m_fileQueue.queueFile(envHeaderPath, envHeaderContent);
- }
- }
-
- return cppOk && pluginHeaderOk && envHeaderOk;
-}
-
-const char MAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl";
-
-bool CmakeFileGenerator::generateMainQml(const FilePath &dir)
-{
- QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_TEMPLATE_PATH);
- FilePath filePath = dir.pathAppended(FILENAME_MAINQML);
- return m_fileQueue.queueFile(filePath, content);
-}
-
-bool CmakeFileGenerator::isFileResource(const QString &relativeFilePath)
-{
- if (m_resourceFileLocations.contains(relativeFilePath))
- return true;
-
- return false;
-}
-
-} //GenerateCmake
-} //QmlDesigner
-
diff --git a/src/plugins/qmldesigner/generatecmakelists.h b/src/plugins/qmldesigner/generatecmakelists.h
deleted file mode 100644
index 7045ce17c8a..00000000000
--- a/src/plugins/qmldesigner/generatecmakelists.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/project.h>
-
-#include <utils/fileutils.h>
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-struct GeneratableFile {
- Utils::FilePath filePath;
- QString content;
- bool fileExists;
-};
-
-bool operator==(const GeneratableFile &left, const GeneratableFile &right);
-
-void generateMenuEntry();
-void onGenerateCmakeLists();
-bool isErrorFatal(int error);
-int isProjectCorrectlyFormed(const Utils::FilePath &rootDir);
-void showProjectDirErrorDialog(int error);
-QString readTemplate(const QString &templatePath);
-const QString projectEnvironmentVariable(const QString &key);
-
-class FileQueue {
-public:
- bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
- const QVector<GeneratableFile> queuedFiles() const;
- bool writeQueuedFiles();
- void filterFiles(const Utils::FilePaths keepFiles);
-
-private:
- bool writeFile(const GeneratableFile &file);
-
-private:
- QVector<GeneratableFile> m_queuedFiles;
-};
-
-class CmakeFileGenerator {
-public:
- bool prepare(const Utils::FilePath &rootDir, bool check = true);
- const FileQueue fileQueue() const;
- void filterFileQueue(const Utils::FilePaths &keepFiles);
- bool execute();
-
-private:
- void generateMainCmake(const Utils::FilePath &rootDir);
- void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString());
- void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString());
- bool generateEntryPointFiles(const Utils::FilePath &dir);
- bool generateMainCpp(const Utils::FilePath &dir);
- bool generateMainQml(const Utils::FilePath &dir);
- QStringList getDirectoryQmls(const Utils::FilePath &dir);
- QStringList getDirectoryResources(const Utils::FilePath &dir);
- QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
- QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
- QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
- void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
- bool isFileResource(const QString &relativeFilePath);
- bool isFileBlacklisted(const QString &fileName);
- bool isDirBlacklisted(const Utils::FilePath &dir);
- bool includeFile(const Utils::FilePath &filePath);
-
-private:
- FileQueue m_fileQueue;
- QStringList m_resourceFileLocations;
- QStringList m_moduleNames;
- bool m_checkFileIsInProject;
-};
-
-} //GenerateCmake
-
-} //QmlDesigner
diff --git a/src/plugins/qmldesigner/generatecmakelistsconstants.h b/src/plugins/qmldesigner/generatecmakelistsconstants.h
deleted file mode 100644
index e4358dc5999..00000000000
--- a/src/plugins/qmldesigner/generatecmakelistsconstants.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Design Tooling
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#ifndef GENERATECMAKELISTSCONSTANTS_H
-#define GENERATECMAKELISTSCONSTANTS_H
-
-#pragma once
-
-namespace QmlDesigner {
-namespace GenerateCmake {
-namespace Constants {
-
-const char DIRNAME_CONTENT[] = "content";
-const char DIRNAME_IMPORT[] = "imports";
-const char DIRNAME_ASSET[] = "assets";
-const char DIRNAME_ASSETIMPORT[] = "asset_imports";
-const char DIRNAME_CPP[] = "src";
-const char DIRNAME_DESIGNER[] = "designer";
-
-const char FILENAME_CMAKELISTS[] = "CMakeLists.txt";
-const char FILENAME_APPMAINQML[] = "App.qml";
-const char FILENAME_MAINQML[] = "main.qml";
-const char FILENAME_MAINCPP[] = "main.cpp";
-const char FILENAME_MAINCPP_HEADER[] = "import_qml_plugins.h";
-const char FILENAME_MODULES[] = "qmlmodules";
-const char FILENAME_QMLDIR[] = "qmldir";
-const char FILENAME_ENV_HEADER[] = "app_environment.h";
-
-const char FILENAME_SUFFIX_QMLPROJECT[] = "qmlproject";
-const char FILENAME_SUFFIX_QML[] = "qml";
-const char FILENAME_SUFFIX_USER[] = "user";
-
-const char FILENAME_FILTER_QMLPROJECT[] = "*.qmlproject";
-const char FILENAME_FILTER_QML[] = "*.qml";
-
-const char ENV_VARIABLE_CONTROLCONF[] = "QT_QUICK_CONTROLS_CONF";
-
-} //Constants
-} //GenerateCmake
-} //QmlDesigner
-
-#endif // GENERATECMAKELISTSCONSTANTS_H
diff --git a/src/plugins/qmldesigner/generateresource.cpp b/src/plugins/qmldesigner/generateresource.cpp
index 7210a144717..2233538196f 100644
--- a/src/plugins/qmldesigner/generateresource.cpp
+++ b/src/plugins/qmldesigner/generateresource.cpp
@@ -195,7 +195,7 @@ QList<GenerateResource::ResourceFile> getFilesFromQrc(QFile *file, bool inProjec
return fileList;
}
-void GenerateResource::generateMenuEntry()
+void GenerateResource::generateMenuEntry(QObject *parent)
{
Core::ActionContainer *menu =
Core::ActionManager::actionContainer(Core::Constants::M_FILE);
@@ -203,7 +203,7 @@ void GenerateResource::generateMenuEntry()
const Core::Context projectContext(QmlProjectManager::Constants::QML_PROJECT_ID);
// ToDo: move this to QtCreator and add tr to the string then
auto action = new QAction(QCoreApplication::translate("QmlDesigner::GenerateResource",
- "Generate QRC Resource File"));
+ "Generate QRC Resource File"), parent);
action->setEnabled(ProjectExplorer::SessionManager::startupProject() != nullptr);
// todo make it more intelligent when it gets enabled
QObject::connect(ProjectExplorer::SessionManager::instance(),
@@ -217,7 +217,7 @@ void GenerateResource::generateMenuEntry()
QTC_ASSERT(currentProject, return);
const FilePath projectPath = currentProject->projectFilePath().parentDir();
- auto projectFileName = Core::DocumentManager::getSaveFileName(
+ auto projectFileName = Core::DocumentManager::getSaveFileNameWithExtension(
QCoreApplication::translate("QmlDesigner::GenerateResource", "Save Project as QRC File"),
projectPath.pathAppended(currentProject->displayName() + ".qrc"),
QCoreApplication::translate("QmlDesigner::GenerateResource",
@@ -255,7 +255,6 @@ void GenerateResource::generateMenuEntry()
QByteArray stdOut;
QByteArray stdErr;
if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
- rccProcess.stopProcess();
Core::MessageManager::writeDisrupting(
QCoreApplication::translate("QmlDesigner::GenerateResource",
"A timeout occurred running \"%1\"")
@@ -353,7 +352,7 @@ void GenerateResource::generateMenuEntry()
// ToDo: move this to QtCreator and add tr to the string then
auto rccAction = new QAction(QCoreApplication::translate("QmlDesigner::GenerateResource",
- "Generate Deployable Package"));
+ "Generate Deployable Package"), parent);
rccAction->setEnabled(ProjectExplorer::SessionManager::startupProject() != nullptr);
QObject::connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged, [rccAction]() {
@@ -367,7 +366,7 @@ void GenerateResource::generateMenuEntry()
QTC_ASSERT(currentProject, return);
const FilePath projectPath = currentProject->projectFilePath().parentDir();
- const FilePath resourceFileName = Core::DocumentManager::getSaveFileName(
+ const FilePath resourceFileName = Core::DocumentManager::getSaveFileNameWithExtension(
QCoreApplication::translate("QmlDesigner::GenerateResource", "Save Project as Resource"),
projectPath.pathAppended(currentProject->displayName() + ".qmlrc"),
QCoreApplication::translate("QmlDesigner::GenerateResource",
@@ -415,7 +414,6 @@ void GenerateResource::generateMenuEntry()
QByteArray stdOut;
QByteArray stdErr;
if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
- rccProcess.stopProcess();
Core::MessageManager::writeDisrupting(
QCoreApplication::translate("QmlDesigner::GenerateResource",
"A timeout occurred running \"%1\"")
@@ -545,7 +543,6 @@ void GenerateResource::generateMenuEntry()
QByteArray stdOut;
QByteArray stdErr;
if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
- rccProcess.stopProcess();
Core::MessageManager::writeDisrupting(
QCoreApplication::translate("QmlDesigner::GenerateResource",
"A timeout occurred running \"%1\"")
diff --git a/src/plugins/qmldesigner/generateresource.h b/src/plugins/qmldesigner/generateresource.h
index 42d96c2d513..d96274efe5e 100644
--- a/src/plugins/qmldesigner/generateresource.h
+++ b/src/plugins/qmldesigner/generateresource.h
@@ -33,7 +33,7 @@ struct ResourceFile
QString fileName;
bool inProject;
};
- void generateMenuEntry();
+ void generateMenuEntry(QObject *parent);
QStringList getFileList(const QList<ResourceFile> &);
QTableWidget* createFilesTable(const QList<ResourceFile> &);
}
diff --git a/src/plugins/qmldesigner/openuiqmlfiledialog.cpp b/src/plugins/qmldesigner/openuiqmlfiledialog.cpp
index bfb49c25c56..8bd5a0e17ce 100644
--- a/src/plugins/qmldesigner/openuiqmlfiledialog.cpp
+++ b/src/plugins/qmldesigner/openuiqmlfiledialog.cpp
@@ -75,7 +75,7 @@ void OpenUiQmlFileDialog::setUiQmlFiles(const QString &projectPath, const QStrin
{
QDir projectDir(projectPath);
- foreach (const QString &fileName, stringList) {
+ for (const QString &fileName : stringList) {
QListWidgetItem *item = new QListWidgetItem(projectDir.relativeFilePath(fileName), ui->listWidget);
item->setData(Qt::UserRole, fileName);
ui->listWidget->addItem(item);
diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h
index 486faeaa267..ee5fa690dca 100644
--- a/src/plugins/qmldesigner/qmldesignerconstants.h
+++ b/src/plugins/qmldesigner/qmldesignerconstants.h
@@ -32,11 +32,12 @@ const char C_BACKSPACE[] = "QmlDesigner.Backspace";
const char C_DELETE[] = "QmlDesigner.Delete";
// Context
-const char C_QMLDESIGNER[] = "QmlDesigner::QmlDesignerMain";
-const char C_QMLFORMEDITOR[] = "QmlDesigner::FormEditor";
-const char C_QMLEDITOR3D[] = "QmlDesigner::Editor3D";
-const char C_QMLNAVIGATOR[] = "QmlDesigner::Navigator";
-const char C_QMLTEXTEDITOR[] = "QmlDesigner::TextEditor";
+const char C_QMLDESIGNER[] = "QmlDesigner::QmlDesignerMain";
+const char C_QMLFORMEDITOR[] = "QmlDesigner::FormEditor";
+const char C_QMLEDITOR3D[] = "QmlDesigner::Editor3D";
+const char C_QMLNAVIGATOR[] = "QmlDesigner::Navigator";
+const char C_QMLTEXTEDITOR[] = "QmlDesigner::TextEditor";
+const char C_QMLMATERIALBROWSER[] = "QmlDesigner::MaterialBrowser";
// Special context for preview menu, shared b/w designer and text editor
const char C_QT_QUICK_TOOLS_MENU[] = "QmlDesigner::ToolsMenu";
@@ -68,6 +69,7 @@ const char EDIT3D_EDIT_SHOW_GRID[] = "QmlDesigner.Editor3D.ToggleGrid";
const char EDIT3D_EDIT_SELECT_BACKGROUND_COLOR[] = "QmlDesigner.Editor3D.SelectBackgroundColor";
const char EDIT3D_EDIT_SELECT_GRID_COLOR[] = "QmlDesigner.Editor3D.SelectGridColor";
const char EDIT3D_EDIT_RESET_BACKGROUND_COLOR[] = "QmlDesigner.Editor3D.ResetBackgroundColor";
+const char EDIT3D_EDIT_SYNC_BACKGROUND_COLOR[] = "QmlDesigner.Editor3D.SyncBackgroundColor";
const char EDIT3D_EDIT_SHOW_SELECTION_BOX[] = "QmlDesigner.Editor3D.ToggleSelectionBox";
const char EDIT3D_EDIT_SHOW_ICON_GIZMO[] = "QmlDesigner.Editor3D.ToggleIconGizmo";
const char EDIT3D_EDIT_SHOW_CAMERA_FRUSTUM[] = "QmlDesigner.Editor3D.ToggleCameraFrustum";
@@ -131,6 +133,8 @@ const char EVENT_ITEMLIBRARY_TIME[] = "itemLibrary";
const char EVENT_TRANSLATIONVIEW_TIME[] = "translationView";
const char EVENT_NAVIGATORVIEW_TIME[] = "navigatorView";
const char EVENT_DESIGNMODE_TIME[] = "designMode";
+const char EVENT_MATERIALEDITOR_TIME[] = "materialEditor";
+const char EVENT_MATERIALBROWSER_TIME[] = "materialBrowser";
const char PROPERTY_EDITOR_CLASSNAME_PROPERTY[] = "__classNamePrivateInternal";
diff --git a/src/plugins/qmldesigner/qmldesignercore.cmake b/src/plugins/qmldesigner/qmldesignercore.cmake
index 9a2b0b6f3e6..8795659c691 100644
--- a/src/plugins/qmldesigner/qmldesignercore.cmake
+++ b/src/plugins/qmldesigner/qmldesignercore.cmake
@@ -27,9 +27,6 @@ function(extend_with_qmldesigner_core target_name)
QmlProjectManager
QtSupport
TextEditor
- DEFINES
- DESIGNER_CORE_LIBRARY
- TEST_EXPORTS
INCLUDES
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/components
@@ -50,6 +47,21 @@ function(extend_with_qmldesigner_core target_name)
rewritertransaction.h
)
+ # autouic gets confused when adding the ui files to tests in the qtquickdesigner repo,
+ # so manually add them for UIC
+ set(UI_FILES
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/designercore/instances/puppetbuildprogressdialog.ui
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/designercore/instances/puppetdialog.ui
+ )
+ qt_wrap_ui(UI_SOURCES ${UI_FILES})
+ extend_qtc_target(${target_name}
+ INCLUDES ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES
+ ${UI_SOURCES}
+ ${UI_FILES}
+ )
+ set_source_files_properties(${UI_FILES} PROPERTIES SKIP_AUTOUIC ON)
+
extend_qtc_target(${target_name}
INCLUDES
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/designercore/exceptions
@@ -207,12 +219,10 @@ function(extend_with_qmldesigner_core target_name)
instances/nodeinstanceview.cpp
instances/puppetbuildprogressdialog.cpp
instances/puppetbuildprogressdialog.h
- instances/puppetbuildprogressdialog.ui
instances/puppetcreator.cpp
instances/puppetcreator.h
instances/puppetdialog.cpp
instances/puppetdialog.h
- instances/puppetdialog.ui
instances/qprocessuniqueptr.h
metainfo/itemlibraryinfo.cpp
@@ -422,4 +432,11 @@ function(extend_with_qmldesigner_core target_name)
SOURCES_PREFIX ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../../share/qtcreator/qml/qmlpuppet/container
SOURCES sharedmemory_qt.cpp
)
+
+ set(export_symbol_declaration DEFINES QMLDESIGNER_LIBRARY)
+ if (QTC_STATIC_BUILD)
+ set(export_symbol_declaration PUBLIC_DEFINES QMLDESIGNER_STATIC_LIBRARY)
+ endif()
+ extend_qtc_target(${target_name} ${export_symbol_declaration})
+
endfunction()
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
index 5ab50135eb2..69d3db51c32 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.cpp
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -24,11 +24,9 @@
****************************************************************************/
#include "qmldesignerplugin.h"
-#include "cmakeprojectconverter.h"
#include "designmodecontext.h"
#include "designmodewidget.h"
#include "exception.h"
-#include "generatecmakelists.h"
#include "generateresource.h"
#include "nodeinstanceview.h"
#include "openuiqmlfiledialog.h"
@@ -240,10 +238,7 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
return false;
d = new QmlDesignerPluginPrivate;
if (QmlProjectManager::QmlProject::isQtDesignStudio())
- GenerateResource::generateMenuEntry();
-
- GenerateCmake::generateMenuEntry();
- GenerateCmake::CmakeProjectConverter::generateMenuEntry();
+ GenerateResource::generateMenuEntry(this);
const QString fontPath
= Core::ICore::resourcePath(
@@ -375,7 +370,8 @@ static QStringList allUiQmlFilesforCurrentProject(const Utils::FilePath &fileNam
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(fileName);
if (currentProject) {
- foreach (const Utils::FilePath &fileName, currentProject->files(ProjectExplorer::Project::SourceFiles)) {
+ const QList<Utils::FilePath> fileNames = currentProject->files(ProjectExplorer::Project::SourceFiles);
+ for (const Utils::FilePath &fileName : fileNames) {
if (fileName.endsWith(".ui.qml"))
list.append(fileName.toString());
}
@@ -403,15 +399,18 @@ void QmlDesignerPlugin::integrateIntoQtCreator(QWidget *modeWidget)
Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR);
Core::Context qmlDesignerEditor3dContext(Constants::C_QMLEDITOR3D);
Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR);
+ Core::Context qmlDesignerMaterialBrowserContext(Constants::C_QMLMATERIALBROWSER);
context->context().add(qmlDesignerMainContext);
context->context().add(qmlDesignerFormEditorContext);
context->context().add(qmlDesignerEditor3dContext);
context->context().add(qmlDesignerNavigatorContext);
+ context->context().add(qmlDesignerMaterialBrowserContext);
context->context().add(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID);
d->shortCutManager.registerActions(qmlDesignerMainContext, qmlDesignerFormEditorContext,
- qmlDesignerEditor3dContext, qmlDesignerNavigatorContext);
+ qmlDesignerEditor3dContext, qmlDesignerNavigatorContext,
+ qmlDesignerMaterialBrowserContext);
const QStringList mimeTypes = { QmlJSTools::Constants::QML_MIMETYPE,
QmlJSTools::Constants::QMLUI_MIMETYPE };
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs
index be482a22ca6..9125ec82a3a 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.qbs
+++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs
@@ -5,13 +5,12 @@ Project {
name: "QmlDesigner"
QtcPlugin {
+ condition: Qt.quickwidgets.present && Qt.svg.present
fileName: FileInfo.fileName(filePath)
Depends {
- name: "Qt";
- submodules: [
- "core-private", "quickwidgets", "xml", "svg"
- ]
+ name: "Qt"; versionAtLeast: "6.2"; required: false
+ submodules: ["core-private", "quickwidgets", "xml", "svg"]
}
Depends { name: "AdvancedDockingSystem" }
Depends { name: "Core" }
@@ -29,7 +28,7 @@ Project {
Depends { name: "Sqlite" }
cpp.defines: base.concat([
- "DESIGNER_CORE_LIBRARY",
+ "QMLDESIGNER_LIBRARY",
"TIMELINE_QML_PATH=\"" + FileInfo.joinPaths(path, "components",
"timelineeditor", "qml") + "\""
])
@@ -762,7 +761,7 @@ Project {
"propertyeditor/qmlmodelnodeproxy.h",
"propertyeditor/tooltip.cpp",
"propertyeditor/tooltip.h",
- "resources/resources.qrc",
+ "resources/resources_qmldesigner_components.qrc",
"stateseditor/stateseditorimageprovider.cpp",
"stateseditor/stateseditorimageprovider.h",
"stateseditor/stateseditormodel.cpp",
@@ -971,7 +970,6 @@ Project {
"timelineeditor/preseteditor.h",
"timelineeditor/setframevaluedialog.cpp",
"timelineeditor/setframevaluedialog.h",
- "timelineeditor/setframevaluedialog.ui",
"timelineeditor/splineeditor.cpp",
"timelineeditor/splineeditor.h",
"timelineeditor/timeline.qrc",
@@ -1056,19 +1054,6 @@ Project {
files: [
"generateresource.cpp",
"generateresource.h",
- "generatecmakelists.cpp",
- "generatecmakelists.h",
- "generatecmakelistsconstants.h",
- "checkablefiletreeitem.cpp",
- "checkablefiletreeitem.h",
- "cmakegeneratordialogtreemodel.cpp",
- "cmakegeneratordialogtreemodel.h",
- "cmakegeneratordialog.cpp",
- "cmakegeneratordialog.h",
- "cmakeprojectconverter.cpp",
- "cmakeprojectconverter.h",
- "cmakeprojectconverterdialog.cpp",
- "cmakeprojectconverterdialog.h",
"designersettings.cpp",
"designersettings.h",
"designmodecontext.cpp",
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp
index 09375ba69ff..d3252ea8e3e 100644
--- a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp
@@ -30,8 +30,10 @@
#include <designersettings.h>
#include <utils/utilsicons.h>
+
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
@@ -73,7 +75,7 @@ static void handleAction(const SelectionContext &context)
}
ProjectExplorerPlugin::runStartupProject(Constants::QML_PREVIEW_RUN_MODE, skipDeploy);
} else {
- QmlPreviewPlugin::stopAllRunControls();
+ QmlPreviewWidgetPlugin::stopAllRunControls();
}
}
}
@@ -81,14 +83,14 @@ static void handleAction(const SelectionContext &context)
QmlPreviewAction::QmlPreviewAction() : ModelNodeAction(livePreviewId,
"Live Preview",
previewIcon.icon(),
- QmlPreviewPlugin::tr("Show Live Preview"),
+ QmlPreviewWidgetPlugin::tr("Show Live Preview"),
ComponentCoreConstants::qmlPreviewCategory,
QKeySequence("Alt+p"),
20,
&handleAction,
&SelectionContextFunctors::always)
{
- if (!QmlPreviewPlugin::getPreviewPlugin())
+ if (!QmlPreviewWidgetPlugin::getPreviewPlugin())
defaultAction()->setVisible(false);
defaultAction()->setCheckable(true);
@@ -97,7 +99,7 @@ QmlPreviewAction::QmlPreviewAction() : ModelNodeAction(livePreviewId,
void QmlPreviewAction::updateContext()
{
if (selectionContext().view()->isAttached())
- QmlPreviewPlugin::setQmlFile();
+ QmlPreviewWidgetPlugin::setQmlFile();
defaultAction()->setSelectionContext(selectionContext());
}
@@ -111,9 +113,9 @@ ZoomPreviewAction::ZoomPreviewAction()
: m_zoomAction(new ZoomAction(nullptr))
{
QObject::connect(m_zoomAction.get(), &ZoomAction::zoomLevelChanged, [=](float d) {
- QmlPreviewPlugin::setZoomFactor(d);
+ QmlPreviewWidgetPlugin::setZoomFactor(d);
});
- if (!QmlPreviewPlugin::getPreviewPlugin())
+ if (!QmlPreviewWidgetPlugin::getPreviewPlugin())
m_zoomAction->setVisible(false);
}
@@ -281,7 +283,7 @@ SwitchLanguageAction::SwitchLanguageAction()
: m_switchLanguageAction(new SwitchLanguageComboboxAction(nullptr))
{
QObject::connect(m_switchLanguageAction.get(), &SwitchLanguageComboboxAction::currentLocaleChanged,
- &QmlPreviewPlugin::setLanguageLocale);
+ &QmlPreviewWidgetPlugin::setLanguageLocale);
}
QAction *SwitchLanguageAction::action() const
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp
index 0975acfde30..701ed349030 100644
--- a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp
@@ -53,7 +53,7 @@ Q_DECLARE_METATYPE(QmlPreview::QmlPreviewRunControlList)
namespace QmlDesigner {
static QObject *s_previewPlugin = nullptr;
-QmlPreviewPlugin::QmlPreviewPlugin()
+QmlPreviewWidgetPlugin::QmlPreviewWidgetPlugin()
{
DesignerActionManager &designerActionManager =
QmlDesignerPlugin::instance()->designerActionManager();
@@ -92,12 +92,12 @@ QmlPreviewPlugin::QmlPreviewPlugin()
}
}
-QString QmlPreviewPlugin::pluginName() const
+QString QmlPreviewWidgetPlugin::pluginName() const
{
return QLatin1String("QmlPreviewPlugin");
}
-void QmlPreviewPlugin::stopAllRunControls()
+void QmlPreviewWidgetPlugin::stopAllRunControls()
{
QTC_ASSERT(s_previewPlugin, return);
@@ -109,7 +109,7 @@ void QmlPreviewPlugin::stopAllRunControls()
}
-void QmlPreviewPlugin::handleRunningPreviews()
+void QmlPreviewWidgetPlugin::handleRunningPreviews()
{
QTC_ASSERT(s_previewPlugin, return);
@@ -124,12 +124,12 @@ void QmlPreviewPlugin::handleRunningPreviews()
}
}
-QString QmlPreviewPlugin::metaInfo() const
+QString QmlPreviewWidgetPlugin::metaInfo() const
{
return QLatin1String(":/qmlpreviewplugin/qmlpreview.metainfo");
}
-void QmlPreviewPlugin::setQmlFile()
+void QmlPreviewWidgetPlugin::setQmlFile()
{
if (s_previewPlugin) {
const Utils::FilePath qmlFileName =
@@ -140,7 +140,7 @@ void QmlPreviewPlugin::setQmlFile()
}
}
-float QmlPreviewPlugin::zoomFactor()
+float QmlPreviewWidgetPlugin::zoomFactor()
{
QVariant zoomFactorVariant = 1.0;
if (s_previewPlugin && !s_previewPlugin->property("zoomFactor").isNull())
@@ -148,7 +148,7 @@ float QmlPreviewPlugin::zoomFactor()
return zoomFactorVariant.toFloat();
}
-void QmlPreviewPlugin::setZoomFactor(float zoomFactor)
+void QmlPreviewWidgetPlugin::setZoomFactor(float zoomFactor)
{
if (auto s_previewPlugin = getPreviewPlugin()) {
bool hasZoomFactor = s_previewPlugin->setProperty("zoomFactor", zoomFactor);
@@ -156,7 +156,7 @@ void QmlPreviewPlugin::setZoomFactor(float zoomFactor)
}
}
-void QmlPreviewPlugin::setLanguageLocale(const QString &locale)
+void QmlPreviewWidgetPlugin::setLanguageLocale(const QString &locale)
{
if (auto s_previewPlugin = getPreviewPlugin()) {
bool hasLocaleIsoCode = s_previewPlugin->setProperty("localeIsoCode", locale);
@@ -164,7 +164,7 @@ void QmlPreviewPlugin::setLanguageLocale(const QString &locale)
}
}
-QObject *QmlPreviewPlugin::getPreviewPlugin()
+QObject *QmlPreviewWidgetPlugin::getPreviewPlugin()
{
const QVector<ExtensionSystem::PluginSpec *> &specs = ExtensionSystem::PluginManager::plugins();
const auto pluginIt = std::find_if(specs.cbegin(), specs.cend(),
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h
index 7f50d76696d..858bce6afba 100644
--- a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h
@@ -33,18 +33,18 @@ QT_FORWARD_DECLARE_CLASS(QAction)
namespace QmlDesigner {
-class QmlPreviewPlugin : public QObject, QmlDesigner::IWidgetPlugin
+class QmlPreviewWidgetPlugin : public QObject, QmlDesigner::IWidgetPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QmlDesignerPlugin" FILE "qmlpreviewplugin.json")
- Q_DISABLE_COPY(QmlPreviewPlugin)
+ Q_DISABLE_COPY(QmlPreviewWidgetPlugin)
Q_INTERFACES(QmlDesigner::IWidgetPlugin)
public:
- QmlPreviewPlugin();
- ~QmlPreviewPlugin() override = default;
+ QmlPreviewWidgetPlugin();
+ ~QmlPreviewWidgetPlugin() override = default;
QString metaInfo() const override;
QString pluginName() const override;
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs
index 8e48e6aa850..05e809d4331 100644
--- a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs
@@ -2,6 +2,7 @@ import qbs
QtcProduct {
name: "qmlpreviewplugin"
+ condition: QmlDesigner.present
type: ["dynamiclibrary"]
installDir: qtc.ide_plugin_path + '/' + installDirName
property string installDirName: qbs.targetOS.contains("macos") ? "QmlDesigner" : "qmldesigner"
@@ -15,7 +16,7 @@ QtcProduct {
Depends { name: "Core" }
Depends { name: "ProjectExplorer" }
- Depends { name: "QmlDesigner" }
+ Depends { name: "QmlDesigner"; required: false }
Depends { name: "Qt.qml" }
Depends { name: "Utils" }
diff --git a/src/plugins/qmldesigner/shortcutmanager.cpp b/src/plugins/qmldesigner/shortcutmanager.cpp
index e82e7a04c01..4cda11748c6 100644
--- a/src/plugins/qmldesigner/shortcutmanager.cpp
+++ b/src/plugins/qmldesigner/shortcutmanager.cpp
@@ -77,8 +77,11 @@ ShortCutManager::ShortCutManager()
void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContext,
const Core::Context &qmlDesignerFormEditorContext,
const Core::Context &qmlDesignerEditor3DContext,
- const Core::Context &qmlDesignerNavigatorContext)
+ const Core::Context &qmlDesignerNavigatorContext,
+ const Core::Context &qmlDesignerMaterialBrowserContext)
{
+ Q_UNUSED(qmlDesignerMaterialBrowserContext)
+
Core::ActionContainer *editMenu = Core::ActionManager::actionContainer(Core::Constants::M_EDIT);
Core::ActionContainer *fileMenu = Core::ActionManager::actionContainer(Core::Constants::M_FILE);
@@ -195,9 +198,12 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
m_pasteAction.setEnabled(true);
});
- connect(Core::ICore::instance(), &Core::ICore::contextChanged, this, [&designerActionManager, this](const Core::Context &context){
- if (!context.contains(Constants::C_QMLFORMEDITOR) && !context.contains(Constants::C_QMLEDITOR3D) && !context.contains(Constants::C_QMLNAVIGATOR)) {
- m_deleteAction.setEnabled(false);
+ connect(Core::ICore::instance(), &Core::ICore::contextChanged, this, [&](const Core::Context &context) {
+ isMatBrowserActive = context.contains(Constants::C_QMLMATERIALBROWSER);
+
+ if (!context.contains(Constants::C_QMLFORMEDITOR) && !context.contains(Constants::C_QMLEDITOR3D)
+ && !context.contains(Constants::C_QMLNAVIGATOR)) {
+ m_deleteAction.setEnabled(isMatBrowserActive);
m_cutAction.setEnabled(false);
m_copyAction.setEnabled(false);
m_pasteAction.setEnabled(false);
@@ -249,8 +255,12 @@ void ShortCutManager::redo()
void ShortCutManager::deleteSelected()
{
- if (currentDesignDocument())
+ if (isMatBrowserActive) {
+ DesignerActionManager &designerActionManager = QmlDesignerPlugin::instance()->viewManager().designerActionManager();
+ designerActionManager.view()->emitCustomNotification("delete_selected_material");
+ } else if (currentDesignDocument()) {
currentDesignDocument()->deleteSelected();
+ }
}
void ShortCutManager::cutSelected()
diff --git a/src/plugins/qmldesigner/shortcutmanager.h b/src/plugins/qmldesigner/shortcutmanager.h
index 4bc4ae5f848..149bf566400 100644
--- a/src/plugins/qmldesigner/shortcutmanager.h
+++ b/src/plugins/qmldesigner/shortcutmanager.h
@@ -47,7 +47,8 @@ public:
void registerActions(const Core::Context &qmlDesignerMainContext,
const Core::Context &qmlDesignerFormEditorContext,
const Core::Context &qmlDesignerEditor3DContext,
- const Core::Context &qmlDesignerNavigatorContext);
+ const Core::Context &qmlDesignerNavigatorContext,
+ const Core::Context &qmlDesignerMaterialBrowserContext);
void connectUndoActions(DesignDocument *designDocument);
void disconnectUndoActions(DesignDocument *designDocument);
@@ -84,6 +85,8 @@ private:
QAction m_pasteAction;
QAction m_selectAllAction;
QAction m_escapeAction;
+
+ bool isMatBrowserActive = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/studioplugin/CMakeLists.txt b/src/plugins/qmldesigner/studioplugin/CMakeLists.txt
index be48a6eab5c..3c04dfd6243 100644
--- a/src/plugins/qmldesigner/studioplugin/CMakeLists.txt
+++ b/src/plugins/qmldesigner/studioplugin/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(StudioPlugin
+ PLUGIN_CLASS StudioPlugin
CONDITION TARGET QmlDesigner
DEPENDS Core QmlDesigner Utils ProjectExplorer
SOURCES
diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp
index 5fc1e3d7041..d3e262bb9e1 100644
--- a/src/plugins/qmljseditor/qmljscompletionassist.cpp
+++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp
@@ -101,7 +101,7 @@ static void addCompletions(QList<AssistProposalItemInterface *> *completions,
const QIcon &icon,
int order)
{
- foreach (const QString &text, newCompletions)
+ for (const QString &text : newCompletions)
addCompletion(completions, text, icon, order);
}
@@ -226,7 +226,8 @@ public:
_processed.clear();
_propertyProcessor = processor;
- foreach (const ObjectValue *scope, _scopeChain->all())
+ const QList<const ObjectValue *> scopes = _scopeChain->all();
+ for (const ObjectValue *scope : scopes)
processProperties(scope);
}
@@ -302,7 +303,7 @@ const Value *getPropertyValue(const ObjectValue *object,
return nullptr;
const Value *value = object;
- foreach (const QString &name, propertyNames) {
+ for (const QString &name : propertyNames) {
if (const ObjectValue *objectValue = value->asObjectValue()) {
value = objectValue->lookupMember(name, context);
if (!value)
@@ -334,10 +335,11 @@ QStringList qmlJSAutoComplete(QTextDocument *textDocument,
{
QStringList list;
QmlJSCompletionAssistProcessor processor;
+ QTextCursor cursor(textDocument);
+ cursor.setPosition(position);
QScopedPointer<IAssistProposal> proposal(processor.perform( /* The processor takes ownership. */
new QmlJSCompletionAssistInterface(
- textDocument,
- position,
+ cursor,
fileName,
reason,
info)));
@@ -686,7 +688,7 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const AssistInterface *
QStringList nCompletions;
QString prefix(libVersion.left(toSkip));
nCompletions.reserve(completions.size());
- foreach (const QString &completion, completions)
+ for (const QString &completion : qAsConst(completions))
if (completion.startsWith(prefix))
nCompletions.append(completion.right(completion.size()-toSkip));
completions = nCompletions;
@@ -799,7 +801,8 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const AssistInterface *
if (const QmlEnumValue *enumValue =
value_cast<QmlEnumValue>(value)) {
const QString &name = context->imports(document.data())->nameForImportedObject(enumValue->owner(), context.data());
- foreach (const QString &key, enumValue->keys()) {
+ const QStringList keys = enumValue->keys();
+ for (const QString &key : keys) {
QString completion;
if (name.isEmpty())
completion = QString::fromLatin1("\"%1\"").arg(key);
@@ -909,7 +912,7 @@ bool QmlJSCompletionAssistProcessor::acceptsIdleEditor() const
Scanner scanner;
const QList<Token> tokens = scanner(blockText, blockState);
const int column = block.position() - m_interface->position();
- foreach (const Token &tk, tokens) {
+ for (const Token &tk : tokens) {
if (column >= tk.begin() && column <= tk.end()) {
if (charBeforeCursor == QLatin1Char('/') && tk.is(Token::String))
return true; // path completion inside string literals
@@ -978,12 +981,11 @@ bool QmlJSCompletionAssistProcessor::completeUrl(const QString &relativeBasePath
// ------------------------------
// QmlJSCompletionAssistInterface
// ------------------------------
-QmlJSCompletionAssistInterface::QmlJSCompletionAssistInterface(QTextDocument *textDocument,
- int position,
+QmlJSCompletionAssistInterface::QmlJSCompletionAssistInterface(const QTextCursor &cursor,
const Utils::FilePath &fileName,
AssistReason reason,
const SemanticInfo &info)
- : AssistInterface(textDocument, position, fileName, reason)
+ : AssistInterface(cursor, fileName, reason)
, m_semanticInfo(info)
{}
@@ -1051,7 +1053,7 @@ void QmlJSAssistProposalModel::filter(const QString &prefix)
return;
QList<AssistProposalItemInterface *> newCurrentItems;
newCurrentItems.reserve(m_currentItems.size());
- foreach (AssistProposalItemInterface *item, m_currentItems)
+ for (AssistProposalItemInterface *item : qAsConst(m_currentItems))
if (!item->text().startsWith(QLatin1String("__")))
newCurrentItems << item;
m_currentItems = newCurrentItems;
diff --git a/src/plugins/qmljseditor/qmljscompletionassist.h b/src/plugins/qmljseditor/qmljscompletionassist.h
index 4c8a5eb53db..e9f0218c28a 100644
--- a/src/plugins/qmljseditor/qmljscompletionassist.h
+++ b/src/plugins/qmljseditor/qmljscompletionassist.h
@@ -105,8 +105,7 @@ private:
class QMLJSEDITOR_EXPORT QmlJSCompletionAssistInterface : public TextEditor::AssistInterface
{
public:
- QmlJSCompletionAssistInterface(QTextDocument *textDocument,
- int position,
+ QmlJSCompletionAssistInterface(const QTextCursor &cursor,
const Utils::FilePath &fileName,
TextEditor::AssistReason reason,
const QmlJSTools::SemanticInfo &info);
diff --git a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
index 248107e966f..290565051ca 100644
--- a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
+++ b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
@@ -123,13 +123,14 @@ public:
QStringList sortedPropertiesWithoutId;
- foreach (const QString &property, propertyReader.properties())
+ const QStringList properties = propertyReader.properties();
+ for (const QString &property : properties)
if (property != QLatin1String("id"))
sortedPropertiesWithoutId.append(property);
sortedPropertiesWithoutId.sort();
- foreach (const QString &property, sortedPropertiesWithoutId)
+ for (const QString &property : qAsConst(sortedPropertiesWithoutId))
sourcePreview.append(QLatin1String(" ") + property + QLatin1String(": ") + propertyReader.readAstValue(property));
const bool confirm = ComponentNameDialog::go(&componentName, &path, &suffix,
@@ -178,7 +179,7 @@ public:
if (program->members)
astRootNode = program->members->member;
- foreach (const QString &property, result)
+ for (const QString &property : qAsConst(result))
rewriter.removeBindingByName(initializerOfObject(astRootNode), property);
} else {
qWarning() << Q_FUNC_INFO << "parsing failed:" << newComponentSource;
@@ -208,7 +209,7 @@ public:
if (!m_idName.isEmpty())
replacement += QLatin1String("id: ") + m_idName + QLatin1Char('\n');
- foreach (const QString &property, result)
+ for (const QString &property : qAsConst(result))
replacement += property + QLatin1String(": ") + propertyReader.readAstValue(property) + QLatin1Char('\n');
Utils::ChangeSet changes;
diff --git a/src/plugins/qmljseditor/qmljseditingsettingspage.cpp b/src/plugins/qmljseditor/qmljseditingsettingspage.cpp
index 6c960ba60a8..5186d80b7a3 100644
--- a/src/plugins/qmljseditor/qmljseditingsettingspage.cpp
+++ b/src/plugins/qmljseditor/qmljseditingsettingspage.cpp
@@ -27,6 +27,7 @@
#include "qmljseditorconstants.h"
#include <qmljstools/qmljstoolsconstants.h>
+#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <QSettings>
@@ -38,7 +39,7 @@ const char AUTO_FORMAT_ONLY_CURRENT_PROJECT[] = "QmlJSEditor.AutoFormatOnlyCurre
const char QML_CONTEXTPANE_KEY[] = "QmlJSEditor.ContextPaneEnabled";
const char QML_CONTEXTPANEPIN_KEY[] = "QmlJSEditor.ContextPanePinned";
const char FOLD_AUX_DATA[] = "QmlJSEditor.FoldAuxData";
-const char OPEN_UIQML_FILES_IN_QDS[] = "QmlJSEditor.openUiQmlFilesInQDS";
+const char UIQML_OPEN_MODE[] = "QmlJSEditor.openUiQmlMode";
using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
@@ -49,7 +50,7 @@ QmlJsEditingSettings::QmlJsEditingSettings()
m_autoFormatOnSave(false),
m_autoFormatOnlyCurrentProject(false),
m_foldAuxData(false),
- m_openUiQmlFilesInQDS(false)
+ m_uiQmlOpenMode("")
{}
void QmlJsEditingSettings::set()
@@ -67,7 +68,7 @@ void QmlJsEditingSettings::fromSettings(QSettings *settings)
m_autoFormatOnlyCurrentProject
= settings->value(AUTO_FORMAT_ONLY_CURRENT_PROJECT, QVariant(false)).toBool();
m_foldAuxData = settings->value(FOLD_AUX_DATA, QVariant(true)).toBool();
- m_openUiQmlFilesInQDS = settings->value(OPEN_UIQML_FILES_IN_QDS, QVariant(false)).toBool();
+ m_uiQmlOpenMode = settings->value(UIQML_OPEN_MODE, "").toString();
settings->endGroup();
}
@@ -79,7 +80,7 @@ void QmlJsEditingSettings::toSettings(QSettings *settings) const
settings->setValue(AUTO_FORMAT_ON_SAVE, m_autoFormatOnSave);
settings->setValue(AUTO_FORMAT_ONLY_CURRENT_PROJECT, m_autoFormatOnlyCurrentProject);
settings->setValue(FOLD_AUX_DATA, m_foldAuxData);
- settings->setValue(OPEN_UIQML_FILES_IN_QDS, m_openUiQmlFilesInQDS);
+ settings->setValue(UIQML_OPEN_MODE, m_uiQmlOpenMode);
settings->endGroup();
}
@@ -90,7 +91,7 @@ bool QmlJsEditingSettings::equals(const QmlJsEditingSettings &other) const
&& m_autoFormatOnSave == other.m_autoFormatOnSave
&& m_autoFormatOnlyCurrentProject == other.m_autoFormatOnlyCurrentProject
&& m_foldAuxData == other.m_foldAuxData
- && m_openUiQmlFilesInQDS == other.m_openUiQmlFilesInQDS;
+ && m_uiQmlOpenMode == other.m_uiQmlOpenMode;
}
bool QmlJsEditingSettings::enableContextPane() const
@@ -143,14 +144,14 @@ void QmlJsEditingSettings::setFoldAuxData(const bool foldAuxData)
m_foldAuxData = foldAuxData;
}
-void QmlJsEditingSettings::setOpenUiQmlFilesInQDS(const bool openUiQmlFilesInQDS)
+const QString QmlJsEditingSettings::uiQmlOpenMode() const
{
- m_openUiQmlFilesInQDS = openUiQmlFilesInQDS;
+ return m_uiQmlOpenMode;
}
-bool QmlJsEditingSettings::openUiQmlFilesInQDS() const
+void QmlJsEditingSettings::setUiQmlOpenMode(const QString &mode)
{
- return m_openUiQmlFilesInQDS;
+ m_uiQmlOpenMode = mode;
}
class QmlJsEditingSettingsPageWidget final : public Core::IOptionsPageWidget
@@ -168,7 +169,13 @@ public:
m_ui.autoFormatOnSave->setChecked(s.autoFormatOnSave());
m_ui.autoFormatOnlyCurrentProject->setChecked(s.autoFormatOnlyCurrentProject());
m_ui.foldAuxDataCheckBox->setChecked(s.foldAuxData());
- m_ui.openUiQmlFilesInQDS->setChecked(s.openUiQmlFilesInQDS());
+ m_ui.uiQmlOpenComboBox->addItem(tr("Always Ask"), "");
+ m_ui.uiQmlOpenComboBox->addItem(tr("Qt Design Studio"), Core::Constants::MODE_DESIGN);
+ m_ui.uiQmlOpenComboBox->addItem(tr("Qt Creator"), Core::Constants::MODE_EDIT);
+ int comboIndex = m_ui.uiQmlOpenComboBox->findData(s.uiQmlOpenMode());
+ if (comboIndex < 0)
+ comboIndex = 0;
+ m_ui.uiQmlOpenComboBox->setCurrentIndex(comboIndex);
}
void apply() final
@@ -179,7 +186,7 @@ public:
s.setAutoFormatOnSave(m_ui.autoFormatOnSave->isChecked());
s.setAutoFormatOnlyCurrentProject(m_ui.autoFormatOnlyCurrentProject->isChecked());
s.setFoldAuxData(m_ui.foldAuxDataCheckBox->isChecked());
- s.setOpenUiQmlFilesInQDS(m_ui.openUiQmlFilesInQDS->isChecked());
+ s.setUiQmlOpenMode(m_ui.uiQmlOpenComboBox->currentData().toString());
s.set();
}
diff --git a/src/plugins/qmljseditor/qmljseditingsettingspage.h b/src/plugins/qmljseditor/qmljseditingsettingspage.h
index 8a5957b0199..bc152f22de2 100644
--- a/src/plugins/qmljseditor/qmljseditingsettingspage.h
+++ b/src/plugins/qmljseditor/qmljseditingsettingspage.h
@@ -64,8 +64,8 @@ public:
bool foldAuxData() const;
void setFoldAuxData(const bool foldAuxData);
- bool openUiQmlFilesInQDS() const;
- void setOpenUiQmlFilesInQDS(const bool foldAuxData);
+ const QString uiQmlOpenMode() const;
+ void setUiQmlOpenMode(const QString &mode);
friend bool operator==(const QmlJsEditingSettings &s1, const QmlJsEditingSettings &s2)
{ return s1.equals(s2); }
@@ -78,7 +78,7 @@ private:
bool m_autoFormatOnSave;
bool m_autoFormatOnlyCurrentProject;
bool m_foldAuxData;
- bool m_openUiQmlFilesInQDS;
+ QString m_uiQmlOpenMode;
};
namespace Internal {
diff --git a/src/plugins/qmljseditor/qmljseditingsettingspage.ui b/src/plugins/qmljseditor/qmljseditingsettingspage.ui
index ddd4ee98ba1..4a82cbf4bce 100644
--- a/src/plugins/qmljseditor/qmljseditingsettingspage.ui
+++ b/src/plugins/qmljseditor/qmljseditingsettingspage.ui
@@ -93,12 +93,26 @@
</widget>
</item>
<item>
- <widget class="QCheckBox" name="openUiQmlFilesInQDS">
- <property name="text">
- <string>Open .ui.qml files in Qt Design Studio</string>
- </property>
- </widget>
- </item>
+ <layout class="QHBoxLayout" name="uiQmlLayout">
+ <item alignment="Qt::AlignLeft">
+ <widget class="QLabel" name="uiQmlOpenLabel">
+ <property name="text">
+ <string>Open .ui.qml files with:</string>
+ </property>
+ </widget>
+ </item>
+ <item alignment="Qt::AlignLeft">
+ <widget class="QComboBox" name="uiQmlOpenComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 265b59ca1a7..9052ca40f13 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -189,7 +189,7 @@ static void appendExtraSelectionsForMessages(
const QList<DiagnosticMessage> &messages,
const QTextDocument *document)
{
- foreach (const DiagnosticMessage &d, messages) {
+ for (const DiagnosticMessage &d : messages) {
const int line = d.loc.startLine;
const int column = qMax(1U, d.loc.startColumn);
@@ -511,10 +511,10 @@ void QmlJSEditorWidget::setSelectedElements()
if (m_qmlJsEditorDocument->semanticInfo().isValid()) {
SelectedElement selectedMembers;
- QList<UiObjectMember *> members
- = selectedMembers(m_qmlJsEditorDocument->semanticInfo().document, startPos, endPos);
+ const QList<UiObjectMember *> members
+ = selectedMembers(m_qmlJsEditorDocument->semanticInfo().document, startPos, endPos);
if (!members.isEmpty()) {
- foreach (UiObjectMember *m, members) {
+ for (UiObjectMember *m : members) {
offsets << m;
}
}
@@ -753,7 +753,7 @@ void QmlJSEditorWidget::inspectElementUnderCursor() const
}
void QmlJSEditorWidget::findLinkAt(const QTextCursor &cursor,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool /*resolveTarget*/,
bool /*inNextSplit*/)
{
@@ -768,9 +768,11 @@ void QmlJSEditorWidget::findLinkAt(const QTextCursor &cursor,
if (auto importAst = cast<const AST::UiImport *>(node)) {
// if it's a file import, link to the file
- foreach (const ImportInfo &import, semanticInfo.document->bind()->imports()) {
+ const QList<ImportInfo> imports = semanticInfo.document->bind()->imports();
+ for (const ImportInfo &import : imports) {
if (import.ast() == importAst && import.type() == ImportType::File) {
- Utils::Link link(Utils::FilePath::fromString(import.path()));
+ Utils::Link link(
+ m_modelManager->fileToSource(FilePath::fromString(import.path())));
link.linkTextStart = importAst->firstSourceLocation().begin();
link.linkTextEnd = importAst->lastSourceLocation().end();
processLinkCallback(Utils::Link());
@@ -792,11 +794,9 @@ void QmlJSEditorWidget::findLinkAt(const QTextCursor &cursor,
processLinkCallback(link);
return;
}
- const QString relative = QString::fromLatin1("%1/%2").arg(
- semanticInfo.document->path(),
- text);
- if (QFileInfo::exists(relative)) {
- link.targetFilePath = Utils::FilePath::fromString(relative);
+ const Utils::FilePath relative = Utils::FilePath::fromString(semanticInfo.document->path()).pathAppended(text);
+ if (relative.exists()) {
+ link.targetFilePath = m_modelManager->fileToSource(relative);
processLinkCallback(link);
return;
}
@@ -813,7 +813,7 @@ void QmlJSEditorWidget::findLinkAt(const QTextCursor &cursor,
return processLinkCallback(Utils::Link());
Utils::Link link;
- link.targetFilePath = Utils::FilePath::fromString(fileName);
+ link.targetFilePath = m_modelManager->fileToSource(FilePath::fromString(fileName));
link.targetLine = line;
link.targetColumn = column - 1; // adjust the column
@@ -896,7 +896,8 @@ void QmlJSEditorWidget::contextMenuEvent(QContextMenuEvent *e)
if (ActionContainer *mcontext = ActionManager::actionContainer(Constants::M_CONTEXT)) {
QMenu *contextMenu = mcontext->menu();
- foreach (QAction *action, contextMenu->actions()) {
+ const QList<QAction *> actions = contextMenu->actions();
+ for (QAction *action : actions) {
menu->addAction(action);
if (action->objectName() == QLatin1String(Constants::M_REFACTORING_MENU_INSERTION_POINT))
menu->addMenu(refactoringMenu);
@@ -1021,11 +1022,8 @@ AssistInterface *QmlJSEditorWidget::createAssistInterface(
AssistReason reason) const
{
if (assistKind == Completion) {
- return new QmlJSCompletionAssistInterface(document(),
- position(),
- textDocument()->filePath(),
- reason,
- m_qmlJsEditorDocument->semanticInfo());
+ return new QmlJSCompletionAssistInterface(textCursor(), textDocument()->filePath(),
+ reason, m_qmlJsEditorDocument->semanticInfo());
} else if (assistKind == QuickFix) {
return new Internal::QmlJSQuickFixAssistInterface(const_cast<QmlJSEditorWidget *>(this), reason);
}
diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h
index bcb75a32238..03e0796fe0e 100644
--- a/src/plugins/qmljseditor/qmljseditor.h
+++ b/src/plugins/qmljseditor/qmljseditor.h
@@ -102,7 +102,7 @@ protected:
void applyFontSettings() override;
void createToolBar();
void findLinkAt(const QTextCursor &cursor,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool resolveTarget = true,
bool inNextSplit = false) override;
QString foldReplacementText(const QTextBlock &block) const override;
diff --git a/src/plugins/qmljseditor/qmljseditor_global.h b/src/plugins/qmljseditor/qmljseditor_global.h
index bd4a5139dcd..126b5119ffa 100644
--- a/src/plugins/qmljseditor/qmljseditor_global.h
+++ b/src/plugins/qmljseditor/qmljseditor_global.h
@@ -29,6 +29,8 @@
#if defined(QMLJSEDITOR_LIBRARY)
# define QMLJSEDITOR_EXPORT Q_DECL_EXPORT
+#elif defined(QMLJSEDITOR_STATIC_LIBRARY)
+# define QMLJSEDITOR_EXPORT
#else
# define QMLJSEDITOR_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp
index fea27341a25..8e6a466e8e0 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.cpp
+++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp
@@ -38,6 +38,8 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsreformatter.h>
#include <qmljstools/qmljstoolsconstants.h>
+#include <qmljstools/qmljstoolssettings.h>
+#include <qmljstools/qmljscodestylepreferences.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
@@ -274,7 +276,8 @@ void QmlJSEditorPluginPrivate::reformatFile()
TextEditor::TabSettings tabSettings = m_currentDocument->tabSettings();
const QString &newText = QmlJS::reformat(document,
tabSettings.m_indentSize,
- tabSettings.m_tabSize);
+ tabSettings.m_tabSize,
+ QmlJSTools::QmlJSToolsSettings::globalCodeStyle()->currentCodeStyleSettings().lineLength);
// QTextDocument::setPlainText cannot be used, as it would reset undo/redo history
const auto setNewText = [this, &newText]() {
@@ -286,10 +289,12 @@ void QmlJSEditorPluginPrivate::reformatFile()
IEditor *ed = EditorManager::currentEditor();
if (ed) {
+ QByteArray state = ed->saveState();
int line = ed->currentLine();
int column = ed->currentColumn();
setNewText();
- ed->gotoLine(line, column);
+ ed->gotoLine(line, column - 1);
+ ed->restoreState(state);
} else {
setNewText();
}
diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp
index 7c02a5da291..38717948ee6 100644
--- a/src/plugins/qmljseditor/qmljsfindreferences.cpp
+++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp
@@ -28,10 +28,11 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/searchresultwindow.h>
#include <coreplugin/icore.h>
-#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
+#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/basefilefind.h>
+#include <utils/algorithm.h>
#include <utils/filesearch.h>
#include <utils/runextensions.h>
@@ -260,7 +261,8 @@ private:
if (root && root->lookupMember(_name, _scopeChain.context()))
return check(root);
- foreach (const QmlComponentChain *parent, chain->instantiatingComponents()) {
+ const QList<const QmlComponentChain *> parents = chain->instantiatingComponents();
+ for (const QmlComponentChain *parent : parents) {
if (contains(parent))
return true;
}
@@ -278,7 +280,8 @@ private:
bool checkQmlScope()
{
- foreach (const ObjectValue *s, _scopeChain.qmlScopeObjects()) {
+ const QList<const ObjectValue *> scopes = _scopeChain.qmlScopeObjects();
+ for (const ObjectValue *s : scopes) {
if (check(s))
return true;
}
@@ -743,15 +746,16 @@ public:
future->waitForResume();
if (future->isCanceled())
return usages;
+ ModelManagerInterface *modelManager = ModelManagerInterface::instance();
Document::Ptr doc = context->snapshot().document(fileName);
if (!doc)
return usages;
// find all idenfifier expressions, try to resolve them and check if the result is in scope
FindUsages findUsages(doc, context);
- FindUsages::Result results = findUsages(name, scope);
- foreach (const SourceLocation &loc, results)
- usages.append(Usage(fileName, matchingLine(loc.offset, doc->source()), loc.startLine, loc.startColumn - 1, loc.length));
+ const FindUsages::Result results = findUsages(name, scope);
+ for (const SourceLocation &loc : results)
+ usages.append(Usage(modelManager->fileToSource(Utils::FilePath::fromString(fileName)).toString(), matchingLine(loc.offset, doc->source()), loc.startLine, loc.startColumn - 1, loc.length));
if (future->isPaused())
future->waitForResume();
return usages;
@@ -791,8 +795,8 @@ public:
// find all idenfifier expressions, try to resolve them and check if the result is in scope
FindTypeUsages findUsages(doc, context);
- FindTypeUsages::Result results = findUsages(name, scope);
- foreach (const SourceLocation &loc, results)
+ const FindTypeUsages::Result results = findUsages(name, scope);
+ for (const SourceLocation &loc : results)
usages.append(Usage(fileName, matchingLine(loc.offset, doc->source()), loc.startLine, loc.startColumn - 1, loc.length));
if (future->isPaused())
future->waitForResume();
@@ -815,7 +819,7 @@ public:
void operator()(QList<Usage> &, const QList<Usage> &usages)
{
- foreach (const Usage &u, usages)
+ for (const Usage &u : usages)
future->reportResult(u);
future->setProgressValue(future->progressValue() + 1);
@@ -892,10 +896,11 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
replacement = name;
QStringList files;
- foreach (const Document::Ptr &doc, snapshot) {
+ for (const Document::Ptr &doc : qAsConst(snapshot)) {
// ### skip files that don't contain the name token
- files.append(doc->fileName());
+ files.append(modelManager->fileToSource(Utils::FilePath::fromString(doc->fileName())).toString());
}
+ files = Utils::filteredUnique(files);
future.setProgressRange(0, files.size());
@@ -974,11 +979,23 @@ QList<FindReferences::Usage> FindReferences::findUsageOfType(const QString &file
QmlJS::Snapshot snapshot = modelManager->snapshot();
- foreach (const QmlJS::Document::Ptr &doc, snapshot) {
- FindTypeUsages findUsages(doc, context);
- FindTypeUsages::Result results = findUsages(typeName, targetValue);
- foreach (const SourceLocation &loc, results) {
- usages.append(Usage(doc->fileName(), matchingLine(loc.offset, doc->source()), loc.startLine, loc.startColumn - 1, loc.length));
+ QSet<QString> docDone;
+ for (const QmlJS::Document::Ptr &doc : qAsConst(snapshot)) {
+ QString sourceFile = modelManager->fileToSource(Utils::FilePath::fromString(doc->fileName())).toString();
+ if (docDone.contains(sourceFile))
+ continue;
+ docDone.insert(sourceFile);
+ QmlJS::Document::Ptr sourceDoc = doc;
+ if (sourceFile != doc->fileName())
+ sourceDoc = snapshot.document(sourceFile);
+ FindTypeUsages findUsages(sourceDoc, context);
+ const FindTypeUsages::Result results = findUsages(typeName, targetValue);
+ for (const SourceLocation &loc : results) {
+ usages.append(Usage(sourceFile,
+ matchingLine(loc.offset, doc->source()),
+ loc.startLine,
+ loc.startColumn - 1,
+ loc.length));
}
}
return usages;
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp
index d761c3e4cd7..085b6ce157b 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp
@@ -268,15 +268,17 @@ void QmlJSHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, R
bool QmlJSHoverHandler::matchDiagnosticMessage(QmlJSEditorWidget *qmlEditor, int pos)
{
- foreach (const QTextEdit::ExtraSelection &sel,
- qmlEditor->extraSelections(TextEditorWidget::CodeWarningsSelection)) {
+ const QList<QTextEdit::ExtraSelection> selections =
+ qmlEditor->extraSelections(TextEditorWidget::CodeWarningsSelection);
+ for (const QTextEdit::ExtraSelection &sel : selections) {
if (pos >= sel.cursor.selectionStart() && pos <= sel.cursor.selectionEnd()) {
setToolTip(sel.format.toolTip());
return true;
}
}
- foreach (const QTextLayout::FormatRange &range,
- qmlEditor->qmlJsEditorDocument()->diagnosticRanges()) {
+ const QVector<QTextLayout::FormatRange> ranges =
+ qmlEditor->qmlJsEditorDocument()->diagnosticRanges();
+ for (const QTextLayout::FormatRange &range : ranges) {
if (pos >= range.start && pos < range.start+range.length) {
setToolTip(range.format.toolTip());
return true;
@@ -357,7 +359,8 @@ void QmlJSHoverHandler::handleImport(const ScopeChain &scopeChain, AST::UiImport
if (!imports)
return;
- foreach (const Import &import, imports->all()) {
+ const QList<Import> importList = imports->all();
+ for (const Import &import : importList) {
if (import.info.ast() == node) {
if (import.info.type() == ImportType::Library
&& !import.libraryPath.isEmpty()) {
diff --git a/src/plugins/qmljseditor/qmljsquickfixassist.cpp b/src/plugins/qmljseditor/qmljsquickfixassist.cpp
index 15feed0cfd5..482bcc34aa8 100644
--- a/src/plugins/qmljseditor/qmljsquickfixassist.cpp
+++ b/src/plugins/qmljseditor/qmljsquickfixassist.cpp
@@ -48,8 +48,7 @@ using namespace Internal;
// -----------------------
QmlJSQuickFixAssistInterface::QmlJSQuickFixAssistInterface(QmlJSEditorWidget *editor,
AssistReason reason)
- : AssistInterface(editor->document(), editor->position(),
- editor->textDocument()->filePath(), reason)
+ : AssistInterface(editor->textCursor(), editor->textDocument()->filePath(), reason)
, m_semanticInfo(editor->qmlJsEditorDocument()->semanticInfo())
, m_currentFile(QmlJSRefactoringChanges::file(editor, m_semanticInfo.document))
{}
diff --git a/src/plugins/qmljseditor/qmljsquickfixassist.h b/src/plugins/qmljseditor/qmljsquickfixassist.h
index a5f39688eb8..1254f2510c0 100644
--- a/src/plugins/qmljseditor/qmljsquickfixassist.h
+++ b/src/plugins/qmljseditor/qmljsquickfixassist.h
@@ -45,6 +45,7 @@ public:
const QmlJSTools::SemanticInfo &semanticInfo() const;
QmlJSTools::QmlJSRefactoringFilePtr currentFile() const;
+ bool isBaseObject() const override { return false; }
private:
QmlJSTools::SemanticInfo m_semanticInfo;
diff --git a/src/plugins/qmljseditor/qmljsquickfixes.cpp b/src/plugins/qmljseditor/qmljsquickfixes.cpp
index d0f63d74ae0..9536738ac3e 100644
--- a/src/plugins/qmljseditor/qmljsquickfixes.cpp
+++ b/src/plugins/qmljseditor/qmljsquickfixes.cpp
@@ -154,7 +154,7 @@ void matchAddAnalysisMessageSuppressionCommentQuickFix(const QmlJSQuickFixInterf
{
const QList<StaticAnalysis::Message> &messages = interface->semanticInfo().staticAnalysisMessages;
- foreach (const StaticAnalysis::Message &message, messages) {
+ for (const StaticAnalysis::Message &message : messages) {
if (interface->currentFile()->isCursorOn(message.location)) {
result << new AnalysizeMessageSuppressionOperation(interface, message);
return;
diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp
index 8909c471e0e..bf0454a3d9c 100644
--- a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp
+++ b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp
@@ -59,7 +59,7 @@ namespace {
static bool isIdScope(const ObjectValue *scope, const QList<const QmlComponentChain *> &chain)
{
- foreach (const QmlComponentChain *c, chain) {
+ for (const QmlComponentChain *c : chain) {
if (c->idScope() == scope)
return true;
if (isIdScope(scope, c->instantiatingComponents()))
@@ -391,7 +391,7 @@ protected:
void addMessages(QList<DiagnosticMessage> messages,
const Document::Ptr &doc)
{
- foreach (const DiagnosticMessage &d, messages) {
+ for (const DiagnosticMessage &d : messages) {
int line = d.loc.startLine;
int column = qMax(1U, d.loc.startColumn);
int length = d.loc.length;
@@ -426,7 +426,7 @@ protected:
void addMessages(const QList<StaticAnalysis::Message> &messages,
const Document::Ptr &doc)
{
- foreach (const StaticAnalysis::Message &d, messages) {
+ for (const StaticAnalysis::Message &d : messages) {
int line = d.location.startLine;
int column = qMax(1U, d.location.startColumn);
int length = d.location.length;
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.cpp b/src/plugins/qmljseditor/qmloutlinemodel.cpp
index a62696b8abe..08d5a4d4c3c 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.cpp
+++ b/src/plugins/qmljseditor/qmloutlinemodel.cpp
@@ -400,7 +400,7 @@ bool QmlOutlineModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
stream >> rowPath;
QModelIndex index;
- foreach (int row, rowPath) {
+ for (int row : qAsConst(rowPath)) {
index = this->index(row, 0, index);
if (!index.isValid())
continue;
@@ -883,7 +883,7 @@ void QmlOutlineModel::reparentNodes(QmlOutlineItem *targetItem, int row, QList<Q
TextEditor::RefactoringFilePtr file = refactoring.file(
Utils::FilePath::fromString(m_semanticInfo.document->fileName()));
file->setChangeSet(changeSet);
- foreach (const Utils::ChangeSet::Range &range, changedRanges) {
+ for (const Utils::ChangeSet::Range &range : qAsConst(changedRanges)) {
file->appendIndentRange(range);
}
file->apply();
diff --git a/src/plugins/qmljseditor/qmltaskmanager.cpp b/src/plugins/qmljseditor/qmltaskmanager.cpp
index 366702f8016..1e84d8a671e 100644
--- a/src/plugins/qmljseditor/qmltaskmanager.cpp
+++ b/src/plugins/qmljseditor/qmltaskmanager.cpp
@@ -63,7 +63,7 @@ QmlTaskManager::QmlTaskManager()
static Tasks convertToTasks(const QList<DiagnosticMessage> &messages, const FilePath &fileName, Utils::Id category)
{
Tasks result;
- foreach (const DiagnosticMessage &msg, messages) {
+ for (const DiagnosticMessage &msg : messages) {
Task::TaskType type = msg.isError() ? Task::Error : Task::Warning;
Task task(type, msg.message, fileName, msg.loc.startLine, category);
result += task;
@@ -74,17 +74,18 @@ static Tasks convertToTasks(const QList<DiagnosticMessage> &messages, const File
static Tasks convertToTasks(const QList<StaticAnalysis::Message> &messages, const FilePath &fileName, Utils::Id category)
{
QList<DiagnosticMessage> diagnostics;
- foreach (const StaticAnalysis::Message &msg, messages)
+ for (const StaticAnalysis::Message &msg : messages)
diagnostics += msg.toDiagnosticMessage();
return convertToTasks(diagnostics, fileName, category);
}
-void QmlTaskManager::collectMessages(
- QFutureInterface<FileErrorMessages> &future,
- Snapshot snapshot, QList<ModelManagerInterface::ProjectInfo> projectInfos,
- ViewerContext vContext, bool updateSemantic)
+void QmlTaskManager::collectMessages(QFutureInterface<FileErrorMessages> &future,
+ Snapshot snapshot,
+ const QList<ModelManagerInterface::ProjectInfo> &projectInfos,
+ ViewerContext vContext,
+ bool updateSemantic)
{
- foreach (const ModelManagerInterface::ProjectInfo &info, projectInfos) {
+ for (const ModelManagerInterface::ProjectInfo &info : projectInfos) {
QHash<QString, QList<DiagnosticMessage> > linkMessages;
ContextPtr context;
if (updateSemantic) {
@@ -92,7 +93,7 @@ void QmlTaskManager::collectMessages(
context = link(&linkMessages);
}
- foreach (const QString &fileName, info.sourceFiles) {
+ for (const QString &fileName : qAsConst(info.sourceFiles)) {
Document::Ptr document = snapshot.document(fileName);
if (!document)
continue;
@@ -157,15 +158,15 @@ void QmlTaskManager::updateMessagesNow(bool updateSemantic)
void QmlTaskManager::documentsRemoved(const QStringList &path)
{
- foreach (const QString &item, path)
+ for (const QString &item : path)
removeTasksForFile(item);
}
void QmlTaskManager::displayResults(int begin, int end)
{
for (int i = begin; i < end; ++i) {
- FileErrorMessages result = m_messageCollector.resultAt(i);
- foreach (const Task &task, result.tasks) {
+ const ProjectExplorer::Tasks tasks = m_messageCollector.resultAt(i).tasks;
+ for (const Task &task : tasks) {
insertTask(task);
}
}
@@ -189,7 +190,7 @@ void QmlTaskManager::removeTasksForFile(const QString &fileName)
{
if (m_docsWithTasks.contains(fileName)) {
const Tasks tasks = m_docsWithTasks.value(fileName);
- foreach (const Task &task, tasks)
+ for (const Task &task : tasks)
TaskHub::removeTask(task);
m_docsWithTasks.remove(fileName);
}
diff --git a/src/plugins/qmljseditor/qmltaskmanager.h b/src/plugins/qmljseditor/qmltaskmanager.h
index dfc8174ba12..692f74f3c41 100644
--- a/src/plugins/qmljseditor/qmltaskmanager.h
+++ b/src/plugins/qmljseditor/qmltaskmanager.h
@@ -69,7 +69,7 @@ private:
};
static void collectMessages(QFutureInterface<FileErrorMessages> &future,
QmlJS::Snapshot snapshot,
- QList<QmlJS::ModelManagerInterface::ProjectInfo> projectInfos,
+ const QList<QmlJS::ModelManagerInterface::ProjectInfo> &projectInfos,
QmlJS::ViewerContext vContext,
bool updateSemantic);
diff --git a/src/plugins/qmljseditor/quicktoolbar.cpp b/src/plugins/qmljseditor/quicktoolbar.cpp
index 15dec5a80c5..5318c8d51ac 100644
--- a/src/plugins/qmljseditor/quicktoolbar.cpp
+++ b/src/plugins/qmljseditor/quicktoolbar.cpp
@@ -129,20 +129,20 @@ void QuickToolBar::apply(TextEditor::TextEditorWidget *editorWidget, Document::P
if (scopeChain && scopeObject) {
m_prototypes.clear();
- foreach (const ObjectValue *object,
- PrototypeIterator(scopeObject, scopeChain->context()).all()) {
+ const QList<const ObjectValue *> objects
+ = PrototypeIterator(scopeObject, scopeChain->context()).all();
+ for (const ObjectValue *object : objects)
m_prototypes.append(object->className());
- }
if (m_prototypes.contains(QLatin1String("PropertyChanges"))) {
isPropertyChanges = true;
const ObjectValue *targetObject = getPropertyChangesTarget(node, *scopeChain);
m_prototypes.clear();
if (targetObject) {
- foreach (const ObjectValue *object,
- PrototypeIterator(targetObject, scopeChain->context()).all()) {
+ const QList<const ObjectValue *> objects
+ = PrototypeIterator(targetObject, scopeChain->context()).all();
+ for (const ObjectValue *object : objects)
m_prototypes.append(object->className());
- }
}
}
}
diff --git a/src/plugins/qmljstools/CMakeLists.txt b/src/plugins/qmljstools/CMakeLists.txt
index 329f5dbce09..f0c3d6792d3 100644
--- a/src/plugins/qmljstools/CMakeLists.txt
+++ b/src/plugins/qmljstools/CMakeLists.txt
@@ -5,6 +5,10 @@ add_qtc_plugin(QmlJSTools
SOURCES
qmljsbundleprovider.cpp qmljsbundleprovider.h
qmljscodestylepreferencesfactory.cpp qmljscodestylepreferencesfactory.h
+ qmljscodestylepreferences.cpp qmljscodestylepreferences.h
+ qmljscodestylepreferenceswidget.cpp qmljscodestylepreferenceswidget.h
+ qmljscodestylesettings.cpp qmljscodestylesettings.h
+ qmljscodestylesettingswidget.cpp qmljscodestylesettingswidget.h qmljscodestylesettingswidget.ui
qmljscodestylesettingspage.cpp qmljscodestylesettingspage.h qmljscodestylesettingspage.ui
qmljsfunctionfilter.cpp qmljsfunctionfilter.h
qmljsindenter.cpp qmljsindenter.h
diff --git a/src/plugins/qmljstools/qmljscodestylepreferences.cpp b/src/plugins/qmljstools/qmljscodestylepreferences.cpp
new file mode 100644
index 00000000000..191b8139f19
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylepreferences.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmljscodestylepreferences.h"
+
+namespace QmlJSTools {
+
+QmlJSCodeStylePreferences::QmlJSCodeStylePreferences(QObject *parent) :
+ ICodeStylePreferences(parent)
+{
+ setSettingsSuffix("CodeStyleSettings");
+
+ connect(this, &QmlJSCodeStylePreferences::currentValueChanged,
+ this, &QmlJSCodeStylePreferences::slotCurrentValueChanged);
+}
+
+QVariant QmlJSCodeStylePreferences::value() const
+{
+ QVariant v;
+ v.setValue(codeStyleSettings());
+ return v;
+}
+
+void QmlJSCodeStylePreferences::setValue(const QVariant &data)
+{
+ if (!data.canConvert<QmlJSCodeStyleSettings>())
+ return;
+
+ setCodeStyleSettings(data.value<QmlJSCodeStyleSettings>());
+}
+
+QmlJSCodeStyleSettings QmlJSCodeStylePreferences::codeStyleSettings() const
+{
+ return m_data;
+}
+
+void QmlJSCodeStylePreferences::setCodeStyleSettings(const QmlJSCodeStyleSettings &data)
+{
+ if (m_data == data)
+ return;
+
+ m_data = data;
+
+ QVariant v;
+ v.setValue(data);
+ emit valueChanged(v);
+ emit codeStyleSettingsChanged(m_data);
+ if (!currentDelegate())
+ emit currentValueChanged(v);
+}
+
+QmlJSCodeStyleSettings QmlJSCodeStylePreferences::currentCodeStyleSettings() const
+{
+ QVariant v = currentValue();
+ if (!v.canConvert<QmlJSCodeStyleSettings>()) {
+ // warning
+ return {};
+ }
+ return v.value<QmlJSCodeStyleSettings>();
+}
+
+void QmlJSCodeStylePreferences::slotCurrentValueChanged(const QVariant &value)
+{
+ if (!value.canConvert<QmlJSCodeStyleSettings>())
+ return;
+
+ emit currentCodeStyleSettingsChanged(value.value<QmlJSCodeStyleSettings>());
+}
+
+QVariantMap QmlJSCodeStylePreferences::toMap() const
+{
+ QVariantMap map = ICodeStylePreferences::toMap();
+ if (!currentDelegate()) {
+ const QVariantMap dataMap = m_data.toMap();
+ for (auto it = dataMap.begin(), end = dataMap.end(); it != end; ++it)
+ map.insert(it.key(), it.value());
+ }
+ return map;
+}
+
+void QmlJSCodeStylePreferences::fromMap(const QVariantMap &map)
+{
+ ICodeStylePreferences::fromMap(map);
+ if (!currentDelegate())
+ m_data.fromMap(map);
+}
+
+} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljscodestylepreferences.h b/src/plugins/qmljstools/qmljscodestylepreferences.h
new file mode 100644
index 00000000000..3f3b75475de
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylepreferences.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "qmljstools_global.h"
+
+#include "qmljscodestylesettings.h"
+
+#include <texteditor/icodestylepreferences.h>
+
+namespace QmlJSTools {
+
+class QMLJSTOOLS_EXPORT QmlJSCodeStylePreferences : public TextEditor::ICodeStylePreferences
+{
+ Q_OBJECT
+public:
+ explicit QmlJSCodeStylePreferences(QObject *parent = nullptr);
+
+ QVariant value() const override;
+ void setValue(const QVariant &) override;
+
+ QmlJSCodeStyleSettings codeStyleSettings() const;
+
+ // tracks parent hierarchy until currentParentSettings is null
+ QmlJSCodeStyleSettings currentCodeStyleSettings() const;
+
+ QVariantMap toMap() const override;
+ void fromMap(const QVariantMap &map) override;
+
+public slots:
+ void setCodeStyleSettings(const QmlJSCodeStyleSettings &data);
+
+signals:
+ void codeStyleSettingsChanged(const QmlJSCodeStyleSettings &);
+ void currentCodeStyleSettingsChanged(const QmlJSCodeStyleSettings &);
+
+private:
+ void slotCurrentValueChanged(const QVariant &);
+
+ QmlJSCodeStyleSettings m_data;
+};
+
+} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljscodestylepreferencesfactory.cpp b/src/plugins/qmljstools/qmljscodestylepreferencesfactory.cpp
index 7b280e6e4f0..d774bcad2ce 100644
--- a/src/plugins/qmljstools/qmljscodestylepreferencesfactory.cpp
+++ b/src/plugins/qmljstools/qmljscodestylepreferencesfactory.cpp
@@ -24,11 +24,12 @@
****************************************************************************/
#include "qmljscodestylepreferencesfactory.h"
+
+#include "qmljscodestylepreferences.h"
#include "qmljscodestylesettingspage.h"
-#include "qmljstoolsconstants.h"
#include "qmljsindenter.h"
+#include "qmljstoolsconstants.h"
-#include <texteditor/simplecodestylepreferences.h>
#include <qmljseditor/qmljseditorconstants.h>
@@ -68,18 +69,21 @@ QString QmlJSCodeStylePreferencesFactory::displayName()
TextEditor::ICodeStylePreferences *QmlJSCodeStylePreferencesFactory::createCodeStyle() const
{
- return new TextEditor::SimpleCodeStylePreferences();
+ return new QmlJSCodeStylePreferences();
}
-QWidget *QmlJSCodeStylePreferencesFactory::createEditor(
+TextEditor::CodeStyleEditorWidget *QmlJSCodeStylePreferencesFactory::createEditor(
TextEditor::ICodeStylePreferences *preferences,
ProjectExplorer::Project *project,
QWidget *parent) const
{
Q_UNUSED(project)
+ auto qmlJSPreferences = qobject_cast<QmlJSCodeStylePreferences *>(preferences);
+ if (!qmlJSPreferences)
+ return nullptr;
auto widget = new Internal::QmlJSCodeStylePreferencesWidget(parent);
widget->layout()->setContentsMargins(0, 0, 0, 0);
- widget->setPreferences(preferences);
+ widget->setPreferences(qmlJSPreferences);
return widget;
}
diff --git a/src/plugins/qmljstools/qmljscodestylepreferencesfactory.h b/src/plugins/qmljstools/qmljscodestylepreferencesfactory.h
index eee110704a9..3625a2474fa 100644
--- a/src/plugins/qmljstools/qmljscodestylepreferencesfactory.h
+++ b/src/plugins/qmljstools/qmljscodestylepreferencesfactory.h
@@ -37,9 +37,9 @@ public:
Utils::Id languageId() override;
QString displayName() override;
TextEditor::ICodeStylePreferences *createCodeStyle() const override;
- QWidget *createEditor(TextEditor::ICodeStylePreferences *settings,
- ProjectExplorer::Project *project,
- QWidget *parent) const override;
+ TextEditor::CodeStyleEditorWidget *createEditor(TextEditor::ICodeStylePreferences *settings,
+ ProjectExplorer::Project *project,
+ QWidget *parent) const override;
TextEditor::Indenter *createIndenter(QTextDocument *doc) const override;
QString snippetProviderGroupId() const override;
QString previewText() const override;
diff --git a/src/plugins/qmljstools/qmljscodestylepreferenceswidget.cpp b/src/plugins/qmljstools/qmljscodestylepreferenceswidget.cpp
new file mode 100644
index 00000000000..c7fac08af69
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylepreferenceswidget.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmljscodestylepreferenceswidget.h"
+
+#include "qmljscodestylepreferences.h"
+#include "qmljscodestylesettings.h"
+#include "qmljscodestylesettingswidget.h"
+
+#include <QLabel>
+#include <QVBoxLayout>
+
+namespace QmlJSTools {
+
+QmlJSCodeStylePreferencesWidget::QmlJSCodeStylePreferencesWidget(QWidget *parent) :
+ QWidget(parent)
+{
+ m_codeStyleSettingsWidget = new QmlJSCodeStyleSettingsWidget(this);
+ auto layout = new QVBoxLayout(this);
+ layout->addWidget(m_codeStyleSettingsWidget);
+ layout->setContentsMargins(QMargins());
+ m_codeStyleSettingsWidget->setEnabled(false);
+}
+
+void QmlJSCodeStylePreferencesWidget::setPreferences(QmlJSCodeStylePreferences *preferences)
+{
+ if (m_preferences == preferences)
+ return; // nothing changes
+
+ // cleanup old
+ if (m_preferences) {
+ disconnect(m_preferences, &QmlJSCodeStylePreferences::currentCodeStyleSettingsChanged,
+ m_codeStyleSettingsWidget, &QmlJSCodeStyleSettingsWidget::setCodeStyleSettings);
+ disconnect(m_preferences, &QmlJSCodeStylePreferences::currentPreferencesChanged,
+ this, &QmlJSCodeStylePreferencesWidget::slotCurrentPreferencesChanged);
+ disconnect(m_codeStyleSettingsWidget, &QmlJSCodeStyleSettingsWidget::settingsChanged,
+ this, &QmlJSCodeStylePreferencesWidget::slotSettingsChanged);
+ }
+ m_preferences = preferences;
+ // fillup new
+ if (m_preferences) {
+ slotCurrentPreferencesChanged(m_preferences->currentPreferences());
+
+ m_codeStyleSettingsWidget->setCodeStyleSettings(m_preferences->currentCodeStyleSettings());
+
+ connect(m_preferences, &QmlJSCodeStylePreferences::currentCodeStyleSettingsChanged,
+ m_codeStyleSettingsWidget, &QmlJSCodeStyleSettingsWidget::setCodeStyleSettings);
+ connect(m_preferences, &QmlJSCodeStylePreferences::currentPreferencesChanged,
+ this, &QmlJSCodeStylePreferencesWidget::slotCurrentPreferencesChanged);
+ connect(m_codeStyleSettingsWidget, &QmlJSCodeStyleSettingsWidget::settingsChanged,
+ this, &QmlJSCodeStylePreferencesWidget::slotSettingsChanged);
+ }
+ m_codeStyleSettingsWidget->setEnabled(m_preferences);
+}
+
+void QmlJSCodeStylePreferencesWidget::slotCurrentPreferencesChanged(TextEditor::ICodeStylePreferences *preferences)
+{
+ m_codeStyleSettingsWidget->setEnabled(!preferences->isReadOnly() && !m_preferences->currentDelegate());
+}
+
+void QmlJSCodeStylePreferencesWidget::slotSettingsChanged(const QmlJSCodeStyleSettings &settings)
+{
+ if (!m_preferences)
+ return;
+
+ QmlJSCodeStylePreferences *current = qobject_cast<QmlJSCodeStylePreferences*>(m_preferences->currentPreferences());
+ if (!current)
+ return;
+
+ current->setCodeStyleSettings(settings);
+}
+
+} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljscodestylepreferenceswidget.h b/src/plugins/qmljstools/qmljscodestylepreferenceswidget.h
new file mode 100644
index 00000000000..12861bda5ee
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylepreferenceswidget.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "qmljstools_global.h"
+
+#include <QWidget>
+
+namespace TextEditor {
+class ICodeStylePreferences;
+}
+
+namespace QmlJSTools {
+class QmlJSCodeStyleSettings;
+class QmlJSCodeStyleSettingsWidget;
+class QmlJSCodeStylePreferences;
+
+class QMLJSTOOLS_EXPORT QmlJSCodeStylePreferencesWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit QmlJSCodeStylePreferencesWidget(QWidget *parent = nullptr);
+
+ void setPreferences(QmlJSCodeStylePreferences *tabPreferences);
+
+private:
+ void slotCurrentPreferencesChanged(TextEditor::ICodeStylePreferences* preferences);
+ void slotSettingsChanged(const QmlJSCodeStyleSettings &settings);
+
+ QmlJSCodeStyleSettingsWidget *m_codeStyleSettingsWidget;
+ QmlJSCodeStylePreferences *m_preferences = nullptr;
+};
+
+} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljscodestylesettings.cpp b/src/plugins/qmljstools/qmljscodestylesettings.cpp
new file mode 100644
index 00000000000..75e09b7b42c
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylesettings.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmljscodestylesettings.h"
+
+#include "qmljscodestylepreferences.h"
+#include "qmljstoolssettings.h"
+
+#include <projectexplorer/editorconfiguration.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projecttree.h>
+
+#include <texteditor/tabsettings.h>
+
+#include <cplusplus/Overview.h>
+
+#include <utils/qtcassert.h>
+#include <utils/settingsutils.h>
+
+static const char lineLengthKey[] = "LineLength";
+
+namespace QmlJSTools {
+
+// ------------------ QmlJSCodeStyleSettingsWidget
+
+QmlJSCodeStyleSettings::QmlJSCodeStyleSettings() = default;
+
+QVariantMap QmlJSCodeStyleSettings::toMap() const
+{
+ return {
+ {lineLengthKey, lineLength}
+ };
+}
+
+void QmlJSCodeStyleSettings::fromMap(const QVariantMap &map)
+{
+ lineLength = map.value(lineLengthKey, lineLength).toInt();
+}
+
+bool QmlJSCodeStyleSettings::equals(const QmlJSCodeStyleSettings &rhs) const
+{
+ return lineLength == rhs.lineLength;
+}
+
+QmlJSCodeStyleSettings QmlJSCodeStyleSettings::currentGlobalCodeStyle()
+{
+ QmlJSCodeStylePreferences *QmlJSCodeStylePreferences = QmlJSToolsSettings::globalCodeStyle();
+ QTC_ASSERT(QmlJSCodeStylePreferences, return QmlJSCodeStyleSettings());
+
+ return QmlJSCodeStylePreferences->currentCodeStyleSettings();
+}
+
+TextEditor::TabSettings QmlJSCodeStyleSettings::currentGlobalTabSettings()
+{
+ QmlJSCodeStylePreferences *QmlJSCodeStylePreferences = QmlJSToolsSettings::globalCodeStyle();
+ QTC_ASSERT(QmlJSCodeStylePreferences, return TextEditor::TabSettings());
+
+ return QmlJSCodeStylePreferences->currentTabSettings();
+}
+
+} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljscodestylesettings.h b/src/plugins/qmljstools/qmljscodestylesettings.h
new file mode 100644
index 00000000000..35d87519bc8
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylesettings.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "qmljstools_global.h"
+
+#include <utils/optional.h>
+
+#include <QVariantMap>
+
+namespace TextEditor { class TabSettings; }
+
+namespace QmlJSTools {
+
+class QMLJSTOOLS_EXPORT QmlJSCodeStyleSettings
+{
+public:
+ QmlJSCodeStyleSettings();
+
+ int lineLength = 80;
+
+ QVariantMap toMap() const;
+ void fromMap(const QVariantMap &map);
+
+ bool equals(const QmlJSCodeStyleSettings &rhs) const;
+ bool operator==(const QmlJSCodeStyleSettings &s) const { return equals(s); }
+ bool operator!=(const QmlJSCodeStyleSettings &s) const { return !equals(s); }
+
+ static QmlJSCodeStyleSettings currentGlobalCodeStyle();
+ static TextEditor::TabSettings currentGlobalTabSettings();
+};
+
+} // namespace CppEditor
+
+Q_DECLARE_METATYPE(QmlJSTools::QmlJSCodeStyleSettings)
diff --git a/src/plugins/qmljstools/qmljscodestylesettingspage.cpp b/src/plugins/qmljstools/qmljscodestylesettingspage.cpp
index f99f98f1b36..9113d0f559b 100644
--- a/src/plugins/qmljstools/qmljscodestylesettingspage.cpp
+++ b/src/plugins/qmljstools/qmljscodestylesettingspage.cpp
@@ -24,22 +24,23 @@
****************************************************************************/
#include "qmljscodestylesettingspage.h"
-#include "ui_qmljscodestylesettingspage.h"
-#include "qmljstoolsconstants.h"
-#include "qmljstoolssettings.h"
+
+#include "qmljscodestylepreferences.h"
#include "qmljsindenter.h"
#include "qmljsqtstylecodeformatter.h"
+#include "qmljstoolsconstants.h"
+#include "qmljstoolssettings.h"
+#include "ui_qmljscodestylesettingspage.h"
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+#include <qmljseditor/qmljseditorconstants.h>
+#include <texteditor/codestyleeditor.h>
+#include <texteditor/displaysettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/snippets/snippetprovider.h>
#include <texteditor/tabsettings.h>
-#include <texteditor/simplecodestylepreferences.h>
-#include <texteditor/displaysettings.h>
#include <texteditor/texteditorsettings.h>
-#include <texteditor/codestyleeditor.h>
-#include <extensionsystem/pluginmanager.h>
-#include <qmljseditor/qmljseditorconstants.h>
-#include <coreplugin/icore.h>
#include <QTextStream>
@@ -51,7 +52,7 @@ namespace Internal {
// ------------------ CppCodeStyleSettingsWidget
QmlJSCodeStylePreferencesWidget::QmlJSCodeStylePreferencesWidget(QWidget *parent) :
- QWidget(parent),
+ TextEditor::CodeStyleEditorWidget(parent),
m_ui(new Ui::QmlJSCodeStyleSettingsPage)
{
m_ui->setupUi(this);
@@ -70,13 +71,18 @@ QmlJSCodeStylePreferencesWidget::~QmlJSCodeStylePreferencesWidget()
delete m_ui;
}
-void QmlJSCodeStylePreferencesWidget::setPreferences(ICodeStylePreferences *preferences)
+void QmlJSCodeStylePreferencesWidget::setPreferences(QmlJSCodeStylePreferences *preferences)
{
m_preferences = preferences;
m_ui->tabPreferencesWidget->setPreferences(preferences);
+ m_ui->codeStylePreferencesWidget->setPreferences(preferences);
if (m_preferences)
+ {
connect(m_preferences, &ICodeStylePreferences::currentTabSettingsChanged,
this, &QmlJSCodeStylePreferencesWidget::slotSettingsChanged);
+ connect(m_preferences, &QmlJSCodeStylePreferences::currentCodeStyleSettingsChanged,
+ this, &QmlJSCodeStylePreferencesWidget::slotSettingsChanged);
+ }
updatePreview();
}
@@ -134,15 +140,16 @@ QmlJSCodeStyleSettingsPage::QmlJSCodeStyleSettingsPage()
QWidget *QmlJSCodeStyleSettingsPage::widget()
{
if (!m_widget) {
- SimpleCodeStylePreferences *originalTabPreferences
+ QmlJSCodeStylePreferences *originalPreferences
= QmlJSToolsSettings::globalCodeStyle();
- m_pageTabPreferences = new SimpleCodeStylePreferences(m_widget);
- m_pageTabPreferences->setDelegatingPool(originalTabPreferences->delegatingPool());
- m_pageTabPreferences->setTabSettings(originalTabPreferences->tabSettings());
- m_pageTabPreferences->setCurrentDelegate(originalTabPreferences->currentDelegate());
- m_pageTabPreferences->setId(originalTabPreferences->id());
+ m_preferences = new QmlJSCodeStylePreferences(m_widget);
+ m_preferences->setDelegatingPool(originalPreferences->delegatingPool());
+ m_preferences->setCodeStyleSettings(originalPreferences->codeStyleSettings());
+ m_preferences->setTabSettings(originalPreferences->tabSettings());
+ m_preferences->setCurrentDelegate(originalPreferences->currentDelegate());
+ m_preferences->setId(originalPreferences->id());
m_widget = new CodeStyleEditor(TextEditorSettings::codeStyleFactory(QmlJSTools::Constants::QML_JS_SETTINGS_ID),
- m_pageTabPreferences);
+ m_preferences);
}
return m_widget;
}
@@ -152,14 +159,18 @@ void QmlJSCodeStyleSettingsPage::apply()
if (m_widget) {
QSettings *s = Core::ICore::settings();
- SimpleCodeStylePreferences *originalTabPreferences = QmlJSToolsSettings::globalCodeStyle();
- if (originalTabPreferences->tabSettings() != m_pageTabPreferences->tabSettings()) {
- originalTabPreferences->setTabSettings(m_pageTabPreferences->tabSettings());
- originalTabPreferences->toSettings(QLatin1String(QmlJSTools::Constants::QML_JS_SETTINGS_ID), s);
+ QmlJSCodeStylePreferences *originalPreferences = QmlJSToolsSettings::globalCodeStyle();
+ if (originalPreferences->codeStyleSettings() != m_preferences->codeStyleSettings()) {
+ originalPreferences->setCodeStyleSettings(m_preferences->codeStyleSettings());
+ originalPreferences->toSettings(QLatin1String(QmlJSTools::Constants::QML_JS_SETTINGS_ID), s);
+ }
+ if (originalPreferences->tabSettings() != m_preferences->tabSettings()) {
+ originalPreferences->setTabSettings(m_preferences->tabSettings());
+ originalPreferences->toSettings(QLatin1String(QmlJSTools::Constants::QML_JS_SETTINGS_ID), s);
}
- if (originalTabPreferences->currentDelegate() != m_pageTabPreferences->currentDelegate()) {
- originalTabPreferences->setCurrentDelegate(m_pageTabPreferences->currentDelegate());
- originalTabPreferences->toSettings(QLatin1String(QmlJSTools::Constants::QML_JS_SETTINGS_ID), s);
+ if (originalPreferences->currentDelegate() != m_preferences->currentDelegate()) {
+ originalPreferences->setCurrentDelegate(m_preferences->currentDelegate());
+ originalPreferences->toSettings(QLatin1String(QmlJSTools::Constants::QML_JS_SETTINGS_ID), s);
}
}
}
diff --git a/src/plugins/qmljstools/qmljscodestylesettingspage.h b/src/plugins/qmljstools/qmljscodestylesettingspage.h
index f260ecdcfda..64a8f45173e 100644
--- a/src/plugins/qmljstools/qmljscodestylesettingspage.h
+++ b/src/plugins/qmljstools/qmljscodestylesettingspage.h
@@ -26,6 +26,8 @@
#pragma once
#include <coreplugin/dialogs/ioptionspage.h>
+#include <texteditor/icodestylepreferencesfactory.h>
+
#include <QWidget>
#include <QPointer>
@@ -35,17 +37,18 @@ QT_END_NAMESPACE
namespace TextEditor {
class FontSettings;
- class TabSettings;
class CodeStyleEditor;
- class ICodeStylePreferences;
}
namespace QmlJSTools {
+class QmlJSCodeStylePreferences;
+class QmlJSCodeStyleSettings;
+
namespace Internal {
namespace Ui { class QmlJSCodeStyleSettingsPage; }
-class QmlJSCodeStylePreferencesWidget : public QWidget
+class QmlJSCodeStylePreferencesWidget : public TextEditor::CodeStyleEditorWidget
{
Q_OBJECT
@@ -53,7 +56,7 @@ public:
explicit QmlJSCodeStylePreferencesWidget(QWidget *parent = nullptr);
~QmlJSCodeStylePreferencesWidget() override;
- void setPreferences(TextEditor::ICodeStylePreferences *preferences);
+ void setPreferences(QmlJSCodeStylePreferences* preferences);
private:
void decorateEditor(const TextEditor::FontSettings &fontSettings);
@@ -61,7 +64,7 @@ private:
void slotSettingsChanged();
void updatePreview();
- TextEditor::ICodeStylePreferences *m_preferences = nullptr;
+ QmlJSCodeStylePreferences *m_preferences = nullptr;
Ui::QmlJSCodeStyleSettingsPage *m_ui;
};
@@ -76,7 +79,7 @@ public:
void finish() override;
private:
- TextEditor::ICodeStylePreferences *m_pageTabPreferences = nullptr;
+ QmlJSCodeStylePreferences *m_preferences = nullptr;
QPointer<TextEditor::CodeStyleEditor> m_widget;
};
diff --git a/src/plugins/qmljstools/qmljscodestylesettingspage.ui b/src/plugins/qmljstools/qmljscodestylesettingspage.ui
index beabf9cbe6e..acb034c71fd 100644
--- a/src/plugins/qmljstools/qmljscodestylesettingspage.ui
+++ b/src/plugins/qmljstools/qmljscodestylesettingspage.ui
@@ -24,7 +24,20 @@
</property>
</widget>
</item>
- <item row="0" column="1" rowspan="2">
+ <item row="2" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>267</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1" rowspan="3">
<widget class="TextEditor::SnippetEditorWidget" name="previewTextEdit">
<property name="plainText">
<string notr="true">import QtQuick 1.0
@@ -48,17 +61,7 @@ Rectangle {
</widget>
</item>
<item row="1" column="0">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>267</height>
- </size>
- </property>
- </spacer>
+ <widget class="QmlJSTools::QmlJSCodeStylePreferencesWidget" name="codeStylePreferencesWidget" native="true"/>
</item>
</layout>
</widget>
@@ -74,6 +77,12 @@ Rectangle {
<extends>QPlainTextEdit</extends>
<header location="global">texteditor/snippets/snippeteditor.h</header>
</customwidget>
+ <customwidget>
+ <class>QmlJSTools::QmlJSCodeStylePreferencesWidget</class>
+ <extends>QWidget</extends>
+ <header location="global">qmljstools/qmljscodestylepreferenceswidget.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/src/plugins/qmljstools/qmljscodestylesettingswidget.cpp b/src/plugins/qmljstools/qmljscodestylesettingswidget.cpp
new file mode 100644
index 00000000000..7cb7eb2dc50
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylesettingswidget.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmljscodestylesettingswidget.h"
+
+#include "qmljscodestylesettings.h"
+#include "ui_qmljscodestylesettingswidget.h"
+
+#include <QTextStream>
+
+namespace QmlJSTools {
+
+QmlJSCodeStyleSettingsWidget::QmlJSCodeStyleSettingsWidget(QWidget *parent) :
+ QGroupBox(parent),
+ ui(new Internal::Ui::QmlJSCodeStyleSettingsWidget)
+{
+ ui->setupUi(this);
+
+ auto spinValueChanged = QOverload<int>::of(&QSpinBox::valueChanged);
+ connect(ui->lineLengthSpinBox, spinValueChanged,
+ this, &QmlJSCodeStyleSettingsWidget::slotSettingsChanged);
+}
+
+QmlJSCodeStyleSettingsWidget::~QmlJSCodeStyleSettingsWidget()
+{
+ delete ui;
+}
+
+void QmlJSCodeStyleSettingsWidget::setCodeStyleSettings(const QmlJSCodeStyleSettings& s)
+{
+ QSignalBlocker blocker(this);
+ ui->lineLengthSpinBox->setValue(s.lineLength);
+}
+
+QmlJSCodeStyleSettings QmlJSCodeStyleSettingsWidget::codeStyleSettings() const
+{
+ QmlJSCodeStyleSettings set;
+
+ set.lineLength = ui->lineLengthSpinBox->value();
+
+ return set;
+}
+
+void QmlJSCodeStyleSettingsWidget::slotSettingsChanged()
+{
+ emit settingsChanged(codeStyleSettings());
+}
+
+} // namespace TextEditor
diff --git a/src/plugins/qmljstools/qmljscodestylesettingswidget.h b/src/plugins/qmljstools/qmljscodestylesettingswidget.h
new file mode 100644
index 00000000000..ece704fbf3b
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylesettingswidget.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "qmljstools_global.h"
+
+#include <QGroupBox>
+
+namespace QmlJSTools {
+class QmlJSCodeStyleSettings;
+
+namespace Internal { namespace Ui { class QmlJSCodeStyleSettingsWidget; } }
+
+
+class QMLJSTOOLS_EXPORT QmlJSCodeStyleSettingsWidget : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ enum CodingStyleLink {
+ CppLink,
+ QtQuickLink
+ };
+
+ explicit QmlJSCodeStyleSettingsWidget(QWidget *parent = nullptr);
+ ~QmlJSCodeStyleSettingsWidget() override;
+
+ QmlJSCodeStyleSettings codeStyleSettings() const;
+
+ void setCodingStyleWarningVisible(bool visible);
+ void setCodeStyleSettings(const QmlJSCodeStyleSettings& s);
+
+signals:
+ void settingsChanged(const QmlJSCodeStyleSettings &);
+
+private:
+ void slotSettingsChanged();
+ void codingStyleLinkActivated(const QString &linkString);
+
+ Internal::Ui::QmlJSCodeStyleSettingsWidget *ui;
+};
+
+} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljscodestylesettingswidget.ui b/src/plugins/qmljstools/qmljscodestylesettingswidget.ui
new file mode 100644
index 00000000000..a8756925ed6
--- /dev/null
+++ b/src/plugins/qmljstools/qmljscodestylesettingswidget.ui
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QmlJSTools::Internal::QmlJSCodeStyleSettingsWidget</class>
+ <widget class="QGroupBox" name="QmlJSTools::Internal::QmlJSCodeStyleSettingsWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>254</width>
+ <height>203</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string notr="true"/>
+ </property>
+ <property name="title">
+ <string>Qml JS Code Style</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="lineLengthLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Line length:</string>
+ </property>
+ <property name="buddy">
+ <cstring>lineLengthSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="lineLengthSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>999</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>lineLengthSpinBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qmljstools/qmljsindenter.cpp b/src/plugins/qmljstools/qmljsindenter.cpp
index ce6f18eca90..e46891cc26f 100644
--- a/src/plugins/qmljstools/qmljsindenter.cpp
+++ b/src/plugins/qmljstools/qmljsindenter.cpp
@@ -99,7 +99,7 @@ TextEditor::IndentationForBlock Indenter::indentationForBlocks(
codeFormatter.updateStateUntil(blocks.last());
TextEditor::IndentationForBlock ret;
- foreach (QTextBlock block, blocks)
+ for (QTextBlock block : blocks)
ret.insert(block.blockNumber(), codeFormatter.indentFor(block));
return ret;
}
diff --git a/src/plugins/qmljstools/qmljslocatordata.cpp b/src/plugins/qmljstools/qmljslocatordata.cpp
index 92611a99a64..9f135b0383b 100644
--- a/src/plugins/qmljstools/qmljslocatordata.cpp
+++ b/src/plugins/qmljstools/qmljslocatordata.cpp
@@ -252,7 +252,7 @@ void LocatorData::onDocumentUpdated(const Document::Ptr &doc)
void LocatorData::onAboutToRemoveFiles(const QStringList &files)
{
QMutexLocker l(&m_mutex);
- foreach (const QString &file, files) {
+ for (const QString &file : files) {
m_entries.remove(file);
}
}
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
index 5d60d88b974..941494699ef 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -55,7 +55,7 @@
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <QDir>
#include <QFile>
@@ -92,10 +92,11 @@ static void setupProjectInfoQmlBundles(ModelManagerInterface::ProjectInfo &proje
if (projectInfo.project) {
QSet<Kit *> currentKits;
- foreach (const Target *t, projectInfo.project->targets())
+ const QList<Target *> targets = projectInfo.project->targets();
+ for (const Target *t : targets)
currentKits.insert(t->kit());
currentKits.remove(activeKit);
- foreach (Kit *kit, currentKits) {
+ for (Kit *kit : qAsConst(currentKits)) {
for (IBundleProvider *bp : IBundleProvider::allBundleProviders())
bp->mergeBundlesForKit(kit, projectInfo.extendedBundle, replacements);
}
@@ -214,22 +215,28 @@ QHash<QString,Dialect> ModelManager::initLanguageForSuffix() const
if (ICore::instance()) {
MimeType jsSourceTy = Utils::mimeTypeForName(Constants::JS_MIMETYPE);
- foreach (const QString &suffix, jsSourceTy.suffixes())
+ const QStringList jsSuffixes = jsSourceTy.suffixes();
+ for (const QString &suffix : jsSuffixes)
res[suffix] = Dialect::JavaScript;
MimeType qmlSourceTy = Utils::mimeTypeForName(Constants::QML_MIMETYPE);
- foreach (const QString &suffix, qmlSourceTy.suffixes())
+ const QStringList qmlSuffixes = qmlSourceTy.suffixes();
+ for (const QString &suffix : qmlSuffixes)
res[suffix] = Dialect::Qml;
MimeType qbsSourceTy = Utils::mimeTypeForName(Constants::QBS_MIMETYPE);
- foreach (const QString &suffix, qbsSourceTy.suffixes())
+ const QStringList qbsSuffixes = qbsSourceTy.suffixes();
+ for (const QString &suffix : qbsSuffixes)
res[suffix] = Dialect::QmlQbs;
MimeType qmlProjectSourceTy = Utils::mimeTypeForName(Constants::QMLPROJECT_MIMETYPE);
- foreach (const QString &suffix, qmlProjectSourceTy.suffixes())
+ const QStringList qmlProjSuffixes = qmlProjectSourceTy.suffixes();
+ for (const QString &suffix : qmlProjSuffixes)
res[suffix] = Dialect::QmlProject;
MimeType qmlUiSourceTy = Utils::mimeTypeForName(Constants::QMLUI_MIMETYPE);
- foreach (const QString &suffix, qmlUiSourceTy.suffixes())
+ const QStringList qmlUiSuffixes = qmlUiSourceTy.suffixes();
+ for (const QString &suffix : qmlUiSuffixes)
res[suffix] = Dialect::QmlQtQuick2Ui;
MimeType jsonSourceTy = Utils::mimeTypeForName(Constants::JSON_MIMETYPE);
- foreach (const QString &suffix, jsonSourceTy.suffixes())
+ const QStringList jsonSuffixes = jsonSourceTy.suffixes();
+ for (const QString &suffix : jsonSuffixes)
res[suffix] = Dialect::Json;
}
return res;
@@ -288,7 +295,8 @@ ModelManagerInterface::WorkingCopy ModelManager::workingCopyInternal() const
if (!Core::ICore::instance())
return workingCopy;
- foreach (IDocument *document, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents) {
const QString key = document->filePath().toString();
if (auto textDocument = qobject_cast<const TextEditor::TextDocument *>(document)) {
// TODO the language should be a property on the document, not the editor
diff --git a/src/plugins/qmljstools/qmljsrefactoringchanges.cpp b/src/plugins/qmljstools/qmljsrefactoringchanges.cpp
index e2e8bb2bda4..98d86199dd3 100644
--- a/src/plugins/qmljstools/qmljsrefactoringchanges.cpp
+++ b/src/plugins/qmljstools/qmljsrefactoringchanges.cpp
@@ -57,7 +57,7 @@ public:
const QTextBlock end = doc->findBlock(selection.selectionEnd()).next();
const TextEditor::TabSettings &tabSettings =
- ProjectExplorer::actualTabSettings(filePath.toString(), textDocument);
+ ProjectExplorer::actualTabSettings(filePath, textDocument);
CreatorCodeFormatter codeFormatter(tabSettings);
codeFormatter.updateStateUntil(block);
do {
@@ -82,7 +82,7 @@ public:
const TextEditor::TextDocument *textDocument) const override
{
const TextEditor::TabSettings &tabSettings =
- ProjectExplorer::actualTabSettings(filePath.toString(), textDocument);
+ ProjectExplorer::actualTabSettings(filePath, textDocument);
QmlJSEditor::Internal::Indenter indenter(selection.document());
indenter.reindent(selection, tabSettings);
diff --git a/src/plugins/qmljstools/qmljssemanticinfo.cpp b/src/plugins/qmljstools/qmljssemanticinfo.cpp
index b136747e7a0..451d264789b 100644
--- a/src/plugins/qmljstools/qmljssemanticinfo.cpp
+++ b/src/plugins/qmljstools/qmljssemanticinfo.cpp
@@ -191,7 +191,7 @@ QList<AST::Node *> SemanticInfo::rangePath(int cursorPosition) const
{
QList<AST::Node *> path;
- foreach (const Range &range, ranges) {
+ for (const Range &range : qAsConst(ranges)) {
if (range.begin.isNull() || range.end.isNull())
continue;
else if (cursorPosition >= range.begin.position() && cursorPosition <= range.end.position())
diff --git a/src/plugins/qmljstools/qmljstools.qbs b/src/plugins/qmljstools/qmljstools.qbs
index 96c0b359b25..b619d9aeada 100644
--- a/src/plugins/qmljstools/qmljstools.qbs
+++ b/src/plugins/qmljstools/qmljstools.qbs
@@ -19,11 +19,20 @@ QtcPlugin {
files: [
"qmljsbundleprovider.cpp",
"qmljsbundleprovider.h",
+ "qmljscodestylepreferences.cpp",
+ "qmljscodestylepreferences.h",
"qmljscodestylepreferencesfactory.cpp",
"qmljscodestylepreferencesfactory.h",
+ "qmljscodestylepreferenceswidget.cpp",
+ "qmljscodestylepreferenceswidget.h",
+ "qmljscodestylesettings.cpp",
+ "qmljscodestylesettings.h",
"qmljscodestylesettingspage.cpp",
"qmljscodestylesettingspage.h",
"qmljscodestylesettingspage.ui",
+ "qmljscodestylesettingswidget.cpp",
+ "qmljscodestylesettingswidget.h",
+ "qmljscodestylesettingswidget.ui",
"qmljsfunctionfilter.cpp",
"qmljsfunctionfilter.h",
"qmljsindenter.cpp",
diff --git a/src/plugins/qmljstools/qmljstools_global.h b/src/plugins/qmljstools/qmljstools_global.h
index 4ea360e5fee..bdbf9136c21 100644
--- a/src/plugins/qmljstools/qmljstools_global.h
+++ b/src/plugins/qmljstools/qmljstools_global.h
@@ -29,7 +29,7 @@
#if defined(QMLJSTOOLS_LIBRARY)
# define QMLJSTOOLS_EXPORT Q_DECL_EXPORT
-#elif defined(QMLJSTOOLS_STATIC)
+#elif defined(QMLJSTOOLS_STATIC_LIBRARY)
# define QMLJSTOOLS_EXPORT
#else
# define QMLJSTOOLS_EXPORT Q_DECL_IMPORT
diff --git a/src/plugins/qmljstools/qmljstoolssettings.cpp b/src/plugins/qmljstools/qmljstoolssettings.cpp
index dcfe957027c..52717ae9c14 100644
--- a/src/plugins/qmljstools/qmljstoolssettings.cpp
+++ b/src/plugins/qmljstools/qmljstoolssettings.cpp
@@ -25,10 +25,10 @@
#include "qmljstoolssettings.h"
#include "qmljstoolsconstants.h"
+#include "qmljscodestylepreferences.h"
#include "qmljscodestylepreferencesfactory.h"
#include <texteditor/texteditorsettings.h>
-#include <texteditor/simplecodestylepreferences.h>
#include <texteditor/tabsettings.h>
#include <texteditor/codestylepool.h>
@@ -44,7 +44,7 @@ namespace QmlJSTools {
const char idKey[] = "QmlJSGlobal";
-static SimpleCodeStylePreferences *m_globalCodeStyle = nullptr;
+static QmlJSCodeStylePreferences *m_globalCodeStyle = nullptr;
QmlJSToolsSettings::QmlJSToolsSettings()
{
@@ -59,7 +59,7 @@ QmlJSToolsSettings::QmlJSToolsSettings()
TextEditorSettings::registerCodeStylePool(Constants::QML_JS_SETTINGS_ID, pool);
// global code style settings
- m_globalCodeStyle = new SimpleCodeStylePreferences(this);
+ m_globalCodeStyle = new QmlJSCodeStylePreferences(this);
m_globalCodeStyle->setDelegatingPool(pool);
m_globalCodeStyle->setDisplayName(tr("Global", "Settings"));
m_globalCodeStyle->setId(idKey);
@@ -68,7 +68,7 @@ QmlJSToolsSettings::QmlJSToolsSettings()
// built-in settings
// Qt style
- auto qtCodeStyle = new SimpleCodeStylePreferences;
+ auto qtCodeStyle = new QmlJSCodeStylePreferences;
qtCodeStyle->setId("qt");
qtCodeStyle->setDisplayName(tr("Qt"));
qtCodeStyle->setReadOnly(true);
@@ -78,6 +78,9 @@ QmlJSToolsSettings::QmlJSToolsSettings()
qtTabSettings.m_indentSize = 4;
qtTabSettings.m_continuationAlignBehavior = TabSettings::ContinuationAlignWithIndent;
qtCodeStyle->setTabSettings(qtTabSettings);
+ QmlJSCodeStyleSettings qtQmlJSSetings;
+ qtQmlJSSetings.lineLength = 80;
+ qtCodeStyle->setCodeStyleSettings(qtQmlJSSetings);
pool->addCodeStyle(qtCodeStyle);
// default delegate for global preferences
@@ -148,7 +151,7 @@ QmlJSToolsSettings::~QmlJSToolsSettings()
m_globalCodeStyle = nullptr;
}
-SimpleCodeStylePreferences *QmlJSToolsSettings::globalCodeStyle()
+QmlJSCodeStylePreferences *QmlJSToolsSettings::globalCodeStyle()
{
return m_globalCodeStyle;
}
diff --git a/src/plugins/qmljstools/qmljstoolssettings.h b/src/plugins/qmljstools/qmljstoolssettings.h
index 85521d6b5e0..7965b489125 100644
--- a/src/plugins/qmljstools/qmljstoolssettings.h
+++ b/src/plugins/qmljstools/qmljstoolssettings.h
@@ -29,9 +29,8 @@
#include <QObject>
-namespace TextEditor { class SimpleCodeStylePreferences; }
-
namespace QmlJSTools {
+class QmlJSCodeStylePreferences;
/**
* This class provides a central place for cpp tools settings.
@@ -44,7 +43,7 @@ public:
explicit QmlJSToolsSettings();
~QmlJSToolsSettings() override;
- static TextEditor::SimpleCodeStylePreferences *globalCodeStyle();
+ static QmlJSCodeStylePreferences *globalCodeStyle();
};
} // namespace QmlJSTools
diff --git a/src/plugins/qmlpreview/CMakeLists.txt b/src/plugins/qmlpreview/CMakeLists.txt
index 4b537c4cf97..02435547d82 100644
--- a/src/plugins/qmlpreview/CMakeLists.txt
+++ b/src/plugins/qmlpreview/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(QmlPreview
+ CONDITION TARGET QmlProjectManager
PUBLIC_DEPENDS QmlDebug
DEPENDS QmlJS
PLUGIN_DEPENDS
diff --git a/src/plugins/qmlpreview/qmlpreview_global.h b/src/plugins/qmlpreview/qmlpreview_global.h
index 372847578f3..0419c6bff2b 100644
--- a/src/plugins/qmlpreview/qmlpreview_global.h
+++ b/src/plugins/qmlpreview/qmlpreview_global.h
@@ -29,6 +29,8 @@
#if defined(QMLPREVIEW_LIBRARY)
# define QMLPREVIEW_EXPORT Q_DECL_EXPORT
+#elif defined(QMLPREVIEW_STATIC_LIBRARY)
+# define QMLPREVIEW_EXPORT
#else
# define QMLPREVIEW_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp
index e5f5ec8b2d1..67dcb82081c 100644
--- a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp
@@ -202,7 +202,7 @@ void QmlPreviewConnectionManager::createPreviewClient()
&QmlPreviewClient::errorReported,
this,
[](const QString &error) {
- Core::MessageManager::writeDisrupting("Error loading QML Live Preview:");
+ Core::MessageManager::writeFlashing("Error loading QML Live Preview:");
Core::MessageManager::writeSilently(error);
});
diff --git a/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp b/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp
index aebce83d5a9..f4c6e438072 100644
--- a/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp
@@ -33,8 +33,6 @@
#include <projectexplorer/projecttree.h>
#include <projectexplorer/target.h>
-#include <resourceeditor/resourcenode.h>
-
#include <utils/qtcassert.h>
namespace QmlPreview {
@@ -52,7 +50,7 @@ ProjectExplorer::Target *QmlPreviewFileOnTargetFinder::target() const
QString resourceNodePath(const ProjectExplorer::Node *node)
{
- if (auto resourceNode = dynamic_cast<const ResourceEditor::ResourceFileNode *>(node))
+ if (auto resourceNode = dynamic_cast<const ProjectExplorer::ResourceFileNode *>(node))
return ":" + resourceNode->qrcPath();
return QString();
}
diff --git a/src/plugins/qmlpreview/qmlpreviewplugin.cpp b/src/plugins/qmlpreview/qmlpreviewplugin.cpp
index 6bd695ac72b..72907a15419 100644
--- a/src/plugins/qmlpreview/qmlpreviewplugin.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewplugin.cpp
@@ -44,6 +44,7 @@
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/runconfiguration.h>
@@ -449,10 +450,6 @@ void QmlPreviewPluginPrivate::setDirty()
void QmlPreviewPluginPrivate::addPreview(ProjectExplorer::RunControl *preview)
{
m_runningPreviews.append(preview);
- if (auto multiLanguageAspect = preview->aspect<QmlProjectManager::QmlMultiLanguageAspect>()) {
- connect(multiLanguageAspect, &QmlProjectManager::QmlMultiLanguageAspect::changed,
- preview, &ProjectExplorer::RunControl::initiateStop);
- }
emit q->runningPreviewsChanged(m_runningPreviews);
}
diff --git a/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp b/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp
index 1af9f8bb793..baade35da40 100644
--- a/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp
@@ -41,6 +41,8 @@
#include <utils/url.h>
#include <utils/fileutils.h>
+using namespace Utils;
+
namespace QmlPreview {
static const QString QmlServerUrl = "QmlServerUrl";
@@ -81,9 +83,9 @@ QmlPreviewRunner::QmlPreviewRunner(const QmlPreviewRunnerSetting &settings)
return;
this->connect(runControl(), &ProjectExplorer::RunControl::stopped, [this]() {
- ProjectExplorer::ProjectExplorerPlugin::runRunConfiguration(
- runControl()->runConfiguration(),
- ProjectExplorer::Constants::QML_PREVIEW_RUN_MODE, true);
+ auto rc = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PREVIEW_RUN_MODE);
+ rc->copyDataFromRunControl(runControl());
+ ProjectExplorer::ProjectExplorerPlugin::startRunControl(rc);
});
runControl()->initiateStop();
@@ -126,30 +128,32 @@ LocalQmlPreviewSupport::LocalQmlPreviewSupport(ProjectExplorer::RunControl *runC
addStopDependency(preview);
addStartDependency(preview);
- setStarter([this, runControl, serverUrl] {
- ProjectExplorer::Runnable runnable = runControl->runnable();
- QStringList qmlProjectRunConfigurationArguments = runnable.command.splitArguments();
+ setStartModifier([this, runControl, serverUrl] {
+ CommandLine cmd = commandLine();
+
+ QStringList qmlProjectRunConfigurationArguments = cmd.splitArguments();
const auto currentTarget = runControl->target();
const auto *qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(currentTarget->buildSystem());
if (const auto aspect = runControl->aspect<QmlProjectManager::QmlMainFileAspect>()) {
- const QString mainScript = aspect->mainScript();
- const QString currentFile = aspect->currentFile();
+ const QString mainScript = aspect->mainScript;
+ const QString currentFile = aspect->currentFile;
const QString mainScriptFromProject = qmlBuildSystem->targetFile(
Utils::FilePath::fromString(mainScript)).toString();
if (!currentFile.isEmpty() && qmlProjectRunConfigurationArguments.last().contains(mainScriptFromProject)) {
qmlProjectRunConfigurationArguments.removeLast();
- runnable.command = Utils::CommandLine(runnable.command.executable(), qmlProjectRunConfigurationArguments);
- runnable.command.addArg(currentFile);
+ cmd = Utils::CommandLine(cmd.executable(), qmlProjectRunConfigurationArguments);
+ cmd.addArg(currentFile);
}
}
- runnable.command.addArg(QmlDebug::qmlDebugLocalArguments(QmlDebug::QmlPreviewServices,
- serverUrl.path()));
- doStart(runnable, {});
+ cmd.addArg(QmlDebug::qmlDebugLocalArguments(QmlDebug::QmlPreviewServices, serverUrl.path()));
+ setCommandLine(cmd);
+
+ forceRunOnHost();
});
}
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.cpp b/src/plugins/qmlprofiler/flamegraphmodel.cpp
index d03fd21451d..eb280ce49eb 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.cpp
+++ b/src/plugins/qmlprofiler/flamegraphmodel.cpp
@@ -200,7 +200,8 @@ QVariant FlameGraphModel::lookup(const FlameGraphData &stats, int role) const
if (!m_typeIdsWithNotes.contains(stats.typeIndex))
return ret;
Timeline::TimelineNotesModel *notes = m_modelManager->notesModel();
- foreach (const QVariant &item, notes->byTypeId(stats.typeIndex)) {
+ const QList<QVariant> items = notes->byTypeId(stats.typeIndex);
+ for (const QVariant &item : items) {
if (ret.isEmpty())
ret = notes->text(item.toInt());
else
diff --git a/src/plugins/qmlprofiler/pixmapcachemodel.cpp b/src/plugins/qmlprofiler/pixmapcachemodel.cpp
index 3efe0a7d202..5006ef31dfa 100644
--- a/src/plugins/qmlprofiler/pixmapcachemodel.cpp
+++ b/src/plugins/qmlprofiler/pixmapcachemodel.cpp
@@ -432,7 +432,7 @@ QString PixmapCacheModel::fileName(int index) const
void PixmapCacheModel::computeMaxCacheSize()
{
- foreach (const PixmapCacheModel::Item &event, m_data) {
+ for (const PixmapCacheModel::Item &event : qAsConst(m_data)) {
if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) {
if (event.cacheSize > m_maxCacheSize)
m_maxCacheSize = event.cacheSize;
diff --git a/src/plugins/qmlprofiler/qmlprofiler_global.h b/src/plugins/qmlprofiler/qmlprofiler_global.h
index 2da08c05674..0a3384ad197 100644
--- a/src/plugins/qmlprofiler/qmlprofiler_global.h
+++ b/src/plugins/qmlprofiler/qmlprofiler_global.h
@@ -29,6 +29,8 @@
#if defined(QMLPROFILER_LIBRARY)
# define QMLPROFILER_EXPORT Q_DECL_EXPORT
+#elif defined(QMLPROFILER_STATIC_LIBRARY)
+# define QMLPROFILER_EXPORT
#else
# define QMLPROFILER_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp b/src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp
index 35ac01a5ae2..2c30b8e708e 100644
--- a/src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilernotesmodel.cpp
@@ -41,7 +41,8 @@ int QmlProfilerNotesModel::addQmlNote(int typeId, int collapsedRow, qint64 start
int foundTypeId = -1;
int timelineModel = -1;
int timelineIndex = -1;
- foreach (const Timeline::TimelineModel *model, timelineModels()) {
+ const QList<const Timeline::TimelineModel *> models = timelineModels();
+ for (const Timeline::TimelineModel *model : models) {
if (model->handlesTypeId(typeId)) {
for (int i = model->firstIndex(start); i <= model->lastIndex(start + duration); ++i) {
if (i < 0)
diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
index f6592de524e..06c6f269be1 100644
--- a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
@@ -28,7 +28,6 @@
#include "qmlprofilerruncontrol.h"
#include "qmlprofilersettings.h"
#include "qmlprofilertool.h"
-#include "qmlprofilertimelinemodel.h"
#include "qmlprofileractions.h"
#ifdef WITH_TESTS
@@ -65,6 +64,7 @@
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
index 9eaf06fee4b..89bddb68791 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
@@ -25,7 +25,6 @@
#include "qmlprofilerruncontrol.h"
-#include "qmlprofilerclientmanager.h"
#include "qmlprofilertool.h"
#include <coreplugin/icore.h>
@@ -236,8 +235,7 @@ LocalQmlProfilerSupport::LocalQmlProfilerSupport(RunControl *runControl, const Q
// In the TCP case, it doesn't hurt either to start the profiler before.
addStartDependency(profiler);
- setStarter([this, runControl, profiler, serverUrl] {
- Runnable debuggee = runControl->runnable();
+ setStartModifier([this, profiler, serverUrl] {
QUrl serverUrl = profiler->serverUrl();
QString code;
@@ -251,12 +249,13 @@ LocalQmlProfilerSupport::LocalQmlProfilerSupport(RunControl *runControl, const Q
QString arguments = Utils::ProcessArgs::quoteArg(
QmlDebug::qmlDebugCommandLineArguments(QmlDebug::QmlProfilerServices, code, true));
- if (!debuggee.command.arguments().isEmpty())
- arguments += ' ' + debuggee.command.arguments();
+ Utils::CommandLine cmd = commandLine();
+ const QString oldArgs = cmd.arguments();
+ cmd.setArguments(arguments);
+ cmd.addArgs(oldArgs, Utils::CommandLine::Raw);
+ setCommandLine(cmd);
- debuggee.command.setArguments(arguments);
-
- doStart(debuggee, {});
+ forceRunOnHost();
});
}
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
index ad203258a6d..92a1b1b623a 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
@@ -156,26 +156,32 @@ QString QmlProfilerStatisticsModel::summary(const QVector<int> &typeIds) const
double maximum = 0;
double sum = 0;
+ QSet<RangeType> types;
+
for (int typeId : typeIds) {
+ types << m_modelManager->eventType(typeId).rangeType();
const double percentage = durationPercent(typeId);
if (percentage > maximum)
maximum = percentage;
sum += percentage;
}
+ const QStringList typeNames = Utils::transform<QList>(types, &nameForType);
+ const QString typeSummary = QString(" (%1)").arg(typeNames.join(", "));
+
const QLatin1Char percent('%');
if (sum < cutoff)
- return QLatin1Char('<') + QString::number(cutoff, 'f', 1) + percent;
+ return QLatin1Char('<') + QString::number(cutoff, 'f', 1) + percent + typeSummary;
if (typeIds.length() == 1)
- return QLatin1Char('~') + QString::number(maximum, 'f', 1) + percent;
+ return QLatin1Char('~') + QString::number(maximum, 'f', 1) + percent + typeSummary;
// add/subtract 0.05 to avoid problematic rounding
if (maximum < cutoff)
- return QChar(0x2264) + QString::number(sum + round, 'f', 1) + percent;
+ return QChar(0x2264) + QString::number(sum + round, 'f', 1) + percent + typeSummary;
- return QChar(0x2265) + QString::number(qMax(maximum - round, cutoff), 'f', 1) + percent;
+ return QChar(0x2265) + QString::number(qMax(maximum - round, cutoff), 'f', 1) + percent + typeSummary;
}
void QmlProfilerStatisticsModel::clear()
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
index 81d57358756..8b0fe63d8c8 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
@@ -137,8 +137,8 @@ void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
QPoint position = ev->globalPos();
- QList <QAction *> commonActions = QmlProfilerTool::profilerContextMenuActions();
- foreach (QAction *act, commonActions)
+ const QList <QAction *> commonActions = QmlProfilerTool::profilerContextMenuActions();
+ for (QAction *act : commonActions)
menu.addAction(act);
if (mouseOnTable(position)) {
diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
index 3630d6a2d2f..f0e19fc80c4 100644
--- a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
@@ -39,29 +39,21 @@ namespace QmlProfiler {
namespace Internal {
QmlProfilerTextMark::QmlProfilerTextMark(QmlProfilerViewManager *viewManager, int typeId,
- const FilePath &fileName, int lineNumber) :
- TextMark(fileName, lineNumber, Constants::TEXT_MARK_CATEGORY, 3.5), m_viewManager(viewManager),
- m_typeIds(1, typeId)
+ const FilePath &fileName, int lineNumber)
+ : TextMark(fileName, lineNumber, Constants::TEXT_MARK_CATEGORY)
+ , m_viewManager(viewManager)
{
+ addTypeId(typeId);
}
void QmlProfilerTextMark::addTypeId(int typeId)
{
m_typeIds.append(typeId);
-}
-void QmlProfilerTextMark::paintIcon(QPainter *painter, const QRect &paintRect) const
-{
const QmlProfilerStatisticsView *statisticsView = m_viewManager->statisticsView();
QTC_ASSERT(statisticsView, return);
- painter->save();
- painter->setPen(Qt::black);
- painter->fillRect(paintRect, Qt::white);
- painter->drawRect(paintRect);
- painter->drawText(paintRect, statisticsView->summary(m_typeIds),
- Qt::AlignRight | Qt::AlignVCenter);
- painter->restore();
+ setLineAnnotation(statisticsView->summary(m_typeIds));
}
void QmlProfilerTextMark::clicked()
@@ -142,12 +134,27 @@ bool QmlProfilerTextMark::addToolTipContent(QLayout *target) const
auto layout = new QGridLayout;
layout->setHorizontalSpacing(10);
for (int row = 0, rowEnd = m_typeIds.length(); row != rowEnd; ++row) {
+ int typeId = m_typeIds[row];
const QStringList typeDetails = statisticsView->details(m_typeIds[row]);
for (int column = 0, columnEnd = typeDetails.length(); column != columnEnd; ++column) {
QLabel *label = new QLabel;
label->setAlignment(column == columnEnd - 1 ? Qt::AlignRight : Qt::AlignLeft);
- label->setTextFormat(Qt::PlainText);
- label->setText(typeDetails[column]);
+ if (column == 0) {
+ label->setTextFormat(Qt::RichText);
+ label->setTextInteractionFlags(Qt::LinksAccessibleByMouse
+ | Qt::LinksAccessibleByKeyboard);
+ label->setText(QString("<a href='selectType' style='text-decoration:none'>%1</a>")
+ .arg(typeDetails[column]));
+ QObject::connect(label,
+ &QLabel::linkActivated,
+ m_viewManager,
+ [this, typeId]() {
+ emit m_viewManager->typeSelected(typeId);
+ });
+ } else {
+ label->setTextFormat(Qt::PlainText);
+ label->setText(typeDetails[column]);
+ }
layout->addWidget(label, row, column);
}
}
diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.h b/src/plugins/qmlprofiler/qmlprofilertextmark.h
index 5b529cd3c16..1c7edea23fe 100644
--- a/src/plugins/qmlprofiler/qmlprofilertextmark.h
+++ b/src/plugins/qmlprofiler/qmlprofilertextmark.h
@@ -39,7 +39,6 @@ public:
const Utils::FilePath &fileName, int lineNumber);
void addTypeId(int typeId);
- void paintIcon(QPainter *painter, const QRect &rect) const override;
void clicked() override;
bool isClickable() const override { return true; }
bool addToolTipContent(QLayout *target) const override;
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
index 74243a574bd..551cf32e32c 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -31,8 +31,6 @@
#include "qmlprofilerviewmanager.h"
#include "qmlprofilerclientmanager.h"
#include "qmlprofilermodelmanager.h"
-#include "qmlprofilerdetailsrewriter.h"
-#include "qmlprofilernotesmodel.h"
#include "qmlprofilerrunconfigurationaspect.h"
#include "qmlprofilersettings.h"
#include "qmlprofilerplugin.h"
@@ -40,38 +38,42 @@
#include <app/app_version.h>
-#include <debugger/debuggericons.h>
-#include <debugger/debuggermainwindow.h>
-#include <debugger/analyzer/analyzermanager.h>
-
-#include <utils/fancymainwindow.h>
-#include <utils/fileinprojectfinder.h>
-#include <utils/qtcassert.h>
-#include <utils/url.h>
-#include <utils/utilsicons.h>
-#include <projectexplorer/environmentaspect.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/session.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/taskhub.h>
-#include <texteditor/texteditor.h>
-
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/findplugin.h>
#include <coreplugin/icore.h>
+#include <coreplugin/imode.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/helpmanager.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
-#include <coreplugin/imode.h>
+
+#include <debugger/analyzer/analyzermanager.h>
+#include <debugger/debuggericons.h>
+#include <debugger/debuggermainwindow.h>
+
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/environmentaspect.h>
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/taskhub.h>
#include <qtsupport/qtkitinformation.h>
+#include <texteditor/texteditor.h>
+
+#include <utils/fancymainwindow.h>
+#include <utils/fileinprojectfinder.h>
+#include <utils/qtcassert.h>
+#include <utils/url.h>
+#include <utils/utilsicons.h>
+
#include <QApplication>
#include <QDockWidget>
#include <QElapsedTimer>
@@ -311,9 +313,8 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
{
d->m_toolBusy = true;
auto runControl = runWorker->runControl();
- if (auto aspect = static_cast<QmlProfilerRunConfigurationAspect *>(
- runControl->aspect(Constants::SETTINGS))) {
- if (auto settings = static_cast<const QmlProfilerSettings *>(aspect->currentSettings())) {
+ if (auto aspect = runControl->aspect<QmlProfilerRunConfigurationAspect>()) {
+ if (auto settings = static_cast<const QmlProfilerSettings *>(aspect->currentSettings)) {
d->m_profilerConnections->setFlushInterval(settings->flushEnabled.value() ?
settings->flushInterval.value() : 0);
d->m_profilerModelManager->setAggregateTraces(settings->aggregateTraces.value());
@@ -501,7 +502,8 @@ void QmlProfilerTool::setButtonsEnabled(bool enable)
void QmlProfilerTool::createInitialTextMarks()
{
QmlProfilerTextMarkModel *model = d->m_profilerModelManager->textMarkModel();
- foreach (IDocument *document, DocumentModel::openedDocuments())
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents)
model->createMarks(d->m_viewContainer, document->filePath().toString());
}
@@ -562,7 +564,7 @@ ProjectExplorer::RunControl *QmlProfilerTool::attachToWaitingApplication()
d->m_viewContainer->perspective()->select();
auto runControl = new RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
- runControl->setRunConfiguration(SessionManager::startupRunConfiguration());
+ runControl->copyDataFromRunConfiguration(SessionManager::startupRunConfiguration());
auto profiler = new QmlProfilerRunner(runControl);
profiler->setServerUrl(serverUrl);
@@ -734,7 +736,8 @@ void QmlProfilerTool::setAvailableFeatures(quint64 features)
void QmlProfilerTool::setRecordedFeatures(quint64 features)
{
- foreach (QAction *action, d->m_displayFeaturesMenu->actions())
+ const QList<QAction *> actions = d->m_displayFeaturesMenu->actions();
+ for (QAction *action : actions)
action->setEnabled(features & (1ULL << action->data().toUInt()));
}
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.h b/src/plugins/qmlprofiler/qmlprofilertool.h
index a6065e502d1..450607c9c35 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.h
+++ b/src/plugins/qmlprofiler/qmlprofilertool.h
@@ -26,8 +26,6 @@
#pragma once
#include "qmlprofiler_global.h"
-#include "qmlprofilerconstants.h"
-#include "qmlprofilereventtypes.h"
#include <QAction>
#include <QObject>
diff --git a/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
index 9432407d7b6..1d749fee724 100644
--- a/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
@@ -25,12 +25,15 @@
#include "qmlprofilerviewmanager.h"
-#include "qmlprofilertool.h"
+#include "qmlprofilerconstants.h"
#include "qmlprofilerstatewidget.h"
-#include <utils/qtcassert.h>
#include <debugger/analyzer/analyzermanager.h>
+#include <projectexplorer/projectexplorerconstants.h>
+
+#include <utils/qtcassert.h>
+
#include <QDockWidget>
using namespace Debugger;
@@ -51,7 +54,7 @@ QmlProfilerViewManager::QmlProfilerViewManager(QObject *parent,
QTC_ASSERT(m_profilerModelManager, return);
QTC_ASSERT(m_profilerState, return);
- m_perspective = new Utils::Perspective(Constants::QmlProfilerPerspectiveId, tr("QML Profiler"));
+ m_perspective = new Perspective(Constants::QmlProfilerPerspectiveId, tr("QML Profiler"));
m_perspective->setAboutToActivateCallback([this]() { createViews(); });
}
diff --git a/src/plugins/qmlprofiler/qmlprofilerviewmanager.h b/src/plugins/qmlprofiler/qmlprofilerviewmanager.h
index d65f3c4965a..fc2b4252cab 100644
--- a/src/plugins/qmlprofiler/qmlprofilerviewmanager.h
+++ b/src/plugins/qmlprofiler/qmlprofilerviewmanager.h
@@ -29,15 +29,11 @@
#include "qmlprofilertraceview.h"
#include "flamegraphview.h"
-#include <QObject>
-
namespace Utils { class Perspective; }
namespace QmlProfiler {
namespace Internal {
-class QmlProfilerTool;
-
class QmlProfilerViewManager : public QObject
{
Q_OBJECT
diff --git a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
index 15f30b1025e..bdf08103fba 100644
--- a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
+++ b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
@@ -27,6 +27,8 @@
#include <debugger/analyzer/analyzermanager.h>
+#include <projectexplorer/projectexplorerconstants.h>
+
#include <qmlprofiler/qmlprofilerruncontrol.h>
#include <qmlprofiler/qmlprofilertool.h>
@@ -36,6 +38,9 @@
#include <QtTest>
#include <QTcpServer>
+using namespace ProjectExplorer;
+using namespace Utils;
+
namespace QmlProfiler {
namespace Internal {
@@ -45,9 +50,8 @@ LocalQmlProfilerRunnerTest::LocalQmlProfilerRunnerTest(QObject *parent) : QObjec
void LocalQmlProfilerRunnerTest::testRunner()
{
- QPointer<ProjectExplorer::RunControl> runControl;
+ QPointer<RunControl> runControl;
QPointer<LocalQmlProfilerSupport> profiler;
- ProjectExplorer::Runnable debuggee;
QUrl serverUrl;
bool running = false;
@@ -56,37 +60,35 @@ void LocalQmlProfilerRunnerTest::testRunner()
int runCount = 0;
int stopCount = 0;
- debuggee.command.setExecutable("\\-/|\\-/");
- debuggee.environment = Utils::Environment::systemEnvironment();
-
// should not be used anywhere but cannot be empty
serverUrl.setScheme(Utils::urlSocketScheme());
serverUrl.setPath("invalid");
- runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
- runControl->setRunnable(debuggee);
+ runControl = new RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ runControl->setCommandLine({"\\-/|\\-/", {}});
+
profiler = new LocalQmlProfilerSupport(runControl, serverUrl);
auto connectRunner = [&]() {
- connect(runControl, &ProjectExplorer::RunControl::aboutToStart, this, [&]() {
+ connect(runControl, &RunControl::aboutToStart, this, [&] {
QVERIFY(!started);
QVERIFY(!running);
++startCount;
started = true;
});
- connect(runControl, &ProjectExplorer::RunControl::started, this, [&]() {
+ connect(runControl, &RunControl::started, this, [&] {
QVERIFY(started);
QVERIFY(!running);
++runCount;
running = true;
});
- connect(runControl, &ProjectExplorer::RunControl::stopped, this, [&]() {
+ connect(runControl, &RunControl::stopped, this, [&] {
QVERIFY(started);
++stopCount;
running = false;
started = false;
});
- connect(runControl, &ProjectExplorer::RunControl::finished, this, [&]() {
+ connect(runControl, &RunControl::finished, this, [&]{
running = false;
started = false;
});
@@ -110,10 +112,10 @@ void LocalQmlProfilerRunnerTest::testRunner()
serverUrl = Utils::urlFromLocalSocket();
// comma is used to specify a test function. In this case, an invalid one.
- debuggee.command = Utils::CommandLine(Utils::FilePath::fromString(QCoreApplication::applicationFilePath()),
- {"-test", "QmlProfiler,"});
- runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
- runControl->setRunnable(debuggee);
+ runControl = new RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+
+ const FilePath app = FilePath::fromString(QCoreApplication::applicationFilePath());
+ runControl->setCommandLine({app, {"-test", "QmlProfiler,"}});
profiler = new LocalQmlProfilerSupport(runControl, serverUrl);
connectRunner();
runControl->initiateStart();
@@ -128,11 +130,10 @@ void LocalQmlProfilerRunnerTest::testRunner()
QTRY_VERIFY(runControl.isNull());
QVERIFY(profiler.isNull());
- debuggee.command.setArguments({});
serverUrl.clear();
serverUrl = Utils::urlFromLocalHostAndFreePort();
- runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
- runControl->setRunnable(debuggee);
+ runControl = new RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ runControl->setCommandLine({app, {}});
profiler = new LocalQmlProfilerSupport(runControl, serverUrl);
connectRunner();
runControl->initiateStart();
@@ -148,7 +149,6 @@ void LocalQmlProfilerRunnerTest::testRunner()
QTRY_VERIFY(runControl.isNull());
QVERIFY(profiler.isNull());
- debuggee.command.setArguments("-test QmlProfiler,");
serverUrl.setScheme(Utils::urlSocketScheme());
{
Utils::TemporaryFile file("file with spaces");
@@ -156,8 +156,8 @@ void LocalQmlProfilerRunnerTest::testRunner()
serverUrl.setPath(file.fileName());
}
- runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
- runControl->setRunnable(debuggee);
+ runControl = new RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ runControl->setCommandLine({app, {"-test", "QmlProfiler,"}});
profiler = new LocalQmlProfilerSupport(runControl, serverUrl);
connectRunner();
runControl->initiateStart();
diff --git a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h
index 53ef39e8ff1..39491ec0c94 100644
--- a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h
+++ b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h
@@ -28,14 +28,13 @@
#include <qmlprofiler/qmlprofilermodelmanager.h>
#include <qmlprofiler/qmlprofilerruncontrol.h>
-#include <QUrl>
-
namespace QmlProfiler {
namespace Internal {
class LocalQmlProfilerRunnerTest : public QObject
{
Q_OBJECT
+
public:
LocalQmlProfilerRunnerTest(QObject *parent = nullptr);
diff --git a/src/plugins/qmlprojectmanager/CMakeLists.txt b/src/plugins/qmlprojectmanager/CMakeLists.txt
index fa037362a50..42013e53868 100644
--- a/src/plugins/qmlprojectmanager/CMakeLists.txt
+++ b/src/plugins/qmlprojectmanager/CMakeLists.txt
@@ -1,10 +1,25 @@
add_qtc_plugin(QmlProjectManager
- DEPENDS QmlJS
+ CONDITION TARGET Qt5::QuickWidgets
+ PLUGIN_CLASS QmlProjectPlugin
+ DEPENDS QmlJS Qt5::QuickWidgets
PLUGIN_DEPENDS Core ProjectExplorer QtSupport
SOURCES
fileformat/filefilteritems.cpp fileformat/filefilteritems.h
fileformat/qmlprojectfileformat.cpp fileformat/qmlprojectfileformat.h
fileformat/qmlprojectitem.cpp fileformat/qmlprojectitem.h
+ cmakegen/checkablefiletreeitem.cpp cmakegen/checkablefiletreeitem.h
+ cmakegen/cmakegeneratordialog.cpp cmakegen/cmakegeneratordialog.h
+ cmakegen/cmakegeneratordialogtreemodel.cpp cmakegen/cmakegeneratordialogtreemodel.h
+ cmakegen/cmakeprojectconverter.cpp cmakegen/cmakeprojectconverter.h
+ cmakegen/cmakeprojectconverterdialog.cpp cmakegen/cmakeprojectconverterdialog.h
+ cmakegen/generatecmakelists.cpp cmakegen/generatecmakelists.h
+ cmakegen/generatecmakelistsconstants.h
+ cmakegen/boilerplate.qrc
+ qmlprojectgen/qmlprojectgenerator.cpp qmlprojectgen/qmlprojectgenerator.h
+ qmlprojectgen/templates.qrc
+ projectfilecontenttools.cpp projectfilecontenttools.h
+ qdslandingpage.cpp qdslandingpage.h
+ qdslandingpagetheme.cpp qdslandingpagetheme.h
qmlmainfileaspect.cpp qmlmainfileaspect.h
qmlmultilanguageaspect.cpp qmlmultilanguageaspect.h
qmlproject.cpp qmlproject.h
@@ -15,4 +30,5 @@ add_qtc_plugin(QmlProjectManager
qmlprojectnodes.cpp qmlprojectnodes.h
qmlprojectplugin.cpp qmlprojectplugin.h
qmlprojectrunconfiguration.cpp qmlprojectrunconfiguration.h
+ "${PROJECT_SOURCE_DIR}/src/share/3rdparty/studiofonts/studiofonts.qrc"
)
diff --git a/src/plugins/qmldesigner/boilerplate.qrc b/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc
index a89643d6fff..a89643d6fff 100644
--- a/src/plugins/qmldesigner/boilerplate.qrc
+++ b/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc
diff --git a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp b/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp
new file mode 100644
index 00000000000..815ad2628a0
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "checkablefiletreeitem.h"
+
+using namespace Utils;
+
+namespace QmlProjectManager {
+
+CheckableFileTreeItem::CheckableFileTreeItem(const FilePath &filePath)
+ :QStandardItem(filePath.toString())
+{
+ Qt::ItemFlags itemFlags = flags();
+ if (!isDir())
+ itemFlags |= Qt::ItemIsUserCheckable;
+ itemFlags &= ~(Qt::ItemIsEditable | Qt::ItemIsSelectable);
+ setFlags(itemFlags);
+}
+
+const FilePath CheckableFileTreeItem::toFilePath() const
+{
+ return FilePath::fromString(text());
+}
+
+bool CheckableFileTreeItem::isFile() const
+{
+ return FilePath::fromString(text()).isFile();
+}
+
+bool CheckableFileTreeItem::isDir() const
+{
+ return FilePath::fromString(text()).isDir();
+}
+
+void CheckableFileTreeItem::setChecked(bool checked)
+{
+ this->checked = checked;
+}
+
+bool CheckableFileTreeItem::isChecked() const
+{
+ return this->checked;
+}
+
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h b/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h
new file mode 100644
index 00000000000..19566ae7c53
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#ifndef CHECKABLEFILETREEITEM_H
+#define CHECKABLEFILETREEITEM_H
+
+#include <utils/fileutils.h>
+
+#include <QStandardItem>
+
+namespace QmlProjectManager {
+
+class CheckableFileTreeItem : public QStandardItem
+{
+public:
+ explicit CheckableFileTreeItem(const Utils::FilePath &text = Utils::FilePath());
+
+ const Utils::FilePath toFilePath() const;
+ bool isFile() const;
+ bool isDir() const;
+
+ bool isChecked() const;
+ void setChecked(bool checked);
+
+private:
+ bool checked;
+};
+
+} //QmlProjectManager
+
+#endif // CHECKABLEFILETREEITEM_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp
new file mode 100644
index 00000000000..f6767c42962
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "cmakegeneratordialog.h"
+#include "cmakegeneratordialogtreemodel.h"
+#include "generatecmakelistsconstants.h"
+
+#include <utils/utilsicons.h>
+#include <utils/detailswidget.h>
+
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QLayout>
+#include <QLabel>
+
+#include <QSplitter>
+
+using namespace Utils;
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+
+CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePaths &files)
+ : QDialog(),
+ m_rootDir(rootDir),
+ m_files(files)
+{
+ setWindowTitle(QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "Select Files to Generate"));
+
+ QLabel *mainLabel = new QLabel(QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "Start CMakeFiles.txt generation"),
+ this);
+ mainLabel->setMargin(30);
+
+ QVBoxLayout *dialogLayout = new QVBoxLayout(this);
+ dialogLayout->addWidget(mainLabel);
+ dialogLayout->addWidget(createDetailsWidget());
+ dialogLayout->addWidget(createButtons());
+ setLayout(dialogLayout);
+
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ setMaximumHeight(layout()->totalSizeHint().height());
+
+ refreshNotificationText();
+}
+
+QTreeView* CmakeGeneratorDialog::createFileTree()
+{
+ m_model = new CMakeGeneratorDialogTreeModel(m_rootDir, m_files, this);
+
+ QTreeView *tree = new QTreeView(this);
+ tree->setModel(m_model);
+ tree->expandAll();
+ tree->setHeaderHidden(true);
+
+ return tree;
+}
+
+QWidget* CmakeGeneratorDialog::createDetailsWidget()
+{
+ QTreeView* tree = createFileTree();
+
+ m_notifications = new QTextEdit(this);
+ m_warningIcon = Utils::Icons::WARNING.pixmap();
+
+ QSplitter *advancedInnerWidget = new QSplitter(this);
+ advancedInnerWidget->addWidget(tree);
+ advancedInnerWidget->addWidget(m_notifications);
+ advancedInnerWidget->setStretchFactor(0, 2);
+ advancedInnerWidget->setStretchFactor(1, 1);
+ advancedInnerWidget->setOrientation(Qt::Vertical);
+ advancedInnerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::MinimumExpanding);
+
+ DetailsWidget *advancedWidget = new DetailsWidget(this);
+ advancedWidget->setMinimumWidth(600);
+ advancedWidget->setWidget(advancedInnerWidget);
+ advancedWidget->setSummaryText(QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "Advanced Options"));
+ connect(advancedWidget, &DetailsWidget::expanded, this, &CmakeGeneratorDialog::advancedVisibilityChanged);
+
+ return advancedWidget;
+}
+
+QWidget* CmakeGeneratorDialog::createButtons()
+{
+ QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
+ auto *okButton = buttons->button(QDialogButtonBox::Ok);
+ okButton->setDefault(true);
+
+ connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ connect(m_model, &CMakeGeneratorDialogTreeModel::checkedStateChanged, this, &CmakeGeneratorDialog::refreshNotificationText);
+
+ return buttons;
+}
+
+FilePaths CmakeGeneratorDialog::getFilePaths()
+{
+ FilePaths paths;
+
+ QList<CheckableFileTreeItem*> items = m_model->checkedItems();
+ for (CheckableFileTreeItem *item: items) {
+ paths.append(FilePath::fromString(item->text()));
+ }
+
+ return paths;
+}
+
+const QString FILE_CREATE_NOTIFICATION = QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "File %1 will be created.\n");
+const QString FILE_OVERWRITE_NOTIFICATION = QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "File %1 will be overwritten.\n");
+
+void CmakeGeneratorDialog::refreshNotificationText()
+{
+ QTextDocument *document = m_notifications->document();
+ document->clear();
+ document->addResource(QTextDocument::ImageResource, QUrl("cmakegendialog://warningicon"), m_warningIcon);
+
+ QTextCursor cursor = m_notifications->textCursor();
+ QTextImageFormat iformat;
+ iformat.setName("cmakegendialog://warningicon");
+
+ QList<CheckableFileTreeItem*> nodes = m_model->items();
+
+ for (CheckableFileTreeItem *node : nodes) {
+ if (!m_files.contains(node->toFilePath()))
+ continue;
+
+ if (!node->toFilePath().exists() && node->isChecked()) {
+ QString relativePath = QString(node->toFilePath().toString()).remove(m_rootDir.toString()+'/');
+ cursor.insertText(QString(FILE_CREATE_NOTIFICATION).arg(relativePath));
+ }
+ }
+
+ if (!document->toPlainText().isEmpty())
+ cursor.insertBlock();
+
+ for (CheckableFileTreeItem *node : nodes) {
+ if (!m_files.contains(node->toFilePath()))
+ continue;
+
+ if (node->toFilePath().exists() && node->isChecked()) {
+ QString relativePath = node->toFilePath().relativePath(m_rootDir).toString();
+ cursor.insertImage(iformat);
+ cursor.insertText(QString(FILE_OVERWRITE_NOTIFICATION).arg(relativePath));
+ }
+ }
+}
+
+void CmakeGeneratorDialog::advancedVisibilityChanged(bool visible)
+{
+ if (visible) {
+ setMaximumHeight(QWIDGETSIZE_MAX);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ }
+ else {
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ int height = layout()->totalSizeHint().height();
+ setMaximumHeight(height);
+ resize(width(), height);
+ }
+}
+
+} //GenerateCmake
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h
new file mode 100644
index 00000000000..9ef428c2f4c
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+
+#ifndef CMAKEGENERATORDIALOG_H
+#define CMAKEGENERATORDIALOG_H
+
+#include "cmakegeneratordialogtreemodel.h"
+
+#include <utils/fileutils.h>
+
+#include <QDialog>
+#include <QTextEdit>
+#include <QTreeView>
+#include <QLabel>
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+
+class CmakeGeneratorDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ CmakeGeneratorDialog(const Utils::FilePath &rootDir, const Utils::FilePaths &files);
+ Utils::FilePaths getFilePaths();
+
+public slots:
+ void refreshNotificationText();
+ void advancedVisibilityChanged(bool visible);
+
+private:
+ QTreeView* createFileTree();
+ QWidget* createDetailsWidget();
+ QWidget* createButtons();
+
+private:
+ CMakeGeneratorDialogTreeModel *m_model;
+ QTextEdit *m_notifications;
+ QVariant m_warningIcon;
+ Utils::FilePath m_rootDir;
+ Utils::FilePaths m_files;
+};
+
+} //GenerateCmake
+} //QmlProjectManager
+
+#endif // CMAKEGENERATORDIALOG_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp
new file mode 100644
index 00000000000..f7b76538d37
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "cmakegeneratordialogtreemodel.h"
+#include "generatecmakelistsconstants.h"
+#include "checkablefiletreeitem.h"
+
+#include <utils/utilsicons.h>
+
+using namespace Utils;
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+
+CMakeGeneratorDialogTreeModel::CMakeGeneratorDialogTreeModel(const FilePath &rootDir,
+ const FilePaths &files, QObject *parent)
+ :QStandardItemModel(parent),
+ rootDir(rootDir),
+ m_icons(new QFileIconProvider())
+{
+ createNodes(files, invisibleRootItem());
+}
+
+CMakeGeneratorDialogTreeModel::~CMakeGeneratorDialogTreeModel()
+{
+ delete m_icons;
+}
+
+QVariant CMakeGeneratorDialogTreeModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid()) {
+ const CheckableFileTreeItem *node = constNodeForIndex(index);
+ if (role == Qt::CheckStateRole) {
+ if (!node->isDir())
+ return node->isChecked() ? Qt::Checked : Qt::Unchecked;
+ return {};
+ }
+ else if (role == Qt::DisplayRole) {
+ FilePath fullPath = node->toFilePath();
+ return QVariant(fullPath.fileName());
+ }
+ else if (role == Qt::DecorationRole) {
+ if (node->isFile())
+ return Utils::Icons::WARNING.icon();
+ if (node->isDir())
+ return m_icons->icon(QFileIconProvider::Folder);
+ else
+ return Utils::Icons::NEWFILE.icon();
+ }
+ else if (role == Qt::ToolTipRole) {
+ if (node->isFile())
+ return QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "This file already exists and will be overwritten.");
+ if (!node->toFilePath().exists())
+ return QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "This file or folder will be created.");
+ }
+ }
+
+ return QStandardItemModel::data(index, role);
+}
+
+bool CMakeGeneratorDialogTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (index.isValid()) {
+ CheckableFileTreeItem *node = nodeForIndex(index);
+ if (role == Qt::CheckStateRole) {
+ node->setChecked(value.value<bool>());
+ emit checkedStateChanged(node);
+ return true;
+ }
+ }
+
+ return QStandardItemModel::setData(index, value, role);;
+}
+
+const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::items() const
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
+ QList<QStandardItem*> standardItems = findItems("*", Qt::MatchWildcard | Qt::MatchRecursive);
+#else
+ QList<QStandardItem*> standardItems = findItems(".*", Qt::MatchRegularExpression | Qt::MatchRecursive);
+#endif
+ QList<CheckableFileTreeItem*> checkableItems;
+ for (QStandardItem *item : standardItems)
+ checkableItems.append(static_cast<CheckableFileTreeItem*>(item));
+
+ return checkableItems;
+}
+
+const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::checkedItems() const
+{
+ QList<CheckableFileTreeItem*> allItems = items();
+
+ QList<CheckableFileTreeItem*> checkedItems;
+ for (CheckableFileTreeItem *item : allItems) {
+ if (item->isChecked())
+ checkedItems.append(item);
+ }
+
+ return checkedItems;
+}
+
+bool CMakeGeneratorDialogTreeModel::checkedByDefault(const Utils::FilePath &file) const
+{
+ if (file.exists()) {
+ QString relativePath = file.relativeChildPath(rootDir).toString();
+ if (relativePath.compare(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS) == 0)
+ return false;
+ if (relativePath.endsWith(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS)
+ && relativePath.length() > QString(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS).length())
+ return true;
+ if (relativePath.compare(QmlProjectManager::GenerateCmake::Constants::FILENAME_MODULES) == 0)
+ return true;
+ if (relativePath.compare(
+ FilePath::fromString(QmlProjectManager::GenerateCmake::Constants::DIRNAME_CPP)
+ .pathAppended(QmlProjectManager::GenerateCmake::Constants::FILENAME_MAINCPP_HEADER)
+ .toString())
+ == 0)
+ return true;
+ }
+
+ return !file.exists();
+}
+
+void CMakeGeneratorDialogTreeModel::createNodes(const FilePaths &candidates, QStandardItem *parent)
+{
+ if (!parent)
+ return;
+
+ CheckableFileTreeItem *checkParent = dynamic_cast<CheckableFileTreeItem*>(parent);
+ FilePath thisDir = (parent == invisibleRootItem()) ? rootDir : checkParent->toFilePath();
+
+ for (const FilePath &file : candidates) {
+ if (file.parentDir() == thisDir) {
+ CheckableFileTreeItem *fileNode = new CheckableFileTreeItem(file);
+ fileNode->setChecked(checkedByDefault(file));
+ if (!file.exists())
+ fileNode->setChecked(true);
+ parent->appendRow(fileNode);
+ }
+ }
+
+ FilePaths directSubDirs;
+ for (const FilePath &file : candidates) {
+ FilePath dir = file.parentDir();
+ if (dir.parentDir() == thisDir && !directSubDirs.contains(dir))
+ directSubDirs.append(dir);
+ }
+
+ for (const FilePath &subDir : directSubDirs) {
+ CheckableFileTreeItem *dirNode = new CheckableFileTreeItem(subDir);
+ parent->appendRow(dirNode);
+
+ FilePaths subDirCandidates;
+ for (const FilePath &file : candidates)
+ if (file.isChildOf(subDir))
+ subDirCandidates.append(file);
+
+ createNodes(subDirCandidates, dirNode);
+ }
+}
+
+const CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::constNodeForIndex(const QModelIndex &index) const
+{
+ const QStandardItem *parent = static_cast<const QStandardItem*>(index.internalPointer());
+ const QStandardItem *item = parent->child(index.row(), index.column());
+ return static_cast<const CheckableFileTreeItem*>(item);
+}
+
+CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::nodeForIndex(const QModelIndex &index)
+{
+ QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer());
+ QStandardItem *item = parent->child(index.row(), index.column());
+ return static_cast<CheckableFileTreeItem*>(item);
+}
+
+} //GenerateCmake
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h
new file mode 100644
index 00000000000..13cd25a01d3
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#ifndef CMAKEGENERATORDIALOGTREEMODEL_H
+#define CMAKEGENERATORDIALOGTREEMODEL_H
+
+#include "checkablefiletreeitem.h"
+
+#include <QFileIconProvider>
+#include <QStandardItemModel>
+
+#include <utils/fileutils.h>
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+
+class CMakeGeneratorDialogTreeModel : public QStandardItemModel
+{
+ Q_OBJECT
+
+public:
+ CMakeGeneratorDialogTreeModel(const Utils::FilePath &rootDir,
+ const Utils::FilePaths &files, QObject *parent = nullptr);
+ ~CMakeGeneratorDialogTreeModel();
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+
+ const QList<CheckableFileTreeItem*> items() const;
+ const QList<CheckableFileTreeItem*> checkedItems() const;
+ const CheckableFileTreeItem* constNodeForIndex(const QModelIndex &index) const;
+ CheckableFileTreeItem* nodeForIndex(const QModelIndex &index);
+
+signals:
+ void checkedStateChanged(CheckableFileTreeItem *item);
+
+protected:
+ bool checkedByDefault(const Utils::FilePath &file) const;
+ Utils::FilePath rootDir;
+
+private:
+ void createNodes(const Utils::FilePaths &candidates, QStandardItem *parent);
+
+ QFileIconProvider* m_icons;
+};
+
+} //GenerateCmake
+} //QmlProjectManager
+
+
+#endif // CMAKEGENERATORDIALOGTREEMODEL_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp
new file mode 100644
index 00000000000..d64dc672503
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+#include "cmakeprojectconverter.h"
+#include "cmakeprojectconverterdialog.h"
+#include "generatecmakelists.h"
+#include "generatecmakelistsconstants.h"
+
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/icore.h>
+
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/target.h>
+
+#include <QAction>
+#include <QMessageBox>
+#include <QRegularExpression>
+
+using namespace Utils;
+using namespace QmlProjectManager::GenerateCmake::Constants;
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+
+const QString MENU_ITEM_CONVERT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
+ "Export as Latest Project Format");
+const QString ERROR_TITLE = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
+ "Creating Project");
+const QString SUCCESS_TITLE = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
+ "Creating Project");
+const QString ERROR_TEXT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
+ "Creating project failed.\n%1");
+const QString SUCCESS_TEXT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
+ "Creating project succeeded.");
+
+void CmakeProjectConverter::generateMenuEntry(QObject *parent)
+{
+ Core::ActionContainer *menu =
+ Core::ActionManager::actionContainer(Core::Constants::M_FILE);
+ auto action = new QAction(MENU_ITEM_CONVERT, parent);
+ QObject::connect(action, &QAction::triggered, CmakeProjectConverter::onConvertProject);
+ Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.ConvertToCmakeProject");
+ menu->addAction(cmd, Core::Constants::G_FILE_EXPORT);
+
+ action->setEnabled(isProjectConvertable(ProjectExplorer::SessionManager::startupProject()));
+ QObject::connect(ProjectExplorer::SessionManager::instance(),
+ &ProjectExplorer::SessionManager::startupProjectChanged, [action]() {
+ action->setEnabled(isProjectConvertable(ProjectExplorer::SessionManager::startupProject()));
+ });
+}
+
+bool CmakeProjectConverter::isProjectConvertable(const ProjectExplorer::Project *project)
+{
+ if (!project)
+ return false;
+
+ return !isProjectCurrentFormat(project);
+}
+
+const QStringList sanityCheckFiles({FILENAME_CMAKELISTS,
+ FILENAME_MODULES,
+ FILENAME_MAINQML,
+ QString(DIRNAME_CONTENT)+'/'+FILENAME_CMAKELISTS,
+ QString(DIRNAME_IMPORT)+'/'+FILENAME_CMAKELISTS,
+ QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP,
+ QString(DIRNAME_CPP)+'/'+FILENAME_ENV_HEADER,
+ QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP_HEADER
+ });
+
+bool CmakeProjectConverter::isProjectCurrentFormat(const ProjectExplorer::Project *project)
+{
+ const QmlProjectManager::QmlProject *qmlprj = qobject_cast<const QmlProjectManager::QmlProject*>(project);
+
+ if (!qmlprj)
+ return false;
+
+ FilePath rootDir = qmlprj->rootProjectDirectory();
+ for (const QString &file : sanityCheckFiles)
+ if (!rootDir.pathAppended(file).exists())
+ return false;
+
+ return true;
+}
+
+void CmakeProjectConverter::onConvertProject()
+{
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ const QmlProjectManager::QmlProject *qmlProject =
+ qobject_cast<const QmlProjectManager::QmlProject*>(project);
+ if (qmlProject) {
+ CmakeProjectConverterDialog dialog(qmlProject);
+ if (dialog.exec()) {
+ FilePath newProjectPath = dialog.newPath();
+ CmakeProjectConverter converter;
+ converter.convertProject(qmlProject, newProjectPath);
+ }
+ }
+}
+
+bool CmakeProjectConverter::convertProject(const QmlProjectManager::QmlProject *project,
+ const FilePath &targetDir)
+{
+ m_converterObjects.clear();
+ m_projectDir = project->projectDirectory();
+ m_newProjectDir = targetDir;
+ m_project = project;
+
+ m_rootDirFiles = QStringList(FILENAME_FILTER_QMLPROJECT);
+ const QString confFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+ if (!confFile.isEmpty())
+ m_rootDirFiles.append(confFile);
+
+ bool retVal = prepareAndExecute();
+
+ if (retVal) {
+ QMessageBox::information(Core::ICore::dialogParent(), SUCCESS_TITLE, SUCCESS_TEXT);
+ ProjectExplorer::ProjectExplorerPlugin::OpenProjectResult result
+ = ProjectExplorer::ProjectExplorerPlugin::openProject(newProjectFile());
+ if (!result)
+ ProjectExplorer::ProjectExplorerPlugin::showOpenProjectError(result);
+ }
+ else {
+ QMessageBox::critical(Core::ICore::dialogParent(), ERROR_TITLE, ERROR_TEXT.arg(m_errorText));
+ }
+
+ return retVal;
+}
+
+bool CmakeProjectConverter::prepareAndExecute()
+{
+ GenerateCmake::CmakeFileGenerator cmakeGenerator;
+
+ if (!performSanityCheck())
+ return false;
+ if (!prepareBaseDirectoryStructure())
+ return false;
+ if (!prepareCopy())
+ return false;
+ if (!createPreparedProject())
+ return false;
+ if (!cmakeGenerator.prepare(m_newProjectDir, false))
+ return false;
+ if (!cmakeGenerator.execute())
+ return false;
+ if (!modifyNewFiles())
+ return false;
+
+ return true;
+}
+
+bool CmakeProjectConverter::isFileBlacklisted(const Utils::FilePath &file) const
+{
+ if (!file.fileName().compare(FILENAME_CMAKELISTS))
+ return true;
+ if (!file.suffix().compare(FILENAME_SUFFIX_QMLPROJECT))
+ return true;
+ if (!file.suffix().compare(FILENAME_SUFFIX_USER))
+ return true;
+ if (m_rootDirFiles.contains(file.fileName()))
+ return true;
+
+ return false;
+}
+
+bool CmakeProjectConverter::isDirBlacklisted(const Utils::FilePath &dir) const
+{
+ if (!dir.isDir())
+ return true;
+
+ return false;
+}
+
+const QString ERROR_CANNOT_WRITE_DIR = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter",
+ "Unable to write to directory\n%1.");
+
+bool CmakeProjectConverter::performSanityCheck()
+{
+ if (!m_newProjectDir.parentDir().isWritableDir()) {
+ m_errorText = ERROR_CANNOT_WRITE_DIR.arg(m_newProjectDir.parentDir().toString());
+ return false;
+ }
+
+ return true;
+}
+
+bool CmakeProjectConverter::prepareBaseDirectoryStructure()
+{
+ addDirectory(m_newProjectDir);
+ addDirectory(contentDir());
+ addDirectory(sourceDir());
+ addDirectory(importDir());
+ addDirectory(assetDir());
+ addDirectory(assetImportDir());
+ addFile(contentDir().pathAppended(FILENAME_APPMAINQML));
+
+ return true;
+}
+
+bool CmakeProjectConverter::prepareCopy()
+{
+ FilePaths rootFiles = m_projectDir.dirEntries({m_rootDirFiles, QDir::Files});
+ for (const FilePath &file : rootFiles) {
+ addFile(file, m_newProjectDir.pathAppended(file.fileName()));
+ }
+
+ prepareCopyDirFiles(m_projectDir, contentDir());
+
+ FilePaths subDirs = m_projectDir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot);
+ for (FilePath &subDir : subDirs) {
+ if (subDir.fileName() == DIRNAME_IMPORT) {
+ prepareCopyDirTree(subDir, importDir());
+ }
+ else if (subDir.fileName() == DIRNAME_CPP) {
+ prepareCopyDirTree(subDir, sourceDir());
+ }
+ else if (subDir.fileName() == DIRNAME_ASSET) {
+ prepareCopyDirTree(subDir, assetDir());
+ }
+ else if (subDir.fileName() == DIRNAME_ASSETIMPORT) {
+ prepareCopyDirTree(subDir, assetImportDir());
+ }
+ else {
+ prepareCopyDirTree(subDir, contentDir().pathAppended(subDir.fileName()));
+ }
+ }
+
+ return true;
+}
+
+bool CmakeProjectConverter::prepareCopyDirFiles(const FilePath &dir, const FilePath &targetDir)
+{
+ FilePaths dirFiles = dir.dirEntries(QDir::Files);
+ for (FilePath file : dirFiles) {
+ if (!isFileBlacklisted(file))
+ addFile(file, targetDir.pathAppended(file.fileName()));
+ }
+
+ return true;
+}
+
+bool CmakeProjectConverter::prepareCopyDirTree(const FilePath &dir, const FilePath &targetDir)
+{
+ prepareCopyDirFiles(dir, targetDir);
+ FilePaths subDirs = dir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot);
+ for (FilePath &subDir : subDirs) {
+ if (isDirBlacklisted(subDir))
+ continue;
+ addDirectory(targetDir.pathAppended(subDir.fileName()));
+ prepareCopyDirFiles(subDir, targetDir.pathAppended(subDir.fileName()));
+ prepareCopyDirTree(subDir, targetDir.pathAppended(subDir.fileName()));
+ }
+
+ return true;
+}
+
+bool CmakeProjectConverter::addDirectory(const Utils::FilePath &target)
+{
+ return addObject(ProjectConverterObjectType::Directory, FilePath(), target);
+}
+
+bool CmakeProjectConverter::addFile(const Utils::FilePath &target)
+{
+ return addFile(FilePath(), target);
+}
+
+bool CmakeProjectConverter::addFile(const Utils::FilePath &original, const Utils::FilePath &target)
+{
+ addDirectory(target.parentDir());
+ return addObject(ProjectConverterObjectType::File, original, target);
+}
+
+bool CmakeProjectConverter::addObject(ProjectConverterObjectType type,
+ const Utils::FilePath &original, const Utils::FilePath &target)
+{
+ if (target.isChildOf(m_projectDir))
+ return false;
+
+ if (!target.isChildOf(m_newProjectDir) &&
+ ((type == ProjectConverterObjectType::Directory) && (target != m_newProjectDir))) {
+ return false;
+ }
+
+ for (ProjectConverterObject &o : m_converterObjects) {
+ if (o.target == target)
+ return false;
+ }
+
+ ProjectConverterObject object;
+ object.type = type;
+ object.target = target;
+ object.original = original;
+
+ m_converterObjects.append(object);
+
+ return true;
+}
+
+bool CmakeProjectConverter::createPreparedProject()
+{
+ for (ProjectConverterObject &pco : m_converterObjects) {
+ if (pco.type == ProjectConverterObjectType::Directory) {
+ pco.target.createDir();
+ }
+ else if (pco.type == ProjectConverterObjectType::File) {
+ if (pco.original.isEmpty()) {
+ QFile newFile(pco.target.toString());
+ newFile.open(QIODevice::WriteOnly);
+ newFile.close();
+ }
+ else {
+ pco.original.copyFile(pco.target);
+ }
+ }
+ }
+
+ return true;
+}
+
+const FilePath CmakeProjectConverter::contentDir() const
+{
+ return m_newProjectDir.pathAppended(DIRNAME_CONTENT);
+}
+
+const FilePath CmakeProjectConverter::sourceDir() const
+{
+ return m_newProjectDir.pathAppended(DIRNAME_CPP);
+}
+
+const FilePath CmakeProjectConverter::importDir() const
+{
+ return m_newProjectDir.pathAppended(DIRNAME_IMPORT);
+}
+
+const FilePath CmakeProjectConverter::assetDir() const
+{
+ return contentDir().pathAppended(DIRNAME_ASSET);
+}
+
+const FilePath CmakeProjectConverter::assetImportDir() const
+{
+ return m_newProjectDir.pathAppended(DIRNAME_ASSETIMPORT);
+}
+
+const FilePath CmakeProjectConverter::newProjectFile() const
+{
+ return m_newProjectDir.pathAppended(m_project->projectFilePath().fileName());
+}
+
+const FilePath CmakeProjectConverter::projectMainFile() const
+{
+ auto *target = m_project->activeTarget();
+ if (target && target->buildSystem()) {
+ auto buildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
+ if (buildSystem) {
+ return buildSystem->mainFilePath();
+ }
+ }
+ return {};
+}
+
+const QString CmakeProjectConverter::projectMainClass() const
+{
+ return projectMainFile().baseName();
+}
+
+bool CmakeProjectConverter::modifyNewFiles()
+{
+ return modifyAppMainQml() && modifyProjectFile();
+}
+
+const char APPMAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectappmainqml.tpl";
+
+bool CmakeProjectConverter::modifyAppMainQml()
+{
+ QString appMainQmlPath = contentDir().pathAppended(FILENAME_APPMAINQML).toString();
+ QFile appMainQml(appMainQmlPath);
+ appMainQml.open(QIODevice::ReadWrite);
+ if (!appMainQml.isOpen())
+ return false;
+
+ QString templateContent = GenerateCmake::readTemplate(APPMAIN_QMLFILE_TEMPLATE_PATH);
+ QString appMainQmlContent = templateContent.arg(projectMainClass());
+
+ appMainQml.reset();
+ appMainQml.write(appMainQmlContent.toUtf8());
+ appMainQml.close();
+
+ return true;
+}
+
+bool CmakeProjectConverter::modifyProjectFile()
+{
+ QString projectFileName = m_project->projectFilePath().fileName();
+ FilePath projectFilePath = m_newProjectDir.pathAppended(projectFileName);
+ QFile projectFile(projectFilePath.toString());
+ projectFile.open(QIODevice::ReadOnly);
+ if (!projectFile.isOpen())
+ return false;
+ QString projectFileContent = QString::fromUtf8(projectFile.readAll());
+ projectFile.close();
+
+ const QRegularExpression mainFilePattern("^\\s*mainFile:\\s*\".*\"", QRegularExpression::MultilineOption);
+ const QString mainFileString(" mainFile: \"content/App.qml\"");
+
+ projectFileContent.replace(mainFilePattern, mainFileString);
+
+ projectFile.open(QIODevice::WriteOnly|QIODevice::Truncate);
+ if (!projectFile.isOpen())
+ return false;
+ projectFile.write(projectFileContent.toUtf8());
+ projectFile.close();
+
+ return true;
+}
+
+} //GenerateCmake
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h
new file mode 100644
index 00000000000..1022f657b27
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#ifndef CMAKEPROJECTCONVERTER_H
+#define CMAKEPROJECTCONVERTER_H
+
+#include <utils/fileutils.h>
+#include <qmlprojectmanager/qmlproject.h>
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+enum ProjectConverterObjectType {
+ File,
+ Directory
+};
+
+struct ProjectConverterObject {
+ ProjectConverterObjectType type;
+ Utils::FilePath target;
+ Utils::FilePath original;
+};
+
+class CmakeProjectConverter {
+
+public:
+ bool convertProject(const QmlProjectManager::QmlProject *project,
+ const Utils::FilePath &targetDir);
+ static void generateMenuEntry(QObject *parent);
+ static void onConvertProject();
+ static bool isProjectConvertable(const ProjectExplorer::Project *project);
+ static bool isProjectCurrentFormat(const ProjectExplorer::Project *project);
+
+private:
+ bool prepareAndExecute();
+ bool isFileBlacklisted(const Utils::FilePath &file) const;
+ bool isDirBlacklisted(const Utils::FilePath &dir) const;
+ bool performSanityCheck();
+ bool prepareBaseDirectoryStructure();
+ bool prepareCopyDirFiles(const Utils::FilePath &dir, const Utils::FilePath &targetDir);
+ bool prepareCopyDirTree(const Utils::FilePath &dir, const Utils::FilePath &targetDir);
+ bool prepareCopy();
+ bool addDirectory(const Utils::FilePath &target);
+ bool addFile(const Utils::FilePath &target);
+ bool addFile(const Utils::FilePath &original, const Utils::FilePath &target);
+ bool addObject(ProjectConverterObjectType type,
+ const Utils::FilePath &original, const Utils::FilePath &target);
+ bool createPreparedProject();
+
+ const Utils::FilePath contentDir() const;
+ const Utils::FilePath sourceDir() const;
+ const Utils::FilePath importDir() const;
+ const Utils::FilePath assetDir() const;
+ const Utils::FilePath assetImportDir() const;
+ const Utils::FilePath newProjectFile() const;
+
+ const QString environmentVariable(const QString &key) const;
+ const Utils::FilePath projectMainFile() const;
+ const QString projectMainClass() const;
+ bool modifyNewFiles();
+ bool modifyAppMainQml();
+ bool modifyProjectFile();
+
+private:
+ QList<ProjectConverterObject> m_converterObjects;
+ QStringList m_rootDirFiles;
+ Utils::FilePath m_projectDir;
+ Utils::FilePath m_newProjectDir;
+ const QmlProjectManager::QmlProject *m_project;
+ QString m_errorText;
+};
+
+} //GenerateCmake
+} //QmlProjectManager
+
+#endif // CMAKEPROJECTCONVERTER_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp
new file mode 100644
index 00000000000..e2fdf82b195
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "cmakeprojectconverterdialog.h"
+
+#include <coreplugin/documentmanager.h>
+
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QGroupBox>
+#include <QLabel>
+#include <QLayout>
+#include <QPushButton>
+#include <QRegularExpression>
+
+using namespace Utils;
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+
+const QRegularExpression projectNameRegexp("^(?!(import))(?!(QtQml))(?!(QtQuick))(?:[A-Z][a-zA-Z0-9-_]*)$");
+
+static bool projectNameValidationFunction(FancyLineEdit *editor, QString *)
+{
+ return editor->text().count(projectNameRegexp);
+}
+
+static bool dirValidationFunction(FancyLineEdit *editor, QString *)
+{
+ return FilePath::fromString(editor->text()).isWritableDir();
+}
+
+const QString EXPLANATION_TEXT = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "This process creates a copy of the existing project. The new project's folder structure is adjusted for CMake build process and necessary related new files are generated.\n\nThe new project can be opened in Qt Creator using the main CMakeLists.txt file.");
+
+const QString PROJECT_NAME_LABEL = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Name:");
+
+const QString PARENT_DIR_LABEL = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Create in:");
+
+CmakeProjectConverterDialog::CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject)
+ : QDialog()
+{
+ const FilePath defaultDir = Core::DocumentManager::projectsDirectory();
+ const QString defaultName = uniqueProjectName(defaultDir, oldProject->displayName());
+
+ QLabel *mainLabel = new QLabel(EXPLANATION_TEXT, this);
+ mainLabel->setWordWrap(true);
+
+ mainLabel->setMargin(20);
+ mainLabel->setMinimumWidth(600);
+
+ m_errorLabel = new InfoLabel();
+ m_errorLabel->setType(InfoLabel::InfoType::None);
+
+ m_nameEditor = new FancyLineEdit();
+ m_nameEditor->setValidationFunction(projectNameValidationFunction);
+ m_nameEditor->setText(defaultName);
+
+ m_dirSelector = new PathChooser();
+ m_dirSelector->setExpectedKind(PathChooser::Directory);
+ m_dirSelector->setValidationFunction(dirValidationFunction);
+ m_dirSelector->setPath(defaultDir.toString());
+
+ QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
+ m_okButton = buttons->button(QDialogButtonBox::Ok);
+ m_okButton->setDefault(true);
+
+ connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ connect(m_nameEditor, &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged);
+ connect(m_dirSelector->lineEdit(), &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged);
+
+ QGroupBox *form = new QGroupBox();
+ QFormLayout *formLayout = new QFormLayout(form);
+ formLayout->addRow(PROJECT_NAME_LABEL, m_nameEditor);
+ formLayout->addRow(PARENT_DIR_LABEL, m_dirSelector);
+
+ QVBoxLayout *dialogLayout = new QVBoxLayout(this);
+ dialogLayout->addWidget(mainLabel);
+ dialogLayout->addWidget(form);
+ dialogLayout->addWidget(m_errorLabel);
+ dialogLayout->addWidget(buttons);
+
+ pathValidChanged();
+}
+
+void CmakeProjectConverterDialog::pathValidChanged()
+{
+ bool valid = isValid();
+
+ if (valid) {
+ m_newProjectDir = FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text());
+ }
+ else {
+ m_newProjectDir = FilePath();
+ }
+
+ const QString error = errorText();
+ m_errorLabel->setType(error.isEmpty() ? InfoLabel::None : InfoLabel::Warning);
+ m_errorLabel->setText(error);
+ m_okButton->setEnabled(valid);
+}
+
+const FilePath CmakeProjectConverterDialog::newPath() const
+{
+ return m_newProjectDir;
+}
+
+const QStringList blackListedStarts = {"import","QtQml","QtQuick"};
+
+const QString CmakeProjectConverterDialog::startsWithBlacklisted(const QString &text) const
+{
+ for (const QString &badWord : blackListedStarts) {
+ if (text.startsWith(badWord))
+ return badWord;
+ }
+
+ return {};
+}
+
+const QString ERROR_TEXT_NAME_EMPTY = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Name is empty.");
+const QString ERROR_TEXT_NAME_BAD_START = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Name must not start with \"%1\".");
+const QString ERROR_TEXT_NAME_LOWERCASE_START = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Name must begin with a capital letter");
+const QString ERROR_TEXT_NAME_BAD_CHARACTERS = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Name must contain only letters, numbers or characters - _.");
+
+const QString ERROR_DIR_NOT_DIR = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Target is not a directory.");
+const QString ERROR_DIR_NOT_WRITABLE = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Cannot write to target directory.");
+const QString ERROR_DIR_EXISTS = QCoreApplication::translate(
+ "QmlDesigner::CmakeProjectConverterDialog",
+ "Project directory already exists.");
+
+const QString CmakeProjectConverterDialog::errorText() const
+{
+ QString text;
+
+ if (!m_nameEditor->isValid()) {
+ QString name = m_nameEditor->text();
+
+ if (name.isEmpty())
+ return ERROR_TEXT_NAME_EMPTY;
+
+ const QString badStart = startsWithBlacklisted(text);
+ if (!badStart.isEmpty())
+ return ERROR_TEXT_NAME_BAD_START.arg(badStart);
+
+ if (name[0].isLower())
+ return ERROR_TEXT_NAME_LOWERCASE_START;
+
+ return ERROR_TEXT_NAME_BAD_CHARACTERS;
+
+ }
+
+ if (!m_dirSelector->isValid()) {
+ FilePath path = m_dirSelector->filePath();
+ if (!path.isDir())
+ return ERROR_DIR_NOT_DIR;
+ if (!path.isWritableDir())
+ return ERROR_DIR_NOT_WRITABLE;
+ }
+
+ if (FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text()).exists())
+ return ERROR_DIR_EXISTS;
+
+
+ return text;
+}
+
+const QString CmakeProjectConverterDialog::uniqueProjectName(const FilePath &dir, const QString &oldName) const
+{
+ for (unsigned i = 0; ; ++i) {
+ QString name = oldName;
+ if (i)
+ name += QString::number(i);
+ if (!dir.pathAppended(name).exists())
+ return name;
+ }
+ return oldName;
+}
+
+bool CmakeProjectConverterDialog::isValid()
+{
+ FilePath newPath = FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text());
+ return m_dirSelector->isValid() && m_nameEditor->isValid() && !newPath.exists();
+}
+
+} //GenerateCmake
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h
new file mode 100644
index 00000000000..d526adb8d8c
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+
+#ifndef CMAKEPROJECTCONVERTERDIALOG_H
+#define CMAKEPROJECTCONVERTERDIALOG_H
+
+#include <qmlprojectmanager/qmlproject.h>
+#include <utils/fancylineedit.h>
+#include <utils/filepath.h>
+#include <utils/infolabel.h>
+#include <utils/pathchooser.h>
+
+#include <QDialog>
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+
+class CmakeProjectConverterDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject);
+ const Utils::FilePath newPath() const;
+
+public slots:
+ void pathValidChanged();
+
+private:
+ const QString startsWithBlacklisted(const QString &text) const;
+ const QString errorText() const;
+ const QString uniqueProjectName(const Utils::FilePath &dir, const QString &oldName) const;
+ bool isValid();
+
+private:
+ Utils::FilePath m_newProjectDir;
+ Utils::FancyLineEdit *m_nameEditor;
+ Utils::PathChooser *m_dirSelector;
+ Utils::InfoLabel *m_errorLabel;
+ QPushButton *m_okButton;
+};
+
+} //GenerateCmake
+} //QmlProjectManager
+
+#endif // CMAKEPROJECTCONVERTERDIALOG_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
new file mode 100644
index 00000000000..613b6b03b4b
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
@@ -0,0 +1,629 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "generatecmakelists.h"
+#include "generatecmakelistsconstants.h"
+#include "cmakegeneratordialog.h"
+
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
+
+#include <projectexplorer/buildsystem.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/runcontrol.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/target.h>
+
+#include <qmlprojectmanager/qmlproject.h>
+#include <qmlprojectmanager/qmlprojectmanagerconstants.h>
+#include <qmlprojectmanager/qmlmainfileaspect.h>
+
+#include <utils/fileutils.h>
+
+#include <QAction>
+#include <QMessageBox>
+#include <QtConcurrent>
+#include <QRegularExpression>
+#include <QStringList>
+#include <QTextStream>
+
+using namespace Utils;
+using namespace QmlProjectManager::GenerateCmake::Constants;
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+bool operator==(const GeneratableFile &left, const GeneratableFile &right)
+{
+ return (left.filePath == right.filePath && left.content == right.content);
+}
+
+enum ProjectDirectoryError {
+ NoError = 0,
+ MissingContentDir = 1<<1,
+ MissingImportDir = 1<<2,
+ MissingAssetDir = 1<<3,
+ MissingAssetImportDir = 1<<4,
+ MissingCppDir = 1<<5,
+ MissingMainCMake = 1<<6,
+ MissingMainQml = 1<<7,
+ MissingAppMainQml = 1<<8,
+ MissingQmlModules = 1<<9,
+ MissingMainCpp = 1<<10,
+ MissingMainCppHeader = 1<<11,
+ MissingEnvHeader = 1<<12
+};
+
+const QString MENU_ITEM_GENERATE = QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "Generate CMake Build Files");
+
+void generateMenuEntry(QObject *parent)
+{
+ Core::ActionContainer *menu =
+ Core::ActionManager::actionContainer(Core::Constants::M_FILE);
+ auto action = new QAction(MENU_ITEM_GENERATE, parent);
+ QObject::connect(action, &QAction::triggered, GenerateCmake::onGenerateCmakeLists);
+ Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.CreateCMakeLists");
+ menu->addAction(cmd, Core::Constants::G_FILE_EXPORT);
+
+ action->setEnabled(false);
+ QObject::connect(ProjectExplorer::SessionManager::instance(),
+ &ProjectExplorer::SessionManager::startupProjectChanged,
+ [action]() {
+ auto qmlProject = qobject_cast<QmlProject *>(
+ ProjectExplorer::SessionManager::startupProject());
+ action->setEnabled(qmlProject != nullptr);
+ });
+}
+
+void onGenerateCmakeLists()
+{
+ FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory();
+
+ int projectDirErrors = isProjectCorrectlyFormed(rootDir);
+ if (projectDirErrors != NoError) {
+ showProjectDirErrorDialog(projectDirErrors);
+ if (isErrorFatal(projectDirErrors))
+ return;
+ }
+
+ CmakeFileGenerator cmakeGen;
+ cmakeGen.prepare(rootDir);
+
+ FilePaths allFiles;
+ for (const GeneratableFile &file: cmakeGen.fileQueue().queuedFiles())
+ allFiles.append(file.filePath);
+
+ CmakeGeneratorDialog dialog(rootDir, allFiles);
+ if (dialog.exec()) {
+ FilePaths confirmedFiles = dialog.getFilePaths();
+ cmakeGen.filterFileQueue(confirmedFiles);
+ cmakeGen.execute();
+ }
+}
+
+bool isErrorFatal(int error)
+{
+ if (error & MissingContentDir ||
+ error & MissingImportDir ||
+ error & MissingCppDir ||
+ error & MissingAppMainQml)
+ return true;
+
+ return false;
+}
+
+int isProjectCorrectlyFormed(const FilePath &rootDir)
+{
+ int errors = NoError;
+
+ if (!rootDir.pathAppended(DIRNAME_CONTENT).exists())
+ errors |= MissingContentDir;
+ if (!rootDir.pathAppended(DIRNAME_CONTENT).pathAppended(FILENAME_APPMAINQML).exists())
+ errors |= MissingAppMainQml;
+
+ if (!rootDir.pathAppended(DIRNAME_IMPORT).exists())
+ errors |= MissingImportDir;
+ if (!rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists())
+ errors |= MissingAssetImportDir;
+
+ if (!rootDir.pathAppended(DIRNAME_CPP).exists())
+ errors |= MissingCppDir;
+ if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP).exists())
+ errors |= MissingMainCpp;
+ if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP_HEADER).exists())
+ errors |= MissingMainCppHeader;
+ if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_ENV_HEADER).exists())
+ errors |= MissingEnvHeader;
+
+ if (!rootDir.pathAppended(FILENAME_CMAKELISTS).exists())
+ errors |= MissingMainCMake;
+ if (!rootDir.pathAppended(FILENAME_MODULES).exists())
+ errors |= MissingQmlModules;
+ if (!rootDir.pathAppended(FILENAME_MAINQML).exists())
+ errors |= MissingMainQml;
+
+ return errors;
+}
+
+const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1");
+//const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
+// "The project is not properly structured for automatically generating CMake files.\n\nThe following files or directories are missing and may be created:\n\n%1");
+const QString WARNING_TITLE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
+ "Cannot Generate CMake Files");
+//const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
+// "Problems with Generating CMake Files");
+
+void showProjectDirErrorDialog(int error)
+{
+ bool isFatal = isErrorFatal(error);
+
+ if (isFatal) {
+ QString fatalList;
+
+ if (error & MissingContentDir)
+ fatalList.append(QString(DIRNAME_CONTENT) + "\n");
+ if (error & MissingAppMainQml)
+ fatalList.append(QString(DIRNAME_CONTENT)
+ + QDir::separator()
+ + QString(FILENAME_APPMAINQML)
+ + "\n");
+ if (error & MissingCppDir)
+ fatalList.append(QString(DIRNAME_CPP) + "\n");
+ if (error & MissingImportDir)
+ fatalList.append(QString(DIRNAME_IMPORT) + "\n");
+
+ QMessageBox::critical(nullptr,
+ WARNING_TITLE_FATAL,
+ WARNING_MISSING_STRUCTURE_FATAL.arg(fatalList));
+ }
+}
+
+bool FileQueue::queueFile(const FilePath &filePath, const QString &fileContent)
+{
+ GeneratableFile file;
+ file.filePath = filePath;
+ file.content = fileContent;
+ file.fileExists = filePath.exists();
+ m_queuedFiles.append(file);
+
+ return true;
+}
+
+const QVector<GeneratableFile> FileQueue::queuedFiles() const
+{
+ return m_queuedFiles;
+}
+
+bool FileQueue::writeQueuedFiles()
+{
+ for (GeneratableFile &file: m_queuedFiles)
+ if (!writeFile(file))
+ return false;
+
+ return true;
+}
+
+bool FileQueue::writeFile(const GeneratableFile &file)
+{
+ QFile fileHandle(file.filePath.toString());
+ fileHandle.open(QIODevice::WriteOnly);
+ QTextStream stream(&fileHandle);
+ stream << file.content;
+ fileHandle.close();
+
+ return true;
+}
+
+void FileQueue::filterFiles(const Utils::FilePaths keepFiles)
+{
+ QtConcurrent::blockingFilter(m_queuedFiles, [keepFiles](const GeneratableFile &qf) {
+ return keepFiles.contains(qf.filePath);
+ });
+}
+
+QString readTemplate(const QString &templatePath)
+{
+ QFile templatefile(templatePath);
+ templatefile.open(QIODevice::ReadOnly);
+ QTextStream stream(&templatefile);
+ QString content = stream.readAll();
+ templatefile.close();
+
+ return content;
+}
+
+const QString projectEnvironmentVariable(const QString &key)
+{
+ QString value = {};
+
+ auto *target = ProjectExplorer::SessionManager::startupProject()->activeTarget();
+ if (target && target->buildSystem()) {
+ auto buildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
+ if (buildSystem) {
+ auto envItems = buildSystem->environment();
+ auto confEnv = std::find_if(envItems.begin(), envItems.end(),
+ [key](NameValueItem &item){return item.name == key;});
+ if (confEnv != envItems.end())
+ value = confEnv->value;
+ }
+ }
+ return value;
+}
+
+const QDir::Filters FILES_ONLY = QDir::Files;
+const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
+
+const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl";
+const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl";
+
+bool CmakeFileGenerator::prepare(const FilePath &rootDir, bool checkFileBelongs)
+{
+ m_checkFileIsInProject = checkFileBelongs;
+
+ FilePath contentDir = rootDir.pathAppended(DIRNAME_CONTENT);
+ FilePath importDir = rootDir.pathAppended(DIRNAME_IMPORT);
+ FilePath assetImportDir = rootDir.pathAppended(DIRNAME_ASSETIMPORT);
+
+ generateModuleCmake(contentDir);
+ generateImportCmake(importDir);
+ generateImportCmake(assetImportDir);
+ generateMainCmake(rootDir);
+ generateEntryPointFiles(rootDir);
+
+ return true;
+}
+
+const FileQueue CmakeFileGenerator::fileQueue() const
+{
+ return m_fileQueue;
+}
+
+void CmakeFileGenerator::filterFileQueue(const Utils::FilePaths &keepFiles)
+{
+ m_fileQueue.filterFiles(keepFiles);
+}
+
+bool CmakeFileGenerator::execute()
+{
+ return m_fileQueue.writeQueuedFiles();
+}
+
+const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n";
+const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
+
+void CmakeFileGenerator::generateMainCmake(const FilePath &rootDir)
+{
+ //TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all.
+ QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
+ QString appName = projectName + "App";
+
+ QString fileSection = "";
+ const QString qtcontrolsConfFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+ if (!qtcontrolsConfFile.isEmpty())
+ fileSection = QString(" FILES\n %1").arg(qtcontrolsConfFile);
+
+ QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH)
+ .arg(appName)
+ .arg(fileSection);
+
+ queueCmakeFile(rootDir, cmakeFileContent);
+
+ QString subdirIncludes;
+ subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_CONTENT));
+ subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_IMPORT));
+ if (rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists())
+ subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_ASSETIMPORT));
+
+ QString modulesAsPlugins;
+ for (const QString &moduleName : m_moduleNames)
+ modulesAsPlugins.append(" " + moduleName + "plugin\n");
+
+ QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH)
+ .arg(appName)
+ .arg(subdirIncludes)
+ .arg(modulesAsPlugins);
+
+ m_fileQueue.queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent);
+}
+
+void CmakeFileGenerator::generateImportCmake(const FilePath &dir, const QString &modulePrefix)
+{
+ if (!dir.exists())
+ return;
+
+ QString fileContent;
+
+ fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
+ FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
+ for (FilePath &subDir : subDirs) {
+ if (isDirBlacklisted(subDir))
+ continue;
+ if (getDirectoryTreeQmls(subDir).isEmpty() && getDirectoryTreeResources(subDir).isEmpty())
+ continue;
+ fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
+ QString prefix = modulePrefix.isEmpty() ?
+ modulePrefix % subDir.fileName() :
+ QString(modulePrefix + '.') + subDir.fileName();
+ if (getDirectoryQmls(subDir).isEmpty()) {
+ generateImportCmake(subDir, prefix);
+ } else {
+ generateModuleCmake(subDir, prefix);
+ }
+ }
+
+ queueCmakeFile(dir, fileContent);
+}
+
+const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
+const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
+const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
+
+void CmakeFileGenerator::generateModuleCmake(const FilePath &dir, const QString &uri)
+{
+ QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
+
+ QString singletonContent;
+ FilePaths qmldirFileList = dir.dirEntries({QStringList(FILENAME_QMLDIR), FILES_ONLY});
+ if (!qmldirFileList.isEmpty()) {
+ QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
+ for (QString &singleton : singletons) {
+ singletonContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true"));
+ }
+ }
+
+ QStringList qmlFileList = getDirectoryTreeQmls(dir);
+ QString qmlFiles;
+ for (QString &qmlFile : qmlFileList)
+ qmlFiles.append(QString(" %1\n").arg(qmlFile));
+
+ QStringList resourceFileList = getDirectoryTreeResources(dir);
+ QString resourceFiles;
+ for (QString &resourceFile : resourceFileList)
+ resourceFiles.append(QString(" %1\n").arg(resourceFile));
+
+ QString moduleContent;
+ if (!qmlFiles.isEmpty()) {
+ moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFiles));
+ }
+ if (!resourceFiles.isEmpty()) {
+ moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
+ }
+
+ QString moduleUri = uri.isEmpty() ?
+ dir.fileName() :
+ uri;
+
+ QString moduleName = QString(moduleUri).replace('.', '_');
+ m_moduleNames.append(moduleName);
+
+ QString fileContent;
+ fileContent.append(fileTemplate.arg(singletonContent, moduleName, moduleUri, moduleContent));
+ queueCmakeFile(dir, fileContent);
+}
+
+QStringList CmakeFileGenerator::getSingletonsFromQmldirFile(const FilePath &filePath)
+{
+ QStringList singletons;
+ QFile f(filePath.toString());
+ f.open(QIODevice::ReadOnly);
+ QTextStream stream(&f);
+
+ while (!stream.atEnd()) {
+ QString line = stream.readLine();
+ if (line.startsWith("singleton", Qt::CaseInsensitive)) {
+ QStringList tokenizedLine = line.split(QRegularExpression("\\s+"));
+ QString fileName = tokenizedLine.last();
+ if (fileName.endsWith(".qml", Qt::CaseInsensitive)) {
+ singletons.append(fileName);
+ }
+ }
+ }
+
+ f.close();
+
+ return singletons;
+}
+
+QStringList CmakeFileGenerator::getDirectoryQmls(const FilePath &dir)
+{
+ QStringList moduleFiles;
+
+ const QStringList qmlFilesOnly(FILENAME_FILTER_QML);
+ FilePaths allFiles = dir.dirEntries({qmlFilesOnly, FILES_ONLY});
+ for (FilePath &file : allFiles) {
+ if (includeFile(file)) {
+ moduleFiles.append(file.fileName());
+ }
+ }
+
+ return moduleFiles;
+}
+
+QStringList CmakeFileGenerator::getDirectoryResources(const FilePath &dir)
+{
+ QStringList moduleFiles;
+
+ FilePaths allFiles = dir.dirEntries(FILES_ONLY);
+ for (FilePath &file : allFiles) {
+ if (!file.fileName().endsWith(".qml", Qt::CaseInsensitive) &&
+ includeFile(file)) {
+ moduleFiles.append(file.fileName());
+ }
+ }
+
+ return moduleFiles;
+}
+
+QStringList CmakeFileGenerator::getDirectoryTreeQmls(const FilePath &dir)
+{
+ QStringList qmlFileList;
+
+ qmlFileList.append(getDirectoryQmls(dir));
+
+ FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
+ for (FilePath &subDir : subDirsList) {
+ if (isDirBlacklisted(subDir))
+ continue;
+ QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir);
+ for (QString &qmlFile : subDirQmlFiles) {
+ qmlFileList.append(subDir.fileName().append('/').append(qmlFile));
+ }
+ }
+
+ return qmlFileList;
+}
+
+QStringList CmakeFileGenerator::getDirectoryTreeResources(const FilePath &dir)
+{
+ QStringList resourceFileList;
+
+ resourceFileList.append(getDirectoryResources(dir));
+
+ FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
+ for (FilePath &subDir : subDirsList) {
+ if (isDirBlacklisted(subDir))
+ continue;
+ QStringList subDirResources = getDirectoryTreeResources(subDir);
+ for (QString &resource : subDirResources) {
+ resourceFileList.append(subDir.fileName().append('/').append(resource));
+ }
+
+ }
+
+ return resourceFileList;
+}
+
+void CmakeFileGenerator::queueCmakeFile(const FilePath &dir, const QString &content)
+{
+ FilePath filePath = dir.pathAppended(FILENAME_CMAKELISTS);
+ m_fileQueue.queueFile(filePath, content);
+}
+
+bool CmakeFileGenerator::isFileBlacklisted(const QString &fileName)
+{
+ return (!fileName.compare(FILENAME_QMLDIR) ||
+ !fileName.compare(FILENAME_CMAKELISTS));
+}
+
+bool CmakeFileGenerator::isDirBlacklisted(const FilePath &dir)
+{
+ return (!dir.fileName().compare(DIRNAME_DESIGNER));
+}
+
+bool CmakeFileGenerator::includeFile(const FilePath &filePath)
+{
+ if (m_checkFileIsInProject) {
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ if (!project->isKnownFile(filePath))
+ return false;
+ }
+
+ return !isFileBlacklisted(filePath.fileName());
+}
+
+
+bool CmakeFileGenerator::generateEntryPointFiles(const FilePath &dir)
+{
+ const QString qtcontrolsConf = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+ if (!qtcontrolsConf.isEmpty())
+ m_resourceFileLocations.append(qtcontrolsConf);
+
+ bool cppOk = generateMainCpp(dir);
+ bool qmlOk = generateMainQml(dir);
+
+ return cppOk && qmlOk;
+}
+
+const char MAIN_CPPFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
+const char MAIN_CPPFILE_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
+const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n";
+const char ENV_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl";
+const char ENV_HEADER_VARIABLE_LINE[] = " qputenv(\"%1\", \"%2\");\n";
+
+bool CmakeFileGenerator::generateMainCpp(const FilePath &dir)
+{
+ FilePath srcDir = dir.pathAppended(DIRNAME_CPP);
+
+ QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH);
+ FilePath cppFilePath = srcDir.pathAppended(FILENAME_MAINCPP);
+ bool cppOk = m_fileQueue.queueFile(cppFilePath, cppContent);
+
+ QString modulesAsPlugins;
+ for (const QString &moduleName : m_moduleNames)
+ modulesAsPlugins.append(
+ QString(MAIN_CPPFILE_HEADER_PLUGIN_LINE).arg(moduleName + "Plugin"));
+
+ QString headerContent = GenerateCmake::readTemplate(MAIN_CPPFILE_HEADER_TEMPLATE_PATH)
+ .arg(modulesAsPlugins);
+ FilePath headerFilePath = srcDir.pathAppended(FILENAME_MAINCPP_HEADER);
+ bool pluginHeaderOk = m_fileQueue.queueFile(headerFilePath, headerContent);
+
+ bool envHeaderOk = true;
+ QString environment;
+ auto *target = ProjectExplorer::SessionManager::startupProject()->activeTarget();
+ if (target && target->buildSystem()) {
+ auto buildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
+ if (buildSystem) {
+ for (EnvironmentItem &envItem : buildSystem->environment()) {
+ QString key = envItem.name;
+ QString value = envItem.value;
+ if (isFileResource(value))
+ value.prepend(":/");
+ environment.append(QString(ENV_HEADER_VARIABLE_LINE).arg(key).arg(value));
+ }
+ QString envHeaderContent = GenerateCmake::readTemplate(ENV_HEADER_TEMPLATE_PATH)
+ .arg(environment);
+ FilePath envHeaderPath = srcDir.pathAppended(FILENAME_ENV_HEADER);
+ envHeaderOk = m_fileQueue.queueFile(envHeaderPath, envHeaderContent);
+ }
+ }
+
+ return cppOk && pluginHeaderOk && envHeaderOk;
+}
+
+const char MAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl";
+
+bool CmakeFileGenerator::generateMainQml(const FilePath &dir)
+{
+ QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_TEMPLATE_PATH);
+ FilePath filePath = dir.pathAppended(FILENAME_MAINQML);
+ return m_fileQueue.queueFile(filePath, content);
+}
+
+bool CmakeFileGenerator::isFileResource(const QString &relativeFilePath)
+{
+ if (m_resourceFileLocations.contains(relativeFilePath))
+ return true;
+
+ return false;
+}
+
+} //GenerateCmake
+} //QmlProjectManager
+
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h
new file mode 100644
index 00000000000..02cf19b7028
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectexplorer/project.h>
+
+#include <utils/fileutils.h>
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+struct GeneratableFile {
+ Utils::FilePath filePath;
+ QString content;
+ bool fileExists;
+};
+
+bool operator==(const GeneratableFile &left, const GeneratableFile &right);
+
+void generateMenuEntry(QObject *parent);
+void onGenerateCmakeLists();
+bool isErrorFatal(int error);
+int isProjectCorrectlyFormed(const Utils::FilePath &rootDir);
+void showProjectDirErrorDialog(int error);
+QString readTemplate(const QString &templatePath);
+const QString projectEnvironmentVariable(const QString &key);
+
+class FileQueue {
+public:
+ bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
+ const QVector<GeneratableFile> queuedFiles() const;
+ bool writeQueuedFiles();
+ void filterFiles(const Utils::FilePaths keepFiles);
+
+private:
+ bool writeFile(const GeneratableFile &file);
+
+private:
+ QVector<GeneratableFile> m_queuedFiles;
+};
+
+class CmakeFileGenerator {
+public:
+ bool prepare(const Utils::FilePath &rootDir, bool check = true);
+ const FileQueue fileQueue() const;
+ void filterFileQueue(const Utils::FilePaths &keepFiles);
+ bool execute();
+
+private:
+ void generateMainCmake(const Utils::FilePath &rootDir);
+ void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString());
+ void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString());
+ bool generateEntryPointFiles(const Utils::FilePath &dir);
+ bool generateMainCpp(const Utils::FilePath &dir);
+ bool generateMainQml(const Utils::FilePath &dir);
+ QStringList getDirectoryQmls(const Utils::FilePath &dir);
+ QStringList getDirectoryResources(const Utils::FilePath &dir);
+ QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
+ QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
+ QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
+ void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
+ bool isFileResource(const QString &relativeFilePath);
+ bool isFileBlacklisted(const QString &fileName);
+ bool isDirBlacklisted(const Utils::FilePath &dir);
+ bool includeFile(const Utils::FilePath &filePath);
+
+private:
+ FileQueue m_fileQueue;
+ QStringList m_resourceFileLocations;
+ QStringList m_moduleNames;
+ bool m_checkFileIsInProject;
+};
+
+} //GenerateCmake
+
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h
new file mode 100644
index 00000000000..d60656d1fe3
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#ifndef GENERATECMAKELISTSCONSTANTS_H
+#define GENERATECMAKELISTSCONSTANTS_H
+
+#pragma once
+
+namespace QmlProjectManager {
+namespace GenerateCmake {
+namespace Constants {
+
+const char DIRNAME_CONTENT[] = "content";
+const char DIRNAME_IMPORT[] = "imports";
+const char DIRNAME_ASSET[] = "assets";
+const char DIRNAME_ASSETIMPORT[] = "asset_imports";
+const char DIRNAME_CPP[] = "src";
+const char DIRNAME_DESIGNER[] = "designer";
+
+const char FILENAME_CMAKELISTS[] = "CMakeLists.txt";
+const char FILENAME_APPMAINQML[] = "App.qml";
+const char FILENAME_MAINQML[] = "main.qml";
+const char FILENAME_MAINCPP[] = "main.cpp";
+const char FILENAME_MAINCPP_HEADER[] = "import_qml_plugins.h";
+const char FILENAME_MODULES[] = "qmlmodules";
+const char FILENAME_QMLDIR[] = "qmldir";
+const char FILENAME_ENV_HEADER[] = "app_environment.h";
+
+const char FILENAME_SUFFIX_QMLPROJECT[] = "qmlproject";
+const char FILENAME_SUFFIX_QML[] = "qml";
+const char FILENAME_SUFFIX_USER[] = "user";
+
+const char FILENAME_FILTER_QMLPROJECT[] = "*.qmlproject";
+const char FILENAME_FILTER_QML[] = "*.qml";
+
+const char ENV_VARIABLE_CONTROLCONF[] = "QT_QUICK_CONTROLS_CONF";
+
+} //Constants
+} //GenerateCmake
+} //QmlProjectManager
+
+#endif // GENERATECMAKELISTSCONSTANTS_H
diff --git a/src/plugins/qmldesigner/qmlprojectappmainqml.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl
index 35f8218dc65..35f8218dc65 100644
--- a/src/plugins/qmldesigner/qmlprojectappmainqml.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl
diff --git a/src/plugins/qmldesigner/qmlprojectenvheader.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl
index bf60adb4ac1..bf60adb4ac1 100644
--- a/src/plugins/qmldesigner/qmlprojectenvheader.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl
diff --git a/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl
index 423ed1a921a..423ed1a921a 100644
--- a/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl
diff --git a/src/plugins/qmldesigner/qmlprojectmaincpp.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl
index f6d614c3bb4..f6d614c3bb4 100644
--- a/src/plugins/qmldesigner/qmlprojectmaincpp.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl
diff --git a/src/plugins/qmldesigner/qmlprojectmaincppheader.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl
index 60cef09a82c..60cef09a82c 100644
--- a/src/plugins/qmldesigner/qmlprojectmaincppheader.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl
diff --git a/src/plugins/qmldesigner/qmlprojectmainqml.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl
index fa8f6d1cc18..fa8f6d1cc18 100644
--- a/src/plugins/qmldesigner/qmlprojectmainqml.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl
diff --git a/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
index e193ebf5ba1..e193ebf5ba1 100644
--- a/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
diff --git a/src/plugins/qmldesigner/qmlprojectmodules.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
index a1fdb4071dc..a1fdb4071dc 100644
--- a/src/plugins/qmldesigner/qmlprojectmodules.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
index f385cc74660..ec84d34d4a7 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
@@ -142,7 +142,8 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi
if (debug)
qDebug() << "importPath:" << importPathsProperty.value << "mainFile:" << mainFileProperty.value;
- foreach (const QmlJS::SimpleReaderNode::Ptr &childNode, rootNode->children()) {
+ const QList<QmlJS::SimpleReaderNode::Ptr> childNodes = rootNode->children();
+ for (const QmlJS::SimpleReaderNode::Ptr &childNode : childNodes) {
if (debug)
qDebug() << "reading type:" << childNode->name();
diff --git a/src/plugins/qmlprojectmanager/projectfilecontenttools.cpp b/src/plugins/qmlprojectmanager/projectfilecontenttools.cpp
new file mode 100644
index 00000000000..3de9a325d46
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/projectfilecontenttools.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "projectfilecontenttools.h"
+
+#include <projectexplorer/project.h>
+
+#include <QRegularExpression>
+#include <QRegularExpressionMatch>
+
+namespace QmlProjectManager {
+namespace ProjectFileContentTools {
+
+QRegularExpression qdsVerRegexp(R"x(qdsVersion: "(.*)")x");
+
+const Utils::FilePaths rootCmakeFiles(ProjectExplorer::Project *project)
+{
+ if (!project)
+ project = ProjectExplorer::SessionManager::startupProject();
+ if (!project)
+ return {};
+ return project->projectDirectory().dirEntries({QList<QString>({"CMakeLists.txt"}), QDir::Files});
+}
+
+const QString readFileContents(const Utils::FilePath &filePath)
+{
+ Utils::FileReader reader;
+ if (!reader.fetch(filePath))
+ return {};
+ return QString::fromUtf8(reader.data());
+}
+
+const QString qdsVersion(const Utils::FilePath &projectFilePath)
+{
+ const QString projectFileContent = readFileContents(projectFilePath);
+ QRegularExpressionMatch match = qdsVerRegexp.match(projectFileContent);
+ if (match.hasMatch()) {
+ const QString version = match.captured(1);
+ if (!version.isEmpty())
+ return version;
+ }
+
+ return QObject::tr("Unknown");
+}
+
+QRegularExpression quickRegexp("(quickVersion:)\\s*\"(\\d+.\\d+)\"",
+ QRegularExpression::CaseInsensitiveOption);
+QRegularExpression qt6Regexp("(qt6Project:)\\s*\"*(true|false)\"*",
+ QRegularExpression::CaseInsensitiveOption);
+
+const QString qtVersion(const Utils::FilePath &projectFilePath)
+{
+ const QString defaultReturn = QObject::tr("Unknown");
+ const QString data = readFileContents(projectFilePath);
+
+ // First check if quickVersion is contained in the project file
+ QRegularExpressionMatch match = quickRegexp.match(data);
+ if (match.hasMatch())
+ return QString("Qt %1").arg(match.captured(2));
+
+ // If quickVersion wasn't found check for qt6Project
+ match = qt6Regexp.match(data);
+ if (match.hasMatch())
+ return match.captured(2).contains("true", Qt::CaseInsensitive) ? QObject::tr("Qt 6")
+ : QObject::tr("Qt 5");
+
+ return defaultReturn;
+}
+
+bool isQt6Project(const Utils::FilePath &projectFilePath)
+{
+ const QString data = readFileContents(projectFilePath);
+ QRegularExpressionMatch match = qt6Regexp.match(data);
+ if (!match.hasMatch())
+ return false;
+ return match.captured(2).contains("true", Qt::CaseInsensitive);
+}
+
+const QString getMainQmlFile(const Utils::FilePath &projectFilePath)
+{
+ const QString defaultReturn = "content/App.qml";
+ const QString data = readFileContents(projectFilePath);
+ QRegularExpression regexp(R"x(mainFile: "(.*)")x");
+ QRegularExpressionMatch match = regexp.match(data);
+ if (!match.hasMatch())
+ return defaultReturn;
+ return match.captured(1);
+}
+
+const QString appQmlFile(const Utils::FilePath &projectFilePath)
+{
+ return projectFilePath.toFileInfo().dir().absolutePath() + "/" + getMainQmlFile(projectFilePath);
+}
+
+const Resolution resolutionFromConstants(const Utils::FilePath &projectFilePath)
+{
+ const QFileInfo fileInfo = projectFilePath.toFileInfo();
+ const QString fileName = fileInfo.dir().absolutePath()
+ + "/" + "imports" + "/" + fileInfo.baseName() + "/Constants.qml";
+ Utils::FileReader reader;
+ if (!reader.fetch(Utils::FilePath::fromString(fileName)))
+ return {};
+ const QByteArray data = reader.data();
+ const QRegularExpression regexpWidth(R"x(readonly\s+property\s+int\s+width:\s+(\d*))x");
+ const QRegularExpression regexpHeight(R"x(readonly\s+property\s+int\s+height:\s+(\d*))x");
+ int width = -1;
+ int height = -1;
+ QRegularExpressionMatch match = regexpHeight.match(QString::fromUtf8(data));
+ if (match.hasMatch())
+ height = match.captured(1).toInt();
+ match = regexpWidth.match(QString::fromUtf8(data));
+ if (match.hasMatch())
+ width = match.captured(1).toInt();
+ if (width > 0 && height > 0)
+ return {width, height};
+ return {};
+}
+
+} //ProjectFileContentTools
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/projectfilecontenttools.h b/src/plugins/qmlprojectmanager/projectfilecontenttools.h
new file mode 100644
index 00000000000..3fe4fd003a5
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/projectfilecontenttools.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "qmlprojectmanager_global.h"
+
+#include <projectexplorer/projectmanager.h>
+#include <projectexplorer/session.h>
+
+#include <utils/fileutils.h>
+
+namespace QmlProjectManager {
+namespace ProjectFileContentTools {
+
+struct QMLPROJECTMANAGER_EXPORT Resolution {
+ int width;
+ int height;
+};
+
+const Utils::FilePaths QMLPROJECTMANAGER_EXPORT rootCmakeFiles(ProjectExplorer::Project *project = nullptr);
+const QString QMLPROJECTMANAGER_EXPORT readFileContents(const Utils::FilePath &filePath);
+const QString QMLPROJECTMANAGER_EXPORT qdsVersion(const Utils::FilePath &projectFilePath);
+const QString QMLPROJECTMANAGER_EXPORT qtVersion(const Utils::FilePath &projectFilePath);
+const QString QMLPROJECTMANAGER_EXPORT getMainQmlFile(const Utils::FilePath &projectFilePath);
+const QString QMLPROJECTMANAGER_EXPORT appQmlFile(const Utils::FilePath &projectFilePath);
+const Resolution QMLPROJECTMANAGER_EXPORT resolutionFromConstants(const Utils::FilePath &projectFilePath);
+
+} //ProjectFileContentTools
+} //QmlProjectManager
+
diff --git a/src/plugins/qmlprojectmanager/qdslandingpage.cpp b/src/plugins/qmlprojectmanager/qdslandingpage.cpp
new file mode 100644
index 00000000000..d9fbe8be232
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qdslandingpage.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qdslandingpage.h"
+#include "projectfilecontenttools.h"
+#include "qdslandingpagetheme.h"
+#include "qmlprojectconstants.h"
+#include "qmlprojectgen/qmlprojectgenerator.h"
+#include "qmlprojectplugin.h"
+#include "utils/algorithm.h"
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/modemanager.h>
+
+#include <QDesktopServices>
+#include <QHBoxLayout>
+#include <QQuickItem>
+#include <QtQml/QQmlEngine>
+
+namespace QmlProjectManager {
+namespace Internal {
+
+const char INSTALL_QDS_URL[] = "https://www.qt.io/product/ui-design-tools";
+
+QdsLandingPageWidget::QdsLandingPageWidget(QWidget* parent)
+ : QWidget(parent)
+{
+ setLayout(new QHBoxLayout());
+ layout()->setContentsMargins(0, 0, 0, 0);
+}
+
+QdsLandingPageWidget::~QdsLandingPageWidget()
+{
+ if (m_widget)
+ m_widget->deleteLater();
+}
+
+QQuickWidget *QdsLandingPageWidget::widget()
+{
+ if (!m_widget) {
+ m_widget = new QQuickWidget();
+
+ const QString resourcePath
+ = Core::ICore::resourcePath(QmlProjectManager::Constants::QML_RESOURCE_PATH).toString();
+ const QString landingPath
+ = Core::ICore::resourcePath(QmlProjectManager::Constants::LANDING_PAGE_PATH).toString();
+
+ QdsLandingPageTheme::setupTheme(m_widget->engine());
+
+ m_widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ m_widget->engine()->addImportPath(landingPath + "/imports");
+ m_widget->engine()->addImportPath(resourcePath);
+ m_widget->setSource(QUrl::fromLocalFile(landingPath + "/main.qml"));
+ m_widget->hide();
+
+ layout()->addWidget(m_widget);
+ }
+
+ return m_widget;
+}
+
+QdsLandingPage::QdsLandingPage()
+ : m_widget{nullptr}
+{}
+
+void QdsLandingPage::openQtc(bool rememberSelection)
+{
+ if (rememberSelection)
+ Core::ICore::settings()->setValue(QmlProjectManager::Constants::ALWAYS_OPEN_UI_MODE,
+ Core::Constants::MODE_EDIT);
+
+ hide();
+
+ Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
+}
+
+void QdsLandingPage::openQds(bool rememberSelection)
+{
+ if (rememberSelection)
+ Core::ICore::settings()->setValue(QmlProjectManager::Constants::ALWAYS_OPEN_UI_MODE,
+ Core::Constants::MODE_DESIGN);
+
+ auto editor = Core::EditorManager::currentEditor();
+ if (editor)
+ QmlProjectPlugin::openInQDSWithProject(editor->document()->filePath());
+}
+
+void QdsLandingPage::installQds()
+{
+ QDesktopServices::openUrl(QUrl(INSTALL_QDS_URL));
+}
+
+void QdsLandingPage::generateProjectFile()
+{
+ GenerateQmlProject::QmlProjectFileGenerator generator;
+
+ Core::IEditor *editor = Core::EditorManager::currentEditor();
+ if (!editor)
+ return;
+
+ if (generator.prepareForUiQmlFile(editor->document()->filePath())) {
+ if (generator.execute()) {
+ const QString qtVersion = ProjectFileContentTools::qtVersion(generator.targetFile());
+ const QString qdsVersion = ProjectFileContentTools::qdsVersion(generator.targetFile());
+ setProjectFileExists(generator.targetFile().exists());
+ setQtVersion(qtVersion);
+ setQdsVersion(qdsVersion);
+ }
+ }
+}
+
+void QdsLandingPage::setWidget(QWidget *widget)
+{
+ m_widget = widget;
+}
+
+QWidget *QdsLandingPage::widget()
+{
+ return m_widget;
+}
+
+void QdsLandingPage::show()
+{
+ if (!m_widget)
+ return;
+
+ m_widget->show();
+}
+
+void QdsLandingPage::hide()
+{
+ if (!m_widget)
+ return;
+
+ m_widget->hide();
+}
+
+bool QdsLandingPage::qdsInstalled() const
+{
+ return m_qdsInstalled;
+}
+
+void QdsLandingPage::setQdsInstalled(bool installed)
+{
+ if (m_qdsInstalled != installed) {
+ m_qdsInstalled = installed;
+ emit qdsInstalledChanged();
+ }
+}
+
+bool QdsLandingPage::projectFileExists() const
+{
+ return m_projectFileExists;
+}
+
+void QdsLandingPage::setProjectFileExists(bool exists)
+{
+ if (m_projectFileExists != exists) {
+ m_projectFileExists = exists;
+ emit projectFileExistshanged();
+ }
+}
+
+const QString QdsLandingPage::qtVersion() const
+{
+ return m_qtVersion;
+}
+
+void QdsLandingPage::setQtVersion(const QString &version)
+{
+ if (m_qtVersion != version) {
+ m_qtVersion = version;
+ emit qtVersionChanged();
+ }
+}
+
+const QString QdsLandingPage::qdsVersion() const
+{
+ return m_qdsVersion;
+}
+
+void QdsLandingPage::setQdsVersion(const QString &version)
+{
+ if (m_qdsVersion != version) {
+ m_qdsVersion = version;
+ emit qdsVersionChanged();
+ }
+}
+
+const QStringList QdsLandingPage::cmakeResources() const
+{
+ return m_cmakeResources;
+}
+
+void QdsLandingPage::setCmakeResources(const Utils::FilePaths &resources)
+{
+ QStringList strings = Utils::transform(resources,
+ [](const Utils::FilePath &path)
+ { return path.fileName(); });
+ setCmakeResources(strings);
+}
+
+void QdsLandingPage::setCmakeResources(const QStringList &resources)
+{
+ m_cmakeResources = resources;
+}
+
+} // namespace Internal
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qdslandingpage.h b/src/plugins/qmlprojectmanager/qdslandingpage.h
new file mode 100644
index 00000000000..7162705021e
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qdslandingpage.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <coreplugin/icontext.h>
+
+#include <utils/filepath.h>
+
+#include <QtQuickWidgets/QQuickWidget>
+
+namespace QmlProjectManager {
+namespace Internal {
+
+class DesignModeContext : public Core::IContext
+{
+ Q_OBJECT
+
+public:
+ DesignModeContext(QWidget *widget) : Core::IContext(widget) { setWidget(widget); }
+};
+
+class QdsLandingPageWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QdsLandingPageWidget(QWidget* parent = nullptr);
+ ~QdsLandingPageWidget();
+ QQuickWidget *widget();
+
+private:
+ QQuickWidget *m_widget = nullptr;
+};
+
+class QdsLandingPage : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q_PROPERTY(bool qdsInstalled MEMBER m_qdsInstalled READ qdsInstalled WRITE setQdsInstalled
+ NOTIFY qdsInstalledChanged)
+ Q_PROPERTY(bool projectFileExists MEMBER m_projectFileExists READ projectFileExists WRITE
+ setProjectFileExists NOTIFY projectFileExistshanged)
+ Q_PROPERTY(QString qtVersion MEMBER m_qtVersion READ qtVersion WRITE setQtVersion NOTIFY
+ qtVersionChanged)
+ Q_PROPERTY(QString qdsVersion MEMBER m_qdsVersion READ qdsVersion WRITE setQdsVersion NOTIFY
+ qdsVersionChanged)
+
+public:
+ QdsLandingPage();
+
+ Q_INVOKABLE void openQtc(bool rememberSelection);
+ Q_INVOKABLE void openQds(bool rememberSelection);
+ Q_INVOKABLE void installQds();
+ Q_INVOKABLE void generateProjectFile();
+
+ void setWidget(QWidget *widget);
+ QWidget *widget();
+ void show();
+ void hide();
+
+ bool qdsInstalled() const;
+ void setQdsInstalled(bool installed);
+ bool projectFileExists() const;
+ void setProjectFileExists(bool exists);
+ const QString qtVersion() const;
+ void setQtVersion(const QString &version);
+ const QString qdsVersion() const;
+ void setQdsVersion(const QString &version);
+ const QStringList cmakeResources() const;
+ void setCmakeResources(const Utils::FilePaths &resources);
+ void setCmakeResources(const QStringList &resources);
+
+signals:
+ void qdsInstalledChanged();
+ void projectFileExistshanged();
+ void qtVersionChanged();
+ void qdsVersionChanged();
+
+private:
+ QWidget *m_widget = nullptr;
+
+ bool m_qdsInstalled = false;
+ bool m_projectFileExists = false;
+ QString m_qtVersion;
+ QString m_qdsVersion;
+ QStringList m_cmakeResources;
+};
+
+} // namespace Internal
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qdslandingpagetheme.cpp b/src/plugins/qmlprojectmanager/qdslandingpagetheme.cpp
new file mode 100644
index 00000000000..00a49a974e6
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qdslandingpagetheme.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qdslandingpagetheme.h"
+
+#include "qmlprojectplugin.h"
+
+#include <coreplugin/icore.h>
+
+#include <QQmlEngine>
+#include <QQmlComponent>
+
+namespace QmlProjectManager {
+
+QdsLandingPageTheme::QdsLandingPageTheme(Utils::Theme *originTheme, QObject *parent)
+ : Utils::Theme(originTheme, parent)
+{
+
+}
+
+void QdsLandingPageTheme::setupTheme(QQmlEngine *engine)
+{
+ Q_UNUSED(engine)
+
+ static const int typeIndex = qmlRegisterSingletonType<QdsLandingPageTheme>(
+ "LandingPageTheme", 1, 0, "Theme", [](QQmlEngine *, QJSEngine *) {
+ return new QdsLandingPageTheme(Utils::creatorTheme(), nullptr);
+ });
+ QScopedPointer<QdsLandingPageTheme> theme(new QdsLandingPageTheme(Utils::creatorTheme(), nullptr));
+
+ Q_UNUSED(typeIndex)
+}
+
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qdslandingpagetheme.h b/src/plugins/qmlprojectmanager/qdslandingpagetheme.h
new file mode 100644
index 00000000000..0befcdf89e7
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qdslandingpagetheme.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <qqmlengine.h>
+
+#include <utils/theme/theme.h>
+
+namespace QmlProjectManager {
+
+class QdsLandingPageTheme : public Utils::Theme
+{
+ Q_OBJECT
+ QML_SINGLETON
+
+public:
+ static void setupTheme(QQmlEngine *engine);
+
+private:
+ QdsLandingPageTheme(Utils::Theme *originTheme, QObject *parent);
+};
+
+} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp
index 2667fcb66b1..9eaeaddd4c9 100644
--- a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp
+++ b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp
@@ -27,7 +27,6 @@
#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
-#include "qmlprojectrunconfiguration.h"
#include <qmljstools/qmljstoolsconstants.h>
@@ -35,16 +34,18 @@
#include <coreplugin/editormanager/ieditor.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/algorithm.h>
+#include <utils/layoutbuilder.h>
+#include <utils/mimeutils.h>
#include <QComboBox>
-#include <utils/layoutbuilder.h>
-
using namespace Core;
using namespace ProjectExplorer;
+using namespace Utils;
namespace QmlProjectManager {
@@ -60,6 +61,9 @@ QmlMainFileAspect::QmlMainFileAspect(Target *target)
: m_target(target)
, m_scriptFile(M_CURRENT_FILE)
{
+ addDataExtractor(this, &QmlMainFileAspect::mainScript, &Data::mainScript);
+ addDataExtractor(this, &QmlMainFileAspect::currentFile, &Data::currentFile);
+
connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
this, &QmlMainFileAspect::changeCurrentFile);
connect(EditorManager::instance(), &EditorManager::currentDocumentStateChanged,
@@ -71,7 +75,7 @@ QmlMainFileAspect::~QmlMainFileAspect()
delete m_fileListCombo;
}
-void QmlMainFileAspect::addToLayout(Utils::LayoutBuilder &builder)
+void QmlMainFileAspect::addToLayout(LayoutBuilder &builder)
{
QTC_ASSERT(!m_fileListCombo, delete m_fileListCombo);
m_fileListCombo = new QComboBox;
@@ -234,7 +238,7 @@ bool QmlMainFileAspect::isQmlFilePresent()
bool qmlFileFound = false;
if (mainScriptSource() == FileInEditor) {
IDocument *document = EditorManager::currentDocument();
- Utils::MimeType mainScriptMimeType = Utils::mimeTypeForFile(mainScript());
+ const MimeType mainScriptMimeType = mimeTypeForFile(mainScript());
if (document) {
m_currentFileFilename = document->filePath().toString();
if (mainScriptMimeType.matchesName(ProjectExplorer::Constants::QML_MIMETYPE)
@@ -247,11 +251,9 @@ bool QmlMainFileAspect::isQmlFilePresent()
// find a qml file with lowercase filename. This is slow, but only done
// in initialization/other border cases.
const auto files = m_target->project()->files(Project::SourceFiles);
- for (const Utils::FilePath &filename : files) {
- const QFileInfo fi = filename.toFileInfo();
-
- if (!filename.isEmpty() && fi.baseName().at(0).isLower()) {
- Utils::MimeType type = Utils::mimeTypeForFile(fi);
+ for (const FilePath &filename : files) {
+ if (!filename.isEmpty() && filename.baseName().at(0).isLower()) {
+ const MimeType type = mimeTypeForFile(filename);
if (type.matchesName(ProjectExplorer::Constants::QML_MIMETYPE)
|| type.matchesName(ProjectExplorer::Constants::QMLUI_MIMETYPE)) {
m_currentFileFilename = filename.toString();
diff --git a/src/plugins/qmlprojectmanager/qmlmainfileaspect.h b/src/plugins/qmlprojectmanager/qmlmainfileaspect.h
index 7eacb128b22..ede3d8f4117 100644
--- a/src/plugins/qmlprojectmanager/qmlmainfileaspect.h
+++ b/src/plugins/qmlprojectmanager/qmlmainfileaspect.h
@@ -47,6 +47,7 @@ class QmlBuildSystem;
class QMLPROJECTMANAGER_EXPORT QmlMainFileAspect : public Utils::BaseAspect
{
Q_OBJECT
+
public:
explicit QmlMainFileAspect(ProjectExplorer::Target *target);
~QmlMainFileAspect() override;
@@ -57,6 +58,12 @@ public:
FileInSettings
};
+ struct Data : BaseAspect::Data
+ {
+ QString mainScript;
+ QString currentFile;
+ };
+
void addToLayout(Utils::LayoutBuilder &builder) final;
void toMap(QVariantMap &map) const final;
void fromMap(const QVariantMap &map) final;
@@ -74,7 +81,6 @@ public:
QmlBuildSystem *qmlBuildSystem() const;
public:
-
ProjectExplorer::Target *m_target = nullptr;
QPointer<QComboBox> m_fileListCombo;
QStandardItemModel m_fileListModel;
diff --git a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp
index dc57689cad9..c1e74e0a167 100644
--- a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp
+++ b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp
@@ -30,6 +30,7 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -81,6 +82,16 @@ QmlMultiLanguageAspect::QmlMultiLanguageAspect(ProjectExplorer::Target *target)
setDefaultValue(!databaseFilePath().isEmpty());
QVariantMap getDefaultValues;
fromMap(getDefaultValues);
+
+ addDataExtractor(this, &QmlMultiLanguageAspect::origin, &Data::origin);
+
+ connect(this, &BoolAspect::changed, this, [this] {
+ for (ProjectExplorer::RunControl *runControl :
+ ProjectExplorer::ProjectExplorerPlugin::allRunControls()) {
+ if (runControl->aspect<QmlMultiLanguageAspect>()->origin == this)
+ runControl->initiateStop();
+ }
+ });
}
QmlMultiLanguageAspect::~QmlMultiLanguageAspect()
diff --git a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.h b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.h
index 5eae6c78948..bc58b32b505 100644
--- a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.h
+++ b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.h
@@ -50,10 +50,17 @@ public:
static QmlMultiLanguageAspect *current(ProjectExplorer::Project *project);
static QmlMultiLanguageAspect *current(ProjectExplorer::Target *target);
+ struct Data : BaseAspect::Data
+ {
+ const void *origin = nullptr;
+ };
+
signals:
void currentLocaleChanged(const QString &locale);
private:
+ const void *origin() const { return this; }
+
ProjectExplorer::Target *m_target = nullptr;
mutable Utils::FilePath m_databaseFilePath;
QString m_currentLocale;
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 49181e4a2dd..ba00ad797fd 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -30,8 +30,6 @@
#include "qmlprojectconstants.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectnodes.h"
-#include "qmlprojectplugin.h"
-#include "qmlprojectrunconfiguration.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/documentmodel.h>
@@ -42,8 +40,11 @@
#include <coreplugin/messagemanager.h>
#include <projectexplorer/deploymentdata.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <qtsupport/baseqtversion.h>
@@ -56,6 +57,7 @@
#include <utils/algorithm.h>
#include <utils/infobar.h>
+#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <QDebug>
@@ -107,25 +109,11 @@ QmlProject::QmlProject(const Utils::FilePath &fileName)
setNeedsBuildConfigurations(false);
setBuildSystemCreator([](Target *t) { return new QmlBuildSystem(t); });
- if (!QmlProject::isQtDesignStudio()) {
- if (QmlProjectPlugin::qdsInstallationExists()) {
- auto lambda = [fileName]() {
- if (Core::ICore::infoBar()->canInfoBeAdded(openInQDSAppSetting)) {
- Utils::InfoBarEntry
- info(openInQDSAppSetting,
- tr("Would you like to open the project in Qt Design Studio?"),
- Utils::InfoBarEntry::GlobalSuppression::Disabled);
- info.addCustomButton(tr("Open in Qt Design Studio"), [&, fileName] {
- Core::ICore::infoBar()->removeInfo(openInQDSAppSetting);
- QmlProjectPlugin::openQDS(fileName);
- });
- Core::ICore::infoBar()->addInfo(info);
- }
- };
+ if (QmlProject::isQtDesignStudio()) {
+
+ EditorManager::closeAllDocuments();
+ SessionManager::closeAllProjects();
- QTimer::singleShot(0, this, lambda);
- }
- } else {
m_openFileConnection
= connect(this,
&QmlProject::anyParsingFinished,
@@ -336,7 +324,8 @@ void QmlBuildSystem::refresh(RefreshOptions options)
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
modelManager->defaultProjectInfoForProject(project());
- foreach (const QString &searchPath, makeAbsolute(canonicalProjectDir(), customImportPaths()))
+ const QStringList searchPaths = makeAbsolute(canonicalProjectDir(), customImportPaths());
+ for (const QString &searchPath : searchPaths)
projectInfo.importPaths.maybeInsert(Utils::FilePath::fromString(searchPath),
QmlJS::Dialect::Qml);
@@ -610,6 +599,10 @@ Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *erro
auto setKitWithVersion = [&](int qtMajorVersion) {
const QList<Kit *> qtVersionkits
= Utils::filtered(kits, [qtMajorVersion](const Kit *k) {
+ if (!k->isAutoDetected())
+ return false;
+ if (k->isReplacementKit())
+ return false;
QtSupport::QtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
return (version && version->qtVersion().majorVersion == qtMajorVersion);
});
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index a5ce067be69..5d9dc15b7c7 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -26,7 +26,6 @@
#pragma once
#include "qmlprojectmanager_global.h"
-#include "qmlprojectnodes.h"
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/project.h>
diff --git a/src/plugins/qmlprojectmanager/qmlprojectconstants.h b/src/plugins/qmlprojectmanager/qmlprojectconstants.h
index 3ba2b101462..89d3cc630d3 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectconstants.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectconstants.h
@@ -43,5 +43,9 @@ const char customImportPaths[] = "CustomImportPaths";
const char canonicalProjectDir[] ="CanonicalProjectDir";
const char enviromentLaunchedQDS[] = "QTC_LAUNCHED_QDS";
+
+const char ALWAYS_OPEN_UI_MODE[] = "J.QtQuick/QmlJSEditor.openUiQmlMode";
+const char QML_RESOURCE_PATH[] = "qmldesigner/propertyEditorQmlSources/imports";
+const char LANDING_PAGE_PATH[] = "qmldesigner/landingpage";
} // namespace Constants
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectgen/qmlproject.tpl b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlproject.tpl
new file mode 100644
index 00000000000..28543b4a7d3
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlproject.tpl
@@ -0,0 +1,72 @@
+import QmlProject
+
+Project {
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+
+%1
+%2
+%3
+%4
+
+ Files {
+ filter: "*.conf"
+ files: ["qtquickcontrols2.conf"]
+ }
+
+ Files {
+ filter: "qmldir"
+ directory: "."
+ }
+
+ Files {
+ filter: "*.ttf;*.otf"
+ }
+
+ Files {
+ filter: "*.wav;*.mp3"
+ }
+
+ Files {
+ filter: "*.mp4"
+ }
+
+ Files {
+ filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag"
+ }
+
+ Environment {
+ QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
+ QT_AUTO_SCREEN_SCALE_FACTOR: "1"
+ QT_LOGGING_RULES: "qt.qml.connections=false"
+ QT_ENABLE_HIGHDPI_SCALING: "0"
+ /* Useful for debugging
+ QSG_VISUALIZE=batches
+ QSG_VISUALIZE=clip
+ QSG_VISUALIZE=changes
+ QSG_VISUALIZE=overdraw
+ */
+ }
+
+ qt6Project: true
+ createdInQtCreator: true
+ qdsVersion: "3.4"
+
+ %5
+
+ /* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */
+ widgetApp: true
+
+ /* args: Specifies command line arguments for qsb tool to generate shaders.
+ files: Specifies target files for qsb tool. If path is included, it must be relative to this file.
+ Wildcard '*' can be used in the file name part of the path.
+ e.g. files: [ "content/shaders/*.vert", "*.frag" ] */
+ ShaderTool {
+ args: "-s --glsl \\\"100 es,120,150\\\" --hlsl 50 --msl 12"
+ files: [ "content/shaders/*" ]
+ }
+
+ multilanguageSupport: true
+ supportedLanguages: ["en"]
+ primaryLanguage: "en"
+}
diff --git a/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp
new file mode 100644
index 00000000000..b33278f3783
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmlprojectgenerator.h"
+#include "../cmakegen/generatecmakelists.h"
+
+#include <coreplugin/documentmanager.h>
+#include <coreplugin/icore.h>
+
+#include <QMessageBox>
+
+using namespace Utils;
+
+namespace QmlProjectManager {
+namespace GenerateQmlProject {
+
+bool QmlProjectFileGenerator::prepareForUiQmlFile(const FilePath &uiQmlFilePath)
+{
+ return prepare(selectTargetFile(uiQmlFilePath));
+}
+
+bool QmlProjectFileGenerator::prepare(const FilePath &targetDir)
+{
+ m_targetFile = targetDir.isEmpty() ? selectTargetFile() : targetDir;
+ m_targetDir = m_targetFile.parentDir();
+
+ return true;
+}
+
+const char QMLPROJECT_FILE_TEMPLATE_PATH[] = ":/projectfiletemplates/qmlproject.tpl";
+const char FILE_QML[] = "*.qml";
+const char FILE_JS[] = "*.js";
+const char FILE_JPG[] = "*.jpg";
+const char FILE_PNG[] = "*.png";
+const char FILE_GIF[] = "*.gif";
+const char FILE_MESH[] = "*.mesh";
+const char BLOCKTITLE_QML[] = "QmlFiles";
+const char BLOCKTITLE_IMAGE[] = "ImageFiles";
+const char BLOCKTITLE_JS[] = "JavaScriptFiles";
+const char BLOCK_CONTENTDIR[] = "\n %1 {\n directory: \"%2\"\n }\n";
+const char BLOCK_FILTEREDDIR[] = "\n Files {\n filter: \"%1\"\n directory: \"%2\"\n }\n";
+const char BLOCK_DIRARRAY[] = "\n %1: [ %2 ]\n";
+
+bool QmlProjectFileGenerator::execute()
+{
+ static const QStringList filesQml = {FILE_QML};
+ static const QStringList filesImage = {FILE_PNG, FILE_JPG, FILE_GIF};
+ static const QStringList filesJs = {FILE_QML, FILE_JS};
+ static const QStringList filesAsset = {FILE_MESH};
+
+ if (m_targetFile.isEmpty() || !m_targetDir.isWritableDir())
+ return false;
+
+ const QString contentEntry = createContentDirEntries(BLOCKTITLE_QML, filesQml);
+ const QString imageEntry = createContentDirEntries(BLOCKTITLE_IMAGE, filesImage);
+ const QString jsEntry = createContentDirEntries(BLOCKTITLE_JS, filesJs);
+ const QString assetEntry = createFilteredDirEntries(filesAsset);
+ QStringList importDirs = findContentDirs(filesQml + filesAsset);
+ importDirs.removeAll(".");
+ importDirs.removeAll("content");
+ const QString importPaths = createDirArrayEntry("importPaths", importDirs);
+
+ const QString fileContent = GenerateCmake::readTemplate(QMLPROJECT_FILE_TEMPLATE_PATH)
+ .arg(contentEntry, imageEntry, jsEntry, assetEntry, importPaths);
+
+ QFile file(m_targetFile.toString());
+ file.open(QIODevice::WriteOnly);
+ if (!file.isOpen())
+ return false;
+
+ file.reset();
+ file.write(fileContent.toUtf8());
+ file.close();
+
+ QMessageBox::information(Core::ICore::dialogParent(),
+ QObject::tr("Project File Generated"),
+ QObject::tr("File created:\n\n%1").arg(m_targetFile.toString()),
+ QMessageBox::Ok);
+
+ return true;
+}
+
+const FilePath QmlProjectFileGenerator::targetDir() const
+{
+ return m_targetDir;
+}
+
+const FilePath QmlProjectFileGenerator::targetFile() const
+{
+ return m_targetFile;
+}
+
+bool QmlProjectFileGenerator::isStandardStructure(const FilePath &projectDir) const
+{
+ if (projectDir.pathAppended("content").isDir() &&
+ projectDir.pathAppended("imports").isDir())
+ return true;
+
+ return false;
+}
+
+const QString QmlProjectFileGenerator::createContentDirEntries(const QString &containerName,
+ const QStringList &suffixes) const
+{
+ QString entries;
+
+ const QStringList contentDirs = findContentDirs(suffixes);
+ for (const QString &dir : contentDirs)
+ entries.append(QString(BLOCK_CONTENTDIR).arg(containerName, dir));
+
+ return entries;
+}
+
+const QString QmlProjectFileGenerator::createFilteredDirEntries(const QStringList &suffixes) const
+{
+ QString entries;
+ const QString filterList = suffixes.join(';');
+
+ const QStringList contentDirs = findContentDirs(suffixes);
+ for (const QString &dir : contentDirs)
+ entries.append(QString(BLOCK_FILTEREDDIR).arg(filterList, dir));
+
+ return entries;
+}
+
+const QString QmlProjectFileGenerator::createDirArrayEntry(const QString &arrayName,
+ const QStringList &relativePaths) const
+{
+ if (relativePaths.isEmpty())
+ return {};
+
+ QStringList formattedDirs = relativePaths;
+ for (QString &dir : formattedDirs)
+ dir.append('"').prepend('"');
+
+ return QString(BLOCK_DIRARRAY).arg(arrayName, formattedDirs.join(", "));
+}
+
+const FilePath QmlProjectFileGenerator::selectTargetFile(const FilePath &uiFilePath)
+{
+ FilePath suggestedDir;
+
+ if (!uiFilePath.isEmpty())
+ if (uiFilePath.parentDir().parentDir().exists())
+ suggestedDir = uiFilePath.parentDir().parentDir();
+
+ if (suggestedDir.isEmpty())
+ suggestedDir = FilePath::fromString(QDir::homePath());
+
+ FilePath targetFile;
+ bool selectionCompleted = false;
+ do {
+ targetFile = Core::DocumentManager::getSaveFileNameWithExtension(
+ QObject::tr("Select File Location"),
+ suggestedDir,
+ QObject::tr("Qt Design Studio Project Files (*.qmlproject)"));
+ selectionCompleted = isDirAcceptable(targetFile.parentDir(), uiFilePath);
+ } while (!selectionCompleted);
+
+ return targetFile;
+}
+
+bool QmlProjectFileGenerator::isDirAcceptable(const FilePath &dir, const FilePath &uiFile)
+{
+ const FilePath uiFileParentDir = uiFile.parentDir();
+
+ if (dir.isChildOf(uiFileParentDir)) {
+ QMessageBox::warning(Core::ICore::dialogParent(),
+ QObject::tr("Invalid Directory"),
+ QObject::tr("Project file must be placed in a parent directory of the QML files."),
+ QMessageBox::Ok);
+ return false;
+ }
+
+ if (uiFileParentDir.isChildOf(dir)) {
+ const FilePath relativePath = uiFileParentDir.relativeChildPath(dir);
+ QStringList components = relativePath.toString().split("/");
+ if (components.size() > 2) {
+ QMessageBox::StandardButton sel = QMessageBox::question(Core::ICore::dialogParent(),
+ QObject::tr("Problem"),
+ QObject::tr("Selected directory is far away from the QML file. This can cause unexpected results.\n\nAre you sure?"),
+ QMessageBox::Yes | QMessageBox::No);
+ if (sel == QMessageBox::No)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+const int TOO_FAR_AWAY = 4;
+const QDir::Filters FILES_ONLY = QDir::Files;
+const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
+
+const FilePath QmlProjectFileGenerator::findInDirTree(const FilePath &dir, const QStringList &suffixes, int currentSearchDepth) const
+{
+ if (currentSearchDepth > TOO_FAR_AWAY)
+ return {};
+
+ currentSearchDepth++;
+
+ const FilePaths files = dir.dirEntries({suffixes, FILES_ONLY});
+ if (!files.isEmpty())
+ return dir;
+
+ FilePaths subdirs = dir.dirEntries(DIRS_ONLY);
+ for (const FilePath &subdir : subdirs) {
+ const FilePath result = findInDirTree(subdir, suffixes, currentSearchDepth);
+ if (!result.isEmpty())
+ return result;
+ }
+
+ return {};
+}
+
+const QStringList QmlProjectFileGenerator::findContentDirs(const QStringList &suffixes) const
+{
+ FilePaths results;
+
+ if (!isStandardStructure(m_targetDir))
+ if (!m_targetDir.dirEntries({suffixes, FILES_ONLY}).isEmpty())
+ return {"."};
+
+ const FilePaths dirs = m_targetDir.dirEntries(DIRS_ONLY);
+ for (const FilePath &dir : dirs) {
+ const FilePath result = findInDirTree(dir, suffixes);
+ if (!result.isEmpty())
+ results.append(result);
+ }
+
+ QStringList relativePaths;
+ for (const FilePath &fullPath : results) {
+ if (fullPath == m_targetDir)
+ relativePaths.append(".");
+ else
+ relativePaths.append(fullPath.relativeChildPath(m_targetDir).toString().split('/').first());
+ }
+
+ return relativePaths;
+}
+
+} // GenerateQmlProject
+} // QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.h b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.h
new file mode 100644
index 00000000000..184233c2ca8
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Tooling
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/filepath.h>
+
+namespace QmlProjectManager {
+namespace GenerateQmlProject {
+
+class QmlProjectFileGenerator {
+public:
+ bool prepare(const Utils::FilePath &targetDir);
+ bool prepareForUiQmlFile(const Utils::FilePath &uiFilePath);
+ bool execute();
+
+ const Utils::FilePath targetDir() const;
+ const Utils::FilePath targetFile() const;
+
+private:
+ const QString createFilteredDirEntries(const QStringList &suffixes) const;
+ const QString createDirArrayEntry(const QString &arrayName, const QStringList &relativePaths) const;
+ const Utils::FilePath selectTargetFile(const Utils::FilePath &uiFilePath = {});
+ bool isStandardStructure(const Utils::FilePath &projectDir) const;
+ bool isDirAcceptable(const Utils::FilePath &dir, const Utils::FilePath &uiFile);
+ const QString createContentDirEntries(const QString &containerName,
+ const QStringList &suffixes) const;
+ const Utils::FilePath findInDirTree(const Utils::FilePath &dir,
+ const QStringList &suffixes,
+ int currentSearchDepth = 0) const;
+ const QStringList findContentDirs(const QStringList &suffixes) const;
+
+private:
+ Utils::FilePath m_targetDir;
+ Utils::FilePath m_targetFile;
+};
+
+} // GenerateQmlProject
+} // QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectgen/templates.qrc b/src/plugins/qmlprojectmanager/qmlprojectgen/templates.qrc
new file mode 100644
index 00000000000..c45ef145cd0
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectgen/templates.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/projectfiletemplates">
+ <file>qmlproject.tpl</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
index 1a160bff1cd..0bac36cf7c9 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
@@ -3,7 +3,7 @@ import qbs 1.0
QtcPlugin {
name: "QmlProjectManager"
- Depends { name: "Qt"; submodules: ["widgets", "network"] }
+ Depends { name: "Qt"; submodules: ["widgets", "network", "quickwidgets"] }
Depends { name: "QmlJS" }
Depends { name: "Utils" }
@@ -15,6 +15,9 @@ QtcPlugin {
Group {
name: "General"
files: [
+ "projectfilecontenttools.cpp", "projectfilecontenttools.h",
+ "qdslandingpagetheme.cpp", "qdslandingpagetheme.h",
+ "qdslandingpage.cpp", "qdslandingpage.h",
"qmlmainfileaspect.cpp", "qmlmainfileaspect.h",
"qmlmultilanguageaspect.cpp", "qmlmultilanguageaspect.h",
"qmlproject.cpp", "qmlproject.h",
@@ -24,7 +27,8 @@ QtcPlugin {
"qmlprojectmanagerconstants.h",
"qmlprojectnodes.cpp", "qmlprojectnodes.h",
"qmlprojectplugin.cpp", "qmlprojectplugin.h",
- "qmlprojectrunconfiguration.cpp", "qmlprojectrunconfiguration.h"
+ "qmlprojectrunconfiguration.cpp", "qmlprojectrunconfiguration.h",
+ project.ide_source_tree + "/src/share/3rdparty/studiofonts/studiofonts.qrc"
]
}
@@ -37,4 +41,27 @@ QtcPlugin {
"qmlprojectitem.cpp", "qmlprojectitem.h",
]
}
+
+ Group {
+ name: "CMake Generator"
+ prefix: "cmakegen/"
+ files: [
+ "generatecmakelists.cpp", "generatecmakelists.h",
+ "generatecmakelistsconstants.h",
+ "checkablefiletreeitem.cpp", "checkablefiletreeitem.h",
+ "cmakegeneratordialogtreemodel.cpp", "cmakegeneratordialogtreemodel.h",
+ "cmakegeneratordialog.cpp", "cmakegeneratordialog.h",
+ "cmakeprojectconverter.cpp", "cmakeprojectconverter.h",
+ "cmakeprojectconverterdialog.cpp", "cmakeprojectconverterdialog.h",
+ ]
+ }
+
+ Group {
+ name: "QML Project File Generator"
+ prefix: "qmlprojectgen/"
+ files: [
+ "qmlprojectgenerator.cpp", "qmlprojectgenerator.h",
+ "templates.qrc"
+ ]
+ }
}
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager_global.h b/src/plugins/qmlprojectmanager/qmlprojectmanager_global.h
index 0d30f82da9b..ac73b0b5873 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager_global.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager_global.h
@@ -29,6 +29,8 @@
#if defined(QMLPROJECTMANAGER_LIBRARY)
# define QMLPROJECTMANAGER_EXPORT Q_DECL_EXPORT
+#elif defined(QMLPROJECTMANAGER_STATIC_LIBRARY)
+# define QMLPROJECTMANAGER_EXPORT
#else
# define QMLPROJECTMANAGER_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
index ff58349dc00..ee4cf88ddc7 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
@@ -1,4 +1,4 @@
-/****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
@@ -23,17 +23,25 @@
**
****************************************************************************/
+#include "qdslandingpage.h"
#include "qmlprojectplugin.h"
#include "qmlproject.h"
#include "qmlprojectconstants.h"
#include "qmlprojectrunconfiguration.h"
+#include "projectfilecontenttools.h"
+#include "cmakegen/cmakeprojectconverter.h"
+#include "cmakegen/generatecmakelists.h"
+#include "qmlprojectgen/qmlprojectgenerator.h"
-#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/designmode.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
+#include <coreplugin/modemanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
@@ -45,28 +53,29 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmljseditor/qmljseditor.h>
+#include <qmljseditor/qmljseditorconstants.h>
+
#include <qmljstools/qmljstoolsconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
-#include <utils/infobar.h>
+#include <utils/fileutils.h>
#include <utils/qtcprocess.h>
#include <QAction>
+#include <QDesktopServices>
#include <QMessageBox>
+#include <QPointer>
#include <QPushButton>
#include <QTimer>
-#include <QPointer>
using namespace ProjectExplorer;
namespace QmlProjectManager {
namespace Internal {
-const char openInQDSAppInfoBar[] = "OpenInQDSAppUiQml";
-const char alwaysOpenUiQmlInQDS[] = "J.QtQuick/QmlJSEditor.openUiQmlFilesInQDS";
-
static bool isQmlDesigner(const ExtensionSystem::PluginSpec *spec)
{
if (!spec)
@@ -82,14 +91,21 @@ static bool qmlDesignerEnabled()
return it != plugins.end() && (*it)->plugin();
}
-static bool alwaysOpenUiQmlfileInQds()
+static QString alwaysOpenWithMode()
+{
+ return Core::ICore::settings()
+ ->value(QmlProjectManager::Constants::ALWAYS_OPEN_UI_MODE, "")
+ .toString();
+}
+
+static void setAlwaysOpenWithMode(const QString &mode)
{
- return Core::ICore::settings()->value(alwaysOpenUiQmlInQDS, false).toBool();
+ Core::ICore::settings()->setValue(QmlProjectManager::Constants::ALWAYS_OPEN_UI_MODE, mode);
}
-static void enableAlwaysOpenUiQmlfileInQds()
+static void clearAlwaysOpenWithMode()
{
- return Core::ICore::settings()->setValue(alwaysOpenUiQmlInQDS, true);
+ Core::ICore::settings()->remove(QmlProjectManager::Constants::ALWAYS_OPEN_UI_MODE);
}
class QmlProjectPluginPrivate
@@ -100,12 +116,18 @@ public:
{ProjectExplorer::Constants::NORMAL_RUN_MODE},
{runConfigFactory.runConfigurationId()}};
QPointer<QMessageBox> lastMessageBox;
+ QdsLandingPage *landingPage = nullptr;
+ QdsLandingPageWidget *landingPageWidget = nullptr;
};
QmlProjectPlugin::~QmlProjectPlugin()
{
if (d->lastMessageBox)
d->lastMessageBox->deleteLater();
+ if (d->landingPage)
+ d->landingPage->deleteLater();
+ if (d->landingPageWidget)
+ d->landingPageWidget->deleteLater();
delete d;
}
@@ -125,6 +147,8 @@ void QmlProjectPlugin::openQDS(const Utils::FilePath &fileName)
QMessageBox::warning(Core::ICore::dialogParent(),
fileName.fileName(),
QObject::tr("Failed to start Qt Design Studio."));
+ if (alwaysOpenWithMode() == Core::Constants::MODE_DESIGN)
+ clearAlwaysOpenWithMode();
}
}
@@ -141,15 +165,30 @@ bool QmlProjectPlugin::qdsInstallationExists()
return qdsInstallationEntry().exists();
}
-Utils::FilePath findQmlProject(const Utils::FilePath &folder)
+bool QmlProjectPlugin::checkIfEditorIsuiQml(Core::IEditor *editor)
{
- QDir dir = folder.toDir();
- for (const QString &file : dir.entryList({"*.qmlproject"}))
- return Utils::FilePath::fromString(folder.toString() + "/" + file);
- return {};
+ if (editor
+ && (editor->document()->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID
+ || editor->document()->id() == QmlJSEditor::Constants::C_QTQUICKDESIGNEREDITOR_ID)) {
+ QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
+ QmlJS::Document::Ptr document =
+ modelManager->ensuredGetDocumentForPath(editor->document()->filePath().toString());
+ if (!document.isNull())
+ return document->language() == QmlJS::Dialect::QmlQtQuick2Ui;
+ }
+ return false;
}
-Utils::FilePath findQmlProjectUpwards(const Utils::FilePath &folder)
+const Utils::FilePath findQmlProject(const Utils::FilePath &folder)
+{
+ const Utils::FilePaths files = folder.dirEntries({QStringList("*.qmlproject"), QDir::Files});
+ if (files.isEmpty())
+ return {};
+
+ return files.constFirst();
+}
+
+const Utils::FilePath findQmlProjectUpwards(const Utils::FilePath &folder)
{
auto ret = findQmlProject(folder);
if (ret.exists())
@@ -163,7 +202,6 @@ Utils::FilePath findQmlProjectUpwards(const Utils::FilePath &folder)
static bool findAndOpenProject(const Utils::FilePath &filePath)
{
-
ProjectExplorer::Project *project
= ProjectExplorer::SessionManager::projectForFile(filePath);
@@ -228,56 +266,24 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
d = new QmlProjectPluginPrivate;
if (!qmlDesignerEnabled()) {
- connect(Core::EditorManager::instance(),
- &Core::EditorManager::currentEditorChanged,
- this,
- [this](Core::IEditor *editor) {
- QmlJS::ModelManagerInterface *modelManager
- = QmlJS::ModelManagerInterface::instance();
-
- if (!editor || !modelManager)
- return;
+ QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf");
+ d->landingPage = new QdsLandingPage();
+ qmlRegisterSingletonInstance<QdsLandingPage>("LandingPageApi",
+ 1,
+ 0,
+ "LandingPageApi",
+ d->landingPage);
- if (d->lastMessageBox)
- return;
- auto filePath = editor->document()->filePath();
- QmlJS::Document::Ptr document = modelManager->ensuredGetDocumentForPath(
- filePath.toString());
- if (!document.isNull()
- && document->language() == QmlJS::Dialect::QmlQtQuick2Ui) {
-
- const QString description = tr("Files of the type ui.qml are intended for Qt Design Studio.");
-
- if (!qdsInstallationExists()) {
- if (Core::ICore::infoBar()->canInfoBeAdded(openInQDSAppInfoBar)) {
- Utils::InfoBarEntry
- info(openInQDSAppInfoBar,
- description + tr(" Learn more about Qt Design Studio here: ")
- + "<a href='https://www.qt.io/product/ui-design-tools'>Qt Design Studio</a>",
- Utils::InfoBarEntry::GlobalSuppression::Disabled);
- Core::ICore::infoBar()->addInfo(info);
- }
- return;
- }
-
-
- if (alwaysOpenUiQmlfileInQds()) {
- openInQDSWithProject(filePath);
- } else if (Core::ICore::infoBar()->canInfoBeAdded(openInQDSAppInfoBar)) {
- Utils::InfoBarEntry
- info(openInQDSAppInfoBar,
- description + "\n" + tr("Do you want to open this file always in Qt Design Studio?"),
- Utils::InfoBarEntry::GlobalSuppression::Disabled);
- info.addCustomButton(tr("Always open in Qt Design Studio"), [filePath] {
- Core::ICore::infoBar()->removeInfo(openInQDSAppInfoBar);
-
- enableAlwaysOpenUiQmlfileInQds();
- openInQDSWithProject(filePath);
- });
- Core::ICore::infoBar()->addInfo(info);
- }
- }
- });
+ d->landingPageWidget = new QdsLandingPageWidget();
+
+ const QStringList mimeTypes = {QmlJSTools::Constants::QMLUI_MIMETYPE};
+ auto context = new Internal::DesignModeContext(d->landingPageWidget);
+ Core::ICore::addContextObject(context);
+
+ Core::DesignMode::registerDesignWidget(d->landingPageWidget, mimeTypes, context->context());
+
+ connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged,
+ this, &QmlProjectPlugin::editorModeChanged);
}
ProjectManager::registerProjectType<QmlProject>(QmlJSTools::Constants::QMLPROJECT_MIMETYPE);
@@ -372,8 +378,99 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
});
}
+ GenerateCmake::generateMenuEntry(this);
+ if (QmlProject::isQtDesignStudio())
+ GenerateCmake::CmakeProjectConverter::generateMenuEntry(this);
+
return true;
-} // namespace Internal
+}
+
+void QmlProjectPlugin::displayQmlLandingPage()
+{
+ if (!d->landingPage)
+ return;
+
+ d->landingPage->setWidget(d->landingPageWidget->widget());
+
+ updateQmlLandingPageProjectInfo(projectFilePath());
+ d->landingPage->setQdsInstalled(qdsInstallationExists());
+ d->landingPage->setCmakeResources(ProjectFileContentTools::rootCmakeFiles());
+ d->landingPage->show();
+}
+
+void QmlProjectPlugin::hideQmlLandingPage()
+{
+ if (d->landingPage)
+ d->landingPage->hide();
+}
+
+static bool isDesignerMode(Utils::Id mode)
+{
+ return mode == Core::Constants::MODE_DESIGN;
+}
+
+void QmlProjectPlugin::editorModeChanged(Utils::Id newMode, Utils::Id oldMode)
+{
+ Core::IEditor *currentEditor = Core::EditorManager::currentEditor();
+ if (checkIfEditorIsuiQml(currentEditor)) {
+ if (isDesignerMode(newMode)) {
+ if (alwaysOpenWithMode() == Core::Constants::MODE_DESIGN)
+ openQds();
+ else if (alwaysOpenWithMode() == Core::Constants::MODE_EDIT)
+ openQtc();
+ else
+ displayQmlLandingPage();
+ } else if (isDesignerMode(oldMode)) {
+ hideQmlLandingPage();
+ }
+ }
+}
+
+void QmlProjectPlugin::openQtc(bool permanent)
+{
+ if (permanent)
+ setAlwaysOpenWithMode(Core::Constants::MODE_EDIT);
+
+ if (d->landingPage)
+ hideQmlLandingPage();
+
+ Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
+}
+
+void QmlProjectPlugin::openQds(bool permanent)
+{
+ if (permanent)
+ setAlwaysOpenWithMode(Core::Constants::MODE_DESIGN);
+
+ if (d->landingPage)
+ hideQmlLandingPage();
+
+ auto editor = Core::EditorManager::currentEditor();
+ if (editor)
+ openInQDSWithProject(editor->document()->filePath());
+}
+
+void QmlProjectPlugin::updateQmlLandingPageProjectInfo(const Utils::FilePath &projectFile)
+{
+ if (!d->landingPage)
+ return;
+
+ const QString qtVersionString = ProjectFileContentTools::qtVersion(projectFile);
+ const QString qdsVersionString = ProjectFileContentTools::qdsVersion(projectFile);
+ d->landingPage->setProjectFileExists(projectFile.exists());
+ d->landingPage->setQtVersion(qtVersionString);
+ d->landingPage->setQdsVersion(qdsVersionString);
+}
+
+Utils::FilePath QmlProjectPlugin::projectFilePath()
+{
+ auto project = ProjectExplorer::SessionManager::startupProject();
+ const QmlProjectManager::QmlProject *qmlProject = qobject_cast<const QmlProjectManager::QmlProject*>(project);
+ if (qmlProject)
+ return qmlProject->projectFilePath();
+
+ return {};
+}
} // namespace Internal
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.h b/src/plugins/qmlprojectmanager/qmlprojectplugin.h
index e793cee74b8..ffc23351bb3 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.h
@@ -25,6 +25,7 @@
#pragma once
+#include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/iplugin.h>
#include <utils/filepath.h>
@@ -43,11 +44,24 @@ public:
static void openQDS(const Utils::FilePath &fileName);
static Utils::FilePath qdsInstallationEntry();
static bool qdsInstallationExists();
-
-private:
+ static bool checkIfEditorIsuiQml(Core::IEditor *editor);
+ static Utils::FilePath projectFilePath();
+ static Utils::FilePaths rootCmakeFiles();
+ static QString qtVersion(const Utils::FilePath &projectFilePath);
+ static QString qdsVersion(const Utils::FilePath &projectFilePath);
static void openInQDSWithProject(const Utils::FilePath &filePath);
+ static const QString readFileContents(const Utils::FilePath &filePath);
+public slots:
+ void editorModeChanged(Utils::Id newMode, Utils::Id oldMode);
+ void openQtc(bool permanent = false);
+ void openQds(bool permanent = false);
+
+private:
bool initialize(const QStringList &arguments, QString *errorString) final;
+ void displayQmlLandingPage();
+ void hideQmlLandingPage();
+ void updateQmlLandingPageProjectInfo(const Utils::FilePath &projectFile);
class QmlProjectPluginPrivate *d = nullptr;
};
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
index 1309230e8cc..64c6301da18 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
@@ -34,10 +34,12 @@
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/session.h>
@@ -46,10 +48,10 @@
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtsupportconstants.h>
+#include <utils/algorithm.h>
#include <utils/aspects.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcprocess.h>
#include <utils/winutils.h>
@@ -97,7 +99,7 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
m_qmlViewerAspect->setDisplayStyle(StringAspect::LineEditDisplay);
m_qmlViewerAspect->setHistoryCompleter("QmlProjectManager.viewer.history");
- auto argumentAspect = addAspect<ArgumentsAspect>();
+ auto argumentAspect = addAspect<ArgumentsAspect>(macroExpander());
argumentAspect->setSettingsKey(Constants::QML_VIEWER_ARGUMENTS_KEY);
setCommandLineGetter([this] {
@@ -205,14 +207,15 @@ FilePath QmlProjectRunConfiguration::qmlRuntimeFilePath() const
QString QmlProjectRunConfiguration::commandLineArguments() const
{
// arguments in .user file
- QString args = aspect<ArgumentsAspect>()->arguments(macroExpander());
+ QString args = aspect<ArgumentsAspect>()->arguments();
const IDevice::ConstPtr device = DeviceKitAspect::device(kit());
const OsType osType = device ? device->osType() : HostOsInfo::hostOs();
// arguments from .qmlproject file
const QmlBuildSystem *bs = qobject_cast<QmlBuildSystem *>(target()->buildSystem());
- foreach (const QString &importPath,
- QmlBuildSystem::makeAbsolute(bs->targetDirectory(), bs->customImportPaths())) {
+ const QStringList importPaths = QmlBuildSystem::makeAbsolute(bs->targetDirectory(),
+ bs->customImportPaths());
+ for (const QString &importPath : importPaths) {
ProcessArgs::addArg(&args, "-I", osType);
ProcessArgs::addArg(&args, importPath, osType);
}
diff --git a/src/plugins/qnx/CMakeLists.txt b/src/plugins/qnx/CMakeLists.txt
index 5e2e2934cb8..8e9342b9e2d 100644
--- a/src/plugins/qnx/CMakeLists.txt
+++ b/src/plugins/qnx/CMakeLists.txt
@@ -1,5 +1,5 @@
add_qtc_plugin(Qnx
- DEPENDS QtcSsh QmlDebug Qt5::Xml
+ DEPENDS QmlDebug Qt5::Xml
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport RemoteLinux
SOURCES
qnx.qrc
@@ -11,7 +11,6 @@ add_qtc_plugin(Qnx
qnxdebugsupport.cpp qnxdebugsupport.h
qnxdeployqtlibrariesdialog.cpp qnxdeployqtlibrariesdialog.h qnxdeployqtlibrariesdialog.ui
qnxdevice.cpp qnxdevice.h
- qnxdeviceprocess.cpp qnxdeviceprocess.h
qnxdeviceprocesslist.cpp qnxdeviceprocesslist.h
qnxdeviceprocesssignaloperation.cpp qnxdeviceprocesssignaloperation.h
qnxdevicetester.cpp qnxdevicetester.h
diff --git a/src/plugins/qnx/qnx.qbs b/src/plugins/qnx/qnx.qbs
index b4b3aeede17..fe56430e17e 100644
--- a/src/plugins/qnx/qnx.qbs
+++ b/src/plugins/qnx/qnx.qbs
@@ -4,7 +4,6 @@ QtcPlugin {
name: "Qnx"
Depends { name: "Qt"; submodules: ["widgets", "xml", "network"] }
- Depends { name: "QtcSsh" }
Depends { name: "QmlDebug" }
Depends { name: "Utils" }
@@ -36,8 +35,6 @@ QtcPlugin {
"qnxdeviceprocesslist.h",
"qnxdeviceprocesssignaloperation.cpp",
"qnxdeviceprocesssignaloperation.h",
- "qnxdeviceprocess.cpp",
- "qnxdeviceprocess.h",
"qnxdevicetester.cpp",
"qnxdevicetester.h",
"qnxsettingswidget.ui",
diff --git a/src/plugins/qnx/qnxanalyzesupport.cpp b/src/plugins/qnx/qnxanalyzesupport.cpp
index a7bfd50cffe..83f4194bace 100644
--- a/src/plugins/qnx/qnxanalyzesupport.cpp
+++ b/src/plugins/qnx/qnxanalyzesupport.cpp
@@ -56,14 +56,13 @@ QnxQmlProfilerSupport::QnxQmlProfilerSupport(RunControl *runControl)
profiler->addStartDependency(this);
addStopDependency(profiler);
- setStarter([this, runControl, portsGatherer, profiler] {
+ setStartModifier([this, portsGatherer, profiler] {
const QUrl serverUrl = portsGatherer->findEndPoint();
profiler->recordData("QmlServerUrl", serverUrl);
- Runnable r = runControl->runnable();
- r.command.addArg(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices, serverUrl));
-
- doStart(r, runControl->device());
+ CommandLine cmd = commandLine();
+ cmd.addArg(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices, serverUrl));
+ setCommandLine(cmd);
});
}
diff --git a/src/plugins/qnx/qnxconfiguration.cpp b/src/plugins/qnx/qnxconfiguration.cpp
index 751bab34013..2901f3a3f59 100644
--- a/src/plugins/qnx/qnxconfiguration.cpp
+++ b/src/plugins/qnx/qnxconfiguration.cpp
@@ -50,6 +50,7 @@
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
+#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include <QFileInfo>
diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp
index c345d76506e..c9f794fbc29 100644
--- a/src/plugins/qnx/qnxdebugsupport.cpp
+++ b/src/plugins/qnx/qnxdebugsupport.cpp
@@ -26,11 +26,9 @@
#include "qnxdebugsupport.h"
#include "qnxconstants.h"
-#include "qnxdevice.h"
#include "qnxrunconfiguration.h"
#include "slog2inforunner.h"
#include "qnxqtversion.h"
-#include "qnxutils.h"
#include <coreplugin/icore.h>
@@ -38,8 +36,8 @@
#include <debugger/debuggerruncontrol.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
-#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitchooser.h>
#include <projectexplorer/kitinformation.h>
@@ -55,6 +53,7 @@
#include <utils/pathchooser.h>
#include <utils/portlist.h>
+#include <utils/processinfo.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -103,21 +102,21 @@ public:
{
setId("QnxDebuggeeRunner");
- setStarter([this, runControl, portsGatherer] {
- Runnable r = runControl->runnable();
+ setStartModifier([this, portsGatherer] {
+ CommandLine cmd = commandLine();
QStringList arguments;
if (portsGatherer->useGdbServer()) {
int pdebugPort = portsGatherer->gdbServer().port();
- r.command.setExecutable(FilePath::fromString(QNX_DEBUG_EXECUTABLE));
+ cmd.setExecutable(device()->filePath(QNX_DEBUG_EXECUTABLE));
arguments.append(QString::number(pdebugPort));
}
if (portsGatherer->useQmlServer()) {
arguments.append(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
portsGatherer->qmlServer()));
}
- r.command.setArguments(ProcessArgs::joinArgs(arguments));
+ cmd.setArguments(ProcessArgs::joinArgs(arguments));
+ setCommandLine(cmd);
- doStart(r, runControl->device());
});
}
};
@@ -147,8 +146,10 @@ QnxDebugSupport::QnxDebugSupport(RunControl *runControl)
setCloseMode(KillAtClose);
setUseCtrlCStub(true);
setSolibSearchPath(searchPaths(k));
- if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitAspect::qtVersion(k)))
+ if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitAspect::qtVersion(k))) {
setSysRoot(qtVersion->qnxTarget());
+ modifyDebuggerEnvironment(qtVersion->environment());
+ }
}
@@ -197,12 +198,9 @@ public:
setId("PDebugRunner");
addStartDependency(portsGatherer);
- setStarter([this, runControl, portsGatherer] {
+ setStartModifier([this, portsGatherer] {
const int pdebugPort = portsGatherer->gdbServer().port();
-
- Runnable r;
- r.command = {QNX_DEBUG_EXECUTABLE, {QString::number(pdebugPort)}};
- doStart(r, runControl->device());
+ setCommandLine({QNX_DEBUG_EXECUTABLE, {QString::number(pdebugPort)}});
});
}
};
@@ -243,8 +241,7 @@ void QnxAttachDebugSupport::showProcessesDialog()
if (!runConfig)
return;
- DeviceProcessItem process = dlg.currentProcess();
- const int pid = process.pid;
+ const int pid = dlg.currentProcess().processId;
// QString projectSourceDirectory = dlg.projectSource();
FilePath localExecutable = dlg.localExecutable();
if (localExecutable.isEmpty()) {
@@ -253,7 +250,7 @@ void QnxAttachDebugSupport::showProcessesDialog()
}
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
- runControl->setRunConfiguration(runConfig);
+ runControl->copyDataFromRunConfiguration(runConfig);
auto debugger = new QnxAttachDebugSupport(runControl);
debugger->setStartMode(AttachToRemoteServer);
debugger->setCloseMode(DetachAtClose);
diff --git a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
index d877c7a2541..3fa29a35a66 100644
--- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
+++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
@@ -30,9 +30,9 @@
#include "qnxqtversion.h"
#include <projectexplorer/deployablefile.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <qtsupport/qtversionmanager.h>
#include <remotelinux/genericdirectuploadservice.h>
-#include <ssh/sshremoteprocessrunner.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -40,34 +40,32 @@
#include <QDir>
#include <QMessageBox>
-using namespace QtSupport;
using namespace ProjectExplorer;
+using namespace QtSupport;
using namespace RemoteLinux;
+using namespace Utils;
namespace Qnx {
namespace Internal {
QnxDeployQtLibrariesDialog::QnxDeployQtLibrariesDialog(const IDevice::ConstPtr &device,
- QWidget *parent) :
- QDialog(parent),
- m_ui(new Ui::QnxDeployQtLibrariesDialog),
- m_device(device),
- m_progressCount(0),
- m_state(Inactive)
+ QWidget *parent)
+ : QDialog(parent)
+ , m_ui(new Ui::QnxDeployQtLibrariesDialog)
+ , m_device(device)
{
m_ui->setupUi(this);
- const QList<QtVersion*> qtVersions
- = QtVersionManager::sortVersions(
- QtVersionManager::versions(QtVersion::isValidPredicate(Utils::equal(&QtVersion::type,
- QString::fromLatin1(Constants::QNX_QNX_QT)))));
+ const QList<QtVersion*> qtVersions = QtVersionManager::sortVersions(
+ QtVersionManager::versions(QtVersion::isValidPredicate(
+ equal(&QtVersion::type, QString::fromLatin1(Constants::QNX_QNX_QT)))));
for (QtVersion *v : qtVersions)
m_ui->qtLibraryCombo->addItem(v->displayName(), v->uniqueId());
m_ui->basePathLabel->setText(QString());
m_ui->remoteDirectory->setText(QLatin1String("/qt"));
- m_uploadService = new RemoteLinux::GenericDirectUploadService(this);
+ m_uploadService = new GenericDirectUploadService(this);
m_uploadService->setDevice(m_device);
connect(m_uploadService, &AbstractRemoteLinuxDeployService::progressMessage,
@@ -88,11 +86,10 @@ QnxDeployQtLibrariesDialog::QnxDeployQtLibrariesDialog(const IDevice::ConstPtr &
connect(m_uploadService, &AbstractRemoteLinuxDeployService::finished,
this, &QnxDeployQtLibrariesDialog::handleUploadFinished);
- m_processRunner = new QSsh::SshRemoteProcessRunner(this);
- connect(m_processRunner, &QSsh::SshRemoteProcessRunner::connectionError,
- this, &QnxDeployQtLibrariesDialog::handleRemoteProcessError);
- connect(m_processRunner, &QSsh::SshRemoteProcessRunner::processClosed,
- this, &QnxDeployQtLibrariesDialog::handleRemoteProcessCompleted);
+ connect(&m_checkDirProcess, &QtcProcess::done,
+ this, &QnxDeployQtLibrariesDialog::handleCheckDirDone);
+ connect(&m_removeDirProcess, &QtcProcess::done,
+ this, &QnxDeployQtLibrariesDialog::handleRemoveDirDone);
connect(m_ui->deployButton, &QAbstractButton::clicked,
this, &QnxDeployQtLibrariesDialog::deployLibraries);
@@ -118,10 +115,9 @@ void QnxDeployQtLibrariesDialog::closeEvent(QCloseEvent *event)
{
// A disabled Deploy button indicates the upload is still running
if (!m_ui->deployButton->isEnabled()) {
- int answer = QMessageBox::question(this, windowTitle(),
- tr("Closing the dialog will stop the deployment. "
- "Are you sure you want to do this?"),
- QMessageBox::Yes | QMessageBox::No);
+ const int answer = QMessageBox::question(this, windowTitle(),
+ tr("Closing the dialog will stop the deployment. Are you sure you want to do this?"),
+ QMessageBox::Yes | QMessageBox::No);
if (answer == QMessageBox::No)
event->ignore();
else if (answer == QMessageBox::Yes)
@@ -148,7 +144,7 @@ void QnxDeployQtLibrariesDialog::deployLibraries()
m_ui->qtLibraryCombo->setEnabled(false);
m_ui->deployLogWindow->clear();
- checkRemoteDirectoryExistance();
+ startCheckDirProcess();
}
void QnxDeployQtLibrariesDialog::startUpload()
@@ -185,44 +181,6 @@ void QnxDeployQtLibrariesDialog::handleUploadFinished()
m_state = Inactive;
}
-void QnxDeployQtLibrariesDialog::handleRemoteProcessError()
-{
- QTC_CHECK(m_state == CheckingRemoteDirectory || m_state == RemovingRemoteDirectory);
-
- m_ui->deployLogWindow->appendPlainText(
- tr("Connection failed: %1")
- .arg(m_processRunner->lastConnectionErrorString()));
- handleUploadFinished();
-}
-
-void QnxDeployQtLibrariesDialog::handleRemoteProcessCompleted()
-{
- QTC_CHECK(m_state == CheckingRemoteDirectory || m_state == RemovingRemoteDirectory);
-
- if (m_state == CheckingRemoteDirectory) {
- // Directory exists
- if (m_processRunner->processExitCode() == 0) {
- int answer = QMessageBox::question(this, windowTitle(),
- tr("The remote directory \"%1\" already exists. "
- "Deploying to that directory will remove any files "
- "already present.\n\n"
- "Are you sure you want to continue?")
- .arg(fullRemoteDirectory()),
- QMessageBox::Yes | QMessageBox::No);
- if (answer == QMessageBox::Yes)
- removeRemoteDirectory();
- else
- handleUploadFinished();
- } else {
- startUpload();
- }
- } else if (m_state == RemovingRemoteDirectory) {
- QTC_ASSERT(m_processRunner->processExitCode() == 0, return);
-
- startUpload();
- }
-}
-
QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles()
{
QList<DeployableFile> result;
@@ -235,7 +193,7 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles()
QTC_ASSERT(qtVersion, return result);
- if (Utils::HostOsInfo::isWindowsHost()) {
+ if (HostOsInfo::isWindowsHost()) {
result.append(gatherFiles(qtVersion->libraryPath().toString(),
QString(),
QStringList() << QLatin1String("*.so.?")));
@@ -247,7 +205,6 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles()
result.append(gatherFiles(qtVersion->pluginPath().toString()));
result.append(gatherFiles(qtVersion->importsPath().toString()));
result.append(gatherFiles(qtVersion->qmlPath().toString()));
-
return result;
}
@@ -263,7 +220,7 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles(
if (unusedDirs.contains(dp))
return result;
- QDir dir(dirPath);
+ const QDir dir(dirPath);
QFileInfoList list = dir.entryInfoList(nameFilters,
QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
@@ -286,7 +243,7 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles(
remoteDir = fullRemoteDirectory() + QLatin1Char('/') +
baseDir.relativeFilePath(dirPath);
}
- result.append(DeployableFile(Utils::FilePath::fromString(fileInfo.absoluteFilePath()),
+ result.append(DeployableFile(FilePath::fromString(fileInfo.absoluteFilePath()),
remoteDir));
}
}
@@ -296,27 +253,72 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles(
QString QnxDeployQtLibrariesDialog::fullRemoteDirectory() const
{
- return m_ui->remoteDirectory->text();
+ return m_ui->remoteDirectory->text();
}
-void QnxDeployQtLibrariesDialog::checkRemoteDirectoryExistance()
+void QnxDeployQtLibrariesDialog::startCheckDirProcess()
{
QTC_CHECK(m_state == Inactive);
-
m_state = CheckingRemoteDirectory;
m_ui->deployLogWindow->appendPlainText(tr("Checking existence of \"%1\"")
.arg(fullRemoteDirectory()));
- m_processRunner->run("test -d " + fullRemoteDirectory(), m_device->sshParameters());
+ m_checkDirProcess.setCommand({m_device->filePath("test"),
+ {"-d", fullRemoteDirectory()}});
+ m_checkDirProcess.start();
}
-void QnxDeployQtLibrariesDialog::removeRemoteDirectory()
+void QnxDeployQtLibrariesDialog::startRemoveDirProcess()
{
QTC_CHECK(m_state == CheckingRemoteDirectory);
-
m_state = RemovingRemoteDirectory;
m_ui->deployLogWindow->appendPlainText(tr("Removing \"%1\"").arg(fullRemoteDirectory()));
- m_processRunner->run("rm -rf " + fullRemoteDirectory(), m_device->sshParameters());
+ m_removeDirProcess.setCommand({m_device->filePath("rm"),
+ {"-rf", fullRemoteDirectory()}});
+ m_removeDirProcess.start();
}
+void QnxDeployQtLibrariesDialog::handleCheckDirDone()
+{
+ QTC_CHECK(m_state == CheckingRemoteDirectory);
+ if (handleError(m_checkDirProcess))
+ return;
+
+ if (m_checkDirProcess.exitCode() == 0) { // Directory exists
+ const int answer = QMessageBox::question(this, windowTitle(),
+ tr("The remote directory \"%1\" already exists.\n"
+ "Deploying to that directory will remove any files already present.\n\n"
+ "Are you sure you want to continue?").arg(fullRemoteDirectory()),
+ QMessageBox::Yes | QMessageBox::No);
+ if (answer == QMessageBox::Yes)
+ startRemoveDirProcess();
+ else
+ handleUploadFinished();
+ } else {
+ startUpload();
+ }
+}
+
+void QnxDeployQtLibrariesDialog::handleRemoveDirDone()
+{
+ QTC_CHECK(m_state == RemovingRemoteDirectory);
+ if (handleError(m_removeDirProcess))
+ return;
+
+ QTC_ASSERT(m_removeDirProcess.exitCode() == 0, return);
+ startUpload();
+}
+
+// Returns true if the error appeared, false when finished with success
+bool QnxDeployQtLibrariesDialog::handleError(const QtcProcess &process)
+{
+ if (process.result() == ProcessResult::FinishedWithSuccess)
+ return false;
+
+ m_ui->deployLogWindow->appendPlainText(tr("Connection failed: %1").arg(process.errorString()));
+ handleUploadFinished();
+ return true;
+}
+
+
} // namespace Internal
} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdeployqtlibrariesdialog.h b/src/plugins/qnx/qnxdeployqtlibrariesdialog.h
index 10e771ee045..56f8c3ce154 100644
--- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.h
+++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.h
@@ -27,23 +27,16 @@
#include <QDialog>
-#include <projectexplorer/deployablefile.h>
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
+#include <utils/qtcprocess.h>
-namespace QSsh {
-class SshRemoteProcessRunner;
-}
-
-namespace RemoteLinux {
-class GenericDirectUploadService;
-}
+namespace ProjectExplorer { class DeployableFile; }
+namespace RemoteLinux { class GenericDirectUploadService; }
namespace Qnx {
namespace Internal {
-namespace Ui {
-class QnxDeployQtLibrariesDialog;
-}
+namespace Ui { class QnxDeployQtLibrariesDialog; }
class QnxDeployQtLibrariesDialog : public QDialog
{
@@ -57,7 +50,7 @@ public:
Uploading
};
- explicit QnxDeployQtLibrariesDialog(const ProjectExplorer::IDevice::ConstPtr &device,
+ explicit QnxDeployQtLibrariesDialog(const ProjectExplorer::IDeviceConstPtr &device,
QWidget *parent = nullptr);
~QnxDeployQtLibrariesDialog() override;
@@ -66,35 +59,36 @@ public:
protected:
void closeEvent(QCloseEvent *event) override;
-private slots:
+private:
void deployLibraries();
void updateProgress(const QString &progressMessage);
void handleUploadFinished();
- void handleRemoteProcessError();
- void handleRemoteProcessCompleted();
+ void startCheckDirProcess();
+ void startRemoveDirProcess();
+
+ void handleCheckDirDone();
+ void handleRemoveDirDone();
+ bool handleError(const Utils::QtcProcess &process);
-private:
QList<ProjectExplorer::DeployableFile> gatherFiles();
QList<ProjectExplorer::DeployableFile> gatherFiles(const QString &dirPath,
const QString &baseDir = QString(),
const QStringList &nameFilters = QStringList());
QString fullRemoteDirectory() const;
- void checkRemoteDirectoryExistance();
- void removeRemoteDirectory();
void startUpload();
Ui::QnxDeployQtLibrariesDialog *m_ui;
- QSsh::SshRemoteProcessRunner *m_processRunner;
+ Utils::QtcProcess m_checkDirProcess;
+ Utils::QtcProcess m_removeDirProcess;
RemoteLinux::GenericDirectUploadService *m_uploadService;
- ProjectExplorer::IDevice::ConstPtr m_device;
-
- int m_progressCount;
+ ProjectExplorer::IDeviceConstPtr m_device;
- State m_state;
+ int m_progressCount = 0;
+ State m_state = Inactive;
};
} // namespace Internal
diff --git a/src/plugins/qnx/qnxdevice.cpp b/src/plugins/qnx/qnxdevice.cpp
index 764355b1e1e..c354739dc48 100644
--- a/src/plugins/qnx/qnxdevice.cpp
+++ b/src/plugins/qnx/qnxdevice.cpp
@@ -30,52 +30,80 @@
#include "qnxdeviceprocesslist.h"
#include "qnxdeviceprocesssignaloperation.h"
#include "qnxdeployqtlibrariesdialog.h"
-#include "qnxdeviceprocess.h"
#include "qnxdevicewizard.h"
-#include <projectexplorer/devicesupport/sshdeviceprocess.h>
-#include <projectexplorer/runcontrol.h>
+#include <remotelinux/sshprocessinterface.h>
-#include <ssh/sshconnection.h>
#include <utils/port.h>
#include <utils/qtcassert.h>
-#include <utils/stringutils.h>
+#include <utils/qtcprocess.h>
-#include <QApplication>
#include <QRegularExpression>
-#include <QStringList>
-#include <QThread>
using namespace ProjectExplorer;
+using namespace RemoteLinux;
using namespace Utils;
namespace Qnx {
namespace Internal {
-const char QnxVersionKey[] = "QnxVersion";
+class QnxProcessImpl final : public SshProcessInterface
+{
+public:
+ QnxProcessImpl(const LinuxDevice *linuxDevice);
+ ~QnxProcessImpl() { killIfRunning(); }
+
+private:
+ QString fullCommandLine(const CommandLine &commandLine) const final;
+ void sendControlSignal(Utils::ControlSignal controlSignal) final;
+
+ const QString m_pidFile;
+};
+
+static std::atomic_int s_pidFileCounter = 1;
-class QnxPortsGatheringMethod : public PortsGatheringMethod
+QnxProcessImpl::QnxProcessImpl(const LinuxDevice *linuxDevice)
+ : SshProcessInterface(linuxDevice)
+ , m_pidFile(QString::fromLatin1("/var/run/qtc.%1.pid").arg(s_pidFileCounter.fetch_add(1)))
{
- // TODO: The command is probably needlessly complicated because the parsing method
- // used to be fixed. These two can now be matched to each other.
- CommandLine commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const override
- {
- Q_UNUSED(protocol)
- return {"netstat", {"-na"}};
- }
+}
- QList<Port> usedPorts(const QByteArray &output) const override
- {
- QList<Utils::Port> ports;
- const QList<QByteArray> lines = output.split('\n');
- for (const QByteArray &line : lines) {
- const Port port(Utils::parseUsedPortFromNetstatOutput(line));
- if (port.isValid() && !ports.contains(port))
- ports.append(port);
- }
- return ports;
+QString QnxProcessImpl::fullCommandLine(const CommandLine &commandLine) const
+{
+ QStringList args = ProcessArgs::splitArgs(commandLine.arguments());
+ args.prepend(commandLine.executable().toString());
+ const QString cmd = ProcessArgs::createUnixArgs(args).toString();
+
+ QString fullCommandLine =
+ "test -f /etc/profile && . /etc/profile ; "
+ "test -f $HOME/profile && . $HOME/profile ; ";
+
+ if (!m_setup.m_workingDirectory.isEmpty())
+ fullCommandLine += QString::fromLatin1("cd %1 ; ").arg(
+ ProcessArgs::quoteArg(m_setup.m_workingDirectory.toString()));
+
+ const Environment env = m_setup.m_environment;
+ for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
+ fullCommandLine += QString::fromLatin1("%1='%2' ")
+ .arg(env.key(it)).arg(env.expandedValueForKey(env.key(it)));
}
-};
+
+ fullCommandLine += QString::fromLatin1("%1 & echo $! > %2").arg(cmd).arg(m_pidFile);
+
+ return fullCommandLine;
+}
+
+void QnxProcessImpl::sendControlSignal(Utils::ControlSignal controlSignal)
+{
+ QTC_ASSERT(controlSignal != ControlSignal::KickOff, return);
+ const QString args = QString::fromLatin1("-%1 `cat %2`")
+ .arg(controlSignalToInt(controlSignal)).arg(m_pidFile);
+ CommandLine command = { "kill", args, CommandLine::Raw };
+ // Note: This blocking call takes up to 2 ms for local remote.
+ runInShell(command);
+}
+
+const char QnxVersionKey[] = "QnxVersion";
QnxDevice::QnxDevice()
{
@@ -99,20 +127,10 @@ int QnxDevice::qnxVersion() const
void QnxDevice::updateVersionNumber() const
{
- QEventLoop eventLoop;
- SshDeviceProcess versionNumberProcess(sharedFromThis());
- QObject::connect(&versionNumberProcess, &SshDeviceProcess::finished, &eventLoop, &QEventLoop::quit);
- QObject::connect(&versionNumberProcess, &DeviceProcess::errorOccurred, &eventLoop, &QEventLoop::quit);
-
- Runnable r;
- r.command = {"uname", {"-r"}};
- versionNumberProcess.start(r);
+ QtcProcess versionNumberProcess;
- bool isGuiThread = QThread::currentThread() == QCoreApplication::instance()->thread();
- if (isGuiThread)
- QApplication::setOverrideCursor(Qt::WaitCursor);
-
- eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
+ versionNumberProcess.setCommand({filePath("uname"), {"-r"}});
+ versionNumberProcess.runBlocking(EventLoopMode::On);
QByteArray output = versionNumberProcess.readAllStandardOutput();
QString versionMessage = QString::fromLatin1(output);
@@ -124,27 +142,33 @@ void QnxDevice::updateVersionNumber() const
int patch = match.captured(3).toInt();
m_versionNumber = (major << 16)|(minor<<8)|(patch);
}
-
- if (isGuiThread)
- QApplication::restoreOverrideCursor();
}
void QnxDevice::fromMap(const QVariantMap &map)
{
m_versionNumber = map.value(QLatin1String(QnxVersionKey), 0).toInt();
- RemoteLinux::LinuxDevice::fromMap(map);
+ LinuxDevice::fromMap(map);
}
QVariantMap QnxDevice::toMap() const
{
- QVariantMap map(RemoteLinux::LinuxDevice::toMap());
+ QVariantMap map(LinuxDevice::toMap());
map.insert(QLatin1String(QnxVersionKey), m_versionNumber);
return map;
}
-PortsGatheringMethod::Ptr QnxDevice::portsGatheringMethod() const
+PortsGatheringMethod QnxDevice::portsGatheringMethod() const
{
- return PortsGatheringMethod::Ptr(new QnxPortsGatheringMethod);
+ return {
+ // TODO: The command is probably needlessly complicated because the parsing method
+ // used to be fixed. These two can now be matched to each other.
+ [this](QAbstractSocket::NetworkLayerProtocol protocol) -> CommandLine {
+ Q_UNUSED(protocol)
+ return {filePath("netstat"), {"-na"}};
+ },
+
+ &Port::parseFromNetstatOutput
+ };
}
DeviceProcessList *QnxDevice::createProcessListModel(QObject *parent) const
@@ -157,15 +181,14 @@ DeviceTester *QnxDevice::createDeviceTester() const
return new QnxDeviceTester;
}
-DeviceProcess *QnxDevice::createProcess(QObject *parent) const
+Utils::ProcessInterface *QnxDevice::createProcessInterface() const
{
- return new QnxDeviceProcess(sharedFromThis(), parent);
+ return new QnxProcessImpl(this);
}
DeviceProcessSignalOperation::Ptr QnxDevice::signalOperation() const
{
- return DeviceProcessSignalOperation::Ptr(
- new QnxDeviceProcessSignalOperation(sshParameters()));
+ return DeviceProcessSignalOperation::Ptr(new QnxDeviceProcessSignalOperation(sharedFromThis()));
}
// Factory
diff --git a/src/plugins/qnx/qnxdevice.h b/src/plugins/qnx/qnxdevice.h
index 7ea275c7428..af72214d5ea 100644
--- a/src/plugins/qnx/qnxdevice.h
+++ b/src/plugins/qnx/qnxdevice.h
@@ -42,12 +42,12 @@ public:
static Ptr create() { return Ptr(new QnxDevice); }
- ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const override;
+ ProjectExplorer::PortsGatheringMethod portsGatheringMethod() const override;
ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const override;
ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override;
ProjectExplorer::DeviceTester *createDeviceTester() const override;
- ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const override;
+ Utils::ProcessInterface *createProcessInterface() const override;
int qnxVersion() const;
diff --git a/src/plugins/qnx/qnxdeviceprocess.cpp b/src/plugins/qnx/qnxdeviceprocess.cpp
deleted file mode 100644
index 0a272c3d001..00000000000
--- a/src/plugins/qnx/qnxdeviceprocess.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 BlackBerry Limited. All rights reserved.
-** Contact: KDAB (info@kdab.com)
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "qnxdeviceprocess.h"
-
-#include <projectexplorer/devicesupport/sshdeviceprocess.h>
-#include <projectexplorer/runcontrol.h>
-
-#include <utils/qtcprocess.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Qnx {
-namespace Internal {
-
-static int pidFileCounter = 0;
-
-QnxDeviceProcess::QnxDeviceProcess(const QSharedPointer<const IDevice> &device, QObject *parent)
- : SshDeviceProcess(device, parent)
-{
- m_pidFile = QString::fromLatin1("/var/run/qtc.%1.pid").arg(++pidFileCounter);
-}
-
-QString QnxDeviceProcess::fullCommandLine(const Runnable &runnable) const
-{
- QStringList args = ProcessArgs::splitArgs(runnable.command.arguments());
- args.prepend(runnable.command.executable().toString());
- QString cmd = ProcessArgs::createUnixArgs(args).toString();
-
- QString fullCommandLine =
- "test -f /etc/profile && . /etc/profile ; "
- "test -f $HOME/profile && . $HOME/profile ; ";
-
- if (!runnable.workingDirectory.isEmpty())
- fullCommandLine += QString::fromLatin1("cd %1 ; ").arg(
- ProcessArgs::quoteArg(runnable.workingDirectory.toString()));
-
- const Environment env = runnable.environment;
- for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
- fullCommandLine += QString::fromLatin1("%1='%2' ")
- .arg(env.key(it)).arg(env.expandedValueForKey(env.key(it)));
- }
-
- fullCommandLine += QString::fromLatin1("%1 & echo $! > %2").arg(cmd).arg(m_pidFile);
-
- return fullCommandLine;
-}
-
-void QnxDeviceProcess::doSignal(int sig)
-{
- auto signaler = new SshDeviceProcess(device(), this);
- Runnable r;
- const QString args = QString("-%2 `cat %1`").arg(m_pidFile).arg(sig);
- r.command = CommandLine(FilePath::fromString("kill"), args, CommandLine::Raw);
- connect(signaler, &SshDeviceProcess::finished, signaler, &QObject::deleteLater);
- signaler->start(r);
-}
-
-} // namespace Internal
-} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdeviceprocess.h b/src/plugins/qnx/qnxdeviceprocess.h
deleted file mode 100644
index eeffad6fbb4..00000000000
--- a/src/plugins/qnx/qnxdeviceprocess.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 BlackBerry Limited. All rights reserved.
-** Contact: KDAB (info@kdab.com)
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "qnx_export.h"
-#include <remotelinux/linuxdevice.h>
-#include <projectexplorer/devicesupport/sshdeviceprocess.h>
-
-namespace Qnx {
-namespace Internal {
-
-class QnxDeviceProcess : public ProjectExplorer::SshDeviceProcess
-{
-public:
- QnxDeviceProcess(const QSharedPointer<const ProjectExplorer::IDevice> &device, QObject *parent);
-
- void interrupt() override { doSignal(2); }
- void terminate() override { doSignal(15); }
- void kill() override { doSignal(9); }
- QString fullCommandLine(const ProjectExplorer::Runnable &runnable) const override;
-
-private:
- void doSignal(int sig);
- QString m_pidFile;
-};
-
-} // namespace Internal
-} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdeviceprocesslist.cpp b/src/plugins/qnx/qnxdeviceprocesslist.cpp
index 1269ea3c165..df45f9f8093 100644
--- a/src/plugins/qnx/qnxdeviceprocesslist.cpp
+++ b/src/plugins/qnx/qnxdeviceprocesslist.cpp
@@ -25,14 +25,17 @@
#include "qnxdeviceprocesslist.h"
+#include <projectexplorer/devicesupport/idevice.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
+#include <utils/processinfo.h>
#include <QRegularExpression>
#include <QStringList>
using namespace Qnx;
using namespace Qnx::Internal;
+using namespace Utils;
QnxDeviceProcessList::QnxDeviceProcessList(
const ProjectExplorer::IDevice::ConstPtr &device, QObject *parent)
@@ -45,10 +48,9 @@ QString QnxDeviceProcessList::listProcessesCommandLine() const
return QLatin1String("pidin -F '%a %A {/%n}'");
}
-QList<ProjectExplorer::DeviceProcessItem> QnxDeviceProcessList::buildProcessList(
- const QString &listProcessesReply) const
+QList<ProcessInfo> QnxDeviceProcessList::buildProcessList(const QString &listProcessesReply) const
{
- QList<ProjectExplorer::DeviceProcessItem> processes;
+ QList<ProcessInfo> processes;
QStringList lines = listProcessesReply.split(QLatin1Char('\n'));
if (lines.isEmpty())
return processes;
@@ -64,10 +66,10 @@ QList<ProjectExplorer::DeviceProcessItem> QnxDeviceProcessList::buildProcessList
const int pid = captures[1].toInt();
const QString args = captures[2];
const QString exe = captures[3];
- ProjectExplorer::DeviceProcessItem deviceProcess;
- deviceProcess.pid = pid;
- deviceProcess.exe = exe.trimmed();
- deviceProcess.cmdLine = args.trimmed();
+ ProcessInfo deviceProcess;
+ deviceProcess.processId = pid;
+ deviceProcess.executable = exe.trimmed();
+ deviceProcess.commandLine = args.trimmed();
processes.append(deviceProcess);
}
}
diff --git a/src/plugins/qnx/qnxdeviceprocesslist.h b/src/plugins/qnx/qnxdeviceprocesslist.h
index 4f96b1afe7e..1de7d3a7c06 100644
--- a/src/plugins/qnx/qnxdeviceprocesslist.h
+++ b/src/plugins/qnx/qnxdeviceprocesslist.h
@@ -25,7 +25,6 @@
#pragma once
-#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/sshdeviceprocesslist.h>
namespace Qnx {
@@ -36,12 +35,11 @@ class QnxDeviceProcessList : public ProjectExplorer::SshDeviceProcessList
Q_OBJECT
public:
explicit QnxDeviceProcessList(
- const ProjectExplorer::IDevice::ConstPtr &device, QObject *parent = nullptr);
+ const ProjectExplorer::IDeviceConstPtr &device, QObject *parent = nullptr);
private:
QString listProcessesCommandLine() const override;
- QList<ProjectExplorer::DeviceProcessItem> buildProcessList(
- const QString &listProcessesReply) const override;
+ QList<Utils::ProcessInfo> buildProcessList(const QString &listProcessesReply) const override;
};
} // namespace Internal
diff --git a/src/plugins/qnx/qnxdeviceprocesssignaloperation.cpp b/src/plugins/qnx/qnxdeviceprocesssignaloperation.cpp
index be72624d7ce..24b6417f0dc 100644
--- a/src/plugins/qnx/qnxdeviceprocesssignaloperation.cpp
+++ b/src/plugins/qnx/qnxdeviceprocesssignaloperation.cpp
@@ -25,14 +25,11 @@
#include "qnxdeviceprocesssignaloperation.h"
-#include <utils/fileutils.h>
-
-using namespace Qnx;
using namespace Qnx::Internal;
QnxDeviceProcessSignalOperation::QnxDeviceProcessSignalOperation(
- const QSsh::SshConnectionParameters &sshParameters)
- : RemoteLinux::RemoteLinuxSignalOperation(sshParameters)
+ const ProjectExplorer::IDeviceConstPtr &device)
+ : RemoteLinux::RemoteLinuxSignalOperation(device)
{
}
diff --git a/src/plugins/qnx/qnxdeviceprocesssignaloperation.h b/src/plugins/qnx/qnxdeviceprocesssignaloperation.h
index be3795bba0c..d1337fbb169 100644
--- a/src/plugins/qnx/qnxdeviceprocesssignaloperation.h
+++ b/src/plugins/qnx/qnxdeviceprocesssignaloperation.h
@@ -34,7 +34,7 @@ class QnxDeviceProcessSignalOperation : public RemoteLinux::RemoteLinuxSignalOpe
{
Q_OBJECT
protected:
- explicit QnxDeviceProcessSignalOperation(const QSsh::SshConnectionParameters &sshParameters);
+ explicit QnxDeviceProcessSignalOperation(const ProjectExplorer::IDeviceConstPtr &device);
private:
QString killProcessByNameCommandLine(const QString &filePath) const override;
diff --git a/src/plugins/qnx/qnxdevicetester.cpp b/src/plugins/qnx/qnxdevicetester.cpp
index 17787274c0f..8dd664ad8b7 100644
--- a/src/plugins/qnx/qnxdevicetester.cpp
+++ b/src/plugins/qnx/qnxdevicetester.cpp
@@ -26,18 +26,15 @@
#include "qnxdevicetester.h"
#include "qnxdevice.h"
-#include <ssh/sshremoteprocessrunner.h>
#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
+
+using namespace Utils;
namespace Qnx {
namespace Internal {
QnxDeviceTester::QnxDeviceTester(QObject *parent)
: ProjectExplorer::DeviceTester(parent)
- , m_result(TestSuccess)
- , m_state(Inactive)
- , m_currentCommandIndex(-1)
{
m_genericTester = new RemoteLinux::GenericLinuxDeviceTester(this);
connect(m_genericTester, &DeviceTester::progressMessage,
@@ -47,11 +44,7 @@ QnxDeviceTester::QnxDeviceTester(QObject *parent)
connect(m_genericTester, &DeviceTester::finished,
this, &QnxDeviceTester::handleGenericTestFinished);
- m_processRunner = new QSsh::SshRemoteProcessRunner(this);
- connect(m_processRunner, &QSsh::SshRemoteProcessRunner::connectionError,
- this, &QnxDeviceTester::handleConnectionError);
- connect(m_processRunner, &QSsh::SshRemoteProcessRunner::processClosed,
- this, &QnxDeviceTester::handleProcessFinished);
+ connect(&m_process, &QtcProcess::done, this, &QnxDeviceTester::handleProcessDone);
m_commandsToTest << QLatin1String("awk")
<< QLatin1String("cat")
@@ -75,9 +68,7 @@ QnxDeviceTester::QnxDeviceTester(QObject *parent)
void QnxDeviceTester::testDevice(const ProjectExplorer::IDevice::Ptr &deviceConfiguration)
{
QTC_ASSERT(m_state == Inactive, return);
-
m_deviceConfiguration = deviceConfiguration;
-
m_state = GenericTest;
m_genericTester->testDevice(deviceConfiguration);
}
@@ -86,20 +77,10 @@ void QnxDeviceTester::stopTest()
{
QTC_ASSERT(m_state != Inactive, return);
- switch (m_state) {
- case Inactive:
- break;
- case GenericTest:
+ if (m_state == GenericTest)
m_genericTester->stopTest();
- break;
- case VarRunTest:
- case CommandsTest:
- m_processRunner->cancel();
- break;
- }
- m_result = TestFailure;
- setFinished();
+ setFinished(TestFailure);
}
void QnxDeviceTester::handleGenericTestFinished(TestResult result)
@@ -107,98 +88,88 @@ void QnxDeviceTester::handleGenericTestFinished(TestResult result)
QTC_ASSERT(m_state == GenericTest, return);
if (result == TestFailure) {
- m_result = TestFailure;
- setFinished();
+ setFinished(TestFailure);
return;
}
m_state = VarRunTest;
emit progressMessage(tr("Checking that files can be created in /var/run..."));
- m_processRunner->run(QStringLiteral("rm %1 > /dev/null 2>&1; echo ABC > %1 && rm %1")
- .arg("/var/run/qtc_xxxx.pid"),
- m_deviceConfiguration->sshParameters());
+ const CommandLine cmd {m_deviceConfiguration->filePath("/bin/sh"),
+ {"-c", QLatin1String("rm %1 > /dev/null 2>&1; echo ABC > %1 && rm %1")
+ .arg("/var/run/qtc_xxxx.pid")}};
+ m_process.setCommand(cmd);
+ m_process.start();
}
-void QnxDeviceTester::handleVarRunProcessFinished(const QString &error)
+void QnxDeviceTester::handleProcessDone()
{
- QTC_ASSERT(m_state == VarRunTest, return);
-
- if (error.isEmpty()) {
- if (m_processRunner->processExitCode() == 0) {
- emit progressMessage(tr("Files can be created in /var/run.") + QLatin1Char('\n'));
- } else {
- emit errorMessage(tr("Files cannot be created in /var/run.") + QLatin1Char('\n'));
- m_result = TestFailure;
- }
+ if (m_state == VarRunTest)
+ handleVarRunDone();
+ else if (m_state == CommandsTest)
+ handleCommandDone();
+ else
+ QTC_CHECK(false);
+}
+
+void QnxDeviceTester::handleVarRunDone()
+{
+ if (m_process.result() == ProcessResult::FinishedWithSuccess) {
+ emit progressMessage(tr("Files can be created in /var/run.") + '\n');
} else {
- emit errorMessage(tr("An error occurred while checking that"
- " files can be created in /var/run.")
- + QLatin1Char('\n'));
m_result = TestFailure;
+ const QString message = m_process.result() == ProcessResult::StartFailed
+ ? tr("An error occurred while checking that files can be created in /var/run.")
+ + '\n' + m_process.errorString()
+ : tr("Files cannot be created in /var/run.");
+ emit errorMessage(message + '\n');
}
- m_state = CommandsTest;
-
QnxDevice::ConstPtr qnxDevice = m_deviceConfiguration.dynamicCast<const QnxDevice>();
m_commandsToTest.append(versionSpecificCommandsToTest(qnxDevice->qnxVersion()));
testNextCommand();
}
-void QnxDeviceTester::handleProcessFinished(const QString &error)
+void QnxDeviceTester::handleCommandDone()
{
- if (m_state == VarRunTest) {
- handleVarRunProcessFinished(error);
- return;
- }
-
- QTC_ASSERT(m_state == CommandsTest, return);
-
const QString command = m_commandsToTest[m_currentCommandIndex];
- if (error.isEmpty()) {
- if (m_processRunner->processExitCode() == 0) {
- emit progressMessage(tr("%1 found.").arg(command) + QLatin1Char('\n'));
- } else {
- emit errorMessage(tr("%1 not found.").arg(command) + QLatin1Char('\n'));
- m_result = TestFailure;
- }
+ if (m_process.result() == ProcessResult::FinishedWithSuccess) {
+ emit progressMessage(tr("%1 found.").arg(command) + '\n');
} else {
- emit errorMessage(tr("An error occurred while checking for %1.").arg(command) + QLatin1Char('\n'));
m_result = TestFailure;
+ const QString message = m_process.result() == ProcessResult::StartFailed
+ ? tr("An error occurred while checking for %1.").arg(command)
+ + '\n' + m_process.errorString()
+ : tr("%1 not found.").arg(command);
+ emit errorMessage(message + '\n');
}
- testNextCommand();
-}
-void QnxDeviceTester::handleConnectionError()
-{
- QTC_ASSERT(m_state == CommandsTest, return);
-
- m_result = TestFailure;
- emit errorMessage(tr("SSH connection error: %1").arg(m_processRunner->lastConnectionErrorString()) + QLatin1Char('\n'));
- setFinished();
+ ++m_currentCommandIndex;
+ testNextCommand();
}
void QnxDeviceTester::testNextCommand()
{
- ++m_currentCommandIndex;
-
- if (m_currentCommandIndex >= m_commandsToTest.size()) {
- setFinished();
+ m_state = CommandsTest;
+ m_process.close();
+ if (m_commandsToTest.size() == m_currentCommandIndex) {
+ setFinished(TestSuccess);
return;
}
- QString command = m_commandsToTest[m_currentCommandIndex];
+ const QString command = m_commandsToTest[m_currentCommandIndex];
emit progressMessage(tr("Checking for %1...").arg(command));
-
- m_processRunner->run("command -v " + command, m_deviceConfiguration->sshParameters());
+ m_process.setCommand({m_deviceConfiguration->filePath("command"), {"-v", command}});
+ m_process.start();
}
-void QnxDeviceTester::setFinished()
+void QnxDeviceTester::setFinished(TestResult result)
{
+ if (m_result == TestSuccess)
+ m_result = result;
m_state = Inactive;
disconnect(m_genericTester, nullptr, this, nullptr);
- if (m_processRunner)
- disconnect(m_processRunner, nullptr, this, nullptr);
+ m_process.close();
emit finished(m_result);
}
diff --git a/src/plugins/qnx/qnxdevicetester.h b/src/plugins/qnx/qnxdevicetester.h
index 21c555e5381..4941cb6c8a5 100644
--- a/src/plugins/qnx/qnxdevicetester.h
+++ b/src/plugins/qnx/qnxdevicetester.h
@@ -26,29 +26,23 @@
#pragma once
#include <remotelinux/linuxdevicetester.h>
+#include <utils/qtcprocess.h>
#include <QStringList>
-namespace QSsh { class SshRemoteProcessRunner; }
-
namespace Qnx {
namespace Internal {
class QnxDeviceTester : public ProjectExplorer::DeviceTester
{
Q_OBJECT
+
public:
explicit QnxDeviceTester(QObject *parent = nullptr);
void testDevice(const ProjectExplorer::IDevice::Ptr &deviceConfiguration) override;
void stopTest() override;
-private slots:
- void handleGenericTestFinished(ProjectExplorer::DeviceTester::TestResult result);
-
- void handleProcessFinished(const QString &error);
- void handleConnectionError();
-
private:
enum State {
Inactive,
@@ -57,21 +51,24 @@ private:
CommandsTest
};
+ void handleGenericTestFinished(ProjectExplorer::DeviceTester::TestResult result);
+ void handleProcessDone();
+ void handleVarRunDone();
+ void handleCommandDone();
+
void testNextCommand();
- void setFinished();
+ void setFinished(ProjectExplorer::DeviceTester::TestResult result);
QStringList versionSpecificCommandsToTest(int versionNumber) const;
- void handleVarRunProcessFinished(const QString &error);
-
RemoteLinux::GenericLinuxDeviceTester *m_genericTester;
ProjectExplorer::IDevice::ConstPtr m_deviceConfiguration;
- ProjectExplorer::DeviceTester::TestResult m_result;
- State m_state;
+ ProjectExplorer::DeviceTester::TestResult m_result = TestSuccess;
+ State m_state = Inactive;
- int m_currentCommandIndex;
+ int m_currentCommandIndex = 0;
QStringList m_commandsToTest;
- QSsh::SshRemoteProcessRunner *m_processRunner;
+ Utils::QtcProcess m_process;
};
} // namespace Internal
diff --git a/src/plugins/qnx/qnxdevicewizard.cpp b/src/plugins/qnx/qnxdevicewizard.cpp
index c0e64a53903..292f6946bff 100644
--- a/src/plugins/qnx/qnxdevicewizard.cpp
+++ b/src/plugins/qnx/qnxdevicewizard.cpp
@@ -27,7 +27,7 @@
#include "qnxconstants.h"
-#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <remotelinux/genericlinuxdeviceconfigurationwizardpages.h>
#include <utils/portlist.h>
@@ -50,7 +50,7 @@ QnxDeviceWizard::QnxDeviceWizard(QWidget *parent) :
setPage(KeyDeploymenPageId, m_keyDeploymentPage);
setPage(FinalPageId, m_finalPage);
m_finalPage->setCommitPage(true);
- QSsh::SshConnectionParameters sshParams;
+ SshParameters sshParams;
sshParams.timeout = 10;
m_device = QnxDevice::create();
m_device->setupId(IDevice::ManuallyAdded);
diff --git a/src/plugins/qnx/qnxplugin.cpp b/src/plugins/qnx/qnxplugin.cpp
index 2adaa33d78b..f5cf7991ec6 100644
--- a/src/plugins/qnx/qnxplugin.cpp
+++ b/src/plugins/qnx/qnxplugin.cpp
@@ -56,7 +56,6 @@
#include <remotelinux/genericdirectuploadstep.h>
#include <remotelinux/makeinstallstep.h>
-#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
#include <remotelinux/remotelinux_constants.h>
#include <qtsupport/qtkitinformation.h>
@@ -105,7 +104,6 @@ public:
&& prj->hasMakeInstallEquivalent();
});
addInitialStep(DeviceCheckBuildStep::stepId());
- addInitialStep(RemoteLinux::Constants::CheckForFreeDiskSpaceId);
addInitialStep(QnxUploadStep::stepId());
}
};
@@ -123,7 +121,6 @@ public:
QnxDeviceFactory deviceFactory;
QnxDeployConfigurationFactory deployConfigFactory;
GenericQnxDeployStepFactory<QnxUploadStep> directUploadDeployFactory;
- GenericQnxDeployStepFactory<RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep> checkForFreeDiskSpaceDeployFactory;
GenericQnxDeployStepFactory<RemoteLinux::MakeInstallStep> makeInstallDeployFactory;
GenericQnxDeployStepFactory<DeviceCheckBuildStep> checkBuildDeployFactory;
QnxRunConfigurationFactory runConfigFactory;
diff --git a/src/plugins/qnx/qnxqtversion.h b/src/plugins/qnx/qnxqtversion.h
index c67aaafc971..c75968da9ff 100644
--- a/src/plugins/qnx/qnxqtversion.h
+++ b/src/plugins/qnx/qnxqtversion.h
@@ -66,11 +66,11 @@ public:
Utils::FilePath sdpPath() const;
void setSdpPath(const Utils::FilePath &sdpPath);
+ Utils::EnvironmentItems environment() const;
+
private:
void updateEnvironment() const;
- Utils::EnvironmentItems environment() const;
-
Utils::FilePath m_sdpPath;
mutable QString m_cpuDir;
diff --git a/src/plugins/qnx/qnxrunconfiguration.cpp b/src/plugins/qnx/qnxrunconfiguration.cpp
index 02f61894b71..927a9a94691 100644
--- a/src/plugins/qnx/qnxrunconfiguration.cpp
+++ b/src/plugins/qnx/qnxrunconfiguration.cpp
@@ -44,12 +44,11 @@ using namespace Utils;
namespace Qnx {
namespace Internal {
-QnxRunConfiguration::QnxRunConfiguration(Target *target, Utils::Id id)
+QnxRunConfiguration::QnxRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- auto exeAspect = addAspect<ExecutableAspect>();
+ auto exeAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
exeAspect->setLabelText(tr("Executable on device:"));
- exeAspect->setExecutablePathStyle(OsTypeLinux);
exeAspect->setPlaceHolderText(tr("Remote path not set"));
exeAspect->makeOverridable("RemoteLinux.RunConfig.AlternateRemoteExecutable",
"RemoteLinux.RunConfig.UseAlternateRemoteExecutable");
@@ -59,10 +58,11 @@ QnxRunConfiguration::QnxRunConfiguration(Target *target, Utils::Id id)
symbolsAspect->setLabelText(tr("Executable on host:"));
symbolsAspect->setDisplayStyle(SymbolFileAspect::LabelDisplay);
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ auto envAspect = addAspect<RemoteLinuxEnvironmentAspect>(target);
+
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
addAspect<TerminalAspect>();
- addAspect<RemoteLinuxEnvironmentAspect>(target);
auto libAspect = addAspect<StringAspect>();
libAspect->setSettingsKey("Qt4ProjectManager.QnxRunConfiguration.QtLibPath");
diff --git a/src/plugins/qnx/qnxtoolchain.cpp b/src/plugins/qnx/qnxtoolchain.cpp
index 1503552a8ee..08ec60699f8 100644
--- a/src/plugins/qnx/qnxtoolchain.cpp
+++ b/src/plugins/qnx/qnxtoolchain.cpp
@@ -221,6 +221,10 @@ QnxToolChainFactory::QnxToolChainFactory()
Toolchains QnxToolChainFactory::autoDetect(const ToolchainDetector &detector) const
{
+ // FIXME: Support detecting toolchains on remote devices
+ if (detector.device)
+ return {};
+
Toolchains tcs;
const auto configurations = QnxConfigurationManager::instance()->configurations();
for (QnxConfiguration *configuration : configurations)
diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp
index 90e3aeb8518..1670419a432 100644
--- a/src/plugins/qnx/qnxutils.cpp
+++ b/src/plugins/qnx/qnxutils.cpp
@@ -118,16 +118,14 @@ EnvironmentItems QnxUtils::qnxEnvironmentFromEnvFile(const FilePath &filePath)
QApplication::setOverrideCursor(Qt::BusyCursor);
bool waitResult = process.waitForFinished(10000);
QApplication::restoreOverrideCursor();
- if (!waitResult) {
- process.stopProcess();
+ if (!waitResult)
return items;
- }
- if (process.result() != QtcProcess::FinishedWithSuccess)
+ if (process.result() != ProcessResult::FinishedWithSuccess)
return items;
// parsing process output
- const QString output = process.stdOut();
+ const QString output = process.cleanedStdOut();
for (const QString &line : output.split('\n')) {
int equalIndex = line.indexOf('=');
if (equalIndex < 0)
diff --git a/src/plugins/qnx/slog2inforunner.cpp b/src/plugins/qnx/slog2inforunner.cpp
index c5209fdfe54..7c632a30ca5 100644
--- a/src/plugins/qnx/slog2inforunner.cpp
+++ b/src/plugins/qnx/slog2inforunner.cpp
@@ -26,12 +26,12 @@
#include "slog2inforunner.h"
#include "qnxdevice.h"
-#include "qnxdeviceprocess.h"
#include "qnxrunconfiguration.h"
#include <projectexplorer/runconfigurationaspects.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QRegularExpression>
@@ -45,22 +45,22 @@ Slog2InfoRunner::Slog2InfoRunner(RunControl *runControl)
: RunWorker(runControl)
{
setId("Slog2InfoRunner");
- m_applicationId = runControl->aspect<ExecutableAspect>()->executable().fileName();
+ m_applicationId = runControl->aspect<ExecutableAspect>()->executable.fileName();
// See QTCREATORBUG-10712 for details.
// We need to limit length of ApplicationId to 63 otherwise it would not match one in slog2info.
m_applicationId.truncate(63);
- m_testProcess = new QnxDeviceProcess(device(), this);
- connect(m_testProcess, &DeviceProcess::finished, this, &Slog2InfoRunner::handleTestProcessCompleted);
+ m_testProcess = new QtcProcess(this);
+ connect(m_testProcess, &QtcProcess::done, this, &Slog2InfoRunner::handleTestProcessCompleted);
- m_launchDateTimeProcess = new SshDeviceProcess(device(), this);
- connect(m_launchDateTimeProcess, &DeviceProcess::finished, this, &Slog2InfoRunner::launchSlog2Info);
+ m_launchDateTimeProcess = new QtcProcess(this);
+ connect(m_launchDateTimeProcess, &QtcProcess::done, this, &Slog2InfoRunner::launchSlog2Info);
- m_logProcess = new QnxDeviceProcess(device(), this);
- connect(m_logProcess, &DeviceProcess::readyReadStandardOutput, this, &Slog2InfoRunner::readLogStandardOutput);
- connect(m_logProcess, &DeviceProcess::readyReadStandardError, this, &Slog2InfoRunner::readLogStandardError);
- connect(m_logProcess, &DeviceProcess::errorOccurred, this, &Slog2InfoRunner::handleLogError);
+ m_logProcess = new QtcProcess(this);
+ connect(m_logProcess, &QtcProcess::readyReadStandardOutput, this, &Slog2InfoRunner::readLogStandardOutput);
+ connect(m_logProcess, &QtcProcess::readyReadStandardError, this, &Slog2InfoRunner::readLogStandardError);
+ connect(m_logProcess, &QtcProcess::done, this, &Slog2InfoRunner::handleLogDone);
}
void Slog2InfoRunner::printMissingWarning()
@@ -70,9 +70,8 @@ void Slog2InfoRunner::printMissingWarning()
void Slog2InfoRunner::start()
{
- Runnable r;
- r.command = {"slog2info", {}};
- m_testProcess->start(r);
+ m_testProcess->setCommand({device()->filePath("slog2info"), {}});
+ m_testProcess->start();
reportStarted();
}
@@ -108,9 +107,9 @@ void Slog2InfoRunner::handleTestProcessCompleted()
void Slog2InfoRunner::readLaunchTime()
{
- Runnable r;
- r.command = CommandLine("date", "+\"%d %H:%M:%S\"", CommandLine::Raw);
- m_launchDateTimeProcess->start(r);
+ m_launchDateTimeProcess->setCommand({device()->filePath("date"),
+ "+\"%d %H:%M:%S\"", CommandLine::Raw});
+ m_launchDateTimeProcess->start();
}
void Slog2InfoRunner::launchSlog2Info()
@@ -121,12 +120,14 @@ void Slog2InfoRunner::launchSlog2Info()
if (m_logProcess->state() == QProcess::Running)
return;
+ if (m_launchDateTimeProcess->error() != QProcess::UnknownError)
+ return;
+
m_launchDateTime = QDateTime::fromString(QString::fromLatin1(m_launchDateTimeProcess->readAllStandardOutput()).trimmed(),
QString::fromLatin1("dd HH:mm:ss"));
- Runnable r;
- r.command = {"slog2info", {"-w"}};
- m_logProcess->start(r);
+ m_logProcess->setCommand({device()->filePath("slog2info"), {"-w"}});
+ m_logProcess->start();
}
void Slog2InfoRunner::readLogStandardOutput()
@@ -193,8 +194,11 @@ void Slog2InfoRunner::readLogStandardError()
appendMessage(QString::fromLatin1(m_logProcess->readAllStandardError()), Utils::StdErrFormat);
}
-void Slog2InfoRunner::handleLogError()
+void Slog2InfoRunner::handleLogDone()
{
+ if (m_logProcess->error() == QProcess::UnknownError)
+ return;
+
appendMessage(tr("Cannot show slog2info output. Error: %1")
.arg(m_logProcess->errorString()), Utils::StdErrFormat);
}
diff --git a/src/plugins/qnx/slog2inforunner.h b/src/plugins/qnx/slog2inforunner.h
index 92a4ace254e..1f6f4aeb22a 100644
--- a/src/plugins/qnx/slog2inforunner.h
+++ b/src/plugins/qnx/slog2inforunner.h
@@ -28,13 +28,12 @@
#include <QObject>
#include <projectexplorer/runcontrol.h>
-#include <remotelinux/linuxdevice.h>
#include <utils/outputformat.h>
#include <QDateTime>
#include <QByteArray>
-namespace ProjectExplorer { class SshDeviceProcess; }
+namespace Utils { class QtcProcess; }
namespace Qnx {
namespace Internal {
@@ -56,7 +55,7 @@ private:
void readLogStandardOutput();
void readLogStandardError();
- void handleLogError();
+ void handleLogDone();
void printMissingWarning();
void readLaunchTime();
@@ -70,9 +69,9 @@ private:
bool m_currentLogs = false;
QString m_remainingData;
- ProjectExplorer::SshDeviceProcess *m_launchDateTimeProcess = nullptr;
- ProjectExplorer::SshDeviceProcess *m_testProcess = nullptr;
- ProjectExplorer::SshDeviceProcess *m_logProcess = nullptr;
+ Utils::QtcProcess *m_launchDateTimeProcess = nullptr;
+ Utils::QtcProcess *m_testProcess = nullptr;
+ Utils::QtcProcess *m_logProcess = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/qtsupport/CMakeLists.txt b/src/plugins/qtsupport/CMakeLists.txt
index 97b79767536..b3cd6b045e8 100644
--- a/src/plugins/qtsupport/CMakeLists.txt
+++ b/src/plugins/qtsupport/CMakeLists.txt
@@ -29,7 +29,6 @@ add_qtc_plugin(QtSupport
qtversioninfo.ui
qtversionmanager.cpp qtversionmanager.h qtversionmanager.ui
qtversions.cpp qtversions.h
- screenshotcropper.cpp screenshotcropper.h
showbuildlog.ui
translationwizardpage.cpp translationwizardpage.h
uicgenerator.cpp uicgenerator.h
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index 1aafe1f575c..8b51cdaa6d9 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -157,6 +157,10 @@ static QSet<Id> versionedIds(const QByteArray &prefix, int major, int minor)
result.insert(Id::fromName(featureDotMajor + '.' + minorStr));
}
+ // FIXME: Terrible hack. Get rid of using version numbers as tags!
+ if (major > 5)
+ result.unite(versionedIds(prefix, major - 1, 15));
+
return result;
}
@@ -190,7 +194,7 @@ public:
static bool queryQMakeVariables(const FilePath &binary,
const Environment &env,
QHash<ProKey, ProString> *versionInfo,
- QString *error = nullptr);
+ QString *error);
enum PropertyVariant { PropertyVariantDev, PropertyVariantGet, PropertyVariantSrc };
QString qmakeProperty(const QByteArray &name, PropertyVariant variant = PropertyVariantGet);
static QString qmakeProperty(const QHash<ProKey, ProString> &versionInfo,
@@ -1321,10 +1325,11 @@ void QtVersionPrivate::updateVersionInfo()
m_data.hasExamples = false;
m_data.hasDocumentation = false;
- if (!queryQMakeVariables(m_qmakeCommand, q->qmakeRunEnvironment(), &m_versionInfo)) {
+ QString error;
+ if (!queryQMakeVariables(m_qmakeCommand, q->qmakeRunEnvironment(), &m_versionInfo, &error)) {
m_qmakeIsExecutable = false;
- qWarning("Cannot update Qt version information: %s cannot be run.",
- qPrintable(m_qmakeCommand.toString()));
+ qWarning("Cannot update Qt version information from %s: %s.",
+ qPrintable(m_qmakeCommand.displayName()), qPrintable(error));
return;
}
m_qmakeIsExecutable = true;
@@ -1692,7 +1697,7 @@ void QtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Target
if (startupProject) {
if (ProjectNode *rootNode = startupProject->rootProjectNode()) {
rootNode->forEachNode([&](FileNode *node) {
- if (auto resourceNode = dynamic_cast<ResourceEditor::ResourceFileNode *>(node))
+ if (auto resourceNode = dynamic_cast<ProjectExplorer::ResourceFileNode *>(node))
finder->addMappedPath(node->filePath(), ":" + resourceNode->qrcPath());
});
} else {
@@ -1760,7 +1765,7 @@ Tasks QtVersion::reportIssuesImpl(const QString &proFile, const QString &buildDi
if (!qmake.isExecutableFile()) {
//: %1: Path to qmake executable
const QString msg = QCoreApplication::translate("QmakeProjectManager::QtVersion",
- "The qmake command \"%1\" was not found or is not executable.").arg(qmake.toUserOutput());
+ "The qmake command \"%1\" was not found or is not executable.").arg(qmake.displayName());
results.append(BuildSystemTask(Task::Error, msg));
}
@@ -1799,21 +1804,30 @@ static QByteArray runQmakeQuery(const FilePath &binary, const Environment &env,
process.start();
if (!process.waitForStarted()) {
- *error = QCoreApplication::translate("QtVersion", "Cannot start \"%1\": %2").arg(binary.toUserOutput()).arg(process.errorString());
- return QByteArray();
+ *error = QCoreApplication::translate("QtVersion", "Cannot start \"%1\": %2")
+ .arg(binary.displayName()).arg(process.errorString());
+ return {};
}
if (!process.waitForFinished(timeOutMS)) {
- process.stopProcess();
- *error = QCoreApplication::translate("QtVersion", "Timeout running \"%1\" (%2 ms).").arg(binary.toUserOutput()).arg(timeOutMS);
- return QByteArray();
+ *error = QCoreApplication::translate("QtVersion", "Timeout running \"%1\" (%2 ms).")
+ .arg(binary.displayName()).arg(timeOutMS);
+ return {};
}
if (process.exitStatus() != QProcess::NormalExit) {
- *error = QCoreApplication::translate("QtVersion", "\"%1\" crashed.").arg(binary.toUserOutput());
- return QByteArray();
+ *error = QCoreApplication::translate("QtVersion", "\"%1\" crashed.")
+ .arg(binary.displayName());
+ return {};
+ }
+
+ const QByteArray out = process.readAllStandardOutput();
+ if (out.isEmpty()) {
+ *error = QCoreApplication::translate("QtVersion", "\"%1\" produced no output: %2.")
+ .arg(binary.displayName(), process.cleanedStdErr());
+ return {};
}
error->clear();
- return process.readAllStandardOutput();
+ return out;
}
bool QtVersionPrivate::queryQMakeVariables(const FilePath &binary, const Environment &env,
@@ -1824,7 +1838,8 @@ bool QtVersionPrivate::queryQMakeVariables(const FilePath &binary, const Environ
error = &tmp;
if (!binary.isExecutableFile()) {
- *error = QCoreApplication::translate("QtVersion", "qmake \"%1\" is not an executable.").arg(binary.toUserOutput());
+ *error = QCoreApplication::translate("QtVersion", "qmake \"%1\" is not an executable.")
+ .arg(binary.displayName());
return false;
}
@@ -1837,7 +1852,7 @@ bool QtVersionPrivate::queryQMakeVariables(const FilePath &binary, const Environ
// starting container process caused: exec: "/bin/qmake": stat /bin/qmake: no such file or directory"
// Since we have a rough idea on what the output looks like we can work around this.
// Output does not always start with QT_SYSROOT, see QTCREATORBUG-26123.
- *error = QString::fromUtf8(output);
+ *error += QString::fromUtf8(output);
return false;
}
@@ -2367,7 +2382,7 @@ QtVersion *QtVersionFactory::createQtVersionFromQMakePath
ProFileCacheManager::instance()->decRefCount();
if (error) {
*error = QCoreApplication::translate("QtSupport::QtVersionFactory",
- "No factory found for qmake: \"%1\"").arg(qmakePath.toUserOutput());
+ "No factory found for qmake: \"%1\"").arg(qmakePath.displayName());
}
return nullptr;
}
diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp
index 841ecd318ff..404a565463e 100644
--- a/src/plugins/qtsupport/exampleslistmodel.cpp
+++ b/src/plugins/qtsupport/exampleslistmodel.cpp
@@ -24,9 +24,9 @@
****************************************************************************/
#include "exampleslistmodel.h"
-#include "screenshotcropper.h"
#include <QBuffer>
+#include <QApplication>
#include <QDir>
#include <QFile>
#include <QImageReader>
@@ -527,8 +527,13 @@ QPixmap ExamplesListModel::fetchPixmapAndUpdatePixmapCache(const QString &url) c
imgBuffer.open(QIODevice::ReadOnly);
QImageReader reader(&imgBuffer, QFileInfo(url).suffix().toLatin1());
QImage img = reader.read();
- img = ScreenshotCropper::croppedImage(img, url, ListModel::defaultImageSize);
- pixmap = QPixmap::fromImage(img);
+ img.convertTo(QImage::Format_RGB32);
+ const int dpr = qApp->devicePixelRatio();
+ // boundedTo -> don't scale thumbnails up
+ const QSize scaledSize = ListModel::defaultImageSize.boundedTo(img.size()) * dpr;
+ pixmap = QPixmap::fromImage(
+ img.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ pixmap.setDevicePixelRatio(dpr);
}
}
QPixmapCache::insert(url, pixmap);
diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
index e163165f962..574d9b62209 100644
--- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
+++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
@@ -26,10 +26,11 @@
#include "gettingstartedwelcomepage.h"
#include "exampleslistmodel.h"
-#include "screenshotcropper.h"
+#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/pathchooser.h>
+#include <utils/stylehelper.h>
#include <utils/theme/theme.h>
#include <utils/winutils.h>
@@ -39,8 +40,10 @@
#include <coreplugin/helpmanager.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/welcomepagehelper.h>
-#include <projectexplorer/projectexplorer.h>
+
#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <QComboBox>
#include <QDesktopServices>
@@ -254,6 +257,14 @@ protected:
painter->drawText(currentPixmapRect.translated(0, -WelcomePageHelpers::ItemGap),
exampleItem->videoLength, Qt::AlignBottom | Qt::AlignHCenter);
painter->restore();
+ static const QPixmap playOverlay =
+ StyleHelper::dpiSpecificImageFile(":/qtsupport/images/icons/playoverlay.png");
+ const QSize playOverlaySize = playOverlay.size() / playOverlay.devicePixelRatio();
+ const QPoint playOverlayPos =
+ QPoint((currentPixmapRect.width() - playOverlaySize.width()) / 2,
+ (currentPixmapRect.height() - playOverlaySize.height()) / 2)
+ + currentPixmapRect.topLeft();
+ painter->drawPixmap(playOverlayPos, playOverlay);
}
}
diff --git a/src/plugins/qtsupport/images/icons/playoverlay.png b/src/plugins/qtsupport/images/icons/playoverlay.png
new file mode 100644
index 00000000000..8a7b8b5db44
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/playoverlay.png
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/playoverlay@2x.png b/src/plugins/qtsupport/images/icons/playoverlay@2x.png
new file mode 100644
index 00000000000..627598f52f8
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/playoverlay@2x.png
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/qteventicon.png b/src/plugins/qtsupport/images/icons/qteventicon.png
deleted file mode 100644
index e6beb718ba8..00000000000
--- a/src/plugins/qtsupport/images/icons/qteventicon.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/qteventicon@2x.png b/src/plugins/qtsupport/images/icons/qteventicon@2x.png
deleted file mode 100644
index 2e6590d1e3a..00000000000
--- a/src/plugins/qtsupport/images/icons/qteventicon@2x.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/videotutorialicon.png b/src/plugins/qtsupport/images/icons/videotutorialicon.png
deleted file mode 100644
index 17f22d3c2e1..00000000000
--- a/src/plugins/qtsupport/images/icons/videotutorialicon.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/videotutorialicon@2x.png b/src/plugins/qtsupport/images/icons/videotutorialicon@2x.png
deleted file mode 100644
index c015be74f84..00000000000
--- a/src/plugins/qtsupport/images/icons/videotutorialicon@2x.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtube-xhiVA0P4yk.webp b/src/plugins/qtsupport/images/icons/youtube-xhiVA0P4yk.webp
new file mode 100644
index 00000000000..cd9bcf48a97
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtube-xhiVA0P4yk.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtube1tSpq5OLkYI.webp b/src/plugins/qtsupport/images/icons/youtube1tSpq5OLkYI.webp
new file mode 100644
index 00000000000..8d9aa54d4fa
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtube1tSpq5OLkYI.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtube1w0ak9RNNWY.webp b/src/plugins/qtsupport/images/icons/youtube1w0ak9RNNWY.webp
new file mode 100644
index 00000000000..3eadb302d12
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtube1w0ak9RNNWY.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtube2RvhhEAZQxM.webp b/src/plugins/qtsupport/images/icons/youtube2RvhhEAZQxM.webp
new file mode 100644
index 00000000000..3f595e8d335
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtube2RvhhEAZQxM.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtube3o2Wo4YzlII.webp b/src/plugins/qtsupport/images/icons/youtube3o2Wo4YzlII.webp
new file mode 100644
index 00000000000..80b9c46e242
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtube3o2Wo4YzlII.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtube9BcAYDlpuT8.webp b/src/plugins/qtsupport/images/icons/youtube9BcAYDlpuT8.webp
new file mode 100644
index 00000000000..f0ec6e5bb46
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtube9BcAYDlpuT8.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtube9xqhq9nDiOg.webp b/src/plugins/qtsupport/images/icons/youtube9xqhq9nDiOg.webp
new file mode 100644
index 00000000000..37556bbfbda
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtube9xqhq9nDiOg.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeB0X5FOev9Lw.webp b/src/plugins/qtsupport/images/icons/youtubeB0X5FOev9Lw.webp
new file mode 100644
index 00000000000..7a4415f1c91
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeB0X5FOev9Lw.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeBkgjJfxYN20.webp b/src/plugins/qtsupport/images/icons/youtubeBkgjJfxYN20.webp
new file mode 100644
index 00000000000..f1d5598844a
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeBkgjJfxYN20.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeDP0lMoLVneY.webp b/src/plugins/qtsupport/images/icons/youtubeDP0lMoLVneY.webp
new file mode 100644
index 00000000000..c1805e4734e
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeDP0lMoLVneY.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeDRFz0Tll4G8.webp b/src/plugins/qtsupport/images/icons/youtubeDRFz0Tll4G8.webp
new file mode 100644
index 00000000000..382c89979aa
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeDRFz0Tll4G8.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeECA8_oLT0ZE.webp b/src/plugins/qtsupport/images/icons/youtubeECA8_oLT0ZE.webp
new file mode 100644
index 00000000000..a3e659a12b5
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeECA8_oLT0ZE.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeG0AbgVHGdXI.webp b/src/plugins/qtsupport/images/icons/youtubeG0AbgVHGdXI.webp
new file mode 100644
index 00000000000..98618835566
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeG0AbgVHGdXI.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeKo3DuCgFamo.webp b/src/plugins/qtsupport/images/icons/youtubeKo3DuCgFamo.webp
new file mode 100644
index 00000000000..293cd973e8a
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeKo3DuCgFamo.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubePzV2MYRAUYQ.webp b/src/plugins/qtsupport/images/icons/youtubePzV2MYRAUYQ.webp
new file mode 100644
index 00000000000..b46ee947afd
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubePzV2MYRAUYQ.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeR6zWLfHIYJw.webp b/src/plugins/qtsupport/images/icons/youtubeR6zWLfHIYJw.webp
new file mode 100644
index 00000000000..ed06e95b649
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeR6zWLfHIYJw.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeT_13aX5NTPk.webp b/src/plugins/qtsupport/images/icons/youtubeT_13aX5NTPk.webp
new file mode 100644
index 00000000000..e8dd66eede7
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeT_13aX5NTPk.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeTiJiF0MOOFc.webp b/src/plugins/qtsupport/images/icons/youtubeTiJiF0MOOFc.webp
new file mode 100644
index 00000000000..1117656c146
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeTiJiF0MOOFc.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeW3WC-VpKdGQ.webp b/src/plugins/qtsupport/images/icons/youtubeW3WC-VpKdGQ.webp
new file mode 100644
index 00000000000..cc2f6429945
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeW3WC-VpKdGQ.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeWIRRoPxIerc.webp b/src/plugins/qtsupport/images/icons/youtubeWIRRoPxIerc.webp
new file mode 100644
index 00000000000..701c20f67b4
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeWIRRoPxIerc.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeX0kEkB0ewyw.webp b/src/plugins/qtsupport/images/icons/youtubeX0kEkB0ewyw.webp
new file mode 100644
index 00000000000..655de9e2081
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeX0kEkB0ewyw.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeY-MM-9FigTc.webp b/src/plugins/qtsupport/images/icons/youtubeY-MM-9FigTc.webp
new file mode 100644
index 00000000000..d6117927c1f
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeY-MM-9FigTc.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeYJfFwDBOvqk.webp b/src/plugins/qtsupport/images/icons/youtubeYJfFwDBOvqk.webp
new file mode 100644
index 00000000000..4c387525b07
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeYJfFwDBOvqk.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeau3brB7lNms.webp b/src/plugins/qtsupport/images/icons/youtubeau3brB7lNms.webp
new file mode 100644
index 00000000000..b810f0ef5f2
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeau3brB7lNms.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubehrKz63Q_Rf0.webp b/src/plugins/qtsupport/images/icons/youtubehrKz63Q_Rf0.webp
new file mode 100644
index 00000000000..1736505fad3
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubehrKz63Q_Rf0.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubejbx3Oq1Q4gY.webp b/src/plugins/qtsupport/images/icons/youtubejbx3Oq1Q4gY.webp
new file mode 100644
index 00000000000..893553ffb7b
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubejbx3Oq1Q4gY.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubemAhwHsGdJuI.webp b/src/plugins/qtsupport/images/icons/youtubemAhwHsGdJuI.webp
new file mode 100644
index 00000000000..7ac3f12fd3f
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubemAhwHsGdJuI.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubemn-JmXIMCqk.webp b/src/plugins/qtsupport/images/icons/youtubemn-JmXIMCqk.webp
new file mode 100644
index 00000000000..42d41e63347
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubemn-JmXIMCqk.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubenmvurCcsWos.webp b/src/plugins/qtsupport/images/icons/youtubenmvurCcsWos.webp
new file mode 100644
index 00000000000..ed46fb8fe17
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubenmvurCcsWos.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubepN0pRBUqrrc.webp b/src/plugins/qtsupport/images/icons/youtubepN0pRBUqrrc.webp
new file mode 100644
index 00000000000..ec20d7bf6d4
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubepN0pRBUqrrc.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeqclquZ99ZVQ.webp b/src/plugins/qtsupport/images/icons/youtubeqclquZ99ZVQ.webp
new file mode 100644
index 00000000000..e7605eafccf
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeqclquZ99ZVQ.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubesRihJdZFuCg.webp b/src/plugins/qtsupport/images/icons/youtubesRihJdZFuCg.webp
new file mode 100644
index 00000000000..3ffe30240e1
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubesRihJdZFuCg.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubetnZo9umrPtg.webp b/src/plugins/qtsupport/images/icons/youtubetnZo9umrPtg.webp
new file mode 100644
index 00000000000..feebe2c0d66
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubetnZo9umrPtg.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubeuuhmSZxK1mk.webp b/src/plugins/qtsupport/images/icons/youtubeuuhmSZxK1mk.webp
new file mode 100644
index 00000000000..086bfeee8c2
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubeuuhmSZxK1mk.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubev4glCQt2jE0.webp b/src/plugins/qtsupport/images/icons/youtubev4glCQt2jE0.webp
new file mode 100644
index 00000000000..d67f7a64b01
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubev4glCQt2jE0.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubev_ynSET9FHU.webp b/src/plugins/qtsupport/images/icons/youtubev_ynSET9FHU.webp
new file mode 100644
index 00000000000..7c412959e26
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubev_ynSET9FHU.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubexNIz78IPBu0.webp b/src/plugins/qtsupport/images/icons/youtubexNIz78IPBu0.webp
new file mode 100644
index 00000000000..a125d6cb633
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubexNIz78IPBu0.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images/icons/youtubezAqSiIGdj8M.webp b/src/plugins/qtsupport/images/icons/youtubezAqSiIGdj8M.webp
new file mode 100644
index 00000000000..a08e25daca9
--- /dev/null
+++ b/src/plugins/qtsupport/images/icons/youtubezAqSiIGdj8M.webp
Binary files differ
diff --git a/src/plugins/qtsupport/images_areaofinterest.xml b/src/plugins/qtsupport/images_areaofinterest.xml
deleted file mode 100644
index 6013decc382..00000000000
--- a/src/plugins/qtsupport/images_areaofinterest.xml
+++ /dev/null
@@ -1,380 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<areas>
- <area image="2dpainting-example.png" x="270" y="90" width="118" height="92"/>
- <area image="activeqt-webbrowser-example.png" x="192" y="26" width="146" height="88"/>
- <area image="addressbook-example.png" x="4" y="50" width="138" height="111"/>
- <area image="addressbook-tutorial-part1-screenshot.png" x="9" y="25" width="112" height="93"/>
- <area image="affine-demo.png" x="412" y="34" width="156" height="115"/>
- <area image="analogclock-example.png" x="82" y="98" width="125" height="89"/>
- <area image="analogclock-window-example.png" x="0" y="0" width="100" height="100"/>
- <area image="animatedtiles-example.png" x="191" y="197" width="128" height="121"/>
- <area image="anomaly-demo.png" x="217" y="530" width="143" height="110"/>
- <area image="appchooser-example.png" x="189" y="214" width="119" height="117"/>
- <area image="application.png" x="4" y="9" width="145" height="117"/>
- <area image="arthurplugin-demo.png" x="136" y="168" width="132" height="110"/>
- <area image="audiodevices-example.png" x="36" y="119" width="173" height="101"/>
- <area image="audioinput-example.png" x="0" y="0" width="120" height="120"/>
- <area image="audiooutput-example.png" x="16" y="39" width="152" height="56"/>
- <area image="basicdrawing-example.png" x="155" y="190" width="160" height="133"/>
- <area image="basicgraphicslayouts-example.png" x="17" y="35" width="135" height="143"/>
- <area image="basiclayouts-example.png" x="8" y="44" width="173" height="97"/>
- <area image="basicsortfiltermodel-example.png" x="9" y="25" width="125" height="93"/>
- <area image="bearercloud-example.png" x="215" y="214" width="90" height="69"/>
- <area image="bearermonitor-example.png" x="273" y="105" width="122" height="85"/>
- <area image="behavior-example.png" x="0" y="0" width="64" height="64"/>
- <area image="blockingfortuneclient-example.png" x="0" y="0" width="100" height="100"/>
- <area image="blockingmaster-example.png" x="0" y="0" width="100" height="100"/>
- <area image="blockingslave-example.png" x="0" y="0" width="100" height="100"/>
- <area image="blur_example.png" x="103" y="45" width="55" height="65"/>
- <area image="blurpickereffect-example.png" x="49" y="220" width="67" height="61"/>
- <area image="books-demo.png" x="10" y="32" width="163" height="97"/>
- <area image="borderlayout-example.png" x="1" y="26" width="151" height="128"/>
- <area image="boxes-demo.png" x="248" y="109" width="93" height="105"/>
- <area image="broadcastreceiver-example.png" x="73" y="36" width="145" height="57"/>
- <area image="broadcastsender-example.png" x="99" y="34" width="130" height="64"/>
- <area image="browser-demo.png" x="84" y="31" width="138" height="108"/>
- <area image="btchat-example.png" x="283" y="194" width="123" height="100"/>
- <area image="btfiletransfer-example.png" x="0" y="0" width="100" height="100"/>
- <area image="btscanner-example.png" x="415" y="37" width="125" height="71"/>
- <area image="bttennis-example.png" x="306" y="54" width="124" height="94"/>
- <area image="cachedtable-example.png" x="12" y="33" width="140" height="107"/>
- <area image="calculator-example.png" x="205" y="27" width="126" height="122"/>
- <area image="calculatorbuilder-example.png" x="20" y="41" width="131" height="82"/>
- <area image="calculatorform-example.png" x="14" y="33" width="155" height="72"/>
- <area image="calendar-example.png" x="12" y="34" width="162" height="124"/>
- <area image="calendarwidgetexample.png" x="105" y="66" width="142" height="110"/>
- <area image="camera-example.png" x="473" y="48" width="121" height="118"/>
- <area image="capabilitiesexample.png" x="18" y="283" width="172" height="100"/>
- <area image="cenumerator-example.png" x="1" y="19" width="109" height="79"/>
- <area image="charactermap-example.png" x="13" y="56" width="171" height="108"/>
- <area image="chart-example.png" x="419" y="59" width="150" height="117"/>
- <area image="classwizard.png" x="24" y="111" width="152" height="126"/>
- <area image="checkboxexample.png" x="0" y="0" width="98" height="34"/>
- <area image="chip-demo.png" x="169" y="14" width="127" height="89"/>
- <area image="codecs-example.png" x="163" y="98" width="134" height="94"/>
- <area image="codeeditor-example.png" x="14" y="48" width="143" height="107"/>
- <area image="collidingmice-example.png" x="45" y="86" width="171" height="133"/>
- <area image="coloreditorfactoryimage.png" x="50" y="35" width="155" height="109"/>
- <area image="combowidgetmapper-example.png" x="38" y="168" width="131" height="89"/>
- <area image="completer-example.png" x="11" y="141" width="159" height="107"/>
- <area image="composition-demo.png" x="159" y="50" width="103" height="95"/>
- <area image="concentriccircles-example.png" x="306" y="321" width="50" height="43"/>
- <area image="configdialog-example.png" x="94" y="27" width="122" height="122"/>
- <area image="containerextension-example.png" x="30" y="21" width="110" height="97"/>
- <area image="context2d-example.png" x="0" y="0" width="100" height="100"/>
- <area image="creaderasync-example.png" x="658" y="2" width="155" height="69"/>
- <area image="creadersync-example.png" x="0" y="0" width="100" height="54"/>
- <area image="custom-geometry-example.png" x="99" y="99" width="147" height="89"/>
- <area image="customcompleter-example.png" x="3" y="69" width="151" height="112"/>
- <area image="customsortfiltermodel-example.png" x="10" y="27" width="152" height="117"/>
- <area image="customtypesending-example.png" x="99" y="99" width="152" height="112"/>
- <area image="customwidgetplugin-example.png" x="16" y="18" width="129" height="124"/>
- <area image="cwriterasync-example.png" x="0" y="0" width="100" height="58"/>
- <area image="cwritersync-example.png" x="0" y="0" width="100" height="47"/>
- <area image="dbus-chat-example.png" x="131" y="138" width="138" height="130"/>
- <area image="declarative-anchors_example.png" x="0" y="0" width="100" height="100"/>
- <area image="declarative-radio-example.png" x="8" y="215" width="156" height="85"/>
- <area image="declarative-textballoons_example.png" x="31" y="20" width="145" height="96"/>
- <area image="defaultprototypes-example.png" x="2" y="15" width="104" height="111"/>
- <area image="diagramscene.png" x="1" y="47" width="164" height="138"/>
- <area image="deform-demo.png" x="228" y="252" width="147" height="116"/>
- <area image="delayedecoding-example.png" x="0" y="0" width="100" height="100"/>
- <area image="dialogbuttonboxexample.png" x="432" y="48" width="153" height="112"/>
- <area image="digitalclock-example.png" x="57" y="37" width="129" height="96"/>
- <area image="dirview-example.png" x="21" y="96" width="122" height="90"/>
- <area image="dockwidgets-example.png" x="498" y="262" width="180" height="109"/>
- <area image="dombookmarks-example.png" x="2" y="53" width="131" height="129"/>
- <area image="draganddroppuzzle-example.png" x="183" y="230" width="145" height="127"/>
- <area image="dragdroprobot-example.png" x="119" y="101" width="115" height="129"/>
- <area image="draggableicons-example.png" x="181" y="67" width="111" height="124"/>
- <area image="draggabletext-example.png" x="48" y="78" width="96" height="90"/>
- <area image="drilldown-example.png" x="119" y="34" width="162" height="132"/>
- <area image="dropsite-example.png" x="32" y="319" width="181" height="91"/>
- <area image="dynamiclayouts-example.png" x="223" y="2" width="178" height="106"/>
- <area image="easing-example.png" x="230" y="27" width="116" height="110"/>
- <area image="echopluginexample.png" x="65" y="27" width="125" height="96"/>
- <area image="elasticnodes-example.png" x="72" y="71" width="120" height="107"/>
- <area image="elidedlabel-example.png" x="47" y="8" width="174" height="110"/>
- <area image="embedded-simpledecoration-example.png" x="0" y="0" width="143" height="91"/>
- <area image="embeddeddesktopservices-demo.png" x="0" y="0" width="100" height="100"/>
- <area image="embeddeddialogs-demo.png" x="250" y="0" width="161" height="104"/>
- <area image="embeddedsvgviewer-demo.png" x="99" y="25" width="112" height="121"/>
- <area image="enumerator-example.png" x="15" y="4" width="119" height="106"/>
- <area image="extension-example.png" x="15" y="31" width="198" height="84"/>
- <area image="factorial-example.png" x="51" y="38" width="145" height="78"/>
- <area image="fademessageeffect-example.png" x="68" y="153" width="129" height="114"/>
- <area image="fancybrowser-example.png" x="385" y="201" width="170" height="94"/>
- <area image="fetchmore-example.png" x="11" y="35" width="129" height="99"/>
- <area image="filetree_1-example.png" x="11" y="33" width="164" height="112"/>
- <area image="filetree_2-example.png" x="15" y="67" width="150" height="105"/>
- <area image="findfiles-example.png" x="61" y="5" width="158" height="138"/>
- <area image="flickable-demo.png" x="2" y="71" width="176" height="102"/>
- <area image="flickrview-example.png" x="144" y="297" width="140" height="98"/>
- <area image="flightinfo-demo.png" x="153" y="107" width="121" height="98"/>
- <area image="flowlayout-example.png" x="14" y="34" width="165" height="92"/>
- <area image="fluidlauncher-demo.png" x="75" y="166" width="135" height="113"/>
- <area image="fontsampler-example.png" x="4" y="42" width="148" height="104"/>
- <area image="formextractor-example.png" x="56" y="137" width="144" height="108"/>
- <area image="fortuneclient-example.png" x="7" y="31" width="172" height="102"/>
- <area image="fortuneserver-example.png" x="72" y="29" width="121" height="86"/>
- <area image="framebufferobject-example.png" x="147" y="114" width="178" height="131"/>
- <area image="framebufferobject2-example.png" x="320" y="114" width="136" height="105"/>
- <area image="framecapture-example.png" x="0" y="0" width="100" height="100"/>
- <area image="fridgemagnets-example.png" x="211" y="51" width="114" height="111"/>
- <area image="frozencolumn-example.png" x="6" y="22" width="127" height="97"/>
- <area image="googlechat-example.png" x="384" y="416" width="177" height="120"/>
- <area image="googlesuggest-example.png" x="18" y="18" width="129" height="109"/>
- <area image="grabber-example.png" x="180" y="105" width="158" height="142"/>
- <area image="gradients-demo.png" x="80" y="141" width="119" height="120"/>
- <area image="graphicsanchorlayout-example.png" x="156" y="182" width="185" height="124"/>
- <area image="graphicsflowlayout-example.png" x="113" y="115" width="170" height="76"/>
- <area image="graphicssimpleanchorlayout-example.png" x="90" y="104" width="189" height="116"/>
- <area image="gridLayout_example.png" x="0" y="0" width="100" height="100"/>
- <area image="gridviewexample.png" x="0" y="0" width="64" height="64"/>
- <area image="groupbox-example.png" x="11" y="30" width="163" height="101"/>
- <area image="hellogl-es-example.png" x="56" y="166" width="164" height="132"/>
- <area image="hellogl-example.png" x="105" y="147" width="127" height="106"/>
- <area image="horizontalpositioner_example.png" x="0" y="0" width="100" height="74"/>
- <area image="http-example.png" x="17" y="33" width="179" height="87"/>
- <area image="i18n-example.png" x="15" y="103" width="130" height="108"/>
- <area image="icons-example.png" x="243" y="87" width="160" height="114"/>
- <area image="imagecomposition-example.png" x="618" y="72" width="137" height="127"/>
- <area image="imagescaling_example.png" x="164" y="42" width="141" height="128"/>
- <area image="imageviewer-example.png" x="10" y="24" width="154" height="145"/>
- <area image="inputpanel-example.png" x="59" y="131" width="163" height="140"/>
- <area image="interview-demo.png" x="268" y="29" width="122" height="81"/>
- <area image="itemviewspuzzle-example.png" x="410" y="141" width="129" height="99"/>
- <area image="licensewizard-example.png" x="147" y="40" width="176" height="117"/>
- <area image="lightingeffect-example.png" x="95" y="180" width="104" height="65"/>
- <area image="lightmaps-demo.png" x="126" y="109" width="142" height="106"/>
- <area image="lineedits-example.png" x="236" y="26" width="125" height="118"/>
- <area image="linguist-arrowpad_en.png" x="12" y="52" width="149" height="98"/>
- <area image="linguist-hellotr_en.png" x="28" y="2" width="118" height="61"/>
- <area image="linguist-trollprint_10_en.png" x="0" y="0" width="120" height="120"/>
- <area image="localfortuneclient-example.png" x="8" y="27" width="161" height="86"/>
- <area image="localfortuneserver-example.png" x="13" y="29" width="159" height="88"/>
- <area image="loopback-example.png" x="11" y="35" width="122" height="116"/>
- <area image="maemovibration-example.png" x="85" y="200" width="183" height="106"/>
- <area image="mainwindow-demo.png" x="246" y="33" width="159" height="97"/>
- <area image="mainwindow-docks-example.png" x="109" y="13" width="141" height="123"/>
- <area image="mandelbrot-example.png" x="67" y="77" width="161" height="123"/>
- <area image="masterdetail-example.png" x="6" y="38" width="102" height="79"/>
- <area image="mdi-example.png" x="134" y="46" width="147" height="127"/>
- <area image="menus-example.png" x="27" y="24" width="162" height="112"/>
- <area image="mouseareaexample.png" x="0" y="0" width="64" height="64"/>
- <area image="moveblocks-example.png" x="35" y="59" width="86" height="89"/>
- <area image="movie-example.png" x="14" y="306" width="168" height="126"/>
- <area image="multicastreceiver-example.png" x="14" y="33" width="173" height="74"/>
- <area image="multicastsender-example.png" x="20" y="39" width="126" height="51"/>
- <area image="multipleinheritance-example.png" x="7" y="38" width="177" height="66"/>
- <area image="network-chat-example.png" x="58" y="68" width="166" height="115"/>
- <area image="openglwindow-example.png" x="261" y="102" width="116" height="122"/>
- <area image="orderform-example.png" x="247" y="212" width="157" height="106"/>
- <area image="overpainting-example.png" x="119" y="69" width="172" height="139"/>
- <area image="padnavigator-example.png" x="8" y="22" width="214" height="197"/>
- <area image="painterpaths-example.png" x="9" y="286" width="172" height="113"/>
- <area image="pathexample.png" x="0" y="0" width="100" height="100"/>
- <area image="pathstroke-demo.png" x="382" y="207" width="111" height="87"/>
- <area image="pbuffers-example.png" x="100" y="262" width="145" height="141"/>
- <area image="pbuffers2-example.png" x="196" y="95" width="156" height="131"/>
- <area image="pingpong-example.png" x="143" y="119" width="192" height="86"/>
- <area image="pixelator-example.png" x="242" y="127" width="119" height="110"/>
- <area image="plugandpaint.png" x="42" y="83" width="183" height="97"/>
- <area image="portedasteroids-example.png" x="487" y="8" width="161" height="109"/>
- <area image="portedcanvas-example.png" x="393" y="178" width="151" height="133"/>
- <area image="pixmapfilter-example.png" x="354" y="63" width="101" height="101"/>
- <area image="positioner-example.png" x="0" y="0" width="100" height="100"/>
- <area image="previewer-example.png" x="108" y="62" width="186" height="119"/>
- <area image="qcameraexample.png" x="314" y="91" width="178" height="97"/>
- <area image="qmediaplayer-demo.png" x="11" y="26" width="203" height="126"/>
- <area image="qml-abstractitemmodel-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-affectors-example.png" x="78" y="225" width="152" height="109"/>
- <area image="qml-animations-example.png" x="86" y="170" width="133" height="85"/>
- <area image="qml-behaviors-example.png" x="166" y="86" width="164" height="128"/>
- <area image="qml-borderimage-example.png" x="6" y="7" width="171" height="128"/>
- <area image="qml-borderimage-shadows-example.png" x="213" y="12" width="114" height="108"/>
- <area image="qml-calculator-example.png" x="218" y="5" width="142" height="125"/>
- <area image="qml-canvas-example.png" x="0" y="282" width="141" height="122"/>
- <area image="qml-clocks-example.png" x="244" y="90" width="157" height="133"/>
- <area image="qml-coloranim-example.png" x="99" y="21" width="141" height="102"/>
- <area image="qml-corkboards-example.png" x="37" y="22" width="133" height="124"/>
- <area image="qml-customparticle-example.png" x="69" y="119" width="131" height="124"/>
- <area image="qml-dialcontrol-example.png" x="84" y="70" width="123" height="104"/>
- <area image="qml-dnd2-example.png" x="63" y="59" width="145" height="81"/>
- <area image="qml-draganddrop-example.png" x="5" y="29" width="160" height="136"/>
- <area image="qml-dynamicscene-example.png" x="31" y="191" width="117" height="122"/>
- <area image="qml-easing-example.png" x="156" y="79" width="175" height="126"/>
- <area image="qml-emitters-example.png" x="92" y="150" width="141" height="140"/>
- <area image="qml-flickr-demo.png" x="1" y="1" width="167" height="125"/>
- <area image="qml-flipable-example.png" x="253" y="121" width="146" height="85"/>
- <area image="qml-focus-example.png" x="195" y="109" width="205" height="108"/>
- <area image="qml-fonts-availableFonts-example.png" x="99" y="49" width="147" height="87"/>
- <area image="qml-fonts-banner-example.png" x="105" y="34" width="164" height="102"/>
- <area image="qml-fonts-fonts-example.png" x="1" y="39" width="148" height="104"/>
- <area image="qml-fonts-hello-example.png" x="61" y="95" width="160" height="47"/>
- <area image="qml-gridview-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-guitartuner-example.png" x="180" y="120" width="169" height="144"/>
- <area image="qml-i18n-example.png" x="0" y="0" width="100" height="38"/>
- <area image="qml-image-example.png" x="16" y="149" width="153" height="114"/>
- <area image="qml-imageelements-example.png" x="86" y="148" width="217" height="145"/>
- <area image="qml-imageparticle-example.png" x="113" y="147" width="147" height="115"/>
- <area image="qml-imageprovider-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-keyinteraction-example.png" x="79" y="27" width="188" height="96"/>
- <area image="qml-layoutitem-example.png" x="77" y="3" width="103" height="118"/>
- <area image="qml-listview-dynamiclist-example.png" x="11" y="56" width="99" height="84"/>
- <area image="qml-listview-expandingdelegates-example.png" x="1" y="31" width="159" height="151"/>
- <area image="qml-listview-highlight-example.png" x="4" y="121" width="144" height="88"/>
- <area image="qml-listview-highlightranges-example.png" x="99" y="99" width="126" height="126"/>
- <area image="qml-listview-sections-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-localstorage-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-minehunt-demo.png" x="155" y="112" width="168" height="124"/>
- <area image="qml-modelviews-example.png" x="297" y="182" width="178" height="110"/>
- <area image="qml-mousearea-example.png" x="25" y="65" width="126" height="56"/>
- <area image="qml-objectlistmodel-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-package-example.png" x="171" y="23" width="146" height="101"/>
- <area image="qml-parallax-example.png" x="59" y="220" width="148" height="139"/>
- <area image="qml-pathview-example.png" x="121" y="76" width="182" height="127"/>
- <area image="qml-photoviewer-demo.png" x="103" y="17" width="202" height="153"/>
- <area image="qml-plugins-example.png" x="45" y="13" width="150" height="113"/>
- <area image="qml-positioners-example.png" x="92" y="99" width="125" height="146"/>
- <area image="qml-positioners-layoutdirection-example.png" x="99" y="45" width="138" height="125"/>
- <area image="qml-poster-example.png" x="471" y="147" width="117" height="58"/>
- <area image="qml-progressbar-example.png" x="408" y="238" width="188" height="127"/>
- <area image="qml-propertyanim-example.png" x="72" y="147" width="99" height="117"/>
- <area image="qml-qgraphicsgridlayout-example.png" x="106" y="1" width="87" height="152"/>
- <area image="qml-qgraphicslinearlayout-example.png" x="70" y="0" width="72" height="76"/>
- <area image="qml-qtbubblelevel-demo.png" x="158" y="1" width="177" height="48"/>
- <area image="qml-qwidgets-example.png" x="23" y="22" width="161" height="111"/>
- <area image="qml-righttoleft-example.png" x="131" y="247" width="184" height="104"/>
- <area image="qml-righttoleft-layoutdirection-example.png" x="82" y="18" width="115" height="124"/>
- <area image="qml-righttoleft-layoutmirroring-example.png" x="2" y="182" width="172" height="123"/>
- <area image="qml-rssnews-demo.png" x="5" y="57" width="168" height="105"/>
- <area image="qml-samegame-demo.png" x="211" y="294" width="157" height="106"/>
- <area image="qml-scrollbar-example.png" x="300" y="247" width="191" height="103"/>
- <area image="qml-searchbox-example.png" x="119" y="61" width="153" height="123"/>
- <area image="qml-shadereffects-example.png" x="217" y="30" width="198" height="138"/>
- <area image="qml-slideswitch-example.png" x="119" y="86" width="161" height="71"/>
- <area image="qml-snake-demo.png" x="271" y="150" width="189" height="79"/>
- <area image="qml-spinner-example.png" x="59" y="95" width="121" height="109"/>
- <area image="qml-states-example.png" x="186" y="73" width="121" height="93"/>
- <area image="qml-stringlistmodel-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-system-example.png" x="99" y="99" width="162" height="83"/>
- <area image="qml-tabwidget-example.png" x="65" y="5" width="169" height="61"/>
- <area image="qml-text-example.png" x="185" y="312" width="228" height="135"/>
- <area image="qml-textselection-example.png" x="10" y="12" width="205" height="108"/>
- <area image="qml-threading-example.png" x="82" y="44" width="160" height="79"/>
- <area image="qml-tic-tac-toe-example.png" x="47" y="72" width="211" height="166"/>
- <area image="qml-touchinteraction-example.png" x="162" y="121" width="157" height="137"/>
- <area image="qml-transitions-example.png" x="156" y="66" width="159" height="118"/>
- <area image="qml-tvtennis-example.png" x="225" y="249" width="134" height="111"/>
- <area image="qml-twitter-demo.png" x="5" y="10" width="162" height="112"/>
- <area image="qml-visualitemmodel-example.png" x="71" y="262" width="100" height="58"/>
- <area image="qml-webbrowser-demo.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-webview-alert-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-webview-autosize-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-webview-googlemaps-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-webview-inlinehtml-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-webview-newwindows-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-window-example.png" x="0" y="0" width="100" height="100"/>
- <area image="qml-xmlhttprequest-example.png" x="8" y="29" width="120" height="82"/>
- <area image="qml-xmllistmodel-example.png" x="0" y="0" width="100" height="76"/>
- <area image="qobjectxmlmodel-example.png" x="9" y="41" width="139" height="119"/>
- <area image="qpainter-compositiondemo.png" x="64" y="24" width="69" height="62"/>
- <area image="qpainterpath-demo.png" x="71" y="99" width="66" height="96"/>
- <area image="qpainterpath-example.png" x="99" y="99" width="104" height="93"/>
- <area image="qpen-demo.png" x="34" y="31" width="183" height="125"/>
- <area image="qtdemo-example.png" x="30" y="34" width="179" height="114"/>
- <area image="qtdemo.png" x="494" y="151" width="173" height="129"/>
- <area image="qtscript-calculator-example.png" x="195" y="22" width="127" height="111"/>
- <area image="querymodel-example.png" x="462" y="48" width="129" height="113"/>
- <area image="queuedcustomtype-example.png" x="270" y="28" width="140" height="120"/>
- <area image="radio-example.png" x="3" y="59" width="138" height="107"/>
- <area image="raycasting-demo.png" x="157" y="130" width="143" height="122"/>
- <area image="recentfiles-example.png" x="0" y="0" width="173" height="138"/>
- <area image="recipes-example.png" x="3" y="139" width="154" height="103"/>
- <area image="reflection_example.png" x="5" y="66" width="132" height="93"/>
- <area image="regexp-example.png" x="12" y="34" width="166" height="114"/>
- <area image="relationaltablemodel-example.png" x="3" y="28" width="172" height="85"/>
- <area image="remotecontrolledcar-car-example.png" x="139" y="77" width="117" height="136"/>
- <area image="remotecontrolledcar-controller-example.png" x="80" y="21" width="121" height="96"/>
- <area image="rogue-example.png" x="7" y="30" width="115" height="100"/>
- <area image="rsslistingexample.png" x="13" y="30" width="157" height="110"/>
- <area image="samplebuffers-example.png" x="88" y="279" width="174" height="116"/>
- <area image="saxbookmarks-example.png" x="4" y="53" width="143" height="114"/>
- <area image="schema-example.png" x="55" y="104" width="169" height="98"/>
- <area image="screenshot-example.png" x="7" y="169" width="176" height="135"/>
- <area image="scribble-example.png" x="152" y="126" width="206" height="161"/>
- <area image="sdi-example.png" x="3" y="9" width="150" height="132"/>
- <area image="securesocketclient.png" x="10" y="25" width="148" height="101"/>
- <area image="settingseditor-example.png" x="13" y="152" width="165" height="121"/>
- <area image="shaderexample.png" x="54" y="117" width="145" height="67"/>
- <area image="shadow_example.png" x="2" y="104" width="112" height="124"/>
- <area image="shapedclock-example.png" x="107" y="36" width="131" height="115"/>
- <area image="sharedmemory-example_1.png" x="149" y="18" width="164" height="79"/>
- <area image="simpleanchorlayout-example.png" x="87" y="28" width="167" height="122"/>
- <area image="simpledommodel-example.png" x="7" y="84" width="134" height="111"/>
- <area image="simpletextviewer-example.png" x="112" y="23" width="141" height="110"/>
- <area image="simpletreemodel-example.png" x="3" y="33" width="172" height="118"/>
- <area image="simplewidgetmapper-example.png" x="11" y="36" width="160" height="91"/>
- <area image="sliders-example.png" x="461" y="42" width="182" height="127"/>
- <area image="sortingmodel-example.png" x="342" y="136" width="145" height="118"/>
- <area image="spectrum-demo.png" x="77" y="79" width="211" height="123"/>
- <area image="spinboxdelegate-example.png" x="82" y="86" width="152" height="96"/>
- <area image="spinboxes-example.png" x="263" y="65" width="169" height="113"/>
- <area image="spreadsheet-demo.png" x="7" y="50" width="162" height="115"/>
- <area image="sqlbrowser-demo.png" x="19" y="72" width="143" height="93"/>
- <area image="standarddialogs-example.png" x="187" y="33" width="178" height="149"/>
- <area image="stardelegate.png" x="220" y="21" width="180" height="95"/>
- <area image="states-example.png" x="236" y="258" width="176" height="77"/>
- <area image="stickman-example.png" x="1" y="1" width="467" height="510"/>
- <area image="styles-enabledwood.png" x="12" y="24" width="185" height="95"/>
- <area image="stylesheet-coffee-plastique.png" x="40" y="64" width="180" height="115"/>
- <area image="styledemo-demo.png" x="220" y="148" width="163" height="111"/>
- <area image="styledemo.png" x="104" y="140" width="112" height="94"/>
- <area image="stylepluginexample.png" x="16" y="26" width="140" height="82"/>
- <area image="sub-attaq-demo.png" x="171" y="279" width="157" height="82"/>
- <area image="svggenerator-example.png" x="162" y="64" width="90" height="72"/>
- <area image="svgviewer-example.png" x="193" y="245" width="102" height="91"/>
- <area image="syntaxhighlighter-example.png" x="4" y="67" width="153" height="101"/>
- <area image="systemtray-example.png" x="163" y="36" width="181" height="113"/>
- <area image="t1.png" x="0" y="0" width="108" height="56"/>
- <area image="tabdialog-example.png" x="7" y="30" width="168" height="105"/>
- <area image="tablemodel-example.png" x="342" y="44" width="157" height="116"/>
- <area image="tabletexample.png" x="26" y="70" width="167" height="112"/>
- <area image="tankgame-example.png" x="9" y="25" width="145" height="102"/>
- <area image="taskmenuextension-example.png" x="84" y="63" width="170" height="126"/>
- <area image="terminal-example.png" x="0" y="0" width="100" height="100"/>
- <area image="tetrix-example.png" x="46" y="72" width="112" height="112"/>
- <area image="textedit-demo.png" x="4" y="33" width="134" height="145"/>
- <area image="textfinder-example.png" x="347" y="27" width="137" height="85"/>
- <area image="textobject-example.png" x="86" y="73" width="99" height="80"/>
- <area image="textures-example.png" x="245" y="70" width="154" height="137"/>
- <area image="threadedfortuneserver-example.png" x="100" y="30" width="122" height="85"/>
- <area image="threadvisual-example.png" x="34" y="99" width="116" height="94"/>
- <area image="tooltips-example.png" x="96" y="63" width="128" height="129"/>
- <area image="torrent-example.png" x="5" y="29" width="175" height="126"/>
- <area image="touch-dials-example.png" x="64" y="162" width="138" height="110"/>
- <area image="touch-fingerpaint-example.png" x="99" y="78" width="166" height="135"/>
- <area image="touch-knobs-example.png" x="66" y="9" width="81" height="85"/>
- <area image="touch-pinchzoom-example.png" x="99" y="67" width="113" height="103"/>
- <area image="trafficinfo-example.png" x="45" y="1" width="207" height="62"/>
- <area image="trafficlight-example.png" x="8" y="219" width="112" height="104"/>
- <area image="transformations-example.png" x="484" y="92" width="128" height="125"/>
- <area image="treemodelcompleter-example.png" x="11" y="319" width="181" height="109"/>
- <area image="trivialwizard-example-introduction.png" x="248" y="333" width="170" height="61"/>
- <area image="undodemo.png" x="230" y="190" width="173" height="126"/>
- <area image="undoframeworkexample.png" x="176" y="1" width="136" height="121"/>
- <area image="verticalpositioner_example.png" x="0" y="0" width="50" height="100"/>
- <area image="visual-coordinates-example.png" x="54" y="44" width="117" height="122"/>
- <area image="visual-parent-example.png" x="166" y="49" width="119" height="147"/>
- <area image="weatheranchorlayout-example.png" x="111" y="53" width="161" height="131"/>
- <area image="weatherinfo-demo.png" x="284" y="33" width="191" height="130"/>
- <area image="wheel-example.png" x="60" y="74" width="103" height="102"/>
- <area image="wiggly-example.png" x="10" y="58" width="155" height="113"/>
- <area image="windowflags-example.png" x="9" y="82" width="140" height="119"/>
- <area image="worldtimeclockbuilder-example.png" x="99" y="57" width="154" height="93"/>
- <area image="worldtimeclockplugin-example.png" x="109" y="34" width="141" height="116"/>
- <area image="xmlstreamexample-screenshot.png" x="2" y="54" width="139" height="98"/>
- <area image="xmlhttprequestexample.png" x="0" y="0" width="64" height="64"/>
- <area image="youtubeview-example.png" x="99" y="13" width="184" height="141"/>
-</areas>
diff --git a/src/plugins/qtsupport/qtbuildaspects.cpp b/src/plugins/qtsupport/qtbuildaspects.cpp
index fcd7b213c16..d1cbfbf8300 100644
--- a/src/plugins/qtsupport/qtbuildaspects.cpp
+++ b/src/plugins/qtsupport/qtbuildaspects.cpp
@@ -27,6 +27,7 @@
#include "baseqtversion.h"
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildpropertiessettings.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/kitmanager.h>
@@ -42,7 +43,8 @@ using namespace Utils;
namespace QtSupport {
-QmlDebuggingAspect::QmlDebuggingAspect()
+QmlDebuggingAspect::QmlDebuggingAspect(BuildConfiguration *buildConfig)
+ : m_buildConfig(buildConfig)
{
setSettingsKey("EnableQmlDebugging");
setDisplayName(tr("QML debugging and profiling:"));
@@ -58,7 +60,9 @@ void QmlDebuggingAspect::addToLayout(LayoutBuilder &builder)
builder.addRow({{}, warningLabel});
const auto changeHandler = [this, warningLabel] {
QString warningText;
- const bool supported = m_kit && QtVersion::isQmlDebuggingSupported(m_kit, &warningText);
+ QTC_ASSERT(m_buildConfig, return);
+ Kit *kit = m_buildConfig->kit();
+ const bool supported = kit && QtVersion::isQmlDebuggingSupported(kit, &warningText);
if (!supported) {
setValue(TriState::Default);
} else if (value() == TriState::Enabled) {
@@ -76,7 +80,8 @@ void QmlDebuggingAspect::addToLayout(LayoutBuilder &builder)
changeHandler();
}
-QtQuickCompilerAspect::QtQuickCompilerAspect()
+QtQuickCompilerAspect::QtQuickCompilerAspect(BuildConfiguration *buildConfig)
+ : m_buildConfig(buildConfig)
{
setSettingsKey("QtQuickCompiler");
setDisplayName(tr("Qt Quick Compiler:"));
@@ -92,13 +97,17 @@ void QtQuickCompilerAspect::addToLayout(LayoutBuilder &builder)
builder.addRow({{}, warningLabel});
const auto changeHandler = [this, warningLabel] {
QString warningText;
- const bool supported = m_kit
- && QtVersion::isQtQuickCompilerSupported(m_kit, &warningText);
+ QTC_ASSERT(m_buildConfig, return);
+ Kit *kit = m_buildConfig->kit();
+ const bool supported = kit
+ && QtVersion::isQtQuickCompilerSupported(kit, &warningText);
if (!supported)
setValue(TriState::Default);
- if (value() == TriState::Enabled
- && m_qmlDebuggingAspect && m_qmlDebuggingAspect->value() == TriState::Enabled) {
- warningText = tr("Disables QML debugging. QML profiling will still work.");
+ if (value() == TriState::Enabled) {
+ if (auto qmlDebuggingAspect = m_buildConfig->aspect<QmlDebuggingAspect>()) {
+ if (qmlDebuggingAspect->value() == TriState::Enabled)
+ warningText = tr("Disables QML debugging. QML profiling will still work.");
+ }
}
warningLabel->setText(warningText);
setVisible(supported);
@@ -109,14 +118,9 @@ void QtQuickCompilerAspect::addToLayout(LayoutBuilder &builder)
connect(KitManager::instance(), &KitManager::kitsChanged, warningLabel, changeHandler);
connect(this, &QmlDebuggingAspect::changed, warningLabel, changeHandler);
connect(this, &QtQuickCompilerAspect::changed, warningLabel, changeHandler);
- if (m_qmlDebuggingAspect)
- connect(m_qmlDebuggingAspect, &QmlDebuggingAspect::changed, warningLabel, changeHandler);
+ if (auto qmlDebuggingAspect = m_buildConfig->aspect<QmlDebuggingAspect>())
+ connect(qmlDebuggingAspect, &QmlDebuggingAspect::changed, warningLabel, changeHandler);
changeHandler();
}
-void QtQuickCompilerAspect::acquaintSiblings(const AspectContainer &siblings)
-{
- m_qmlDebuggingAspect = siblings.aspect<QmlDebuggingAspect>();
-}
-
} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qtbuildaspects.h b/src/plugins/qtsupport/qtbuildaspects.h
index 428f9dc811a..8434039d089 100644
--- a/src/plugins/qtsupport/qtbuildaspects.h
+++ b/src/plugins/qtsupport/qtbuildaspects.h
@@ -29,37 +29,34 @@
#include <utils/aspects.h>
-namespace ProjectExplorer { class Kit; }
+namespace ProjectExplorer { class BuildConfiguration; }
namespace QtSupport {
class QTSUPPORT_EXPORT QmlDebuggingAspect : public Utils::TriStateAspect
{
Q_OBJECT
+
public:
- QmlDebuggingAspect();
+ explicit QmlDebuggingAspect(ProjectExplorer::BuildConfiguration *buildConfig);
- void setKit(const ProjectExplorer::Kit *kit) { m_kit = kit; }
void addToLayout(Utils::LayoutBuilder &builder) override;
private:
- const ProjectExplorer::Kit *m_kit = nullptr;
+ const ProjectExplorer::BuildConfiguration *m_buildConfig = nullptr;
};
class QTSUPPORT_EXPORT QtQuickCompilerAspect : public Utils::TriStateAspect
{
Q_OBJECT
-public:
- QtQuickCompilerAspect();
- void setKit(const ProjectExplorer::Kit *kit) { m_kit = kit; }
+public:
+ QtQuickCompilerAspect(ProjectExplorer::BuildConfiguration *buildConfig);
private:
void addToLayout(Utils::LayoutBuilder &builder) override;
- void acquaintSiblings(const Utils::AspectContainer &siblings) override;
- const ProjectExplorer::Kit *m_kit = nullptr;
- const QmlDebuggingAspect *m_qmlDebuggingAspect = nullptr;
+ const ProjectExplorer::BuildConfiguration *m_buildConfig = nullptr;
};
} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qtcreator_tutorials.xml b/src/plugins/qtsupport/qtcreator_tutorials.xml
index 4d898483609..f3a850a5a84 100644
--- a/src/plugins/qtsupport/qtcreator_tutorials.xml
+++ b/src/plugins/qtsupport/qtcreator_tutorials.xml
@@ -26,156 +26,156 @@
<tags>qt quick,controls,tumbler,help</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: How to set up and deploy an application using Qt for Device Creation" isVideo="true" videoUrl="https://youtu.be/1tSpq5OLkYI" videoLength="5:48">
+ <tutorial imageUrl=":qtsupport/images/icons/youtube1tSpq5OLkYI.webp" difficulty="" projectPath="" name="Online: How to set up and deploy an application using Qt for Device Creation" isVideo="true" videoUrl="https://youtu.be/1tSpq5OLkYI" videoLength="5:48">
<description><![CDATA[Using Qt Creator to deploy applications to an embedded device.]]></description>
<tags>qt creator,embedded,device creation,video,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt SCXML and State Machine Tooling in Qt Creator" isVideo="true" videoUrl="https://youtu.be/9xqhq9nDiOg" videoLength="4:53">
+ <tutorial imageUrl=":qtsupport/images/icons/youtube9xqhq9nDiOg.webp" difficulty="" projectPath="" name="Online: Qt SCXML and State Machine Tooling in Qt Creator" isVideo="true" videoUrl="https://youtu.be/9xqhq9nDiOg" videoLength="4:53">
<description><![CDATA[Creating state machines.]]></description>
<tags>qt creator,SCXML,video</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Using C++ Models in QML - To-do List" isVideo="true" videoUrl="https://www.youtube.com/watch?v=9BcAYDlpuT8" videoLength="49:48">
+ <tutorial imageUrl=":qtsupport/images/icons/youtube9BcAYDlpuT8.webp" difficulty="" projectPath="" name="Online: Using C++ Models in QML - To-do List" isVideo="true" videoUrl="https://www.youtube.com/watch?v=9BcAYDlpuT8" videoLength="49:48">
<description><![CDATA[Creating and using a C++ model in QML.]]></description>
<tags>qt creator,qt quick,c++,video</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt Creator - Meet Qt Creator" isVideo="true" videoUrl="https://youtu.be/zAqSiIGdj8M" videoLength="2:06">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubezAqSiIGdj8M.webp" difficulty="" projectPath="" name="Online: Qt Creator - Meet Qt Creator" isVideo="true" videoUrl="https://youtu.be/zAqSiIGdj8M" videoLength="2:06">
<description><![CDATA[Overview of Qt Creator.]]></description>
<tags>qt creator,video</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt Creator - Examples" isVideo="true" videoUrl="https://www.youtube.com/watch?v=R6zWLfHIYJw" videoLength="9:29">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeR6zWLfHIYJw.webp" difficulty="" projectPath="" name="Online: Qt Creator - Examples" isVideo="true" videoUrl="https://www.youtube.com/watch?v=R6zWLfHIYJw" videoLength="9:29">
<description><![CDATA[Using Qt Creator tutorials and examples to develop Qt applications.]]></description>
<tags>qt creator,video,2018</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt Creator - Introduction to Qt Quick Controls" isVideo="true" videoUrl="https://www.youtube.com/watch?v=uuhmSZxK1mk" videoLength="7:09">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeuuhmSZxK1mk.webp" difficulty="" projectPath="" name="Online: Qt Creator - Introduction to Qt Quick Controls" isVideo="true" videoUrl="https://www.youtube.com/watch?v=uuhmSZxK1mk" videoLength="7:09">
<description><![CDATA[Using Qt Quick Controls to develop Qt Quick applications.]]></description>
<tags>qt creator,qt quick,controls,video,2018</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Debugging inside Qt Creator" isVideo="true" videoUrl="https://youtu.be/Y-MM-9FigTc" videoLength="21:54">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeY-MM-9FigTc.webp" difficulty="" projectPath="" name="Online: Debugging inside Qt Creator" isVideo="true" videoUrl="https://youtu.be/Y-MM-9FigTc" videoLength="21:54">
<description><![CDATA[Debugging applications in Qt Creator.]]></description>
<tags>qt creator,debugging,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: How to do translations with Qt Linguist" isVideo="true" videoUrl="https://youtu.be/xNIz78IPBu0" videoLength="9:14">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubexNIz78IPBu0.webp" difficulty="" projectPath="" name="Online: How to do translations with Qt Linguist" isVideo="true" videoUrl="https://youtu.be/xNIz78IPBu0" videoLength="9:14">
<description><![CDATA[Preparing applications for translation, translating them with Qt Linguist, and using the translations in apps.]]></description>
<tags>qt creator,qt linguist,translation,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt Windows Online Installer walkthrough" isVideo="true" videoUrl="https://youtu.be/-xhiVA0P4yk" videoLength="6:17">
+ <tutorial imageUrl=":qtsupport/images/icons/youtube-xhiVA0P4yk.webp" difficulty="" projectPath="" name="Online: Qt Windows Online Installer walkthrough" isVideo="true" videoUrl="https://youtu.be/-xhiVA0P4yk" videoLength="6:17">
<description><![CDATA[Downloading and installing Qt with the options that you want.]]></description>
<tags>qt,installation,online installer,modules,video,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: How to install and set up Qt for Device Creation on Linux" isVideo="true" videoUrl="https://youtu.be/YJfFwDBOvqk" videoLength="6:52">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeYJfFwDBOvqk.webp" difficulty="" projectPath="" name="Online: How to install and set up Qt for Device Creation on Linux" isVideo="true" videoUrl="https://youtu.be/YJfFwDBOvqk" videoLength="6:52">
<description><![CDATA[Downloading and installing Qt Device Creation with the options that you want.]]></description>
<tags>embedded,installation,device creation,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Creating a simple widget app" isVideo="true" videoUrl="https://youtu.be/jbx3Oq1Q4gY" videoLength="6:08">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubejbx3Oq1Q4gY.webp" difficulty="" projectPath="" name="Online: Creating a simple widget app" isVideo="true" videoUrl="https://youtu.be/jbx3Oq1Q4gY" videoLength="6:08">
<description><![CDATA[Creating a simple widget-based application and running it on your development machine using Qt Creator 5.0.]]></description>
<tags>qt creator,widgets,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Creating a simple Qt Quick app" isVideo="true" videoUrl="https://youtu.be/mAhwHsGdJuI" videoLength="8:21">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubemAhwHsGdJuI.webp" difficulty="" projectPath="" name="Online: Creating a simple Qt Quick app" isVideo="true" videoUrl="https://youtu.be/mAhwHsGdJuI" videoLength="8:21">
<description><![CDATA[Creating a simple Qt Quick application and running it on your development machine using Qt Creator 5.0.]]></description>
<tags>qt creator,qt quick,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt Widgets or Qt Quick" isVideo="true" videoUrl="https://youtu.be/2RvhhEAZQxM" videoLength="5:00">
+ <tutorial imageUrl=":qtsupport/images/icons/youtube2RvhhEAZQxM.webp" difficulty="" projectPath="" name="Online: Qt Widgets or Qt Quick" isVideo="true" videoUrl="https://youtu.be/2RvhhEAZQxM" videoLength="5:00">
<description><![CDATA[Learning the differences between Qt Widgets and Qt Quick and making the right choice for your application needs.]]></description>
<tags>qt quick,widgets,ui,video,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: How to install and set up Qt for MCUs" isVideo="true" videoUrl="https://youtu.be/DRFz0Tll4G8" videoLength="8:29">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeDRFz0Tll4G8.webp" difficulty="" projectPath="" name="Online: How to install and set up Qt for MCUs" isVideo="true" videoUrl="https://youtu.be/DRFz0Tll4G8" videoLength="8:29">
<description><![CDATA[Downloading and installing Qt for MCUs with the options that you want.]]></description>
<tags>qt,mcus,video,STM32H750B-DISCOVERY,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: How to build your first 'Qt for MCUs' application" isVideo="true" videoUrl="https://youtu.be/BkgjJfxYN20" videoLength="21:54">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeBkgjJfxYN20.webp" difficulty="" projectPath="" name="Online: How to build your first 'Qt for MCUs' application" isVideo="true" videoUrl="https://youtu.be/BkgjJfxYN20" videoLength="21:54">
<description><![CDATA[Building your first application for the NXP IMXRT1050 device.]]></description>
<tags>qtformcus,mcus,qt,video,NXP IMXRT1050-EVKB,2020</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: How to create a simple application with Qt for MCUs" isVideo="true" videoUrl="https://youtu.be/mn-JmXIMCqk" videoLength="5:16">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubemn-JmXIMCqk.webp" difficulty="" projectPath="" name="Online: How to create a simple application with Qt for MCUs" isVideo="true" videoUrl="https://youtu.be/mn-JmXIMCqk" videoLength="5:16">
<description><![CDATA[Creating a simple Qt for MCUs application and running it on your development machine using Qt Creator 5.0.]]></description>
<tags>qtformcus,mcus,qt,video,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Custom Qt Creator Wizards" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3DuCgFamo" videoLength="27:21">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeKo3DuCgFamo.webp" difficulty="" projectPath="" name="Talk: Custom Qt Creator Wizards" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3DuCgFamo" videoLength="27:21">
<description><![CDATA[Adding custom file and project creation wizards to Qt Creator.]]></description>
<tags>qt creator,wizard,talk,2015</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Extending Qt Creator" isVideo="true" videoUrl="http://www.youtube.com/watch?v=DP0lMoLVneY" videoLength="59:49">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeDP0lMoLVneY.webp" difficulty="" projectPath="" name="Talk: Extending Qt Creator" isVideo="true" videoUrl="http://www.youtube.com/watch?v=DP0lMoLVneY" videoLength="59:49">
<description><![CDATA[Customizing Qt Creator to fit your own or your customers' purposes.]]></description>
<tags>qt creator,configuration,talk,2013</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: How to create a plugin for Qt Creator" isVideo="true" videoUrl="https://youtu.be/PzV2MYRAUYQ" videoLength="55:37">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubePzV2MYRAUYQ.webp" difficulty="" projectPath="" name="Talk: How to create a plugin for Qt Creator" isVideo="true" videoUrl="https://youtu.be/PzV2MYRAUYQ" videoLength="55:37">
<description><![CDATA[Adding plugins to Qt Creator.]]></description>
<tags>qt creator,plugins,talk,2019</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Using the QML Profiler" isVideo="true" videoUrl="https://www.youtube.com/watch?v=TiJiF0MOOFc" videoLength="55:12">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeTiJiF0MOOFc.webp" difficulty="" projectPath="" name="Talk: Qt Creator - Using the QML Profiler" isVideo="true" videoUrl="https://www.youtube.com/watch?v=TiJiF0MOOFc" videoLength="55:12">
<description><![CDATA[Monitoring the performance of a Qt Quick application.]]></description>
<tags>qt quick,qt creator,qml profiler,talk,2014</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: The CPU Usage Analyzer for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=G0AbgVHGdXI" videoLength="22:30">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeG0AbgVHGdXI.webp" difficulty="" projectPath="" name="Talk: The CPU Usage Analyzer for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=G0AbgVHGdXI" videoLength="22:30">
<description><![CDATA[Using the Linux perf tool to generate data for code analysis.]]></description>
<tags>qt creator,cpu usage analyzer,perf,embedded,device creation,talk,2015</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt SCXML - State Machines Made Easier" isVideo="true" videoUrl="https://youtu.be/X0kEkB0ewyw" videoLength="42:22">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeX0kEkB0ewyw.webp" difficulty="" projectPath="" name="Talk: Qt SCXML - State Machines Made Easier" isVideo="true" videoUrl="https://youtu.be/X0kEkB0ewyw" videoLength="42:22">
<description><![CDATA[Using the Qt SCXML module and Qt Creator SCXML editor.]]></description>
<tags>qt creator,scxml,talk,2016</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Effective Multi-Platform Development with Qt Creator, QBS, and QEMU" isVideo="true" videoUrl="https://www.youtube.com/watch?v=v4glCQt2jE0" videoLength="19:08">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubev4glCQt2jE0.webp" difficulty="" projectPath="" name="Talk: Effective Multi-Platform Development with Qt Creator, QBS, and QEMU" isVideo="true" videoUrl="https://www.youtube.com/watch?v=v4glCQt2jE0" videoLength="19:08">
<description><![CDATA[Using Qt Creator, Qbs, and QEMU for application development.]]></description>
<tags>qt creator,qbs,qemu,talk,2015</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt for iOS - A to Z" isVideo="true" videoUrl="https://youtu.be/T_13aX5NTPk" videoLength="1:00:13">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeT_13aX5NTPk.webp" difficulty="" projectPath="" name="Talk: Qt for iOS - A to Z" isVideo="true" videoUrl="https://youtu.be/T_13aX5NTPk" videoLength="1:00:13">
<description><![CDATA[Developing Qt applications for iOS.]]></description>
<tags>qt creator,ios,talk,2016</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator for Bare Metal Development" isVideo="true" videoUrl="http://www.youtube.com/watch?v=hrKz63Q_Rf0" videoLength="9:35">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubehrKz63Q_Rf0.webp" difficulty="" projectPath="" name="Talk: Qt Creator for Bare Metal Development" isVideo="true" videoUrl="http://www.youtube.com/watch?v=hrKz63Q_Rf0" videoLength="9:35">
<description><![CDATA[Developing Qt Applications for Bare Metal devices.]]></description>
<tags>qt creator,baremetal,talk,2013</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: The Curse of Choice - An Overview of GUI Technologies in Qt" isVideo="true" videoUrl="https://youtu.be/WIRRoPxIerc" videoLength="40:45">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeWIRRoPxIerc.webp" difficulty="" projectPath="" name="Talk: The Curse of Choice - An Overview of GUI Technologies in Qt" isVideo="true" videoUrl="https://youtu.be/WIRRoPxIerc" videoLength="40:45">
<description><![CDATA[Overview of UI technologies that can be used with Qt.]]></description>
<tags>qt quick,ui,widgets,talk,2016</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Code Once Deploy Everywhere: How Qt is ideal for cross-platform development" isVideo="true" videoUrl="https://youtu.be/sRihJdZFuCg" videoLength="42:37">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubesRihJdZFuCg.webp" difficulty="" projectPath="" name="Talk: Code Once Deploy Everywhere: How Qt is ideal for cross-platform development" isVideo="true" videoUrl="https://youtu.be/sRihJdZFuCg" videoLength="42:37">
<description><![CDATA[Using Qt Creator for cross-platform development.]]></description>
<tags>qt creator,talk,2019</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: WEBASM with Qt - Qt for WebAssembly" isVideo="true" videoUrl="https://youtu.be/W3WC-VpKdGQ" videoLength="27:50">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeW3WC-VpKdGQ.webp" difficulty="" projectPath="" name="Talk: WEBASM with Qt - Qt for WebAssembly" isVideo="true" videoUrl="https://youtu.be/W3WC-VpKdGQ" videoLength="27:50">
<description><![CDATA[Running Qt applications on the Web using Qt for WebAssembly.]]></description>
<tags>qt creator,webassembly,emscripten,talk,2019</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: How to Develop with Qt for Multiple Screen Resolutions and Platforms and Best Practices for an Efficient App Lifecycle with Qt" isVideo="true" videoUrl="https://youtu.be/qclquZ99ZVQ" videoLength="27:44">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeqclquZ99ZVQ.webp" difficulty="" projectPath="" name="Talk: How to Develop with Qt for Multiple Screen Resolutions and Platforms and Best Practices for an Efficient App Lifecycle with Qt" isVideo="true" videoUrl="https://youtu.be/qclquZ99ZVQ" videoLength="27:44">
<description><![CDATA[Best practices for an efficient app lifecycle.]]></description>
<tags>qt,qt quick,screen resolution,ui,talk,2016</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Designer tutorial: Integrate custom widgets" isVideo="true" videoUrl="https://youtu.be/B0X5FOev9Lw" videoLength="27:07">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeB0X5FOev9Lw.webp" difficulty="" projectPath="" name="Talk: Qt Designer tutorial: Integrate custom widgets" isVideo="true" videoUrl="https://youtu.be/B0X5FOev9Lw" videoLength="27:07">
<description><![CDATA[Integrating custom widgets into Qt Designer.]]></description>
<tags>qt designer,widgets,ui,talk,2019</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Android &amp; iOS - Put Your App on a Diet" isVideo="true" videoUrl="https://www.youtube.com/watch?v=3o2Wo4YzlII" videoLength="23:41">
+ <tutorial imageUrl=":qtsupport/images/icons/youtube3o2Wo4YzlII.webp" difficulty="" projectPath="" name="Talk: Android &amp; iOS - Put Your App on a Diet" isVideo="true" videoUrl="https://www.youtube.com/watch?v=3o2Wo4YzlII" videoLength="23:41">
<description><![CDATA[Making Android and iOS apps smaller.]]></description>
<tags>android,ios,talk,2017</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: LTTng for full stack tracing" isVideo="true" videoUrl="https://youtu.be/v_ynSET9FHU" videoLength="25:46">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubev_ynSET9FHU.webp" difficulty="" projectPath="" name="Talk: LTTng for full stack tracing" isVideo="true" videoUrl="https://youtu.be/v_ynSET9FHU" videoLength="25:46">
<description><![CDATA[Using tracing and profiling to optimize the startup time of apps.]]></description>
<tags>qt creator,qml profiler,ctf viewer,lttng,talk,2019</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: No Limits - How to Make a More Complicated Mobile Business App" isVideo="true" videoUrl="https://www.youtube.com/watch?v=au3brB7lNms" videoLength="23:33">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeau3brB7lNms.webp" difficulty="" projectPath="" name="Talk: No Limits - How to Make a More Complicated Mobile Business App" isVideo="true" videoUrl="https://www.youtube.com/watch?v=au3brB7lNms" videoLength="23:33">
<description><![CDATA[Creating mobile business apps using Qt Quick Controls 2.]]></description>
<tags>android,ios,qt quick,controls,talk,2017</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt &amp; Yocto, an ECU development workflow" isVideo="true" videoUrl="https://youtu.be/ECA8_oLT0ZE" videoLength="29:08">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubeECA8_oLT0ZE.webp" difficulty="" projectPath="" name="Talk: Qt &amp; Yocto, an ECU development workflow" isVideo="true" videoUrl="https://youtu.be/ECA8_oLT0ZE" videoLength="29:08">
<description><![CDATA[Using Qt Creator kits and Yocto when developing for embedded devices.]]></description>
<tags>qt creator,kits,yocto,embedded,talk,2019</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator in Space" isVideo="true" videoUrl="https://youtu.be/1w0ak9RNNWY" videoLength="28:05">
+ <tutorial imageUrl=":qtsupport/images/icons/youtube1w0ak9RNNWY.webp" difficulty="" projectPath="" name="Talk: Qt Creator in Space" isVideo="true" videoUrl="https://youtu.be/1w0ak9RNNWY" videoLength="28:05">
<description><![CDATA[Creating and maintaining a portfolio of Qt Creator plugins.]]></description>
<tags>qt creator,plugins,video,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: All You Need to Get Your App Done with Qt for Android" isVideo="true" videoUrl="https://youtu.be/nmvurCcsWos" videoLength="24:11">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubenmvurCcsWos.webp" difficulty="" projectPath="" name="Talk: All You Need to Get Your App Done with Qt for Android" isVideo="true" videoUrl="https://youtu.be/nmvurCcsWos" videoLength="24:11">
<description><![CDATA[Developing an Android app using Qt for Android.]]></description>
<tags>android,talk,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Styling a Qt Quick Controls Desktop Application" isVideo="true" videoUrl="https://youtu.be/tnZo9umrPtg" videoLength="29:40">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubetnZo9umrPtg.webp" difficulty="" projectPath="" name="Talk: Styling a Qt Quick Controls Desktop Application" isVideo="true" videoUrl="https://youtu.be/tnZo9umrPtg" videoLength="29:40">
<description><![CDATA[Styling Qt Quick Controls using the styling API.]]></description>
<tags>qt quick,controls,styling,ui,talk,2021</tags>
</tutorial>
- <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: The New Property Bindings: Making C++ more QMLish" isVideo="true" videoUrl="https://youtu.be/pN0pRBUqrrc" videoLength="29:54">
+ <tutorial imageUrl=":qtsupport/images/icons/youtubepN0pRBUqrrc.webp" difficulty="" projectPath="" name="Talk: The New Property Bindings: Making C++ more QMLish" isVideo="true" videoUrl="https://youtu.be/pN0pRBUqrrc" videoLength="29:54">
<description><![CDATA[Using the Qt 6 property system in pure C++ and mixed C++/QML applications.]]></description>
<tags>qt,c++,qml,talk,2021</tags>
</tutorial>
diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp
index ab8643f535f..c0049058abd 100644
--- a/src/plugins/qtsupport/qtoptionspage.cpp
+++ b/src/plugins/qtsupport/qtoptionspage.cpp
@@ -124,11 +124,12 @@ public:
return m_icon;
if (role == Qt::ToolTipRole) {
- const QString row = "<tr><td>%1:</td><td>%2</td></tr>";
- return QString("<table>"
+ const QString row = "<dt style=\"font-weight:bold\">%1:</dt>"
+ "<dd>%2</dd>";
+ return QString("<dl style=\"white-space:pre\">"
+ row.arg(tr("Qt Version"), m_version->qtVersionString())
+ row.arg(tr("Location of qmake"), m_version->qmakeFilePath().toUserOutput())
- + "</table>");
+ + "</dl>");
}
return QVariant();
diff --git a/src/plugins/qtsupport/qtsupport.qbs b/src/plugins/qtsupport/qtsupport.qbs
index 4a3e556f075..e234f45de7e 100644
--- a/src/plugins/qtsupport/qtsupport.qbs
+++ b/src/plugins/qtsupport/qtsupport.qbs
@@ -99,8 +99,6 @@ Project {
"qtversionmanager.cpp",
"qtversionmanager.h",
"qtversionmanager.ui",
- "screenshotcropper.cpp",
- "screenshotcropper.h",
"showbuildlog.ui",
"translationwizardpage.cpp",
"translationwizardpage.h",
diff --git a/src/plugins/qtsupport/qtsupport.qrc b/src/plugins/qtsupport/qtsupport.qrc
index 03c14062c04..a082a454159 100644
--- a/src/plugins/qtsupport/qtsupport.qrc
+++ b/src/plugins/qtsupport/qtsupport.qrc
@@ -4,13 +4,48 @@
<file>images/dark_qml.png</file>
<file>images/dark_qt_project.png</file>
<file>images/dark_qt_qrc.png</file>
- <file>images_areaofinterest.xml</file>
<file>qtcreator_tutorials.xml</file>
+ <file>images/icons/playoverlay.png</file>
+ <file>images/icons/playoverlay@2x.png</file>
<file>images/icons/tutorialicon.png</file>
<file>images/icons/tutorialicon@2x.png</file>
- <file>images/icons/videotutorialicon.png</file>
- <file>images/icons/videotutorialicon@2x.png</file>
- <file>images/icons/qteventicon.png</file>
- <file>images/icons/qteventicon@2x.png</file>
+ <file>images/icons/youtube-xhiVA0P4yk.webp</file>
+ <file>images/icons/youtube1tSpq5OLkYI.webp</file>
+ <file>images/icons/youtube1w0ak9RNNWY.webp</file>
+ <file>images/icons/youtube2RvhhEAZQxM.webp</file>
+ <file>images/icons/youtube3o2Wo4YzlII.webp</file>
+ <file>images/icons/youtube9BcAYDlpuT8.webp</file>
+ <file>images/icons/youtube9xqhq9nDiOg.webp</file>
+ <file>images/icons/youtubeB0X5FOev9Lw.webp</file>
+ <file>images/icons/youtubeBkgjJfxYN20.webp</file>
+ <file>images/icons/youtubeDP0lMoLVneY.webp</file>
+ <file>images/icons/youtubeDRFz0Tll4G8.webp</file>
+ <file>images/icons/youtubeECA8_oLT0ZE.webp</file>
+ <file>images/icons/youtubeG0AbgVHGdXI.webp</file>
+ <file>images/icons/youtubeKo3DuCgFamo.webp</file>
+ <file>images/icons/youtubePzV2MYRAUYQ.webp</file>
+ <file>images/icons/youtubeR6zWLfHIYJw.webp</file>
+ <file>images/icons/youtubeT_13aX5NTPk.webp</file>
+ <file>images/icons/youtubeTiJiF0MOOFc.webp</file>
+ <file>images/icons/youtubeW3WC-VpKdGQ.webp</file>
+ <file>images/icons/youtubeWIRRoPxIerc.webp</file>
+ <file>images/icons/youtubeX0kEkB0ewyw.webp</file>
+ <file>images/icons/youtubeY-MM-9FigTc.webp</file>
+ <file>images/icons/youtubeYJfFwDBOvqk.webp</file>
+ <file>images/icons/youtubeau3brB7lNms.webp</file>
+ <file>images/icons/youtubehrKz63Q_Rf0.webp</file>
+ <file>images/icons/youtubejbx3Oq1Q4gY.webp</file>
+ <file>images/icons/youtubemAhwHsGdJuI.webp</file>
+ <file>images/icons/youtubemn-JmXIMCqk.webp</file>
+ <file>images/icons/youtubenmvurCcsWos.webp</file>
+ <file>images/icons/youtubepN0pRBUqrrc.webp</file>
+ <file>images/icons/youtubeqclquZ99ZVQ.webp</file>
+ <file>images/icons/youtubesRihJdZFuCg.webp</file>
+ <file>images/icons/youtubetnZo9umrPtg.webp</file>
+ <file>images/icons/youtubeuuhmSZxK1mk.webp</file>
+ <file>images/icons/youtubev4glCQt2jE0.webp</file>
+ <file>images/icons/youtubev_ynSET9FHU.webp</file>
+ <file>images/icons/youtubexNIz78IPBu0.webp</file>
+ <file>images/icons/youtubezAqSiIGdj8M.webp</file>
</qresource>
</RCC>
diff --git a/src/plugins/qtsupport/qtsupport_global.h b/src/plugins/qtsupport/qtsupport_global.h
index 993bfcdb089..a6e4f7311c4 100644
--- a/src/plugins/qtsupport/qtsupport_global.h
+++ b/src/plugins/qtsupport/qtsupport_global.h
@@ -29,6 +29,8 @@
#if defined(QTSUPPORT_LIBRARY)
# define QTSUPPORT_EXPORT Q_DECL_EXPORT
+#elif defined(QTSUPPORT_STATIC_LIBRARY)
+# define QTSUPPORT_EXPORT
#else
# define QTSUPPORT_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp
index 0265c493eb6..442175a30f7 100644
--- a/src/plugins/qtsupport/qtsupportplugin.cpp
+++ b/src/plugins/qtsupport/qtsupportplugin.cpp
@@ -119,7 +119,7 @@ static void askAboutQtInstallation()
kLinkWithQtInstallationSetting,
QtSupportPlugin::tr(
"Link with a Qt installation to automatically register Qt versions and kits? To do "
- "this later, select Options > Kits > Qt Versions > Link with Qt."),
+ "this later, select Edit > Preferences > Kits > Qt Versions > Link with Qt."),
Utils::InfoBarEntry::GlobalSuppression::Enabled);
info.addCustomButton(QtSupportPlugin::tr("Link with Qt"), [] {
ICore::infoBar()->removeInfo(kLinkWithQtInstallationSetting);
diff --git a/src/plugins/qtsupport/screenshotcropper.cpp b/src/plugins/qtsupport/screenshotcropper.cpp
deleted file mode 100644
index 920a6aa9bc1..00000000000
--- a/src/plugins/qtsupport/screenshotcropper.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "screenshotcropper.h"
-
-#include <utils/fileutils.h>
-
-#include <QXmlStreamReader>
-#include <QXmlStreamWriter>
-#include <QDebug>
-#include <QFile>
-
-namespace QtSupport {
-namespace Internal {
-
-class AreasOfInterest {
-public:
- AreasOfInterest();
- QMap<QString, QRect> areas;
-};
-
-AreasOfInterest::AreasOfInterest()
-{
-#ifdef QT_CREATOR
- areas = ScreenshotCropper::loadAreasOfInterest(":/qtsupport/images_areaofinterest.xml");
-#endif // QT_CREATOR
-}
-
-Q_GLOBAL_STATIC(AreasOfInterest, welcomeScreenAreas)
-
-static inline QString fileNameForPath(const QString &path)
-{
- return Utils::FilePath::fromString(path).fileName();
-}
-
-static QRect cropRectForAreaOfInterest(const QSize &imageSize, const QSize &cropSize, const QRect &areaOfInterest)
-{
- QRect result;
- if (areaOfInterest.width() <= cropSize.width()
- && areaOfInterest.height() <= cropSize.height()) {
- const QPoint areaOfInterestCenter = areaOfInterest.center();
- const int cropX = qBound(0,
- areaOfInterestCenter.x() - cropSize.width() / 2,
- imageSize.width() - cropSize.width());
- const int cropY = qBound(0,
- areaOfInterestCenter.y() - cropSize.height() / 2,
- imageSize.height() - cropSize.height());
- const int cropWidth = qMin(imageSize.width(), cropSize.width());
- const int cropHeight = qMin(imageSize.height(), cropSize.height());
- result = QRect(cropX, cropY, cropWidth, cropHeight);
- } else {
- QSize resultSize = cropSize.scaled(areaOfInterest.width(), areaOfInterest.height(),
- Qt::KeepAspectRatioByExpanding);
- result = QRect(QPoint(), resultSize);
- result.moveCenter(areaOfInterest.center());
- }
- return result;
-}
-
-} // namespace Internal
-
-namespace ScreenshotCropper {
-
-QImage croppedImage(const QImage &sourceImage, const QString &filePath, const QSize &cropSize,
- const QRect &areaOfInterest)
-{
- const QRect area = areaOfInterest.isValid() ? areaOfInterest :
- Internal::welcomeScreenAreas()->areas.value(Internal::fileNameForPath(filePath));
-
- QImage result;
- if (area.isValid()) {
- const QRect cropRect = Internal::cropRectForAreaOfInterest(sourceImage.size(),
- cropSize, areaOfInterest);
- const QSize cropRectSize = cropRect.size();
- result = sourceImage.copy(cropRect);
- if (cropRectSize.width() <= cropSize.width() && cropRectSize.height() <= cropSize.height())
- return result;
- } else {
- result = sourceImage;
- }
-
- if (result.format() != QImage::Format_ARGB32)
- result = result.convertToFormat(QImage::Format_ARGB32);
- return result.scaled(cropSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
-}
-
-static int areaAttribute(const QXmlStreamAttributes &attributes, const QString &name)
-{
- bool ok;
- const int result = attributes.value(name).toString().toInt(&ok);
- if (!ok)
- qWarning() << Q_FUNC_INFO << "Could not parse" << name << "for" << attributes.value(QLatin1String("image")).toString();
- return result;
-}
-
-static const QString xmlTagAreas = QLatin1String("areas");
-static const QString xmlTagArea = QLatin1String("area");
-static const QString xmlAttributeImage = QLatin1String("image");
-static const QString xmlAttributeX = QLatin1String("x");
-static const QString xmlAttributeY = QLatin1String("y");
-static const QString xmlAttributeWidth = QLatin1String("width");
-static const QString xmlAttributeHeight = QLatin1String("height");
-
-QMap<QString, QRect> loadAreasOfInterest(const QString &areasXmlFile)
-{
- QMap<QString, QRect> areasOfInterest;
- QFile xmlFile(areasXmlFile);
- if (!xmlFile.open(QIODevice::ReadOnly)) {
- qWarning() << Q_FUNC_INFO << "Could not open file" << areasXmlFile;
- return areasOfInterest;
- }
- QXmlStreamReader reader(&xmlFile);
- while (!reader.atEnd()) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement:
- if (reader.name() == xmlTagArea) {
- const QXmlStreamAttributes attributes = reader.attributes();
- const QString imageName = attributes.value(xmlAttributeImage).toString();
- if (imageName.isEmpty())
- qWarning() << Q_FUNC_INFO << "Could not parse name";
-
- const QRect area(areaAttribute(attributes, xmlAttributeX), areaAttribute(attributes, xmlAttributeY),
- areaAttribute(attributes, xmlAttributeWidth), areaAttribute(attributes, xmlAttributeHeight));
- areasOfInterest.insert(imageName, area);
- }
- break;
- default: // nothing
- break;
- }
- }
-
- return areasOfInterest;
-}
-
-bool saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas)
-{
- QFile file(areasXmlFile);
- if (!file.open(QIODevice::WriteOnly))
- return false;
- QXmlStreamWriter writer(&file);
- writer.setAutoFormatting(true);
- writer.writeStartDocument();
- writer.writeStartElement(xmlTagAreas);
- for (auto i = areas.cbegin(), end = areas.cend(); i != end; ++i) {
- writer.writeStartElement(xmlTagArea);
- writer.writeAttribute(xmlAttributeImage, i.key());
- writer.writeAttribute(xmlAttributeX, QString::number(i.value().x()));
- writer.writeAttribute(xmlAttributeY, QString::number(i.value().y()));
- writer.writeAttribute(xmlAttributeWidth, QString::number(i.value().width()));
- writer.writeAttribute(xmlAttributeHeight, QString::number(i.value().height()));
- writer.writeEndElement(); // xmlTagArea
- }
- writer.writeEndElement(); // xmlTagAreas
- writer.writeEndDocument();
- return true;
-}
-
-} // ScreenshotCropper
-} // namespace QtSupport
diff --git a/src/plugins/qtsupport/screenshotcropper.h b/src/plugins/qtsupport/screenshotcropper.h
deleted file mode 100644
index d4a90e7387e..00000000000
--- a/src/plugins/qtsupport/screenshotcropper.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "qtsupport_global.h"
-
-#include <QMap>
-#include <QRect>
-
-QT_BEGIN_NAMESPACE
-class QImage;
-class QSize;
-QT_END_NAMESPACE
-
-namespace QtSupport {
-namespace ScreenshotCropper {
-
-QTSUPPORT_EXPORT QImage croppedImage(const QImage &sourceImage, const QString &filePath,
- const QSize &cropSize, const QRect &areaOfInterest = {});
-QTSUPPORT_EXPORT QMap<QString, QRect> loadAreasOfInterest(const QString &areasXmlFile);
-QTSUPPORT_EXPORT bool saveAreasOfInterest(const QString &areasXmlFile,
- QMap<QString, QRect> &areas);
-
-} // ScreenshotCropper
-} // namespace QtSupport
diff --git a/src/plugins/remotelinux/CMakeLists.txt b/src/plugins/remotelinux/CMakeLists.txt
index fb9299c3564..a13af8cd47b 100644
--- a/src/plugins/remotelinux/CMakeLists.txt
+++ b/src/plugins/remotelinux/CMakeLists.txt
@@ -1,11 +1,10 @@
add_qtc_plugin(RemoteLinux
- DEPENDS QmlDebug QtcSsh
+ DEPENDS QmlDebug
PLUGIN_DEPENDS Core Debugger ProjectExplorer
SOURCES
- abstractpackagingstep.cpp abstractpackagingstep.h
abstractremotelinuxdeployservice.cpp abstractremotelinuxdeployservice.h
abstractremotelinuxdeploystep.cpp abstractremotelinuxdeploystep.h
- abstractuploadandinstallpackageservice.cpp abstractuploadandinstallpackageservice.h
+ customcommanddeploystep.cpp customcommanddeploystep.h
deploymenttimeinfo.cpp deploymenttimeinfo.h
genericdirectuploadservice.cpp genericdirectuploadservice.h
genericdirectuploadstep.cpp genericdirectuploadstep.h
@@ -13,37 +12,31 @@ add_qtc_plugin(RemoteLinux
genericlinuxdeviceconfigurationwizard.cpp genericlinuxdeviceconfigurationwizard.h
genericlinuxdeviceconfigurationwizardpages.cpp genericlinuxdeviceconfigurationwizardpages.h
genericlinuxdeviceconfigurationwizardsetuppage.ui
+ killappstep.cpp killappstep.h
linuxdevice.cpp linuxdevice.h
- linuxdeviceprocess.cpp linuxdeviceprocess.h
linuxdevicetester.cpp linuxdevicetester.h
+ linuxprocessinterface.h
makeinstallstep.cpp makeinstallstep.h
- packageuploader.cpp packageuploader.h
publickeydeploymentdialog.cpp publickeydeploymentdialog.h
remotelinux.qrc
remotelinux_constants.h
remotelinux_export.h
- remotelinuxcheckforfreediskspaceservice.cpp remotelinuxcheckforfreediskspaceservice.h
- remotelinuxcheckforfreediskspacestep.cpp remotelinuxcheckforfreediskspacestep.h
- remotelinuxcustomcommanddeploymentstep.cpp remotelinuxcustomcommanddeploymentstep.h
- remotelinuxcustomcommanddeployservice.cpp remotelinuxcustomcommanddeployservice.h
remotelinuxcustomrunconfiguration.cpp remotelinuxcustomrunconfiguration.h
remotelinuxdebugsupport.cpp remotelinuxdebugsupport.h
remotelinuxdeployconfiguration.cpp remotelinuxdeployconfiguration.h
remotelinuxenvironmentaspect.cpp remotelinuxenvironmentaspect.h
remotelinuxenvironmentaspectwidget.cpp remotelinuxenvironmentaspectwidget.h
remotelinuxenvironmentreader.cpp remotelinuxenvironmentreader.h
- remotelinuxkillappservice.cpp remotelinuxkillappservice.h
- remotelinuxkillappstep.cpp remotelinuxkillappstep.h
- remotelinuxpackageinstaller.cpp remotelinuxpackageinstaller.h
remotelinuxplugin.cpp remotelinuxplugin.h
remotelinuxqmltoolingsupport.cpp remotelinuxqmltoolingsupport.h
remotelinuxrunconfiguration.cpp remotelinuxrunconfiguration.h
remotelinuxsignaloperation.cpp remotelinuxsignaloperation.h
- remotelinuxx11forwardingaspect.cpp remotelinuxx11forwardingaspect.h
rsyncdeploystep.cpp rsyncdeploystep.h
- sshkeydeployer.cpp sshkeydeployer.h
+ sshkeycreationdialog.cpp sshkeycreationdialog.h sshkeycreationdialog.ui
+ sshprocessinterface.h
tarpackagecreationstep.cpp tarpackagecreationstep.h
- uploadandinstalltarpackagestep.cpp uploadandinstalltarpackagestep.h
+ tarpackagedeploystep.cpp tarpackagedeploystep.h
+ x11forwardingaspect.cpp x11forwardingaspect.h
)
extend_qtc_plugin(RemoteLinux
diff --git a/src/plugins/remotelinux/abstractpackagingstep.cpp b/src/plugins/remotelinux/abstractpackagingstep.cpp
deleted file mode 100644
index 2c31b8aa75f..00000000000
--- a/src/plugins/remotelinux/abstractpackagingstep.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "abstractpackagingstep.h"
-
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/deploymentdata.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/task.h>
-
-#include <QDateTime>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace RemoteLinux {
-namespace Internal {
-
-class AbstractPackagingStepPrivate
-{
-public:
- FilePath cachedPackageFilePath;
- FilePath cachedPackageDirectory;
- bool deploymentDataModified = false;
-};
-
-} // namespace Internal
-
-AbstractPackagingStep::AbstractPackagingStep(BuildStepList *bsl, Utils::Id id)
- : BuildStep(bsl, id)
-{
- d = new Internal::AbstractPackagingStepPrivate;
-
- connect(target(), &Target::deploymentDataChanged,
- this, &AbstractPackagingStep::setDeploymentDataModified);
- setDeploymentDataModified();
-
- connect(this, &AbstractPackagingStep::unmodifyDeploymentData,
- this, &AbstractPackagingStep::setDeploymentDataUnmodified);
-}
-
-AbstractPackagingStep::~AbstractPackagingStep()
-{
- delete d;
-}
-
-FilePath AbstractPackagingStep::cachedPackageFilePath() const
-{
- return d->cachedPackageFilePath;
-}
-
-FilePath AbstractPackagingStep::packageFilePath() const
-{
- if (packageDirectory().isEmpty())
- return {};
- return packageDirectory().pathAppended(packageFileName());
-}
-
-FilePath AbstractPackagingStep::cachedPackageDirectory() const
-{
- return d->cachedPackageDirectory;
-}
-
-FilePath AbstractPackagingStep::packageDirectory() const
-{
- return buildDirectory();
-}
-
-bool AbstractPackagingStep::isPackagingNeeded() const
-{
- const FilePath packagePath = packageFilePath();
- if (!packagePath.exists() || d->deploymentDataModified)
- return true;
-
- const DeploymentData &dd = target()->deploymentData();
- for (int i = 0; i < dd.fileCount(); ++i) {
- if (dd.fileAt(i).localFilePath().isNewerThan(packagePath.lastModified()))
- return true;
- }
-
- return false;
-}
-
-bool AbstractPackagingStep::init()
-{
- d->cachedPackageDirectory = packageDirectory();
- d->cachedPackageFilePath = packageFilePath();
- return true;
-}
-
-void AbstractPackagingStep::setPackagingStarted()
-{
-}
-
-// called in ::run thread
-void AbstractPackagingStep::setPackagingFinished(bool success)
-{
- if (success)
- emit unmodifyDeploymentData();
-}
-
-// called in gui thread
-void AbstractPackagingStep::setDeploymentDataUnmodified()
-{
- d->deploymentDataModified = false;
-}
-
-void AbstractPackagingStep::setDeploymentDataModified()
-{
- d->deploymentDataModified = true;
-}
-
-void AbstractPackagingStep::raiseError(const QString &errorMessage)
-{
- emit addTask(DeploymentTask(Task::Error, errorMessage));
- emit addOutput(errorMessage, BuildStep::OutputFormat::Stderr);
-}
-
-void AbstractPackagingStep::raiseWarning(const QString &warningMessage)
-{
- emit addTask(DeploymentTask(Task::Warning, warningMessage));
- emit addOutput(warningMessage, OutputFormat::ErrorMessage);
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/abstractpackagingstep.h b/src/plugins/remotelinux/abstractpackagingstep.h
deleted file mode 100644
index 681ba70ac00..00000000000
--- a/src/plugins/remotelinux/abstractpackagingstep.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "remotelinux_export.h"
-
-#include <projectexplorer/buildstep.h>
-
-namespace RemoteLinux {
-
-namespace Internal { class AbstractPackagingStepPrivate; }
-
-class REMOTELINUX_EXPORT AbstractPackagingStep : public ProjectExplorer::BuildStep
-{
- Q_OBJECT
-
-public:
- explicit AbstractPackagingStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
- ~AbstractPackagingStep() override;
-
- Utils::FilePath packageFilePath() const;
- Utils::FilePath cachedPackageFilePath() const;
- bool init() override;
-
-signals:
- void unmodifyDeploymentData();
-
-protected:
- void setPackagingStarted();
- void setPackagingFinished(bool success);
-
- void raiseError(const QString &errorMessage);
- void raiseWarning(const QString &warningMessage);
- Utils::FilePath cachedPackageDirectory() const;
- Utils::FilePath packageDirectory() const;
-
- virtual bool isPackagingNeeded() const;
-
-private:
- void setDeploymentDataUnmodified();
- void setDeploymentDataModified();
-
- virtual QString packageFileName() const = 0;
-
- Internal::AbstractPackagingStepPrivate *d;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
index 2649ebeeddc..aee4d2eec53 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
+++ b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
@@ -24,30 +24,27 @@
****************************************************************************/
#include "abstractremotelinuxdeployservice.h"
+
#include "deploymenttimeinfo.h"
#include <projectexplorer/deployablefile.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshconnectionmanager.h>
-
#include <utils/qtcassert.h>
#include <QDateTime>
#include <QFileInfo>
#include <QPointer>
-#include <QString>
using namespace ProjectExplorer;
-using namespace QSsh;
namespace RemoteLinux {
namespace Internal {
namespace {
-enum State { Inactive, SettingUpDevice, Connecting, Deploying };
+enum State { Inactive, Deploying };
} // anonymous namespace
class AbstractRemoteLinuxDeployServicePrivate
@@ -57,7 +54,6 @@ public:
QPointer<Target> target;
DeploymentTimeInfo deployTimes;
- SshConnection *connection = nullptr;
State state = Inactive;
bool stopRequested = false;
};
@@ -80,7 +76,7 @@ const Target *AbstractRemoteLinuxDeployService::target() const
return d->target;
}
-const Kit *AbstractRemoteLinuxDeployService::profile() const
+const Kit *AbstractRemoteLinuxDeployService::kit() const
{
return d->target ? d->target->kit() : nullptr;
}
@@ -90,33 +86,28 @@ IDevice::ConstPtr AbstractRemoteLinuxDeployService::deviceConfiguration() const
return d->deviceConfiguration;
}
-SshConnection *AbstractRemoteLinuxDeployService::connection() const
-{
- return d->connection;
-}
-
void AbstractRemoteLinuxDeployService::saveDeploymentTimeStamp(const DeployableFile &deployableFile,
const QDateTime &remoteTimestamp)
{
- d->deployTimes.saveDeploymentTimeStamp(deployableFile, profile(), remoteTimestamp);
+ d->deployTimes.saveDeploymentTimeStamp(deployableFile, kit(), remoteTimestamp);
}
bool AbstractRemoteLinuxDeployService::hasLocalFileChanged(
const DeployableFile &deployableFile) const
{
- return d->deployTimes.hasLocalFileChanged(deployableFile, profile());
+ return d->deployTimes.hasLocalFileChanged(deployableFile, kit());
}
bool AbstractRemoteLinuxDeployService::hasRemoteFileChanged(
const DeployableFile &deployableFile, const QDateTime &remoteTimestamp) const
{
- return d->deployTimes.hasRemoteFileChanged(deployableFile, profile(), remoteTimestamp);
+ return d->deployTimes.hasRemoteFileChanged(deployableFile, kit(), remoteTimestamp);
}
void AbstractRemoteLinuxDeployService::setTarget(Target *target)
{
d->target = target;
- d->deviceConfiguration = DeviceKitAspect::device(profile());
+ d->deviceConfiguration = DeviceKitAspect::device(kit());
}
void AbstractRemoteLinuxDeployService::setDevice(const IDevice::ConstPtr &device)
@@ -141,8 +132,8 @@ void AbstractRemoteLinuxDeployService::start()
return;
}
- d->state = SettingUpDevice;
- doDeviceSetup();
+ d->state = Deploying;
+ doDeploy();
}
void AbstractRemoteLinuxDeployService::stop()
@@ -150,20 +141,9 @@ void AbstractRemoteLinuxDeployService::stop()
if (d->stopRequested)
return;
- switch (d->state) {
- case Inactive:
- break;
- case SettingUpDevice:
- d->stopRequested = true;
- stopDeviceSetup();
- break;
- case Connecting:
- setFinished();
- break;
- case Deploying:
+ if (d->state == Deploying) {
d->stopRequested = true;
stopDeployment();
- break;
}
}
@@ -184,32 +164,6 @@ void AbstractRemoteLinuxDeployService::importDeployTimes(const QVariantMap &map)
d->deployTimes.importDeployTimes(map);
}
-void AbstractRemoteLinuxDeployService::handleDeviceSetupDone(bool success)
-{
- QTC_ASSERT(d->state == SettingUpDevice, return);
-
- if (!success || d->stopRequested) {
- setFinished();
- return;
- }
-
- d->state = Connecting;
- d->connection = SshConnectionManager::acquireConnection(deviceConfiguration()->sshParameters());
- connect(d->connection, &SshConnection::errorOccurred,
- this, &AbstractRemoteLinuxDeployService::handleConnectionFailure);
- if (d->connection->state() == SshConnection::Connected) {
- handleConnected();
- } else {
- connect(d->connection, &SshConnection::connected,
- this, &AbstractRemoteLinuxDeployService::handleConnected);
- emit progressMessage(tr("Connecting to device \"%1\" (%2).")
- .arg(deviceConfiguration()->displayName())
- .arg(deviceConfiguration()->sshParameters().host()));
- if (d->connection->state() == SshConnection::Unconnected)
- d->connection->connectToHost();
- }
-}
-
void AbstractRemoteLinuxDeployService::handleDeploymentDone()
{
QTC_ASSERT(d->state == Deploying, return);
@@ -217,51 +171,9 @@ void AbstractRemoteLinuxDeployService::handleDeploymentDone()
setFinished();
}
-void AbstractRemoteLinuxDeployService::handleConnected()
-{
- QTC_ASSERT(d->state == Connecting, return);
-
- if (d->stopRequested) {
- setFinished();
- return;
- }
-
- d->state = Deploying;
- doDeploy();
-}
-
-void AbstractRemoteLinuxDeployService::handleConnectionFailure()
-{
- switch (d->state) {
- case Inactive:
- case SettingUpDevice:
- qWarning("%s: Unexpected state %d.", Q_FUNC_INFO, d->state);
- break;
- case Connecting: {
- QString errorMsg = tr("Could not connect to host: %1").arg(d->connection->errorString());
- errorMsg += QLatin1Char('\n');
- if (deviceConfiguration()->machineType() == IDevice::Emulator)
- errorMsg += tr("Did the emulator fail to start?");
- else
- errorMsg += tr("Is the device connected and set up for network access?");
- emit errorMessage(errorMsg);
- setFinished();
- break;
- }
- case Deploying:
- emit errorMessage(tr("Connection error: %1").arg(d->connection->errorString()));
- stopDeployment();
- }
-}
-
void AbstractRemoteLinuxDeployService::setFinished()
{
d->state = Inactive;
- if (d->connection) {
- disconnect(d->connection, nullptr, this, nullptr);
- SshConnectionManager::releaseConnection(d->connection);
- d->connection = nullptr;
- }
d->stopRequested = false;
emit finished();
}
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeployservice.h b/src/plugins/remotelinux/abstractremotelinuxdeployservice.h
index 3d63136fa74..5590d879d03 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeployservice.h
+++ b/src/plugins/remotelinux/abstractremotelinuxdeployservice.h
@@ -27,12 +27,10 @@
#include "remotelinux_export.h"
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
+#include <QtCore/qcontainerfwd.h>
#include <QObject>
-#include <QVariantMap>
-
-namespace QSsh { class SshConnection; }
namespace ProjectExplorer {
class DeployableFile;
@@ -69,7 +67,7 @@ public:
void setTarget(ProjectExplorer::Target *bc);
// Only use setDevice() as fallback if no target is available
- void setDevice(const ProjectExplorer::IDevice::ConstPtr &device);
+ void setDevice(const ProjectExplorer::IDeviceConstPtr &device);
void start();
void stop();
@@ -88,9 +86,8 @@ signals:
protected:
const ProjectExplorer::Target *target() const;
- const ProjectExplorer::Kit *profile() const;
- ProjectExplorer::IDevice::ConstPtr deviceConfiguration() const;
- QSsh::SshConnection *connection() const;
+ const ProjectExplorer::Kit *kit() const;
+ ProjectExplorer::IDeviceConstPtr deviceConfiguration() const;
void saveDeploymentTimeStamp(const ProjectExplorer::DeployableFile &deployableFile,
const QDateTime &remoteTimestamp);
@@ -99,21 +96,12 @@ protected:
bool hasRemoteFileChanged(const ProjectExplorer::DeployableFile &deployableFile,
const QDateTime &remoteTimestamp) const;
- void handleDeviceSetupDone(bool success);
void handleDeploymentDone();
- // Should do things needed *before* connecting. Call default implementation afterwards.
- virtual void doDeviceSetup() { handleDeviceSetupDone(true); }
- virtual void stopDeviceSetup() { handleDeviceSetupDone(false); }
-
void setFinished();
private:
- void handleConnected();
- void handleConnectionFailure();
-
virtual bool isDeploymentNecessary() const = 0;
-
virtual void doDeploy() = 0;
virtual void stopDeployment() = 0;
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp b/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
index ba6c827d87a..b23f7244337 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
+++ b/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
@@ -26,7 +26,6 @@
#include "abstractremotelinuxdeploystep.h"
#include "abstractremotelinuxdeployservice.h"
-#include "remotelinuxdeployconfiguration.h"
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/kitinformation.h>
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeploystep.h b/src/plugins/remotelinux/abstractremotelinuxdeploystep.h
index 14d84a4f59e..2f72c68f559 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeploystep.h
+++ b/src/plugins/remotelinux/abstractremotelinuxdeploystep.h
@@ -27,12 +27,13 @@
#include "remotelinux_export.h"
-#include "abstractremotelinuxdeployservice.h"
-
#include <projectexplorer/buildstep.h>
namespace RemoteLinux {
+class AbstractRemoteLinuxDeployService;
+class CheckResult;
+
namespace Internal { class AbstractRemoteLinuxDeployStepPrivate; }
class REMOTELINUX_EXPORT AbstractRemoteLinuxDeployStep : public ProjectExplorer::BuildStep
diff --git a/src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp b/src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp
deleted file mode 100644
index f307ed2dcc9..00000000000
--- a/src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "abstractuploadandinstallpackageservice.h"
-
-#include "packageuploader.h"
-#include "remotelinuxpackageinstaller.h"
-
-#include <projectexplorer/deployablefile.h>
-#include <utils/qtcassert.h>
-
-#include <QDateTime>
-#include <QString>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace RemoteLinux {
-namespace Internal {
-namespace {
-enum State { Inactive, Uploading, Installing };
-} // anonymous namespace
-
-class AbstractUploadAndInstallPackageServicePrivate
-{
-public:
- AbstractUploadAndInstallPackageServicePrivate()
- : state(Inactive), uploader(new PackageUploader)
- {
- }
- ~AbstractUploadAndInstallPackageServicePrivate() { delete uploader; }
-
- State state;
- PackageUploader * const uploader;
- Utils::FilePath packageFilePath;
-};
-
-} // namespace Internal
-
-using namespace Internal;
-
-AbstractUploadAndInstallPackageService::AbstractUploadAndInstallPackageService()
- : d(new AbstractUploadAndInstallPackageServicePrivate)
-{
-}
-
-AbstractUploadAndInstallPackageService::~AbstractUploadAndInstallPackageService()
-{
- delete d;
-}
-
-void AbstractUploadAndInstallPackageService::setPackageFilePath(const FilePath &filePath)
-{
- d->packageFilePath = filePath;
-}
-
-QString AbstractUploadAndInstallPackageService::uploadDir() const
-{
- return QLatin1String("/tmp");
-}
-
-bool AbstractUploadAndInstallPackageService::isDeploymentNecessary() const
-{
- return hasLocalFileChanged(DeployableFile(d->packageFilePath, QString()));
-}
-
-void AbstractUploadAndInstallPackageService::doDeviceSetup()
-{
- QTC_ASSERT(d->state == Inactive, return);
- AbstractRemoteLinuxDeployService::doDeviceSetup();
-}
-
-void AbstractUploadAndInstallPackageService::stopDeviceSetup()
-{
- QTC_ASSERT(d->state == Inactive, return);
- AbstractRemoteLinuxDeployService::stopDeviceSetup();
-}
-
-void AbstractUploadAndInstallPackageService::doDeploy()
-{
- QTC_ASSERT(d->state == Inactive, return);
-
- d->state = Uploading;
- const QString fileName = d->packageFilePath.fileName();
- const QString remoteFilePath = uploadDir() + QLatin1Char('/') + fileName;
- connect(d->uploader, &PackageUploader::progress,
- this, &AbstractUploadAndInstallPackageService::progressMessage);
- connect(d->uploader, &PackageUploader::uploadFinished,
- this, &AbstractUploadAndInstallPackageService::handleUploadFinished);
- d->uploader->uploadPackage(connection(), d->packageFilePath.toString(), remoteFilePath);
-}
-
-void AbstractUploadAndInstallPackageService::stopDeployment()
-{
- switch (d->state) {
- case Inactive:
- qWarning("%s: Unexpected state 'Inactive'.", Q_FUNC_INFO);
- break;
- case Uploading:
- d->uploader->cancelUpload();
- setFinished();
- break;
- case Installing:
- packageInstaller()->cancelInstallation();
- setFinished();
- break;
- }
-}
-
-void AbstractUploadAndInstallPackageService::handleUploadFinished(const QString &errorMsg)
-{
- QTC_ASSERT(d->state == Uploading, return);
-
- if (!errorMsg.isEmpty()) {
- emit errorMessage(errorMsg);
- setFinished();
- return;
- }
-
- emit progressMessage(tr("Successfully uploaded package file."));
- const QString remoteFilePath = uploadDir() + '/' + d->packageFilePath.fileName();
- d->state = Installing;
- emit progressMessage(tr("Installing package to device..."));
- connect(packageInstaller(), &AbstractRemoteLinuxPackageInstaller::stdoutData,
- this, &AbstractRemoteLinuxDeployService::stdOutData);
- connect(packageInstaller(), &AbstractRemoteLinuxPackageInstaller::stderrData,
- this, &AbstractRemoteLinuxDeployService::stdErrData);
- connect(packageInstaller(), &AbstractRemoteLinuxPackageInstaller::finished,
- this, &AbstractUploadAndInstallPackageService::handleInstallationFinished);
- packageInstaller()->installPackage(deviceConfiguration(), remoteFilePath, true);
-}
-
-void AbstractUploadAndInstallPackageService::handleInstallationFinished(const QString &errorMsg)
-{
- QTC_ASSERT(d->state == Installing, return);
-
- if (errorMsg.isEmpty()) {
- saveDeploymentTimeStamp(DeployableFile(d->packageFilePath, QString()), QDateTime());
- emit progressMessage(tr("Package installed."));
- } else {
- emit errorMessage(errorMsg);
- }
- setFinished();
-}
-
-void AbstractUploadAndInstallPackageService::setFinished()
-{
- d->state = Inactive;
- disconnect(d->uploader, nullptr, this, nullptr);
- disconnect(packageInstaller(), nullptr, this, nullptr);
- handleDeploymentDone();
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/abstractuploadandinstallpackageservice.h b/src/plugins/remotelinux/abstractuploadandinstallpackageservice.h
deleted file mode 100644
index 1fedd8686af..00000000000
--- a/src/plugins/remotelinux/abstractuploadandinstallpackageservice.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "abstractremotelinuxdeployservice.h"
-#include "remotelinux_export.h"
-
-namespace RemoteLinux {
-class AbstractRemoteLinuxPackageInstaller;
-
-namespace Internal { class AbstractUploadAndInstallPackageServicePrivate; }
-
-class REMOTELINUX_EXPORT AbstractUploadAndInstallPackageService : public AbstractRemoteLinuxDeployService
-{
- Q_OBJECT
-
-public:
- void setPackageFilePath(const Utils::FilePath &filePath);
-
-protected:
- AbstractUploadAndInstallPackageService();
- ~AbstractUploadAndInstallPackageService() override;
-
-private:
- void handleUploadFinished(const QString &errorMsg);
- void handleInstallationFinished(const QString &errorMsg);
-
- virtual AbstractRemoteLinuxPackageInstaller *packageInstaller() const = 0;
- virtual QString uploadDir() const; // Defaults to remote user's home directory.
-
- bool isDeploymentNecessary() const override;
- void doDeviceSetup() override;
- void stopDeviceSetup() override;
- void doDeploy() override;
- void stopDeployment() override;
-
- void setFinished();
-
- Internal::AbstractUploadAndInstallPackageServicePrivate * const d;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/customcommanddeploystep.cpp b/src/plugins/remotelinux/customcommanddeploystep.cpp
new file mode 100644
index 00000000000..1e11a1b779c
--- /dev/null
+++ b/src/plugins/remotelinux/customcommanddeploystep.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "customcommanddeploystep.h"
+
+#include "abstractremotelinuxdeployservice.h"
+#include "abstractremotelinuxdeploystep.h"
+#include "remotelinux_constants.h"
+
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/runconfigurationaspects.h>
+
+#include <utils/qtcprocess.h>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace RemoteLinux {
+namespace Internal {
+
+class CustomCommandDeployService : public AbstractRemoteLinuxDeployService
+{
+ Q_DECLARE_TR_FUNCTIONS(RemoteLinux::Internal::CustomCommandDeployService)
+
+public:
+ CustomCommandDeployService();
+
+ void setCommandLine(const QString &commandLine);
+
+ bool isDeploymentNecessary() const override { return true; }
+ CheckResult isDeploymentPossible() const override;
+
+protected:
+ void doDeploy() override;
+ void stopDeployment() override;
+
+ QString m_commandLine;
+ QtcProcess m_process;
+};
+
+CustomCommandDeployService::CustomCommandDeployService()
+{
+ connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
+ emit stdOutData(QString::fromUtf8(m_process.readAllStandardOutput()));
+ });
+ connect(&m_process, &QtcProcess::readyReadStandardError, this, [this] {
+ emit stdErrData(QString::fromUtf8(m_process.readAllStandardError()));
+ });
+ connect(&m_process, &QtcProcess::done, this, [this] {
+ if (m_process.error() != QProcess::UnknownError
+ || m_process.exitStatus() != QProcess::NormalExit) {
+ emit errorMessage(tr("Remote process failed: %1").arg(m_process.errorString()));
+ } else if (m_process.exitCode() != 0) {
+ emit errorMessage(tr("Remote process finished with exit code %1.")
+ .arg(m_process.exitCode()));
+ } else {
+ emit progressMessage(tr("Remote command finished successfully."));
+ }
+ stopDeployment();
+ });
+}
+
+void CustomCommandDeployService::setCommandLine(const QString &commandLine)
+{
+ m_commandLine = commandLine;
+}
+
+CheckResult CustomCommandDeployService::isDeploymentPossible() const
+{
+ if (m_commandLine.isEmpty())
+ return CheckResult::failure(tr("No command line given."));
+
+ return AbstractRemoteLinuxDeployService::isDeploymentPossible();
+}
+
+void CustomCommandDeployService::doDeploy()
+{
+ emit progressMessage(tr("Starting remote command \"%1\"...").arg(m_commandLine));
+ m_process.setCommand({deviceConfiguration()->filePath("/bin/sh"),
+ {"-c", m_commandLine}});
+ m_process.start();
+}
+
+void CustomCommandDeployService::stopDeployment()
+{
+ m_process.close();
+ handleDeploymentDone();
+}
+
+class CustomCommandDeployStep : public AbstractRemoteLinuxDeployStep
+{
+ Q_DECLARE_TR_FUNCTIONS(RemoteLinux::Internal::CustomCommandDeployStep)
+
+public:
+ CustomCommandDeployStep(BuildStepList *bsl, Id id)
+ : AbstractRemoteLinuxDeployStep(bsl, id)
+ {
+ auto service = createDeployService<CustomCommandDeployService>();
+
+ auto commandLine = addAspect<StringAspect>();
+ commandLine->setSettingsKey("RemoteLinuxCustomCommandDeploymentStep.CommandLine");
+ commandLine->setLabelText(tr("Command line:"));
+ commandLine->setDisplayStyle(StringAspect::LineEditDisplay);
+ commandLine->setHistoryCompleter("RemoteLinuxCustomCommandDeploymentStep.History");
+
+ setInternalInitializer([service, commandLine] {
+ service->setCommandLine(commandLine->value().trimmed());
+ return service->isDeploymentPossible();
+ });
+
+ addMacroExpander();
+ }
+};
+
+
+// CustomCommandDeployStepFactory
+
+CustomCommandDeployStepFactory::CustomCommandDeployStepFactory()
+{
+ registerStep<CustomCommandDeployStep>(Constants::CustomCommandDeployStepId);
+ setDisplayName(CustomCommandDeployStep::tr("Run custom remote command"));
+ setSupportedConfiguration(RemoteLinux::Constants::DeployToGenericLinux);
+ setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY);
+}
+
+} // Internal
+} // RemoteLinux
diff --git a/src/plugins/remotelinux/customcommanddeploystep.h b/src/plugins/remotelinux/customcommanddeploystep.h
new file mode 100644
index 00000000000..09b6aaceafc
--- /dev/null
+++ b/src/plugins/remotelinux/customcommanddeploystep.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectexplorer/buildstep.h>
+
+namespace RemoteLinux {
+namespace Internal {
+
+class CustomCommandDeployStepFactory : public ProjectExplorer::BuildStepFactory
+{
+public:
+ CustomCommandDeployStepFactory();
+};
+
+} // Internal
+} // RemoteLinux
diff --git a/src/plugins/remotelinux/deploymenttimeinfo.cpp b/src/plugins/remotelinux/deploymenttimeinfo.cpp
index eef2b77cf4b..3dde7d5d2af 100644
--- a/src/plugins/remotelinux/deploymenttimeinfo.cpp
+++ b/src/plugins/remotelinux/deploymenttimeinfo.cpp
@@ -26,17 +26,15 @@
#include "deploymenttimeinfo.h"
#include <projectexplorer/deployablefile.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshconnectionmanager.h>
-
#include <QDateTime>
using namespace ProjectExplorer;
using namespace Utils;
-using namespace QSsh;
namespace RemoteLinux {
diff --git a/src/plugins/remotelinux/deploymenttimeinfo.h b/src/plugins/remotelinux/deploymenttimeinfo.h
index 3c91be74c7f..202d97aebbe 100644
--- a/src/plugins/remotelinux/deploymenttimeinfo.h
+++ b/src/plugins/remotelinux/deploymenttimeinfo.h
@@ -26,7 +26,10 @@
#pragma once
#include <QVariantMap>
-#include <projectexplorer/devicesupport/idevice.h>
+
+QT_BEGIN_NAMESPACE
+class QDateTime;
+QT_END_NAMESPACE
namespace ProjectExplorer {
class DeployableFile;
diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp
index 58680b6a859..37b7b0da8ab 100644
--- a/src/plugins/remotelinux/filesystemaccess_test.cpp
+++ b/src/plugins/remotelinux/filesystemaccess_test.cpp
@@ -26,14 +26,20 @@
#include "filesystemaccess_test.h"
#include "linuxdevice.h"
-#include "remotelinux_constants.h"
#include <projectexplorer/devicesupport/devicemanager.h>
-#include <ssh/sshconnection.h>
+#include <projectexplorer/devicesupport/filetransfer.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <utils/filepath.h>
+#include <utils/processinterface.h>
#include <QDebug>
+#include <QFile>
+#include <QRandomGenerator>
#include <QTest>
+#include <QTimer>
+
+Q_DECLARE_METATYPE(ProjectExplorer::FileTransferMethod)
using namespace ProjectExplorer;
using namespace Utils;
@@ -45,44 +51,44 @@ static const char TEST_DIR[] = "/tmp/testdir";
static const FilePath baseFilePath()
{
- return FilePath::fromString("ssh://" + QSsh::SshTest::userAtHost() + QString(TEST_DIR));
+ return FilePath::fromString("ssh://" + SshTest::userAtHost() + QString(TEST_DIR));
}
TestLinuxDeviceFactory::TestLinuxDeviceFactory()
: IDeviceFactory("test")
{
- setDisplayName("Generic Linux Device");
+ setDisplayName("Remote Linux Device");
setIcon(QIcon());
setConstructionFunction(&LinuxDevice::create);
setCreator([] {
- LinuxDevice::Ptr newDev = LinuxDevice::create();
- newDev->setType("test");
- qDebug() << "device : " << newDev->type();
- QSsh::SshConnectionParameters sshParams = QSsh::SshTest::getParameters();
- newDev->setSshParameters(sshParams);
- return newDev;
+ LinuxDevice::Ptr device = LinuxDevice::create();
+ device->setupId(IDevice::ManuallyAdded);
+ device->setType("test");
+ qDebug() << "device : " << device->type();
+ device->setSshParameters(SshTest::getParameters());
+ return device;
});
}
FilePath createFile(const QString &name)
{
FilePath testFilePath = baseFilePath() / name;
- FilePath dummyFilePath = FilePath::fromString("ssh://" + QSsh::SshTest::userAtHost() + "/dev/null");
+ FilePath dummyFilePath = FilePath::fromString("ssh://" + SshTest::userAtHost() + "/dev/null");
dummyFilePath.copyFile(testFilePath);
return testFilePath;
}
void FileSystemAccessTest::initTestCase()
{
- const QSsh::SshConnectionParameters params = QSsh::SshTest::getParameters();
+ const SshParameters params = SshTest::getParameters();
qDebug() << "Using following SSH parameter:"
<< "\nHost:" << params.host()
<< "\nPort:" << params.port()
<< "\nUser:" << params.userName()
<< "\nSSHKey:" << params.privateKeyFile;
- if (!QSsh::SshTest::checkParameters(params)) {
+ if (!SshTest::checkParameters(params)) {
m_skippedAtWhole = true;
- QSsh::SshTest::printSetupHelp();
+ SshTest::printSetupHelp();
QSKIP("Ensure you have added your default ssh public key to your own authorized keys and "
"environment QTC_REMOTELINUX_SSH_DEFAULTS set or follow setup help above.");
return;
@@ -90,10 +96,12 @@ void FileSystemAccessTest::initTestCase()
FilePath filePath = baseFilePath();
if (DeviceManager::deviceForPath(filePath) == nullptr) {
- DeviceManager *const devMgr = DeviceManager::instance();
- const IDevice::Ptr newDev = m_testLinuxDeviceFactory.create();
- QVERIFY(!newDev.isNull());
- devMgr->addDevice(newDev);
+ const IDevice::Ptr device = m_testLinuxDeviceFactory.create();
+ QVERIFY(!device.isNull());
+ DeviceManager *deviceManager = DeviceManager::instance();
+ deviceManager->addDevice(device);
+ m_device = deviceManager->find(device->id());
+ QVERIFY(m_device);
}
if (filePath.exists()) // Do initial cleanup after possible leftovers from previously failed test
QVERIFY(filePath.removeRecursively());
@@ -175,7 +183,7 @@ void FileSystemAccessTest::testDirStatus()
void FileSystemAccessTest::testBytesAvailable()
{
- FilePath testFilePath = FilePath::fromString("ssh://" + QSsh::SshTest::userAtHost() + "/tmp");
+ FilePath testFilePath = FilePath::fromString("ssh://" + SshTest::userAtHost() + "/tmp");
QVERIFY(testFilePath.exists());
QVERIFY(testFilePath.bytesAvailable() > 0);
}
@@ -210,5 +218,83 @@ void FileSystemAccessTest::testFileActions()
QVERIFY(!newTestFilePath.exists());
}
+void FileSystemAccessTest::testFileTransfer_data()
+{
+ QTest::addColumn<FileTransferMethod>("fileTransferMethod");
+
+ QTest::addRow("Sftp") << FileTransferMethod::Sftp;
+// QTest::addRow("Rsync") << FileTransferMethod::Rsync;
+}
+
+void FileSystemAccessTest::testFileTransfer()
+{
+ QFETCH(FileTransferMethod, fileTransferMethod);
+
+ FileTransfer fileTransfer;
+ fileTransfer.setTransferMethod(fileTransferMethod);
+
+ // Create and upload 1000 small files and one big file
+ QTemporaryDir dirForFilesToUpload;
+ QTemporaryDir dirForFilesToDownload;
+ QTemporaryDir dir2ForFilesToDownload;
+ QVERIFY2(dirForFilesToUpload.isValid(), qPrintable(dirForFilesToUpload.errorString()));
+ QVERIFY2(dirForFilesToDownload.isValid(), qPrintable(dirForFilesToDownload.errorString()));
+ QVERIFY2(dir2ForFilesToDownload.isValid(), qPrintable(dirForFilesToDownload.errorString()));
+ static const auto getRemoteFilePath = [this](const QString &localFileName) {
+ return m_device->filePath(QString("/tmp/").append(localFileName).append(".upload"));
+ };
+ FilesToTransfer filesToUpload;
+ std::srand(QDateTime::currentDateTime().toSecsSinceEpoch());
+ for (int i = 0; i < 100; ++i) {
+ const QString fileName = "testFile" + QString::number(i + 1);
+ QFile file(dirForFilesToUpload.path() + '/' + fileName);
+ QVERIFY2(file.open(QIODevice::WriteOnly), qPrintable(file.errorString()));
+ int content[1024 / sizeof(int)];
+ for (size_t j = 0; j < sizeof content / sizeof content[0]; ++j)
+ content[j] = QRandomGenerator::global()->generate();
+ file.write(reinterpret_cast<char *>(content), sizeof content);
+ file.close();
+ QVERIFY2(file.error() == QFile::NoError, qPrintable(file.errorString()));
+ filesToUpload << FileToTransfer{FilePath::fromString(file.fileName()),
+ getRemoteFilePath(fileName)};
+ }
+
+ const QString bigFileName("bigFile");
+ QFile bigFile(dirForFilesToUpload.path() + '/' + bigFileName);
+ QVERIFY2(bigFile.open(QIODevice::WriteOnly), qPrintable(bigFile.errorString()));
+ const int bigFileSize = 100 * 1024 * 1024;
+ const int blockSize = 8192;
+ const int blockCount = bigFileSize / blockSize;
+ for (int block = 0; block < blockCount; ++block) {
+ int content[blockSize / sizeof(int)];
+ for (size_t j = 0; j < sizeof content / sizeof content[0]; ++j)
+ content[j] = QRandomGenerator::global()->generate();
+ bigFile.write(reinterpret_cast<char *>(content), sizeof content);
+ }
+ bigFile.close();
+ QVERIFY2(bigFile.error() == QFile::NoError, qPrintable(bigFile.errorString()));
+ filesToUpload << FileToTransfer{FilePath::fromString(bigFile.fileName()),
+ getRemoteFilePath(bigFileName)};
+ fileTransfer.setFilesToTransfer(filesToUpload);
+
+ QString jobError;
+ QEventLoop loop;
+ connect(&fileTransfer, &FileTransfer::done, [&jobError, &loop]
+ (const ProcessResultData &resultData) {
+ jobError = resultData.m_errorString;
+ loop.quit();
+ });
+ QTimer timer;
+ QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
+ timer.setSingleShot(true);
+ timer.setInterval(30 * 1000);
+ timer.start();
+ fileTransfer.start();
+ loop.exec();
+ QVERIFY(timer.isActive());
+ timer.stop();
+ QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
+}
+
} // Internal
} // RemoteLinux
diff --git a/src/plugins/remotelinux/filesystemaccess_test.h b/src/plugins/remotelinux/filesystemaccess_test.h
index c0a2d9aefb1..652a9ee4528 100644
--- a/src/plugins/remotelinux/filesystemaccess_test.h
+++ b/src/plugins/remotelinux/filesystemaccess_test.h
@@ -25,11 +25,8 @@
#pragma once
-#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/idevicefactory.h>
-#include <utils/fileutils.h>
-
namespace RemoteLinux {
namespace Internal {
@@ -51,12 +48,15 @@ private slots:
void testDirStatus();
void testBytesAvailable();
void testFileActions();
+ void testFileTransfer_data();
+ void testFileTransfer();
void cleanupTestCase();
private:
TestLinuxDeviceFactory m_testLinuxDeviceFactory;
bool m_skippedAtWhole = false;
+ ProjectExplorer::IDeviceConstPtr m_device;
};
} // Internal
diff --git a/src/plugins/remotelinux/genericdirectuploadservice.cpp b/src/plugins/remotelinux/genericdirectuploadservice.cpp
index ecbac0498c6..6842eb43311 100644
--- a/src/plugins/remotelinux/genericdirectuploadservice.cpp
+++ b/src/plugins/remotelinux/genericdirectuploadservice.cpp
@@ -26,12 +26,12 @@
#include "genericdirectuploadservice.h"
#include <projectexplorer/deployablefile.h>
+#include <projectexplorer/devicesupport/filetransfer.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <utils/hostosinfo.h>
+#include <utils/processinterface.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <ssh/sftptransfer.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshremoteprocess.h>
#include <QDateTime>
#include <QDir>
@@ -42,7 +42,6 @@
#include <QString>
using namespace ProjectExplorer;
-using namespace QSsh;
using namespace Utils;
namespace RemoteLinux {
@@ -55,7 +54,7 @@ const int MaxConcurrentStatCalls = 10;
class GenericDirectUploadServicePrivate
{
public:
- DeployableFile getFileForProcess(SshRemoteProcess *proc)
+ DeployableFile getFileForProcess(QtcProcess *proc)
{
const auto it = remoteProcs.find(proc);
QTC_ASSERT(it != remoteProcs.end(), return DeployableFile());
@@ -66,11 +65,11 @@ public:
IncrementalDeployment incremental = IncrementalDeployment::NotSupported;
bool ignoreMissingFiles = false;
- QHash<SshRemoteProcess *, DeployableFile> remoteProcs;
+ QHash<QtcProcess *, DeployableFile> remoteProcs;
QQueue<DeployableFile> filesToStat;
State state = Inactive;
QList<DeployableFile> filesToUpload;
- SftpTransferPtr uploader;
+ FileTransfer uploader;
QList<DeployableFile> deployableFiles;
};
@@ -81,6 +80,20 @@ using namespace Internal;
GenericDirectUploadService::GenericDirectUploadService(QObject *parent)
: AbstractRemoteLinuxDeployService(parent), d(new GenericDirectUploadServicePrivate)
{
+ connect(&d->uploader, &FileTransfer::done, this, [this](const ProcessResultData &result) {
+ QTC_ASSERT(d->state == Uploading, return);
+ if (result.m_error != QProcess::UnknownError) {
+ emit errorMessage(result.m_errorString);
+ setFinished();
+ handleDeploymentDone();
+ return;
+ }
+ d->state = PostProcessing;
+ chmod();
+ queryFiles();
+ });
+ connect(&d->uploader, &FileTransfer::progress,
+ this, &GenericDirectUploadService::progressMessage);
}
GenericDirectUploadService::~GenericDirectUploadService()
@@ -115,18 +128,6 @@ bool GenericDirectUploadService::isDeploymentNecessary() const
return !d->deployableFiles.isEmpty();
}
-void GenericDirectUploadService::doDeviceSetup()
-{
- QTC_ASSERT(d->state == Inactive, return);
- AbstractRemoteLinuxDeployService::doDeviceSetup();
-}
-
-void GenericDirectUploadService::stopDeviceSetup()
-{
- QTC_ASSERT(d->state == Inactive, return);
- AbstractRemoteLinuxDeployService::stopDeviceSetup();
-}
-
void GenericDirectUploadService::doDeploy()
{
QTC_ASSERT(d->state == Inactive, setFinished(); return);
@@ -135,21 +136,27 @@ void GenericDirectUploadService::doDeploy()
}
QDateTime GenericDirectUploadService::timestampFromStat(const DeployableFile &file,
- SshRemoteProcess *statProc,
- const QString &errorMsg)
+ QtcProcess *statProc)
{
- QString errorDetails;
- if (!errorMsg.isEmpty())
- errorDetails = errorMsg;
- else if (statProc->exitCode() != 0)
- errorDetails = QString::fromUtf8(statProc->readAllStandardError());
- if (!errorDetails.isEmpty()) {
+ bool succeeded = false;
+ QString error;
+ if (statProc->error() == QProcess::FailedToStart) {
+ error = tr("Failed to start \"stat\": %1").arg(statProc->errorString());
+ } else if (statProc->exitStatus() == QProcess::CrashExit) {
+ error = tr("\"stat\" crashed.");
+ } else if (statProc->exitCode() != 0) {
+ error = tr("\"stat\" failed with exit code %1: %2")
+ .arg(statProc->exitCode()).arg(statProc->cleanedStdErr());
+ } else {
+ succeeded = true;
+ }
+ if (!succeeded) {
emit warningMessage(tr("Failed to retrieve remote timestamp for file \"%1\". "
"Incremental deployment will not work. Error message was: %2")
- .arg(file.remoteFilePath(), errorDetails));
+ .arg(file.remoteFilePath(), error));
return QDateTime();
}
- QByteArray output = statProc->readAllStandardOutput().trimmed();
+ const QByteArray output = statProc->readAllStandardOutput().trimmed();
const QString warningString(tr("Unexpected stat output for remote file \"%1\": %2")
.arg(file.remoteFilePath()).arg(QString::fromUtf8(output)));
if (!output.startsWith(file.remoteFilePath().toUtf8())) {
@@ -197,15 +204,14 @@ void GenericDirectUploadService::stopDeployment()
void GenericDirectUploadService::runStat(const DeployableFile &file)
{
// We'd like to use --format=%Y, but it's not supported by busybox.
- const QString statCmd = "stat -t " + Utils::ProcessArgs::quoteArgUnix(file.remoteFilePath());
- SshRemoteProcess * const statProc = connection()->createRemoteProcess(statCmd).release();
- statProc->setParent(this);
- connect(statProc, &SshRemoteProcess::done, this,
- [this, statProc, state = d->state](const QString &errorMsg) {
+ QtcProcess * const statProc = new QtcProcess(this);
+ statProc->setCommand({deviceConfiguration()->filePath("stat"),
+ {"-t", Utils::ProcessArgs::quoteArgUnix(file.remoteFilePath())}});
+ connect(statProc, &QtcProcess::done, this, [this, statProc, state = d->state] {
QTC_ASSERT(d->state == state, return);
const DeployableFile file = d->getFileForProcess(statProc);
QTC_ASSERT(file.isValid(), return);
- const QDateTime timestamp = timestampFromStat(file, statProc, errorMsg);
+ const QDateTime timestamp = timestampFromStat(file, statProc);
statProc->deleteLater();
switch (state) {
case PreChecking:
@@ -252,11 +258,7 @@ void GenericDirectUploadService::setFinished()
it.key()->terminate();
}
d->remoteProcs.clear();
- if (d->uploader) {
- d->uploader->disconnect();
- d->uploader->stop();
- d->uploader.release()->deleteLater();
- }
+ d->uploader.stop();
d->filesToUpload.clear();
}
@@ -294,11 +296,11 @@ void GenericDirectUploadService::uploadFiles()
return;
}
emit progressMessage(tr("%n file(s) need to be uploaded.", "", d->filesToUpload.size()));
- FilesToTransfer filesToTransfer;
- for (const DeployableFile &f : qAsConst(d->filesToUpload)) {
- if (!f.localFilePath().exists()) {
+ FilesToTransfer files;
+ for (const DeployableFile &file : qAsConst(d->filesToUpload)) {
+ if (!file.localFilePath().exists()) {
const QString message = tr("Local file \"%1\" does not exist.")
- .arg(f.localFilePath().toUserOutput());
+ .arg(file.localFilePath().toUserOutput());
if (d->ignoreMissingFiles) {
emit warningMessage(message);
continue;
@@ -309,24 +311,12 @@ void GenericDirectUploadService::uploadFiles()
return;
}
}
- filesToTransfer << FileToTransfer(f.localFilePath().toString(), f.remoteFilePath());
+ files.append({file.localFilePath(),
+ deviceConfiguration()->filePath(file.remoteFilePath())});
}
- d->uploader = connection()->createUpload(filesToTransfer, FileTransferErrorHandling::Abort);
- connect(d->uploader.get(), &SftpTransfer::done, [this](const QString &error) {
- QTC_ASSERT(d->state == Uploading, return);
- if (!error.isEmpty()) {
- emit errorMessage(error);
- setFinished();
- handleDeploymentDone();
- return;
- }
- d->state = PostProcessing;
- chmod();
- queryFiles();
- });
- connect(d->uploader.get(), &SftpTransfer::progress,
- this, &GenericDirectUploadService::progressMessage);
- d->uploader->start();
+
+ d->uploader.setFilesToTransfer(files);
+ d->uploader.start();
}
void GenericDirectUploadService::chmod()
@@ -337,16 +327,14 @@ void GenericDirectUploadService::chmod()
for (const DeployableFile &f : qAsConst(d->filesToUpload)) {
if (!f.isExecutable())
continue;
- const QString command = QLatin1String("chmod a+x ")
- + Utils::ProcessArgs::quoteArgUnix(f.remoteFilePath());
- SshRemoteProcess * const chmodProc
- = connection()->createRemoteProcess(command).release();
- chmodProc->setParent(this);
- connect(chmodProc, &SshRemoteProcess::done, this,
- [this, chmodProc, state = d->state](const QString &error) {
+ QtcProcess * const chmodProc = new QtcProcess(this);
+ chmodProc->setCommand({deviceConfiguration()->filePath("chmod"),
+ {"a+x", Utils::ProcessArgs::quoteArgUnix(f.remoteFilePath())}});
+ connect(chmodProc, &QtcProcess::done, this, [this, chmodProc, state = d->state] {
QTC_ASSERT(state == d->state, return);
const DeployableFile file = d->getFileForProcess(chmodProc);
QTC_ASSERT(file.isValid(), return);
+ const QString error = chmodProc->errorString();
if (!error.isEmpty()) {
emit warningMessage(tr("Remote chmod failed for file \"%1\": %2")
.arg(file.remoteFilePath(), error));
diff --git a/src/plugins/remotelinux/genericdirectuploadservice.h b/src/plugins/remotelinux/genericdirectuploadservice.h
index 998a8275527..a426481f1f1 100644
--- a/src/plugins/remotelinux/genericdirectuploadservice.h
+++ b/src/plugins/remotelinux/genericdirectuploadservice.h
@@ -25,18 +25,20 @@
#pragma once
-#include "abstractremotelinuxdeployservice.h"
#include "remotelinux_export.h"
-#include <ssh/sftpdefs.h>
+#include "abstractremotelinuxdeployservice.h"
#include <QList>
-QT_FORWARD_DECLARE_CLASS(QDateTime)
-QT_FORWARD_DECLARE_CLASS(QString)
+QT_BEGIN_NAMESPACE
+class QDateTime;
+class QString;
+QT_END_NAMESPACE
namespace ProjectExplorer { class DeployableFile; }
-namespace QSsh { class SshRemoteProcess; }
+namespace Utils { class QtcProcess; }
+
namespace RemoteLinux {
namespace Internal { class GenericDirectUploadServicePrivate; }
@@ -56,16 +58,13 @@ public:
protected:
bool isDeploymentNecessary() const override;
- void doDeviceSetup() override;
- void stopDeviceSetup() override;
-
void doDeploy() override;
void stopDeployment() override;
private:
void runStat(const ProjectExplorer::DeployableFile &file);
QDateTime timestampFromStat(const ProjectExplorer::DeployableFile &file,
- QSsh::SshRemoteProcess *statProc, const QString &errorMsg);
+ Utils::QtcProcess *statProc);
void checkForStateChangeOnRemoteProcFinished();
QList<ProjectExplorer::DeployableFile> collectFilesToUpload(
diff --git a/src/plugins/remotelinux/genericdirectuploadstep.h b/src/plugins/remotelinux/genericdirectuploadstep.h
index ef5e429fb8c..595d74c8547 100644
--- a/src/plugins/remotelinux/genericdirectuploadstep.h
+++ b/src/plugins/remotelinux/genericdirectuploadstep.h
@@ -25,9 +25,10 @@
#pragma once
-#include "abstractremotelinuxdeploystep.h"
#include "remotelinux_export.h"
+#include "abstractremotelinuxdeploystep.h"
+
namespace RemoteLinux {
class REMOTELINUX_EXPORT GenericDirectUploadStep : public AbstractRemoteLinuxDeployStep
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
index 7187799790f..7c5d09faddb 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
@@ -26,16 +26,17 @@
#include "genericlinuxdeviceconfigurationwidget.h"
#include "ui_genericlinuxdeviceconfigurationwidget.h"
+#include "sshkeycreationdialog.h"
+
#include <coreplugin/coreconstants.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <utils/portlist.h>
#include <utils/fancylineedit.h>
#include <utils/utilsicons.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshkeycreationdialog.h>
using namespace ProjectExplorer;
using namespace RemoteLinux;
-using namespace QSsh;
using namespace Utils;
GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget(
@@ -82,11 +83,11 @@ GenericLinuxDeviceConfigurationWidget::~GenericLinuxDeviceConfigurationWidget()
void GenericLinuxDeviceConfigurationWidget::authenticationTypeChanged()
{
- SshConnectionParameters sshParams = device()->sshParameters();
+ SshParameters sshParams = device()->sshParameters();
const bool useKeyFile = m_ui->keyButton->isChecked();
sshParams.authenticationType = useKeyFile
- ? SshConnectionParameters::AuthenticationTypeSpecificKey
- : SshConnectionParameters::AuthenticationTypeAll;
+ ? SshParameters::AuthenticationTypeSpecificKey
+ : SshParameters::AuthenticationTypeAll;
device()->setSshParameters(sshParams);
m_ui->keyFileLineEdit->setEnabled(useKeyFile);
m_ui->keyLabel->setEnabled(useKeyFile);
@@ -94,42 +95,42 @@ void GenericLinuxDeviceConfigurationWidget::authenticationTypeChanged()
void GenericLinuxDeviceConfigurationWidget::hostNameEditingFinished()
{
- SshConnectionParameters sshParams = device()->sshParameters();
+ SshParameters sshParams = device()->sshParameters();
sshParams.setHost(m_ui->hostLineEdit->text().trimmed());
device()->setSshParameters(sshParams);
}
void GenericLinuxDeviceConfigurationWidget::sshPortEditingFinished()
{
- SshConnectionParameters sshParams = device()->sshParameters();
+ SshParameters sshParams = device()->sshParameters();
sshParams.setPort(m_ui->sshPortSpinBox->value());
device()->setSshParameters(sshParams);
}
void GenericLinuxDeviceConfigurationWidget::timeoutEditingFinished()
{
- SshConnectionParameters sshParams = device()->sshParameters();
+ SshParameters sshParams = device()->sshParameters();
sshParams.timeout = m_ui->timeoutSpinBox->value();
device()->setSshParameters(sshParams);
}
void GenericLinuxDeviceConfigurationWidget::userNameEditingFinished()
{
- SshConnectionParameters sshParams = device()->sshParameters();
+ SshParameters sshParams = device()->sshParameters();
sshParams.setUserName(m_ui->userLineEdit->text());
device()->setSshParameters(sshParams);
}
void GenericLinuxDeviceConfigurationWidget::keyFileEditingFinished()
{
- SshConnectionParameters sshParams = device()->sshParameters();
+ SshParameters sshParams = device()->sshParameters();
sshParams.privateKeyFile = m_ui->keyFileLineEdit->filePath();
device()->setSshParameters(sshParams);
}
void GenericLinuxDeviceConfigurationWidget::gdbServerEditingFinished()
{
- device()->setDebugServerPath(FilePath::fromString(m_ui->gdbServerLineEdit->text()));
+ device()->setDebugServerPath(device()->filePath(m_ui->gdbServerLineEdit->text()));
}
void GenericLinuxDeviceConfigurationWidget::handleFreePortsChanged()
@@ -153,7 +154,7 @@ void GenericLinuxDeviceConfigurationWidget::createNewKey()
void GenericLinuxDeviceConfigurationWidget::hostKeyCheckingChanged(bool doCheck)
{
- SshConnectionParameters sshParams = device()->sshParameters();
+ SshParameters sshParams = device()->sshParameters();
sshParams.hostKeyCheckingMode
= doCheck ? SshHostKeyCheckingAllowNoMatch : SshHostKeyCheckingNone;
device()->setSshParameters(sshParams);
@@ -191,13 +192,13 @@ void GenericLinuxDeviceConfigurationWidget::initGui()
= new QRegularExpressionValidator(QRegularExpression(PortList::regularExpression()), this);
m_ui->portsLineEdit->setValidator(portsValidator);
- const SshConnectionParameters &sshParams = device()->sshParameters();
+ const SshParameters &sshParams = device()->sshParameters();
switch (sshParams.authenticationType) {
- case SshConnectionParameters::AuthenticationTypeSpecificKey:
+ case SshParameters::AuthenticationTypeSpecificKey:
m_ui->keyButton->setChecked(true);
break;
- case SshConnectionParameters::AuthenticationTypeAll:
+ case SshParameters::AuthenticationTypeAll:
m_ui->defaultAuthButton->setChecked(true);
break;
}
@@ -212,6 +213,7 @@ void GenericLinuxDeviceConfigurationWidget::initGui()
m_ui->timeoutSpinBox->setValue(sshParams.timeout);
m_ui->userLineEdit->setText(sshParams.userName());
m_ui->keyFileLineEdit->setFilePath(sshParams.privateKeyFile);
- m_ui->gdbServerLineEdit->setText(device()->debugServerPath().toString());
+ // FIXME: Use a remote executable line edit
+ m_ui->gdbServerLineEdit->setText(device()->debugServerPath().path());
updatePortsWarningLabel();
}
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
index 20c8b2aecbf..241347aa1bd 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
@@ -25,9 +25,11 @@
#pragma once
+#include "remotelinux_export.h"
+
#include <projectexplorer/devicesupport/idevicewidget.h>
-#include "remotelinux_export.h"
+namespace Utils { class FilePath; }
namespace RemoteLinux {
@@ -40,7 +42,7 @@ class REMOTELINUX_EXPORT GenericLinuxDeviceConfigurationWidget
public:
explicit GenericLinuxDeviceConfigurationWidget(
- const ProjectExplorer::IDevice::Ptr &deviceConfig);
+ const ProjectExplorer::IDevicePtr &deviceConfig);
~GenericLinuxDeviceConfigurationWidget() override;
private:
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
index 63596622e82..f17d786b91b 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
@@ -29,11 +29,12 @@
#include "linuxdevice.h"
#include "remotelinux_constants.h"
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
#include <utils/portlist.h>
#include <utils/fileutils.h>
using namespace ProjectExplorer;
-using namespace QSsh;
namespace RemoteLinux {
namespace Internal {
@@ -58,7 +59,7 @@ GenericLinuxDeviceConfigurationWizard::GenericLinuxDeviceConfigurationWizard(QWi
: Utils::Wizard(parent),
d(new Internal::GenericLinuxDeviceConfigurationWizardPrivate(this))
{
- setWindowTitle(tr("New Generic Linux Device Configuration Setup"));
+ setWindowTitle(tr("New Remote Linux Device Configuration Setup"));
setPage(Internal::SetupPageId, &d->setupPage);
setPage(Internal::KeyDeploymentPageId, &d->keyDeploymentPage);
setPage(Internal::FinalPageId, &d->finalPage);
@@ -68,7 +69,7 @@ GenericLinuxDeviceConfigurationWizard::GenericLinuxDeviceConfigurationWizard(QWi
d->device->setType(Constants::GenericLinuxOsType);
d->device->setMachineType(IDevice::Hardware);
d->device->setFreePorts(Utils::PortList::fromString(QLatin1String("10000-10100")));
- SshConnectionParameters sshParams;
+ SshParameters sshParams;
sshParams.timeout = 10;
d->device->setSshParameters(sshParams);
d->setupPage.setDevice(d->device);
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h
index ff69a68113e..03d02380eb3 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h
@@ -27,7 +27,7 @@
#include "remotelinux_export.h"
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
#include <utils/wizard.h>
namespace RemoteLinux {
@@ -41,7 +41,7 @@ public:
GenericLinuxDeviceConfigurationWizard(QWidget *parent = nullptr);
~GenericLinuxDeviceConfigurationWizard() override;
- ProjectExplorer::IDevice::Ptr device();
+ ProjectExplorer::IDevicePtr device();
private:
Internal::GenericLinuxDeviceConfigurationWizardPrivate * const d;
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp
index e069892ca0d..60663cb3c0f 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp
@@ -27,11 +27,13 @@
#include "ui_genericlinuxdeviceconfigurationwizardsetuppage.h"
#include "publickeydeploymentdialog.h"
+#include "sshkeycreationdialog.h"
-#include <projectexplorer/devicesupport/idevice.h>
-#include <ssh/sshkeycreationdialog.h>
-#include <utils/utilsicons.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
+
+#include <utils/fileutils.h>
#include <utils/pathchooser.h>
+#include <utils/utilsicons.h>
#include <QHBoxLayout>
#include <QLabel>
@@ -39,6 +41,9 @@
#include <QStringList>
#include <QVBoxLayout>
+using namespace ProjectExplorer;
+using namespace Utils;
+
namespace RemoteLinux {
namespace Internal {
@@ -57,9 +62,6 @@ public:
} // namespace Internal
-using namespace QSsh;
-using namespace Utils;
-
GenericLinuxDeviceConfigurationWizardSetupPage::GenericLinuxDeviceConfigurationWizardSetupPage(
QWidget *parent) :
QWizardPage(parent), d(new Internal::GenericLinuxDeviceConfigurationWizardSetupPagePrivate)
@@ -94,7 +96,7 @@ bool GenericLinuxDeviceConfigurationWizardSetupPage::isComplete() const
bool GenericLinuxDeviceConfigurationWizardSetupPage::validatePage()
{
d->device->setDisplayName(configurationName());
- SshConnectionParameters sshParams = d->device->sshParameters();
+ SshParameters sshParams = d->device->sshParameters();
sshParams.url = url();
d->device->setSshParameters(sshParams);
return true;
@@ -232,8 +234,8 @@ bool GenericLinuxDeviceConfigurationWizardKeyDeploymentPage::isComplete() const
bool GenericLinuxDeviceConfigurationWizardKeyDeploymentPage::validatePage()
{
if (!d->defaultKeys().contains(d->keyFileChooser.filePath())) {
- SshConnectionParameters sshParams = d->device->sshParameters();
- sshParams.authenticationType = SshConnectionParameters::AuthenticationTypeSpecificKey;
+ SshParameters sshParams = d->device->sshParameters();
+ sshParams.authenticationType = SshParameters::AuthenticationTypeSpecificKey;
sshParams.privateKeyFile = d->keyFileChooser.filePath();
d->device->setSshParameters(sshParams);
}
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.h
index 2b8c6f641f5..2fa8e0d01cf 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.h
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.h
@@ -25,10 +25,9 @@
#pragma once
-#include "linuxdevice.h"
#include "remotelinux_export.h"
-#include <ssh/sshconnection.h>
+#include "linuxdevice.h"
#include <QWizardPage>
diff --git a/src/plugins/remotelinux/killappstep.cpp b/src/plugins/remotelinux/killappstep.cpp
new file mode 100644
index 00000000000..03d40e31666
--- /dev/null
+++ b/src/plugins/remotelinux/killappstep.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "killappstep.h"
+
+#include "abstractremotelinuxdeployservice.h"
+#include "remotelinux_constants.h"
+
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/runcontrol.h>
+#include <projectexplorer/target.h>
+#include <utils/qtcassert.h>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace RemoteLinux {
+namespace Internal {
+
+class KillAppService : public AbstractRemoteLinuxDeployService
+{
+ Q_OBJECT
+public:
+ ~KillAppService() override;
+
+ void setRemoteExecutable(const QString &filePath);
+
+private:
+ void handleStdErr();
+ void handleProcessFinished();
+
+ bool isDeploymentNecessary() const override;
+
+ void doDeploy() override;
+ void stopDeployment() override;
+
+ void handleSignalOpFinished(const QString &errorMessage);
+ void cleanup();
+ void finishDeployment();
+
+ QString m_remoteExecutable;
+ ProjectExplorer::DeviceProcessSignalOperation::Ptr m_signalOperation;
+};
+
+KillAppService::~KillAppService()
+{
+ cleanup();
+}
+
+void KillAppService::setRemoteExecutable(const QString &filePath)
+{
+ m_remoteExecutable = filePath;
+}
+
+bool KillAppService::isDeploymentNecessary() const
+{
+ return !m_remoteExecutable.isEmpty();
+}
+
+void KillAppService::doDeploy()
+{
+ m_signalOperation = deviceConfiguration()->signalOperation();
+ if (!m_signalOperation) {
+ handleDeploymentDone();
+ return;
+ }
+ connect(m_signalOperation.data(), &ProjectExplorer::DeviceProcessSignalOperation::finished,
+ this, &KillAppService::handleSignalOpFinished);
+ emit progressMessage(tr("Trying to kill \"%1\" on remote device...").arg(m_remoteExecutable));
+ m_signalOperation->killProcess(m_remoteExecutable);
+}
+
+void KillAppService::cleanup()
+{
+ if (m_signalOperation) {
+ disconnect(m_signalOperation.data(), nullptr, this, nullptr);
+ m_signalOperation.clear();
+ }
+}
+
+void KillAppService::finishDeployment()
+{
+ cleanup();
+ handleDeploymentDone();
+}
+
+void KillAppService::stopDeployment()
+{
+ finishDeployment();
+}
+
+void KillAppService::handleSignalOpFinished(const QString &errorMessage)
+{
+ if (errorMessage.isEmpty())
+ emit progressMessage(tr("Remote application killed."));
+ else
+ emit progressMessage(tr("Failed to kill remote application. Assuming it was not running."));
+ finishDeployment();
+}
+
+} // namespace Internal
+
+KillAppStep::KillAppStep(BuildStepList *bsl, Id id)
+ : AbstractRemoteLinuxDeployStep(bsl, id)
+{
+ auto service = createDeployService<Internal::KillAppService>();
+
+ setWidgetExpandedByDefault(false);
+
+ setInternalInitializer([this, service] {
+ Target * const theTarget = target();
+ QTC_ASSERT(theTarget, return CheckResult::failure());
+ RunConfiguration * const rc = theTarget->activeRunConfiguration();
+ const QString remoteExe = rc ? rc->runnable().command.executable().toString() : QString();
+ service->setRemoteExecutable(remoteExe);
+ return CheckResult::success();
+ });
+}
+
+Id KillAppStep::stepId()
+{
+ return Constants::KillAppStepId;
+}
+
+QString KillAppStep::displayName()
+{
+ return tr("Kill current application instance");
+}
+
+} // namespace RemoteLinux
+
+#include "killappstep.moc"
diff --git a/src/plugins/remotelinux/killappstep.h b/src/plugins/remotelinux/killappstep.h
new file mode 100644
index 00000000000..f26161e26ad
--- /dev/null
+++ b/src/plugins/remotelinux/killappstep.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "remotelinux_export.h"
+
+#include "abstractremotelinuxdeploystep.h"
+
+namespace RemoteLinux {
+
+class REMOTELINUX_EXPORT KillAppStep : public AbstractRemoteLinuxDeployStep
+{
+ Q_OBJECT
+public:
+ explicit KillAppStep(ProjectExplorer::BuildStepList *bsl,
+ Utils::Id id = stepId());
+
+ static Utils::Id stepId();
+ static QString displayName();
+};
+
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp
index 0d2f44f070c..0ec48a41fe9 100644
--- a/src/plugins/remotelinux/linuxdevice.cpp
+++ b/src/plugins/remotelinux/linuxdevice.cpp
@@ -27,28 +27,32 @@
#include "genericlinuxdeviceconfigurationwidget.h"
#include "genericlinuxdeviceconfigurationwizard.h"
-#include "linuxdeviceprocess.h"
#include "linuxdevicetester.h"
+#include "linuxprocessinterface.h"
#include "publickeydeploymentdialog.h"
#include "remotelinux_constants.h"
#include "remotelinuxsignaloperation.h"
#include "remotelinuxenvironmentreader.h"
+#include "sshprocessinterface.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
+#include <projectexplorer/devicesupport/filetransfer.h>
+#include <projectexplorer/devicesupport/filetransferinterface.h>
#include <projectexplorer/devicesupport/sshdeviceprocesslist.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
+#include <projectexplorer/devicesupport/sshsettings.h>
#include <projectexplorer/runcontrol.h>
-#include <ssh/sshconnectionmanager.h>
-#include <ssh/sshremoteprocessrunner.h>
-#include <ssh/sshsettings.h>
-
#include <utils/algorithm.h>
+#include <utils/deviceshell.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/port.h>
+#include <utils/processinfo.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <utils/temporaryfile.h>
@@ -56,14 +60,18 @@
#include <QLoggingCategory>
#include <QMutex>
#include <QRegularExpression>
+#include <QScopeGuard>
+#include <QTemporaryDir>
#include <QThread>
+#include <QTimer>
using namespace ProjectExplorer;
-using namespace QSsh;
using namespace Utils;
namespace RemoteLinux {
+const QByteArray s_pidMarker = "__qtc";
+
const char Delimiter0[] = "x--";
const char Delimiter1[] = "---";
@@ -73,6 +81,222 @@ static Q_LOGGING_CATEGORY(linuxDeviceLog, "qtc.remotelinux.device", QtWarningMsg
//#define DEBUG(x) LOG(x)
#define DEBUG(x)
+class SshSharedConnection : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit SshSharedConnection(const SshParameters &sshParameters, QObject *parent = nullptr);
+ ~SshSharedConnection() override;
+
+ SshParameters sshParameters() const { return m_sshParameters; }
+ void ref();
+ void deref();
+ void makeStale();
+
+ void connectToHost();
+ void disconnectFromHost();
+
+ QProcess::ProcessState state() const;
+ QString socketFilePath() const
+ {
+ QTC_ASSERT(m_masterSocketDir, return QString());
+ return m_masterSocketDir->path() + "/cs";
+ }
+
+signals:
+ void connected(const QString &socketFilePath);
+ void disconnected(const ProcessResultData &result);
+
+ void autoDestructRequested();
+
+private:
+ void emitConnected();
+ void emitError(QProcess::ProcessError processError, const QString &errorString);
+ void emitDisconnected();
+ QString fullProcessError() const;
+ QStringList connectionArgs(const FilePath &binary) const;
+
+ const SshParameters m_sshParameters;
+ std::unique_ptr<QtcProcess> m_masterProcess;
+ std::unique_ptr<QTemporaryDir> m_masterSocketDir;
+ QTimer m_timer;
+ int m_ref = 0;
+ bool m_stale = false;
+ QProcess::ProcessState m_state = QProcess::NotRunning;
+};
+
+SshSharedConnection::SshSharedConnection(const SshParameters &sshParameters, QObject *parent)
+ : QObject(parent), m_sshParameters(sshParameters)
+{
+}
+
+SshSharedConnection::~SshSharedConnection()
+{
+ QTC_CHECK(m_ref == 0);
+ disconnect();
+ disconnectFromHost();
+}
+
+void SshSharedConnection::ref()
+{
+ ++m_ref;
+ m_timer.stop();
+}
+
+void SshSharedConnection::deref()
+{
+ QTC_ASSERT(m_ref, return);
+ if (--m_ref)
+ return;
+ if (m_stale) // no one uses it
+ deleteLater();
+ // not stale, so someone may reuse it
+ m_timer.start(SshSettings::connectionSharingTimeout() * 1000 * 60);
+}
+
+void SshSharedConnection::makeStale()
+{
+ m_stale = true;
+ if (!m_ref) // no one uses it
+ deleteLater();
+}
+
+void SshSharedConnection::connectToHost()
+{
+ if (state() != QProcess::NotRunning)
+ return;
+
+ const FilePath sshBinary = SshSettings::sshFilePath();
+ if (!sshBinary.exists()) {
+ emitError(QProcess::FailedToStart, tr("Cannot establish SSH connection: ssh binary "
+ "\"%1\" does not exist.").arg(sshBinary.toUserOutput()));
+ return;
+ }
+
+ m_masterSocketDir.reset(new QTemporaryDir);
+ if (!m_masterSocketDir->isValid()) {
+ emitError(QProcess::FailedToStart, tr("Cannot establish SSH connection: Failed to create temporary "
+ "directory for control socket: %1")
+ .arg(m_masterSocketDir->errorString()));
+ m_masterSocketDir.reset();
+ return;
+ }
+
+ m_masterProcess.reset(new QtcProcess);
+ SshParameters::setupSshEnvironment(m_masterProcess.get());
+ m_timer.setSingleShot(true);
+ connect(&m_timer, &QTimer::timeout, this, &SshSharedConnection::autoDestructRequested);
+ connect(m_masterProcess.get(), &QtcProcess::readyReadStandardOutput, [this] {
+ const QByteArray reply = m_masterProcess->readAllStandardOutput();
+ if (reply == "\n")
+ emitConnected();
+ // TODO: otherwise emitError and finish master process?
+ });
+ // TODO: in case of refused connection we are getting the following on stdErr:
+ // ssh: connect to host 127.0.0.1 port 22: Connection refused\r\n
+ connect(m_masterProcess.get(), &QtcProcess::done, [this] {
+ const ProcessResult result = m_masterProcess->result();
+ const ProcessResultData resultData = m_masterProcess->resultData();
+ if (result == ProcessResult::StartFailed) {
+ emitError(QProcess::FailedToStart, tr("Cannot establish SSH connection.\n"
+ "Control process failed to start."));
+ return;
+ } else if (result == ProcessResult::FinishedWithError) {
+ emitError(resultData.m_error, fullProcessError());
+ return;
+ }
+ emit disconnected(resultData);
+ });
+
+ QStringList args = QStringList{"-M", "-N", "-o", "ControlPersist=no",
+ "-o", "PermitLocalCommand=yes", // Enable local command
+ "-o", "LocalCommand=echo"} // Local command is executed after successfully
+ // connecting to the server. "echo" will print "\n"
+ // on the process output if everything went fine.
+ << connectionArgs(sshBinary);
+ if (!m_sshParameters.x11DisplayName.isEmpty()) {
+ args.prepend("-X");
+ Environment env = m_masterProcess->environment();
+ env.set("DISPLAY", m_sshParameters.x11DisplayName);
+ m_masterProcess->setEnvironment(env);
+ }
+ m_masterProcess->setCommand(CommandLine(sshBinary, args));
+ m_masterProcess->start();
+}
+
+void SshSharedConnection::disconnectFromHost()
+{
+ m_masterProcess.reset();
+ m_masterSocketDir.reset();
+}
+
+QProcess::ProcessState SshSharedConnection::state() const
+{
+ return m_state;
+}
+
+void SshSharedConnection::emitConnected()
+{
+ m_state = QProcess::Running;
+ emit connected(socketFilePath());
+}
+
+void SshSharedConnection::emitError(QProcess::ProcessError error, const QString &errorString)
+{
+ m_state = QProcess::NotRunning;
+ ProcessResultData resultData = m_masterProcess->resultData();
+ resultData.m_error = error;
+ resultData.m_errorString = errorString;
+ emit disconnected(resultData);
+}
+
+void SshSharedConnection::emitDisconnected()
+{
+ m_state = QProcess::NotRunning;
+ emit disconnected(m_masterProcess->resultData());
+}
+
+QString SshSharedConnection::fullProcessError() const
+{
+ const QString errorString = m_masterProcess->exitStatus() == QProcess::CrashExit
+ ? m_masterProcess->errorString() : QString();
+ const QString standardError = m_masterProcess->cleanedStdErr();
+ const QString errorPrefix = errorString.isEmpty() && standardError.isEmpty()
+ ? tr("SSH connection failure.") : tr("SSH connection failure:");
+ QStringList allErrors {errorPrefix, errorString, standardError};
+ allErrors.removeAll({});
+ return allErrors.join('\n');
+}
+
+QStringList SshSharedConnection::connectionArgs(const FilePath &binary) const
+{
+ return m_sshParameters.connectionOptions(binary) << "-o" << ("ControlPath=" + socketFilePath())
+ << m_sshParameters.host();
+}
+
+// SshConnectionHandle
+
+class SshConnectionHandle : public QObject
+{
+ Q_OBJECT
+public:
+ SshConnectionHandle(const IDevice::ConstPtr &device) : m_device(device) {}
+ ~SshConnectionHandle() override { emit detachFromSharedConnection(); }
+
+signals:
+ // direction: connection -> caller
+ void connected(const QString &socketFilePath);
+ void disconnected(const ProcessResultData &result);
+ // direction: caller -> connection
+ void detachFromSharedConnection();
+
+private:
+ // Store the IDevice::ConstPtr in order to extend the lifetime of device for as long
+ // as this object is alive.
+ IDevice::ConstPtr m_device;
+};
+
static QString visualizeNull(QString s)
{
return s.replace(QLatin1Char('\0'), QLatin1String("<null>"));
@@ -100,12 +324,12 @@ private:
"done").arg(QLatin1String(Delimiter0)).arg(QLatin1String(Delimiter1));
}
- QList<DeviceProcessItem> buildProcessList(const QString &listProcessesReply) const override
+ QList<ProcessInfo> buildProcessList(const QString &listProcessesReply) const override
{
- QList<DeviceProcessItem> processes;
+ QList<ProcessInfo> processes;
const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0)
+ QString::fromLatin1(Delimiter1), Qt::SkipEmptyParts);
- foreach (const QString &line, lines) {
+ for (const QString &line : lines) {
const QStringList elements = line.split(QLatin1Char('\n'));
if (elements.count() < 4) {
qDebug("%s: Expected four list elements, got %d. Line was '%s'.", Q_FUNC_INFO,
@@ -132,10 +356,10 @@ private:
+ QLatin1Char(']');
}
- DeviceProcessItem process;
- process.pid = pid;
- process.cmdLine = command;
- process.exe = elements.at(3);
+ ProcessInfo process;
+ process.processId = pid;
+ process.commandLine = command;
+ process.executable = elements.at(3);
processes.append(process);
}
@@ -144,164 +368,551 @@ private:
}
};
-class LinuxPortsGatheringMethod : public PortsGatheringMethod
+
+// LinuxDevicePrivate
+
+class ShellThreadHandler;
+
+class LinuxDevicePrivate
{
- CommandLine commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const override
- {
- // We might encounter the situation that protocol is given IPv6
- // but the consumer of the free port information decides to open
- // an IPv4(only) port. As a result the next IPv6 scan will
- // report the port again as open (in IPv6 namespace), while the
- // same port in IPv4 namespace might still be blocked, and
- // re-use of this port fails.
- // GDBserver behaves exactly like this.
+public:
+ explicit LinuxDevicePrivate(LinuxDevice *parent);
+ ~LinuxDevicePrivate();
+
+ bool setupShell();
+ bool runInShell(const CommandLine &cmd, const QByteArray &data = {});
+ QByteArray outputForRunInShell(const CommandLine &cmd);
+ void attachToSharedConnection(SshConnectionHandle *connectionHandle,
+ const SshParameters &sshParameters);
+
+ LinuxDevice *q = nullptr;
+ QThread m_shellThread;
+ ShellThreadHandler *m_handler = nullptr;
+ mutable QMutex m_shellMutex;
+ QList<QtcProcess *> m_terminals;
+};
+
+// SshProcessImpl
+
+class SshProcessInterfacePrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ SshProcessInterfacePrivate(SshProcessInterface *sshInterface, LinuxDevicePrivate *devicePrivate);
+
+ void start();
+
+ void handleConnected(const QString &socketFilePath);
+ void handleDisconnected(const ProcessResultData &result);
+
+ void handleStarted();
+ void handleDone();
+ void handleReadyReadStandardOutput();
+ void handleReadyReadStandardError();
+
+ void clearForStart();
+ void doStart();
+ CommandLine fullLocalCommandLine() const;
- Q_UNUSED(protocol)
+ SshProcessInterface *q = nullptr;
- // /proc/net/tcp* covers /proc/net/tcp and /proc/net/tcp6
- return {"sed", "-e 's/.*: [[:xdigit:]]*:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' /proc/net/tcp*",
- CommandLine::Raw};
+ qint64 m_processId = 0;
+ // Store the IDevice::ConstPtr in order to extend the lifetime of device for as long
+ // as this object is alive.
+ IDevice::ConstPtr m_device;
+ std::unique_ptr<SshConnectionHandle> m_connectionHandle;
+ QtcProcess m_process;
+ LinuxDevicePrivate *m_devicePrivate = nullptr;
+
+ QString m_socketFilePath;
+ SshParameters m_sshParameters;
+ bool m_connecting = false;
+ bool m_killed = false;
+
+ ProcessResultData m_result;
+};
+
+SshProcessInterface::SshProcessInterface(const LinuxDevice *linuxDevice)
+ : d(new SshProcessInterfacePrivate(this, linuxDevice->d))
+{
+}
+
+SshProcessInterface::~SshProcessInterface()
+{
+ delete d;
+}
+
+void SshProcessInterface::handleStarted(qint64 processId)
+{
+ emitStarted(processId);
+}
+
+void SshProcessInterface::handleDone(const ProcessResultData &resultData)
+{
+ emit done(resultData);
+}
+
+void SshProcessInterface::handleReadyReadStandardOutput(const QByteArray &outputData)
+{
+ emit readyRead(outputData, {});
+}
+
+void SshProcessInterface::handleReadyReadStandardError(const QByteArray &errorData)
+{
+ emit readyRead({}, errorData);
+}
+
+void SshProcessInterface::emitStarted(qint64 processId)
+{
+ d->m_processId = processId;
+ emit started(processId);
+}
+
+void SshProcessInterface::killIfRunning()
+{
+ if (d->m_killed || d->m_process.state() != QProcess::Running)
+ return;
+ sendControlSignal(ControlSignal::Kill);
+ d->m_killed = true;
+}
+
+qint64 SshProcessInterface::processId() const
+{
+ return d->m_processId;
+}
+
+bool SshProcessInterface::runInShell(const CommandLine &command, const QByteArray &data)
+{
+ return d->m_devicePrivate->runInShell(command, data);
+}
+
+void SshProcessInterface::start()
+{
+ d->start();
+}
+
+qint64 SshProcessInterface::write(const QByteArray &data)
+{
+ return d->m_process.writeRaw(data);
+}
+
+LinuxProcessInterface::LinuxProcessInterface(const LinuxDevice *linuxDevice)
+ : SshProcessInterface(linuxDevice)
+{
+}
+
+LinuxProcessInterface::~LinuxProcessInterface()
+{
+ killIfRunning();
+}
+
+void LinuxProcessInterface::sendControlSignal(ControlSignal controlSignal)
+{
+ QTC_ASSERT(controlSignal != ControlSignal::KickOff, return);
+ const qint64 pid = processId();
+ QTC_ASSERT(pid, return); // TODO: try sending a signal based on process name
+ const QString args = QString::fromLatin1("-%1 %2")
+ .arg(controlSignalToInt(controlSignal)).arg(pid);
+ CommandLine command = { "kill", args, CommandLine::Raw };
+ // Note: This blocking call takes up to 2 ms for local remote.
+ runInShell(command);
+}
+
+QString LinuxProcessInterface::fullCommandLine(const CommandLine &commandLine) const
+{
+ CommandLine cmd;
+
+ if (!commandLine.isEmpty()) {
+ const QStringList rcFilesToSource = {"/etc/profile", "$HOME/.profile"};
+ for (const QString &filePath : rcFilesToSource) {
+ cmd.addArgs({"test", "-f", filePath});
+ cmd.addArgs("&&", CommandLine::Raw);
+ cmd.addArgs({".", filePath});
+ cmd.addArgs(";", CommandLine::Raw);
+ }
}
- QList<Utils::Port> usedPorts(const QByteArray &output) const override
- {
- QList<Utils::Port> ports;
- QList<QByteArray> portStrings = output.split('\n');
- foreach (const QByteArray &portString, portStrings) {
- if (portString.size() != 4)
- continue;
- bool ok;
- const Utils::Port port(portString.toInt(&ok, 16));
- if (ok) {
- if (!ports.contains(port))
- ports << port;
- } else {
- qWarning("%s: Unexpected string '%s' is not a port.",
- Q_FUNC_INFO, portString.data());
- }
+ if (!m_setup.m_workingDirectory.isEmpty()) {
+ cmd.addArgs({"cd", m_setup.m_workingDirectory.path()});
+ cmd.addArgs("&&", CommandLine::Raw);
+ }
+
+ if (m_setup.m_terminalMode == TerminalMode::Off)
+ cmd.addArgs(QString("echo ") + s_pidMarker + "$$" + s_pidMarker + " && ", CommandLine::Raw);
+
+ const Environment &env = m_setup.m_environment;
+ for (auto it = env.constBegin(); it != env.constEnd(); ++it)
+ cmd.addArgs(env.key(it) + "='" + env.expandedValueForKey(env.key(it)) + '\'', CommandLine::Raw);
+
+ if (m_setup.m_terminalMode == TerminalMode::Off)
+ cmd.addArg("exec");
+
+ if (!commandLine.isEmpty())
+ cmd.addCommandLineAsArgs(commandLine, CommandLine::Raw);
+ return cmd.arguments();
+}
+
+void LinuxProcessInterface::handleStarted(qint64 processId)
+{
+ // Don't emit started() when terminal is off,
+ // it's being done later inside handleReadyReadStandardOutput().
+ if (m_setup.m_terminalMode == TerminalMode::Off)
+ return;
+
+ m_pidParsed = true;
+ emitStarted(processId);
+}
+
+void LinuxProcessInterface::handleDone(const ProcessResultData &resultData)
+{
+ ProcessResultData finalData = resultData;
+ if (!m_pidParsed) {
+ finalData.m_error = QProcess::FailedToStart;
+ if (!m_error.isEmpty()) {
+ if (!finalData.m_errorString.isEmpty())
+ finalData.m_errorString += "\n";
+ finalData.m_errorString += QString::fromLocal8Bit(m_error);
}
- return ports;
}
-};
+ emit done(finalData);
+}
+
+void LinuxProcessInterface::handleReadyReadStandardOutput(const QByteArray &outputData)
+{
+ if (m_pidParsed) {
+ emit readyRead(outputData, {});
+ return;
+ }
+
+ m_output.append(outputData);
+
+ static const QByteArray endMarker = s_pidMarker + '\n';
+ const int endMarkerOffset = m_output.indexOf(endMarker);
+ if (endMarkerOffset == -1)
+ return;
+ const int startMarkerOffset = m_output.indexOf(s_pidMarker);
+ if (startMarkerOffset == endMarkerOffset) // Only theoretically possible.
+ return;
+ const int pidStart = startMarkerOffset + s_pidMarker.length();
+ const QByteArray pidString = m_output.mid(pidStart, endMarkerOffset - pidStart);
+ m_pidParsed = true;
+ const qint64 processId = pidString.toLongLong();
+
+ // We don't want to show output from e.g. /etc/profile.
+ m_output = m_output.mid(endMarkerOffset + endMarker.length());
+
+ emitStarted(processId);
+
+ if (!m_output.isEmpty() || !m_error.isEmpty())
+ emit readyRead(m_output, m_error);
+
+ m_output.clear();
+ m_error.clear();
+}
+
+void LinuxProcessInterface::handleReadyReadStandardError(const QByteArray &errorData)
+{
+ if (m_pidParsed) {
+ emit readyRead({}, errorData);
+ return;
+ }
+ m_error.append(errorData);
+}
+
+SshProcessInterfacePrivate::SshProcessInterfacePrivate(SshProcessInterface *sshInterface,
+ LinuxDevicePrivate *devicePrivate)
+ : QObject(sshInterface)
+ , q(sshInterface)
+ , m_device(devicePrivate->q->sharedFromThis())
+ , m_process(this)
+ , m_devicePrivate(devicePrivate)
+{
+ connect(&m_process, &QtcProcess::started, this, &SshProcessInterfacePrivate::handleStarted);
+ connect(&m_process, &QtcProcess::done, this, &SshProcessInterfacePrivate::handleDone);
+ connect(&m_process, &QtcProcess::readyReadStandardOutput,
+ this, &SshProcessInterfacePrivate::handleReadyReadStandardOutput);
+ connect(&m_process, &QtcProcess::readyReadStandardError,
+ this, &SshProcessInterfacePrivate::handleReadyReadStandardError);
+}
+
+void SshProcessInterfacePrivate::start()
+{
+ clearForStart();
+
+ m_sshParameters = m_devicePrivate->q->sshParameters();
+ // TODO: Do we really need it for master process?
+ m_sshParameters.x11DisplayName
+ = q->m_setup.m_extraData.value("Ssh.X11ForwardToDisplay").toString();
+ if (SshSettings::connectionSharingEnabled()) {
+ m_connecting = true;
+ m_connectionHandle.reset(new SshConnectionHandle(m_devicePrivate->q->sharedFromThis()));
+ m_connectionHandle->setParent(this);
+ connect(m_connectionHandle.get(), &SshConnectionHandle::connected,
+ this, &SshProcessInterfacePrivate::handleConnected);
+ connect(m_connectionHandle.get(), &SshConnectionHandle::disconnected,
+ this, &SshProcessInterfacePrivate::handleDisconnected);
+ m_devicePrivate->attachToSharedConnection(m_connectionHandle.get(), m_sshParameters);
+ } else {
+ doStart();
+ }
+}
+
+void SshProcessInterfacePrivate::handleConnected(const QString &socketFilePath)
+{
+ m_connecting = false;
+ m_socketFilePath = socketFilePath;
+ doStart();
+}
+
+void SshProcessInterfacePrivate::handleDisconnected(const ProcessResultData &result)
+{
+ ProcessResultData resultData = result;
+ if (m_connecting)
+ resultData.m_error = QProcess::FailedToStart;
+
+ m_connecting = false;
+ if (m_connectionHandle) // TODO: should it disconnect from signals first?
+ m_connectionHandle.release()->deleteLater();
+
+ if (resultData.m_error != QProcess::UnknownError || m_process.state() != QProcess::NotRunning)
+ emit q->done(resultData); // TODO: don't emit done() on process finished afterwards
+}
+
+void SshProcessInterfacePrivate::handleStarted()
+{
+ const qint64 processId = m_process.usesTerminal() ? m_process.processId() : 0;
+ // By default emits started signal, Linux impl doesn't emit it when terminal is off.
+ q->handleStarted(processId);
+}
+
+void SshProcessInterfacePrivate::handleDone()
+{
+ if (m_connectionHandle) // TODO: should it disconnect from signals first?
+ m_connectionHandle.release()->deleteLater();
+ q->handleDone(m_process.resultData());
+}
+
+void SshProcessInterfacePrivate::handleReadyReadStandardOutput()
+{
+ // By default emits signal. LinuxProcessImpl does custom parsing for processId
+ // and emits delayed start() - only when terminal is off.
+ q->handleReadyReadStandardOutput(m_process.readAllStandardOutput());
+}
+
+void SshProcessInterfacePrivate::handleReadyReadStandardError()
+{
+ // By default emits signal. LinuxProcessImpl buffers the error channel until
+ // it emits delayed start() - only when terminal is off.
+ q->handleReadyReadStandardError(m_process.readAllStandardError());
+}
+
+void SshProcessInterfacePrivate::clearForStart()
+{
+ m_result = {};
+}
+
+void SshProcessInterfacePrivate::doStart()
+{
+ m_process.setProcessImpl(q->m_setup.m_processImpl);
+ m_process.setProcessMode(q->m_setup.m_processMode);
+ m_process.setTerminalMode(q->m_setup.m_terminalMode);
+ m_process.setReaperTimeout(q->m_setup.m_reaperTimeout);
+ m_process.setWriteData(q->m_setup.m_writeData);
+ // TODO: what about other fields from m_setup?
+ SshParameters::setupSshEnvironment(&m_process);
+ if (!m_sshParameters.x11DisplayName.isEmpty()) {
+ Environment env = m_process.controlEnvironment();
+ // Note: it seems this is no-op when shared connection is used.
+ // In this case the display is taken from master process.
+ env.set("DISPLAY", m_sshParameters.x11DisplayName);
+ m_process.setControlEnvironment(env);
+ }
+ m_process.setCommand(fullLocalCommandLine());
+ m_process.start();
+}
+
+CommandLine SshProcessInterfacePrivate::fullLocalCommandLine() const
+{
+ CommandLine cmd{SshSettings::sshFilePath()};
+
+ if (!m_sshParameters.x11DisplayName.isEmpty())
+ cmd.addArg("-X");
+ if (q->m_setup.m_terminalMode != TerminalMode::Off)
+ cmd.addArg("-tt");
+
+ cmd.addArg("-q");
+
+ QStringList options = m_sshParameters.connectionOptions(SshSettings::sshFilePath());
+ if (!m_socketFilePath.isEmpty())
+ options << "-o" << ("ControlPath=" + m_socketFilePath);
+ options << m_sshParameters.host();
+ cmd.addArgs(options);
+
+ CommandLine remoteWithLocalPath = q->m_setup.m_commandLine;
+ FilePath executable;
+ executable.setPath(remoteWithLocalPath.executable().path());
+ remoteWithLocalPath.setExecutable(executable);
+
+ cmd.addArg(q->fullCommandLine(remoteWithLocalPath));
+ return cmd;
+}
// ShellThreadHandler
+static SshParameters displayless(const SshParameters &sshParameters)
+{
+ SshParameters parameters = sshParameters;
+ parameters.x11DisplayName.clear();
+ return parameters;
+}
+
class ShellThreadHandler : public QObject
{
+ class LinuxDeviceShell : public DeviceShell
+ {
+ public:
+ LinuxDeviceShell(const CommandLine &cmdLine)
+ : m_cmdLine(cmdLine)
+ {
+ }
+
+ private:
+ void setupShellProcess(QtcProcess *shellProcess) override
+ {
+ SshParameters::setupSshEnvironment(shellProcess);
+ shellProcess->setCommand(m_cmdLine);
+ }
+
+ private:
+ const CommandLine m_cmdLine;
+ };
+
public:
~ShellThreadHandler()
{
- if (m_shell)
- delete m_shell;
+ closeShell();
+ qDeleteAll(m_connections);
}
- bool startFailed(const SshConnectionParameters &parameters)
+ void closeShell()
{
- delete m_shell;
- m_shell = nullptr;
- qCDebug(linuxDeviceLog) << "Failed to connect to" << parameters.host();
- return false;
+ m_shell.reset();
}
- bool start(const SshConnectionParameters &parameters)
+ // Call me with shell mutex locked
+ bool start(const SshParameters &parameters)
{
- // TODO: start here shared ssh connection if needed (take it from settings)
- // connect to it
- // wait for connected
- m_shell = new SshRemoteProcess("/bin/sh",
- parameters.connectionOptions(SshSettings::sshFilePath()) << parameters.host(),
- ProcessMode::Writer);
- m_shell->start();
- const bool startOK = m_shell->waitForStarted();
- if (!startOK)
- return startFailed(parameters);
-
- m_shell->write("echo\n");
- const bool readOK = m_shell->waitForReadyRead();
- if (!readOK)
- return startFailed(parameters);
-
- const QByteArray output = m_shell->readAllStandardOutput();
- if (output != "\n")
- return startFailed(parameters);
-
- return true;
+ closeShell();
+ setSshParameters(parameters);
+
+ const FilePath sshPath = SshSettings::sshFilePath();
+ CommandLine cmd { sshPath };
+ cmd.addArg("-q");
+ cmd.addArgs(m_displaylessSshParameters.connectionOptions(sshPath)
+ << m_displaylessSshParameters.host());
+ cmd.addArg("/bin/sh");
+
+ m_shell.reset(new LinuxDeviceShell(cmd));
+ connect(m_shell.get(), &DeviceShell::done, this, [this] { m_shell.reset(); });
+ return m_shell->start();
}
+ // Call me with shell mutex locked
bool runInShell(const CommandLine &cmd, const QByteArray &data = {})
{
QTC_ASSERT(m_shell, return false);
- QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
-
- const QByteArray prefix = !data.isEmpty()
- ? QByteArray("echo '" + data.toBase64() + "' | base64 -d | ") : QByteArray("");
- const QByteArray suffix = QByteArray(" > /dev/null 2>&1\necho $?\n");
- const QByteArray command = prefix + cmd.toUserOutput().toUtf8() + suffix;
-
- m_shell->write(command);
- DEBUG("RUN1 " << cmd.toUserOutput());
- m_shell->waitForReadyRead();
- const QByteArray output = m_shell->readAllStandardOutput();
- DEBUG("GOT1 " << output);
- bool ok = false;
- const int result = output.toInt(&ok);
- LOG("Run command in shell:" << cmd.toUserOutput() << "result: " << output << " ==>" << result);
- QTC_ASSERT(ok, return false);
- return !result;
- }
-
- QByteArray outputForRunInShell(const QString &cmd)
+ return m_shell->runInShell(cmd, data);
+ }
+
+ // Call me with shell mutex locked
+ QByteArray outputForRunInShell(const CommandLine &cmd)
{
QTC_ASSERT(m_shell, return {});
- QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
-
- static int val = 0;
- const QByteArray delim = QString::number(++val, 16).toUtf8();
-
- DEBUG("RUN2 " << cmd);
- const QByteArray marker = "___QTC___" + delim + "_OUTPUT_MARKER___";
- DEBUG(" CMD: " << cmd.toUtf8() + "\necho " + marker + "\n");
- m_shell->write(cmd.toUtf8() + "\necho " + marker + "\n");
- QByteArray output;
- while (!output.contains(marker)) {
- DEBUG("OUTPUT" << output);
- m_shell->waitForReadyRead();
- output.append(m_shell->readAllStandardOutput());
- }
- DEBUG("GOT2 " << output);
- LOG("Run command in shell:" << cmd << "output size:" << output.size());
- const int pos = output.indexOf(marker);
- if (pos >= 0)
- output = output.left(pos);
- DEBUG("CHOPPED2 " << output);
- return output;
+ return m_shell->outputForRunInShell(cmd).stdOut;
}
- bool isRunning() const { return m_shell; }
-private:
- SshRemoteProcess *m_shell = nullptr;
-};
+ void setSshParameters(const SshParameters &sshParameters)
+ {
+ QMutexLocker locker(&m_mutex);
+ const SshParameters displaylessSshParameters = displayless(sshParameters);
+
+ if (m_displaylessSshParameters == displaylessSshParameters)
+ return;
+
+ // If displayless sshParameters don't match the old connections' sshParameters, then stale
+ // old connections (don't delete, as the last deref() to each one will delete them).
+ for (SshSharedConnection *connection : qAsConst(m_connections))
+ connection->makeStale();
+ m_connections.clear();
+ m_displaylessSshParameters = displaylessSshParameters;
+ }
-// LinuxDevicePrivate
+ QString attachToSharedConnection(SshConnectionHandle *connectionHandle,
+ const SshParameters &sshParameters)
+ {
+ setSshParameters(sshParameters);
-class LinuxDevicePrivate
-{
-public:
- explicit LinuxDevicePrivate(LinuxDevice *parent);
- ~LinuxDevicePrivate();
+ SshSharedConnection *matchingConnection = nullptr;
- CommandLine fullLocalCommandLine(const CommandLine &remoteCommand,
- QtcProcess::TerminalMode terminalMode,
- bool hasDisplay) const;
- bool setupShell();
- bool runInShell(const CommandLine &cmd, const QByteArray &data = {});
- QByteArray outputForRunInShell(const QString &cmd);
- QByteArray outputForRunInShell(const CommandLine &cmd);
+ // Find the matching connection
+ for (SshSharedConnection *connection : qAsConst(m_connections)) {
+ if (connection->sshParameters() == sshParameters) {
+ matchingConnection = connection;
+ break;
+ }
+ }
- LinuxDevice *q = nullptr;
- QThread m_shellThread;
- ShellThreadHandler *m_handler = nullptr;
- mutable QMutex m_shellMutex;
+ // If no matching connection has been found, create a new one
+ if (!matchingConnection) {
+ matchingConnection = new SshSharedConnection(sshParameters);
+ connect(matchingConnection, &SshSharedConnection::autoDestructRequested,
+ this, [this, matchingConnection] {
+ // This slot is just for removing the matchingConnection from the connection list.
+ // The SshSharedConnection could have deleted itself otherwise.
+ m_connections.removeOne(matchingConnection);
+ matchingConnection->deleteLater();
+ });
+ m_connections.append(matchingConnection);
+ }
+
+ matchingConnection->ref();
+
+ connect(matchingConnection, &SshSharedConnection::connected,
+ connectionHandle, &SshConnectionHandle::connected);
+ connect(matchingConnection, &SshSharedConnection::disconnected,
+ connectionHandle, &SshConnectionHandle::disconnected);
+
+ connect(connectionHandle, &SshConnectionHandle::detachFromSharedConnection,
+ matchingConnection, &SshSharedConnection::deref,
+ Qt::BlockingQueuedConnection); // Ensure the signal is delivered before sender's
+ // destruction, otherwise we may get out of sync
+ // with ref count.
+
+ if (matchingConnection->state() == QProcess::Running)
+ return matchingConnection->socketFilePath();
+
+ if (matchingConnection->state() == QProcess::NotRunning)
+ matchingConnection->connectToHost();
+
+ return {};
+ }
+
+ // Call me with shell mutex locked, called from other thread
+ bool isRunning(const SshParameters &sshParameters) const
+ {
+ if (!m_shell)
+ return false;
+ QMutexLocker locker(&m_mutex);
+ if (m_displaylessSshParameters != displayless(sshParameters))
+ return false;
+ return true;
+ }
+private:
+ mutable QMutex m_mutex;
+ SshParameters m_displaylessSshParameters;
+ QList<SshSharedConnection *> m_connections;
+ std::unique_ptr<LinuxDeviceShell> m_shell;
};
// LinuxDevice
@@ -309,8 +920,8 @@ public:
LinuxDevice::LinuxDevice()
: d(new LinuxDevicePrivate(this))
{
- setDisplayType(tr("Generic Linux"));
- setDefaultDisplayName(tr("Generic Linux Device"));
+ setDisplayType(tr("Remote Linux"));
+ setDefaultDisplayName(tr("Remote Linux Device"));
setOsType(OsTypeLinux);
addDeviceAction({tr("Deploy Public Key..."), [](const IDevice::Ptr &device, QWidget *parent) {
@@ -321,30 +932,29 @@ LinuxDevice::LinuxDevice()
}});
setOpenTerminal([this](const Environment &env, const FilePath &workingDir) {
- DeviceProcess * const proc = createProcess(nullptr);
- QObject::connect(proc, &DeviceProcess::finished, [proc] {
- if (!proc->errorString().isEmpty()) {
- Core::MessageManager::writeDisrupting(
- tr("Error running remote shell: %1").arg(proc->errorString()));
+ QtcProcess * const proc = new QtcProcess;
+ d->m_terminals.append(proc);
+ QObject::connect(proc, &QtcProcess::done, [this, proc] {
+ if (proc->error() != QProcess::UnknownError) {
+ const QString errorString = proc->errorString();
+ QString message;
+ if (proc->error() == QProcess::FailedToStart)
+ message = tr("Error starting remote shell.");
+ else if (errorString.isEmpty())
+ message = tr("Error running remote shell.");
+ else
+ message = tr("Error running remote shell: %1").arg(errorString);
+ Core::MessageManager::writeDisrupting(message);
}
proc->deleteLater();
+ d->m_terminals.removeOne(proc);
});
- QObject::connect(proc, &DeviceProcess::errorOccurred, [proc] {
- Core::MessageManager::writeDisrupting(tr("Error starting remote shell."));
- proc->deleteLater();
- });
- Runnable runnable;
- runnable.device = sharedFromThis();
- runnable.environment = env;
- runnable.workingDirectory = workingDir;
-
- // It seems we cannot pass an environment to OpenSSH dynamically
- // without specifying an executable.
- if (env.size() > 0)
- runnable.command.setExecutable("/bin/sh");
-
- proc->setRunInTerminal(true);
- proc->start(runnable);
+
+ proc->setCommand({filePath({}), {}});
+ proc->setTerminalMode(TerminalMode::On);
+ proc->setEnvironment(env);
+ proc->setWorkingDirectory(workingDir);
+ proc->start();
});
addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) {
@@ -362,19 +972,33 @@ IDeviceWidget *LinuxDevice::createWidget()
return new GenericLinuxDeviceConfigurationWidget(sharedFromThis());
}
-DeviceProcess *LinuxDevice::createProcess(QObject *parent) const
-{
- return new LinuxDeviceProcess(sharedFromThis(), parent);
-}
-
bool LinuxDevice::canAutoDetectPorts() const
{
return true;
}
-PortsGatheringMethod::Ptr LinuxDevice::portsGatheringMethod() const
+PortsGatheringMethod LinuxDevice::portsGatheringMethod() const
{
- return LinuxPortsGatheringMethod::Ptr(new LinuxPortsGatheringMethod);
+ return {
+ [this](QAbstractSocket::NetworkLayerProtocol protocol) -> CommandLine {
+ // We might encounter the situation that protocol is given IPv6
+ // but the consumer of the free port information decides to open
+ // an IPv4(only) port. As a result the next IPv6 scan will
+ // report the port again as open (in IPv6 namespace), while the
+ // same port in IPv4 namespace might still be blocked, and
+ // re-use of this port fails.
+ // GDBserver behaves exactly like this.
+
+ Q_UNUSED(protocol)
+
+ // /proc/net/tcp* covers /proc/net/tcp and /proc/net/tcp6
+ return {filePath("sed"),
+ "-e 's/.*: [[:xdigit:]]*:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' /proc/net/tcp*",
+ CommandLine::Raw};
+ },
+
+ &Port::parseFromSedOutput
+ };
}
DeviceProcessList *LinuxDevice::createProcessListModel(QObject *parent) const
@@ -389,7 +1013,7 @@ DeviceTester *LinuxDevice::createDeviceTester() const
DeviceProcessSignalOperation::Ptr LinuxDevice::signalOperation() const
{
- return DeviceProcessSignalOperation::Ptr(new RemoteLinuxSignalOperation(sshParameters()));
+ return DeviceProcessSignalOperation::Ptr(new RemoteLinuxSignalOperation(sharedFromThis()));
}
class LinuxDeviceEnvironmentFetcher : public DeviceEnvironmentFetcher
@@ -407,7 +1031,7 @@ public:
private:
void start() override { m_reader.start(); }
void readerFinished() { emit finished(m_reader.remoteEnvironment(), true); }
- void readerError() { emit finished(Utils::Environment(), false); }
+ void readerError() { emit finished(Environment(), false); }
Internal::RemoteLinuxEnvironmentReader m_reader;
};
@@ -422,72 +1046,23 @@ QString LinuxDevice::userAtHost() const
return sshParameters().userAtHost();
}
-FilePath LinuxDevice::mapToGlobalPath(const FilePath &pathOnDevice) const
-{
- if (pathOnDevice.needsDevice()) {
- // Already correct form, only sanity check it's ours...
- QTC_CHECK(handlesFile(pathOnDevice));
- return pathOnDevice;
- }
- FilePath result;
- result.setScheme("ssh");
- result.setHost(userAtHost());
- result.setPath(pathOnDevice.path());
- return result;
-}
-
bool LinuxDevice::handlesFile(const FilePath &filePath) const
{
- return filePath.scheme() == "ssh" && filePath.host() == userAtHost();
+ if (filePath.scheme() == "device" && filePath.host() == id().toString())
+ return true;
+ if (filePath.scheme() == "ssh" && filePath.host() == userAtHost())
+ return true;
+ return false;
}
-CommandLine LinuxDevicePrivate::fullLocalCommandLine(const CommandLine &remoteCommand,
- QtcProcess::TerminalMode terminalMode,
- bool hasDisplay) const
+ProcessInterface *LinuxDevice::createProcessInterface() const
{
- Utils::CommandLine cmd{SshSettings::sshFilePath()};
- const SshConnectionParameters parameters = q->sshParameters();
-
- if (hasDisplay)
- cmd.addArg("-X");
- if (terminalMode != QtcProcess::TerminalOff)
- cmd.addArg("-tt");
-
- cmd.addArg("-q");
- // TODO: currently this drops shared connection (-o ControlPath=socketFilePath)
- cmd.addArgs(parameters.connectionOptions(SshSettings::sshFilePath()) << parameters.host());
-
- CommandLine remoteWithLocalPath = remoteCommand;
- FilePath executable = remoteWithLocalPath.executable();
- executable.setScheme({});
- executable.setHost({});
- remoteWithLocalPath.setExecutable(executable);
- cmd.addArg(remoteWithLocalPath.toUserOutput());
- return cmd;
+ return new LinuxProcessInterface(this);
}
-void LinuxDevice::runProcess(QtcProcess &process) const
+Environment LinuxDevice::systemEnvironment() const
{
- QTC_ASSERT(!process.isRunning(), return);
-
- Utils::Environment env = process.hasEnvironment() ? process.environment()
- : Utils::Environment::systemEnvironment();
- const bool hasDisplay = env.hasKey("DISPLAY") && (env.value("DISPLAY") != QString(":0"));
- if (SshSettings::askpassFilePath().exists()) {
- env.set("SSH_ASKPASS", SshSettings::askpassFilePath().toUserOutput());
-
- // OpenSSH only uses the askpass program if DISPLAY is set, regardless of the platform.
- if (!env.hasKey("DISPLAY"))
- env.set("DISPLAY", ":0");
- }
- process.setEnvironment(env);
-
- // Otherwise, ssh will ignore SSH_ASKPASS and read from /dev/tty directly.
- process.setDisableUnixTerminal();
-
- process.setCommand(d->fullLocalCommandLine(process.commandLine(), process.terminalMode(),
- hasDisplay));
- process.start();
+ return {}; // FIXME. See e.g. Docker implementation.
}
LinuxDevicePrivate::LinuxDevicePrivate(LinuxDevice *parent)
@@ -501,15 +1076,27 @@ LinuxDevicePrivate::LinuxDevicePrivate(LinuxDevice *parent)
LinuxDevicePrivate::~LinuxDevicePrivate()
{
- m_shellThread.quit();
- m_shellThread.wait();
+ qDeleteAll(m_terminals);
+ auto closeShell = [this] {
+ m_shellThread.quit();
+ m_shellThread.wait();
+ };
+ if (QThread::currentThread() == m_shellThread.thread())
+ closeShell();
+ else // We might be in a non-main thread now due to extended lifetime of IDevice::Ptr
+ QMetaObject::invokeMethod(&m_shellThread, closeShell, Qt::BlockingQueuedConnection);
}
+// Call me with shell mutex locked
bool LinuxDevicePrivate::setupShell()
{
+ const SshParameters sshParameters = q->sshParameters();
+ if (m_handler->isRunning(sshParameters))
+ return true;
+
bool ok = false;
- QMetaObject::invokeMethod(m_handler, [this, parameters = q->sshParameters()] {
- return m_handler->start(parameters);
+ QMetaObject::invokeMethod(m_handler, [this, sshParameters] {
+ return m_handler->start(sshParameters);
}, Qt::BlockingQueuedConnection, &ok);
return ok;
}
@@ -518,10 +1105,7 @@ bool LinuxDevicePrivate::runInShell(const CommandLine &cmd, const QByteArray &da
{
QMutexLocker locker(&m_shellMutex);
DEBUG(cmd.toUserOutput());
- if (!m_handler->isRunning()) {
- const bool ok = setupShell();
- QTC_ASSERT(ok, return false);
- }
+ QTC_ASSERT(setupShell(), return false);
bool ret = false;
QMetaObject::invokeMethod(m_handler, [this, &cmd, &data] {
@@ -530,14 +1114,11 @@ bool LinuxDevicePrivate::runInShell(const CommandLine &cmd, const QByteArray &da
return ret;
}
-QByteArray LinuxDevicePrivate::outputForRunInShell(const QString &cmd)
+QByteArray LinuxDevicePrivate::outputForRunInShell(const CommandLine &cmd)
{
QMutexLocker locker(&m_shellMutex);
DEBUG(cmd);
- if (!m_handler->isRunning()) {
- const bool ok = setupShell();
- QTC_ASSERT(ok, return {});
- }
+ QTC_ASSERT(setupShell(), return {});
QByteArray ret;
QMetaObject::invokeMethod(m_handler, [this, &cmd] {
@@ -546,9 +1127,15 @@ QByteArray LinuxDevicePrivate::outputForRunInShell(const QString &cmd)
return ret;
}
-QByteArray LinuxDevicePrivate::outputForRunInShell(const CommandLine &cmd)
+void LinuxDevicePrivate::attachToSharedConnection(SshConnectionHandle *connectionHandle,
+ const SshParameters &sshParameters)
{
- return outputForRunInShell(cmd.toUserOutput());
+ QString socketFilePath;
+ QMetaObject::invokeMethod(m_handler, [this, connectionHandle, sshParameters] {
+ return m_handler->attachToSharedConnection(connectionHandle, sshParameters);
+ }, Qt::BlockingQueuedConnection, &socketFilePath);
+ if (!socketFilePath.isEmpty())
+ emit connectionHandle->connected(socketFilePath);
}
bool LinuxDevice::isExecutableFile(const FilePath &filePath) const
@@ -660,7 +1247,7 @@ bool LinuxDevice::renameFile(const FilePath &filePath, const FilePath &target) c
QDateTime LinuxDevice::lastModified(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return {});
- const QByteArray output = d->outputForRunInShell({"stat", {"-c", "%Y", filePath.path()}});
+ const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%Y", filePath.path()}});
const qint64 secs = output.toLongLong();
const QDateTime dt = QDateTime::fromSecsSinceEpoch(secs, Qt::UTC);
return dt;
@@ -677,7 +1264,7 @@ FilePath LinuxDevice::symLinkTarget(const FilePath &filePath) const
qint64 LinuxDevice::fileSize(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return -1);
- const QByteArray output = d->outputForRunInShell({"stat", {"-c", "%s", filePath.path()}});
+ const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%s", filePath.path()}});
return output.toLongLong();
}
@@ -687,7 +1274,7 @@ qint64 LinuxDevice::bytesAvailable(const FilePath &filePath) const
CommandLine cmd("df", {"-k"});
cmd.addArg(filePath.path());
cmd.addArgs("|tail -n 1 |sed 's/ */ /g'|cut -d ' ' -f 4", CommandLine::Raw);
- const QByteArray output = d->outputForRunInShell(cmd.toUserOutput());
+ const QByteArray output = d->outputForRunInShell(cmd);
bool ok = false;
const qint64 size = output.toLongLong(&ok);
if (ok)
@@ -698,7 +1285,7 @@ qint64 LinuxDevice::bytesAvailable(const FilePath &filePath) const
QFileDevice::Permissions LinuxDevice::permissions(const FilePath &filePath) const
{
QTC_ASSERT(handlesFile(filePath), return {});
- const QByteArray output = d->outputForRunInShell({"stat", {"-c", "%a", filePath.path()}});
+ const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%a", filePath.path()}});
const uint bits = output.toUInt(nullptr, 8);
QFileDevice::Permissions perm = {};
#define BIT(n, p) if (bits & (1<<n)) perm |= QFileDevice::p
@@ -715,47 +1302,13 @@ QFileDevice::Permissions LinuxDevice::permissions(const FilePath &filePath) cons
return perm;
}
-bool LinuxDevice::setPermissions(const Utils::FilePath &filePath, QFileDevice::Permissions permissions) const
+bool LinuxDevice::setPermissions(const FilePath &filePath, QFileDevice::Permissions permissions) const
{
QTC_ASSERT(handlesFile(filePath), return false);
const int flags = int(permissions);
return d->runInShell({"chmod", {QString::number(flags, 16), filePath.path()}});
}
-static void filterEntriesHelper(const FilePath &base,
- const std::function<bool(const FilePath &)> &callBack,
- const QStringList &entries,
- const FileFilter &filter)
-{
- const QList<QRegularExpression> nameRegexps =
- transform(filter.nameFilters, [](const QString &filter) {
- QRegularExpression re;
- re.setPattern(QRegularExpression::wildcardToRegularExpression(filter));
- QTC_CHECK(re.isValid());
- return re;
- });
-
- const auto nameMatches = [&nameRegexps](const QString &fileName) {
- for (const QRegularExpression &re : nameRegexps) {
- const QRegularExpressionMatch match = re.match(fileName);
- if (match.hasMatch())
- return true;
- }
- return nameRegexps.isEmpty();
- };
-
- // FIXME: Handle filters. For now bark on unsupported options.
- QTC_CHECK(filter.fileFilters == QDir::NoFilter);
- QTC_CHECK(filter.iteratorFlags == QDirIterator::NoIteratorFlags);
-
- for (const QString &entry : entries) {
- if (!nameMatches(entry))
- continue;
- if (!callBack(base.pathAppended(entry)))
- break;
- }
-}
-
void LinuxDevice::iterateDirectory(const FilePath &filePath,
const std::function<bool(const FilePath &)> &callBack,
const FileFilter &filter) const
@@ -763,9 +1316,8 @@ void LinuxDevice::iterateDirectory(const FilePath &filePath,
QTC_ASSERT(handlesFile(filePath), return);
// if we do not have find - use ls as fallback
const QByteArray output = d->outputForRunInShell({"ls", {"-1", "-b", "--", filePath.path()}});
- const QString out = QString::fromUtf8(output.data(), output.size());
- const QStringList entries = out.split('\n', Qt::SkipEmptyParts);
- filterEntriesHelper(filePath, callBack, entries, filter);
+ const QStringList entries = QString::fromUtf8(output).split('\n', Qt::SkipEmptyParts);
+ FileUtils::iterateLsOutput(filePath, entries, filter, callBack);
}
QByteArray LinuxDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const
@@ -779,7 +1331,7 @@ QByteArray LinuxDevice::fileContents(const FilePath &filePath, qint64 limit, qin
CommandLine cmd(FilePath::fromString("dd"), args, CommandLine::Raw);
const QByteArray output = d->outputForRunInShell(cmd);
- DEBUG(output << output << QByteArray::fromHex(output));
+ DEBUG(output << QByteArray::fromHex(output));
return output;
}
@@ -789,6 +1341,311 @@ bool LinuxDevice::writeFileContents(const FilePath &filePath, const QByteArray &
return d->runInShell({"dd", {"of=" + filePath.path()}}, data);
}
+static FilePaths dirsToCreate(const FilesToTransfer &files)
+{
+ FilePaths dirs;
+ for (const FileToTransfer &file : files) {
+ FilePath parentDir = file.m_target.parentDir();
+ while (true) {
+ if (dirs.contains(parentDir) || QDir(parentDir.path()).isRoot())
+ break;
+ dirs << parentDir;
+ parentDir = parentDir.parentDir();
+ }
+ }
+ sort(dirs);
+ return dirs;
+}
+
+static QByteArray transferCommand(const FileTransferDirection direction, bool link)
+{
+ if (direction == FileTransferDirection::Upload)
+ return link ? "ln -s" : "put";
+ if (direction == FileTransferDirection::Download)
+ return "get";
+ return {};
+}
+
+class SshTransferInterface : public FileTransferInterface
+{
+ Q_OBJECT
+
+protected:
+ SshTransferInterface(const FileTransferSetupData &setup, LinuxDevicePrivate *devicePrivate)
+ : FileTransferInterface(setup)
+ , m_device(devicePrivate->q->sharedFromThis())
+ , m_devicePrivate(devicePrivate)
+ , m_process(this)
+ {
+ m_direction = m_setup.m_files.isEmpty() ? FileTransferDirection::Invalid
+ : m_setup.m_files.first().direction();
+ SshParameters::setupSshEnvironment(&m_process);
+ connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
+ emit progress(QString::fromLocal8Bit(m_process.readAllStandardOutput()));
+ });
+ connect(&m_process, &QtcProcess::done, this, &SshTransferInterface::doneImpl);
+ }
+
+ bool handleError()
+ {
+ ProcessResultData resultData = m_process.resultData();
+ if (resultData.m_error == QProcess::FailedToStart) {
+ resultData.m_errorString = tr("\"%1\" failed to start: %2")
+ .arg(FileTransfer::transferMethodName(m_setup.m_method), resultData.m_errorString);
+ } else if (resultData.m_exitStatus != QProcess::NormalExit) {
+ resultData.m_errorString = tr("\"%1\" crashed.")
+ .arg(FileTransfer::transferMethodName(m_setup.m_method));
+ } else if (resultData.m_exitCode != 0) {
+ resultData.m_errorString = QString::fromLocal8Bit(m_process.readAllStandardError());
+ } else {
+ return false;
+ }
+ emit done(resultData);
+ return true;
+ }
+
+ void handleDone()
+ {
+ if (!handleError())
+ emit done(m_process.resultData());
+ }
+
+ QStringList fullConnectionOptions() const
+ {
+ QStringList options = m_sshParameters.connectionOptions(SshSettings::sshFilePath());
+ if (!m_socketFilePath.isEmpty())
+ options << "-o" << ("ControlPath=" + m_socketFilePath);
+ return options;
+ }
+
+ QString host() const { return m_sshParameters.host(); }
+ QString userAtHost() const { return m_sshParameters.userName() + '@' + m_sshParameters.host(); }
+
+ QtcProcess &process() { return m_process; }
+ FileTransferDirection direction() const { return m_direction; }
+
+private:
+ virtual void startImpl() = 0;
+ virtual void doneImpl() = 0;
+
+ void start() final
+ {
+ m_sshParameters = displayless(m_device->sshParameters());
+ if (SshSettings::connectionSharingEnabled()) {
+ m_connecting = true;
+ m_connectionHandle.reset(new SshConnectionHandle(m_device));
+ m_connectionHandle->setParent(this);
+ connect(m_connectionHandle.get(), &SshConnectionHandle::connected,
+ this, &SshTransferInterface::handleConnected);
+ connect(m_connectionHandle.get(), &SshConnectionHandle::disconnected,
+ this, &SshTransferInterface::handleDisconnected);
+ m_devicePrivate->attachToSharedConnection(m_connectionHandle.get(), m_sshParameters);
+ } else {
+ startImpl();
+ }
+ }
+
+ void handleConnected(const QString &socketFilePath)
+ {
+ m_connecting = false;
+ m_socketFilePath = socketFilePath;
+ startImpl();
+ }
+
+ void handleDisconnected(const ProcessResultData &result)
+ {
+ ProcessResultData resultData = result;
+ if (m_connecting)
+ resultData.m_error = QProcess::FailedToStart;
+
+ m_connecting = false;
+ if (m_connectionHandle) // TODO: should it disconnect from signals first?
+ m_connectionHandle.release()->deleteLater();
+
+ if (resultData.m_error != QProcess::UnknownError || m_process.state() != QProcess::NotRunning)
+ emit done(resultData); // TODO: don't emit done() on process finished afterwards
+ }
+
+ IDevice::ConstPtr m_device;
+ LinuxDevicePrivate *m_devicePrivate = nullptr;
+ SshParameters m_sshParameters;
+ FileTransferDirection m_direction = FileTransferDirection::Invalid; // helper
+
+ // ssh shared connection related
+ std::unique_ptr<SshConnectionHandle> m_connectionHandle;
+ QString m_socketFilePath;
+ bool m_connecting = false;
+
+ QtcProcess m_process;
+};
+
+class SftpTransferImpl : public SshTransferInterface
+{
+public:
+ SftpTransferImpl(const FileTransferSetupData &setup, LinuxDevicePrivate *devicePrivate)
+ : SshTransferInterface(setup, devicePrivate) { }
+
+private:
+ void startImpl() final
+ {
+ const FilePath sftpBinary = SshSettings::sftpFilePath();
+ if (!sftpBinary.exists()) {
+ startFailed(SshTransferInterface::tr("\"sftp\" binary \"%1\" does not exist.")
+ .arg(sftpBinary.toUserOutput()));
+ return;
+ }
+
+ m_batchFile.reset(new QTemporaryFile(this));
+ if (!m_batchFile->isOpen() && !m_batchFile->open()) {
+ startFailed(SshTransferInterface::tr("Could not create temporary file: %1")
+ .arg(m_batchFile->errorString()));
+ return;
+ }
+
+ const FilePaths dirs = dirsToCreate(m_setup.m_files);
+ for (const FilePath &dir : dirs) {
+ if (direction() == FileTransferDirection::Upload) {
+ m_batchFile->write("-mkdir " + ProcessArgs::quoteArgUnix(dir.path()).toLocal8Bit()
+ + '\n');
+ } else if (direction() == FileTransferDirection::Download) {
+ if (!QDir::root().mkpath(dir.path())) {
+ startFailed(SshTransferInterface::tr("Failed to create local directory \"%1\".")
+ .arg(QDir::toNativeSeparators(dir.path())));
+ return;
+ }
+ }
+ }
+
+ for (const FileToTransfer &file : m_setup.m_files) {
+ FilePath sourceFileOrLinkTarget = file.m_source;
+ bool link = false;
+ if (direction() == FileTransferDirection::Upload) {
+ const QFileInfo fi(file.m_source.toFileInfo());
+ if (fi.isSymLink()) {
+ link = true;
+ m_batchFile->write("-rm " + ProcessArgs::quoteArgUnix(
+ file.m_target.path()).toLocal8Bit() + '\n');
+ // see QTBUG-5817.
+ sourceFileOrLinkTarget.setPath(fi.dir().relativeFilePath(fi.symLinkTarget()));
+ }
+ }
+ m_batchFile->write(transferCommand(direction(), link) + ' '
+ + ProcessArgs::quoteArgUnix(sourceFileOrLinkTarget.path()).toLocal8Bit() + ' '
+ + ProcessArgs::quoteArgUnix(file.m_target.path()).toLocal8Bit() + '\n');
+ }
+ m_batchFile->close();
+ process().setCommand(CommandLine(sftpBinary, fullConnectionOptions()
+ << "-b" << m_batchFile->fileName() << host()));
+ process().start();
+ }
+
+ void doneImpl() final { handleDone(); }
+
+ std::unique_ptr<QTemporaryFile> m_batchFile;
+};
+
+class RsyncTransferImpl : public SshTransferInterface
+{
+public:
+ RsyncTransferImpl(const FileTransferSetupData &setup, LinuxDevicePrivate *devicePrivate)
+ : SshTransferInterface(setup, devicePrivate)
+ { }
+
+private:
+ void startImpl() final
+ {
+ m_currentIndex = 0;
+ startNextFile();
+ }
+
+ void doneImpl() final
+ {
+ if (m_setup.m_files.size() == 0 || m_currentIndex == m_setup.m_files.size() - 1)
+ return handleDone();
+
+ if (handleError())
+ return;
+
+ ++m_currentIndex;
+ startNextFile();
+ }
+
+ void startNextFile()
+ {
+ process().close();
+
+ const QString sshCmdLine = ProcessArgs::joinArgs(
+ QStringList{SshSettings::sshFilePath().toUserOutput()}
+ << fullConnectionOptions(), OsTypeLinux);
+ QStringList options{"-e", sshCmdLine, m_setup.m_rsyncFlags};
+
+ if (!m_setup.m_files.isEmpty()) { // NormalRun
+ const FileToTransfer file = m_setup.m_files.at(m_currentIndex);
+ const FileToTransfer fixedFile = fixLocalFileOnWindows(file, options);
+ const auto fixedPaths = fixPaths(fixedFile, userAtHost());
+
+ options << fixedPaths.first << fixedPaths.second;
+ } else { // TestRun
+ options << "-n" << "--exclude=*" << (userAtHost() + ":/tmp");
+ }
+ // TODO: Get rsync location from settings?
+ process().setCommand(CommandLine("rsync", options));
+ process().start();
+ }
+
+ // On Windows, rsync is either from msys or cygwin. Neither work with the other's ssh.exe.
+ FileToTransfer fixLocalFileOnWindows(const FileToTransfer &file, const QStringList &options) const
+ {
+ if (!HostOsInfo::isWindowsHost())
+ return file;
+
+ QString localFilePath = direction() == FileTransferDirection::Upload
+ ? file.m_source.path() : file.m_target.path();
+ localFilePath = '/' + localFilePath.at(0) + localFilePath.mid(2);
+ if (anyOf(options, [](const QString &opt) {
+ return opt.contains("cygwin", Qt::CaseInsensitive); })) {
+ localFilePath.prepend("/cygdrive");
+ }
+
+ FileToTransfer fixedFile = file;
+ (direction() == FileTransferDirection::Upload) ? fixedFile.m_source.setPath(localFilePath)
+ : fixedFile.m_target.setPath(localFilePath);
+ return fixedFile;
+ }
+
+ QPair<QString, QString> fixPaths(const FileToTransfer &file, const QString &remoteHost) const
+ {
+ FilePath localPath;
+ FilePath remotePath;
+ if (direction() == FileTransferDirection::Upload) {
+ localPath = file.m_source;
+ remotePath = file.m_target;
+ } else {
+ remotePath = file.m_source;
+ localPath = file.m_target;
+ }
+ const QString local = (localPath.isDir() && localPath.path().back() != '/')
+ ? localPath.path() + '/' : localPath.path();
+ const QString remote = remoteHost + ':' + remotePath.path();
+
+ return direction() == FileTransferDirection::Upload ? qMakePair(local, remote)
+ : qMakePair(remote, local);
+ }
+
+ int m_currentIndex = 0;
+};
+
+FileTransferInterface *LinuxDevice::createFileTransferInterface(
+ const FileTransferSetupData &setup) const
+{
+ switch (setup.m_method) {
+ case FileTransferMethod::Sftp: return new SftpTransferImpl(setup, d);
+ case FileTransferMethod::Rsync: return new RsyncTransferImpl(setup, d);
+ }
+ QTC_CHECK(false);
+ return {};
+}
+
namespace Internal {
// Factory
@@ -796,7 +1653,7 @@ namespace Internal {
LinuxDeviceFactory::LinuxDeviceFactory()
: IDeviceFactory(Constants::GenericLinuxOsType)
{
- setDisplayName(LinuxDevice::tr("Generic Linux Device"));
+ setDisplayName(LinuxDevice::tr("Remote Linux Device"));
setIcon(QIcon());
setConstructionFunction(&LinuxDevice::create);
setCreator([] {
@@ -809,3 +1666,5 @@ LinuxDeviceFactory::LinuxDeviceFactory()
} // namespace Internal
} // namespace RemoteLinux
+
+#include "linuxdevice.moc"
diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h
index d2906b230c3..2e7000a09dd 100644
--- a/src/plugins/remotelinux/linuxdevice.h
+++ b/src/plugins/remotelinux/linuxdevice.h
@@ -46,10 +46,8 @@ public:
ProjectExplorer::IDeviceWidget *createWidget() override;
- bool canCreateProcess() const override { return true; }
- ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const override;
bool canAutoDetectPorts() const override;
- ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const override;
+ ProjectExplorer::PortsGatheringMethod portsGatheringMethod() const override;
bool canCreateProcessModel() const override { return true; }
ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const override;
bool hasDeviceTester() const override { return true; }
@@ -58,7 +56,6 @@ public:
ProjectExplorer::DeviceEnvironmentFetcher::Ptr environmentFetcher() const override;
QString userAtHost() const;
- Utils::FilePath mapToGlobalPath(const Utils::FilePath &pathOnDevice) const override;
bool handlesFile(const Utils::FilePath &filePath) const override;
bool isExecutableFile(const Utils::FilePath &filePath) const override;
@@ -82,7 +79,10 @@ public:
QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const override;
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
QDateTime lastModified(const Utils::FilePath &filePath) const override;
- void runProcess(Utils::QtcProcess &process) const override;
+ Utils::ProcessInterface *createProcessInterface() const override;
+ ProjectExplorer::FileTransferInterface *createFileTransferInterface(
+ const ProjectExplorer::FileTransferSetupData &setup) const override;
+ Utils::Environment systemEnvironment() const override;
qint64 fileSize(const Utils::FilePath &filePath) const override;
qint64 bytesAvailable(const Utils::FilePath &filePath) const override;
QFileDevice::Permissions permissions(const Utils::FilePath &filePath) const override;
@@ -92,6 +92,8 @@ protected:
LinuxDevice();
class LinuxDevicePrivate *d;
+ friend class SshProcessInterface;
+ friend class SshTransferInterface;
};
namespace Internal {
diff --git a/src/plugins/remotelinux/linuxdeviceprocess.cpp b/src/plugins/remotelinux/linuxdeviceprocess.cpp
deleted file mode 100644
index 4953c8e5aba..00000000000
--- a/src/plugins/remotelinux/linuxdeviceprocess.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "linuxdeviceprocess.h"
-
-#include <projectexplorer/runcontrol.h>
-
-#include <utils/environment.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace RemoteLinux {
-
-const QByteArray pidMarker = "__qtc";
-
-LinuxDeviceProcess::LinuxDeviceProcess(const QSharedPointer<const ProjectExplorer::IDevice> &device,
- QObject *parent)
- : ProjectExplorer::SshDeviceProcess(device, parent)
-{
- connect(this, &DeviceProcess::finished, this, [this]() {
- m_processId = 0;
- });
- connect(this, &DeviceProcess::started, this, [this]() {
- m_pidParsed = false;
- m_output.clear();
- });
-}
-
-QByteArray LinuxDeviceProcess::readAllStandardOutput()
-{
- QByteArray output = SshDeviceProcess::readAllStandardOutput();
- if (m_pidParsed || runInTerminal())
- return output;
-
- m_output.append(output);
- static const QByteArray endMarker = pidMarker + '\n';
- const int endMarkerOffset = m_output.indexOf(endMarker);
- if (endMarkerOffset == -1)
- return {};
- const int startMarkerOffset = m_output.indexOf(pidMarker);
- if (startMarkerOffset == endMarkerOffset) // Only theoretically possible.
- return {};
- const int pidStart = startMarkerOffset + pidMarker.length();
- const QByteArray pidString = m_output.mid(pidStart, endMarkerOffset - pidStart);
- m_pidParsed = true;
- m_processId = pidString.toLongLong();
-
- // We don't want to show output from e.g. /etc/profile.
- const QByteArray actualOutput = m_output.mid(endMarkerOffset + endMarker.length());
- m_output.clear();
- return actualOutput;
-}
-
-qint64 LinuxDeviceProcess::processId() const
-{
- return m_processId < 0 ? 0 : m_processId;
-}
-
-QString LinuxDeviceProcess::fullCommandLine(const Runnable &runnable) const
-{
- CommandLine cmd;
-
- const QStringList rcFilesToSource = {"/etc/profile", "$HOME/.profile"};
- for (const QString &filePath : rcFilesToSource) {
- cmd.addArgs({"test", "-f", filePath});
- cmd.addArgs("&&", CommandLine::Raw);
- cmd.addArgs({".", filePath});
- cmd.addArgs(";", CommandLine::Raw);
- }
-
- if (!runnable.workingDirectory.isEmpty()) {
- cmd.addArgs({"cd", runnable.workingDirectory.path()});
- cmd.addArgs("&&", CommandLine::Raw);
- }
-
- if (!runInTerminal())
- cmd.addArgs(QString("echo ") + pidMarker + "$$" + pidMarker + " && ", CommandLine::Raw);
-
- const Environment &env = runnable.environment;
- for (auto it = env.constBegin(); it != env.constEnd(); ++it)
- cmd.addArgs(env.key(it) + "='" + env.expandedValueForKey(env.key(it)) + '\'', CommandLine::Raw);
-
- if (!runInTerminal())
- cmd.addArg("exec");
-
- cmd.addArg(runnable.command.executable().toString());
- cmd.addArgs(runnable.command.arguments(), CommandLine::Raw);
-
- return cmd.arguments();
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/linuxdeviceprocess.h b/src/plugins/remotelinux/linuxdeviceprocess.h
deleted file mode 100644
index 2de4ceadf1e..00000000000
--- a/src/plugins/remotelinux/linuxdeviceprocess.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "remotelinux_export.h"
-
-#include <projectexplorer/devicesupport/sshdeviceprocess.h>
-
-#include <QStringList>
-
-namespace RemoteLinux {
-
-class REMOTELINUX_EXPORT LinuxDeviceProcess : public ProjectExplorer::SshDeviceProcess
-{
- Q_OBJECT
-public:
- explicit LinuxDeviceProcess(const QSharedPointer<const ProjectExplorer::IDevice> &device,
- QObject *parent = nullptr);
-
- QByteArray readAllStandardOutput() override;
-
-private:
- QString fullCommandLine(const ProjectExplorer::Runnable &) const override;
- qint64 processId() const override;
-
- QByteArray m_output;
- qint64 m_processId = 0;
- bool m_pidParsed = false;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp
index 1353d91764f..6d0028fb800 100644
--- a/src/plugins/remotelinux/linuxdevicetester.cpp
+++ b/src/plugins/remotelinux/linuxdevicetester.cpp
@@ -26,40 +26,79 @@
#include "linuxdevicetester.h"
#include "remotelinux_constants.h"
-#include "rsyncdeploystep.h"
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
+#include <projectexplorer/devicesupport/filetransfer.h>
+#include <utils/algorithm.h>
#include <utils/port.h>
+#include <utils/processinterface.h>
#include <utils/qtcassert.h>
-#include <ssh/sftptransfer.h>
-#include <ssh/sshremoteprocess.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshconnectionmanager.h>
+#include <utils/qtcprocess.h>
using namespace ProjectExplorer;
-using namespace QSsh;
+using namespace Utils;
namespace RemoteLinux {
namespace Internal {
namespace {
-enum State { Inactive, Connecting, RunningUname, TestingPorts, TestingSftp, TestingRsync };
+enum State { Inactive,
+ TestingEcho,
+ TestingUname,
+ TestingPorts,
+ TestingSftp,
+ TestingRsync,
+ TestingCommands };
} // anonymous namespace
class GenericLinuxDeviceTesterPrivate
{
public:
- IDevice::Ptr deviceConfiguration;
- SshConnection *connection = nullptr;
- SshRemoteProcessPtr process;
+ IDevice::Ptr device;
+ QtcProcess echoProcess;
+ QtcProcess unameProcess;
DeviceUsedPortsGatherer portsGatherer;
- SftpTransferPtr sftpTransfer;
- SshProcess rsyncProcess;
+ FileTransfer fileTransfer;
State state = Inactive;
bool sftpWorks = false;
+ int currentCommandIndex = 0;
+ bool commandFailed = false;
+ QtcProcess commandsProcess;
};
+const QStringList s_commandsToTest = {"base64",
+ "cat",
+ "chmod",
+ "cp",
+ "cut",
+ "dd",
+ "df",
+ "echo",
+ "eval",
+ "exit",
+ "kill",
+ "ls",
+ "mkdir",
+ "mkfifo",
+ "mktemp",
+ "mv",
+ "printf",
+ "read",
+ "readlink",
+ "rm",
+ "sed",
+ "sh",
+ "shift",
+ "stat",
+ "tail",
+ "test",
+ "trap",
+ "touch",
+ "which"};
+// other possible commands (checked for qnx):
+// "awk", "grep", "netstat", "print", "pidin", "sleep", "uname"
+
} // namespace Internal
using namespace Internal;
@@ -67,30 +106,29 @@ using namespace Internal;
GenericLinuxDeviceTester::GenericLinuxDeviceTester(QObject *parent)
: DeviceTester(parent), d(new GenericLinuxDeviceTesterPrivate)
{
+ connect(&d->echoProcess, &QtcProcess::done, this,
+ &GenericLinuxDeviceTester::handleEchoDone);
+ connect(&d->unameProcess, &QtcProcess::done, this,
+ &GenericLinuxDeviceTester::handleUnameDone);
+ connect(&d->portsGatherer, &DeviceUsedPortsGatherer::error,
+ this, &GenericLinuxDeviceTester::handlePortsGathererError);
+ connect(&d->portsGatherer, &DeviceUsedPortsGatherer::portListReady,
+ this, &GenericLinuxDeviceTester::handlePortsGathererDone);
+ connect(&d->fileTransfer, &FileTransfer::done,
+ this, &GenericLinuxDeviceTester::handleFileTransferDone);
+ connect(&d->commandsProcess, &QtcProcess::done,
+ this, &GenericLinuxDeviceTester::handleCommandDone);
}
-GenericLinuxDeviceTester::~GenericLinuxDeviceTester()
-{
- if (d->connection)
- SshConnectionManager::releaseConnection(d->connection);
- delete d;
-}
+GenericLinuxDeviceTester::~GenericLinuxDeviceTester() = default;
void GenericLinuxDeviceTester::testDevice(const IDevice::Ptr &deviceConfiguration)
{
QTC_ASSERT(d->state == Inactive, return);
- d->deviceConfiguration = deviceConfiguration;
- SshConnectionManager::forceNewConnection(deviceConfiguration->sshParameters());
- d->connection = SshConnectionManager::acquireConnection(deviceConfiguration->sshParameters());
- connect(d->connection, &SshConnection::connected,
- this, &GenericLinuxDeviceTester::handleConnected);
- connect(d->connection, &SshConnection::errorOccurred,
- this, &GenericLinuxDeviceTester::handleConnectionFailure);
-
- emit progressMessage(tr("Connecting to host..."));
- d->state = Connecting;
- d->connection->connectToHost();
+ d->device = deviceConfiguration;
+
+ testEcho();
}
void GenericLinuxDeviceTester::stopTest()
@@ -98,21 +136,22 @@ void GenericLinuxDeviceTester::stopTest()
QTC_ASSERT(d->state != Inactive, return);
switch (d->state) {
- case Connecting:
- d->connection->disconnectFromHost();
+ case TestingEcho:
+ d->echoProcess.close();
break;
case TestingPorts:
d->portsGatherer.stop();
break;
- case RunningUname:
- d->process->close();
+ case TestingUname:
+ d->unameProcess.close();
break;
case TestingSftp:
- d->sftpTransfer->stop();
- break;
case TestingRsync:
- d->rsyncProcess.disconnect();
- d->rsyncProcess.kill();
+ d->fileTransfer.stop();
+ break;
+ case TestingCommands:
+ d->commandsProcess.close();
+ break;
case Inactive:
break;
}
@@ -120,53 +159,74 @@ void GenericLinuxDeviceTester::stopTest()
setFinished(TestFailure);
}
-void GenericLinuxDeviceTester::handleConnected()
-{
- QTC_ASSERT(d->state == Connecting, return);
+static const char s_echoContents[] = "Hello Remote World!";
- d->process = d->connection->createRemoteProcess("uname -rsm");
- connect(d->process.get(), &SshRemoteProcess::done,
- this, &GenericLinuxDeviceTester::handleProcessFinished);
+void GenericLinuxDeviceTester::testEcho()
+{
+ d->state = TestingEcho;
+ emit progressMessage(tr("Sending echo to device..."));
- emit progressMessage(tr("Checking kernel version..."));
- d->state = RunningUname;
- d->process->start();
+ d->echoProcess.setCommand({d->device->filePath("echo"), {s_echoContents}});
+ d->echoProcess.start();
}
-void GenericLinuxDeviceTester::handleConnectionFailure()
+void GenericLinuxDeviceTester::handleEchoDone()
{
- QTC_ASSERT(d->state != Inactive, return);
+ QTC_ASSERT(d->state == TestingEcho, return);
+ if (d->echoProcess.result() != ProcessResult::FinishedWithSuccess) {
+ const QByteArray stdErrOutput = d->echoProcess.readAllStandardError();
+ if (!stdErrOutput.isEmpty())
+ emit errorMessage(tr("echo failed: %1").arg(QString::fromUtf8(stdErrOutput)) + '\n');
+ else
+ emit errorMessage(tr("echo failed.") + '\n');
+ setFinished(TestFailure);
+ return;
+ }
- emit errorMessage(d->connection->errorString() + QLatin1Char('\n'));
+ const QString reply = d->echoProcess.cleanedStdOut().chopped(1); // Remove trailing \n
+ if (reply != s_echoContents)
+ emit errorMessage(tr("Device replied to echo with unexpected contents.") + '\n');
+ else
+ emit progressMessage(tr("Device replied to echo with expected contents.") + '\n');
- setFinished(TestFailure);
+ testUname();
+}
+
+void GenericLinuxDeviceTester::testUname()
+{
+ d->state = TestingUname;
+ emit progressMessage(tr("Checking kernel version..."));
+
+ d->unameProcess.setCommand({d->device->filePath("uname"), {"-rsm"}});
+ d->unameProcess.start();
}
-void GenericLinuxDeviceTester::handleProcessFinished(const QString &error)
+void GenericLinuxDeviceTester::handleUnameDone()
{
- QTC_ASSERT(d->state == RunningUname, return);
+ QTC_ASSERT(d->state == TestingUname, return);
- if (!error.isEmpty() || d->process->exitCode() != 0) {
- const QByteArray stderrOutput = d->process->readAllStandardError();
+ if (!d->unameProcess.errorString().isEmpty() || d->unameProcess.exitCode() != 0) {
+ const QByteArray stderrOutput = d->unameProcess.readAllStandardError();
if (!stderrOutput.isEmpty())
emit errorMessage(tr("uname failed: %1").arg(QString::fromUtf8(stderrOutput)) + QLatin1Char('\n'));
else
emit errorMessage(tr("uname failed.") + QLatin1Char('\n'));
} else {
- emit progressMessage(QString::fromUtf8(d->process->readAllStandardOutput()));
+ emit progressMessage(QString::fromUtf8(d->unameProcess.readAllStandardOutput()));
}
- connect(&d->portsGatherer, &DeviceUsedPortsGatherer::error,
- this, &GenericLinuxDeviceTester::handlePortsGatheringError);
- connect(&d->portsGatherer, &DeviceUsedPortsGatherer::portListReady,
- this, &GenericLinuxDeviceTester::handlePortListReady);
+ testPortsGatherer();
+}
- emit progressMessage(tr("Checking if specified ports are available..."));
+void GenericLinuxDeviceTester::testPortsGatherer()
+{
d->state = TestingPorts;
- d->portsGatherer.start(d->deviceConfiguration);
+ emit progressMessage(tr("Checking if specified ports are available..."));
+
+ d->portsGatherer.start(d->device);
}
-void GenericLinuxDeviceTester::handlePortsGatheringError(const QString &message)
+void GenericLinuxDeviceTester::handlePortsGathererError(const QString &message)
{
QTC_ASSERT(d->state == TestingPorts, return);
@@ -174,110 +234,128 @@ void GenericLinuxDeviceTester::handlePortsGatheringError(const QString &message)
setFinished(TestFailure);
}
-void GenericLinuxDeviceTester::handlePortListReady()
+void GenericLinuxDeviceTester::handlePortsGathererDone()
{
QTC_ASSERT(d->state == TestingPorts, return);
if (d->portsGatherer.usedPorts().isEmpty()) {
emit progressMessage(tr("All specified ports are available.") + QLatin1Char('\n'));
} else {
- QString portList;
- foreach (const Utils::Port port, d->portsGatherer.usedPorts())
- portList += QString::number(port.number()) + QLatin1String(", ");
- portList.remove(portList.count() - 2, 2);
+ const QString portList = transform(d->portsGatherer.usedPorts(), [](const Port &port) {
+ return QString::number(port.number());
+ }).join(", ");
emit errorMessage(tr("The following specified ports are currently in use: %1")
.arg(portList) + QLatin1Char('\n'));
}
- emit progressMessage(tr("Checking whether an SFTP connection can be set up..."));
- d->sftpTransfer = d->connection->createDownload(FilesToTransfer(),
- FileTransferErrorHandling::Abort);
- connect(d->sftpTransfer.get(), &SftpTransfer::done,
- this, &GenericLinuxDeviceTester::handleSftpFinished);
- d->state = TestingSftp;
- d->sftpTransfer->start();
+ testFileTransfer(FileTransferMethod::Sftp);
}
-void GenericLinuxDeviceTester::handleSftpStarted()
+void GenericLinuxDeviceTester::testFileTransfer(FileTransferMethod method)
{
- QTC_ASSERT(d->state == TestingSftp, return);
+ switch (method) {
+ case FileTransferMethod::Sftp: d->state = TestingSftp; break;
+ case FileTransferMethod::Rsync: d->state = TestingRsync; break;
+ }
+ emit progressMessage(tr("Checking whether \"%1\" works...")
+ .arg(FileTransfer::transferMethodName(method)));
+
+ d->fileTransfer.setTransferMethod(method);
+ d->fileTransfer.test(d->device);
}
-void GenericLinuxDeviceTester::handleSftpFinished(const QString &error)
+void GenericLinuxDeviceTester::handleFileTransferDone(const ProcessResultData &resultData)
{
- QTC_ASSERT(d->state == TestingSftp, return);
- if (error.isEmpty()) {
- d->sftpWorks = true;
- emit progressMessage(tr("SFTP service available.\n"));
+ QTC_ASSERT(d->state == TestingSftp || d->state == TestingRsync, return);
+
+ bool succeeded = false;
+ QString error;
+ const QString methodName = FileTransfer::transferMethodName(d->fileTransfer.transferMethod());
+ if (resultData.m_error == QProcess::FailedToStart) {
+ error = tr("Failed to start \"%1\": %2\n").arg(methodName, resultData.m_errorString);
+ } else if (resultData.m_exitStatus == QProcess::CrashExit) {
+ error = tr("\"%1\" crashed.\n").arg(methodName);
+ } else if (resultData.m_exitCode != 0) {
+ error = tr("\"%1\" failed with exit code %2: %3\n")
+ .arg(methodName).arg(resultData.m_exitCode).arg(resultData.m_errorString);
} else {
- d->sftpWorks = false;
- emit errorMessage(tr("Error setting up SFTP connection: %1\n").arg(error));
+ succeeded = true;
+ }
+
+ if (succeeded)
+ emit progressMessage(tr("\"%1\" is functional.\n").arg(methodName));
+ else
+ emit errorMessage(error);
+
+ if (d->state == TestingSftp) {
+ d->sftpWorks = succeeded;
+ testFileTransfer(FileTransferMethod::Rsync);
+ } else {
+ if (!succeeded) {
+ if (d->sftpWorks) {
+ emit progressMessage(tr("SFTP will be used for deployment, because rsync "
+ "is not available.\n"));
+ } else {
+ emit errorMessage(tr("Deployment to this device will not work out of the box.\n"));
+ }
+ }
+ d->device->setExtraData(Constants::SupportsRSync, succeeded);
+ if (d->sftpWorks || succeeded)
+ testCommands();
+ else
+ setFinished(TestFailure);
}
- disconnect(d->sftpTransfer.get(), nullptr, this, nullptr);
- testRsync();
}
-void GenericLinuxDeviceTester::testRsync()
+void GenericLinuxDeviceTester::testCommands()
{
- emit progressMessage(tr("Checking whether rsync works..."));
- connect(&d->rsyncProcess, &Utils::QtcProcess::errorOccurred, [this] {
- if (d->rsyncProcess.error() == QProcess::FailedToStart)
- handleRsyncFinished();
- });
- connect(&d->rsyncProcess, &Utils::QtcProcess::finished, this, [this] {
- handleRsyncFinished();
- });
- const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*d->connection,
- RsyncDeployStep::defaultFlags());
- const QStringList args = QStringList(cmdLine.options)
- << "-n" << "--exclude=*" << (cmdLine.remoteHostSpec + ":/tmp");
- d->rsyncProcess.setCommand(Utils::CommandLine("rsync", args));
- d->rsyncProcess.start();
+ d->state = TestingCommands;
+ emit progressMessage(tr("Checking if required commands are available..."));
+
+ d->currentCommandIndex = 0;
+ d->commandFailed = false;
+ testNextCommand();
}
-void GenericLinuxDeviceTester::handleRsyncFinished()
+void GenericLinuxDeviceTester::testNextCommand()
{
- QString error;
- if (d->rsyncProcess.error() == QProcess::FailedToStart) {
- error = tr("Failed to start rsync: %1\n").arg(d->rsyncProcess.errorString());
- } else if (d->rsyncProcess.exitStatus() == QProcess::CrashExit) {
- error = tr("rsync crashed.\n");
- } else if (d->rsyncProcess.exitCode() != 0) {
- error = tr("rsync failed with exit code %1: %2\n")
- .arg(d->rsyncProcess.exitCode())
- .arg(QString::fromLocal8Bit(d->rsyncProcess.readAllStandardError()));
+ d->commandsProcess.close();
+ if (s_commandsToTest.size() == d->currentCommandIndex) {
+ setFinished(d->commandFailed ? TestFailure : TestSuccess);
+ return;
}
- TestResult result = TestSuccess;
- if (!error.isEmpty()) {
- emit errorMessage(error);
- if (d->sftpWorks) {
- emit progressMessage(tr("SFTP will be used for deployment, because rsync "
- "is not available.\n"));
- } else {
- emit errorMessage(tr("Deployment to this device will not work out of the box.\n"));
- result = TestFailure;
- }
+
+ const QString commandName = s_commandsToTest[d->currentCommandIndex];
+ emit progressMessage(tr("%1...").arg(commandName));
+ CommandLine command{d->device->filePath("/bin/sh"), {"-c"}};
+ command.addArgs(QLatin1String("\"command -v %1\"").arg(commandName), CommandLine::Raw);
+ d->commandsProcess.setCommand(command);
+ d->commandsProcess.start();
+}
+
+void GenericLinuxDeviceTester::handleCommandDone()
+{
+ QTC_ASSERT(d->state == TestingCommands, return);
+
+ const QString command = s_commandsToTest[d->currentCommandIndex];
+ if (d->commandsProcess.result() == ProcessResult::FinishedWithSuccess) {
+ emit progressMessage(tr("%1 found.").arg(command));
} else {
- emit progressMessage(tr("rsync is functional.\n"));
+ d->commandFailed = true;
+ const QString message = d->commandsProcess.result() == ProcessResult::StartFailed
+ ? tr("An error occurred while checking for %1.").arg(command)
+ + '\n' + d->commandsProcess.errorString()
+ : tr("%1 not found.").arg(command);
+ emit errorMessage(message);
}
- d->deviceConfiguration->setExtraData(Constants::SupportsRSync, error.isEmpty());
- setFinished(result);
+ ++d->currentCommandIndex;
+ testNextCommand();
}
void GenericLinuxDeviceTester::setFinished(TestResult result)
{
d->state = Inactive;
- disconnect(&d->portsGatherer, nullptr, this, nullptr);
- if (d->sftpTransfer) {
- disconnect(d->sftpTransfer.get(), nullptr, this, nullptr);
- d->sftpTransfer.release()->deleteLater();
- }
- if (d->connection) {
- disconnect(d->connection, nullptr, this, nullptr);
- SshConnectionManager::releaseConnection(d->connection);
- d->connection = nullptr;
- }
emit finished(result);
}
diff --git a/src/plugins/remotelinux/linuxdevicetester.h b/src/plugins/remotelinux/linuxdevicetester.h
index 4cc6c7f9af1..67c392771a6 100644
--- a/src/plugins/remotelinux/linuxdevicetester.h
+++ b/src/plugins/remotelinux/linuxdevicetester.h
@@ -29,6 +29,9 @@
#include <projectexplorer/devicesupport/idevice.h>
+namespace ProjectExplorer { enum class FileTransferMethod; }
+namespace Utils { class ProcessResultData; }
+
namespace RemoteLinux {
namespace Internal { class GenericLinuxDeviceTesterPrivate; }
@@ -45,18 +48,26 @@ public:
void stopTest() override;
private:
- void handleConnected();
- void handleConnectionFailure();
- void handleProcessFinished(const QString &error);
- void handlePortsGatheringError(const QString &message);
- void handlePortListReady();
- void handleSftpStarted();
- void handleSftpFinished(const QString &error);
- void testRsync();
- void handleRsyncFinished();
+ void testEcho();
+ void handleEchoDone();
+
+ void testUname();
+ void handleUnameDone();
+
+ void testPortsGatherer();
+ void handlePortsGathererError(const QString &message);
+ void handlePortsGathererDone();
+
+ void testFileTransfer(ProjectExplorer::FileTransferMethod method);
+ void handleFileTransferDone(const Utils::ProcessResultData &resultData);
+
+ void testCommands();
+ void testNextCommand();
+ void handleCommandDone();
+
void setFinished(ProjectExplorer::DeviceTester::TestResult result);
- Internal::GenericLinuxDeviceTesterPrivate * const d;
+ std::unique_ptr<Internal::GenericLinuxDeviceTesterPrivate> d;
};
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/linuxprocessinterface.h b/src/plugins/remotelinux/linuxprocessinterface.h
new file mode 100644
index 00000000000..110e6939f8c
--- /dev/null
+++ b/src/plugins/remotelinux/linuxprocessinterface.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "remotelinux_export.h"
+
+#include "sshprocessinterface.h"
+
+namespace RemoteLinux {
+
+class LinuxDevice;
+class SshProcessInterfacePrivate;
+
+class REMOTELINUX_EXPORT LinuxProcessInterface : public SshProcessInterface
+{
+public:
+ LinuxProcessInterface(const LinuxDevice *linuxDevice);
+ ~LinuxProcessInterface();
+
+private:
+ void sendControlSignal(Utils::ControlSignal controlSignal) override;
+
+ void handleStarted(qint64 processId) final;
+ void handleDone(const Utils::ProcessResultData &resultData) final;
+ void handleReadyReadStandardOutput(const QByteArray &outputData) final;
+ void handleReadyReadStandardError(const QByteArray &errorData) final;
+
+ QString fullCommandLine(const Utils::CommandLine &commandLine) const final;
+
+ QByteArray m_output;
+ QByteArray m_error;
+ bool m_pidParsed = false;
+};
+
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp
index 9d51a024e4f..79a90814eea 100644
--- a/src/plugins/remotelinux/makeinstallstep.cpp
+++ b/src/plugins/remotelinux/makeinstallstep.cpp
@@ -31,10 +31,15 @@
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/deployconfiguration.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/kitinformation.h>
#include <projectexplorer/processparameters.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/target.h>
#include <projectexplorer/task.h>
+
+#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -56,7 +61,7 @@ const char CleanInstallRootAspectId[] = "RemoteLinux.MakeInstall.CleanInstallRoo
const char FullCommandLineAspectId[] = "RemoteLinux.MakeInstall.FullCommandLine";
const char CustomCommandLineAspectId[] = "RemoteLinux.MakeInstall.CustomCommandLine";
-MakeInstallStep::MakeInstallStep(BuildStepList *parent, Utils::Id id) : MakeStep(parent, id)
+MakeInstallStep::MakeInstallStep(BuildStepList *parent, Id id) : MakeStep(parent, id)
{
makeCommandAspect()->setVisible(false);
buildTargetsAspect()->setVisible(false);
@@ -66,7 +71,20 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Utils::Id id) : MakeStep
jobCountAspect()->setVisible(false);
disabledForSubdirsAspect()->setVisible(false);
- const auto makeAspect = addAspect<ExecutableAspect>();
+ // FIXME: Hack, Part#1: If the build device is not local, start with a temp dir
+ // inside the build dir. On Docker that's typically shared with the host.
+ const IDevice::ConstPtr device = BuildDeviceKitAspect::device(target()->kit());
+ const bool hack = device && device->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+ FilePath rootPath;
+ if (hack) {
+ rootPath = buildDirectory().pathAppended(".tmp-root");
+ } else {
+ QTemporaryDir tmpDir;
+ rootPath = FilePath::fromString(tmpDir.path());
+ }
+
+ const auto makeAspect = addAspect<ExecutableAspect>(parent->target(),
+ ExecutableAspect::BuildDevice);
makeAspect->setId(MakeAspectId);
makeAspect->setSettingsKey(MakeAspectId);
makeAspect->setDisplayStyle(StringAspect::PathChooserDisplay);
@@ -80,6 +98,7 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Utils::Id id) : MakeStep
installRootAspect->setDisplayStyle(StringAspect::PathChooserDisplay);
installRootAspect->setExpectedKind(PathChooser::Directory);
installRootAspect->setLabelText(tr("Install root:"));
+ installRootAspect->setFilePath(rootPath);
connect(installRootAspect, &StringAspect::changed,
this, &MakeInstallStep::updateArgsFromAspect);
@@ -88,7 +107,7 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Utils::Id id) : MakeStep
cleanInstallRootAspect->setSettingsKey(CleanInstallRootAspectId);
cleanInstallRootAspect->setLabel(tr("Clean install root first:"),
BoolAspect::LabelPlacement::InExtraLabel);
- cleanInstallRootAspect->setValue(false);
+ cleanInstallRootAspect->setValue(true);
const auto commandLineAspect = addAspect<StringAspect>();
commandLineAspect->setId(FullCommandLineAspectId);
@@ -108,17 +127,16 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Utils::Id id) : MakeStep
updateArgsFromAspect();
updateFromCustomCommandLineAspect();
};
+
connect(customCommandLineAspect, &StringAspect::checkedChanged, this, updateCommand);
connect(customCommandLineAspect, &StringAspect::changed,
this, &MakeInstallStep::updateFromCustomCommandLineAspect);
connect(target(), &Target::buildSystemUpdated, this, updateCommand);
- QTemporaryDir tmpDir;
- installRootAspect->setFilePath(FilePath::fromString(tmpDir.path()));
- const MakeInstallCommand cmd = target()->makeInstallCommand(tmpDir.path());
+ const MakeInstallCommand cmd = buildSystem()->makeInstallCommand(rootPath);
QTC_ASSERT(!cmd.command.isEmpty(), return);
- makeAspect->setExecutable(cmd.command);
+ makeAspect->setExecutable(cmd.command.executable());
}
Utils::Id MakeInstallStep::stepId()
@@ -141,22 +159,22 @@ bool MakeInstallStep::init()
{
if (!MakeStep::init())
return false;
- const QString rootDirPath = installRoot().toString();
- if (rootDirPath.isEmpty()) {
+
+ const FilePath rootDir = installRoot().onDevice(makeCommand());
+ if (rootDir.isEmpty()) {
emit addTask(BuildSystemTask(Task::Error, tr("You must provide an install root.")));
return false;
}
- QDir rootDir(rootDirPath);
if (cleanInstallRoot() && !rootDir.removeRecursively()) {
emit addTask(BuildSystemTask(Task::Error,
tr("The install root \"%1\" could not be cleaned.")
- .arg(installRoot().toUserOutput())));
+ .arg(rootDir.displayName())));
return false;
}
- if (!rootDir.exists() && !QDir::root().mkpath(rootDirPath)) {
+ if (!rootDir.exists() && !rootDir.createDir()) {
emit addTask(BuildSystemTask(Task::Error,
tr("The install root \"%1\" could not be created.")
- .arg(installRoot().toUserOutput())));
+ .arg(rootDir.displayName())));
return false;
}
if (this == deployConfiguration()->stepList()->steps().last()) {
@@ -165,8 +183,9 @@ bool MakeInstallStep::init()
"last in the list of deploy steps. "
"Consider moving it up.")));
}
- const MakeInstallCommand cmd = target()->makeInstallCommand(installRoot().toString());
- if (cmd.environment.size() > 0) {
+
+ const MakeInstallCommand cmd = buildSystem()->makeInstallCommand(rootDir);
+ if (cmd.environment.isValid()) {
Environment env = processParameters()->environment();
for (auto it = cmd.environment.constBegin(); it != cmd.environment.constEnd(); ++it) {
if (cmd.environment.isEnabled(it)) {
@@ -189,21 +208,37 @@ bool MakeInstallStep::init()
void MakeInstallStep::finish(bool success)
{
if (success) {
+ const bool hack = makeCommand().needsDevice();
+ const FilePath rootDir = installRoot().onDevice(makeCommand());
+
m_deploymentData = DeploymentData();
- m_deploymentData.setLocalInstallRoot(installRoot());
- QDirIterator dit(installRoot().toString(), QDir::Files | QDir::Hidden,
- QDirIterator::Subdirectories);
+ m_deploymentData.setLocalInstallRoot(rootDir);
+
+ const int startPos = rootDir.toString().length();
+
const auto appFileNames = transform<QSet<QString>>(buildSystem()->applicationTargets(),
[](const BuildTargetInfo &appTarget) { return appTarget.targetFilePath.fileName(); });
- while (dit.hasNext()) {
- dit.next();
- const QFileInfo fi = dit.fileInfo();
- const DeployableFile::Type type = appFileNames.contains(fi.fileName())
+
+ auto handleFile = [this, &appFileNames, startPos, hack](const FilePath &filePath) {
+ const DeployableFile::Type type = appFileNames.contains(filePath.fileName())
? DeployableFile::TypeExecutable
: DeployableFile::TypeNormal;
- m_deploymentData.addFile(FilePath::fromString(fi.filePath()),
- fi.dir().path().mid(installRoot().toString().length()), type);
- }
+ QString targetDir = filePath.parentDir().toString().mid(startPos);
+ // FIXME: This is conceptually the wrong place, but currently "downstream" like
+ // the rsync step doesn't handle full remote paths here.
+ targetDir = FilePath::fromString(targetDir).path();
+
+ // FIXME: Hack, Part#2: If the build was indeed not local, drop the remoteness.
+ // As we rely on shared build directory, this "maps" to the host.
+ if (hack)
+ m_deploymentData.addFile(FilePath::fromString(filePath.path()), targetDir, type);
+ else
+ m_deploymentData.addFile(filePath, targetDir, type);
+ return true;
+ };
+ rootDir.iterateDirectory(handleFile,
+ {{}, QDir::Files | QDir::Hidden, QDirIterator::Subdirectories});
+
buildSystem()->setDeploymentData(m_deploymentData);
} else if (m_noInstallTarget && m_isCmakeProject) {
emit addTask(DeploymentTask(Task::Warning, tr("You need to add an install statement "
@@ -243,9 +278,8 @@ void MakeInstallStep::updateArgsFromAspect()
{
if (customCommandLineAspect()->isChecked())
return;
- setUserArguments(ProcessArgs::joinArgs(target()->makeInstallCommand(
- static_cast<StringAspect *>(aspect(InstallRootAspectId))->filePath().toString())
- .arguments));
+ const CommandLine cmd = buildSystem()->makeInstallCommand(installRoot()).command;
+ setUserArguments(cmd.arguments());
updateFullCommandLine();
}
diff --git a/src/plugins/remotelinux/makeinstallstep.h b/src/plugins/remotelinux/makeinstallstep.h
index fd41291de8c..aff62afbf77 100644
--- a/src/plugins/remotelinux/makeinstallstep.h
+++ b/src/plugins/remotelinux/makeinstallstep.h
@@ -30,11 +30,6 @@
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/makestep.h>
-namespace Utils {
-class FilePath;
-class StringAspect;
-} // Utils
-
namespace RemoteLinux {
class REMOTELINUX_EXPORT MakeInstallStep : public ProjectExplorer::MakeStep
diff --git a/src/plugins/remotelinux/packageuploader.cpp b/src/plugins/remotelinux/packageuploader.cpp
deleted file mode 100644
index cb5af237840..00000000000
--- a/src/plugins/remotelinux/packageuploader.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "packageuploader.h"
-
-#include <utils/qtcassert.h>
-#include <ssh/sftptransfer.h>
-#include <ssh/sshconnection.h>
-
-using namespace QSsh;
-
-namespace RemoteLinux {
-namespace Internal {
-
-PackageUploader::PackageUploader(QObject *parent) :
- QObject(parent), m_state(Inactive), m_connection(nullptr)
-{
-}
-
-PackageUploader::~PackageUploader() = default;
-
-void PackageUploader::uploadPackage(SshConnection *connection,
- const QString &localFilePath, const QString &remoteFilePath)
-{
- QTC_ASSERT(m_state == Inactive, return);
-
- setState(Uploading);
- emit progress(tr("Preparing SFTP connection..."));
-
- m_connection = connection;
- connect(m_connection, &SshConnection::errorOccurred,
- this, &PackageUploader::handleConnectionFailure);
- m_uploader = m_connection->createUpload({FileToTransfer(localFilePath, remoteFilePath)},
- FileTransferErrorHandling::Abort);
- connect(m_uploader.get(), &SftpTransfer::done, this, &PackageUploader::handleUploadDone);
- m_uploader->start();
-}
-
-void PackageUploader::cancelUpload()
-{
- QTC_ASSERT(m_state == Uploading, return);
-
- setState(Inactive);
- emit uploadFinished(tr("Package upload canceled."));
-}
-
-void PackageUploader::handleConnectionFailure()
-{
- if (m_state == Inactive)
- return;
-
- const QString errorMsg = m_connection->errorString();
- setState(Inactive);
- emit uploadFinished(tr("Connection failed: %1").arg(errorMsg));
-}
-
-void PackageUploader::handleUploadDone(const QString &errorMsg)
-{
- QTC_ASSERT(m_state == Uploading, return);
-
- setState(Inactive);
- if (!errorMsg.isEmpty())
- emit uploadFinished(tr("Failed to upload package: %2").arg(errorMsg));
- else
- emit uploadFinished();
-}
-
-void PackageUploader::setState(State newState)
-{
- if (m_state == newState)
- return;
- if (newState == Inactive) {
- if (m_uploader) {
- disconnect(m_uploader.get(), nullptr, this, nullptr);
- m_uploader->stop();
- m_uploader.release()->deleteLater();
- }
- if (m_connection) {
- disconnect(m_connection, nullptr, this, nullptr);
- m_connection = nullptr;
- }
- }
- m_state = newState;
-}
-
-} // namespace Internal
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/packageuploader.h b/src/plugins/remotelinux/packageuploader.h
deleted file mode 100644
index 99499e9a16d..00000000000
--- a/src/plugins/remotelinux/packageuploader.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QObject>
-#include <QString>
-
-#include <ssh/sftpdefs.h>
-
-namespace QSsh {
-class SftpChannel;
-class SshConnection;
-}
-
-namespace RemoteLinux {
-namespace Internal {
-
-class PackageUploader : public QObject
-{
- Q_OBJECT
-public:
- explicit PackageUploader(QObject *parent = nullptr);
- ~PackageUploader() override;
-
- // Connection has to be established already.
- void uploadPackage(QSsh::SshConnection *connection,
- const QString &localFilePath, const QString &remoteFilePath);
- void cancelUpload();
-
-signals:
- void progress(const QString &message);
- void uploadFinished(const QString &errorMsg = QString());
-
-private:
- enum State { Uploading, Inactive };
-
- void handleConnectionFailure();
- void handleUploadDone(const QString &error);
- void setState(State newState);
-
- State m_state;
- QSsh::SshConnection *m_connection;
- QSsh::SftpTransferPtr m_uploader;
-};
-
-} // namespace Internal
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/publickeydeploymentdialog.cpp b/src/plugins/remotelinux/publickeydeploymentdialog.cpp
index fd43803a262..3ba3f011d70 100644
--- a/src/plugins/remotelinux/publickeydeploymentdialog.cpp
+++ b/src/plugins/remotelinux/publickeydeploymentdialog.cpp
@@ -25,10 +25,11 @@
#include "publickeydeploymentdialog.h"
-#include "sshkeydeployer.h"
-
-#include <coreplugin/icore.h>
-#include <ssh/sshconnection.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/sshparameters.h>
+#include <projectexplorer/devicesupport/sshsettings.h>
+#include <utils/fileutils.h>
+#include <utils/qtcprocess.h>
#include <utils/theme/theme.h>
using namespace ProjectExplorer;
@@ -36,11 +37,12 @@ using namespace Utils;
namespace RemoteLinux {
namespace Internal {
+
class PublicKeyDeploymentDialogPrivate
{
public:
- SshKeyDeployer keyDeployer;
- bool done;
+ QtcProcess m_process;
+ bool m_done;
};
} // namespace Internal;
@@ -67,60 +69,85 @@ PublicKeyDeploymentDialog::PublicKeyDeploymentDialog(const IDevice::ConstPtr &de
setMinimumDuration(0);
setMaximum(1);
- d->done = false;
+ d->m_done = false;
setLabelText(tr("Deploying..."));
setValue(0);
- connect(this, &PublicKeyDeploymentDialog::canceled,
- this, &PublicKeyDeploymentDialog::handleCanceled);
- connect(&d->keyDeployer, &SshKeyDeployer::error,
- this, &PublicKeyDeploymentDialog::handleDeploymentError);
- connect(&d->keyDeployer, &SshKeyDeployer::finishedSuccessfully,
- this, &PublicKeyDeploymentDialog::handleDeploymentSuccess);
- d->keyDeployer.deployPublicKey(deviceConfig->sshParameters(), publicKeyFileName);
-}
+ connect(this, &PublicKeyDeploymentDialog::canceled, this,
+ [this] { d->m_done ? accept() : reject(); });
+ connect(&d->m_process, &QtcProcess::done, this, [this] {
+ const bool succeeded = d->m_process.result() == ProcessResult::FinishedWithSuccess;
+ QString finalMessage;
+ if (!succeeded) {
+ QString errorMessage = d->m_process.errorString();
+ if (errorMessage.isEmpty())
+ errorMessage = d->m_process.cleanedStdErr();
+ if (errorMessage.endsWith('\n'))
+ errorMessage.chop(1);
+ finalMessage = tr("Key deployment failed.");
+ if (!errorMessage.isEmpty())
+ finalMessage += '\n' + errorMessage;
+ }
+ handleDeploymentDone(succeeded, finalMessage);
+ });
-PublicKeyDeploymentDialog::~PublicKeyDeploymentDialog()
-{
- delete d;
-}
+ FileReader reader;
+ if (!reader.fetch(publicKeyFileName)) {
+ handleDeploymentDone(false, tr("Public key error: %1").arg(reader.errorString()));
+ return;
+ }
-void PublicKeyDeploymentDialog::handleDeploymentSuccess()
-{
- handleDeploymentFinished(QString());
- setValue(1);
- d->done = true;
+ const QString command = "test -d .ssh || mkdir -p ~/.ssh && chmod 0700 .ssh && echo '"
+ + QString::fromLocal8Bit(reader.data())
+ + "' >> .ssh/authorized_keys && chmod 0600 .ssh/authorized_keys";
+
+ const SshParameters params = deviceConfig->sshParameters();
+ const QString hostKeyCheckingString = params.hostKeyCheckingMode == SshHostKeyCheckingStrict
+ ? QLatin1String("yes") : QLatin1String("no");
+ const bool isWindows = HostOsInfo::isWindowsHost()
+ && SshSettings::sshFilePath().toString().toLower().contains("/system32/");
+ const bool useTimeout = (params.timeout != 0) && !isWindows;
+
+ Utils::CommandLine cmd{SshSettings::sshFilePath()};
+ QStringList args{"-q",
+ "-o", "StrictHostKeyChecking=" + hostKeyCheckingString,
+ "-o", "Port=" + QString::number(params.port())};
+ if (!params.userName().isEmpty())
+ args << "-o" << "User=" + params.userName();
+ args << "-o" << "BatchMode=no";
+ if (useTimeout)
+ args << "-o" << "ConnectTimeout=" + QString::number(params.timeout);
+ args << params.host();
+ cmd.addArgs(args);
+
+ CommandLine execCmd;
+ execCmd.addArg("exec");
+ execCmd.addCommandLineAsArgs({"/bin/sh", {"-c", command}}, CommandLine::Raw);
+
+ cmd.addArg(execCmd.arguments());
+ d->m_process.setCommand(cmd);
+ SshParameters::setupSshEnvironment(&d->m_process);
+ d->m_process.start();
}
-void PublicKeyDeploymentDialog::handleDeploymentError(const QString &errorMsg)
+PublicKeyDeploymentDialog::~PublicKeyDeploymentDialog()
{
- handleDeploymentFinished(errorMsg);
+ delete d;
}
-void PublicKeyDeploymentDialog::handleDeploymentFinished(const QString &errorMsg)
+void PublicKeyDeploymentDialog::handleDeploymentDone(bool succeeded, const QString &errorMessage)
{
- QString buttonText;
- QString textColor;
- if (errorMsg.isEmpty()) {
- buttonText = tr("Deployment finished successfully.");
- textColor = Utils::creatorTheme()->color(Utils::Theme::TextColorNormal).name();
- } else {
- buttonText = errorMsg;
- textColor = Utils::creatorTheme()->color(Utils::Theme::TextColorError).name();
- }
+ QString buttonText = succeeded ? tr("Deployment finished successfully.") : errorMessage;
+ const QString textColor = creatorTheme()->color(
+ succeeded ? Theme::TextColorNormal : Theme::TextColorError).name();
setLabelText(QString::fromLatin1("<font color=\"%1\">%2</font>")
- .arg(textColor)
- .arg(buttonText.replace("\n", "<br/>")));
+ .arg(textColor, buttonText.replace("\n", "<br/>")));
setCancelButtonText(tr("Close"));
-}
-void PublicKeyDeploymentDialog::handleCanceled()
-{
- disconnect(&d->keyDeployer, nullptr, this, nullptr);
- d->keyDeployer.stopDeployment();
- if (d->done)
- accept();
- else
- reject();
+ if (!succeeded)
+ return;
+
+ setValue(1);
+ d->m_done = true;
}
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/publickeydeploymentdialog.h b/src/plugins/remotelinux/publickeydeploymentdialog.h
index e2792cc376f..2d533782fc5 100644
--- a/src/plugins/remotelinux/publickeydeploymentdialog.h
+++ b/src/plugins/remotelinux/publickeydeploymentdialog.h
@@ -27,10 +27,12 @@
#include "remotelinux_export.h"
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
#include <QProgressDialog>
+namespace Utils { class FilePath; }
+
namespace RemoteLinux {
namespace Internal { class PublicKeyDeploymentDialogPrivate; }
@@ -39,19 +41,16 @@ class REMOTELINUX_EXPORT PublicKeyDeploymentDialog : public QProgressDialog
Q_OBJECT
public:
// Asks for public key and returns null if the file dialog is canceled.
- static PublicKeyDeploymentDialog *createDialog(const ProjectExplorer::IDevice::ConstPtr &deviceConfig,
+ static PublicKeyDeploymentDialog *createDialog(const ProjectExplorer::IDeviceConstPtr &deviceConfig,
QWidget *parent = nullptr);
- PublicKeyDeploymentDialog(const ProjectExplorer::IDevice::ConstPtr &deviceConfig,
+ PublicKeyDeploymentDialog(const ProjectExplorer::IDeviceConstPtr &deviceConfig,
const Utils::FilePath &publicKeyFileName, QWidget *parent = nullptr);
~PublicKeyDeploymentDialog() override;
private:
- void handleDeploymentFinished(const QString &errorMsg);
- void handleDeploymentError(const QString &errorMsg);
- void handleDeploymentSuccess();
- void handleCanceled();
+ void handleDeploymentDone(bool succeeded, const QString &errorMessage);
Internal::PublicKeyDeploymentDialogPrivate * const d;
};
diff --git a/src/plugins/remotelinux/remotelinux.qbs b/src/plugins/remotelinux/remotelinux.qbs
index 8c8d8c63eed..8aaf6fbcc2e 100644
--- a/src/plugins/remotelinux/remotelinux.qbs
+++ b/src/plugins/remotelinux/remotelinux.qbs
@@ -5,7 +5,6 @@ Project {
QtcPlugin {
Depends { name: "Qt.widgets" }
- Depends { name: "QtcSsh" }
Depends { name: "QmlDebug" }
Depends { name: "Utils" }
@@ -14,16 +13,14 @@ Project {
Depends { name: "ProjectExplorer" }
files: [
- "abstractpackagingstep.cpp",
- "abstractpackagingstep.h",
"abstractremotelinuxdeployservice.cpp",
"abstractremotelinuxdeployservice.h",
"abstractremotelinuxdeploystep.cpp",
"abstractremotelinuxdeploystep.h",
- "abstractuploadandinstallpackageservice.cpp",
- "abstractuploadandinstallpackageservice.h",
"deploymenttimeinfo.cpp",
"deploymenttimeinfo.h",
+ "customcommanddeploystep.cpp",
+ "customcommanddeploystep.h",
"genericdirectuploadservice.cpp",
"genericdirectuploadservice.h",
"genericdirectuploadstep.cpp",
@@ -36,29 +33,20 @@ Project {
"genericlinuxdeviceconfigurationwizardpages.cpp",
"genericlinuxdeviceconfigurationwizardpages.h",
"genericlinuxdeviceconfigurationwizardsetuppage.ui",
+ "killappstep.cpp",
+ "killappstep.h",
"linuxdevice.cpp",
"linuxdevice.h",
- "linuxdeviceprocess.cpp",
- "linuxdeviceprocess.h",
"linuxdevicetester.cpp",
"linuxdevicetester.h",
+ "linuxprocessinterface.h",
"makeinstallstep.cpp",
"makeinstallstep.h",
- "packageuploader.cpp",
- "packageuploader.h",
"publickeydeploymentdialog.cpp",
"publickeydeploymentdialog.h",
"remotelinux.qrc",
"remotelinux_constants.h",
"remotelinux_export.h",
- "remotelinuxcheckforfreediskspaceservice.cpp",
- "remotelinuxcheckforfreediskspaceservice.h",
- "remotelinuxcheckforfreediskspacestep.cpp",
- "remotelinuxcheckforfreediskspacestep.h",
- "remotelinuxcustomcommanddeploymentstep.cpp",
- "remotelinuxcustomcommanddeploymentstep.h",
- "remotelinuxcustomcommanddeployservice.cpp",
- "remotelinuxcustomcommanddeployservice.h",
"remotelinuxcustomrunconfiguration.cpp",
"remotelinuxcustomrunconfiguration.h",
"remotelinuxdebugsupport.cpp",
@@ -71,12 +59,6 @@ Project {
"remotelinuxenvironmentaspectwidget.h",
"remotelinuxenvironmentreader.cpp",
"remotelinuxenvironmentreader.h",
- "remotelinuxkillappservice.cpp",
- "remotelinuxkillappservice.h",
- "remotelinuxkillappstep.cpp",
- "remotelinuxkillappstep.h",
- "remotelinuxpackageinstaller.cpp",
- "remotelinuxpackageinstaller.h",
"remotelinuxplugin.cpp",
"remotelinuxplugin.h",
"remotelinuxqmltoolingsupport.cpp",
@@ -85,16 +67,18 @@ Project {
"remotelinuxrunconfiguration.h",
"remotelinuxsignaloperation.cpp",
"remotelinuxsignaloperation.h",
- "remotelinuxx11forwardingaspect.cpp",
- "remotelinuxx11forwardingaspect.h",
"rsyncdeploystep.cpp",
"rsyncdeploystep.h",
- "sshkeydeployer.cpp",
- "sshkeydeployer.h",
+ "sshkeycreationdialog.cpp",
+ "sshkeycreationdialog.h",
+ "sshkeycreationdialog.ui",
+ "sshprocessinterface.h",
"tarpackagecreationstep.cpp",
"tarpackagecreationstep.h",
- "uploadandinstalltarpackagestep.cpp",
- "uploadandinstalltarpackagestep.h",
+ "tarpackagedeploystep.cpp",
+ "tarpackagedeploystep.h",
+ "x11forwardingaspect.cpp",
+ "x11forwardingaspect.h",
"images/embeddedtarget.png",
]
@@ -110,7 +94,6 @@ Project {
Export {
Depends { name: "Debugger" }
Depends { name: "Core" }
- Depends { name: "QtcSsh" }
}
}
}
diff --git a/src/plugins/remotelinux/remotelinux_constants.h b/src/plugins/remotelinux/remotelinux_constants.h
index c3fcdad4a51..909d327e5d3 100644
--- a/src/plugins/remotelinux/remotelinux_constants.h
+++ b/src/plugins/remotelinux/remotelinux_constants.h
@@ -30,11 +30,12 @@ namespace Constants {
const char GenericLinuxOsType[] = "GenericLinuxOsType";
-const char CheckForFreeDiskSpaceId[] = "RemoteLinux.CheckForFreeDiskSpaceStep";
+const char DeployToGenericLinux[] = "DeployToGenericLinux";
+
const char DirectUploadStepId[] = "RemoteLinux.DirectUploadStep";
const char MakeInstallStepId[] = "RemoteLinux.MakeInstall";
const char TarPackageCreationStepId[] = "MaemoTarPackageCreationStep";
-const char UploadAndInstallTarPackageStepId[] = "MaemoUploadAndInstallTarPackageStep";
+const char TarPackageDeployStepId[] = "MaemoUploadAndInstallTarPackageStep";
const char RsyncDeployStepId[] = "RemoteLinux.RsyncDeployStep";
const char CustomCommandDeployStepId[] = "RemoteLinux.GenericRemoteLinuxCustomCommandDeploymentStep";
const char KillAppStepId[] = "RemoteLinux.KillAppStep";
diff --git a/src/plugins/remotelinux/remotelinux_export.h b/src/plugins/remotelinux/remotelinux_export.h
index e9df11a1f03..7b681a4d54b 100644
--- a/src/plugins/remotelinux/remotelinux_export.h
+++ b/src/plugins/remotelinux/remotelinux_export.h
@@ -29,6 +29,8 @@
#if defined(REMOTELINUX_LIBRARY)
# define REMOTELINUX_EXPORT Q_DECL_EXPORT
+#elif defined(REMOTELINUX_STATIC_LIBRARY)
+# define REMOTELINUX_EXPORT
#else
# define REMOTELINUX_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp
deleted file mode 100644
index bb1b67a746b..00000000000
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotelinuxcheckforfreediskspaceservice.h"
-
-#include <ssh/sshremoteprocessrunner.h>
-#include <utils/fileutils.h>
-
-#include <QScopeGuard>
-
-namespace RemoteLinux {
-namespace Internal {
-class RemoteLinuxCheckForFreeDiskSpaceServicePrivate
-{
-public:
- QString pathToCheck;
- quint64 requiredSpaceInBytes = 0;
-};
-} // namespace Internal
-
-RemoteLinuxCheckForFreeDiskSpaceService::RemoteLinuxCheckForFreeDiskSpaceService(QObject *parent)
- : AbstractRemoteLinuxDeployService(parent),
- d(new Internal::RemoteLinuxCheckForFreeDiskSpaceServicePrivate)
-{
-}
-
-RemoteLinuxCheckForFreeDiskSpaceService::~RemoteLinuxCheckForFreeDiskSpaceService()
-{
- delete d;
-}
-
-void RemoteLinuxCheckForFreeDiskSpaceService::setPathToCheck(const QString &path)
-{
- d->pathToCheck = path;
-}
-
-void RemoteLinuxCheckForFreeDiskSpaceService::setRequiredSpaceInBytes(quint64 sizeInBytes)
-{
- d->requiredSpaceInBytes = sizeInBytes;
-}
-
-void RemoteLinuxCheckForFreeDiskSpaceService::deployAndFinish()
-{
- auto cleanup = qScopeGuard([this] { setFinished(); });
- const Utils::FilePath path
- = deviceConfiguration()->mapToGlobalPath(Utils::FilePath::fromString(d->pathToCheck));
- const qint64 freeSpace = path.bytesAvailable();
- if (freeSpace < 0) {
- emit errorMessage(tr("Cannot get info about free disk space for \"%1\"")
- .arg(path.toUserOutput()));
- return;
- }
-
- const qint64 mb = 1024 * 1024;
- const qint64 freeSpaceMB = freeSpace / mb;
- const qint64 requiredSpaceMB = d->requiredSpaceInBytes / mb;
-
- if (freeSpaceMB < requiredSpaceMB) {
- emit errorMessage(tr("The remote file system has only %n megabytes of free space, "
- "but %1 megabytes are required.", nullptr, freeSpaceMB)
- .arg(requiredSpaceMB));
- return;
- }
-
- emit progressMessage(tr("The remote file system has %n megabytes of free space, going ahead.",
- nullptr, freeSpaceMB));
-}
-
-CheckResult RemoteLinuxCheckForFreeDiskSpaceService::isDeploymentPossible() const
-{
- if (!d->pathToCheck.startsWith(QLatin1Char('/'))) {
- return CheckResult::failure(
- tr("Cannot check for free disk space: \"%1\" is not an absolute path.")
- .arg(d->pathToCheck));
- }
-
- return AbstractRemoteLinuxDeployService::isDeploymentPossible();
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h
deleted file mode 100644
index 3d565d37d7b..00000000000
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "abstractremotelinuxdeployservice.h"
-
-namespace RemoteLinux {
-namespace Internal { class RemoteLinuxCheckForFreeDiskSpaceServicePrivate; }
-
-class REMOTELINUX_EXPORT RemoteLinuxCheckForFreeDiskSpaceService :
- public AbstractRemoteLinuxDeployService
-{
- Q_OBJECT
-public:
- RemoteLinuxCheckForFreeDiskSpaceService(QObject *parent = nullptr);
- ~RemoteLinuxCheckForFreeDiskSpaceService() override;
-
- void setPathToCheck(const QString &path);
- void setRequiredSpaceInBytes(quint64 sizeInBytes);
-
-private:
- void deployAndFinish();
- bool isDeploymentNecessary() const override { return true; }
-
- CheckResult isDeploymentPossible() const override;
- void doDeviceSetup() final { deployAndFinish(); }
- void stopDeviceSetup() final { }
-
- void doDeploy() final {};
- void stopDeployment() final {};
-
- Internal::RemoteLinuxCheckForFreeDiskSpaceServicePrivate * const d;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp b/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp
deleted file mode 100644
index 5d074a83534..00000000000
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotelinuxcheckforfreediskspacestep.h"
-
-#include "remotelinuxcheckforfreediskspaceservice.h"
-
-#include <utils/aspects.h>
-
-#include <limits>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace RemoteLinux {
-
-RemoteLinuxCheckForFreeDiskSpaceStep::RemoteLinuxCheckForFreeDiskSpaceStep
- (BuildStepList *bsl, Utils::Id id)
- : AbstractRemoteLinuxDeployStep(bsl, id)
-{
- auto service = createDeployService<RemoteLinuxCheckForFreeDiskSpaceService>();
-
- auto pathToCheckAspect = addAspect<StringAspect>();
- pathToCheckAspect->setSettingsKey("RemoteLinux.CheckForFreeDiskSpaceStep.PathToCheck");
- pathToCheckAspect->setDisplayStyle(StringAspect::LineEditDisplay);
- pathToCheckAspect->setValue("/");
- pathToCheckAspect->setLabelText(tr("Remote path to check for free space:"));
-
- auto requiredSpaceAspect = addAspect<IntegerAspect>();
- requiredSpaceAspect->setSettingsKey("RemoteLinux.CheckForFreeDiskSpaceStep.RequiredSpace");
- requiredSpaceAspect->setLabel(tr("Required disk space:"));
- requiredSpaceAspect->setDisplayScaleFactor(1024*1024);
- requiredSpaceAspect->setValue(5*1024*1024);
- requiredSpaceAspect->setSuffix(tr("MB"));
- requiredSpaceAspect->setRange(1, std::numeric_limits<int>::max());
-
- setInternalInitializer([service, pathToCheckAspect, requiredSpaceAspect] {
- service->setPathToCheck(pathToCheckAspect->value());
- service->setRequiredSpaceInBytes(requiredSpaceAspect->value());
- return CheckResult::success();
- });
-}
-
-RemoteLinuxCheckForFreeDiskSpaceStep::~RemoteLinuxCheckForFreeDiskSpaceStep() = default;
-
-Utils::Id RemoteLinuxCheckForFreeDiskSpaceStep::stepId()
-{
- return "RemoteLinux.CheckForFreeDiskSpaceStep";
-}
-
-QString RemoteLinuxCheckForFreeDiskSpaceStep::displayName()
-{
- return tr("Check for free disk space");
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h b/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h
deleted file mode 100644
index 723b4f19b32..00000000000
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "abstractremotelinuxdeploystep.h"
-
-namespace RemoteLinux {
-
-class REMOTELINUX_EXPORT RemoteLinuxCheckForFreeDiskSpaceStep : public AbstractRemoteLinuxDeployStep
-{
- Q_OBJECT
-
-public:
- RemoteLinuxCheckForFreeDiskSpaceStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
- ~RemoteLinuxCheckForFreeDiskSpaceStep() override;
-
- static Utils::Id stepId();
- static QString displayName();
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp b/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp
deleted file mode 100644
index 68cba388052..00000000000
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotelinuxcustomcommanddeploymentstep.h"
-
-#include "remotelinux_constants.h"
-#include "remotelinuxcustomcommanddeployservice.h"
-
-#include <projectexplorer/runconfigurationaspects.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace RemoteLinux {
-
-RemoteLinuxCustomCommandDeploymentStep::RemoteLinuxCustomCommandDeploymentStep
- (BuildStepList *bsl, Utils::Id id)
- : AbstractRemoteLinuxDeployStep(bsl, id)
-{
- auto service = createDeployService<RemoteLinuxCustomCommandDeployService>();
-
- auto commandLine = addAspect<StringAspect>();
- commandLine->setSettingsKey("RemoteLinuxCustomCommandDeploymentStep.CommandLine");
- commandLine->setLabelText(tr("Command line:"));
- commandLine->setDisplayStyle(StringAspect::LineEditDisplay);
- commandLine->setHistoryCompleter("RemoteLinuxCustomCommandDeploymentStep.History");
-
- setInternalInitializer([service, commandLine] {
- service->setCommandLine(commandLine->value().trimmed());
- return service->isDeploymentPossible();
- });
-
- addMacroExpander();
-}
-
-RemoteLinuxCustomCommandDeploymentStep::~RemoteLinuxCustomCommandDeploymentStep() = default;
-
-Utils::Id RemoteLinuxCustomCommandDeploymentStep::stepId()
-{
- return Constants::CustomCommandDeployStepId;
-}
-
-QString RemoteLinuxCustomCommandDeploymentStep::displayName()
-{
- return tr("Run custom remote command");
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h b/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h
deleted file mode 100644
index 7200c201a0f..00000000000
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "abstractremotelinuxdeploystep.h"
-
-namespace RemoteLinux {
-
-class REMOTELINUX_EXPORT RemoteLinuxCustomCommandDeploymentStep
- : public AbstractRemoteLinuxDeployStep
-{
- Q_OBJECT
-
-public:
- RemoteLinuxCustomCommandDeploymentStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
- ~RemoteLinuxCustomCommandDeploymentStep() override;
-
- static Utils::Id stepId();
- static QString displayName();
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
deleted file mode 100644
index 7b7f59efd5c..00000000000
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotelinuxcustomcommanddeployservice.h"
-
-#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
-#include <ssh/sshremoteprocessrunner.h>
-
-using namespace QSsh;
-
-namespace RemoteLinux {
-namespace Internal {
-namespace {
-enum State { Inactive, Running };
-}
-
-class RemoteLinuxCustomCommandDeployservicePrivate
-{
-public:
- QString commandLine;
- State state = Inactive;
- SshRemoteProcessRunner *runner = nullptr;
-};
-
-} // namespace Internal
-
-using namespace Internal;
-
-
-RemoteLinuxCustomCommandDeployService::RemoteLinuxCustomCommandDeployService(QObject *parent)
- : AbstractRemoteLinuxDeployService(parent), d(new RemoteLinuxCustomCommandDeployservicePrivate)
-{
-}
-
-RemoteLinuxCustomCommandDeployService::~RemoteLinuxCustomCommandDeployService()
-{
- delete d;
-}
-
-void RemoteLinuxCustomCommandDeployService::setCommandLine(const QString &commandLine)
-{
- QTC_ASSERT(d->state == Inactive, return);
-
- d->commandLine = commandLine;
-}
-
-CheckResult RemoteLinuxCustomCommandDeployService::isDeploymentPossible() const
-{
- QTC_ASSERT(d->state == Inactive, return CheckResult::failure());
-
- if (d->commandLine.isEmpty())
- return CheckResult::failure(tr("No command line given."));
-
- return AbstractRemoteLinuxDeployService::isDeploymentPossible();
-}
-
-void RemoteLinuxCustomCommandDeployService::doDeploy()
-{
- QTC_ASSERT(d->state == Inactive, handleDeploymentDone());
-
- if (!d->runner)
- d->runner = new SshRemoteProcessRunner(this);
- connect(d->runner, &SshRemoteProcessRunner::readyReadStandardOutput,
- this, &RemoteLinuxCustomCommandDeployService::handleStdout);
- connect(d->runner, &SshRemoteProcessRunner::readyReadStandardError,
- this, &RemoteLinuxCustomCommandDeployService::handleStderr);
- connect(d->runner, &SshRemoteProcessRunner::processClosed,
- this, &RemoteLinuxCustomCommandDeployService::handleProcessClosed);
-
- emit progressMessage(tr("Starting remote command \"%1\"...").arg(d->commandLine));
- d->state = Running;
- d->runner->run(d->commandLine, deviceConfiguration()->sshParameters());
-}
-
-void RemoteLinuxCustomCommandDeployService::stopDeployment()
-{
- QTC_ASSERT(d->state == Running, return);
-
- disconnect(d->runner, nullptr, this, nullptr);
- d->runner->cancel();
- d->state = Inactive;
- handleDeploymentDone();
-}
-
-void RemoteLinuxCustomCommandDeployService::handleStdout()
-{
- emit stdOutData(QString::fromUtf8(d->runner->readAllStandardOutput()));
-}
-
-void RemoteLinuxCustomCommandDeployService::handleStderr()
-{
- emit stdErrData(QString::fromUtf8(d->runner->readAllStandardError()));
-}
-
-void RemoteLinuxCustomCommandDeployService::handleProcessClosed(const QString &error)
-{
- QTC_ASSERT(d->state == Running, return);
-
- if (!error.isEmpty()) {
- emit errorMessage(tr("Remote process failed: %1").arg(error));
- } else if (d->runner->processExitCode() != 0) {
- emit errorMessage(tr("Remote process finished with exit code %1.")
- .arg(d->runner->processExitCode()));
- } else {
- emit progressMessage(tr("Remote command finished successfully."));
- }
-
- stopDeployment();
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h
deleted file mode 100644
index ee0ff0ebcc1..00000000000
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "abstractremotelinuxdeployservice.h"
-
-namespace RemoteLinux {
-namespace Internal { class RemoteLinuxCustomCommandDeployservicePrivate; }
-
-class REMOTELINUX_EXPORT RemoteLinuxCustomCommandDeployService
- : public AbstractRemoteLinuxDeployService
-{
- Q_OBJECT
-public:
- explicit RemoteLinuxCustomCommandDeployService(QObject *parent = nullptr);
- ~RemoteLinuxCustomCommandDeployService() override;
-
- void setCommandLine(const QString &commandLine);
-
- bool isDeploymentNecessary() const override { return true; }
- CheckResult isDeploymentPossible() const override;
-
-protected:
- void doDeploy() override;
- void stopDeployment() override;
-
-private:
- void handleStdout();
- void handleStderr();
- void handleProcessClosed(const QString &error);
-
- Internal::RemoteLinuxCustomCommandDeployservicePrivate *d;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
index b3604332d17..38668ae1b54 100644
--- a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
@@ -27,7 +27,7 @@
#include "remotelinux_constants.h"
#include "remotelinuxenvironmentaspect.h"
-#include "remotelinuxx11forwardingaspect.h"
+#include "x11forwardingaspect.h"
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/runcontrol.h>
@@ -57,10 +57,11 @@ private:
RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- auto exeAspect = addAspect<ExecutableAspect>();
+ auto envAspect = addAspect<RemoteLinuxEnvironmentAspect>(target);
+
+ auto exeAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
exeAspect->setSettingsKey("RemoteLinux.CustomRunConfig.RemoteExecutable");
exeAspect->setLabelText(tr("Remote executable:"));
- exeAspect->setExecutablePathStyle(OsTypeLinux);
exeAspect->setDisplayStyle(StringAspect::LineEditDisplay);
exeAspect->setHistoryCompleter("RemoteLinux.CustomExecutable.History");
exeAspect->setExpectedKind(PathChooser::Any);
@@ -70,17 +71,16 @@ RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(Target *tar
symbolsAspect->setLabelText(tr("Local executable:"));
symbolsAspect->setDisplayStyle(SymbolFileAspect::PathChooserDisplay);
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
if (HostOsInfo::isAnyUnixHost())
addAspect<TerminalAspect>();
- addAspect<RemoteLinuxEnvironmentAspect>(target);
if (HostOsInfo::isAnyUnixHost())
- addAspect<X11ForwardingAspect>();
+ addAspect<X11ForwardingAspect>(macroExpander());
setRunnableModifier([this](Runnable &r) {
if (const auto * const forwardingAspect = aspect<X11ForwardingAspect>())
- r.extraData.insert("Ssh.X11ForwardToDisplay", forwardingAspect->display(macroExpander()));
+ r.extraData.insert("Ssh.X11ForwardToDisplay", forwardingAspect->display());
});
setDefaultDisplayName(runConfigDefaultDisplayName());
diff --git a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
index 9a54527eba7..37a44298017 100644
--- a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
@@ -25,14 +25,10 @@
#include "remotelinuxdeployconfiguration.h"
-#include "genericdirectuploadstep.h"
#include "makeinstallstep.h"
-#include "remotelinuxcheckforfreediskspacestep.h"
-#include "remotelinuxkillappstep.h"
#include "remotelinux_constants.h"
-#include "rsyncdeploystep.h"
-#include <projectexplorer/abi.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
@@ -42,19 +38,11 @@
using namespace ProjectExplorer;
namespace RemoteLinux {
-
-using namespace Internal;
-
-Utils::Id genericDeployConfigurationId()
-{
- return "DeployToGenericLinux";
-}
-
namespace Internal {
RemoteLinuxDeployConfigurationFactory::RemoteLinuxDeployConfigurationFactory()
{
- setConfigBaseId(genericDeployConfigurationId());
+ setConfigBaseId(RemoteLinux::Constants::DeployToGenericLinux);
addSupportedTargetDeviceType(RemoteLinux::Constants::GenericLinuxOsType);
setDefaultDisplayName(QCoreApplication::translate("RemoteLinux",
"Deploy to Remote Linux Host"));
@@ -74,14 +62,13 @@ RemoteLinuxDeployConfigurationFactory::RemoteLinuxDeployConfigurationFactory()
}
});
- addInitialStep(MakeInstallStep::stepId(), needsMakeInstall);
- addInitialStep(RemoteLinuxCheckForFreeDiskSpaceStep::stepId());
- addInitialStep(RemoteLinuxKillAppStep::stepId());
- addInitialStep(RsyncDeployStep::stepId(), [](Target *target) {
+ addInitialStep(Constants::MakeInstallStepId, needsMakeInstall);
+ addInitialStep(Constants::KillAppStepId);
+ addInitialStep(Constants::RsyncDeployStepId, [](Target *target) {
auto device = DeviceKitAspect::device(target->kit());
return device && device->extraData(Constants::SupportsRSync).toBool();
});
- addInitialStep(GenericDirectUploadStep::stepId(), [](Target *target) {
+ addInitialStep(Constants::DirectUploadStepId, [](Target *target) {
auto device = DeviceKitAspect::device(target->kit());
return device && !device->extraData(Constants::SupportsRSync).toBool();
});
diff --git a/src/plugins/remotelinux/remotelinuxdeployconfiguration.h b/src/plugins/remotelinux/remotelinuxdeployconfiguration.h
index 723c6b30380..3a4c803d219 100644
--- a/src/plugins/remotelinux/remotelinuxdeployconfiguration.h
+++ b/src/plugins/remotelinux/remotelinuxdeployconfiguration.h
@@ -25,15 +25,9 @@
#pragma once
-#include "remotelinux_export.h"
-
-#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/deployconfiguration.h>
namespace RemoteLinux {
-
-Utils::Id genericDeployConfigurationId();
-
namespace Internal {
class RemoteLinuxDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory
diff --git a/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp b/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp
index 0aab43c44ab..a3016371044 100644
--- a/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp
+++ b/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp
@@ -26,7 +26,7 @@
#include "remotelinuxenvironmentaspectwidget.h"
#include "linuxdevice.h"
-#include "remotelinuxrunconfiguration.h"
+#include "remotelinuxenvironmentaspect.h"
#include "remotelinuxenvironmentreader.h"
#include <coreplugin/icore.h>
@@ -52,21 +52,22 @@ const QString FetchEnvButtonText
namespace RemoteLinux {
RemoteLinuxEnvironmentAspectWidget::RemoteLinuxEnvironmentAspectWidget
- (RemoteLinuxEnvironmentAspect *aspect, Target *target) :
- EnvironmentAspectWidget(aspect, new QPushButton)
+ (RemoteLinuxEnvironmentAspect *aspect, Target *target)
+ : EnvironmentAspectWidget(aspect)
+ , m_fetchButton(new QPushButton(FetchEnvButtonText))
{
+ addWidget(m_fetchButton);
+
IDevice::ConstPtr device = DeviceKitAspect::device(target->kit());
- deviceEnvReader = new RemoteLinuxEnvironmentReader(device, this);
+ m_deviceEnvReader = new RemoteLinuxEnvironmentReader(device, this);
connect(target, &ProjectExplorer::Target::kitChanged,
- deviceEnvReader, &RemoteLinuxEnvironmentReader::handleCurrentDeviceConfigChanged);
+ m_deviceEnvReader, &RemoteLinuxEnvironmentReader::handleCurrentDeviceConfigChanged);
- QPushButton *button = fetchButton();
- button->setText(FetchEnvButtonText);
- connect(button, &QPushButton::clicked, this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironment);
- connect(deviceEnvReader, &RemoteLinuxEnvironmentReader::finished,
+ connect(m_fetchButton, &QPushButton::clicked, this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironment);
+ connect(m_deviceEnvReader, &RemoteLinuxEnvironmentReader::finished,
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentFinished);
- connect(deviceEnvReader, &RemoteLinuxEnvironmentReader::error,
+ connect(m_deviceEnvReader, &RemoteLinuxEnvironmentReader::error,
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentError);
const EnvironmentWidget::OpenTerminalFunc openTerminalFunc
@@ -85,36 +86,25 @@ RemoteLinuxEnvironmentAspectWidget::RemoteLinuxEnvironmentAspectWidget
envWidget()->setOpenTerminalFunc(openTerminalFunc);
}
-RemoteLinuxEnvironmentAspect *RemoteLinuxEnvironmentAspectWidget::aspect() const
-{
- return dynamic_cast<RemoteLinuxEnvironmentAspect *>(EnvironmentAspectWidget::aspect());
-}
-
-QPushButton *RemoteLinuxEnvironmentAspectWidget::fetchButton() const
-{
- return qobject_cast<QPushButton *>(additionalWidget());
-}
-
void RemoteLinuxEnvironmentAspectWidget::fetchEnvironment()
{
- QPushButton *button = fetchButton();
- disconnect(button, &QPushButton::clicked,
+ disconnect(m_fetchButton, &QPushButton::clicked,
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironment);
- connect(button, &QPushButton::clicked,
+ connect(m_fetchButton, &QPushButton::clicked,
this, &RemoteLinuxEnvironmentAspectWidget::stopFetchEnvironment);
- button->setText(tr("Cancel Fetch Operation"));
- deviceEnvReader->start();
+ m_fetchButton->setText(tr("Cancel Fetch Operation"));
+ m_deviceEnvReader->start();
}
void RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentFinished()
{
- QPushButton *button = fetchButton();
- disconnect(button, &QPushButton::clicked,
+ disconnect(m_fetchButton, &QPushButton::clicked,
this, &RemoteLinuxEnvironmentAspectWidget::stopFetchEnvironment);
- connect(button, &QPushButton::clicked,
+ connect(m_fetchButton, &QPushButton::clicked,
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironment);
- button->setText(FetchEnvButtonText);
- aspect()->setRemoteEnvironment(deviceEnvReader->remoteEnvironment());
+ m_fetchButton->setText(FetchEnvButtonText);
+ qobject_cast<RemoteLinuxEnvironmentAspect *>(aspect())->setRemoteEnvironment(
+ m_deviceEnvReader->remoteEnvironment());
}
void RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentError(const QString &error)
@@ -125,7 +115,7 @@ void RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentError(const QString &er
void RemoteLinuxEnvironmentAspectWidget::stopFetchEnvironment()
{
- deviceEnvReader->stop();
+ m_deviceEnvReader->stop();
fetchEnvironmentFinished();
}
diff --git a/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.h b/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.h
index ae254fda62b..1f65d594234 100644
--- a/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.h
+++ b/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.h
@@ -25,14 +25,16 @@
#pragma once
-#include "remotelinuxenvironmentaspect.h"
-
#include <projectexplorer/environmentaspectwidget.h>
-QT_FORWARD_DECLARE_CLASS(QPushButton)
+QT_BEGIN_NAMESPACE
+class QPushButton;
+QT_END_NAMESPACE
namespace RemoteLinux {
+class RemoteLinuxEnvironmentAspect;
+
namespace Internal { class RemoteLinuxEnvironmentReader; }
class RemoteLinuxEnvironmentAspectWidget : public ProjectExplorer::EnvironmentAspectWidget
@@ -43,16 +45,14 @@ public:
RemoteLinuxEnvironmentAspectWidget(RemoteLinuxEnvironmentAspect *aspect,
ProjectExplorer::Target *target);
- RemoteLinuxEnvironmentAspect *aspect() const override;
- QPushButton *fetchButton() const;
-
private:
void fetchEnvironment();
void fetchEnvironmentFinished();
void fetchEnvironmentError(const QString &error);
void stopFetchEnvironment();
- Internal::RemoteLinuxEnvironmentReader *deviceEnvReader;
+ Internal::RemoteLinuxEnvironmentReader *m_deviceEnvReader = nullptr;
+ QPushButton *m_fetchButton = nullptr;
};
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxenvironmentreader.cpp b/src/plugins/remotelinux/remotelinuxenvironmentreader.cpp
index fd59e384317..3f88ac4b5e1 100644
--- a/src/plugins/remotelinux/remotelinuxenvironmentreader.cpp
+++ b/src/plugins/remotelinux/remotelinuxenvironmentreader.cpp
@@ -25,10 +25,10 @@
#include "remotelinuxenvironmentreader.h"
-#include <projectexplorer/devicesupport/deviceprocess.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/runcontrol.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
using namespace ProjectExplorer;
@@ -52,30 +52,20 @@ void RemoteLinuxEnvironmentReader::start()
setFinished();
return;
}
- m_stop = false;
- m_deviceProcess = m_device->createProcess(this);
- connect(m_deviceProcess, &DeviceProcess::errorOccurred,
- this, &RemoteLinuxEnvironmentReader::handleError);
- connect(m_deviceProcess, &DeviceProcess::finished,
- this, &RemoteLinuxEnvironmentReader::remoteProcessFinished);
- Runnable runnable;
- runnable.command.setExecutable("env");
- m_deviceProcess->start(runnable);
+ m_deviceProcess = new QtcProcess(this);
+ connect(m_deviceProcess, &QtcProcess::done,
+ this, &RemoteLinuxEnvironmentReader::handleDone);
+ m_deviceProcess->setCommand({m_device->filePath("env"), {}});
+ m_deviceProcess->start();
}
void RemoteLinuxEnvironmentReader::stop()
{
- m_stop = true;
- destroyProcess();
-}
-
-void RemoteLinuxEnvironmentReader::handleError()
-{
- if (m_stop)
+ if (!m_deviceProcess)
return;
-
- emit error(tr("Error: %1").arg(m_deviceProcess->errorString()));
- setFinished();
+ m_deviceProcess->disconnect(this);
+ m_deviceProcess->deleteLater();
+ m_deviceProcess = nullptr;
}
void RemoteLinuxEnvironmentReader::handleCurrentDeviceConfigChanged()
@@ -84,10 +74,13 @@ void RemoteLinuxEnvironmentReader::handleCurrentDeviceConfigChanged()
setFinished();
}
-void RemoteLinuxEnvironmentReader::remoteProcessFinished()
+void RemoteLinuxEnvironmentReader::handleDone()
{
- if (m_stop)
+ if (m_deviceProcess->result() != ProcessResult::FinishedWithSuccess) {
+ emit error(tr("Error: %1").arg(m_deviceProcess->errorString()));
+ setFinished();
return;
+ }
m_env.clear();
QString errorMessage;
@@ -97,6 +90,7 @@ void RemoteLinuxEnvironmentReader::remoteProcessFinished()
errorMessage = tr("Process exited with code %1.")
.arg(m_deviceProcess->exitCode());
}
+
if (!errorMessage.isEmpty()) {
errorMessage = tr("Error running 'env': %1").arg(errorMessage);
const QString remoteStderr
@@ -105,7 +99,7 @@ void RemoteLinuxEnvironmentReader::remoteProcessFinished()
errorMessage += QLatin1Char('\n') + tr("Remote stderr was: \"%1\"").arg(remoteStderr);
emit error(errorMessage);
} else {
- QString remoteOutput = QString::fromUtf8(m_deviceProcess->readAllStandardOutput());
+ const QString remoteOutput = QString::fromUtf8(m_deviceProcess->readAllStandardOutput());
if (!remoteOutput.isEmpty()) {
m_env = Utils::Environment(remoteOutput.split(QLatin1Char('\n'),
Qt::SkipEmptyParts), Utils::OsTypeLinux);
@@ -120,16 +114,5 @@ void RemoteLinuxEnvironmentReader::setFinished()
emit finished();
}
-void RemoteLinuxEnvironmentReader::destroyProcess()
-{
- if (!m_deviceProcess)
- return;
- m_deviceProcess->disconnect(this);
- if (m_deviceProcess->state() != QProcess::NotRunning)
- m_deviceProcess->terminate();
- m_deviceProcess->deleteLater();
- m_deviceProcess = nullptr;
-}
-
} // namespace Internal
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxenvironmentreader.h b/src/plugins/remotelinux/remotelinuxenvironmentreader.h
index d16664e8708..6c313d0d926 100644
--- a/src/plugins/remotelinux/remotelinuxenvironmentreader.h
+++ b/src/plugins/remotelinux/remotelinuxenvironmentreader.h
@@ -25,12 +25,13 @@
#pragma once
-#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefwd.h>
#include <utils/environment.h>
#include <QObject>
+#include <QSharedPointer>
-namespace ProjectExplorer { class DeviceProcess; }
+namespace Utils { class QtcProcess; }
namespace RemoteLinux {
namespace Internal {
@@ -40,7 +41,7 @@ class RemoteLinuxEnvironmentReader : public QObject
Q_OBJECT
public:
- RemoteLinuxEnvironmentReader(const ProjectExplorer::IDevice::ConstPtr &device,
+ RemoteLinuxEnvironmentReader(const ProjectExplorer::IDeviceConstPtr &device,
QObject *parent = nullptr);
void start();
void stop();
@@ -53,15 +54,12 @@ signals:
void error(const QString &error);
private:
- void handleError();
- void remoteProcessFinished();
+ void handleDone();
void setFinished();
- void destroyProcess();
- bool m_stop = false;
Utils::Environment m_env;
- ProjectExplorer::IDevice::ConstPtr m_device;
- ProjectExplorer::DeviceProcess *m_deviceProcess = nullptr;
+ ProjectExplorer::IDeviceConstPtr m_device;
+ Utils::QtcProcess *m_deviceProcess = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/remotelinux/remotelinuxkillappservice.cpp b/src/plugins/remotelinux/remotelinuxkillappservice.cpp
deleted file mode 100644
index ddbe72b1f0d..00000000000
--- a/src/plugins/remotelinux/remotelinuxkillappservice.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotelinuxkillappservice.h"
-
-#include <utils/fileutils.h>
-
-namespace RemoteLinux {
-namespace Internal {
-class RemoteLinuxKillAppServicePrivate
-{
-public:
- QString remoteExecutable;
- ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOp;
-};
-} // namespace Internal
-
-RemoteLinuxKillAppService::RemoteLinuxKillAppService()
- : d(new Internal::RemoteLinuxKillAppServicePrivate)
-{
-}
-
-RemoteLinuxKillAppService::~RemoteLinuxKillAppService()
-{
- cleanup();
- delete d;
-}
-
-void RemoteLinuxKillAppService::setRemoteExecutable(const QString &filePath)
-{
- d->remoteExecutable = filePath;
-}
-
-bool RemoteLinuxKillAppService::isDeploymentNecessary() const
-{
- return !d->remoteExecutable.isEmpty();
-}
-
-void RemoteLinuxKillAppService::doDeploy()
-{
- d->signalOp = deviceConfiguration()->signalOperation();
- if (!d->signalOp) {
- handleDeploymentDone();
- return;
- }
- connect(d->signalOp.data(), &ProjectExplorer::DeviceProcessSignalOperation::finished,
- this, &RemoteLinuxKillAppService::handleSignalOpFinished);
- emit progressMessage(tr("Trying to kill \"%1\" on remote device...").arg(d->remoteExecutable));
- d->signalOp->killProcess(d->remoteExecutable);
-}
-
-void RemoteLinuxKillAppService::cleanup()
-{
- if (d->signalOp) {
- disconnect(d->signalOp.data(), nullptr, this, nullptr);
- d->signalOp.clear();
- }
-}
-
-void RemoteLinuxKillAppService::finishDeployment()
-{
- cleanup();
- handleDeploymentDone();
-}
-
-void RemoteLinuxKillAppService::stopDeployment()
-{
- finishDeployment();
-}
-
-void RemoteLinuxKillAppService::handleSignalOpFinished(const QString &errorMessage)
-{
- if (errorMessage.isEmpty())
- emit progressMessage(tr("Remote application killed."));
- else
- emit progressMessage(tr("Failed to kill remote application. Assuming it was not running."));
- finishDeployment();
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxkillappservice.h b/src/plugins/remotelinux/remotelinuxkillappservice.h
deleted file mode 100644
index 042f4bac0ea..00000000000
--- a/src/plugins/remotelinux/remotelinuxkillappservice.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "abstractremotelinuxdeployservice.h"
-
-namespace RemoteLinux {
-namespace Internal { class RemoteLinuxKillAppServicePrivate; }
-
-class REMOTELINUX_EXPORT RemoteLinuxKillAppService : public AbstractRemoteLinuxDeployService
-{
- Q_OBJECT
-public:
- RemoteLinuxKillAppService();
- ~RemoteLinuxKillAppService() override;
-
- void setRemoteExecutable(const QString &filePath);
-
-private:
- void handleStdErr();
- void handleProcessFinished();
-
- bool isDeploymentNecessary() const override;
-
- void doDeploy() override;
- void stopDeployment() override;
-
- void handleSignalOpFinished(const QString &errorMessage);
- void cleanup();
- void finishDeployment();
-
- Internal::RemoteLinuxKillAppServicePrivate * const d;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxkillappstep.cpp b/src/plugins/remotelinux/remotelinuxkillappstep.cpp
deleted file mode 100644
index daa451d97e0..00000000000
--- a/src/plugins/remotelinux/remotelinuxkillappstep.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotelinuxkillappstep.h"
-
-#include "remotelinux_constants.h"
-#include "remotelinuxkillappservice.h"
-
-#include <projectexplorer/runcontrol.h>
-#include <projectexplorer/target.h>
-#include <utils/qtcassert.h>
-
-using namespace ProjectExplorer;
-
-namespace RemoteLinux {
-
-RemoteLinuxKillAppStep::RemoteLinuxKillAppStep(BuildStepList *bsl, Utils::Id id)
- : AbstractRemoteLinuxDeployStep(bsl, id)
-{
- auto service = createDeployService<RemoteLinuxKillAppService>();
-
- setWidgetExpandedByDefault(false);
-
- setInternalInitializer([this, service] {
- Target * const theTarget = target();
- QTC_ASSERT(theTarget, return CheckResult::failure());
- RunConfiguration * const rc = theTarget->activeRunConfiguration();
- const QString remoteExe = rc ? rc->runnable().command.executable().toString() : QString();
- service->setRemoteExecutable(remoteExe);
- return CheckResult::success();
- });
-}
-
-Utils::Id RemoteLinuxKillAppStep::stepId()
-{
- return Constants::KillAppStepId;
-}
-
-QString RemoteLinuxKillAppStep::displayName()
-{
- return tr("Kill current application instance");
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxkillappstep.h b/src/plugins/remotelinux/remotelinuxkillappstep.h
deleted file mode 100644
index 506bc99d817..00000000000
--- a/src/plugins/remotelinux/remotelinuxkillappstep.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "abstractremotelinuxdeploystep.h"
-
-namespace RemoteLinux {
-
-class REMOTELINUX_EXPORT RemoteLinuxKillAppStep : public AbstractRemoteLinuxDeployStep
-{
- Q_OBJECT
-public:
- explicit RemoteLinuxKillAppStep(ProjectExplorer::BuildStepList *bsl,
- Utils::Id id = stepId());
-
- static Utils::Id stepId();
- static QString displayName();
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp b/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp
deleted file mode 100644
index e61a0bb7e9d..00000000000
--- a/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotelinuxpackageinstaller.h"
-
-#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
-#include <ssh/sshremoteprocessrunner.h>
-
-using namespace ProjectExplorer;
-using namespace QSsh;
-
-namespace RemoteLinux {
-namespace Internal {
-
-class AbstractRemoteLinuxPackageInstallerPrivate
-{
-public:
- bool isRunning = false;
- IDevice::ConstPtr deviceConfig;
- SshRemoteProcessRunner *installer = nullptr;
- SshRemoteProcessRunner *killProcess = nullptr;
-};
-
-} // namespace Internal
-
-AbstractRemoteLinuxPackageInstaller::AbstractRemoteLinuxPackageInstaller(QObject *parent)
- : QObject(parent), d(new Internal::AbstractRemoteLinuxPackageInstallerPrivate)
-{
-}
-
-AbstractRemoteLinuxPackageInstaller::~AbstractRemoteLinuxPackageInstaller()
-{
- delete d;
-}
-
-void AbstractRemoteLinuxPackageInstaller::installPackage(const IDevice::ConstPtr &deviceConfig,
- const QString &packageFilePath, bool removePackageFile)
-{
- QTC_ASSERT(!d->isRunning, return);
-
- d->deviceConfig = deviceConfig;
- prepareInstallation();
- if (!d->installer)
- d->installer = new SshRemoteProcessRunner(this);
- connect(d->installer, &SshRemoteProcessRunner::connectionError,
- this, &AbstractRemoteLinuxPackageInstaller::handleConnectionError);
- connect(d->installer, &SshRemoteProcessRunner::readyReadStandardOutput,
- this, &AbstractRemoteLinuxPackageInstaller::handleInstallerOutput);
- connect(d->installer, &SshRemoteProcessRunner::readyReadStandardError,
- this, &AbstractRemoteLinuxPackageInstaller::handleInstallerErrorOutput);
- connect(d->installer, &SshRemoteProcessRunner::processClosed,
- this, &AbstractRemoteLinuxPackageInstaller::handleInstallationFinished);
-
- QString cmdLine = installCommandLine(packageFilePath);
- if (removePackageFile)
- cmdLine += QLatin1String(" && (rm ") + packageFilePath + QLatin1String(" || :)");
- d->installer->run(cmdLine, deviceConfig->sshParameters());
- d->isRunning = true;
-}
-
-void AbstractRemoteLinuxPackageInstaller::cancelInstallation()
-{
- QTC_ASSERT(d->installer && d->isRunning, return);
-
- if (!d->killProcess)
- d->killProcess = new SshRemoteProcessRunner(this);
- d->killProcess->run(cancelInstallationCommandLine(), d->deviceConfig->sshParameters());
- setFinished();
-}
-
-void AbstractRemoteLinuxPackageInstaller::handleConnectionError()
-{
- if (!d->isRunning)
- return;
- emit finished(tr("Connection failure: %1").arg(d->installer->lastConnectionErrorString()));
- setFinished();
-}
-
-void AbstractRemoteLinuxPackageInstaller::handleInstallationFinished(const QString &error)
-{
- if (!d->isRunning)
- return;
-
- if (!error.isEmpty() || d->installer->processExitCode() != 0)
- emit finished(tr("Installing package failed."));
- else if (!errorString().isEmpty())
- emit finished(errorString());
- else
- emit finished();
-
- setFinished();
-}
-
-void AbstractRemoteLinuxPackageInstaller::handleInstallerOutput()
-{
- emit stdoutData(QString::fromUtf8(d->installer->readAllStandardOutput()));
-}
-
-void AbstractRemoteLinuxPackageInstaller::handleInstallerErrorOutput()
-{
- emit stderrData(QString::fromUtf8(d->installer->readAllStandardError()));
-}
-
-void AbstractRemoteLinuxPackageInstaller::setFinished()
-{
- disconnect(d->installer, nullptr, this, nullptr);
- d->isRunning = false;
-}
-
-
-RemoteLinuxTarPackageInstaller::RemoteLinuxTarPackageInstaller(QObject *parent)
- : AbstractRemoteLinuxPackageInstaller(parent)
-{
-}
-
-QString RemoteLinuxTarPackageInstaller::installCommandLine(const QString &packageFilePath) const
-{
- return QLatin1String("cd / && tar xvf ") + packageFilePath;
-}
-
-QString RemoteLinuxTarPackageInstaller::cancelInstallationCommandLine() const
-{
- return QLatin1String("pkill tar");
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxpackageinstaller.h b/src/plugins/remotelinux/remotelinuxpackageinstaller.h
deleted file mode 100644
index ddf713eda28..00000000000
--- a/src/plugins/remotelinux/remotelinuxpackageinstaller.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "remotelinux_export.h"
-
-#include <projectexplorer/devicesupport/idevice.h>
-
-namespace RemoteLinux {
-
-namespace Internal { class AbstractRemoteLinuxPackageInstallerPrivate; }
-
-class REMOTELINUX_EXPORT AbstractRemoteLinuxPackageInstaller : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(AbstractRemoteLinuxPackageInstaller)
-public:
- ~AbstractRemoteLinuxPackageInstaller() override;
-
- void installPackage(const ProjectExplorer::IDevice::ConstPtr &deviceConfig,
- const QString &packageFilePath, bool removePackageFile);
- void cancelInstallation();
-
-signals:
- void stdoutData(const QString &output);
- void stderrData(const QString &output);
- void finished(const QString &errorMsg = QString());
-
-protected:
- explicit AbstractRemoteLinuxPackageInstaller(QObject *parent = nullptr);
-
-private:
- void handleConnectionError();
- void handleInstallationFinished(const QString &error);
- void handleInstallerOutput();
- void handleInstallerErrorOutput();
-
- virtual QString installCommandLine(const QString &packageFilePath) const = 0;
- virtual QString cancelInstallationCommandLine() const = 0;
-
- virtual void prepareInstallation() {}
- virtual QString errorString() const { return QString(); }
-
- void setFinished();
-
- Internal::AbstractRemoteLinuxPackageInstallerPrivate * const d;
-};
-
-
-class REMOTELINUX_EXPORT RemoteLinuxTarPackageInstaller : public AbstractRemoteLinuxPackageInstaller
-{
- Q_OBJECT
-public:
- RemoteLinuxTarPackageInstaller(QObject *parent = nullptr);
-
-private:
- QString installCommandLine(const QString &packageFilePath) const override;
- QString cancelInstallationCommandLine() const override;
-};
-
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxplugin.cpp b/src/plugins/remotelinux/remotelinuxplugin.cpp
index ba3286be0ba..b79fc79eb45 100644
--- a/src/plugins/remotelinux/remotelinuxplugin.cpp
+++ b/src/plugins/remotelinux/remotelinuxplugin.cpp
@@ -25,29 +25,28 @@
#include "remotelinuxplugin.h"
+#include "customcommanddeploystep.h"
+#include "genericdirectuploadstep.h"
+#include "killappstep.h"
#include "linuxdevice.h"
+#include "makeinstallstep.h"
#include "remotelinux_constants.h"
+#include "remotelinuxdeployconfiguration.h"
#include "remotelinuxqmltoolingsupport.h"
#include "remotelinuxcustomrunconfiguration.h"
#include "remotelinuxdebugsupport.h"
#include "remotelinuxdeployconfiguration.h"
#include "remotelinuxrunconfiguration.h"
-
-#include "genericdirectuploadstep.h"
-#include "makeinstallstep.h"
-#include "remotelinuxcheckforfreediskspacestep.h"
-#include "remotelinuxdeployconfiguration.h"
-#include "remotelinuxcustomcommanddeploymentstep.h"
-#include "remotelinuxkillappstep.h"
#include "rsyncdeploystep.h"
#include "tarpackagecreationstep.h"
-#include "uploadandinstalltarpackagestep.h"
+#include "tarpackagedeploystep.h"
#ifdef WITH_TESTS
#include "filesystemaccess_test.h"
#endif
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
using namespace ProjectExplorer;
@@ -63,7 +62,7 @@ public:
{
registerStep<Step>(Step::stepId());
setDisplayName(Step::displayName());
- setSupportedConfiguration(genericDeployConfigurationId());
+ setSupportedConfiguration(RemoteLinux::Constants::DeployToGenericLinux);
setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY);
}
};
@@ -76,14 +75,11 @@ public:
RemoteLinuxCustomRunConfigurationFactory customRunConfigurationFactory;
RemoteLinuxDeployConfigurationFactory deployConfigurationFactory;
GenericDeployStepFactory<TarPackageCreationStep> tarPackageCreationStepFactory;
- GenericDeployStepFactory<UploadAndInstallTarPackageStep> uploadAndInstallTarPackageStepFactory;
+ TarPackageDeployStepFactory tarPackageDeployStepFactory;
GenericDeployStepFactory<GenericDirectUploadStep> genericDirectUploadStepFactory;
GenericDeployStepFactory<RsyncDeployStep> rsyncDeployStepFactory;
- GenericDeployStepFactory<RemoteLinuxCustomCommandDeploymentStep>
- customCommandDeploymentStepFactory;
- GenericDeployStepFactory<RemoteLinuxCheckForFreeDiskSpaceStep>
- checkForFreeDiskSpaceStepFactory;
- GenericDeployStepFactory<RemoteLinuxKillAppStep> remoteLinuxKillAppStepFactory;
+ CustomCommandDeployStepFactory customCommandDeployStepFactory;
+ GenericDeployStepFactory<KillAppStep> killAppStepFactory;
GenericDeployStepFactory<MakeInstallStep> makeInstallStepFactory;
const QList<Utils::Id> supportedRunConfigs {
diff --git a/src/plugins/remotelinux/remotelinuxqmltoolingsupport.cpp b/src/plugins/remotelinux/remotelinuxqmltoolingsupport.cpp
index 674371278f6..7135446539d 100644
--- a/src/plugins/remotelinux/remotelinuxqmltoolingsupport.cpp
+++ b/src/plugins/remotelinux/remotelinuxqmltoolingsupport.cpp
@@ -51,16 +51,15 @@ RemoteLinuxQmlToolingSupport::RemoteLinuxQmlToolingSupport(RunControl *runContro
runworker->addStartDependency(this);
addStopDependency(runworker);
- setStarter([this, runControl, portsGatherer, runworker] {
+ setStartModifier([this, runControl, portsGatherer, runworker] {
const QUrl serverUrl = portsGatherer->findEndPoint();
runworker->recordData("QmlServerUrl", serverUrl);
QmlDebug::QmlDebugServicesPreset services = QmlDebug::servicesForRunMode(runControl->runMode());
- Runnable r = runControl->runnable();
- r.command.addArg(QmlDebug::qmlDebugTcpArguments(services, serverUrl));
-
- doStart(r, runControl->device());
+ CommandLine cmd = commandLine();
+ cmd.addArg(QmlDebug::qmlDebugTcpArguments(services, serverUrl));
+ setCommandLine(cmd);
});
}
diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
index c964d235cc5..14f95365613 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
@@ -26,8 +26,8 @@
#include "remotelinuxrunconfiguration.h"
#include "remotelinux_constants.h"
-#include "remotelinuxx11forwardingaspect.h"
#include "remotelinuxenvironmentaspect.h"
+#include "x11forwardingaspect.h"
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/buildtargetinfo.h>
@@ -57,9 +57,10 @@ public:
RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- auto exeAspect = addAspect<ExecutableAspect>();
+ auto envAspect = addAspect<RemoteLinuxEnvironmentAspect>(target);
+
+ auto exeAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
exeAspect->setLabelText(tr("Executable on device:"));
- exeAspect->setExecutablePathStyle(OsTypeLinux);
exeAspect->setPlaceHolderText(tr("Remote path not set"));
exeAspect->makeOverridable("RemoteLinux.RunConfig.AlternateRemoteExecutable",
"RemoteLinux.RunConfig.UseAlternateRemoteExecutable");
@@ -69,13 +70,12 @@ RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *target, Id id)
symbolsAspect->setLabelText(tr("Executable on host:"));
symbolsAspect->setDisplayStyle(SymbolFileAspect::LabelDisplay);
- addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>();
+ addAspect<ArgumentsAspect>(macroExpander());
+ addAspect<WorkingDirectoryAspect>(macroExpander(), envAspect);
if (HostOsInfo::isAnyUnixHost())
addAspect<TerminalAspect>();
- addAspect<RemoteLinuxEnvironmentAspect>(target);
if (HostOsInfo::isAnyUnixHost())
- addAspect<X11ForwardingAspect>();
+ addAspect<X11ForwardingAspect>(macroExpander());
setUpdater([this, target, exeAspect, symbolsAspect] {
BuildTargetInfo bti = buildTargetInfo();
@@ -88,7 +88,7 @@ RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *target, Id id)
setRunnableModifier([this](Runnable &r) {
if (const auto * const forwardingAspect = aspect<X11ForwardingAspect>())
- r.extraData.insert("Ssh.X11ForwardToDisplay", forwardingAspect->display(macroExpander()));
+ r.extraData.insert("Ssh.X11ForwardToDisplay", forwardingAspect->display());
});
connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.h b/src/plugins/remotelinux/remotelinuxrunconfiguration.h
index 59951dbe457..eceeb5b6267 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfiguration.h
+++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.h
@@ -25,8 +25,6 @@
#pragma once
-#include "remotelinux_export.h"
-
#include <projectexplorer/runconfiguration.h>
namespace RemoteLinux {
diff --git a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
index cbe3b6f9d5e..a0dec6b269c 100644
--- a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
+++ b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
@@ -25,46 +25,35 @@
#include "remotelinuxsignaloperation.h"
-#include <ssh/sshremoteprocessrunner.h>
-#include <ssh/sshconnection.h>
-#include <utils/qtcassert.h>
+#include <utils/commandline.h>
#include <utils/fileutils.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
using namespace RemoteLinux;
using namespace ProjectExplorer;
+using namespace Utils;
RemoteLinuxSignalOperation::RemoteLinuxSignalOperation(
- const QSsh::SshConnectionParameters &sshParameters)
- : m_sshParameters(sshParameters)
+ const IDeviceConstPtr &device)
+ : m_device(device)
{}
-RemoteLinuxSignalOperation::~RemoteLinuxSignalOperation()
-{
- if (m_runner)
- m_runner->deleteLater();
-}
+RemoteLinuxSignalOperation::~RemoteLinuxSignalOperation() = default;
static QString signalProcessGroupByPidCommandLine(qint64 pid, int signal)
{
- return QString::fromLatin1("kill -%1 -%2 %2").arg(signal).arg(pid);
+ return QString::fromLatin1("kill -%1 %2").arg(signal).arg(pid);
}
void RemoteLinuxSignalOperation::run(const QString &command)
{
- QTC_ASSERT(!m_runner, return);
- m_runner = new QSsh::SshRemoteProcessRunner();
- connect(m_runner, &QSsh::SshRemoteProcessRunner::processClosed,
- this, &RemoteLinuxSignalOperation::runnerProcessFinished);
- connect(m_runner, &QSsh::SshRemoteProcessRunner::connectionError,
- this, &RemoteLinuxSignalOperation::runnerConnectionError);
- m_runner->run(command, m_sshParameters);
-}
+ QTC_ASSERT(!m_process, return);
+ m_process.reset(new QtcProcess);
+ connect(m_process.get(), &QtcProcess::done, this, &RemoteLinuxSignalOperation::runnerDone);
-void RemoteLinuxSignalOperation::finish()
-{
- delete m_runner;
- m_runner = nullptr;
- emit finished(m_errorMessage);
+ m_process->setCommand({m_device->filePath("/bin/sh"), {"-c", command}});
+ m_process->start();
}
static QString signalProcessGroupByNameCommandLine(const QString &filePath, int signal)
@@ -91,9 +80,8 @@ QString RemoteLinuxSignalOperation::interruptProcessByNameCommandLine(const QStr
void RemoteLinuxSignalOperation::killProcess(qint64 pid)
{
- run(QString::fromLatin1("%1; sleep 1; %2 && %3")
+ run(QString::fromLatin1("%1 && %2")
.arg(signalProcessGroupByPidCommandLine(pid, 15),
- signalProcessGroupByPidCommandLine(pid, 0),
signalProcessGroupByPidCommandLine(pid, 9)));
}
@@ -112,21 +100,16 @@ void RemoteLinuxSignalOperation::interruptProcess(const QString &filePath)
run(interruptProcessByNameCommandLine(filePath));
}
-void RemoteLinuxSignalOperation::runnerProcessFinished()
+void RemoteLinuxSignalOperation::runnerDone()
{
m_errorMessage.clear();
- if (m_runner->processExitStatus() != QProcess::NormalExit) {
- m_errorMessage = m_runner->processErrorString();
- } else if (m_runner->processExitCode() != 0) {
- m_errorMessage = tr("Exit code is %1. stderr:").arg(m_runner->processExitCode())
+ if (m_process->exitStatus() != QProcess::NormalExit) {
+ m_errorMessage = m_process->errorString();
+ } else if (m_process->exitCode() != 0) {
+ m_errorMessage = tr("Exit code is %1. stderr:").arg(m_process->exitCode())
+ QLatin1Char(' ')
- + QString::fromLatin1(m_runner->readAllStandardError());
+ + QString::fromLatin1(m_process->readAllStandardError());
}
- finish();
-}
-
-void RemoteLinuxSignalOperation::runnerConnectionError()
-{
- m_errorMessage = m_runner->lastConnectionErrorString();
- finish();
+ m_process.release()->deleteLater();
+ emit finished(m_errorMessage);
}
diff --git a/src/plugins/remotelinux/remotelinuxsignaloperation.h b/src/plugins/remotelinux/remotelinuxsignaloperation.h
index dc479141b3c..844c3c6d2fd 100644
--- a/src/plugins/remotelinux/remotelinuxsignaloperation.h
+++ b/src/plugins/remotelinux/remotelinuxsignaloperation.h
@@ -28,11 +28,6 @@
#include "remotelinux_export.h"
#include <projectexplorer/devicesupport/idevice.h>
-#include <ssh/sshconnection.h>
-
-namespace QSsh {
-class SshRemoteProcessRunner;
-}
namespace RemoteLinux {
@@ -49,19 +44,17 @@ public:
void interruptProcess(const QString &filePath) override;
protected:
- RemoteLinuxSignalOperation(const QSsh::SshConnectionParameters &sshParameters);
+ RemoteLinuxSignalOperation(const ProjectExplorer::IDeviceConstPtr &device);
private:
virtual QString killProcessByNameCommandLine(const QString &filePath) const;
virtual QString interruptProcessByNameCommandLine(const QString &filePath) const;
- void runnerProcessFinished();
- void runnerConnectionError();
+ void runnerDone();
void run(const QString &command);
- void finish();
- const QSsh::SshConnectionParameters m_sshParameters;
- QSsh::SshRemoteProcessRunner *m_runner = nullptr;
+ const ProjectExplorer::IDeviceConstPtr m_device;
+ std::unique_ptr<Utils::QtcProcess> m_process;
friend class LinuxDevice;
};
diff --git a/src/plugins/remotelinux/remotelinuxx11forwardingaspect.cpp b/src/plugins/remotelinux/remotelinuxx11forwardingaspect.cpp
deleted file mode 100644
index 739a470321f..00000000000
--- a/src/plugins/remotelinux/remotelinuxx11forwardingaspect.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotelinuxx11forwardingaspect.h"
-
-#include <utils/macroexpander.h>
-#include <utils/qtcassert.h>
-
-using namespace Utils;
-
-namespace RemoteLinux {
-
-static QString defaultDisplay() { return QLatin1String(qgetenv("DISPLAY")); }
-
-X11ForwardingAspect::X11ForwardingAspect()
-{
- setLabelText(tr("X11 Forwarding:"));
- setDisplayStyle(LineEditDisplay);
- setId("X11ForwardingAspect");
- setSettingsKey("RunConfiguration.X11Forwarding");
- makeCheckable(CheckBoxPlacement::Right, tr("Forward to local display"),
- "RunConfiguration.UseX11Forwarding");
- setValue(defaultDisplay());
-}
-
-QString X11ForwardingAspect::display(const Utils::MacroExpander *expander) const
-{
- QTC_ASSERT(expander, return value());
- return !isChecked() ? QString() : expander->expandProcessArgs(value());
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxx11forwardingaspect.h b/src/plugins/remotelinux/remotelinuxx11forwardingaspect.h
deleted file mode 100644
index b518782fbc8..00000000000
--- a/src/plugins/remotelinux/remotelinuxx11forwardingaspect.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "remotelinux_export.h"
-
-#include <utils/aspects.h>
-
-namespace Utils { class MacroExpander; }
-
-namespace RemoteLinux {
-
-class REMOTELINUX_EXPORT X11ForwardingAspect : public Utils::StringAspect
-{
- Q_OBJECT
-
-public:
- X11ForwardingAspect();
-
- QString display(const Utils::MacroExpander *expander) const;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/rsyncdeploystep.cpp b/src/plugins/remotelinux/rsyncdeploystep.cpp
index 21981ba9626..7b8cf858f19 100644
--- a/src/plugins/remotelinux/rsyncdeploystep.cpp
+++ b/src/plugins/remotelinux/rsyncdeploystep.cpp
@@ -29,16 +29,15 @@
#include "remotelinux_constants.h"
#include <projectexplorer/deploymentdata.h>
+#include <projectexplorer/devicesupport/filetransfer.h>
+#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/target.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshremoteprocess.h>
-#include <ssh/sshsettings.h>
#include <utils/algorithm.h>
+#include <utils/processinterface.h>
#include <utils/qtcprocess.h>
using namespace ProjectExplorer;
-using namespace QSsh;
using namespace Utils;
namespace RemoteLinux {
@@ -48,9 +47,46 @@ class RsyncDeployService : public AbstractRemoteLinuxDeployService
{
Q_OBJECT
public:
- RsyncDeployService(QObject *parent = nullptr) : AbstractRemoteLinuxDeployService(parent) {}
+ RsyncDeployService(QObject *parent = nullptr) : AbstractRemoteLinuxDeployService(parent)
+ {
+ connect(&m_mkdir, &QtcProcess::done, this, [this] {
+ if (m_mkdir.result() != ProcessResult::FinishedWithSuccess) {
+ QString finalMessage = m_mkdir.errorString();
+ const QString stdErr = m_mkdir.cleanedStdErr();
+ if (!stdErr.isEmpty()) {
+ if (!finalMessage.isEmpty())
+ finalMessage += '\n';
+ finalMessage += stdErr;
+ }
+ emit errorMessage(tr("Deploy via rsync: failed to create remote directories:")
+ + '\n' + finalMessage);
+ setFinished();
+ return;
+ }
+ deployFiles();
+ });
+ connect(&m_mkdir, &QtcProcess::readyReadStandardError, this, [this] {
+ emit stdErrData(QString::fromLocal8Bit(m_mkdir.readAllStandardError()));
+ });
+ connect(&m_fileTransfer, &FileTransfer::progress,
+ this, &AbstractRemoteLinuxDeployService::stdOutData);
+ connect(&m_fileTransfer, &FileTransfer::done, this, [this](const ProcessResultData &result) {
+ auto notifyError = [this](const QString &message) {
+ emit errorMessage(message);
+ setFinished();
+ };
+ if (result.m_error == QProcess::FailedToStart)
+ notifyError(tr("rsync failed to start: %1").arg(result.m_errorString));
+ else if (result.m_exitStatus == QProcess::CrashExit)
+ notifyError(tr("rsync crashed."));
+ else if (result.m_exitCode != 0)
+ notifyError(tr("rsync failed with exit code %1.").arg(result.m_exitCode));
+ else
+ setFinished();
+ });
+ }
- void setDeployableFiles(const QList<DeployableFile> &files) { m_deployableFiles = files; }
+ void setDeployableFiles(const QList<DeployableFile> &files);
void setIgnoreMissingFiles(bool ignore) { m_ignoreMissingFiles = ignore; }
void setFlags(const QString &flags) { m_flags = flags; }
@@ -60,23 +96,28 @@ private:
void doDeploy() override;
void stopDeployment() override { setFinished(); };
- void filterDeployableFiles() const;
+ void filterFiles() const;
void createRemoteDirectories();
void deployFiles();
- void deployNextFile();
void setFinished();
- mutable QList<DeployableFile> m_deployableFiles;
+ mutable FilesToTransfer m_files;
bool m_ignoreMissingFiles = false;
QString m_flags;
- SshProcess m_rsync;
- SshRemoteProcessPtr m_mkdir;
+ QtcProcess m_mkdir;
+ FileTransfer m_fileTransfer;
};
+void RsyncDeployService::setDeployableFiles(const QList<DeployableFile> &files)
+{
+ for (const DeployableFile &f : files)
+ m_files.append({f.localFilePath(), deviceConfiguration()->filePath(f.remoteFilePath())});
+}
+
bool RsyncDeployService::isDeploymentNecessary() const
{
- filterDeployableFiles();
- return !m_deployableFiles.empty();
+ filterFiles();
+ return !m_files.empty();
}
void RsyncDeployService::doDeploy()
@@ -84,104 +125,38 @@ void RsyncDeployService::doDeploy()
createRemoteDirectories();
}
-void RsyncDeployService::filterDeployableFiles() const
+void RsyncDeployService::filterFiles() const
{
- if (m_ignoreMissingFiles) {
- Utils::erase(m_deployableFiles, [](const DeployableFile &f) {
- return !f.localFilePath().exists();
- });
- }
+ if (!m_ignoreMissingFiles)
+ return;
+
+ Utils::erase(m_files, [](const FileToTransfer &file) { return !file.m_source.exists(); });
}
void RsyncDeployService::createRemoteDirectories()
{
QStringList remoteDirs;
- for (const DeployableFile &f : qAsConst(m_deployableFiles))
- remoteDirs << f.remoteDirectory();
+ for (const FileToTransfer &file : qAsConst(m_files))
+ remoteDirs << file.m_target.parentDir().path();
remoteDirs.sort();
remoteDirs.removeDuplicates();
- m_mkdir = connection()->createRemoteProcess("mkdir -p " +
- ProcessArgs::createUnixArgs(remoteDirs).toString());
- connect(m_mkdir.get(), &SshRemoteProcess::done, this, [this](const QString &error) {
- QString userError;
- if (!error.isEmpty())
- userError = error;
- if (m_mkdir->exitCode() != 0)
- userError = QString::fromUtf8(m_mkdir->readAllStandardError());
- if (!userError.isEmpty()) {
- emit errorMessage(tr("Failed to create remote directories: %1").arg(userError));
- setFinished();
- return;
- }
- deployFiles();
- });
- m_mkdir->start();
-}
-void RsyncDeployService::deployFiles()
-{
- connect(&m_rsync, &QtcProcess::readyReadStandardOutput, this, [this] {
- emit progressMessage(QString::fromLocal8Bit(m_rsync.readAllStandardOutput()));
- });
- connect(&m_rsync, &QtcProcess::readyReadStandardError, this, [this] {
- emit warningMessage(QString::fromLocal8Bit(m_rsync.readAllStandardError()));
- });
- connect(&m_rsync, &QtcProcess::errorOccurred, this, [this] {
- if (m_rsync.error() == QProcess::FailedToStart) {
- emit errorMessage(tr("rsync failed to start: %1").arg(m_rsync.errorString()));
- setFinished();
- }
- });
- connect(&m_rsync, &QtcProcess::finished, this, [this] {
- if (m_rsync.exitStatus() == QProcess::CrashExit) {
- emit errorMessage(tr("rsync crashed."));
- setFinished();
- return;
- }
- if (m_rsync.exitCode() != 0) {
- emit errorMessage(tr("rsync failed with exit code %1.").arg(m_rsync.exitCode()));
- setFinished();
- return;
- }
- deployNextFile();
- });
- deployNextFile();
+ m_mkdir.setCommand({deviceConfiguration()->filePath("mkdir"), QStringList("-p") + remoteDirs});
+ m_mkdir.start();
}
-void RsyncDeployService::deployNextFile()
+void RsyncDeployService::deployFiles()
{
- if (m_deployableFiles.empty()) {
- setFinished();
- return;
- }
- const DeployableFile file = m_deployableFiles.takeFirst();
- const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*connection(), m_flags);
- QString localFilePath = file.localFilePath().toString();
-
- // On Windows, rsync is either from msys or cygwin. Neither work with the other's ssh.exe.
- if (HostOsInfo::isWindowsHost()) {
- localFilePath = '/' + localFilePath.at(0) + localFilePath.mid(2);
- if (anyOf(cmdLine.options, [](const QString &opt) {
- return opt.contains("cygwin", Qt::CaseInsensitive); })) {
- localFilePath.prepend("/cygdrive");
- }
- }
-
- const QStringList args = QStringList(cmdLine.options)
- << (localFilePath + (file.localFilePath().isDir() ? "/" : QString()))
- << (cmdLine.remoteHostSpec + ':' + file.remoteFilePath());
- m_rsync.setCommand(CommandLine("rsync", args));
- m_rsync.start(); // TODO: Get rsync location from settings?
+ m_fileTransfer.setTransferMethod(FileTransferMethod::Rsync);
+ m_fileTransfer.setRsyncFlags(m_flags);
+ m_fileTransfer.setFilesToTransfer(m_files);
+ m_fileTransfer.start();
}
void RsyncDeployService::setFinished()
{
- if (m_mkdir) {
- m_mkdir->disconnect();
- m_mkdir->kill();
- }
- m_rsync.disconnect();
- m_rsync.kill();
+ m_mkdir.close();
+ m_fileTransfer.stop();
handleDeploymentDone();
}
@@ -196,7 +171,7 @@ RsyncDeployStep::RsyncDeployStep(BuildStepList *bsl, Utils::Id id)
flags->setDisplayStyle(StringAspect::LineEditDisplay);
flags->setSettingsKey("RemoteLinux.RsyncDeployStep.Flags");
flags->setLabelText(tr("Flags:"));
- flags->setValue(defaultFlags());
+ flags->setValue(FileTransferSetupData::defaultRsyncFlags());
auto ignoreMissingFiles = addAspect<BoolAspect>();
ignoreMissingFiles->setSettingsKey("RemoteLinux.RsyncDeployStep.IgnoreMissingFiles");
@@ -227,22 +202,6 @@ QString RsyncDeployStep::displayName()
return tr("Deploy files via rsync");
}
-QString RsyncDeployStep::defaultFlags()
-{
- return QString("-av");
-}
-
-RsyncCommandLine RsyncDeployStep::rsyncCommand(const SshConnection &sshConnection,
- const QString &flags)
-{
- const QString sshCmdLine = ProcessArgs::joinArgs(
- QStringList{SshSettings::sshFilePath().toUserOutput()}
- << sshConnection.connectionOptions(SshSettings::sshFilePath()), OsTypeLinux);
- const SshConnectionParameters sshParams = sshConnection.connectionParameters();
- return RsyncCommandLine(QStringList{"-e", sshCmdLine, flags},
- sshParams.userName() + '@' + sshParams.host());
-}
-
} //namespace RemoteLinux
#include <rsyncdeploystep.moc>
diff --git a/src/plugins/remotelinux/rsyncdeploystep.h b/src/plugins/remotelinux/rsyncdeploystep.h
index 0dd0f5484f7..76373a2ef86 100644
--- a/src/plugins/remotelinux/rsyncdeploystep.h
+++ b/src/plugins/remotelinux/rsyncdeploystep.h
@@ -25,21 +25,12 @@
#pragma once
-#include "abstractremotelinuxdeploystep.h"
#include "remotelinux_export.h"
-namespace QSsh { class SshConnection; }
+#include "abstractremotelinuxdeploystep.h"
namespace RemoteLinux {
-class RsyncCommandLine
-{
-public:
- RsyncCommandLine(const QStringList &o, const QString &h) : options(o), remoteHostSpec(h) {}
- const QStringList options;
- const QString remoteHostSpec;
-};
-
class REMOTELINUX_EXPORT RsyncDeployStep : public AbstractRemoteLinuxDeployStep
{
Q_OBJECT
@@ -50,10 +41,6 @@ public:
static Utils::Id stepId();
static QString displayName();
-
- static QString defaultFlags();
- static RsyncCommandLine rsyncCommand(const QSsh::SshConnection &sshConnection,
- const QString &flags);
};
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/sshkeycreationdialog.cpp b/src/plugins/remotelinux/sshkeycreationdialog.cpp
new file mode 100644
index 00000000000..cc57f2d24f8
--- /dev/null
+++ b/src/plugins/remotelinux/sshkeycreationdialog.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sshkeycreationdialog.h"
+#include "ui_sshkeycreationdialog.h"
+
+#include <projectexplorer/devicesupport/sshsettings.h>
+
+#include <utils/fileutils.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcprocess.h>
+
+#include <QApplication>
+#include <QMessageBox>
+#include <QStandardPaths>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace RemoteLinux {
+
+SshKeyCreationDialog::SshKeyCreationDialog(QWidget *parent)
+ : QDialog(parent), m_ui(new Ui::SshKeyCreationDialog)
+{
+ m_ui->setupUi(this);
+ m_ui->privateKeyFileButton->setText(Utils::PathChooser::browseButtonLabel());
+ const QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
+ + QLatin1String("/.ssh/qtc_id");
+ setPrivateKeyFile(FilePath::fromString(defaultPath));
+
+ connect(m_ui->rsa, &QRadioButton::toggled,
+ this, &SshKeyCreationDialog::keyTypeChanged);
+ connect(m_ui->privateKeyFileButton, &QPushButton::clicked,
+ this, &SshKeyCreationDialog::handleBrowseButtonClicked);
+ connect(m_ui->generateButton, &QPushButton::clicked,
+ this, &SshKeyCreationDialog::generateKeys);
+ keyTypeChanged();
+}
+
+SshKeyCreationDialog::~SshKeyCreationDialog()
+{
+ delete m_ui;
+}
+
+void SshKeyCreationDialog::keyTypeChanged()
+{
+ m_ui->comboBox->clear();
+ QStringList keySizes;
+ if (m_ui->rsa->isChecked())
+ keySizes << QLatin1String("1024") << QLatin1String("2048") << QLatin1String("4096");
+ else if (m_ui->ecdsa->isChecked())
+ keySizes << QLatin1String("256") << QLatin1String("384") << QLatin1String("521");
+ m_ui->comboBox->addItems(keySizes);
+ if (!keySizes.isEmpty())
+ m_ui->comboBox->setCurrentIndex(0);
+ m_ui->comboBox->setEnabled(!keySizes.isEmpty());
+}
+
+void SshKeyCreationDialog::generateKeys()
+{
+ if (SshSettings::keygenFilePath().isEmpty()) {
+ showError(tr("The ssh-keygen tool was not found."));
+ return;
+ }
+ if (privateKeyFilePath().exists()) {
+ showError(tr("Refusing to overwrite existing private key file \"%1\".")
+ .arg(privateKeyFilePath().toUserOutput()));
+ return;
+ }
+ const QString keyTypeString = QLatin1String(m_ui->rsa->isChecked() ? "rsa": "ecdsa");
+ QApplication::setOverrideCursor(Qt::BusyCursor);
+ QtcProcess keygen;
+ const QStringList args{"-t", keyTypeString, "-b", m_ui->comboBox->currentText(),
+ "-N", QString(), "-f", privateKeyFilePath().path()};
+ QString errorMsg;
+ keygen.setCommand({SshSettings::keygenFilePath(), args});
+ keygen.start();
+ if (!keygen.waitForStarted() || !keygen.waitForFinished())
+ errorMsg = keygen.errorString();
+ else if (keygen.exitCode() != 0)
+ errorMsg = QString::fromLocal8Bit(keygen.readAllStandardError());
+ if (!errorMsg.isEmpty()) {
+ showError(tr("The ssh-keygen tool at \"%1\" failed: %2")
+ .arg(SshSettings::keygenFilePath().toUserOutput(), errorMsg));
+ }
+ QApplication::restoreOverrideCursor();
+ accept();
+}
+
+void SshKeyCreationDialog::handleBrowseButtonClicked()
+{
+ const FilePath filePath = FileUtils::getSaveFilePath(this, tr("Choose Private Key File Name"));
+ if (!filePath.isEmpty())
+ setPrivateKeyFile(filePath);
+}
+
+void SshKeyCreationDialog::setPrivateKeyFile(const FilePath &filePath)
+{
+ m_ui->privateKeyFileValueLabel->setText(filePath.toUserOutput());
+ m_ui->generateButton->setEnabled(!privateKeyFilePath().isEmpty());
+ m_ui->publicKeyFileLabel->setText(filePath.toUserOutput() + ".pub");
+}
+
+void SshKeyCreationDialog::showError(const QString &details)
+{
+ QMessageBox::critical(this, tr("Key Generation Failed"), details);
+}
+
+FilePath SshKeyCreationDialog::privateKeyFilePath() const
+{
+ return FilePath::fromUserInput(m_ui->privateKeyFileValueLabel->text());
+}
+
+FilePath SshKeyCreationDialog::publicKeyFilePath() const
+{
+ return FilePath::fromUserInput(m_ui->publicKeyFileLabel->text());
+}
+
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/sshkeycreationdialog.h b/src/plugins/remotelinux/sshkeycreationdialog.h
new file mode 100644
index 00000000000..859ac326a67
--- /dev/null
+++ b/src/plugins/remotelinux/sshkeycreationdialog.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QDialog>
+
+namespace Utils { class FilePath; }
+
+namespace RemoteLinux {
+
+namespace Ui { class SshKeyCreationDialog; }
+
+class SshKeyCreationDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ SshKeyCreationDialog(QWidget *parent = nullptr);
+ ~SshKeyCreationDialog();
+
+ Utils::FilePath privateKeyFilePath() const;
+ Utils::FilePath publicKeyFilePath() const;
+
+private:
+ void keyTypeChanged();
+ void generateKeys();
+ void handleBrowseButtonClicked();
+ void setPrivateKeyFile(const Utils::FilePath &filePath);
+ void showError(const QString &details);
+
+private:
+ Ui::SshKeyCreationDialog *m_ui;
+};
+
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/sshkeycreationdialog.ui b/src/plugins/remotelinux/sshkeycreationdialog.ui
new file mode 100644
index 00000000000..21f435be227
--- /dev/null
+++ b/src/plugins/remotelinux/sshkeycreationdialog.ui
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RemoteLinux::SshKeyCreationDialog</class>
+ <widget class="QDialog" name="RemoteLinux::SshKeyCreationDialog">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>385</width>
+ <height>231</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>SSH Key Configuration</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="keyAlgo">
+ <property name="text">
+ <string>Key algorithm:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QRadioButton" name="rsa">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;RSA</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="ecdsa">
+ <property name="text">
+ <string>ECDSA</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="keySize">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Key &amp;size:</string>
+ </property>
+ <property name="buddy">
+ <cstring>comboBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QComboBox" name="comboBox"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="privateKeyFileLabel">
+ <property name="text">
+ <string>Private key file:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QLabel" name="privateKeyFileValueLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="privateKeyFileButton">
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Public key file:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="publicKeyFileLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="generateButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Generate And Save Key Pair</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="closeButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>closeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>RemoteLinux::SshKeyCreationDialog</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>195</x>
+ <y>184</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>381</x>
+ <y>107</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/remotelinux/sshkeydeployer.cpp b/src/plugins/remotelinux/sshkeydeployer.cpp
deleted file mode 100644
index 9d5435ed4bf..00000000000
--- a/src/plugins/remotelinux/sshkeydeployer.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sshkeydeployer.h"
-
-#include <ssh/sshremoteprocessrunner.h>
-#include <utils/filepath.h>
-
-using namespace QSsh;
-using namespace Utils;
-
-namespace RemoteLinux {
-namespace Internal {
-
-class SshKeyDeployerPrivate
-{
-public:
- SshRemoteProcessRunner deployProcess;
-};
-
-} // namespace Internal
-
-SshKeyDeployer::SshKeyDeployer(QObject *parent)
- : QObject(parent), d(new Internal::SshKeyDeployerPrivate)
-{
-}
-
-SshKeyDeployer::~SshKeyDeployer()
-{
- cleanup();
- delete d;
-}
-
-void SshKeyDeployer::deployPublicKey(const SshConnectionParameters &sshParams,
- const FilePath &keyFilePath)
-{
- cleanup();
-
- FileReader reader;
- if (!reader.fetch(keyFilePath)) {
- emit error(tr("Public key error: %1").arg(reader.errorString()));
- return;
- }
-
- connect(&d->deployProcess, &SshRemoteProcessRunner::connectionError,
- this, &SshKeyDeployer::handleConnectionFailure);
- connect(&d->deployProcess, &SshRemoteProcessRunner::processClosed,
- this, &SshKeyDeployer::handleKeyUploadFinished);
- const QString command = "test -d .ssh "
- "|| mkdir -p ~/.ssh && chmod 0700 .ssh && echo '"
- + QString::fromLocal8Bit(reader.data())
- + "' >> .ssh/authorized_keys && chmod 0600 .ssh/authorized_keys";
- d->deployProcess.run(command, sshParams);
-}
-
-void SshKeyDeployer::handleConnectionFailure()
-{
- cleanup();
- emit error(tr("Connection failed: %1").arg(d->deployProcess.lastConnectionErrorString()));
-}
-
-void SshKeyDeployer::handleKeyUploadFinished()
-{
- const int exitCode = d->deployProcess.processExitCode();
- const QString errorMsg = d->deployProcess.processErrorString();
- cleanup();
- if (errorMsg.isEmpty() && exitCode == 0) {
- emit finishedSuccessfully();
- } else {
- emit error(tr("Key deployment failed: %1.").arg(errorMsg.isEmpty()
- ? QString::fromUtf8(d->deployProcess.readAllStandardError())
- : errorMsg));
- }
-}
-
-void SshKeyDeployer::stopDeployment()
-{
- cleanup();
-}
-
-void SshKeyDeployer::cleanup()
-{
- disconnect(&d->deployProcess, nullptr, this, nullptr);
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/sshkeydeployer.h b/src/plugins/remotelinux/sshkeydeployer.h
deleted file mode 100644
index 984f7a664f5..00000000000
--- a/src/plugins/remotelinux/sshkeydeployer.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "remotelinux_export.h"
-
-#include <QObject>
-
-namespace QSsh { class SshConnectionParameters; }
-namespace Utils { class FilePath; }
-
-namespace RemoteLinux {
-namespace Internal { class SshKeyDeployerPrivate; }
-
-class REMOTELINUX_EXPORT SshKeyDeployer : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(SshKeyDeployer)
-public:
- explicit SshKeyDeployer(QObject *parent = nullptr);
- ~SshKeyDeployer() override;
-
- void deployPublicKey(const QSsh::SshConnectionParameters &sshParams,
- const Utils::FilePath &keyFilePath);
- void stopDeployment();
-
-signals:
- void error(const QString &errorMsg);
- void finishedSuccessfully();
-
-private:
- void handleConnectionFailure();
- void handleKeyUploadFinished();
- void cleanup();
-
- Internal::SshKeyDeployerPrivate * const d;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/sshprocessinterface.h b/src/plugins/remotelinux/sshprocessinterface.h
new file mode 100644
index 00000000000..871c90d3ed6
--- /dev/null
+++ b/src/plugins/remotelinux/sshprocessinterface.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "remotelinux_export.h"
+
+#include <utils/processinterface.h>
+
+namespace RemoteLinux {
+
+class LinuxDevice;
+class SshProcessInterfacePrivate;
+
+class REMOTELINUX_EXPORT SshProcessInterface : public Utils::ProcessInterface
+{
+public:
+ SshProcessInterface(const LinuxDevice *linuxDevice);
+ ~SshProcessInterface();
+
+protected:
+ void emitStarted(qint64 processId);
+ // To be called from leaf destructor.
+ // Can't call it from SshProcessInterface destructor as it calls virtual method.
+ void killIfRunning();
+ qint64 processId() const;
+ bool runInShell(const Utils::CommandLine &command, const QByteArray &data = {});
+
+private:
+ virtual void handleStarted(qint64 processId);
+ virtual void handleDone(const Utils::ProcessResultData &resultData);
+ virtual void handleReadyReadStandardOutput(const QByteArray &outputData);
+ virtual void handleReadyReadStandardError(const QByteArray &errorData);
+
+ virtual QString fullCommandLine(const Utils::CommandLine &commandLine) const = 0;
+
+ void start() final;
+ qint64 write(const QByteArray &data) final;
+ void sendControlSignal(Utils::ControlSignal controlSignal) override = 0;
+
+ friend class SshProcessInterfacePrivate;
+ SshProcessInterfacePrivate *d = nullptr;
+};
+
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/tarpackagecreationstep.cpp b/src/plugins/remotelinux/tarpackagecreationstep.cpp
index ed89fb6564f..23eb9745bd7 100644
--- a/src/plugins/remotelinux/tarpackagecreationstep.cpp
+++ b/src/plugins/remotelinux/tarpackagecreationstep.cpp
@@ -25,6 +25,7 @@
#include "tarpackagecreationstep.h"
+#include "deploymenttimeinfo.h"
#include "remotelinux_constants.h"
#include <projectexplorer/buildmanager.h>
@@ -32,9 +33,6 @@
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshconnectionmanager.h>
-
#include <QDateTime>
#include <QDir>
#include <QFile>
@@ -46,7 +44,7 @@ using namespace ProjectExplorer;
using namespace Utils;
namespace RemoteLinux {
-namespace {
+
const char IgnoreMissingFilesKey[] = "RemoteLinux.TarPackageCreationStep.IgnoreMissingFiles";
const char IncrementalDeploymentKey[] = "RemoteLinux.TarPackageCreationStep.IncrementalDeployment";
@@ -71,20 +69,40 @@ struct TarFileHeader {
char padding[12];
};
-} // Anonymous namespace.
+namespace Internal {
+
+class TarPackageCreationStepPrivate
+{
+public:
+ FilePath m_cachedPackageFilePath;
+ bool m_deploymentDataModified = false;
+ DeploymentTimeInfo m_deployTimes;
+ BoolAspect *m_incrementalDeploymentAspect = nullptr;
+ BoolAspect *m_ignoreMissingFilesAspect = nullptr;
+ bool m_packagingNeeded = false;
+ QList<DeployableFile> m_files;
+};
+
+} // namespace Internal
-TarPackageCreationStep::TarPackageCreationStep(BuildStepList *bsl, Utils::Id id)
- : AbstractPackagingStep(bsl, id)
+TarPackageCreationStep::TarPackageCreationStep(BuildStepList *bsl, Id id)
+ : BuildStep(bsl, id)
+ , d(new Internal::TarPackageCreationStepPrivate)
{
- m_ignoreMissingFilesAspect = addAspect<BoolAspect>();
- m_ignoreMissingFilesAspect->setLabel(tr("Ignore missing files"),
+ connect(target(), &Target::deploymentDataChanged, this, [this] {
+ d->m_deploymentDataModified = true;
+ });
+ d->m_deploymentDataModified = true;
+
+ d->m_ignoreMissingFilesAspect = addAspect<BoolAspect>();
+ d->m_ignoreMissingFilesAspect->setLabel(tr("Ignore missing files"),
BoolAspect::LabelPlacement::AtCheckBox);
- m_ignoreMissingFilesAspect->setSettingsKey(IgnoreMissingFilesKey);
+ d->m_ignoreMissingFilesAspect->setSettingsKey(IgnoreMissingFilesKey);
- m_incrementalDeploymentAspect = addAspect<BoolAspect>();
- m_incrementalDeploymentAspect->setLabel(tr("Package modified files only"),
+ d->m_incrementalDeploymentAspect = addAspect<BoolAspect>();
+ d->m_incrementalDeploymentAspect->setLabel(tr("Package modified files only"),
BoolAspect::LabelPlacement::AtCheckBox);
- m_incrementalDeploymentAspect->setSettingsKey(IncrementalDeploymentKey);
+ d->m_incrementalDeploymentAspect->setSettingsKey(IncrementalDeploymentKey);
setSummaryUpdater([this] {
FilePath path = packageFilePath();
@@ -95,13 +113,30 @@ TarPackageCreationStep::TarPackageCreationStep(BuildStepList *bsl, Utils::Id id)
});
}
-bool TarPackageCreationStep::init()
+TarPackageCreationStep::~TarPackageCreationStep() = default;
+
+Utils::Id TarPackageCreationStep::stepId()
{
- if (!AbstractPackagingStep::init())
- return false;
+ return Constants::TarPackageCreationStepId;
+}
- m_packagingNeeded = isPackagingNeeded();
+QString TarPackageCreationStep::displayName()
+{
+ return tr("Create tarball");
+}
+
+FilePath TarPackageCreationStep::packageFilePath() const
+{
+ if (buildDirectory().isEmpty())
+ return {};
+ const QString packageFileName = project()->displayName() + QLatin1String(".tar");
+ return buildDirectory().pathAppended(packageFileName);
+}
+bool TarPackageCreationStep::init()
+{
+ d->m_cachedPackageFilePath = packageFilePath();
+ d->m_packagingNeeded = isPackagingNeeded();
return true;
}
@@ -110,14 +145,76 @@ void TarPackageCreationStep::doRun()
runInThread([this] { return runImpl(); });
}
+bool TarPackageCreationStep::fromMap(const QVariantMap &map)
+{
+ if (!BuildStep::fromMap(map))
+ return false;
+ d->m_deployTimes.importDeployTimes(map);
+ return true;
+}
+
+QVariantMap TarPackageCreationStep::toMap() const
+{
+ QVariantMap map = BuildStep::toMap();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ map.insert(d->m_deployTimes.exportDeployTimes());
+#else
+ map.unite(d->m_deployTimes.exportDeployTimes());
+#endif
+ return map;
+}
+
+void TarPackageCreationStep::raiseError(const QString &errorMessage)
+{
+ emit addTask(DeploymentTask(Task::Error, errorMessage));
+ emit addOutput(errorMessage, BuildStep::OutputFormat::Stderr);
+}
+
+void TarPackageCreationStep::raiseWarning(const QString &warningMessage)
+{
+ emit addTask(DeploymentTask(Task::Warning, warningMessage));
+ emit addOutput(warningMessage, OutputFormat::ErrorMessage);
+}
+
+bool TarPackageCreationStep::isPackagingNeeded() const
+{
+ const FilePath packagePath = packageFilePath();
+ if (!packagePath.exists() || d->m_deploymentDataModified)
+ return true;
+
+ const DeploymentData &dd = target()->deploymentData();
+ for (int i = 0; i < dd.fileCount(); ++i) {
+ if (dd.fileAt(i).localFilePath().isNewerThan(packagePath.lastModified()))
+ return true;
+ }
+
+ return false;
+}
+
+void TarPackageCreationStep::deployFinished(bool success)
+{
+ disconnect(BuildManager::instance(), &BuildManager::buildQueueFinished,
+ this, &TarPackageCreationStep::deployFinished);
+
+ if (!success)
+ return;
+
+ const Kit *kit = target()->kit();
+
+ // Store files that have been tar'd and successfully deployed
+ const auto files = d->m_files;
+ for (const DeployableFile &file : files)
+ d->m_deployTimes.saveDeploymentTimeStamp(file, kit, QDateTime());
+}
+
void TarPackageCreationStep::addNeededDeploymentFiles(
const ProjectExplorer::DeployableFile &deployable,
const ProjectExplorer::Kit *kit)
{
const QFileInfo fileInfo = deployable.localFilePath().toFileInfo();
if (!fileInfo.isDir()) {
- if (m_deployTimes.hasLocalFileChanged(deployable, kit))
- m_files << deployable;
+ if (d->m_deployTimes.hasLocalFileChanged(deployable, kit))
+ d->m_files << deployable;
return;
}
@@ -125,7 +222,7 @@ void TarPackageCreationStep::addNeededDeploymentFiles(
.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
if (files.isEmpty()) {
- m_files << deployable;
+ d->m_files << deployable;
return;
}
@@ -139,16 +236,43 @@ void TarPackageCreationStep::addNeededDeploymentFiles(
}
}
+bool TarPackageCreationStep::runImpl()
+{
+ const QList<DeployableFile> &files = target()->deploymentData().allFiles();
+
+ if (d->m_incrementalDeploymentAspect->value()) {
+ d->m_files.clear();
+ for (const DeployableFile &file : files)
+ addNeededDeploymentFiles(file, kit());
+ } else {
+ d->m_files = files;
+ }
+
+ const bool success = doPackage();
+
+ if (success) {
+ d->m_deploymentDataModified = false;
+ emit addOutput(tr("Packaging finished successfully."), OutputFormat::NormalMessage);
+ } else {
+ emit addOutput(tr("Packaging failed."), OutputFormat::ErrorMessage);
+ }
+
+ connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
+ this, &TarPackageCreationStep::deployFinished);
+
+ return success;
+}
+
bool TarPackageCreationStep::doPackage()
{
emit addOutput(tr("Creating tarball..."), OutputFormat::NormalMessage);
- if (!m_packagingNeeded) {
+ if (!d->m_packagingNeeded) {
emit addOutput(tr("Tarball up to date, skipping packaging."), OutputFormat::NormalMessage);
return true;
}
// TODO: Optimization: Only package changed files
- const FilePath tarFilePath = cachedPackageFilePath();
+ const FilePath tarFilePath = d->m_cachedPackageFilePath;
QFile tarFile(tarFilePath.toString());
if (!tarFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
@@ -157,7 +281,7 @@ bool TarPackageCreationStep::doPackage()
return false;
}
- foreach (const DeployableFile &d, m_files) {
+ for (const DeployableFile &d : qAsConst(d->m_files)) {
if (d.remoteDirectory().isEmpty()) {
emit addOutput(tr("No remote path specified for file \"%1\", skipping.")
.arg(d.localFilePath().toUserOutput()), OutputFormat::ErrorMessage);
@@ -180,66 +304,6 @@ bool TarPackageCreationStep::doPackage()
return true;
}
-bool TarPackageCreationStep::appendFile(QFile &tarFile, const QFileInfo &fileInfo,
- const QString &remoteFilePath)
-{
- if (!writeHeader(tarFile, fileInfo, remoteFilePath))
- return false;
- if (fileInfo.isDir()) {
- QDir dir(fileInfo.absoluteFilePath());
- foreach (const QString &fileName,
- dir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
- const QString thisLocalFilePath = dir.path() + QLatin1Char('/') + fileName;
- const QString thisRemoteFilePath = remoteFilePath + QLatin1Char('/') + fileName;
- if (!appendFile(tarFile, QFileInfo(thisLocalFilePath), thisRemoteFilePath))
- return false;
- }
- return true;
- }
-
- const QString nativePath = QDir::toNativeSeparators(fileInfo.filePath());
- QFile file(fileInfo.filePath());
- if (!file.open(QIODevice::ReadOnly)) {
- const QString message = tr("Error reading file \"%1\": %2.")
- .arg(nativePath, file.errorString());
- if (m_ignoreMissingFilesAspect->value()) {
- raiseWarning(message);
- return true;
- } else {
- raiseError(message);
- return false;
- }
- }
-
- const int chunkSize = 1024*1024;
-
- emit addOutput(tr("Adding file \"%1\" to tarball...").arg(nativePath),
- OutputFormat::NormalMessage);
-
- // TODO: Wasteful. Work with fixed-size buffer.
- while (!file.atEnd() && file.error() == QFile::NoError && tarFile.error() == QFile::NoError) {
- const QByteArray data = file.read(chunkSize);
- tarFile.write(data);
- if (isCanceled())
- return false;
- }
- if (file.error() != QFile::NoError) {
- raiseError(tr("Error reading file \"%1\": %2.").arg(nativePath, file.errorString()));
- return false;
- }
-
- const int blockModulo = file.size() % TarBlockSize;
- if (blockModulo != 0)
- tarFile.write(QByteArray(TarBlockSize - blockModulo, 0));
-
- if (tarFile.error() != QFile::NoError) {
- raiseError(tr("Error writing tar file \"%1\": %2.")
- .arg(QDir::toNativeSeparators(tarFile.fileName()), tarFile.errorString()));
- return false;
- }
- return true;
-}
-
static bool setFilePath(TarFileHeader &header, const QByteArray &filePath)
{
if (filePath.length() <= int(sizeof header.fileName)) {
@@ -260,13 +324,14 @@ static bool setFilePath(TarFileHeader &header, const QByteArray &filePath)
return false;
}
-bool TarPackageCreationStep::writeHeader(QFile &tarFile, const QFileInfo &fileInfo,
- const QString &remoteFilePath)
+static bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo, const QString &remoteFilePath,
+ const QString &cachedPackageFilePath, QString *errorMessage)
{
TarFileHeader header;
std::memset(&header, '\0', sizeof header);
if (!setFilePath(header, remoteFilePath.toUtf8())) {
- raiseError(tr("Cannot add file \"%1\" to tar-archive: path too long.").arg(remoteFilePath));
+ *errorMessage = QCoreApplication::translate("RemoteLinux::TarPackageCreationStep",
+ "Cannot add file \"%1\" to tar-archive: path too long.").arg(remoteFilePath);
return false;
}
int permissions = (0400 * fileInfo.permission(QFile::ReadOwner))
@@ -311,89 +376,75 @@ bool TarPackageCreationStep::writeHeader(QFile &tarFile, const QFileInfo &fileIn
std::memcpy(&header.chksum, checksumString.data(), checksumString.length());
header.chksum[sizeof header.chksum-1] = 0;
if (!tarFile.write(reinterpret_cast<char *>(&header), sizeof header)) {
- raiseError(tr("Error writing tar file \"%1\": %2")
- .arg(cachedPackageFilePath().toUserOutput(), tarFile.errorString()));
+ *errorMessage = QCoreApplication::translate("RemoteLinux::TarPackageCreationStep",
+ "Error writing tar file \"%1\": %2").arg(cachedPackageFilePath, tarFile.errorString());
return false;
}
return true;
}
-void TarPackageCreationStep::deployFinished(bool success)
-{
- disconnect(BuildManager::instance(), &BuildManager::buildQueueFinished,
- this, &TarPackageCreationStep::deployFinished);
-
- if (!success)
- return;
-
- const Kit *kit = target()->kit();
-
- // Store files that have been tar'd and successfully deployed
- const auto files = m_files;
- for (const DeployableFile &file : files)
- m_deployTimes.saveDeploymentTimeStamp(file, kit, QDateTime());
-}
-
-QString TarPackageCreationStep::packageFileName() const
-{
- return project()->displayName() + QLatin1String(".tar");
-}
-
-bool TarPackageCreationStep::runImpl()
+bool TarPackageCreationStep::appendFile(QFile &tarFile, const QFileInfo &fileInfo,
+ const QString &remoteFilePath)
{
- setPackagingStarted();
-
- const QList<DeployableFile> &files = target()->deploymentData().allFiles();
+ QString errorMessage;
+ if (!writeHeader(tarFile, fileInfo, remoteFilePath, d->m_cachedPackageFilePath.toUserOutput(),
+ &errorMessage)) {
+ raiseError(errorMessage);
+ return false;
+ }
+ if (fileInfo.isDir()) {
+ QDir dir(fileInfo.absoluteFilePath());
+ foreach (const QString &fileName,
+ dir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
+ const QString thisLocalFilePath = dir.path() + QLatin1Char('/') + fileName;
+ const QString thisRemoteFilePath = remoteFilePath + QLatin1Char('/') + fileName;
+ if (!appendFile(tarFile, QFileInfo(thisLocalFilePath), thisRemoteFilePath))
+ return false;
+ }
+ return true;
+ }
- if (m_incrementalDeploymentAspect->value()) {
- m_files.clear();
- for (const DeployableFile &file : files)
- addNeededDeploymentFiles(file, kit());
- } else {
- m_files = files;
+ const QString nativePath = QDir::toNativeSeparators(fileInfo.filePath());
+ QFile file(fileInfo.filePath());
+ if (!file.open(QIODevice::ReadOnly)) {
+ const QString message = tr("Error reading file \"%1\": %2.")
+ .arg(nativePath, file.errorString());
+ if (d->m_ignoreMissingFilesAspect->value()) {
+ raiseWarning(message);
+ return true;
+ } else {
+ raiseError(message);
+ return false;
+ }
}
- const bool success = doPackage();
+ const int chunkSize = 1024*1024;
- setPackagingFinished(success);
- if (success)
- emit addOutput(tr("Packaging finished successfully."), OutputFormat::NormalMessage);
- else
- emit addOutput(tr("Packaging failed."), OutputFormat::ErrorMessage);
+ emit addOutput(tr("Adding file \"%1\" to tarball...").arg(nativePath),
+ OutputFormat::NormalMessage);
- connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
- this, &TarPackageCreationStep::deployFinished);
+ // TODO: Wasteful. Work with fixed-size buffer.
+ while (!file.atEnd() && file.error() == QFile::NoError && tarFile.error() == QFile::NoError) {
+ const QByteArray data = file.read(chunkSize);
+ tarFile.write(data);
+ if (isCanceled())
+ return false;
+ }
+ if (file.error() != QFile::NoError) {
+ raiseError(tr("Error reading file \"%1\": %2.").arg(nativePath, file.errorString()));
+ return false;
+ }
- return success;
-}
+ const int blockModulo = file.size() % TarBlockSize;
+ if (blockModulo != 0)
+ tarFile.write(QByteArray(TarBlockSize - blockModulo, 0));
-bool TarPackageCreationStep::fromMap(const QVariantMap &map)
-{
- if (!AbstractPackagingStep::fromMap(map))
+ if (tarFile.error() != QFile::NoError) {
+ raiseError(tr("Error writing tar file \"%1\": %2.")
+ .arg(QDir::toNativeSeparators(tarFile.fileName()), tarFile.errorString()));
return false;
- m_deployTimes.importDeployTimes(map);
+ }
return true;
}
-QVariantMap TarPackageCreationStep::toMap() const
-{
- QVariantMap map = AbstractPackagingStep::toMap();
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- map.insert(m_deployTimes.exportDeployTimes());
-#else
- map.unite(m_deployTimes.exportDeployTimes());
-#endif
- return map;
-}
-
-Utils::Id TarPackageCreationStep::stepId()
-{
- return Constants::TarPackageCreationStepId;
-}
-
-QString TarPackageCreationStep::displayName()
-{
- return tr("Create tarball");
-}
-
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/tarpackagecreationstep.h b/src/plugins/remotelinux/tarpackagecreationstep.h
index 33a7b4358e6..73b80fcac2e 100644
--- a/src/plugins/remotelinux/tarpackagecreationstep.h
+++ b/src/plugins/remotelinux/tarpackagecreationstep.h
@@ -25,63 +25,51 @@
#pragma once
-#include "abstractpackagingstep.h"
-#include "deploymenttimeinfo.h"
#include "remotelinux_export.h"
-#include <projectexplorer/deployablefile.h>
-
-#include <utils/aspects.h>
+#include <projectexplorer/buildstep.h>
QT_BEGIN_NAMESPACE
class QFile;
class QFileInfo;
QT_END_NAMESPACE
+namespace ProjectExplorer { class DeployableFile; }
+
namespace RemoteLinux {
-class REMOTELINUX_EXPORT TarPackageCreationStep : public AbstractPackagingStep
+namespace Internal { class TarPackageCreationStepPrivate; }
+
+class REMOTELINUX_EXPORT TarPackageCreationStep : public ProjectExplorer::BuildStep
{
Q_OBJECT
+
public:
- TarPackageCreationStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
+ explicit TarPackageCreationStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
+ ~TarPackageCreationStep() override;
static Utils::Id stepId();
static QString displayName();
- void setIgnoreMissingFiles(bool ignoreMissingFiles);
- bool ignoreMissingFiles() const;
-
- void setIncrementalDeployment(bool incrementalDeployment);
- bool isIncrementalDeployment() const;
+ Utils::FilePath packageFilePath() const;
private:
bool init() override;
void doRun() override;
+ bool fromMap(const QVariantMap &map) override;
+ QVariantMap toMap() const override;
+ void raiseError(const QString &errorMessage);
+ void raiseWarning(const QString &warningMessage);
+ bool isPackagingNeeded() const;
void deployFinished(bool success);
-
void addNeededDeploymentFiles(const ProjectExplorer::DeployableFile &deployable,
const ProjectExplorer::Kit *kit);
-
- bool fromMap(const QVariantMap &map) override;
- QVariantMap toMap() const override;
-
- QString packageFileName() const override;
-
bool runImpl();
bool doPackage();
- bool appendFile(QFile &tarFile, const QFileInfo &fileInfo,
- const QString &remoteFilePath);
- bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo,
- const QString &remoteFilePath);
-
- DeploymentTimeInfo m_deployTimes;
+ bool appendFile(QFile &tarFile, const QFileInfo &fileInfo, const QString &remoteFilePath);
- Utils::BoolAspect *m_incrementalDeploymentAspect = nullptr;
- Utils::BoolAspect *m_ignoreMissingFilesAspect = nullptr;
- bool m_packagingNeeded = false;
- QList<ProjectExplorer::DeployableFile> m_files;
+ std::unique_ptr<Internal::TarPackageCreationStepPrivate> d;
};
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/tarpackagedeploystep.cpp b/src/plugins/remotelinux/tarpackagedeploystep.cpp
new file mode 100644
index 00000000000..83732a071ba
--- /dev/null
+++ b/src/plugins/remotelinux/tarpackagedeploystep.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "tarpackagedeploystep.h"
+
+#include "abstractremotelinuxdeployservice.h"
+#include "abstractremotelinuxdeploystep.h"
+#include "remotelinux_constants.h"
+#include "tarpackagecreationstep.h"
+
+#include <projectexplorer/deployconfiguration.h>
+#include <projectexplorer/devicesupport/filetransfer.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/projectexplorerconstants.h>
+
+#include <utils/processinterface.h>
+#include <utils/qtcprocess.h>
+
+#include <QDateTime>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace RemoteLinux {
+namespace Internal {
+
+class TarPackageInstaller : public QObject
+{
+ Q_OBJECT
+
+public:
+ TarPackageInstaller();
+
+ void installPackage(const IDeviceConstPtr &deviceConfig,
+ const QString &packageFilePath,
+ bool removePackageFile);
+ void cancelInstallation();
+
+signals:
+ void stdoutData(const QString &output);
+ void stderrData(const QString &output);
+ void finished(const QString &errorMsg = QString());
+
+private:
+ IDevice::ConstPtr m_device;
+ QtcProcess m_installer;
+ QtcProcess m_killer;
+};
+
+TarPackageInstaller::TarPackageInstaller()
+{
+ connect(&m_installer, &QtcProcess::readyReadStandardOutput, this, [this] {
+ emit stdoutData(QString::fromUtf8(m_installer.readAllStandardOutput()));
+ });
+ connect(&m_installer, &QtcProcess::readyReadStandardError, this, [this] {
+ emit stderrData(QString::fromUtf8(m_installer.readAllStandardError()));
+ });
+ connect(&m_installer, &QtcProcess::done, this, [this] {
+ const QString errorMessage = m_installer.result() == ProcessResult::FinishedWithSuccess
+ ? QString() : tr("Installing package failed.") + m_installer.errorString();
+ emit finished(errorMessage);
+ });
+}
+
+void TarPackageInstaller::installPackage(const IDevice::ConstPtr &deviceConfig,
+ const QString &packageFilePath, bool removePackageFile)
+{
+ QTC_ASSERT(m_installer.state() == QProcess::NotRunning, return);
+
+ m_device = deviceConfig;
+
+ QString cmdLine = QLatin1String("cd / && tar xvf ") + packageFilePath;
+ if (removePackageFile)
+ cmdLine += QLatin1String(" && (rm ") + packageFilePath + QLatin1String(" || :)");
+ m_installer.setCommand({m_device->filePath("/bin/sh"), {"-c", cmdLine}});
+ m_installer.start();
+}
+
+void TarPackageInstaller::cancelInstallation()
+{
+ QTC_ASSERT(m_installer.state() != QProcess::NotRunning, return);
+
+ m_killer.setCommand({m_device->filePath("/bin/sh"), {"-c", "pkill tar"}});
+ m_killer.start();
+ m_installer.close();
+}
+
+class TarPackageDeployService : public AbstractRemoteLinuxDeployService
+{
+ Q_OBJECT
+
+public:
+ TarPackageDeployService();
+ void setPackageFilePath(const FilePath &filePath);
+
+private:
+ enum State { Inactive, Uploading, Installing };
+
+ void handleUploadFinished(const ProcessResultData &resultData);
+ void handleInstallationFinished(const QString &errorMsg);
+
+ QString uploadDir() const; // Defaults to remote user's home directory.
+
+ bool isDeploymentNecessary() const override;
+ void doDeploy() override;
+ void stopDeployment() override;
+
+ void setFinished();
+
+ State m_state = Inactive;
+ FileTransfer m_uploader;
+ FilePath m_packageFilePath;
+ TarPackageInstaller m_installer;
+};
+
+TarPackageDeployService::TarPackageDeployService()
+{
+ connect(&m_uploader, &FileTransfer::done, this,
+ &TarPackageDeployService::handleUploadFinished);
+ connect(&m_uploader, &FileTransfer::progress, this,
+ &TarPackageDeployService::progressMessage);
+}
+
+void TarPackageDeployService::setPackageFilePath(const FilePath &filePath)
+{
+ m_packageFilePath = filePath;
+}
+
+QString TarPackageDeployService::uploadDir() const
+{
+ return QLatin1String("/tmp");
+}
+
+bool TarPackageDeployService::isDeploymentNecessary() const
+{
+ return hasLocalFileChanged(DeployableFile(m_packageFilePath, {}));
+}
+
+void TarPackageDeployService::doDeploy()
+{
+ QTC_ASSERT(m_state == Inactive, return);
+
+ m_state = Uploading;
+
+ const QString remoteFilePath = uploadDir() + QLatin1Char('/') + m_packageFilePath.fileName();
+ const FilesToTransfer files {{m_packageFilePath,
+ deviceConfiguration()->filePath(remoteFilePath)}};
+ m_uploader.setFilesToTransfer(files);
+ m_uploader.start();
+}
+
+void TarPackageDeployService::stopDeployment()
+{
+ switch (m_state) {
+ case Inactive:
+ qWarning("%s: Unexpected state 'Inactive'.", Q_FUNC_INFO);
+ break;
+ case Uploading:
+ m_uploader.stop();
+ setFinished();
+ break;
+ case Installing:
+ m_installer.cancelInstallation();
+ setFinished();
+ break;
+ }
+}
+
+void TarPackageDeployService::handleUploadFinished(const ProcessResultData &resultData)
+{
+ QTC_ASSERT(m_state == Uploading, return);
+
+ if (resultData.m_error != QProcess::UnknownError) {
+ emit errorMessage(resultData.m_errorString);
+ setFinished();
+ return;
+ }
+
+ emit progressMessage(tr("Successfully uploaded package file."));
+ const QString remoteFilePath = uploadDir() + '/' + m_packageFilePath.fileName();
+ m_state = Installing;
+ emit progressMessage(tr("Installing package to device..."));
+ connect(&m_installer, &TarPackageInstaller::stdoutData,
+ this, &AbstractRemoteLinuxDeployService::stdOutData);
+ connect(&m_installer, &TarPackageInstaller::stderrData,
+ this, &AbstractRemoteLinuxDeployService::stdErrData);
+ connect(&m_installer, &TarPackageInstaller::finished,
+ this, &TarPackageDeployService::handleInstallationFinished);
+ m_installer.installPackage(deviceConfiguration(), remoteFilePath, true);
+}
+
+void TarPackageDeployService::handleInstallationFinished(const QString &errorMsg)
+{
+ QTC_ASSERT(m_state == Installing, return);
+
+ if (errorMsg.isEmpty()) {
+ saveDeploymentTimeStamp(DeployableFile(m_packageFilePath, {}), {});
+ emit progressMessage(tr("Package installed."));
+ } else {
+ emit errorMessage(errorMsg);
+ }
+ setFinished();
+}
+
+void TarPackageDeployService::setFinished()
+{
+ m_state = Inactive;
+ m_uploader.stop();
+ disconnect(&m_installer, nullptr, this, nullptr);
+ handleDeploymentDone();
+}
+
+// TarPackageDeployStep
+
+class TarPackageDeployStep : public AbstractRemoteLinuxDeployStep
+{
+ Q_DECLARE_TR_FUNCTIONS(RemoteLinux::Internal::TarPackageDeployStep)
+
+public:
+ TarPackageDeployStep(BuildStepList *bsl, Id id)
+ : AbstractRemoteLinuxDeployStep(bsl, id)
+ {
+ auto service = createDeployService<TarPackageDeployService>();
+
+ setWidgetExpandedByDefault(false);
+
+ setInternalInitializer([this, service] {
+ const TarPackageCreationStep *pStep = nullptr;
+
+ for (BuildStep *step : deployConfiguration()->stepList()->steps()) {
+ if (step == this)
+ break;
+ if ((pStep = qobject_cast<TarPackageCreationStep *>(step)))
+ break;
+ }
+ if (!pStep)
+ return CheckResult::failure(tr("No tarball creation step found."));
+
+ service->setPackageFilePath(pStep->packageFilePath());
+ return service->isDeploymentPossible();
+ });
+ }
+};
+
+
+// TarPackageDeployStepFactory
+
+TarPackageDeployStepFactory::TarPackageDeployStepFactory()
+{
+ registerStep<TarPackageDeployStep>(Constants::TarPackageDeployStepId);
+ setDisplayName(TarPackageDeployStep::tr("Deploy tarball via SFTP upload"));
+ setSupportedConfiguration(RemoteLinux::Constants::DeployToGenericLinux);
+ setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY);
+}
+
+} // Internal
+} // RemoteLinux
+
+#include "tarpackagedeploystep.moc"
diff --git a/src/plugins/remotelinux/tarpackagedeploystep.h b/src/plugins/remotelinux/tarpackagedeploystep.h
new file mode 100644
index 00000000000..716fbb7876b
--- /dev/null
+++ b/src/plugins/remotelinux/tarpackagedeploystep.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectexplorer/buildstep.h>
+
+namespace RemoteLinux {
+namespace Internal {
+
+class TarPackageDeployStepFactory : public ProjectExplorer::BuildStepFactory
+{
+public:
+ TarPackageDeployStepFactory();
+};
+
+} // Internal
+} // RemoteLinux
diff --git a/src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp b/src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp
deleted file mode 100644
index 06edf9f867c..00000000000
--- a/src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "uploadandinstalltarpackagestep.h"
-
-#include "remotelinux_constants.h"
-#include "remotelinuxdeployconfiguration.h"
-#include "remotelinuxpackageinstaller.h"
-#include "tarpackagecreationstep.h"
-
-using namespace ProjectExplorer;
-
-namespace RemoteLinux {
-namespace Internal {
-
-class UploadAndInstallTarPackageServicePrivate
-{
-public:
- RemoteLinuxTarPackageInstaller installer;
-};
-
-} // namespace Internal
-
-using namespace Internal;
-
-UploadAndInstallTarPackageService::UploadAndInstallTarPackageService()
- : d(new UploadAndInstallTarPackageServicePrivate)
-{
-}
-
-UploadAndInstallTarPackageService::~UploadAndInstallTarPackageService()
-{
- delete d;
-}
-
-AbstractRemoteLinuxPackageInstaller *UploadAndInstallTarPackageService::packageInstaller() const
-{
- return &d->installer;
-}
-
-
-UploadAndInstallTarPackageStep::UploadAndInstallTarPackageStep(BuildStepList *bsl, Utils::Id id)
- : AbstractRemoteLinuxDeployStep(bsl, id)
-{
- auto service = createDeployService<UploadAndInstallTarPackageService>();
-
- setWidgetExpandedByDefault(false);
-
- setInternalInitializer([this, service] {
- const TarPackageCreationStep *pStep = nullptr;
-
- for (BuildStep *step : deployConfiguration()->stepList()->steps()) {
- if (step == this)
- break;
- if ((pStep = dynamic_cast<TarPackageCreationStep *>(step)))
- break;
- }
- if (!pStep)
- return CheckResult::failure(tr("No tarball creation step found."));
-
- service->setPackageFilePath(pStep->packageFilePath());
- return service->isDeploymentPossible();
- });
-}
-
-Utils::Id UploadAndInstallTarPackageStep::stepId()
-{
- return Constants::UploadAndInstallTarPackageStepId;
-}
-
-QString UploadAndInstallTarPackageStep::displayName()
-{
- return tr("Deploy tarball via SFTP upload");
-}
-
-} //namespace RemoteLinux
diff --git a/src/plugins/remotelinux/uploadandinstalltarpackagestep.h b/src/plugins/remotelinux/uploadandinstalltarpackagestep.h
deleted file mode 100644
index f67e768baf4..00000000000
--- a/src/plugins/remotelinux/uploadandinstalltarpackagestep.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "abstractuploadandinstallpackageservice.h"
-#include "abstractremotelinuxdeploystep.h"
-
-namespace RemoteLinux {
-class AbstractRemoteLinuxPackageInstaller;
-
-namespace Internal { class UploadAndInstallTarPackageServicePrivate; }
-
-class REMOTELINUX_EXPORT UploadAndInstallTarPackageService : public AbstractUploadAndInstallPackageService
-{
- Q_OBJECT
-
-public:
- UploadAndInstallTarPackageService();
- ~UploadAndInstallTarPackageService() override;
-
-private:
- AbstractRemoteLinuxPackageInstaller *packageInstaller() const override;
-
- Internal::UploadAndInstallTarPackageServicePrivate *d;
-};
-
-
-class REMOTELINUX_EXPORT UploadAndInstallTarPackageStep : public AbstractRemoteLinuxDeployStep
-{
- Q_OBJECT
-
-public:
- UploadAndInstallTarPackageStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
-
- static Utils::Id stepId();
- static QString displayName();
-};
-
-} //namespace RemoteLinux
diff --git a/src/plugins/remotelinux/x11forwardingaspect.cpp b/src/plugins/remotelinux/x11forwardingaspect.cpp
new file mode 100644
index 00000000000..952170a8224
--- /dev/null
+++ b/src/plugins/remotelinux/x11forwardingaspect.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "x11forwardingaspect.h"
+
+#include <utils/macroexpander.h>
+#include <utils/qtcassert.h>
+
+using namespace Utils;
+
+namespace RemoteLinux {
+
+static QString defaultDisplay() { return qEnvironmentVariable("DISPLAY"); }
+
+X11ForwardingAspect::X11ForwardingAspect(const MacroExpander *expander)
+ : m_macroExpander(expander)
+{
+ setLabelText(tr("X11 Forwarding:"));
+ setDisplayStyle(LineEditDisplay);
+ setId("X11ForwardingAspect");
+ setSettingsKey("RunConfiguration.X11Forwarding");
+ makeCheckable(CheckBoxPlacement::Right, tr("Forward to local display"),
+ "RunConfiguration.UseX11Forwarding");
+ setValue(defaultDisplay());
+
+ addDataExtractor(this, &X11ForwardingAspect::display, &Data::display);
+}
+
+QString X11ForwardingAspect::display() const
+{
+ QTC_ASSERT(m_macroExpander, return value());
+ return !isChecked() ? QString() : m_macroExpander->expandProcessArgs(value());
+}
+
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/x11forwardingaspect.h b/src/plugins/remotelinux/x11forwardingaspect.h
new file mode 100644
index 00000000000..5e61ec36c30
--- /dev/null
+++ b/src/plugins/remotelinux/x11forwardingaspect.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "remotelinux_export.h"
+
+#include <utils/aspects.h>
+
+namespace Utils { class MacroExpander; }
+
+namespace RemoteLinux {
+
+class REMOTELINUX_EXPORT X11ForwardingAspect : public Utils::StringAspect
+{
+ Q_OBJECT
+
+public:
+ X11ForwardingAspect(const Utils::MacroExpander *macroExpander);
+
+ struct Data : StringAspect::Data
+ {
+ QString display;
+ };
+
+ QString display() const;
+
+private:
+ const Utils::MacroExpander *m_macroExpander;
+};
+
+} // namespace RemoteLinux
diff --git a/src/plugins/resourceeditor/CMakeLists.txt b/src/plugins/resourceeditor/CMakeLists.txt
index e6d4003bf30..8efebaae292 100644
--- a/src/plugins/resourceeditor/CMakeLists.txt
+++ b/src/plugins/resourceeditor/CMakeLists.txt
@@ -1,6 +1,5 @@
add_qtc_plugin(ResourceEditor
DEPENDS Qt5::Xml
- DEFINES RESOURCE_LIBRARY
PLUGIN_DEPENDS Core ProjectExplorer
SOURCES
qrceditor/qrceditor.cpp qrceditor/qrceditor.h qrceditor/qrceditor.ui
diff --git a/src/plugins/resourceeditor/resource_global.h b/src/plugins/resourceeditor/resource_global.h
index 7fffa85432d..2fd743ef384 100644
--- a/src/plugins/resourceeditor/resource_global.h
+++ b/src/plugins/resourceeditor/resource_global.h
@@ -27,8 +27,10 @@
#include <qglobal.h>
-#if defined(RESOURCE_LIBRARY)
+#if defined(RESOURCEEDITOR_LIBRARY)
# define RESOURCE_EXPORT Q_DECL_EXPORT
+#elif defined(RESOURCEEDITOR_STATIC_LIBRARY)
+# define RESOURCE_EXPORT
#else
# define RESOURCE_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/resourceeditor/resourceeditor.qbs b/src/plugins/resourceeditor/resourceeditor.qbs
index 5cf943becf2..71a99ccb67b 100644
--- a/src/plugins/resourceeditor/resourceeditor.qbs
+++ b/src/plugins/resourceeditor/resourceeditor.qbs
@@ -11,7 +11,7 @@ Project {
Depends { name: "Core" }
- cpp.defines: base.concat(["RESOURCE_LIBRARY"])
+ cpp.defines: base.concat(["RESOURCEEDITOR_LIBRARY"])
Group {
name: "General"
diff --git a/src/plugins/resourceeditor/resourcenode.cpp b/src/plugins/resourceeditor/resourcenode.cpp
index 75f35da4d8a..bc9274fa895 100644
--- a/src/plugins/resourceeditor/resourcenode.cpp
+++ b/src/plugins/resourceeditor/resourcenode.cpp
@@ -34,7 +34,7 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/threadutils.h>
@@ -637,28 +637,4 @@ ResourceTopLevelNode *ResourceFolderNode::resourceNode() const
return m_topLevelNode;
}
-ResourceFileNode::ResourceFileNode(const FilePath &filePath, const QString &qrcPath, const QString &displayName)
- : FileNode(filePath, FileNode::fileTypeForFileName(filePath))
- , m_qrcPath(qrcPath)
- , m_displayName(displayName)
-{
-}
-
-QString ResourceFileNode::displayName() const
-{
- return m_displayName;
-}
-
-QString ResourceFileNode::qrcPath() const
-{
- return m_qrcPath;
-}
-
-bool ResourceFileNode::supportsAction(ProjectAction action, const Node *node) const
-{
- if (action == HidePathActions)
- return false;
- return parentFolderNode()->supportsAction(action, node);
-}
-
} // ResourceEditor
diff --git a/src/plugins/resourceeditor/resourcenode.h b/src/plugins/resourceeditor/resourcenode.h
index 03ae8039f0c..bb974cb2af5 100644
--- a/src/plugins/resourceeditor/resourcenode.h
+++ b/src/plugins/resourceeditor/resourcenode.h
@@ -91,18 +91,4 @@ private:
QString m_lang;
};
-class RESOURCE_EXPORT ResourceFileNode : public ProjectExplorer::FileNode
-{
-public:
- ResourceFileNode(const Utils::FilePath &filePath, const QString &qrcPath, const QString &displayName);
-
- QString displayName() const override;
- QString qrcPath() const;
- bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
-
-private:
- QString m_qrcPath;
- QString m_displayName;
-};
-
} // namespace ResourceEditor
diff --git a/src/plugins/scxmleditor/common/colorsettings.cpp b/src/plugins/scxmleditor/common/colorsettings.cpp
index 49bbb395efc..b375bbfe5e5 100644
--- a/src/plugins/scxmleditor/common/colorsettings.cpp
+++ b/src/plugins/scxmleditor/common/colorsettings.cpp
@@ -39,11 +39,6 @@ ColorSettings::ColorSettings(QWidget *parent)
m_ui.setupUi(this);
m_ui.m_colorThemeView->setEnabled(false);
- connect(m_ui.m_comboColorThemes, QOverload<int>::of(&QComboBox::currentIndexChanged),
- this, &ColorSettings::selectTheme);
- connect(m_ui.m_colorThemeView, &ColorThemeView::colorChanged, this, &ColorSettings::updateCurrentColors);
- connect(m_ui.m_addColorTheme, &QToolButton::clicked, this, &ColorSettings::createTheme);
- connect(m_ui.m_removeColorTheme, &QToolButton::clicked, this, &ColorSettings::removeTheme);
const QSettings *s = Core::ICore::settings();
@@ -53,6 +48,12 @@ ColorSettings::ColorSettings(QWidget *parent)
for (auto it = m_colorThemes.cbegin(); it != m_colorThemes.cend(); ++it)
m_ui.m_comboColorThemes->addItem(it.key());
m_ui.m_comboColorThemes->setCurrentText(s->value(Constants::C_SETTINGS_COLORSETTINGS_CURRENTCOLORTHEME).toString());
+
+ connect(m_ui.m_comboColorThemes, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &ColorSettings::selectTheme);
+ connect(m_ui.m_colorThemeView, &ColorThemeView::colorChanged, this, &ColorSettings::updateCurrentColors);
+ connect(m_ui.m_addColorTheme, &QToolButton::clicked, this, &ColorSettings::createTheme);
+ connect(m_ui.m_removeColorTheme, &QToolButton::clicked, this, &ColorSettings::removeTheme);
}
void ColorSettings::save()
diff --git a/src/plugins/scxmleditor/common/structure.cpp b/src/plugins/scxmleditor/common/structure.cpp
index 742a822c076..a1640112f33 100644
--- a/src/plugins/scxmleditor/common/structure.cpp
+++ b/src/plugins/scxmleditor/common/structure.cpp
@@ -154,7 +154,7 @@ void Structure::addCheckbox(const QString &name, TagType type)
void Structure::updateCheckBoxes()
{
QVector<TagType> visibleTags;
- foreach (QCheckBox *box, m_checkboxes) {
+ for (QCheckBox *box : qAsConst(m_checkboxes)) {
if (box->isChecked()) {
switch (TagType(box->property(Constants::C_SCXMLTAG_TAGTYPE).toInt())) {
case State:
diff --git a/src/plugins/scxmleditor/outputpane/warningmodel.cpp b/src/plugins/scxmleditor/outputpane/warningmodel.cpp
index d0166bfff98..49580b78ac6 100644
--- a/src/plugins/scxmleditor/outputpane/warningmodel.cpp
+++ b/src/plugins/scxmleditor/outputpane/warningmodel.cpp
@@ -58,7 +58,7 @@ void WarningModel::clear(bool sendSignal)
{
emit modelAboutToBeClear();
- foreach (Warning *w, m_warnings)
+ for (Warning *w : qAsConst(m_warnings))
w->disconnect(this);
beginResetModel();
diff --git a/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp b/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp
index 8a634a8c4ca..f3f6ea5e60c 100644
--- a/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "actionhandler.h"
+
#include "mytypes.h"
#include <utils/utilsicons.h>
diff --git a/src/plugins/scxmleditor/plugin_interface/connectableitem.cpp b/src/plugins/scxmleditor/plugin_interface/connectableitem.cpp
index f7f6718f9b0..5132f19038b 100644
--- a/src/plugins/scxmleditor/plugin_interface/connectableitem.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/connectableitem.cpp
@@ -64,19 +64,16 @@ ConnectableItem::~ConnectableItem()
{
setBlockUpdates(true);
- foreach (ConnectableItem *item, m_overlappedItems) {
+ for (ConnectableItem *item : qAsConst(m_overlappedItems))
item->removeOverlappingItem(this);
- }
m_overlappedItems.clear();
- foreach (TransitionItem *transition, m_outputTransitions) {
+ for (TransitionItem *transition : qAsConst(m_outputTransitions))
transition->disconnectItem(this);
- }
m_outputTransitions.clear();
- foreach (TransitionItem *transition, m_inputTransitions) {
+ for (TransitionItem *transition : qAsConst(m_inputTransitions))
transition->disconnectItem(this);
- }
m_inputTransitions.clear();
qDeleteAll(m_quickTransitions);
@@ -291,7 +288,7 @@ void ConnectableItem::removeInputTransition(TransitionItem *transition)
void ConnectableItem::updateInputTransitions()
{
- foreach (TransitionItem *transition, m_inputTransitions) {
+ for (TransitionItem *transition : qAsConst(m_inputTransitions)) {
transition->updateComponents();
transition->updateUIProperties();
}
@@ -300,7 +297,7 @@ void ConnectableItem::updateInputTransitions()
void ConnectableItem::updateOutputTransitions()
{
- foreach (TransitionItem *transition, m_outputTransitions) {
+ for (TransitionItem *transition : qAsConst(m_outputTransitions)) {
transition->updateComponents();
transition->updateUIProperties();
}
@@ -313,7 +310,7 @@ void ConnectableItem::updateTransitions(bool allChildren)
updateInputTransitions();
if (allChildren) {
- foreach (QGraphicsItem *it, childItems()) {
+ for (QGraphicsItem *it : childItems()) {
auto item = static_cast<ConnectableItem*>(it);
if (item && item->type() >= InitialStateType)
item->updateTransitions(allChildren);
@@ -323,14 +320,15 @@ void ConnectableItem::updateTransitions(bool allChildren)
void ConnectableItem::updateTransitionAttributes(bool allChildren)
{
- foreach (TransitionItem *transition, m_outputTransitions)
+ for (TransitionItem *transition : qAsConst(m_outputTransitions))
transition->updateTarget();
- foreach (TransitionItem *transition, m_inputTransitions)
+ for (TransitionItem *transition : qAsConst(m_inputTransitions))
transition->updateTarget();
if (allChildren) {
- foreach (QGraphicsItem *it, childItems()) {
+ const QList<QGraphicsItem *> items = childItems();
+ for (QGraphicsItem *it : items) {
auto item = static_cast<ConnectableItem*>(it);
if (item && item->type() >= InitialStateType)
item->updateTransitionAttributes(allChildren);
@@ -352,7 +350,7 @@ QPointF ConnectableItem::getInternalPosition(const TransitionItem *transition, T
int ind = 0;
if (type == TransitionItem::InternalNoTarget) {
- foreach (TransitionItem *item, m_outputTransitions) {
+ for (TransitionItem *item : qAsConst(m_outputTransitions)) {
if (item->targetType() == TransitionItem::InternalSameTarget)
ind++;
}
@@ -396,7 +394,8 @@ void ConnectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
//Restore old behavior if ctrl & alt modifiers are present
if (!m_releasedFromParent && !(event->modifiers() & Qt::AltModifier) && !(event->modifiers() & Qt::ControlModifier)) {
releaseFromParent();
- foreach (QGraphicsItem *it, scene()->selectedItems()) {
+ const QList<QGraphicsItem *> items = scene()->selectedItems();
+ for (QGraphicsItem *it : items) {
if (it->type() >= InitialStateType && it != this) {
qgraphicsitem_cast<ConnectableItem*>(it)->releaseFromParent();
}
@@ -431,7 +430,8 @@ void ConnectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
}
connectToParent(parentItem);
- foreach (QGraphicsItem *it, scene()->selectedItems()) {
+ const QList<QGraphicsItem *> items = scene()->selectedItems();
+ for (QGraphicsItem *it : items) {
if (it->type() >= InitialStateType && it != this)
qgraphicsitem_cast<ConnectableItem*>(it)->connectToParent(parentItem);
}
@@ -582,7 +582,7 @@ void ConnectableItem::updateAttributes()
{
BaseItem::updateAttributes();
- foreach (TransitionItem *transition, m_inputTransitions) {
+ for (TransitionItem *transition : qAsConst(m_inputTransitions)) {
if (transition->isEndItem(this))
transition->setTagValue("target", itemId());
}
@@ -698,13 +698,13 @@ void ConnectableItem::finalizeCreation()
bool ConnectableItem::hasInputTransitions(const ConnectableItem *parentItem, bool checkChildren) const
{
- foreach (const TransitionItem *it, m_inputTransitions) {
+ for (const TransitionItem *it : qAsConst(m_inputTransitions))
if (!SceneUtils::isChild(parentItem, it->connectedItem(this)))
return true;
- }
if (checkChildren) {
- foreach (QGraphicsItem *it, childItems()) {
+ const QList<QGraphicsItem *> items = childItems();
+ for (QGraphicsItem *it : items) {
if (it->type() >= InitialStateType) {
auto item = qgraphicsitem_cast<ConnectableItem*>(it);
if (item && item->hasInputTransitions(parentItem, checkChildren))
@@ -718,13 +718,13 @@ bool ConnectableItem::hasInputTransitions(const ConnectableItem *parentItem, boo
bool ConnectableItem::hasOutputTransitions(const ConnectableItem *parentItem, bool checkChildren) const
{
- foreach (TransitionItem *it, m_outputTransitions) {
+ for (TransitionItem *it : qAsConst(m_outputTransitions))
if (!SceneUtils::isChild(parentItem, it->connectedItem(this)))
return true;
- }
if (checkChildren) {
- foreach (QGraphicsItem *it, childItems()) {
+ const QList<QGraphicsItem *> items = childItems();
+ for (QGraphicsItem *it : items) {
if (it->type() >= InitialStateType) {
auto item = qgraphicsitem_cast<ConnectableItem*>(it);
if (item && item->hasOutputTransitions(parentItem, checkChildren))
@@ -755,7 +755,8 @@ void ConnectableItem::removeOverlappingItem(ConnectableItem *item)
void ConnectableItem::checkOverlapping()
{
QVector<ConnectableItem*> overlappedItems;
- foreach (QGraphicsItem *it, collidingItems()) {
+ const QList<QGraphicsItem *> items = collidingItems();
+ for (QGraphicsItem *it : items) {
if (it->type() >= InitialStateType && it->parentItem() == parentItem()) {
overlappedItems << qgraphicsitem_cast<ConnectableItem*>(it);
}
@@ -770,7 +771,7 @@ void ConnectableItem::checkOverlapping()
}
// Add new overlapped items
- foreach (ConnectableItem *it, overlappedItems) {
+ for (ConnectableItem *it : qAsConst(overlappedItems)) {
if (!m_overlappedItems.contains(it)) {
m_overlappedItems << it;
it->addOverlappingItem(this);
diff --git a/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp b/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp
index 52ce0fc9a13..c86f22e152b 100644
--- a/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp
@@ -67,7 +67,7 @@ GraphicsScene::~GraphicsScene()
void GraphicsScene::unselectAll()
{
const QList<QGraphicsItem*> selectedItems = this->selectedItems();
- foreach (QGraphicsItem *it, selectedItems)
+ for (QGraphicsItem *it : selectedItems)
it->setSelected(false);
if (m_document)
m_document->setCurrentTag(nullptr);
@@ -75,20 +75,20 @@ void GraphicsScene::unselectAll()
void GraphicsScene::unhighlightAll()
{
- foreach (BaseItem *it, m_baseItems)
+ for (BaseItem *it : qAsConst(m_baseItems))
it->setHighlight(false);
}
void GraphicsScene::highlightItems(const QVector<ScxmlTag*> &lstIds)
{
- foreach (BaseItem *it, m_baseItems)
+ for (BaseItem *it : qAsConst(m_baseItems))
it->setHighlight(lstIds.contains(it->tag()));
}
QRectF GraphicsScene::selectedBoundingRect() const
{
QRectF r;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected())
r = r.united(item->sceneBoundingRect());
}
@@ -98,7 +98,7 @@ QRectF GraphicsScene::selectedBoundingRect() const
qreal GraphicsScene::selectedMaxWidth() const
{
qreal maxw = 0;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType)
maxw = qMax(maxw, item->sceneBoundingRect().width());
}
@@ -108,7 +108,7 @@ qreal GraphicsScene::selectedMaxWidth() const
qreal GraphicsScene::selectedMaxHeight() const
{
qreal maxh = 0;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType)
maxh = qMax(maxh, item->sceneBoundingRect().height());
}
@@ -124,37 +124,37 @@ void GraphicsScene::alignStates(int alignType)
if (r.isValid()) {
switch (alignType) {
case ActionAlignLeft:
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType)
item->moveStateBy(r.left() - item->sceneBoundingRect().left(), 0);
}
break;
case ActionAlignRight:
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType)
item->moveStateBy(r.right() - item->sceneBoundingRect().right(), 0);
}
break;
case ActionAlignTop:
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType)
item->moveStateBy(0, r.top() - item->sceneBoundingRect().top());
}
break;
case ActionAlignBottom:
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType)
item->moveStateBy(0, r.bottom() - item->sceneBoundingRect().bottom());
}
break;
case ActionAlignHorizontal:
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType)
item->moveStateBy(0, r.center().y() - item->sceneBoundingRect().center().y());
}
break;
case ActionAlignVertical:
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType)
item->moveStateBy(r.center().x() - item->sceneBoundingRect().center().x(), 0);
}
@@ -175,7 +175,7 @@ void GraphicsScene::adjustStates(int adjustType)
qreal maxw = selectedMaxWidth();
qreal maxh = selectedMaxHeight();
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= InitialStateType) {
QRectF rr = item->boundingRect();
if ((adjustType == ActionAdjustWidth || adjustType == ActionAdjustSize) && !qFuzzyCompare(rr.width(), maxw))
@@ -223,7 +223,7 @@ void GraphicsScene::copy()
QVector<ScxmlTag*> tags;
if (m_document->currentTag()->tagType() == Scxml) {
QVector<BaseItem*> items;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (!item->parentItem())
items << item;
}
@@ -241,9 +241,9 @@ void GraphicsScene::copy()
mime->setText(QLatin1String(result));
mime->setData("StateChartEditor/StateData", result);
QStringList strTypes;
- foreach (const ScxmlTag *tag, tags) {
+ for (const ScxmlTag *tag : qAsConst(tags))
strTypes << tag->tagName(false);
- }
+
mime->setData("StateChartEditor/CopiedTagTypes", strTypes.join(",").toLocal8Bit());
mime->setData("StateChartEditor/CopiedMinPos", QString::fromLatin1("%1:%2").arg(minPos.x()).arg(minPos.y()).toLocal8Bit());
QGuiApplication::clipboard()->setMimeData(mime);
@@ -267,7 +267,7 @@ void GraphicsScene::paste(const QPointF &targetPos)
QPointF startPos(targetPos);
BaseItem *targetItem = nullptr;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= StateType) {
targetItem = item;
break;
@@ -296,7 +296,7 @@ void GraphicsScene::paste(const QPointF &targetPos)
void GraphicsScene::setEditorInfo(const QString &key, const QString &value)
{
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected() && item->type() >= TransitionType)
item->setEditorInfo(key, value);
}
@@ -371,7 +371,7 @@ void GraphicsScene::runLayoutToSelectedStates()
m_document->undoStack()->beginMacro(tr("Re-layout"));
QVector<BaseItem*> selectedItems;
- foreach (BaseItem *node, m_baseItems) {
+ for (BaseItem *node : qAsConst(m_baseItems)) {
if (node->isSelected()) {
int index = 0;
for (int i = 0; i < selectedItems.count(); ++i) {
@@ -391,22 +391,20 @@ void GraphicsScene::runLayoutToSelectedStates()
// Layout scene items if necessary
if (selectedItems.isEmpty()) {
QList<QGraphicsItem*> sceneItems;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->type() >= InitialStateType && !item->parentItem())
sceneItems << item;
}
SceneUtils::layout(sceneItems);
- foreach (QGraphicsItem *item, sceneItems) {
+ for (QGraphicsItem *item : qAsConst(sceneItems))
if (item->type() >= StateType)
static_cast<StateItem*>(item)->shrink();
- }
}
// Update properties
- foreach (BaseItem *node, selectedItems) {
+ for (BaseItem *node : qAsConst(selectedItems))
node->updateUIProperties();
- }
m_document->undoStack()->endMacro();
}
@@ -417,31 +415,31 @@ void GraphicsScene::runAutomaticLayout()
// 1. Find max depth
int maxDepth = 0;
- foreach (BaseItem *node, m_baseItems) {
+ for (BaseItem *node : qAsConst(m_baseItems)) {
maxDepth = qMax(maxDepth, node->depth());
node->setBlockUpdates(true);
}
// 2. Layout every depth-level separately
for (int d = (maxDepth + 1); d--;) {
- foreach (BaseItem *node, m_baseItems)
+ for (BaseItem *node : qAsConst(m_baseItems))
node->doLayout(d);
}
// 3. Layout scene items
QList<QGraphicsItem*> sceneItems;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->type() >= InitialStateType && !item->parentItem())
sceneItems << item;
}
SceneUtils::layout(sceneItems);
- foreach (QGraphicsItem *item, sceneItems) {
+ for (QGraphicsItem *item : qAsConst(sceneItems)) {
if (item->type() >= StateType)
static_cast<StateItem*>(item)->shrink();
}
- foreach (BaseItem *node, m_baseItems) {
+ for (BaseItem *node : qAsConst(m_baseItems)) {
node->updateUIProperties();
node->setBlockUpdates(false);
}
@@ -468,21 +466,21 @@ void GraphicsScene::endTagChange(ScxmlDocument::TagChange change, ScxmlTag *tag,
switch (change) {
case ScxmlDocument::TagAttributesChanged: {
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->tag() == tag)
item->updateAttributes();
}
break;
}
case ScxmlDocument::TagEditorInfoChanged: {
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->tag() == tag)
item->updateEditorInfo();
}
break;
}
case ScxmlDocument::TagCurrentChanged: {
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (!item->isSelected() && item->tag() == tag)
item->setSelected(true);
}
@@ -725,7 +723,7 @@ BaseItem *GraphicsScene::findItem(const ScxmlTag *tag) const
if (!tag)
return nullptr;
- foreach (BaseItem *it, m_baseItems) {
+ for (BaseItem *it : qAsConst(m_baseItems)) {
if (it->tag() == tag)
return it;
}
@@ -738,7 +736,7 @@ void GraphicsScene::removeItems(const ScxmlTag *tag)
if (tag) {
// Find right items
QVector<BaseItem*> items;
- foreach (BaseItem *it, m_baseItems) {
+ for (BaseItem *it : qAsConst(m_baseItems)) {
if (it->tag() == tag)
items << it;
}
@@ -764,7 +762,7 @@ QPair<bool, bool> GraphicsScene::checkSnapToItem(BaseItem *item, const QPointF &
qreal diffY = 8;
qreal diffYdX = 2000;
- foreach (BaseItem *it, m_baseItems) {
+ for (BaseItem *it : qAsConst(m_baseItems)) {
if (!it->isSelected() && it != item && it->parentItem() == parentItem && it->type() >= InitialStateType) {
QPointF c = it->sceneCenter();
qreal dX = qAbs(c.x() - p.x());
@@ -802,7 +800,7 @@ void GraphicsScene::selectionChanged(bool para)
int baseCount = 0;
int stateTypeCount = 0;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->isSelected()) {
if (item->type() >= TransitionType)
baseCount++;
@@ -848,22 +846,20 @@ void GraphicsScene::removeWarningItem(WarningItem *item)
void GraphicsScene::warningVisibilityChanged(int type, WarningItem *item)
{
if (!m_autoLayoutRunning && !m_initializing) {
- foreach (WarningItem *it, m_allWarnings) {
+ for (WarningItem *it : qAsConst(m_allWarnings))
if (it != item && (type == 0 || it->type() == type))
it->check();
- }
}
}
ScxmlTag *GraphicsScene::tagByWarning(const ScxmlEditor::OutputPane::Warning *w) const
{
ScxmlTag *tag = nullptr;
- foreach (WarningItem *it, m_allWarnings) {
+ for (WarningItem *it : qAsConst(m_allWarnings))
if (it->warning() == w) {
tag = it->tag();
break;
}
- }
return tag;
}
@@ -921,7 +917,7 @@ void GraphicsScene::removeChild(BaseItem *item)
void GraphicsScene::checkItemsVisibility(double scaleFactor)
{
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
item->checkVisibility(scaleFactor);
}
}
@@ -930,7 +926,7 @@ void GraphicsScene::checkInitialState()
{
if (m_document) {
QList<QGraphicsItem*> sceneItems;
- foreach (BaseItem *item, m_baseItems) {
+ for (BaseItem *item : qAsConst(m_baseItems)) {
if (item->type() >= InitialStateType && !item->parentItem())
sceneItems << item;
}
@@ -944,14 +940,14 @@ void GraphicsScene::checkInitialState()
void GraphicsScene::clearAllTags()
{
- foreach (BaseItem *it, m_baseItems) {
+ for (BaseItem *it : qAsConst(m_baseItems)) {
it->setTag(nullptr);
}
}
void GraphicsScene::setBlockUpdates(bool block)
{
- foreach (BaseItem *it, m_baseItems) {
+ for (BaseItem *it : qAsConst(m_baseItems)) {
it->setBlockUpdates(block);
}
}
diff --git a/src/plugins/scxmleditor/plugin_interface/parallelitem.cpp b/src/plugins/scxmleditor/plugin_interface/parallelitem.cpp
index d3ed8c127db..b3d3d85b066 100644
--- a/src/plugins/scxmleditor/plugin_interface/parallelitem.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/parallelitem.cpp
@@ -63,7 +63,8 @@ void ParallelItem::doLayout(int d)
// 1. Find children items
QVector<StateItem*> children;
- foreach (QGraphicsItem *it, childItems()) {
+ const QList<QGraphicsItem *> items = childItems();
+ for (QGraphicsItem *it : items) {
if (it->type() >= StateType) {
auto itt = qgraphicsitem_cast<StateItem*>(it);
if (itt)
@@ -72,17 +73,16 @@ void ParallelItem::doLayout(int d)
}
// 2. Adjust sizes
- foreach (StateItem *itt, children) {
+ for (StateItem *itt : qAsConst(children))
itt->shrink();
- }
qreal maxw = 0;
- foreach (StateItem *itt, children) {
+ for (StateItem *itt : qAsConst(children)) {
QRectF rr = itt->boundingRect();
maxw = qMax(rr.width(), maxw);
}
- foreach (StateItem *itt, children) {
+ for (StateItem *itt : qAsConst(children)) {
QRectF rr = itt->boundingRect();
if (!qFuzzyCompare(rr.width(), maxw))
rr.setWidth(maxw);
diff --git a/src/plugins/scxmleditor/plugin_interface/scattributeitemdelegate.cpp b/src/plugins/scxmleditor/plugin_interface/scattributeitemdelegate.cpp
index 58edac0896b..bd90d3f8463 100644
--- a/src/plugins/scxmleditor/plugin_interface/scattributeitemdelegate.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/scattributeitemdelegate.cpp
@@ -78,9 +78,9 @@ void SCAttributeItemDelegate::setEditorData(QWidget *editor, const QModelIndex &
auto combo = qobject_cast<QComboBox*>(editor);
if (combo) {
combo->clear();
- QStringList values = index.data(DataRole).toString().split(";");
+ const QStringList values = index.data(DataRole).toString().split(";");
- foreach (QString val, values)
+ for (QString val : values)
combo->addItem(val);
combo->setCurrentText(index.data().toString());
diff --git a/src/plugins/scxmleditor/plugin_interface/sceneutils.cpp b/src/plugins/scxmleditor/plugin_interface/sceneutils.cpp
index 97fd56c7f6e..450409209f2 100644
--- a/src/plugins/scxmleditor/plugin_interface/sceneutils.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/sceneutils.cpp
@@ -149,7 +149,7 @@ QVector<ScxmlTag*> findCopyTags(const QVector<BaseItem*> &items, QPointF &minPos
{
QPointF pp(0, 0);
QVector<ScxmlTag*> tags;
- foreach (BaseItem *it, items) {
+ for (BaseItem *it : items) {
if (it->type() >= InitialStateType && it->isSelected()) {
BaseItem *parent = it->parentBaseItem();
BaseItem *lastSelectedParent = it;
@@ -181,7 +181,7 @@ QVector<ScxmlTag*> findRemovedTags(const QVector<BaseItem*> &items)
{
// Find right tags
QVector<ScxmlTag*> tags;
- foreach (BaseItem *it, items) {
+ for (BaseItem *it : items) {
if (it->isSelected()) {
// Find the last selected parent
BaseItem *parent = it->parentBaseItem();
@@ -207,7 +207,7 @@ void layout(const QList<QGraphicsItem*> &items)
QList<ConnectableItem*> childItems;
ConnectableItem *initialItem = nullptr;
ConnectableItem *finalItem = nullptr;
- foreach (QGraphicsItem *item, items) {
+ for (QGraphicsItem *item : items) {
auto connectableItem = qgraphicsitem_cast<ConnectableItem*>(item);
if (connectableItem) {
if (connectableItem->type() == InitialStateType)
@@ -317,12 +317,16 @@ void layout(const QList<QGraphicsItem*> &items)
}
// Finally set initial and final positions
- foreach (ConnectableItem *item, childItems) {
+ for (ConnectableItem *item : qAsConst(childItems)) {
if (item == firstItem)
- initialItem->setPos(firstItem->pos() + firstItem->boundingRect().topLeft() - QPointF(50, 50));
+ initialItem->setPos(firstItem->pos() + firstItem->boundingRect().topLeft()
+ - QPointF(50, 50));
else if (item == lastItem) {
int angle = startAngle + childItems.indexOf(item) * angleDiff;
- QLineF line = QLineF::fromPolar(qMax(lastItem->boundingRect().width() / 2, lastItem->boundingRect().height() / 2) + 20, angle);
+ QLineF line = QLineF::fromPolar(qMax(lastItem->boundingRect().width() / 2,
+ lastItem->boundingRect().height() / 2)
+ + 20,
+ angle);
finalItem->setPos(lastItem->pos() + lastItem->boundingRect().center() + line.p2());
}
}
diff --git a/src/plugins/scxmleditor/plugin_interface/sceneutils.h b/src/plugins/scxmleditor/plugin_interface/sceneutils.h
index 2b13f46a347..34d8262c227 100644
--- a/src/plugins/scxmleditor/plugin_interface/sceneutils.h
+++ b/src/plugins/scxmleditor/plugin_interface/sceneutils.h
@@ -70,17 +70,15 @@ bool hasSiblingStates(T *item)
if (parentItem) {
children = parentItem->childItems();
} else if (item->scene()) {
- foreach (QGraphicsItem *it, item->scene()->items()) {
+ const QList<QGraphicsItem *> items = item->scene()->items();
+ for (QGraphicsItem *it : items)
if (!it->parentItem())
children << it;
- }
}
- foreach (QGraphicsItem *it, children) {
- if (it != item && it->type() == item->type()) {
+ for (QGraphicsItem *it : qAsConst(children))
+ if (it != item && it->type() == item->type())
return true;
- }
- }
}
return false;
diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp
index d32bbdc22b7..fa9c0a20c29 100644
--- a/src/plugins/silversearcher/findinfilessilversearcher.cpp
+++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp
@@ -90,7 +90,7 @@ bool isSilverSearcherAvailable()
silverSearcherProcess.setCommand({"ag", {"--version"}});
silverSearcherProcess.start();
if (silverSearcherProcess.waitForFinished(1000)) {
- if (silverSearcherProcess.stdOut().contains("ag version"))
+ if (silverSearcherProcess.cleanedStdOut().contains("ag version"))
return true;
}
@@ -145,7 +145,7 @@ void runSilverSeacher(FutureInterfaceType &fi, FileFindParameters parameters)
regexp.setPattern(parameters.text);
regexp.setPatternOptions(patternOptions);
}
- SilverSearcher::SilverSearcherOutputParser parser(process.stdOut(), regexp);
+ SilverSearcher::SilverSearcherOutputParser parser(process.cleanedStdOut(), regexp);
FileSearchResultList items = parser.parse();
if (!items.isEmpty())
fi.reportResult(items);
diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp
index c759f684bc1..9131009f563 100644
--- a/src/plugins/studiowelcome/examplecheckout.cpp
+++ b/src/plugins/studiowelcome/examplecheckout.cpp
@@ -123,7 +123,7 @@ void FileDownloader::start()
if (reply->error()) {
if (m_tempFile.exists())
m_tempFile.remove();
- qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
+ qWarning() << Q_FUNC_INFO << m_url << reply->errorString();
emit downloadFailed();
} else {
m_tempFile.flush();
@@ -382,9 +382,8 @@ void FileExtractor::extract()
// Create a new directory to generate a proper creation date
targetDir.mkdir(targetFolder);
- Utils::Archive *archive = Utils::Archive::unarchive(m_sourceFile, m_targetPath);
- archive->setParent(this);
- QTC_ASSERT(archive, return );
+ Utils::Archive *archive = new Utils::Archive(m_sourceFile, m_targetPath);
+ QTC_ASSERT(archive->isValid(), delete archive; return);
m_timer.start();
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
@@ -424,7 +423,8 @@ void FileExtractor::extract()
emit detailedTextChanged();
});
- QObject::connect(archive, &Utils::Archive::finished, this, [this](bool ret) {
+ QObject::connect(archive, &Utils::Archive::finished, this, [this, archive](bool ret) {
+ delete archive;
m_finished = ret;
m_timer.stop();
@@ -433,8 +433,9 @@ void FileExtractor::extract()
emit targetFolderExistsChanged();
emit finishedChanged();
- QTC_ASSERT(ret, ;);
+ QTC_CHECK(ret);
});
+ archive->unarchive();
}
static Utils::FilePath tempFilePath()
@@ -455,21 +456,28 @@ DataModelDownloader::DataModelDownloader(QObject * /* parent */)
&FileDownloader::progressChanged,
this,
&DataModelDownloader::progressChanged);
+
+ connect(&m_fileDownloader,
+ &FileDownloader::downloadFailed,
+ this,
+ &DataModelDownloader::downloadFailed);
}
-void DataModelDownloader::start()
+bool DataModelDownloader::start()
{
if (!enableDownload()) {
m_available = false;
emit availableChanged();
- return;
+ return false;
}
m_fileDownloader.setUrl(QUrl::fromUserInput(
"https://download.qt.io/learning/examples/qtdesignstudio/dataImports.zip"));
- connect(&m_fileDownloader, &FileDownloader::availableChanged, this, [this]() {
+ bool started = false;
+
+ connect(&m_fileDownloader, &FileDownloader::availableChanged, this, [this, &started]() {
m_available = m_fileDownloader.available();
@@ -483,23 +491,26 @@ void DataModelDownloader::start()
if (!m_forceDownload && (m_fileDownloader.lastModified() <= m_birthTime))
return;
+ started = true;
+
m_fileDownloader.start();
connect(&m_fileDownloader, &FileDownloader::finishedChanged, this, [this]() {
if (m_fileDownloader.finished()) {
- Utils::Archive *archive = Utils::Archive::unarchive(Utils::FilePath::fromString(
- m_fileDownloader.tempFile()),
- tempFilePath());
-
- archive->setParent(this);
- QTC_ASSERT(archive, return );
-
- QObject::connect(archive, &Utils::Archive::finished, this, [this](bool ret) {
+ const Utils::FilePath archiveFile = Utils::FilePath::fromString(
+ m_fileDownloader.tempFile());
+ QTC_ASSERT(Utils::Archive::supportsFile(archiveFile), return );
+ auto archive = new Utils::Archive(archiveFile, tempFilePath());
+ QTC_ASSERT(archive->isValid(), delete archive; return );
+ QObject::connect(archive, &Utils::Archive::finished, this, [this, archive](bool ret) {
+ QTC_CHECK(ret);
+ delete archive;
emit finished();
- QTC_ASSERT(ret, ;);
});
+ archive->unarchive();
}
});
});
+ return started;
}
bool DataModelDownloader::exists() const
diff --git a/src/plugins/studiowelcome/examplecheckout.h b/src/plugins/studiowelcome/examplecheckout.h
index fae0fea3368..42b8b9a41b9 100644
--- a/src/plugins/studiowelcome/examplecheckout.h
+++ b/src/plugins/studiowelcome/examplecheckout.h
@@ -163,7 +163,7 @@ class DataModelDownloader : public QObject
public:
explicit DataModelDownloader(QObject *parent = nullptr);
- void start();
+ bool start();
bool exists() const;
bool available() const;
Utils::FilePath targetFolder() const;
@@ -174,6 +174,7 @@ signals:
void finished();
void availableChanged();
void progressChanged();
+ void downloadFailed();
private:
FileDownloader m_fileDownloader;
diff --git a/src/plugins/studiowelcome/presetmodel.cpp b/src/plugins/studiowelcome/presetmodel.cpp
index 6705b6ca650..136a56dd014 100644
--- a/src/plugins/studiowelcome/presetmodel.cpp
+++ b/src/plugins/studiowelcome/presetmodel.cpp
@@ -34,8 +34,8 @@ constexpr int NameRole = Qt::UserRole;
constexpr int ScreenSizeRole = Qt::UserRole + 1;
constexpr int IsUserPresetRole = Qt::UserRole + 2;
-static const QString RecentsTabName = QObject::tr("Recents");
-static const QString CustomTabName = QObject::tr("Custom");
+static const QString RecentsTabName = ::StudioWelcome::PresetModel::tr("Recents");
+static const QString CustomTabName = ::StudioWelcome::PresetModel::tr("Custom");
/****************** PresetData ******************/
diff --git a/src/plugins/studiowelcome/studiowelcome.qbs b/src/plugins/studiowelcome/studiowelcome.qbs
index 4c82c8112ec..7d254824ba5 100644
--- a/src/plugins/studiowelcome/studiowelcome.qbs
+++ b/src/plugins/studiowelcome/studiowelcome.qbs
@@ -2,6 +2,7 @@ import qbs.FileInfo
QtcPlugin {
name: "StudioWelcome"
+ condition: QmlDesigner.present
Depends { name: "Qt"; submodules: ["qml", "qml-private", "quick", "quickwidgets"] }
Depends { name: "Utils" }
@@ -9,7 +10,7 @@ QtcPlugin {
Depends { name: "Core" }
Depends { name: "ProjectExplorer" }
Depends { name: "QtSupport" }
- Depends { name: "QmlDesigner" }
+ Depends { name: "QmlDesigner"; required: false }
Depends { name: "QmlProjectManager" }
Depends { name: "app_version_header" }
diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
index 7a4e09e92a3..f78bc1ca626 100644
--- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp
+++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
@@ -44,6 +44,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
+#include <qmlprojectmanager/projectfilecontenttools.h>
#include <qmlprojectmanager/qmlproject.h>
#include <qmldesigner/components/componentcore/theme.h>
@@ -54,7 +55,6 @@
#include <utils/hostosinfo.h>
#include <utils/icon.h>
#include <utils/infobar.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/stringutils.h>
#include <utils/theme/theme.h>
@@ -330,43 +330,10 @@ int ProjectModel::rowCount(const QModelIndex &) const
QString getQDSVersion(const QString &projectFilePath)
{
- const QString defaultReturn = "";
- Utils::FileReader reader;
- if (!reader.fetch(Utils::FilePath::fromString(projectFilePath)))
- return defaultReturn;
-
- const QByteArray data = reader.data();
-
- QRegularExpression regexp(R"x(qdsVersion: "(.*)")x");
- QRegularExpressionMatch match = regexp.match(QString::fromUtf8(data));
-
- if (!match.hasMatch())
- return defaultReturn;
-
- return ProjectModel::tr("Created with Qt Design Studio version: %1").arg(match.captured(1));
-}
-
-QString getMainQmlFile(const QString &projectFilePath)
-{
- const QString defaultReturn = "content/App.qml";
- Utils::FileReader reader;
- if (!reader.fetch(Utils::FilePath::fromString(projectFilePath)))
- return defaultReturn;
-
- const QByteArray data = reader.data();
-
- QRegularExpression regexp(R"x(mainFile: "(.*)")x");
- QRegularExpressionMatch match = regexp.match(QString::fromUtf8(data));
-
- if (!match.hasMatch())
- return defaultReturn;
-
- return match.captured(1);
-}
+ const QString qdsVersion = QmlProjectManager::ProjectFileContentTools::qdsVersion(
+ Utils::FilePath::fromString(projectFilePath));
-QString appQmlFile(const QString &projectFilePath)
-{
- return QFileInfo(projectFilePath).dir().absolutePath() + "/" + getMainQmlFile(projectFilePath);
+ return ProjectModel::tr("Created with Qt Design Studio version: %1").arg(qdsVersion);
}
static QString fromCamelCase(const QString &s) {
@@ -382,32 +349,12 @@ static QString fromCamelCase(const QString &s) {
static QString resolutionFromConstants(const QString &projectFilePath)
{
- const QFileInfo fileInfo(projectFilePath);
- const QString fileName = fileInfo.dir().absolutePath()
- + "/" + "imports" + "/" + fileInfo.baseName() + "/Constants.qml";
-
- Utils::FileReader reader;
- if (!reader.fetch(Utils::FilePath::fromString(fileName)))
- return {};
-
- const QByteArray data = reader.data();
-
- const QRegularExpression regexpWidth(R"x(readonly\s+property\s+int\s+width:\s+(\d*))x");
- const QRegularExpression regexpHeight(R"x(readonly\s+property\s+int\s+height:\s+(\d*))x");
-
- int width = -1;
- int height = -1;
-
- QRegularExpressionMatch match = regexpHeight.match(QString::fromUtf8(data));
- if (match.hasMatch())
- height = match.captured(1).toInt();
-
- match = regexpWidth.match(QString::fromUtf8(data));
- if (match.hasMatch())
- width = match.captured(1).toInt();
+ QmlProjectManager::ProjectFileContentTools::Resolution res =
+ QmlProjectManager::ProjectFileContentTools::resolutionFromConstants(
+ Utils::FilePath::fromString(projectFilePath));
- if (width > 0 && height > 0)
- return ProjectModel::tr("Resolution: %1x%2").arg(width).arg(height);
+ if (res.width > 0 && res.height > 0)
+ return ProjectModel::tr("Resolution: %1x%2").arg(res.width).arg(res.height);
return {};
}
@@ -449,8 +396,8 @@ static QString tags(const QString &projectFilePath)
QVariant ProjectModel::data(const QModelIndex &index, int role) const
{
- QPair<QString, QString> data = ProjectExplorer::ProjectExplorerPlugin::recentProjects().at(
- index.row());
+ const ProjectExplorer::RecentProjectsEntry data =
+ ProjectExplorer::ProjectExplorerPlugin::recentProjects().at(index.row());
switch (role) {
case Qt::DisplayRole:
return data.second;
@@ -460,7 +407,9 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
case PrettyFilePathRole:
return Utils::withTildeHomePath(QFileInfo(data.first).dir().absolutePath());
case PreviewUrl:
- return QVariant(QStringLiteral("image://project_preview/") + appQmlFile(data.first));
+ return QVariant(QStringLiteral("image://project_preview/") +
+ QmlProjectManager::ProjectFileContentTools::appQmlFile(
+ Utils::FilePath::fromString(data.first)));
case TagData:
return tags(data.first);
case Description:
@@ -501,7 +450,11 @@ public:
~WelcomeMode() override;
private:
- QQuickWidget *m_modeWidget = nullptr;
+ void setupQuickWidget(const QString &welcomePagePath);
+ void createQuickWidget();
+
+ QQuickWidget *m_quickWidget = nullptr;
+ QWidget *m_modeWidget = nullptr;
DataModelDownloader *m_dataModelDownloader = nullptr;
};
@@ -588,7 +541,7 @@ void StudioWelcomePlugin::extensionsInitialized()
const QString filters = QString("Project (*.qmlproject);;UI file (*.ui.qml);;QML file "
"(*.qml);;JavaScript file (*.js);;%1")
- .arg(Utils::allFilesFilterString());
+ .arg(Core::DocumentManager::allFilesFilterString());
Core::DocumentManager::setFileDialogFilter(filters);
}
@@ -685,66 +638,46 @@ WelcomeMode::WelcomeMode()
QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf");
ExampleCheckout::registerTypes();
- m_modeWidget = new QQuickWidget;
- m_modeWidget->setMinimumSize(640, 480);
- m_modeWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
- QmlDesigner::Theme::setupTheme(m_modeWidget->engine());
- m_modeWidget->engine()->addImportPath("qrc:/studiofonts");
-
- QmlDesigner::QmlDesignerPlugin::registerPreviewImageProvider(m_modeWidget->engine());
-
- m_modeWidget->engine()->setOutputWarningsToStandardError(false);
+ createQuickWidget();
if (forceDownLoad() || !readme.exists()) // Only downloads contain the readme
m_dataModelDownloader->setForceDownload(true);
connect(m_dataModelDownloader, &DataModelDownloader::progressChanged, this, [this](){
- m_modeWidget->rootObject()->setProperty("loadingProgress", m_dataModelDownloader->progress());
+ m_quickWidget->rootObject()->setProperty("loadingProgress", m_dataModelDownloader->progress());
});
- connect(m_dataModelDownloader, &DataModelDownloader::finished, this, [this](){
- auto source = m_modeWidget->source();
- m_modeWidget->engine()->clearComponentCache();
- m_modeWidget->setSource(source);
- m_modeWidget->rootObject()->setProperty("loadingProgress", 100);
+ m_quickWidget->setEnabled(false);
+
+ connect(m_dataModelDownloader, &DataModelDownloader::finished, this, [this, welcomePagePath]() {
+ delete m_quickWidget;
+ createQuickWidget();
+ setupQuickWidget(welcomePagePath);
+ m_modeWidget->layout()->addWidget(m_quickWidget);
});
- m_dataModelDownloader->start();
+ connect(m_dataModelDownloader, &DataModelDownloader::downloadFailed, this, [this]() {
+ m_quickWidget->setEnabled(true);
+ });
+
+ if (m_dataModelDownloader->start())
+ m_quickWidget->setEnabled(false);
+
+/*
connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, this, [this](Utils::Id mode){
bool active = (mode == Core::Constants::MODE_WELCOME);
m_modeWidget->rootObject()->setProperty("active", active);
});
+*/
+ setupQuickWidget(welcomePagePath);
- if (!useNewWelcomePage()) {
-
-#ifdef QT_DEBUG
- m_modeWidget->engine()->addImportPath(QLatin1String(STUDIO_QML_PATH)
- + "welcomepage/imports");
- m_modeWidget->setSource(QUrl::fromLocalFile(QLatin1String(STUDIO_QML_PATH)
- + "welcomepage/main.qml"));
-#else
- m_modeWidget->engine()->addImportPath("qrc:/qml/welcomepage/imports");
- m_modeWidget->setSource(QUrl("qrc:/qml/welcomepage/main.qml"));
-#endif
- } else {
-
- m_modeWidget->engine()->addImportPath(Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources/imports").toString());
-
- m_modeWidget->engine()->addImportPath(welcomePagePath + "/imports");
- m_modeWidget->engine()->addImportPath(m_dataModelDownloader->targetFolder().toString());
- m_modeWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
-
- QShortcut *updateShortcut = nullptr;
- if (Utils::HostOsInfo::isMacHost())
- updateShortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_F5), m_modeWidget);
- else
- updateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F5), m_modeWidget);
- connect(updateShortcut, &QShortcut::activated, this, [this, welcomePagePath](){
- m_modeWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
- });
- }
+ QVBoxLayout *boxLayout = new QVBoxLayout();
+ boxLayout->setContentsMargins(0, 0, 0, 0);
+ m_modeWidget = new QWidget;
+ m_modeWidget->setLayout(boxLayout);
+ boxLayout->addWidget(m_quickWidget);
setWidget(m_modeWidget);
QStringList designStudioQchPathes
@@ -795,6 +728,51 @@ WelcomeMode::~WelcomeMode()
delete m_modeWidget;
}
+void WelcomeMode::setupQuickWidget(const QString &welcomePagePath)
+{
+ if (!useNewWelcomePage()) {
+
+#ifdef QT_DEBUG
+ m_quickWidget->engine()->addImportPath(QLatin1String(STUDIO_QML_PATH)
+ + "welcomepage/imports");
+ m_quickWidget->setSource(
+ QUrl::fromLocalFile(QLatin1String(STUDIO_QML_PATH) + "welcomepage/main.qml"));
+#else
+ m_quickWidget->engine()->addImportPath("qrc:/qml/welcomepage/imports");
+ m_quickWidget->setSource(QUrl("qrc:/qml/welcomepage/main.qml"));
+#endif
+ } else {
+
+ m_quickWidget->engine()->addImportPath(Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources/imports").toString());
+
+ m_quickWidget->engine()->addImportPath(welcomePagePath + "/imports");
+ m_quickWidget->engine()->addImportPath(m_dataModelDownloader->targetFolder().toString());
+ m_quickWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
+
+ QShortcut *updateShortcut = nullptr;
+ if (Utils::HostOsInfo::isMacHost())
+ updateShortcut = new QShortcut(QKeySequence(Qt::ALT | Qt::Key_F5), m_quickWidget);
+ else
+ updateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F5), m_quickWidget);
+ connect(updateShortcut, &QShortcut::activated, this, [this, welcomePagePath](){
+ m_quickWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
+ });
+ }
+}
+
+void WelcomeMode::createQuickWidget()
+{
+ m_quickWidget = new QQuickWidget;
+ m_quickWidget->setMinimumSize(640, 480);
+ m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QmlDesigner::Theme::setupTheme(m_quickWidget->engine());
+ m_quickWidget->engine()->addImportPath("qrc:/studiofonts");
+
+ QmlDesigner::QmlDesignerPlugin::registerPreviewImageProvider(m_quickWidget->engine());
+
+ m_quickWidget->engine()->setOutputWarningsToStandardError(false);
+}
+
StudioSettingsPage::StudioSettingsPage()
: m_buildCheckBox(new QCheckBox(tr("Build")))
, m_debugCheckBox(new QCheckBox(tr("Debug")))
diff --git a/src/plugins/studiowelcome/userpresets.h b/src/plugins/studiowelcome/userpresets.h
index 3f614f4ea07..e5e8103228f 100644
--- a/src/plugins/studiowelcome/userpresets.h
+++ b/src/plugins/studiowelcome/userpresets.h
@@ -30,6 +30,8 @@
#include <QFile>
#include <QDebug>
+#include <vector>
+
namespace StudioWelcome {
struct UserPresetData
diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp
index 01c4eae407f..99f13476586 100644
--- a/src/plugins/subversion/subversionclient.cpp
+++ b/src/plugins/subversion/subversionclient.cpp
@@ -41,6 +41,7 @@
#include <diffeditor/diffutils.h>
#include <utils/algorithm.h>
+#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -94,7 +95,7 @@ bool SubversionClient::doCommit(const FilePath &repositoryRoot,
QtcProcess proc;
vcsSynchronousExec(proc, repositoryRoot, args << svnExtraOptions << escapeFiles(files),
VcsCommand::ShowStdOut | VcsCommand::NoFullySync);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
void SubversionClient::commit(const FilePath &repositoryRoot,
@@ -153,10 +154,10 @@ QString SubversionClient::synchronousTopic(const FilePath &repository) const
svnVersionBinary.append(HostOsInfo::withExecutableSuffix("svnversion"));
QtcProcess proc;
vcsFullySynchronousExec(proc, repository, {FilePath::fromString(svnVersionBinary), args});
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return QString();
- return proc.stdOut().trimmed();
+ return proc.cleanedStdOut().trimmed();
}
QString SubversionClient::escapeFile(const QString &file)
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index e65a1b88cb8..46231e4052d 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -53,6 +53,7 @@
#include <coreplugin/messagemanager.h>
#include <utils/algorithm.h>
+#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/parameteraction.h>
@@ -1030,11 +1031,11 @@ SubversionResponse SubversionPluginPrivate::runSvn(const FilePath &workingDir,
QtcProcess proc;
m_client->vcsFullySynchronousExec(proc, workingDir, arguments, flags, timeOutS, outputCodec);
- response.error = proc.result() != QtcProcess::FinishedWithSuccess;
+ response.error = proc.result() != ProcessResult::FinishedWithSuccess;
if (response.error)
response.message = proc.exitMessage();
- response.stdErr = proc.stdErr();
- response.stdOut = proc.stdOut();
+ response.stdErr = proc.cleanedStdErr();
+ response.stdOut = proc.cleanedStdOut();
return response;
}
diff --git a/src/plugins/texteditor/CMakeLists.txt b/src/plugins/texteditor/CMakeLists.txt
index caaa4846b7f..73b52c8bc96 100644
--- a/src/plugins/texteditor/CMakeLists.txt
+++ b/src/plugins/texteditor/CMakeLists.txt
@@ -13,7 +13,7 @@ add_qtc_plugin(TextEditor
basefilefind.cpp basefilefind.h
basehoverhandler.cpp basehoverhandler.h
behaviorsettings.cpp behaviorsettings.h
- behaviorsettingspage.cpp behaviorsettingspage.h behaviorsettingspage.ui
+ behaviorsettingspage.cpp behaviorsettingspage.h
behaviorsettingswidget.cpp behaviorsettingswidget.h behaviorsettingswidget.ui
blockrange.h
circularclipboard.cpp circularclipboard.h
diff --git a/src/plugins/texteditor/behaviorsettingspage.cpp b/src/plugins/texteditor/behaviorsettingspage.cpp
index f1c25b45470..d38c2926d36 100644
--- a/src/plugins/texteditor/behaviorsettingspage.cpp
+++ b/src/plugins/texteditor/behaviorsettingspage.cpp
@@ -26,15 +26,15 @@
#include "behaviorsettingspage.h"
#include "behaviorsettings.h"
-#include "typingsettings.h"
-#include "storagesettings.h"
-#include "tabsettings.h"
+#include "behaviorsettingswidget.h"
+#include "codestylepool.h"
#include "extraencodingsettings.h"
-#include "ui_behaviorsettingspage.h"
#include "simplecodestylepreferences.h"
+#include "storagesettings.h"
+#include "tabsettings.h"
#include "texteditorconstants.h"
-#include "codestylepool.h"
#include "texteditorsettings.h"
+#include "typingsettings.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -48,8 +48,10 @@
#include <qmljseditor/qmljseditorconstants.h>
#include <qmljstools/qmljstoolsconstants.h>
+#include <QGridLayout>
#include <QPointer>
#include <QSettings>
+#include <QSpacerItem>
namespace TextEditor {
@@ -59,7 +61,7 @@ struct BehaviorSettingsPage::BehaviorSettingsPagePrivate : public QObject
const QString m_settingsPrefix{"text"};
QPointer<QWidget> m_widget;
- Internal::Ui::BehaviorSettingsPage *m_page = nullptr;
+ TextEditor::BehaviorSettingsWidget *m_behaviorWidget = nullptr;
CodeStylePool *m_defaultCodeStylePool = nullptr;
SimpleCodeStylePreferences *m_codeStyle = nullptr;
@@ -110,17 +112,23 @@ QWidget *BehaviorSettingsPage::widget()
{
if (!d->m_widget) {
d->m_widget = new QWidget;
- d->m_page = new Internal::Ui::BehaviorSettingsPage;
- d->m_page->setupUi(d->m_widget);
+ d->m_behaviorWidget = new BehaviorSettingsWidget(d->m_widget);
+
+ auto verticalSpacer = new QSpacerItem(20, 13, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ auto gridLayout = new QGridLayout(d->m_widget);
if (Utils::HostOsInfo::isMacHost())
- d->m_page->gridLayout->setContentsMargins(-1, 0, -1, 0); // don't ask.
+ gridLayout->setContentsMargins(-1, 0, -1, 0); // don't ask.
+ gridLayout->addWidget(d->m_behaviorWidget, 0, 0, 1, 1);
+ gridLayout->addItem(verticalSpacer, 1, 0, 1, 1);
+
d->m_pageCodeStyle = new SimpleCodeStylePreferences(d->m_widget);
d->m_pageCodeStyle->setDelegatingPool(d->m_codeStyle->delegatingPool());
d->m_pageCodeStyle->setTabSettings(d->m_codeStyle->tabSettings());
d->m_pageCodeStyle->setCurrentDelegate(d->m_codeStyle->currentDelegate());
- d->m_page->behaviorWidget->setCodeStyle(d->m_pageCodeStyle);
+ d->m_behaviorWidget->setCodeStyle(d->m_pageCodeStyle);
- TabSettingsWidget *tabSettingsWidget = d->m_page->behaviorWidget->tabSettingsWidget();
+ TabSettingsWidget *tabSettingsWidget = d->m_behaviorWidget->tabSettingsWidget();
tabSettingsWidget->setCodingStyleWarningVisible(true);
connect(tabSettingsWidget, &TabSettingsWidget::codingStyleLinkClicked,
this, &BehaviorSettingsPage::openCodingStylePreferences);
@@ -132,7 +140,7 @@ QWidget *BehaviorSettingsPage::widget()
void BehaviorSettingsPage::apply()
{
- if (!d->m_page) // page was never shown
+ if (!d->m_behaviorWidget) // page was never shown
return;
TypingSettings newTypingSettings;
@@ -185,9 +193,9 @@ void BehaviorSettingsPage::apply()
}
s->setValue(QLatin1String(Core::Constants::SETTINGS_DEFAULTTEXTENCODING),
- d->m_page->behaviorWidget->assignedCodecName());
+ d->m_behaviorWidget->assignedCodecName());
s->setValue(QLatin1String(Core::Constants::SETTINGS_DEFAULT_LINE_TERMINATOR),
- d->m_page->behaviorWidget->assignedLineEnding());
+ d->m_behaviorWidget->assignedLineEnding());
}
void BehaviorSettingsPage::settingsFromUI(TypingSettings *typingSettings,
@@ -195,29 +203,25 @@ void BehaviorSettingsPage::settingsFromUI(TypingSettings *typingSettings,
BehaviorSettings *behaviorSettings,
ExtraEncodingSettings *extraEncodingSettings) const
{
- d->m_page->behaviorWidget->assignedTypingSettings(typingSettings);
- d->m_page->behaviorWidget->assignedStorageSettings(storageSettings);
- d->m_page->behaviorWidget->assignedBehaviorSettings(behaviorSettings);
- d->m_page->behaviorWidget->assignedExtraEncodingSettings(extraEncodingSettings);
+ d->m_behaviorWidget->assignedTypingSettings(typingSettings);
+ d->m_behaviorWidget->assignedStorageSettings(storageSettings);
+ d->m_behaviorWidget->assignedBehaviorSettings(behaviorSettings);
+ d->m_behaviorWidget->assignedExtraEncodingSettings(extraEncodingSettings);
}
void BehaviorSettingsPage::settingsToUI()
{
- d->m_page->behaviorWidget->setAssignedTypingSettings(d->m_typingSettings);
- d->m_page->behaviorWidget->setAssignedStorageSettings(d->m_storageSettings);
- d->m_page->behaviorWidget->setAssignedBehaviorSettings(d->m_behaviorSettings);
- d->m_page->behaviorWidget->setAssignedExtraEncodingSettings(d->m_extraEncodingSettings);
- d->m_page->behaviorWidget->setAssignedCodec(Core::EditorManager::defaultTextCodec());
- d->m_page->behaviorWidget->setAssignedLineEnding(Core::EditorManager::defaultLineEnding());
+ d->m_behaviorWidget->setAssignedTypingSettings(d->m_typingSettings);
+ d->m_behaviorWidget->setAssignedStorageSettings(d->m_storageSettings);
+ d->m_behaviorWidget->setAssignedBehaviorSettings(d->m_behaviorSettings);
+ d->m_behaviorWidget->setAssignedExtraEncodingSettings(d->m_extraEncodingSettings);
+ d->m_behaviorWidget->setAssignedCodec(Core::EditorManager::defaultTextCodec());
+ d->m_behaviorWidget->setAssignedLineEnding(Core::EditorManager::defaultLineEnding());
}
void BehaviorSettingsPage::finish()
{
delete d->m_widget;
- if (!d->m_page) // page was never shown
- return;
- delete d->m_page;
- d->m_page = nullptr;
}
ICodeStylePreferences *BehaviorSettingsPage::codeStyle() const
diff --git a/src/plugins/texteditor/behaviorsettingspage.ui b/src/plugins/texteditor/behaviorsettingspage.ui
deleted file mode 100644
index 44fcf405dc2..00000000000
--- a/src/plugins/texteditor/behaviorsettingspage.ui
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>TextEditor::Internal::BehaviorSettingsPage</class>
- <widget class="QWidget" name="TextEditor::Internal::BehaviorSettingsPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>432</width>
- <height>50</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="TextEditor::BehaviorSettingsWidget" name="behaviorWidget" native="true"/>
- </item>
- <item row="1" column="0">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>13</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>TextEditor::BehaviorSettingsWidget</class>
- <extends>QWidget</extends>
- <header>texteditor/behaviorsettingswidget.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/texteditor/behaviorsettingswidget.cpp b/src/plugins/texteditor/behaviorsettingswidget.cpp
index 510796afab9..409f80dfa7f 100644
--- a/src/plugins/texteditor/behaviorsettingswidget.cpp
+++ b/src/plugins/texteditor/behaviorsettingswidget.cpp
@@ -36,6 +36,7 @@
#include <texteditor/behaviorsettings.h>
#include <texteditor/extraencodingsettings.h>
#include <utils/algorithm.h>
+#include <utils/hostosinfo.h>
#include <QList>
#include <QString>
@@ -65,10 +66,11 @@ BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent)
std::find_if(mibs.begin(), mibs.end(), [](int n) { return n >=0; });
if (firstNonNegative != mibs.end())
std::rotate(mibs.begin(), firstNonNegative, mibs.end());
- foreach (int mib, mibs) {
+ for (int mib : qAsConst(mibs)) {
if (QTextCodec *codec = QTextCodec::codecForMib(mib)) {
QString compoundName = QLatin1String(codec->name());
- foreach (const QByteArray &alias, codec->aliases()) {
+ const QList<QByteArray> aliases = codec->aliases();
+ for (const QByteArray &alias : aliases) {
compoundName += QLatin1String(" / ");
compoundName += QString::fromLatin1(alias);
}
@@ -121,6 +123,8 @@ BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent)
this, &BehaviorSettingsWidget::slotBehaviorSettingsChanged);
connect(d->m_ui.smartSelectionChanging, &QAbstractButton::clicked,
this, &BehaviorSettingsWidget::slotBehaviorSettingsChanged);
+
+ d->m_ui.mouseHiding->setVisible(!Utils::HostOsInfo::isMacHost());
}
BehaviorSettingsWidget::~BehaviorSettingsWidget()
diff --git a/src/plugins/texteditor/codeassist/assistinterface.cpp b/src/plugins/texteditor/codeassist/assistinterface.cpp
index 0a25e1ff34f..43edc19196a 100644
--- a/src/plugins/texteditor/codeassist/assistinterface.cpp
+++ b/src/plugins/texteditor/codeassist/assistinterface.cpp
@@ -101,13 +101,14 @@ using namespace TextEditor;
namespace TextEditor {
-AssistInterface::AssistInterface(QTextDocument *textDocument,
- int position,
- const Utils::FilePath &filePath,
- AssistReason reason)
- : m_textDocument(textDocument)
+AssistInterface::AssistInterface(const QTextCursor &cursor,
+ const Utils::FilePath &filePath,
+ AssistReason reason)
+ : m_textDocument(cursor.document())
+ , m_cursor(cursor)
, m_isAsync(false)
- , m_position(position)
+ , m_position(cursor.position())
+ , m_anchor(cursor.anchor())
, m_filePath(filePath)
, m_reason(reason)
{}
@@ -141,6 +142,9 @@ void AssistInterface::prepareForAsyncUse()
void AssistInterface::recreateTextDocument()
{
m_textDocument = new QTextDocument(m_text);
+ m_cursor = QTextCursor(m_textDocument);
+ m_cursor.setPosition(m_anchor);
+ m_cursor.setPosition(m_position, QTextCursor::KeepAnchor);
m_text.clear();
QTC_CHECK(m_textDocument->blockCount() == m_userStates.count());
diff --git a/src/plugins/texteditor/codeassist/assistinterface.h b/src/plugins/texteditor/codeassist/assistinterface.h
index 85a738309ad..9c49603ceac 100644
--- a/src/plugins/texteditor/codeassist/assistinterface.h
+++ b/src/plugins/texteditor/codeassist/assistinterface.h
@@ -30,21 +30,17 @@
#include <texteditor/texteditor_global.h>
#include <QString>
+#include <QTextCursor>
#include <QVector>
-#include <utils/fileutils.h>
-
-QT_BEGIN_NAMESPACE
-class QTextDocument;
-QT_END_NAMESPACE
+#include <utils/filepath.h>
namespace TextEditor {
class TEXTEDITOR_EXPORT AssistInterface
{
public:
- AssistInterface(QTextDocument *textDocument,
- int position,
+ AssistInterface(const QTextCursor &cursor,
const Utils::FilePath &filePath,
AssistReason reason);
virtual ~AssistInterface();
@@ -52,16 +48,20 @@ public:
virtual int position() const { return m_position; }
virtual QChar characterAt(int position) const;
virtual QString textAt(int position, int length) const;
+ QTextCursor cursor() const { return m_cursor; }
virtual Utils::FilePath filePath() const { return m_filePath; }
virtual QTextDocument *textDocument() const { return m_textDocument; }
virtual void prepareForAsyncUse();
virtual void recreateTextDocument();
virtual AssistReason reason() const;
+ virtual bool isBaseObject() const { return true; }
private:
QTextDocument *m_textDocument;
+ QTextCursor m_cursor;
bool m_isAsync;
int m_position;
+ int m_anchor;
Utils::FilePath m_filePath;
AssistReason m_reason;
QString m_text;
diff --git a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
index b1fd5f3848c..bedc6a98691 100644
--- a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
+++ b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
@@ -27,8 +27,6 @@
#include "textdocumentmanipulatorinterface.h"
-#include <utils/declarationmacros.h>
-
QT_BEGIN_NAMESPACE
class QIcon;
class QString;
@@ -54,7 +52,7 @@ public:
AssistProposalItemInterface() = default;
virtual ~AssistProposalItemInterface() noexcept = default;
- UTILS_DELETE_MOVE_AND_COPY(AssistProposalItemInterface)
+ Q_DISABLE_COPY_MOVE(AssistProposalItemInterface)
virtual QString text() const = 0;
virtual QString filterText() const { return text(); }
diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp
index d16ad59146f..6613042c52b 100644
--- a/src/plugins/texteditor/codeassist/codeassistant.cpp
+++ b/src/plugins/texteditor/codeassist/codeassistant.cpp
@@ -64,7 +64,10 @@ public:
void invoke(AssistKind kind, IAssistProvider *provider = nullptr);
void process();
- void requestProposal(AssistReason reason, AssistKind kind, IAssistProvider *provider = nullptr);
+ void requestProposal(AssistReason reason,
+ AssistKind kind,
+ IAssistProvider *provider = nullptr,
+ bool isUpdate = false);
void cancelCurrentRequest();
void invalidateCurrentRequestData();
void displayProposal(IAssistProposal *newProposal, AssistReason reason);
@@ -152,7 +155,8 @@ void CodeAssistantPrivate::invoke(AssistKind kind, IAssistProvider *provider)
stopAutomaticProposalTimer();
- if (isDisplayingProposal() && m_assistKind == kind && !m_proposal->isFragile()) {
+ if (isDisplayingProposal() && m_assistKind == kind && !m_proposal->isFragile()
+ && m_proposal->supportsPrefix()) {
m_proposalWidget->setReason(ExplicitlyInvoked);
m_proposalWidget->updateProposal(m_editorWidget->textAt(
m_proposal->basePosition(),
@@ -192,7 +196,8 @@ void CodeAssistantPrivate::process()
void CodeAssistantPrivate::requestProposal(AssistReason reason,
AssistKind kind,
- IAssistProvider *provider)
+ IAssistProvider *provider,
+ bool isUpdate)
{
// make sure to cleanup old proposals if we cannot find a new assistant
Utils::ExecuteOnDestruction earlyReturnContextClear([this]() { destroyContext(); });
@@ -266,13 +271,13 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
if (processor != m_asyncProcessor)
return;
invalidateCurrentRequestData();
- if (processor && processor->needsRestart() && m_receivedContentWhileWaiting) {
+ if (processor->needsRestart() && m_receivedContentWhileWaiting) {
delete newProposal;
m_receivedContentWhileWaiting = false;
requestProposal(reason, m_assistKind, m_requestProvider);
} else {
displayProposal(newProposal, reason);
- if (processor && processor->running())
+ if (processor->running())
m_asyncProcessor = processor;
else
emit q->finished();
@@ -284,6 +289,8 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
displayProposal(newProposal, reason);
delete processor;
} else if (!processor->running()) {
+ if (isUpdate)
+ destroyContext();
delete processor;
} else { // ...async request was triggered
if (IAssistProposal *newProposal = processor->immediateProposal(assistInterface))
@@ -318,8 +325,10 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR
// TODO: The proposal should own the model until someone takes it explicitly away.
QScopedPointer<IAssistProposal> proposalCandidate(newProposal);
- if (isDisplayingProposal() && !m_proposal->isFragile())
+ if (isDisplayingProposal() && !m_proposal->isFragile()
+ && !m_proposalWidget->supportsModelUpdate(proposalCandidate->id())) {
return;
+ }
int basePosition = proposalCandidate->basePosition();
if (m_editorWidget->position() < basePosition) {
@@ -345,6 +354,7 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR
&& basePosition == proposalCandidate->basePosition()
&& m_proposalWidget->supportsModelUpdate(proposalCandidate->id())) {
m_proposal.reset(proposalCandidate.take());
+ m_proposal->setReason(reason);
m_proposalWidget->updateModel(m_proposal->model());
m_proposalWidget->updateProposal(prefix);
return;
@@ -354,6 +364,7 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR
clearAbortedPosition();
m_proposal.reset(proposalCandidate.take());
+ m_proposal->setReason(reason);
if (m_proposal->isCorrective(m_editorWidget))
m_proposal->makeCorrection(m_editorWidget);
@@ -485,7 +496,7 @@ void CodeAssistantPrivate::notifyChange()
if (!isDisplayingProposal())
requestActivationCharProposal();
} else {
- requestProposal(ExplicitlyInvoked, m_assistKind, m_requestProvider);
+ requestProposal(m_proposal->reason(), m_assistKind, m_requestProvider, true);
}
}
}
diff --git a/src/plugins/texteditor/codeassist/documentcontentcompletion.cpp b/src/plugins/texteditor/codeassist/documentcontentcompletion.cpp
index ddf0d8a16a1..a12912f186d 100644
--- a/src/plugins/texteditor/codeassist/documentcontentcompletion.cpp
+++ b/src/plugins/texteditor/codeassist/documentcontentcompletion.cpp
@@ -86,7 +86,7 @@ DocumentContentCompletionProcessor::~DocumentContentCompletionProcessor()
static void createProposal(QFutureInterface<QStringList> &future, const QString &text,
const QString &wordUnderCursor)
{
- const QRegularExpression wordRE("([a-zA-Z_][a-zA-Z0-9_]{2,})");
+ const QRegularExpression wordRE("([\\p{L}_][\\p{L}0-9_]{2,})");
QSet<QString> words;
QRegularExpressionMatchIterator it = wordRE.globalMatch(text);
diff --git a/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp b/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp
index 926ebfde39b..aab407acdbe 100644
--- a/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp
+++ b/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp
@@ -299,8 +299,6 @@ bool FunctionHintProposalWidget::eventFilter(QObject *obj, QEvent *e)
if (d->m_model && d->m_model->size() > 1)
return false;
}
- if (QTC_GUARD(d->m_assistant))
- d->m_assistant->notifyChange();
}
break;
case QEvent::WindowDeactivate:
diff --git a/src/plugins/texteditor/codeassist/genericproposal.cpp b/src/plugins/texteditor/codeassist/genericproposal.cpp
index 4b2e0415ab3..2bc66db2e69 100644
--- a/src/plugins/texteditor/codeassist/genericproposal.cpp
+++ b/src/plugins/texteditor/codeassist/genericproposal.cpp
@@ -53,7 +53,7 @@ GenericProposal *GenericProposal::createProposal(const AssistInterface *interfac
return nullptr;
QList<AssistProposalItemInterface *> items;
- foreach (const QuickFixOperation::Ptr &op, quickFixes) {
+ for (const QuickFixOperation::Ptr &op : quickFixes) {
QVariant v;
v.setValue(op);
auto item = new AssistProposalItem;
diff --git a/src/plugins/texteditor/codeassist/iassistproposal.h b/src/plugins/texteditor/codeassist/iassistproposal.h
index d4784a3f60d..feb92caf9f2 100644
--- a/src/plugins/texteditor/codeassist/iassistproposal.h
+++ b/src/plugins/texteditor/codeassist/iassistproposal.h
@@ -57,11 +57,15 @@ public:
Utils::Id id() const { return m_id; }
+ AssistReason reason() const { return m_reason; }
+ void setReason(const AssistReason &reason) { m_reason = reason; }
+
protected:
Utils::Id m_id;
int m_basePosition;
bool m_isFragile = false;
bool m_supportsPrefix = true;
+ AssistReason m_reason = IdleEditor;
};
} // TextEditor
diff --git a/src/plugins/texteditor/codestyleselectorwidget.cpp b/src/plugins/texteditor/codestyleselectorwidget.cpp
index 061e24d91b5..b62612e535c 100644
--- a/src/plugins/texteditor/codestyleselectorwidget.cpp
+++ b/src/plugins/texteditor/codestyleselectorwidget.cpp
@@ -108,7 +108,8 @@ CodeStyleDialog::CodeStyleDialog(ICodeStylePreferencesFactory *factory,
m_codeStyle->setValue(codeStyle->value());
m_codeStyle->setId(codeStyle->id());
m_codeStyle->setDisplayName(m_originalDisplayName);
- QWidget *editor = factory->createEditor(m_codeStyle, project, this);
+ m_codeStyle->setReadOnly(codeStyle->isReadOnly());
+ TextEditor::CodeStyleEditorWidget *editor = factory->createEditor(m_codeStyle, project, this);
m_buttons = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
@@ -124,6 +125,7 @@ CodeStyleDialog::CodeStyleDialog(ICodeStylePreferencesFactory *factory,
connect(m_lineEdit, &QLineEdit::textChanged, this, &CodeStyleDialog::slotDisplayNameChanged);
connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(m_buttons, &QDialogButtonBox::accepted, editor, &TextEditor::CodeStyleEditorWidget::apply);
connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
diff --git a/src/plugins/texteditor/codestyleselectorwidget.ui b/src/plugins/texteditor/codestyleselectorwidget.ui
index 3bb61a3507d..5d3daa543bd 100644
--- a/src/plugins/texteditor/codestyleselectorwidget.ui
+++ b/src/plugins/texteditor/codestyleselectorwidget.ui
@@ -14,7 +14,7 @@
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
- <property name="margin">
+ <property name="margin" stdset="0">
<number>0</number>
</property>
<item row="0" column="0">
diff --git a/src/plugins/texteditor/colorschemeedit.cpp b/src/plugins/texteditor/colorschemeedit.cpp
index ec316880bd2..72bfbe4a9f1 100644
--- a/src/plugins/texteditor/colorschemeedit.cpp
+++ b/src/plugins/texteditor/colorschemeedit.cpp
@@ -456,7 +456,8 @@ void ColorSchemeEdit::eraseBackColor()
m_ui->backgroundToolButton->setStyleSheet(colorButtonStyleSheet(newColor));
m_ui->eraseBackgroundToolButton->setEnabled(false);
- foreach (const QModelIndex &index, m_ui->itemList->selectionModel()->selectedRows()) {
+ const QList<QModelIndex> indexes = m_ui->itemList->selectionModel()->selectedRows();
+ for (const QModelIndex &index : indexes) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setBackground(newColor);
m_formatsModel->emitDataChanged(index);
@@ -473,7 +474,8 @@ void ColorSchemeEdit::eraseForeColor()
m_ui->foregroundToolButton->setStyleSheet(colorButtonStyleSheet(newColor));
m_ui->eraseForegroundToolButton->setEnabled(false);
- for (const QModelIndex &index : m_ui->itemList->selectionModel()->selectedRows()) {
+ const QList<QModelIndex> indexes = m_ui->itemList->selectionModel()->selectedRows();
+ for (const QModelIndex &index : indexes) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setForeground(newColor);
m_formatsModel->emitDataChanged(index);
@@ -538,7 +540,8 @@ void ColorSchemeEdit::eraseRelativeBackColor()
m_ui->backgroundSaturationSpinBox->setValue(0.0);
m_ui->backgroundLightnessSpinBox->setValue(0.0);
- foreach (const QModelIndex &index, m_ui->itemList->selectionModel()->selectedRows()) {
+ const QList<QModelIndex> indexes = m_ui->itemList->selectionModel()->selectedRows();
+ for (const QModelIndex &index : indexes) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setRelativeBackgroundSaturation(0.0);
m_scheme.formatFor(category).setRelativeBackgroundLightness(0.0);
diff --git a/src/plugins/texteditor/displaysettings.cpp b/src/plugins/texteditor/displaysettings.cpp
index c5e41fb4991..f092150a0e6 100644
--- a/src/plugins/texteditor/displaysettings.cpp
+++ b/src/plugins/texteditor/displaysettings.cpp
@@ -47,6 +47,7 @@ static const char autoFoldFirstCommentKey[] = "AutoFoldFirstComment";
static const char centerCursorOnScrollKey[] = "CenterCursorOnScroll";
static const char openLinksInNextSplitKey[] = "OpenLinksInNextSplitKey";
static const char displayFileEncodingKey[] = "DisplayFileEncoding";
+static const char displayFileLineEndingKey[] = "DisplayFileLineEnding";
static const char scrollBarHighlightsKey[] = "ScrollBarHighlights";
static const char animateNavigationWithinFileKey[] = "AnimateNavigationWithinFile";
static const char animateWithinFileTimeMaxKey[] = "AnimateWithinFileTimeMax";
@@ -76,6 +77,7 @@ void DisplaySettings::toSettings(const QString &category, QSettings *s) const
s->setValue(QLatin1String(centerCursorOnScrollKey), m_centerCursorOnScroll);
s->setValue(QLatin1String(openLinksInNextSplitKey), m_openLinksInNextSplit);
s->setValue(QLatin1String(displayFileEncodingKey), m_displayFileEncoding);
+ s->setValue(QLatin1String(displayFileLineEndingKey), m_displayFileLineEnding);
s->setValue(QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights);
s->setValue(QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile);
s->setValue(QLatin1String(displayAnnotationsKey), m_displayAnnotations);
@@ -105,6 +107,7 @@ void DisplaySettings::fromSettings(const QString &category, const QSettings *s)
m_centerCursorOnScroll = s->value(group + QLatin1String(centerCursorOnScrollKey), m_centerCursorOnScroll).toBool();
m_openLinksInNextSplit = s->value(group + QLatin1String(openLinksInNextSplitKey), m_openLinksInNextSplit).toBool();
m_displayFileEncoding = s->value(group + QLatin1String(displayFileEncodingKey), m_displayFileEncoding).toBool();
+ m_displayFileLineEnding = s->value(group + QLatin1String(displayFileLineEndingKey), m_displayFileLineEnding).toBool();
m_scrollBarHighlights = s->value(group + QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights).toBool();
m_animateNavigationWithinFile = s->value(group + QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile).toBool();
m_animateWithinFileTimeMax = s->value(group + QLatin1String(animateWithinFileTimeMaxKey), m_animateWithinFileTimeMax).toInt();
@@ -131,6 +134,7 @@ bool DisplaySettings::equals(const DisplaySettings &ds) const
&& m_openLinksInNextSplit == ds.m_openLinksInNextSplit
&& m_forceOpenLinksInNextSplit == ds.m_forceOpenLinksInNextSplit
&& m_displayFileEncoding == ds.m_displayFileEncoding
+ && m_displayFileLineEnding == ds.m_displayFileLineEnding
&& m_scrollBarHighlights == ds.m_scrollBarHighlights
&& m_animateNavigationWithinFile == ds.m_animateNavigationWithinFile
&& m_animateWithinFileTimeMax == ds.m_animateWithinFileTimeMax
diff --git a/src/plugins/texteditor/displaysettings.h b/src/plugins/texteditor/displaysettings.h
index ae87f76dfbd..97b716a8fc7 100644
--- a/src/plugins/texteditor/displaysettings.h
+++ b/src/plugins/texteditor/displaysettings.h
@@ -69,6 +69,7 @@ public:
bool m_openLinksInNextSplit = false;
bool m_forceOpenLinksInNextSplit = false;
bool m_displayFileEncoding = false;
+ bool m_displayFileLineEnding = true;
bool m_scrollBarHighlights = true;
bool m_animateNavigationWithinFile = false;
int m_animateWithinFileTimeMax = 333; // read only setting
diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp
index fa551504211..f972e1735a8 100644
--- a/src/plugins/texteditor/displaysettingspage.cpp
+++ b/src/plugins/texteditor/displaysettingspage.cpp
@@ -102,6 +102,7 @@ void DisplaySettingsWidget::settingsFromUI(DisplaySettings &displaySettings,
displaySettings.m_centerCursorOnScroll = m_ui.centerOnScroll->isChecked();
displaySettings.m_openLinksInNextSplit = m_ui.openLinksInNextSplit->isChecked();
displaySettings.m_displayFileEncoding = m_ui.displayFileEncoding->isChecked();
+ displaySettings.m_displayFileLineEnding = m_ui.displayFileLineEnding->isChecked();
displaySettings.m_scrollBarHighlights = m_ui.scrollBarHighlights->isChecked();
displaySettings.m_animateNavigationWithinFile = m_ui.animateNavigationWithinFile->isChecked();
displaySettings.m_displayAnnotations = m_ui.displayAnnotations->isChecked();
@@ -135,6 +136,7 @@ void DisplaySettingsWidget::settingsToUI()
m_ui.centerOnScroll->setChecked(displaySettings.m_centerCursorOnScroll);
m_ui.openLinksInNextSplit->setChecked(displaySettings.m_openLinksInNextSplit);
m_ui.displayFileEncoding->setChecked(displaySettings.m_displayFileEncoding);
+ m_ui.displayFileLineEnding->setChecked(displaySettings.m_displayFileLineEnding);
m_ui.scrollBarHighlights->setChecked(displaySettings.m_scrollBarHighlights);
m_ui.animateNavigationWithinFile->setChecked(displaySettings.m_animateNavigationWithinFile);
m_ui.displayAnnotations->setChecked(displaySettings.m_displayAnnotations);
diff --git a/src/plugins/texteditor/displaysettingspage.ui b/src/plugins/texteditor/displaysettingspage.ui
index c7d49ac0692..29dea5649a3 100644
--- a/src/plugins/texteditor/displaysettingspage.ui
+++ b/src/plugins/texteditor/displaysettingspage.ui
@@ -97,6 +97,13 @@
</property>
</widget>
</item>
+ <item row="7" column="1">
+ <widget class="QCheckBox" name="displayFileLineEnding">
+ <property name="text">
+ <string>Display file line ending</string>
+ </property>
+ </widget>
+ </item>
<item row="2" column="1">
<widget class="QCheckBox" name="animateMatchingParentheses">
<property name="text">
@@ -170,7 +177,7 @@
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="8" column="0">
<widget class="QCheckBox" name="animateNavigationWithinFile">
<property name="text">
<string>Animate navigation within file</string>
diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp
index 9b0a3b4c70b..7f135af611b 100644
--- a/src/plugins/texteditor/findinfiles.cpp
+++ b/src/plugins/texteditor/findinfiles.cpp
@@ -159,7 +159,8 @@ QWidget *FindInFiles::createConfigWidget()
gridLayout->addWidget(m_searchEngineCombo, row, 1);
m_searchEngineWidget = new QStackedWidget(m_configWidget);
- foreach (SearchEngine *searchEngine, searchEngines()) {
+ const QVector<SearchEngine *> searchEngineVector = searchEngines();
+ for (const SearchEngine *searchEngine : searchEngineVector) {
m_searchEngineWidget->addWidget(searchEngine->widget());
m_searchEngineCombo->addItem(searchEngine->title());
}
@@ -197,7 +198,7 @@ QWidget *FindInFiles::createConfigWidget()
setValid(currentSearchEngine()->isEnabled() && m_directory->isValid());
};
connect(this, &BaseFileFind::currentSearchEngineChanged, this, updateValidity);
- foreach (SearchEngine *searchEngine, searchEngines())
+ for (const SearchEngine *searchEngine : searchEngineVector)
connect(searchEngine, &SearchEngine::enabledChanged, this, updateValidity);
connect(m_directory.data(), &PathChooser::validChanged, this, updateValidity);
updateValidity();
diff --git a/src/plugins/texteditor/findinopenfiles.cpp b/src/plugins/texteditor/findinopenfiles.cpp
index 80f0e130973..4f10a430794 100644
--- a/src/plugins/texteditor/findinopenfiles.cpp
+++ b/src/plugins/texteditor/findinopenfiles.cpp
@@ -66,8 +66,8 @@ Utils::FileIterator *FindInOpenFiles::files(const QStringList &nameFilters,
= TextDocument::openedTextDocumentEncodings();
QStringList fileNames;
QList<QTextCodec *> codecs;
- foreach (Core::DocumentModel::Entry *entry,
- Core::DocumentModel::entries()) {
+ const QList<Core::DocumentModel::Entry *> entries = Core::DocumentModel::entries();
+ for (Core::DocumentModel::Entry *entry : entries) {
QString fileName = entry->fileName().toString();
if (!fileName.isEmpty()) {
fileNames.append(fileName);
diff --git a/src/plugins/texteditor/fontsettings.cpp b/src/plugins/texteditor/fontsettings.cpp
index ef8a36af948..a946f4cc201 100644
--- a/src/plugins/texteditor/fontsettings.cpp
+++ b/src/plugins/texteditor/fontsettings.cpp
@@ -414,13 +414,17 @@ bool FontSettings::loadColorScheme(const QString &fileName,
}
// Apply default formats to undefined categories
- foreach (const FormatDescription &desc, descriptions) {
+ for (const FormatDescription &desc : descriptions) {
const TextStyle id = desc.id();
if (!m_scheme.contains(id)) {
if (id == C_NAMESPACE && m_scheme.contains(C_TYPE)) {
m_scheme.setFormatFor(C_NAMESPACE, m_scheme.formatFor(C_TYPE));
continue;
}
+ if (id == C_MACRO && m_scheme.contains(C_FUNCTION)) {
+ m_scheme.setFormatFor(C_MACRO, m_scheme.formatFor(C_FUNCTION));
+ continue;
+ }
Format format;
const Format &descFormat = desc.format();
// Default fallback for background and foreground is C_TEXT, which is set through
diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp
index f3ac7597a48..7cced1e7aaa 100644
--- a/src/plugins/texteditor/fontsettingspage.cpp
+++ b/src/plugins/texteditor/fontsettingspage.cpp
@@ -306,6 +306,8 @@ QColor FormatDescription::defaultForeground(TextStyle id)
return QColor(0x00, 0x00, 0x33);
} else if (id == C_SEARCH_RESULT_ALT2) {
return QColor(0x33, 0x00, 0x00);
+ } else if (id == C_SEARCH_RESULT_CONTAINING_FUNCTION) {
+ return Qt::black;
}
return QColor();
}
@@ -322,6 +324,8 @@ QColor FormatDescription::defaultBackground(TextStyle id)
return QColor(0xb6, 0xcc, 0xff);
} else if (id == C_SEARCH_RESULT_ALT2) {
return QColor(0xff, 0xb6, 0xcc);
+ } else if (id == C_SEARCH_RESULT_CONTAINING_FUNCTION) {
+ return Qt::white;
} else if (id == C_PARENTHESES) {
return QColor(0xb4, 0xee, 0xb4);
} else if (id == C_PARENTHESES_MISMATCH) {
@@ -626,7 +630,7 @@ void FontSettingsPageWidget::refreshColorSchemeList()
QString defaultScheme = Utils::FilePath::fromString(FontSettings::defaultSchemeFileName()).fileName();
if (schemeList.removeAll(defaultScheme))
schemeList.prepend(defaultScheme);
- foreach (const QString &file, schemeList) {
+ for (const QString &file : qAsConst(schemeList)) {
const QString fileName = styleDir.absoluteFilePath(file);
if (m_value.colorSchemeFileName() == fileName)
selected = colorSchemes.size();
@@ -638,7 +642,8 @@ void FontSettingsPageWidget::refreshColorSchemeList()
styleDir.setPath(customStylesPath().path());
- foreach (const QString &file, styleDir.entryList()) {
+ const QStringList files = styleDir.entryList();
+ for (const QString &file : files) {
const QString fileName = styleDir.absoluteFilePath(file);
if (m_value.colorSchemeFileName() == fileName)
selected = colorSchemes.size();
diff --git a/src/plugins/texteditor/fontsettingspage.h b/src/plugins/texteditor/fontsettingspage.h
index cf516e38d12..731c7d1965c 100644
--- a/src/plugins/texteditor/fontsettingspage.h
+++ b/src/plugins/texteditor/fontsettingspage.h
@@ -53,6 +53,7 @@ public:
enum ShowControls {
ShowForegroundControl = 0x1,
ShowBackgroundControl = 0x2,
+ ShowForeAndBackgroundControl = ShowForegroundControl | ShowBackgroundControl,
ShowFontControls = 0x4,
ShowUnderlineControl = 0x8,
ShowRelativeForegroundControl = 0x10,
diff --git a/src/plugins/texteditor/formattexteditor.cpp b/src/plugins/texteditor/formattexteditor.cpp
index 830a8e8a992..a01f543f1a1 100644
--- a/src/plugins/texteditor/formattexteditor.cpp
+++ b/src/plugins/texteditor/formattexteditor.cpp
@@ -92,12 +92,12 @@ static FormatTask format(FormatTask task)
process.setTimeoutS(5);
process.setCommand({FilePath::fromString(executable), options});
process.runBlocking();
- if (process.result() != QtcProcess::FinishedWithSuccess) {
+ if (process.result() != ProcessResult::FinishedWithSuccess) {
task.error = QString(QT_TRANSLATE_NOOP("TextEditor", "Failed to format: %1."))
.arg(process.exitMessage());
return task;
}
- const QString output = process.stdErr();
+ const QString output = process.cleanedStdErr();
if (!output.isEmpty())
task.error = executable + QLatin1String(": ") + output;
@@ -127,7 +127,6 @@ static FormatTask format(FormatTask task)
return task;
}
if (!process.waitForFinished(5000)) {
- process.kill();
task.error = QString(QT_TRANSLATE_NOOP("TextEditor",
"Cannot call %1 or some other error occurred. Timeout "
"reached while formatting file %2."))
diff --git a/src/plugins/texteditor/highlighter.cpp b/src/plugins/texteditor/highlighter.cpp
index 5a7cb017055..f8e90f49abe 100644
--- a/src/plugins/texteditor/highlighter.cpp
+++ b/src/plugins/texteditor/highlighter.cpp
@@ -34,15 +34,15 @@
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
-#include <DefinitionDownloader>
-#include <FoldingRegion>
-#include <Format>
-#include <Repository>
-#include <SyntaxHighlighter>
+#include <KSyntaxHighlighting/DefinitionDownloader>
+#include <KSyntaxHighlighting/FoldingRegion>
+#include <KSyntaxHighlighting/Format>
+#include <KSyntaxHighlighting/Repository>
+#include <KSyntaxHighlighting/SyntaxHighlighter>
#include <QLoggingCategory>
#include <QMetaEnum>
diff --git a/src/plugins/texteditor/highlighter.h b/src/plugins/texteditor/highlighter.h
index e18a67e8f8e..3127589096f 100644
--- a/src/plugins/texteditor/highlighter.h
+++ b/src/plugins/texteditor/highlighter.h
@@ -29,8 +29,8 @@
#include <utils/fileutils.h>
-#include <AbstractHighlighter>
-#include <Definition>
+#include <KSyntaxHighlighting/AbstractHighlighter>
+#include <KSyntaxHighlighting/Definition>
namespace TextEditor {
class TextDocument;
diff --git a/src/plugins/texteditor/highlightersettings.cpp b/src/plugins/texteditor/highlightersettings.cpp
index 75875249b7a..d4755948084 100644
--- a/src/plugins/texteditor/highlightersettings.cpp
+++ b/src/plugins/texteditor/highlightersettings.cpp
@@ -70,8 +70,8 @@ FilePath findFallbackDefinitionsLocation()
process.setTimeoutS(5);
process.setCommand({program, {"--prefix"}});
process.runBlocking();
- if (process.result() == QtcProcess::FinishedWithSuccess) {
- QString output = process.stdOut();
+ if (process.result() == ProcessResult::FinishedWithSuccess) {
+ QString output = process.cleanedStdOut();
output.remove('\n');
const FilePath dir = FilePath::fromString(output);
for (auto &kateSyntaxPath : kateSyntaxPaths) {
diff --git a/src/plugins/texteditor/highlightersettingspage.cpp b/src/plugins/texteditor/highlightersettingspage.cpp
index d169d498475..c571308c83f 100644
--- a/src/plugins/texteditor/highlightersettingspage.cpp
+++ b/src/plugins/texteditor/highlightersettingspage.cpp
@@ -29,6 +29,7 @@
#include "ui_highlightersettingspage.h"
#include <coreplugin/icore.h>
+#include <utils/hostosinfo.h>
#include <QDir>
#include <QMessageBox>
diff --git a/src/plugins/texteditor/icodestylepreferencesfactory.h b/src/plugins/texteditor/icodestylepreferencesfactory.h
index 123c88b8739..c3d18b5514a 100644
--- a/src/plugins/texteditor/icodestylepreferencesfactory.h
+++ b/src/plugins/texteditor/icodestylepreferencesfactory.h
@@ -64,9 +64,9 @@ public:
virtual Utils::Id languageId() = 0;
virtual QString displayName() = 0;
virtual ICodeStylePreferences *createCodeStyle() const = 0;
- virtual QWidget *createEditor(ICodeStylePreferences *preferences,
- ProjectExplorer::Project *project = nullptr,
- QWidget *parent = nullptr) const = 0;
+ virtual CodeStyleEditorWidget *createEditor(ICodeStylePreferences *preferences,
+ ProjectExplorer::Project *project = nullptr,
+ QWidget *parent = nullptr) const = 0;
virtual TextEditor::Indenter *createIndenter(QTextDocument *doc) const = 0;
virtual QString snippetProviderGroupId() const = 0;
virtual QString previewText() const = 0;
diff --git a/src/plugins/texteditor/outlinefactory.cpp b/src/plugins/texteditor/outlinefactory.cpp
index 6590ccdce1f..2b04c20c10f 100644
--- a/src/plugins/texteditor/outlinefactory.cpp
+++ b/src/plugins/texteditor/outlinefactory.cpp
@@ -129,7 +129,8 @@ void OutlineWidgetStack::restoreSettings(QSettings *settings, int position)
bool syncWithEditor = true;
m_widgetSettings.clear();
- foreach (const QString &longKey, settings->allKeys()) {
+ const QStringList longKeys = settings->allKeys();
+ for (const QString &longKey : longKeys) {
if (!longKey.startsWith(baseKey))
continue;
@@ -169,10 +170,10 @@ void OutlineWidgetStack::toggleSort()
void OutlineWidgetStack::updateFilterMenu()
{
m_filterMenu->clear();
- if (auto outlineWidget = qobject_cast<IOutlineWidget*>(currentWidget())) {
- foreach (QAction *filterAction, outlineWidget->filterMenuActions()) {
+ if (auto outlineWidget = qobject_cast<IOutlineWidget *>(currentWidget())) {
+ const QList<QAction *> filterActions = outlineWidget->filterMenuActions();
+ for (QAction *filterAction : filterActions)
m_filterMenu->addAction(filterAction);
- }
}
m_filterButton->setVisible(!m_filterMenu->actions().isEmpty());
}
diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp
index 506290732f7..77f168661f1 100644
--- a/src/plugins/texteditor/refactoringchanges.cpp
+++ b/src/plugins/texteditor/refactoringchanges.cpp
@@ -48,12 +48,8 @@ using namespace Utils;
namespace TextEditor {
-RefactoringChanges::RefactoringChanges()
- : m_data(new RefactoringChangesData)
-{}
-
RefactoringChanges::RefactoringChanges(RefactoringChangesData *data)
- : m_data(data)
+ : m_data(data ? data : new RefactoringChangesData)
{}
RefactoringChanges::~RefactoringChanges() = default;
@@ -63,7 +59,7 @@ RefactoringSelections RefactoringChanges::rangesToSelections(QTextDocument *docu
{
RefactoringSelections selections;
- foreach (const Range &range, ranges) {
+ for (const Range &range : ranges) {
QTextCursor start(document);
start.setPosition(range.start);
start.setKeepPositionOnInsert(true);
diff --git a/src/plugins/texteditor/refactoringchanges.h b/src/plugins/texteditor/refactoringchanges.h
index bce0e5d745f..714bdfd6835 100644
--- a/src/plugins/texteditor/refactoringchanges.h
+++ b/src/plugins/texteditor/refactoringchanges.h
@@ -122,7 +122,7 @@ class TEXTEDITOR_EXPORT RefactoringChanges
public:
using Range = Utils::ChangeSet::Range;
- RefactoringChanges();
+ explicit RefactoringChanges(RefactoringChangesData *data = nullptr);
virtual ~RefactoringChanges();
static RefactoringFilePtr file(TextEditorWidget *editor);
@@ -134,8 +134,6 @@ public:
bool removeFile(const Utils::FilePath &filePath) const;
protected:
- explicit RefactoringChanges(RefactoringChangesData *data);
-
static TextEditorWidget *openEditor(const Utils::FilePath &filePath,
bool activate,
int line,
diff --git a/src/plugins/texteditor/snippets/snippet.cpp b/src/plugins/texteditor/snippets/snippet.cpp
index 45b93f5c514..885b0080267 100644
--- a/src/plugins/texteditor/snippets/snippet.cpp
+++ b/src/plugins/texteditor/snippets/snippet.cpp
@@ -26,6 +26,7 @@
#include "snippet.h"
#include <utils/algorithm.h>
+#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
#include <utils/templateengine.h>
diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp
index a51138d0cdc..b9ef8ab22e3 100644
--- a/src/plugins/texteditor/tabsettings.cpp
+++ b/src/plugins/texteditor/tabsettings.cpp
@@ -273,7 +273,7 @@ bool TabSettings::guessSpacesForTabs(const QTextBlock &_block) const
if (currentBlocks.at(1).isValid())
currentBlocks[1] = currentBlocks.at(1).next();
bool done = true;
- foreach (const QTextBlock &block, currentBlocks) {
+ for (const QTextBlock &block : qAsConst(currentBlocks)) {
if (block.isValid())
done = false;
if (!block.isValid() || block.length() == 0)
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index 7e0adaacbf9..8c560c14959 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -27,21 +27,21 @@
#include "extraencodingsettings.h"
#include "fontsettings.h"
-#include "textindenter.h"
#include "storagesettings.h"
#include "syntaxhighlighter.h"
#include "tabsettings.h"
#include "textdocumentlayout.h"
#include "texteditor.h"
#include "texteditorconstants.h"
+#include "textindenter.h"
#include "typingsettings.h"
#include <coreplugin/diffservice.h>
-#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/documentmodel.h>
+#include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/pluginmanager.h>
-#include <utils/textutils.h>
#include <utils/guard.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
+#include <utils/textutils.h>
#include <QAction>
#include <QApplication>
@@ -260,7 +260,8 @@ TextDocument::~TextDocument()
QMap<QString, QString> TextDocument::openedTextDocumentContents()
{
QMap<QString, QString> workingCopy;
- foreach (IDocument *document, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents) {
auto textEditorDocument = qobject_cast<TextDocument *>(document);
if (!textEditorDocument)
continue;
@@ -273,7 +274,8 @@ QMap<QString, QString> TextDocument::openedTextDocumentContents()
QMap<QString, QTextCodec *> TextDocument::openedTextDocumentEncodings()
{
QMap<QString, QTextCodec *> workingCopy;
- foreach (IDocument *document, DocumentModel::openedDocuments()) {
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents) {
auto textEditorDocument = qobject_cast<TextDocument *>(document);
if (!textEditorDocument)
continue;
@@ -912,7 +914,7 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool inEntireDocument,
const IndentationForBlock &indentations
= d->m_indenter->indentationForBlocks(blocks, currentTabSettings);
- foreach (block, blocks) {
+ for (QTextBlock block : qAsConst(blocks)) {
QString blockText = block.text();
if (removeTrailingWhitespace)
@@ -968,6 +970,13 @@ void TextDocument::updateLayout() const
documentLayout->requestUpdate();
}
+void TextDocument::scheduleUpdateLayout() const
+{
+ auto documentLayout = qobject_cast<TextDocumentLayout*>(d->m_document.documentLayout());
+ QTC_ASSERT(documentLayout, return);
+ documentLayout->scheduleUpdate();
+}
+
TextMarks TextDocument::marks() const
{
return d->m_marksCache;
@@ -999,7 +1008,7 @@ bool TextDocument::addMark(TextMark *mark)
documentLayout->hasMarks = true;
documentLayout->maxMarkWidthFactor = newMaxWidthFactor;
if (fullUpdate)
- documentLayout->requestUpdate();
+ documentLayout->scheduleUpdate();
else
documentLayout->requestExtraAreaUpdate();
return true;
@@ -1050,7 +1059,7 @@ void TextDocument::removeMarkFromMarksCache(TextMark *mark)
documentLayout->requestExtraAreaUpdate();
} else {
double maxWidthFactor = 1.0;
- foreach (const TextMark *mark, marks()) {
+ for (const TextMark *mark : qAsConst(d->m_marksCache)) {
if (!mark->isVisible())
continue;
maxWidthFactor = qMax(mark->widthFactor(), maxWidthFactor);
@@ -1078,7 +1087,7 @@ void TextDocument::removeMark(TextMark *mark)
removeMarkFromMarksCache(mark);
emit markRemoved(mark);
mark->setBaseTextDocument(nullptr);
- updateLayout();
+ scheduleUpdateLayout();
}
void TextDocument::updateMark(TextMark *mark)
@@ -1090,7 +1099,7 @@ void TextDocument::updateMark(TextMark *mark)
userData->removeMark(mark);
userData->addMark(mark);
}
- updateLayout();
+ scheduleUpdateLayout();
}
void TextDocument::moveMark(TextMark *mark, int previousLine)
diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h
index 58e5ea972c7..b11d1a3a588 100644
--- a/src/plugins/texteditor/textdocument.h
+++ b/src/plugins/texteditor/textdocument.h
@@ -111,6 +111,8 @@ public:
bool addMark(TextMark *mark);
TextMarks marksAt(int line) const;
void removeMark(TextMark *mark);
+ void updateLayout() const;
+ void scheduleUpdateLayout() const;
void updateMark(TextMark *mark);
void moveMark(TextMark *mark, int previousLine);
void removeMarkFromMarksCache(TextMark *mark);
@@ -187,7 +189,6 @@ private:
void cleanWhitespace(QTextCursor &cursor, bool inEntireDocument, bool cleanIndentation);
void ensureFinalNewLine(QTextCursor &cursor);
void modificationChanged(bool modified);
- void updateLayout() const;
TextDocumentPrivate *d;
};
diff --git a/src/plugins/texteditor/textdocumentlayout.cpp b/src/plugins/texteditor/textdocumentlayout.cpp
index 64a7375f369..beabf503dfd 100644
--- a/src/plugins/texteditor/textdocumentlayout.cpp
+++ b/src/plugins/texteditor/textdocumentlayout.cpp
@@ -638,6 +638,20 @@ void TextDocumentLayout::updateMarksBlock(const QTextBlock &block)
}
}
+void TextDocumentLayout::scheduleUpdate()
+{
+ if (m_updateScheduled)
+ return;
+ m_updateScheduled = true;
+ QMetaObject::invokeMethod(this, &TextDocumentLayout::requestUpdateNow, Qt::QueuedConnection);
+}
+
+void TextDocumentLayout::requestUpdateNow()
+{
+ m_updateScheduled = false;
+ requestUpdate();
+}
+
QRectF TextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
{
QRectF boundingRect = QPlainTextDocumentLayout::blockBoundingRect(block);
diff --git a/src/plugins/texteditor/textdocumentlayout.h b/src/plugins/texteditor/textdocumentlayout.h
index 69034bf7656..1b0bb8b5e18 100644
--- a/src/plugins/texteditor/textdocumentlayout.h
+++ b/src/plugins/texteditor/textdocumentlayout.h
@@ -32,7 +32,7 @@
#include <utils/id.h>
-#include <State>
+#include <KSyntaxHighlighting/State>
#include <QTextBlockUserData>
#include <QPlainTextDocumentLayout>
@@ -237,6 +237,11 @@ public:
void documentReloaded(TextMarks marks, TextDocument *baseextDocument);
void updateMarksLineNumber();
void updateMarksBlock(const QTextBlock &block);
+ void scheduleUpdate();
+ void requestUpdateNow();
+
+private:
+ bool m_updateScheduled = false;
signals:
void updateExtraArea();
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 74cfe43cfce..b5f5a6e4cb9 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -79,7 +79,8 @@
#include <utils/fixedsizeclicklabel.h>
#include <utils/hostosinfo.h>
#include <utils/infobar.h>
-#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimeutils.h>
+#include <utils/minimizableinfobars.h>
#include <utils/multitextcursor.h>
#include <utils/qtcassert.h>
#include <utils/styledbar.h>
@@ -150,7 +151,6 @@
implementation matches the MIME type.
*/
-
using namespace Core;
using namespace Utils;
@@ -387,7 +387,6 @@ public:
restart();
}
-private:
void abortHandlers()
{
for (BaseHoverHandler *handler : m_handlers)
@@ -395,6 +394,7 @@ private:
m_currentHandlerIndex = -1;
}
+private:
void restart()
{
abortHandlers();
@@ -529,6 +529,7 @@ public:
void handleBackspaceKey();
void moveLineUpDown(bool up);
void copyLineUpDown(bool up);
+ void addSelectionNextFindMatch();
void saveCurrentCursorPositionForNavigation();
void updateHighlights();
void updateCurrentLineInScrollbar();
@@ -623,7 +624,7 @@ public:
int start;
int length;
};
- void addSearchResultsToScrollBar(QVector<SearchResult> results);
+ void addSearchResultsToScrollBar(const QVector<SearchResult> &results);
void adjustScrollBarRanges();
void setFindScope(const MultiTextCursor &scope);
@@ -639,10 +640,14 @@ public:
void slotSelectionChanged();
void _q_animateUpdate(const QTextCursor &cursor, QPointF lastPos, QRectF rect);
void updateCodeFoldingVisible();
+ void updateFileLineEndingVisible();
void reconfigure();
void updateSyntaxInfoBar(const Highlighter::Definitions &definitions, const QString &fileName);
+ void removeSyntaxInfoBar();
void configureGenericHighlighter(const KSyntaxHighlighting::Definition &definition);
+ void setupFromDefinition(const KSyntaxHighlighting::Definition &definition);
+ KSyntaxHighlighting::Definition currentDefinition();
void rememberCurrentSyntaxDefinition();
void openLinkUnderCursor(bool openInNextSplit);
@@ -950,10 +955,9 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
m_fileLineEnding->addItems(ExtraEncodingSettings::lineTerminationModeNames());
m_fileLineEnding->setContentsMargins(spacing, 0, spacing, 0);
m_fileLineEndingAction = m_toolBar->addWidget(m_fileLineEnding);
- m_fileLineEndingAction->setVisible(!q->isReadOnly());
- connect(q, &TextEditorWidget::readOnlyChanged, this, [this] {
- m_fileLineEndingAction->setVisible(!q->isReadOnly());
- });
+ updateFileLineEndingVisible();
+ connect(q, &TextEditorWidget::readOnlyChanged,
+ this, &TextEditorWidgetPrivate::updateFileLineEndingVisible);
m_fileEncodingLabel = new FixedSizeClickLabel;
m_fileEncodingLabel->setContentsMargins(spacing, 0, spacing, 0);
@@ -1214,7 +1218,7 @@ void TextEditorWidgetPrivate::ctor(const QSharedPointer<TextDocument> &doc)
connect(m_document->document(), &QTextDocument::modificationChanged,
q, &TextEditorWidget::updateTextLineEndingLabel);
q->updateTextLineEndingLabel();
-
+ setupFromDefinition(currentDefinition());
}
TextEditorWidget::~TextEditorWidget()
@@ -2226,7 +2230,8 @@ void TextEditorWidgetPrivate::moveLineUpDown(bool up)
RefactorMarkers nonAffectedMarkers;
QList<int> markerOffsets;
- foreach (const RefactorMarker &marker, m_refactorOverlay->markers()) {
+ const QList<RefactorMarker> markers = m_refactorOverlay->markers();
+ for (const RefactorMarker &marker : markers) {
//test if marker is part of the selection to be moved
if ((move.selectionStart() <= marker.cursor.position())
&& (move.selectionEnd() >= marker.cursor.position())) {
@@ -2671,7 +2676,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
QChar electricChar;
if (d->m_document->typingSettings().m_autoIndent) {
- foreach (QChar c, eventText) {
+ for (const QChar c : eventText) {
if (d->m_document->indenter()->isElectricCharacter(c)) {
electricChar = c;
break;
@@ -3097,7 +3102,7 @@ void TextEditorWidget::restoreState(const QByteArray &state)
stream >> collapsedBlocks;
QTextDocument *doc = document();
bool layoutChanged = false;
- foreach (int blockNumber, collapsedBlocks) {
+ for (const int blockNumber : qAsConst(collapsedBlocks)) {
QTextBlock block = doc->findBlockByNumber(qMax(0, blockNumber));
if (block.isValid()) {
TextDocumentLayout::doFoldOrUnfold(block, false);
@@ -3222,6 +3227,11 @@ void TextEditorWidgetPrivate::updateCodeFoldingVisible()
}
}
+void TextEditorWidgetPrivate::updateFileLineEndingVisible()
+{
+ m_fileLineEndingAction->setVisible(m_displaySettings.m_displayFileLineEnding && !q->isReadOnly());
+}
+
void TextEditorWidgetPrivate::reconfigure()
{
m_document->setMimeType(Utils::mimeTypeForFile(m_document->filePath()).name());
@@ -3253,8 +3263,8 @@ void TextEditorWidgetPrivate::updateSyntaxInfoBar(const Highlighter::Definitions
BaseTextEditor::tr("More than one highlight definition was found for this file. "
"Which one should be used to highlight this file?"));
info.setComboInfo(Utils::transform(definitions, &Highlighter::Definition::name),
- [this](const QString &definition) {
- this->configureGenericHighlighter(Highlighter::definitionForName(definition));
+ [this](const InfoBarEntry::ComboInfo &info) {
+ this->configureGenericHighlighter(Highlighter::definitionForName(info.displayText));
});
info.addCustomButton(BaseTextEditor::tr("Remember My Choice"), [multiple, this]() {
@@ -3270,6 +3280,13 @@ void TextEditorWidgetPrivate::updateSyntaxInfoBar(const Highlighter::Definitions
}
}
+void TextEditorWidgetPrivate::removeSyntaxInfoBar()
+{
+ InfoBar *infoBar = m_document->infoBar();
+ infoBar->removeInfo(Constants::INFO_MISSING_SYNTAX_DEFINITION);
+ infoBar->removeInfo(Constants::INFO_MULTIPLE_SYNTAX_DEFINITIONS);
+}
+
void TextEditorWidgetPrivate::configureGenericHighlighter(
const KSyntaxHighlighting::Definition &definition)
{
@@ -3278,10 +3295,7 @@ void TextEditorWidgetPrivate::configureGenericHighlighter(
if (definition.isValid()) {
highlighter->setDefinition(definition);
- m_commentDefinition.singleLine = definition.singleLineCommentMarker();
- m_commentDefinition.multiLineStart = definition.multiLineCommentMarker().first;
- m_commentDefinition.multiLineEnd = definition.multiLineCommentMarker().second;
- q->setCodeFoldingSupported(true);
+ setupFromDefinition(definition);
} else {
q->setCodeFoldingSupported(false);
}
@@ -3289,12 +3303,26 @@ void TextEditorWidgetPrivate::configureGenericHighlighter(
m_document->setFontSettings(TextEditorSettings::fontSettings());
}
-void TextEditorWidgetPrivate::rememberCurrentSyntaxDefinition()
+void TextEditorWidgetPrivate::setupFromDefinition(const KSyntaxHighlighting::Definition &definition)
{
- auto highlighter = qobject_cast<Highlighter *>(m_document->syntaxHighlighter());
- if (!highlighter)
+ if (!definition.isValid())
return;
- const Highlighter::Definition &definition = highlighter->definition();
+ m_commentDefinition.singleLine = definition.singleLineCommentMarker();
+ m_commentDefinition.multiLineStart = definition.multiLineCommentMarker().first;
+ m_commentDefinition.multiLineEnd = definition.multiLineCommentMarker().second;
+ q->setCodeFoldingSupported(true);
+}
+
+KSyntaxHighlighting::Definition TextEditorWidgetPrivate::currentDefinition()
+{
+ if (auto highlighter = qobject_cast<Highlighter *>(m_document->syntaxHighlighter()))
+ return highlighter->definition();
+ return {};
+}
+
+void TextEditorWidgetPrivate::rememberCurrentSyntaxDefinition()
+{
+ const Highlighter::Definition &definition = currentDefinition();
if (definition.isValid())
Highlighter::rememberDefinitionForDocument(definition, m_document.data());
}
@@ -3347,7 +3375,7 @@ void TextEditorWidget::setMouseHidingEnabled(bool b)
bool TextEditorWidget::mouseHidingEnabled() const
{
- return d->m_behaviorSettings.m_mouseHiding;
+ return Utils::HostOsInfo::isMacHost() ? false : d->m_behaviorSettings.m_mouseHiding;
}
void TextEditorWidget::setScrollWheelZoomingEnabled(bool b)
@@ -3962,7 +3990,7 @@ void TextEditorWidgetPrivate::updateLineAnnotation(const PaintEventData &data,
return;
TextMarks marks = Utils::filtered(blockUserData->marks(), [](const TextMark* mark){
- return !mark->lineAnnotation().isEmpty();
+ return !mark->lineAnnotation().isEmpty() && mark->isVisible();
});
const bool annotationsVisible = !marks.isEmpty();
@@ -4007,24 +4035,21 @@ void TextEditorWidgetPrivate::updateLineAnnotation(const PaintEventData &data,
}
for (const TextMark *mark : qAsConst(marks)) {
- if (!mark->isVisible())
- continue;
boundingRect = QRectF(x, boundingRect.top(), q->viewport()->width() - x, boundingRect.height());
if (boundingRect.isEmpty())
break;
- if (data.eventRect.intersects(boundingRect.toRect()))
- mark->paintAnnotation(painter, &boundingRect, offset, itemOffset / 2, q->contentOffset());
+
+ mark->paintAnnotation(painter,
+ data.eventRect,
+ &boundingRect,
+ offset,
+ itemOffset / 2,
+ q->contentOffset());
x = boundingRect.right();
offset = itemOffset / 2;
m_annotationRects[data.block.blockNumber()].append({boundingRect, mark});
}
-
- QRect updateRect(lineRect.toRect().topRight(), boundingRect.toRect().bottomRight());
- updateRect.setLeft(qBound(0, updateRect.left(), q->viewport()->width() - 1));
- updateRect.setRight(qBound(0, updateRect.right(), q->viewport()->width() - 1));
- if (!updateRect.isEmpty() && !data.eventRect.contains(q->viewport()->rect() & updateRect))
- q->viewport()->update(updateRect);
}
QColor blendRightMarginColor(const FontSettings &settings, bool areaColor)
@@ -4098,10 +4123,12 @@ void TextEditorWidgetPrivate::paintBlockHighlight(const PaintEventData &data,
int n = block.blockNumber();
int depth = 0;
- foreach (int i, m_highlightBlocksInfo.open)
+ const QList<int> open = m_highlightBlocksInfo.open;
+ for (const int i : open)
if (n >= i)
++depth;
- foreach (int i, m_highlightBlocksInfo.close)
+ const QList<int> close = m_highlightBlocksInfo.close;
+ for (const int i : close)
if (n > i)
--depth;
@@ -4237,9 +4264,6 @@ void TextEditorWidgetPrivate::paintCurrentLineHighlight(const PaintEventData &da
lineRect.moveTop(lineRect.top() + blockRect.top());
lineRect.setLeft(0);
lineRect.setRight(data.viewportRect.width());
- // set alpha, otherwise we cannot see block highlighting and find scope underneath
- if (!data.eventRect.contains(lineRect.toAlignedRect()))
- q->viewport()->update(lineRect.toAlignedRect());
painter.fillRect(lineRect, color);
}
}
@@ -4624,8 +4648,8 @@ void TextEditorWidget::paintEvent(QPaintEvent *e)
d->paintAdditionalVisualWhitespaces(data, painter, blockData.boundingRect.top());
d->paintReplacement(data, painter, blockData.boundingRect.top());
+ d->updateLineAnnotation(data, blockData, painter);
}
- d->updateLineAnnotation(data, blockData, painter);
data.offset.ry() += blockData.boundingRect.height();
@@ -5104,25 +5128,28 @@ void TextEditorWidgetPrivate::updateCurrentLineHighlight()
// the extra area shows information for the entire current block, not just the currentline.
// This is why we must force a bigger update region.
- QList<int> cursorBlockNumbers;
const QPointF offset = q->contentOffset();
+ auto updateBlock = [&](const QTextBlock &block) {
+ if (block.isValid() && block.isVisible()) {
+ QRect updateRect = q->blockBoundingGeometry(block).translated(offset).toAlignedRect();
+ m_extraArea->update(updateRect);
+ updateRect.setLeft(0);
+ updateRect.setRight(q->viewport()->width());
+ q->viewport()->update(updateRect);
+ }
+ };
+ QList<int> cursorBlockNumbers;
for (const QTextCursor &c : m_cursors) {
int cursorBlockNumber = c.blockNumber();
- if (!m_cursorBlockNumbers.contains(cursorBlockNumber)) {
- QTextBlock block = c.block();
- if (block.isValid() && block.isVisible())
- m_extraArea->update(q->blockBoundingGeometry(block).translated(offset).toAlignedRect());
- }
+ if (!m_cursorBlockNumbers.contains(cursorBlockNumber))
+ updateBlock(c.block());
if (!cursorBlockNumbers.contains(c.blockNumber()))
cursorBlockNumbers << c.blockNumber();
}
if (m_cursorBlockNumbers != cursorBlockNumbers) {
for (int oldBlock : m_cursorBlockNumbers) {
- if (cursorBlockNumbers.contains(oldBlock))
- continue;
- QTextBlock block = m_document->document()->findBlockByNumber(oldBlock);
- if (block.isValid() && block.isVisible())
- m_extraArea->update(q->blockBoundingGeometry(block).translated(offset).toAlignedRect());
+ if (!cursorBlockNumbers.contains(oldBlock))
+ updateBlock(m_document->document()->findBlockByNumber(oldBlock));
}
m_cursorBlockNumbers = cursorBlockNumbers;
}
@@ -5339,7 +5366,7 @@ void TextEditorWidget::mouseMoveEvent(QMouseEvent *e)
anchorCursor.blockNumber(),
anchorColumn};
- cursor.setCursors(d->generateCursorsForBlockSelection(blockSelection));
+ cursor.addCursors(d->generateCursorsForBlockSelection(blockSelection));
if (!cursor.isNull())
setMultiTextCursor(cursor);
} else {
@@ -5487,7 +5514,30 @@ void TextEditorWidget::mouseDoubleClickEvent(QMouseEvent *e)
}
}
+ QTextCursor oldCursor = multiTextCursor().mainCursor();
+ const int oldPosition = oldCursor.position();
+
QPlainTextEdit::mouseDoubleClickEvent(e);
+
+ // QPlainTextEdit::mouseDoubleClickEvent just selects the word under the text cursor. If the
+ // event is triggered on a position that is inbetween two whitespaces this event selects the
+ // previous word or nothing if the whitespaces are at the block start. Replace this behavior
+ // with selecting the whitespaces starting from the previous word end to the next word.
+ const QChar character = characterAt(oldPosition);
+ const QChar prevCharacter = characterAt(oldPosition - 1);
+
+ if (character.isSpace() && prevCharacter.isSpace()) {
+ if (prevCharacter != QChar::ParagraphSeparator) {
+ oldCursor.movePosition(QTextCursor::PreviousWord);
+ oldCursor.movePosition(QTextCursor::EndOfWord);
+ } else if (character == QChar::ParagraphSeparator) {
+ return; // no special handling for empty lines
+ }
+ oldCursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);
+ MultiTextCursor cursor = multiTextCursor();
+ cursor.replaceMainCursor(oldCursor);
+ setMultiTextCursor(cursor);
+ }
}
void TextEditorWidgetPrivate::setClipboardSelection()
@@ -5537,7 +5587,8 @@ static void appendMenuActionsFromContext(QMenu *menu, Id menuContextId)
ActionContainer *mcontext = ActionManager::actionContainer(menuContextId);
QMenu *contextMenu = mcontext->menu();
- foreach (QAction *action, contextMenu->actions())
+ const QList<QAction *> actions = contextMenu->actions();
+ for (QAction *action : actions)
menu->addAction(action);
}
@@ -6047,7 +6098,7 @@ void TextEditorWidget::zoomReset()
}
void TextEditorWidget::findLinkAt(const QTextCursor &cursor,
- Utils::ProcessLinkCallback &&callback,
+ const Utils::LinkHandler &callback,
bool resolveTarget,
bool inNextSplit)
{
@@ -6183,7 +6234,8 @@ void TextEditorWidgetPrivate::searchResultsReady(int beginIndex, int endIndex)
{
QVector<SearchResult> results;
for (int index = beginIndex; index < endIndex; ++index) {
- foreach (Utils::FileSearchResult result, m_searchWatcher->resultAt(index)) {
+ const QList<Utils::FileSearchResult> resultList = m_searchWatcher->resultAt(index);
+ for (Utils::FileSearchResult result : resultList) {
const QTextBlock &block = q->document()->findBlockByNumber(result.lineNumber - 1);
const int matchStart = block.position() + result.matchStart;
QTextCursor cursor(block);
@@ -6282,11 +6334,11 @@ Highlight::Priority textMarkPrioToScrollBarPrio(const TextMark::Priority &prio)
}
}
-void TextEditorWidgetPrivate::addSearchResultsToScrollBar(QVector<SearchResult> results)
+void TextEditorWidgetPrivate::addSearchResultsToScrollBar(const QVector<SearchResult> &results)
{
if (!m_highlightScrollBarController)
return;
- foreach (SearchResult result, results) {
+ for (SearchResult result : results) {
const QTextBlock &block = q->document()->findBlock(result.start);
if (block.isValid() && block.isVisible()) {
const int firstLine = block.layout()->lineForTextPosition(result.start - block.position()).lineNumber();
@@ -6528,7 +6580,9 @@ void TextEditorWidgetPrivate::_q_matchParentheses()
if (animatePosition >= 0) {
- foreach (const QTextEdit::ExtraSelection &sel, q->extraSelections(TextEditorWidget::ParenthesesMatchingSelection)) {
+ const QList<QTextEdit::ExtraSelection> selections = q->extraSelections(
+ TextEditorWidget::ParenthesesMatchingSelection);
+ for (const QTextEdit::ExtraSelection &sel : selections) {
if (sel.cursor.selectionStart() == animatePosition
|| sel.cursor.selectionEnd() - 1 == animatePosition) {
animatePosition = -1;
@@ -6680,6 +6734,7 @@ void TextEditorWidget::focusInEvent(QFocusEvent *e)
void TextEditorWidget::focusOutEvent(QFocusEvent *e)
{
QPlainTextEdit::focusOutEvent(e);
+ d->m_hoverHandlerRunner.abortHandlers();
if (viewport()->cursor().shape() == Qt::BlankCursor)
viewport()->setCursor(Qt::IBeamCursor);
d->m_cursorFlashTimer.stop();
@@ -6724,6 +6779,42 @@ void TextEditorWidget::copyLine()
copy();
}
+void TextEditorWidgetPrivate::addSelectionNextFindMatch()
+{
+ MultiTextCursor cursor = q->multiTextCursor();
+ const QList<QTextCursor> cursors = cursor.cursors();
+
+ if (cursor.cursorCount() == 0 || !cursors.first().hasSelection())
+ return;
+
+ const QTextCursor &firstCursor = cursors.first();
+ QTextDocumentFragment selection = firstCursor.selection();
+ QTextDocument *document = firstCursor.document();
+
+ if (Utils::anyOf(cursors, [&firstCursor](const QTextCursor &c) {
+ return c.selection().toPlainText().toCaseFolded()
+ != firstCursor.selection().toPlainText().toCaseFolded();
+ })) {
+ return;
+ }
+
+ const QTextDocument::FindFlags findFlags = textDocumentFlagsForFindFlags(m_findFlags);
+
+ int searchFrom = cursors.last().selectionEnd();
+ while (true) {
+ QTextCursor next = document->find(selection.toPlainText(), searchFrom, findFlags);
+ if (next.isNull()) {
+ searchFrom = 0;
+ continue;
+ }
+ if (next.selectionStart() == firstCursor.selectionStart())
+ break;
+ cursor.addCursor(next);
+ q->setMultiTextCursor(cursor);
+ break;
+ }
+}
+
void TextEditorWidgetPrivate::duplicateSelection(bool comment)
{
if (comment && !m_commentDefinition.hasMultiLineStyle())
@@ -6768,6 +6859,11 @@ void TextEditorWidget::duplicateSelection()
d->duplicateSelection(false);
}
+void TextEditorWidget::addSelectionNextFindMatch()
+{
+ d->addSelectionNextFindMatch();
+}
+
void TextEditorWidget::duplicateSelectionAndComment()
{
d->duplicateSelection(true);
@@ -6835,7 +6931,7 @@ void TextEditorWidgetPrivate::setExtraSelections(Id kind, const QList<QTextEdit:
if (kind == TextEditorWidget::CodeSemanticsSelection) {
m_overlay->clear();
- foreach (const QTextEdit::ExtraSelection &selection, m_extraSelections[kind]) {
+ for (const QTextEdit::ExtraSelection &selection : selections) {
m_overlay->addOverlaySelection(selection.cursor,
selection.format.background().color(),
selection.format.background().color(),
@@ -6866,7 +6962,7 @@ QList<QTextEdit::ExtraSelection> TextEditorWidget::extraSelections(Id kind) cons
QString TextEditorWidget::extraSelectionTooltip(int pos) const
{
- foreach (const QList<QTextEdit::ExtraSelection> &sel, d->m_extraSelections) {
+ for (const QList<QTextEdit::ExtraSelection> &sel : qAsConst(d->m_extraSelections)) {
for (const QTextEdit::ExtraSelection &s : sel) {
if (s.cursor.selectionStart() <= pos
&& s.cursor.selectionEnd() >= pos
@@ -6897,7 +6993,7 @@ void TextEditorWidget::rewrapParagraph()
{
const int paragraphWidth = marginSettings().m_marginColumn;
const QRegularExpression anyLettersOrNumbers("\\w");
- const int tabSize = d->m_document->tabSettings().m_tabSize;
+ const TabSettings ts = d->m_document->tabSettings();
QTextCursor cursor = textCursor();
cursor.beginEditBlock();
@@ -6918,18 +7014,8 @@ void TextEditorWidget::rewrapParagraph()
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
// Find indent level of current block.
-
- int indentLevel = 0;
const QString text = cursor.block().text();
-
- for (const QChar &ch : text) {
- if (ch == QLatin1Char(' '))
- indentLevel++;
- else if (ch == QLatin1Char('\t'))
- indentLevel += tabSize - (indentLevel % tabSize);
- else
- break;
- }
+ int indentLevel = ts.indentationColumn(text);
// If there is a common prefix, it should be kept and expanded to all lines.
// this allows nice reflowing of doxygen style comments.
@@ -6966,11 +7052,10 @@ void TextEditorWidget::rewrapParagraph()
QString spacing;
if (commonPrefix.isEmpty()) {
- spacing = d->m_document->tabSettings().indentationString(
- 0, indentLevel, 0, textCursor().block());
+ spacing = ts.indentationString(0, indentLevel, 0, textCursor().block());
} else {
spacing = commonPrefix;
- indentLevel = commonPrefix.length();
+ indentLevel = ts.columnCountForText(spacing);
}
int currentLength = indentLevel;
@@ -7144,6 +7229,7 @@ void TextEditorWidget::setDisplaySettings(const DisplaySettings &ds)
}
d->updateCodeFoldingVisible();
+ d->updateFileLineEndingVisible();
d->updateHighlights();
d->setupScrollBar();
viewport()->update();
@@ -7365,7 +7451,8 @@ QMimeData *TextEditorWidget::createMimeDataFromSelection() const
current = current.next()) {
if (selectionVisible(current.blockNumber())) {
const QTextLayout *layout = current.layout();
- foreach (const QTextLayout::FormatRange &range, layout->formats()) {
+ const QVector<QTextLayout::FormatRange> ranges = layout->formats();
+ for (const QTextLayout::FormatRange &range : ranges) {
const int startPosition = current.position() + range.start
- selectionStart - removedCount;
const int endPosition = startPosition + range.length;
@@ -7377,7 +7464,7 @@ QMimeData *TextEditorWidget::createMimeDataFromSelection() const
tempCursor.setCharFormat(range.format);
}
} else {
- const int startPosition = current.position() - start.position()
+ const int startPosition = current.position() - selectionStart
- removedCount;
int endPosition = startPosition + current.text().count();
if (current != last)
@@ -7905,10 +7992,11 @@ RefactorMarkers TextEditorWidget::refactorMarkers() const
void TextEditorWidget::setRefactorMarkers(const RefactorMarkers &markers)
{
- foreach (const RefactorMarker &marker, d->m_refactorOverlay->markers())
+ const QList<RefactorMarker> oldMarkers = d->m_refactorOverlay->markers();
+ for (const RefactorMarker &marker : oldMarkers)
emit requestBlockUpdate(marker.cursor.block());
d->m_refactorOverlay->setMarkers(markers);
- foreach (const RefactorMarker &marker, markers)
+ for (const RefactorMarker &marker : markers)
emit requestBlockUpdate(marker.cursor.block());
}
@@ -8100,10 +8188,10 @@ void TextEditorWidget::invokeAssist(AssistKind kind, IAssistProvider *provider)
}
AssistInterface *TextEditorWidget::createAssistInterface(AssistKind kind,
- AssistReason reason) const
+ AssistReason reason) const
{
Q_UNUSED(kind)
- return new AssistInterface(document(), position(), d->m_document->filePath(), reason);
+ return new AssistInterface(textCursor(), d->m_document->filePath(), reason);
}
QString TextEditorWidget::foldReplacementText(const QTextBlock &) const
@@ -8181,6 +8269,14 @@ void TextEditorWidget::configureGenericHighlighter()
d->updateSyntaxInfoBar(definitions, textDocument()->filePath().fileName());
}
+void TextEditorWidget::configureGenericHighlighter(const Utils::MimeType &mimeType)
+{
+ Highlighter::Definitions definitions = Highlighter::definitionsForMimeType(mimeType.name());
+ d->configureGenericHighlighter(definitions.isEmpty() ? Highlighter::Definition()
+ : definitions.first());
+ d->removeSyntaxInfoBar();
+}
+
int TextEditorWidget::blockNumberForVisibleRow(int row) const
{
QTextBlock block = blockForVisibleRow(row);
@@ -8458,6 +8554,12 @@ BaseTextEditor *TextEditorFactoryPrivate::createEditorHelper(const TextDocumentP
if (m_useGenericHighlighter)
textEditorWidget->setupGenericHighlighter();
textEditorWidget->finalizeInitialization();
+
+ // Toolbar: Actions to show minimized info bars
+ document->minimizableInfoBars()->createShowInfoBarActions([textEditorWidget](QWidget *w) {
+ return textEditorWidget->insertExtraToolBarWidget(TextEditorWidget::Left, w);
+ });
+
editor->finalizeInitialization();
return editor;
}
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index 7daed6de22c..b29b69b9ccf 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -384,6 +384,7 @@ public:
void updateTextCodecLabel();
void selectLineEnding(int index);
void updateTextLineEndingLabel();
+ void addSelectionNextFindMatch();
void gotoBlockStart();
void gotoBlockEnd();
@@ -457,7 +458,11 @@ public:
/// Abort code assistant if it is running.
void abortAssist();
+ /// Overwrite the current highlighter with a new generic highlighter based on the mimetype of
+ /// the current document
void configureGenericHighlighter();
+ /// Overwrite the current highlighter with a new generic highlighter based on the given mimetype
+ void configureGenericHighlighter(const Utils::MimeType &mimeType);
Q_INVOKABLE void inSnippetMode(bool *active); // Used by FakeVim.
@@ -491,7 +496,7 @@ signals:
void requestBlockUpdate(const QTextBlock &);
- void requestLinkAt(const QTextCursor &cursor, Utils::ProcessLinkCallback &callback,
+ void requestLinkAt(const QTextCursor &cursor, const Utils::LinkHandler &callback,
bool resolveTarget, bool inNextSplit);
void requestUsages(const QTextCursor &cursor);
void requestRename(const QTextCursor &cursor);
@@ -577,7 +582,7 @@ protected:
(it isn't until the link is used).
*/
virtual void findLinkAt(const QTextCursor &,
- Utils::ProcessLinkCallback &&processLinkCallback,
+ const Utils::LinkHandler &processLinkCallback,
bool resolveTarget = true,
bool inNextSplit = false);
diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs
index 896c9d515ef..b25d0ea222d 100644
--- a/src/plugins/texteditor/texteditor.qbs
+++ b/src/plugins/texteditor/texteditor.qbs
@@ -30,7 +30,6 @@ Project {
"behaviorsettings.h",
"behaviorsettingspage.cpp",
"behaviorsettingspage.h",
- "behaviorsettingspage.ui",
"behaviorsettingswidget.cpp",
"behaviorsettingswidget.h",
"behaviorsettingswidget.ui",
diff --git a/src/plugins/texteditor/texteditor_global.h b/src/plugins/texteditor/texteditor_global.h
index 08f7adc5eb2..88ac76b3978 100644
--- a/src/plugins/texteditor/texteditor_global.h
+++ b/src/plugins/texteditor/texteditor_global.h
@@ -29,6 +29,8 @@
#if defined(TEXTEDITOR_LIBRARY)
# define TEXTEDITOR_EXPORT Q_DECL_EXPORT
+#elif defined(TEXTEDITOR_STATIC_LIBRARY)
+# define TEXTEDITOR_EXPORT
#else
# define TEXTEDITOR_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp
index 98b66f10008..d0b0172629e 100644
--- a/src/plugins/texteditor/texteditoractionhandler.cpp
+++ b/src/plugins/texteditor/texteditoractionhandler.cpp
@@ -329,6 +329,10 @@ void TextEditorActionHandlerPrivate::createActions()
[] (TextEditorWidget *w) { w->copyLine(); }, false, tr("Copy &Line"),
QKeySequence(tr("Ctrl+Ins")),
G_EDIT_TEXT, advancedEditMenu);
+ registerAction(ADD_SELECT_NEXT_FIND_MATCH,
+ [] (TextEditorWidget *w) { w->addSelectionNextFindMatch(); }, false, tr("Add Next Occurrence to Selection"),
+ QKeySequence(tr("Ctrl+D")),
+ G_EDIT_TEXT, advancedEditMenu);
m_modifyingActions << registerAction(DUPLICATE_SELECTION,
[] (TextEditorWidget *w) { w->duplicateSelection(); }, false, tr("&Duplicate Selection"),
QKeySequence(),
@@ -453,7 +457,7 @@ void TextEditorActionHandlerPrivate::createActions()
void TextEditorActionHandlerPrivate::updateActions()
{
bool isWritable = m_currentEditorWidget && !m_currentEditorWidget->isReadOnly();
- foreach (QAction *a, m_modifyingActions)
+ for (QAction *a : qAsConst(m_modifyingActions))
a->setEnabled(isWritable);
m_unCommentSelectionAction->setEnabled((m_optionalActions & TextEditorActionHandler::UnCommentSelection) && isWritable);
m_visualizeWhitespaceAction->setEnabled(m_currentEditorWidget);
diff --git a/src/plugins/texteditor/texteditorconstants.cpp b/src/plugins/texteditor/texteditorconstants.cpp
index 01459630bb5..dedef17fdfe 100644
--- a/src/plugins/texteditor/texteditorconstants.cpp
+++ b/src/plugins/texteditor/texteditorconstants.cpp
@@ -41,6 +41,7 @@ const char *nameForStyle(TextStyle style)
case C_SEARCH_RESULT: return "SearchResult";
case C_SEARCH_RESULT_ALT1: return "SearchResultAlt1";
case C_SEARCH_RESULT_ALT2: return "SearchResultAlt2";
+ case C_SEARCH_RESULT_CONTAINING_FUNCTION: return "SearchResultContainingFunction";
case C_SEARCH_SCOPE: return "SearchScope";
case C_PARENTHESES: return "Parentheses";
case C_PARENTHESES_MISMATCH:return "ParenthesesMismatch";
@@ -70,6 +71,7 @@ const char *nameForStyle(TextStyle style)
case C_OVERLOADED_OPERATOR: return "Overloaded Operator";
case C_PUNCTUATION: return "Punctuation";
case C_PREPROCESSOR: return "Preprocessor";
+ case C_MACRO: return "Macro";
case C_LABEL: return "Label";
case C_COMMENT: return "Comment";
case C_DOXYGEN_COMMENT: return "Doxygen.Comment";
@@ -117,6 +119,18 @@ const char *nameForStyle(TextStyle style)
case C_OUTPUT_ARGUMENT: return "OutputArgument";
case C_STATIC_MEMBER: return "StaticMember";
+ case C_COCO_CODE_ADDED: return "CocoCodeAdded";
+ case C_COCO_PARTIALLY_COVERED: return "CocoPartiallyCovered";
+ case C_COCO_NOT_COVERED: return "CocoNotCovered";
+ case C_COCO_FULLY_COVERED: return "CocoFullyCovered";
+ case C_COCO_MANUALLY_VALIDATED: return "CocoManuallyValidated";
+ case C_COCO_DEAD_CODE: return "CocoDeadCode";
+ case C_COCO_EXECUTION_COUNT_TOO_LOW: return "CocoExecutionCountTooLow";
+ case C_COCO_NOT_COVERED_INFO: return "CocoNotCoveredInfo";
+ case C_COCO_COVERED_INFO: return "CocoCoveredInfo";
+ case C_COCO_MANUALLY_VALIDATED_INFO: return "CocoManuallyValidatedInfo";
+
+
case C_LAST_STYLE_SENTINEL: return "LastStyleSentinel";
}
return "Unknown Style";
diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h
index 060c521a400..68667f40adc 100644
--- a/src/plugins/texteditor/texteditorconstants.h
+++ b/src/plugins/texteditor/texteditorconstants.h
@@ -41,6 +41,7 @@ enum TextStyle : quint8 {
C_SEARCH_RESULT,
C_SEARCH_RESULT_ALT1,
C_SEARCH_RESULT_ALT2,
+ C_SEARCH_RESULT_CONTAINING_FUNCTION,
C_SEARCH_SCOPE,
C_PARENTHESES,
C_PARENTHESES_MISMATCH,
@@ -68,6 +69,7 @@ enum TextStyle : quint8 {
C_OVERLOADED_OPERATOR,
C_PUNCTUATION,
C_PREPROCESSOR,
+ C_MACRO,
C_LABEL,
C_COMMENT,
C_DOXYGEN_COMMENT,
@@ -85,7 +87,6 @@ enum TextStyle : quint8 {
C_QML_STATE_NAME,
C_BINDING,
-
C_DISABLED_CODE,
C_ADDED_LINE,
@@ -117,6 +118,17 @@ enum TextStyle : quint8 {
C_OUTPUT_ARGUMENT,
C_STATIC_MEMBER,
+ C_COCO_CODE_ADDED,
+ C_COCO_PARTIALLY_COVERED,
+ C_COCO_NOT_COVERED,
+ C_COCO_FULLY_COVERED,
+ C_COCO_MANUALLY_VALIDATED,
+ C_COCO_DEAD_CODE,
+ C_COCO_EXECUTION_COUNT_TOO_LOW,
+ C_COCO_NOT_COVERED_INFO,
+ C_COCO_COVERED_INFO,
+ C_COCO_MANUALLY_VALIDATED_INFO,
+
C_LAST_STYLE_SENTINEL
};
@@ -168,6 +180,7 @@ const char LOWERCASE_SELECTION[] = "TextEditor.LowercaseSelection";
const char SORT_SELECTED_LINES[] = "TextEditor.SortSelectedLines";
const char CUT_LINE[] = "TextEditor.CutLine";
const char COPY_LINE[] = "TextEditor.CopyLine";
+const char ADD_SELECT_NEXT_FIND_MATCH[] = "TextEditor.AddSelectionNextFindMatch";
const char DUPLICATE_SELECTION[] = "TextEditor.DuplicateSelection";
const char DUPLICATE_SELECTION_AND_COMMENT[] = "TextEditor.DuplicateSelectionAndComment";
const char DELETE_LINE[] = "TextEditor.DeleteLine";
diff --git a/src/plugins/texteditor/texteditoroverlay.cpp b/src/plugins/texteditor/texteditoroverlay.cpp
index 4fb7de00a25..5af06eb187b 100644
--- a/src/plugins/texteditor/texteditoroverlay.cpp
+++ b/src/plugins/texteditor/texteditoroverlay.cpp
@@ -312,7 +312,8 @@ QPainterPath TextEditorOverlay::createSelectionPath(const QTextCursor &begin, co
}
void TextEditorOverlay::paintSelection(QPainter *painter,
- const OverlaySelection &selection)
+ const OverlaySelection &selection,
+ const QRect &clip)
{
QTextCursor begin = selection.m_cursor_begin;
@@ -325,7 +326,7 @@ void TextEditorOverlay::paintSelection(QPainter *painter,
if (begin.isNull() || end.isNull() || begin.position() > end.position() || !bg.isValid())
return;
- QPainterPath path = createSelectionPath(begin, end, m_editor->viewport()->rect());
+ QPainterPath path = createSelectionPath(begin, end, clip);
painter->save();
QColor penColor = fg;
@@ -374,14 +375,15 @@ void TextEditorOverlay::paintSelection(QPainter *painter,
void TextEditorOverlay::fillSelection(QPainter *painter,
const OverlaySelection &selection,
- const QColor &color)
+ const QColor &color,
+ const QRect &clip)
{
const QTextCursor &begin = selection.m_cursor_begin;
const QTextCursor &end= selection.m_cursor_end;
if (begin.isNull() || end.isNull() || begin.position() > end.position())
return;
- QPainterPath path = createSelectionPath(begin, end, m_editor->viewport()->rect());
+ QPainterPath path = createSelectionPath(begin, end, clip);
painter->save();
painter->translate(-.5, -.5);
@@ -402,7 +404,7 @@ void TextEditorOverlay::paint(QPainter *painter, const QRect &clip)
!= selection.m_fixedLength)
continue;
- paintSelection(painter, selection);
+ paintSelection(painter, selection, clip);
}
for (int i = m_selections.size()-1; i >= 0; --i) {
const OverlaySelection &selection = m_selections.at(i);
@@ -413,7 +415,7 @@ void TextEditorOverlay::paint(QPainter *painter, const QRect &clip)
!= selection.m_fixedLength)
continue;
- paintSelection(painter, selection);
+ paintSelection(painter, selection, clip);
}
}
@@ -444,7 +446,7 @@ void TextEditorOverlay::fill(QPainter *painter, const QColor &color, const QRect
!= selection.m_fixedLength)
continue;
- fillSelection(painter, selection, color);
+ fillSelection(painter, selection, color, clip);
}
for (int i = m_selections.size()-1; i >= 0; --i) {
const OverlaySelection &selection = m_selections.at(i);
@@ -455,7 +457,7 @@ void TextEditorOverlay::fill(QPainter *painter, const QColor &color, const QRect
!= selection.m_fixedLength)
continue;
- fillSelection(painter, selection, color);
+ fillSelection(painter, selection, color, clip);
}
}
diff --git a/src/plugins/texteditor/texteditoroverlay.h b/src/plugins/texteditor/texteditoroverlay.h
index d87a0fe7aab..4c3811b8950 100644
--- a/src/plugins/texteditor/texteditoroverlay.h
+++ b/src/plugins/texteditor/texteditoroverlay.h
@@ -100,8 +100,8 @@ protected:
private:
QPainterPath createSelectionPath(const QTextCursor &begin, const QTextCursor &end, const QRect& clip);
- void paintSelection(QPainter *painter, const OverlaySelection &selection);
- void fillSelection(QPainter *painter, const OverlaySelection &selection, const QColor &color);
+ void paintSelection(QPainter *painter, const OverlaySelection &selection, const QRect &clip);
+ void fillSelection(QPainter *painter, const OverlaySelection &selection, const QColor &color, const QRect &clip);
bool m_visible;
bool m_alpha;
diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp
index 6613b43a70e..14206d621c6 100644
--- a/src/plugins/texteditor/texteditorplugin.cpp
+++ b/src/plugins/texteditor/texteditorplugin.cpp
@@ -280,16 +280,23 @@ void TextEditorPluginPrivate::updateSearchResultsFont(const FontSettings &settin
const Format defaultResultFormat = settings.formatFor(C_SEARCH_RESULT);
const Format alt1ResultFormat = settings.formatFor(C_SEARCH_RESULT_ALT1);
const Format alt2ResultFormat = settings.formatFor(C_SEARCH_RESULT_ALT2);
+ const Format containingFunctionResultFormat =
+ settings.formatFor(C_SEARCH_RESULT_CONTAINING_FUNCTION);
window->setTextEditorFont(QFont(settings.family(), settings.fontSize() * settings.fontZoom() / 100),
{std::make_pair(SearchResultColor::Style::Default,
SearchResultColor(textFormat.background(), textFormat.foreground(),
- defaultResultFormat.background(), defaultResultFormat.foreground())),
+ defaultResultFormat.background(), defaultResultFormat.foreground(),
+ containingFunctionResultFormat.background(), containingFunctionResultFormat.foreground())),
std::make_pair(SearchResultColor::Style::Alt1,
SearchResultColor(textFormat.background(), textFormat.foreground(),
- alt1ResultFormat.background(), alt1ResultFormat.foreground())),
+ alt1ResultFormat.background(), alt1ResultFormat.foreground(),
+ containingFunctionResultFormat.background(),
+ containingFunctionResultFormat.foreground())),
std::make_pair(SearchResultColor::Style::Alt2,
SearchResultColor(textFormat.background(), textFormat.foreground(),
- alt2ResultFormat.background(), alt2ResultFormat.foreground()))});
+ alt2ResultFormat.background(), alt2ResultFormat.foreground(),
+ containingFunctionResultFormat.background(),
+ containingFunctionResultFormat.foreground()))});
}
}
diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp
index 4141806679c..221b59964c9 100644
--- a/src/plugins/texteditor/texteditorsettings.cpp
+++ b/src/plugins/texteditor/texteditorsettings.cpp
@@ -112,6 +112,11 @@ FormatDescriptions TextEditorSettingsPrivate::initialFormats()
tr("Highlighted search results inside the editor.\n"
"Used to mark write accesses to C++ symbols."),
FormatDescription::ShowBackgroundControl);
+ formatDescr.emplace_back(C_SEARCH_RESULT_CONTAINING_FUNCTION,
+ tr("Search Result Containing function"),
+ tr("Highlighted search results inside the editor.\n"
+ "Used to mark containing function of the symbol usage."),
+ FormatDescription::ShowForeAndBackgroundControl);
formatDescr.emplace_back(C_SEARCH_SCOPE, tr("Search Scope"),
tr("Section where the pattern is searched in."),
FormatDescription::ShowBackgroundControl);
@@ -258,6 +263,8 @@ FormatDescriptions TextEditorSettingsPrivate::initialFormats()
FormatDescription::ShowAllControls);
formatDescr.emplace_back(C_PREPROCESSOR, tr("Preprocessor"),
tr("Preprocessor directives."), Qt::darkBlue);
+ formatDescr.emplace_back(C_MACRO, tr("Macro"),
+ tr("Macros."), functionFormat);
formatDescr.emplace_back(C_LABEL, tr("Label"), tr("Labels for goto statements."),
Qt::darkRed);
formatDescr.emplace_back(C_COMMENT, tr("Comment"),
@@ -368,6 +375,58 @@ FormatDescriptions TextEditorSettingsPrivate::initialFormats()
tr("Names of static fields or member functions."),
FormatDescription::ShowAllControls);
+ const auto cocoControls = FormatDescription::ShowControls(
+ FormatDescription::ShowAllAbsoluteControls | FormatDescription::ShowRelativeControls);
+ formatDescr.emplace_back(C_COCO_CODE_ADDED,
+ tr("Code Coverage Added Code"),
+ tr("New code that was not checked for tests."),
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_PARTIALLY_COVERED,
+ tr("Partially Covered Code"),
+ tr("Partial branch/condition coverage."),
+ Qt::darkYellow,
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_NOT_COVERED,
+ tr("Uncovered Code"),
+ tr("Not covered at all."),
+ Qt::red,
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_FULLY_COVERED,
+ tr("Fully Covered Code"),
+ tr("Fully covered code."),
+ Qt::green,
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_MANUALLY_VALIDATED,
+ tr("Manually Validated Code"),
+ tr("User added validation."),
+ Qt::blue,
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_DEAD_CODE,
+ tr("Code Coverage Dead Code"),
+ tr("Unreachable code."),
+ Qt::magenta,
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_EXECUTION_COUNT_TOO_LOW,
+ tr("Code Coverage Execution Count Too Low"),
+ tr("Minimum count not reached."),
+ Qt::red,
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_NOT_COVERED_INFO,
+ tr("Implicitly Not Covered Code"),
+ tr("PLACEHOLDER"),
+ Qt::red,
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_COVERED_INFO,
+ tr("Implicitly Covered Code"),
+ tr("PLACEHOLDER"),
+ Qt::green,
+ cocoControls);
+ formatDescr.emplace_back(C_COCO_MANUALLY_VALIDATED_INFO,
+ tr("Implicit Manual Coverage Validation"),
+ tr("PLACEHOLDER"),
+ Qt::blue,
+ cocoControls);
+
return formatDescr;
}
diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp
index 43aaf3e54b5..635e1a0c9bc 100644
--- a/src/plugins/texteditor/textmark.cpp
+++ b/src/plugins/texteditor/textmark.cpp
@@ -97,9 +97,6 @@ TextMark::TextMark(const FilePath &fileName, int lineNumber, Id category, double
TextMark::~TextMark()
{
- qDeleteAll(m_actions);
- m_actions.clear();
- delete m_settingsAction;
if (!m_fileName.isEmpty())
TextMarkRegistry::remove(this);
if (m_baseTextDocument)
@@ -133,23 +130,34 @@ void TextMark::paintIcon(QPainter *painter, const QRect &rect) const
icon().paint(painter, rect, Qt::AlignCenter);
}
-void TextMark::paintAnnotation(QPainter &painter, QRectF *annotationRect,
- const qreal fadeInOffset, const qreal fadeOutOffset,
+void TextMark::paintAnnotation(QPainter &painter,
+ const QRect &eventRect,
+ QRectF *annotationRect,
+ const qreal fadeInOffset,
+ const qreal fadeOutOffset,
const QPointF &contentOffset) const
{
QString text = lineAnnotation();
if (text.isEmpty())
return;
- const AnnotationRects &rects = annotationRects(*annotationRect, painter.fontMetrics(),
- fadeInOffset, fadeOutOffset);
- const QColor &markColor = m_color.has_value()
- ? Utils::creatorTheme()->color(m_color.value()).toHsl()
- : painter.pen().color();
+ const AnnotationRects &rects = annotationRects(*annotationRect,
+ painter.fontMetrics(),
+ fadeInOffset,
+ fadeOutOffset);
+ annotationRect->setRight(rects.fadeOutRect.right());
+ const QRectF eventRectF(eventRect);
+ if (!(rects.fadeInRect.intersects(eventRectF) || rects.annotationRect.intersects(eventRectF)
+ || rects.fadeOutRect.intersects(eventRectF))) {
+ return;
+ }
+
+ const QColor &markColor = annotationColor();
const FontSettings &fontSettings = m_baseTextDocument->fontSettings();
const AnnotationColors &colors = AnnotationColors::getAnnotationColors(
- markColor, fontSettings.toTextCharFormat(C_TEXT).background().color());
+ markColor.isValid() ? markColor : painter.pen().color(),
+ fontSettings.toTextCharFormat(C_TEXT).background().color());
painter.save();
QLinearGradient grad(rects.fadeInRect.topLeft() - contentOffset,
@@ -169,7 +177,6 @@ void TextMark::paintAnnotation(QPainter &painter, QRectF *annotationRect,
painter.fillRect(rects.fadeOutRect, grad);
}
painter.restore();
- annotationRect->setRight(rects.fadeOutRect.right());
}
TextMark::AnnotationRects TextMark::annotationRects(const QRectF &boundingRect,
@@ -232,13 +239,14 @@ void TextMark::removedFromEditor()
void TextMark::updateMarker()
{
if (m_baseTextDocument)
- m_baseTextDocument->updateMark(this);
+ m_baseTextDocument->scheduleUpdateLayout();
}
void TextMark::setPriority(TextMark::Priority prioriy)
{
m_priority = prioriy;
- updateMarker();
+ if (m_baseTextDocument)
+ m_baseTextDocument->updateMark(this);
}
bool TextMark::isVisible() const
@@ -300,19 +308,29 @@ void TextMark::addToToolTipLayout(QGridLayout *target) const
target->addLayout(contentLayout, row, 1);
// Right column: action icons/button
- QVector<QAction *> actions = m_actions;
- if (m_settingsAction)
- actions << m_settingsAction;
+ QList<QAction *> actions{m_actions.begin(), m_actions.end()};
+ if (m_actionsProvider)
+ actions = m_actionsProvider();
+ if (m_settingsPage.isValid()) {
+ auto settingsAction = new QAction;
+ settingsAction->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon());
+ settingsAction->setToolTip(tr("Show Diagnostic Settings"));
+ QObject::connect(settingsAction, &QAction::triggered, Core::ICore::instance(),
+ [id = m_settingsPage] { Core::ICore::showOptionsDialog(id); },
+ Qt::QueuedConnection);
+ actions.append(settingsAction);
+ }
if (!actions.isEmpty()) {
auto actionsLayout = new QHBoxLayout;
QMargins margins = actionsLayout->contentsMargins();
margins.setLeft(margins.left() + 5);
actionsLayout->setContentsMargins(margins);
for (QAction *action : qAsConst(actions)) {
- QTC_ASSERT(!action->icon().isNull(), continue);
+ QTC_ASSERT(!action->icon().isNull(), delete action; continue);
auto button = new QToolButton;
button->setIcon(action->icon());
button->setToolTip(action->toolTip());
+ action->setParent(button);
QObject::connect(button, &QToolButton::clicked, action, &QAction::triggered);
QObject::connect(button, &QToolButton::clicked, []() {
Utils::ToolTip::hideImmediately();
@@ -344,15 +362,24 @@ bool TextMark::addToolTipContent(QLayout *target) const
return true;
}
+QColor TextMark::annotationColor() const
+{
+ if (m_color.has_value())
+ return Utils::creatorTheme()->color(*m_color).toHsl();
+ return {};
+}
+
void TextMark::setIcon(const QIcon &icon)
{
m_icon = icon;
m_iconProvider = std::function<QIcon()>();
+ updateMarker();
}
void TextMark::setIconProvider(const std::function<QIcon ()> &iconProvider)
{
m_iconProvider = iconProvider;
+ updateMarker();
}
const QIcon TextMark::icon() const
@@ -368,6 +395,13 @@ Utils::optional<Theme::Color> TextMark::color() const
void TextMark::setColor(const Theme::Color &color)
{
m_color = color;
+ updateMarker();
+}
+
+void TextMark::setLineAnnotation(const QString &lineAnnotation)
+{
+ m_lineAnnotation = lineAnnotation;
+ updateMarker();
}
void TextMark::setToolTipProvider(const std::function<QString()> &toolTipProvider)
@@ -396,15 +430,14 @@ void TextMark::setActions(const QVector<QAction *> &actions)
m_actions = actions;
}
+void TextMark::setActionsProvider(const std::function<QList<QAction *>()> &actionsProvider)
+{
+ m_actionsProvider = actionsProvider;
+}
+
void TextMark::setSettingsPage(Id settingsPage)
{
- delete m_settingsAction;
- m_settingsAction = new QAction;
- m_settingsAction->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon());
- m_settingsAction->setToolTip(tr("Show Diagnostic Settings"));
- QObject::connect(m_settingsAction, &QAction::triggered, Core::ICore::instance(),
- [settingsPage] { Core::ICore::showOptionsDialog(settingsPage); },
- Qt::QueuedConnection);
+ m_settingsPage = settingsPage;
}
TextMarkRegistry::TextMarkRegistry(QObject *parent)
@@ -446,7 +479,8 @@ void TextMarkRegistry::editorOpened(IEditor *editor)
if (!m_marks.contains(document->filePath()))
return;
- foreach (TextMark *mark, m_marks.value(document->filePath()))
+ const QSet<TextMark *> marks = m_marks.value(document->filePath());
+ for (TextMark *mark : marks)
document->addMark(mark);
}
@@ -461,13 +495,14 @@ void TextMarkRegistry::documentRenamed(IDocument *document,
return;
QSet<TextMark *> toBeMoved;
- foreach (TextMark *mark, baseTextDocument->marks())
+ const QList<TextMark *> marks = baseTextDocument->marks();
+ for (TextMark *mark : marks)
toBeMoved.insert(mark);
m_marks[oldPath].subtract(toBeMoved);
m_marks[newPath].unite(toBeMoved);
- foreach (TextMark *mark, toBeMoved)
+ for (TextMark *mark : qAsConst(toBeMoved))
mark->updateFileName(newPath);
}
@@ -476,12 +511,12 @@ void TextMarkRegistry::allDocumentsRenamed(const FilePath &oldPath, const FilePa
if (!m_marks.contains(oldPath))
return;
- QSet<TextMark *> oldFileNameMarks = m_marks.value(oldPath);
+ const QSet<TextMark *> oldFileNameMarks = m_marks.value(oldPath);
m_marks[newPath].unite(oldFileNameMarks);
m_marks[oldPath].clear();
- foreach (TextMark *mark, oldFileNameMarks)
+ for (TextMark *mark : oldFileNameMarks)
mark->updateFileName(newPath);
}
diff --git a/src/plugins/texteditor/textmark.h b/src/plugins/texteditor/textmark.h
index fe999755e3c..d191ee07a73 100644
--- a/src/plugins/texteditor/textmark.h
+++ b/src/plugins/texteditor/textmark.h
@@ -72,8 +72,11 @@ public:
int lineNumber() const;
virtual void paintIcon(QPainter *painter, const QRect &rect) const;
- virtual void paintAnnotation(QPainter &painter, QRectF *annotationRect,
- const qreal fadeInOffset, const qreal fadeOutOffset,
+ virtual void paintAnnotation(QPainter &painter,
+ const QRect &eventRect,
+ QRectF *annotationRect,
+ const qreal fadeInOffset,
+ const qreal fadeOutOffset,
const QPointF &contentOffset) const;
struct AnnotationRects
{
@@ -98,11 +101,11 @@ public:
virtual void dragToLine(int lineNumber);
void addToToolTipLayout(QGridLayout *target) const;
virtual bool addToolTipContent(QLayout *target) const;
+ virtual QColor annotationColor() const;
void setIcon(const QIcon &icon);
void setIconProvider(const std::function<QIcon()> &iconProvider);
const QIcon icon() const;
- // call this if the icon has changed.
void updateMarker();
Priority priority() const { return m_priority;}
void setPriority(Priority prioriy);
@@ -122,7 +125,7 @@ public:
void setBaseTextDocument(TextDocument *baseTextDocument) { m_baseTextDocument = baseTextDocument; }
QString lineAnnotation() const { return m_lineAnnotation; }
- void setLineAnnotation(const QString &lineAnnotation) { m_lineAnnotation = lineAnnotation; }
+ void setLineAnnotation(const QString &lineAnnotation);
QString toolTip() const;
void setToolTip(const QString &toolTip);
@@ -130,6 +133,7 @@ public:
QVector<QAction *> actions() const;
void setActions(const QVector<QAction *> &actions); // Takes ownership
+ void setActionsProvider(const std::function<QList<QAction *>()> &actionsProvider); // Takes ownership
protected:
void setSettingsPage(Utils::Id settingsPage);
@@ -151,8 +155,9 @@ private:
QString m_toolTip;
std::function<QString()> m_toolTipProvider;
QString m_defaultToolTip;
- QVector<QAction *> m_actions;
- QAction *m_settingsAction = nullptr;
+ QVector<QAction *> m_actions; // FIXME Remove in master
+ std::function<QList<QAction *>()> m_actionsProvider;
+ Utils::Id m_settingsPage;
};
} // namespace TextEditor
diff --git a/src/plugins/todo/constants.h b/src/plugins/todo/constants.h
index 4b396eb726f..db55309ad02 100644
--- a/src/plugins/todo/constants.h
+++ b/src/plugins/todo/constants.h
@@ -31,6 +31,8 @@
namespace Todo {
namespace Constants {
+const char TODO_SETTINGS[] = "TodoSettings";
+
// Settings entries
const char SETTINGS_GROUP[] = "TodoPlugin";
const char SCANNING_SCOPE[] = "ScanningScope";
diff --git a/src/plugins/todo/optionsdialog.cpp b/src/plugins/todo/optionsdialog.cpp
index dc4f2d1d940..7dbcb14556d 100644
--- a/src/plugins/todo/optionsdialog.cpp
+++ b/src/plugins/todo/optionsdialog.cpp
@@ -212,7 +212,7 @@ void OptionsDialog::apply()
TodoOptionsPage::TodoOptionsPage(Settings *settings, const std::function<void ()> &onApply)
{
- setId("TodoSettings");
+ setId(Constants::TODO_SETTINGS);
setDisplayName(OptionsDialog::tr("To-Do"));
setCategory("To-Do");
setDisplayCategory(OptionsDialog::tr("To-Do"));
diff --git a/src/plugins/todo/todoicons.cpp b/src/plugins/todo/todoicons.cpp
index a159a87bca3..4f8bf31d58f 100644
--- a/src/plugins/todo/todoicons.cpp
+++ b/src/plugins/todo/todoicons.cpp
@@ -23,12 +23,13 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
+
+#include "todoicons.h"
+
#include <utils/icon.h>
#include <utils/theme/theme.h>
#include <utils/utilsicons.h>
-#include "todoicons.h"
-
using namespace Utils;
namespace Todo {
diff --git a/src/plugins/todo/todoitem.h b/src/plugins/todo/todoitem.h
index f44cf0b42c8..bc767a01763 100644
--- a/src/plugins/todo/todoitem.h
+++ b/src/plugins/todo/todoitem.h
@@ -29,7 +29,7 @@
#include "constants.h"
#include "todoicons.h"
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <QMetaType>
#include <QString>
diff --git a/src/plugins/todo/todoprojectsettingswidget.cpp b/src/plugins/todo/todoprojectsettingswidget.cpp
index d2dbbd5aa58..b8b934ecec0 100644
--- a/src/plugins/todo/todoprojectsettingswidget.cpp
+++ b/src/plugins/todo/todoprojectsettingswidget.cpp
@@ -44,6 +44,7 @@ TodoProjectSettingsWidget::TodoProjectSettingsWidget(ProjectExplorer::Project *p
ui->setupUi(this);
setExcludedPatternsButtonsEnabled();
+ setGlobalSettingsId(Constants::TODO_SETTINGS);
connect(ui->addExcludedPatternButton, &QPushButton::clicked,
this, &TodoProjectSettingsWidget::addExcludedPatternButtonClicked);
connect(ui->removeExcludedPatternButton, &QPushButton::clicked,
diff --git a/src/plugins/todo/todoprojectsettingswidget.h b/src/plugins/todo/todoprojectsettingswidget.h
index d711922eb66..acbf5ea44c4 100644
--- a/src/plugins/todo/todoprojectsettingswidget.h
+++ b/src/plugins/todo/todoprojectsettingswidget.h
@@ -25,6 +25,8 @@
#pragma once
+#include <projectexplorer/projectsettingswidget.h>
+
#include <QWidget>
QT_BEGIN_NAMESPACE
@@ -42,7 +44,7 @@ namespace Ui {
class TodoProjectSettingsWidget;
}
-class TodoProjectSettingsWidget : public QWidget
+class TodoProjectSettingsWidget : public ProjectExplorer::ProjectSettingsWidget
{
Q_OBJECT
diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp
index 743802f3700..78d31e72910 100644
--- a/src/plugins/updateinfo/updateinfoplugin.cpp
+++ b/src/plugins/updateinfo/updateinfoplugin.cpp
@@ -32,8 +32,9 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
+#include <coreplugin/progressmanager/futureprogress.h>
+#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/settingsdatabase.h>
-#include <coreplugin/shellcommand.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/infobar.h>
@@ -53,7 +54,9 @@
#include <QTimer>
#include <QVersionNumber>
-Q_LOGGING_CATEGORY(log, "qtc.updateinfo", QtWarningMsg)
+#include <memory>
+
+Q_LOGGING_CATEGORY(updateLog, "qtc.updateinfo", QtWarningMsg)
const char UpdaterGroup[] = "Updater";
const char MaintenanceToolKey[] = "MaintenanceTool";
@@ -68,6 +71,7 @@ const char InstallUpdates[] = "UpdateInfo.InstallUpdates";
const char InstallQtUpdates[] = "UpdateInfo.InstallQtUpdates";
using namespace Core;
+using namespace Utils;
namespace UpdateInfo {
namespace Internal {
@@ -76,11 +80,11 @@ class UpdateInfoPluginPrivate
{
public:
QString m_maintenanceTool;
- QPointer<ShellCommand> m_checkUpdatesCommand;
+ std::unique_ptr<QtcProcess> m_maintenanceToolProcess;
QPointer<FutureProgress> m_progress;
- QString m_collectedOutput;
+ QString m_updateOutput;
+ QString m_packagesOutput;
QTimer *m_checkUpdatesTimer = nullptr;
-
struct Settings
{
bool automaticCheck = true;
@@ -125,7 +129,7 @@ void UpdateInfoPlugin::stopAutoCheckForUpdates()
void UpdateInfoPlugin::doAutoCheckForUpdates()
{
- if (d->m_checkUpdatesCommand)
+ if (d->m_maintenanceToolProcess)
return; // update task is still running (might have been run manually just before)
if (nextCheckDate().isValid() && nextCheckDate() > QDate::currentDate())
@@ -138,51 +142,86 @@ void UpdateInfoPlugin::startCheckForUpdates()
{
stopCheckForUpdates();
- d->m_checkUpdatesCommand = new ShellCommand({}, Utils::Environment::systemEnvironment());
- d->m_checkUpdatesCommand->setDisplayName(tr("Checking for Updates"));
- connect(d->m_checkUpdatesCommand, &ShellCommand::stdOutText, this, &UpdateInfoPlugin::collectCheckForUpdatesOutput);
- connect(d->m_checkUpdatesCommand, &ShellCommand::finished, this, &UpdateInfoPlugin::checkForUpdatesFinished);
- d->m_checkUpdatesCommand->addJob({Utils::FilePath::fromString(d->m_maintenanceTool),
- {"ch", "-g", "*=false,ifw.package.*=true"}},
- 60 * 3, // 3 minutes timeout
- /*workingDirectory=*/{},
- [](int /*exitCode*/) {
- return Utils::QtcProcess::FinishedWithSuccess;
- });
- if (d->m_settings.checkForQtVersions) {
- d->m_checkUpdatesCommand
- ->addJob({Utils::FilePath::fromString(d->m_maintenanceTool),
- {"se", "qt[.]qt[0-9][.][0-9]+$", "-g", "*=false,ifw.package.*=true"}},
- 60 * 3, // 3 minutes timeout
- /*workingDirectory=*/{},
- [](int /*exitCode*/) { return Utils::QtcProcess::FinishedWithSuccess; });
- }
- d->m_checkUpdatesCommand->execute();
- d->m_progress = d->m_checkUpdatesCommand->futureProgress();
- if (d->m_progress) {
- d->m_progress->setKeepOnFinish(FutureProgress::KeepOnFinishTillUserInteraction);
- d->m_progress->setSubtitleVisibleInStatusBar(true);
- }
+ QFutureInterface<void> futureIf;
+ FutureProgress *futureProgress
+ = ProgressManager::addTimedTask(futureIf,
+ tr("Checking for Updates"),
+ Id("UpdateInfo.CheckingForUpdates"),
+ 60);
+ futureProgress->setKeepOnFinish(FutureProgress::KeepOnFinishTillUserInteraction);
+ futureProgress->setSubtitleVisibleInStatusBar(true);
+ connect(futureProgress, &FutureProgress::canceled, this, [this, futureIf]() mutable {
+ futureIf.reportCanceled();
+ futureIf.reportFinished();
+ stopCheckForUpdates();
+ });
+
+ d->m_maintenanceToolProcess.reset(new QtcProcess);
+ d->m_maintenanceToolProcess->setCommand({Utils::FilePath::fromString(d->m_maintenanceTool),
+ {"ch", "-g", "*=false,ifw.package.*=true"}});
+ d->m_maintenanceToolProcess->setTimeoutS(3 * 60); // 3 minutes
+ // TODO handle error
+ connect(
+ d->m_maintenanceToolProcess.get(),
+ &QtcProcess::done,
+ this,
+ [this, futureIf]() mutable {
+ if (d->m_maintenanceToolProcess->result() == ProcessResult::FinishedWithSuccess) {
+ d->m_updateOutput = d->m_maintenanceToolProcess->cleanedStdOut();
+ if (d->m_settings.checkForQtVersions) {
+ d->m_maintenanceToolProcess.reset(new QtcProcess);
+ d->m_maintenanceToolProcess->setCommand(
+ {Utils::FilePath::fromString(d->m_maintenanceTool),
+ {"se", "qt[.]qt[0-9][.][0-9]+$", "-g", "*=false,ifw.package.*=true"}});
+ d->m_maintenanceToolProcess->setTimeoutS(3 * 60); // 3 minutes
+ connect(
+ d->m_maintenanceToolProcess.get(),
+ &QtcProcess::done,
+ this,
+ [this, futureIf]() mutable {
+ if (d->m_maintenanceToolProcess->result()
+ == ProcessResult::FinishedWithSuccess) {
+ d->m_packagesOutput = d->m_maintenanceToolProcess->cleanedStdOut();
+ d->m_maintenanceToolProcess.reset();
+ futureIf.reportFinished();
+ checkForUpdatesFinished();
+ } else {
+ futureIf.reportCanceled(); // is used to indicate error
+ futureIf.reportFinished();
+ }
+ },
+ Qt::QueuedConnection);
+ d->m_maintenanceToolProcess->start();
+ } else {
+ d->m_maintenanceToolProcess.reset();
+ futureIf.reportFinished();
+ checkForUpdatesFinished();
+ }
+ } else {
+ futureIf.reportCanceled(); // is used to indicate error
+ futureIf.reportFinished();
+ }
+ },
+ Qt::QueuedConnection);
+
+ d->m_maintenanceToolProcess->start();
+ futureIf.reportStarted();
+
emit checkForUpdatesRunningChanged(true);
}
void UpdateInfoPlugin::stopCheckForUpdates()
{
- if (!d->m_checkUpdatesCommand)
+ if (!d->m_maintenanceToolProcess)
return;
- d->m_collectedOutput.clear();
- d->m_checkUpdatesCommand->disconnect();
- d->m_checkUpdatesCommand->cancel();
- d->m_checkUpdatesCommand = nullptr;
+ d->m_maintenanceToolProcess->disconnect();
+ d->m_maintenanceToolProcess.reset();
+ d->m_updateOutput.clear();
+ d->m_packagesOutput.clear();
emit checkForUpdatesRunningChanged(false);
}
-void UpdateInfoPlugin::collectCheckForUpdatesOutput(const QString &contents)
-{
- d->m_collectedOutput += contents;
-}
-
static void showUpdateInfo(const QList<Update> &updates, const std::function<void()> &startUpdater)
{
Utils::InfoBarEntry info(InstallUpdates,
@@ -215,9 +254,9 @@ static void showQtUpdateInfo(const QtPackage &package,
{
Utils::InfoBarEntry info(InstallQtUpdates,
UpdateInfoPlugin::tr(
- "%1 is available. Check the <a "
- "href=\"https://www.qt.io/blog\">Qt blog</a> for details.")
- .arg(package.displayName));
+ "%1 is available. Check the <a %2>Qt blog</a> for details.")
+ .arg(package.displayName,
+ QString("href=\"https://www.qt.io/blog/tag/releases\"")));
info.addCustomButton(UpdateInfoPlugin::tr("Start Package Manager"), [startPackageManager] {
Core::ICore::infoBar()->removeInfo(InstallQtUpdates);
startPackageManager();
@@ -235,22 +274,23 @@ void UpdateInfoPlugin::checkForUpdatesFinished()
{
setLastCheckDate(QDate::currentDate());
- qCDebug(log) << "--- MaintenanceTool output (combined):";
- qCDebug(log) << qPrintable(d->m_collectedOutput);
- std::unique_ptr<QDomDocument> document = documentForResponse(d->m_collectedOutput);
+ qCDebug(updateLog) << "--- MaintenanceTool output (updates):";
+ qCDebug(updateLog) << qPrintable(d->m_updateOutput);
+ qCDebug(updateLog) << "--- MaintenanceTool output (packages):";
+ qCDebug(updateLog) << qPrintable(d->m_packagesOutput);
stopCheckForUpdates();
- const QList<Update> updates = availableUpdates(*document);
- const QList<QtPackage> qtPackages = availableQtPackages(*document);
- if (log().isDebugEnabled()) {
- qCDebug(log) << "--- Available updates:";
+ const QList<Update> updates = availableUpdates(d->m_updateOutput);
+ const QList<QtPackage> qtPackages = availableQtPackages(d->m_packagesOutput);
+ if (updateLog().isDebugEnabled()) {
+ qCDebug(updateLog) << "--- Available updates:";
for (const Update &u : updates)
- qCDebug(log) << u.name << u.version;
- qCDebug(log) << "--- Available Qt packages:";
+ qCDebug(updateLog) << u.name << u.version;
+ qCDebug(updateLog) << "--- Available Qt packages:";
for (const QtPackage &p : qtPackages) {
- qCDebug(log) << p.displayName << p.version << "installed:" << p.installed
- << "prerelease:" << p.isPrerelease;
+ qCDebug(updateLog) << p.displayName << p.version << "installed:" << p.installed
+ << "prerelease:" << p.isPrerelease;
}
}
Utils::optional<QtPackage> qtToNag = qtToNagAbout(qtPackages, &d->m_lastMaxQtVersion);
@@ -275,7 +315,7 @@ void UpdateInfoPlugin::checkForUpdatesFinished()
bool UpdateInfoPlugin::isCheckForUpdatesRunning() const
{
- return d->m_checkUpdatesCommand;
+ return d->m_maintenanceToolProcess.get() != nullptr;
}
void UpdateInfoPlugin::extensionsInitialized()
diff --git a/src/plugins/updateinfo/updateinfoplugin.h b/src/plugins/updateinfo/updateinfoplugin.h
index 78177fee919..2dfcfe346d3 100644
--- a/src/plugins/updateinfo/updateinfoplugin.h
+++ b/src/plugins/updateinfo/updateinfoplugin.h
@@ -89,7 +89,6 @@ private:
void startPackageManager();
void stopCheckForUpdates();
- void collectCheckForUpdatesOutput(const QString &contents);
void checkForUpdatesFinished();
void loadSettings() const;
diff --git a/src/plugins/updateinfo/updateinfotools.h b/src/plugins/updateinfo/updateinfotools.h
index c8dd3a7fd07..f664628966c 100644
--- a/src/plugins/updateinfo/updateinfotools.h
+++ b/src/plugins/updateinfo/updateinfotools.h
@@ -34,22 +34,7 @@
#include <QRegularExpression>
#include <QVersionNumber>
-#include <memory>
-
-Q_DECLARE_LOGGING_CATEGORY(log)
-
-std::unique_ptr<QDomDocument> documentForResponse(const QString &response)
-{
- // since the output can contain two toplevel items from the two separate MaintenanceTool runs,
- // clean up any <?xml version="1.0"?> and surround with a toplevel element
- QString responseWithoutHeader = response;
- responseWithoutHeader.remove(QRegularExpression("<\\?xml.*\\?>"));
- const QString xml = response.isEmpty() ? QString()
- : ("<doc>" + responseWithoutHeader + "</doc>");
- std::unique_ptr<QDomDocument> doc(new QDomDocument);
- doc->setContent(xml);
- return doc;
-}
+Q_DECLARE_LOGGING_CATEGORY(updateLog)
struct Update
{
@@ -62,8 +47,10 @@ struct Update
};
};
-QList<Update> availableUpdates(const QDomDocument &document)
+QList<Update> availableUpdates(const QString &updateXml)
{
+ QDomDocument document;
+ document.setContent(updateXml);
if (document.isNull() || !document.firstChildElement().hasChildNodes())
return {};
QList<Update> result;
@@ -93,8 +80,10 @@ struct QtPackage
}
};
-QList<QtPackage> availableQtPackages(const QDomDocument &document)
+QList<QtPackage> availableQtPackages(const QString &packageXml)
{
+ QDomDocument document;
+ document.setContent(packageXml);
if (document.isNull() || !document.firstChildElement().hasChildNodes())
return {};
QList<QtPackage> result;
@@ -144,8 +133,8 @@ Utils::optional<QtPackage> qtToNagAbout(const QList<QtPackage> &allPackages,
if (packages.isEmpty())
return {};
const QtPackage highest = packages.constFirst();
- qCDebug(log) << "Highest available (non-prerelease) Qt:" << highest.version;
- qCDebug(log) << "Highest previously seen (non-prerelease) Qt:" << *highestSeen;
+ qCDebug(updateLog) << "Highest available (non-prerelease) Qt:" << highest.version;
+ qCDebug(updateLog) << "Highest previously seen (non-prerelease) Qt:" << *highestSeen;
// if the highestSeen version is null, we don't know if the Qt version is new, and better don't nag
const bool isNew = !highestSeen->isNull() && highest.version > *highestSeen;
if (highestSeen->isNull() || isNew)
@@ -153,9 +142,9 @@ Utils::optional<QtPackage> qtToNagAbout(const QList<QtPackage> &allPackages,
if (!isNew)
return {};
const Utils::optional<QtPackage> highestInstalled = highestInstalledQt(packages);
- qCDebug(log) << "Highest installed Qt:"
- << qPrintable(highestInstalled ? highestInstalled->version.toString()
- : QString("none"));
+ qCDebug(updateLog) << "Highest installed Qt:"
+ << qPrintable(highestInstalled ? highestInstalled->version.toString()
+ : QString("none"));
if (!highestInstalled) // don't nag if no Qt is installed at all
return {};
if (highestInstalled->version == highest.version)
diff --git a/src/plugins/valgrind/CMakeLists.txt b/src/plugins/valgrind/CMakeLists.txt
index 83720cb2c0e..192304e5795 100644
--- a/src/plugins/valgrind/CMakeLists.txt
+++ b/src/plugins/valgrind/CMakeLists.txt
@@ -1,10 +1,9 @@
add_qtc_plugin(Valgrind
- DEPENDS CPlusPlus QtcSsh
+ DEPENDS CPlusPlus
PLUGIN_DEPENDS Core Debugger ProjectExplorer TextEditor
SOURCES
callgrind/callgrindabstractmodel.h
callgrind/callgrindcallmodel.cpp callgrind/callgrindcallmodel.h
- callgrind/callgrindcontroller.cpp callgrind/callgrindcontroller.h
callgrind/callgrindcostitem.cpp callgrind/callgrindcostitem.h
callgrind/callgrindcycledetection.cpp callgrind/callgrindcycledetection.h
callgrind/callgrinddatamodel.cpp callgrind/callgrinddatamodel.h
diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp
deleted file mode 100644
index 83f98cc71bb..00000000000
--- a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "callgrindcontroller.h"
-
-#include <ssh/sftpsession.h>
-#include <ssh/sshconnectionmanager.h>
-
-#include <utils/fileutils.h>
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-#include <utils/temporaryfile.h>
-
-#include <QDebug>
-#include <QDir>
-#include <QEventLoop>
-
-#define CALLGRIND_CONTROL_DEBUG 0
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Valgrind {
-namespace Callgrind {
-
-const char CALLGRIND_CONTROL_BINARY[] = "callgrind_control";
-
-CallgrindController::CallgrindController() = default;
-
-CallgrindController::~CallgrindController()
-{
- cleanupTempFile();
-}
-
-static QString toOptionString(CallgrindController::Option option)
-{
- /* callgrind_control help from v3.9.0
-
- Options:
- -h --help Show this help text
- --version Show version
- -s --stat Show statistics
- -b --back Show stack/back trace
- -e [<A>,...] Show event counters for <A>,... (default: all)
- --dump[=<s>] Request a dump optionally using <s> as description
- -z --zero Zero all event counters
- -k --kill Kill
- --instr=<on|off> Switch instrumentation state on/off
- */
-
- switch (option) {
- case CallgrindController::Dump:
- return QLatin1String("--dump");
- case CallgrindController::ResetEventCounters:
- return QLatin1String("--zero");
- case CallgrindController::Pause:
- return QLatin1String("--instr=off");
- case CallgrindController::UnPause:
- return QLatin1String("--instr=on");
- default:
- return QString(); // never reached
- }
-}
-
-void CallgrindController::run(Option option)
-{
- if (m_controllerProcess) {
- emit statusMessage(tr("Previous command has not yet finished."));
- return;
- }
-
- // save back current running operation
- m_lastOption = option;
-
- m_controllerProcess = new ApplicationLauncher;
-
- switch (option) {
- case CallgrindController::Dump:
- emit statusMessage(tr("Dumping profile data..."));
- break;
- case CallgrindController::ResetEventCounters:
- emit statusMessage(tr("Resetting event counters..."));
- break;
- case CallgrindController::Pause:
- emit statusMessage(tr("Pausing instrumentation..."));
- break;
- case CallgrindController::UnPause:
- emit statusMessage(tr("Unpausing instrumentation..."));
- break;
- default:
- break;
- }
-
-#if CALLGRIND_CONTROL_DEBUG
- m_controllerProcess->setProcessChannelMode(QProcess::ForwardedChannels);
-#endif
- connect(m_controllerProcess, &ApplicationLauncher::processExited,
- this, &CallgrindController::controllerProcessFinished);
- connect(m_controllerProcess, &ApplicationLauncher::error,
- this, &CallgrindController::handleControllerProcessError);
-
- Runnable controller = m_valgrindRunnable;
- controller.command.setExecutable(FilePath::fromString(CALLGRIND_CONTROL_BINARY));
- controller.command.setArguments(QString("%1 %2").arg(toOptionString(option)).arg(m_pid));
-
- if (!m_valgrindRunnable.device
- || m_valgrindRunnable.device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
- m_controllerProcess->start(controller);
- else
- m_controllerProcess->start(controller, m_valgrindRunnable.device);
-}
-
-void CallgrindController::setValgrindPid(qint64 pid)
-{
- m_pid = pid;
-}
-
-void CallgrindController::handleControllerProcessError(QProcess::ProcessError)
-{
- QTC_ASSERT(m_controllerProcess, return);
- const QString error = m_controllerProcess->errorString();
- emit statusMessage(tr("An error occurred while trying to run %1: %2").arg(CALLGRIND_CONTROL_BINARY).arg(error));
-
- m_controllerProcess->deleteLater();
- m_controllerProcess = nullptr;
-}
-
-void CallgrindController::controllerProcessFinished(int rc, QProcess::ExitStatus status)
-{
- QTC_ASSERT(m_controllerProcess, return);
- const QString error = m_controllerProcess->errorString();
-
- m_controllerProcess->deleteLater(); // Called directly from finished() signal in m_process
- m_controllerProcess = nullptr;
-
- if (rc != 0 || status != QProcess::NormalExit) {
- qWarning() << "Controller exited abnormally:" << error;
- return;
- }
-
- // this call went fine, we might run another task after this
- switch (m_lastOption) {
- case ResetEventCounters:
- // lets dump the new reset profiling info
- run(Dump);
- return;
- case Pause:
- break;
- case Dump:
- emit statusMessage(tr("Callgrind dumped profiling info"));
- break;
- case UnPause:
- emit statusMessage(tr("Callgrind unpaused."));
- break;
- default:
- break;
- }
-
- emit finished(m_lastOption);
- m_lastOption = Unknown;
-}
-
-void CallgrindController::getLocalDataFile()
-{
- cleanupTempFile();
- {
- TemporaryFile dataFile("callgrind.out");
- dataFile.open();
- m_hostOutputFile = FilePath::fromString(dataFile.fileName());
- }
-
-// ///TODO: error handling
-// emit statusMessage(tr("Downloading remote profile data..."));
-// m_ssh = m_valgrindProc->connection();
-// [...]
-// m_sftp = m_ssh->createSftpSession();
-// connect(m_sftp.get(), &QSsh::SftpSession::commandFinished,
-// this, &CallgrindController::sftpJobFinished);
-// connect(m_sftp.get(), &QSsh::SftpSession::started,
-// this, &CallgrindController::sftpInitialized);
-// m_sftp->start();
-
- const auto afterCopy = [this](bool res) {
- QTC_CHECK(res);
- emit localParseDataAvailable(m_hostOutputFile);
- };
- m_valgrindOutputFile.asyncCopyFile(afterCopy, m_hostOutputFile);
-}
-
-void CallgrindController::sftpInitialized()
-{
- m_downloadJob = m_sftp->downloadFile(m_valgrindOutputFile.path(), m_hostOutputFile.path());
-}
-
-void CallgrindController::sftpJobFinished(QSsh::SftpJobId job, const QString &error)
-{
- QTC_ASSERT(job == m_downloadJob, return);
-
- m_sftp->quit();
-
- if (error.isEmpty())
- emit localParseDataAvailable(m_hostOutputFile);
-}
-
-void CallgrindController::cleanupTempFile()
-{
- if (!m_hostOutputFile.isEmpty() && m_hostOutputFile.exists())
- m_hostOutputFile.removeFile();
-
- m_hostOutputFile.clear();
-}
-
-void CallgrindController::setValgrindRunnable(const Runnable &runnable)
-{
- m_valgrindRunnable = runnable;
-}
-
-} // namespace Callgrind
-} // namespace Valgrind
diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.h b/src/plugins/valgrind/callgrind/callgrindcontroller.h
deleted file mode 100644
index 848c2ba2b62..00000000000
--- a/src/plugins/valgrind/callgrind/callgrindcontroller.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <ssh/sftpdefs.h>
-#include <ssh/sshremoteprocess.h>
-
-#include <projectexplorer/runcontrol.h>
-
-#include <QProcess>
-
-namespace Valgrind {
-namespace Callgrind {
-
-class CallgrindController : public QObject
-{
- Q_OBJECT
-public:
- enum Option {
- Unknown,
- Dump,
- ResetEventCounters,
- Pause,
- UnPause
- };
- Q_ENUM(Option)
-
- CallgrindController();
- ~CallgrindController() override;
-
- void run(Option option);
-
- /**
- * Make data file available locally, triggers @c localParseDataAvailable.
- *
- * If the valgrind process was run remotely, this transparently
- * downloads the data file first and returns a local path.
- */
- void getLocalDataFile();
- void setValgrindPid(qint64 pid);
- void setValgrindRunnable(const ProjectExplorer::Runnable &runnable);
- void setValgrindOutputFile(const Utils::FilePath &output) { m_valgrindOutputFile = output; }
-
-signals:
- void finished(Valgrind::Callgrind::CallgrindController::Option option);
- void localParseDataAvailable(const Utils::FilePath &file);
- void statusMessage(const QString &msg);
-
-private:
- void handleControllerProcessError(QProcess::ProcessError);
-
- void sftpInitialized();
- void sftpJobFinished(QSsh::SftpJobId job, const QString &error);
- void cleanupTempFile();
-
- void controllerProcessFinished(int, QProcess::ExitStatus);
- void controllerProcessError(QProcess::ProcessError);
-
- ProjectExplorer::ApplicationLauncher *m_controllerProcess = nullptr;
- ProjectExplorer::Runnable m_valgrindRunnable;
- qint64 m_pid = 0;
-
- Option m_lastOption = Unknown;
-
- // remote callgrind support
- Utils::FilePath m_valgrindOutputFile; // On the device that runs valgrind
- Utils::FilePath m_hostOutputFile; // On the device that runs creator
- QSsh::SftpSessionPtr m_sftp;
- QSsh::SftpJobId m_downloadJob = 0;
-};
-
-} // namespace Callgrind
-} // namespace Valgrind
diff --git a/src/plugins/valgrind/callgrind/callgrindcycledetection.cpp b/src/plugins/valgrind/callgrind/callgrindcycledetection.cpp
index b47ecb4697d..79443aa5b65 100644
--- a/src/plugins/valgrind/callgrind/callgrindcycledetection.cpp
+++ b/src/plugins/valgrind/callgrind/callgrindcycledetection.cpp
@@ -45,14 +45,14 @@ CycleDetection::CycleDetection(ParseData *data)
QVector<const Function *> CycleDetection::run(const QVector<const Function *> &input)
{
- foreach (const Function *function, input) {
+ for (const Function *function : input) {
Node *node = new Node;
node->function = function;
node->dfs = -1;
node->lowlink = -1;
m_nodes.insert(function, node);
}
- foreach (Node *node, m_nodes) {
+ for (Node *node : qAsConst(m_nodes)) {
if (node->dfs == -1)
tarjan(node);
}
@@ -69,7 +69,8 @@ void CycleDetection::tarjan(Node *node)
m_depth++;
m_stack.push(node);
- foreach (const FunctionCall *call, node->function->outgoingCalls())
+ const QVector<const FunctionCall *> calls = node->function->outgoingCalls();
+ for (const FunctionCall *call : calls)
tarjanForChildNode(node, m_nodes.value(call->callee()));
if (node->dfs == node->lowlink) {
diff --git a/src/plugins/valgrind/callgrind/callgrindfunction.cpp b/src/plugins/valgrind/callgrind/callgrindfunction.cpp
index f468164aec3..9a7f4fe81bc 100644
--- a/src/plugins/valgrind/callgrind/callgrindfunction.cpp
+++ b/src/plugins/valgrind/callgrind/callgrindfunction.cpp
@@ -67,7 +67,7 @@ void Function::Private::accumulateCost(QVector<quint64> &base, const QVector<qui
} else {
///TODO: see whether .data() is noticably faster (less detaching)
int i = 0;
- foreach (quint64 cost, add)
+ for (quint64 cost : add)
base[i++] += cost;
}
}
@@ -175,7 +175,7 @@ void Function::setObject(qint64 id)
QString Function::location() const
{
QString pos;
- foreach (const CostItem *costItem, d->m_costItems) {
+ for (const CostItem *costItem : qAsConst(d->m_costItems)) {
if (costItem->differingFileId() != -1) {
QTextStream stream(&pos);
stream << '(';
@@ -214,7 +214,7 @@ int Function::lineNumber() const
if (lineIdx == -1)
return -1;
- foreach (const CostItem *costItem, d->m_costItems) {
+ for (const CostItem *costItem : qAsConst(d->m_costItems)) {
if (costItem->differingFileId() == -1)
return costItem->position(lineIdx);
}
@@ -287,7 +287,7 @@ void Function::addCostItem(const CostItem *item)
void Function::finalize()
{
bool recursive = false;
- foreach (const FunctionCall *call, d->m_incomingCalls) {
+ for (const FunctionCall *call : qAsConst(d->m_incomingCalls)) {
if (call->caller() == this) {
recursive = true;
break;
@@ -300,9 +300,10 @@ void Function::finalize()
// e.g.: A -> B -> B ..., C -> B -> B ...
// cost of B = cost of call to B in A + cost of call to B in C + ...
d->m_inclusiveCost.fill(0);
- foreach (const FunctionCall *call, d->m_incomingCalls) {
+ for (const FunctionCall *call : qAsConst(d->m_incomingCalls)) {
if (call->caller() != this) {
- foreach (const CostItem *costItem, call->caller()->costItems()) {
+ const QVector<const CostItem *> costItems = call->caller()->costItems();
+ for (const CostItem *costItem : costItems) {
if (costItem->call() && costItem->call()->callee() == this)
d->accumulateCost(d->m_inclusiveCost, costItem->costs());
}
diff --git a/src/plugins/valgrind/callgrind/callgrindfunctioncycle.cpp b/src/plugins/valgrind/callgrind/callgrindfunctioncycle.cpp
index e070b5a6876..ca943b5ce0f 100644
--- a/src/plugins/valgrind/callgrind/callgrindfunctioncycle.cpp
+++ b/src/plugins/valgrind/callgrind/callgrindfunctioncycle.cpp
@@ -73,16 +73,18 @@ void FunctionCycle::setFunctions(const QVector<const Function *> &functions)
d->m_selfCost.fill(0, d->m_data->events().size());
d->m_inclusiveCost.fill(0, d->m_data->events().size());
- foreach (const Function *func, functions) {
+ for (const Function *func : functions) {
// just add up self cost
Private::accumulateCost(d->m_selfCost, func->selfCosts());
// add outgoing calls to functions that are not part of the cycle
- foreach (const FunctionCall *call, func->outgoingCalls()) {
+ const QVector<const FunctionCall *> calls = func->outgoingCalls();
+ for (const FunctionCall *call : calls) {
if (!functions.contains(call->callee()))
d->accumulateCall(call, Function::Private::Outgoing);
}
// add incoming calls from functions that are not part of the cycle
- foreach (const FunctionCall *call, func->incomingCalls()) {
+ const QVector<const FunctionCall *> inCalls = func->incomingCalls();
+ for (const FunctionCall *call : inCalls) {
if (!functions.contains(call->caller())) {
d->accumulateCall(call, Function::Private::Incoming);
d->m_called += call->calls();
diff --git a/src/plugins/valgrind/callgrind/callgrindparsedata.cpp b/src/plugins/valgrind/callgrind/callgrindparsedata.cpp
index 55398ce79ae..ba1e4258023 100644
--- a/src/plugins/valgrind/callgrind/callgrindparsedata.cpp
+++ b/src/plugins/valgrind/callgrind/callgrindparsedata.cpp
@@ -92,7 +92,7 @@ ParseData::Private::~Private()
void ParseData::Private::cleanupFunctionCycles()
{
m_cycleCacheValid = false;
- foreach (const Function *func, m_cycleCache) {
+ for (const Function *func : qAsConst(m_cycleCache)) {
if (dynamic_cast<const FunctionCycle *>(func))
delete func;
}
diff --git a/src/plugins/valgrind/callgrind/callgrindparser.cpp b/src/plugins/valgrind/callgrind/callgrindparser.cpp
index 1288bd16846..421583d3671 100644
--- a/src/plugins/valgrind/callgrind/callgrindparser.cpp
+++ b/src/plugins/valgrind/callgrind/callgrindparser.cpp
@@ -219,17 +219,19 @@ void Parser::Private::parse(const FilePath &filePath)
// build fast lookup of functions by their nameId
QHash<qint64, QList<const Function *> > functionLookup;
- foreach (const Function *function, data->functions()) {
+ const QVector<const Function *> functions = data->functions();
+ for (const Function *function : functions) {
functionLookup[function->nameId()].append(function);
}
// functions that need to accumulate their calees
QSet<Function *> pendingFunctions;
- foreach (const CallData &callData, pendingCallees) {
+ for (const CallData &callData : qAsConst(pendingCallees)) {
Function *calledFunction = nullptr;
QTC_ASSERT(callData.call, continue);
QTC_ASSERT(callData.call->caller(), continue);
- foreach (const Function *function, functionLookup.value(callData.calledFunction)) {
+ const QList<const Function *> functions = functionLookup.value(callData.calledFunction);
+ for (const Function *function : functions) {
QTC_ASSERT(function->nameId() == callData.calledFunction, continue);
if (function->objectId() == callData.calledObject
&& function->fileId() == callData.calledFile)
@@ -245,7 +247,7 @@ void Parser::Private::parse(const FilePath &filePath)
qDebug() << "caller is:" << callData.call->caller()->name() << callData.call->caller()->nameId();
qDebug() << "called file:" << callData.calledFile << "object:" << callData.calledObject;
qDebug() << data->stringForFileCompression(callData.calledFile) << data->stringForObjectCompression(callData.calledObject);
- foreach (const Function *function, functionLookup.value(callData.calledFunction)) {
+ for (const Function *function, functionLookup.value(callData.calledFunction)) {
qDebug() << "available function file:" << function->fileId() << function->file() << "object:" << function->objectId() << function->object();
}
}
@@ -263,7 +265,7 @@ void Parser::Private::parse(const FilePath &filePath)
// lookup done
// now accumulate callees
- foreach (Function *func, pendingFunctions)
+ for (Function *func : qAsConst(pendingFunctions))
func->finalize();
emit q->parserDataReady();
@@ -322,7 +324,8 @@ void Parser::Private::parseHeader(QIODevice *device)
} else if (line.startsWith("summary: ")) {
QString values = getValue(line, 9);
uint i = 0;
- foreach (const QString &value, values.split(' ', Qt::SkipEmptyParts))
+ const QStringList valueList = values.split(' ', Qt::SkipEmptyParts);
+ for (const QString &value : valueList)
data->setTotalCost(i++, value.toULongLong());
} else if (!line.trimmed().isEmpty()) {
// handle line and exit parseHeader
diff --git a/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp b/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp
index 66a362f4956..68f77e83f88 100644
--- a/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp
+++ b/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp
@@ -130,7 +130,8 @@ bool DataProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_
// check if the function from this index is a child of (called by) the filter function
if (m_function) {
bool isValid = false;
- foreach (const FunctionCall *call, func->incomingCalls()) {
+ const QVector<const FunctionCall *> calls = func->incomingCalls();
+ for (const FunctionCall *call : calls) {
if (call->caller() == m_function) {
isValid = true;
break;
diff --git a/src/plugins/valgrind/callgrindengine.cpp b/src/plugins/valgrind/callgrindengine.cpp
index 61ecb13a3e2..8aafa076ae7 100644
--- a/src/plugins/valgrind/callgrindengine.cpp
+++ b/src/plugins/valgrind/callgrindengine.cpp
@@ -25,10 +25,8 @@
#include "callgrindengine.h"
-#include "callgrindtool.h"
#include "valgrindsettings.h"
-#include <valgrind/callgrind/callgrindcontroller.h>
#include <valgrind/callgrind/callgrindparser.h>
#include <valgrind/valgrindrunner.h>
@@ -37,6 +35,11 @@
#include <utils/filepath.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
+#include <utils/temporaryfile.h>
+
+#include <QDebug>
+
+#define CALLGRIND_CONTROL_DEBUG 0
using namespace ProjectExplorer;
using namespace Valgrind::Callgrind;
@@ -45,6 +48,8 @@ using namespace Utils;
namespace Valgrind {
namespace Internal {
+const char CALLGRIND_CONTROL_BINARY[] = "callgrind_control";
+
void setupCallgrindRunner(CallgrindToolRunner *);
CallgrindToolRunner::CallgrindToolRunner(RunControl *runControl)
@@ -52,34 +57,30 @@ CallgrindToolRunner::CallgrindToolRunner(RunControl *runControl)
{
setId("CallgrindToolRunner");
- connect(&m_runner, &ValgrindRunner::finished,
- this, &CallgrindToolRunner::slotFinished);
- connect(&m_parser, &Callgrind::Parser::parserDataReady,
- this, &CallgrindToolRunner::slotFinished);
-
- connect(&m_controller, &CallgrindController::finished,
- this, &CallgrindToolRunner::controllerFinished);
- connect(&m_controller, &CallgrindController::localParseDataAvailable,
- this, &CallgrindToolRunner::handleLocalParseData);
- connect(&m_controller, &CallgrindController::statusMessage,
- this, &CallgrindToolRunner::showStatusMessage);
-
- connect(&m_runner, &ValgrindRunner::valgrindStarted,
- &m_controller, &CallgrindController::setValgrindPid);
-
- connect(&m_runner, &ValgrindRunner::extraProcessFinished, this, [this] {
+ connect(&m_runner, &ValgrindRunner::valgrindStarted, this, [this](qint64 pid) {
+ m_pid = pid;
+ });
+ connect(&m_runner, &ValgrindRunner::finished, this, [this] {
triggerParse();
+ emit parserDataReady(this);
+ });
+ connect(&m_parser, &Callgrind::Parser::parserDataReady, this, [this] {
+ emit parserDataReady(this);
});
- m_controller.setValgrindRunnable(runnable());
+ m_valgrindRunnable = runControl->runnable();
static int fileCount = 100;
- m_valgrindOutputFile = runnable().workingDirectory / QString("callgrind.out.f%1").arg(++fileCount);
- m_controller.setValgrindOutputFile(m_valgrindOutputFile);
+ m_valgrindOutputFile = runControl->workingDirectory() / QString("callgrind.out.f%1").arg(++fileCount);
setupCallgrindRunner(this);
}
+CallgrindToolRunner::~CallgrindToolRunner()
+{
+ cleanupTempFile();
+}
+
QStringList CallgrindToolRunner::toolArguments() const
{
QStringList arguments = {"--tool=callgrind"};
@@ -105,7 +106,7 @@ QStringList CallgrindToolRunner::toolArguments() const
arguments << "--callgrind-out-file=" + m_valgrindOutputFile.path();
- arguments << Utils::ProcessArgs::splitArgs(m_settings.callgrindArguments.value());
+ arguments << ProcessArgs::splitArgs(m_settings.callgrindArguments.value());
return arguments;
}
@@ -117,15 +118,11 @@ QString CallgrindToolRunner::progressTitle() const
void CallgrindToolRunner::start()
{
- appendMessage(tr("Profiling %1").arg(executable().toUserOutput()), Utils::NormalMessageFormat);
+ const FilePath executable = runControl()->commandLine().executable();
+ appendMessage(tr("Profiling %1").arg(executable.toUserOutput()), NormalMessageFormat);
return ValgrindToolRunner::start();
}
-void CallgrindToolRunner::dump()
-{
- m_controller.run(CallgrindController::Dump);
-}
-
void CallgrindToolRunner::setPaused(bool paused)
{
if (m_markAsPaused == paused)
@@ -148,64 +145,153 @@ void CallgrindToolRunner::setToggleCollectFunction(const QString &toggleCollectF
m_argumentForToggleCollect = "--toggle-collect=" + toggleCollectFunction;
}
-void CallgrindToolRunner::reset()
+Callgrind::ParseData *CallgrindToolRunner::takeParserData()
{
- m_controller.run(Callgrind::CallgrindController::ResetEventCounters);
+ return m_parser.takeData();
}
-void CallgrindToolRunner::pause()
+void CallgrindToolRunner::showStatusMessage(const QString &message)
{
- m_controller.run(Callgrind::CallgrindController::Pause);
+ Debugger::showPermanentStatusMessage(message);
}
-void CallgrindToolRunner::unpause()
+static QString toOptionString(CallgrindToolRunner::Option option)
{
- m_controller.run(Callgrind::CallgrindController::UnPause);
+ /* callgrind_control help from v3.9.0
+
+ Options:
+ -h --help Show this help text
+ --version Show version
+ -s --stat Show statistics
+ -b --back Show stack/back trace
+ -e [<A>,...] Show event counters for <A>,... (default: all)
+ --dump[=<s>] Request a dump optionally using <s> as description
+ -z --zero Zero all event counters
+ -k --kill Kill
+ --instr=<on|off> Switch instrumentation state on/off
+ */
+
+ switch (option) {
+ case CallgrindToolRunner::Dump:
+ return QLatin1String("--dump");
+ case CallgrindToolRunner::ResetEventCounters:
+ return QLatin1String("--zero");
+ case CallgrindToolRunner::Pause:
+ return QLatin1String("--instr=off");
+ case CallgrindToolRunner::UnPause:
+ return QLatin1String("--instr=on");
+ default:
+ return QString(); // never reached
+ }
}
-Callgrind::ParseData *CallgrindToolRunner::takeParserData()
+void CallgrindToolRunner::run(Option option)
{
- return m_parser.takeData();
-}
+ if (m_controllerProcess) {
+ showStatusMessage(tr("Previous command has not yet finished."));
+ return;
+ }
-void CallgrindToolRunner::slotFinished()
-{
- emit parserDataReady(this);
+ // save back current running operation
+ m_lastOption = option;
+
+ m_controllerProcess.reset(new QtcProcess);
+
+ switch (option) {
+ case CallgrindToolRunner::Dump:
+ showStatusMessage(tr("Dumping profile data..."));
+ break;
+ case CallgrindToolRunner::ResetEventCounters:
+ showStatusMessage(tr("Resetting event counters..."));
+ break;
+ case CallgrindToolRunner::Pause:
+ showStatusMessage(tr("Pausing instrumentation..."));
+ break;
+ case CallgrindToolRunner::UnPause:
+ showStatusMessage(tr("Unpausing instrumentation..."));
+ break;
+ default:
+ break;
+ }
+
+#if CALLGRIND_CONTROL_DEBUG
+ m_controllerProcess->setProcessChannelMode(QProcess::ForwardedChannels);
+#endif
+ connect(m_controllerProcess.get(), &QtcProcess::done,
+ this, &CallgrindToolRunner::controllerProcessDone);
+
+ const FilePath control =
+ FilePath(CALLGRIND_CONTROL_BINARY).onDevice(m_valgrindRunnable.command.executable());
+ m_controllerProcess->setCommand({control, {toOptionString(option), QString::number(m_pid)}});
+ m_controllerProcess->setWorkingDirectory(m_valgrindRunnable.workingDirectory);
+ m_controllerProcess->setEnvironment(m_valgrindRunnable.environment);
+ m_controllerProcess->start();
}
-void CallgrindToolRunner::showStatusMessage(const QString &message)
+void CallgrindToolRunner::controllerProcessDone()
{
- Debugger::showPermanentStatusMessage(message);
+ const QString error = m_controllerProcess->errorString();
+ const ProcessResult result = m_controllerProcess->result();
+
+ m_controllerProcess.release()->deleteLater();
+
+ if (result != ProcessResult::FinishedWithSuccess) {
+ showStatusMessage(tr("An error occurred while trying to run %1: %2").arg(CALLGRIND_CONTROL_BINARY).arg(error));
+ qWarning() << "Controller exited abnormally:" << error;
+ return;
+ }
+
+ // this call went fine, we might run another task after this
+ switch (m_lastOption) {
+ case ResetEventCounters:
+ // lets dump the new reset profiling info
+ run(Dump);
+ return;
+ case Pause:
+ m_paused = true;
+ break;
+ case Dump:
+ showStatusMessage(tr("Callgrind dumped profiling info"));
+ triggerParse();
+ break;
+ case UnPause:
+ m_paused = false;
+ showStatusMessage(tr("Callgrind unpaused."));
+ break;
+ default:
+ break;
+ }
+
+ m_lastOption = Unknown;
}
void CallgrindToolRunner::triggerParse()
{
- m_controller.getLocalDataFile();
-}
+ cleanupTempFile();
+ {
+ TemporaryFile dataFile("callgrind.out");
+ if (!dataFile.open()) {
+ showStatusMessage(tr("Failed opening temp file..."));
+ return;
+ }
+ m_hostOutputFile = FilePath::fromString(dataFile.fileName());
+ }
-void CallgrindToolRunner::handleLocalParseData(const FilePath &outputFile)
-{
- QTC_ASSERT(outputFile.exists(), return);
- showStatusMessage(tr("Parsing Profile Data..."));
- m_parser.parse(outputFile);
+ const auto afterCopy = [this](bool res) {
+ QTC_CHECK(res);
+ QTC_ASSERT(m_hostOutputFile.exists(), return);
+ showStatusMessage(tr("Parsing Profile Data..."));
+ m_parser.parse(m_hostOutputFile);
+ };
+ m_valgrindOutputFile.asyncCopyFile(afterCopy, m_hostOutputFile);
}
-void CallgrindToolRunner::controllerFinished(CallgrindController::Option option)
+void CallgrindToolRunner::cleanupTempFile()
{
- switch (option)
- {
- case CallgrindController::Pause:
- m_paused = true;
- break;
- case CallgrindController::UnPause:
- m_paused = false;
- break;
- case CallgrindController::Dump:
- triggerParse();
- break;
- default:
- break; // do nothing
- }
+ if (!m_hostOutputFile.isEmpty() && m_hostOutputFile.exists())
+ m_hostOutputFile.removeFile();
+
+ m_hostOutputFile.clear();
}
} // Internal
diff --git a/src/plugins/valgrind/callgrindengine.h b/src/plugins/valgrind/callgrindengine.h
index dfee79d95b2..1037b234167 100644
--- a/src/plugins/valgrind/callgrindengine.h
+++ b/src/plugins/valgrind/callgrindengine.h
@@ -26,11 +26,11 @@
#pragma once
#include "valgrindengine.h"
-#include "valgrindrunner.h"
#include "callgrind/callgrindparsedata.h"
#include "callgrind/callgrindparser.h"
-#include "callgrind/callgrindcontroller.h"
+
+#include <utils/qtcprocess.h>
namespace Valgrind {
namespace Internal {
@@ -41,16 +41,17 @@ class CallgrindToolRunner : public ValgrindToolRunner
public:
explicit CallgrindToolRunner(ProjectExplorer::RunControl *runControl);
+ ~CallgrindToolRunner() override;
void start() override;
Valgrind::Callgrind::ParseData *takeParserData();
/// controller actions
- void dump();
- void reset();
- void pause();
- void unpause();
+ void dump() { run(Dump); }
+ void reset() { run(ResetEventCounters); }
+ void pause() { run(Pause); }
+ void unpause() { run(UnPause); }
/// marks the callgrind process as paused
/// calls pause() and unpause() if there's an active run
@@ -58,6 +59,16 @@ public:
void setToggleCollectFunction(const QString &toggleCollectFunction);
+ enum Option {
+ Unknown,
+ Dump,
+ ResetEventCounters,
+ Pause,
+ UnPause
+ };
+
+ Q_ENUM(Option)
+
protected:
QStringList toolArguments() const override;
QString progressTitle() const override;
@@ -66,16 +77,34 @@ signals:
void parserDataReady(CallgrindToolRunner *engine);
private:
- void slotFinished();
void showStatusMessage(const QString &message);
+ /**
+ * Make data file available locally, triggers @c localParseDataAvailable.
+ *
+ * If the valgrind process was run remotely, this transparently
+ * downloads the data file first and returns a local path.
+ */
void triggerParse();
- void handleLocalParseData(const Utils::FilePath &filePath);
- void controllerFinished(Callgrind::CallgrindController::Option option);
+ void controllerFinished(Option option);
+
+ void run(Option option);
+
+ void cleanupTempFile();
+ void controllerProcessDone();
bool m_markAsPaused = false;
- Utils::FilePath m_valgrindOutputFile;
- Callgrind::CallgrindController m_controller;
+
+ std::unique_ptr<Utils::QtcProcess> m_controllerProcess;
+ ProjectExplorer::Runnable m_valgrindRunnable;
+ qint64 m_pid = 0;
+
+ Option m_lastOption = Unknown;
+
+ // remote callgrind support
+ Utils::FilePath m_valgrindOutputFile; // On the device that runs valgrind
+ Utils::FilePath m_hostOutputFile; // On the device that runs creator
+
Callgrind::Parser m_parser;
bool m_paused = false;
diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp
index d8498901d70..4819d356f06 100644
--- a/src/plugins/valgrind/callgrindtool.cpp
+++ b/src/plugins/valgrind/callgrindtool.cpp
@@ -75,6 +75,7 @@
#include <utils/fancymainwindow.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/styledbar.h>
#include <utils/utilsicons.h>
@@ -282,11 +283,10 @@ CallgrindToolPrivate::CallgrindToolPrivate()
return;
m_perspective.select();
auto runControl = new RunControl(CALLGRIND_RUN_MODE);
- runControl->setRunConfiguration(runConfig);
+ runControl->copyDataFromRunConfiguration(runConfig);
runControl->createMainWorker();
- const auto runnable = dlg.runnable();
- runControl->setRunnable(runnable);
- runControl->setDisplayName(runnable.command.executable().toUserOutput());
+ runControl->setCommandLine(dlg.commandLine());
+ runControl->setWorkingDirectory(dlg.workingDirectory());
ProjectExplorerPlugin::startRunControl(runControl);
});
@@ -734,7 +734,8 @@ void CallgrindToolPrivate::updateEventCombo()
}
m_eventCombo->show();
- foreach (const QString &event, data->events())
+ const QStringList events = data->events();
+ for (const QString &event : events)
m_eventCombo->addItem(ParseData::prettyStringForEvent(event));
}
@@ -847,7 +848,7 @@ void CallgrindToolPrivate::editorOpened(IEditor *editor)
void CallgrindToolPrivate::requestContextMenu(TextEditorWidget *widget, int line, QMenu *menu)
{
// Find callgrind text mark that corresponds to this editor's file and line number
- foreach (CallgrindTextMark *textMark, m_textMarks) {
+ for (CallgrindTextMark *textMark : qAsConst(m_textMarks)) {
if (textMark->fileName() == widget->textDocument()->filePath() && textMark->lineNumber() == line) {
const Function *func = textMark->function();
QAction *action = menu->addAction(CallgrindTool::tr("Select This Function in the Analyzer Output"));
@@ -863,7 +864,7 @@ void CallgrindToolPrivate::handleShowCostsOfFunction()
if (!symbol)
return;
- if (!symbol->isFunction())
+ if (!symbol->asFunction())
return;
CPlusPlus::Overview view;
diff --git a/src/plugins/valgrind/callgrindvisualisation.cpp b/src/plugins/valgrind/callgrindvisualisation.cpp
index 4d829394c5d..e159b153b3b 100644
--- a/src/plugins/valgrind/callgrindvisualisation.cpp
+++ b/src/plugins/valgrind/callgrindvisualisation.cpp
@@ -236,7 +236,8 @@ void Visualization::Private::handleMousePressEvent(QMouseEvent *event,
{
// find the first item that accepts mouse presses under the cursor position
QGraphicsItem *itemAtPos = nullptr;
- foreach (QGraphicsItem *item, q->items(event->pos())) {
+ const QList<QGraphicsItem *>items = q->items(event->pos());
+ for (QGraphicsItem *item : items) {
if (!(item->acceptedMouseButtons() & event->button()))
continue;
@@ -291,7 +292,8 @@ const Function *Visualization::functionForItem(QGraphicsItem *item) const
QGraphicsItem *Visualization::itemForFunction(const Function *function) const
{
- foreach (QGraphicsItem *item, items()) {
+ const QList<QGraphicsItem *> itemList = items();
+ for (QGraphicsItem *item : itemList) {
if (functionForItem(item) == function)
return item;
}
diff --git a/src/plugins/valgrind/memcheckerrorview.cpp b/src/plugins/valgrind/memcheckerrorview.cpp
index 19e3199b72b..951136f8c6e 100644
--- a/src/plugins/valgrind/memcheckerrorview.cpp
+++ b/src/plugins/valgrind/memcheckerrorview.cpp
@@ -100,7 +100,7 @@ QList<QAction *> MemcheckErrorView::customActions() const
QTC_ASSERT(!indizes.isEmpty(), return actions);
bool hasErrors = false;
- foreach (const QModelIndex &index, indizes) {
+ for (const QModelIndex &index : indizes) {
Error error = model()->data(index, ErrorListModel::ErrorRole).value<Error>();
if (!error.suppression().isNull()) {
hasErrors = true;
diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp
index bfa440c25fc..1cd50e2a19b 100644
--- a/src/plugins/valgrind/memchecktool.cpp
+++ b/src/plugins/valgrind/memchecktool.cpp
@@ -28,7 +28,6 @@
#include "memcheckerrorview.h"
#include "valgrindsettings.h"
-#include "valgrindplugin.h"
#include "valgrindengine.h"
#include "valgrindsettings.h"
#include "valgrindrunner.h"
@@ -38,9 +37,6 @@
#include "xmlprotocol/errorlistmodel.h"
#include "xmlprotocol/frame.h"
#include "xmlprotocol/stack.h"
-#include "xmlprotocol/stackmodel.h"
-#include "xmlprotocol/status.h"
-#include "xmlprotocol/suppression.h"
#include "xmlprotocol/threadedparser.h"
#include <debugger/debuggerkitinformation.h>
@@ -51,9 +47,11 @@
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/deploymentdata.h>
+#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -71,13 +69,11 @@
#include <coreplugin/icore.h>
#include <coreplugin/modemanager.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshconnectionmanager.h>
-
#include <utils/checkablemessagebox.h>
#include <utils/fancymainwindow.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/utilsicons.h>
#include <QAction>
@@ -155,37 +151,38 @@ public:
void start() override
{
- m_connection = QSsh::SshConnectionManager::acquireConnection(device()->sshParameters());
- if (!m_connection) {
- reportFailure();
- return;
- }
-
- connect(m_connection, &QSsh::SshConnection::errorOccurred, this, [this] {
- reportFailure();
- });
-
- auto connected = [this] {
- *m_localServerAddress = m_connection->connectionInfo().localAddress;
+ QTC_ASSERT(!m_process, return);
+ m_process.reset(new QtcProcess);
+ m_process->setCommand({device()->filePath("echo"), "-n $SSH_CLIENT", CommandLine::Raw});
+ connect(m_process.get(), &QtcProcess::done, this, [this] {
+ if (m_process->error() != QProcess::UnknownError) {
+ reportFailure();
+ return;
+ }
+ const QByteArrayList data = m_process->readAllStandardOutput().split(' ');
+ if (data.size() != 3) {
+ reportFailure();
+ return;
+ }
+ QHostAddress hostAddress;
+ if (!hostAddress.setAddress(QString::fromLatin1(data.first()))) {
+ reportFailure();
+ return;
+ }
+ *m_localServerAddress = hostAddress;
reportStarted();
- };
- if (m_connection->state() == QSsh::SshConnection::Connected) {
- connected();
- } else {
- connect(m_connection, &QSsh::SshConnection::connected, this, connected);
- m_connection->connectToHost();
- }
+ m_process.release()->deleteLater();
+ });
+ m_process->start();
}
void stop() override
{
- if (m_connection)
- QSsh::SshConnectionManager::releaseConnection(m_connection);
reportStopped();
}
private:
- QSsh::SshConnection *m_connection = nullptr;
+ std::unique_ptr<QtcProcess> m_process = nullptr;
QHostAddress *m_localServerAddress = nullptr;
};
@@ -284,7 +281,7 @@ static ErrorListModel::RelevantFrameFinder makeFrameFinder(const QStringList &pr
//find the first frame belonging to the project
if (!projectFiles.isEmpty()) {
- foreach (const Frame &frame, frames) {
+ for (const Frame &frame : frames) {
if (frame.directory().isEmpty() || frame.fileName().isEmpty())
continue;
@@ -296,7 +293,7 @@ static ErrorListModel::RelevantFrameFinder makeFrameFinder(const QStringList &pr
}
//if no frame belonging to the project was found, return the first one that is not malloc/new
- foreach (const Frame &frame, frames) {
+ for (const Frame &frame : frames) {
if (!frame.functionName().isEmpty() && frame.functionName() != "malloc"
&& !frame.functionName().startsWith("operator new("))
{
@@ -365,9 +362,10 @@ bool MemcheckErrorFilterProxyModel::filterAcceptsRow(int sourceRow, const QModel
QSet<QString> validFolders;
for (Project *project : SessionManager::projects()) {
validFolders << project->projectDirectory().toString();
- foreach (Target *target, project->targets()) {
- foreach (const DeployableFile &file,
- target->deploymentData().allFiles()) {
+ const QList<Target *> targets = project->targets();
+ for (const Target *target : targets) {
+ const QList<DeployableFile> files = target->deploymentData().allFiles();
+ for (const DeployableFile &file : files) {
if (file.isExecutable())
validFolders << file.remoteDirectory();
}
@@ -383,7 +381,7 @@ bool MemcheckErrorFilterProxyModel::filterAcceptsRow(int sourceRow, const QModel
bool inProject = false;
for (int i = 0; i < framesToLookAt; ++i) {
const Frame &frame = frames.at(i);
- foreach (const QString &folder, validFolders) {
+ for (const QString &folder : qAsConst(validFolders)) {
if (frame.directory().startsWith(folder)) {
inProject = true;
break;
@@ -633,7 +631,7 @@ MemcheckToolPrivate::MemcheckToolPrivate()
filterButton->setProperty("noArrow", true);
m_filterMenu = new QMenu(filterButton);
- foreach (QAction *filterAction, m_errorFilterActions)
+ for (QAction *filterAction : qAsConst(m_errorFilterActions))
m_filterMenu->addAction(filterAction);
m_filterMenu->addSeparator();
m_filterMenu->addAction(m_filterProjectAction);
@@ -708,11 +706,10 @@ MemcheckToolPrivate::MemcheckToolPrivate()
TaskHub::clearTasks(Debugger::Constants::ANALYZERTASK_ID);
m_perspective.select();
RunControl *rc = new RunControl(MEMCHECK_RUN_MODE);
- rc->setRunConfiguration(runConfig);
+ rc->copyDataFromRunConfiguration(runConfig);
rc->createMainWorker();
- const auto runnable = dlg.runnable();
- rc->setRunnable(runnable);
- rc->setDisplayName(runnable.command.executable().toUserOutput());
+ rc->setCommandLine(dlg.commandLine());
+ rc->setWorkingDirectory(dlg.workingDirectory());
ProjectExplorerPlugin::startRunControl(rc);
});
@@ -745,10 +742,9 @@ void MemcheckToolPrivate::heobAction()
kit = target->kit();
if (kit) {
abi = ToolChainKitAspect::targetAbi(kit);
-
- const Runnable runnable = rc->runnable();
- sr = runnable;
- const IDevice::ConstPtr device = sr.device;
+ sr = rc->runnable();
+ const IDevice::ConstPtr device
+ = DeviceManager::deviceForPath(sr.command.executable());
hasLocalRc = device && device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
if (!hasLocalRc)
hasLocalRc = DeviceTypeKitAspect::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
@@ -934,9 +930,10 @@ void MemcheckToolPrivate::settingsDestroyed(QObject *settings)
void MemcheckToolPrivate::updateFromSettings()
{
- foreach (QAction *action, m_errorFilterActions) {
+ for (QAction *action : qAsConst(m_errorFilterActions)) {
bool contained = true;
- foreach (const QVariant &v, action->data().toList()) {
+ const QList<QVariant> actions = action->data().toList();
+ for (const QVariant &v : actions) {
bool ok;
int kind = v.toInt(&ok);
if (ok && !m_settings->visibleErrorKinds.value().contains(kind))
@@ -1012,7 +1009,7 @@ void MemcheckToolPrivate::setupRunner(MemcheckToolRunner *runTool)
m_loadExternalLogFile->setDisabled(true);
const FilePath dir = runControl->project()->projectDirectory();
- const QString name = runTool->executable().fileName();
+ const QString name = runControl->commandLine().executable().fileName();
m_errorView->setDefaultSuppressionFile(dir.pathAppended(name + ".supp"));
@@ -1119,10 +1116,11 @@ void MemcheckToolPrivate::updateErrorFilter()
m_settings->filterExternalIssues.setValue(!m_filterProjectAction->isChecked());
QList<int> errorKinds;
- foreach (QAction *a, m_errorFilterActions) {
+ for (QAction *a : qAsConst(m_errorFilterActions)) {
if (!a->isChecked())
continue;
- foreach (const QVariant &v, a->data().toList()) {
+ const QList<QVariant> actions = a->data().toList();
+ for (const QVariant &v : actions) {
bool ok;
int kind = v.toInt(&ok);
if (ok)
@@ -1669,7 +1667,6 @@ void HeobData::processFinished()
auto debugger = new DebuggerRunTool(m_runControl);
debugger->setAttachPid(ProcessHandle(m_data[1]));
debugger->setRunControlName(tr("Process %1").arg(m_data[1]));
- debugger->setInferiorDevice(DeviceKitAspect::device(m_kit));
debugger->setStartMode(AttachToLocalProcess);
debugger->setCloseMode(DetachAtClose);
debugger->setContinueAfterAttach(true);
diff --git a/src/plugins/valgrind/memchecktool.h b/src/plugins/valgrind/memchecktool.h
index 99808a97c20..1e4e245cd78 100644
--- a/src/plugins/valgrind/memchecktool.h
+++ b/src/plugins/valgrind/memchecktool.h
@@ -26,7 +26,7 @@
#pragma once
-#include <QCoreApplication>
+#include <QObject>
namespace Valgrind {
namespace Internal {
diff --git a/src/plugins/valgrind/valgrind.qbs b/src/plugins/valgrind/valgrind.qbs
index 65573c31415..8830ba2b8b3 100644
--- a/src/plugins/valgrind/valgrind.qbs
+++ b/src/plugins/valgrind/valgrind.qbs
@@ -6,7 +6,6 @@ QtcPlugin {
Depends { name: "Qt"; submodules: ["widgets", "network"] }
Depends { name: "CPlusPlus"}
- Depends { name: "QtcSsh" }
Depends { name: "Utils" }
Depends { name: "Core" }
@@ -45,7 +44,6 @@ QtcPlugin {
files: [
"callgrindabstractmodel.h",
"callgrindcallmodel.cpp", "callgrindcallmodel.h",
- "callgrindcontroller.cpp", "callgrindcontroller.h",
"callgrindcostitem.cpp", "callgrindcostitem.h",
"callgrindcycledetection.cpp", "callgrindcycledetection.h",
"callgrinddatamodel.cpp", "callgrinddatamodel.h",
diff --git a/src/plugins/valgrind/valgrindengine.cpp b/src/plugins/valgrind/valgrindengine.cpp
index 6b34dc809dc..fdb147e1c74 100644
--- a/src/plugins/valgrind/valgrindengine.cpp
+++ b/src/plugins/valgrind/valgrindengine.cpp
@@ -26,7 +26,6 @@
#include "valgrindengine.h"
#include "valgrindsettings.h"
-#include "valgrindplugin.h"
#include <debugger/analyzer/analyzermanager.h>
@@ -36,6 +35,8 @@
#include <coreplugin/progressmanager/futureprogress.h>
#include <extensionsystem/pluginmanager.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorericons.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/runconfigurationaspects.h>
@@ -59,6 +60,17 @@ ValgrindToolRunner::ValgrindToolRunner(RunControl *runControl)
setSupportsReRunning(false);
m_settings.fromMap(runControl->settingsData(ANALYZER_VALGRIND_SETTINGS));
+
+ connect(&m_runner, &ValgrindRunner::appendMessage,
+ this, &ValgrindToolRunner::appendMessage);
+ connect(&m_runner, &ValgrindRunner::valgrindExecuted,
+ this, [this](const QString &commandLine) {
+ appendMessage(commandLine, NormalMessageFormat);
+ });
+ connect(&m_runner, &ValgrindRunner::processErrorReceived,
+ this, &ValgrindToolRunner::receiveProcessError);
+ connect(&m_runner, &ValgrindRunner::finished,
+ this, &ValgrindToolRunner::runnerFinished);
}
void ValgrindToolRunner::start()
@@ -77,28 +89,21 @@ void ValgrindToolRunner::start()
emit outputReceived(tr("Command line arguments: %1").arg(runnable().debuggeeArgs), LogMessageFormat);
#endif
- CommandLine valgrind{m_settings.valgrindExecutable.filePath()};
+
+ FilePath valgrindExecutable = m_settings.valgrindExecutable.filePath();
+ if (IDevice::ConstPtr dev = DeviceKitAspect::device(runControl()->kit()))
+ valgrindExecutable = dev->filePath(valgrindExecutable.path());
+
+ CommandLine valgrind{valgrindExecutable};
valgrind.addArgs(m_settings.valgrindArguments.value(), CommandLine::Raw);
valgrind.addArgs(genericToolArguments());
valgrind.addArgs(toolArguments());
m_runner.setValgrindCommand(valgrind);
- m_runner.setDevice(device());
- m_runner.setDebuggee(runnable());
+ m_runner.setDebuggee(runControl()->runnable());
if (auto aspect = runControl()->aspect<TerminalAspect>())
- m_runner.setUseTerminal(aspect->useTerminal());
-
- connect(&m_runner, &ValgrindRunner::processOutputReceived,
- this, &ValgrindToolRunner::receiveProcessOutput);
- connect(&m_runner, &ValgrindRunner::valgrindExecuted,
- this, [this](const QString &commandLine) {
- appendMessage(commandLine, NormalMessageFormat);
- });
- connect(&m_runner, &ValgrindRunner::processErrorReceived,
- this, &ValgrindToolRunner::receiveProcessError);
- connect(&m_runner, &ValgrindRunner::finished,
- this, &ValgrindToolRunner::runnerFinished);
+ m_runner.setUseTerminal(aspect->useTerminal);
if (!m_runner.start()) {
m_progress.cancel();
@@ -115,11 +120,6 @@ void ValgrindToolRunner::stop()
m_runner.stop();
}
-FilePath ValgrindToolRunner::executable() const
-{
- return runnable().command.executable();
-}
-
QStringList ValgrindToolRunner::genericToolArguments() const
{
QString smcCheckValue;
@@ -159,19 +159,9 @@ void ValgrindToolRunner::runnerFinished()
m_progress.reportFinished();
- disconnect(&m_runner, &ValgrindRunner::processOutputReceived,
- this, &ValgrindToolRunner::receiveProcessOutput);
- disconnect(&m_runner, &ValgrindRunner::finished,
- this, &ValgrindToolRunner::runnerFinished);
-
reportStopped();
}
-void ValgrindToolRunner::receiveProcessOutput(const QString &output, OutputFormat format)
-{
- appendMessage(output, format);
-}
-
void ValgrindToolRunner::receiveProcessError(const QString &message, QProcess::ProcessError error)
{
if (error == QProcess::FailedToStart) {
diff --git a/src/plugins/valgrind/valgrindengine.h b/src/plugins/valgrind/valgrindengine.h
index 4eb3a119a4c..8bb050405af 100644
--- a/src/plugins/valgrind/valgrindengine.h
+++ b/src/plugins/valgrind/valgrindengine.h
@@ -47,8 +47,6 @@ public:
void start() override;
void stop() override;
- Utils::FilePath executable() const;
-
protected:
virtual QString progressTitle() const = 0;
virtual QStringList toolArguments() const = 0;
@@ -62,7 +60,6 @@ private:
void handleProgressFinished();
void runnerFinished();
- void receiveProcessOutput(const QString &output, Utils::OutputFormat format);
void receiveProcessError(const QString &message, QProcess::ProcessError error);
QStringList genericToolArguments() const;
diff --git a/src/plugins/valgrind/valgrindmemcheckparsertest.cpp b/src/plugins/valgrind/valgrindmemcheckparsertest.cpp
index 4ca3d768126..4218f75b211 100644
--- a/src/plugins/valgrind/valgrindmemcheckparsertest.cpp
+++ b/src/plugins/valgrind/valgrindmemcheckparsertest.cpp
@@ -31,7 +31,6 @@
#include "xmlprotocol/stack.h"
#include "xmlprotocol/suppression.h"
-#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/runconfiguration.h>
@@ -483,8 +482,6 @@ void ValgrindMemcheckParserTest::testParserStop()
"-i", dataFile("memcheck-output-sample1.xml"), "--wait", "5" }});
runner.setProcessChannelMode(QProcess::ForwardedChannels);
- runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
- ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE));
runner.start();
QTest::qWait(500);
runner.stop();
@@ -505,8 +502,6 @@ void ValgrindMemcheckParserTest::testRealValgrind()
ValgrindRunner runner;
runner.setValgrindCommand({"valgrind", {}});
runner.setDebuggee(debuggee);
- runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
- ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE));
RunnerDumper dumper(&runner);
runner.start();
runner.waitForFinished();
@@ -544,8 +539,6 @@ void ValgrindMemcheckParserTest::testValgrindStartError()
ValgrindRunner runner;
runner.setValgrindCommand({FilePath::fromString(valgrindExe), valgrindArgs});
runner.setDebuggee(debuggeeExecutable);
- runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
- ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE));
RunnerDumper dumper(&runner);
runner.start();
runner.waitForFinished();
diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp
index 95cfcc0faf5..f606789cf11 100644
--- a/src/plugins/valgrind/valgrindrunner.cpp
+++ b/src/plugins/valgrind/valgrindrunner.cpp
@@ -44,49 +44,98 @@ namespace Valgrind {
class ValgrindRunner::Private : public QObject
{
public:
- Private(ValgrindRunner *owner) : q(owner) {}
+ Private(ValgrindRunner *owner) : q(owner) {
+ connect(&m_process, &QtcProcess::started, this, [this] {
+ emit q->valgrindStarted(m_process.processId());
+ });
+ connect(&m_process, &QtcProcess::done, this, [this] {
+ if (m_process.result() != ProcessResult::FinishedWithSuccess)
+ emit q->processErrorReceived(m_process.errorString(), m_process.error());
+ emit q->finished();
+ });
+ connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
+ emit q->appendMessage(QString::fromUtf8(m_process.readAllStandardOutput()),
+ StdOutFormat);
+ });
+ connect(&m_process, &QtcProcess::readyReadStandardError, this, [this] {
+ emit q->appendMessage(QString::fromUtf8(m_process.readAllStandardError()),
+ StdErrFormat);
+ });
+
+ connect(&m_xmlServer, &QTcpServer::newConnection, this, &Private::xmlSocketConnected);
+ connect(&m_logServer, &QTcpServer::newConnection, this, &Private::logSocketConnected);
+ }
+ void xmlSocketConnected();
+ void logSocketConnected();
+ bool startServers();
bool run();
- void processStarted();
- void localProcessStarted();
- void remoteProcessStarted();
- void findPidOutputReceived(const QString &out, Utils::OutputFormat format);
-
ValgrindRunner *q;
Runnable m_debuggee;
- ApplicationLauncher m_valgrindProcess;
- IDevice::ConstPtr m_device;
- ApplicationLauncher m_findPID;
+ CommandLine m_command;
+ QtcProcess m_process;
- CommandLine m_valgrindCommand;
+ QHostAddress m_localServerAddress;
- QHostAddress localServerAddress;
- QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels;
- bool m_finished = false;
+ QTcpServer m_xmlServer;
+ XmlProtocol::ThreadedParser m_parser;
+ QTcpServer m_logServer;
+};
+
+void ValgrindRunner::Private::xmlSocketConnected()
+{
+ QTcpSocket *socket = m_xmlServer.nextPendingConnection();
+ QTC_ASSERT(socket, return);
+ m_xmlServer.close();
+ m_parser.parse(socket);
+}
- QTcpServer xmlServer;
- XmlProtocol::ThreadedParser parser;
- QTcpServer logServer;
- QTcpSocket *logSocket = nullptr;
+void ValgrindRunner::Private::logSocketConnected()
+{
+ QTcpSocket *logSocket = m_logServer.nextPendingConnection();
+ QTC_ASSERT(logSocket, return);
+ connect(logSocket, &QIODevice::readyRead, this, [this, logSocket] {
+ emit q->logMessageReceived(logSocket->readAll());
+ });
+ m_logServer.close();
+}
- // Workaround for valgrind bug when running vgdb with xml output
- // https://bugs.kde.org/show_bug.cgi?id=343902
- bool disableXml = false;
-};
+bool ValgrindRunner::Private::startServers()
+{
+ const bool xmlOK = m_xmlServer.listen(m_localServerAddress);
+ const QString ip = m_localServerAddress.toString();
+ if (!xmlOK) {
+ emit q->processErrorReceived(tr("XmlServer on %1:").arg(ip) + ' '
+ + m_xmlServer.errorString(), QProcess::FailedToStart );
+ return false;
+ }
+ m_xmlServer.setMaxPendingConnections(1);
+ const bool logOK = m_logServer.listen(m_localServerAddress);
+ if (!logOK) {
+ emit q->processErrorReceived(tr("LogServer on %1:").arg(ip) + ' '
+ + m_logServer.errorString(), QProcess::FailedToStart );
+ return false;
+ }
+ m_logServer.setMaxPendingConnections(1);
+ return true;
+}
bool ValgrindRunner::Private::run()
{
- CommandLine cmd{m_valgrindCommand.executable(), {}};
+ CommandLine cmd;
+ cmd.setExecutable(m_command.executable());
- if (!localServerAddress.isNull()) {
- if (!q->startServers())
+ if (!m_localServerAddress.isNull()) {
+ if (!startServers())
return false;
cmd.addArg("--child-silent-after-fork=yes");
- bool enableXml = !disableXml;
+ // Workaround for valgrind bug when running vgdb with xml output
+ // https://bugs.kde.org/show_bug.cgi?id=343902
+ bool enableXml = true;
auto handleSocketParameter = [&enableXml, &cmd](const QString &prefix, const QTcpServer &tcpServer)
{
@@ -102,119 +151,33 @@ bool ValgrindRunner::Private::run()
}
};
- handleSocketParameter("--xml-socket", xmlServer);
- handleSocketParameter("--log-socket", logServer);
+ handleSocketParameter("--xml-socket", m_xmlServer);
+ handleSocketParameter("--log-socket", m_logServer);
if (enableXml)
cmd.addArg("--xml=yes");
}
- cmd.addArgs(m_valgrindCommand.arguments(), CommandLine::Raw);
+ cmd.addArgs(m_command.arguments(), CommandLine::Raw);
- m_valgrindProcess.setProcessChannelMode(channelMode);
// consider appending our options last so they override any interfering user-supplied options
// -q as suggested by valgrind manual
- connect(&m_valgrindProcess, &ApplicationLauncher::processExited,
- q, &ValgrindRunner::processFinished);
- connect(&m_valgrindProcess, &ApplicationLauncher::processStarted,
- this, &ValgrindRunner::Private::processStarted);
- connect(&m_valgrindProcess, &ApplicationLauncher::error,
- q, &ValgrindRunner::processError);
- connect(&m_valgrindProcess, &ApplicationLauncher::appendMessage,
- q, &ValgrindRunner::processOutputReceived);
-
- if (HostOsInfo::isMacHost())
+ if (cmd.executable().osType() == OsTypeMac) {
// May be slower to start but without it we get no filenames for symbols.
cmd.addArg("--dsymutil=yes");
+ }
cmd.addCommandLineAsArgs(m_debuggee.command);
emit q->valgrindExecuted(cmd.toUserOutput());
- Runnable valgrind;
- valgrind.command = cmd;
- valgrind.workingDirectory = m_debuggee.workingDirectory;
- valgrind.environment = m_debuggee.environment;
- valgrind.device = m_device;
-
- if (m_device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
- m_valgrindProcess.start(valgrind);
- } else if (m_device->type() == "DockerDeviceType") {
- valgrind.device = {};
- m_valgrindProcess.start(valgrind);
- } else {
- m_valgrindProcess.start(valgrind, m_device);
- }
-
+ m_process.setCommand(cmd);
+ m_process.setWorkingDirectory(m_debuggee.workingDirectory);
+ m_process.setEnvironment(m_debuggee.environment);
+ m_process.start();
return true;
}
-void ValgrindRunner::Private::processStarted()
-{
- if (m_valgrindProcess.isLocal())
- localProcessStarted();
- else
- remoteProcessStarted();
-}
-
-void ValgrindRunner::Private::localProcessStarted()
-{
- qint64 pid = m_valgrindProcess.applicationPID().pid();
- emit q->valgrindStarted(pid);
-}
-
-void ValgrindRunner::Private::remoteProcessStarted()
-{
- // find out what PID our process has
-
- // NOTE: valgrind cloaks its name,
- // e.g.: valgrind --tool=memcheck foobar
- // => ps aux, pidof will see valgrind.bin
- // => pkill/killall/top... will see memcheck-amd64-linux or similar
- // hence we need to do something more complex...
-
- // plain path to exe, m_valgrindExe contains e.g. env vars etc. pp.
- // FIXME: Really?
- const QString proc = m_valgrindCommand.executable().toString().split(' ').last();
- QString procEscaped = proc;
- procEscaped.replace("/", "\\\\/");
-
- Runnable findPid;
- // sleep required since otherwise we might only match "bash -c..." and not the actual
- // valgrind run
- findPid.command.setExecutable("/bin/sh");
- findPid.command.setArguments(QString("-c \""
- "sleep 1; ps ax" // list all processes with aliased name
- " | grep '%1.*%2'" // find valgrind process that runs with our exec
- " | awk '\\$5 ~ /^%3/" // 5th column must start with valgrind process
- " {print \\$1;}'" // print 1st then (with PID)
- "\"").arg(proc, m_debuggee.command.executable().fileName(), procEscaped));
-
-// m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8());
- connect(&m_findPID, &ApplicationLauncher::appendMessage,
- this, &ValgrindRunner::Private::findPidOutputReceived);
- m_findPID.start(findPid, m_device);
-}
-
-void ValgrindRunner::Private::findPidOutputReceived(const QString &out, Utils::OutputFormat format)
-{
- if (format != Utils::StdOutFormat) {
- emit q->processOutputReceived(out, format);
- return;
- }
- if (out.isEmpty())
- return;
- bool ok;
- const qint64 pid = out.trimmed().toLongLong(&ok);
- if (!ok) {
-// m_remote.m_errorString = tr("Could not determine remote PID.");
-// emit ValgrindRunner::Private::error(QProcess::FailedToStart);
-// close();
- } else {
- emit q->valgrindStarted(pid);
- }
-}
-
ValgrindRunner::ValgrindRunner(QObject *parent)
: QObject(parent), d(new Private(this))
{
@@ -222,11 +185,11 @@ ValgrindRunner::ValgrindRunner(QObject *parent)
ValgrindRunner::~ValgrindRunner()
{
- if (d->m_valgrindProcess.isRunning()) {
+ if (d->m_process.isRunning()) {
// make sure we don't delete the thread while it's still running
waitForFinished();
}
- if (d->parser.isRunning()) {
+ if (d->m_parser.isRunning()) {
// make sure we don't delete the thread while it's still running
waitForFinished();
}
@@ -234,9 +197,9 @@ ValgrindRunner::~ValgrindRunner()
d = nullptr;
}
-void ValgrindRunner::setValgrindCommand(const Utils::CommandLine &command)
+void ValgrindRunner::setValgrindCommand(const CommandLine &command)
{
- d->m_valgrindCommand = command;
+ d->m_command = command;
}
void ValgrindRunner::setDebuggee(const Runnable &debuggee)
@@ -246,27 +209,22 @@ void ValgrindRunner::setDebuggee(const Runnable &debuggee)
void ValgrindRunner::setProcessChannelMode(QProcess::ProcessChannelMode mode)
{
- d->channelMode = mode;
+ d->m_process.setProcessChannelMode(mode);
}
void ValgrindRunner::setLocalServerAddress(const QHostAddress &localServerAddress)
{
- d->localServerAddress = localServerAddress;
-}
-
-void ValgrindRunner::setDevice(const IDevice::ConstPtr &device)
-{
- d->m_device = device;
+ d->m_localServerAddress = localServerAddress;
}
void ValgrindRunner::setUseTerminal(bool on)
{
- d->m_valgrindProcess.setUseTerminal(on);
+ d->m_process.setTerminalMode(on ? TerminalMode::On : TerminalMode::Off);
}
void ValgrindRunner::waitForFinished() const
{
- if (d->m_finished)
+ if (d->m_process.state() == QProcess::NotRunning)
return;
QEventLoop loop;
@@ -274,99 +232,24 @@ void ValgrindRunner::waitForFinished() const
loop.exec();
}
-bool ValgrindRunner::start()
-{
- return d->run();
-}
-
-void ValgrindRunner::processError(QProcess::ProcessError e)
-{
- if (d->m_finished)
- return;
-
- d->m_finished = true;
-
- // make sure we don't wait for the connection anymore
- emit processErrorReceived(errorString(), e);
- emit finished();
-}
-
-void ValgrindRunner::processFinished(int ret, QProcess::ExitStatus status)
+QString ValgrindRunner::errorString() const
{
- emit extraProcessFinished();
-
- if (d->m_finished)
- return;
-
- d->m_finished = true;
-
- // make sure we don't wait for the connection anymore
- emit finished();
-
- if (ret != 0 || status == QProcess::CrashExit)
- emit processErrorReceived(errorString(), d->m_valgrindProcess.processError());
+ return d->m_process.errorString();
}
-QString ValgrindRunner::errorString() const
+bool ValgrindRunner::start()
{
- return d->m_valgrindProcess.errorString();
+ return d->run();
}
void ValgrindRunner::stop()
{
- d->m_valgrindProcess.stop();
+ d->m_process.stop();
}
XmlProtocol::ThreadedParser *ValgrindRunner::parser() const
{
- return &d->parser;
-}
-
-void ValgrindRunner::xmlSocketConnected()
-{
- QTcpSocket *socket = d->xmlServer.nextPendingConnection();
- QTC_ASSERT(socket, return);
- d->xmlServer.close();
- d->parser.parse(socket);
-}
-
-void ValgrindRunner::logSocketConnected()
-{
- d->logSocket = d->logServer.nextPendingConnection();
- QTC_ASSERT(d->logSocket, return);
- connect(d->logSocket, &QIODevice::readyRead,
- this, &ValgrindRunner::readLogSocket);
- d->logServer.close();
-}
-
-void ValgrindRunner::readLogSocket()
-{
- QTC_ASSERT(d->logSocket, return);
- emit logMessageReceived(d->logSocket->readAll());
-}
-
-bool ValgrindRunner::startServers()
-{
- bool check = d->xmlServer.listen(d->localServerAddress);
- const QString ip = d->localServerAddress.toString();
- if (!check) {
- emit processErrorReceived(tr("XmlServer on %1:").arg(ip) + ' '
- + d->xmlServer.errorString(), QProcess::FailedToStart );
- return false;
- }
- d->xmlServer.setMaxPendingConnections(1);
- connect(&d->xmlServer, &QTcpServer::newConnection,
- this, &ValgrindRunner::xmlSocketConnected);
- check = d->logServer.listen(d->localServerAddress);
- if (!check) {
- emit processErrorReceived(tr("LogServer on %1:").arg(ip) + ' '
- + d->logServer.errorString(), QProcess::FailedToStart );
- return false;
- }
- d->logServer.setMaxPendingConnections(1);
- connect(&d->logServer, &QTcpServer::newConnection,
- this, &ValgrindRunner::logSocketConnected);
- return true;
+ return &d->m_parser;
}
} // namespace Valgrind
diff --git a/src/plugins/valgrind/valgrindrunner.h b/src/plugins/valgrind/valgrindrunner.h
index 647cac8bae8..c8701b6e89a 100644
--- a/src/plugins/valgrind/valgrindrunner.h
+++ b/src/plugins/valgrind/valgrindrunner.h
@@ -32,6 +32,10 @@
#include <QProcess>
+QT_BEGIN_NAMESPACE
+class QHostAddress;
+QT_END_NAMESPACE
+
namespace Valgrind {
namespace XmlProtocol { class ThreadedParser; }
@@ -48,7 +52,6 @@ public:
void setDebuggee(const ProjectExplorer::Runnable &debuggee);
void setProcessChannelMode(QProcess::ProcessChannelMode mode);
void setLocalServerAddress(const QHostAddress &localServerAddress);
- void setDevice(const ProjectExplorer::IDevice::ConstPtr &device);
void setUseTerminal(bool on);
void waitForFinished() const;
@@ -61,23 +64,15 @@ public:
XmlProtocol::ThreadedParser *parser() const;
signals:
+ void appendMessage(const QString &, Utils::OutputFormat);
+
void logMessageReceived(const QByteArray &);
- void processOutputReceived(const QString &, Utils::OutputFormat);
void processErrorReceived(const QString &, QProcess::ProcessError);
void valgrindExecuted(const QString &);
void valgrindStarted(qint64 pid);
void finished();
- void extraProcessFinished();
private:
- bool startServers();
- void processError(QProcess::ProcessError);
- void processFinished(int, QProcess::ExitStatus);
-
- void xmlSocketConnected();
- void logSocketConnected();
- void readLogSocket();
-
class Private;
Private *d;
};
diff --git a/src/plugins/valgrind/valgrindsettings.cpp b/src/plugins/valgrind/valgrindsettings.cpp
index 21d056e3fd0..4ffac890746 100644
--- a/src/plugins/valgrind/valgrindsettings.cpp
+++ b/src/plugins/valgrind/valgrindsettings.cpp
@@ -25,11 +25,11 @@
****************************************************************************/
#include "valgrindsettings.h"
-#include "valgrindplugin.h"
#include "valgrindconfigwidget.h"
#include <coreplugin/icore.h>
+#include <utils/algorithm.h>
#include <utils/layoutbuilder.h>
#include <utils/qtcassert.h>
#include <utils/treemodel.h>
diff --git a/src/plugins/valgrind/valgrindtestrunnertest.cpp b/src/plugins/valgrind/valgrindtestrunnertest.cpp
index 4dde3013628..889422b6189 100644
--- a/src/plugins/valgrind/valgrindtestrunnertest.cpp
+++ b/src/plugins/valgrind/valgrindtestrunnertest.cpp
@@ -91,8 +91,6 @@ QString ValgrindTestRunnerTest::runTestBinary(const QString &binary, const QStri
m_runner->setLocalServerAddress(QHostAddress::LocalHost);
m_runner->setValgrindCommand(valgrind);
m_runner->setDebuggee(debuggee);
- m_runner->setDevice(DeviceManager::instance()->defaultDevice(
- ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE));
m_runner->start();
m_runner->waitForFinished();
return binPath;
diff --git a/src/plugins/valgrind/xmlprotocol/error.cpp b/src/plugins/valgrind/xmlprotocol/error.cpp
index efc04f52232..0adf0dbfab8 100644
--- a/src/plugins/valgrind/xmlprotocol/error.cpp
+++ b/src/plugins/valgrind/xmlprotocol/error.cpp
@@ -205,12 +205,13 @@ QString Error::toXml() const
stream << " <what>" << d->what << "</what>\n";
}
- foreach (const Stack &stack, d->stacks) {
+ for (const Stack &stack : qAsConst(d->stacks)) {
if (!stack.auxWhat().isEmpty())
stream << " <auxwhat>" << stack.auxWhat() << "</auxwhat>\n";
stream << " <stack>\n";
- foreach (const Frame &frame, stack.frames()) {
+ const QVector<Frame> frames = stack.frames();
+ for (const Frame &frame : frames) {
stream << " <frame>\n";
stream << " <ip>0x" << QString::number(frame.instructionPointer(), 16) << "</ip>\n";
if (!frame.object().isEmpty())
diff --git a/src/plugins/valgrind/xmlprotocol/errorlistmodel.cpp b/src/plugins/valgrind/xmlprotocol/errorlistmodel.cpp
index a4d4234d070..7431b0692cd 100644
--- a/src/plugins/valgrind/xmlprotocol/errorlistmodel.cpp
+++ b/src/plugins/valgrind/xmlprotocol/errorlistmodel.cpp
@@ -165,10 +165,12 @@ ErrorItem::ErrorItem(const ErrorListModel *model, const Error &error)
// just annoy the user.
// The same goes for the frame level.
if (m_error.stacks().count() > 1) {
- foreach (const Stack &s, m_error.stacks())
+ const QVector<Stack> stacks = m_error.stacks();
+ for (const Stack &s : stacks)
appendChild(new StackItem(s));
} else if (m_error.stacks().constFirst().frames().count() > 1) {
- foreach (const Frame &f, m_error.stacks().constFirst().frames())
+ const QVector<Frame> frames = m_error.stacks().constFirst().frames();
+ for (const Frame &f : frames)
appendChild(new FrameItem(f));
}
}
@@ -197,11 +199,13 @@ QVariant ErrorItem::data(int column, int role) const
<< m_model->errorLocation(m_error)
<< "\n";
- foreach (const Stack &stack, m_error.stacks()) {
+ const QVector<Stack> stacks = m_error.stacks();
+ for (const Stack &stack : stacks) {
if (!stack.auxWhat().isEmpty())
stream << stack.auxWhat();
int i = 1;
- foreach (const Frame &frame, stack.frames())
+ const QVector<Frame> frames = stack.frames();
+ for (const Frame &frame : frames)
stream << " " << i++ << ": " << makeFrameName(frame, true) << "\n";
}
@@ -229,7 +233,8 @@ QVariant ErrorItem::data(int column, int role) const
StackItem::StackItem(const Stack &stack) : m_stack(stack)
{
- foreach (const Frame &f, m_stack.frames())
+ const QVector<Frame> frames = m_stack.frames();
+ for (const Frame &f : frames)
appendChild(new FrameItem(f));
}
diff --git a/src/plugins/valgrind/xmlprotocol/modelhelpers.cpp b/src/plugins/valgrind/xmlprotocol/modelhelpers.cpp
index 48e0a325771..d2722311871 100644
--- a/src/plugins/valgrind/xmlprotocol/modelhelpers.cpp
+++ b/src/plugins/valgrind/xmlprotocol/modelhelpers.cpp
@@ -64,7 +64,7 @@ QString toolTipForFrame(const Frame &frame)
"<style>dt { font-weight:bold; } dd { font-family: monospace; }</style>\n"
"</head><body><dl>";
- foreach (const StringPair &pair, lines) {
+ for (const StringPair &pair : qAsConst(lines)) {
html += "<dt>";
html += pair.first;
html += "</dt><dd>";
diff --git a/src/plugins/valgrind/xmlprotocol/suppression.cpp b/src/plugins/valgrind/xmlprotocol/suppression.cpp
index 14ad429416f..0864a2f2f4e 100644
--- a/src/plugins/valgrind/xmlprotocol/suppression.cpp
+++ b/src/plugins/valgrind/xmlprotocol/suppression.cpp
@@ -208,7 +208,7 @@ QString Suppression::toString() const
stream << "{\n";
stream << indent << d->name << '\n';
stream << indent << d->kind << '\n';
- foreach (const SuppressionFrame &frame, d->frames)
+ for (const SuppressionFrame &frame : qAsConst(d->frames))
stream << indent << frame.toString() << '\n';
stream << "}\n";
return ret;
diff --git a/src/plugins/vcsbase/CMakeLists.txt b/src/plugins/vcsbase/CMakeLists.txt
index 0f7a6fc9efc..d5623d73533 100644
--- a/src/plugins/vcsbase/CMakeLists.txt
+++ b/src/plugins/vcsbase/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_plugin(VcsBase
+ PLUGIN_CLASS VcsPlugin
PLUGIN_DEPENDS Core DiffEditor ProjectExplorer TextEditor
PLUGIN_RECOMMENDS CodePaster CppEditor
SOURCES
diff --git a/src/plugins/vcsbase/baseannotationhighlighter.cpp b/src/plugins/vcsbase/baseannotationhighlighter.cpp
index ac23e85394f..6c455515177 100644
--- a/src/plugins/vcsbase/baseannotationhighlighter.cpp
+++ b/src/plugins/vcsbase/baseannotationhighlighter.cpp
@@ -93,20 +93,21 @@ BaseAnnotationHighlighter::~BaseAnnotationHighlighter()
void BaseAnnotationHighlighter::setChangeNumbers(const ChangeNumbers &changeNumbers)
{
d->m_changeNumberMap.clear();
- if (!changeNumbers.isEmpty()) {
- // Assign a color gradient to annotation change numbers. Give
- // each change number a unique color.
- const QList<QColor> colors =
- TextEditor::SyntaxHighlighter::generateColors(changeNumbers.size(), d->m_background);
- int m = 0;
- const int cstep = colors.count() / changeNumbers.count();
- const ChangeNumbers::const_iterator cend = changeNumbers.constEnd();
- for (ChangeNumbers::const_iterator it = changeNumbers.constBegin(); it != cend; ++it) {
- QTextCharFormat format;
- format.setForeground(colors.at(m));
- d->m_changeNumberMap.insert(*it, format);
- m += cstep;
- }
+ const int changeNumberCount = changeNumbers.size();
+ if (changeNumberCount == 0)
+ return;
+ // Assign a color gradient to annotation change numbers. Give
+ // each change number a unique color.
+ const QList<QColor> colors =
+ TextEditor::SyntaxHighlighter::generateColors(changeNumberCount, d->m_background);
+ int m = 0;
+ const int cstep = colors.count() / changeNumberCount;
+ const ChangeNumbers::const_iterator cend = changeNumbers.constEnd();
+ for (ChangeNumbers::const_iterator it = changeNumbers.constBegin(); it != cend; ++it) {
+ QTextCharFormat format;
+ format.setForeground(colors.at(m));
+ d->m_changeNumberMap.insert(*it, format);
+ m += cstep;
}
}
diff --git a/src/plugins/vcsbase/basevcseditorfactory.cpp b/src/plugins/vcsbase/basevcseditorfactory.cpp
index 84414bf76da..e97de8f308e 100644
--- a/src/plugins/vcsbase/basevcseditorfactory.cpp
+++ b/src/plugins/vcsbase/basevcseditorfactory.cpp
@@ -82,4 +82,6 @@ VcsEditorFactory::VcsEditorFactory(const VcsBaseEditorParameters *parameters,
setMarksVisible(false);
}
+VcsEditorFactory::~VcsEditorFactory() = default;
+
} // namespace VcsBase
diff --git a/src/plugins/vcsbase/basevcseditorfactory.h b/src/plugins/vcsbase/basevcseditorfactory.h
index ddd90a93dac..bbc57669784 100644
--- a/src/plugins/vcsbase/basevcseditorfactory.h
+++ b/src/plugins/vcsbase/basevcseditorfactory.h
@@ -41,6 +41,8 @@ public:
VcsEditorFactory(const VcsBaseEditorParameters *parameters,
const EditorWidgetCreator editorWidgetCreator,
std::function<void(const Utils::FilePath &, const QString &)> describeFunc);
+
+ ~VcsEditorFactory();
};
} // namespace VcsBase
diff --git a/src/plugins/vcsbase/basevcssubmiteditorfactory.cpp b/src/plugins/vcsbase/basevcssubmiteditorfactory.cpp
index b285f6453d1..ba6d4fe5c62 100644
--- a/src/plugins/vcsbase/basevcssubmiteditorfactory.cpp
+++ b/src/plugins/vcsbase/basevcssubmiteditorfactory.cpp
@@ -74,4 +74,6 @@ VcsSubmitEditorFactory::VcsSubmitEditorFactory
ActionManager::registerAction(&m_diffAction, DIFF_SELECTED, context);
}
+VcsSubmitEditorFactory::~VcsSubmitEditorFactory() = default;
+
} // namespace VcsBase
diff --git a/src/plugins/vcsbase/basevcssubmiteditorfactory.h b/src/plugins/vcsbase/basevcssubmiteditorfactory.h
index f71d61bbbbf..30e1696d335 100644
--- a/src/plugins/vcsbase/basevcssubmiteditorfactory.h
+++ b/src/plugins/vcsbase/basevcssubmiteditorfactory.h
@@ -53,6 +53,8 @@ public:
const EditorCreator &editorCreator,
VcsBasePluginPrivate *plugin);
+ ~VcsSubmitEditorFactory();
+
private:
QAction m_submitAction;
QAction m_diffAction;
diff --git a/src/plugins/vcsbase/cleandialog.cpp b/src/plugins/vcsbase/cleandialog.cpp
index e70caddd42b..b5e0ec65eca 100644
--- a/src/plugins/vcsbase/cleandialog.cpp
+++ b/src/plugins/vcsbase/cleandialog.cpp
@@ -62,7 +62,8 @@ static void removeFileRecursion(QFutureInterface<void> &futureInterface,
return;
if (f.isDir()) {
const QDir dir(f.absoluteFilePath());
- foreach (const QFileInfo &fi, dir.entryInfoList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::Hidden))
+ const QList<QFileInfo> infos = dir.entryInfoList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::Hidden);
+ for (const QFileInfo &fi : infos)
removeFileRecursion(futureInterface, fi, errorMessage);
QDir parent = f.absoluteDir();
if (!parent.rmdir(f.fileName()))
@@ -86,7 +87,7 @@ static void runCleanFiles(QFutureInterface<void> &futureInterface,
QString errorMessage;
futureInterface.setProgressRange(0, files.size());
futureInterface.setProgressValue(0);
- foreach (const QString &name, files) {
+ for (const QString &name : files) {
removeFileRecursion(futureInterface, QFileInfo(name), &errorMessage);
if (futureInterface.isCanceled())
break;
@@ -177,9 +178,9 @@ void CleanDialog::setFileList(const QString &workingDirectory, const QStringList
if (const int oldRowCount = d->m_filesModel->rowCount())
d->m_filesModel->removeRows(0, oldRowCount);
- foreach (const QString &fileName, files)
+ for (const QString &fileName : files)
addFile(workingDirectory, fileName, true);
- foreach (const QString &fileName, ignoredFiles)
+ for (const QString &fileName : ignoredFiles)
addFile(workingDirectory, fileName, false);
for (int c = 0; c < d->m_filesModel->columnCount(); c++)
diff --git a/src/plugins/vcsbase/submiteditorwidget.cpp b/src/plugins/vcsbase/submiteditorwidget.cpp
index 06f815b308a..6359a95a297 100644
--- a/src/plugins/vcsbase/submiteditorwidget.cpp
+++ b/src/plugins/vcsbase/submiteditorwidget.cpp
@@ -573,7 +573,7 @@ void SubmitEditorWidget::descriptionTextChanged()
wrapDescription();
trimDescription();
// append field entries
- foreach (const SubmitFieldWidget *fw, d->m_fieldWidgets)
+ for (const SubmitFieldWidget *fw : qAsConst(d->m_fieldWidgets))
d->m_description += fw->fieldValues();
updateSubmitAction();
}
@@ -664,8 +664,8 @@ void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &pos)
{
QScopedPointer<QMenu> menu(d->m_ui.description->createStandardContextMenu());
// Extend
- foreach (const SubmitEditorWidgetPrivate::AdditionalContextMenuAction &a,
- d->descriptionEditContextMenuActions) {
+ for (const SubmitEditorWidgetPrivate::AdditionalContextMenuAction &a :
+ qAsConst(d->descriptionEditContextMenuActions)) {
if (a.second) {
if (a.first >= 0)
menu->insertAction(menu->actions().at(a.first), a.second);
diff --git a/src/plugins/vcsbase/submitfieldwidget.cpp b/src/plugins/vcsbase/submitfieldwidget.cpp
index df3513e59fd..46978f3519e 100644
--- a/src/plugins/vcsbase/submitfieldwidget.cpp
+++ b/src/plugins/vcsbase/submitfieldwidget.cpp
@@ -210,7 +210,7 @@ void SubmitFieldWidget::setHasBrowseButton(bool on)
if (d->hasBrowseButton == on)
return;
d->hasBrowseButton = on;
- foreach (const FieldEntry &fe, d->fieldEntries)
+ for (const FieldEntry &fe : qAsConst(d->fieldEntries))
fe.browseButton->setVisible(on);
}
@@ -234,7 +234,7 @@ void SubmitFieldWidget::setCompleter(QCompleter *c)
if (c == d->completer)
return;
d->completer = c;
- foreach (const FieldEntry &fe, d->fieldEntries)
+ for (const FieldEntry &fe : qAsConst(d->fieldEntries))
fe.lineEdit->setCompleter(c);
}
@@ -254,7 +254,7 @@ QString SubmitFieldWidget::fieldValues() const
const QChar newLine = QLatin1Char('\n');
// Format as "RevBy: value\nSigned-Off: value\n"
QString rc;
- foreach (const FieldEntry &fe, d->fieldEntries) {
+ for (const FieldEntry &fe : qAsConst(d->fieldEntries)) {
const QString value = fe.lineEdit->text().trimmed();
if (!value.isEmpty()) {
rc += fe.combo->currentText();
diff --git a/src/plugins/vcsbase/vcsbase_global.h b/src/plugins/vcsbase/vcsbase_global.h
index 2bf2f78e202..fd08e4e70b1 100644
--- a/src/plugins/vcsbase/vcsbase_global.h
+++ b/src/plugins/vcsbase/vcsbase_global.h
@@ -29,6 +29,8 @@
#if defined(VCSBASE_LIBRARY)
# define VCSBASE_EXPORT Q_DECL_EXPORT
+#elif defined(VCSBASE_STATIC_LIBRARY)
+# define VCSBASE_EXPORT
#else
# define VCSBASE_EXPORT Q_DECL_IMPORT
#endif
diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp
index 9339d2ffd68..ea43dca0046 100644
--- a/src/plugins/vcsbase/vcsbaseclient.cpp
+++ b/src/plugins/vcsbase/vcsbaseclient.cpp
@@ -34,6 +34,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/idocument.h>
+#include <utils/environment.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -62,7 +63,8 @@ using namespace Utils;
static Core::IEditor *locateEditor(const char *property, const QString &entry)
{
- foreach (Core::IDocument *document, Core::DocumentModel::openedDocuments())
+ const QList<Core::IDocument *> documents = Core::DocumentModel::openedDocuments();
+ for (Core::IDocument *document : documents)
if (document->property(property).toString() == entry)
return Core::DocumentModel::editorsForDocument(document).constFirst();
return nullptr;
@@ -107,11 +109,26 @@ VcsCommand *VcsBaseClientImpl::createCommand(const FilePath &workingDirectory,
return cmd;
}
+VcsCommand *VcsBaseClientImpl::execBgCommand(const FilePath &workingDirectory,
+ const QStringList &args,
+ const std::function<void (const QString &)> &outputCallback,
+ unsigned flags) const
+{
+ VcsCommand *cmd = createCommand(workingDirectory);
+ cmd->addFlags(flags
+ | VcsCommand::SuppressCommandLogging
+ | VcsCommand::SuppressStdErr
+ | VcsCommand::SuppressFailMessage);
+ cmd->addJob({vcsBinary(), args});
+ connect(cmd, &VcsCommand::stdOutText, this, outputCallback);
+ cmd->execute();
+ return cmd;
+}
+
void VcsBaseClientImpl::enqueueJob(VcsCommand *cmd, const QStringList &args,
- const FilePath &workingDirectory,
const ExitCodeInterpreter &interpreter) const
{
- cmd->addJob({vcsBinary(), args}, vcsTimeoutS(), workingDirectory, interpreter);
+ cmd->addJob({vcsBinary(), args}, vcsTimeoutS(), {}, interpreter);
cmd->execute();
}
@@ -198,7 +215,7 @@ void VcsBaseClientImpl::vcsSynchronousExec(QtcProcess &proc,
QTextCodec *outputCodec) const
{
Environment env = processEnvironment();
- VcsCommand command(workingDir, env.size() == 0 ? Environment::systemEnvironment() : env);
+ VcsCommand command(workingDir, env.isValid() ? env : Environment::systemEnvironment());
proc.setTimeoutS(vcsTimeoutS());
command.addFlags(flags);
command.setCodec(outputCodec);
@@ -258,9 +275,9 @@ bool VcsBaseClient::synchronousCreateRepository(const FilePath &workingDirectory
args << extraOptions;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDirectory, args);
- if (proc.result() != QtcProcess::FinishedWithSuccess)
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
return false;
- VcsOutputWindow::append(proc.stdOut());
+ VcsOutputWindow::append(proc.cleanedStdOut());
resetCachedVcsInfo(workingDirectory);
@@ -279,7 +296,7 @@ bool VcsBaseClient::synchronousClone(const FilePath &workingDir,
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDir, args);
resetCachedVcsInfo(workingDir);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool VcsBaseClient::synchronousAdd(const FilePath &workingDir,
@@ -290,7 +307,7 @@ bool VcsBaseClient::synchronousAdd(const FilePath &workingDir,
args << vcsCommandString(AddCommand) << extraOptions << relFileName;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDir, args);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool VcsBaseClient::synchronousRemove(const FilePath &workingDir,
@@ -301,7 +318,7 @@ bool VcsBaseClient::synchronousRemove(const FilePath &workingDir,
args << vcsCommandString(RemoveCommand) << extraOptions << filename;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDir, args);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool VcsBaseClient::synchronousMove(const FilePath &workingDir,
@@ -313,7 +330,7 @@ bool VcsBaseClient::synchronousMove(const FilePath &workingDir,
args << vcsCommandString(MoveCommand) << extraOptions << from << to;
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDir, args);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
bool VcsBaseClient::synchronousPull(const FilePath &workingDir,
@@ -329,7 +346,7 @@ bool VcsBaseClient::synchronousPull(const FilePath &workingDir,
| VcsCommand::ShowSuccessMessage;
QtcProcess proc;
vcsSynchronousExec(proc, workingDir, args, flags);
- const bool ok = proc.result() == QtcProcess::FinishedWithSuccess;
+ const bool ok = proc.result() == ProcessResult::FinishedWithSuccess;
if (ok)
emit changed(QVariant(workingDir.toString()));
return ok;
@@ -348,7 +365,7 @@ bool VcsBaseClient::synchronousPush(const FilePath &workingDir,
| VcsCommand::ShowSuccessMessage;
QtcProcess proc;
vcsSynchronousExec(proc, workingDir, args, flags);
- return proc.result() == QtcProcess::FinishedWithSuccess;
+ return proc.result() == ProcessResult::FinishedWithSuccess;
}
VcsBaseEditorWidget *VcsBaseClient::annotate(
@@ -411,7 +428,7 @@ void VcsBaseClient::diff(const FilePath &workingDir, const QStringList &files,
: VcsBaseEditor::getCodec(source);
VcsCommand *command = createCommand(workingDir, editor);
command->setCodec(codec);
- enqueueJob(command, args, workingDir, exitCodeInterpreter(DiffCommand));
+ enqueueJob(command, args, exitCodeInterpreter(DiffCommand));
}
void VcsBaseClient::log(const FilePath &workingDir,
@@ -609,7 +626,7 @@ void VcsBaseClient::statusParser(const QString &text)
QStringList rawStatusList = text.split(QLatin1Char('\n'));
- foreach (const QString &string, rawStatusList) {
+ for (const QString &string : qAsConst(rawStatusList)) {
const VcsBaseClient::StatusItem lineInfo = parseStatusLine(string);
if (!lineInfo.flags.isEmpty() && !lineInfo.file.isEmpty())
lineInfoList.append(lineInfo);
diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h
index 7abc9a03f33..57bff0cb87e 100644
--- a/src/plugins/vcsbase/vcsbaseclient.h
+++ b/src/plugins/vcsbase/vcsbaseclient.h
@@ -31,7 +31,7 @@
#include <utils/fileutils.h>
#include <utils/id.h>
-#include <utils/qtcprocess.h>
+#include <utils/processenums.h>
#include <QObject>
#include <QStringList>
@@ -41,9 +41,12 @@
QT_BEGIN_NAMESPACE
class QFileInfo;
+class QTextCodec;
class QToolBar;
QT_END_NAMESPACE
+namespace Utils { class QtcProcess; }
+
namespace VcsBase {
class VcsCommand;
@@ -79,8 +82,12 @@ public:
VcsBaseEditorWidget *editor = nullptr,
JobOutputBindMode mode = NoOutputBind) const;
+ VcsCommand *execBgCommand(const Utils::FilePath &workingDirectory,
+ const QStringList &args,
+ const std::function<void (const QString &)> &outputCallback,
+ unsigned flags = 0) const;
+
void enqueueJob(VcsCommand *cmd, const QStringList &args,
- const Utils::FilePath &workingDirectory = {},
const Utils::ExitCodeInterpreter &interpreter = {}) const;
virtual Utils::Environment processEnvironment() const;
diff --git a/src/plugins/vcsbase/vcsbaseclientsettings.cpp b/src/plugins/vcsbase/vcsbaseclientsettings.cpp
index 00e20342adf..419e26268f9 100644
--- a/src/plugins/vcsbase/vcsbaseclientsettings.cpp
+++ b/src/plugins/vcsbase/vcsbaseclientsettings.cpp
@@ -75,6 +75,8 @@ VcsBaseSettings::VcsBaseSettings()
timeout.setSuffix(tr("s"));
}
+VcsBaseSettings::~VcsBaseSettings() = default;
+
FilePaths VcsBaseSettings::searchPathList() const
{
return Utils::transform(path.value().split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts),
diff --git a/src/plugins/vcsbase/vcsbaseclientsettings.h b/src/plugins/vcsbase/vcsbaseclientsettings.h
index d6597945038..76091f1d3c5 100644
--- a/src/plugins/vcsbase/vcsbaseclientsettings.h
+++ b/src/plugins/vcsbase/vcsbaseclientsettings.h
@@ -37,6 +37,7 @@ class VCSBASE_EXPORT VcsBaseSettings : public Utils::AspectContainer
public:
VcsBaseSettings();
+ ~VcsBaseSettings();
Utils::StringAspect binaryPath;
Utils::StringAspect userName;
diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp
index 3448af8e16c..577da8cdc94 100644
--- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp
+++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp
@@ -31,6 +31,7 @@
#include <coreplugin/progressmanager/progressmanager.h>
#include <diffeditor/diffutils.h>
+#include <utils/commandline.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 0cf39890c79..0f6bd38cc62 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -44,6 +44,7 @@
#include <projectexplorer/session.h>
#include <texteditor/textdocument.h>
#include <texteditor/textdocumentlayout.h>
+#include <utils/algorithm.h>
#include <utils/porting.h>
#include <utils/progressindicator.h>
#include <utils/qtcassert.h>
@@ -307,7 +308,7 @@ void ChangeTextCursorHandler::fillContextMenu(QMenu *menu, EditorContentType typ
menu->addAction(createAnnotateAction(widget->decorateVersion(m_currentChange), false));
const QStringList previousVersions = widget->annotationPreviousVersions(m_currentChange);
if (!previousVersions.isEmpty()) {
- foreach (const QString &pv, previousVersions)
+ for (const QString &pv : previousVersions)
menu->addAction(createAnnotateAction(widget->decorateVersion(pv), true));
}
break;
@@ -591,7 +592,7 @@ VcsBaseEditorWidgetPrivate::VcsBaseEditorWidgetPrivate(VcsBaseEditorWidget *edit
AbstractTextCursorHandler *VcsBaseEditorWidgetPrivate::findTextCursorHandler(const QTextCursor &cursor)
{
- foreach (AbstractTextCursorHandler *handler, m_textCursorHandlers) {
+ for (AbstractTextCursorHandler *handler : qAsConst(m_textCursorHandlers)) {
if (handler->findContentsUnderCursor(cursor))
return handler;
}
@@ -1383,7 +1384,7 @@ QString VcsBaseEditor::getTitleId(const FilePath &workingDirectory,
const QString &revision)
{
QStringList nonEmptyFileNames;
- foreach (const QString& fileName, fileNames) {
+ for (const QString& fileName : fileNames) {
if (!fileName.trimmed().isEmpty())
nonEmptyFileNames.append(fileName);
}
@@ -1668,7 +1669,8 @@ void VcsBaseEditor::tagEditor(Core::IEditor *e, const QString &tag)
Core::IEditor *VcsBaseEditor::locateEditorByTag(const QString &tag)
{
- foreach (Core::IDocument *document, Core::DocumentModel::openedDocuments()) {
+ const QList<Core::IDocument *> documents = Core::DocumentModel::openedDocuments();
+ for (Core::IDocument *document : documents) {
const QVariant tagPropertyValue = document->property(tagPropertyC);
if (tagPropertyValue.type() == QVariant::String && tagPropertyValue.toString() == tag)
return Core::DocumentModel::editorsForDocument(document).constFirst();
diff --git a/src/plugins/vcsbase/vcsbaseeditorconfig.cpp b/src/plugins/vcsbase/vcsbaseeditorconfig.cpp
index f4b704b6e9a..de7830698f4 100644
--- a/src/plugins/vcsbase/vcsbaseeditorconfig.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditorconfig.cpp
@@ -163,7 +163,7 @@ QStringList VcsBaseEditorConfig::arguments() const
{
// Compile effective arguments
QStringList args = baseArguments();
- foreach (const OptionMapping &mapping, optionMappings())
+ for (const OptionMapping &mapping : optionMappings())
args += argumentsForOption(mapping);
return args;
}
@@ -332,7 +332,7 @@ QStringList VcsBaseEditorConfig::argumentsForOption(const OptionMapping &mapping
void VcsBaseEditorConfig::updateMappedSettings()
{
- foreach (const OptionMapping &optMapping, d->m_optionMappings) {
+ for (const OptionMapping &optMapping : optionMappings()) {
if (d->m_settingMapping.contains(optMapping.object)) {
Internal::SettingMappingData& settingData = d->m_settingMapping[optMapping.object];
switch (settingData.type()) {
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index b371c8b2f64..74edfd3dd34 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -199,7 +199,7 @@ public:
explicit StateListener(QObject *parent);
~StateListener();
- static QString windowTitleVcsTopic(const QString &filePath);
+ static QString windowTitleVcsTopic(const FilePath &filePath);
signals:
void stateChanged(const VcsBase::Internal::State &s, IVersionControl *vc);
@@ -230,11 +230,11 @@ StateListener::~StateListener()
EditorManager::setWindowTitleVcsTopicHandler({});
}
-QString StateListener::windowTitleVcsTopic(const QString &filePath)
+QString StateListener::windowTitleVcsTopic(const FilePath &filePath)
{
FilePath searchPath;
if (!filePath.isEmpty()) {
- searchPath = FilePath::fromString(filePath).absolutePath();
+ searchPath = filePath.absolutePath();
} else {
// use single project's information if there is only one loaded.
const QList<Project *> projects = SessionManager::projects();
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
index 89e3a962ea6..ae8d877452a 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
@@ -263,7 +263,7 @@ static inline QStringList fieldTexts(const QString &fileContents)
{
QStringList rc;
const QStringList rawFields = fileContents.trimmed().split(QLatin1Char('\n'));
- foreach (const QString &field, rawFields) {
+ for (const QString &field : rawFields) {
const QString trimmedField = field.trimmed();
if (!trimmedField.isEmpty())
rc.push_back(trimmedField);
@@ -669,7 +669,6 @@ bool VcsBaseSubmitEditor::runSubmitMessageCheckScript(const QString &checkScript
QByteArray stdOutData;
QByteArray stdErrData;
if (!checkProcess.readDataFromProcess(30, &stdOutData, &stdErrData, false)) {
- checkProcess.stopProcess();
*errorMessage = tr("The check script \"%1\" timed out.").
arg(QDir::toNativeSeparators(checkScript));
return false;
diff --git a/src/plugins/vcsbase/vcscommand.cpp b/src/plugins/vcsbase/vcscommand.cpp
index 85623541eaa..66b422cd936 100644
--- a/src/plugins/vcsbase/vcscommand.cpp
+++ b/src/plugins/vcsbase/vcscommand.cpp
@@ -30,6 +30,7 @@
#include <coreplugin/documentmanager.h>
#include <coreplugin/vcsmanager.h>
+#include <utils/environment.h>
#include <utils/globalfilechangeblocker.h>
#include <utils/qtcprocess.h>
diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp
index 5151bc71fe6..976bf82c428 100644
--- a/src/plugins/vcsbase/vcsoutputwindow.cpp
+++ b/src/plugins/vcsbase/vcsoutputwindow.cpp
@@ -315,7 +315,12 @@ VcsOutputWindow::VcsOutputWindow()
TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
};
+ auto updateFontSettings = [] {
+ d->widget.setBaseFont(TextEditor::TextEditorSettings::fontSettings().font());
+ };
+
updateBehaviorSettings();
+ updateFontSettings();
setupContext(Internal::C_VCS_OUTPUT_PANE, &d->widget);
connect(this, &IOutputPane::zoomInRequested, &d->widget, &Core::OutputWindow::zoomIn);
@@ -323,6 +328,8 @@ VcsOutputWindow::VcsOutputWindow()
connect(this, &IOutputPane::resetZoomRequested, &d->widget, &Core::OutputWindow::resetZoom);
connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
this, updateBehaviorSettings);
+ connect(TextEditor::TextEditorSettings::instance(),
+ &TextEditor::TextEditorSettings::fontSettingsChanged, this, updateFontSettings);
}
static QString filterPasswordFromUrls(QString input)
@@ -421,12 +428,12 @@ void VcsOutputWindow::append(const QString &text, MessageStyle style, bool silen
void VcsOutputWindow::appendError(const QString &text)
{
- append(text, Error, false);
+ append(text.endsWith('\n') ? text : text + '\n', Error, false);
}
void VcsOutputWindow::appendWarning(const QString &text)
{
- append(text, Warning, false);
+ append(text + '\n', Warning, false);
}
QString VcsOutputWindow::msgExecutionLogEntry(const FilePath &workingDir, const CommandLine &command)
@@ -448,7 +455,7 @@ void VcsOutputWindow::appendCommand(const FilePath &workingDirectory, const Comm
void VcsOutputWindow::appendMessage(const QString &text)
{
- append(text, Message, true);
+ append(text + '\n', Message, true);
}
void VcsOutputWindow::destroy()
diff --git a/src/plugins/vcsbase/wizard/vcscommandpage.cpp b/src/plugins/vcsbase/wizard/vcscommandpage.cpp
index 5da40d2cd03..2cfc5b5d706 100644
--- a/src/plugins/vcsbase/wizard/vcscommandpage.cpp
+++ b/src/plugins/vcsbase/wizard/vcscommandpage.cpp
@@ -31,6 +31,7 @@
#include <projectexplorer/jsonwizard/jsonwizard.h>
#include <utils/algorithm.h>
+#include <utils/commandline.h>
#include <utils/qtcassert.h>
#include <QDir>
@@ -97,7 +98,8 @@ WizardPage *VcsCommandPageFactory::create(JsonWizard *wizard, Id typeId, const Q
tmp.value(QLatin1String(VCSCOMMAND_CHECKOUTNAME)).toString(),
args);
- foreach (const QVariant &value, tmp.value(QLatin1String(VCSCOMMAND_JOBS)).toList()) {
+ const QVariantList values = tmp.value(QLatin1String(VCSCOMMAND_JOBS)).toList();
+ for (const QVariant &value : values) {
const QVariantMap job = value.toMap();
const bool skipEmpty = job.value(QLatin1String(JOB_SKIP_EMPTY), true).toBool();
const FilePath workDir = FilePath::fromVariant(job.value(QLatin1String(JOB_WORK_DIRECTORY)));
@@ -182,7 +184,8 @@ bool VcsCommandPageFactory::validateData(Id typeId, const QVariant &data, QStrin
.arg(QLatin1String(VCSCOMMAND_JOBS));
}
- foreach (const QVariant &j, jobs.toList()) {
+ const QVariantList jobList = jobs.toList();
+ for (const QVariant &j : jobList) {
if (j.isNull()) {
em = tr("Job in \"VcsCommand\" page is empty.");
break;
@@ -276,7 +279,7 @@ void VcsCommandPage::delayedInitialize()
setStartedStatus(runMessage);
QStringList extraArgs;
- foreach (const QString &in, m_arguments) {
+ for (const QString &in : qAsConst(m_arguments)) {
const QString tmp = wiz->expander()->expand(in);
if (tmp.isEmpty())
continue;
@@ -289,7 +292,7 @@ void VcsCommandPage::delayedInitialize()
= vc->createInitialCheckoutCommand(repo, FilePath::fromString(base),
name, extraArgs);
- foreach (const JobData &job, m_additionalJobs) {
+ for (const JobData &job : qAsConst(m_additionalJobs)) {
QTC_ASSERT(!job.job.isEmpty(), continue);
if (!JsonWizard::boolFromVariant(job.condition, wiz->expander()))
diff --git a/src/plugins/webassembly/webassemblydevice.cpp b/src/plugins/webassembly/webassemblydevice.cpp
index ae9fb02ae3e..43d06ae5546 100644
--- a/src/plugins/webassembly/webassemblydevice.cpp
+++ b/src/plugins/webassembly/webassemblydevice.cpp
@@ -26,7 +26,6 @@
#include "webassemblyconstants.h"
#include "webassemblydevice.h"
-#include <projectexplorer/devicesupport/deviceprocess.h>
#include <projectexplorer/runcontrol.h>
using namespace ProjectExplorer;
diff --git a/src/plugins/webassembly/webassemblyemsdk.cpp b/src/plugins/webassembly/webassemblyemsdk.cpp
index c5da7d13570..351bda3062e 100644
--- a/src/plugins/webassembly/webassemblyemsdk.cpp
+++ b/src/plugins/webassembly/webassemblyemsdk.cpp
@@ -118,7 +118,7 @@ QVersionNumber WebAssemblyEmSdk::version(const FilePath &sdkRoot)
emcc.setCommand(command);
emcc.setEnvironment(env);
emcc.runBlocking();
- const QString version = emcc.stdOut();
+ const QString version = emcc.cleanedStdOut();
emSdkVersionCache()->insert(cacheKey,
new QVersionNumber(QVersionNumber::fromString(version)));
}
diff --git a/src/plugins/webassembly/webassemblyplugin.cpp b/src/plugins/webassembly/webassemblyplugin.cpp
index a2cf03826e5..2ad5fd943f6 100644
--- a/src/plugins/webassembly/webassemblyplugin.cpp
+++ b/src/plugins/webassembly/webassemblyplugin.cpp
@@ -106,7 +106,7 @@ void WebAssemblyPlugin::askUserAboutEmSdkSetup()
InfoBarEntry info(setupWebAssemblyEmSdk,
tr("Setup Emscripten SDK for WebAssembly? "
- "To do it later, select Options > Devices > WebAssembly."),
+ "To do it later, select Edit > Preferences > Devices > WebAssembly."),
InfoBarEntry::GlobalSuppression::Enabled);
info.addCustomButton(tr("Setup Emscripten SDK"), [setupWebAssemblyEmSdk] {
ICore::infoBar()->removeInfo(setupWebAssemblyEmSdk);
diff --git a/src/plugins/webassembly/webassemblyrunconfiguration.cpp b/src/plugins/webassembly/webassemblyrunconfiguration.cpp
index a9fb67356b3..11ca7c7ce36 100644
--- a/src/plugins/webassembly/webassemblyrunconfiguration.cpp
+++ b/src/plugins/webassembly/webassemblyrunconfiguration.cpp
@@ -56,15 +56,17 @@ static FilePath pythonInterpreter(const Environment &env)
return {};
}
-static CommandLine emrunCommand(const RunConfiguration *rc, const QString &browser,
+static CommandLine emrunCommand(const Target *target,
+ const QString &buildKey,
+ const QString &browser,
const QString &port)
{
- if (BuildConfiguration *bc = rc->target()->activeBuildConfiguration()) {
+ if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
const Environment env = bc->environment();
const FilePath emrun = env.searchInPath("emrun");
const FilePath emrunPy = emrun.absolutePath().pathAppended(emrun.baseName() + ".py");
- const FilePath target = rc->buildTargetInfo().targetFilePath;
- const FilePath html = target.absolutePath() / target.baseName() + ".html";
+ const FilePath targetPath = bc->buildSystem()->buildTarget(buildKey).targetFilePath;
+ const FilePath html = targetPath.absolutePath() / targetPath.baseName() + ".html";
QStringList args(emrunPy.path());
if (!browser.isEmpty()) {
@@ -97,8 +99,9 @@ public:
effectiveEmrunCall->setDisplayStyle(StringAspect::TextEditDisplay);
effectiveEmrunCall->setReadOnly(true);
- setUpdater([this, effectiveEmrunCall, webBrowserAspect] {
- effectiveEmrunCall->setValue(emrunCommand(this,
+ setUpdater([this, target, effectiveEmrunCall, webBrowserAspect] {
+ effectiveEmrunCall->setValue(emrunCommand(target,
+ buildKey(),
webBrowserAspect->currentBrowser(),
"<port>").toUserOutput());
});
@@ -117,15 +120,14 @@ public:
auto portsGatherer = new PortsGatherer(runControl);
addStartDependency(portsGatherer);
- setStarter([this, runControl, portsGatherer] {
- Runnable r;
+ setStartModifier([this, runControl, portsGatherer] {
const QString browserId =
- runControl->aspect<WebBrowserSelectionAspect>()->currentBrowser();
- r.command = emrunCommand(runControl->runConfiguration(),
- browserId,
- QString::number(portsGatherer->findEndPoint().port()));
- r.environment = runControl->buildEnvironment();
- SimpleTargetRunner::doStart(r, {});
+ runControl->aspect<WebBrowserSelectionAspect>()->currentBrowser;
+ setCommandLine(emrunCommand(runControl->target(),
+ runControl->buildKey(),
+ browserId,
+ QString::number(portsGatherer->findEndPoint().port())));
+ setEnvironment(runControl->buildEnvironment());
});
}
};
diff --git a/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp b/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp
index b022c5147dc..e7e73608c7b 100644
--- a/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp
+++ b/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp
@@ -33,6 +33,7 @@
#include <utils/qtcprocess.h>
#include <QComboBox>
+#include <QTextStream>
#ifdef WITH_TESTS
# include <QTest>
@@ -89,6 +90,8 @@ WebBrowserSelectionAspect::WebBrowserSelectionAspect(ProjectExplorer::Target *ta
setDisplayName(tr("Web Browser"));
setId("WebBrowserAspect");
setSettingsKey("RunConfiguration.WebBrowser");
+
+ addDataExtractor(this, &WebBrowserSelectionAspect::currentBrowser, &Data::currentBrowser);
}
void WebBrowserSelectionAspect::addToLayout(LayoutBuilder &builder)
diff --git a/src/plugins/webassembly/webassemblyrunconfigurationaspects.h b/src/plugins/webassembly/webassemblyrunconfigurationaspects.h
index b1360a79faf..312ed40adf2 100644
--- a/src/plugins/webassembly/webassemblyrunconfigurationaspects.h
+++ b/src/plugins/webassembly/webassemblyrunconfigurationaspects.h
@@ -49,6 +49,11 @@ public:
QString currentBrowser() const;
+ struct Data : BaseAspect::Data
+ {
+ QString currentBrowser;
+ };
+
private:
QComboBox *m_webBrowserComboBox = nullptr;
QString m_currentBrowser;
diff --git a/src/plugins/webassembly/webassemblytoolchain.cpp b/src/plugins/webassembly/webassemblytoolchain.cpp
index d263c9decc4..a9df48c6464 100644
--- a/src/plugins/webassembly/webassemblytoolchain.cpp
+++ b/src/plugins/webassembly/webassemblytoolchain.cpp
@@ -111,6 +111,43 @@ const QVersionNumber &WebAssemblyToolChain::minimumSupportedEmSdkVersion()
return number;
}
+static Toolchains doAutoDetect(const ToolchainDetector &detector)
+{
+ const FilePath sdk = WebAssemblyEmSdk::registeredEmSdk();
+ if (!WebAssemblyEmSdk::isValid(sdk))
+ return {};
+
+ if (detector.device) {
+ // Only detect toolchains from the emsdk installation device
+ const FilePath deviceRoot = detector.device->rootPath();
+ if (deviceRoot.host() != sdk.host())
+ return {};
+ }
+
+ Environment env = sdk.deviceEnvironment();
+ WebAssemblyEmSdk::addToEnvironment(sdk, env);
+
+ Toolchains result;
+ for (auto languageId : {ProjectExplorer::Constants::C_LANGUAGE_ID,
+ ProjectExplorer::Constants::CXX_LANGUAGE_ID}) {
+ auto toolChain = new WebAssemblyToolChain;
+ toolChain->setLanguage(languageId);
+ toolChain->setDetection(ToolChain::AutoDetection);
+ const bool cLanguage = languageId == ProjectExplorer::Constants::C_LANGUAGE_ID;
+ const QString script = QLatin1String(cLanguage ? "emcc" : "em++")
+ + QLatin1String(sdk.osType() == OsTypeWindows ? ".bat" : "");
+ const FilePath scriptFile = sdk.withNewPath(script).searchInDirectories(env.path());
+ toolChain->setCompilerCommand(scriptFile);
+
+ const QString displayName = WebAssemblyToolChain::tr("Emscripten Compiler %1 for %2")
+ .arg(toolChain->version(), QLatin1String(cLanguage ? "C" : "C++"));
+ toolChain->setDisplayName(displayName);
+ result.append(toolChain);
+ }
+
+ return result;
+}
+
void WebAssemblyToolChain::registerToolChains()
{
// Remove old toolchains
@@ -121,12 +158,9 @@ void WebAssemblyToolChain::registerToolChains()
};
// Create new toolchains and register them
- ToolChainFactory *factory =
- findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){
- return f->supportedToolChainType() == Constants::WEBASSEMBLY_TOOLCHAIN_TYPEID;
- });
- QTC_ASSERT(factory, return);
- for (auto toolChain : factory->autoDetect(ToolchainDetector({}, {}, {})))
+ ToolchainDetector detector({}, {}, {});
+ const Toolchains toolchains = doAutoDetect(detector);
+ for (auto toolChain : toolchains)
ToolChainManager::registerToolChain(toolChain);
// Let kits pick up the new toolchains
@@ -157,39 +191,7 @@ WebAssemblyToolChainFactory::WebAssemblyToolChainFactory()
Toolchains WebAssemblyToolChainFactory::autoDetect(const ToolchainDetector &detector) const
{
- const FilePath sdk = WebAssemblyEmSdk::registeredEmSdk();
- if (!WebAssemblyEmSdk::isValid(sdk))
- return {};
-
- if (detector.device) {
- // Only detect toolchains from the emsdk installation device
- const FilePath deviceRoot = detector.device->mapToGlobalPath({});
- if (deviceRoot.host() != sdk.host())
- return {};
- }
-
- Environment env = sdk.deviceEnvironment();
- WebAssemblyEmSdk::addToEnvironment(sdk, env);
-
- Toolchains result;
- for (auto languageId : {ProjectExplorer::Constants::C_LANGUAGE_ID,
- ProjectExplorer::Constants::CXX_LANGUAGE_ID}) {
- auto toolChain = new WebAssemblyToolChain;
- toolChain->setLanguage(languageId);
- toolChain->setDetection(ToolChain::AutoDetection);
- const bool cLanguage = languageId == ProjectExplorer::Constants::C_LANGUAGE_ID;
- const QString script = QLatin1String(cLanguage ? "emcc" : "em++")
- + QLatin1String(sdk.osType() == OsTypeWindows ? ".bat" : "");
- const FilePath scriptFile = sdk.withNewPath(script).searchInDirectories(env.path());
- toolChain->setCompilerCommand(scriptFile);
-
- const QString displayName = WebAssemblyToolChain::tr("Emscripten Compiler %1 for %2")
- .arg(toolChain->version(), QLatin1String(cLanguage ? "C" : "C++"));
- toolChain->setDisplayName(displayName);
- result.append(toolChain);
- }
-
- return result;
+ return doAutoDetect(detector);
}
} // namespace Internal
diff --git a/src/plugins/webassembly/webassemblytoolchain.h b/src/plugins/webassembly/webassemblytoolchain.h
index 41eeb72e94b..95291af7f41 100644
--- a/src/plugins/webassembly/webassemblytoolchain.h
+++ b/src/plugins/webassembly/webassemblytoolchain.h
@@ -37,6 +37,8 @@ class WebAssemblyToolChain final : public ProjectExplorer::GccToolChain
Q_DECLARE_TR_FUNCTIONS(WebAssembly::Internal::WebAssemblyToolChain)
public:
+ WebAssemblyToolChain();
+
void addToEnvironment(Utils::Environment &env) const override;
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
@@ -45,11 +47,6 @@ public:
static const QVersionNumber &minimumSupportedEmSdkVersion();
static void registerToolChains();
static bool areToolChainsRegistered();
-
-private:
- WebAssemblyToolChain();
-
- friend class WebAssemblyToolChainFactory;
};
class WebAssemblyToolChainFactory : public ProjectExplorer::ToolChainFactory
diff --git a/src/plugins/welcome/introductionwidget.cpp b/src/plugins/welcome/introductionwidget.cpp
index 6fc31990d20..f6b5d82c916 100644
--- a/src/plugins/welcome/introductionwidget.cpp
+++ b/src/plugins/welcome/introductionwidget.cpp
@@ -143,7 +143,7 @@ IntroductionWidget::IntroductionWidget(QWidget *parent)
"<li>click on the magnifier icon for a complete list of possible options</li>"
"</ul>")},
{QLatin1String("OutputPaneButtons"),
- tr("Output Panes"),
+ tr("Output"),
tr("Find compile and application output here, "
"as well as a list of configuration and build issues, "
"and the panel for global searches."),
@@ -155,7 +155,7 @@ IntroductionWidget::IntroductionWidget(QWidget *parent)
{{},
tr("Escape to Editor"),
tr("Pressing the Escape key brings you back to the editor. Press it "
- "multiple times to also hide output panes and context help, giving the editor more "
+ "multiple times to also hide context help and output, giving the editor more "
"space."),
{}},
{{},
diff --git a/src/plugins/winrt/CMakeLists.txt b/src/plugins/winrt/CMakeLists.txt
deleted file mode 100644
index 693b5446121..00000000000
--- a/src/plugins/winrt/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-add_qtc_plugin(WinRt
- PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport
- SOURCES
- winrt.qrc
- winrtconstants.h
- winrtdebugsupport.cpp winrtdebugsupport.h
- winrtdeployconfiguration.cpp winrtdeployconfiguration.h
- winrtdevice.cpp winrtdevice.h
- winrtpackagedeploymentstep.cpp winrtpackagedeploymentstep.h
- winrtphoneqtversion.cpp winrtphoneqtversion.h
- winrtplugin.cpp winrtplugin.h
- winrtqtversion.cpp winrtqtversion.h
- winrtrunconfiguration.cpp winrtrunconfiguration.h
- winrtruncontrol.cpp winrtruncontrol.h
- winrtrunnerhelper.cpp winrtrunnerhelper.h
-)
diff --git a/src/plugins/winrt/WinRt.json.in b/src/plugins/winrt/WinRt.json.in
deleted file mode 100644
index e776ddf9616..00000000000
--- a/src/plugins/winrt/WinRt.json.in
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- \"Name\" : \"WinRt\",
- \"Version\" : \"$$QTCREATOR_VERSION\",
- \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
- \"Platform\" : \"Windows (8.1|10|11)\",
- \"Vendor\" : \"The Qt Company Ltd\",
- \"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\",
- \"License\" : [ \"Commercial Usage\",
- \"\",
- \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\",
- \"\",
- \"GNU General Public License Usage\",
- \"\",
- \"Alternatively, this plugin may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this plugin. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html.\"
- ],
- \"Category\" : \"Device Support\",
- \"Description\" : \"Helper for Windows Runtime projects.\",
- \"Url\" : \"http://www.qt.io\",
- $$dependencyList
-}
diff --git a/src/plugins/winrt/images/winrtdevice.png b/src/plugins/winrt/images/winrtdevice.png
deleted file mode 100644
index 2b45adb69a1..00000000000
--- a/src/plugins/winrt/images/winrtdevice.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/winrt/images/winrtdevice@2x.png b/src/plugins/winrt/images/winrtdevice@2x.png
deleted file mode 100644
index a57f2b49783..00000000000
--- a/src/plugins/winrt/images/winrtdevice@2x.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/winrt/images/winrtdevicesmall.png b/src/plugins/winrt/images/winrtdevicesmall.png
deleted file mode 100644
index 42749765745..00000000000
--- a/src/plugins/winrt/images/winrtdevicesmall.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/winrt/images/winrtdevicesmall@2x.png b/src/plugins/winrt/images/winrtdevicesmall@2x.png
deleted file mode 100644
index 87f90b29ec5..00000000000
--- a/src/plugins/winrt/images/winrtdevicesmall@2x.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/winrt/winrt.qbs b/src/plugins/winrt/winrt.qbs
deleted file mode 100644
index f511a9c31a2..00000000000
--- a/src/plugins/winrt/winrt.qbs
+++ /dev/null
@@ -1,38 +0,0 @@
-import qbs 1.0
-
-QtcPlugin {
- name: "WinRt"
-
- Depends { name: "Core" }
- Depends { name: "Debugger" }
- Depends { name: "ProjectExplorer" }
- Depends { name: "QtSupport" }
- Depends { name: "QmakeProjectManager" }
- Depends { name: "Qt.gui" }
- Depends { name: "app_version_header" }
-
- files: [
- "winrt.qrc",
- "winrtconstants.h",
- "winrtdebugsupport.cpp",
- "winrtdebugsupport.h",
- "winrtdeployconfiguration.cpp",
- "winrtdeployconfiguration.h",
- "winrtdevice.cpp",
- "winrtdevice.h",
- "winrtpackagedeploymentstep.cpp",
- "winrtpackagedeploymentstep.h",
- "winrtphoneqtversion.cpp",
- "winrtphoneqtversion.h",
- "winrtplugin.cpp",
- "winrtplugin.h",
- "winrtqtversion.cpp",
- "winrtqtversion.h",
- "winrtrunconfiguration.cpp",
- "winrtrunconfiguration.h",
- "winrtruncontrol.cpp",
- "winrtruncontrol.h",
- "winrtrunnerhelper.cpp",
- "winrtrunnerhelper.h"
- ]
-}
diff --git a/src/plugins/winrt/winrt.qrc b/src/plugins/winrt/winrt.qrc
deleted file mode 100644
index 0771e1d0aa1..00000000000
--- a/src/plugins/winrt/winrt.qrc
+++ /dev/null
@@ -1,8 +0,0 @@
-<RCC>
- <qresource prefix="/winrt">
- <file>images/winrtdevice.png</file>
- <file>images/winrtdevice@2x.png</file>
- <file>images/winrtdevicesmall.png</file>
- <file>images/winrtdevicesmall@2x.png</file>
- </qresource>
-</RCC>
diff --git a/src/plugins/winrt/winrtconstants.h b/src/plugins/winrt/winrtconstants.h
deleted file mode 100644
index 03a6fbd36a0..00000000000
--- a/src/plugins/winrt/winrtconstants.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-namespace WinRt {
-namespace Internal {
-namespace Constants {
-
-const char WINRT_DEVICE_TYPE_LOCAL[] = "WinRt.Device.Local";
-const char WINRT_DEVICE_TYPE_EMULATOR[] = "WinRt.Device.Emulator";
-const char WINRT_DEVICE_TYPE_PHONE[] = "WinRt.Device.Phone";
-const char WINRT_BUILD_STEP_DEPLOY[] = "WinRt.BuildStep.Deploy";
-const char WINRT_WINRTQT[] = "WinRt.QtVersion.WindowsRuntime";
-const char WINRT_WINPHONEQT[] = "WinRt.QtVersion.WindowsPhone";
-const char WINRT_QTMAP_SUBKEYNAME[] = "WinRt";
-const char WINRT_QTMAP_OSFLAVOR[] = "OsFlavor";
-const char WINRT_MANIFEST_EDITOR_ID[] = "WinRTManifestEditorID";
-
-} // Constants
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtdebugsupport.cpp b/src/plugins/winrt/winrtdebugsupport.cpp
deleted file mode 100644
index 5ae70764b33..00000000000
--- a/src/plugins/winrt/winrtdebugsupport.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtdebugsupport.h"
-#include "winrtrunconfiguration.h"
-#include "winrtrunnerhelper.h"
-
-#include <app/app_version.h>
-
-#include <projectexplorer/target.h>
-#include <projectexplorer/toolchain.h>
-
-#include <qmldebug/qmldebugcommandlinearguments.h>
-
-#include <QFileInfo>
-#include <QLocalServer>
-#include <QLocalSocket>
-#include <QTcpServer>
-
-#include <utils/qtcprocess.h>
-#include <utils/url.h>
-
-using namespace Debugger;
-using namespace ProjectExplorer;
-
-namespace WinRt {
-namespace Internal {
-
-WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl)
- : DebuggerRunTool(runControl)
-{
- // FIXME: This is just working for local debugging;
- setStartMode(AttachToLocalProcess);
- // The first Thread needs to be resumed manually.
- setCommandsAfterConnect("~0 m");
-
- QFileInfo debuggerHelper(QCoreApplication::applicationDirPath()
- + QLatin1String("/winrtdebughelper.exe"));
- if (!debuggerHelper.isExecutable()) {
- reportFailure(tr("The WinRT debugging helper is missing from your %1 "
- "installation. It was assumed to be located at %2")
- .arg(Core::Constants::IDE_DISPLAY_NAME)
- .arg(debuggerHelper.absoluteFilePath()));
- return;
- }
-
- if (isQmlDebugging()) {
- QUrl qmlServer = Utils::urlFromLocalHostAndFreePort();
- if (qmlServer.port() <= 0) {
- reportFailure(tr("Not enough free ports for QML debugging."));
- return;
- }
- setQmlServer(qmlServer);
- }
-
- setSymbolFile(runControl->targetFilePath());
- QString errorMessage;
- m_runner = new WinRtRunnerHelper(this, &errorMessage);
- if (!errorMessage.isEmpty()) {
- reportFailure(errorMessage);
- return;
- }
-
- QLocalServer server;
- server.listen(QLatin1String("QtCreatorWinRtDebugPIDPipe"));
-
- m_runner->debug(debuggerHelper.absoluteFilePath());
- if (!m_runner->waitForStarted()) {
- reportFailure(tr("Cannot start the WinRT Runner Tool."));
- return;
- }
-
- if (!server.waitForNewConnection(10000)) {
- reportFailure(tr("Cannot establish connection to the WinRT debugging helper."));
- return;
- }
-
- while (server.hasPendingConnections()) {
- QLocalSocket *connection = server.nextPendingConnection();
- if (connection->waitForReadyRead(1000)) {
- const QByteArray &output = connection->readAll();
- QList<QByteArray> arg = output.split(':');
- if (arg.first() == "PID") {
- bool ok =false;
- int pid = arg.last().toInt(&ok);
- if (!ok) {
- reportFailure(tr("Cannot extract the PID from the WinRT debugging helper. "
- "(output: %1)").arg(QString::fromLocal8Bit(output)));
- return;
- }
- setAttachPid(Utils::ProcessHandle(pid));
- server.close();
- return;
- }
- }
- }
-
- server.close();
-
- reportFailure(tr("Cannot create an appropriate run control for "
- "the current run configuration."));
-}
-
-WinRtDebugSupport::~WinRtDebugSupport()
-{
- delete m_runner;
-}
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtdebugsupport.h b/src/plugins/winrt/winrtdebugsupport.h
deleted file mode 100644
index b8e3c6846ac..00000000000
--- a/src/plugins/winrt/winrtdebugsupport.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <debugger/debuggerruncontrol.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtRunConfiguration;
-class WinRtRunnerHelper;
-
-class WinRtDebugSupport : public Debugger::DebuggerRunTool
-{
- Q_OBJECT
-
-public:
- explicit WinRtDebugSupport(ProjectExplorer::RunControl *runControl);
- ~WinRtDebugSupport();
-
-private:
- WinRtRunnerHelper *m_runner = nullptr;
-};
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtdeployconfiguration.cpp b/src/plugins/winrt/winrtdeployconfiguration.cpp
deleted file mode 100644
index f42d48c924e..00000000000
--- a/src/plugins/winrt/winrtdeployconfiguration.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtdeployconfiguration.h"
-#include "winrtpackagedeploymentstep.h"
-#include "winrtconstants.h"
-
-#include <projectexplorer/project.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/buildsteplist.h>
-#include <projectexplorer/projectexplorerconstants.h>
-
-#include <QCoreApplication>
-
-using namespace ProjectExplorer;
-
-namespace WinRt {
-namespace Internal {
-
-WinRtAppDeployConfigurationFactory::WinRtAppDeployConfigurationFactory()
-{
- setConfigBaseId("WinRTAppxDeployConfiguration");
- setDefaultDisplayName(QCoreApplication::translate("WinRt::Internal::WinRtDeployConfiguration",
- "Run windeployqt"));
- addSupportedTargetDeviceType(Constants::WINRT_DEVICE_TYPE_LOCAL);
- addInitialStep(Constants::WINRT_BUILD_STEP_DEPLOY);
-}
-
-WinRtPhoneDeployConfigurationFactory::WinRtPhoneDeployConfigurationFactory()
-{
- setConfigBaseId("WinRTPhoneDeployConfiguration");
- setDefaultDisplayName(QCoreApplication::translate("WinRt::Internal::WinRtDeployConfiguration",
- "Deploy to Windows Phone"));
- addSupportedTargetDeviceType(Constants::WINRT_DEVICE_TYPE_PHONE);
- addInitialStep(Constants::WINRT_BUILD_STEP_DEPLOY);
-}
-
-WinRtEmulatorDeployConfigurationFactory::WinRtEmulatorDeployConfigurationFactory()
-{
- setConfigBaseId("WinRTEmulatorDeployConfiguration");
- setDefaultDisplayName(QCoreApplication::translate("WinRt::Internal::WinRtDeployConfiguration",
- "Deploy to Windows Phone Emulator"));
- addSupportedTargetDeviceType(Constants::WINRT_DEVICE_TYPE_EMULATOR);
- addInitialStep(Constants::WINRT_BUILD_STEP_DEPLOY);
-}
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtdeployconfiguration.h b/src/plugins/winrt/winrtdeployconfiguration.h
deleted file mode 100644
index 1ea45eb8e91..00000000000
--- a/src/plugins/winrt/winrtdeployconfiguration.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/deployconfiguration.h>
-#include <projectexplorer/buildstep.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtAppDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory
-{
-public:
- WinRtAppDeployConfigurationFactory();
-};
-
-class WinRtPhoneDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory
-{
-public:
- WinRtPhoneDeployConfigurationFactory();
-};
-
-class WinRtEmulatorDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory
-{
-public:
- WinRtEmulatorDeployConfigurationFactory();
-};
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtdevice.cpp b/src/plugins/winrt/winrtdevice.cpp
deleted file mode 100644
index 9c10c113a80..00000000000
--- a/src/plugins/winrt/winrtdevice.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtdevice.h"
-#include "winrtconstants.h"
-#include "winrtqtversion.h"
-
-#include <coreplugin/messagemanager.h>
-
-#include <projectexplorer/devicesupport/desktopprocesssignaloperation.h>
-#include <projectexplorer/devicesupport/devicemanager.h>
-#include <projectexplorer/devicesupport/deviceprocesslist.h>
-#include <projectexplorer/projectexplorerconstants.h>
-
-#include <qtsupport/qtversionmanager.h>
-
-#include <utils/qtcassert.h>
-#include <utils/portlist.h>
-
-#include <QFileInfo>
-#include <QIcon>
-#include <QLoggingCategory>
-#include <QWizard>
-
-using QtSupport::QtVersion;
-using QtSupport::QtVersionManager;
-
-
-using namespace Core;
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace WinRt {
-namespace Internal {
-
-static Q_LOGGING_CATEGORY(winrtDeviceLog, "qtc.winrt.deviceParser", QtWarningMsg)
-
-WinRtDevice::WinRtDevice()
-{
- setDisplayType(displayNameForType(type()));
- setOsType(OsTypeWindows);
-
- Utils::PortList portList;
- portList.addRange(Utils::Port(ProjectExplorer::Constants::DESKTOP_PORT_START),
- Utils::Port(ProjectExplorer::Constants::DESKTOP_PORT_END));
- setFreePorts(portList);
-}
-
-IDeviceWidget *WinRtDevice::createWidget()
-{
- return nullptr;
-}
-
-DeviceProcessSignalOperation::Ptr WinRtDevice::signalOperation() const
-{
- class WinRtDesktopSignalOperation : public DesktopProcessSignalOperation
- {
- public:
- WinRtDesktopSignalOperation() {}
- ~WinRtDesktopSignalOperation() {}
- };
-
- return DeviceProcessSignalOperation::Ptr(new WinRtDesktopSignalOperation());
-}
-
-void WinRtDevice::fromMap(const QVariantMap &map)
-{
- IDevice::fromMap(map);
- m_deviceId = map.value(QStringLiteral("WinRtRunnerDeviceId")).toInt();
-}
-
-QVariantMap WinRtDevice::toMap() const
-{
- QVariantMap map = IDevice::toMap();
- map.insert(QStringLiteral("WinRtRunnerDeviceId"), m_deviceId);
- return map;
-}
-
-QString WinRtDevice::displayNameForType(Utils::Id type)
-{
- if (type == Constants::WINRT_DEVICE_TYPE_LOCAL)
- return QCoreApplication::translate("WinRt::Internal::WinRtDevice",
- "Windows Runtime (Local)");
- if (type == Constants::WINRT_DEVICE_TYPE_PHONE)
- return QCoreApplication::translate("WinRt::Internal::WinRtDevice",
- "Windows Phone");
- if (type == Constants::WINRT_DEVICE_TYPE_EMULATOR)
- return QCoreApplication::translate("WinRt::Internal::WinRtDevice",
- "Windows Phone Emulator");
- return QString();
-}
-
-
-// Factory
-
-WinRtDeviceFactory::WinRtDeviceFactory(Utils::Id deviceType)
- : ProjectExplorer::IDeviceFactory(deviceType)
-{
- if (allPrerequisitesLoaded()) {
- onPrerequisitesLoaded();
- } else {
- connect(DeviceManager::instance(), &DeviceManager::devicesLoaded,
- this, &WinRtDeviceFactory::onPrerequisitesLoaded, Qt::QueuedConnection);
- connect(QtVersionManager::instance(),
- &QtVersionManager::qtVersionsLoaded,
- this, &WinRtDeviceFactory::onPrerequisitesLoaded, Qt::QueuedConnection);
- }
- setDisplayName(WinRtDevice::displayNameForType(deviceType));
- setConstructionFunction(&WinRtDevice::create);
- setCombinedIcon(":/winrt/images/winrtdevicesmall.png",
- ":/winrt/images/winrtdevice.png");
-}
-
-void WinRtDeviceFactory::autoDetect()
-{
- qCDebug(winrtDeviceLog) << __FUNCTION__;
- const QString runnerFilePath = findRunnerFilePath();
- if (runnerFilePath.isEmpty()) {
- qCDebug(winrtDeviceLog) << "No winrtrunner.exe found.";
- return;
- }
-
- if (!m_process) {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Creating process";
- m_process = new Utils::QtcProcess(this);
- connect(m_process, &QtcProcess::errorOccurred, this, &WinRtDeviceFactory::onProcessError);
- connect(m_process, &QtcProcess::finished, this, &WinRtDeviceFactory::onProcessFinished);
- }
-
- const CommandLine cmd{FilePath::fromString(runnerFilePath), {"--list-devices"}};
- m_process->setCommand(cmd);
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Starting process" << cmd.toUserOutput();
- m_process->start();
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Process started";
-}
-
-void WinRtDeviceFactory::onPrerequisitesLoaded()
-{
- if (!allPrerequisitesLoaded() || m_initialized)
- return;
-
- qCDebug(winrtDeviceLog) << __FUNCTION__;
- m_initialized = true;
- disconnect(DeviceManager::instance(), &DeviceManager::devicesLoaded,
- this, &WinRtDeviceFactory::onPrerequisitesLoaded);
- disconnect(QtVersionManager::instance(), &QtVersionManager::qtVersionsLoaded,
- this, &WinRtDeviceFactory::onPrerequisitesLoaded);
- autoDetect();
- connect(QtVersionManager::instance(), &QtVersionManager::qtVersionsChanged,
- this, &WinRtDeviceFactory::autoDetect);
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Done";
-}
-
-void WinRtDeviceFactory::onProcessError()
-{
- MessageManager::writeDisrupting(
- tr("Error while executing winrtrunner: %1").arg(m_process->errorString()));
-}
-
-void WinRtDeviceFactory::onProcessFinished()
-{
- int exitCode = m_process->exitCode();
- QProcess::ExitStatus exitStatus = m_process->exitStatus();
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Exit code:" << exitCode <<"\tExit status:"
- << exitStatus;
- if (exitStatus == QProcess::CrashExit) {
- // already handled in onProcessError
- return;
- }
-
- if (exitCode != 0) {
- MessageManager::writeFlashing(tr("winrtrunner returned with exit code %1.").arg(exitCode));
- return;
- }
-
- const QByteArray stdOut = m_process->readAllStandardOutput();
- const QByteArray stdErr = m_process->readAllStandardError();
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "winrtrunner's stdout:" << stdOut;
- if (!stdErr.isEmpty())
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "winrtrunner's stderr:" << stdErr;
- parseRunnerOutput(stdOut);
-}
-
-bool WinRtDeviceFactory::allPrerequisitesLoaded()
-{
- return QtVersionManager::isLoaded() && DeviceManager::instance()->isLoaded();
-}
-
-QString WinRtDeviceFactory::findRunnerFilePath() const
-{
- qCDebug(winrtDeviceLog) << __FUNCTION__;
- const QString winRtRunnerExe = QStringLiteral("/winrtrunner.exe");
- const QList<QtVersion *> winrtVersions
- = QtVersionManager::sortVersions(
- QtVersionManager::versions(QtVersion::isValidPredicate([](const QtVersion *v) {
- return v->type() == QLatin1String(Constants::WINRT_WINRTQT)
- || v->type() == QLatin1String(Constants::WINRT_WINPHONEQT);
- })));
- QString filePath;
- QtVersion *qt = nullptr;
- for (QtVersion *v : winrtVersions) {
- if (!qt || qt->qtVersion() < v->qtVersion()) {
- QFileInfo fi(v->hostBinPath().toString() + winRtRunnerExe);
- if (fi.isFile() && fi.isExecutable()) {
- qt = v;
- filePath = fi.absoluteFilePath();
- }
- }
- }
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Found" << filePath;
- return filePath;
-}
-
-static int extractDeviceId(QByteArray *line)
-{
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Line:" << *line;
- int pos = line->indexOf(' ');
- if (pos < 0) {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Could not find space, returning -1";
- return -1;
- }
- bool ok;
- int id = line->left(pos).toInt(&ok);
- if (!ok) {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Could not extract ID";
- return -1;
- }
- line->remove(0, pos + 1);
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Found ID" << id;
- return id;
-}
-
-static IDevice::MachineType machineTypeFromLine(const QByteArray &line)
-{
- return line.contains("Emulator ") ? IDevice::Emulator : IDevice::Hardware;
-}
-
-/*
- * The output of "winrtrunner --list-devices" looks like this:
- *
- * Available devices:
- * Appx:
- * 0 local
- * Phone:
- * 0 Device
- * 1 Emulator 8.1 WVGA 4 inch 512MB
- * 2 Emulator 8.1 WVGA 4 inch
- * 3 Emulator 8.1 WXGA 4 inch
- * 4 Emulator 8.1 720P 4.7 inch
- * 5 Emulator 8.1 1080P 5.5 inch
- * 6 Emulator 8.1 1080P 6 inch
- * 7 WE8.1H Emulator WVGA 512MB
- * 8 WE8.1H Emulator WVGA
- * 9 WE8.1H Emulator WXGA
- * 10 WE8.1H Emulator 720P
- * 11 WE8.1H Emulator 1080P
- * Xap:
- * 0 Device
- * 1 Emulator WVGA 512MB
- * 2 Emulator WVGA
- * 3 Emulator WXGA
- * 4 Emulator 720P
- */
-void WinRtDeviceFactory::parseRunnerOutput(const QByteArray &output) const
-{
- qCDebug(winrtDeviceLog) << __FUNCTION__;
- ProjectExplorer::DeviceManager *deviceManager = ProjectExplorer::DeviceManager::instance();
- enum State { StartState, AppxState, PhoneState, XapState };
- State state = StartState;
- int numFound = 0;
- int numSkipped = 0;
- foreach (QByteArray line, output.split('\n')) {
- line = line.trimmed();
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Line:" << line;
- if (line == "Appx:") {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "state = AppxState";
- state = AppxState;
- } else if (line == "Phone:") {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "state = PhoneState";
- state = PhoneState;
- } else if (line == "Xap:") {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "state = XapState";
- state = XapState;
- } else {
- const int deviceId = extractDeviceId(&line);
- if (deviceId < 0) {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Could not extract device ID";
- continue;
- }
-
- const IDevice::MachineType machineType = machineTypeFromLine(line);
- Utils::Id deviceType;
- QString name;
- QString internalName = QStringLiteral("WinRT.");
- if (state == AppxState) {
- internalName += QStringLiteral("appx.");
- deviceType = Constants::WINRT_DEVICE_TYPE_LOCAL;
- name = tr("Windows Runtime local UI");
- } else if (state == PhoneState) {
- internalName += QStringLiteral("phone.");
- name = QString::fromLocal8Bit(line);
- if (machineType == IDevice::Emulator)
- deviceType = Constants::WINRT_DEVICE_TYPE_EMULATOR;
- else
- deviceType = Constants::WINRT_DEVICE_TYPE_PHONE;
- } else if (state == XapState) {
- internalName += QStringLiteral("xap.");
- name = QString::fromLocal8Bit(line);
- if (machineType == IDevice::Emulator)
- deviceType = Constants::WINRT_DEVICE_TYPE_EMULATOR;
- else
- deviceType = Constants::WINRT_DEVICE_TYPE_PHONE;
- }
- internalName += QString::number(deviceId);
- const Utils::Id internalId = Utils::Id::fromString(internalName);
- ++numFound;
- if (DeviceManager::instance()->find(internalId)) {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Skipping device with ID" << deviceId;
- ++numSkipped;
- continue;
- }
-
- auto device = WinRtDevice::create();
- device->setupId(IDevice::AutoDetected, internalId);
- device->setDeviceId(deviceId);
- device->setType(deviceType);
- device->setMachineType(machineType);
- device->setDefaultDisplayName(name);
- deviceManager->addDevice(ProjectExplorer::IDevice::ConstPtr(device));
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Added device" << name << "(internal name:"
- << internalName << ")";
- }
- }
- QString message = tr("Found %n Windows Runtime devices.", nullptr, numFound);
- if (const int numNew = numFound - numSkipped) {
- message += QLatin1Char(' ');
- message += tr("%n of them are new.", nullptr, numNew);
- }
- qCDebug(winrtDeviceLog) << message;
-}
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtdevice.h b/src/plugins/winrt/winrtdevice.h
deleted file mode 100644
index 37d81131557..00000000000
--- a/src/plugins/winrt/winrtdevice.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/devicesupport/idevice.h>
-#include <projectexplorer/devicesupport/idevicefactory.h>
-
-#include <utils/qtcprocess.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtDevice final : public ProjectExplorer::IDevice
-{
-public:
- typedef QSharedPointer<WinRtDevice> Ptr;
- typedef QSharedPointer<const WinRtDevice> ConstPtr;
-
- static Ptr create() { return Ptr(new WinRtDevice); }
-
- ProjectExplorer::IDeviceWidget *createWidget() override;
- ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override;
-
- static QString displayNameForType(Utils::Id type);
- int deviceId() const { return m_deviceId; }
- void setDeviceId(int deviceId) { m_deviceId = deviceId; }
-
-protected:
- void fromMap(const QVariantMap &map) final;
- QVariantMap toMap() const final;
-
-private:
- WinRtDevice();
-
- int m_deviceId = -1;
-};
-
-class WinRtDeviceFactory final : public QObject, public ProjectExplorer::IDeviceFactory
-{
- Q_OBJECT
-public:
- explicit WinRtDeviceFactory(Utils::Id deviceType);
-
- void autoDetect();
- void onPrerequisitesLoaded();
-
-private:
- void onProcessError();
- void onProcessFinished();
-
- static bool allPrerequisitesLoaded();
- QString findRunnerFilePath() const;
- void parseRunnerOutput(const QByteArray &output) const;
-
- Utils::QtcProcess *m_process = nullptr;
- bool m_initialized = false;
-};
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtpackagedeploymentstep.cpp b/src/plugins/winrt/winrtpackagedeploymentstep.cpp
deleted file mode 100644
index 067c04c361b..00000000000
--- a/src/plugins/winrt/winrtpackagedeploymentstep.cpp
+++ /dev/null
@@ -1,408 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtpackagedeploymentstep.h"
-
-#include "winrtconstants.h"
-
-#include <projectexplorer/abstractprocessstep.h>
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/buildtargetinfo.h>
-#include <projectexplorer/deployablefile.h>
-#include <projectexplorer/deploymentdata.h>
-#include <projectexplorer/processparameters.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/runconfiguration.h>
-#include <projectexplorer/target.h>
-
-#include <qtsupport/qtkitinformation.h>
-
-#include <utils/aspects.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-#include <utils/fancylineedit.h>
-#include <utils/layoutbuilder.h>
-
-#include <QLabel>
-#include <QLayout>
-#include <QRegularExpression>
-#include <QToolButton>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace WinRt {
-namespace Internal {
-
-const char ARGUMENTS_KEY[] = "WinRt.BuildStep.Deploy.Arguments";
-const char DEFAULTARGUMENTS_KEY[] = "WinRt.BuildStep.Deploy.DefaultArguments";
-
-class WinRtArgumentsAspect final : public BaseAspect
-{
- Q_DECLARE_TR_FUNCTIONS(WinRt::Internal::WinRtArgumentsAspect)
-
-public:
- WinRtArgumentsAspect() = default;
-
- void addToLayout(LayoutBuilder &builder) final;
-
- void fromMap(const QVariantMap &map) final;
- void toMap(QVariantMap &map) const final;
-
- void setValue(const QString &value);
- QString value() const { return m_value; }
-
- void setDefaultValue(const QString &value) { m_defaultValue = value; }
- QString defaultValue() const { return m_defaultValue; }
-
- void restoreDefaultValue();
-
-private:
- FancyLineEdit *m_lineEdit = nullptr;
- QString m_value;
- QString m_defaultValue;
-};
-
-class WinRtPackageDeploymentStep final : public AbstractProcessStep
-{
- Q_DECLARE_TR_FUNCTIONS(WinRt::Internal::WinRtPackageDeploymentStep)
-
-public:
- WinRtPackageDeploymentStep(BuildStepList *bsl, Utils::Id id);
-
- QString defaultWinDeployQtArguments() const;
-
- void raiseError(const QString &errorMessage);
- void raiseWarning(const QString &warningMessage);
-
-private:
- bool init() override;
- void doRun() override;
- bool processSucceeded(int exitCode, QProcess::ExitStatus status) override;
- void stdOutput(const QString &line) override;
-
- bool parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *items, QString *executable);
-
- WinRtArgumentsAspect *m_argsAspect = nullptr;
- QString m_targetFilePath;
- QString m_targetDirPath;
- QString m_executablePathInManifest;
- QString m_mappingFileContent;
- QString m_manifestFileName;
- bool m_createMappingFile = false;
-};
-
-void WinRtArgumentsAspect::addToLayout(LayoutBuilder &builder)
-{
- QTC_CHECK(!m_lineEdit);
- auto label = new QLabel(tr("Arguments:"));
- label->setTextInteractionFlags(Qt::TextSelectableByMouse);
- builder.addItem(label);
-
- auto *layout = new QHBoxLayout();
- m_lineEdit = new Utils::FancyLineEdit();
- if (!m_value.isEmpty())
- m_lineEdit->setText(m_value);
- else if (!m_defaultValue.isEmpty())
- m_lineEdit->setText(m_defaultValue);
- connect(m_lineEdit, &Utils::FancyLineEdit::textEdited,
- this, &WinRtArgumentsAspect::setValue);
- layout->addWidget(m_lineEdit);
-
- auto restoreDefaultButton = new QToolButton();
- restoreDefaultButton->setText(tr("Restore Default Arguments"));
- connect(restoreDefaultButton, &QToolButton::clicked,
- this, &WinRtArgumentsAspect::restoreDefaultValue);
- layout->addWidget(restoreDefaultButton);
- builder.addItem(layout);
-}
-
-void WinRtArgumentsAspect::fromMap(const QVariantMap &map)
-{
- m_defaultValue = map.value(DEFAULTARGUMENTS_KEY).toString();
- m_value = map.value(ARGUMENTS_KEY).toString();
-}
-
-void WinRtArgumentsAspect::toMap(QVariantMap &map) const
-{
- map.insert(DEFAULTARGUMENTS_KEY, m_defaultValue);
- map.insert(ARGUMENTS_KEY, m_value);
-}
-
-void WinRtArgumentsAspect::setValue(const QString &value)
-{
- if (value == m_value)
- return;
-
- m_value = value;
- if (m_lineEdit)
- m_lineEdit->setText(value);
- emit changed();
-}
-
-void WinRtArgumentsAspect::restoreDefaultValue()
-{
- if (m_defaultValue == m_value)
- return;
-
- setValue(m_defaultValue);
-}
-
-WinRtPackageDeploymentStep::WinRtPackageDeploymentStep(BuildStepList *bsl, Utils::Id id)
- : AbstractProcessStep(bsl, id)
-{
- setDisplayName(tr("Run windeployqt"));
-
- m_argsAspect = addAspect<WinRtArgumentsAspect>();
- m_argsAspect->setDefaultValue(defaultWinDeployQtArguments());
- m_argsAspect->setValue(defaultWinDeployQtArguments());
-}
-
-bool WinRtPackageDeploymentStep::init()
-{
- if (!AbstractProcessStep::init())
- return false;
-
- RunConfiguration *rc = target()->activeRunConfiguration();
- QTC_ASSERT(rc, return false);
-
- const BuildTargetInfo bti = rc->buildTargetInfo();
- Utils::FilePath appTargetFilePath = bti.targetFilePath;
-
- m_targetFilePath = appTargetFilePath.toString();
- if (m_targetFilePath.isEmpty()) {
- raiseError(tr("No executable to deploy found in %1.").arg(bti.projectFilePath.toString()));
- return false;
- }
-
- // ### Ideally, the file paths in applicationTargets() should already have the .exe suffix.
- // Whenever this will eventually work, we can drop appending the .exe suffix here.
- if (!m_targetFilePath.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive))
- m_targetFilePath.append(QLatin1String(".exe"));
-
- m_targetDirPath = appTargetFilePath.parentDir().toString();
- if (!m_targetDirPath.endsWith(QLatin1Char('/')))
- m_targetDirPath += QLatin1Char('/');
-
- const QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(kit());
- if (!qt)
- return false;
-
- const FilePath windeployqtPath = qt->hostBinPath().resolvePath(QString("windeployqt.exe"));
-
- CommandLine windeployqt{windeployqtPath};
- windeployqt.addArg(QDir::toNativeSeparators(m_targetFilePath));
- windeployqt.addArgs(m_argsAspect->value(), CommandLine::Raw);
-
- if (qt->type() == Constants::WINRT_WINPHONEQT) {
- m_createMappingFile = true;
- windeployqt.addArgs({"-list", "mapping"});
- }
-
- ProcessParameters *params = processParameters();
- if (!windeployqtPath.exists()) {
- raiseError(tr("Cannot find windeployqt.exe in \"%1\".")
- .arg(QDir::toNativeSeparators(qt->hostBinPath().toString())));
- return false;
- }
- params->setCommandLine(windeployqt);
- params->setEnvironment(target()->activeBuildConfiguration()
- ? target()->activeBuildConfiguration()->environment()
- : Environment::systemEnvironment());
-
- return true;
-}
-
-void WinRtPackageDeploymentStep::doRun()
-{
- const QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(kit());
- if (!qt)
- return;
-
- m_manifestFileName = QStringLiteral("AppxManifest");
-
- if (m_createMappingFile) {
- m_mappingFileContent = QLatin1String("[Files]\n");
-
- QDir assetDirectory(m_targetDirPath + QLatin1String("assets"));
- if (assetDirectory.exists()) {
- QStringList iconsToDeploy;
- const QString fullManifestPath = m_targetDirPath + m_manifestFileName
- + QLatin1String(".xml");
- if (!parseIconsAndExecutableFromManifest(fullManifestPath, &iconsToDeploy,
- &m_executablePathInManifest)) {
- raiseError(tr("Cannot parse manifest file %1.").arg(fullManifestPath));
- return;
- }
- foreach (const QString &icon, iconsToDeploy) {
- m_mappingFileContent += QLatin1Char('"')
- + QDir::toNativeSeparators(m_targetDirPath + icon) + QLatin1String("\" \"")
- + QDir::toNativeSeparators(icon) + QLatin1String("\"\n");
- }
- }
- }
-
- AbstractProcessStep::doRun();
-}
-
-bool WinRtPackageDeploymentStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
-{
- if (m_createMappingFile) {
- QString targetInstallationPath;
- // The list holds the local file paths and the "remote" file paths
- QList<QPair<QString, QString> > installableFilesList;
- foreach (DeployableFile file, target()->deploymentData().allFiles()) {
- QString remoteFilePath = file.remoteFilePath();
- while (remoteFilePath.startsWith(QLatin1Char('/')))
- remoteFilePath.remove(0, 1);
- QString localFilePath = file.localFilePath().toString();
- if (localFilePath == m_targetFilePath) {
- if (!m_targetFilePath.endsWith(QLatin1String(".exe"))) {
- remoteFilePath += QLatin1String(".exe");
- localFilePath += QLatin1String(".exe");
- }
- targetInstallationPath = remoteFilePath;
- }
- installableFilesList.append(QPair<QString, QString>(localFilePath, remoteFilePath));
- }
-
- // if there are no INSTALLS set we just deploy the files from windeployqt,
- // the icons referenced in the manifest file and the actual build target
- QString baseDir;
- if (targetInstallationPath.isEmpty()) {
- if (!m_targetFilePath.endsWith(QLatin1String(".exe")))
- m_targetFilePath.append(QLatin1String(".exe"));
- m_mappingFileContent
- += QLatin1Char('"') + QDir::toNativeSeparators(m_targetFilePath)
- + QLatin1String("\" \"")
- + QDir::toNativeSeparators(m_executablePathInManifest) + QLatin1String("\"\n");
- baseDir = m_targetDirPath;
- } else {
- baseDir = targetInstallationPath.left(targetInstallationPath.lastIndexOf(QLatin1Char('/')) + 1);
- }
-
- typedef QPair<QString, QString> QStringPair;
- foreach (const QStringPair &pair, installableFilesList) {
- // For the mapping file we need the remote paths relative to the application's executable
- QString relativeRemotePath;
- if (QDir(pair.second).isRelative())
- relativeRemotePath = pair.second;
- else
- relativeRemotePath = QDir(baseDir).relativeFilePath(pair.second);
-
- if (QDir(relativeRemotePath).isAbsolute() || relativeRemotePath.startsWith(QLatin1String(".."))) {
- raiseWarning(tr("File %1 is outside of the executable's directory. These files cannot be installed.").arg(relativeRemotePath));
- continue;
- }
-
- m_mappingFileContent += QLatin1Char('"') + QDir::toNativeSeparators(pair.first)
- + QLatin1String("\" \"") + QDir::toNativeSeparators(relativeRemotePath)
- + QLatin1String("\"\n");
- }
-
- const QString mappingFilePath = m_targetDirPath + m_manifestFileName
- + QLatin1String(".map");
- QFile mappingFile(mappingFilePath);
- if (!mappingFile.open(QFile::WriteOnly | QFile::Text)) {
- raiseError(tr("Cannot open mapping file %1 for writing.").arg(mappingFilePath));
- return false;
- }
- mappingFile.write(m_mappingFileContent.toUtf8());
- }
-
- return AbstractProcessStep::processSucceeded(exitCode, status);
-}
-
-void WinRtPackageDeploymentStep::stdOutput(const QString &line)
-{
- if (m_createMappingFile)
- m_mappingFileContent += line;
- AbstractProcessStep::stdOutput(line);
-}
-
-QString WinRtPackageDeploymentStep::defaultWinDeployQtArguments() const
-{
- QString args;
- ProcessArgs::addArg(&args, QStringLiteral("--qmldir"));
- ProcessArgs::addArg(&args, project()->projectDirectory().toUserOutput());
- return args;
-}
-
-void WinRtPackageDeploymentStep::raiseError(const QString &errorMessage)
-{
- emit addOutput(errorMessage, BuildStep::OutputFormat::ErrorMessage);
- emit addTask(DeploymentTask(Task::Error, errorMessage), 1);
-}
-
-void WinRtPackageDeploymentStep::raiseWarning(const QString &warningMessage)
-{
- emit addOutput(warningMessage, BuildStep::OutputFormat::NormalMessage);
- emit addTask(DeploymentTask(Task::Warning, warningMessage), 1);
-}
-
-bool WinRtPackageDeploymentStep::parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *icons, QString *executable)
-{
- if (!icons->isEmpty())
- icons->clear();
- QFile manifestFile(manifestFileName);
- if (!manifestFile.open(QFile::ReadOnly))
- return false;
- const QString contents = QString::fromUtf8(manifestFile.readAll());
-
- QRegularExpression iconPattern(QStringLiteral("[\\\\/a-zA-Z0-9_\\-\\!]*\\.(png|jpg|jpeg)"));
- QRegularExpressionMatchIterator iterator = iconPattern.globalMatch(contents);
- while (iterator.hasNext()) {
- QRegularExpressionMatch match = iterator.next();
- const QString icon = match.captured(0);
- icons->append(icon);
- }
-
- const QLatin1String executablePrefix(manifestFileName.contains(QLatin1String("AppxManifest")) ? "Executable=" : "ImagePath=");
- QRegularExpression executablePattern(executablePrefix + QStringLiteral("\"([a-zA-Z0-9_-]*\\.exe)\""));
- QRegularExpressionMatch match = executablePattern.match(contents);
- if (!match.hasMatch())
- return false;
- *executable = match.captured(1);
-
- return true;
-}
-
-// WinRtDeployStepFactory
-
-WinRtDeployStepFactory::WinRtDeployStepFactory()
-{
- registerStep<WinRtPackageDeploymentStep>(Constants::WINRT_BUILD_STEP_DEPLOY);
- setDisplayName(QCoreApplication::translate("WinRt::Internal::WinRtDeployStepFactory", "Run windeployqt"));
- setFlags(BuildStepInfo::Unclonable);
- setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY);
- setSupportedDeviceTypes({Constants::WINRT_DEVICE_TYPE_LOCAL,
- Constants::WINRT_DEVICE_TYPE_EMULATOR,
- Constants::WINRT_DEVICE_TYPE_PHONE});
- setRepeatable(false);
-}
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtpackagedeploymentstep.h b/src/plugins/winrt/winrtpackagedeploymentstep.h
deleted file mode 100644
index c20898ade90..00000000000
--- a/src/plugins/winrt/winrtpackagedeploymentstep.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/buildstep.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtDeployStepFactory final : public ProjectExplorer::BuildStepFactory
-{
-public:
- WinRtDeployStepFactory();
-};
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtphoneqtversion.cpp b/src/plugins/winrt/winrtphoneqtversion.cpp
deleted file mode 100644
index de0289bdd11..00000000000
--- a/src/plugins/winrt/winrtphoneqtversion.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtphoneqtversion.h"
-
-#include "winrtconstants.h"
-
-#include <qtsupport/qtsupportconstants.h>
-
-#include <utils/id.h>
-
-#include <QSet>
-
-namespace WinRt {
-namespace Internal {
-
-QString WinRtPhoneQtVersion::description() const
-{
- return tr("Windows Phone");
-}
-
-QSet<Utils::Id> WinRtPhoneQtVersion::targetDeviceTypes() const
-{
- return {Constants::WINRT_DEVICE_TYPE_PHONE, Constants::WINRT_DEVICE_TYPE_EMULATOR};
-}
-
-QSet<Utils::Id> WinRtPhoneQtVersion::availableFeatures() const
-{
- QSet<Utils::Id> features = QtSupport::QtVersion::availableFeatures();
- features.insert(QtSupport::Constants::FEATURE_MOBILE);
- features.remove(QtSupport::Constants::FEATURE_QT_CONSOLE);
- features.remove(Utils::Id::versionedId(QtSupport::Constants::FEATURE_QT_QUICK_CONTROLS_PREFIX, 1));
- features.remove(QtSupport::Constants::FEATURE_QT_WEBKIT);
- return features;
-}
-
-// Factory
-
-WinRtPhoneQtVersionFactory::WinRtPhoneQtVersionFactory()
-{
- setQtVersionCreator([] { return new WinRtPhoneQtVersion; });
- setSupportedType(Constants::WINRT_WINPHONEQT);
- setRestrictionChecker([](const SetupData &setup) { return setup.platforms.contains("winphone"); });
- setPriority(10);
-}
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtphoneqtversion.h b/src/plugins/winrt/winrtphoneqtversion.h
deleted file mode 100644
index 060d551c6f0..00000000000
--- a/src/plugins/winrt/winrtphoneqtversion.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "winrtqtversion.h"
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtPhoneQtVersion : public QtSupport::QtVersion
-{
- Q_DECLARE_TR_FUNCTIONS(WinRt::Internal::WinRtQtVersion)
-public:
- WinRtPhoneQtVersion() = default;
-
- QSet<Utils::Id> availableFeatures() const override;
-
- QString description() const override;
- QSet<Utils::Id> targetDeviceTypes() const override;
-};
-
-class WinRtPhoneQtVersionFactory : public QtSupport::QtVersionFactory
-{
-public:
- WinRtPhoneQtVersionFactory();
-};
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtplugin.cpp b/src/plugins/winrt/winrtplugin.cpp
deleted file mode 100644
index 2b603bff266..00000000000
--- a/src/plugins/winrt/winrtplugin.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtplugin.h"
-
-#include "winrtconstants.h"
-#include "winrtdebugsupport.h"
-#include "winrtdeployconfiguration.h"
-#include "winrtdevice.h"
-#include "winrtpackagedeploymentstep.h"
-#include "winrtphoneqtversion.h"
-#include "winrtqtversion.h"
-#include "winrtrunconfiguration.h"
-#include "winrtruncontrol.h"
-
-#include <projectexplorer/devicesupport/devicemanager.h>
-#include <projectexplorer/devicesupport/idevice.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/target.h>
-
-using namespace ProjectExplorer;
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtPluginPrivate
-{
-public:
- WinRtRunConfigurationFactory runConfigFactory;
- WinRtQtVersionFactory qtVersionFactory;
- WinRtPhoneQtVersionFactory phoneQtVersionFactory;
- WinRtAppDeployConfigurationFactory appDeployConfigFactory;
- WinRtPhoneDeployConfigurationFactory phoneDeployConfigFactory;
- WinRtEmulatorDeployConfigurationFactory emulatorDeployFactory;
- WinRtDeployStepFactory deployStepFactory;
- WinRtDeviceFactory localDeviceFactory{Constants::WINRT_DEVICE_TYPE_LOCAL};
- WinRtDeviceFactory phoneDeviceFactory{Constants::WINRT_DEVICE_TYPE_PHONE};
- WinRtDeviceFactory emulatorDeviceFactory{Constants::WINRT_DEVICE_TYPE_EMULATOR};
-
- RunWorkerFactory runWorkerFactory{
- RunWorkerFactory::make<WinRtRunner>(),
- {ProjectExplorer::Constants::NORMAL_RUN_MODE},
- {runConfigFactory.runConfigurationId()}
- };
-
- RunWorkerFactory debugWorkerFactory{
- RunWorkerFactory::make<WinRtDebugSupport>(),
- {ProjectExplorer::Constants::DEBUG_RUN_MODE},
- {runConfigFactory.runConfigurationId()},
- {Internal::Constants::WINRT_DEVICE_TYPE_LOCAL}
- };
-};
-
-WinRtPlugin::~WinRtPlugin()
-{
- delete d;
-}
-
-bool WinRtPlugin::initialize(const QStringList &arguments, QString *errorMessage)
-{
- Q_UNUSED(arguments)
- Q_UNUSED(errorMessage)
-
- d = new WinRtPluginPrivate;
-
- return true;
-}
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtplugin.h b/src/plugins/winrt/winrtplugin.h
deleted file mode 100644
index bdfc0f09f1e..00000000000
--- a/src/plugins/winrt/winrtplugin.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <extensionsystem/iplugin.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtPlugin final : public ExtensionSystem::IPlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "WinRt.json")
-
-public:
- ~WinRtPlugin() final;
-
-private:
- bool initialize(const QStringList &arguments, QString *errorMessage) final;
-
- class WinRtPluginPrivate *d = nullptr;
-};
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtqtversion.cpp b/src/plugins/winrt/winrtqtversion.cpp
deleted file mode 100644
index 4b3ce1facd9..00000000000
--- a/src/plugins/winrt/winrtqtversion.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtqtversion.h"
-
-#include "winrtconstants.h"
-
-#include <coreplugin/featureprovider.h>
-#include <qtsupport/qtsupportconstants.h>
-
-namespace WinRt {
-namespace Internal {
-
-QString WinRtQtVersion::description() const
-{
- return tr("Windows Runtime");
-}
-
-QSet<Utils::Id> WinRtQtVersion::availableFeatures() const
-{
- QSet<Utils::Id> features = QtSupport::QtVersion::availableFeatures();
- features.insert(QtSupport::Constants::FEATURE_MOBILE);
- features.remove(QtSupport::Constants::FEATURE_QT_CONSOLE);
- features.remove(Utils::Id::versionedId(QtSupport::Constants::FEATURE_QT_QUICK_CONTROLS_PREFIX, 1));
- features.remove(QtSupport::Constants::FEATURE_QT_WEBKIT);
- return features;
-}
-
-QSet<Utils::Id> WinRtQtVersion::targetDeviceTypes() const
-{
- return {Constants::WINRT_DEVICE_TYPE_LOCAL, Constants::WINRT_DEVICE_TYPE_EMULATOR};
-}
-
-
-// Factory
-
-WinRtQtVersionFactory::WinRtQtVersionFactory()
-{
- setQtVersionCreator([] { return new WinRtQtVersion; });
- setSupportedType(Constants::WINRT_WINRTQT);
- setRestrictionChecker([](const SetupData &setup) { return setup.platforms.contains("winrt"); });
- setPriority(10);
-}
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtqtversion.h b/src/plugins/winrt/winrtqtversion.h
deleted file mode 100644
index 2c767ff3d01..00000000000
--- a/src/plugins/winrt/winrtqtversion.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <qtsupport/baseqtversion.h>
-#include <qtsupport/qtversionfactory.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtQtVersion : public QtSupport::QtVersion
-{
- Q_DECLARE_TR_FUNCTIONS(WinRt::Internal::WinRtQtVersion)
-public:
- WinRtQtVersion() = default;
-
- QString description() const override;
- QSet<Utils::Id> availableFeatures() const override;
-
- QSet<Utils::Id> targetDeviceTypes() const override;
-};
-
-class WinRtQtVersionFactory : public QtSupport::QtVersionFactory
-{
-public:
- WinRtQtVersionFactory();
-};
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtrunconfiguration.cpp b/src/plugins/winrt/winrtrunconfiguration.cpp
deleted file mode 100644
index 6103a469b18..00000000000
--- a/src/plugins/winrt/winrtrunconfiguration.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtrunconfiguration.h"
-#include "winrtconstants.h"
-
-#include <projectexplorer/target.h>
-#include <qtsupport/baseqtversion.h>
-#include <qtsupport/qtkitinformation.h>
-
-using namespace ProjectExplorer;
-
-namespace WinRt {
-namespace Internal {
-
-// UninstallAfterStopAspect
-
-UninstallAfterStopAspect::UninstallAfterStopAspect()
- : BoolAspect("WinRtRunConfigurationUninstallAfterStopId")
-{
- setLabel(WinRtRunConfiguration::tr("Uninstall package after application stops"),
- LabelPlacement::AtCheckBox);
-}
-
-// LoopbackExemptClientAspect
-
-LoopbackExemptClientAspect::LoopbackExemptClientAspect()
- : BoolAspect("WinRtRunConfigurationLoopbackExemptClient")
-{
- setLabel(WinRtRunConfiguration::tr("Enable localhost communication for clients"),
- LabelPlacement::AtCheckBox);
-}
-
-// LoopbackExemptServerAspect
-
-LoopbackExemptServerAspect::LoopbackExemptServerAspect()
- : BoolAspect("WinRtRunConfigurationLoopbackExemptServer")
-{
- setLabel(WinRtRunConfiguration::tr("Enable localhost communication for "
- "servers (requires elevated rights)"),
- LabelPlacement::AtCheckBox);
-}
-
-// WinRtRunConfiguration
-
-WinRtRunConfiguration::WinRtRunConfiguration(Target *target, Utils::Id id)
- : RunConfiguration(target, id)
-{
- setDisplayName(tr("Run App Package"));
- addAspect<ArgumentsAspect>();
- addAspect<UninstallAfterStopAspect>();
-
- const QtSupport::QtVersion *qt
- = QtSupport::QtKitAspect::qtVersion(target->kit());
- if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 12, 0)) {
- addAspect<LoopbackExemptClientAspect>();
- addAspect<LoopbackExemptServerAspect>();
- }
-}
-
-// WinRtRunConfigurationFactory
-
-WinRtRunConfigurationFactory::WinRtRunConfigurationFactory()
-{
- registerRunConfiguration<WinRtRunConfiguration>("WinRt.WinRtRunConfiguration:");
- addSupportedTargetDeviceType(Constants::WINRT_DEVICE_TYPE_LOCAL);
- addSupportedTargetDeviceType(Constants::WINRT_DEVICE_TYPE_PHONE);
- addSupportedTargetDeviceType(Constants::WINRT_DEVICE_TYPE_EMULATOR);
-}
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtrunconfiguration.h b/src/plugins/winrt/winrtrunconfiguration.h
deleted file mode 100644
index 8e9cf4f0c1e..00000000000
--- a/src/plugins/winrt/winrtrunconfiguration.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/runconfigurationaspects.h>
-
-namespace WinRt {
-namespace Internal {
-
-class UninstallAfterStopAspect : public Utils::BoolAspect
-{
- Q_OBJECT
-
-public:
- UninstallAfterStopAspect();
-};
-
-class LoopbackExemptClientAspect : public Utils::BoolAspect
-{
- Q_OBJECT
-
-public:
- LoopbackExemptClientAspect();
-};
-
-class LoopbackExemptServerAspect : public Utils::BoolAspect
-{
- Q_OBJECT
-
-public:
- LoopbackExemptServerAspect();
-};
-
-class WinRtRunConfiguration : public ProjectExplorer::RunConfiguration
-{
- Q_OBJECT
-
-public:
- WinRtRunConfiguration(ProjectExplorer::Target *target, Utils::Id id);
-};
-
-class WinRtRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
-{
-public:
- WinRtRunConfigurationFactory();
-};
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtruncontrol.cpp b/src/plugins/winrt/winrtruncontrol.cpp
deleted file mode 100644
index 53099cec5cf..00000000000
--- a/src/plugins/winrt/winrtruncontrol.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtruncontrol.h"
-
-#include "winrtdevice.h"
-#include "winrtrunconfiguration.h"
-#include "winrtrunnerhelper.h"
-
-#include <coreplugin/idocument.h>
-#include <extensionsystem/pluginmanager.h>
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/buildtargetinfo.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/kitinformation.h>
-#include <qtsupport/qtkitinformation.h>
-#include <utils/utilsicons.h>
-
-#include <QTimer>
-
-using ProjectExplorer::DeviceKitAspect;
-using ProjectExplorer::IDevice;
-using ProjectExplorer::RunControl;
-using Utils::Id;
-using ProjectExplorer::Target;
-
-namespace WinRt {
-namespace Internal {
-
-WinRtRunner::WinRtRunner(RunControl *runControl)
- : RunWorker(runControl)
-{
- runControl->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR);
-}
-
-void WinRtRunner::start()
-{
- if (m_state != StoppedState)
- return;
-
- QTC_ASSERT(!m_runner, m_state = StoppedState; reportFailure(); return);
- QString errorMessage;
- m_runner = new WinRtRunnerHelper(this, &errorMessage);
- if (!errorMessage.isEmpty()) {
- reportFailure(errorMessage);
- return;
- }
- connect(m_runner, &WinRtRunnerHelper::started, this, &WinRtRunner::onProcessStarted);
- connect(m_runner, &WinRtRunnerHelper::finished, this, &WinRtRunner::onProcessFinished);
- connect(m_runner, &WinRtRunnerHelper::error, this, &WinRtRunner::onProcessError);
- m_state = StartingState;
- m_runner->start();
-}
-
-void WinRtRunner::stop()
-{
- if (m_state == StoppedState)
- return;
-
- m_runner->stop();
-}
-
-void WinRtRunner::onProcessStarted()
-{
- QTC_CHECK(m_state == StartingState);
- m_state = StartedState;
- reportStarted();
-}
-
-void WinRtRunner::onProcessFinished()
-{
- QTC_CHECK(m_state == StartedState);
- onProcessError();
-}
-
-void WinRtRunner::onProcessError()
-{
- QTC_ASSERT(m_runner, return);
- m_runner->disconnect();
- m_runner->deleteLater();
- m_runner = nullptr;
- m_state = StoppedState;
- reportStopped();
-}
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtruncontrol.h b/src/plugins/winrt/winrtruncontrol.h
deleted file mode 100644
index 6105525d15d..00000000000
--- a/src/plugins/winrt/winrtruncontrol.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "winrtdevice.h"
-
-#include <projectexplorer/runcontrol.h>
-#include <utils/qtcprocess.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtRunnerHelper;
-
-class WinRtRunner : public ProjectExplorer::RunWorker
-{
- Q_OBJECT
-public:
- explicit WinRtRunner(ProjectExplorer::RunControl *runControl);
-
- void start() override;
- void stop() override;
-
-private:
- enum State { StartingState, StartedState, StoppedState };
-
- void onProcessStarted();
- void onProcessFinished();
- void onProcessError();
-
- State m_state = StoppedState;
- Utils::QtcProcess *m_process = nullptr;
- WinRtRunnerHelper *m_runner = nullptr;
-};
-
-} // namespace Internal
-} // namespace WinRt
diff --git a/src/plugins/winrt/winrtrunnerhelper.cpp b/src/plugins/winrt/winrtrunnerhelper.cpp
deleted file mode 100644
index 4340c2260c6..00000000000
--- a/src/plugins/winrt/winrtrunnerhelper.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtrunnerhelper.h"
-
-#include "winrtconstants.h"
-#include "winrtrunconfiguration.h"
-
-#include <coreplugin/idocument.h>
-
-#include <projectexplorer/buildtargetinfo.h>
-#include <projectexplorer/devicesupport/idevice.h>
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/runcontrol.h>
-#include <projectexplorer/target.h>
-
-#include <qtsupport/baseqtversion.h>
-#include <qtsupport/qtkitinformation.h>
-#include <utils/qtcprocess.h>
-
-#include <QDir>
-
-using namespace ProjectExplorer;
-
-using namespace WinRt;
-using namespace WinRt::Internal;
-
-WinRtRunnerHelper::WinRtRunnerHelper(ProjectExplorer::RunWorker *runWorker, QString *errorMessage)
- : QObject(runWorker)
- , m_worker(runWorker)
-{
- auto runControl = runWorker->runControl();
-
- m_device = runWorker->device().dynamicCast<const WinRtDevice>();
-
- const QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(runControl->kit());
- if (!qt) {
- *errorMessage = tr("The current kit has no Qt version.");
- return;
- }
-
- m_runnerFilePath = qt->hostBinPath().toString() + QStringLiteral("/winrtrunner.exe");
- if (!QFile::exists(m_runnerFilePath)) {
- *errorMessage = tr("Cannot find winrtrunner.exe in \"%1\".").arg(
- QDir::toNativeSeparators(qt->hostBinPath().toString()));
- return;
- }
-
- m_executableFilePath = runControl->targetFilePath();
-
- if (m_executableFilePath.isEmpty()) {
- *errorMessage = tr("Cannot determine the executable file path for \"%1\".")
- .arg(runControl->projectFilePath().toUserOutput());
- return;
- }
-
- // ### we should not need to append ".exe" here.
- if (!m_executableFilePath.endsWith(QLatin1String(".exe")))
- m_executableFilePath = m_executableFilePath + QStringLiteral(".exe");
-
- bool loopbackExemptClient = false;
- bool loopbackExemptServer = false;
- if (auto aspect = runControl->aspect<ArgumentsAspect>())
- m_arguments = aspect->arguments(runControl->macroExpander());
- if (auto aspect = runControl->aspect<UninstallAfterStopAspect>())
- m_uninstallAfterStop = aspect->value();
- if (auto aspect = runControl->aspect<LoopbackExemptClientAspect>())
- loopbackExemptClient = aspect->value();
- if (auto aspect = runControl->aspect<LoopbackExemptServerAspect>())
- loopbackExemptServer = aspect->value();
- if (loopbackExemptClient && loopbackExemptServer)
- m_loopbackArguments = QStringList{"--loopbackexempt", "clientserver"};
- else if (loopbackExemptClient)
- m_loopbackArguments = QStringList{"--loopbackexempt", "client"};
- else if (loopbackExemptServer)
- m_loopbackArguments = QStringList{"--loopbackexempt", "server"};
-}
-
-void WinRtRunnerHelper::appendMessage(const QString &message, Utils::OutputFormat format)
-{
- QTC_ASSERT(m_worker, return);
- m_worker->appendMessage(message, format);
-}
-
-void WinRtRunnerHelper::debug(const QString &debuggerExecutable, const QString &debuggerArguments)
-{
- m_debuggerExecutable = debuggerExecutable;
- m_debuggerArguments = debuggerArguments;
- startWinRtRunner(Debug);
-}
-
-void WinRtRunnerHelper::start()
-{
- startWinRtRunner(Start);
-}
-
-void WinRtRunnerHelper::stop()
-{
- if (m_process)
- m_process->interrupt();
- else
- startWinRtRunner(Stop);
-}
-
-bool WinRtRunnerHelper::waitForStarted(int msecs)
-{
- QTC_ASSERT(m_process, return false);
- return m_process->waitForStarted(msecs);
-}
-
-void WinRtRunnerHelper::onProcessReadyReadStdOut()
-{
- QTC_ASSERT(m_process, return);
- appendMessage(QString::fromLocal8Bit(m_process->readAllStandardOutput()), Utils::StdOutFormat);
-}
-
-void WinRtRunnerHelper::onProcessReadyReadStdErr()
-{
- QTC_ASSERT(m_process, return);
- appendMessage(QString::fromLocal8Bit(m_process->readAllStandardError()), Utils::StdErrFormat);
-}
-
-void WinRtRunnerHelper::onProcessFinished()
-{
- QTC_ASSERT(m_process, return);
- m_process->disconnect();
- m_process->deleteLater();
- m_process = nullptr;
- emit finished();
-}
-
-void WinRtRunnerHelper::onProcessError(QProcess::ProcessError processError)
-{
- QTC_ASSERT(m_process, return);
- appendMessage(tr("Error while executing the WinRT Runner Tool: %1\n").arg(
- m_process->errorString()), Utils::ErrorMessageFormat);
- m_process->disconnect();
- m_process->deleteLater();
- m_process = nullptr;
- emit error(processError);
-}
-
-void WinRtRunnerHelper::startWinRtRunner(const RunConf &conf)
-{
- using namespace Utils;
- CommandLine cmdLine(FilePath::fromString(m_runnerFilePath), {});
- if (m_device) {
- cmdLine.addArg("--device");
- cmdLine.addArg(QString::number(m_device->deviceId()));
- }
-
- QtcProcess *process = nullptr;
- bool connectProcess = false;
-
- switch (conf) {
- case Debug:
- cmdLine.addArg("--debug");
- cmdLine.addArg(m_debuggerExecutable);
- if (!m_debuggerArguments.isEmpty()) {
- cmdLine.addArg("--debugger-arguments");
- cmdLine.addArg(m_debuggerArguments);
- }
- Q_FALLTHROUGH();
- case Start:
- cmdLine.addArgs({"--start", "--stop", "--wait", "0"});
- connectProcess = true;
- QTC_ASSERT(!m_process, m_process->deleteLater());
- m_process = new QtcProcess(this);
- process = m_process;
- break;
- case Stop:
- cmdLine.addArg("--stop");
- process = new QtcProcess(this);
- break;
- }
-
- if (m_device->type() == Constants::WINRT_DEVICE_TYPE_LOCAL)
- cmdLine.addArgs({"--profile", "appx"});
- else if (m_device->type() == Constants::WINRT_DEVICE_TYPE_PHONE ||
- m_device->type() == Constants::WINRT_DEVICE_TYPE_EMULATOR)
- cmdLine.addArgs({"--profile", "appxphone"});
-
- cmdLine.addArgs(m_loopbackArguments);
- cmdLine.addArg(m_executableFilePath.toString());
- cmdLine.addArgs(m_arguments, CommandLine::Raw);
-
- appendMessage(cmdLine.toUserOutput(), NormalMessageFormat);
-
- if (connectProcess) {
- connect(process, &QtcProcess::started, this, &WinRtRunnerHelper::started);
- connect(process, &QtcProcess::finished, this, &WinRtRunnerHelper::onProcessFinished);
- connect(process, &QtcProcess::errorOccurred, this, &WinRtRunnerHelper::onProcessError);
- connect(process, &QtcProcess::readyReadStandardOutput, this, &WinRtRunnerHelper::onProcessReadyReadStdOut);
- connect(process, &QtcProcess::readyReadStandardError, this, &WinRtRunnerHelper::onProcessReadyReadStdErr);
- }
-
- process->setUseCtrlCStub(true);
- process->setCommand(cmdLine);
- process->setEnvironment(m_worker->runControl()->buildEnvironment());
- process->setWorkingDirectory(m_executableFilePath.absolutePath());
- process->start();
-}
diff --git a/src/plugins/winrt/winrtrunnerhelper.h b/src/plugins/winrt/winrtrunnerhelper.h
deleted file mode 100644
index 1e790de56aa..00000000000
--- a/src/plugins/winrt/winrtrunnerhelper.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "winrtdevice.h"
-
-#include <utils/environment.h>
-#include <utils/filepath.h>
-#include <utils/outputformat.h>
-
-#include <QObject>
-#include <QProcess>
-
-
-namespace Utils { class QtcProcess; }
-namespace ProjectExplorer { class RunWorker; }
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtRunnerHelper : public QObject
-{
- Q_OBJECT
-public:
- WinRtRunnerHelper(ProjectExplorer::RunWorker *runWorker, QString *errorMessage);
-
- void debug(const QString &debuggerExecutable, const QString &debuggerArguments = QString());
- void start();
-
- void stop();
-
- bool waitForStarted(int msecs = 10000);
-
-signals:
- void started();
- void finished();
- void error(QProcess::ProcessError error);
-
-private:
- enum RunConf { Start, Stop, Debug };
-
- void onProcessReadyReadStdOut();
- void onProcessReadyReadStdErr();
- void onProcessFinished();
- void onProcessError(QProcess::ProcessError processError);
-
- void startWinRtRunner(const RunConf &conf);
- void appendMessage(const QString &message, Utils::OutputFormat format);
-
- ProjectExplorer::RunWorker *m_worker = nullptr;
- WinRtDevice::ConstPtr m_device;
- QString m_runnerFilePath;
- Utils::FilePath m_executableFilePath;
- QString m_debuggerExecutable;
- QString m_debuggerArguments;
- QString m_arguments;
- QStringList m_loopbackArguments;
- bool m_uninstallAfterStop = false;
- Utils::QtcProcess *m_process = nullptr;
-};
-
-} // namespace WinRt
-} // namespace Internal
diff --git a/src/share/3rdparty/fonts/SourceCodePro-Bold.ttf b/src/share/3rdparty/fonts/SourceCodePro-Bold.ttf
index 5a5be2fd456..dd00982d495 100644
--- a/src/share/3rdparty/fonts/SourceCodePro-Bold.ttf
+++ b/src/share/3rdparty/fonts/SourceCodePro-Bold.ttf
Binary files differ
diff --git a/src/share/3rdparty/fonts/SourceCodePro-BoldIt.ttf b/src/share/3rdparty/fonts/SourceCodePro-BoldIt.ttf
new file mode 100644
index 00000000000..0734c6af1a3
--- /dev/null
+++ b/src/share/3rdparty/fonts/SourceCodePro-BoldIt.ttf
Binary files differ
diff --git a/src/share/3rdparty/fonts/SourceCodePro-It.ttf b/src/share/3rdparty/fonts/SourceCodePro-It.ttf
index 437cbe16d60..efc777e2a5e 100644
--- a/src/share/3rdparty/fonts/SourceCodePro-It.ttf
+++ b/src/share/3rdparty/fonts/SourceCodePro-It.ttf
Binary files differ
diff --git a/src/share/3rdparty/fonts/SourceCodePro-Regular.ttf b/src/share/3rdparty/fonts/SourceCodePro-Regular.ttf
index c58300335a7..1decfb95af6 100644
--- a/src/share/3rdparty/fonts/SourceCodePro-Regular.ttf
+++ b/src/share/3rdparty/fonts/SourceCodePro-Regular.ttf
Binary files differ
diff --git a/src/share/3rdparty/package-manager/conan.cmake b/src/share/3rdparty/package-manager/conan.cmake
index 18fb62a8863..4f5f67e74ca 100644
--- a/src/share/3rdparty/package-manager/conan.cmake
+++ b/src/share/3rdparty/package-manager/conan.cmake
@@ -33,7 +33,7 @@
# but it is only necessary on the end-user side. It is not necessary to create conan
# packages, in fact it shouldn't be use for that. Check the project documentation.
-# version: 0.16.0-dev
+# version: 0.18.1
include(CMakeParseArguments)
@@ -55,23 +55,14 @@ function(_get_msvc_ide_version result)
set(${result} 15 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1920 AND MSVC_VERSION VERSION_LESS 1930)
set(${result} 16 PARENT_SCOPE)
+ elseif(NOT MSVC_VERSION VERSION_LESS 1930 AND MSVC_VERSION VERSION_LESS 1940)
+ set(${result} 17 PARENT_SCOPE)
else()
message(FATAL_ERROR "Conan: Unknown MSVC compiler version [${MSVC_VERSION}]")
endif()
endfunction()
-function(conan_cmake_settings result)
- #message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER})
- #message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER_ID})
- #message(STATUS "VERSION " ${CMAKE_CXX_COMPILER_VERSION})
- #message(STATUS "FLAGS " ${CMAKE_LANG_FLAGS})
- #message(STATUS "LIB ARCH " ${CMAKE_CXX_LIBRARY_ARCHITECTURE})
- #message(STATUS "BUILD TYPE " ${CMAKE_BUILD_TYPE})
- #message(STATUS "GENERATOR " ${CMAKE_GENERATOR})
- #message(STATUS "GENERATOR WIN64 " ${CMAKE_CL_64})
-
- message(STATUS "Conan: Automatic detection of conan settings from cmake")
-
+macro(_conan_detect_build_type)
conan_parse_arguments(${ARGV})
if(ARGUMENTS_BUILD_TYPE)
@@ -92,10 +83,9 @@ function(conan_cmake_settings result)
elseif(_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "MINSIZEREL")
set(_CONAN_SETTING_BUILD_TYPE "MinSizeRel")
endif()
+endmacro()
- if(ARGUMENTS_ARCH)
- set(_CONAN_SETTING_ARCH ${ARGUMENTS_ARCH})
- endif()
+macro(_conan_check_system_name)
#handle -s os setting
if(CMAKE_SYSTEM_NAME AND NOT CMAKE_SYSTEM_NAME STREQUAL "Generic")
#use default conan os setting if CMAKE_SYSTEM_NAME is not defined
@@ -115,7 +105,9 @@ function(conan_cmake_settings result)
message(FATAL_ERROR "cmake system ${CONAN_SYSTEM_NAME} is not supported by conan. Use one of ${CONAN_SUPPORTED_PLATFORMS}")
endif()
endif()
+endmacro()
+macro(_conan_check_language)
get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
if (";${_languages};" MATCHES ";CXX;")
set(LANGUAGE CXX)
@@ -126,6 +118,19 @@ function(conan_cmake_settings result)
else ()
message(FATAL_ERROR "Conan: Neither C or C++ was detected as a language for the project. Unabled to detect compiler version.")
endif()
+endmacro()
+
+macro(_conan_detect_compiler)
+
+ conan_parse_arguments(${ARGV})
+
+ if(ARGUMENTS_ARCH)
+ set(_CONAN_SETTING_ARCH ${ARGUMENTS_ARCH})
+ endif()
+
+ if(USING_CXX)
+ set(_CONAN_SETTING_COMPILER_CPPSTD ${CMAKE_CXX_STANDARD})
+ endif()
if (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL GNU)
# using GCC
@@ -143,6 +148,17 @@ function(conan_cmake_settings result)
conan_cmake_detect_unix_libcxx(_LIBCXX)
set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
endif ()
+ elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Intel)
+ string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION})
+ list(GET VERSION_LIST 0 MAJOR)
+ list(GET VERSION_LIST 1 MINOR)
+ set(COMPILER_VERSION ${MAJOR}.${MINOR})
+ set(_CONAN_SETTING_COMPILER intel)
+ set(_CONAN_SETTING_COMPILER_VERSION ${COMPILER_VERSION})
+ if (USING_CXX)
+ conan_cmake_detect_unix_libcxx(_LIBCXX)
+ set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
+ endif ()
elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL AppleClang)
# using AppleClang
string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION})
@@ -154,7 +170,10 @@ function(conan_cmake_settings result)
conan_cmake_detect_unix_libcxx(_LIBCXX)
set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
endif ()
- elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Clang)
+ elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Clang
+ AND NOT "${CMAKE_${LANGUAGE}_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC"
+ AND NOT "${CMAKE_${LANGUAGE}_SIMULATE_ID}" STREQUAL "MSVC")
+
string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION})
list(GET VERSION_LIST 0 MAJOR)
list(GET VERSION_LIST 1 MINOR)
@@ -174,7 +193,11 @@ function(conan_cmake_settings result)
conan_cmake_detect_unix_libcxx(_LIBCXX)
set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
endif ()
- elseif(${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL MSVC)
+ elseif(${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL MSVC
+ OR (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Clang
+ AND "${CMAKE_${LANGUAGE}_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC"
+ AND "${CMAKE_${LANGUAGE}_SIMULATE_ID}" STREQUAL "MSVC"))
+
set(_VISUAL "Visual Studio")
_get_msvc_ide_version(_VISUAL_VERSION)
if("${_VISUAL_VERSION}" STREQUAL "")
@@ -197,7 +220,7 @@ function(conan_cmake_settings result)
endif()
endif()
- conan_cmake_detect_vs_runtime(_vs_runtime)
+ conan_cmake_detect_vs_runtime(_vs_runtime ${ARGV})
message(STATUS "Conan: Detected VS runtime: ${_vs_runtime}")
set(_CONAN_SETTING_COMPILER_RUNTIME ${_vs_runtime})
@@ -206,10 +229,34 @@ function(conan_cmake_settings result)
elseif(CMAKE_VS_PLATFORM_TOOLSET AND (CMAKE_GENERATOR STREQUAL "Ninja"))
set(_CONAN_SETTING_COMPILER_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET})
endif()
- else()
+ else()
message(FATAL_ERROR "Conan: compiler setup not recognized")
endif()
+endmacro()
+
+function(conan_cmake_settings result)
+ #message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER})
+ #message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER_ID})
+ #message(STATUS "VERSION " ${CMAKE_CXX_COMPILER_VERSION})
+ #message(STATUS "FLAGS " ${CMAKE_LANG_FLAGS})
+ #message(STATUS "LIB ARCH " ${CMAKE_CXX_LIBRARY_ARCHITECTURE})
+ #message(STATUS "BUILD TYPE " ${CMAKE_BUILD_TYPE})
+ #message(STATUS "GENERATOR " ${CMAKE_GENERATOR})
+ #message(STATUS "GENERATOR WIN64 " ${CMAKE_CL_64})
+
+ message(STATUS "Conan: Automatic detection of conan settings from cmake")
+
+ conan_parse_arguments(${ARGV})
+
+ _conan_detect_build_type(${ARGV})
+
+ _conan_check_system_name()
+
+ _conan_check_language()
+
+ _conan_detect_compiler(${ARGV})
+
# If profile is defined it is used
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND ARGUMENTS_DEBUG_PROFILE)
set(_APPLIED_PROFILES ${ARGUMENTS_DEBUG_PROFILE})
@@ -346,7 +393,19 @@ function(conan_cmake_detect_unix_libcxx result)
endfunction()
function(conan_cmake_detect_vs_runtime result)
- string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
+
+ conan_parse_arguments(${ARGV})
+ if(ARGUMENTS_BUILD_TYPE)
+ set(build_type "${ARGUMENTS_BUILD_TYPE}")
+ elseif(CMAKE_BUILD_TYPE)
+ set(build_type "${CMAKE_BUILD_TYPE}")
+ else()
+ message(FATAL_ERROR "Please specify in command line CMAKE_BUILD_TYPE (-DCMAKE_BUILD_TYPE=Release)")
+ endif()
+
+ if(build_type)
+ string(TOUPPER "${build_type}" build_type)
+ endif()
set(variables CMAKE_CXX_FLAGS_${build_type} CMAKE_C_FLAGS_${build_type} CMAKE_CXX_FLAGS CMAKE_C_FLAGS)
foreach(variable ${variables})
if(NOT "${${variable}}" STREQUAL "")
@@ -367,17 +426,39 @@ function(conan_cmake_detect_vs_runtime result)
endif()
endfunction()
+function(_collect_settings result)
+ set(ARGUMENTS_PROFILE_AUTO arch build_type compiler compiler.version
+ compiler.runtime compiler.libcxx compiler.toolset
+ compiler.cppstd)
+ foreach(ARG ${ARGUMENTS_PROFILE_AUTO})
+ string(TOUPPER ${ARG} _arg_name)
+ string(REPLACE "." "_" _arg_name ${_arg_name})
+ if(_CONAN_SETTING_${_arg_name})
+ set(detected_setings ${detected_setings} ${ARG}=${_CONAN_SETTING_${_arg_name}})
+ endif()
+ endforeach()
+ set(${result} ${detected_setings} PARENT_SCOPE)
+endfunction()
+
+function(conan_cmake_autodetect detected_settings)
+ _conan_detect_build_type(${ARGV})
+ _conan_check_system_name()
+ _conan_check_language()
+ _conan_detect_compiler(${ARGV})
+ _collect_settings(collected_settings)
+ set(${detected_settings} ${collected_settings} PARENT_SCOPE)
+endfunction()
macro(conan_parse_arguments)
set(options BASIC_SETUP CMAKE_TARGETS UPDATE KEEP_RPATHS NO_LOAD NO_OUTPUT_DIRS OUTPUT_QUIET NO_IMPORTS SKIP_STD)
- set(oneValueArgs CONANFILE ARCH BUILD_TYPE INSTALL_FOLDER CONAN_COMMAND)
+ set(oneValueArgs CONANFILE ARCH BUILD_TYPE INSTALL_FOLDER OUTPUT_FOLDER CONAN_COMMAND)
set(multiValueArgs DEBUG_PROFILE RELEASE_PROFILE RELWITHDEBINFO_PROFILE MINSIZEREL_PROFILE
PROFILE REQUIRES OPTIONS IMPORTS SETTINGS BUILD ENV GENERATORS PROFILE_AUTO
- INSTALL_ARGS CONFIGURATION_TYPES PROFILE_BUILD)
+ INSTALL_ARGS CONFIGURATION_TYPES PROFILE_BUILD BUILD_REQUIRES)
cmake_parse_arguments(ARGUMENTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
endmacro()
-function(conan_cmake_install)
+function(old_conan_cmake_install)
# Calls "conan install"
# Argument BUILD is equivalant to --build={missing, PkgName,...} or
# --build when argument is 'BUILD all' (which builds all packages from source)
@@ -428,6 +509,10 @@ function(conan_cmake_install)
if(ARGUMENTS_INSTALL_FOLDER)
set(CONAN_INSTALL_FOLDER -if=${ARGUMENTS_INSTALL_FOLDER})
endif()
+ set(CONAN_OUTPUT_FOLDER "")
+ if(ARGUMENTS_OUTPUT_FOLDER)
+ set(CONAN_OUTPUT_FOLDER -of=${ARGUMENTS_OUTPUT_FOLDER})
+ endif()
foreach(ARG ${ARGUMENTS_GENERATORS})
set(CONAN_GENERATORS ${CONAN_GENERATORS} -g=${ARG})
endforeach()
@@ -457,6 +542,220 @@ function(conan_cmake_install)
endfunction()
+function(conan_cmake_install)
+ if(DEFINED CONAN_COMMAND)
+ set(CONAN_CMD ${CONAN_COMMAND})
+ else()
+ conan_check(REQUIRED)
+ endif()
+
+ set(installOptions UPDATE NO_IMPORTS OUTPUT_QUIET ERROR_QUIET)
+ set(installOneValueArgs PATH_OR_REFERENCE REFERENCE REMOTE LOCKFILE LOCKFILE_OUT LOCKFILE_NODE_ID INSTALL_FOLDER OUTPUT_FOLDER)
+ set(installMultiValueArgs GENERATOR BUILD ENV ENV_HOST ENV_BUILD OPTIONS_HOST OPTIONS OPTIONS_BUILD PROFILE
+ PROFILE_HOST PROFILE_BUILD SETTINGS SETTINGS_HOST SETTINGS_BUILD)
+ cmake_parse_arguments(ARGS "${installOptions}" "${installOneValueArgs}" "${installMultiValueArgs}" ${ARGN})
+ foreach(arg ${installOptions})
+ if(ARGS_${arg})
+ set(${arg} ${${arg}} ${ARGS_${arg}})
+ endif()
+ endforeach()
+ foreach(arg ${installOneValueArgs})
+ if(DEFINED ARGS_${arg})
+ if("${arg}" STREQUAL "REMOTE")
+ set(flag "--remote")
+ elseif("${arg}" STREQUAL "LOCKFILE")
+ set(flag "--lockfile")
+ elseif("${arg}" STREQUAL "LOCKFILE_OUT")
+ set(flag "--lockfile-out")
+ elseif("${arg}" STREQUAL "LOCKFILE_NODE_ID")
+ set(flag "--lockfile-node-id")
+ elseif("${arg}" STREQUAL "INSTALL_FOLDER")
+ set(flag "--install-folder")
+ elseif("${arg}" STREQUAL "OUTPUT_FOLDER")
+ set(flag "--output-folder")
+ endif()
+ set(${arg} ${${arg}} ${flag} ${ARGS_${arg}})
+ endif()
+ endforeach()
+ foreach(arg ${installMultiValueArgs})
+ if(DEFINED ARGS_${arg})
+ if("${arg}" STREQUAL "GENERATOR")
+ set(flag "--generator")
+ elseif("${arg}" STREQUAL "BUILD")
+ set(flag "--build")
+ elseif("${arg}" STREQUAL "ENV")
+ set(flag "--env")
+ elseif("${arg}" STREQUAL "ENV_HOST")
+ set(flag "--env:host")
+ elseif("${arg}" STREQUAL "ENV_BUILD")
+ set(flag "--env:build")
+ elseif("${arg}" STREQUAL "OPTIONS")
+ set(flag "--options")
+ elseif("${arg}" STREQUAL "OPTIONS_HOST")
+ set(flag "--options:host")
+ elseif("${arg}" STREQUAL "OPTIONS_BUILD")
+ set(flag "--options:build")
+ elseif("${arg}" STREQUAL "PROFILE")
+ set(flag "--profile")
+ elseif("${arg}" STREQUAL "PROFILE_HOST")
+ set(flag "--profile:host")
+ elseif("${arg}" STREQUAL "PROFILE_BUILD")
+ set(flag "--profile:build")
+ elseif("${arg}" STREQUAL "SETTINGS")
+ set(flag "--settings")
+ elseif("${arg}" STREQUAL "SETTINGS_HOST")
+ set(flag "--settings:host")
+ elseif("${arg}" STREQUAL "SETTINGS_BUILD")
+ set(flag "--settings:build")
+ endif()
+ list(LENGTH ARGS_${arg} numargs)
+ foreach(item ${ARGS_${arg}})
+ if(${item} STREQUAL "all" AND ${arg} STREQUAL "BUILD")
+ set(${arg} "--build")
+ break()
+ endif()
+ set(${arg} ${${arg}} ${flag} ${item})
+ endforeach()
+ endif()
+ endforeach()
+ if(DEFINED UPDATE)
+ set(UPDATE --update)
+ endif()
+ if(DEFINED NO_IMPORTS)
+ set(NO_IMPORTS --no-imports)
+ endif()
+ set(install_args install ${PATH_OR_REFERENCE} ${REFERENCE} ${UPDATE} ${NO_IMPORTS} ${REMOTE} ${LOCKFILE} ${LOCKFILE_OUT} ${LOCKFILE_NODE_ID} ${INSTALL_FOLDER} ${OUTPUT_FOLDER}
+ ${GENERATOR} ${BUILD} ${ENV} ${ENV_HOST} ${ENV_BUILD} ${OPTIONS} ${OPTIONS_HOST} ${OPTIONS_BUILD}
+ ${PROFILE} ${PROFILE_HOST} ${PROFILE_BUILD} ${SETTINGS} ${SETTINGS_HOST} ${SETTINGS_BUILD})
+
+ string(REPLACE ";" " " _install_args "${install_args}")
+ message(STATUS "Conan executing: ${CONAN_CMD} ${_install_args}")
+
+ if(ARGS_OUTPUT_QUIET)
+ set(OUTPUT_OPT OUTPUT_QUIET)
+ endif()
+ if(ARGS_ERROR_QUIET)
+ set(ERROR_OPT ERROR_QUIET)
+ endif()
+
+ execute_process(COMMAND ${CONAN_CMD} ${install_args}
+ RESULT_VARIABLE return_code
+ ${OUTPUT_OPT}
+ ${ERROR_OPT}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+
+ if(NOT "${return_code}" STREQUAL "0")
+ if (ARGS_ERROR_QUIET)
+ message(WARNING "Conan install failed='${return_code}'")
+ else()
+ message(FATAL_ERROR "Conan install failed='${return_code}'")
+ endif()
+ endif()
+
+endfunction()
+
+function(conan_cmake_lock_create)
+ if(DEFINED CONAN_COMMAND)
+ set(CONAN_CMD ${CONAN_COMMAND})
+ else()
+ conan_check(REQUIRED)
+ endif()
+
+ set(lockCreateOptions UPDATE BASE OUTPUT_QUIET ERROR_QUIET)
+ set(lockCreateOneValueArgs PATH REFERENCE REMOTE LOCKFILE LOCKFILE_OUT)
+ set(lockCreateMultiValueArgs BUILD ENV ENV_HOST ENV_BUILD OPTIONS_HOST OPTIONS OPTIONS_BUILD PROFILE
+ PROFILE_HOST PROFILE_BUILD SETTINGS SETTINGS_HOST SETTINGS_BUILD)
+ cmake_parse_arguments(ARGS "${lockCreateOptions}" "${lockCreateOneValueArgs}" "${lockCreateMultiValueArgs}" ${ARGN})
+ foreach(arg ${lockCreateOptions})
+ if(ARGS_${arg})
+ set(${arg} ${${arg}} ${ARGS_${arg}})
+ endif()
+ endforeach()
+ foreach(arg ${lockCreateOneValueArgs})
+ if(DEFINED ARGS_${arg})
+ if("${arg}" STREQUAL "REMOTE")
+ set(flag "--remote")
+ elseif("${arg}" STREQUAL "LOCKFILE")
+ set(flag "--lockfile")
+ elseif("${arg}" STREQUAL "LOCKFILE_OUT")
+ set(flag "--lockfile-out")
+ endif()
+ set(${arg} ${${arg}} ${flag} ${ARGS_${arg}})
+ endif()
+ endforeach()
+ foreach(arg ${lockCreateMultiValueArgs})
+ if(DEFINED ARGS_${arg})
+ if("${arg}" STREQUAL "BUILD")
+ set(flag "--build")
+ elseif("${arg}" STREQUAL "ENV")
+ set(flag "--env")
+ elseif("${arg}" STREQUAL "ENV_HOST")
+ set(flag "--env:host")
+ elseif("${arg}" STREQUAL "ENV_BUILD")
+ set(flag "--env:build")
+ elseif("${arg}" STREQUAL "OPTIONS")
+ set(flag "--options")
+ elseif("${arg}" STREQUAL "OPTIONS_HOST")
+ set(flag "--options:host")
+ elseif("${arg}" STREQUAL "OPTIONS_BUILD")
+ set(flag "--options:build")
+ elseif("${arg}" STREQUAL "PROFILE")
+ set(flag "--profile")
+ elseif("${arg}" STREQUAL "PROFILE_HOST")
+ set(flag "--profile:host")
+ elseif("${arg}" STREQUAL "PROFILE_BUILD")
+ set(flag "--profile:build")
+ elseif("${arg}" STREQUAL "SETTINGS")
+ set(flag "--settings")
+ elseif("${arg}" STREQUAL "SETTINGS_HOST")
+ set(flag "--settings:host")
+ elseif("${arg}" STREQUAL "SETTINGS_BUILD")
+ set(flag "--settings:build")
+ endif()
+ list(LENGTH ARGS_${arg} numargs)
+ foreach(item ${ARGS_${arg}})
+ if(${item} STREQUAL "all" AND ${arg} STREQUAL "BUILD")
+ set(${arg} "--build")
+ break()
+ endif()
+ set(${arg} ${${arg}} ${flag} ${item})
+ endforeach()
+ endif()
+ endforeach()
+ if(DEFINED UPDATE)
+ set(UPDATE --update)
+ endif()
+ if(DEFINED BASE)
+ set(BASE --base)
+ endif()
+ set(lock_create_Args lock create ${PATH} ${REFERENCE} ${UPDATE} ${BASE} ${REMOTE} ${LOCKFILE} ${LOCKFILE_OUT} ${LOCKFILE_NODE_ID} ${INSTALL_FOLDER}
+ ${GENERATOR} ${BUILD} ${ENV} ${ENV_HOST} ${ENV_BUILD} ${OPTIONS} ${OPTIONS_HOST} ${OPTIONS_BUILD}
+ ${PROFILE} ${PROFILE_HOST} ${PROFILE_BUILD} ${SETTINGS} ${SETTINGS_HOST} ${SETTINGS_BUILD})
+
+ string(REPLACE ";" " " _lock_create_Args "${lock_create_Args}")
+ message(STATUS "Conan executing: ${CONAN_CMD} ${_lock_create_Args}")
+
+ if(ARGS_OUTPUT_QUIET)
+ set(OUTPUT_OPT OUTPUT_QUIET)
+ endif()
+ if(ARGS_ERROR_QUIET)
+ set(ERROR_OPT ERROR_QUIET)
+ endif()
+
+ execute_process(COMMAND ${CONAN_CMD} ${lock_create_Args}
+ RESULT_VARIABLE return_code
+ ${OUTPUT_OPT}
+ ${ERROR_OPT}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+
+ if(NOT "${return_code}" STREQUAL "0")
+ if (ARGS_ERROR_QUIET)
+ message(WARNING "Conan lock create failed='${return_code}'")
+ else()
+ message(FATAL_ERROR "Conan lock create failed='${return_code}'")
+ endif()
+ endif()
+endfunction()
function(conan_cmake_setup_conanfile)
conan_parse_arguments(${ARGV})
@@ -466,26 +765,64 @@ function(conan_cmake_setup_conanfile)
configure_file(${ARGUMENTS_CONANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${_CONANFILE_NAME}.junk COPYONLY)
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${_CONANFILE_NAME}.junk)
else()
- conan_cmake_generate_conanfile(${ARGV})
+ conan_cmake_generate_conanfile(ON ${ARGV})
endif()
endfunction()
-function(conan_cmake_generate_conanfile)
- # Generate, writing in disk a conanfile.txt with the requires, options, and imports
- # specified as arguments
- # This will be considered as temporary file, generated in CMAKE_CURRENT_BINARY_DIR)
- conan_parse_arguments(${ARGV})
- set(_FN "${CMAKE_CURRENT_BINARY_DIR}/conanfile.txt")
+function(conan_cmake_configure)
+ conan_cmake_generate_conanfile(OFF ${ARGV})
+endfunction()
+
+# Generate, writing in disk a conanfile.txt with the requires, options, and imports
+# specified as arguments
+# This will be considered as temporary file, generated in CMAKE_CURRENT_BINARY_DIR)
+function(conan_cmake_generate_conanfile DEFAULT_GENERATOR)
+
+ conan_parse_arguments(${ARGV})
+
+ set(_FN "${CMAKE_CURRENT_BINARY_DIR}/conanfile.txt")
+ file(WRITE ${_FN} "")
- file(WRITE ${_FN} "[generators]\ncmake\n\n[requires]\n")
- foreach(ARG ${ARGUMENTS_REQUIRES})
- file(APPEND ${_FN} ${ARG} "\n")
- endforeach()
+ if(DEFINED ARGUMENTS_REQUIRES)
+ file(APPEND ${_FN} "[requires]\n")
+ foreach(REQUIRE ${ARGUMENTS_REQUIRES})
+ file(APPEND ${_FN} ${REQUIRE} "\n")
+ endforeach()
+ endif()
+
+ if (DEFAULT_GENERATOR OR DEFINED ARGUMENTS_GENERATORS)
+ file(APPEND ${_FN} "[generators]\n")
+ if (DEFAULT_GENERATOR)
+ file(APPEND ${_FN} "cmake\n")
+ endif()
+ if (DEFINED ARGUMENTS_GENERATORS)
+ foreach(GENERATOR ${ARGUMENTS_GENERATORS})
+ file(APPEND ${_FN} ${GENERATOR} "\n")
+ endforeach()
+ endif()
+ endif()
+
+ if(DEFINED ARGUMENTS_BUILD_REQUIRES)
+ file(APPEND ${_FN} "[build_requires]\n")
+ foreach(BUILD_REQUIRE ${ARGUMENTS_BUILD_REQUIRES})
+ file(APPEND ${_FN} ${BUILD_REQUIRE} "\n")
+ endforeach()
+ endif()
+
+ if(DEFINED ARGUMENTS_IMPORTS)
+ file(APPEND ${_FN} "[imports]\n")
+ foreach(IMPORTS ${ARGUMENTS_IMPORTS})
+ file(APPEND ${_FN} ${IMPORTS} "\n")
+ endforeach()
+ endif()
+
+ if(DEFINED ARGUMENTS_OPTIONS)
+ file(APPEND ${_FN} "[options]\n")
+ foreach(OPTION ${ARGUMENTS_OPTIONS})
+ file(APPEND ${_FN} ${OPTION} "\n")
+ endforeach()
+ endif()
- file(APPEND ${_FN} ${ARG} "\n[imports]\n")
- foreach(ARG ${ARGUMENTS_IMPORTS})
- file(APPEND ${_FN} ${ARG} "\n")
- endforeach()
endfunction()
@@ -537,12 +874,12 @@ macro(conan_cmake_run)
foreach(CMAKE_BUILD_TYPE ${ARGUMENTS_CONFIGURATION_TYPES})
set(ENV{CONAN_IMPORT_PATH} ${CMAKE_BUILD_TYPE})
conan_cmake_settings(settings ${ARGV})
- conan_cmake_install(SETTINGS ${settings} ${ARGV})
+ old_conan_cmake_install(SETTINGS ${settings} ${ARGV})
endforeach()
set(CMAKE_BUILD_TYPE)
else()
conan_cmake_settings(settings ${ARGV})
- conan_cmake_install(SETTINGS ${settings} ${ARGV})
+ old_conan_cmake_install(SETTINGS ${settings} ${ARGV})
endif()
endif()
@@ -584,10 +921,17 @@ macro(conan_check)
message(STATUS "Conan: Found program ${CONAN_CMD}")
endif()
execute_process(COMMAND ${CONAN_CMD} --version
+ RESULT_VARIABLE return_code
OUTPUT_VARIABLE CONAN_VERSION_OUTPUT
ERROR_VARIABLE CONAN_VERSION_OUTPUT)
+
+ if(NOT "${return_code}" STREQUAL "0")
+ message(FATAL_ERROR "Conan --version failed='${return_code}'")
+ endif()
+
if(NOT CONAN_DETECT_QUIET)
- message(STATUS "Conan: Version found ${CONAN_VERSION_OUTPUT}")
+ string(STRIP "${CONAN_VERSION_OUTPUT}" _CONAN_VERSION_OUTPUT)
+ message(STATUS "Conan: Version found ${_CONAN_VERSION_OUTPUT}")
endif()
if(DEFINED CONAN_VERSION)
@@ -617,14 +961,18 @@ function(conan_add_remote)
if(DEFINED CONAN_COMMAND)
set(CONAN_CMD ${CONAN_COMMAND})
else()
- conan_check(REQUIRED)
+ conan_check(REQUIRED DETECT_QUIET)
endif()
set(CONAN_VERIFY_SSL_ARG "True")
if(DEFINED CONAN_VERIFY_SSL)
set(CONAN_VERIFY_SSL_ARG ${CONAN_VERIFY_SSL})
endif()
message(STATUS "Conan: Adding ${CONAN_NAME} remote repository (${CONAN_URL}) verify ssl (${CONAN_VERIFY_SSL_ARG})")
- execute_process(COMMAND ${CONAN_CMD} remote add ${CONAN_NAME} ${CONAN_INDEX_ARG} -f ${CONAN_URL} ${CONAN_VERIFY_SSL_ARG})
+ execute_process(COMMAND ${CONAN_CMD} remote add ${CONAN_NAME} ${CONAN_INDEX_ARG} -f ${CONAN_URL} ${CONAN_VERIFY_SSL_ARG}
+ RESULT_VARIABLE return_code)
+ if(NOT "${return_code}" STREQUAL "0")
+ message(FATAL_ERROR "Conan remote failed='${return_code}'")
+ endif()
endfunction()
macro(conan_config_install)
@@ -637,37 +985,42 @@ macro(conan_config_install)
set(multiValueArgs ARGS)
cmake_parse_arguments(CONAN "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
- find_program(CONAN_CMD conan)
- if(NOT CONAN_CMD AND CONAN_REQUIRED)
- message(FATAL_ERROR "Conan executable not found!")
+ if(DEFINED CONAN_COMMAND)
+ set(CONAN_CMD ${CONAN_COMMAND})
+ else()
+ conan_check(REQUIRED)
endif()
if(DEFINED CONAN_VERIFY_SSL)
- set(CONAN_VERIFY_SSL_ARG "--verify-ssl=${CONAN_VERIFY_SSL}")
+ set(CONAN_VERIFY_SSL_ARG "--verify-ssl=${CONAN_VERIFY_SSL}")
endif()
if(DEFINED CONAN_TYPE)
- set(CONAN_TYPE_ARG "--type=${CONAN_TYPE}")
+ set(CONAN_TYPE_ARG "--type=${CONAN_TYPE}")
endif()
if(DEFINED CONAN_ARGS)
- set(CONAN_ARGS_ARGS "--args=\"${CONAN_ARGS}\"")
+ set(CONAN_ARGS_ARGS "--args=\"${CONAN_ARGS}\"")
endif()
if(DEFINED CONAN_SOURCE)
- set(CONAN_SOURCE_ARGS "--source-folder=${CONAN_SOURCE}")
+ set(CONAN_SOURCE_ARGS "--source-folder=${CONAN_SOURCE}")
endif()
if(DEFINED CONAN_TARGET)
- set(CONAN_TARGET_ARGS "--target-folder=${CONAN_TARGET}")
+ set(CONAN_TARGET_ARGS "--target-folder=${CONAN_TARGET}")
endif()
- set (CONAN_CONFIG_INSTALL_ARGS ${CONAN_VERIFY_SSL_ARG}
- ${CONAN_TYPE_ARG}
- ${CONAN_ARGS_ARGS}
- ${CONAN_SOURCE_ARGS}
- ${CONAN_TARGET_ARGS})
+ set (CONAN_CONFIG_INSTALL_ARGS ${CONAN_VERIFY_SSL_ARG}
+ ${CONAN_TYPE_ARG}
+ ${CONAN_ARGS_ARGS}
+ ${CONAN_SOURCE_ARGS}
+ ${CONAN_TARGET_ARGS})
message(STATUS "Conan: Installing config from ${CONAN_ITEM}")
- execute_process(COMMAND ${CONAN_CMD} config install ${CONAN_ITEM} ${CONAN_CONFIG_INSTALL_ARGS})
+ execute_process(COMMAND ${CONAN_CMD} config install ${CONAN_ITEM} ${CONAN_CONFIG_INSTALL_ARGS}
+ RESULT_VARIABLE return_code)
+ if(NOT "${return_code}" STREQUAL "0")
+ message(FATAL_ERROR "Conan config failed='${return_code}'")
+ endif()
endmacro()
diff --git a/src/shared/designerintegrationv2/CMakeLists.txt b/src/shared/designerintegrationv2/CMakeLists.txt
index b527260fa49..e600141bce1 100644
--- a/src/shared/designerintegrationv2/CMakeLists.txt
+++ b/src/shared/designerintegrationv2/CMakeLists.txt
@@ -12,3 +12,10 @@ add_qtc_library(designerintegrationv2 STATIC
widgethostconstants.h
widgethost.cpp widgethost.h
)
+
+if (QTC_STATIC_BUILD)
+ get_target_property(_designerType Qt5::Designer TYPE)
+ if (${_designerType} STREQUAL "STATIC_LIBRARY")
+ extend_qtc_target(designerintegrationv2 PUBLIC_DEFINES QT_DESIGNER_STATIC)
+ endif()
+endif()
diff --git a/src/shared/help/CMakeLists.txt b/src/shared/help/CMakeLists.txt
index b02b82f6105..c3a864da6e9 100644
--- a/src/shared/help/CMakeLists.txt
+++ b/src/shared/help/CMakeLists.txt
@@ -12,7 +12,7 @@ if (isMultiConfig)
endif()
add_qtc_library(shared_help STATIC
- DEPENDS Utils PUBLIC Qt5::Help Qt5::PrintSupport Qt5::Widgets
+ DEPENDS Utils Core PUBLIC Qt5::Help Qt5::PrintSupport Qt5::Widgets
PUBLIC_INCLUDES
"${PLUGIN_SOURCE_DIR}/help"
"${PLUGIN_SOURCE_DIR}"
diff --git a/src/shared/proparser/CMakeLists.txt b/src/shared/proparser/CMakeLists.txt
index 3a8404af7af..0277795a603 100644
--- a/src/shared/proparser/CMakeLists.txt
+++ b/src/shared/proparser/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_qtc_library(ProParser SHARED
+add_qtc_library(ProParser
DEPENDS Qt5::Core Utils
PUBLIC_DEFINES
QMAKE_BUILTIN_PRFS QMAKE_OVERRIDE_PRFS
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject b6a46aa0199c2595766495673f67a8190f3342f
+Subproject 3e0553e4651197e61c5086d96048b75462bde89
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index 79878f18d3a..98b5a94d957 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -1,10 +1,5 @@
add_subdirectory(3rdparty)
add_subdirectory(buildoutputparser)
-if (NOT Clang_FOUND)
- message(WARNING "Could not find Clang installation - disabling clangbackend.")
-else ()
- add_subdirectory(clangbackend)
-endif ()
option(BUILD_CPLUSPLUS_TOOLS "Build CPlusPlus tools" OFF)
@@ -42,11 +37,9 @@ add_subdirectory(qtc-askpass)
add_subdirectory(qtcreatorcrashhandler)
# add_subdirectory(qtcreatorwidgets) ## qbs does not build this either
add_subdirectory(qtpromaker)
-add_subdirectory(screenshotcropper)
add_subdirectory(sdktool)
add_subdirectory(valgrindfake)
add_subdirectory(wininterrupt) ## windows only
-add_subdirectory(winrtdebughelper) ## windows only
if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/perfparser/CMakeLists.txt)
add_subdirectory(perfparser)
diff --git a/src/tools/clangbackend/CMakeLists.txt b/src/tools/clangbackend/CMakeLists.txt
deleted file mode 100644
index c0ad4e864dc..00000000000
--- a/src/tools/clangbackend/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-add_subdirectory(source)
-
-add_qtc_executable(clangbackend
- DEPENDS Qt5::Core Qt5::Network clangbackend_lib Sqlite ClangSupport libclang
- SOURCES
- ../qtcreatorcrashhandler/crashhandlersetup.cpp ../qtcreatorcrashhandler/crashhandlersetup.h
- clangbackendmain.cpp
-)
diff --git a/src/tools/clangbackend/clangbackend.qbs b/src/tools/clangbackend/clangbackend.qbs
deleted file mode 100644
index 495c586f855..00000000000
--- a/src/tools/clangbackend/clangbackend.qbs
+++ /dev/null
@@ -1,38 +0,0 @@
-import qbs 1.0
-
-QtcTool {
- name: "clangbackend"
-
- Depends { name: "ClangSupport" }
- Depends { name: "libclang"; required: false }
-
- Group {
- prefix: "source/"
- files: [
- "*.h",
- "*.cpp"
- ]
- }
-
- Group {
- prefix: "../qtcreatorcrashhandler/"
- files: [
- "crashhandlersetup.cpp",
- "crashhandlersetup.h",
- ]
- }
-
- files: [ "clangbackendmain.cpp" ]
-
- condition: libclang.present
-
- cpp.includePaths: base.concat(["source", libclang.llvmIncludeDir])
- cpp.libraryPaths: base.concat(libclang.llvmLibDir)
- cpp.dynamicLibraries: base.concat(libclang.llvmLibs)
- cpp.rpaths: base.concat(libclang.llvmLibDir)
-
- Properties {
- condition: qbs.targetOS.contains("unix") && !qbs.targetOS.contains("macos")
- cpp.linkerFlags: base.concat(["-z", "origin"])
- }
-}
diff --git a/src/tools/clangbackend/clangbackendmain.cpp b/src/tools/clangbackend/clangbackendmain.cpp
deleted file mode 100644
index 18db1488939..00000000000
--- a/src/tools/clangbackend/clangbackendmain.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "../qtcreatorcrashhandler/crashhandlersetup.h"
-
-#include <QCommandLineParser>
-#include <QCoreApplication>
-#include <QLoggingCategory>
-
-#include <connectionserver.h>
-#include <clangcodemodelserver.h>
-#include <clangcodemodelclientproxy.h>
-
-#include <iostream>
-#include <clocale>
-
-using ClangBackEnd::ClangCodeModelClientProxy;
-using ClangBackEnd::ClangCodeModelServer;
-using ClangBackEnd::ConnectionServer;
-
-QString processArguments(QCoreApplication &application)
-{
- QCommandLineParser parser;
- parser.setApplicationDescription(QStringLiteral("Qt Creator Clang backend process."));
- parser.addHelpOption();
- parser.addVersionOption();
- parser.addPositionalArgument(QStringLiteral("connection"), QStringLiteral("Connection"));
-
- parser.process(application);
-
- if (parser.positionalArguments().isEmpty())
- parser.showHelp(1);
-
- return parser.positionalArguments().constFirst();
-}
-
-#ifdef Q_OS_WIN
-#include <windows.h>
-static void messageOutput(QtMsgType type, const QMessageLogContext &/*context*/,
- const QString &msg)
-{
- OutputDebugStringW(msg.toStdWString().c_str());
- std::wcout << msg.toStdWString() << std::endl;
- if (type == QtFatalMsg)
- abort();
-}
-#endif
-
-int main(int argc, char *argv[])
-{
-#ifdef Q_OS_WIN
- qInstallMessageHandler(&messageOutput);
-#endif
- QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
- QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
- QCoreApplication::setApplicationName(QStringLiteral("ClangBackend"));
- QCoreApplication::setApplicationVersion(QStringLiteral("1.0.0"));
-
- QCoreApplication application(argc, argv);
-
- // Some tidy checks use locale-dependent conversion functions and thus might throw exceptions.
- std::setlocale(LC_NUMERIC, "C");
-
- CrashHandlerSetup setupCrashHandler(QCoreApplication::applicationName(),
- CrashHandlerSetup::DisableRestart);
-
- const QString connection = processArguments(application);
-
- // Printing the stack strace might dead lock as clang's stack printer allocates memory.
- if (qEnvironmentVariableIntValue("QTC_CLANG_ENABLE_STACKTRACES"))
- clang_enableStackTraces();
-
- ClangCodeModelServer clangCodeModelServer;
- ConnectionServer<ClangCodeModelServer, ClangCodeModelClientProxy> connectionServer;
- connectionServer.setServer(&clangCodeModelServer);
- connectionServer.start(connection);
-
- return application.exec();
-}
-
-
diff --git a/src/tools/clangbackend/source/CMakeLists.txt b/src/tools/clangbackend/source/CMakeLists.txt
deleted file mode 100644
index 4311e570534..00000000000
--- a/src/tools/clangbackend/source/CMakeLists.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-add_qtc_library(clangbackend_lib STATIC
- DEPENDS libclang
- PUBLIC_DEPENDS
- Qt5::Widgets # FIXME: change the way to get the gui pch to linkto
- DEFINES
- $<TARGET_PROPERTY:Sqlite,INTERFACE_COMPILE_DEFINITIONS>
- INCLUDES
- $<TARGET_PROPERTY:ClangSupport,INTERFACE_INCLUDE_DIRECTORIES>
- $<TARGET_PROPERTY:Sqlite,INTERFACE_INCLUDE_DIRECTORIES>
- PUBLIC_INCLUDES
- ${CLANG_INCLUDE_DIRS}
- "${CMAKE_CURRENT_LIST_DIR}"
- SOURCES
- clangasyncjob.h
- clangbackend_global.h
- clangclock.h
- clangcodecompleteresults.cpp clangcodecompleteresults.h
- clangcodemodelserver.cpp clangcodemodelserver.h
- clangcompletecodejob.cpp clangcompletecodejob.h
- clangdocument.cpp clangdocument.h
- clangdocumentjob.h
- clangdocumentprocessor.cpp clangdocumentprocessor.h
- clangdocumentprocessors.cpp clangdocumentprocessors.h
- clangdocuments.cpp clangdocuments.h
- clangdocumentsuspenderresumer.cpp clangdocumentsuspenderresumer.h
- clangexceptions.cpp clangexceptions.h
- clangfilepath.cpp clangfilepath.h
- clangfilesystemwatcher.cpp clangfilesystemwatcher.h
- clangfollowsymbol.cpp clangfollowsymbol.h
- clangfollowsymboljob.cpp clangfollowsymboljob.h
- clangiasyncjob.cpp clangiasyncjob.h
- clangjobcontext.cpp clangjobcontext.h
- clangjobqueue.cpp clangjobqueue.h
- clangjobrequest.cpp clangjobrequest.h
- clangjobs.cpp clangjobs.h
- clangparsesupportivetranslationunitjob.cpp clangparsesupportivetranslationunitjob.h
- clangreferencescollector.cpp clangreferencescollector.h
- clangrequestannotationsjob.cpp clangrequestannotationsjob.h
- clangrequestreferencesjob.cpp clangrequestreferencesjob.h
- clangrequesttooltipjob.cpp clangrequesttooltipjob.h
- clangresumedocumentjob.cpp clangresumedocumentjob.h
- clangstring.h
- clangsupportivetranslationunitinitializer.cpp clangsupportivetranslationunitinitializer.h
- clangsuspenddocumentjob.cpp clangsuspenddocumentjob.h
- clangtooltipinfocollector.cpp clangtooltipinfocollector.h
- clangtranslationunit.cpp clangtranslationunit.h
- clangtranslationunits.cpp clangtranslationunits.h
- clangtranslationunitupdater.cpp clangtranslationunitupdater.h
- clangtype.cpp clangtype.h
- clangunsavedfilesshallowarguments.cpp clangunsavedfilesshallowarguments.h
- clangupdateannotationsjob.cpp clangupdateannotationsjob.h
- clangupdateextraannotationsjob.cpp clangupdateextraannotationsjob.h
- codecompleter.cpp codecompleter.h
- codecompletionchunkconverter.cpp codecompletionchunkconverter.h
- codecompletionsextractor.cpp codecompletionsextractor.h
- commandlinearguments.cpp commandlinearguments.h
- cursor.cpp cursor.h
- diagnostic.cpp diagnostic.h
- diagnosticset.cpp diagnosticset.h
- diagnosticsetiterator.h
- fixit.cpp fixit.h
- fulltokeninfo.cpp fulltokeninfo.h
- skippedsourceranges.cpp skippedsourceranges.h
- sourcelocation.cpp sourcelocation.h
- sourcerange.cpp sourcerange.h
- token.cpp token.h
- tokeninfo.cpp tokeninfo.h
- tokenprocessor.h
- tokenprocessoriterator.h
- unsavedfile.cpp unsavedfile.h
- unsavedfiles.cpp unsavedfiles.h
- utf8positionfromlinecolumn.cpp utf8positionfromlinecolumn.h
-)
diff --git a/src/tools/clangbackend/source/clangasyncjob.h b/src/tools/clangbackend/source/clangasyncjob.h
deleted file mode 100644
index 9299658aa45..00000000000
--- a/src/tools/clangbackend/source/clangasyncjob.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangiasyncjob.h"
-
-#include <utils/runextensions.h>
-
-#include <QFutureWatcher>
-#include <QObject>
-
-namespace ClangBackEnd {
-
-template<class Result>
-class AsyncJob : public IAsyncJob
-{
-public:
- AsyncJob() {}
- ~AsyncJob() {}
-
- using Runner = std::function<Result()>;
- Runner runner() const { return m_runner; }
- void setRunner(const Runner &runner) { m_runner = runner; }
-
- Result asyncResult() const { return m_futureWatcher.future().result(); }
-
- QFuture<void> runAsync() final
- {
- const auto onFinished = [this]() {
- finalizeAsyncRun();
- setIsFinished(true);
- finishedHandler()(this);
- };
- QObject::connect(&m_futureWatcher,
- &QFutureWatcher<Result>::finished,
- onFinished);
-
- // Use 16MB stack size as clang_annotateTokens() would with an internal thread.
- const Utils::StackSizeInBytes stackSize = 1024 * 1024 * 16;
- const QFuture<Result> future = Utils::runAsync(stackSize, m_runner);
- m_futureWatcher.setFuture(future);
-
- return QFuture<void>(future);
- }
-
- void preventFinalization() final
- {
- m_futureWatcher.disconnect();
- }
-
-private:
- Runner m_runner;
- QFutureWatcher<Result> m_futureWatcher;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangbackend_global.h b/src/tools/clangbackend/source/clangbackend_global.h
deleted file mode 100644
index e62c9a35130..00000000000
--- a/src/tools/clangbackend/source/clangbackend_global.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-enum class PreferredTranslationUnit
-{
- RecentlyParsed,
- PreviouslyParsed,
- LastUninitialized,
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangclock.h b/src/tools/clangbackend/source/clangclock.h
deleted file mode 100644
index 68d91478f74..00000000000
--- a/src/tools/clangbackend/source/clangclock.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <chrono>
-
-namespace ClangBackEnd {
-
-using Clock = std::chrono::steady_clock;
-using Duration = std::chrono::steady_clock::duration;
-using TimePoint = std::chrono::steady_clock::time_point;
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangcodecompleteresults.cpp b/src/tools/clangbackend/source/clangcodecompleteresults.cpp
deleted file mode 100644
index 818aa9360e3..00000000000
--- a/src/tools/clangbackend/source/clangcodecompleteresults.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcodecompleteresults.h"
-
-#include <memory>
-
-namespace ClangBackEnd {
-
-using std::swap;
-
-ClangCodeCompleteResults::ClangCodeCompleteResults(CXCodeCompleteResults *cxCodeCompleteResults)
- : cxCodeCompleteResults(cxCodeCompleteResults)
-{
-}
-
-ClangCodeCompleteResults::~ClangCodeCompleteResults()
-{
- clang_disposeCodeCompleteResults(cxCodeCompleteResults);
-}
-
-bool ClangCodeCompleteResults::isNull() const
-{
- return cxCodeCompleteResults == nullptr;
-}
-
-bool ClangCodeCompleteResults::isEmpty() const
-{
- return cxCodeCompleteResults->NumResults == 0;
-}
-
-bool ClangCodeCompleteResults::hasResults() const
-{
- return !isNull() && !isEmpty();
-}
-
-bool ClangCodeCompleteResults::hasUnknownContext() const
-{
- const unsigned long long contexts = clang_codeCompleteGetContexts(cxCodeCompleteResults);
- return contexts == CXCompletionContext_Unknown;
-}
-
-CXCodeCompleteResults *ClangCodeCompleteResults::data() const
-{
- return cxCodeCompleteResults;
-}
-
-ClangCodeCompleteResults &ClangCodeCompleteResults::operator=(ClangCodeCompleteResults &&clangCodeCompleteResults)
-{
- swap(cxCodeCompleteResults, clangCodeCompleteResults.cxCodeCompleteResults);
-
- return *this;
-}
-
-ClangCodeCompleteResults::ClangCodeCompleteResults(ClangCodeCompleteResults &&clangCodeCompleteResults)
-{
- swap(cxCodeCompleteResults, clangCodeCompleteResults.cxCodeCompleteResults);
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/clangcodecompleteresults.h b/src/tools/clangbackend/source/clangcodecompleteresults.h
deleted file mode 100644
index 000c424b33b..00000000000
--- a/src/tools/clangbackend/source/clangcodecompleteresults.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clang-c/Index.h>
-
-#include <utf8string.h>
-
-namespace ClangBackEnd {
-
-class ClangCodeCompleteResults
-{
-public:
- ClangCodeCompleteResults() = default;
-
- ClangCodeCompleteResults(CXCodeCompleteResults *cxCodeCompleteResults);
- ~ClangCodeCompleteResults();
-
- ClangCodeCompleteResults(const ClangCodeCompleteResults &ClangCodeCompleteResults) = delete;
- const ClangCodeCompleteResults &operator=(const ClangCodeCompleteResults &ClangCodeCompleteResults) = delete;
-
- ClangCodeCompleteResults(ClangCodeCompleteResults &&ClangCodeCompleteResults);
- ClangCodeCompleteResults &operator=(ClangCodeCompleteResults &&ClangCodeCompleteResults);
-
- bool isNull() const;
- bool isEmpty() const;
-
- bool hasResults() const;
-
- bool hasUnknownContext() const;
-
- CXCodeCompleteResults *data() const;
-
-private:
- CXCodeCompleteResults *cxCodeCompleteResults = nullptr;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangcodemodelserver.cpp b/src/tools/clangbackend/source/clangcodemodelserver.cpp
deleted file mode 100644
index a647b0e6496..00000000000
--- a/src/tools/clangbackend/source/clangcodemodelserver.cpp
+++ /dev/null
@@ -1,520 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcodemodelserver.h"
-
-#include "clangdocuments.h"
-#include "clangdocumentsuspenderresumer.h"
-#include "clangfilesystemwatcher.h"
-#include "clangupdateannotationsjob.h"
-#include "codecompleter.h"
-#include "diagnosticset.h"
-#include "tokenprocessor.h"
-#include "clangexceptions.h"
-#include "skippedsourceranges.h"
-#include "unsavedfile.h"
-
-#include <clangsupport/clangsupportdebugutils.h>
-#include <clangsupport/clangcodemodelservermessages.h>
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-#include <QCoreApplication>
-#include <QDebug>
-#include <QFileInfo>
-#include <QLoggingCategory>
-#include <QDir>
-
-static Q_LOGGING_CATEGORY(serverLog, "qtc.clangbackend.server", QtWarningMsg);
-
-static bool useSupportiveTranslationUnit()
-{
- static bool use = !qEnvironmentVariableIntValue("QTC_CLANG_NO_SUPPORTIVE_TRANSLATIONUNIT");
- return use;
-}
-
-namespace ClangBackEnd {
-
-ClangCodeModelServer::ClangCodeModelServer()
- : documents(unsavedFiles)
-{
- updateAnnotationsTimer.setSingleShot(true);
- QObject::connect(&updateAnnotationsTimer,
- &QTimer::timeout,
- [this]() {
- processJobsForVisibleDocuments();
- });
-
- updateVisibleButNotCurrentDocumentsTimer.setSingleShot(true);
- QObject::connect(&updateVisibleButNotCurrentDocumentsTimer,
- &QTimer::timeout,
- [this]() {
- addAndRunUpdateJobs(documents.dirtyAndVisibleButNotCurrentDocuments());
- });
-
- QObject::connect(documents.clangFileSystemWatcher(),
- &ClangFileSystemWatcher::fileChanged,
- [this](const Utf8String &filePath) {
- if (!documents.hasDocument(filePath))
- updateAnnotationsTimer.start(0);
- });
-}
-
-void ClangCodeModelServer::end()
-{
- QCoreApplication::exit();
-}
-
-void ClangCodeModelServer::documentsOpened(const ClangBackEnd::DocumentsOpenedMessage &message)
-{
- qCDebug(serverLog) << "########## documentsOpened";
- TIME_SCOPE_DURATION("ClangCodeModelServer::documentsOpened");
-
- try {
- DocumentResetInfos toReset;
- QVector<FileContainer> toCreate;
- categorizeFileContainers(message.fileContainers, toCreate, toReset);
-
- std::vector<Document> createdDocuments = documents.create(toCreate);
- for (auto &document : createdDocuments) {
- document.setDirtyIfDependencyIsMet(document.filePath());
- DocumentProcessor processor = documentProcessors().create(document);
- processor.jobs().setJobFinishedCallback([this](const Jobs::RunningJob &a, IAsyncJob *b) {
- return onJobFinished(a, b);
- });
- }
- const std::vector<Document> resetDocuments_ = resetDocuments(toReset);
-
- unsavedFiles.createOrUpdate(message.fileContainers);
- documents.setUsedByCurrentEditor(message.currentEditorFilePath);
- documents.setVisibleInEditors(message.visibleEditorFilePaths);
-
- processSuspendResumeJobs(documents.documents());
- processJobsForVisibleDocuments();
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::documentsOpened:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::documentsChanged(const DocumentsChangedMessage &message)
-{
- qCDebug(serverLog) << "########## documentsChanged";
- TIME_SCOPE_DURATION("ClangCodeModelServer::documentsChanged");
-
- try {
- const auto newerFileContainers = documents.newerFileContainers(message.fileContainers);
- if (newerFileContainers.size() > 0) {
- std::vector<Document> updateDocuments = documents.update(newerFileContainers);
- unsavedFiles.createOrUpdate(newerFileContainers);
-
- for (Document &document : updateDocuments) {
- if (!document.isResponsivenessIncreased())
- document.setResponsivenessIncreaseNeeded(true);
- }
-
- // Start the jobs on the next event loop iteration since otherwise
- // we might block the translation unit for a completion request
- // that comes right after this message.
- updateAnnotationsTimer.start(0);
- }
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::documentsChanged:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::documentsClosed(const ClangBackEnd::DocumentsClosedMessage &message)
-{
- qCDebug(serverLog) << "########## documentsClosed";
- TIME_SCOPE_DURATION("ClangCodeModelServer::documentsClosed");
-
- try {
- for (const auto &fileContainer : message.fileContainers) {
- const Document &document = documents.document(fileContainer);
- documentProcessors().remove(document);
- }
- documents.remove(message.fileContainers);
- unsavedFiles.remove(message.fileContainers);
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::documentsClosed:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message)
-{
- qCDebug(serverLog) << "########## unsavedFilesUpdated";
- TIME_SCOPE_DURATION("ClangCodeModelServer::unsavedFilesUpdated");
-
- try {
- unsavedFiles.createOrUpdate(message.fileContainers);
- documents.updateDocumentsWithChangedDependencies(message.fileContainers);
- resetDocumentsWithUnresolvedIncludes(documents.documents());
-
- updateAnnotationsTimer.start(updateAnnotationsTimeOutInMs);
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::unsavedFilesUpdated:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message)
-{
- qCDebug(serverLog) << "########## unsavedFilesRemoved";
- TIME_SCOPE_DURATION("ClangCodeModelServer::unsavedFilesRemoved");
-
- try {
- unsavedFiles.remove(message.fileContainers);
- documents.updateDocumentsWithChangedDependencies(message.fileContainers);
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::unsavedFilesRemoved:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::requestCompletions(const ClangBackEnd::RequestCompletionsMessage &message)
-{
- qCDebug(serverLog) << "########## requestCompletions";
- TIME_SCOPE_DURATION("ClangCodeModelServer::requestCompletions");
-
- try {
- Document document = documents.document(message.filePath);
- DocumentProcessor processor = documentProcessors().processor(document);
-
- JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestCompletions);
- jobRequest.line = message.line;
- jobRequest.column = message.column;
- jobRequest.funcNameStartLine = message.funcNameStartLine;
- jobRequest.funcNameStartColumn = message.funcNameStartColumn;
- jobRequest.ticketNumber = message.ticketNumber;
-
- processor.addJob(jobRequest);
- processor.process();
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::requestCompletions:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::requestAnnotations(const RequestAnnotationsMessage &message)
-{
- qCDebug(serverLog) << "########## requestAnnotations";
- TIME_SCOPE_DURATION("ClangCodeModelServer::requestAnnotations");
-
- try {
- auto document = documents.document(message.fileContainer.filePath);
-
- DocumentProcessor processor = documentProcessors().processor(document);
- processor.addJob(JobRequest::Type::RequestAnnotations);
- processor.addJob(JobRequest::Type::UpdateExtraAnnotations);
- processor.process();
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::requestAnnotations:" << exception.what();
- }
-}
-
-template <class MessageType>
-static void fillJobRequest(JobRequest &jobRequest, const MessageType &message)
-{
- jobRequest.line = message.line;
- jobRequest.column = message.column;
- jobRequest.ticketNumber = message.ticketNumber;
- jobRequest.textCodecName = message.fileContainer.textCodecName;
- // The unsaved files might get updater later, so take the current
- // revision for the request.
- jobRequest.documentRevision = message.fileContainer.documentRevision;
-}
-
-void ClangCodeModelServer::requestReferences(const RequestReferencesMessage &message)
-{
- qCDebug(serverLog) << "########## requestReferences";
- TIME_SCOPE_DURATION("ClangCodeModelServer::requestReferences");
-
- try {
- const Document document = documents.document(message.fileContainer.filePath);
- DocumentProcessor processor = documentProcessors().processor(document);
-
- JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestReferences);
- fillJobRequest(jobRequest, message);
- jobRequest.localReferences = message.local;
- processor.addJob(jobRequest);
- processor.process();
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::requestReferences:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage &message)
-{
- qCDebug(serverLog) << "########## requestFollowSymbol";
- TIME_SCOPE_DURATION("ClangCodeModelServer::requestFollowSymbol");
-
- try {
- Document document = documents.document(message.fileContainer.filePath);
- DocumentProcessor processor = documentProcessors().processor(document);
-
- JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestFollowSymbol);
- fillJobRequest(jobRequest, message);
- processor.addJob(jobRequest);
- processor.process();
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::requestFollowSymbol:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::requestToolTip(const RequestToolTipMessage &message)
-{
- TIME_SCOPE_DURATION("ClangCodeModelServer::requestToolTip");
-
- try {
- const Document document = documents.document(message.fileContainer.filePath);
- DocumentProcessor processor = documentProcessors().processor(document);
-
- JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestToolTip);
- fillJobRequest(jobRequest, message);
-
- processor.addJob(jobRequest);
- processor.process();
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::requestToolTip:" << exception.what();
- }
-}
-
-void ClangCodeModelServer::documentVisibilityChanged(const DocumentVisibilityChangedMessage &message)
-{
- qCDebug(serverLog) << "########## documentVisibilityChanged";
- TIME_SCOPE_DURATION("ClangCodeModelServer::documentVisibilityChanged");
-
- try {
- documents.setUsedByCurrentEditor(message.currentEditorFilePath);
- documents.setVisibleInEditors(message.visibleEditorFilePaths);
- processSuspendResumeJobs(documents.documents());
-
- updateAnnotationsTimer.start(0);
- } catch (const std::exception &exception) {
- qWarning() << "Error in ClangCodeModelServer::documentVisibilityChanged:" << exception.what();
- }
-}
-
-const Documents &ClangCodeModelServer::documentsForTestOnly() const
-{
- return documents;
-}
-
-QList<Jobs::RunningJob> ClangCodeModelServer::runningJobsForTestsOnly()
-{
- return documentProcessors().runningJobs();
-}
-
-int ClangCodeModelServer::queueSizeForTestsOnly()
-{
- return documentProcessors().queueSize();
-}
-
-bool ClangCodeModelServer::isTimerRunningForTestOnly() const
-{
- return updateAnnotationsTimer.isActive();
-}
-
-void ClangCodeModelServer::processJobsForVisibleDocuments()
-{
- processJobsForCurrentDocument();
- processTimerForVisibleButNotCurrentDocuments();
-}
-
-void ClangCodeModelServer::processJobsForCurrentDocument()
-{
- auto currentDocuments = documents.filtered([](const Document &document) {
- return document.isUsedByCurrentEditor() && document.isDirty();
- });
- QTC_CHECK(currentDocuments.size() <= 1);
-
- addAndRunUpdateJobs(currentDocuments);
-}
-
-static void addUpdateAnnotationsJobsAndProcess(DocumentProcessor &processor)
-{
- processor.addJob(JobRequest::Type::UpdateAnnotations,
- PreferredTranslationUnit::PreviouslyParsed);
- processor.addJob(JobRequest::Type::UpdateExtraAnnotations,
- PreferredTranslationUnit::RecentlyParsed);
- processor.process();
-}
-
-void ClangCodeModelServer::addAndRunUpdateJobs(std::vector<Document> documents)
-{
- for (auto &document : documents) {
- DocumentProcessor processor = documentProcessors().processor(document);
-
- // Run the regular edit-reparse-job
- addUpdateAnnotationsJobsAndProcess(processor);
-
- // If requested, run jobs to increase the responsiveness of the document
- if (useSupportiveTranslationUnit() && document.isResponsivenessIncreaseNeeded()) {
- QTC_CHECK(!document.isResponsivenessIncreased());
- QTC_CHECK(!processor.hasSupportiveTranslationUnit());
- document.setResponsivenessIncreaseNeeded(false);
- processor.startInitializingSupportiveTranslationUnit();
- }
- }
-}
-
-void ClangCodeModelServer::processTimerForVisibleButNotCurrentDocuments()
-{
- if (documents.dirtyAndVisibleButNotCurrentDocuments().empty()) {
- updateVisibleButNotCurrentDocumentsTimer.stop();
- } else {
- updateVisibleButNotCurrentDocumentsTimer.start(
- updateVisibleButNotCurrentDocumentsTimeOutInMs);
- }
-}
-
-void ClangCodeModelServer::processSuspendResumeJobs(const std::vector<Document> &documents)
-{
- const SuspendResumeJobs suspendResumeJobs = createSuspendResumeJobs(documents);
- for (const SuspendResumeJobsEntry &entry : suspendResumeJobs) {
- DocumentProcessor processor = documentProcessors().processor(entry.document);
- processor.addJob(entry.jobRequestType, entry.preferredTranslationUnit);
- if (entry.jobRequestType == JobRequest::Type::ResumeDocument) {
- processor.addJob(JobRequest::Type::UpdateExtraAnnotations,
- PreferredTranslationUnit::RecentlyParsed);
- }
- processor.process();
- }
-}
-
-bool ClangCodeModelServer::onJobFinished(const Jobs::RunningJob &jobRecord, IAsyncJob *job)
-{
- if (jobRecord.jobRequest.type == JobRequest::Type::UpdateAnnotations) {
- const auto updateJob = static_cast<UpdateAnnotationsJob *>(job);
- return resetDocumentsWithUnresolvedIncludes({updateJob->pinnedDocument()});
- }
-
- return false;
-}
-
-void ClangCodeModelServer::categorizeFileContainers(const QVector<FileContainer> &fileContainers,
- QVector<FileContainer> &toCreate,
- DocumentResetInfos &toReset) const
-{
- for (const FileContainer &fileContainer : fileContainers) {
- const std::vector<Document> matching = documents.filtered([&](const Document &document) {
- return document.filePath() == fileContainer.filePath;
- });
- if (matching.empty())
- toCreate.push_back(fileContainer);
- else
- toReset.push_back(DocumentResetInfo{*matching.begin(), fileContainer});
- }
-}
-
-std::vector<Document> ClangCodeModelServer::resetDocuments(const DocumentResetInfos &infos)
-{
- std::vector<Document> newDocuments;
-
- for (const DocumentResetInfo &info : infos) {
- const Document &document = info.documentToRemove;
- QTC_CHECK(document.filePath() == info.fileContainer.filePath);
-
- documents.remove({document.fileContainer()});
-
- Document newDocument = *documents.create({info.fileContainer}).begin();
- newDocument.setDirtyIfDependencyIsMet(document.filePath());
- newDocument.setIsUsedByCurrentEditor(document.isUsedByCurrentEditor());
- newDocument.setIsVisibleInEditor(document.isVisibleInEditor(), document.visibleTimePoint());
- newDocument.setResponsivenessIncreaseNeeded(document.isResponsivenessIncreased());
-
- documentProcessors().reset(document, newDocument);
-
- newDocuments.push_back(newDocument);
- }
-
- return newDocuments;
-}
-
-static bool isDocumentWithUnresolvedIncludesFixable(const Document &document,
- const UnsavedFiles &unsavedFiles)
-{
- for (uint i = 0; i < unsavedFiles.count(); ++i) {
- const UnsavedFile &unsavedFile = unsavedFiles.at(i);
- const Utf8String unsavedFilePath = QDir::cleanPath(unsavedFile.filePath());
-
- for (const Utf8String &unresolvedPath : document.unresolvedFilePaths()) {
- const QString documentDir = QFileInfo(document.filePath()).absolutePath();
- const QString candidate = QDir::cleanPath(documentDir + "/" + unresolvedPath.toString());
-
- if (Utf8String(candidate) == unsavedFilePath)
- return true;
-
- for (const Utf8String &headerPath : document.headerPaths()) {
- Utf8String candidate = headerPath;
- candidate.append(QStringLiteral("/"));
- candidate.append(unresolvedPath);
- candidate = QDir::cleanPath(candidate);
- if (candidate == unsavedFilePath)
- return true;
- }
- }
- }
-
- return false;
-}
-
-int ClangCodeModelServer::resetDocumentsWithUnresolvedIncludes(
- const std::vector<Document> &documents)
-{
- DocumentResetInfos toReset;
-
- for (const Document &document : documents) {
- if (document.unresolvedFilePaths().isEmpty())
- continue;
- if (isDocumentWithUnresolvedIncludesFixable(document, unsavedFiles))
- toReset << DocumentResetInfo{document, document.fileContainer()};
- }
-
- resetDocuments(toReset);
-
- return toReset.size();
-}
-
-void ClangCodeModelServer::setUpdateAnnotationsTimeOutInMsForTestsOnly(int value)
-{
- updateAnnotationsTimeOutInMs = value;
-}
-
-void ClangCodeModelServer::setUpdateVisibleButNotCurrentDocumentsTimeOutInMsForTestsOnly(int value)
-{
- updateVisibleButNotCurrentDocumentsTimeOutInMs = value;
-}
-
-DocumentProcessors &ClangCodeModelServer::documentProcessors()
-{
- if (!documentProcessors_) {
- // DocumentProcessors needs a reference to the client, but the client
- // is not known at construction time of ClangCodeModelServer, so
- // construct DocumentProcessors in a lazy manner.
- documentProcessors_.reset(new DocumentProcessors(documents, unsavedFiles, *client()));
- }
-
- return *documentProcessors_.data();
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangcodemodelserver.h b/src/tools/clangbackend/source/clangcodemodelserver.h
deleted file mode 100644
index 471c27bd8d5..00000000000
--- a/src/tools/clangbackend/source/clangcodemodelserver.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocument.h"
-#include "clangdocuments.h"
-#include "clangdocumentprocessors.h"
-#include "clangjobrequest.h"
-#include "unsavedfiles.h"
-
-#include <clangcodemodelserverinterface.h>
-#include <ipcclientprovider.h>
-#include <utf8string.h>
-
-#include <QScopedPointer>
-#include <QTimer>
-
-namespace ClangBackEnd {
-
-struct DocumentResetInfo {
- Document documentToRemove;
- FileContainer fileContainer;
-};
-using DocumentResetInfos = QVector<DocumentResetInfo>;
-
-class ClangCodeModelServer : public ClangCodeModelServerInterface,
- public IpcClientProvider<ClangCodeModelClientInterface>
-{
-public:
- ClangCodeModelServer();
-
- void end() override;
-
- void documentsOpened(const DocumentsOpenedMessage &message) override;
- void documentsChanged(const DocumentsChangedMessage &message) override;
- void documentsClosed(const DocumentsClosedMessage &message) override;
- void documentVisibilityChanged(const DocumentVisibilityChangedMessage &message) override;
-
- void unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message) override;
- void unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message) override;
-
- void requestCompletions(const RequestCompletionsMessage &message) override;
- void requestAnnotations(const RequestAnnotationsMessage &message) override;
- void requestReferences(const RequestReferencesMessage &message) override;
- void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
- void requestToolTip(const RequestToolTipMessage &message) override;
-
-public: // for tests
- const Documents &documentsForTestOnly() const;
- QList<Jobs::RunningJob> runningJobsForTestsOnly();
- int queueSizeForTestsOnly();
- bool isTimerRunningForTestOnly() const;
- void setUpdateAnnotationsTimeOutInMsForTestsOnly(int value);
- void setUpdateVisibleButNotCurrentDocumentsTimeOutInMsForTestsOnly(int value);
- DocumentProcessors &documentProcessors();
-
-private:
- void processJobsForVisibleDocuments();
- void processJobsForCurrentDocument();
- void processTimerForVisibleButNotCurrentDocuments();
- void processSuspendResumeJobs(const std::vector<Document> &documents);
-
- bool onJobFinished(const Jobs::RunningJob &jobRecord, IAsyncJob *job);
-
- void categorizeFileContainers(const QVector<FileContainer> &fileContainers,
- QVector<FileContainer> &toCreate,
- DocumentResetInfos &toReset) const;
- std::vector<Document> resetDocuments(const DocumentResetInfos &infos);
- int resetDocumentsWithUnresolvedIncludes(const std::vector<Document> &documents);
-
- void addAndRunUpdateJobs(std::vector<Document> documents);
-
-private:
- UnsavedFiles unsavedFiles;
- Documents documents;
-
- QScopedPointer<DocumentProcessors> documentProcessors_; // Delayed initialization
-
- QTimer updateAnnotationsTimer;
- int updateAnnotationsTimeOutInMs = 1500;
-
- QTimer updateVisibleButNotCurrentDocumentsTimer;
- int updateVisibleButNotCurrentDocumentsTimeOutInMs = 2000;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangcompletecodejob.cpp b/src/tools/clangbackend/source/clangcompletecodejob.cpp
deleted file mode 100644
index ad033a9ea5d..00000000000
--- a/src/tools/clangbackend/source/clangcompletecodejob.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangcompletecodejob.h"
-
-#include <clangsupport/clangsupportdebugutils.h>
-#include <clangsupport/clangcodemodelclientinterface.h>
-#include <clangsupport/completionsmessage.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-IAsyncJob::AsyncPrepareResult CompleteCodeJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestCompletions, return AsyncPrepareResult());
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- const TranslationUnit translationUnit = *m_translationUnit;
- const UnsavedFiles unsavedFiles = *context().unsavedFiles;
- const quint32 line = jobRequest.line;
- const quint32 column = jobRequest.column;
- const qint32 funcNameStartLine = jobRequest.funcNameStartLine;
- const qint32 funcNameStartColumn = jobRequest.funcNameStartColumn;
- setRunner([translationUnit, unsavedFiles, line, column,
- funcNameStartLine, funcNameStartColumn]() {
- TIME_SCOPE_DURATION("CompleteCodeJobRunner");
-
- UnsavedFiles theUnsavedFiles = unsavedFiles;
- CompleteCodeJob::AsyncResult asyncResult;
- asyncResult = translationUnit.complete(theUnsavedFiles, line, column,
- funcNameStartLine, funcNameStartColumn);
-
- return asyncResult;
- });
-
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void CompleteCodeJob::finalizeAsyncRun()
-{
- if (context().isDocumentOpen()) {
- const AsyncResult result = asyncResult();
-
- const CompletionsMessage message(result, context().jobRequest.ticketNumber);
- context().client->completions(message);
- }
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangcompletecodejob.h b/src/tools/clangbackend/source/clangcompletecodejob.h
deleted file mode 100644
index 0d62ce8b946..00000000000
--- a/src/tools/clangbackend/source/clangcompletecodejob.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentjob.h"
-
-#include <clangsupport/codecompletion.h>
-
-namespace ClangBackEnd {
-
-class CompleteCodeJob : public DocumentJob<CodeCompletions>
-{
-public:
- using AsyncResult = CodeCompletions;
-
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocument.cpp b/src/tools/clangbackend/source/clangdocument.cpp
deleted file mode 100644
index 672c9028541..00000000000
--- a/src/tools/clangbackend/source/clangdocument.cpp
+++ /dev/null
@@ -1,453 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangdocument.h"
-
-#include "clangdocuments.h"
-#include "clangstring.h"
-#include "clangunsavedfilesshallowarguments.h"
-#include "codecompleter.h"
-#include "clangexceptions.h"
-#include "clangtranslationunit.h"
-#include "clangtranslationunits.h"
-#include "clangtranslationunitupdater.h"
-#include "unsavedfiles.h"
-#include "unsavedfile.h"
-
-#include <utf8string.h>
-
-#include <QDebug>
-#include <QFileInfo>
-#include <QLoggingCategory>
-
-#include <ostream>
-
-namespace ClangBackEnd {
-
-class DocumentData
-{
-public:
- DocumentData(const Utf8String &filePath,
- const Utf8StringVector &compilationArguments,
- const Utf8StringVector &headerPaths,
- Documents &documents);
- ~DocumentData();
-
-public:
- Documents &documents;
-
- const Utf8String filePath;
- const Utf8StringVector compilationArguments;
- const Utf8StringVector headerPaths;
-
- TranslationUnits translationUnits;
-
- QSet<Utf8String> dependedFilePaths;
- QSet<Utf8String> unresolvedFilePaths;
-
- uint documentRevision = 0;
-
- TimePoint visibleTimePoint;
-
- TimePoint isDirtyChangeTimePoint;
- bool isDirty = false;
-
- bool hasParseOrReparseFailed = false;
- bool isUsedByCurrentEditor = false;
- bool isVisibleInEditor = false;
- bool increaseResponsiveness = false;
- bool isSuspended = false;
-};
-
-DocumentData::DocumentData(const Utf8String &filePath,
- const Utf8StringVector &compilationArguments,
- const Utf8StringVector &headerPaths,
- Documents &documents)
- : documents(documents),
- filePath(filePath),
- compilationArguments(compilationArguments),
- headerPaths(headerPaths),
- translationUnits(filePath),
- isDirtyChangeTimePoint(Clock::now())
-{
- dependedFilePaths.insert(filePath);
- translationUnits.createAndAppend();
-}
-
-DocumentData::~DocumentData()
-{
-}
-
-Document::Document(const Utf8String &filePath,
- const Utf8StringVector &compilationArguments,
- const Utf8StringVector &headerPaths,
- Documents &documents,
- FileExistsCheck fileExistsCheck)
- : d(std::make_shared<DocumentData>(filePath,
- compilationArguments,
- headerPaths,
- documents))
-{
- if (fileExistsCheck == FileExistsCheck::Check)
- checkIfFileExists();
-}
-
-Document::~Document() = default;
-Document::Document(const Document &) = default;
-Document &Document::operator=(const Document &) = default;
-
-Document::Document(Document &&other)
- : d(std::move(other.d))
-{
-}
-
-Document &Document::operator=(Document &&other)
-{
- d = std::move(other.d);
-
- return *this;
-}
-
-void Document::reset()
-{
- d.reset();
-}
-
-bool Document::isNull() const
-{
- return !d;
-}
-
-bool Document::isIntact() const
-{
- return !isNull()
- && fileExists()
- && !d->hasParseOrReparseFailed;
-}
-
-bool Document::isParsed() const
-{
- return d->translationUnits.areAllTranslationUnitsParsed();
-}
-
-long Document::useCount() const
-{
- return d.use_count();
-}
-
-Utf8String Document::filePath() const
-{
- checkIfNull();
-
- return d->filePath;
-}
-
-Utf8StringVector Document::compilationArguments() const
-{
- checkIfNull();
-
- return d->compilationArguments;
-}
-
-Utf8StringVector Document::headerPaths() const
-{
- checkIfNull();
-
- return d->headerPaths;
-}
-
-FileContainer Document::fileContainer() const
-{
- checkIfNull();
-
- return FileContainer(d->filePath,
- d->compilationArguments,
- d->headerPaths,
- Utf8String(),
- false,
- d->documentRevision);
-}
-
-uint Document::documentRevision() const
-{
- checkIfNull();
-
- return d->documentRevision;
-}
-
-void Document::setDocumentRevision(uint revision)
-{
- checkIfNull();
-
- d->documentRevision = revision;
-}
-
-bool Document::isResponsivenessIncreased() const
-{
- return d->translationUnits.size() > 1;
-}
-
-bool Document::isResponsivenessIncreaseNeeded() const
-{
- checkIfNull();
-
- return d->increaseResponsiveness;
-}
-
-void Document::setResponsivenessIncreaseNeeded(bool responsivenessIncreaseNeeded)
-{
- d->increaseResponsiveness = responsivenessIncreaseNeeded;
-}
-
-bool Document::isSuspended() const
-{
- checkIfNull();
-
- return d->isSuspended;
-}
-
-void Document::setIsSuspended(bool isSuspended)
-{
- checkIfNull();
-
- d->isSuspended = isSuspended;
-}
-
-bool Document::isUsedByCurrentEditor() const
-{
- checkIfNull();
-
- return d->isUsedByCurrentEditor;
-}
-
-void Document::setIsUsedByCurrentEditor(bool isUsedByCurrentEditor)
-{
- checkIfNull();
-
- d->isUsedByCurrentEditor = isUsedByCurrentEditor;
-}
-
-bool Document::isVisibleInEditor() const
-{
- checkIfNull();
-
- return d->isVisibleInEditor;
-}
-
-void Document::setIsVisibleInEditor(bool isVisibleInEditor, const TimePoint &timePoint)
-{
- checkIfNull();
-
- if (isVisibleInEditor)
- d->visibleTimePoint = timePoint;
- d->isVisibleInEditor = isVisibleInEditor;
-}
-
-TimePoint Document::visibleTimePoint() const
-{
- checkIfNull();
-
- return d->visibleTimePoint;;
-}
-
-bool Document::isDirty() const
-{
- checkIfNull();
-
- return d->isDirty;
-}
-
-TimePoint Document::isDirtyTimeChangePoint() const
-{
- checkIfNull();
-
- return d->isDirtyChangeTimePoint;
-}
-
-void Document::setDirtyIfDependencyIsMet(const Utf8String &filePath)
-{
- if (d->dependedFilePaths.contains(filePath) && isMainFileAndExistsOrIsOtherFile(filePath))
- setDirty();
-}
-
-TranslationUnitUpdateInput Document::createUpdateInput() const
-{
- TranslationUnitUpdateInput updateInput;
- updateInput.reparseNeeded = d->isDirty;
- updateInput.needsToBeReparsedChangeTimePoint = d->isDirtyChangeTimePoint;
- updateInput.filePath = d->filePath;
- updateInput.compilationArguments = d->compilationArguments;
- updateInput.unsavedFiles = d->documents.unsavedFiles();
-
- return updateInput;
-}
-
-TranslationUnitUpdater Document::createUpdater() const
-{
- TranslationUnit unit = translationUnit();
-
- const TranslationUnitUpdateInput updateInput = createUpdateInput();
- TranslationUnitUpdater updater(unit.id(),
- unit.cxIndex(),
- unit.cxTranslationUnit(),
- updateInput);
-
- return updater;
-}
-
-void Document::setHasParseOrReparseFailed(bool hasFailed)
-{
- d->hasParseOrReparseFailed = hasFailed;
-}
-
-void Document::incorporateUpdaterResult(const TranslationUnitUpdateResult &result) const
-{
- d->hasParseOrReparseFailed = result.hasParseOrReparseFailed;
- if (d->hasParseOrReparseFailed) {
- d->isDirty = false;
- return;
- }
-
- if (result.hasParsed() || result.hasReparsed()) {
- d->dependedFilePaths = result.dependedOnFilePaths;
-
- const TimePoint timePoint = qMax(result.parseTimePoint, result.reparseTimePoint);
- d->translationUnits.updateParseTimePoint(result.translationUnitId, timePoint);
- }
-
- d->documents.addWatchedFiles(d->dependedFilePaths);
-
- if (result.hasReparsed()
- && result.needsToBeReparsedChangeTimePoint == d->isDirtyChangeTimePoint) {
- d->isDirty = false;
- }
-}
-
-const QSet<Utf8String> Document::unresolvedFilePaths() const
-{
- checkIfNull();
-
- return d->unresolvedFilePaths;
-}
-
-void Document::setUnresolvedFilePaths(const QSet<Utf8String> &unresolved)
-{
- checkIfNull();
-
- d->unresolvedFilePaths = unresolved;
-}
-
-TranslationUnit Document::translationUnit(PreferredTranslationUnit preferredTranslationUnit) const
-{
- checkIfNull();
-
- return d->translationUnits.get(preferredTranslationUnit);
-}
-
-TranslationUnits &Document::translationUnits() const
-{
- return d->translationUnits;
-}
-
-void Document::parse() const
-{
- checkIfNull();
-
- const TranslationUnitUpdateInput updateInput = createUpdateInput();
- TranslationUnitUpdateResult result = translationUnit().parse(updateInput);
-
- incorporateUpdaterResult(result);
-}
-
-void Document::reparse() const
-{
- checkIfNull();
-
- const TranslationUnitUpdateInput updateInput = createUpdateInput();
- TranslationUnitUpdateResult result = translationUnit().reparse(updateInput);
-
- incorporateUpdaterResult(result);
-}
-
-const QSet<Utf8String> Document::dependedFilePaths() const
-{
- checkIfNull();
- checkIfFileExists();
-
- return d->dependedFilePaths;
-}
-
-void Document::setDependedFilePaths(const QSet<Utf8String> &filePaths)
-{
- d->dependedFilePaths = filePaths;
-}
-
-void Document::setDirty()
-{
- d->isDirtyChangeTimePoint = Clock::now();
- d->isDirty = true;
-}
-
-void Document::checkIfNull() const
-{
- if (isNull())
- throw DocumentIsNullException();
-}
-
-void Document::checkIfFileExists() const
-{
- if (!fileExists())
- throw DocumentFileDoesNotExistException(d->filePath);
-}
-
-bool Document::fileExists() const
-{
- return QFileInfo::exists(d->filePath.toString());
-}
-
-bool Document::isMainFileAndExistsOrIsOtherFile(const Utf8String &filePath) const
-{
- if (filePath == d->filePath)
- return QFileInfo::exists(d->filePath);
-
- return true;
-}
-
-bool operator==(const Document &first, const Document &second)
-{
- return first.filePath() == second.filePath();
-}
-
-std::ostream &operator<<(std::ostream &os, const Document &document)
-{
- os << "("
- << document.filePath() << ", "
- << document.documentRevision()
- << ")";
-
- return os;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocument.h b/src/tools/clangbackend/source/clangdocument.h
deleted file mode 100644
index a637731a6e9..00000000000
--- a/src/tools/clangbackend/source/clangdocument.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangtranslationunitupdater.h"
-
-#include "clangbackend_global.h"
-#include "clangtranslationunit.h"
-
-#include <utf8stringvector.h>
-
-#include <clang-c/Index.h>
-
-#include <QSet>
-#include <QtGlobal>
-
-#include <memory>
-
-class Utf8String;
-
-namespace ClangBackEnd {
-
-class TranslationUnit;
-class TranslationUnits;
-class DocumentData;
-class TranslationUnitUpdateResult;
-class FileContainer;
-class Documents;
-
-class Document
-{
-public:
- enum class FileExistsCheck {
- Check,
- DoNotCheck
- };
-
- Document() = default;
- Document(const Utf8String &filePath,
- const Utf8StringVector &compilationArguments,
- const Utf8StringVector &headerPaths,
- Documents &documents,
- FileExistsCheck fileExistsCheck = FileExistsCheck::Check);
- ~Document();
-
- Document(const Document &document);
- Document &operator=(const Document &document);
-
- Document(Document &&document);
- Document &operator=(Document &&document);
-
- void reset();
-
- bool isNull() const;
- bool isIntact() const;
- bool isParsed() const;
- long useCount() const;
-
- Utf8String filePath() const;
- Utf8StringVector compilationArguments() const;
- Utf8StringVector headerPaths() const;
- FileContainer fileContainer() const;
-
- uint documentRevision() const;
- void setDocumentRevision(uint revision);
-
- bool isResponsivenessIncreased() const;
- bool isResponsivenessIncreaseNeeded() const;
- void setResponsivenessIncreaseNeeded(bool responsivenessIncreaseNeeded);
-
- bool isSuspended() const;
- void setIsSuspended(bool isSuspended);
-
- bool isUsedByCurrentEditor() const;
- void setIsUsedByCurrentEditor(bool isUsedByCurrentEditor);
-
- bool isVisibleInEditor() const;
- void setIsVisibleInEditor(bool isVisibleInEditor, const TimePoint &timePoint);
- TimePoint visibleTimePoint() const;
-
- bool isDirty() const;
- TimePoint isDirtyTimeChangePoint() const;
- void setDirtyIfDependencyIsMet(const Utf8String &filePath);
-
- TranslationUnitUpdateInput createUpdateInput() const;
- void incorporateUpdaterResult(const TranslationUnitUpdateResult &result) const;
-
- const QSet<Utf8String> unresolvedFilePaths() const;
- void setUnresolvedFilePaths(const QSet<Utf8String> &unresolved);
-
- TranslationUnit translationUnit(PreferredTranslationUnit preferredTranslationUnit
- = PreferredTranslationUnit::RecentlyParsed) const;
- TranslationUnits &translationUnits() const;
-
- friend bool operator==(const Document &first, const Document &second);
- friend std::ostream &operator<<(std::ostream &os, const Document &document);
-
-public: // for tests
- void parse() const;
- void reparse() const;
- const QSet<Utf8String> dependedFilePaths() const;
- void setDependedFilePaths(const QSet<Utf8String> &filePaths);
- TranslationUnitUpdater createUpdater() const;
- void setHasParseOrReparseFailed(bool hasFailed);
-
-private:
- void setDirty();
-
- void checkIfNull() const;
- void checkIfFileExists() const;
-
- bool fileExists() const;
- bool isMainFileAndExistsOrIsOtherFile(const Utf8String &filePath) const;
-
-private:
- mutable std::shared_ptr<DocumentData> d;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocumentjob.h b/src/tools/clangbackend/source/clangdocumentjob.h
deleted file mode 100644
index d9b71d3a438..00000000000
--- a/src/tools/clangbackend/source/clangdocumentjob.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangasyncjob.h"
-#include "clangdocument.h"
-
-#include <clangsupport/filecontainer.h>
-
-#include <memory>
-
-namespace ClangBackEnd {
-
-template<class Result>
-class DocumentJob : public AsyncJob<Result>
-{
-public:
- Document pinnedDocument() const { return m_pinnedDocument; }
-
-protected:
- bool acquireDocument()
- {
- try {
- m_pinnedDocument = IAsyncJob::context().documentForJobRequest();
- m_pinnedFileContainer = m_pinnedDocument.fileContainer();
-
- const PreferredTranslationUnit preferredTranslationUnit
- = IAsyncJob::context().jobRequest.preferredTranslationUnit;
- m_translationUnit.reset(
- new TranslationUnit(m_pinnedDocument.translationUnit(preferredTranslationUnit)));
- return true;
- } catch (const std::exception &) {
- return false;
- }
- }
-
-protected:
- Document m_pinnedDocument;
- FileContainer m_pinnedFileContainer;
-
- std::unique_ptr<TranslationUnit> m_translationUnit;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocumentprocessor.cpp b/src/tools/clangbackend/source/clangdocumentprocessor.cpp
deleted file mode 100644
index dd390c6ba68..00000000000
--- a/src/tools/clangbackend/source/clangdocumentprocessor.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangdocumentprocessor.h"
-
-#include "clangdocuments.h"
-#include "clangjobs.h"
-#include "clangsupportivetranslationunitinitializer.h"
-
-#include "clangdocument.h"
-#include "clangtranslationunits.h"
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-#include <QFileInfo>
-
-namespace ClangBackEnd {
-
-class DocumentProcessorData
-{
-public:
- DocumentProcessorData(const Document &document,
- Documents &documents,
- UnsavedFiles &unsavedFiles,
- ClangCodeModelClientInterface &client)
- : document(document)
- , documents(documents)
- , jobs(documents, unsavedFiles, client, QFileInfo(document.filePath()).fileName())
- , supportiveTranslationUnitInitializer(document, jobs)
- {
- const auto isDocumentClosedChecker = [this](const Utf8String &filePath) {
- return !this->documents.hasDocument(filePath);
- };
- supportiveTranslationUnitInitializer.setIsDocumentClosedChecker(isDocumentClosedChecker);
- }
-
-public:
- Document document;
- Documents &documents;
- Jobs jobs;
-
- SupportiveTranslationUnitInitializer supportiveTranslationUnitInitializer;
-};
-
-DocumentProcessor::DocumentProcessor(const Document &document,
- Documents &documents,
- UnsavedFiles &unsavedFiles,
- ClangCodeModelClientInterface &client)
- : d(std::make_shared<DocumentProcessorData>(document,
- documents,
- unsavedFiles,
- client))
-{
-}
-
-Jobs &DocumentProcessor::jobs() const
-{
- return d->jobs;
-}
-
-JobRequest DocumentProcessor::createJobRequest(
- JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit) const
-{
- return d->jobs.createJobRequest(d->document, type, preferredTranslationUnit);
-}
-
-void DocumentProcessor::addJob(const JobRequest &jobRequest)
-{
- d->jobs.add(jobRequest);
-}
-
-void DocumentProcessor::addJob(JobRequest::Type type, PreferredTranslationUnit preferredTranslationUnit)
-{
- d->jobs.add(d->document, type, preferredTranslationUnit);
-}
-
-JobRequests DocumentProcessor::process()
-{
- return d->jobs.process();
-}
-
-JobRequests DocumentProcessor::stop()
-{
- d->supportiveTranslationUnitInitializer.abort();
- return d->jobs.stop();
-}
-
-Document DocumentProcessor::document() const
-{
- return d->document;
-}
-
-bool DocumentProcessor::hasSupportiveTranslationUnit() const
-{
- return d->supportiveTranslationUnitInitializer.state()
- != SupportiveTranslationUnitInitializer::State::NotInitialized;
-}
-
-void DocumentProcessor::startInitializingSupportiveTranslationUnit()
-{
- d->supportiveTranslationUnitInitializer.startInitializing();
-}
-
-bool DocumentProcessor::isSupportiveTranslationUnitInitialized() const
-{
- return d->supportiveTranslationUnitInitializer.state()
- == SupportiveTranslationUnitInitializer::State::Initialized;
-}
-
-JobRequests &DocumentProcessor::queue()
-{
- return d->jobs.queue();
-}
-
-QList<Jobs::RunningJob> DocumentProcessor::runningJobs() const
-{
- return d->jobs.runningJobs();
-}
-
-int DocumentProcessor::queueSize() const
-{
- return d->jobs.queue().size();
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocumentprocessor.h b/src/tools/clangbackend/source/clangdocumentprocessor.h
deleted file mode 100644
index 7de2664322a..00000000000
--- a/src/tools/clangbackend/source/clangdocumentprocessor.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangjobrequest.h"
-#include "clangjobs.h"
-
-#include <memory>
-
-namespace ClangBackEnd {
-
-class ClangCodeModelClientInterface;
-class Document;
-class Documents;
-class DocumentProcessorData;
-class JobRequest;
-class UnsavedFiles;
-
-class DocumentProcessor
-{
-public:
- DocumentProcessor(const Document &document,
- Documents &documents,
- UnsavedFiles &unsavedFiles,
- ClangCodeModelClientInterface &client);
-
- Jobs &jobs() const;
-
- JobRequest createJobRequest(JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit
- = PreferredTranslationUnit::RecentlyParsed) const;
-
- void addJob(const JobRequest &jobRequest);
- void addJob(JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit
- = PreferredTranslationUnit::RecentlyParsed);
-
- JobRequests process();
- JobRequests stop();
-
- Document document() const;
-
- bool hasSupportiveTranslationUnit() const;
- void startInitializingSupportiveTranslationUnit();
-
-public: // for tests
- bool isSupportiveTranslationUnitInitialized() const;
- JobRequests &queue();
- QList<Jobs::RunningJob> runningJobs() const;
- int queueSize() const;
-
-private:
- std::shared_ptr<DocumentProcessorData> d;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocumentprocessors.cpp b/src/tools/clangbackend/source/clangdocumentprocessors.cpp
deleted file mode 100644
index 951e4ef7a17..00000000000
--- a/src/tools/clangbackend/source/clangdocumentprocessors.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangdocumentprocessors.h"
-#include "clangdocument.h"
-#include "clangexceptions.h"
-
-#include <utils/algorithm.h>
-
-namespace ClangBackEnd {
-
-DocumentProcessors::DocumentProcessors(Documents &documents,
- UnsavedFiles &unsavedFiles,
- ClangCodeModelClientInterface &client)
- : m_documents(documents)
- , m_unsavedFiles(unsavedFiles)
- , m_client(client)
-{
-}
-
-DocumentProcessor DocumentProcessors::create(const Document &document)
-{
- const Utf8String filePath{document.filePath()};
- if (m_processors.contains(filePath))
- throw DocumentProcessorAlreadyExists(document.filePath());
-
- const DocumentProcessor element(document, m_documents, m_unsavedFiles, m_client);
- m_processors.insert(filePath, element);
-
- return element;
-}
-
-DocumentProcessor DocumentProcessors::processor(const Document &document)
-{
- const Utf8String filePath = document.filePath();
- const auto it = m_processors.find(filePath);
- if (it == m_processors.end())
- throw DocumentProcessorDoesNotExist(filePath);
-
- return *it;
-}
-
-QList<DocumentProcessor> DocumentProcessors::processors() const
-{
- return m_processors.values();
-}
-
-void DocumentProcessors::remove(const Document &document)
-{
- const int itemsRemoved = m_processors.remove(document.filePath());
- if (itemsRemoved != 1)
- throw DocumentProcessorDoesNotExist(document.filePath());
-}
-
-void DocumentProcessors::reset(const Document &oldDocument, const Document &newDocument)
-{
- // Wait until the currently running jobs finish and remember the not yet
- // processed job requests for the new processor...
- const JobRequests jobsStillInQueue = processor(oldDocument).stop();
- // ...but do not take over irrelevant ones.
- const JobRequests jobsForNewProcessor = Utils::filtered(jobsStillInQueue,
- [](const JobRequest &job) {
- return job.isTakeOverable();
- });
- const Jobs::JobFinishedCallback jobFinishedCallback
- = processor(oldDocument).jobs().jobFinishedCallback();
-
- // Remove current processor
- remove(oldDocument);
-
- // Create new processor and take over not yet processed jobs.
- DocumentProcessor newProcessor = create(newDocument);
- for (const JobRequest &job : jobsForNewProcessor)
- newProcessor.addJob(job);
- newProcessor.jobs().setJobFinishedCallback(jobFinishedCallback);
-}
-
-JobRequests DocumentProcessors::process()
-{
- JobRequests jobsStarted;
- for (auto &processor : m_processors)
- jobsStarted += processor.process();
-
- return jobsStarted;
-}
-
-QList<Jobs::RunningJob> DocumentProcessors::runningJobs() const
-{
- QList<Jobs::RunningJob> jobs;
- for (auto &processor : m_processors)
- jobs += processor.runningJobs();
-
- return jobs;
-}
-
-int DocumentProcessors::queueSize() const
-{
- int total = 0;
- for (auto &processor : m_processors)
- total += processor.queueSize();
-
- return total;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocumentprocessors.h b/src/tools/clangbackend/source/clangdocumentprocessors.h
deleted file mode 100644
index ab00fa8d563..00000000000
--- a/src/tools/clangbackend/source/clangdocumentprocessors.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentprocessor.h"
-#include "clangjobs.h"
-
-#include <utf8string.h>
-
-#include <QMap>
-
-namespace ClangBackEnd {
-
-class Document;
-class DocumentProcessor;
-
-class DocumentProcessors
-{
-public:
- DocumentProcessors(Documents &documents,
- UnsavedFiles &unsavedFiles,
- ClangCodeModelClientInterface &client);
-
- DocumentProcessor create(const Document &document);
- DocumentProcessor processor(const Document &document);
- void remove(const Document &document);
- void reset(const Document &oldDocument, const Document &newDocument);
-
- JobRequests process();
-
-public: // for tests
- QList<DocumentProcessor> processors() const;
- QList<Jobs::RunningJob> runningJobs() const;
- int queueSize() const;
-
-private:
- Documents &m_documents;
- UnsavedFiles &m_unsavedFiles;
- ClangCodeModelClientInterface &m_client;
-
- QMap<Utf8String, DocumentProcessor> m_processors;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocuments.cpp b/src/tools/clangbackend/source/clangdocuments.cpp
deleted file mode 100644
index 7b274d7755c..00000000000
--- a/src/tools/clangbackend/source/clangdocuments.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangdocuments.h"
-
-#include <diagnosticset.h>
-#include <tokenprocessor.h>
-#include <clangexceptions.h>
-#include <skippedsourceranges.h>
-#include <unsavedfiles.h>
-
-#include <utils/algorithm.h>
-
-#include <QDebug>
-
-#include <algorithm>
-
-namespace ClangBackEnd {
-
-bool operator==(const FileContainer &fileContainer, const Document &document)
-{
- return fileContainer.filePath == document.filePath();
-}
-
-bool operator==(const Document &document, const FileContainer &fileContainer)
-{
- return fileContainer == document;
-}
-
-Documents::Documents(UnsavedFiles &unsavedFiles)
- : fileSystemWatcher(*this),
- unsavedFiles_(unsavedFiles)
-{
-}
-
-std::vector<Document> Documents::create(const QVector<FileContainer> &fileContainers)
-{
- checkIfDocumentsDoNotExist(fileContainers);
-
- std::vector<Document> createdDocuments;
-
- for (const FileContainer &fileContainer : fileContainers) {
- if (fileContainer.hasUnsavedFileContent)
- updateDocumentsWithChangedDependency(fileContainer.filePath);
-
- createdDocuments.push_back(createDocument(fileContainer));
- }
-
- return createdDocuments;
-}
-
-std::vector<Document> Documents::update(const QVector<FileContainer> &fileContainers)
-{
- checkIfDocumentsForFilePathsExist(fileContainers);
-
- std::vector<Document> createdDocuments;
-
- for (const FileContainer &fileContainer : fileContainers) {
- const std::vector<Document> documents = updateDocument(fileContainer);
- createdDocuments.insert(createdDocuments.end(), documents.begin(), documents.end());
-
- updateDocumentsWithChangedDependency(fileContainer.filePath);
- }
-
- return createdDocuments;
-}
-
-static bool removeFromFileContainer(QVector<FileContainer> &fileContainers, const Document &document)
-{
- auto position = std::remove(fileContainers.begin(), fileContainers.end(), document);
-
- bool entryIsRemoved = position != fileContainers.end();
-
- fileContainers.erase(position, fileContainers.end());
-
- return entryIsRemoved;
-}
-
-void Documents::remove(const QVector<FileContainer> &fileContainers)
-{
- removeDocuments(fileContainers);
- updateDocumentsWithChangedDependencies(fileContainers);
-}
-
-void Documents::setUsedByCurrentEditor(const Utf8String &filePath)
-{
- for (Document &document : documents_)
- document.setIsUsedByCurrentEditor(document.filePath() == filePath);
-}
-
-void Documents::setVisibleInEditors(const Utf8StringVector &filePaths)
-{
- const TimePoint timePoint = Clock::now();
- for (Document &document : documents_)
- document.setIsVisibleInEditor(filePaths.contains(document.filePath()), timePoint);
-}
-
-const Document &Documents::document(const Utf8String &filePath) const
-{
- auto findIterator = findDocument(filePath);
-
- if (findIterator == documents_.end())
- throw DocumentDoesNotExistException(filePath);
-
- return *findIterator;
-}
-
-const Document &Documents::document(const FileContainer &fileContainer) const
-{
- return document(fileContainer.filePath);
-}
-
-const std::vector<Document> &Documents::documents() const
-{
- return documents_;
-}
-
-const std::vector<Document> Documents::filtered(const IsMatchingDocument &isMatchingDocument) const
-{
- return Utils::filtered(documents_, isMatchingDocument);
-}
-
-std::vector<Document> Documents::dirtyAndVisibleButNotCurrentDocuments() const
-{
- return filtered([](const Document &document) {
- return document.isDirty()
- && document.isVisibleInEditor()
- && !document.isUsedByCurrentEditor();
- });
-}
-
-UnsavedFiles Documents::unsavedFiles() const
-{
- return unsavedFiles_;
-}
-
-void Documents::addWatchedFiles(QSet<Utf8String> &filePaths)
-{
- fileSystemWatcher.addFiles(filePaths);
-}
-
-void Documents::updateDocumentsWithChangedDependency(const Utf8String &filePath)
-{
- for (auto &document : documents_)
- document.setDirtyIfDependencyIsMet(filePath);
-}
-
-void Documents::updateDocumentsWithChangedDependencies(const QVector<FileContainer> &fileContainers)
-{
- for (const FileContainer &fileContainer : fileContainers)
- updateDocumentsWithChangedDependency(fileContainer.filePath);
-}
-
-QVector<FileContainer> Documents::newerFileContainers(const QVector<FileContainer> &fileContainers) const
-{
- QVector<FileContainer> newerContainers;
-
- auto documentIsNewer = [this] (const FileContainer &fileContainer) {
- try {
- return document(fileContainer).documentRevision() != fileContainer.documentRevision;
- } catch (const DocumentDoesNotExistException &) {
- return true;
- }
- };
-
- std::copy_if(fileContainers.cbegin(),
- fileContainers.cend(),
- std::back_inserter(newerContainers),
- documentIsNewer);
-
- return newerContainers;
-}
-
-const ClangFileSystemWatcher *Documents::clangFileSystemWatcher() const
-{
- return &fileSystemWatcher;
-}
-
-Document Documents::createDocument(const FileContainer &fileContainer)
-{
- const Document::FileExistsCheck checkIfFileExists = fileContainer.hasUnsavedFileContent
- ? Document::FileExistsCheck::DoNotCheck
- : Document::FileExistsCheck::Check;
-
- documents_.emplace_back(fileContainer.filePath,
- fileContainer.compilationArguments,
- fileContainer.headerPaths,
- *this,
- checkIfFileExists);
-
- documents_.back().setDocumentRevision(fileContainer.documentRevision);
-
- return documents_.back();
-}
-
-std::vector<Document> Documents::updateDocument(const FileContainer &fileContainer)
-{
- const auto documents = findAllDocumentsWithFilePath(fileContainer.filePath);
-
- for (auto document : documents)
- document.setDocumentRevision(fileContainer.documentRevision);
-
- return documents;
-}
-
-std::vector<Document>::const_iterator Documents::findDocument(const FileContainer &fileContainer) const
-{
- return std::find(documents_.begin(), documents_.end(), fileContainer);
-}
-
-std::vector<Document> Documents::findAllDocumentsWithFilePath(const Utf8String &filePath)
-{
- const auto filePathCompare = [&filePath] (const Document &document) {
- return document.filePath() == filePath;
- };
-
- std::vector<Document> documents;
- std::copy_if(documents_.begin(),
- documents_.end(),
- std::back_inserter(documents),
- filePathCompare);
-
- return documents;
-}
-
-bool Documents::hasDocument(const Utf8String &filePath) const
-{
- auto filePathCompare = [&filePath] (const Document &document) {
- return document.filePath() == filePath;
- };
-
- auto findIterator = std::find_if(documents_.begin(), documents_.end(), filePathCompare);
-
- return findIterator != documents_.end();
-}
-
-void Documents::checkIfDocumentsDoNotExist(const QVector<FileContainer> &fileContainers) const
-{
- for (const FileContainer &fileContainer : fileContainers) {
- if (hasDocument(fileContainer.filePath))
- throw DocumentAlreadyExistsException(fileContainer.filePath);
- }
-}
-
-void Documents::checkIfDocumentsForFilePathsExist(const QVector<FileContainer> &fileContainers) const
-{
- for (const FileContainer &fileContainer : fileContainers) {
- if (!hasDocument(fileContainer.filePath))
- throw DocumentDoesNotExistException(fileContainer.filePath);
- }
-}
-
-void Documents::removeDocuments(const QVector<FileContainer> &fileContainers)
-{
- QVector<FileContainer> processedFileContainers = fileContainers;
-
- auto removeBeginIterator = std::remove_if(documents_.begin(), documents_.end(), [&processedFileContainers] (const Document &document) {
- return removeFromFileContainer(processedFileContainers, document);
- });
-
- documents_.erase(removeBeginIterator, documents_.end());
-
- if (!processedFileContainers.isEmpty()) {
- const FileContainer fileContainer = processedFileContainers.first();
- throw DocumentDoesNotExistException(fileContainer.filePath);
- }
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocuments.h b/src/tools/clangbackend/source/clangdocuments.h
deleted file mode 100644
index 9523e67c838..00000000000
--- a/src/tools/clangbackend/source/clangdocuments.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocument.h"
-#include "clangfilesystemwatcher.h"
-
-#include <filecontainer.h>
-
-#include <QVector>
-
-#include <functional>
-#include <vector>
-
-namespace ClangBackEnd {
-
-class UnsavedFiles;
-
-class Documents
-{
-public:
- Documents(UnsavedFiles &unsavedFiles);
-
- std::vector<Document> create(const QVector<FileContainer> &fileContainers);
- std::vector<Document> update(const QVector<FileContainer> &fileContainers);
- void remove(const QVector<FileContainer> &fileContainers);
-
- void setUsedByCurrentEditor(const Utf8String &filePath);
- void setVisibleInEditors(const Utf8StringVector &filePaths);
-
- const Document &document(const Utf8String &filePath) const;
- const Document &document(const FileContainer &fileContainer) const;
- bool hasDocument(const Utf8String &filePath) const;
-
- const std::vector<Document> &documents() const;
- using IsMatchingDocument = std::function<bool(const Document &document)>;
- const std::vector<Document> filtered(const IsMatchingDocument &isMatchingDocument) const;
- std::vector<Document> dirtyAndVisibleButNotCurrentDocuments() const;
-
- UnsavedFiles unsavedFiles() const;
-
- void addWatchedFiles(QSet<Utf8String> &filePaths);
-
- void updateDocumentsWithChangedDependency(const Utf8String &filePath);
- void updateDocumentsWithChangedDependencies(const QVector<FileContainer> &fileContainers);
-
- QVector<FileContainer> newerFileContainers(const QVector<FileContainer> &fileContainers) const;
-
- const ClangFileSystemWatcher *clangFileSystemWatcher() const;
-
-private:
- Document createDocument(const FileContainer &fileContainer);
- std::vector<Document> updateDocument(const FileContainer &fileContainer);
- std::vector<Document>::const_iterator findDocument(const FileContainer &fileContainer) const;
- std::vector<Document> findAllDocumentsWithFilePath(const Utf8String &filePath);
- void checkIfDocumentsDoNotExist(const QVector<FileContainer> &fileContainers) const;
- void checkIfDocumentsForFilePathsExist(const QVector<FileContainer> &fileContainers) const;
-
- void removeDocuments(const QVector<FileContainer> &fileContainers);
-
-private:
- ClangFileSystemWatcher fileSystemWatcher;
- std::vector<Document> documents_;
- UnsavedFiles &unsavedFiles_;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocumentsuspenderresumer.cpp b/src/tools/clangbackend/source/clangdocumentsuspenderresumer.cpp
deleted file mode 100644
index 6be3aaa7c5b..00000000000
--- a/src/tools/clangbackend/source/clangdocumentsuspenderresumer.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangdocumentsuspenderresumer.h"
-
-#include "clangsupport_global.h"
-#include "clangdocumentprocessors.h"
-#include "clangdocuments.h"
-
-#include <utils/algorithm.h>
-
-#include <algorithm>
-
-namespace ClangBackEnd {
-
-constexpr int DefaultHotDocumentsSize = 7;
-
-void categorizeHotColdDocuments(int hotDocumentsSize,
- const std::vector<Document> &inDocuments,
- std::vector<Document> &hotDocuments,
- std::vector<Document> &coldDocuments)
-{
- // Sort documents, most recently used/visible at top
- std::vector<Document> documents = inDocuments;
- std::stable_sort(documents.begin(), documents.end(), [](const Document &a, const Document &b) {
- return a.visibleTimePoint() > b.visibleTimePoint();
- });
-
- // Ensure that visible documents are always hot, otherwise not all visible
- // documents will be resumed.
- const auto isVisible = [](const Document &document) { return document.isVisibleInEditor(); };
- const int visibleDocumentsSize = Utils::count(documents, isVisible);
- hotDocumentsSize = std::max(hotDocumentsSize, visibleDocumentsSize);
-
- if (documents.size() <= uint(hotDocumentsSize)) {
- hotDocuments = documents;
- coldDocuments.clear();
- } else {
- const auto firstColdIterator = documents.begin() + hotDocumentsSize;
- hotDocuments = std::vector<Document>(documents.begin(), firstColdIterator);
- coldDocuments = std::vector<Document>(firstColdIterator, documents.end());
- }
-}
-
-static int hotDocumentsSize()
-{
- static int hotDocuments = -1;
- if (hotDocuments == -1) {
- bool ok = false;
- const int fromEnvironment = qEnvironmentVariableIntValue("QTC_CLANG_HOT_DOCUMENTS", &ok);
- hotDocuments = ok && fromEnvironment >= 1 ? fromEnvironment : DefaultHotDocumentsSize;
- }
-
- return hotDocuments;
-}
-
-static SuspendResumeJobs createJobs(const Document &document, JobRequest::Type type)
-{
- SuspendResumeJobs jobs;
-
- jobs.append({document, type, PreferredTranslationUnit::RecentlyParsed});
- if (document.isResponsivenessIncreased())
- jobs.append({document, type, PreferredTranslationUnit::PreviouslyParsed});
-
- return jobs;
-}
-
-static bool isFineDocument(const Document &document)
-{
- return !document.isNull() && document.isIntact();
-}
-
-static bool isSuspendable(const Document &document)
-{
- return isFineDocument(document)
- && !document.isSuspended()
- && !document.isVisibleInEditor()
- && document.isParsed();
-}
-
-static bool isResumable(const Document &document)
-{
- return isFineDocument(document)
- && document.isSuspended()
- && document.isVisibleInEditor();
-}
-
-SuspendResumeJobs createSuspendResumeJobs(const std::vector<Document> &documents,
- int customHotDocumentSize)
-{
- SuspendResumeJobs jobs;
-
- std::vector<Document> hotDocuments;
- std::vector<Document> coldDocuments;
-
- const int size = (customHotDocumentSize == -1) ? hotDocumentsSize() : customHotDocumentSize;
- categorizeHotColdDocuments(size, documents, hotDocuments, coldDocuments);
-
- // Cold documents should be suspended...
- const std::vector<Document> toSuspend = Utils::filtered(coldDocuments, &isSuspendable);
- for (const Document &document : toSuspend)
- jobs += createJobs(document, JobRequest::Type::SuspendDocument);
-
- // ...and hot documents that were suspended should be resumed
- const std::vector<Document> toResume = Utils::filtered(hotDocuments, &isResumable);
- for (const Document &document : toResume)
- jobs += createJobs(document, JobRequest::Type::ResumeDocument);
-
- return jobs;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangdocumentsuspenderresumer.h b/src/tools/clangbackend/source/clangdocumentsuspenderresumer.h
deleted file mode 100644
index 7e2bd8722d4..00000000000
--- a/src/tools/clangbackend/source/clangdocumentsuspenderresumer.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocument.h"
-#include "clangjobrequest.h"
-
-#include <vector>
-
-namespace ClangBackEnd {
-
-class SuspendResumeJobsEntry {
-public:
- SuspendResumeJobsEntry() = default;
- SuspendResumeJobsEntry(const Document &document,
- JobRequest::Type jobRequestType,
- PreferredTranslationUnit preferredTranslationUnit)
- : document(document)
- , jobRequestType(jobRequestType)
- , preferredTranslationUnit(preferredTranslationUnit)
- {
- }
-
- Document document;
- JobRequest::Type jobRequestType = JobRequest::Type::SuspendDocument;
- PreferredTranslationUnit preferredTranslationUnit = PreferredTranslationUnit::RecentlyParsed;
-};
-using SuspendResumeJobs = QVector<SuspendResumeJobsEntry>;
-
-SuspendResumeJobs createSuspendResumeJobs(const std::vector<Document> &documents,
- int customHotDocumentCounts = -1);
-
-// for tests
-void categorizeHotColdDocuments(int hotDocumentsSize,
- const std::vector<Document> &inDocuments,
- std::vector<Document> &hotDocuments,
- std::vector<Document> &coldDocuments);
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangexceptions.cpp b/src/tools/clangbackend/source/clangexceptions.cpp
deleted file mode 100644
index b23304e6cba..00000000000
--- a/src/tools/clangbackend/source/clangexceptions.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangexceptions.h"
-
-namespace ClangBackEnd {
-
-const char *ClangBaseException::what() const noexcept
-{
- return m_info.constData();
-}
-
-DocumentAlreadyExistsException::DocumentAlreadyExistsException(const Utf8String &filePath)
-{
- m_info += Utf8StringLiteral("Document '")
- + filePath
- + Utf8StringLiteral("' already exists!");
-}
-
-DocumentDoesNotExistException::DocumentDoesNotExistException(const Utf8String &filePath)
-{
- m_info += Utf8StringLiteral("Document '")
- + filePath
- + Utf8StringLiteral("' does not exist!");
-}
-
-DocumentFileDoesNotExistException::DocumentFileDoesNotExistException(
- const Utf8String &filePath)
-{
- m_info += Utf8StringLiteral("File ")
- + filePath
- + Utf8StringLiteral(" does not exist in file system!");
-}
-
-DocumentIsNullException::DocumentIsNullException()
-{
- m_info = Utf8String::fromUtf8("Tried to access a null Document!");
-}
-
-DocumentProcessorAlreadyExists::DocumentProcessorAlreadyExists(const Utf8String &filePath)
-{
- m_info = Utf8StringLiteral("Document processor for file '")
- + filePath
- + Utf8StringLiteral("' already exists!");
-}
-
-DocumentProcessorDoesNotExist::DocumentProcessorDoesNotExist(const Utf8String &filePath)
-{
- m_info = Utf8StringLiteral("Document processor for file '")
- + filePath
- + Utf8StringLiteral("' does not exist!");
-}
-
-TranslationUnitDoesNotExist::TranslationUnitDoesNotExist(const Utf8String &filePath)
-{
- m_info += Utf8StringLiteral("TranslationUnit for file '")
- + filePath
- + Utf8StringLiteral("' does not exist.");
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangexceptions.h b/src/tools/clangbackend/source/clangexceptions.h
deleted file mode 100644
index da94c96aefe..00000000000
--- a/src/tools/clangbackend/source/clangexceptions.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utf8stringvector.h>
-
-#include <clang-c/Index.h>
-
-#include <exception>
-
-namespace ClangBackEnd {
-
-class ClangBaseException : public std::exception
-{
-public:
- const char *what() const noexcept override;
-
-protected:
- Utf8String m_info;
-};
-
-class DocumentAlreadyExistsException : public ClangBaseException
-{
-public:
- DocumentAlreadyExistsException(const Utf8String &filePath);
-};
-
-class DocumentDoesNotExistException : public ClangBaseException
-{
-public:
- DocumentDoesNotExistException(const Utf8String &filePath);
-};
-
-class DocumentFileDoesNotExistException : public ClangBaseException
-{
-public:
- DocumentFileDoesNotExistException(const Utf8String &filePath);
-};
-
-class DocumentIsNullException : public ClangBaseException
-{
-public:
- DocumentIsNullException();
-};
-
-class DocumentProcessorAlreadyExists : public ClangBaseException
-{
-public:
- DocumentProcessorAlreadyExists(const Utf8String &filePath);
-};
-
-class DocumentProcessorDoesNotExist : public ClangBaseException
-{
-public:
- DocumentProcessorDoesNotExist(const Utf8String &filePath);
-};
-
-class TranslationUnitDoesNotExist : public ClangBaseException
-{
-public:
- TranslationUnitDoesNotExist(const Utf8String &filePath);
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfilepath.cpp b/src/tools/clangbackend/source/clangfilepath.cpp
deleted file mode 100644
index a5fc26b11d2..00000000000
--- a/src/tools/clangbackend/source/clangfilepath.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangfilepath.h"
-
-#include <utf8string.h>
-
-#include <QByteArray>
-
-#if defined(Q_OS_WIN)
-// Parameterized QDir::toNativeSeparators/-fromNativeSeparators for QByteArray
-static inline QByteArray replace(const QByteArray &pathName, char toReplace, char replacement)
-{
- int i = pathName.indexOf(toReplace);
- if (i != -1) {
- QByteArray n(pathName);
-
- char * const data = n.data();
- data[i++] = replacement;
-
- for (; i < n.length(); ++i) {
- if (data[i] == toReplace)
- data[i] = replacement;
- }
-
- return n;
- }
-
- return pathName;
-}
-#endif
-
-static QByteArray fromNativeSeparatorsForQByteArray(const QByteArray &pathName)
-{
-#if defined(Q_OS_WIN)
- return replace(pathName, '\\', '/');
-#else
- return pathName;
-#endif
-}
-
-static QByteArray toNativeSeparatorsForQByteArray(const QByteArray &pathName)
-{
-#if defined(Q_OS_WIN)
- return replace(pathName, '/', '\\');
-#else
- return pathName;
-#endif
-}
-
-namespace ClangBackEnd {
-
-Utf8String FilePath::fromNativeSeparators(const Utf8String &pathName)
-{
- const QByteArray pathNameAsByteArray = pathName.toByteArray();
-
- return Utf8String::fromUtf8(fromNativeSeparatorsForQByteArray(pathNameAsByteArray));
-}
-
-Utf8String FilePath::toNativeSeparators(const Utf8String &pathName)
-{
- const QByteArray pathNameAsByteArray = pathName.toByteArray();
-
- return Utf8String::fromUtf8(toNativeSeparatorsForQByteArray(pathNameAsByteArray));
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfilepath.h b/src/tools/clangbackend/source/clangfilepath.h
deleted file mode 100644
index 014c0129ed9..00000000000
--- a/src/tools/clangbackend/source/clangfilepath.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-class Utf8String;
-
-namespace ClangBackEnd {
-
-class FilePath {
-public:
- static Utf8String fromNativeSeparators(const Utf8String &pathName);
- static Utf8String toNativeSeparators(const Utf8String &pathName);
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfilesystemwatcher.cpp b/src/tools/clangbackend/source/clangfilesystemwatcher.cpp
deleted file mode 100644
index bcd03fac61e..00000000000
--- a/src/tools/clangbackend/source/clangfilesystemwatcher.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangfilesystemwatcher.h"
-
-#include "clangdocuments.h"
-
-#include <utf8stringvector.h>
-
-#include <QFileInfo>
-#include <QStringList>
-
-#include <algorithm>
-#include <iterator>
-
-namespace ClangBackEnd {
-
-namespace {
-QStringList toStringList(const QSet<Utf8String> &files)
-{
- QStringList resultList;
- resultList.reserve(files.size());
-
- std::copy(files.cbegin(), files.cend(), std::back_inserter(resultList));
-
- return resultList;
-}
-
-QStringList filterExistingFiles(QStringList &&filePaths)
-{
- auto fileExists = [] (const QString &filePath) {
- return QFileInfo::exists(filePath);
- };
-
- auto startOfNonExistingFilePaths = std::partition(filePaths.begin(),
- filePaths.end(),
- fileExists);
-
- filePaths.erase(startOfNonExistingFilePaths, filePaths.end());
-
- return std::move(filePaths);
-}
-}
-
-ClangFileSystemWatcher::ClangFileSystemWatcher(Documents &documents)
- : documents(documents)
-{
- connect(&watcher,
- &QFileSystemWatcher::fileChanged,
- this,
- &ClangFileSystemWatcher::updateDocumentsWithChangedDependencies);
-}
-
-void ClangFileSystemWatcher::addFiles(const QSet<Utf8String> &filePaths)
-{
- const auto existingFiles = filterExistingFiles(toStringList(filePaths));
-
- if (!existingFiles.isEmpty())
- watcher.addPaths(existingFiles);
-}
-
-void ClangFileSystemWatcher::updateDocumentsWithChangedDependencies(const QString &filePath)
-{
- documents.updateDocumentsWithChangedDependency(filePath);
-
- emit fileChanged(filePath);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfilesystemwatcher.h b/src/tools/clangbackend/source/clangfilesystemwatcher.h
deleted file mode 100644
index 549870eab00..00000000000
--- a/src/tools/clangbackend/source/clangfilesystemwatcher.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QFileSystemWatcher>
-#include <QSet>
-
-class Utf8String;
-
-namespace ClangBackEnd {
-
-class Documents;
-
-class ClangFileSystemWatcher : public QObject
-{
- Q_OBJECT
-
-public:
- ClangFileSystemWatcher(Documents &documents);
-
- void addFiles(const QSet<Utf8String> &filePaths);
-
-signals:
- void fileChanged(const Utf8String &filePath);
-
-private:
- void updateDocumentsWithChangedDependencies(const QString &filePath);
-
-private:
- QFileSystemWatcher watcher;
- Documents &documents;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfollowsymbol.cpp b/src/tools/clangbackend/source/clangfollowsymbol.cpp
deleted file mode 100644
index 81aaeec5c89..00000000000
--- a/src/tools/clangbackend/source/clangfollowsymbol.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangfollowsymbol.h"
-#include "clangfollowsymboljob.h"
-#include "commandlinearguments.h"
-#include "cursor.h"
-#include "clangstring.h"
-#include "sourcerange.h"
-#include "token.h"
-#include "clangsupportdebugutils.h"
-
-#include <utils/qtcassert.h>
-
-#include <future>
-
-namespace ClangBackEnd {
-
-static SourceRange getOperatorRange(const Tokens &tokens,
- std::vector<Token>::const_iterator currentToken)
-{
- const SourceLocation start = currentToken->location();
- currentToken += 2;
- while (currentToken != tokens.cend() && !(currentToken->spelling() == "("))
- ++currentToken;
-
- return SourceRange(start, currentToken->location());
-}
-
-static SourceRangeContainer extractMatchingTokenRange(const Cursor &cursor,
- const Utf8String &tokenStr)
-{
- Tokens tokens(cursor.sourceRange());
- for (auto it = tokens.cbegin(); it != tokens.cend(); ++it) {
- const Token &currentToken = *it;
- if (!(tokenStr == currentToken.spelling()))
- continue;
-
- if (cursor.isFunctionLike() || cursor.isConstructorOrDestructor()) {
- if (tokenStr == "operator")
- return getOperatorRange(tokens, it);
-
- auto nextIt = it + 1;
- if (nextIt == tokens.cend() || !(nextIt->spelling() == "("))
- continue;
- }
- return currentToken.extent();
- }
- return SourceRangeContainer();
-}
-
-FollowSymbolResult FollowSymbol::followSymbol(CXTranslationUnit tu,
- const Cursor &fullCursor,
- uint line,
- uint column)
-{
- Tokens tokens(fullCursor.sourceRange());
-
- if (!tokens.size()) {
- const Cursor tuCursor(clang_getTranslationUnitCursor(tu));
- tokens = Tokens(tuCursor.sourceRange());
- }
-
- if (!tokens.size())
- return SourceRangeContainer();
-
- std::vector<Cursor> cursors = tokens.annotate();
- const int tokenIndex = tokens.getTokenIndex(tu, line, column);
- QTC_ASSERT(tokenIndex >= 0, return SourceRangeContainer());
-
- const Utf8String tokenSpelling = tokens[tokenIndex].spelling();
- if (tokenSpelling.isEmpty())
- return SourceRangeContainer();
-
- Cursor cursor{cursors[tokenIndex]};
- if (cursor.kind() == CXCursor_CXXThisExpr && tokenSpelling != "this") { // QTCREATORBUG-25342
- cursor.semanticParent().visit([&cursor](CXCursor current, CXCursor parent) {
- if (current == cursor && parent.kind == CXCursor_MemberRefExpr
- && cursor.sourceLocation() == Cursor(parent).sourceLocation()) {
- cursor = parent;
- return CXChildVisit_Break;
- }
- return CXChildVisit_Recurse;
- });
- }
-
- if (cursor.kind() == CXCursor_InclusionDirective) {
- CXFile file = clang_getIncludedFile(cursors[tokenIndex].cx());
- const ClangString filename(clang_getFileName(file));
- const SourceLocation loc(tu, clang_getLocation(tu, file, 1, 1));
- FollowSymbolResult result;
- result.range = SourceRangeContainer(SourceRange(loc, loc));
- // CLANG-UPGRADE-CHECK: Remove if we don't use empty generated ui_* headers anymore.
- if (Utf8String(filename).contains("ui_"))
- result.isResultOnlyForFallBack = true;
- return result;
- }
-
- // For definitions we can always find a declaration in current TU
- if (cursor.isDefinition()) {
- if (tokenSpelling == "auto") {
- Type type = cursor.type().pointeeType();
- if (!type.isValid())
- type = cursor.type();
- const Cursor declCursor = type.declaration();
- return extractMatchingTokenRange(declCursor, declCursor.spelling());
- }
-
- const Cursor declCursor = cursor.canonical();
- FollowSymbolResult result;
- result.range = extractMatchingTokenRange(declCursor, tokenSpelling);
- result.isResultOnlyForFallBack = cursor.isFunctionLike() && declCursor == cursor;
- return result;
- }
-
- if (!cursor.isDeclaration()) {
- // This is the symbol usage
- // We want to return definition
- cursor = cursor.referenced();
- if (cursor.isNull())
- return SourceRangeContainer();
-
- FollowSymbolResult result;
- // We can't find definition in this TU or it's a virtual method call
- if (!cursor.isDefinition() || cursor.isVirtualMethod())
- result.isResultOnlyForFallBack = true;
-
- result.range = extractMatchingTokenRange(cursor, tokenSpelling);
- return result;
- }
-
- const bool isFunction = cursor.isFunctionLike();
- cursor = cursor.definition();
- // If we are able to find a definition in current TU
- if (!cursor.isNull())
- return extractMatchingTokenRange(cursor, tokenSpelling);
-
- return FollowSymbolResult({}, isFunction);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfollowsymbol.h b/src/tools/clangbackend/source/clangfollowsymbol.h
deleted file mode 100644
index 7c5469ef665..00000000000
--- a/src/tools/clangbackend/source/clangfollowsymbol.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QVector>
-
-#include <clang-c/Index.h>
-
-class Utf8String;
-
-namespace ClangBackEnd {
-
-class CommandLineArguments;
-class Cursor;
-class FollowSymbolResult;
-class SourceRangeContainer;
-
-class FollowSymbol
-{
-public:
- static FollowSymbolResult followSymbol(CXTranslationUnit tu,
- const Cursor &fullCursor,
- uint line,
- uint column);
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfollowsymboljob.cpp b/src/tools/clangbackend/source/clangfollowsymboljob.cpp
deleted file mode 100644
index c7ac629f800..00000000000
--- a/src/tools/clangbackend/source/clangfollowsymboljob.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangfollowsymboljob.h"
-
-#include <clangsupport/clangsupportdebugutils.h>
-#include <clangsupport/followsymbolmessage.h>
-#include <clangsupport/clangcodemodelclientinterface.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-IAsyncJob::AsyncPrepareResult FollowSymbolJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestFollowSymbol,
- return AsyncPrepareResult());
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- const TranslationUnit translationUnit = *m_translationUnit;
- const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
-
- const quint32 line = jobRequest.line;
- const quint32 column = jobRequest.column;
- setRunner([translationUnit, line, column]() {
- TIME_SCOPE_DURATION("FollowSymbolJobRunner");
- return translationUnit.followSymbol(line, column);
- });
-
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void FollowSymbolJob::finalizeAsyncRun()
-{
- if (!context().isOutdated()) {
- const AsyncResult result = asyncResult();
-
- const FollowSymbolMessage message(m_pinnedFileContainer,
- result,
- context().jobRequest.ticketNumber);
- context().client->followSymbol(message);
- }
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfollowsymboljob.h b/src/tools/clangbackend/source/clangfollowsymboljob.h
deleted file mode 100644
index 5e625f97d49..00000000000
--- a/src/tools/clangbackend/source/clangfollowsymboljob.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentjob.h"
-
-#include <clangsupport/followsymbolmessage.h>
-#include <clangsupport/sourcerangecontainer.h>
-
-namespace ClangBackEnd {
-
-class FollowSymbolJob : public DocumentJob<FollowSymbolResult>
-{
-public:
- using AsyncResult = FollowSymbolResult;
-
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-};
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangiasyncjob.cpp b/src/tools/clangbackend/source/clangiasyncjob.cpp
deleted file mode 100644
index 2ce218e99e6..00000000000
--- a/src/tools/clangbackend/source/clangiasyncjob.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangiasyncjob.h"
-
-Q_LOGGING_CATEGORY(jobsLog, "qtc.clangbackend.jobs", QtWarningMsg);
-
-namespace ClangBackEnd {
-
-IAsyncJob::IAsyncJob()
- : m_context(JobContext())
-{
-}
-
-IAsyncJob::~IAsyncJob()
-{
-}
-
-JobContext IAsyncJob::context() const
-{
- return m_context;
-}
-
-void IAsyncJob::setContext(const JobContext &context)
-{
- m_context = context;
-}
-
-IAsyncJob::FinishedHandler IAsyncJob::finishedHandler() const
-{
- return m_finishedHandler;
-}
-
-void IAsyncJob::setFinishedHandler(const IAsyncJob::FinishedHandler &finishedHandler)
-{
- m_finishedHandler = finishedHandler;
-}
-
-bool IAsyncJob::isFinished() const
-{
- return m_isFinished;
-}
-
-void IAsyncJob::setIsFinished(bool isFinished)
-{
- m_isFinished = isFinished;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangiasyncjob.h b/src/tools/clangbackend/source/clangiasyncjob.h
deleted file mode 100644
index 9d17e874f1f..00000000000
--- a/src/tools/clangbackend/source/clangiasyncjob.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangjobcontext.h"
-
-#include <QFuture>
-#include <QLoggingCategory>
-
-#include <functional>
-
-Q_DECLARE_LOGGING_CATEGORY(jobsLog);
-#define qCDebugJobs() qCDebug(jobsLog) << "[" << m_logTag << "]"
-
-namespace ClangBackEnd {
-
-class IAsyncJob
-{
-public:
- struct AsyncPrepareResult {
- operator bool() const { return !translationUnitId.isEmpty(); }
- Utf8String translationUnitId;
- };
-
-public:
- IAsyncJob();
- virtual ~IAsyncJob();
-
- JobContext context() const;
- void setContext(const JobContext &context);
-
- using FinishedHandler = std::function<void(IAsyncJob *job)>;
- FinishedHandler finishedHandler() const;
- void setFinishedHandler(const FinishedHandler &finishedHandler);
-
- virtual AsyncPrepareResult prepareAsyncRun() = 0;
- virtual QFuture<void> runAsync() = 0;
- virtual void finalizeAsyncRun() = 0;
-
- virtual void preventFinalization() = 0;
-
-public: // for tests
- bool isFinished() const;
- void setIsFinished(bool isFinished);
-
-private:
- bool m_isFinished = false;
- FinishedHandler m_finishedHandler;
- JobContext m_context;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangjobcontext.cpp b/src/tools/clangbackend/source/clangjobcontext.cpp
deleted file mode 100644
index 59f0c1001e7..00000000000
--- a/src/tools/clangbackend/source/clangjobcontext.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangiasyncjob.h"
-
-#include "clangdocuments.h"
-
-namespace ClangBackEnd {
-
-JobContext::JobContext(const JobRequest &jobRequest,
- Documents *documents,
- UnsavedFiles *unsavedFiles,
- ClangCodeModelClientInterface *clientInterface)
- : jobRequest(jobRequest)
- , documents(documents)
- , unsavedFiles(unsavedFiles)
- , client(clientInterface)
-{
-}
-
-Document JobContext::documentForJobRequest() const
-{
- return documents->document(jobRequest.filePath);
-}
-
-bool JobContext::isOutdated() const
-{
- return !isDocumentOpen() || documentRevisionChanged();
-}
-
-bool JobContext::isDocumentOpen() const
-{
- const bool hasDocument = documents->hasDocument(jobRequest.filePath);
- if (!hasDocument)
- qCDebug(jobsLog) << "Document already closed for results of" << jobRequest;
-
- return hasDocument;
-}
-
-bool JobContext::documentRevisionChanged() const
-{
- const Document &document = documents->document(jobRequest.filePath);
- const bool revisionChanged = document.documentRevision() != jobRequest.documentRevision;
-
- if (revisionChanged)
- qCDebug(jobsLog) << "Document revision changed for results of" << jobRequest;
-
- return revisionChanged;
-}
-
-} // ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangjobcontext.h b/src/tools/clangbackend/source/clangjobcontext.h
deleted file mode 100644
index 629d8320bd3..00000000000
--- a/src/tools/clangbackend/source/clangjobcontext.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangjobrequest.h"
-
-namespace ClangBackEnd {
-
-class ClangCodeModelClientInterface;
-class Document;
-class Documents;
-class UnsavedFiles;
-
-class JobContext
-{
-public:
- JobContext() = default;
- JobContext(const JobRequest &jobRequest,
- Documents *documents,
- UnsavedFiles *unsavedFiles,
- ClangCodeModelClientInterface *client);
-
- Document documentForJobRequest() const;
-
- bool isOutdated() const;
- bool isDocumentOpen() const;
- bool documentRevisionChanged() const;
-
-public:
- JobRequest jobRequest;
- Documents *documents = nullptr;
- UnsavedFiles *unsavedFiles = nullptr;
- ClangCodeModelClientInterface *client = nullptr;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangjobqueue.cpp b/src/tools/clangbackend/source/clangjobqueue.cpp
deleted file mode 100644
index 1be56b3b6ce..00000000000
--- a/src/tools/clangbackend/source/clangjobqueue.cpp
+++ /dev/null
@@ -1,313 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangiasyncjob.h"
-#include "clangjobqueue.h"
-#include "clangdocument.h"
-#include "clangdocuments.h"
-#include "clangtranslationunits.h"
-#include "unsavedfiles.h"
-
-#include <utils/algorithm.h>
-
-namespace ClangBackEnd {
-
-JobQueue::JobQueue(Documents &documents, const Utf8String &logTag)
- : m_documents(documents)
- , m_logTag(logTag)
-{
-}
-
-bool JobQueue::add(const JobRequest &job)
-{
- QString notAddableReason;
- if (isJobRequestAddable(job, notAddableReason)) {
- qCDebugJobs() << "Adding" << job;
- m_queue.append(job);
- return true;
- } else {
- qCDebugJobs() << "Not adding" << job << notAddableReason;
- cancelJobRequest(job);
- return false;
- }
-}
-
-int JobQueue::size() const
-{
- return m_queue.size();
-}
-
-JobRequests JobQueue::processQueue()
-{
- removeExpiredRequests();
- prioritizeRequests();
- const JobRequests jobsToRun = takeJobRequestsToRunNow();
-
- return jobsToRun;
-}
-
-void JobQueue::removeExpiredRequests()
-{
- JobRequests cleanedRequests;
-
- foreach (const JobRequest &jobRequest, m_queue) {
- try {
- QString expirationReason;
- if (isJobRequestExpired(jobRequest, expirationReason)) {
- qCDebugJobs() << "Expired:" << jobRequest << expirationReason;
- cancelJobRequest(jobRequest);
- } else {
- cleanedRequests.append(jobRequest);
- }
- } catch (const std::exception &exception) {
- qWarning() << "Error in Jobs::removeOutDatedRequests for"
- << jobRequest << ":" << exception.what();
- }
- }
-
- m_queue = cleanedRequests;
-}
-
-bool JobQueue::isJobRequestAddable(const JobRequest &jobRequest, QString &notAddableReason)
-{
- if (m_queue.contains(jobRequest)) {
- notAddableReason = "duplicate request in queue";
- return false;
- }
-
- if (isJobRunningForJobRequest(jobRequest)) {
- notAddableReason = "duplicate request for already running job";
- return false;
- }
-
- if (!m_documents.hasDocument(jobRequest.filePath)) {
- notAddableReason = "document already closed";
- return false;
- }
-
- const Document document = m_documents.document(jobRequest.filePath);
- if (!document.isIntact()) {
- notAddableReason = "document not intact";
- return false;
- }
-
- return true;
-}
-
-bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest, QString &expirationReason)
-{
- const JobRequest::ExpirationConditions conditions = jobRequest.expirationConditions;
- const UnsavedFiles unsavedFiles = m_documents.unsavedFiles();
- using Condition = JobRequest::ExpirationCondition;
-
- if (conditions.testFlag(Condition::UnsavedFilesChanged)) {
- if (jobRequest.unsavedFilesChangeTimePoint != unsavedFiles.lastChangeTimePoint()) {
- expirationReason = "outdated unsaved files";
- return true;
- }
- }
-
- if (conditions.testFlag(Condition::DocumentClosed)) {
- if (!m_documents.hasDocument(jobRequest.filePath)) {
- expirationReason = "document already closed";
- return true;
- }
-
- const Document document
- = m_documents.document(jobRequest.filePath);
- if (!document.isIntact()) {
- expirationReason = "document not intact";
- return true;
- }
-
- if (conditions.testFlag(Condition::DocumentRevisionChanged)) {
- if (document.documentRevision() > jobRequest.documentRevision) {
- expirationReason = "changed document revision";
- return true;
- }
- }
- }
-
- return false;
-}
-
-static int priority(const Document &document)
-{
- int thePriority = 0;
-
- if (document.isUsedByCurrentEditor())
- thePriority += 1000;
-
- if (document.isVisibleInEditor())
- thePriority += 100;
-
- return thePriority;
-}
-
-void JobQueue::prioritizeRequests()
-{
- const auto lessThan = [this] (const JobRequest &r1, const JobRequest &r2) {
- // TODO: Getting the TU is O(n) currently, so this might become expensive for large n.
- const Document &t1 = m_documents.document(r1.filePath);
- const Document &t2 = m_documents.document(r2.filePath);
-
- return priority(t1) > priority(t2);
- };
-
- std::stable_sort(m_queue.begin(), m_queue.end(), lessThan);
-}
-
-void JobQueue::cancelJobRequest(const JobRequest &jobRequest)
-{
- if (m_cancelJobRequest)
- m_cancelJobRequest(jobRequest);
-}
-
-bool JobQueue::areRunConditionsMet(const JobRequest &request, const Document &document) const
-{
- using Condition = JobRequest::RunCondition;
- const JobRequest::RunConditions conditions = request.runConditions;
-
- if (conditions.testFlag(Condition::DocumentSuspended) && !document.isSuspended()) {
- qCDebugJobs() << "Not choosing due to unsuspended document:" << request;
- return false;
- }
-
- if (conditions.testFlag(Condition::DocumentUnsuspended) && document.isSuspended()) {
- qCDebugJobs() << "Not choosing due to suspended document:" << request;
- return false;
- }
-
- if (conditions.testFlag(Condition::DocumentVisible) && !document.isVisibleInEditor()) {
- qCDebugJobs() << "Not choosing due to invisible document:" << request;
- return false;
- }
-
- if (conditions.testFlag(Condition::DocumentNotVisible) && document.isVisibleInEditor()) {
- qCDebugJobs() << "Not choosing due to visible document:" << request;
- return false;
- }
-
- if (conditions.testFlag(Condition::CurrentDocumentRevision)) {
- if (document.isDirty()) {
- // TODO: If the document is dirty due to a project update,
- // references are processes later than ideal.
- qCDebugJobs() << "Not choosing due to dirty document:" << request;
- return false;
- }
-
- if (request.documentRevision != document.documentRevision()) {
- qCDebugJobs() << "Not choosing due to revision mismatch:" << request;
- return false;
- }
- }
-
- if (conditions.testFlag(Condition::DocumentParsed)
- && !document.translationUnits().hasParsedTranslationUnit()) {
- qCDebugJobs() << "Not choosing due to not yet parsed translation unit:" << request;
- return false;
- }
-
- return true;
-}
-
-JobRequests JobQueue::takeJobRequestsToRunNow()
-{
- JobRequests jobsToRun;
- using TranslationUnitIds = QSet<Utf8String>;
- TranslationUnitIds translationUnitsScheduledForThisRun;
-
- for (int pos = 0; pos < m_queue.size(); ++pos) {
- const JobRequest &request = m_queue.at(pos);
-
- try {
- const Document &document = m_documents.document(request.filePath);
-
- if (!areRunConditionsMet(request, document))
- continue;
-
- const Utf8String id = document.translationUnit(request.preferredTranslationUnit).id();
- if (translationUnitsScheduledForThisRun.contains(id))
- continue;
-
- if (isJobRunningForTranslationUnit(id))
- continue;
-
- translationUnitsScheduledForThisRun.insert(id);
- jobsToRun += request;
- m_queue.removeAt(pos--);
- } catch (const std::exception &exception) {
- qWarning() << "Error in Jobs::takeJobRequestsToRunNow for"
- << request << ":" << exception.what();
- }
- }
-
- return jobsToRun;
-}
-
-bool JobQueue::isJobRunningForTranslationUnit(const Utf8String &translationUnitId)
-{
- if (m_isJobRunningForTranslationUnitHandler)
- return m_isJobRunningForTranslationUnitHandler(translationUnitId);
-
- return false;
-}
-
-bool JobQueue::isJobRunningForJobRequest(const JobRequest &jobRequest)
-{
- if (m_isJobRunningForJobRequestHandler)
- return m_isJobRunningForJobRequestHandler(jobRequest);
-
- return false;
-}
-
-void JobQueue::setIsJobRunningForTranslationUnitHandler(
- const IsJobRunningForTranslationUnitHandler &isJobRunningHandler)
-{
- m_isJobRunningForTranslationUnitHandler = isJobRunningHandler;
-}
-
-void JobQueue::setIsJobRunningForJobRequestHandler(
- const JobQueue::IsJobRunningForJobRequestHandler &isJobRunningHandler)
-{
- m_isJobRunningForJobRequestHandler = isJobRunningHandler;
-}
-
-void JobQueue::setCancelJobRequest(const JobQueue::CancelJobRequest &cancelJobRequest)
-{
- m_cancelJobRequest = cancelJobRequest;
-}
-
-JobRequests &JobQueue::queue()
-{
- return m_queue;
-}
-
-const JobRequests &JobQueue::queue() const
-{
- return m_queue;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangjobqueue.h b/src/tools/clangbackend/source/clangjobqueue.h
deleted file mode 100644
index 2e0effaf9d1..00000000000
--- a/src/tools/clangbackend/source/clangjobqueue.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangjobrequest.h"
-
-#include <functional>
-
-namespace ClangBackEnd {
-
-class Documents;
-
-class JobQueue
-{
-public:
- JobQueue(Documents &documents, const Utf8String &logTag = Utf8String());
-
- bool add(const JobRequest &job);
-
- JobRequests processQueue();
-
- using IsJobRunningForTranslationUnitHandler = std::function<bool(const Utf8String &)>;
- void setIsJobRunningForTranslationUnitHandler(
- const IsJobRunningForTranslationUnitHandler &isJobRunningHandler);
-
- using IsJobRunningForJobRequestHandler = std::function<bool(const JobRequest &)>;
- void setIsJobRunningForJobRequestHandler(
- const IsJobRunningForJobRequestHandler &isJobRunningHandler);
-
- using CancelJobRequest = std::function<void(const JobRequest &)>;
- void setCancelJobRequest(const CancelJobRequest &cancelJobRequest);
-
-public: // for tests
- JobRequests &queue();
- const JobRequests &queue() const;
- int size() const;
- void prioritizeRequests();
-
-private:
- bool areRunConditionsMet(const JobRequest &request, const Document &document) const;
- void cancelJobRequest(const JobRequest &jobRequest);
- bool isJobRunningForTranslationUnit(const Utf8String &translationUnitId);
- bool isJobRunningForJobRequest(const JobRequest &jobRequest);
- JobRequests takeJobRequestsToRunNow();
- void removeExpiredRequests();
- bool isJobRequestAddable(const JobRequest &jobRequest, QString &notAddableReason);
- bool isJobRequestExpired(const JobRequest &jobRequest, QString &expirationReason);
-
-private:
- Documents &m_documents;
- Utf8String m_logTag;
-
- IsJobRunningForTranslationUnitHandler m_isJobRunningForTranslationUnitHandler;
- IsJobRunningForJobRequestHandler m_isJobRunningForJobRequestHandler;
- CancelJobRequest m_cancelJobRequest;
-
- JobRequests m_queue;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangjobrequest.cpp b/src/tools/clangbackend/source/clangjobrequest.cpp
deleted file mode 100644
index bbf2f726e6d..00000000000
--- a/src/tools/clangbackend/source/clangjobrequest.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangjobrequest.h"
-
-#include "clangcompletecodejob.h"
-#include "clangfollowsymboljob.h"
-#include "clangparsesupportivetranslationunitjob.h"
-#include "clangrequestannotationsjob.h"
-#include "clangrequestreferencesjob.h"
-#include "clangrequesttooltipjob.h"
-#include "clangresumedocumentjob.h"
-#include "clangsuspenddocumentjob.h"
-#include "clangupdateannotationsjob.h"
-#include "clangupdateextraannotationsjob.h"
-
-#include <clangsupport/clangcodemodelclientinterface.h>
-#include <clangsupport/completionsmessage.h>
-#include <clangsupport/followsymbolmessage.h>
-#include <clangsupport/referencesmessage.h>
-#include <clangsupport/tooltipmessage.h>
-
-#include <utils/qtcassert.h>
-
-#include <QFileInfo>
-
-#include <ostream>
-
-namespace ClangBackEnd {
-
-#define RETURN_TEXT_FOR_CASE(enumValue) case JobRequest::Type::enumValue: return #enumValue
-static const char *JobRequestTypeToText(JobRequest::Type type)
-{
- switch (type) {
- RETURN_TEXT_FOR_CASE(Invalid);
- RETURN_TEXT_FOR_CASE(UpdateAnnotations);
- RETURN_TEXT_FOR_CASE(UpdateExtraAnnotations);
- RETURN_TEXT_FOR_CASE(ParseSupportiveTranslationUnit);
- RETURN_TEXT_FOR_CASE(RequestCompletions);
- RETURN_TEXT_FOR_CASE(RequestAnnotations);
- RETURN_TEXT_FOR_CASE(RequestReferences);
- RETURN_TEXT_FOR_CASE(RequestFollowSymbol);
- RETURN_TEXT_FOR_CASE(RequestToolTip);
- RETURN_TEXT_FOR_CASE(SuspendDocument);
- RETURN_TEXT_FOR_CASE(ResumeDocument);
- }
-
- return "UnhandledJobRequestType";
-}
-#undef RETURN_TEXT_FOR_CASE
-
-#define RETURN_TEXT_FOR_CASE(enumValue) case PreferredTranslationUnit::enumValue: return #enumValue
-const char *preferredTranslationUnitToText(PreferredTranslationUnit type)
-{
- switch (type) {
- RETURN_TEXT_FOR_CASE(RecentlyParsed);
- RETURN_TEXT_FOR_CASE(PreviouslyParsed);
- RETURN_TEXT_FOR_CASE(LastUninitialized);
- }
-
- return "UnhandledPreferredTranslationUnitType";
-}
-#undef RETURN_TEXT_FOR_CASE
-
-QDebug operator<<(QDebug debug, JobRequest::Type type)
-{
- debug << JobRequestTypeToText(type);
-
- return debug;
-}
-
-std::ostream &operator<<(std::ostream &os, JobRequest::Type type)
-{
- return os << JobRequestTypeToText(type);
-}
-
-std::ostream &operator<<(std::ostream &os, PreferredTranslationUnit preferredTranslationUnit)
-{
- return os << preferredTranslationUnitToText(preferredTranslationUnit);
-}
-
-QDebug operator<<(QDebug debug, const JobRequest &jobRequest)
-{
- debug.nospace() << "Job<"
- << jobRequest.id
- << ","
- << QFileInfo(jobRequest.filePath).fileName()
- << ","
- << JobRequestTypeToText(jobRequest.type)
- << ","
- << preferredTranslationUnitToText(jobRequest.preferredTranslationUnit)
- << ">";
-
- return debug.space();
-}
-
-static JobRequest::ExpirationConditions expirationConditionsForType(JobRequest::Type type)
-{
- using Type = JobRequest::Type;
- using Condition = JobRequest::ExpirationCondition;
- using Conditions = JobRequest::ExpirationConditions;
-
- switch (type) {
- case Type::UpdateAnnotations:
- case Type::UpdateExtraAnnotations:
- return Conditions(Condition::AnythingChanged);
- case Type::RequestReferences:
- case Type::RequestAnnotations:
- case Type::RequestToolTip:
- case Type::RequestFollowSymbol:
- return Conditions(Condition::DocumentClosed)
- | Conditions(Condition::DocumentRevisionChanged);
- default:
- return Condition::DocumentClosed;
- }
-}
-
-static JobRequest::RunConditions conditionsForType(JobRequest::Type type)
-{
- using Type = JobRequest::Type;
- using Condition = JobRequest::RunCondition;
- using Conditions = JobRequest::RunConditions;
-
- if (type == Type::SuspendDocument) {
- return Conditions(Condition::DocumentUnsuspended)
- | Conditions(Condition::DocumentNotVisible);
- }
-
- if (type == Type::ResumeDocument) {
- return Conditions(Condition::DocumentSuspended)
- | Conditions(Condition::DocumentVisible);
- }
-
- Conditions conditions = Conditions(Condition::DocumentUnsuspended)
- | Conditions(Condition::DocumentVisible);
-
- if (type == Type::RequestReferences || type == Type::RequestFollowSymbol
- || type == Type::RequestToolTip || type == Type::UpdateExtraAnnotations) {
- conditions |= Condition::CurrentDocumentRevision;
- }
-
- if (type != Type::UpdateAnnotations && type != Type::ParseSupportiveTranslationUnit)
- conditions |= Condition::DocumentParsed;
-
- return conditions;
-}
-
-bool JobRequest::isTakeOverable() const
-{
- // When new project information comes in and there are unprocessed jobs
- // in the queue, we need to decide what to do with them.
-
- switch (type) {
- // Never discard these as the client side might wait for a response.
- case Type::RequestCompletions:
- case Type::RequestReferences:
- case Type::RequestFollowSymbol:
- case Type::RequestToolTip:
- return true;
-
- // Discard this one as UpdateAnnotations will have the same effect.
- case Type::RequestAnnotations:
-
- // Discard Suspend because the document will be cleared anyway.
- // Discard Resume because a (re)parse will happen on demand.
- case Type::SuspendDocument:
- case Type::ResumeDocument:
-
- // Discard these as they are initial jobs that will be recreated on demand
- // anyway.
- case Type::UpdateAnnotations:
- case Type::UpdateExtraAnnotations:
-
- // Discard these as they only make sense in a row. Avoid splitting them up.
- case Type::ParseSupportiveTranslationUnit:
-
- case Type::Invalid:
- return false;
- }
-
- return false;
-}
-
-JobRequest::JobRequest(Type type)
-{
- static quint64 idCounter = 0;
-
- id = ++idCounter;
- this->type = type;
- runConditions = conditionsForType(type);
- expirationConditions = expirationConditionsForType(type);
-}
-
-IAsyncJob *JobRequest::createJob() const
-{
- switch (type) {
- case JobRequest::Type::Invalid:
- QTC_CHECK(false && "Cannot create job for invalid job request.");
- break;
- case JobRequest::Type::UpdateAnnotations:
- return new UpdateAnnotationsJob();
- case JobRequest::Type::UpdateExtraAnnotations:
- return new UpdateExtraAnnotationsJob();
- case JobRequest::Type::ParseSupportiveTranslationUnit:
- return new ParseSupportiveTranslationUnitJob();
- case JobRequest::Type::RequestCompletions:
- return new CompleteCodeJob();
- case JobRequest::Type::RequestAnnotations:
- return new RequestAnnotationsJob();
- case JobRequest::Type::RequestReferences:
- return new RequestReferencesJob();
- case JobRequest::Type::RequestToolTip:
- return new RequestToolTipJob();
- case JobRequest::Type::RequestFollowSymbol:
- return new FollowSymbolJob();
- case JobRequest::Type::SuspendDocument:
- return new SuspendDocumentJob();
- case JobRequest::Type::ResumeDocument:
- return new ResumeDocumentJob();
- }
-
- return nullptr;
-}
-
-void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const
-{
- // If a job request with a ticket number is cancelled, the plugin side
- // must get back some results in order to clean up the state there.
-
- switch (type) {
- case JobRequest::Type::Invalid:
- case JobRequest::Type::UpdateAnnotations:
- case JobRequest::Type::UpdateExtraAnnotations:
- case JobRequest::Type::ParseSupportiveTranslationUnit:
- case JobRequest::Type::RequestAnnotations:
- case JobRequest::Type::SuspendDocument:
- case JobRequest::Type::ResumeDocument:
- break;
- case JobRequest::Type::RequestReferences:
- client.references(ReferencesMessage(FileContainer(),
- QVector<SourceRangeContainer>(),
- false,
- ticketNumber));
- break;
- case JobRequest::Type::RequestToolTip:
- client.tooltip(ToolTipMessage(FileContainer(), ToolTipInfo(), ticketNumber));
- break;
- case JobRequest::Type::RequestCompletions:
- client.completions(CompletionsMessage(CodeCompletions(), ticketNumber));
- break;
- case JobRequest::Type::RequestFollowSymbol:
- client.followSymbol(
- FollowSymbolMessage(FileContainer(), SourceRangeContainer(), ticketNumber));
- break;
- }
-}
-
-bool JobRequest::operator==(const JobRequest &other) const
-{
- return type == other.type
- && expirationConditions == other.expirationConditions
- && runConditions == other.runConditions
-
- && filePath == other.filePath
- && unsavedFilesChangeTimePoint == other.unsavedFilesChangeTimePoint
- && documentRevision == other.documentRevision
- && preferredTranslationUnit == other.preferredTranslationUnit
-
- && line == other.line
- && column == other.column
- && ticketNumber == other.ticketNumber;
-
- // Additional members that are not compared here explicitly are
- // supposed to depend on the already compared ones.
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangjobrequest.h b/src/tools/clangbackend/source/clangjobrequest.h
deleted file mode 100644
index fde2eca4dba..00000000000
--- a/src/tools/clangbackend/source/clangjobrequest.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangbackend_global.h"
-#include "clangclock.h"
-
-#include <utf8string.h>
-#include <utf8stringvector.h>
-
-#include <QFlags>
-#include <QDebug>
-#include <QVector>
-
-#include <functional>
-
-namespace ClangBackEnd {
-
-class ClangCodeModelClientInterface;
-class Document;
-class IAsyncJob;
-
-class JobRequest
-{
-public:
- enum class Type {
- Invalid,
-
- UpdateAnnotations,
- UpdateExtraAnnotations,
-
- ParseSupportiveTranslationUnit,
-
- RequestCompletions,
- RequestAnnotations,
- RequestReferences,
- RequestFollowSymbol,
- RequestToolTip,
-
- SuspendDocument,
- ResumeDocument,
- };
-
- enum class RunCondition {
- NoCondition = 1 << 0,
- DocumentVisible = 1 << 1,
- DocumentNotVisible = 1 << 2,
- DocumentSuspended = 1 << 3,
- DocumentUnsuspended = 1 << 4,
- DocumentParsed = 1 << 5,
- CurrentDocumentRevision = 1 << 6,
- };
- Q_DECLARE_FLAGS(RunConditions, RunCondition)
-
- enum class ExpirationCondition {
- Never = 1 << 0,
-
- DocumentClosed = 1 << 1,
- DocumentRevisionChanged = 1 << 2, // Only effective if DocumentIsClosed is also set
- UnsavedFilesChanged = 1 << 3,
-
- AnythingChanged = DocumentClosed
- | DocumentRevisionChanged
- | UnsavedFilesChanged,
- };
- Q_DECLARE_FLAGS(ExpirationConditions, ExpirationCondition)
-
-public:
- JobRequest(Type type = Type::Invalid);
-
- IAsyncJob *createJob() const;
- void cancelJob(ClangCodeModelClientInterface &client) const;
- bool isTakeOverable() const;
-
- bool operator==(const JobRequest &other) const;
- friend QDebug operator<<(QDebug debug, const JobRequest &jobRequest);
-
-public:
- quint64 id = 0;
- Type type;
- ExpirationConditions expirationConditions;
- RunConditions runConditions;
-
- // General
- Utf8String filePath;
- TimePoint unsavedFilesChangeTimePoint;
- uint documentRevision = 0;
- PreferredTranslationUnit preferredTranslationUnit = PreferredTranslationUnit::RecentlyParsed;
-
- // Specific to some jobs
- quint32 line = 0;
- quint32 column = 0;
- qint32 funcNameStartLine = -1;
- qint32 funcNameStartColumn = -1;
- quint64 ticketNumber = 0;
- Utf8String textCodecName;
- bool localReferences = false;
-};
-
-using JobRequests = QVector<JobRequest>;
-
-std::ostream &operator<<(std::ostream &os, JobRequest::Type type);
-std::ostream &operator<<(std::ostream &os, PreferredTranslationUnit preferredTranslationUnit);
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangjobs.cpp b/src/tools/clangbackend/source/clangjobs.cpp
deleted file mode 100644
index 51b875f65f6..00000000000
--- a/src/tools/clangbackend/source/clangjobs.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangjobs.h"
-
-#include "clangdocument.h"
-#include "clangiasyncjob.h"
-
-#include <QDebug>
-#include <QLoggingCategory>
-
-#include <utils/algorithm.h>
-#include <utils/futuresynchronizer.h>
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-Jobs::Jobs(Documents &documents,
- UnsavedFiles &unsavedFiles,
- ClangCodeModelClientInterface &client,
- const Utf8String &logTag)
- : m_documents(documents)
- , m_unsavedFiles(unsavedFiles)
- , m_client(client)
- , m_logTag(logTag)
- , m_queue(documents, logTag)
-{
- m_queue.setIsJobRunningForTranslationUnitHandler([this](const Utf8String &translationUnitId) {
- return isJobRunningForTranslationUnit(translationUnitId);
- });
- m_queue.setIsJobRunningForJobRequestHandler([this](const JobRequest &jobRequest) {
- return isJobRunningForJobRequest(jobRequest);
- });
- m_queue.setCancelJobRequest([this](const JobRequest &jobRequest) {
- jobRequest.cancelJob(m_client);
- });
-}
-
-Jobs::~Jobs()
-{
- foreach (IAsyncJob *asyncJob, m_running.keys())
- asyncJob->preventFinalization();
-
- Utils::FutureSynchronizer waitForFinishedJobs;
- foreach (const RunningJob &runningJob, m_running.values())
- waitForFinishedJobs.addFuture(runningJob.future);
-
- foreach (IAsyncJob *asyncJob, m_running.keys())
- delete asyncJob;
-}
-
-JobRequest Jobs::createJobRequest(const Document &document,
- JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit) const
-{
- JobRequest jobRequest(type);
- jobRequest.filePath = document.filePath();
- jobRequest.unsavedFilesChangeTimePoint = m_unsavedFiles.lastChangeTimePoint();
- jobRequest.documentRevision = document.documentRevision();
- jobRequest.preferredTranslationUnit = preferredTranslationUnit;
-
- return jobRequest;
-}
-
-void Jobs::add(const JobRequest &job)
-{
- m_queue.add(job);
-}
-
-void Jobs::add(const Document &document,
- JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit)
-{
- const JobRequest jobRequest = createJobRequest(document, type, preferredTranslationUnit);
- m_queue.add(jobRequest);
-}
-
-JobRequests Jobs::process()
-{
- const JobRequests jobsToRun = m_queue.processQueue();
- const JobRequests jobsStarted = runJobs(jobsToRun);
-
- QTC_CHECK(jobsToRun.size() == jobsStarted.size());
-
- return jobsStarted;
-}
-
-JobRequests Jobs::stop()
-{
- // Take the queued jobs to prevent processing them.
- const JobRequests queuedJobs = queue();
- queue().clear();
-
- // Wait until currently running jobs finish.
- Utils::FutureSynchronizer waitForFinishedJobs;
- foreach (const RunningJob &runningJob, m_running.values())
- waitForFinishedJobs.addFuture(runningJob.future);
-
- return queuedJobs;
-}
-
-Jobs::JobFinishedCallback Jobs::finishedCallback() const
-{
- return m_jobFinishedCallback;
-}
-
-JobRequests Jobs::runJobs(const JobRequests &jobsRequests)
-{
- JobRequests jobsStarted;
-
- foreach (const JobRequest &jobRequest, jobsRequests) {
- if (runJob(jobRequest))
- jobsStarted += jobRequest;
- }
-
- return jobsStarted;
-}
-
-bool Jobs::runJob(const JobRequest &jobRequest)
-{
- IAsyncJob *asyncJob = jobRequest.createJob();
- QTC_ASSERT(asyncJob, return false);
-
- JobContext context(jobRequest, &m_documents, &m_unsavedFiles, &m_client);
- asyncJob->setContext(context);
-
- if (const IAsyncJob::AsyncPrepareResult prepareResult = asyncJob->prepareAsyncRun()) {
- qCDebugJobs() << "Running" << jobRequest
- << "with TranslationUnit" << prepareResult.translationUnitId;
-
- asyncJob->setFinishedHandler([this](IAsyncJob *asyncJob){ onJobFinished(asyncJob); });
- const QFuture<void> future = asyncJob->runAsync();
-
- const RunningJob runningJob{jobRequest, prepareResult.translationUnitId, future};
- m_running.insert(asyncJob, runningJob);
- return true;
- } else {
- qCDebugJobs() << "Preparation failed for " << jobRequest;
- delete asyncJob;
- }
-
- return false;
-}
-
-void Jobs::onJobFinished(IAsyncJob *asyncJob)
-{
- qCDebugJobs() << "Finishing" << asyncJob->context().jobRequest;
-
- if (m_jobFinishedCallback) {
- const RunningJob runningJob = m_running.value(asyncJob);
- if (m_jobFinishedCallback(runningJob, asyncJob))
- return;
- }
-
- m_running.remove(asyncJob);
- delete asyncJob;
-
- process();
-}
-
-Jobs::JobFinishedCallback Jobs::jobFinishedCallback() const
-{
- return m_jobFinishedCallback;
-}
-
-void Jobs::setJobFinishedCallback(const JobFinishedCallback &jobFinishedCallback)
-{
- m_jobFinishedCallback = jobFinishedCallback;
-}
-
-QList<Jobs::RunningJob> Jobs::runningJobs() const
-{
- return m_running.values();
-}
-
-JobRequests &Jobs::queue()
-{
- return m_queue.queue();
-}
-
-const JobRequests &Jobs::queue() const
-{
- return m_queue.queue();
-}
-
-bool Jobs::isJobRunningForTranslationUnit(const Utf8String &translationUnitId) const
-{
- const auto hasTranslationUnitId = [translationUnitId](const RunningJob &runningJob) {
- return runningJob.translationUnitId == translationUnitId;
- };
-
- return Utils::anyOf(m_running.values(), hasTranslationUnitId);
-}
-
-bool Jobs::isJobRunningForJobRequest(const JobRequest &jobRequest) const
-{
- const auto hasJobRequest = [jobRequest](const RunningJob &runningJob) {
- return runningJob.jobRequest == jobRequest;
- };
-
- return Utils::anyOf(m_running.values(), hasJobRequest);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangjobs.h b/src/tools/clangbackend/source/clangjobs.h
deleted file mode 100644
index 3d8af16fe41..00000000000
--- a/src/tools/clangbackend/source/clangjobs.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangjobqueue.h"
-
-#include <clangsupport/clangcodemodelclientinterface.h>
-
-#include <QFuture>
-
-#include <functional>
-
-namespace ClangBackEnd {
-
-class ClangCodeModelClientInterface;
-class Documents;
-class IAsyncJob;
-class UnsavedFiles;
-
-class Jobs
-{
-public:
- struct RunningJob {
- JobRequest jobRequest;
- Utf8String translationUnitId;
- QFuture<void> future;
- };
-
- using RunningJobs = QHash<IAsyncJob *, RunningJob>;
- using JobFinishedCallback = std::function<bool(RunningJob, IAsyncJob *)>;
-
-public:
- Jobs(Documents &documents,
- UnsavedFiles &unsavedFiles,
- ClangCodeModelClientInterface &client,
- const Utf8String &logTag = Utf8String());
- ~Jobs();
-
- JobRequest createJobRequest(const Document &document, JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit
- = PreferredTranslationUnit::RecentlyParsed) const;
-
- void add(const JobRequest &job);
- void add(const Document &document,
- JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit
- = PreferredTranslationUnit::RecentlyParsed);
-
- JobRequests process();
- JobRequests stop();
-
- JobFinishedCallback finishedCallback() const;
- void setJobFinishedCallback(const JobFinishedCallback &jobFinishedCallback);
-
-public /*for tests*/:
- QList<RunningJob> runningJobs() const;
- JobRequests &queue();
- const JobRequests &queue() const;
- bool isJobRunningForTranslationUnit(const Utf8String &translationUnitId) const;
- bool isJobRunningForJobRequest(const JobRequest &jobRequest) const;
- JobFinishedCallback jobFinishedCallback() const;
-
-private:
- JobRequests runJobs(const JobRequests &jobRequest);
- bool runJob(const JobRequest &jobRequest);
- void onJobFinished(IAsyncJob *asyncJob);
-
-private:
- Documents &m_documents;
- UnsavedFiles &m_unsavedFiles;
- ClangCodeModelClientInterface &m_client;
- Utf8String m_logTag;
-
- JobQueue m_queue;
- RunningJobs m_running;
- JobFinishedCallback m_jobFinishedCallback;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.cpp b/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.cpp
deleted file mode 100644
index 126fac2fbed..00000000000
--- a/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangparsesupportivetranslationunitjob.h"
-
-#include <clangsupport/clangsupportdebugutils.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-IAsyncJob::AsyncPrepareResult ParseSupportiveTranslationUnitJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::ParseSupportiveTranslationUnit, return AsyncPrepareResult());
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- const TranslationUnit translationUnit = *m_translationUnit;
- const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
- setRunner([translationUnit, updateInput]() {
- TIME_SCOPE_DURATION("ParseSupportiveTranslationUnitJob");
-
- TranslationUnitUpdateInput theUpdateInput = updateInput;
- theUpdateInput.parseNeeded = true;
-
- return translationUnit.update(updateInput);
- });
-
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void ParseSupportiveTranslationUnitJob::finalizeAsyncRun()
-{
- if (!context().isOutdated()) {
- const AsyncResult result = asyncResult();
- m_pinnedDocument.incorporateUpdaterResult(result);
- }
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.h b/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.h
deleted file mode 100644
index 5a0cfec1837..00000000000
--- a/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentjob.h"
-#include "clangtranslationunitupdater.h"
-
-namespace ClangBackEnd {
-
-class ParseSupportiveTranslationUnitJob : public DocumentJob<TranslationUnitUpdateResult>
-{
-public:
- using AsyncResult = TranslationUnitUpdateResult;
-
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangreferencescollector.cpp b/src/tools/clangbackend/source/clangreferencescollector.cpp
deleted file mode 100644
index a750beac034..00000000000
--- a/src/tools/clangbackend/source/clangreferencescollector.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangreferencescollector.h"
-
-#include "clangstring.h"
-#include "cursor.h"
-#include "sourcerange.h"
-#include "token.h"
-
-#include <clangsupport/sourcerangecontainer.h>
-#include <utils/qtcassert.h>
-
-#include <utf8string.h>
-
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-namespace {
-
-class ReferencedCursor
-{
-public:
- static ReferencedCursor find(const Cursor &cursor)
- {
- // Query the referenced cursor directly instead of first testing with cursor.isReference().
- // cursor.isReference() reports false for e.g. CXCursor_DeclRefExpr or CXCursor_CallExpr
- // although it returns a valid cursor.
- const Cursor referenced = cursor.referenced();
- if (referenced.isValid())
- return handleReferenced(referenced);
-
- const Cursor definition = cursor.definition();
- if (definition.isValid())
- return definition;
-
- return cursor;
- }
-
- Utf8String usr() const
- {
- return cursor.unifiedSymbolResolution() + usrSuffix;
- }
-
- bool isLocalVariable() const
- {
- return cursor.isLocalVariable();
- }
-
-private:
- ReferencedCursor(const Cursor &cursor, const Utf8String &usrSuffix = Utf8String())
- : cursor(cursor)
- , usrSuffix(usrSuffix)
- {}
-
- static ReferencedCursor handleReferenced(const Cursor &cursor)
- {
- if (cursor.kind() == CXCursor_OverloadedDeclRef) {
- // e.g. Text cursor is on "App" of "using N::App;".
- if (cursor.overloadedDeclarationsCount() >= 1)
- return cursor.overloadedDeclaration(0);
- }
-
- if (cursor.isConstructorOrDestructor()) {
- const Type type = cursor.type();
- if (type.isValid()) {
- const Cursor typeDeclaration = type.declaration();
- if (typeDeclaration.isValid()) {
- // A CXCursor_CallExpr like "new Foo" has a type of CXType_Record and its
- // declaration is e.g. CXCursor_ClassDecl.
- return typeDeclaration;
- } else {
- // A CXCursor_Constructor like "Foo();" has a type of CXType_FunctionProto
- // and its type declaration is invalid, so use the semantic parent.
- const Cursor parent = cursor.semanticParent();
- if (parent.isValid())
- return parent;
- }
- }
- }
-
- if (cursor.isFunctionLike() || cursor.isTemplateLike()) {
- const Cursor parent = cursor.semanticParent();
- const ClangString spelling = cursor.spelling();
- return {parent, Utf8StringLiteral("_qtc_") + Utf8String(spelling)};
- }
-
- return cursor;
- }
-
-private:
- Cursor cursor;
- Utf8String usrSuffix;
-};
-
-class ReferencesCollector
-{
-public:
- ReferencesCollector(CXTranslationUnit cxTranslationUnit);
-
- ReferencesResult collect(uint line, uint column, bool localReferences = false) const;
-
-private:
- bool pointsToIdentifier(int line, int column, unsigned *tokenIndex) const;
- bool matchesIdentifier(const Token &token, const Utf8String &identifier) const;
- bool checkToken(unsigned index, const Utf8String &identifier, const Utf8String &usr) const;
-
-private:
- CXTranslationUnit m_cxTranslationUnit = nullptr;
- Tokens m_tokens;
- std::vector<Cursor> m_cursors;
-};
-
-ReferencesCollector::ReferencesCollector(CXTranslationUnit cxTranslationUnit)
- : m_cxTranslationUnit(cxTranslationUnit)
- , m_tokens(Cursor(clang_getTranslationUnitCursor(m_cxTranslationUnit)).sourceRange())
- , m_cursors(m_tokens.annotate())
-{
-}
-
-bool ReferencesCollector::pointsToIdentifier(int line, int column, unsigned *tokenIndex) const
-{
- for (int i = 0; i < m_tokens.size(); ++i) {
- const Token &token = m_tokens[i];
- if (token.kind() == CXToken_Identifier && token.extent().contains(line, column)) {
- *tokenIndex = i;
- return true;
- }
- }
-
- return false;
-}
-
-bool ReferencesCollector::matchesIdentifier(const Token &token,
- const Utf8String &identifier) const
-{
- const CXTokenKind tokenKind = token.kind();
- if (tokenKind == CXToken_Identifier)
- return token.spelling() == identifier;
-
- return false;
-}
-
-bool ReferencesCollector::checkToken(unsigned index, const Utf8String &identifier,
- const Utf8String &usr) const
-{
- const Token &token = m_tokens[index];
- if (!matchesIdentifier(token, identifier))
- return false;
-
- { // For debugging only
-// const SourceRange range{m_cxTranslationUnit, clang_getTokenExtent(m_cxTranslationUnit, token)};
-// const uint line = range.start().line();
-// const ClangString spellingCs = clang_getTokenSpelling(m_cxTranslationUnit, token);
-// const Utf8String spelling = spellingCs;
-// qWarning() << "ReferencesCollector::checkToken:" << line << spelling;
- }
-
- const ReferencedCursor candidate = ReferencedCursor::find(m_cursors[index]);
-
- return candidate.usr() == usr;
-}
-
-ReferencesResult ReferencesCollector::collect(uint line, uint column, bool localReferences) const
-{
- ReferencesResult result;
-
- unsigned index = 0;
- if (!pointsToIdentifier(line, column, &index))
- return result;
-
- const ReferencedCursor refCursor = ReferencedCursor::find(m_cursors[index]);
- const Utf8String usr = refCursor.usr();
- if (usr.isEmpty())
- return result;
-
- if (localReferences && !refCursor.isLocalVariable())
- return result;
-
- const Token &token = m_tokens[index];
- const Utf8String identifier = token.spelling();
- for (int i = 0; i < m_tokens.size(); ++i) {
- if (checkToken(i, identifier, usr))
- result.references.append(m_tokens[i].extent());
- }
-
- result.isLocalVariable = refCursor.isLocalVariable();
-
- return result;
-}
-
-} // anonymous namespace
-
-ReferencesResult collectReferences(CXTranslationUnit cxTranslationUnit,
- uint line,
- uint column,
- bool localReferences)
-{
- ReferencesCollector collector(cxTranslationUnit);
- return collector.collect(line, column, localReferences);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangreferencescollector.h b/src/tools/clangbackend/source/clangreferencescollector.h
deleted file mode 100644
index c467f8b090a..00000000000
--- a/src/tools/clangbackend/source/clangreferencescollector.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport/sourcerangecontainer.h>
-
-#include <QVector>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class ReferencesResult
-{
-public:
- ReferencesResult() = default;
- ReferencesResult(bool isLocalVariable, const QVector<SourceRangeContainer> &references)
- : isLocalVariable(isLocalVariable)
- , references(references)
- {}
-
- bool operator==(const ReferencesResult &other) const
- {
- return isLocalVariable == other.isLocalVariable
- && references == other.references;
- }
-
- bool isLocalVariable = false;
- QVector<SourceRangeContainer> references;
-};
-
-ReferencesResult collectReferences(CXTranslationUnit cxTranslationUnit,
- uint line,
- uint column,
- bool localReferences = false);
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/clangrequestannotationsjob.cpp b/src/tools/clangbackend/source/clangrequestannotationsjob.cpp
deleted file mode 100644
index 2ffec0157c9..00000000000
--- a/src/tools/clangbackend/source/clangrequestannotationsjob.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangrequestannotationsjob.h"
-
-#include <clangsupport/annotationsmessage.h>
-#include <clangsupport/clangsupportdebugutils.h>
-#include <clangsupport/clangcodemodelclientinterface.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-IAsyncJob::AsyncPrepareResult RequestAnnotationsJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestAnnotations,
- return AsyncPrepareResult());
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- const TranslationUnit translationUnit = *m_translationUnit;
- setRunner([translationUnit]() {
- TIME_SCOPE_DURATION("RequestAnnotationsJobRunner");
-
- RequestAnnotationsJob::AsyncResult asyncResult;
- translationUnit.extractAnnotations(asyncResult.firstHeaderErrorDiagnostic,
- asyncResult.diagnostics,
- asyncResult.tokenInfos,
- asyncResult.skippedSourceRanges);
- return asyncResult;
- });
-
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void RequestAnnotationsJob::finalizeAsyncRun()
-{
- if (context().isDocumentOpen()) {
- const AsyncResult result = asyncResult();
- context().client->annotations(AnnotationsMessage(m_pinnedFileContainer,
- result.diagnostics,
- result.firstHeaderErrorDiagnostic,
- result.tokenInfos,
- result.skippedSourceRanges));
- }
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangrequestannotationsjob.h b/src/tools/clangbackend/source/clangrequestannotationsjob.h
deleted file mode 100644
index c0693eb26e1..00000000000
--- a/src/tools/clangbackend/source/clangrequestannotationsjob.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentjob.h"
-
-#include <clangsupport/diagnosticcontainer.h>
-#include <clangsupport/tokeninfocontainer.h>
-#include <clangsupport/sourcerangecontainer.h>
-
-namespace ClangBackEnd {
-
-struct RequestAnnotationsJobResult
-{
- ClangBackEnd::DiagnosticContainer firstHeaderErrorDiagnostic;
- QVector<ClangBackEnd::DiagnosticContainer> diagnostics;
- QVector<TokenInfoContainer> tokenInfos;
- QVector<SourceRangeContainer> skippedSourceRanges;
-};
-
-class RequestAnnotationsJob : public DocumentJob<RequestAnnotationsJobResult>
-{
-public:
- using AsyncResult = RequestAnnotationsJobResult;
-
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangrequestreferencesjob.cpp b/src/tools/clangbackend/source/clangrequestreferencesjob.cpp
deleted file mode 100644
index cb2354ede3e..00000000000
--- a/src/tools/clangbackend/source/clangrequestreferencesjob.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangrequestreferencesjob.h"
-
-#include <clangsupport/clangsupportdebugutils.h>
-#include <clangsupport/referencesmessage.h>
-#include <clangsupport/clangcodemodelclientinterface.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-IAsyncJob::AsyncPrepareResult RequestReferencesJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestReferences,
- return AsyncPrepareResult());
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- const TranslationUnit translationUnit = *m_translationUnit;
- const quint32 line = jobRequest.line;
- const quint32 column = jobRequest.column;
- const bool localReferences = jobRequest.localReferences;
- setRunner([translationUnit, line, column, localReferences]() {
- TIME_SCOPE_DURATION("RequestReferencesJobRunner");
- return translationUnit.references(line, column, localReferences);
- });
-
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void RequestReferencesJob::finalizeAsyncRun()
-{
- if (!context().isOutdated()) {
- const AsyncResult result = asyncResult();
-
- const ReferencesMessage message(m_pinnedFileContainer,
- result.references,
- result.isLocalVariable,
- context().jobRequest.ticketNumber);
- context().client->references(message);
- }
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangrequestreferencesjob.h b/src/tools/clangbackend/source/clangrequestreferencesjob.h
deleted file mode 100644
index d92d869a9bb..00000000000
--- a/src/tools/clangbackend/source/clangrequestreferencesjob.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentjob.h"
-#include "clangreferencescollector.h"
-
-namespace ClangBackEnd {
-
-class RequestReferencesJob : public DocumentJob<ReferencesResult>
-{
-public:
- using AsyncResult = ReferencesResult;
-
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangrequesttooltipjob.cpp b/src/tools/clangbackend/source/clangrequesttooltipjob.cpp
deleted file mode 100644
index 0e1249e4e8b..00000000000
--- a/src/tools/clangbackend/source/clangrequesttooltipjob.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangrequesttooltipjob.h"
-
-#include <clangsupport/clangsupportdebugutils.h>
-#include <clangsupport/clangcodemodelclientinterface.h>
-#include <clangsupport/tooltipmessage.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-IAsyncJob::AsyncPrepareResult RequestToolTipJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestToolTip, return AsyncPrepareResult());
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- const TranslationUnit translationUnit = *m_translationUnit;
- const UnsavedFiles unsavedFiles = *context().unsavedFiles;
- const quint32 line = jobRequest.line;
- const quint32 column = jobRequest.column;
- const Utf8String textCodecName = jobRequest.textCodecName;
- setRunner([translationUnit, unsavedFiles, line, column, textCodecName]() {
- TIME_SCOPE_DURATION("RequestToolTipJobRunner");
-
- UnsavedFiles theUnsavedFiles = unsavedFiles;
- return translationUnit.tooltip(theUnsavedFiles, textCodecName, line, column);
- });
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void RequestToolTipJob::finalizeAsyncRun()
-{
- if (!context().isOutdated()) {
- const AsyncResult result = asyncResult();
-
- context().client->tooltip(ToolTipMessage(m_pinnedFileContainer,
- result,
- context().jobRequest.ticketNumber));
- }
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangrequesttooltipjob.h b/src/tools/clangbackend/source/clangrequesttooltipjob.h
deleted file mode 100644
index eb121402cb2..00000000000
--- a/src/tools/clangbackend/source/clangrequesttooltipjob.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport/tooltipinfo.h>
-
-#include "clangdocumentjob.h"
-
-namespace ClangBackEnd {
-
-class RequestToolTipJob : public DocumentJob<ToolTipInfo>
-{
-public:
- using AsyncResult = ToolTipInfo;
-
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangresumedocumentjob.cpp b/src/tools/clangbackend/source/clangresumedocumentjob.cpp
deleted file mode 100644
index 537472d66ab..00000000000
--- a/src/tools/clangbackend/source/clangresumedocumentjob.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangresumedocumentjob.h"
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-void ResumeDocumentJob::finalizeAsyncRun()
-{
- if (context().isDocumentOpen()) {
- if (QTC_GUARD(asyncResult().updateResult.hasReparsed()))
- m_pinnedDocument.setIsSuspended(false);
- }
-
- UpdateAnnotationsJob::finalizeAsyncRun();
-}
-
-bool ResumeDocumentJob::isExpectedJobRequestType(const JobRequest &jobRequest) const
-{
- return jobRequest.type == JobRequest::Type::ResumeDocument;
-}
-
-TranslationUnitUpdateInput ResumeDocumentJob::createUpdateInput(const Document &document) const
-{
- TranslationUnitUpdateInput input = UpdateAnnotationsJob::createUpdateInput(document);
- input.reparseNeeded = true;
- return input;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangresumedocumentjob.h b/src/tools/clangbackend/source/clangresumedocumentjob.h
deleted file mode 100644
index 2d9c764e523..00000000000
--- a/src/tools/clangbackend/source/clangresumedocumentjob.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangasyncjob.h"
-#include "clangdocument.h"
-#include "clangupdateannotationsjob.h"
-
-namespace ClangBackEnd {
-
-class ResumeDocumentJob : public UpdateAnnotationsJob
-{
-public:
- void finalizeAsyncRun() override;
-
-private:
- bool isExpectedJobRequestType(const JobRequest &jobRequest) const override;
- TranslationUnitUpdateInput createUpdateInput(const Document &document) const override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangstring.h b/src/tools/clangbackend/source/clangstring.h
deleted file mode 100644
index cc70f548c40..00000000000
--- a/src/tools/clangbackend/source/clangstring.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clang-c/CXString.h>
-
-#include <utf8string.h>
-
-#include <cstring>
-#include <ostream>
-
-namespace ClangBackEnd {
-
-class ClangString
-{
-public:
- ClangString(CXString cxString)
- : m_cxString(cxString)
- {
- }
-
- ~ClangString()
- {
- clang_disposeString(m_cxString);
- }
-
- ClangString(const ClangString &) = delete;
- const ClangString &operator=(const ClangString &) = delete;
-
-
- ClangString(ClangString &&other)
- : m_cxString(std::move(other.m_cxString))
- {
- other.m_cxString.data = nullptr;
- other.m_cxString.private_flags = 0;
- }
-
-
- ClangString &operator=(ClangString &&other)
- {
- if (this != &other) {
- clang_disposeString(m_cxString);
- m_cxString = std::move(other.m_cxString);
- other.m_cxString.data = nullptr;
- other.m_cxString.private_flags = 0;
- }
-
- return *this;
- }
-
- const char *cString() const
- {
- return clang_getCString(m_cxString);
- }
-
- operator Utf8String() const
- {
- return Utf8String(cString(), -1);
- }
-
- bool isNull() const
- {
- return m_cxString.data == nullptr;
- }
-
- bool hasContent() const
- {
- return !isNull() && std::strlen(cString()) > 0;
- }
-
- bool startsWith(const char* str) const
- {
- return std::strncmp(cString(), str, strlen(str)) == 0;
- }
-
- friend bool operator==(const ClangString &first, const ClangString &second)
- {
- return std::strcmp(first.cString(), second.cString()) == 0;
- }
-
- template<std::size_t Size>
- friend bool operator==(const ClangString &first, const char(&second)[Size])
- {
- return std::strncmp(first.cString(), second, Size) == 0; // Size includes \0
- }
-
- template<std::size_t Size>
- friend bool operator==(const char(&first)[Size], const ClangString &second)
- {
- return second == first;
- }
-
- template<typename Type,
- typename = typename std::enable_if<std::is_pointer<Type>::value>::type
- >
- friend bool operator==(const ClangString &first, Type second)
- {
- return std::strcmp(first.cString(), second) == 0;
- }
-
- template<typename Type,
- typename = typename std::enable_if<std::is_pointer<Type>::value>::type
- >
- friend bool operator==(Type first, const ClangString &second)
- {
- return second == first;
- }
-
- friend bool operator!=(const ClangString &first, const ClangString &second)
- {
- return !(first == second);
- }
-
- template<std::size_t Size>
- friend bool operator!=(const ClangString &first, const char(&second)[Size])
- {
- return !(first == second);
- }
-
- template<std::size_t Size>
- friend bool operator!=(const char(&first)[Size], const ClangString &second)
- {
- return second != first;
- }
-
- template<typename Type,
- typename = typename std::enable_if<std::is_pointer<Type>::value>::type
- >
- friend bool operator!=(const ClangString &first, Type second)
- {
- return !(first == second);
- }
-
- template<typename Type,
- typename = typename std::enable_if<std::is_pointer<Type>::value>::type
- >
- friend bool operator!=(Type first, const ClangString &second)
- {
- return !(first == second);
- }
-
- friend std::ostream &operator<<(std::ostream &os, const ClangString &string)
- {
- return os << string.cString();
- }
-
-private:
- CXString m_cxString;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.cpp b/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.cpp
deleted file mode 100644
index a34b7bb1143..00000000000
--- a/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangsupportivetranslationunitinitializer.h"
-
-#include "clangjobs.h"
-#include "clangtranslationunits.h"
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-SupportiveTranslationUnitInitializer::SupportiveTranslationUnitInitializer(
- const Document &document,
- Jobs &jobs)
- : m_document(document)
- , m_jobs(jobs)
-{
-}
-
-void SupportiveTranslationUnitInitializer::setIsDocumentClosedChecker(
- const IsDocumentClosedChecker &isDocumentClosedChecker)
-{
- m_isDocumentClosedChecker = isDocumentClosedChecker;
-}
-
-SupportiveTranslationUnitInitializer::State SupportiveTranslationUnitInitializer::state() const
-{
- return m_state;
-}
-
-void SupportiveTranslationUnitInitializer::startInitializing()
-{
- if (!checkStateAndDocument(State::NotInitialized))
- return;
-
- m_document.translationUnits().createAndAppend();
-
- m_jobs.setJobFinishedCallback([this](const Jobs::RunningJob &runningJob, IAsyncJob *) {
- checkIfParseJobFinished(runningJob);
- return false;
- });
- addJob(JobRequest::Type::ParseSupportiveTranslationUnit);
- m_jobs.process();
-
- m_state = State::WaitingForParseJob;
-}
-
-void SupportiveTranslationUnitInitializer::abort()
-{
- if (m_document.translationUnits().size() > 1)
- m_jobs.setJobFinishedCallback(Jobs::JobFinishedCallback());
- m_state = State::Aborted;
-}
-
-void SupportiveTranslationUnitInitializer::checkIfParseJobFinished(const Jobs::RunningJob &job)
-{
- if (!checkStateAndDocument(State::WaitingForParseJob))
- return;
-
- if (job.jobRequest.type == JobRequest::Type::ParseSupportiveTranslationUnit) {
- if (m_document.translationUnits().areAllTranslationUnitsParsed()) {
- m_jobs.setJobFinishedCallback(nullptr);
- m_state = State::Initialized;
- } else {
- // The supportive translation unit was parsed, but the document
- // revision changed in the meanwhile, so try again.
- addJob(JobRequest::Type::ParseSupportiveTranslationUnit);
- }
- }
-}
-
-bool SupportiveTranslationUnitInitializer::checkStateAndDocument(State currentExpectedState)
-{
- if (m_state != currentExpectedState) {
- m_state = State::Aborted;
- return false;
- }
-
- QTC_CHECK(m_isDocumentClosedChecker);
- if (m_isDocumentClosedChecker(m_document.filePath())) {
- m_state = State::Aborted;
- return false;
- }
-
- return true;
-}
-
-void SupportiveTranslationUnitInitializer::addJob(JobRequest::Type jobRequestType)
-{
- const JobRequest jobRequest = m_jobs.createJobRequest(
- m_document, jobRequestType, PreferredTranslationUnit::LastUninitialized);
-
- m_jobs.add(jobRequest);
-}
-
-void SupportiveTranslationUnitInitializer::setState(const State &state)
-{
- m_state = state;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.h b/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.h
deleted file mode 100644
index 4476bcf4ef9..00000000000
--- a/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangdocument.h"
-#include "clangjobs.h"
-
-#include <functional>
-
-#pragma once
-
-namespace ClangBackEnd {
-
-class SupportiveTranslationUnitInitializer
-{
-public:
- using IsDocumentClosedChecker = std::function<bool(const Utf8String &)>;
-
- enum class State {
- NotInitialized,
- WaitingForParseJob,
- Initialized,
- Aborted
- };
-
-public:
- SupportiveTranslationUnitInitializer(const Document &document, Jobs &jobs);
-
- void setIsDocumentClosedChecker(const IsDocumentClosedChecker &isDocumentClosedChecker);
-
- State state() const;
- void startInitializing();
- void abort();
-
-public: // for tests
- void setState(const State &state);
- void checkIfParseJobFinished(const Jobs::RunningJob &job);
-
-private:
- bool checkStateAndDocument(State currentExpectedState);
- void addJob(JobRequest::Type jobRequestType);
-
-private:
- Document m_document;
- Jobs &m_jobs;
-
- State m_state = State::NotInitialized;
- IsDocumentClosedChecker m_isDocumentClosedChecker;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangsuspenddocumentjob.cpp b/src/tools/clangbackend/source/clangsuspenddocumentjob.cpp
deleted file mode 100644
index 87fe54bfae9..00000000000
--- a/src/tools/clangbackend/source/clangsuspenddocumentjob.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangsuspenddocumentjob.h"
-
-#include <clangsupport/clangsupportdebugutils.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-IAsyncJob::AsyncPrepareResult SuspendDocumentJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::SuspendDocument, return AsyncPrepareResult());
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- TranslationUnit translationUnit = *m_translationUnit;
- setRunner([translationUnit]() {
- TIME_SCOPE_DURATION("SuspendDocumentJobRunner");
- return translationUnit.suspend();
- });
-
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void SuspendDocumentJob::finalizeAsyncRun()
-{
- if (context().isDocumentOpen()) {
- const bool suspendSucceeded = asyncResult();
- if (QTC_GUARD(suspendSucceeded)) {
- m_pinnedDocument.setIsSuspended(true);
- }
- }
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangsuspenddocumentjob.h b/src/tools/clangbackend/source/clangsuspenddocumentjob.h
deleted file mode 100644
index 5948f8226f1..00000000000
--- a/src/tools/clangbackend/source/clangsuspenddocumentjob.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentjob.h"
-
-namespace ClangBackEnd {
-
-class SuspendDocumentJob : public DocumentJob<bool>
-{
-public:
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtooltipinfocollector.cpp b/src/tools/clangbackend/source/clangtooltipinfocollector.cpp
deleted file mode 100644
index 03a328915e9..00000000000
--- a/src/tools/clangbackend/source/clangtooltipinfocollector.cpp
+++ /dev/null
@@ -1,574 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangtooltipinfocollector.h"
-
-#include "clangbackend_global.h"
-#include "clangstring.h"
-#include "cursor.h"
-#include "sourcerange.h"
-#include "token.h"
-#include "unsavedfiles.h"
-#include "unsavedfile.h"
-
-#include <clangsupport/sourcerangecontainer.h>
-#include <utils/fileutils.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcassert.h>
-#include <utils/textfileformat.h>
-
-#include <utf8string.h>
-
-#include <QDebug>
-#include <QDir>
-#include <QTextCodec>
-
-namespace ClangBackEnd {
-
-Utf8String qualificationPrefix(const Cursor &cursor)
-{
- // TODO: Implement with qualificationPrefixAsVector()
- Utf8String qualifiedName;
-
- for (Cursor parent = cursor.semanticParent();
- parent.isValid() && (parent.kind() == CXCursor_Namespace);
- parent = parent.semanticParent()) {
- qualifiedName = parent.spelling() + Utf8StringLiteral("::") + qualifiedName;
- }
-
- return qualifiedName;
-}
-
-namespace {
-
-Utf8StringVector qualificationPrefixAsVector(const Cursor &cursor)
-{
- Utf8StringVector result;
-
- for (Cursor parent = cursor.semanticParent();
- parent.isValid() && (parent.kind() == CXCursor_Namespace || parent.isCompoundType());
- parent = parent.semanticParent()) {
- result.prepend(parent.spelling());
- }
-
- return result;
-}
-
-Utf8String displayName(const Cursor &cursor)
-{
- if (cursor.kind() == CXCursor_ClassTemplate) {
- // TODO: The qualification should be part of the display name. Fix this in libclang.
- return qualificationPrefix(cursor) + cursor.displayName();
- }
-
- return cursor.displayName();
-}
-
-Utf8String textForFunctionLike(const Cursor &cursor)
-{
- CXPrintingPolicy policy = clang_getCursorPrintingPolicy(cursor.cx());
- clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_FullyQualifiedName, 1);
- clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_TerseOutput, 1);
- // Avoid printing attributes/pragmas
- clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_PolishForDeclaration, 1);
- clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_SuppressInitializers, 1);
- const Utf8String prettyPrinted = ClangString(
- clang_getCursorPrettyPrinted(cursor.cx(), policy));
- clang_PrintingPolicy_dispose(policy);
- return prettyPrinted;
-}
-
-Utf8String textForEnumConstantDecl(const Cursor &cursor)
-{
- const Cursor semanticParent = cursor.semanticParent();
- QTC_ASSERT(semanticParent.kind() == CXCursor_EnumDecl, return Utf8String());
-
- const Type enumType = semanticParent.enumType();
- if (enumType.isUnsigned())
- return Utf8String::number(cursor.enumConstantUnsignedValue());
- return Utf8String::number(cursor.enumConstantValue());
-}
-
-Utf8String textForInclusionDirective(const Cursor &cursor)
-{
- const CXFile includedFile = cursor.includedFile();
- const Utf8String fileName = ClangString(clang_getFileName(includedFile));
-
- return QDir::toNativeSeparators(fileName.toString());
-}
-
-Utf8String textForAnyTypeAlias(const Cursor &cursor)
-{
- // For a CXCursor_TypeAliasTemplateDecl the type of cursor/referenced
- // is invalid, so we do not get the underlying type. This here solely
- // reports the unresolved name instead of the empty string.
- if (cursor.kind() == CXCursor_TypeAliasTemplateDecl)
- return cursor.displayName();
-
- return cursor.type().alias().utf8Spelling();
-}
-
-bool includeSizeForCursor(const Cursor &cursor)
-{
- return cursor.isCompoundType()
- || cursor.kind() == CXCursor_EnumDecl
- || cursor.kind() == CXCursor_UnionDecl
- || cursor.kind() == CXCursor_FieldDecl;
-}
-
-Utf8String sizeInBytes(const Cursor &cursor)
-{
- if (includeSizeForCursor(cursor)) {
- bool ok = false;
- const long long size = cursor.type().sizeOf(&ok);
- if (ok)
- return Utf8String::number(size);
- }
-
- return Utf8String();
-}
-
-QVariant value(const Cursor &cursor)
-{
- if (!clang_isDeclaration(cursor.cx().kind) && !clang_isExpression(cursor.cx().kind))
- return {};
- const CXEvalResult evalResult = clang_Cursor_Evaluate(cursor.cx());
- QVariant v;
- switch (clang_EvalResult_getKind(evalResult)) {
- case CXEval_Int:
- v = clang_EvalResult_isUnsignedInt(evalResult)
- ? QVariant::fromValue(clang_EvalResult_getAsUnsigned(evalResult))
- : QVariant::fromValue(clang_EvalResult_getAsLongLong(evalResult));
- break;
- case CXEval_Float:
- v = QVariant::fromValue(clang_EvalResult_getAsDouble(evalResult));
- break;
- default:
- break;
- }
- clang_EvalResult_dispose(evalResult);
- return v;
-}
-
-Cursor referencedCursor(const Cursor &cursor)
-{
- // Query the referenced cursor directly instead of first testing with cursor.isReference().
- // cursor.isReference() reports false for e.g. CXCursor_DeclRefExpr or CXCursor_CallExpr
- // although it returns a valid cursor.
- const Cursor referenced = cursor.referenced();
- if (referenced.isValid())
- return referenced;
-
- const Cursor definition = cursor.definition();
- if (definition.isValid())
- return definition;
-
- return cursor;
-}
-
-class ToolTipInfoCollector
-{
-public:
- ToolTipInfoCollector(UnsavedFiles &unsavedFiles,
- const Utf8String &textCodecName,
- const Utf8String &mainFilePath,
- CXTranslationUnit cxTranslationUnit);
-
- ToolTipInfo collect(uint line, uint column) const;
-
-private:
- Utf8String text(const Cursor &cursor, const Cursor &referenced) const;
- Utf8String textForMacroExpansion(const Cursor &cursor) const;
- Utf8String textForNamespaceAlias(const Cursor &cursor) const;
-
- ToolTipInfo qDocInfo(const Cursor &cursor) const;
-
- CXSourceLocation toCXSourceLocation(uint line, uint column) const;
-
- UnsavedFile unsavedFile(const Utf8String &filePath) const;
- Utf8String lineRange(const Utf8String &filePath, unsigned fromLine, unsigned toLine) const;
-
-private:
- UnsavedFiles &m_unsavedFiles;
- const Utf8String m_textCodecName;
-
- const Utf8String m_mainFilePath;
- CXTranslationUnit m_cxTranslationUnit = nullptr;
-
-};
-
-ToolTipInfoCollector::ToolTipInfoCollector(UnsavedFiles &unsavedFiles,
- const Utf8String &textCodecName,
- const Utf8String &mainFilePath,
- CXTranslationUnit cxTranslationUnit)
- : m_unsavedFiles(unsavedFiles)
- , m_textCodecName(textCodecName)
- , m_mainFilePath(mainFilePath)
- , m_cxTranslationUnit(cxTranslationUnit)
-{
-}
-
-Utf8String ToolTipInfoCollector::text(const Cursor &cursor, const Cursor &referenced) const
-{
- if (cursor.kind() == CXCursor_MacroExpansion)
- return textForMacroExpansion(referenced);
-
- if (referenced.kind() == CXCursor_EnumConstantDecl)
- return textForEnumConstantDecl(referenced);
-
- if (referenced.kind() == CXCursor_InclusionDirective)
- return textForInclusionDirective(referenced);
-
- if (referenced.kind() == CXCursor_Namespace)
- return qualificationPrefix(referenced) + referenced.spelling();
-
- if (referenced.kind() == CXCursor_NamespaceAlias)
- return textForNamespaceAlias(referenced);
-
- if (referenced.isAnyTypeAlias())
- return textForAnyTypeAlias(referenced);
-
- if (referenced.isFunctionLike() || referenced.kind() == CXCursor_Constructor)
- return textForFunctionLike(referenced);
-
- if (referenced.kind() == CXCursor_VarDecl)
- return referenced.type().spelling(); // e.g. "Zii<int>"
-
- const Type referencedType = referenced.type();
- if (referencedType.isValid()) {
- // Generally, the type includes the qualification but has this limitations:
- // * namespace aliases are not resolved
- // * outer class of a inner template class is not included
- // The type includes the qualification, but not resolved namespace aliases.
-
- // For a CXType_Record, this also includes e.g. "const " as prefix.
- return referencedType.canonical().utf8Spelling();
- }
-
- return displayName(referenced);
-}
-
-Utf8String ToolTipInfoCollector::textForMacroExpansion(const Cursor &cursor) const
-{
- QTC_ASSERT(cursor.kind() == CXCursor_MacroDefinition, return Utf8String());
-
- const SourceRange sourceRange = cursor.sourceRange();
- const SourceLocation start = sourceRange.start();
- const SourceLocation end = sourceRange.end();
-
- return lineRange(start.filePath(), start.line(), end.line());
-}
-
-Utf8String ToolTipInfoCollector::textForNamespaceAlias(const Cursor &cursor) const
-{
- // TODO: Add some libclang API to get the aliased name straight away.
-
- const Tokens tokens(cursor.sourceRange());
-
- Utf8String aliasedName;
- // Start at 3 in order to skip these tokens: namespace X =
- for (int i = 3; i < tokens.size(); ++i)
- aliasedName += tokens[i].spelling();
-
- return aliasedName;
-}
-
-static Utf8String typeName(const Type &type)
-{
- return type.declaration().spelling();
-}
-
-static Utf8String qdocMark(const Cursor &cursor)
-{
- if (cursor.kind() == CXCursor_ClassTemplate)
- return cursor.spelling();
-
- if (cursor.type().kind() == CXType_Enum
- || cursor.type().kind() == CXType_Typedef
- || cursor.type().kind() == CXType_Record)
- return typeName(cursor.type());
-
- Utf8String text = cursor.displayName();
- if (cursor.kind() == CXCursor_FunctionDecl) {
- // TODO: Remove this workaround by fixing this in
- // libclang with the help of CXPrintingPolicy.
- text.replace(Utf8StringLiteral("<>"), Utf8String());
- }
-
- return text;
-}
-
-static ToolTipInfo::QdocCategory qdocCategory(const Cursor &cursor)
-{
- if (cursor.isFunctionLike())
- return ToolTipInfo::Function;
-
- if (cursor.kind() == CXCursor_MacroDefinition)
- return ToolTipInfo::Macro;
-
- if (cursor.kind() == CXCursor_EnumConstantDecl)
- return ToolTipInfo::Enum;
-
- if (cursor.type().kind() == CXType_Enum)
- return ToolTipInfo::Enum;
-
- if (cursor.kind() == CXCursor_InclusionDirective)
- return ToolTipInfo::Brief;
-
- // TODO: Handle CXCursor_NamespaceAlias, too?!
- if (cursor.kind() == CXCursor_Namespace)
- return ToolTipInfo::ClassOrNamespace;
-
- if (cursor.isCompoundType())
- return ToolTipInfo::ClassOrNamespace;
-
- if (cursor.kind() == CXCursor_NamespaceAlias)
- return ToolTipInfo::ClassOrNamespace;
-
- if (cursor.type().kind() == CXType_Typedef)
- return ToolTipInfo::Typedef;
-
- if (cursor.type().kind() == CXType_Record)
- return ToolTipInfo::ClassOrNamespace;
-
- if (cursor.kind() == CXCursor_TypeAliasTemplateDecl)
- return ToolTipInfo::Typedef;
-
- if (cursor.kind() == CXCursor_ClassTemplate)
- return ToolTipInfo::ClassOrNamespace;
-
- return ToolTipInfo::Unknown;
-}
-
-static Utf8String name(const Cursor &cursor)
-{
- if (cursor.type().kind() == CXType_Record || cursor.kind() == CXCursor_EnumDecl)
- return typeName(cursor.type());
-
- return cursor.spelling();
-}
-
-static Utf8StringVector qDocIdCandidates(const Cursor &cursor)
-{
- Utf8StringVector components = qualificationPrefixAsVector(cursor);
- if (components.isEmpty())
- return { name(cursor) };
-
- components << name(cursor);
- Utf8StringVector result;
- Utf8String name;
- for (auto it = components.rbegin(); it != components.rend(); ++it) {
- if (name.isEmpty())
- name = *it;
- else
- name = *it + (Utf8StringLiteral("::") + name);
-
- result.prepend(name);
- }
-
- return result;
-}
-
-// TODO: Add libclang API for this?!
-static bool isBuiltinOrPointerToBuiltin(const Type &type)
-{
- Type theType = type;
-
- if (theType.isBuiltinType())
- return true;
-
- // TODO: Simplify
- // TODO: Test with **
- while (theType.pointeeType().isValid() && theType != theType.pointeeType()) {
- theType = theType.pointeeType();
- if (theType.isBuiltinType())
- return true;
- }
-
- return false;
-}
-
-ToolTipInfo ToolTipInfoCollector::qDocInfo(const Cursor &cursor) const
-{
- ToolTipInfo result;
-
- if (isBuiltinOrPointerToBuiltin(cursor.type()))
- return result;
-
- if (cursor.kind() == CXCursor_Constructor) {
- const ToolTipInfo parentInfo = qDocInfo(cursor.semanticParent());
- result.qdocIdCandidates = parentInfo.qdocIdCandidates;
- result.qdocMark = parentInfo.qdocMark;
- result.qdocCategory = ToolTipInfo::Unknown;
- return result;
- }
-
- result.qdocIdCandidates = qDocIdCandidates(cursor);
- result.qdocMark = qdocMark(cursor);
- result.qdocCategory = qdocCategory(cursor);
-
- if (cursor.type().kind() == CXType_Record) {
- result.qdocIdCandidates = qDocIdCandidates(cursor.type().declaration());
- return result;
- }
-
- if (cursor.kind() == CXCursor_VarDecl || cursor.kind() == CXCursor_ParmDecl
- || cursor.kind() == CXCursor_FieldDecl) {
- // maybe template instantiation
- if (cursor.type().kind() == CXType_Unexposed && cursor.type().canonical().kind() == CXType_Record) {
- result.qdocIdCandidates = qDocIdCandidates(cursor.type().canonical().declaration());
- result.qdocMark = typeName(cursor.type());
- result.qdocCategory = ToolTipInfo::ClassOrNamespace;
- return result;
- }
-
- Type type = cursor.type();
- while (type.pointeeType().isValid() && type != type.pointeeType())
- type = type.pointeeType();
-
- const Cursor typeCursor = type.declaration();
- result.qdocIdCandidates = qDocIdCandidates(typeCursor);
- result.qdocCategory = qdocCategory(typeCursor);
- result.qdocMark = typeName(type);
- }
-
- // TODO: Handle also RValueReference()
- if (cursor.type().isLValueReference()) {
- const Cursor pointeeTypeDeclaration = cursor.type().pointeeType().declaration();
- result.qdocIdCandidates = qDocIdCandidates(pointeeTypeDeclaration);
- result.qdocMark = pointeeTypeDeclaration.spelling();
- result.qdocCategory = qdocCategory(pointeeTypeDeclaration);
- return result;
- }
-
- return result;
-}
-
-CXSourceLocation ToolTipInfoCollector::toCXSourceLocation(uint line, uint column) const
-{
- return clang_getLocation(m_cxTranslationUnit,
- clang_getFile(m_cxTranslationUnit,
- m_mainFilePath.constData()),
- line,
- column);
-}
-
-UnsavedFile ToolTipInfoCollector::unsavedFile(const Utf8String &filePath) const
-{
- const UnsavedFile &unsavedFile = m_unsavedFiles.unsavedFile(filePath);
- if (!unsavedFile.filePath().isEmpty())
- return unsavedFile;
-
- // Create an unsaved file with the file content from disk.
- // TODO: Make use of clang_getFileContents() instead of reading from disk.
- QTextCodec *codec = QTextCodec::codecForName(m_textCodecName);
- QByteArray fileContent;
- QString errorString;
- using namespace Utils;
- const TextFileFormat::ReadResult readResult
- = TextFileFormat::readFileUTF8(Utils::FilePath::fromString(filePath),
- codec,
- &fileContent,
- &errorString);
- if (readResult != TextFileFormat::ReadSuccess) {
- qWarning() << "Failed to read file" << filePath << ":" << errorString;
- return UnsavedFile();
- }
-
- return UnsavedFile(filePath, Utf8String::fromByteArray(fileContent));
-}
-
-Utf8String ToolTipInfoCollector::lineRange(const Utf8String &filePath,
- unsigned fromLine,
- unsigned toLine) const
-{
- if (toLine < fromLine)
- return Utf8String();
-
- const UnsavedFile file = unsavedFile(filePath);
- if (file.fileContent().isEmpty())
- return Utf8String();
-
- return file.lineRange(fromLine, toLine);
-}
-
-ToolTipInfo ToolTipInfoCollector::collect(uint line, uint column) const
-{
- Cursor cursor = clang_getCursor(m_cxTranslationUnit, toCXSourceLocation(line, column));
- if (!cursor.isValid()) { // QTCREATORBUG-21194
- Tokens tokens(Cursor(clang_getTranslationUnitCursor(m_cxTranslationUnit)).sourceRange());
- if (!tokens.size())
- return {};
-
- // TODO: Only annotate the tokens up until the location we are interested in?
- // Same goes for FollowSymbol.
- const std::vector<Cursor> cursors = tokens.annotate();
-
- const int tokenIndex = tokens.getTokenIndex(m_cxTranslationUnit, line, column);
- QTC_ASSERT(tokenIndex >= 0, return {});
- const Utf8String tokenSpelling = tokens[tokenIndex].spelling();
- if (tokenSpelling.isEmpty())
- return {};
- cursor = cursors[tokenIndex];
- }
- if (!cursor.isValid())
- return {};
-
- const Cursor referenced = referencedCursor(cursor);
- QTC_CHECK(referenced.isValid());
-
- ToolTipInfo info;
- info.text = text(cursor, referenced);
- info.briefComment = referenced.briefComment();
- info.value = value(cursor);
-
- {
- ToolTipInfo qDocToolTipInfo = qDocInfo(referenced);
- info.qdocIdCandidates = qDocToolTipInfo.qdocIdCandidates;
- info.qdocMark = qDocToolTipInfo.qdocMark;
- info.qdocCategory = qDocToolTipInfo.qdocCategory;
- }
-
- info.sizeInBytes = sizeInBytes(cursor);
-
- return info;
-}
-
-} // anonymous namespace
-
-ToolTipInfo collectToolTipInfo(UnsavedFiles &unsavedFiles,
- const Utf8String &textCodecName,
- const Utf8String &mainFilePath,
- CXTranslationUnit cxTranslationUnit,
- uint line,
- uint column)
-{
- ToolTipInfoCollector collector(unsavedFiles, textCodecName, mainFilePath, cxTranslationUnit);
- const ToolTipInfo info = collector.collect(line, column);
-
- return info;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtooltipinfocollector.h b/src/tools/clangbackend/source/clangtooltipinfocollector.h
deleted file mode 100644
index ae1609c2765..00000000000
--- a/src/tools/clangbackend/source/clangtooltipinfocollector.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utf8string.h>
-
-#include <clangsupport/tooltipinfo.h>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class Cursor;
-class UnsavedFiles;
-
-ToolTipInfo collectToolTipInfo(UnsavedFiles &unsavedFiles,
- const Utf8String &textCodecName,
- const Utf8String &mainFilePath,
- CXTranslationUnit cxTranslationUnit,
- uint line,
- uint column);
-
-Utf8String qualificationPrefix(const Cursor &cursor);
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunit.cpp b/src/tools/clangbackend/source/clangtranslationunit.cpp
deleted file mode 100644
index cc848f89ab7..00000000000
--- a/src/tools/clangbackend/source/clangtranslationunit.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangtranslationunit.h"
-
-#include "clangbackend_global.h"
-#include "clangreferencescollector.h"
-#include "clangtooltipinfocollector.h"
-#include "clangtranslationunitupdater.h"
-#include "clangfollowsymbol.h"
-#include "clangfollowsymboljob.h"
-#include "tokenprocessor.h"
-
-#include <codecompleter.h>
-#include <cursor.h>
-#include <diagnosticcontainer.h>
-#include <diagnosticset.h>
-#include <skippedsourceranges.h>
-#include <sourcelocation.h>
-#include <sourcerange.h>
-#include <commandlinearguments.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-TranslationUnit::TranslationUnit(const Utf8String &id,
- const Utf8String &filepath,
- CXIndex &cxIndex,
- CXTranslationUnit &cxTranslationUnit)
- : m_id(id)
- , m_filePath(filepath)
- , m_cxIndex(cxIndex)
- , m_cxTranslationUnit(cxTranslationUnit)
-{
-}
-
-bool TranslationUnit::isNull() const
-{
- return !m_cxTranslationUnit || !m_cxIndex || m_filePath.isEmpty() || m_id.isEmpty();
-}
-
-Utf8String TranslationUnit::id() const
-{
- return m_id;
-}
-
-Utf8String TranslationUnit::filePath() const
-{
- return m_filePath;
-}
-
-CXIndex &TranslationUnit::cxIndex() const
-{
- return m_cxIndex;
-}
-
-CXTranslationUnit &TranslationUnit::cxTranslationUnit() const
-{
- return m_cxTranslationUnit;
-}
-
-TranslationUnitUpdateResult TranslationUnit::update(
- const TranslationUnitUpdateInput &parseInput) const
-{
- TranslationUnitUpdater updater(id(), cxIndex(), cxTranslationUnit(), parseInput);
-
- return updater.update(TranslationUnitUpdater::UpdateMode::AsNeeded);
-}
-
-TranslationUnitUpdateResult TranslationUnit::parse(
- const TranslationUnitUpdateInput &parseInput) const
-{
- TranslationUnitUpdater updater(id(), cxIndex(), cxTranslationUnit(), parseInput);
-
- return updater.update(TranslationUnitUpdater::UpdateMode::ParseIfNeeded);
-}
-
-TranslationUnitUpdateResult TranslationUnit::reparse(
- const TranslationUnitUpdateInput &parseInput) const
-{
- TranslationUnitUpdater updater(id(), cxIndex(), cxTranslationUnit(), parseInput);
-
- return updater.update(TranslationUnitUpdater::UpdateMode::ForceReparse);
-}
-
-bool TranslationUnit::suspend() const
-{
- return clang_suspendTranslationUnit(cxTranslationUnit());
-}
-
-CodeCompletions TranslationUnit::complete(UnsavedFiles &unsavedFiles, uint line, uint column,
- int funcNameStartLine, int funcNameStartColumn) const
-{
- return CodeCompleter(*this, unsavedFiles).complete(line, column, funcNameStartLine,
- funcNameStartColumn);
-}
-
-void TranslationUnit::extractAnnotations(
- DiagnosticContainer &firstHeaderErrorDiagnostic,
- QVector<DiagnosticContainer> &mainFileDiagnostics,
- QVector<TokenInfoContainer> &tokenInfos,
- QVector<SourceRangeContainer> &skippedSourceRanges) const
-{
- extractDiagnostics(firstHeaderErrorDiagnostic, mainFileDiagnostics);
- tokenInfos = this->tokenInfos().toTokenInfoContainers();
- skippedSourceRanges = this->skippedSourceRanges().toSourceRangeContainers();
-}
-
-ToolTipInfo TranslationUnit::tooltip(UnsavedFiles &unsavedFiles,
- const Utf8String &textCodecName,
- uint line,
- uint column) const
-{
- return collectToolTipInfo(unsavedFiles,
- textCodecName,
- filePath(),
- m_cxTranslationUnit,
- line,
- column);
-}
-
-ReferencesResult TranslationUnit::references(uint line, uint column, bool localReferences) const
-{
- return collectReferences(m_cxTranslationUnit, line, column, localReferences);
-}
-
-DiagnosticSet TranslationUnit::diagnostics() const
-{
- return DiagnosticSet(m_cxTranslationUnit, clang_getDiagnosticSetFromTU(m_cxTranslationUnit));
-}
-
-SourceLocation TranslationUnit::sourceLocationAt(uint line,uint column) const
-{
- return SourceLocation(m_cxTranslationUnit,
- clang_getLocation(m_cxTranslationUnit,
- clang_getFile(m_cxTranslationUnit,
- m_filePath.constData()),
- line, column));
-}
-
-SourceLocation TranslationUnit::sourceLocationAt(const Utf8String &filePath,
- uint line,
- uint column) const
-{
- return SourceLocation(m_cxTranslationUnit,
- clang_getLocation(m_cxTranslationUnit,
- clang_getFile(m_cxTranslationUnit,
- filePath.constData()),
- line, column));
-}
-
-SourceRange TranslationUnit::sourceRange(uint fromLine,
- uint fromColumn,
- uint toLine,
- uint toColumn) const
-{
- return SourceRange(sourceLocationAt(fromLine, fromColumn),
- sourceLocationAt(toLine, toColumn));
-}
-
-Cursor TranslationUnit::cursorAt(uint line, uint column) const
-{
- return clang_getCursor(m_cxTranslationUnit, sourceLocationAt(line, column));
-}
-
-Cursor TranslationUnit::cursorAt(const Utf8String &filePath,
- uint line,
- uint column) const
-{
- return clang_getCursor(m_cxTranslationUnit, sourceLocationAt(filePath, line, column));
-}
-
-Cursor TranslationUnit::cursor() const
-{
- return clang_getTranslationUnitCursor(m_cxTranslationUnit);
-}
-
-TokenProcessor<TokenInfo> TranslationUnit::tokenInfos() const
-{
- return tokenInfosInRange(cursor().sourceRange());
-}
-
-TokenProcessor<TokenInfo> TranslationUnit::tokenInfosInRange(const SourceRange &range) const
-{
- return TokenProcessor<TokenInfo>(range);
-}
-
-TokenProcessor<FullTokenInfo> TranslationUnit::fullTokenInfos() const
-{
- return fullTokenInfosInRange(cursor().sourceRange());
-}
-
-TokenProcessor<FullTokenInfo> TranslationUnit::fullTokenInfosInRange(const SourceRange &range) const
-{
- return TokenProcessor<FullTokenInfo>(range);
-}
-
-SkippedSourceRanges TranslationUnit::skippedSourceRanges() const
-{
- return SkippedSourceRanges(m_cxTranslationUnit, m_filePath.constData());
-}
-
-static bool isMainFileDiagnostic(const Utf8String &mainFilePath, const Diagnostic &diagnostic)
-{
- return diagnostic.location().filePath() == mainFilePath;
-}
-
-static bool isHeaderErrorDiagnostic(const Utf8String &mainFilePath, const Diagnostic &diagnostic)
-{
- const bool isCritical = diagnostic.severity() == DiagnosticSeverity::Error
- || diagnostic.severity() == DiagnosticSeverity::Fatal;
- return isCritical && diagnostic.location().filePath() != mainFilePath;
-}
-
-void TranslationUnit::extractDiagnostics(DiagnosticContainer &firstHeaderErrorDiagnostic,
- QVector<DiagnosticContainer> &mainFileDiagnostics) const
-{
- mainFileDiagnostics.clear();
- mainFileDiagnostics.reserve(int(diagnostics().size()));
-
- bool hasFirstHeaderErrorDiagnostic = false;
-
- for (const Diagnostic &diagnostic : diagnostics()) {
- if (!hasFirstHeaderErrorDiagnostic && isHeaderErrorDiagnostic(m_filePath, diagnostic)) {
- hasFirstHeaderErrorDiagnostic = true;
- firstHeaderErrorDiagnostic = diagnostic.toDiagnosticContainer();
- }
-
- if (isMainFileDiagnostic(m_filePath, diagnostic))
- mainFileDiagnostics.push_back(diagnostic.toDiagnosticContainer());
- }
-}
-
-FollowSymbolResult TranslationUnit::followSymbol(uint line, uint column) const
-{
- return FollowSymbol::followSymbol(m_cxTranslationUnit, cursorAt(line, column), line, column);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunit.h b/src/tools/clangbackend/source/clangtranslationunit.h
deleted file mode 100644
index 83c8d196a6a..00000000000
--- a/src/tools/clangbackend/source/clangtranslationunit.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "fulltokeninfo.h"
-#include "tokenprocessor.h"
-
-#include <clangsupport/codecompletion.h>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class Cursor;
-class DiagnosticContainer;
-class DiagnosticSet;
-class FollowSymbolResult;
-class ReferencesResult;
-class SkippedSourceRanges;
-class SourceLocation;
-class SourceRange;
-class SourceRangeContainer;
-class ToolTipInfo;
-class TranslationUnitUpdateInput;
-class TranslationUnitUpdateResult;
-class UnsavedFiles;
-class CommandLineArguments;
-
-class TranslationUnit
-{
-public:
- TranslationUnit(const Utf8String &id,
- const Utf8String &filePath,
- CXIndex &cxIndex,
- CXTranslationUnit &cxTranslationUnit);
-
- bool isNull() const;
-
- Utf8String id() const;
-
- Utf8String filePath() const;
- CXIndex &cxIndex() const;
- CXTranslationUnit &cxTranslationUnit() const;
-
- bool suspend() const;
-
- TranslationUnitUpdateResult update(const TranslationUnitUpdateInput &parseInput) const;
- TranslationUnitUpdateResult parse(const TranslationUnitUpdateInput &parseInput) const;
- TranslationUnitUpdateResult reparse(const TranslationUnitUpdateInput &parseInput) const;
-
- CodeCompletions complete(UnsavedFiles &unsavedFiles, uint line, uint column,
- int funcNameStartLine, int funcNameStartColumn) const;
-
- void extractDiagnostics(DiagnosticContainer &firstHeaderErrorDiagnostic,
- QVector<DiagnosticContainer> &mainFileDiagnostics) const;
- void extractAnnotations(DiagnosticContainer &firstHeaderErrorDiagnostic,
- QVector<DiagnosticContainer> &mainFileDiagnostics,
- QVector<TokenInfoContainer> &tokenInfos,
- QVector<SourceRangeContainer> &skippedSourceRanges) const;
-
- ReferencesResult references(uint line, uint column, bool localReferences = false) const;
- ToolTipInfo tooltip(UnsavedFiles &unsavedFiles,
- const Utf8String &textCodecName,
- uint line,
- uint column) const;
- DiagnosticSet diagnostics() const;
-
- SourceLocation sourceLocationAt(uint line, uint column) const;
- SourceLocation sourceLocationAt(const Utf8String &filePath, uint line, uint column) const;
- SourceRange sourceRange(uint fromLine, uint fromColumn, uint toLine, uint toColumn) const;
-
- Cursor cursorAt(uint line, uint column) const;
- Cursor cursorAt(const Utf8String &filePath, uint line, uint column) const;
- Cursor cursor() const;
-
- TokenProcessor<TokenInfo> tokenInfos() const;
- TokenProcessor<TokenInfo> tokenInfosInRange(const SourceRange &range) const;
-
- TokenProcessor<FullTokenInfo> fullTokenInfos() const;
- TokenProcessor<FullTokenInfo> fullTokenInfosInRange(const SourceRange &range) const;
-
- SkippedSourceRanges skippedSourceRanges() const;
- FollowSymbolResult followSymbol(uint line, uint column) const;
-
-private:
- const Utf8String m_id;
- const Utf8String m_filePath;
- CXIndex &m_cxIndex;
- CXTranslationUnit &m_cxTranslationUnit;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunits.cpp b/src/tools/clangbackend/source/clangtranslationunits.cpp
deleted file mode 100644
index 6175ea74a06..00000000000
--- a/src/tools/clangbackend/source/clangtranslationunits.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangtranslationunits.h"
-
-#include "clangexceptions.h"
-#include "clangtranslationunit.h"
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-#include <QFileInfo>
-#include <QLoggingCategory>
-#include <QUuid>
-
-static Q_LOGGING_CATEGORY(tuLog, "qtc.clangbackend.translationunits", QtWarningMsg);
-
-namespace ClangBackEnd {
-
-TranslationUnits::TranslationUnitData::TranslationUnitData(const Utf8String &id)
- : id(id)
-{}
-
-TranslationUnits::TranslationUnitData::~TranslationUnitData()
-{
- qCDebug(tuLog) << "Destroying TranslationUnit" << id;
- clang_disposeTranslationUnit(cxTranslationUnit);
- clang_disposeIndex(cxIndex);
-}
-
-TranslationUnits::TranslationUnits(const Utf8String &filePath)
- : m_filePath(filePath)
-{
-}
-
-TranslationUnit TranslationUnits::createAndAppend()
-{
- const Utf8String id = Utf8String::fromByteArray(QUuid::createUuid().toByteArray());
- qCDebug(tuLog) << "Creating TranslationUnit" << id << "for" << QFileInfo(m_filePath).fileName();
-
- m_units.append(TranslationUnitDataPtr(new TranslationUnitData(id)));
-
- return toTranslationUnit(m_units.last());
-}
-
-void TranslationUnits::removeAll()
-{
- m_units.clear();
-}
-
-TranslationUnit TranslationUnits::get(PreferredTranslationUnit type)
-{
- if (m_units.isEmpty())
- throw TranslationUnitDoesNotExist(m_filePath);
-
- if (m_units.size() == 1)
- return toTranslationUnit(m_units.first());
-
- if (areAllTranslationUnitsParsed())
- return getPreferredTranslationUnit(type);
-
- if (type == PreferredTranslationUnit::LastUninitialized)
- return toTranslationUnit(m_units.last());
-
- return toTranslationUnit(m_units.first());
-}
-
-void TranslationUnits::updateParseTimePoint(const Utf8String &translationUnitId,
- TimePoint timePoint)
-{
- QTC_CHECK(timePoint != TimePoint());
-
- findUnit(translationUnitId).parseTimePoint = timePoint;
-
- qCDebug(tuLog) << "Updated" << translationUnitId << "for" << QFileInfo(m_filePath).fileName()
- << "RecentlyParsed:" << get(PreferredTranslationUnit::RecentlyParsed).id()
- << "PreviouslyParsed:" << get(PreferredTranslationUnit::PreviouslyParsed).id();
-}
-
-TimePoint TranslationUnits::parseTimePoint(const Utf8String &translationUnitId)
-{
- return findUnit(translationUnitId).parseTimePoint;
-}
-
-bool TranslationUnits::areAllTranslationUnitsParsed() const
-{
- return Utils::allOf(m_units, [](const TranslationUnitDataPtr &unit) {
- return unit->parseTimePoint != TimePoint();
- });
-}
-
-bool TranslationUnits::hasParsedTranslationUnit() const
-{
- return Utils::anyOf(m_units, [](const TranslationUnitDataPtr &unit) {
- return unit->parseTimePoint != TimePoint();
- });
-}
-
-int TranslationUnits::size() const
-{
- return m_units.size();
-}
-
-TranslationUnit TranslationUnits::getPreferredTranslationUnit(PreferredTranslationUnit type)
-{
- using TuDataPtr = TranslationUnitDataPtr;
-
- const auto lessThan = [](const TuDataPtr &a, const TuDataPtr &b) {
- return a->parseTimePoint < b->parseTimePoint;
- };
- auto it = type == PreferredTranslationUnit::RecentlyParsed
- ? std::max_element(m_units.begin(), m_units.end(), lessThan)
- : std::min_element(m_units.begin(), m_units.end(), lessThan);
-
- if (it == m_units.end())
- throw TranslationUnitDoesNotExist(m_filePath);
-
- return toTranslationUnit(*it);
-}
-
-TranslationUnits::TranslationUnitData &TranslationUnits::findUnit(
- const Utf8String &translationUnitId)
-{
- for (TranslationUnitDataPtr &unit : m_units) {
- if (translationUnitId == unit->id)
- return *unit;
- }
-
- throw TranslationUnitDoesNotExist(m_filePath);
-}
-
-TranslationUnit TranslationUnits::toTranslationUnit(const TranslationUnitDataPtr &unit)
-{
- return TranslationUnit(unit->id,
- m_filePath,
- unit->cxIndex,
- unit->cxTranslationUnit);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunits.h b/src/tools/clangbackend/source/clangtranslationunits.h
deleted file mode 100644
index eed9b2d1ea8..00000000000
--- a/src/tools/clangbackend/source/clangtranslationunits.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangbackend_global.h"
-#include "clangclock.h"
-
-#include <utf8string.h>
-
-#include <clang-c/Index.h>
-
-#include <QList>
-#include <QSharedPointer>
-
-namespace ClangBackEnd {
-
-class TranslationUnit;
-
-class TranslationUnits
-{
-public:
- class TranslationUnitData {
- public:
- TranslationUnitData(const Utf8String &id);
- ~TranslationUnitData();
-
- Utf8String id;
-
- CXTranslationUnit cxTranslationUnit = nullptr;
- CXIndex cxIndex = nullptr;
-
- TimePoint parseTimePoint;
- };
- using TranslationUnitDataPtr = QSharedPointer<TranslationUnitData>;
-
-public:
- TranslationUnits(const Utf8String &filePath);
-
- TranslationUnit createAndAppend();
- void removeAll();
- TranslationUnit get(PreferredTranslationUnit type = PreferredTranslationUnit::RecentlyParsed);
- void updateParseTimePoint(const Utf8String &translationUnitId, TimePoint timePoint);
-
- bool areAllTranslationUnitsParsed() const;
- bool hasParsedTranslationUnit() const;
-
-public: // for tests
- int size() const;
- TimePoint parseTimePoint(const Utf8String &translationUnitId);
-
-private:
- TranslationUnit getPreferredTranslationUnit(PreferredTranslationUnit type);
- TranslationUnitData &findUnit(const Utf8String &translationUnitId);
- TranslationUnit toTranslationUnit(const TranslationUnitDataPtr &unit);
-
-private:
- Utf8String m_filePath;
- QList<TranslationUnitDataPtr> m_units;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunitupdater.cpp b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
deleted file mode 100644
index 0383a1028f1..00000000000
--- a/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangtranslationunitupdater.h"
-
-#include "clangbackend_global.h"
-#include "clangfilepath.h"
-#include "clangstring.h"
-#include "clangunsavedfilesshallowarguments.h"
-
-#include <QLoggingCategory>
-
-static Q_LOGGING_CATEGORY(verboseLibLog, "qtc.clangbackend.verboselib", QtWarningMsg);
-
-static bool isVerboseModeEnabled()
-{
- return verboseLibLog().isDebugEnabled();
-}
-
-namespace ClangBackEnd {
-
-TranslationUnitUpdater::TranslationUnitUpdater(const Utf8String translationUnitId,
- CXIndex &index,
- CXTranslationUnit &cxTranslationUnit,
- const TranslationUnitUpdateInput &updateData)
- : m_cxIndex(index)
- , m_cxTranslationUnit(cxTranslationUnit)
- , m_in(updateData)
-{
- m_out.translationUnitId = translationUnitId;
-}
-
-TranslationUnitUpdateResult TranslationUnitUpdater::update(UpdateMode mode)
-{
- createIndexIfNeeded();
-
- switch (mode) {
- case UpdateMode::AsNeeded:
- recreateAndParseIfNeeded();
- reparseIfNeeded();
- break;
- case UpdateMode::ParseIfNeeded:
- recreateAndParseIfNeeded();
- break;
- case UpdateMode::ForceReparse:
- reparse();
- break;
- }
-
- return m_out;
-}
-
-void TranslationUnitUpdater::recreateAndParseIfNeeded()
-{
- removeTranslationUnitIfProjectPartWasChanged();
- createTranslationUnitIfNeeded();
-}
-
-void TranslationUnitUpdater::removeTranslationUnitIfProjectPartWasChanged()
-{
- if (m_in.parseNeeded) {
- clang_disposeTranslationUnit(m_cxTranslationUnit);
- m_cxTranslationUnit = nullptr;
- }
-}
-
-#define RETURN_TEXT_FOR_CASE(enumValue) case enumValue: return #enumValue
-static const char *errorCodeToText(CXErrorCode errorCode)
-{
- switch (errorCode) {
- RETURN_TEXT_FOR_CASE(CXError_Success);
- RETURN_TEXT_FOR_CASE(CXError_Failure);
- RETURN_TEXT_FOR_CASE(CXError_Crashed);
- RETURN_TEXT_FOR_CASE(CXError_InvalidArguments);
- RETURN_TEXT_FOR_CASE(CXError_ASTReadError);
- }
-
- return "UnknownCXErrorCode";
-}
-#undef RETURN_TEXT_FOR_CASE
-
-void TranslationUnitUpdater::createTranslationUnitIfNeeded()
-{
- if (!m_cxTranslationUnit) {
- m_cxTranslationUnit = CXTranslationUnit();
-
- const auto args = commandLineArguments();
- if (isVerboseModeEnabled())
- args.print();
-
- UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments();
-
- m_parseErrorCode = clang_parseTranslationUnit2(m_cxIndex,
- nullptr,
- args.data(),
- args.count(),
- unsaved.data(),
- unsaved.count(),
- defaultParseOptions(),
- &m_cxTranslationUnit);
-
-
-
- if (parseWasSuccessful()) {
- updateIncludeFilePaths();
- m_out.parseTimePoint = Clock::now();
- } else {
- qWarning() << "Parsing" << m_in.filePath << "failed:"
- << errorCodeToText(m_parseErrorCode);
- m_out.hasParseOrReparseFailed = true;
- }
- }
-}
-
-void TranslationUnitUpdater::reparseIfNeeded()
-{
- if (m_in.reparseNeeded)
- reparse();
-}
-
-void TranslationUnitUpdater::reparse()
-{
- UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments();
-
- m_reparseErrorCode = clang_reparseTranslationUnit(
- m_cxTranslationUnit,
- unsaved.count(),
- unsaved.data(),
- clang_defaultReparseOptions(m_cxTranslationUnit));
-
-
- if (reparseWasSuccessful()) {
- updateIncludeFilePaths();
-
- m_out.reparseTimePoint = Clock::now();
- m_out.needsToBeReparsedChangeTimePoint = m_in.needsToBeReparsedChangeTimePoint;
- } else {
- qWarning() << "Reparsing" << m_in.filePath << "failed:" << m_reparseErrorCode;
- m_out.hasParseOrReparseFailed = true;
- }
-}
-
-void TranslationUnitUpdater::updateIncludeFilePaths()
-{
- m_out.dependedOnFilePaths.clear();
- m_out.dependedOnFilePaths.insert(m_in.filePath);
-
- clang_getInclusions(m_cxTranslationUnit,
- includeCallback,
- const_cast<TranslationUnitUpdater *>(this));
-}
-
-uint TranslationUnitUpdater::defaultParseOptions()
-{
- return CXTranslationUnit_CacheCompletionResults
- | CXTranslationUnit_PrecompiledPreamble
- | CXTranslationUnit_CreatePreambleOnFirstParse
- | CXTranslationUnit_SkipFunctionBodies
- | CXTranslationUnit_LimitSkipFunctionBodiesToPreamble
-// CLANG-UPGRADE-CHECK: Remove when required version is 9
-#if (LLVM_VERSION_MAJOR >= 9) || defined(CINDEX_VERSION_HAS_SKIPWARNINGSFROMINCLUDEDFILES_BACKPORTED)
- | CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles
-#endif
- | CXTranslationUnit_IncludeBriefCommentsInCodeCompletion
- | CXTranslationUnit_DetailedPreprocessingRecord
- | CXTranslationUnit_KeepGoing;
-}
-
-void TranslationUnitUpdater::createIndexIfNeeded()
-{
- if (!m_cxIndex) {
- const bool displayDiagnostics = isVerboseModeEnabled();
- m_cxIndex = clang_createIndex(1, displayDiagnostics);
- }
-}
-
-void TranslationUnitUpdater::includeCallback(CXFile included_file,
- CXSourceLocation *,
- unsigned, CXClientData clientData)
-{
- ClangString includeFilePath(clang_getFileName(included_file));
-
- TranslationUnitUpdater *updater = static_cast<TranslationUnitUpdater *>(clientData);
-
- updater->m_out.dependedOnFilePaths.insert(FilePath::fromNativeSeparators(includeFilePath));
-}
-
-bool TranslationUnitUpdater::parseWasSuccessful() const
-{
- return m_parseErrorCode == CXError_Success;
-}
-
-bool TranslationUnitUpdater::reparseWasSuccessful() const
-{
- return m_reparseErrorCode == 0;
-}
-
-CommandLineArguments TranslationUnitUpdater::commandLineArguments() const
-{
- return CommandLineArguments(m_in.filePath.constData(),
- m_in.compilationArguments,
- isVerboseModeEnabled());
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunitupdater.h b/src/tools/clangbackend/source/clangtranslationunitupdater.h
deleted file mode 100644
index a0f0d0ba3bf..00000000000
--- a/src/tools/clangbackend/source/clangtranslationunitupdater.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangclock.h"
-
-#include "commandlinearguments.h"
-#include "unsavedfiles.h"
-#include "utf8stringvector.h"
-
-#include <clang-c/Index.h>
-
-#include <QSet>
-
-namespace ClangBackEnd {
-
-class TranslationUnitUpdateInput {
-public:
- bool parseNeeded = false;
- bool reparseNeeded = false;
-
- TimePoint needsToBeReparsedChangeTimePoint;
-
- Utf8String filePath;
- Utf8StringVector compilationArguments;
-
- UnsavedFiles unsavedFiles;
-};
-
-class TranslationUnitUpdateResult {
-public:
- bool hasParsed() const
- { return parseTimePoint != TimePoint(); }
-
- bool hasReparsed() const
- { return reparseTimePoint != TimePoint(); }
-
-public:
- Utf8String translationUnitId;
-
- bool hasParseOrReparseFailed = false;
- TimePoint parseTimePoint;
- TimePoint reparseTimePoint;
- TimePoint needsToBeReparsedChangeTimePoint;
-
- QSet<Utf8String> dependedOnFilePaths;
-};
-
-class TranslationUnitUpdater {
-public:
- enum class UpdateMode {
- AsNeeded,
- ParseIfNeeded,
- ForceReparse,
- };
-
-public:
- TranslationUnitUpdater(const Utf8String translationUnitId,
- CXIndex &index,
- CXTranslationUnit &cxTranslationUnit,
- const TranslationUnitUpdateInput &in);
-
- TranslationUnitUpdateResult update(UpdateMode mode);
-
- CommandLineArguments commandLineArguments() const;
- static uint defaultParseOptions();
-
-private:
- void createIndexIfNeeded();
- void createTranslationUnitIfNeeded();
- void removeTranslationUnitIfProjectPartWasChanged();
- void reparseIfNeeded();
- void recreateAndParseIfNeeded();
- void reparse();
-
- void updateIncludeFilePaths();
- static void includeCallback(CXFile included_file,
- CXSourceLocation *,
- unsigned,
- CXClientData clientData);
-
- bool parseWasSuccessful() const;
- bool reparseWasSuccessful() const;
-
-private:
- CXIndex &m_cxIndex;
- CXTranslationUnit &m_cxTranslationUnit;
-
- CXErrorCode m_parseErrorCode = CXError_Success;
- int m_reparseErrorCode = 0;
-
- const TranslationUnitUpdateInput m_in;
- TranslationUnitUpdateResult m_out;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtype.cpp b/src/tools/clangbackend/source/clangtype.cpp
deleted file mode 100644
index 61b5d2bca8c..00000000000
--- a/src/tools/clangbackend/source/clangtype.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangtype.h"
-
-#include "clangstring.h"
-#include "cursor.h"
-
-#include <utf8string.h>
-
-#include <ostream>
-
-namespace ClangBackEnd {
-
-bool Type::isValid() const
-{
- return m_cxType.kind != CXType_Invalid;
-}
-
-bool Type::isConstant() const
-{
- return clang_isConstQualifiedType(m_cxType);
-}
-
-bool Type::isConstantReference()
-{
- return isLValueReference() && pointeeType().isConstant();
-}
-
-bool Type::isPointer() const
-{
- return m_cxType.kind == CXType_Pointer;
-}
-
-bool Type::isPointerToConstant() const
-{
- return isPointer() && pointeeType().isConstant();
-}
-
-bool Type::isConstantPointer() const
-{
- return isPointer() && isConstant();
-}
-
-bool Type::isLValueReference() const
-{
- return m_cxType.kind == CXType_LValueReference;
-}
-
-bool Type::isReferencingConstant() const
-{
- return (isPointer() || isLValueReference()) && pointeeType().isConstant();
-}
-
-bool Type::isOutputArgument() const
-{
- if (isLValueReference() && !pointeeType().isConstant())
- return true;
-
- // We consider a pointer an output argument if it is non-const at any level.
- // This is consistent with how we categorize references in CppEditor.
- Type t = *this;
- while (t.isPointer()) {
- t = t.pointeeType();
- if (!t.isConstant())
- return true;
- }
- return false;
-}
-
-bool Type::isBuiltinType() const
-{
- return m_cxType.kind >= CXType_FirstBuiltin && m_cxType.kind <= CXType_LastBuiltin;
-}
-
-bool Type::isUnsigned() const
-{
- return m_cxType.kind == CXType_UChar
- || m_cxType.kind == CXType_UShort
- || m_cxType.kind == CXType_UInt
- || m_cxType.kind == CXType_ULong
- || m_cxType.kind == CXType_ULongLong
- || m_cxType.kind == CXType_UInt128;
-}
-
-Utf8String Type::utf8Spelling() const
-{
- return ClangString(clang_getTypeSpelling(m_cxType));
-}
-
-ClangString Type::spelling() const
-{
- return ClangString(clang_getTypeSpelling(m_cxType));
-}
-
-static const char *builtinTypeToText(CXTypeKind kind)
-{
- // CLANG-UPGRADE-CHECK: Check for added built-in types.
-
- switch (kind) {
- case CXType_Void:
- return "void";
- case CXType_Bool:
- return "bool";
-
- // See also ${CLANG_REPOSITORY}/lib/Sema/SemaChecking.cpp - IsSameCharType().
- case CXType_Char_U:
- case CXType_UChar:
- return "unsigned char";
- case CXType_Char_S:
- case CXType_SChar:
- return "signed char";
-
- case CXType_Char16:
- return "char16_t";
- case CXType_Char32:
- return "char32_t";
- case CXType_WChar:
- return "wchar_t";
-
- case CXType_UShort:
- return "unsigned short";
- case CXType_UInt:
- return "unsigned int";
- case CXType_ULong:
- return "unsigned long";
- case CXType_ULongLong:
- return "unsigned long long";
- case CXType_Short:
- return "short";
-
- case CXType_Int:
- return "int";
- case CXType_Long:
- return "long";
- case CXType_LongLong:
- return "long long";
-
- case CXType_Float:
- return "float";
- case CXType_Double:
- return "double";
- case CXType_LongDouble:
- return "long double";
-
- case CXType_NullPtr:
- return "nullptr_t";
-
- // https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html
- case CXType_Int128: return "__int128";
- case CXType_UInt128: return "unsigned __int128";
-
- // https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
- case CXType_Float128: return "__float128";
- case CXType_Float16: return "_Float16";
-
- // https://www.khronos.org/registry/OpenCL/sdk/2.1/docs/man/xhtml/scalarDataTypes.html
- case CXType_Half:
- return "half";
-
- default:
- return "";
- }
-}
-
-Utf8String Type::builtinTypeToString() const
-{
- const char *text = builtinTypeToText(m_cxType.kind);
- return Utf8String::fromByteArray(QByteArray::fromRawData(text, int(strlen(text))));
-}
-
-int Type::argumentCount() const
-{
- return clang_getNumArgTypes(m_cxType);
-}
-
-Type Type::alias() const
-{
- return clang_getTypedefDeclUnderlyingType(clang_getTypeDeclaration(m_cxType));
-}
-
-Type Type::canonical() const
-{
- return clang_getCanonicalType(m_cxType);
-}
-
-Type Type::classType() const
-{
- return clang_Type_getClassType(m_cxType);
-}
-
-Type Type::pointeeType() const
-{
- return clang_getPointeeType(m_cxType);
-}
-
-Type Type::resultType() const
-{
- return clang_getResultType(m_cxType);
-}
-
-Type Type::argument(int index) const
-{
- return clang_getArgType(m_cxType, index);
-}
-
-Cursor Type::declaration() const
-{
- return clang_getTypeDeclaration(m_cxType);
-}
-
-long long Type::sizeOf(bool *isValid) const
-{
- const long long size = clang_Type_getSizeOf(m_cxType);
- *isValid = size != CXTypeLayoutError_Invalid
- && size != CXTypeLayoutError_Incomplete
- && size != CXTypeLayoutError_Dependent;
-
- return size;
-}
-
-CXTypeKind Type::kind() const
-{
- return m_cxType.kind;
-}
-
-Type::Type(CXType cxType)
- : m_cxType(cxType)
-{
-}
-
-bool operator==(Type first, Type second)
-{
- return clang_equalTypes(first.m_cxType, second.m_cxType);
-}
-
-bool operator!=(Type first, Type second)
-{
- return !operator==(first, second);
-}
-
-std::ostream &operator<<(std::ostream &os, CXTypeKind typeKind)
-{
- ClangString typeKindSpelling(clang_getTypeKindSpelling(typeKind));
-
- return os << typeKindSpelling.cString();
-}
-
-std::ostream &operator<<(std::ostream &os, const Type &type)
-{
- ClangString typeKindSpelling(clang_getTypeKindSpelling(type.kind()));
- os << typeKindSpelling
- << ": \"" << type.spelling() << "\"";
-
- return os;
-}
-
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/clangtype.h b/src/tools/clangbackend/source/clangtype.h
deleted file mode 100644
index c8dca274d93..00000000000
--- a/src/tools/clangbackend/source/clangtype.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clang-c/Index.h>
-
-#include <iosfwd>
-
-class Utf8String;
-
-namespace ClangBackEnd {
-
-class Cursor;
-class ClangString;
-
-class Type
-{
- friend class Cursor;
- friend bool operator==(Type first, Type second);
- friend bool operator!=(Type first, Type second);
-
-public:
- bool isValid() const;
-
- bool isConstant() const;
- bool isConstantReference();
- bool isPointer() const;
- bool isPointerToConstant() const;
- bool isConstantPointer() const;
- bool isLValueReference() const;
- bool isReferencingConstant() const;
- bool isOutputArgument() const;
- bool isBuiltinType() const;
- bool isUnsigned() const;
-
- Utf8String utf8Spelling() const;
- ClangString spelling() const;
- Utf8String builtinTypeToString() const;
- int argumentCount() const;
-
- Type alias() const;
- Type canonical() const;
- Type classType() const;
- Type pointeeType() const;
- Type resultType() const;
- Type argument(int index) const;
-
- Cursor declaration() const;
-
- long long sizeOf(bool *isValid) const;
-
- CXTypeKind kind() const;
-
-private:
- Type(CXType cxType);
-
-private:
- CXType m_cxType;
-};
-
-std::ostream &operator<<(std::ostream &os, CXTypeKind typeKind);
-std::ostream &operator<<(std::ostream &os, const Type &type);
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.cpp b/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.cpp
deleted file mode 100644
index 6fe23d606fb..00000000000
--- a/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangunsavedfilesshallowarguments.h"
-#include "clangfilepath.h"
-
-#include "unsavedfile.h"
-#include "unsavedfiles.h"
-
-namespace ClangBackEnd {
-
-UnsavedFilesShallowArguments::UnsavedFilesShallowArguments(const UnsavedFiles &unsavedFiles)
-{
- const int unsavedFilesCount = int(unsavedFiles.count());
- m_cxUnsavedFiles.resize(unsavedFilesCount);
-
- for (int i = 0, total = unsavedFilesCount; i < total; ++i) {
- const UnsavedFile &unsavedFile = unsavedFiles.at(i);
- m_cxUnsavedFiles[i].Filename = unsavedFile.nativeFilePath().constData();
- m_cxUnsavedFiles[i].Contents = unsavedFile.fileContent().constData();
- m_cxUnsavedFiles[i].Length = uint(unsavedFile.fileContent().byteSize());
- }
-}
-
-uint UnsavedFilesShallowArguments::count() const
-{
- return uint(m_cxUnsavedFiles.count());
-}
-
-CXUnsavedFile *UnsavedFilesShallowArguments::data()
-{
- return m_cxUnsavedFiles.data();
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.h b/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.h
deleted file mode 100644
index 20c8981ef26..00000000000
--- a/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QVector>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class UnsavedFile;
-class UnsavedFiles;
-
-class UnsavedFilesShallowArguments {
-public:
- UnsavedFilesShallowArguments() = default;
- UnsavedFilesShallowArguments(const UnsavedFiles &unsavedFiles);
-
- uint count() const;
- CXUnsavedFile *data();
-
-private:
- QVector<CXUnsavedFile> m_cxUnsavedFiles;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangupdateannotationsjob.cpp b/src/tools/clangbackend/source/clangupdateannotationsjob.cpp
deleted file mode 100644
index bdd05512e66..00000000000
--- a/src/tools/clangbackend/source/clangupdateannotationsjob.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangupdateannotationsjob.h"
-
-#include <clangsupport/annotationsmessage.h>
-#include <clangsupport/clangsupportdebugutils.h>
-#include <clangsupport/clangcodemodelclientinterface.h>
-
-#include <utils/qtcassert.h>
-
-#include <QRegularExpression>
-
-namespace ClangBackEnd {
-
-// TODO: Add libclang API for this.
-static QSet<Utf8String> unresolvedFilePaths(const QVector<DiagnosticContainer> &diagnostics)
-{
- // We expect something like:
- // fatal error: 'ops.h' file not found
- QRegularExpression re("'(.*)' file not found");
- QSet<Utf8String> unresolved;
-
- for (const DiagnosticContainer &diagnostic : diagnostics) {
- if (diagnostic.severity == DiagnosticSeverity::Error
- && diagnostic.category == Utf8StringLiteral("Lexical or Preprocessor Issue")) {
- const QString path = re.match(diagnostic.text).captured(1);
- if (!path.isEmpty())
- unresolved << path;
- }
- }
-
- return unresolved;
-}
-
-IAsyncJob::AsyncPrepareResult UpdateAnnotationsJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(isExpectedJobRequestType(jobRequest), return AsyncPrepareResult());
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- const TranslationUnit translationUnit = *m_translationUnit;
- const TranslationUnitUpdateInput updateInput = createUpdateInput(m_pinnedDocument);
- setRunner([translationUnit, updateInput]() {
- TIME_SCOPE_DURATION("UpdateAnnotationsJobRunner");
-
- // Update
- UpdateAnnotationsJob::AsyncResult asyncResult;
- asyncResult.updateResult = translationUnit.update(updateInput);
-
- // Collect
- translationUnit.extractAnnotations(asyncResult.firstHeaderErrorDiagnostic,
- asyncResult.diagnostics,
- asyncResult.tokenInfos,
- asyncResult.skippedSourceRanges);
- asyncResult.unresolvedFilePaths.unite(
- unresolvedFilePaths({asyncResult.firstHeaderErrorDiagnostic}));
- asyncResult.unresolvedFilePaths.unite(unresolvedFilePaths(asyncResult.diagnostics));
-
- return asyncResult;
- });
-
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void UpdateAnnotationsJob::finalizeAsyncRun()
-{
- if (!context().isOutdated()) {
- const AsyncResult result = asyncResult();
-
- m_pinnedDocument.incorporateUpdaterResult(result.updateResult);
- m_pinnedDocument.setUnresolvedFilePaths(result.unresolvedFilePaths);
-
- context().client->annotations(AnnotationsMessage(m_pinnedFileContainer,
- result.diagnostics,
- result.firstHeaderErrorDiagnostic,
- result.tokenInfos,
- result.skippedSourceRanges));
- }
-}
-
-bool UpdateAnnotationsJob::isExpectedJobRequestType(const JobRequest &jobRequest) const
-{
- return jobRequest.type == JobRequest::Type::UpdateAnnotations;
-}
-
-TranslationUnitUpdateInput
-UpdateAnnotationsJob::createUpdateInput(const Document &document) const
-{
- return document.createUpdateInput();
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/clangupdateannotationsjob.h b/src/tools/clangbackend/source/clangupdateannotationsjob.h
deleted file mode 100644
index 8a813586ea7..00000000000
--- a/src/tools/clangbackend/source/clangupdateannotationsjob.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentjob.h"
-
-#include <clangsupport/diagnosticcontainer.h>
-#include <clangsupport/tokeninfocontainer.h>
-#include <clangsupport/sourcerangecontainer.h>
-
-#include <QSet>
-#include <QVector>
-
-namespace ClangBackEnd {
-
-struct UpdateAnnotationsJobResult
-{
- TranslationUnitUpdateResult updateResult;
- QSet<Utf8String> unresolvedFilePaths;
-
- ClangBackEnd::DiagnosticContainer firstHeaderErrorDiagnostic;
- QVector<ClangBackEnd::DiagnosticContainer> diagnostics;
- QVector<TokenInfoContainer> tokenInfos;
- QVector<SourceRangeContainer> skippedSourceRanges;
-};
-
-class UpdateAnnotationsJob : public DocumentJob<UpdateAnnotationsJobResult>
-{
-public:
- using AsyncResult = UpdateAnnotationsJobResult;
-
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-
-protected:
- virtual bool isExpectedJobRequestType(const JobRequest &jobRequest) const;
- virtual TranslationUnitUpdateInput createUpdateInput(const Document &document) const;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangupdateextraannotationsjob.cpp b/src/tools/clangbackend/source/clangupdateextraannotationsjob.cpp
deleted file mode 100644
index 7363a28758d..00000000000
--- a/src/tools/clangbackend/source/clangupdateextraannotationsjob.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangupdateextraannotationsjob.h"
-
-#include <clangsupport/annotationsmessage.h>
-#include <clangsupport/clangsupportdebugutils.h>
-#include <clangsupport/clangcodemodelclientinterface.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-IAsyncJob::AsyncPrepareResult UpdateExtraAnnotationsJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
-
- const TranslationUnit translationUnit = *m_translationUnit;
- setRunner([translationUnit]() {
- TIME_SCOPE_DURATION("UpdateExtraAnnotationsJobRunner");
- return translationUnit.fullTokenInfos().toTokenInfoContainers();
- });
-
- return AsyncPrepareResult{translationUnit.id()};
-}
-
-void UpdateExtraAnnotationsJob::finalizeAsyncRun()
-{
- if (context().isOutdated())
- return;
-
- context().client->annotations(AnnotationsMessage(m_pinnedFileContainer, asyncResult()));
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/clangupdateextraannotationsjob.h b/src/tools/clangbackend/source/clangupdateextraannotationsjob.h
deleted file mode 100644
index 2a0e0db84e4..00000000000
--- a/src/tools/clangbackend/source/clangupdateextraannotationsjob.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangdocumentjob.h"
-
-#include <clangsupport/tokeninfocontainer.h>
-
-namespace ClangBackEnd {
-
-using UpdateExtraAnnotationsJobResult = QVector<TokenInfoContainer>;
-
-class UpdateExtraAnnotationsJob : public DocumentJob<UpdateExtraAnnotationsJobResult>
-{
-public:
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/codecompleter.cpp b/src/tools/clangbackend/source/codecompleter.cpp
deleted file mode 100644
index ae49b650dd2..00000000000
--- a/src/tools/clangbackend/source/codecompleter.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "codecompleter.h"
-
-#include "clangbackend_global.h"
-#include "clangcodecompleteresults.h"
-#include "clangdocument.h"
-#include "clangexceptions.h"
-#include "clangfilepath.h"
-#include "clangstring.h"
-#include "clangtranslationunitupdater.h"
-#include "clangunsavedfilesshallowarguments.h"
-#include "codecompletionsextractor.h"
-#include "cursor.h"
-#include "sourcelocation.h"
-#include "sourcerange.h"
-#include "unsavedfile.h"
-#include "unsavedfiles.h"
-
-#include <utils/qtcassert.h>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-namespace {
-
-CodeCompletions toCodeCompletions(const UnsavedFile &unsavedFile,
- const ClangCodeCompleteResults &results,
- bool onlyFunctionOverloads)
-{
- if (results.isNull())
- return CodeCompletions();
-
- CodeCompletionsExtractor extractor(unsavedFile, results.data());
- CodeCompletions codeCompletions = extractor.extractAll(onlyFunctionOverloads);
-
- return codeCompletions;
-}
-
-// CLANG-UPGRADE-CHECK: Remove this workaround once we require LLVM/Clang 11 as that version makes
-// the workaround pointless.
-void filterUnknownContextResults(ClangCodeCompleteResults &results,
- const UnsavedFile &theUnsavedFile,
- uint line,
- uint column)
-{
- if (results.hasUnknownContext()) {
- bool positionIsOk = false;
- const uint position = theUnsavedFile.toUtf8Position(line, column - 1, &positionIsOk);
- if (positionIsOk && (theUnsavedFile.hasCharacterAt(position, '.')
- || (theUnsavedFile.hasCharacterAt(position - 1, '-')
- && theUnsavedFile.hasCharacterAt(position, '>')))) {
- results = {};
- }
- }
-}
-
-} // anonymous namespace
-
-CodeCompleter::CodeCompleter(const TranslationUnit &translationUnit,
- const UnsavedFiles &unsavedFiles)
- : translationUnit(translationUnit)
- , unsavedFiles(unsavedFiles)
-{
-}
-
-static void replaceWithOpeningParen(UnsavedFile &file, uint line, uint column)
-{
- bool ok;
- const uint pos = file.toUtf8Position(line, column, &ok);
- QTC_ASSERT(ok, return;);
- file.replaceAt(pos, 1, Utf8String("(", 1));
-}
-
-CodeCompletions CodeCompleter::complete(int line, int column,
- int funcNameStartLine,
- int funcNameStartColumn)
-{
- if (funcNameStartLine >= 0) {
- UnsavedFile &file = unsavedFiles.unsavedFile(translationUnit.filePath());
- // Replace '{' by '(' to get proper FunctionOverloadCompletionKind for constructor.
- if (file.hasCharacterAt(line, column - 1, '{'))
- replaceWithOpeningParen(file, line, column - 1);
- }
-
- // Check if we have a smart pointer completion and get proper constructor signatures in results.
- // Results are empty when it's not a smart pointer or this completion failed.
- ClangCodeCompleteResults clangCompletions = completeSmartPointerCreation(line,
- column,
- funcNameStartLine,
- funcNameStartColumn);
-
- // Default completion.
- if (clangCompletions.isNull() || clangCompletions.isEmpty())
- clangCompletions = completeHelper(line, column);
-
- filterUnknownContextResults(clangCompletions, unsavedFile(), line, column);
-
- return toCodeCompletions(unsavedFiles.unsavedFile(translationUnit.filePath()),
- clangCompletions,
- funcNameStartLine >= 0);
-}
-
-// For given "make_unique<T>" / "make_shared<T>" / "QSharedPointer<T>::create" return "new T("
-// Otherwize return empty QString
-static QString tweakName(const Utf8String &oldName)
-{
- if (!oldName.contains('>'))
- return QString();
-
- QString fullName = oldName.toString().trimmed();
- if (!fullName.endsWith('>')) {
- // This is the class<type>::method case - remove ::method part
- if (!fullName.endsWith("create") || !fullName.contains("QSharedPointer"))
- return QString();
- fullName = fullName.mid(0, fullName.lastIndexOf(':') - 1);
- } else if (!fullName.contains("make_unique") && !fullName.contains("make_shared")) {
- return QString();
- }
- int templateStart = fullName.indexOf('<');
- QString templatePart = fullName.mid(templateStart + 1,
- fullName.length() - templateStart - 2);
- return "new " + templatePart + "(";
-}
-
-ClangCodeCompleteResults CodeCompleter::completeSmartPointerCreation(uint line,
- uint column,
- int funcNameStartLine,
- int funcNameStartColumn)
-{
- if (column <= 1 || funcNameStartLine == -1)
- return ClangCodeCompleteResults();
-
- UnsavedFile &file = unsavedFiles.unsavedFile(translationUnit.filePath());
- if (!file.hasCharacterAt(line, column - 1, '('))
- return ClangCodeCompleteResults();
-
- bool ok;
- const uint startPos = file.toUtf8Position(funcNameStartLine, funcNameStartColumn, &ok);
- QTC_ASSERT(ok, return ClangCodeCompleteResults(););
- const uint endPos = file.toUtf8Position(line, column - 1, &ok);
- QTC_ASSERT(ok, return ClangCodeCompleteResults(););
-
- const Utf8String content = file.fileContent();
- const Utf8String oldName = content.mid(startPos, endPos - startPos);
- const QString updatedName = tweakName(oldName);
- if (updatedName.isEmpty())
- return ClangCodeCompleteResults();
-
- column += updatedName.length();
- file.replaceAt(endPos + 1, 0, updatedName);
-
- ClangCodeCompleteResults results = completeHelper(line, column);
- if (results.isEmpty()) {
- column -= updatedName.length();
- file.replaceAt(endPos + 1, updatedName.length(), QString());
- }
- return results;
-}
-
-ClangCodeCompleteResults CodeCompleter::completeHelper(uint line, uint column)
-{
- const Utf8String nativeFilePath = FilePath::toNativeSeparators(translationUnit.filePath());
- UnsavedFilesShallowArguments unsaved = unsavedFiles.shallowArguments();
-
- return clang_codeCompleteAt(translationUnit.cxTranslationUnit(),
- nativeFilePath.constData(),
- line,
- column,
- unsaved.data(),
- unsaved.count(),
- defaultOptions());
-}
-
-uint CodeCompleter::defaultOptions() const
-{
- uint options = CXCodeComplete_IncludeMacros
- | CXCodeComplete_IncludeCompletionsWithFixIts
- | CXCodeComplete_IncludeCodePatterns;
-
- if (TranslationUnitUpdater::defaultParseOptions()
- & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion) {
- options |= CXCodeComplete_IncludeBriefComments;
- }
-
- return options;
-}
-
-UnsavedFile &CodeCompleter::unsavedFile()
-{
- return unsavedFiles.unsavedFile(translationUnit.filePath());
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/codecompleter.h b/src/tools/clangbackend/source/codecompleter.h
deleted file mode 100644
index 3fdab36b57b..00000000000
--- a/src/tools/clangbackend/source/codecompleter.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangtranslationunit.h"
-#include "unsavedfiles.h"
-
-#include <codecompletion.h>
-
-#include <utf8stringvector.h>
-
-namespace ClangBackEnd {
-
-class ClangCodeCompleteResults;
-
-class CodeCompleter
-{
-public:
- CodeCompleter(const TranslationUnit &translationUnit,
- const UnsavedFiles &unsavedFiles);
-
- CodeCompletions complete(int line, int column,
- int funcNameStartLine = -1,
- int funcNameStartColumn = -1);
-
-private:
- uint defaultOptions() const;
- UnsavedFile &unsavedFile();
-
- ClangCodeCompleteResults completeHelper(uint line, uint column);
- ClangCodeCompleteResults completeSmartPointerCreation(uint line,
- uint column,
- int funcNameStartLine,
- int funcNameStartColumn);
-
-private:
- TranslationUnit translationUnit;
- UnsavedFiles unsavedFiles;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/codecompletionchunkconverter.cpp b/src/tools/clangbackend/source/codecompletionchunkconverter.cpp
deleted file mode 100644
index 76c578643f5..00000000000
--- a/src/tools/clangbackend/source/codecompletionchunkconverter.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "codecompletionchunkconverter.h"
-
-#include "clangstring.h"
-
-namespace ClangBackEnd {
-
-void CodeCompletionChunkConverter::extractCompletionChunks(CXCompletionString completionString)
-{
- const uint completionChunkCount = clang_getNumCompletionChunks(completionString);
- chunks.reserve(completionChunkCount);
-
- for (uint chunkIndex = 0; chunkIndex < completionChunkCount; ++chunkIndex) {
- const CodeCompletionChunk::Kind kind = chunkKind(completionString, chunkIndex);
-
- if (kind == CodeCompletionChunk::Optional) {
- extractOptionalCompletionChunks(clang_getCompletionChunkCompletionString(completionString, chunkIndex));
- } else {
- chunks.append(CodeCompletionChunk(kind,
- chunkText(completionString, chunkIndex)));
- }
- }
-}
-
-void CodeCompletionChunkConverter::extractOptionalCompletionChunks(CXCompletionString completionString)
-{
- const uint completionChunkCount = clang_getNumCompletionChunks(completionString);
-
- for (uint chunkIndex = 0; chunkIndex < completionChunkCount; ++chunkIndex) {
- const CodeCompletionChunk::Kind kind = chunkKind(completionString, chunkIndex);
-
- if (kind == CodeCompletionChunk::Optional)
- extractOptionalCompletionChunks(clang_getCompletionChunkCompletionString(completionString, chunkIndex));
- else
- chunks.append(CodeCompletionChunk(kind, chunkText(completionString, chunkIndex), true));
- }
-}
-
-CodeCompletionChunk::Kind CodeCompletionChunkConverter::chunkKind(CXCompletionString completionString, uint chunkIndex)
-{
- return CodeCompletionChunk::Kind(clang_getCompletionChunkKind(completionString, chunkIndex));
-}
-
-CodeCompletionChunks CodeCompletionChunkConverter::extract(CXCompletionString completionString)
-{
- CodeCompletionChunkConverter converter;
-
- converter.extractCompletionChunks(completionString);
-
- return converter.chunks;
-}
-
-Utf8String CodeCompletionChunkConverter::chunkText(CXCompletionString completionString, uint chunkIndex)
-{
- return ClangString(clang_getCompletionChunkText(completionString, chunkIndex));
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/codecompletionchunkconverter.h b/src/tools/clangbackend/source/codecompletionchunkconverter.h
deleted file mode 100644
index 0bfb1a19c11..00000000000
--- a/src/tools/clangbackend/source/codecompletionchunkconverter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <codecompletionchunk.h>
-
-#include <QVector>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class CodeCompletionChunkConverter
-{
-public:
- static CodeCompletionChunks extract(CXCompletionString completionString);
-
- static Utf8String chunkText(CXCompletionString completionString, uint chunkIndex);
-
-private:
- static CodeCompletionChunk::Kind chunkKind(CXCompletionString completionString, uint chunkIndex);
- void extractCompletionChunks(CXCompletionString completionString);
- void extractOptionalCompletionChunks(CXCompletionString completionString);
-
-private:
- CodeCompletionChunks chunks;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/codecompletionsextractor.cpp b/src/tools/clangbackend/source/codecompletionsextractor.cpp
deleted file mode 100644
index c2386149be8..00000000000
--- a/src/tools/clangbackend/source/codecompletionsextractor.cpp
+++ /dev/null
@@ -1,530 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "codecompletionsextractor.h"
-
-#include "clangbackend_global.h"
-#include "clangstring.h"
-#include "clangtranslationunit.h"
-#include "codecompletionchunkconverter.h"
-#include "sourcelocation.h"
-#include "sourcerange.h"
-#include "unsavedfile.h"
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-#include <QPair>
-#include <QDebug>
-
-#include <cmath>
-#include <limits>
-
-namespace ClangBackEnd {
-
-CodeCompletionsExtractor::CodeCompletionsExtractor(const UnsavedFile &unsavedFile,
- CXCodeCompleteResults *cxCodeCompleteResults)
- : unsavedFile(unsavedFile)
- , cxCodeCompleteResults(cxCodeCompleteResults)
-{
-}
-
-bool CodeCompletionsExtractor::next()
-{
- const uint cxCodeCompleteResultCount = cxCodeCompleteResults->NumResults;
-
- if (cxCodeCompleteResultIndex < cxCodeCompleteResultCount) {
- currentCxCodeCompleteResult = cxCodeCompleteResults->Results[cxCodeCompleteResultIndex];
-
- currentCodeCompletion_ = CodeCompletion();
-
- extractCompletionKind();
- extractText();
- extractPriority();
- extractAvailability();
- extractHasParameters();
- extractBriefComment();
- extractCompletionChunks();
- adaptPriority();
- extractRequiredFixIts();
-
- ++cxCodeCompleteResultIndex;
-
- return true;
- }
-
- return false;
-}
-
-bool CodeCompletionsExtractor::peek(const Utf8String &name)
-{
- const uint cxCodeCompleteResultCount = cxCodeCompleteResults->NumResults;
-
- uint peekCxCodeCompleteResultIndex = cxCodeCompleteResultIndex;
-
- while (peekCxCodeCompleteResultIndex < cxCodeCompleteResultCount) {
- if (hasText(name, cxCodeCompleteResults->Results[peekCxCodeCompleteResultIndex].CompletionString))
- return true;
-
- ++peekCxCodeCompleteResultIndex;
- }
-
- return false;
-}
-
-CodeCompletions CodeCompletionsExtractor::extractAll(bool onlyFunctionOverloads)
-{
- CodeCompletions codeCompletions;
- codeCompletions.reserve(int(cxCodeCompleteResults->NumResults));
-
- while (next())
- codeCompletions.append(currentCodeCompletion_);
-
- handleCompletions(codeCompletions, onlyFunctionOverloads);
-
- return codeCompletions;
-}
-
-static CodeCompletions filterFunctionOverloads(const CodeCompletions &completions)
-{
- return ::Utils::filtered(completions, [](const CodeCompletion &completion) {
- return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind;
- });
-}
-
-static void adaptOverloadsPriorities(CodeCompletions &codeCompletions)
-{
- std::map<Utf8String, std::vector<CodeCompletion *>> cachedOverloads;
- for (CodeCompletion &currentCompletion : codeCompletions) {
- if (currentCompletion.completionKind != CodeCompletion::ConstructorCompletionKind
- && currentCompletion.completionKind != CodeCompletion::FunctionCompletionKind
- && currentCompletion.completionKind
- != CodeCompletion::FunctionDefinitionCompletionKind) {
- continue;
- }
-
- auto found = cachedOverloads.find(currentCompletion.text);
- if (found == cachedOverloads.end()) {
- cachedOverloads[currentCompletion.text].push_back(&currentCompletion);
- } else {
- const quint32 oldPriority = found->second.front()->priority;
- if (currentCompletion.priority >= oldPriority) {
- currentCompletion.priority = oldPriority;
- } else {
- const quint32 newPriority = currentCompletion.priority;
- for (CodeCompletion *completion : found->second)
- completion->priority = newPriority;
- }
- found->second.push_back(&currentCompletion);
- }
- }
-}
-
-static int comparePriorities(quint32 p1, quint32 p2)
-{
- static const int fuzziness = 2; // Each of const and volatile can introduce a diff of 1.
- const int diff = p1 - p2;
- if (std::abs(diff) > fuzziness)
- return diff;
- return 0;
-}
-
-// The list is already ordered, but since we pass the priorities up to higher layers,
-// we should make sure that adjacent values become identical.
-static void mergeAdjacentPriorities(CodeCompletions &completions)
-{
- static const int maxValue = std::numeric_limits<quint32>::max();
- QPair<QVector<CodeCompletion *>, quint32> priorityGroup;
- priorityGroup.second = maxValue;
- const auto assignGroupPriority = [&priorityGroup] {
- for (CodeCompletion * const c : qAsConst(priorityGroup.first))
- c->priority = priorityGroup.second;
- };
- for (CodeCompletion &currentCompletion : completions) {
- const int prioCmp = comparePriorities(priorityGroup.second, currentCompletion.priority);
- if (prioCmp < 0) {
- assignGroupPriority();
- priorityGroup.first.clear();
- priorityGroup.second = currentCompletion.priority;
- } else if (currentCompletion.priority > priorityGroup.second)
- priorityGroup.second = currentCompletion.priority;
- priorityGroup.first << &currentCompletion;
- }
- assignGroupPriority();
-}
-
-static void sortCodeCompletions(CodeCompletions &codeCompletions)
-{
- auto currentItemsCompare = [](const CodeCompletion &first,
- const CodeCompletion &second) {
- // Items without fix-its come first.
- if (first.requiredFixIts.empty() != second.requiredFixIts.empty())
- return first.requiredFixIts.empty() > second.requiredFixIts.empty();
-
- const int prioCmpResult = comparePriorities(first.priority, second.priority);
- if (prioCmpResult != 0)
- return prioCmpResult < 0;
-
- const int textCmp = first.text.toString().compare(second.text);
- if (textCmp != 0)
- return textCmp < 0;
-
- return first.completionKind < second.completionKind;
- };
-
- // Keep the order for the items with the same priority and name.
- std::stable_sort(codeCompletions.begin(), codeCompletions.end(), currentItemsCompare);
-}
-
-void CodeCompletionsExtractor::handleCompletions(CodeCompletions &codeCompletions,
- bool onlyFunctionOverloads)
-{
- if (onlyFunctionOverloads) {
- const CodeCompletions overloadCompletions = filterFunctionOverloads(codeCompletions);
-
- // If filtered completions are empty the assumption we need function overloads is wrong
- // therefore we do not use filtered results in that case.
- if (!overloadCompletions.isEmpty())
- codeCompletions = overloadCompletions;
- }
-
- adaptOverloadsPriorities(codeCompletions);
- sortCodeCompletions(codeCompletions);
- mergeAdjacentPriorities(codeCompletions);
-}
-
-void CodeCompletionsExtractor::extractCompletionKind()
-{
- switch (currentCxCodeCompleteResult.CursorKind) {
- case CXCursor_FunctionTemplate:
- currentCodeCompletion_.completionKind = CodeCompletion::TemplateFunctionCompletionKind;
- break;
- case CXCursor_CXXMethod:
- extractMethodCompletionKind();
- break;
- case CXCursor_FunctionDecl:
- case CXCursor_ConversionFunction:
- currentCodeCompletion_.completionKind = CodeCompletion::FunctionCompletionKind;
- break;
- case CXCursor_VariableRef:
- case CXCursor_MemberRef:
- case CXCursor_VarDecl:
- case CXCursor_FieldDecl:
- case CXCursor_ParmDecl:
- case CXCursor_NonTypeTemplateParameter:
- currentCodeCompletion_.completionKind = CodeCompletion::VariableCompletionKind;
- break;
- case CXCursor_StructDecl:
- case CXCursor_UnionDecl:
- case CXCursor_ClassDecl:
- case CXCursor_TemplateTypeParameter:
- currentCodeCompletion_.completionKind = CodeCompletion::ClassCompletionKind;
- break;
- case CXCursor_TypedefDecl:
- case CXCursor_TypeAliasDecl:
- currentCodeCompletion_.completionKind = CodeCompletion::TypeAliasCompletionKind;
- break;
- case CXCursor_ClassTemplatePartialSpecialization:
- case CXCursor_ClassTemplate:
- case CXCursor_TemplateTemplateParameter:
- currentCodeCompletion_.completionKind = CodeCompletion::TemplateClassCompletionKind;
- break;
- case CXCursor_Namespace:
- case CXCursor_NamespaceAlias:
- currentCodeCompletion_.completionKind = CodeCompletion::NamespaceCompletionKind;
- break;
- case CXCursor_EnumDecl:
- currentCodeCompletion_.completionKind = CodeCompletion::EnumerationCompletionKind;
- break;
- case CXCursor_EnumConstantDecl:
- currentCodeCompletion_.completionKind = CodeCompletion::EnumeratorCompletionKind;
- break;
- case CXCursor_Constructor:
- currentCodeCompletion_.completionKind = CodeCompletion::ConstructorCompletionKind;
- break;
- case CXCursor_Destructor:
- currentCodeCompletion_.completionKind = CodeCompletion::DestructorCompletionKind;
- break;
- case CXCursor_MacroDefinition:
- extractMacroCompletionKind();
- break;
- case CXCursor_NotImplemented:
- currentCodeCompletion_.completionKind = CodeCompletion::KeywordCompletionKind;
- break;
- case CXCursor_OverloadCandidate:
- currentCodeCompletion_.completionKind = CodeCompletion::FunctionOverloadCompletionKind;
- break;
- default:
- currentCodeCompletion_.completionKind = CodeCompletion::Other;
- }
-}
-
-void CodeCompletionsExtractor::extractText()
-{
- const uint completionChunkCount = clang_getNumCompletionChunks(currentCxCodeCompleteResult.CompletionString);
- for (uint chunkIndex = 0; chunkIndex < completionChunkCount; ++chunkIndex) {
- const CXCompletionChunkKind chunkKind = clang_getCompletionChunkKind(currentCxCodeCompleteResult.CompletionString, chunkIndex);
- if (chunkKind == CXCompletionChunk_TypedText) {
- currentCodeCompletion_.text = CodeCompletionChunkConverter::chunkText(currentCxCodeCompleteResult.CompletionString, chunkIndex);
- break;
- }
- }
-}
-
-void CodeCompletionsExtractor::extractMethodCompletionKind()
-{
- CXCompletionString cxCompletionString = cxCodeCompleteResults->Results[cxCodeCompleteResultIndex].CompletionString;
-
- const unsigned long long contexts = clang_codeCompleteGetContexts(cxCodeCompleteResults);
-
- const uint annotationCount = clang_getCompletionNumAnnotations(cxCompletionString);
-
- for (uint annotationIndex = 0; annotationIndex < annotationCount; ++annotationIndex) {
- ClangString annotation = clang_getCompletionAnnotation(cxCompletionString, annotationIndex);
-
- if (annotation == Utf8StringLiteral("qt_signal")) {
- currentCodeCompletion_.completionKind = CodeCompletion::SignalCompletionKind;
- return;
- }
-
- if (annotation == Utf8StringLiteral("qt_slot")) {
- currentCodeCompletion_.completionKind = CodeCompletion::SlotCompletionKind;
- return;
- }
- }
-
- currentCodeCompletion_.completionKind = CodeCompletion::FunctionDefinitionCompletionKind;
- if ((contexts & CXCompletionContext_DotMemberAccess)
- || (contexts & CXCompletionContext_ArrowMemberAccess)) {
- currentCodeCompletion_.completionKind = CodeCompletion::FunctionCompletionKind;
- }
-}
-
-void CodeCompletionsExtractor::extractMacroCompletionKind()
-{
- CXCompletionString cxCompletionString = cxCodeCompleteResults->Results[cxCodeCompleteResultIndex].CompletionString;
-
- const uint completionChunkCount = clang_getNumCompletionChunks(cxCompletionString);
-
- for (uint chunkIndex = 0; chunkIndex < completionChunkCount; ++chunkIndex) {
- CXCompletionChunkKind kind = clang_getCompletionChunkKind(cxCompletionString, chunkIndex);
- if (kind == CXCompletionChunk_Placeholder) {
- currentCodeCompletion_.completionKind = CodeCompletion::FunctionCompletionKind;
- return;
- }
- }
-
- currentCodeCompletion_.completionKind = CodeCompletion::PreProcessorCompletionKind;
-}
-
-void CodeCompletionsExtractor::extractPriority()
-{
- CXCompletionString cxCompletionString = cxCodeCompleteResults->Results[cxCodeCompleteResultIndex].CompletionString;
- quint32 priority = clang_getCompletionPriority(cxCompletionString);
- currentCodeCompletion_.priority = priority;
-}
-
-void CodeCompletionsExtractor::extractAvailability()
-{
- CXCompletionString cxCompletionString = cxCodeCompleteResults->Results[cxCodeCompleteResultIndex].CompletionString;
- CXAvailabilityKind cxAvailabilityKind = clang_getCompletionAvailability(cxCompletionString);
-
- switch (cxAvailabilityKind) {
- case CXAvailability_Available:
- currentCodeCompletion_.availability = CodeCompletion::Available;
- break;
- case CXAvailability_Deprecated:
- currentCodeCompletion_.availability = CodeCompletion::Deprecated;
- break;
- case CXAvailability_NotAvailable:
- currentCodeCompletion_.availability = CodeCompletion::NotAvailable;
- break;
- case CXAvailability_NotAccessible:
- // QTCREATORBUG-25244
- if (currentCodeCompletion_.completionKind == CodeCompletion::FunctionDefinitionCompletionKind)
- currentCodeCompletion_.availability = CodeCompletion::Available;
- else
- currentCodeCompletion_.availability = CodeCompletion::NotAccessible;
- break;
- }
-}
-
-void CodeCompletionsExtractor::extractHasParameters()
-{
- const uint completionChunkCount = clang_getNumCompletionChunks(currentCxCodeCompleteResult.CompletionString);
- for (uint chunkIndex = 0; chunkIndex < completionChunkCount; ++chunkIndex) {
- const CXCompletionChunkKind chunkKind = clang_getCompletionChunkKind(currentCxCodeCompleteResult.CompletionString, chunkIndex);
- if (chunkKind == CXCompletionChunk_LeftParen) {
- const CXCompletionChunkKind nextChunkKind = clang_getCompletionChunkKind(currentCxCodeCompleteResult.CompletionString, chunkIndex + 1);
- currentCodeCompletion_.hasParameters = nextChunkKind != CXCompletionChunk_RightParen;
- return;
- }
- }
-}
-
-void CodeCompletionsExtractor::extractBriefComment()
-{
- ClangString briefComment = clang_getCompletionBriefComment(currentCxCodeCompleteResult.CompletionString);
-
- currentCodeCompletion_.briefComment = briefComment;
-}
-
-void CodeCompletionsExtractor::extractCompletionChunks()
-{
- currentCodeCompletion_.chunks = CodeCompletionChunkConverter::extract(currentCxCodeCompleteResult.CompletionString);
-}
-
-SourceRangeContainer toRangeContainer(const UnsavedFile &file, CXSourceRange cxSourceRange)
-{
- const CXSourceLocation start = clang_getRangeStart(cxSourceRange);
- const CXSourceLocation end = clang_getRangeEnd(cxSourceRange);
-
- uint startLine = 0;
- uint startColumn = 0;
- uint endLine = 0;
- uint endColumn = 0;
- clang_getFileLocation(start, nullptr, &startLine, &startColumn, nullptr);
- clang_getFileLocation(end, nullptr, &endLine, &endColumn, nullptr);
- QTC_ASSERT(startLine == endLine, return SourceRangeContainer(););
-
- const Utf8String lineText = file.lineRange(startLine, endLine);
- startColumn = lineText.mid(0, startColumn - 1).toString().size() + 1;
- endColumn = lineText.mid(0, endColumn - 1).toString().size() + 1;
-
- return SourceRangeContainer(SourceLocationContainer(file.filePath(), startLine, startColumn),
- SourceLocationContainer(file.filePath(), endLine, endColumn));
-}
-
-void CodeCompletionsExtractor::extractRequiredFixIts()
-{
- unsigned fixItsNumber = clang_getCompletionNumFixIts(cxCodeCompleteResults,
- cxCodeCompleteResultIndex);
-
- if (!fixItsNumber)
- return;
-
- CXSourceRange range;
- for (unsigned i = 0; i < fixItsNumber; ++i) {
- ClangString fixIt = clang_getCompletionFixIt(cxCodeCompleteResults,
- cxCodeCompleteResultIndex,
- i,
- &range);
- currentCodeCompletion_.requiredFixIts.push_back(
- FixItContainer(Utf8String(fixIt), toRangeContainer(unsavedFile, range)));
- }
-}
-
-void CodeCompletionsExtractor::adaptPriority()
-{
- decreasePriorityForDestructors();
- decreasePriorityForNonAvailableCompletions();
- decreasePriorityForQObjectInternals();
- decreasePriorityForSignals();
- decreasePriorityForOperators();
-}
-
-void CodeCompletionsExtractor::decreasePriorityForNonAvailableCompletions()
-{
- if (currentCodeCompletion_.availability != CodeCompletion::Available)
- currentCodeCompletion_.priority = currentCodeCompletion_.priority * 100;
-}
-
-void CodeCompletionsExtractor::decreasePriorityForDestructors()
-{
- if (currentCodeCompletion_.completionKind == CodeCompletion::DestructorCompletionKind)
- currentCodeCompletion_.priority = currentCodeCompletion_.priority * 100;
-}
-
-void CodeCompletionsExtractor::decreasePriorityForSignals()
-{
- if (currentCodeCompletion_.completionKind == CodeCompletion::SignalCompletionKind)
- currentCodeCompletion_.priority = currentCodeCompletion_.priority * 100;
-}
-
-void CodeCompletionsExtractor::decreasePriorityForQObjectInternals()
-{
- quint32 priority = currentCodeCompletion_.priority;
-
- if (currentCodeCompletion_.text.startsWith("qt_"))
- priority *= 100;
-
- if (currentCodeCompletion_.text == Utf8StringLiteral("metaObject"))
- priority *= 10;
-
- if (currentCodeCompletion_.text == Utf8StringLiteral("staticMetaObject"))
- priority *= 100;
-
- currentCodeCompletion_.priority = priority;
-}
-
-bool isOperator(CXCursorKind cxCursorKind, const Utf8String &name)
-{
- return cxCursorKind == CXCursor_ConversionFunction
- || (cxCursorKind == CXCursor_CXXMethod
- && name.startsWith(Utf8StringLiteral("operator")));
-}
-
-void CodeCompletionsExtractor::decreasePriorityForOperators()
-{
- quint32 priority = currentCodeCompletion_.priority;
-
- if (isOperator(currentCxCodeCompleteResult.CursorKind, currentCodeCompletion().text))
- priority *= 100;
-
- currentCodeCompletion_.priority = priority;
-}
-
-bool CodeCompletionsExtractor::hasText(const Utf8String &text, CXCompletionString cxCompletionString) const
-{
- const uint completionChunkCount = clang_getNumCompletionChunks(cxCompletionString);
-
- for (uint chunkIndex = 0; chunkIndex < completionChunkCount; ++chunkIndex) {
- const CXCompletionChunkKind chunkKind = clang_getCompletionChunkKind(cxCompletionString, chunkIndex);
- if (chunkKind == CXCompletionChunk_TypedText) {
- const ClangString currentText(clang_getCompletionChunkText(cxCompletionString, chunkIndex));
- return text == currentText;
- }
- }
-
- return false;
-}
-
-const CodeCompletion &CodeCompletionsExtractor::currentCodeCompletion() const
-{
- return currentCodeCompletion_;
-}
-
-std::ostream &operator<<(std::ostream &os, const CodeCompletionsExtractor &extractor)
-{
- os << "name: " << extractor.currentCodeCompletion().text
- << ", kind: " << extractor.currentCodeCompletion().completionKind
- << ", priority: " << extractor.currentCodeCompletion().priority
- << ", kind: " << extractor.currentCodeCompletion().availability;
-
- return os;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/codecompletionsextractor.h b/src/tools/clangbackend/source/codecompletionsextractor.h
deleted file mode 100644
index 408badc7483..00000000000
--- a/src/tools/clangbackend/source/codecompletionsextractor.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <codecompletion.h>
-
-#include <clang-c/Index.h>
-
-#include <QVector>
-
-#include <iosfwd>
-
-namespace ClangBackEnd {
-
-class UnsavedFile;
-
-class CodeCompletionsExtractor
-{
-public:
- CodeCompletionsExtractor(const UnsavedFile &unsavedFile,
- CXCodeCompleteResults *cxCodeCompleteResults);
-
- CodeCompletionsExtractor(CodeCompletionsExtractor&) = delete;
- CodeCompletionsExtractor &operator=(CodeCompletionsExtractor&) = delete;
-
- CodeCompletionsExtractor(CodeCompletionsExtractor&&) = delete;
- CodeCompletionsExtractor &operator=(CodeCompletionsExtractor&&) = delete;
-
- bool next();
- bool peek(const Utf8String &name);
-
- CodeCompletions extractAll(bool onlyFunctionOverloads);
-
- const CodeCompletion &currentCodeCompletion() const;
-
-private:
- void extractCompletionKind();
- void extractText();
- void extractMethodCompletionKind();
- void extractMacroCompletionKind();
- void extractPriority();
- void extractAvailability();
- void extractHasParameters();
- void extractBriefComment();
- void extractCompletionChunks();
- void extractRequiredFixIts();
-
- void adaptPriority();
- void decreasePriorityForNonAvailableCompletions();
- void decreasePriorityForDestructors();
- void decreasePriorityForSignals();
- void decreasePriorityForQObjectInternals();
- void decreasePriorityForOperators();
-
- void handleCompletions(CodeCompletions &codeCompletions, bool onlyFunctionOverloads);
-
- bool hasText(const Utf8String &text, CXCompletionString cxCompletionString) const;
-
-private:
- CodeCompletion currentCodeCompletion_;
- const UnsavedFile &unsavedFile;
- CXCompletionResult currentCxCodeCompleteResult{CXCursor_UnexposedDecl, nullptr};
- CXCodeCompleteResults *cxCodeCompleteResults = nullptr;
- uint cxCodeCompleteResultIndex = 0;
-};
-
-std::ostream &operator<<(std::ostream &os, const CodeCompletionsExtractor &extractor);
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/commandlinearguments.cpp b/src/tools/clangbackend/source/commandlinearguments.cpp
deleted file mode 100644
index cde7329525f..00000000000
--- a/src/tools/clangbackend/source/commandlinearguments.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "commandlinearguments.h"
-
-#include "clangfilepath.h"
-
-#include <utf8string.h>
-#include <utils/algorithm.h>
-#include <utils/qtcprocess.h>
-
-#include <QByteArray>
-#include <QDebug>
-
-static QList<QByteArray> splitArgs(QString &argsString)
-{
- QList<QByteArray> result;
- Utils::ProcessArgs::ArgIterator it(&argsString);
- while (it.next())
- result.append(it.value().toUtf8());
- return result;
-}
-
-template<size_t Size>
-static QList<QByteArray> extraOptions(const char(&environment)[Size])
-{
- if (!qEnvironmentVariableIsSet(environment))
- return QList<QByteArray>();
- QString arguments = QString::fromLocal8Bit(qgetenv(environment));
- return splitArgs(arguments);
-}
-
-static QList<QByteArray> extraClangCodeModelPrependOptions() {
- constexpr char ccmPrependOptions[] = "QTC_CLANG_CCM_CMD_PREPEND";
- static const QList<QByteArray> options = extraOptions(ccmPrependOptions);
- if (!options.isEmpty())
- qWarning() << "ClangCodeModel options are prepended with " << options;
- return options;
-}
-
-static QList<QByteArray> extraClangCodeModelAppendOptions() {
- constexpr char ccmAppendOptions[] = "QTC_CLANG_CCM_CMD_APPEND";
- static const QList<QByteArray> options = extraOptions(ccmAppendOptions);
- if (!options.isEmpty())
- qWarning() << "ClangCodeModel options are appended with " << options;
- return options;
-}
-
-namespace ClangBackEnd {
-
-CommandLineArguments::CommandLineArguments(const char *filePath,
- const Utf8StringVector &compilationArguments,
- bool addVerboseOption)
- : m_prependArgs(extraClangCodeModelPrependOptions()),
- m_appendArgs(extraClangCodeModelAppendOptions())
-{
- const int elementsToReserve = m_prependArgs.size()
- + compilationArguments.size()
- + (addVerboseOption ? 1 : 0)
- + m_appendArgs.size();
- m_arguments.reserve(static_cast<size_t>(elementsToReserve));
-
- for (const auto &argument : m_prependArgs)
- m_arguments.push_back(argument.constData());
- for (const auto &argument : compilationArguments)
- m_arguments.push_back(argument.constData());
- if (addVerboseOption)
- m_arguments.push_back("-v");
- for (const auto &argument : m_appendArgs)
- m_arguments.push_back(argument.constData());
- m_nativeFilePath = FilePath::toNativeSeparators(Utf8String::fromUtf8(filePath));
- m_arguments.push_back(m_nativeFilePath.constData());
-}
-
-const char * const *CommandLineArguments::data() const
-{
- return m_arguments.data();
-}
-
-int CommandLineArguments::count() const
-{
- return int(m_arguments.size());
-}
-
-const char *CommandLineArguments::at(int position) const
-{
- return m_arguments.at(uint(position));
-}
-
-static Utf8String maybeQuoted(const char *argumentAsCString)
-{
- const QString argumentAsQString = QString::fromUtf8(argumentAsCString);
- const QString quotedArgument = Utils::ProcessArgs::quoteArg(argumentAsQString);
-
- return Utf8String::fromString(quotedArgument);
-}
-
-void CommandLineArguments::print() const
-{
- auto cerr = qCritical();
- cerr << "Arguments to libclang:";
- for (const auto &argument : m_arguments)
- cerr.noquote() << maybeQuoted(argument).constData();
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/commandlinearguments.h b/src/tools/clangbackend/source/commandlinearguments.h
deleted file mode 100644
index 9251ae124b1..00000000000
--- a/src/tools/clangbackend/source/commandlinearguments.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utf8stringvector.h>
-
-#include <vector>
-
-namespace ClangBackEnd {
-
-class CommandLineArguments
-{
-public:
- CommandLineArguments(const char *filePath,
- const Utf8StringVector &compilationArguments,
- bool addVerboseOption);
-
- const char * const *data() const;
- int count() const;
- const char * at(int position) const;
-
- void print() const;
-
-private:
- Utf8String m_nativeFilePath;
- const QList<QByteArray> m_prependArgs;
- const QList<QByteArray> m_appendArgs;
- std::vector<const char *> m_arguments;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/cursor.cpp b/src/tools/clangbackend/source/cursor.cpp
deleted file mode 100644
index be84a64331a..00000000000
--- a/src/tools/clangbackend/source/cursor.cpp
+++ /dev/null
@@ -1,544 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cursor.h"
-
-#include "clangstring.h"
-#include "sourcelocation.h"
-#include "sourcerange.h"
-
-#include "clangbackend_global.h"
-
-#include <ostream>
-
-namespace ClangBackEnd {
-
-Cursor::Cursor()
- : m_cxCursor(clang_getNullCursor())
-{
-}
-
-Cursor::Cursor(CXCursor cxCursor)
- : m_cxCursor(cxCursor)
-{
-}
-
-bool Cursor::isNull() const
-{
- return clang_Cursor_isNull(m_cxCursor);
-}
-
-bool Cursor::isValid() const
-{
- return !clang_isInvalid(kind());
-}
-
-bool Cursor::isTranslationUnit() const
-{
- return clang_isTranslationUnit(kind());
-}
-
-bool Cursor::isDefinition() const
-{
- return clang_isCursorDefinition(m_cxCursor);
-}
-
-bool Cursor::isDynamicCall() const
-{
- return clang_Cursor_isDynamicCall(m_cxCursor);
-}
-
-bool Cursor::isVirtualMethod() const
-{
- return clang_CXXMethod_isVirtual(m_cxCursor);
-}
-
-bool Cursor::isPureVirtualMethod() const
-{
- return clang_CXXMethod_isPureVirtual(m_cxCursor);
-}
-
-bool Cursor::isConstantMethod() const
-{
- return clang_CXXMethod_isConst(m_cxCursor);
-}
-
-bool Cursor::isStaticMethod() const
-{
- return clang_CXXMethod_isStatic(m_cxCursor);
-}
-
-bool Cursor::isCompoundType() const
-{
- switch (kind()) {
- case CXCursor_ClassDecl:
- case CXCursor_StructDecl:
- case CXCursor_UnionDecl: return true;
- default: return false;
- }
-}
-
-bool Cursor::isDeclaration() const
-{
- return clang_isDeclaration(kind());
-}
-
-bool Cursor::isInvalidDeclaration() const
-{
- return clang_isInvalidDeclaration(m_cxCursor);
-}
-
-bool Cursor::isParameter() const
-{
- return kind() == CXCursor_ParmDecl;
-}
-
-bool Cursor::isLocalVariable() const
-{
- switch (semanticParent().kind()) {
- case CXCursor_FunctionDecl:
- case CXCursor_CXXMethod:
- case CXCursor_Constructor:
- case CXCursor_Destructor:
- case CXCursor_ConversionFunction:
- case CXCursor_FunctionTemplate:
- case CXCursor_ObjCInstanceMethodDecl: return true;
- default:
- return false;
- }
-}
-
-bool Cursor::isReference() const
-{
- return clang_isReference(kind());
-}
-
-bool Cursor::isExpression() const
-{
- return clang_isExpression(kind());
-}
-
-bool Cursor::isFunctionLike() const
-{
- const CXCursorKind k = kind();
- return k == CXCursor_FunctionDecl
- || k == CXCursor_CXXMethod
- || k == CXCursor_FunctionTemplate;
-}
-
-bool Cursor::isConstructorOrDestructor() const
-{
- const CXCursorKind k = kind();
- return k == CXCursor_Constructor
- || k == CXCursor_Destructor;
-}
-
-bool Cursor::isTemplateLike() const
-{
- switch (kind()) {
- case CXCursor_ClassTemplate:
- case CXCursor_ClassTemplatePartialSpecialization:
- return true;
- case CXCursor_ClassDecl:
- return specializedCursorTemplate().isValid();
- default:
- return false;
- }
-
- Q_UNREACHABLE();
-}
-
-bool Cursor::isAnyTypeAlias() const
-{
- const CXCursorKind k = kind();
- return k == CXCursor_TypeAliasDecl
- || k == CXCursor_TypedefDecl
- || k == CXCursor_TypeAliasTemplateDecl;
-}
-
-bool Cursor::hasFinalFunctionAttribute() const
-{
- bool hasFinal = false;
-
- visit([&] (Cursor cursor, Cursor /*parent*/) {
- if (cursor.kind() == CXCursor_CXXFinalAttr) {
- hasFinal = true;
- return CXChildVisit_Break;
- } else {
- return CXChildVisit_Recurse;
- }
- });
-
- return hasFinal;
-}
-
-bool Cursor::hasFinalClassAttribute() const
-{
- bool hasFinal = false;
-
- visit([&] (Cursor cursor, Cursor /*parent*/) {
- switch (cursor.kind()) {
- case CXCursor_CXXFinalAttr:
- hasFinal = true;
- return CXChildVisit_Break;
- case CXCursor_CXXMethod:
- return CXChildVisit_Break;
- default:
- return CXChildVisit_Recurse;
- }
- });
-
- return hasFinal;
-}
-
-bool Cursor::isUnexposed() const
-{
- return clang_isUnexposed(kind());
-}
-
-bool Cursor::isAnonymous() const
-{
- return clang_Cursor_isAnonymous(m_cxCursor);
-}
-
-ClangString Cursor::unifiedSymbolResolution() const
-{
- return ClangString(clang_getCursorUSR(m_cxCursor));
-}
-
-ClangString Cursor::mangling() const
-{
- return ClangString(clang_Cursor_getMangling(m_cxCursor));
-}
-
-ClangString Cursor::spelling() const
-{
- return ClangString(clang_getCursorSpelling(m_cxCursor));
-}
-
-Utf8String Cursor::displayName() const
-{
- Utf8String result = ClangString(clang_getCursorDisplayName(m_cxCursor));
- if (!result.hasContent() && isAnonymous())
- result = Utf8String("(anonymous)");
- return result;
-}
-
-ClangString Cursor::briefComment() const
-{
- return ClangString(clang_Cursor_getBriefCommentText(m_cxCursor));
-}
-
-Utf8String Cursor::rawComment() const
-{
- Utf8String comment = ClangString(clang_Cursor_getRawCommentText(m_cxCursor));
- comment.replace(Utf8String("\r\n"), Utf8String("\n"));
- return comment;
-}
-
-int Cursor::argumentCount() const
-{
- return clang_Cursor_getNumArguments(m_cxCursor);
-}
-
-Type Cursor::type() const
-{
- return clang_getCursorType(m_cxCursor);
-}
-
-Type Cursor::nonPointerTupe() const
-{
- auto typeResult = type();
-
- if (typeResult.isPointer())
- typeResult = typeResult.pointeeType();
-
- return typeResult;
-}
-
-Type Cursor::enumType() const
-{
- return clang_getEnumDeclIntegerType(m_cxCursor);
-}
-
-long long Cursor::enumConstantValue() const
-{
- return clang_getEnumConstantDeclValue(m_cxCursor);
-}
-
-unsigned long long Cursor::enumConstantUnsignedValue() const
-{
- return clang_getEnumConstantDeclUnsignedValue(m_cxCursor);
-}
-
-Cursor Cursor::specializedCursorTemplate() const
-{
- return clang_getSpecializedCursorTemplate(m_cxCursor);
-}
-
-CXFile Cursor::includedFile() const
-{
- return clang_getIncludedFile(m_cxCursor);
-}
-
-SourceLocation Cursor::sourceLocation() const
-{
- return {cxTranslationUnit(), clang_getCursorLocation(m_cxCursor)};
-}
-
-CXSourceLocation Cursor::cxSourceLocation() const
-{
- return clang_getCursorLocation(m_cxCursor);
-}
-
-SourceRange Cursor::sourceRange() const
-{
- return {cxTranslationUnit(), clang_getCursorExtent(m_cxCursor)};
-}
-
-CXSourceRange Cursor::cxSourceRange() const
-{
- return clang_getCursorExtent(m_cxCursor);
-}
-
-CXTranslationUnit Cursor::cxTranslationUnit() const
-{
- return clang_Cursor_getTranslationUnit(m_cxCursor);
-}
-
-SourceRange Cursor::commentRange() const
-{
- return {cxTranslationUnit(), clang_Cursor_getCommentRange(m_cxCursor)};
-}
-
-bool Cursor::hasSameSourceLocationAs(const Cursor &other) const
-{
- return clang_equalLocations(clang_getCursorLocation(m_cxCursor),
- clang_getCursorLocation(other.m_cxCursor));
-}
-
-Cursor Cursor::definition() const
-{
- return clang_getCursorDefinition(m_cxCursor);
-}
-
-Cursor Cursor::canonical() const
-{
- return clang_getCanonicalCursor(m_cxCursor);
-}
-
-Cursor Cursor::referenced() const
-{
- return clang_getCursorReferenced(m_cxCursor);
-}
-
-Cursor Cursor::semanticParent() const
-{
- return clang_getCursorSemanticParent(m_cxCursor);
-}
-
-Cursor Cursor::lexicalParent() const
-{
- return clang_getCursorLexicalParent(m_cxCursor);
-}
-
-Cursor Cursor::functionBaseDeclaration() const
-{
- auto functionBaseCursor = functionBase();
-
- if (functionBaseCursor.isValid())
- return functionBaseCursor.nonPointerTupe().canonical().declaration();
- else
- return semanticParent().semanticParent();
-}
-
-Cursor Cursor::functionBase() const
-{
- Cursor functionBaseCursor;
-
- visit([&] (Cursor cursor, Cursor /*parentCursor*/) {
- switch (cursor.kind()) {
- case CXCursor_DeclRefExpr:
- functionBaseCursor = cursor; ;
- return CXChildVisit_Break;
- default:
- return CXChildVisit_Recurse;
- }
- });
-
- return functionBaseCursor;
-}
-
-Type Cursor::resultType() const
-{
- return clang_getResultType(type().m_cxType);
-}
-
-Cursor Cursor::argument(int index) const
-{
- return clang_Cursor_getArgument(m_cxCursor, index);
-}
-
-unsigned Cursor::overloadedDeclarationsCount() const
-{
- return clang_getNumOverloadedDecls(m_cxCursor);
-}
-
-Cursor Cursor::overloadedDeclaration(unsigned index) const
-{
- return clang_getOverloadedDecl(m_cxCursor, index);
-}
-
-namespace {
-
-bool isNotUnexposedLValueReference(const Cursor &argument, const Type &argumentType)
-{
- return !(argument.isUnexposed() && argumentType.isLValueReference());
-}
-
-}
-
-void Cursor::collectOutputArgumentRangesTo(std::vector<CXSourceRange> &outputArgumentRanges) const
-{
- const Type callExpressionType = referenced().type();
- const int argumentCount = this->argumentCount();
- const std::size_t maxSize = std::size_t(std::max(0, argumentCount))
- + outputArgumentRanges.size();
- outputArgumentRanges.reserve(maxSize);
-
- for (int argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex) {
- const Cursor argument = this->argument(argumentIndex);
- const Type argumentType = callExpressionType.argument(argumentIndex);
-
- if (isNotUnexposedLValueReference(argument, argumentType)
- && argumentType.isOutputArgument()) {
- outputArgumentRanges.push_back(argument.cxSourceRange());
- }
- }
-}
-
-std::vector<CXSourceRange> Cursor::outputArgumentRanges() const
-{
- std::vector<CXSourceRange> outputArgumentRanges;
-
- collectOutputArgumentRangesTo(outputArgumentRanges);
-
- return outputArgumentRanges;
-}
-
-CXCursorKind Cursor::kind() const
-{
- return clang_getCursorKind(m_cxCursor);
-}
-
-CXCursor Cursor::cx() const
-{
- return m_cxCursor;
-}
-
-StorageClass Cursor::storageClass() const
-{
- CXCursor cursor = m_cxCursor;
- if (!isDeclaration())
- cursor = referenced().m_cxCursor;
- const CX_StorageClass cxStorageClass = clang_Cursor_getStorageClass(cursor);
- switch (cxStorageClass) {
- case CX_SC_Invalid:
- case CX_SC_OpenCLWorkGroupLocal:
- break;
- case CX_SC_None:
- return StorageClass::None;
- case CX_SC_Extern:
- return StorageClass::Extern;
- case CX_SC_Static:
- return StorageClass::Static;
- case CX_SC_PrivateExtern:
- return StorageClass::PrivateExtern;
- case CX_SC_Auto:
- return StorageClass::Auto;
- case CX_SC_Register:
- return StorageClass::Register;
- }
- return StorageClass::Invalid;
-}
-
-AccessSpecifier Cursor::accessSpecifier() const
-{
- CXCursor cursor = m_cxCursor;
- if (!isDeclaration())
- cursor = referenced().m_cxCursor;
- const CX_CXXAccessSpecifier cxAccessSpecifier = clang_getCXXAccessSpecifier(cursor);
- switch (cxAccessSpecifier) {
- case CX_CXXInvalidAccessSpecifier:
- break;
- case CX_CXXPublic:
- return AccessSpecifier::Public;
- case CX_CXXProtected:
- return AccessSpecifier::Protected;
- case CX_CXXPrivate:
- return AccessSpecifier::Private;
- }
- return AccessSpecifier::Invalid;
-}
-
-bool operator==(const Cursor &first, const Cursor &second)
-{
- return clang_equalCursors(first.m_cxCursor, second.m_cxCursor);
-}
-
-bool operator!=(const Cursor &first, const Cursor &second)
-{
- return !(first == second);
-}
-
-std::ostream &operator<<(std::ostream &os, CXCursorKind cursorKind)
-{
- ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursorKind));
- return os << cursorKindSpelling.cString();
-}
-
-std::ostream &operator<<(std::ostream &os, const Cursor &cursor)
-{
- if (cursor.isValid()) {
- ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursor.kind()));
- os << cursorKindSpelling << " ";
-
- auto identifier = cursor.displayName();
- if (identifier.hasContent()) {
- os << "\""
- << identifier
- << "\": ";
- }
-
- os << cursor.sourceLocation();
- } else {
- os << "Invalid cursor!";
- }
-
- return os;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/cursor.h b/src/tools/clangbackend/source/cursor.h
deleted file mode 100644
index fe9641ecfee..00000000000
--- a/src/tools/clangbackend/source/cursor.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangtype.h"
-
-#include <clangsupport/clangsupport_global.h>
-
-#include <clang-c/Index.h>
-
-#include <iosfwd>
-
-#include <vector>
-
-namespace ClangBackEnd {
-
-class SourceLocation;
-class SourceRange;
-class ClangString;
-
-class Cursor
-{
- friend class Type;
- friend bool operator==(const Cursor &first, const Cursor &second);
-public:
- Cursor();
- Cursor(CXCursor cxCursor);
-
- bool isNull() const;
- bool isValid() const;
-
- bool isTranslationUnit() const;
- bool isDefinition() const;
- bool isDynamicCall() const;
- bool isVirtualMethod() const;
- bool isPureVirtualMethod() const;
- bool isConstantMethod() const;
- bool isStaticMethod() const;
- bool isCompoundType() const;
- bool isDeclaration() const;
- bool isInvalidDeclaration() const;
- bool isParameter() const;
- bool isLocalVariable() const;
- bool isReference() const;
- bool isExpression() const;
- bool isFunctionLike() const;
- bool isConstructorOrDestructor() const;
- bool isTemplateLike() const;
- bool isAnyTypeAlias() const;
- bool hasFinalFunctionAttribute() const;
- bool hasFinalClassAttribute() const;
- bool isUnexposed() const;
- bool isAnonymous() const;
-
- Utf8String displayName() const;
- ClangString unifiedSymbolResolution() const;
- ClangString mangling() const;
- ClangString spelling() const;
- ClangString briefComment() const;
- Utf8String rawComment() const;
- int argumentCount() const;
-
- Type type() const;
- Type nonPointerTupe() const;
- Type enumType() const;
-
- long long enumConstantValue() const;
- unsigned long long enumConstantUnsignedValue() const;
-
- SourceLocation sourceLocation() const;
- CXSourceLocation cxSourceLocation() const;
- SourceRange sourceRange() const;
- CXSourceRange cxSourceRange() const;
- CXTranslationUnit cxTranslationUnit() const;
- SourceRange commentRange() const;
- bool hasSameSourceLocationAs(const Cursor &other) const;
-
- Cursor definition() const;
- Cursor canonical() const;
- Cursor referenced() const;
- Cursor semanticParent() const;
- Cursor lexicalParent() const;
- Cursor functionBaseDeclaration() const;
- Cursor functionBase() const;
- Type resultType() const;
- Cursor argument(int index) const;
- unsigned overloadedDeclarationsCount() const;
- Cursor overloadedDeclaration(unsigned index) const;
- Cursor specializedCursorTemplate() const;
- AccessSpecifier accessSpecifier() const;
- StorageClass storageClass() const;
-
- CXFile includedFile() const;
-
- void collectOutputArgumentRangesTo(
- std::vector<CXSourceRange> &outputArgumentRanges) const;
- std::vector<CXSourceRange> outputArgumentRanges() const;
-
- CXCursorKind kind() const;
-
- template <class VisitorCallback>
- void visit(VisitorCallback visitorCallback) const;
-
- CXCursor cx() const;
-
-private:
- CXCursor m_cxCursor;
-};
-
-template <class VisitorCallback>
-void Cursor::visit(VisitorCallback visitorCallback) const
-{
- auto visitor = [] (CXCursor cursor, CXCursor parent, CXClientData lambda) -> CXChildVisitResult {
- auto &visitorCallback = *static_cast<VisitorCallback*>(lambda);
-
- return visitorCallback(cursor, parent);
- };
-
- clang_visitChildren(m_cxCursor, visitor, &visitorCallback);
-}
-
-bool operator==(const Cursor &first, const Cursor &second);
-bool operator!=(const Cursor &first, const Cursor &second);
-
-std::ostream &operator<<(std::ostream &os, CXCursorKind cursorKind);
-std::ostream &operator<<(std::ostream &os, const Cursor &cursor);
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/diagnostic.cpp b/src/tools/clangbackend/source/diagnostic.cpp
deleted file mode 100644
index b7bcf5b02f6..00000000000
--- a/src/tools/clangbackend/source/diagnostic.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "diagnostic.h"
-
-#include "clangstring.h"
-#include "diagnosticset.h"
-#include "fixit.h"
-#include "sourcelocation.h"
-#include "sourcerange.h"
-
-#include <diagnosticcontainer.h>
-#include <memory>
-
-namespace ClangBackEnd {
-
-Diagnostic::Diagnostic(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic)
- : cxDiagnostic(cxDiagnostic),
- cxTranslationUnit(translationUnit)
-{
-}
-
-Diagnostic::~Diagnostic()
-{
- clang_disposeDiagnostic(cxDiagnostic);
-}
-
-Diagnostic::Diagnostic(Diagnostic &&other)
- : cxDiagnostic(std::move(other.cxDiagnostic)),
- cxTranslationUnit(std::move(other.cxTranslationUnit))
-{
- other.cxDiagnostic = nullptr;
- other.cxTranslationUnit = nullptr;
-}
-
-Diagnostic &Diagnostic::operator=(Diagnostic &&other)
-{
- if (this != &other) {
- clang_disposeDiagnostic(cxDiagnostic);
- cxDiagnostic = std::move(other.cxDiagnostic);
- cxTranslationUnit = std::move(other.cxTranslationUnit);
- other.cxDiagnostic = nullptr;
- other.cxTranslationUnit = nullptr;
- }
-
- return *this;
-}
-
-bool Diagnostic::isNull() const
-{
- return cxDiagnostic == nullptr;
-}
-
-Utf8String Diagnostic::text() const
-{
- return ClangString(clang_formatDiagnostic(cxDiagnostic, 0));
-}
-
-Utf8String Diagnostic::category() const
-{
- return ClangString(clang_getDiagnosticCategoryText(cxDiagnostic));
-}
-
-std::pair<Utf8String, Utf8String> Diagnostic::options() const
-{
- CXString disableString;
-
- const Utf8String enableOption = ClangString(clang_getDiagnosticOption(cxDiagnostic, &disableString));
- const Utf8String disableOption = ClangString(disableString);
-
- return {enableOption, disableOption};
-}
-
-SourceLocation Diagnostic::location() const
-{
- return {cxTranslationUnit, clang_getDiagnosticLocation(cxDiagnostic)};
-}
-
-DiagnosticSeverity Diagnostic::severity() const
-{
- return static_cast<DiagnosticSeverity>(clang_getDiagnosticSeverity(cxDiagnostic));
-}
-
-std::vector<SourceRange> Diagnostic::ranges() const
-{
- std::vector<SourceRange> ranges;
- const uint rangesCount = clang_getDiagnosticNumRanges(cxDiagnostic);
- ranges.reserve(rangesCount);
-
- for (uint index = 0; index < rangesCount; ++index) {
- const SourceRange sourceRange {cxTranslationUnit,
- clang_getDiagnosticRange(cxDiagnostic, index)};
-
- if (sourceRange.isValid())
- ranges.push_back(std::move(sourceRange));
- }
-
- return ranges;
-}
-
-std::vector<FixIt> Diagnostic::fixIts() const
-{
- std::vector<FixIt> fixIts;
-
- const uint fixItsCount = clang_getDiagnosticNumFixIts(cxDiagnostic);
-
- fixIts.reserve(fixItsCount);
-
- for (uint index = 0; index < fixItsCount; ++index)
- fixIts.push_back(FixIt(cxTranslationUnit, cxDiagnostic, index));
-
- return fixIts;
-}
-
-DiagnosticSet Diagnostic::childDiagnostics() const
-{
- return DiagnosticSet(cxTranslationUnit, clang_getChildDiagnostics(cxDiagnostic));
-}
-
-DiagnosticContainer Diagnostic::toDiagnosticContainer() const
-{
- return DiagnosticContainer(text(),
- category(),
- options(),
- severity(),
- location().toSourceLocationContainer(),
- getSourceRangeContainers(),
- getFixItContainers(),
- childDiagnostics().toDiagnosticContainers());
-}
-
-QVector<SourceRangeContainer> Diagnostic::getSourceRangeContainers() const
-{
- auto rangeVector = ranges();
-
- QVector<SourceRangeContainer> sourceRangeContainers;
- sourceRangeContainers.reserve(int(rangeVector.size()));
-
- for (auto &&sourceRange : rangeVector)
- sourceRangeContainers.push_back(sourceRange.toSourceRangeContainer());
-
- return sourceRangeContainers;
-}
-
-QVector<FixItContainer> Diagnostic::getFixItContainers() const
-{
- auto fixItVector = fixIts();
-
- QVector<FixItContainer> fixItContainers;
- fixItContainers.reserve(int(fixItVector.size()));
-
- for (auto &&fixIt : fixItVector)
- fixItContainers.push_back(fixIt.toFixItContainer());
-
- return fixItContainers;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/diagnostic.h b/src/tools/clangbackend/source/diagnostic.h
deleted file mode 100644
index a71ac5afa82..00000000000
--- a/src/tools/clangbackend/source/diagnostic.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport_global.h>
-
-#include <QVector>
-
-#include <clang-c/Index.h>
-
-#include <functional>
-#include <vector>
-
-class Utf8String;
-
-namespace ClangBackEnd {
-
-class SourceLocation;
-class SourceRange;
-class FixIt;
-class DiagnosticSet;
-class DiagnosticContainer;
-class SourceRangeContainer;
-class FixItContainer;
-
-class Diagnostic
-{
- friend class DiagnosticSet;
- friend class DiagnosticSetIterator;
- friend bool operator==(Diagnostic first, Diagnostic second);
-
-public:
- ~Diagnostic();
-
- Diagnostic(const Diagnostic &) = delete;
- const Diagnostic &operator=(const Diagnostic &) = delete;
-
- Diagnostic(Diagnostic &&other);
- Diagnostic &operator=(Diagnostic &&other);
-
- bool isNull() const;
-
- Utf8String text() const;
- Utf8String category() const;
- std::pair<Utf8String, Utf8String> options() const;
- SourceLocation location() const;
- DiagnosticSeverity severity() const;
- std::vector<SourceRange> ranges() const;
- std::vector<FixIt> fixIts() const;
- DiagnosticSet childDiagnostics() const;
-
- DiagnosticContainer toDiagnosticContainer() const;
-
-private:
- Diagnostic(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic);
- QVector<SourceRangeContainer> getSourceRangeContainers() const;
- QVector<FixItContainer> getFixItContainers() const;
-
-private:
- CXDiagnostic cxDiagnostic;
- CXTranslationUnit cxTranslationUnit;
-};
-
-inline bool operator==(Diagnostic first, Diagnostic second)
-{
- return first.cxDiagnostic == second.cxDiagnostic;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/diagnosticset.cpp b/src/tools/clangbackend/source/diagnosticset.cpp
deleted file mode 100644
index 39c82551371..00000000000
--- a/src/tools/clangbackend/source/diagnosticset.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "diagnosticset.h"
-
-#include "diagnostic.h"
-
-#include <diagnosticcontainer.h>
-
-#include <memory>
-
-namespace ClangBackEnd {
-
-DiagnosticSet::DiagnosticSet(CXTranslationUnit translationUnit, CXDiagnosticSet cxDiagnosticSet)
- : cxDiagnosticSet(cxDiagnosticSet),
- cxTranslationUnit(translationUnit)
-{
-}
-
-DiagnosticSet::~DiagnosticSet()
-{
- clang_disposeDiagnosticSet(cxDiagnosticSet);
-}
-
-DiagnosticSet::DiagnosticSet(DiagnosticSet &&other)
- : cxDiagnosticSet(std::move(other.cxDiagnosticSet)),
- cxTranslationUnit(std::move(other.cxTranslationUnit))
-{
- other.cxDiagnosticSet = nullptr;
-}
-
-DiagnosticSet &DiagnosticSet::operator=(DiagnosticSet &&other)
-{
- if (this != &other) {
- clang_disposeDiagnosticSet(cxDiagnosticSet);
- cxDiagnosticSet = std::move(other.cxDiagnosticSet);
- cxTranslationUnit = std::move(other.cxTranslationUnit);
- other.cxDiagnosticSet = nullptr;
- other.cxTranslationUnit = nullptr;
- }
-
- return *this;
-}
-
-Diagnostic DiagnosticSet::front() const
-{
- return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, 0));
-}
-
-Diagnostic DiagnosticSet::back() const
-{
- return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, size() - 1));
-}
-
-DiagnosticSet::ConstIterator DiagnosticSet::begin() const
-{
- return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, 0);
-}
-
-DiagnosticSet::ConstIterator DiagnosticSet::end() const
-{
- return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, size());
-}
-
-QVector<DiagnosticContainer> DiagnosticSet::toDiagnosticContainers() const
-{
- const auto isAcceptedDiagnostic = [](const Diagnostic &) { return true; };
-
- return toDiagnosticContainers(isAcceptedDiagnostic);
-}
-
-QVector<DiagnosticContainer> DiagnosticSet::toDiagnosticContainers(
- const IsAcceptedDiagnostic &isAcceptedDiagnostic) const
-{
- QVector<DiagnosticContainer> diagnosticContainers;
- diagnosticContainers.reserve(size());
-
- for (const Diagnostic &diagnostic : *this) {
- if (isAcceptedDiagnostic(diagnostic))
- diagnosticContainers.push_back(diagnostic.toDiagnosticContainer());
- }
-
- return diagnosticContainers;
-}
-
-uint DiagnosticSet::size() const
-{
- return clang_getNumDiagnosticsInSet(cxDiagnosticSet);
-}
-
-bool DiagnosticSet::isNull() const
-{
- return cxDiagnosticSet == nullptr;
-}
-
-Diagnostic DiagnosticSet::at(uint index) const
-{
- return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, index));
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/diagnosticset.h b/src/tools/clangbackend/source/diagnosticset.h
deleted file mode 100644
index 63f672de419..00000000000
--- a/src/tools/clangbackend/source/diagnosticset.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "diagnostic.h"
-#include "diagnosticsetiterator.h"
-
-#include <clang-c/Index.h>
-
-#include <QVector>
-
-#include <functional>
-
-namespace ClangBackEnd {
-
-class DiagnosticSetIterator;
-
-class DiagnosticSet
-{
- friend class TranslationUnit;
- friend class Diagnostic;
-
-public:
- using ConstIterator = DiagnosticSetIterator;
-
-public:
- ~DiagnosticSet();
-
- DiagnosticSet(const DiagnosticSet &) = delete;
- const DiagnosticSet &operator=(const DiagnosticSet &) = delete;
-
- DiagnosticSet(DiagnosticSet &&other);
- DiagnosticSet &operator=(DiagnosticSet &&other);
-
- uint size() const;
- bool isNull() const;
-
- Diagnostic at(uint index) const;
-
- Diagnostic front() const;
- Diagnostic back() const;
-
- ConstIterator begin() const;
- ConstIterator end() const;
-
- using IsAcceptedDiagnostic = std::function<bool (const Diagnostic &)>;
- QVector<DiagnosticContainer> toDiagnosticContainers() const;
- QVector<DiagnosticContainer> toDiagnosticContainers(
- const IsAcceptedDiagnostic &isAcceptedDiagnostic) const;
-
-private:
- DiagnosticSet(CXTranslationUnit translationUnit, CXDiagnosticSet cxDiagnosticSet);
-
-private:
- CXDiagnosticSet cxDiagnosticSet;
- CXTranslationUnit cxTranslationUnit;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/diagnosticsetiterator.h b/src/tools/clangbackend/source/diagnosticsetiterator.h
deleted file mode 100644
index eb1ceac7a0d..00000000000
--- a/src/tools/clangbackend/source/diagnosticsetiterator.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "diagnostic.h"
-
-#include <iterator>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-using uint = unsigned int;
-
-class DiagnosticSet;
-
-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)
- : cxDiagnosticSet(cxDiagnosticSet),
- cxTranslationUnit(translationUnit),
- index(index)
- {}
-
- DiagnosticSetIterator(const DiagnosticSetIterator &other)
- : cxDiagnosticSet(other.cxDiagnosticSet),
- index(other.index)
- {}
-
- DiagnosticSetIterator& operator++()
- {
- ++index;
- return *this;
- }
-
- DiagnosticSetIterator operator++(int)
- {
- uint oldIndex = index++;
- return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, oldIndex);
- }
-
- bool operator==(const DiagnosticSetIterator &other) const
- {
- return index == other.index && cxDiagnosticSet == other.cxDiagnosticSet;
- }
-
- bool operator!=(const DiagnosticSetIterator &other) const
- {
- return index != other.index || cxDiagnosticSet != other.cxDiagnosticSet;
- }
-
- Diagnostic operator*()
- {
- return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, index));
- }
-
-private:
- CXDiagnosticSet cxDiagnosticSet;
- CXTranslationUnit cxTranslationUnit;
- uint index;
-};
-
-}
diff --git a/src/tools/clangbackend/source/fixit.cpp b/src/tools/clangbackend/source/fixit.cpp
deleted file mode 100644
index 8626602d456..00000000000
--- a/src/tools/clangbackend/source/fixit.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "fixit.h"
-
-#include "clangstring.h"
-
-#include <fixitcontainer.h>
-
-namespace ClangBackEnd {
-
-const Utf8String &FixIt::text() const
-{
- return text_;
-}
-
-const SourceRange &FixIt::range() const
-{
- return sourceRange;
-}
-
-FixItContainer FixIt::toFixItContainer() const
-{
- return FixItContainer(text_, sourceRange.toSourceRangeContainer());
-}
-
-FixIt::FixIt(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic, uint index)
-{
- CXSourceRange cxSourceRange;
-
- text_ = ClangString(clang_getDiagnosticFixIt(cxDiagnostic, index, &cxSourceRange));
- sourceRange = SourceRange(translationUnit, cxSourceRange);
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/fixit.h b/src/tools/clangbackend/source/fixit.h
deleted file mode 100644
index b0c1f139aee..00000000000
--- a/src/tools/clangbackend/source/fixit.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sourcerange.h"
-
-#include <utf8string.h>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class FixItContainer;
-
-using uint = unsigned int;
-
-class FixIt
-{
- friend class Diagnostic;
-public:
- const Utf8String &text() const;
- const SourceRange &range() const;
-
- FixItContainer toFixItContainer() const;
-
-private:
- FixIt(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic, uint index);
-
-private:
- SourceRange sourceRange;
- Utf8String text_;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/fulltokeninfo.cpp b/src/tools/clangbackend/source/fulltokeninfo.cpp
deleted file mode 100644
index 58b8398c972..00000000000
--- a/src/tools/clangbackend/source/fulltokeninfo.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangstring.h"
-#include "clangtooltipinfocollector.h"
-#include "cursor.h"
-#include "fulltokeninfo.h"
-#include "sourcerange.h"
-#include "token.h"
-#include "tokenprocessor.h"
-
-#include <utils/predicates.h>
-
-namespace ClangBackEnd {
-
-FullTokenInfo::FullTokenInfo(const Cursor &cursor,
- const Token *token,
- std::vector<CXSourceRange> &currentOutputArgumentRanges)
- : TokenInfo(cursor, token, currentOutputArgumentRanges)
-{
-}
-
-FullTokenInfo::operator TokenInfoContainer() const
-{
- return TokenInfoContainer(line(), column(), length(), m_types, m_extraInfo);
-}
-
-static Utf8String fullyQualifiedType(const Cursor &cursor) {
- Utf8String prefix;
- if (cursor.kind() == CXCursor_ClassTemplate || cursor.kind() == CXCursor_Namespace)
- return qualificationPrefix(cursor) + cursor.displayName();
-
- return cursor.type().canonical().spelling();
-}
-
-void FullTokenInfo::updateTypeSpelling(const Cursor &cursor, bool functionLike)
-{
- m_extraInfo.semanticParentTypeSpelling = fullyQualifiedType(cursor.semanticParent());
- if (!functionLike) {
- m_extraInfo.typeSpelling = fullyQualifiedType(cursor);
- return;
- }
-
- m_extraInfo.token = cursor.displayName();
- // On the client side full type is typeSpelling + token.
- m_extraInfo.typeSpelling = cursor.type().resultType().utf8Spelling();
-}
-
-static Utf8String propertyParentSpelling(CXTranslationUnit cxTranslationUnit,
- const Utf8String &filePath,
- uint line, uint column)
-{
- // Q_PROPERTY expands into QPropertyMagicFunction which can be found as a child of
- // the containing class.
- Cursor tuCursor = clang_getTranslationUnitCursor(cxTranslationUnit);
- Utf8String parentSpelling;
- tuCursor.visit([&filePath, line, column, &parentSpelling](CXCursor cxCursor, CXCursor parent) {
- const CXCursorKind kind = clang_getCursorKind(cxCursor);
- if (kind == CXCursor_Namespace || kind == CXCursor_StructDecl
- || kind == CXCursor_ClassDecl || kind == CXCursor_StaticAssert) {
- Cursor cursor(cxCursor);
- const SourceRange range = cursor.sourceRange();
- if (range.start().filePath() != filePath)
- return CXChildVisit_Continue;
- if (range.contains(line, column)) {
- if (kind == CXCursor_Namespace || kind == CXCursor_StructDecl
- || kind == CXCursor_ClassDecl) {
- return CXChildVisit_Recurse;
- }
- // CXCursor_StaticAssert case. This is Q_PROPERTY static_assert
- parentSpelling = Cursor(parent).type().spelling();
- return CXChildVisit_Break;
- }
- }
- return CXChildVisit_Continue;
- });
- return parentSpelling;
-}
-
-static Utf8String getPropertyType(const SourceLocation &location, uint propertyPosition)
-{
- // Extract property type from the source code
- CXFile cxFile;
- uint offset;
- clang_getFileLocation(location.cx(), &cxFile, nullptr, nullptr, &offset);
- const char *const contents = clang_getFileContents(location.tu(), cxFile, nullptr);
- const int keywordOffset = QByteArray::fromRawData(contents, propertyPosition)
- .lastIndexOf("Q_PROPERTY");
- if (keywordOffset == -1)
- return {};
- const char * const keywordStart = contents + keywordOffset;
- const char *typeStart = keywordStart + 10;
- typeStart += std::strspn(typeStart, "( \t\n\r");
- if (typeStart - keywordStart >= propertyPosition)
- return Utf8String();
- auto typeEnd = std::find_if(std::reverse_iterator<const char*>(keywordStart + propertyPosition),
- std::reverse_iterator<const char*>(typeStart),
- Utils::unequalTo(' '));
-
- return Utf8String(typeStart, static_cast<int>(&(*typeEnd) + 1 - typeStart));
-}
-
-void FullTokenInfo::updatePropertyData()
-{
- const SourceRange range = m_token->extent();
- m_extraInfo.semanticParentTypeSpelling = propertyParentSpelling(m_token->tu(),
- range.start().filePath(),
- line(),
- column());
- m_extraInfo.cursorRange = range;
- m_extraInfo.declaration = true;
- m_extraInfo.definition = true;
- m_extraInfo.typeSpelling = getPropertyType(range.start(), column() - 1);
-}
-
-void FullTokenInfo::identifierKind(const Cursor &cursor, Recursion recursion)
-{
- updateTypeSpelling(cursor);
-
- TokenInfo::identifierKind(cursor, recursion);
-
- m_extraInfo.identifier = (cursor.kind() != CXCursor_PreprocessingDirective);
-
- if (m_types.mainHighlightingType == HighlightingType::QtProperty)
- updatePropertyData();
- else
- m_extraInfo.cursorRange = cursor.sourceRange();
-}
-
-void FullTokenInfo::referencedTypeKind(const Cursor &cursor)
-{
- updateTypeSpelling(cursor.referenced());
-
- TokenInfo::referencedTypeKind(cursor);
-}
-
-void FullTokenInfo::functionKind(const Cursor &cursor, Recursion recursion)
-{
- updateTypeSpelling(cursor, true);
-
- TokenInfo::functionKind(cursor, recursion);
-
- m_extraInfo.accessSpecifier = cursor.accessSpecifier();
- m_extraInfo.storageClass = cursor.storageClass();
-
- bool isSignal = false;
- bool isSlot = false;
- m_originalCursor.visit([&isSignal, &isSlot](CXCursor cursor, CXCursor) {
- Cursor cur(cursor);
- ClangString spelling = cur.spelling();
- if (spelling == "qt_signal")
- isSignal = true;
- else if (spelling == "qt_slot")
- isSlot = true;
- return CXChildVisit_Break;
- });
- m_extraInfo.signal = isSignal;
- m_extraInfo.slot = isSlot;
-}
-
-void FullTokenInfo::variableKind(const Cursor &cursor)
-{
- TokenInfo::variableKind(cursor);
-
- m_extraInfo.accessSpecifier = cursor.accessSpecifier();
- m_extraInfo.storageClass = cursor.storageClass();
-}
-
-void FullTokenInfo::fieldKind(const Cursor &cursor)
-{
- TokenInfo::fieldKind(cursor);
-
- m_extraInfo.accessSpecifier = cursor.accessSpecifier();
- m_extraInfo.storageClass = cursor.storageClass();
-}
-
-void FullTokenInfo::memberReferenceKind(const Cursor &cursor)
-{
- TokenInfo::memberReferenceKind(cursor);
- if (cursor.isDynamicCall()) {
- m_extraInfo.storageClass = cursor.storageClass();
- m_extraInfo.accessSpecifier = cursor.accessSpecifier();
- }
-}
-
-void FullTokenInfo::keywordKind()
-{
- TokenInfo::keywordKind();
-
- if (m_originalCursor.isAnonymous()) {
- CXCursorKind cursorKind = m_originalCursor.kind();
- if (cursorKind == CXCursor_EnumDecl)
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Enum);
- else if (cursorKind == CXCursor_ClassDecl)
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Class);
- else if (cursorKind == CXCursor_StructDecl)
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Struct);
- else if (cursorKind == CXCursor_Namespace)
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Namespace);
- m_extraInfo.declaration = m_extraInfo.definition = true;
- m_extraInfo.token = m_originalCursor.displayName();
- updateTypeSpelling(m_originalCursor);
- m_extraInfo.cursorRange = m_originalCursor.sourceRange();
- }
-}
-
-void FullTokenInfo::overloadedOperatorKind()
-{
- TokenInfo::overloadedOperatorKind();
-
- if (!m_types.mixinHighlightingTypes.contains(HighlightingType::OverloadedOperator))
- return;
-
- // Overloaded operator
- m_extraInfo.identifier = true;
- if (!m_originalCursor.isDeclaration())
- return;
-
- // Overloaded operator declaration
- m_extraInfo.declaration = true;
- m_extraInfo.definition = m_originalCursor.isDefinition();
-
- updateTypeSpelling(m_originalCursor, true);
- m_extraInfo.cursorRange = m_originalCursor.sourceRange();
- m_extraInfo.accessSpecifier = m_originalCursor.accessSpecifier();
- m_extraInfo.storageClass = m_originalCursor.storageClass();
-}
-
-void FullTokenInfo::evaluate()
-{
- m_extraInfo.token = m_token->spelling();
- CXTokenKind cxTokenKind = m_token->kind();
- if (cxTokenKind == CXToken_Identifier) {
- m_extraInfo.declaration = m_originalCursor.isDeclaration();
- m_extraInfo.definition = m_originalCursor.isDefinition();
- }
- m_extraInfo.includeDirectivePath = (m_originalCursor.kind() == CXCursor_InclusionDirective);
-
- TokenInfo::evaluate();
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/fulltokeninfo.h b/src/tools/clangbackend/source/fulltokeninfo.h
deleted file mode 100644
index 96e374c9056..00000000000
--- a/src/tools/clangbackend/source/fulltokeninfo.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "tokeninfo.h"
-
-namespace ClangBackEnd {
-
-class FullTokenInfo : public TokenInfo
-{
- template<class T> friend class TokenProcessor;
-public:
- FullTokenInfo() = default;
- FullTokenInfo(const Cursor &cursor,
- const Token *token,
- std::vector<CXSourceRange> &m_currentOutputArgumentRanges);
- void evaluate() override;
-
- operator TokenInfoContainer() const override;
-protected:
- void identifierKind(const Cursor &cursor, Recursion recursion) override;
- void referencedTypeKind(const Cursor &cursor) override;
- void functionKind(const Cursor &cursor, Recursion recursion) override;
- void variableKind(const Cursor &cursor) override;
- void fieldKind(const Cursor &cursor) override;
- void memberReferenceKind(const Cursor &cursor) override;
- void keywordKind() override;
- void overloadedOperatorKind() override;
-private:
- void updateTypeSpelling(const Cursor &cursor, bool functionLike = false);
- void updatePropertyData();
-
- ExtraInfo m_extraInfo;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/skippedsourceranges.cpp b/src/tools/clangbackend/source/skippedsourceranges.cpp
deleted file mode 100644
index 83384fcc534..00000000000
--- a/src/tools/clangbackend/source/skippedsourceranges.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "skippedsourceranges.h"
-
-#include "sourcerangecontainer.h"
-
-#include <QVector>
-
-#include <algorithm>
-
-namespace ClangBackEnd {
-
-SkippedSourceRanges::SkippedSourceRanges(CXTranslationUnit cxTranslationUnit, const char *filePath)
- : cxTranslationUnit(cxTranslationUnit)
- , cxSkippedSourceRanges(clang_getSkippedRanges(cxTranslationUnit,
- clang_getFile(cxTranslationUnit, filePath)))
-{
-}
-
-SkippedSourceRanges::~SkippedSourceRanges()
-{
- clang_disposeSourceRangeList(cxSkippedSourceRanges);
-}
-
-SkippedSourceRanges &SkippedSourceRanges::operator=(SkippedSourceRanges &&other)
-{
- if (this != &other) {
- this->~SkippedSourceRanges();
- cxTranslationUnit = other.cxTranslationUnit;
- cxSkippedSourceRanges = other.cxSkippedSourceRanges;
- other.cxTranslationUnit = nullptr;
- other.cxSkippedSourceRanges = nullptr;
- }
-
- return *this;
-}
-
-// For some reason, libclang starts the skipped range on the line containing the
-// preprocessor directive preceding the ifdef'ed out code (i.e. #if or #else)
-// and ends it on the line following the ifdef'ed out code (#else or #endif, respectively).
-// We don't want the preprocessor directives grayed out, so adapt the locations.
-static SourceRange adaptedSourceRange(CXTranslationUnit cxTranslationUnit, const SourceRange &range)
-{
- const SourceLocation end = range.end();
-
- return SourceRange {
- SourceLocation(cxTranslationUnit,
- clang_getLocation(cxTranslationUnit,
- clang_getFile(cxTranslationUnit,
- end.filePath().constData()),
- range.start().line() + 1, 1)),
- SourceLocation(cxTranslationUnit,
- clang_getLocation(cxTranslationUnit,
- clang_getFile(cxTranslationUnit,
- end.filePath().constData()),
- end.line(), 1))
- };
-}
-
-// TODO: This should report a line range.
-std::vector<SourceRange> SkippedSourceRanges::sourceRanges() const
-{
- std::vector<SourceRange> sourceRanges;
-
- auto sourceRangeCount = cxSkippedSourceRanges->count;
- sourceRanges.reserve(sourceRangeCount);
-
- for (uint i = 0; i < cxSkippedSourceRanges->count; ++i) {
- const SourceRange range {cxTranslationUnit, cxSkippedSourceRanges->ranges[i]};
- const SourceRange adaptedRange = adaptedSourceRange(cxTranslationUnit, range);
-
- sourceRanges.push_back(adaptedRange);
- }
-
- return sourceRanges;
-}
-
-QVector<SourceRangeContainer> SkippedSourceRanges::toSourceRangeContainers() const
-{
- QVector<SourceRangeContainer> sourceRangeContainers;
-
- auto sourceRanges = this->sourceRanges();
-
- std::copy(sourceRanges.cbegin(),
- sourceRanges.cend(),
- std::back_inserter(sourceRangeContainers));
-
- return sourceRangeContainers;
-}
-
-bool SkippedSourceRanges::isNull() const
-{
-
- return cxTranslationUnit == nullptr || cxSkippedSourceRanges == nullptr;
-}
-
-ClangBackEnd::SkippedSourceRanges::operator QVector<SourceRangeContainer>() const
-{
- return toSourceRangeContainers();
-}
-
-SkippedSourceRanges::SkippedSourceRanges(SkippedSourceRanges &&other)
- : cxTranslationUnit(other.cxTranslationUnit)
- , cxSkippedSourceRanges(other.cxSkippedSourceRanges)
-{
- other.cxTranslationUnit = nullptr;
- other.cxSkippedSourceRanges = nullptr;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/skippedsourceranges.h b/src/tools/clangbackend/source/skippedsourceranges.h
deleted file mode 100644
index 80bc9436767..00000000000
--- a/src/tools/clangbackend/source/skippedsourceranges.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sourcerange.h"
-
-namespace ClangBackEnd {
-
-class SourceRangeContainer;
-
-class SkippedSourceRanges
-{
-public:
- SkippedSourceRanges(CXTranslationUnit Document, const char *filePath);
- ~SkippedSourceRanges();
-
- SkippedSourceRanges(const SkippedSourceRanges &) = delete;
- const SkippedSourceRanges &operator=(const SkippedSourceRanges &) = delete;
-
- SkippedSourceRanges(SkippedSourceRanges &&);
- SkippedSourceRanges &operator=(SkippedSourceRanges &&);
-
- std::vector<SourceRange> sourceRanges() const;
-
- QVector<SourceRangeContainer> toSourceRangeContainers() const;
-
- bool isNull() const;
-
- operator QVector<SourceRangeContainer>() const;
-
-private:
- CXTranslationUnit cxTranslationUnit = nullptr;
- CXSourceRangeList *cxSkippedSourceRanges = nullptr;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/sourcelocation.cpp b/src/tools/clangbackend/source/sourcelocation.cpp
deleted file mode 100644
index ad52667dd69..00000000000
--- a/src/tools/clangbackend/source/sourcelocation.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sourcelocation.h"
-
-#include "clangdocument.h"
-#include "clangfilepath.h"
-#include "clangstring.h"
-
-#include <clangsupport/sourcelocationcontainer.h>
-
-#include <clangsupport/utf8string.h>
-
-#include <utils/textutils.h>
-
-#include <ostream>
-
-namespace ClangBackEnd {
-
-SourceLocation::SourceLocation()
- : m_cxSourceLocation(clang_getNullLocation())
-{
-}
-
-const Utf8String &SourceLocation::filePath() const
-{
- if (!m_isEvaluated)
- evaluate();
-
- if (m_isFilePathNormalized)
- return m_filePath;
-
- m_isFilePathNormalized = true;
- m_filePath = FilePath::fromNativeSeparators(m_filePath);
-
- return m_filePath;
-}
-
-int SourceLocation::line() const
-{
- if (!m_isEvaluated)
- evaluate();
- return m_line;
-}
-
-int SourceLocation::column() const
-{
- if (!m_isEvaluated)
- evaluate();
- return m_column;
-}
-
-int SourceLocation::offset() const
-{
- if (!m_isEvaluated)
- evaluate();
- return m_offset;
-}
-
-SourceLocationContainer SourceLocation::toSourceLocationContainer() const
-{
- if (!m_isEvaluated)
- evaluate();
- return SourceLocationContainer(filePath(), m_line, m_column);
-}
-
-void SourceLocation::evaluate() const
-{
- m_isEvaluated = true;
-
- CXFile cxFile;
-
- unsigned line, column, offset;
- clang_getFileLocation(m_cxSourceLocation,
- &cxFile,
- &line,
- &column,
- &offset);
- m_line = line;
- m_column = column;
- m_offset = offset;
-
- m_isFilePathNormalized = false;
- if (!cxFile)
- return;
-
- m_filePath = ClangString(clang_getFileName(cxFile));
- if (m_column > 1) {
- const int lineStart = m_offset + 1 - m_column;
- const char *contents = clang_getFileContents(m_cxTranslationUnit, cxFile, nullptr);
- if (!contents)
- return;
- // (1) column in SourceLocation is the actual column shown by CppEditor.
- // (2) column in Clang is the utf8 byte offset from the beginning of the line.
- // Here we convert column from (2) to (1).
- m_column = QString::fromUtf8(&contents[lineStart], m_column - 1).size() + 1;
- }
-}
-
-SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,
- CXSourceLocation cxSourceLocation)
- : m_cxSourceLocation(cxSourceLocation)
- , m_cxTranslationUnit(cxTranslationUnit)
-{
-}
-
-SourceLocation::operator CXSourceLocation() const
-{
- return m_cxSourceLocation;
-}
-
-std::ostream &operator<<(std::ostream &os, const SourceLocation &sourceLocation)
-{
- auto filePath = sourceLocation.filePath();
- if (filePath.hasContent())
- os << filePath << ", ";
-
- os << "line: " << sourceLocation.line()
- << ", column: "<< sourceLocation.column()
- << ", offset: "<< sourceLocation.offset();
-
- return os;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/sourcelocation.h b/src/tools/clangbackend/source/sourcelocation.h
deleted file mode 100644
index 0c668c38dec..00000000000
--- a/src/tools/clangbackend/source/sourcelocation.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clang-c/Index.h>
-
-#include <utf8string.h>
-
-namespace ClangBackEnd {
-
-class SourceLocationContainer;
-class Document;
-
-class SourceLocation
-{
- friend class SourceRange;
- friend class TranslationUnit;
-
- friend bool operator==(const SourceLocation &first, const SourceLocation &second)
- {
- return clang_equalLocations(first.m_cxSourceLocation, second.m_cxSourceLocation);
- }
- friend bool operator!=(const SourceLocation &first, const SourceLocation &second)
- {
- return !(first == second);
- }
-
-public:
- SourceLocation();
- SourceLocation(CXTranslationUnit cxTranslationUnit,
- CXSourceLocation cxSourceLocation);
-
- const Utf8String &filePath() const;
- int line() const;
- int column() const;
- int offset() const;
-
- SourceLocationContainer toSourceLocationContainer() const;
-
- CXTranslationUnit tu() const { return m_cxTranslationUnit; }
- CXSourceLocation cx() const { return m_cxSourceLocation; }
-
-private:
- operator CXSourceLocation() const;
- void evaluate() const;
-
-private:
- CXSourceLocation m_cxSourceLocation;
- CXTranslationUnit m_cxTranslationUnit;
- mutable Utf8String m_filePath;
- mutable int m_line = 0;
- mutable int m_column = 0;
- mutable int m_offset = 0;
- mutable bool m_isFilePathNormalized = true;
- mutable bool m_isEvaluated = false;
-};
-
-std::ostream &operator<<(std::ostream &os, const SourceLocation &sourceLocation);
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/sourcerange.cpp b/src/tools/clangbackend/source/sourcerange.cpp
deleted file mode 100644
index 71001226695..00000000000
--- a/src/tools/clangbackend/source/sourcerange.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sourcerange.h"
-
-#include <sourcerangecontainer.h>
-
-#include <ostream>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-SourceRange::SourceRange()
- : cxSourceRange(clang_getNullRange())
-{
-}
-
-SourceRange::SourceRange(const SourceLocation &start, const SourceLocation &end)
- : cxSourceRange(clang_getRange(start, end)),
- cxTranslationUnit(start.m_cxTranslationUnit)
-{
-}
-
-bool SourceRange::isNull() const
-{
- return clang_Range_isNull(cxSourceRange);
-}
-
-bool SourceRange::isValid() const
-{
- return !isNull() && start().offset() < end().offset();
-}
-
-SourceLocation SourceRange::start() const
-{
- return {cxTranslationUnit, clang_getRangeStart(cxSourceRange)};
-}
-
-SourceLocation SourceRange::end() const
-{
- return {cxTranslationUnit, clang_getRangeEnd(cxSourceRange)};
-}
-
-bool SourceRange::contains(int line, int column) const
-{
- const SourceLocation start_ = start();
- const SourceLocation end_ = end();
-
- if (line < start_.line() || line > end_.line())
- return false;
- if (line == start_.line() && column < start_.column())
- return false;
- if (line == end_.line() && column > end_.column())
- return false;
- return true;
-}
-
-SourceRangeContainer SourceRange::toSourceRangeContainer() const
-{
- return SourceRangeContainer(start().toSourceLocationContainer(),
- end().toSourceLocationContainer());
-}
-
-ClangBackEnd::SourceRange::operator SourceRangeContainer() const
-{
- return toSourceRangeContainer();
-}
-
-ClangBackEnd::SourceRange::operator CXSourceRange() const
-{
- return cxSourceRange;
-}
-
-SourceRange::SourceRange(CXTranslationUnit translationUnit, CXSourceRange cxSourceRange)
- : cxSourceRange(cxSourceRange),
- cxTranslationUnit(translationUnit)
-{
-}
-
-bool operator==(const SourceRange &first, const SourceRange &second)
-{
- return clang_equalRanges(first.cxSourceRange, second.cxSourceRange);
-}
-
-std::ostream &operator<<(std::ostream &os, const SourceRange &sourceRange)
-{
- os << "["
- << sourceRange.start() << ", "
- << sourceRange.end()
- << "]";
-
- return os;
-}
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/source/sourcerange.h b/src/tools/clangbackend/source/sourcerange.h
deleted file mode 100644
index 9cef453b92c..00000000000
--- a/src/tools/clangbackend/source/sourcerange.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sourcelocation.h"
-
-namespace ClangBackEnd {
-
-class SourceRangeContainer;
-
-class SourceRange
-{
- friend class Diagnostic;
- friend class FixIt;
- friend class Cursor;
- friend bool operator==(const SourceRange &first, const SourceRange &second);
- friend std::ostream &operator<<(std::ostream &os, const SourceRange &sourceRange);
-
-public:
- SourceRange();
- SourceRange(CXTranslationUnit cxTranslationUnit, CXSourceRange cxSourceRange);
- SourceRange(const SourceLocation &start, const SourceLocation &end);
-
- bool isNull() const;
- bool isValid() const;
-
- SourceLocation start() const;
- SourceLocation end() const;
-
- bool contains(int line, int column) const;
-
- SourceRangeContainer toSourceRangeContainer() const;
-
- operator CXSourceRange() const;
- operator SourceRangeContainer() const;
-
- CXTranslationUnit tu() const { return cxTranslationUnit; }
-
-private:
- CXSourceRange cxSourceRange;
- CXTranslationUnit cxTranslationUnit = nullptr;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/token.cpp b/src/tools/clangbackend/source/token.cpp
deleted file mode 100644
index 5fa31528ecc..00000000000
--- a/src/tools/clangbackend/source/token.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-
-#include "token.h"
-
-#include "clangstring.h"
-#include "cursor.h"
-#include "sourcelocation.h"
-#include "sourcerange.h"
-
-#include <QList>
-
-namespace ClangBackEnd {
-
-Token::Token(CXTranslationUnit cxTranslationUnit, CXToken *cxToken)
- : m_cxTranslationUnit(cxTranslationUnit)
- , m_cxToken(cxToken)
-{
-}
-
-bool Token::isNull() const
-{
- return !m_cxToken;
-}
-
-CXTokenKind Token::kind() const
-{
- return clang_getTokenKind(*m_cxToken);
-}
-
-CXToken *Token::cx() const
-{
- return m_cxToken;
-}
-
-SourceLocation Token::location() const
-{
- return SourceLocation(m_cxTranslationUnit, clang_getTokenLocation(m_cxTranslationUnit, *m_cxToken));
-}
-
-SourceRange Token::extent() const
-{
- return SourceRange(m_cxTranslationUnit, clang_getTokenExtent(m_cxTranslationUnit, *m_cxToken));
-}
-
-ClangString Token::spelling() const
-{
- return clang_getTokenSpelling(m_cxTranslationUnit, *m_cxToken);
-}
-
-Tokens::Tokens(const SourceRange &range)
- : m_cxTranslationUnit(range.tu())
-{
- CXSourceRange cxRange(range);
- CXToken *cxTokens;
- unsigned numTokens;
- clang_tokenize(m_cxTranslationUnit, cxRange, &cxTokens, &numTokens);
-
- m_tokens.reserve(numTokens);
- for (size_t i = 0; i < numTokens; ++i)
- m_tokens.push_back(Token(m_cxTranslationUnit, cxTokens + i));
-}
-
-std::vector<Cursor> Tokens::annotate() const
-{
- std::vector<Cursor> cursors;
- if (m_tokens.empty())
- return cursors;
-
- std::vector<CXCursor> cxCursors;
- cxCursors.resize(m_tokens.size());
-
- clang_annotateTokens(m_cxTranslationUnit, m_tokens.front().cx(), m_tokens.size(), cxCursors.data());
-
- // The alias declaration "using S = struct {}" results in libclang reporting the type
- // of the surrounding scope (e.g. a namespace or class) for the cursor corresponding to
- // the token "S" (QTCREATORBUG-24875). We need to correct this manually.
- // The same goes for function attributes like "[[deprecated]]".
- // TODO: Investigate whether we can fix this in libclang itself.
- for (int i = 1; i < int(m_tokens.size()) - 2; ++i) {
- const Token &tok = m_tokens.at(i);
- if (tok.kind() != CXToken_Identifier && tok.kind() != CXToken_Keyword)
- continue;
- const Token &prevTok = m_tokens.at(i - 1);
- const Token &nextTok = m_tokens.at(i + 1);
-
- // QTCREATORBUG-24875
- if (prevTok.kind() == CXToken_Keyword
- && prevTok.spelling() == "using"
- && nextTok.spelling() == "="
- && cxCursors.at(i).kind != CXCursor_TypeAliasDecl) {
- // If the surrounding scope is a namespace, the correct type is reported for the token
- // after the identifier, i.e. the "=" symbol. Otherwise, it's not reported at all,
- // and we have to use the cursor after that, which should be the aliased type.
- // Note that we cannot use the next cursors in the cxCursors array, because
- // clang_annotateTokens() reports the surrounding scope for all of these.
- CXCursor nextCursor = clang_getCursor(m_cxTranslationUnit, clang_getTokenLocation(
- m_cxTranslationUnit, *nextTok.cx()));
- if (nextCursor.kind != CXCursor_TypeAliasDecl) {
- nextCursor = clang_getCursor(m_cxTranslationUnit, clang_getTokenLocation(
- m_cxTranslationUnit, *m_tokens.at(i + 2).cx()));
- }
- cxCursors[i] = nextCursor;
- continue;
- }
-
- // QTCREATORBUG-24636, QTCREATORBUG-24650
- if (i >= 2) {
- QList<int> setToNull;
- const Token &prevPrevTok = m_tokens.at(i - 2);
- if (prevTok.kind() == CXToken_Punctuation && prevTok.spelling() == "["
- && prevPrevTok.kind() == CXToken_Punctuation && prevPrevTok.spelling() == "[") {
-
- int endOfAttrList = i + 2; // assume the first possible end of attribute declaration
- while (endOfAttrList < int(m_tokens.size())) {
- const Token &last = m_tokens.at(endOfAttrList);
- const Token &secondLast = m_tokens.at(endOfAttrList - 1);
- const Token &current = m_tokens.at(endOfAttrList - 2);
-
- if (current.kind() == CXToken_Identifier || current.kind() == CXToken_Keyword)
- setToNull.append(endOfAttrList - 2);
- if (last.kind() == CXToken_Punctuation && last.spelling() == "]"
- && secondLast.kind() == CXToken_Punctuation
- && secondLast.spelling() == "]") {
- break;
- }
- ++endOfAttrList;
- }
- for (int index : qAsConst(setToNull)) {
- for (int j = index + 3; j < int(m_tokens.size()); ++j) {
- if (cxCursors[j] == cxCursors[j - 1])
- continue;
- if (cxCursors[j].kind == CXCursor_FunctionDecl
- || cxCursors[j].kind == CXCursor_ParmDecl) {
- cxCursors[index] = clang_getNullCursor();
- cxCursors[index].kind = CXCursor_NotImplemented; // Our magic tag.
- }
- break;
- }
- }
- }
- }
- }
-
- cursors.reserve(cxCursors.size());
- for (const CXCursor &cxCursor : cxCursors)
- cursors.emplace_back(cxCursor);
-
- return cursors;
-}
-
-const Token &Tokens::operator[](int index) const
-{
- return m_tokens[index];
-}
-
-Token &Tokens::operator[](int index)
-{
- return m_tokens[index];
-}
-
-std::vector<Token>::const_iterator Tokens::cbegin() const
-{
- return m_tokens.cbegin();
-}
-
-std::vector<Token>::const_iterator Tokens::cend() const
-{
- return m_tokens.cend();
-}
-
-std::vector<Token>::iterator Tokens::begin()
-{
- return m_tokens.begin();
-}
-
-std::vector<Token>::iterator Tokens::end()
-{
- return m_tokens.end();
-}
-
-int Tokens::getTokenIndex(CXTranslationUnit tu, uint line, uint column) const
-{
- int tokenIndex = -1;
- for (int i = size() - 1; i >= 0; --i) {
- const SourceRange range(tu, (*this)[i].extent());
- if (range.contains(line, column)) {
- tokenIndex = i;
- break;
- }
- }
- return tokenIndex;
-}
-
-Tokens::~Tokens()
-{
- if (m_tokens.empty())
- return;
-
- clang_disposeTokens(m_cxTranslationUnit, m_tokens.front().cx(),
- static_cast<unsigned>(m_tokens.size()));
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/token.h b/src/tools/clangbackend/source/token.h
deleted file mode 100644
index 46635c40019..00000000000
--- a/src/tools/clangbackend/source/token.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/smallstringfwd.h>
-
-#include <clang-c/Index.h>
-
-#include <vector>
-
-namespace ClangBackEnd {
-
-class ClangString;
-class Cursor;
-class SourceLocation;
-class SourceRange;
-
-class Token
-{
- friend class Tokens;
-public:
- bool isNull() const;
-
- CXTokenKind kind() const;
-
- SourceLocation location() const;
- SourceRange extent() const;
- ClangString spelling() const;
-
- CXToken *cx() const;
- CXTranslationUnit tu() const { return m_cxTranslationUnit; }
-
-private:
- Token(CXTranslationUnit m_cxTranslationUnit, CXToken *cxToken);
-
- CXTranslationUnit m_cxTranslationUnit;
- CXToken *m_cxToken;
-};
-
-class Tokens
-{
-public:
- Tokens() = default;
- Tokens(const SourceRange &range);
- ~Tokens();
-
- Tokens(Tokens &&other) = default;
- Tokens(const Tokens &other) = delete;
- Tokens &operator=(Tokens &&other) = default;
- Tokens &operator=(const Tokens &other) = delete;
-
- std::vector<Cursor> annotate() const;
-
- int size() const { return static_cast<int>(m_tokens.size()); }
- const Token &operator[](int index) const;
- Token &operator[](int index);
-
- std::vector<Token>::const_iterator cbegin() const;
- std::vector<Token>::const_iterator cend() const;
- std::vector<Token>::iterator begin();
- std::vector<Token>::iterator end();
-
- int getTokenIndex(CXTranslationUnit tu, uint line, uint column) const;
-
- CXTranslationUnit tu() const { return m_cxTranslationUnit; }
-private:
- CXTranslationUnit m_cxTranslationUnit;
- std::vector<Token> m_tokens;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/tokeninfo.cpp b/src/tools/clangbackend/source/tokeninfo.cpp
deleted file mode 100644
index 1535eb2cc24..00000000000
--- a/src/tools/clangbackend/source/tokeninfo.cpp
+++ /dev/null
@@ -1,799 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangstring.h"
-#include "cursor.h"
-#include "token.h"
-#include "tokeninfo.h"
-#include "sourcelocation.h"
-#include "sourcerange.h"
-#include "sourcerangecontainer.h"
-
-#include <array>
-
-namespace ClangBackEnd {
-
-TokenInfo::TokenInfo(const Cursor &cursor,
- const Token *token,
- std::vector<CXSourceRange> &currentOutputArgumentRanges)
- : m_originalCursor(cursor),
- m_token(token),
- m_currentOutputArgumentRanges(&currentOutputArgumentRanges)
-{
- const SourceRange sourceRange = token->extent();
- const auto start = sourceRange.start();
- const auto end = sourceRange.end();
-
- m_line = start.line();
- m_column = start.column();
- m_offset = start.offset();
- m_length = token->spelling().operator Utf8String().toString().size();
- if (m_length == 0)
- m_length = end.offset() - start.offset(); // Just for safety.
-}
-
-bool TokenInfo::hasInvalidMainType() const
-{
- return m_types.mainHighlightingType == HighlightingType::Invalid;
-}
-
-bool TokenInfo::hasMainType(HighlightingType type) const
-{
- return m_types.mainHighlightingType == type;
-}
-
-unsigned TokenInfo::mixinSize() const {
- return m_types.mixinHighlightingTypes.size();
-}
-
-bool TokenInfo::hasMixinType(HighlightingType type) const
-{
- auto found = std::find(m_types.mixinHighlightingTypes.begin(),
- m_types.mixinHighlightingTypes.end(),
- type);
-
- return found != m_types.mixinHighlightingTypes.end();
-}
-
-bool TokenInfo::hasMixinTypeAt(uint position, HighlightingType type) const
-{
- return m_types.mixinHighlightingTypes.size() > position &&
- m_types.mixinHighlightingTypes.at(position) == type;
-}
-
-bool TokenInfo::hasOnlyType(HighlightingType type) const
-{
- return m_types.mixinHighlightingTypes.size() == 0 && hasMainType(type);
-}
-
-bool TokenInfo::hasFunctionArguments() const
-{
- return m_originalCursor.argumentCount() > 0;
-}
-
-TokenInfo::operator TokenInfoContainer() const
-{
- return TokenInfoContainer(m_line, m_column, m_length, m_types);
-}
-
-static bool isFinalFunction(const Cursor &cursor)
-{
- auto referencedCursor = cursor.referenced();
- if (referencedCursor.hasFinalFunctionAttribute())
- return true;
- else
- return false;
-}
-
-static bool isFunctionInFinalClass(const Cursor &cursor)
-{
- auto functionBase = cursor.functionBaseDeclaration();
- if (functionBase.isValid() && functionBase.hasFinalClassAttribute())
- return true;
-
- return false;
-}
-
-void TokenInfo::memberReferenceKind(const Cursor &cursor)
-{
- if (cursor.isDynamicCall()) {
- if (isFinalFunction(cursor) || isFunctionInFinalClass(cursor))
- m_types.mainHighlightingType = HighlightingType::Function;
- else
- m_types.mainHighlightingType = HighlightingType::VirtualFunction;
- } else {
- identifierKind(cursor.referenced(), Recursion::RecursivePass);
- }
-}
-
-void TokenInfo::overloadedDeclRefKind(const Cursor &cursor)
-{
- m_types.mainHighlightingType = HighlightingType::Function;
-
- // CLANG-UPGRADE-CHECK: Workaround still needed?
- // Workaround https://bugs.llvm.org//show_bug.cgi?id=33256 - SomeType in
- // "using N::SomeType" is mistakenly considered as a CXCursor_OverloadedDeclRef.
- if (cursor.overloadedDeclarationsCount() >= 1
- && cursor.overloadedDeclaration(0).kind() != CXCursor_FunctionDecl
- && cursor.overloadedDeclaration(0).kind() != CXCursor_FunctionTemplate) {
- m_types.mainHighlightingType = HighlightingType::Type;
- }
-}
-
-void TokenInfo::variableKind(const Cursor &cursor)
-{
- if (cursor.isParameter())
- m_types.mainHighlightingType = HighlightingType::Parameter;
- else if (cursor.isLocalVariable())
- m_types.mainHighlightingType = HighlightingType::LocalVariable;
- else
- m_types.mainHighlightingType = HighlightingType::GlobalVariable;
-
- if (isOutputArgument())
- m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument);
-}
-
-void TokenInfo::fieldKind(const Cursor &cursor)
-{
- m_types.mainHighlightingType = HighlightingType::Field;
-
- const CXCursorKind kind = cursor.kind();
- switch (kind) {
- default:
- m_types.mainHighlightingType = HighlightingType::Invalid;
- return;
- case CXCursor_ObjCPropertyDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::ObjectiveCProperty);
- Q_FALLTHROUGH();
- case CXCursor_FieldDecl:
- case CXCursor_MemberRef:
- if (isOutputArgument())
- m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument);
- return;
- case CXCursor_ObjCClassMethodDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::ObjectiveCMethod);
- return;
- case CXCursor_ObjCIvarDecl:
- case CXCursor_ObjCInstanceMethodDecl:
- case CXCursor_ObjCSynthesizeDecl:
- case CXCursor_ObjCDynamicDecl:
- return;
- }
-
-}
-
-bool TokenInfo::isDefinition() const
-{
- return m_originalCursor.isDefinition();
-}
-
-bool TokenInfo::isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const
-{
- return cursor.isVirtualMethod()
- && (m_originalCursor.isDeclaration() || m_originalCursor.isDefinition());
-}
-
-static bool isNotFinalFunction(const Cursor &cursor)
-{
- return !cursor.hasFinalFunctionAttribute();
-}
-
-bool TokenInfo::isRealDynamicCall(const Cursor &cursor) const
-{
- return m_originalCursor.isDynamicCall() && isNotFinalFunction(cursor);
-}
-
-void TokenInfo::addExtraTypeIfFirstPass(HighlightingType type,
- Recursion recursion)
-{
- if (recursion == Recursion::FirstPass)
- m_types.mixinHighlightingTypes.push_back(type);
-}
-
-bool TokenInfo::isArgumentInCurrentOutputArgumentLocations() const
-{
- auto originalSourceLocation = m_originalCursor.cxSourceLocation();
-
- const auto isNotSameOutputArgument = [&] (const CXSourceRange &currentSourceRange) {
- return originalSourceLocation.int_data >= currentSourceRange.begin_int_data
- && originalSourceLocation.int_data <= currentSourceRange.end_int_data;
- };
-
- auto found = std::find_if(m_currentOutputArgumentRanges->begin(),
- m_currentOutputArgumentRanges->end(),
- isNotSameOutputArgument);
-
- bool isOutputArgument = found != m_currentOutputArgumentRanges->end();
-
- return isOutputArgument;
-}
-
-// For reasons I don't fully understand, the cursors from clang_annotateTokens() are sometimes
-// not the actual cursor for the respective token, but the one for a construct higher up
-// in the syntax tree. This is often not what we want (e.g. QTCREATORBUG-21522, QTCREATORBUG-21534),
-// so in such cases we re-retrieve the cursor for the token via clang_getCursor().
-Cursor TokenInfo::realCursor(const Cursor &cursor)
-{
- // Magic Qt stuff.
- if (cursor.kind() == CXCursor_InvalidFile && invalidFileKind() != QtMacroPart::None)
- return cursor;
-
- const SourceLocation tokenLoc = m_token->location();
- const SourceLocation cursorLoc = cursor.sourceLocation();
- if (tokenLoc == cursorLoc)
- return cursor;
-
- // Note: clang_getTokenLocation() does not work.
- const CXFile cxFile = clang_getFile(m_token->tu(), tokenLoc.filePath().toByteArray());
- const CXSourceLocation cxLoc = clang_getLocation(m_token->tu(), cxFile, tokenLoc.line(),
- tokenLoc.column());
- return clang_getCursor(m_token->tu(), cxLoc);
-}
-
-bool TokenInfo::isOutputArgument() const
-{
- if (m_currentOutputArgumentRanges->empty())
- return false;
-
- return isArgumentInCurrentOutputArgumentLocations();
-}
-
-void TokenInfo::collectOutputArguments(const Cursor &cursor)
-{
- cursor.collectOutputArgumentRangesTo(*m_currentOutputArgumentRanges);
- filterOutPreviousOutputArguments();
-}
-
-static uint getEnd(CXSourceRange cxSourceRange)
-{
- CXSourceLocation startSourceLocation = clang_getRangeEnd(cxSourceRange);
-
- uint endOffset;
-
- clang_getFileLocation(startSourceLocation, nullptr, nullptr, nullptr, &endOffset);
-
- return endOffset;
-}
-
-void TokenInfo::filterOutPreviousOutputArguments()
-{
- auto isAfterLocation = [this] (CXSourceRange outputRange) {
- return getEnd(outputRange) > m_offset;
- };
-
- auto precedingBegin = std::partition(m_currentOutputArgumentRanges->begin(),
- m_currentOutputArgumentRanges->end(),
- isAfterLocation);
-
- m_currentOutputArgumentRanges->erase(precedingBegin, m_currentOutputArgumentRanges->end());
-}
-
-void TokenInfo::functionKind(const Cursor &cursor, Recursion recursion)
-{
- if (isRealDynamicCall(cursor) || isVirtualMethodDeclarationOrDefinition(cursor))
- m_types.mainHighlightingType = HighlightingType::VirtualFunction;
- else
- m_types.mainHighlightingType = HighlightingType::Function;
-
- if (isOutputArgument())
- m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument);
-
- addExtraTypeIfFirstPass(HighlightingType::Declaration, recursion);
-
- if (isDefinition())
- addExtraTypeIfFirstPass(HighlightingType::FunctionDefinition, recursion);
-}
-
-void TokenInfo::referencedTypeKind(const Cursor &cursor)
-{
- typeKind(cursor.referenced());
-}
-
-void TokenInfo::typeKind(const Cursor &cursor)
-{
- m_types.mainHighlightingType = HighlightingType::Type;
- const CXCursorKind kind = cursor.kind();
- switch (kind) {
- default:
- m_types.mainHighlightingType = HighlightingType::Invalid;
- return;
- case CXCursor_TemplateRef:
- case CXCursor_NamespaceRef:
- case CXCursor_TypeRef:
- referencedTypeKind(cursor);
- return;
- case CXCursor_ClassTemplate:
- case CXCursor_ClassTemplatePartialSpecialization:
- case CXCursor_ClassDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Class);
- return;
- case CXCursor_UnionDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Union);
- return;
- case CXCursor_StructDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Struct);
- return;
- case CXCursor_EnumDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Enum);
- return;
- case CXCursor_NamespaceAlias:
- case CXCursor_Namespace:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Namespace);
- return;
- case CXCursor_TypeAliasDecl:
- case CXCursor_TypeAliasTemplateDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::TypeAlias);
- return;
- case CXCursor_TypedefDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Typedef);
- return;
- case CXCursor_ObjCClassRef:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::ObjectiveCClass);
- return;
- case CXCursor_ObjCProtocolDecl:
- case CXCursor_ObjCProtocolRef:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::ObjectiveCProtocol);
- return;
- case CXCursor_ObjCInterfaceDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::ObjectiveCInterface);
- return;
- case CXCursor_ObjCImplementationDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::ObjectiveCImplementation);
- return;
- case CXCursor_ObjCCategoryDecl:
- case CXCursor_ObjCCategoryImplDecl:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::ObjectiveCCategory);
- return;
- case CXCursor_TemplateTypeParameter:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::TemplateTypeParameter);
- return;
- case CXCursor_TemplateTemplateParameter:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::TemplateTemplateParameter);
- return;
- case CXCursor_ObjCSuperClassRef:
- case CXCursor_CXXStaticCastExpr:
- case CXCursor_CXXReinterpretCastExpr:
- break;
- }
-}
-
-void TokenInfo::identifierKind(const Cursor &cursor, Recursion recursion)
-{
- if (cursor.isInvalidDeclaration())
- return;
-
- if (recursion == Recursion::FirstPass
- && cursor.kind() != CXCursor_NotImplemented
- && cursor.kind() != CXCursor_PreprocessingDirective) {
- const Cursor c = realCursor(cursor);
- if (!clang_isInvalid(c.kind()) && c != cursor) {
- identifierKind(c, Recursion::FirstPass);
- return;
- }
- }
-
- const CXCursorKind kind = cursor.kind();
- switch (kind) {
- case CXCursor_Destructor:
- case CXCursor_Constructor:
- case CXCursor_FunctionDecl:
- case CXCursor_FunctionTemplate:
- case CXCursor_CallExpr:
- case CXCursor_CXXMethod:
- functionKind(cursor, recursion);
- break;
- case CXCursor_NonTypeTemplateParameter:
- m_types.mainHighlightingType = HighlightingType::LocalVariable;
- break;
- case CXCursor_ParmDecl:
- case CXCursor_VarDecl:
- case CXCursor_VariableRef:
- case CXCursor_UnexposedDecl: // structured bindings; see https://reviews.llvm.org/D78213
- variableKind(cursor.referenced());
- break;
- case CXCursor_DeclRefExpr:
- identifierKind(cursor.referenced(), Recursion::RecursivePass);
- break;
- case CXCursor_MemberRefExpr:
- memberReferenceKind(cursor);
- break;
- case CXCursor_FieldDecl:
- case CXCursor_MemberRef:
- case CXCursor_ObjCPropertyDecl:
- case CXCursor_ObjCIvarDecl:
- case CXCursor_ObjCClassMethodDecl:
- case CXCursor_ObjCInstanceMethodDecl:
- case CXCursor_ObjCSynthesizeDecl:
- case CXCursor_ObjCDynamicDecl:
- fieldKind(cursor);
- break;
- case CXCursor_TemplateRef:
- case CXCursor_NamespaceRef:
- case CXCursor_TypeRef:
- referencedTypeKind(cursor);
- break;
- case CXCursor_ClassDecl:
- case CXCursor_ClassTemplate:
- case CXCursor_ClassTemplatePartialSpecialization:
- case CXCursor_UnionDecl:
- case CXCursor_StructDecl:
- case CXCursor_EnumDecl:
- case CXCursor_Namespace:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Declaration);
- Q_FALLTHROUGH();
- case CXCursor_TemplateTypeParameter:
- case CXCursor_TemplateTemplateParameter:
- case CXCursor_NamespaceAlias:
- case CXCursor_TypeAliasDecl:
- case CXCursor_TypedefDecl:
- case CXCursor_CXXStaticCastExpr:
- case CXCursor_CXXReinterpretCastExpr:
- case CXCursor_ObjCCategoryDecl:
- case CXCursor_ObjCCategoryImplDecl:
- case CXCursor_ObjCImplementationDecl:
- case CXCursor_ObjCInterfaceDecl:
- case CXCursor_ObjCProtocolDecl:
- case CXCursor_ObjCProtocolRef:
- case CXCursor_ObjCClassRef:
- case CXCursor_ObjCSuperClassRef:
- typeKind(cursor);
- break;
- case CXCursor_OverloadedDeclRef:
- overloadedDeclRefKind(cursor);
- break;
- case CXCursor_EnumConstantDecl:
- m_types.mainHighlightingType = HighlightingType::Enumeration;
- break;
- case CXCursor_PreprocessingDirective:
- m_types.mainHighlightingType = HighlightingType::Preprocessor;
- break;
- case CXCursor_MacroExpansion:
- m_types.mainHighlightingType = HighlightingType::PreprocessorExpansion;
- break;
- case CXCursor_MacroDefinition:
- m_types.mainHighlightingType = HighlightingType::PreprocessorDefinition;
- break;
- case CXCursor_InclusionDirective:
- // Included files are sometimes reported as strings and sometimes as
- // include directives, depending on various circumstances.
- m_types.mainHighlightingType = m_token->spelling() == "include"
- ? HighlightingType::Preprocessor : HighlightingType::StringLiteral;
- break;
- case CXCursor_LabelRef:
- case CXCursor_LabelStmt:
- m_types.mainHighlightingType = HighlightingType::Label;
- break;
- default:
- break;
- }
-}
-
-static HighlightingType literalKind(const Cursor &cursor)
-{
- switch (cursor.kind()) {
- case CXCursor_CharacterLiteral:
- case CXCursor_StringLiteral:
- case CXCursor_InclusionDirective:
- case CXCursor_ObjCStringLiteral:
- return HighlightingType::StringLiteral;
- case CXCursor_IntegerLiteral:
- case CXCursor_ImaginaryLiteral:
- case CXCursor_FloatingLiteral:
- return HighlightingType::NumberLiteral;
- default:
- return HighlightingType::Invalid;
- }
-
- Q_UNREACHABLE();
-}
-
-static bool isTokenPartOfOperator(const Cursor &declarationCursor, const Token &token)
-{
- Q_ASSERT(declarationCursor.isDeclaration());
- const CXTranslationUnit cxTranslationUnit = declarationCursor.cxTranslationUnit();
- const ClangString tokenName = token.spelling();
- if (tokenName == "operator")
- return true;
-
- if (tokenName == "(") {
- // Valid operator declarations have at least one token after '(' so
- // it's safe to proceed to token + 1 without extra checks.
- const ClangString nextToken = clang_getTokenSpelling(cxTranslationUnit, *(token.cx() + 1));
- if (nextToken != ")") {
- // Argument lists' parentheses are not operator tokens.
- // This '('-token opens a (non-empty) argument list.
- return false;
- }
- }
-
- // It's safe to evaluate the preceding token because we will at least have
- // the 'operator'-keyword's token to the left.
- CXToken *prevToken = token.cx() - 1;
- if (clang_getTokenKind(*prevToken) == CXToken_Punctuation) {
- if (tokenName == "(") {
- // In an operator declaration, when a '(' follows another punctuation
- // then this '(' opens an argument list. Ex: operator*()|operator()().
- return false;
- }
-
- // This token is preceded by another punctuation token so this token
- // could be the second token of a two-tokened operator such as
- // operator+=|-=|*=|/=|<<|==|<=|++ or the third token of operator
- // new[]|delete[]. We decrement one more time to hit one of the keywords:
- // "operator" / "delete" / "new".
- --prevToken;
- }
-
- const ClangString precedingKeyword =
- clang_getTokenSpelling(cxTranslationUnit, *prevToken);
-
- return precedingKeyword == "operator" ||
- precedingKeyword == "new" ||
- precedingKeyword == "delete";
-}
-
-void TokenInfo::overloadedOperatorKind()
-{
- bool inOperatorDeclaration = m_originalCursor.isDeclaration();
- Cursor declarationCursor =
- inOperatorDeclaration ? m_originalCursor :
- m_originalCursor.referenced();
- if (!declarationCursor.displayName().startsWith("operator"))
- return;
-
- if (inOperatorDeclaration && !isTokenPartOfOperator(declarationCursor, *m_token))
- return;
-
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Operator);
- m_types.mixinHighlightingTypes.push_back(HighlightingType::OverloadedOperator);
-}
-
-void TokenInfo::punctuationOrOperatorKind()
-{
- m_types.mainHighlightingType = HighlightingType::Punctuation;
- auto kind = m_originalCursor.kind();
- switch (kind) {
- case CXCursor_CallExpr:
- collectOutputArguments(m_originalCursor);
- Q_FALLTHROUGH();
- case CXCursor_FunctionDecl:
- case CXCursor_CXXMethod:
- case CXCursor_DeclRefExpr:
- // TODO(QTCREATORBUG-19948): Mark calls to overloaded new and delete.
- // Today we can't because libclang sets these cursors' spelling to "".
- // case CXCursor_CXXNewExpr:
- // case CXCursor_CXXDeleteExpr:
- overloadedOperatorKind();
- break;
- case CXCursor_UnaryOperator:
- case CXCursor_BinaryOperator:
- case CXCursor_CompoundAssignOperator:
- case CXCursor_ConditionalOperator:
- m_types.mixinHighlightingTypes.push_back(HighlightingType::Operator);
- if (kind == CXCursor_ConditionalOperator) {
- if (m_token->spelling() == "?")
- m_types.mixinHighlightingTypes.push_back(HighlightingType::TernaryIf);
- else
- m_types.mixinHighlightingTypes.push_back(HighlightingType::TernaryElse);
- }
- break;
- default:
- break;
- }
-
- if (m_types.mainHighlightingType == HighlightingType::Punctuation
- && m_types.mixinHighlightingTypes.empty()
- && kind != CXCursor_OverloadedDeclRef
- && kind != CXCursor_InclusionDirective
- && kind != CXCursor_PreprocessingDirective
- && kind != CXCursor_MacroDefinition
- && kind != CXCursor_DeclStmt
- && kind != CXCursor_CompoundStmt
- && kind != CXCursor_FirstInvalid) {
- const ClangString spelling = m_token->spelling();
- if (spelling == "<")
- m_types.mixinHighlightingTypes.push_back(HighlightingType::AngleBracketOpen);
- else if (spelling == ">")
- m_types.mixinHighlightingTypes.push_back(HighlightingType::AngleBracketClose);
- else if (spelling == ">>")
- m_types.mixinHighlightingTypes.push_back(HighlightingType::DoubleAngleBracketClose);
- }
-
- if (isOutputArgument())
- m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument);
-}
-
-static bool isFirstTokenOfCursor(const Cursor &cursor, const Token &token)
-{
- return cursor.sourceLocation() == token.location();
-}
-
-static bool isLastTokenOfCursor(const Cursor &cursor, const Token &token)
-{
- return cursor.sourceRange().end() == token.location();
-}
-
-static bool isValidMacroToken(const Cursor &cursor, const Token &token)
-{
- // Proper macro token has at least '(' and ')' around it.
- return !isFirstTokenOfCursor(cursor, token) && !isLastTokenOfCursor(cursor, token);
-}
-
-TokenInfo::QtMacroPart TokenInfo::propertyPart(const Token &token)
-{
- static constexpr const char *propertyKeywords[]
- = {"READ", "WRITE", "MEMBER", "RESET", "NOTIFY", "REVISION", "DESIGNABLE",
- "SCRIPTABLE", "STORED", "USER", "CONSTANT", "FINAL"
- };
-
- if (std::find(std::begin(propertyKeywords), std::end(propertyKeywords), token.spelling())
- != std::end(propertyKeywords)) {
- return QtMacroPart::Keyword;
- }
-
- const ClangString nextToken = clang_getTokenSpelling(token.tu(), *(token.cx() + 1));
- const ClangString previousToken = clang_getTokenSpelling(token.tu(), *(token.cx() - 1));
- if (std::find(std::begin(propertyKeywords), std::end(propertyKeywords), nextToken)
- != std::end(propertyKeywords)) {
- if (std::find(std::begin(propertyKeywords), std::end(propertyKeywords), previousToken)
- == std::end(propertyKeywords)) {
- return QtMacroPart::Property;
- }
-
- return QtMacroPart::FunctionOrPrimitiveType;
- }
-
- if (std::find(std::begin(propertyKeywords), std::end(propertyKeywords), previousToken)
- != std::end(propertyKeywords)) {
- return QtMacroPart::FunctionOrPrimitiveType;
- }
- return QtMacroPart::Type;
-}
-
-TokenInfo::QtMacroPart TokenInfo::signalSlotPart(CXTranslationUnit cxTranslationUnit,
- CXToken *token, bool signal)
-{
- // We are inside macro so current token has at least '(' and macro name before it.
- const ClangString prevToken = clang_getTokenSpelling(cxTranslationUnit, *(token - 2));
- if (signal)
- return (prevToken == "SIGNAL") ? QtMacroPart::SignalFunction : QtMacroPart::SignalType;
- return (prevToken == "SLOT") ? QtMacroPart::SlotFunction : QtMacroPart::SlotType;
-}
-
-TokenInfo::QtMacroPart TokenInfo::qtMacroPart(const Token &token)
-{
- const SourceLocation location = token.location();
-
- // If current token is inside macro then the cursor from token's position will be
- // the whole macro cursor.
- Cursor possibleQtMacroCursor = clang_getCursor(token.tu(), location.cx());
- if (!isValidMacroToken(possibleQtMacroCursor, token))
- return QtMacroPart::None;
-
- ClangString spelling = possibleQtMacroCursor.spelling();
- if (spelling == "Q_PROPERTY")
- return propertyPart(token);
-
- if (spelling == "SIGNAL")
- return signalSlotPart(token.tu(), token.cx(), true);
- if (spelling == "SLOT")
- return signalSlotPart(token.tu(), token.cx(), false);
- return QtMacroPart::None;
-}
-
-TokenInfo::QtMacroPart TokenInfo::invalidFileKind()
-{
- const QtMacroPart macroPart = qtMacroPart(*m_token);
-
- switch (macroPart) {
- case QtMacroPart::None:
- case QtMacroPart::Keyword:
- m_types.mainHighlightingType = HighlightingType::Invalid;
- break;
- case QtMacroPart::SignalFunction:
- case QtMacroPart::SlotFunction:
- m_types.mainHighlightingType = HighlightingType::Function;
- break;
- case QtMacroPart::SignalType:
- case QtMacroPart::SlotType:
- m_types.mainHighlightingType = HighlightingType::Type;
- break;
- case QtMacroPart::Property:
- m_types.mainHighlightingType = HighlightingType::QtProperty;
- break;
- case QtMacroPart::Type:
- m_types.mainHighlightingType = HighlightingType::Type;
- break;
- case QtMacroPart::FunctionOrPrimitiveType:
- m_types.mainHighlightingType = HighlightingType::Function;
- break;
- }
-
- return macroPart;
-}
-
-void TokenInfo::keywordKind()
-{
- switch (m_originalCursor.kind()) {
- case CXCursor_PreprocessingDirective:
- m_types.mainHighlightingType = HighlightingType::Preprocessor;
- return;
- case CXCursor_InclusionDirective:
- m_types.mainHighlightingType = HighlightingType::StringLiteral;
- return;
- default:
- break;
- }
-
- const ClangString spelling = m_token->spelling();
- if (spelling == "bool"
- || spelling == "char"
- || spelling == "char16_t"
- || spelling == "char32_t"
- || spelling == "double"
- || spelling == "float"
- || spelling == "int"
- || spelling == "long"
- || spelling == "short"
- || spelling == "signed"
- || spelling == "unsigned"
- || spelling == "void"
- || spelling == "wchar_t") {
- m_types.mainHighlightingType = HighlightingType::PrimitiveType;
- return;
- }
-
- m_types.mainHighlightingType = HighlightingType::Keyword;
-
- if (spelling == "new" || spelling == "delete" || spelling == "operator")
- overloadedOperatorKind();
-}
-
-void TokenInfo::evaluate()
-{
- auto cxTokenKind = m_token->kind();
-
- m_types = HighlightingTypes();
-
- switch (cxTokenKind) {
- case CXToken_Keyword:
- keywordKind();
- break;
- case CXToken_Punctuation:
- punctuationOrOperatorKind();
- break;
- case CXToken_Identifier:
- identifierKind(m_originalCursor, Recursion::FirstPass);
- break;
- case CXToken_Comment:
- m_types.mainHighlightingType = HighlightingType::Comment;
- break;
- case CXToken_Literal:
- m_types.mainHighlightingType = literalKind(m_originalCursor);
- break;
- }
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/tokeninfo.h b/src/tools/clangbackend/source/tokeninfo.h
deleted file mode 100644
index 8aa868e05d7..00000000000
--- a/src/tools/clangbackend/source/tokeninfo.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangsupport_global.h"
-#include "cursor.h"
-
-#include <clangsupport/tokeninfocontainer.h>
-
-#include <clangsupport/utf8string.h>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class Cursor;
-class Token;
-
-class TokenInfo
-{
- friend bool operator==(const TokenInfo &first, const TokenInfo &second);
- template<class T> friend class TokenProcessor;
-public:
- TokenInfo() = default;
- TokenInfo(const Cursor &cursor,
- const Token *token,
- std::vector<CXSourceRange> &m_currentOutputArgumentRanges);
- virtual ~TokenInfo() = default;
-
- virtual void evaluate();
-
- bool hasInvalidMainType() const;
- bool hasMainType(HighlightingType type) const;
- unsigned mixinSize() const;
- bool hasMixinType(HighlightingType type) const;
- bool hasMixinTypeAt(uint, HighlightingType type) const;
- bool hasOnlyType(HighlightingType type) const;
- bool hasFunctionArguments() const;
-
- virtual operator TokenInfoContainer() const;
-
- const HighlightingTypes &types() const
- {
- return m_types;
- }
-
- uint line () const
- {
- return m_line;
- }
-
- uint column() const
- {
- return m_column;
- }
-
- uint length() const
- {
- return m_length;
- }
-
-protected:
- enum class Recursion {
- FirstPass,
- RecursivePass
- };
-
- virtual void identifierKind(const Cursor &cursor, Recursion recursion);
- virtual void referencedTypeKind(const Cursor &cursor);
- virtual void overloadedDeclRefKind(const Cursor &cursor);
- virtual void variableKind(const Cursor &cursor);
- virtual void fieldKind(const Cursor &cursor);
- virtual void functionKind(const Cursor &cursor, Recursion recursion);
- virtual void memberReferenceKind(const Cursor &cursor);
- virtual void typeKind(const Cursor &cursor);
- virtual void keywordKind();
- virtual void overloadedOperatorKind();
- virtual void punctuationOrOperatorKind();
-
- enum class QtMacroPart {
- None, SignalFunction, SignalType, SlotFunction, SlotType, Type, Property, Keyword,
- FunctionOrPrimitiveType
- };
- virtual QtMacroPart invalidFileKind();
-
- Cursor m_originalCursor;
- const Token *m_token;
- HighlightingTypes m_types;
-
-private:
- bool isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const;
- bool isDefinition() const;
- bool isRealDynamicCall(const Cursor &cursor) const;
- void addExtraTypeIfFirstPass(HighlightingType type, Recursion recursion);
- bool isOutputArgument() const;
- void collectOutputArguments(const Cursor &cursor);
- void filterOutPreviousOutputArguments();
- bool isArgumentInCurrentOutputArgumentLocations() const;
- Cursor realCursor(const Cursor &cursor);
-
- static QtMacroPart propertyPart(const Token &token);
- static QtMacroPart signalSlotPart(CXTranslationUnit cxTranslationUnit, CXToken *token,
- bool signal);
- static QtMacroPart qtMacroPart(const Token &token);
-
- std::vector<CXSourceRange> *m_currentOutputArgumentRanges = nullptr;
- uint m_line = 0;
- uint m_column = 0;
- uint m_length = 0;
- uint m_offset = 0;
-};
-
-
-inline bool operator==(const TokenInfo &first, const TokenInfo &second)
-{
- return first.m_line == second.m_line
- && first.m_column == second.m_column
- && first.m_length == second.m_length
- && first.m_types == second.m_types;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/tokenprocessor.h b/src/tools/clangbackend/source/tokenprocessor.h
deleted file mode 100644
index a0e42bffcf4..00000000000
--- a/src/tools/clangbackend/source/tokenprocessor.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "fulltokeninfo.h"
-#include "sourcerange.h"
-#include "token.h"
-#include "tokenprocessoriterator.h"
-#include "tokeninfocontainer.h"
-
-#include <utils/algorithm.h>
-
-#include <clang-c/Index.h>
-
-#include <QVector>
-
-#include <vector>
-
-namespace ClangBackEnd {
-
-template<class T>
-class TokenProcessor
-{
- static_assert (std::is_base_of<TokenInfo, T>::value,
- "Use TokenProcessor only with classes derived from TokenInfo");
-
-public:
- using const_iterator = TokenProcessorIterator<T>;
- using value_type = T;
-
-public:
- TokenProcessor() = default;
- TokenProcessor(const SourceRange &range)
- : tokens(range)
- , cursors(tokens.annotate())
- {
- }
-
- bool isEmpty() const
- {
- return cursors.empty();
- }
- bool isNull() const
- {
- return !tokens.size();
- }
- size_t size() const
- {
- return cursors.size();
- }
-
- const_iterator begin() const
- {
- return const_iterator(cursors.cbegin(),
- tokens.cbegin(),
- currentOutputArgumentRanges);
- }
-
- const_iterator end() const
- {
- return const_iterator(cursors.cend(),
- tokens.cend(),
- currentOutputArgumentRanges);
- }
-
-
- T operator[](size_t index) const
- {
- T tokenInfo(cursors[index], &tokens[index], currentOutputArgumentRanges);
- tokenInfo.evaluate();
- return tokenInfo;
- }
-
- QVector<TokenInfoContainer> toTokenInfoContainers() const
- {
- return toTokens<TokenInfoContainer>();
- }
-
- bool currentOutputArgumentRangesAreEmpty() const
- {
- return currentOutputArgumentRanges.empty();
- }
-
-private:
- template<class TC>
- QVector<TC> toTokens() const
- {
- QVector<TC> tokenInfos;
- tokenInfos.reserve(int(size()));
-
- const auto isValidTokenInfo = [](const T &tokenInfo) {
- return !tokenInfo.hasInvalidMainType()
- && !tokenInfo.hasMainType(HighlightingType::NumberLiteral)
- && !tokenInfo.hasMainType(HighlightingType::Comment);
- };
-
- for (size_t index = 0; index < cursors.size(); ++index) {
- T tokenInfo = (*this)[index];
- if (isValidTokenInfo(tokenInfo))
- tokenInfos.push_back(tokenInfo);
- }
-
- return tokenInfos;
- }
-
- mutable std::vector<CXSourceRange> currentOutputArgumentRanges;
- Tokens tokens;
- std::vector<Cursor> cursors;
-};
-
-template <>
-inline
-QVector<TokenInfoContainer> TokenProcessor<FullTokenInfo>::toTokenInfoContainers() const
-{
- QVector<FullTokenInfo> tokenInfos = toTokens<FullTokenInfo>();
-
- return Utils::transform(tokenInfos,
- [&tokenInfos](FullTokenInfo &tokenInfo) -> TokenInfoContainer {
- if (!tokenInfo.m_extraInfo.declaration
- || tokenInfo.hasMainType(HighlightingType::LocalVariable)) {
- return tokenInfo;
- }
-
- const int index = tokenInfos.indexOf(tokenInfo);
- const SourceLocationContainer &tokenStart = tokenInfo.m_extraInfo.cursorRange.start;
- for (auto it = tokenInfos.rend() - index; it != tokenInfos.rend(); ++it) {
- if (it->m_extraInfo.declaration && !it->hasMainType(HighlightingType::LocalVariable)
- && it->m_originalCursor != tokenInfo.m_originalCursor
- && it->m_extraInfo.cursorRange.contains(tokenStart)) {
- if (tokenInfo.m_originalCursor.lexicalParent() != it->m_originalCursor
- && !tokenInfo.hasMainType(HighlightingType::QtProperty)) {
- continue;
- }
- tokenInfo.m_extraInfo.lexicalParentIndex = std::distance(it, tokenInfos.rend()) - 1;
- break;
- }
- }
- return tokenInfo;
- });
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/tokenprocessoriterator.h b/src/tools/clangbackend/source/tokenprocessoriterator.h
deleted file mode 100644
index 08bdbc1546f..00000000000
--- a/src/tools/clangbackend/source/tokenprocessoriterator.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "tokeninfo.h"
-
-#include <iterator>
-#include <vector>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class DiagnosticSet;
-class Diagnostic;
-
-template<class T>
-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<Cursor>::const_iterator cursorIterator,
- std::vector<Token>::const_iterator tokenIterator,
- std::vector<CXSourceRange> &currentOutputArgumentRanges)
- : cursorIterator(cursorIterator),
- tokenIterator(tokenIterator),
- currentOutputArgumentRanges(currentOutputArgumentRanges)
- {}
-
- TokenProcessorIterator& operator++()
- {
- ++cursorIterator;
- ++tokenIterator;
-
- return *this;
- }
-
- TokenProcessorIterator operator++(int)
- {
- return TokenProcessorIterator(cursorIterator++,
- tokenIterator++,
- currentOutputArgumentRanges);
- }
-
- bool operator==(TokenProcessorIterator other) const
- {
- return cursorIterator == other.cursorIterator;
- }
-
- bool operator!=(TokenProcessorIterator other) const
- {
- return cursorIterator != other.cursorIterator;
- }
-
- T operator*()
- {
- T tokenInfo(*cursorIterator, &(*tokenIterator), currentOutputArgumentRanges);
- tokenInfo.evaluate();
- return tokenInfo;
- }
-
-private:
- std::vector<Cursor>::const_iterator cursorIterator;
- std::vector<Token>::const_iterator tokenIterator;
- std::vector<CXSourceRange> &currentOutputArgumentRanges;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/unsavedfile.cpp b/src/tools/clangbackend/source/unsavedfile.cpp
deleted file mode 100644
index df667a36306..00000000000
--- a/src/tools/clangbackend/source/unsavedfile.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "unsavedfile.h"
-
-#include "clangfilepath.h"
-#include "utf8positionfromlinecolumn.h"
-
-#include <ostream>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-UnsavedFile::UnsavedFile()
-{
-}
-
-UnsavedFile::UnsavedFile(const Utf8String &filePath,
- const Utf8String &fileContent)
- : m_filePath(filePath)
- , m_nativeFilePath(FilePath::toNativeSeparators(filePath))
- , m_fileContent(fileContent)
-{
-}
-
-Utf8String UnsavedFile::nativeFilePath() const
-{
- return m_nativeFilePath;
-}
-
-Utf8String UnsavedFile::filePath() const
-{
- return m_filePath;
-}
-
-Utf8String UnsavedFile::fileContent() const
-{
- return m_fileContent;
-}
-
-uint UnsavedFile::toUtf8Position(int line, int column, bool *ok) const
-{
- Utf8PositionFromLineColumn converter(m_fileContent.constData());
- if (converter.find(line, column)) {
- *ok = true;
- return converter.position();
- }
-
- *ok = false;
- return 0;
-}
-
-bool UnsavedFile::hasCharacterAt(int line, int column, char character) const
-{
- bool positionIsOk = false;
- const uint utf8Position = toUtf8Position(line, column, &positionIsOk);
-
- return positionIsOk && hasCharacterAt(utf8Position, character);
-}
-
-Utf8String UnsavedFile::lineRange(int fromLine, int toLine) const
-{
- if (fromLine > toLine)
- return Utf8String();
-
- // Find start of first line
- bool ok = false;
- const uint fromPosition = toUtf8Position(fromLine, 1, &ok);
- QTC_ASSERT(ok, return Utf8String());
-
- // Find end of last line
- uint toPosition = toUtf8Position(toLine, 1, &ok);
- QTC_ASSERT(ok, return Utf8String());
- const uint endPosition = uint(m_fileContent.byteSize());
- while (toPosition < endPosition && m_fileContent.constData()[toPosition] != '\n')
- ++toPosition;
-
- return m_fileContent.mid(int(fromPosition), int(toPosition - fromPosition));
-}
-
-bool UnsavedFile::hasCharacterAt(uint position, char character) const
-{
- if (position < uint(m_fileContent.byteSize()))
- return m_fileContent.constData()[position] == character;
-
- return false;
-}
-
-bool UnsavedFile::replaceAt(uint position, uint length, const Utf8String &replacement)
-{
- if (position < uint(m_fileContent.byteSize())) {
- m_fileContent.replace(int(position), int(length), replacement);
- return true;
- }
-
- return false;
-}
-
-std::ostream &operator<<(std::ostream &os, const UnsavedFile &unsavedFile)
-{
- os << "UnsavedFile("
- << unsavedFile.m_filePath << ", "
- << unsavedFile.m_fileContent << ", "
- << unsavedFile.m_fileContent << ")";
-
- return os;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/unsavedfile.h b/src/tools/clangbackend/source/unsavedfile.h
deleted file mode 100644
index 58966dd9bb0..00000000000
--- a/src/tools/clangbackend/source/unsavedfile.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "utf8string.h"
-
-namespace ClangBackEnd {
-
-using uint = unsigned int;
-
-class UnsavedFile
-{
-public:
- friend std::ostream &operator<<(std::ostream &os, const UnsavedFile &unsavedFile);
-
- UnsavedFile();
- UnsavedFile(const Utf8String &filePath, const Utf8String &fileContent);
-
- Utf8String filePath() const;
- Utf8String nativeFilePath() const;
- Utf8String fileContent() const;
-
- // 1-based line and column
- uint toUtf8Position(int line, int column, bool *ok) const;
- bool hasCharacterAt(int line, int column, char character) const;
- Utf8String lineRange(int fromLine, int toLine) const;
-
- // 0-based position
- bool hasCharacterAt(uint position, char character) const;
- bool replaceAt(uint position, uint length, const Utf8String &replacement);
-
-private:
- Utf8String m_filePath;
- Utf8String m_nativeFilePath;
- Utf8String m_fileContent;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/unsavedfiles.cpp b/src/tools/clangbackend/source/unsavedfiles.cpp
deleted file mode 100644
index f436c660d0c..00000000000
--- a/src/tools/clangbackend/source/unsavedfiles.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "unsavedfiles.h"
-
-#include "clangunsavedfilesshallowarguments.h"
-#include "unsavedfile.h"
-
-#include <QSharedData>
-
-#include <algorithm>
-
-namespace ClangBackEnd {
-
-class UnsavedFilesData : public QSharedData
-{
-public:
- UnsavedFilesData();
-
-public:
- TimePoint lastChangeTimePoint;
- QVector<UnsavedFile> unsavedFiles;
-};
-
-UnsavedFilesData::UnsavedFilesData()
- : lastChangeTimePoint(Clock::now())
-{
-}
-
-UnsavedFiles::UnsavedFiles()
- : d(new UnsavedFilesData)
-{
-}
-
-UnsavedFiles::~UnsavedFiles()
-{
-}
-
-UnsavedFiles::UnsavedFiles(const UnsavedFiles &other)
- : d(other.d)
-{
-}
-
-UnsavedFiles &UnsavedFiles::operator=(const UnsavedFiles &other)
-{
- d = other.d;
- return *this;
-}
-
-void UnsavedFiles::createOrUpdate(const QVector<FileContainer> &fileContainers)
-{
- for (const FileContainer &fileContainer : fileContainers)
- updateUnsavedFileWithFileContainer(fileContainer);
-
- updateLastChangeTimePoint();
-}
-
-void UnsavedFiles::remove(const QVector<FileContainer> &fileContainers)
-{
- for (const FileContainer &fileContainer : fileContainers)
- removeUnsavedFile(fileContainer);
-
- updateLastChangeTimePoint();
-}
-
-UnsavedFile &UnsavedFiles::unsavedFile(const Utf8String &filePath)
-{
- const auto isMatchingFile = [filePath] (const UnsavedFile &unsavedFile) {
- return unsavedFile.filePath() == filePath;
- };
- const auto unsavedFileIterator = std::find_if(d->unsavedFiles.begin(),
- d->unsavedFiles.end(),
- isMatchingFile);
-
- if (unsavedFileIterator != d->unsavedFiles.end())
- return *unsavedFileIterator;
-
- static UnsavedFile defaultUnsavedFile = UnsavedFile(Utf8String(), Utf8String());
- return defaultUnsavedFile;
-}
-
-uint UnsavedFiles::count() const
-{
- return uint(d->unsavedFiles.size());
-}
-
-const UnsavedFile &UnsavedFiles::at(int index) const
-{
- return d->unsavedFiles.at(index);
-}
-
-UnsavedFilesShallowArguments UnsavedFiles::shallowArguments() const
-{
- return UnsavedFilesShallowArguments(*this);
-}
-
-const TimePoint UnsavedFiles::lastChangeTimePoint() const
-{
- return d->lastChangeTimePoint;
-}
-
-void UnsavedFiles::updateUnsavedFileWithFileContainer(const FileContainer &fileContainer)
-{
- if (fileContainer.hasUnsavedFileContent)
- addOrUpdateUnsavedFile(fileContainer);
- else
- removeUnsavedFile(fileContainer);
-}
-
-void UnsavedFiles::removeUnsavedFile(const FileContainer &fileContainer)
-{
- const Utf8String &filePath = fileContainer.filePath;
- auto removeBeginIterator = std::partition(d->unsavedFiles.begin(),
- d->unsavedFiles.end(),
- [filePath] (const UnsavedFile &unsavedFile) { return filePath != unsavedFile.filePath(); });
-
- d->unsavedFiles.erase(removeBeginIterator, d->unsavedFiles.end());
-}
-
-void UnsavedFiles::addOrUpdateUnsavedFile(const FileContainer &fileContainer)
-{
- const Utf8String &filePath = fileContainer.filePath;
- const Utf8String &fileContent = fileContainer.unsavedFileContent;
- auto isSameFile = [filePath] (const UnsavedFile &unsavedFile) { return filePath == unsavedFile.filePath(); };
-
- auto unsavedFileIterator = std::find_if(d->unsavedFiles.begin(), d->unsavedFiles.end(), isSameFile);
- if (unsavedFileIterator == d->unsavedFiles.end())
- d->unsavedFiles.append(UnsavedFile(filePath, fileContent));
- else
- *unsavedFileIterator = UnsavedFile(filePath, fileContent);
-}
-
-void UnsavedFiles::updateLastChangeTimePoint()
-{
- d->lastChangeTimePoint = Clock::now();
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/unsavedfiles.h b/src/tools/clangbackend/source/unsavedfiles.h
deleted file mode 100644
index eacab0bc342..00000000000
--- a/src/tools/clangbackend/source/unsavedfiles.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangclock.h"
-
-#include <filecontainer.h>
-
-#include <QSharedPointer>
-#include <QVector>
-
-#include <clang-c/Index.h>
-
-namespace ClangBackEnd {
-
-class UnsavedFile;
-class UnsavedFilesData;
-class UnsavedFilesShallowArguments;
-
-class UnsavedFiles
-{
-public:
- UnsavedFiles();
- ~UnsavedFiles();
-
- UnsavedFiles(const UnsavedFiles &other);
- UnsavedFiles &operator=(const UnsavedFiles &other);
-
- void createOrUpdate(const QVector<FileContainer> &fileContainers);
- void remove(const QVector<FileContainer> &fileContainers);
-
- uint count() const;
- const UnsavedFile &at(int index) const;
-
- UnsavedFile &unsavedFile(const Utf8String &filePath);
-
- UnsavedFilesShallowArguments shallowArguments() const;
-
- const TimePoint lastChangeTimePoint() const;
-
-private:
- void updateUnsavedFileWithFileContainer(const FileContainer &fileContainer);
- void removeUnsavedFile(const FileContainer &fileContainer);
- void addOrUpdateUnsavedFile(const FileContainer &fileContainer);
- void updateLastChangeTimePoint();
-
-private:
- QSharedDataPointer<UnsavedFilesData> d;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/utf8positionfromlinecolumn.cpp b/src/tools/clangbackend/source/utf8positionfromlinecolumn.cpp
deleted file mode 100644
index 36f5747a5b7..00000000000
--- a/src/tools/clangbackend/source/utf8positionfromlinecolumn.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "utf8positionfromlinecolumn.h"
-
-#include <utils/textutils.h>
-
-#include <QtGlobal>
-
-namespace ClangBackEnd {
-
-Utf8PositionFromLineColumn::Utf8PositionFromLineColumn(const char *utf8Text)
- : m_utf8Text(utf8Text)
- , m_currentByte(utf8Text)
-{
-}
-
-bool Utf8PositionFromLineColumn::find(int line, int column)
-{
- if (!m_utf8Text || *m_utf8Text == '\0' || line == 0 || column == 0)
- return false;
-
- return advanceToLine(line)
- && advanceToColumn(column);
-}
-
-uint Utf8PositionFromLineColumn::position() const
-{
- return m_previousByte - m_utf8Text;
-}
-
-bool Utf8PositionFromLineColumn::advanceToLine(int line)
-{
- if (line == 1)
- return true;
-
- int currentLine = 1;
- do {
- if (*m_currentByte == '\n' && ++currentLine == line) {
- advanceCodePoint();
- return true;
- }
- } while (advanceCodePoint());
-
- return false;
-}
-
-bool Utf8PositionFromLineColumn::advanceToColumn(int column)
-{
- while (column) {
- if (advanceCodePoint(/*stopOnNewLine=*/ true))
- --column;
- else
- break;
- }
-
- return column == 0;
-}
-
-bool Utf8PositionFromLineColumn::advanceCodePoint(bool stopOnNewLine)
-{
- if (Q_UNLIKELY(*m_currentByte == '\0') || (stopOnNewLine && *m_currentByte == '\n'))
- return false;
-
- m_previousByte = m_currentByte;
- return Utils::Text::utf8AdvanceCodePoint(m_currentByte);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/utf8positionfromlinecolumn.h b/src/tools/clangbackend/source/utf8positionfromlinecolumn.h
deleted file mode 100644
index 22f5b7ff545..00000000000
--- a/src/tools/clangbackend/source/utf8positionfromlinecolumn.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-namespace ClangBackEnd {
-
-using uint = unsigned;
-
-class Utf8PositionFromLineColumn
-{
-public:
- Utf8PositionFromLineColumn(const char *utf8Text);
-
- // 1-based line and column
- bool find(int line, int column);
-
- uint position() const;
-
-private:
- bool advanceToLine(int line);
- bool advanceToColumn(int column);
- bool advanceCodePoint(bool stopOnNewLine = false);
-
-private:
- const char * const m_utf8Text = nullptr;
-
- const char *m_previousByte = nullptr;
- const char *m_currentByte = nullptr;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
index 29a2111880a..ecf281ac908 100644
--- a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
+++ b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
@@ -97,7 +97,7 @@ public:
typedef QPair<QByteArray, QByteArray> Pair;
- foreach (const Pair &conn, _connections)
+ for (const Pair &conn : qAsConst(_connections))
out << conn.first.constData() << " -> " << conn.second.constData() << std::endl;
alignTerminals();
@@ -113,7 +113,7 @@ public:
protected:
void alignTerminals() {
out<<"{ rank=same;" << std::endl;
- foreach (const QByteArray &terminalShape, _terminalShapes) {
+ for (const QByteArray &terminalShape : qAsConst(_terminalShapes)) {
out << " " << std::string(terminalShape.constData(), terminalShape.size()).c_str() << ";" << std::endl;
}
out<<"}"<<std::endl;
@@ -439,10 +439,10 @@ public:
/// successfully parse with one of the given parseModes (one parse mode after the other
/// is tried), otherwise a null pointer.
static Document::Ptr parse(const QString &fileName, const QByteArray &source,
- QList<Document::ParseMode> parseModes, QByteArray *errors,
+ const QList<Document::ParseMode> parseModes, QByteArray *errors,
bool verbose = false)
{
- foreach (const Document::ParseMode parseMode, parseModes) {
+ for (const Document::ParseMode parseMode : parseModes) {
ErrorHandler *errorHandler = new ErrorHandler(parseMode, errors); // Deleted by ~Document.
if (verbose)
std::cout << "Parsing as " << qPrintable(parseModeToString(parseMode)) << "...";
@@ -466,7 +466,7 @@ static Document::Ptr parse(const QString &fileName, const QByteArray &source,
/// Convenience function
static Document::Ptr parse(const QString &fileName, const QByteArray &source,
- Document::ParseMode parseMode, QByteArray *errors,
+ const Document::ParseMode parseMode, QByteArray *errors,
bool verbose = false)
{
QList<Document::ParseMode> parseModes = QList<Document::ParseMode>() << parseMode;
@@ -576,7 +576,7 @@ int main(int argc, char *argv[])
// Process files
const QStringList files = args;
- foreach (const QString &fileName, files) {
+ for (const QString &fileName : files) {
if (! QFile::exists(fileName)) {
std::cerr << "Error: File \"" << qPrintable(fileName) << "\" does not exist."
<< std::endl;
@@ -638,7 +638,7 @@ int main(int argc, char *argv[])
QString(fileName + QLatin1String(".ast.png"))));
inputOutputFiles.append(qMakePair(QString(fileName + QLatin1String(".symbols.dot")),
QString(fileName + QLatin1String(".symbols.png"))));
- foreach (const Pair &pair, inputOutputFiles) {
+ for (const Pair &pair : qAsConst(inputOutputFiles)) {
createImageFromDot(pair.first, pair.second, optionVerbose);
std::cout << qPrintable(QDir::toNativeSeparators(pair.second)) << std::endl;
}
diff --git a/src/tools/cplusplus-frontend/cplusplus-frontend.cpp b/src/tools/cplusplus-frontend/cplusplus-frontend.cpp
index 3701a1759c0..5f9bef2cff8 100644
--- a/src/tools/cplusplus-frontend/cplusplus-frontend.cpp
+++ b/src/tools/cplusplus-frontend/cplusplus-frontend.cpp
@@ -80,7 +80,7 @@ int main(int argc, char *argv[])
// Process files
const QStringList files = args;
- foreach (const QString &fileName, files) {
+ for (const QString &fileName : files) {
// Run preprocessor
const QString fileNamePreprocessed = fileName + QLatin1String(".preprocessed");
CplusplusToolsUtils::SystemPreprocessor preprocessor(optionVerbose);
diff --git a/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp b/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp
index d834a62db0f..2a6f7b1ac30 100644
--- a/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp
+++ b/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp
@@ -65,7 +65,7 @@ class MkVisitor: protected SymbolVisitor
bool isMiscNode(ClassOrNamespace *b) const
{
- foreach (ClassOrNamespace *u, b->usings()) {
+ for (const ClassOrNamespace *u : b->usings()) {
if (oo(u->symbols().first()->name()) == QLatin1String("AST"))
return true;
}
@@ -126,11 +126,11 @@ public:
<< " Semantic(TranslationUnit *unit): ASTVisitor(unit) { translationUnit(unit->ast()->asTranslationUnit()); }" << std::endl
<< std::endl;
- foreach (ClassOrNamespace *b, interfaces) {
+ for (ClassOrNamespace *b : qAsConst(interfaces)) {
Q_ASSERT(! b->symbols().isEmpty());
Class *klass = 0;
- foreach (Symbol *s, b->symbols())
+ for (Symbol *s : b->symbols())
if ((klass = s->asClass()) != 0)
break;
@@ -158,9 +158,9 @@ public:
<< std::endl;
QHash<ClassOrNamespace *, QList<ClassOrNamespace *> > implements;
- foreach (ClassOrNamespace *b, nodes) {
+ for (ClassOrNamespace *b : qAsConst(nodes)) {
ClassOrNamespace *iface = 0;
- foreach (ClassOrNamespace *u, b->usings()) {
+ for (ClassOrNamespace *u : b->usings()) {
if (interfaces.contains(u)) {
iface = u;
break;
@@ -170,13 +170,14 @@ public:
implements[iface].append(b);
}
- foreach (ClassOrNamespace *iface, interfaces) {
- foreach (ClassOrNamespace *b, implements.value(iface)) {
+ for (ClassOrNamespace *iface : qAsConst(interfaces)) {
+ const QList<ClassOrNamespace *> values = implements.value(iface);
+ for (ClassOrNamespace *b : values) {
if (! isMiscNode(b))
continue;
Class *klass = 0;
- foreach (Symbol *s, b->symbols())
+ for (Symbol *s : b->symbols())
if ((klass = s->asClass()) != 0)
break;
@@ -190,11 +191,12 @@ public:
std::cout << std::endl;
- foreach (ClassOrNamespace *iface, interfaces) {
+ for (ClassOrNamespace *iface : qAsConst(interfaces)) {
std::cout << " // " << qPrintable(oo(iface->symbols().first()->name())) << std::endl;
- foreach (ClassOrNamespace *b, implements.value(iface)) {
+ const QList<ClassOrNamespace *> values = implements.value(iface);
+ for (ClassOrNamespace *b : values) {
Class *klass = 0;
- foreach (Symbol *s, b->symbols())
+ for (Symbol *s : b->symbols())
if ((klass = s->asClass()) != 0)
break;
@@ -207,11 +209,11 @@ public:
}
std::cout << "private:" << std::endl;
- foreach (ClassOrNamespace *b, interfaces) {
+ for (ClassOrNamespace *b : qAsConst(interfaces)) {
Q_ASSERT(! b->symbols().isEmpty());
Class *klass = 0;
- foreach (Symbol *s, b->symbols())
+ for (Symbol *s : b->symbols())
if ((klass = s->asClass()) != 0)
break;
@@ -240,11 +242,11 @@ public:
// implementation
- foreach (ClassOrNamespace *b, interfaces) {
+ for (ClassOrNamespace *b : qAsConst(interfaces)) {
Q_ASSERT(! b->symbols().isEmpty());
Class *klass = 0;
- foreach (Symbol *s, b->symbols())
+ for (Symbol *s : b->symbols())
if ((klass = s->asClass()) != 0)
break;
@@ -275,11 +277,12 @@ public:
<< std::endl;
}
- foreach (ClassOrNamespace *iface, interfaces) {
+ for (ClassOrNamespace *iface : qAsConst(interfaces)) {
std::cout << "// " << qPrintable(oo(iface->symbols().first()->name())) << std::endl;
- foreach (ClassOrNamespace *b, implements.value(iface)) {
+ const QList<ClassOrNamespace *> values = implements.value(iface);
+ for (ClassOrNamespace *b : values) {
Class *klass = 0;
- foreach (Symbol *s, b->symbols())
+ for (Symbol *s : b->symbols())
if ((klass = s->asClass()) != 0)
break;
@@ -383,8 +386,8 @@ protected:
QList<ClassOrNamespace *> baseClasses(ClassOrNamespace *b) {
QList<ClassOrNamespace *> usings = b->usings();
- foreach (ClassOrNamespace *u, usings)
- usings += baseClasses(u);
+ for (int length = usings.size(), i = 0; i < length; ++i)
+ usings += baseClasses(usings[i]);
return usings;
}
@@ -400,7 +403,7 @@ protected:
if (Symbol *s = klass->find(accept0)) {
if (Function *meth = s->type()->asFunctionType()) {
if (! meth->isPureVirtual()) {
- foreach (ClassOrNamespace *u, b->usings()) {
+ for (ClassOrNamespace *u : b->usings()) {
if (interfaces.contains(u)) {
// qDebug() << oo(klass->name()) << "implements" << oo(u->symbols().first()->name());
} else {
diff --git a/src/tools/cplusplus-update-frontend/cplusplus-update-frontend.cpp b/src/tools/cplusplus-update-frontend/cplusplus-update-frontend.cpp
index df796046822..5fe66c57c1a 100644
--- a/src/tools/cplusplus-update-frontend/cplusplus-update-frontend.cpp
+++ b/src/tools/cplusplus-update-frontend/cplusplus-update-frontend.cpp
@@ -1294,7 +1294,7 @@ void generateASTMatcher_H(const Snapshot &, const QDir &cplusplusDir,
" virtual ~ASTMatcher();\n"
"\n";
- foreach (const QByteArray &klass, classes) {
+ for (const QByteArray &klass : classes) {
out << " virtual bool match(" << klass << " *node, " << klass << " *pattern);\n";
}
@@ -1340,7 +1340,7 @@ QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir, co
Overview oo;
QStringList castMethods;
- foreach (ClassSpecifierAST *classAST, astNodes.deriveds) {
+ for (ClassSpecifierAST *classAST : qAsConst(astNodes.deriveds)) {
cursors[classAST] = removeCastMethods(classAST);
const QString className = oo(classAST->symbol->name());
const QString methodName = QLatin1String("as") + className.mid(0, className.length() - 3);
diff --git a/src/tools/icons/downloadytthumbnails.py b/src/tools/icons/downloadytthumbnails.py
new file mode 100644
index 00000000000..af5f6575f24
--- /dev/null
+++ b/src/tools/icons/downloadytthumbnails.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python
+
+############################################################################
+#
+# Copyright (C) 2022 The Qt Company Ltd.
+# Contact: https://www.qt.io/licensing/
+#
+# This file is part of Qt Creator.
+#
+# Commercial License Usage
+# Licensees holding valid commercial Qt licenses may use this file in
+# accordance with the commercial license agreement provided with the
+# Software or, alternatively, in accordance with the terms contained in
+# a written agreement between you and The Qt Company. For licensing terms
+# and conditions see https://www.qt.io/terms-conditions. For further
+# information use the contact form at https://www.qt.io/contact-us.
+#
+# GNU General Public License Usage
+# Alternatively, this file may be used under the terms of the GNU
+# General Public License version 3 as published by the Free Software
+# Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+# included in the packaging of this file. Please review the following
+# information to ensure the GNU General Public License requirements will
+# be met: https://www.gnu.org/licenses/gpl-3.0.html.
+#
+############################################################################
+
+import argparse
+import os
+import pathlib
+import subprocess
+import sys
+import tempfile
+import urllib.request
+import xml.etree.ElementTree as ET
+
+from distutils import spawn
+
+
+def qtcRoot():
+ return os.path.abspath(
+ os.path.join(os.path.dirname(sys.argv[0]), '../../..')).replace('\\', '/')
+
+
+def youtubeIdsFromXmlFile(xmlFile):
+ ids = []
+ xmlTree = ET.ElementTree()
+ xmlTree.parse(xmlFile)
+ xmlTreeRoot = xmlTree.getroot()
+ for xmlElement in xmlTreeRoot.iter():
+ try:
+ videoUrlAttrib = xmlElement.attrib['videoUrl']
+ ids.append(videoUrlAttrib[-11 : ])
+ except Exception:
+ pass
+ return ids
+
+
+def youtubeThumbnailPath(youtubeId):
+ return tempfile.gettempdir() + os.path.sep + youtubeId + ".jpg"
+
+
+def downloadThumbnails(youtubeIds, outputDir, overwriteFiles):
+ print("Downloading YouTube thumbnails:")
+ for id in youtubeIds:
+ thumbnailUrl = "https://img.youtube.com/vi/{}/maxresdefault.jpg".format(id)
+ # Available thumbnail options: "0.jpg", "hqdefault.jpg", "maxresdefault.jpg"
+ thumbnailFile = youtubeThumbnailPath(id)
+ if not overwriteFiles and os.path.exists(thumbnailFile):
+ print("Skipping " + thumbnailFile)
+ continue
+ print(thumbnailUrl + " -> " + thumbnailFile)
+ try:
+ urllib.request.urlretrieve(thumbnailUrl, thumbnailFile)
+ except Exception:
+ print("Failed to download " + thumbnailUrl)
+ pass
+
+
+def saveQtcThumbnails(youtubeIds, outputDir, magick):
+ print("Creating Qt Creator thumbnails:")
+ for id in youtubeIds:
+ ytThumbnail = youtubeThumbnailPath(id)
+ qtcThumbnail = os.path.abspath(outputDir) + os.path.sep + "youtube" + id + ".webp"
+ print(qtcThumbnail)
+ try:
+ subprocess.check_call([magick,
+ ytThumbnail,
+
+ # https://imagemagick.org/script/command-line-options.php#filter
+ "-filter", "Parzen",
+
+ # ListMyoutubeThumbnailPathodel::defaultImageSize(214, 160);
+ "-resize", "214x160",
+
+ # https://imagemagick.org/script/webp.php
+ "-define", "webp:use-sharp-yuv=1",
+ "-define", "webp:image-hint=picture",
+ "-define", "webp:method=6",
+ "-define", "webp:near-lossless=100",
+
+ qtcThumbnail])
+ except subprocess.CalledProcessError:
+ print("Failed to convert to {}.".format(qtcThumbnail))
+ pass
+
+
+def processXmlFile(xmlFile, outputDir, overwriteFiles, magick):
+ ids = youtubeIdsFromXmlFile(xmlFile)
+ downloadThumbnails(ids, outputDir, overwriteFiles)
+ saveQtcThumbnails(ids, outputDir, magick)
+
+
+def main():
+ parser = argparse.ArgumentParser(description='Parses a \'qtcreator_tutorials.xml\', '
+ 'downloads the video thumbnails from YouTube, '
+ 'scales them down to WelcomeScreen thumbnail size '
+ 'and saves them as .webm files.')
+ parser.add_argument('-xmlfile',
+ help='The \'qtcreator_tutorials.xml\' file.',
+ type=pathlib.Path,
+ default=qtcRoot() + "/src/plugins/qtsupport/qtcreator_tutorials.xml")
+ parser.add_argument('-outputdir',
+ help='Where the downloaded files are written.',
+ type=pathlib.Path,
+ default=qtcRoot() + "/src/plugins/qtsupport/images/icons")
+ parser.add_argument('-overwrite',
+ help='Overwrite existing downloaded files.',
+ action='store_true')
+ args = parser.parse_args()
+
+ magick = spawn.find_executable("magick")
+ if magick is None:
+ magick = spawn.find_executable("convert")
+ if magick is None:
+ sys.exit("ImageMagick was not found in Path.")
+
+ processXmlFile(args.xmlfile, args.outputdir, args.overwrite, magick)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/src/tools/icons/export.py b/src/tools/icons/export.py
index 2ead1ceab4c..e4739b51597 100644
--- a/src/tools/icons/export.py
+++ b/src/tools/icons/export.py
@@ -74,7 +74,8 @@ def pngName(svgID, scale):
def checkDirectories(svgIDs):
invalidDirectories = []
for id in svgIDs:
- if not os.path.isdir(os.path.join(qtcRoot(), id, '../')):
+ dirForId = os.path.abspath(os.path.join(qtcRoot(), id, os.pardir))
+ if not os.path.isdir(dirForId):
invalidDirectories.append(id)
if invalidDirectories:
diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg
index a6116294e1f..cf36d208929 100644
--- a/src/tools/icons/qtcreatoricons.svg
+++ b/src/tools/icons/qtcreatoricons.svg
@@ -32,22 +32,6 @@
</linearGradient>
<linearGradient
inkscape:collect="always"
- id="linearGradient3970">
- <stop
- style="stop-color:#000000;stop-opacity:0"
- offset="0"
- id="stop3966" />
- <stop
- id="stop3974"
- offset="0.35135135"
- style="stop-color:#000000;stop-opacity:0" />
- <stop
- style="stop-color:#000000;stop-opacity:1"
- offset="1"
- id="stop3968" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
id="linearGradient9821">
<stop
style="stop-color:#000000;stop-opacity:1"
@@ -499,27 +483,6 @@
</linearGradient>
<linearGradient
inkscape:collect="always"
- xlink:href="#linear-gradient-7"
- id="linearGradient2898"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(75,0,0,-75,14430,8329)"
- x1="-190.82001"
- y1="109.69"
- x2="-191.87"
- y2="110.83" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3970"
- id="radialGradient3972"
- cx="548.5"
- cy="91.5"
- fx="548.5"
- fy="91.5"
- r="18.5"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(112,18)" />
- <linearGradient
- inkscape:collect="always"
xlink:href="#linearGradient2550"
id="linearGradient2552"
x1="74"
@@ -527,6 +490,43 @@
x2="75"
y2="534"
gradientUnits="userSpaceOnUse" />
+ <filter
+ style="color-interpolation-filters:sRGB;"
+ inkscape:label="Drop Shadow"
+ id="filter7112"
+ x="-0.34384615"
+ y="-0.34384615"
+ width="1.6876923"
+ height="1.6876923"
+ inkscape:auto-region="false">
+ <feFlood
+ flood-opacity=".85"
+ flood-color="rgb(0,0,0)"
+ result="flood"
+ id="feFlood7102" />
+ <feComposite
+ in="flood"
+ in2="SourceGraphic"
+ operator="in"
+ result="composite1"
+ id="feComposite7104" />
+ <feGaussianBlur
+ in="composite1"
+ stdDeviation="3.1"
+ result="blur"
+ id="feGaussianBlur7106" />
+ <feOffset
+ dx="0"
+ dy="0"
+ result="offset"
+ id="feOffset7108" />
+ <feComposite
+ in="offset"
+ in2="SourceGraphic"
+ operator="destination-over"
+ result="composite2"
+ id="feComposite7110" />
+ </filter>
</defs>
<sodipodi:namedview
id="base"
@@ -673,27 +673,32 @@
id="layer7"
inkscape:label="Welcome screen thumbnails">
<g
- id="src/plugins/qtsupport/images/icons/videotutorialicon"
- transform="translate(0,-32)">
- <rect
- id="rect2451"
- height="160"
- width="214"
- class="cls-1"
+ id="src/plugins/qtsupport/images/icons/playoverlay"
+ transform="translate(-166,-44)">
+ <use
x="0"
y="0"
- style="fill:#26282a" />
- <path
- d="M 102.73,92.34 V 81.12 l 9.62,5.61 z m -0.53,-14 a 1,1 0 0 0 -1.06,0 1.05,1.05 0 0 0 -0.54,0.93 V 94.2 a 1,1 0 0 0 0.54,0.92 1,1 0 0 0 0.53,0.15 1,1 0 0 0 0.53,-0.15 L 115,87.65 a 1.06,1.06 0 0 0 0,-1.84 z m 32.53,-11.88 v 38.4 a 1.07,1.07 0 0 1 -2.13,0 V 66.47 A 1.07,1.07 0 0 0 131.53,65.4 H 82.47 a 1.07,1.07 0 0 0 -1.07,1.07 v 41.6 h 52.27 a 1.07,1.07 0 0 1 0,2.13 H 80.33 a 1.06,1.06 0 0 1 -1.06,-1.07 V 66.47 a 3.2,3.2 0 0 1 3.2,-3.2 h 49.06 a 3.2,3.2 0 0 1 3.2,3.2 z M 95.27,116.6 a 1.07,1.07 0 1 1 1.06,-1.07 1.07,1.07 0 0 1 -1.06,1.07 z m 36.26,-2.13 H 98.27 a 3.18,3.18 0 0 0 -6,0 H 84.6 a 1.07,1.07 0 1 0 0,2.13 h 7.66 a 3.18,3.18 0 0 0 6,0 h 33.26 a 1.07,1.07 0 1 0 0,-2.13 z m 5.34,3.2 a 3.21,3.21 0 0 1 -3.2,3.2 H 80.33 a 3.21,3.21 0 0 1 -3.2,-3.2 V 64.33 a 3.21,3.21 0 0 1 3.2,-3.2 h 53.34 a 3.21,3.21 0 0 1 3.2,3.2 z M 133.67,59 H 80.33 A 5.33,5.33 0 0 0 75,64.33 v 53.34 a 5.33,5.33 0 0 0 5.33,5.33 h 53.34 A 5.33,5.33 0 0 0 139,117.67 V 64.33 A 5.33,5.33 0 0 0 133.67,59 Z"
- class="cls-2"
- id="video-player"
- inkscape:connector-curvature="0"
- style="fill:url(#linearGradient2898);fill-opacity:1" />
- <path
- id="path2480"
- style="fill:#17a81a"
- d="M 157.135,41.74 V 29 h 2 v 12.74 z m -2.58,-6.22 v 4.1 a 0.91,0.91 0 0 0 0.21,0.58 1,1 0 0 0 0.59,0.25 l -0.06,1.49 a 3.8,3.8 0 0 1 -2.39,-0.66 6.91,6.91 0 0 1 -2.9,0.66 c -1.79,0 -2.68,-1 -2.68,-2.86 a 2.44,2.44 0 0 1 0.73,-2 4,4 0 0 1 2.24,-0.74 l 2.32,-0.2 V 35.5 a 1.33,1.33 0 0 0 -0.31,-1 1.35,1.35 0 0 0 -0.93,-0.29 c -0.77,0 -1.73,0 -2.88,0.14 h -0.58 L 147.845,33 a 15.72,15.72 0 0 1 3.61,-0.46 3.31,3.31 0 0 1 2.38,0.71 3,3 0 0 1 0.72,2.27 z m -4,2.23 a 1.21,1.21 0 0 0 -1.24,1.35 c 0,0.83 0.37,1.24 1.1,1.24 a 7.1,7.1 0 0 0 1.91,-0.29 l 0.32,-0.11 v -2.39 z m -6.99,-6.54 v -2.07 h 2 v 2.07 z m 0,10.53 v -9 h 2 v 9 z m -6.5,0 v -9 h 1.94 v 1.08 a 8.5,8.5 0 0 1 3.06,-1.27 v 2 a 12.57,12.57 0 0 0 -2.64,0.79 l -0.4,0.16 v 6.28 z m -9.05,-8.02 a 4.67,4.67 0 0 1 6.18,0 5.57,5.57 0 0 1 0.92,3.51 5.76,5.76 0 0 1 -0.9,3.52 4.66,4.66 0 0 1 -6.22,0 5.76,5.76 0 0 1 -0.9,-3.52 5.57,5.57 0 0 1 0.92,-3.51 z m 1.47,5.85 a 2.18,2.18 0 0 0 3.24,0 5,5 0 0 0 0.41,-2.36 4.42,4.42 0 0 0 -0.44,-2.32 2.18,2.18 0 0 0 -3.18,0 4.42,4.42 0 0 0 -0.44,2.32 5,5 0 0 0 0.41,2.36 z m -3.56,-5.15 h -2.49 v 4 a 4.12,4.12 0 0 0 0.17,1.46 c 0.1,0.24 0.38,0.36 0.82,0.36 l 1.48,-0.06 0.09,1.57 a 11.12,11.12 0 0 1 -1.84,0.23 2.55,2.55 0 0 1 -2.09,-0.7 4.41,4.41 0 0 1 -0.57,-2.65 v -4.21 h -1.15 v -1.68 h 1.15 v -2.61 h 1.94 v 2.61 h 2.49 z m -9.17,-1.68 h 2 v 9 h -2 v -0.55 a 4.93,4.93 0 0 1 -2.43,0.75 2.71,2.71 0 0 1 -2.48,-1 7,7 0 0 1 -0.63,-3.5 v -4.7 h 2 v 4.72 a 5.78,5.78 0 0 0 0.22,2.18 c 0.18,0.37 0.6,0.56 1.26,0.56 a 4.32,4.32 0 0 0 1.78,-0.36 l 0.27,-0.11 z m -14.65,-1.54 v -1.79 h 9 v 1.79 h -3.47 v 10.54 h -2 V 31.2 Z m -12.05,2.52 a 4.65,4.65 0 0 1 6.17,0 5.57,5.57 0 0 1 0.93,3.51 5.76,5.76 0 0 1 -0.9,3.52 3.65,3.65 0 0 1 -3.11,1.19 3.66,3.66 0 0 1 -3.12,-1.19 5.76,5.76 0 0 1 -0.9,-3.52 5.57,5.57 0 0 1 0.93,-3.51 z m 1.47,5.85 a 1.69,1.69 0 0 0 1.62,0.72 1.71,1.71 0 0 0 1.62,-0.72 5.08,5.08 0 0 0 0.41,-2.36 4.42,4.42 0 0 0 -0.44,-2.32 2.18,2.18 0 0 0 -3.18,0 4.41,4.41 0 0 0 -0.45,2.32 4.93,4.93 0 0 0 0.42,2.36 z m -4.7,0.55 0.5,-0.05 v 1.46 a 19.1,19.1 0 0 1 -3.64,0.41 3.44,3.44 0 0 1 -2.87,-1.1 5.65,5.65 0 0 1 -0.87,-3.51 q 0,-4.78 3.91,-4.78 3.91,0 3.78,4.12 l -0.13,1.4 h -5.54 a 2.41,2.41 0 0 0 0.47,1.64 2.27,2.27 0 0 0 1.74,0.52 c 0.87,0 1.75,-0.03 2.65,-0.11 z m -1.08,-3.56 a 3.07,3.07 0 0 0 -0.42,-1.86 1.71,1.71 0 0 0 -1.43,-0.53 1.78,1.78 0 0 0 -1.47,0.55 3,3 0 0 0 -0.48,1.84 z M 78.045,29 v 12.74 h -2 v -0.46 a 5.42,5.42 0 0 1 -2.41,0.66 3,3 0 0 1 -2.58,-1.06 5.92,5.92 0 0 1 -0.82,-3.56 5.81,5.81 0 0 1 0.91,-3.64 3.39,3.39 0 0 1 2.83,-1.13 13.15,13.15 0 0 1 2,0.23 V 29 Z m -2.27,10.87 0.3,-0.12 v -5.33 a 12.14,12.14 0 0 0 -2,-0.18 c -1.22,0 -1.82,1 -1.82,3 a 4.48,4.48 0 0 0 0.42,2.3 1.5,1.5 0 0 0 1.34,0.64 4.66,4.66 0 0 0 1.76,-0.31 z m -9.42,-8.66 v -2.07 h 2 v 2.07 z m 0,10.53 v -9 h 2 v 9 z m -3.63,-12.33 h 2.09 l -3,12.33 h -3.95 l -3,-12.33 h 2.09 L 59.375,40 h 0.9 z"
- inkscape:connector-curvature="0" />
+ xlink:href="#transparentBackgroundRect"
+ id="use7212"
+ width="100%"
+ height="100%"
+ transform="matrix(4.5,0,0,4.5,238,-1990)" />
+ <g
+ id="g6770"
+ style="filter:url(#filter7112)"
+ transform="translate(32.5,-8)">
+ <circle
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path1730"
+ cx="169.5"
+ cy="88"
+ r="20.5" />
+ <path
+ style="fill:#ffffff;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 164.5,79.5 v 17 L 178,88 Z"
+ id="path5039"
+ sodipodi:nodetypes="cccc" />
+ </g>
</g>
<g
id="src/plugins/qtsupport/images/icons/tutorialicon"
@@ -718,36 +723,6 @@
d="M 133.5,41.74 V 29 h 2 v 12.74 z m -2.57,-6.22 v 4.1 a 0.86,0.86 0 0 0 0.2,0.58 1,1 0 0 0 0.59,0.25 v 1.49 a 3.81,3.81 0 0 1 -2.4,-0.66 6.91,6.91 0 0 1 -2.9,0.66 c -1.79,0 -2.68,-1 -2.68,-2.86 a 2.44,2.44 0 0 1 0.73,-2 4,4 0 0 1 2.24,-0.74 l 2.32,-0.2 V 35.5 a 1.33,1.33 0 0 0 -0.31,-1 1.35,1.35 0 0 0 -0.93,-0.29 c -0.77,0 -1.73,0 -2.88,0.14 h -0.57 L 124.21,33 a 15.72,15.72 0 0 1 3.61,-0.46 3.31,3.31 0 0 1 2.38,0.71 3.05,3.05 0 0 1 0.73,2.27 z m -4,2.23 a 1.21,1.21 0 0 0 -1.25,1.35 c 0,0.83 0.37,1.24 1.1,1.24 a 7,7 0 0 0 1.91,-0.29 l 0.32,-0.11 v -2.39 z m -7,-6.54 v -2.07 h 2 v 2.07 z m 0,10.53 v -9 h 2 v 9 z m -6.5,0 v -9 h 1.95 v 1.08 a 8.42,8.42 0 0 1 3.06,-1.27 v 2 a 12.5,12.5 0 0 0 -2.65,0.79 l -0.4,0.16 v 6.28 z m -9.04,-8.02 a 4.65,4.65 0 0 1 6.17,0 5.57,5.57 0 0 1 0.94,3.51 5.76,5.76 0 0 1 -0.9,3.52 4.67,4.67 0 0 1 -6.23,0 5.76,5.76 0 0 1 -0.9,-3.52 5.57,5.57 0 0 1 0.92,-3.51 z m 1.46,5.85 a 1.71,1.71 0 0 0 1.62,0.72 1.69,1.69 0 0 0 1.62,-0.72 4.93,4.93 0 0 0 0.41,-2.36 4.53,4.53 0 0 0 -0.44,-2.32 1.76,1.76 0 0 0 -1.56,-0.69 1.74,1.74 0 0 0 -1.59,0.69 4.53,4.53 0 0 0 -0.44,2.32 5.08,5.08 0 0 0 0.38,2.36 z m -3.56,-5.15 h -2.48 v 4 a 4.19,4.19 0 0 0 0.16,1.46 c 0.11,0.24 0.38,0.36 0.83,0.36 l 1.47,-0.06 0.09,1.57 a 10.91,10.91 0 0 1 -1.83,0.23 2.59,2.59 0 0 1 -2.1,-0.7 4.41,4.41 0 0 1 -0.57,-2.65 v -4.21 h -1.15 v -1.68 h 1.15 v -2.61 h 2 v 2.61 h 2.48 z m -9.16,-1.68 h 1.94 v 9 h -1.94 v -0.55 a 5,5 0 0 1 -2.43,0.75 2.72,2.72 0 0 1 -2.49,-1 7,7 0 0 1 -0.63,-3.5 v -4.7 h 2 v 4.72 a 5.78,5.78 0 0 0 0.27,2.18 c 0.18,0.37 0.6,0.56 1.26,0.56 a 4.36,4.36 0 0 0 1.78,-0.36 l 0.27,-0.11 z M 78.5,31.2 v -1.79 h 9 V 31.2 H 84 V 41.74 H 82 V 31.2 Z"
inkscape:connector-curvature="0" />
</g>
- <g
- id="src/plugins/qtsupport/images/icons/qteventicon"
- transform="translate(428,-32)">
- <rect
- id="rect2709"
- height="160"
- width="214"
- class="cls-1"
- x="0"
- y="0"
- style="fill:#ffffff" />
- <path
- d="m 139,66.2 v 4.27 a 1.06,1.06 0 0 1 -1.07,1.06 h -1.06 v 24.54 a 1.07,1.07 0 0 1 -2.14,0 v -25.6 a 1.07,1.07 0 0 1 1.07,-1.07 h 1.07 V 67.27 H 77.13 v 2.13 h 54.4 a 1.07,1.07 0 1 1 0,2.13 H 76.07 A 1.06,1.06 0 0 1 75,70.47 V 66.2 a 1.07,1.07 0 0 1 1.07,-1.07 h 29.86 v -1.06 a 1.07,1.07 0 1 1 2.14,0 v 1.06 h 29.86 A 1.07,1.07 0 0 1 139,66.2 Z M 88.87,80.07 h 8.53 a 1.07,1.07 0 0 0 0,-2.14 h -8.53 a 1.07,1.07 0 0 0 0,2.14 z m 0,6.4 h 19.2 a 1.07,1.07 0 0 0 0,-2.14 h -19.2 a 1.07,1.07 0 0 0 0,2.14 z m 17.06,-6.4 a 1.07,1.07 0 0 0 0,-2.14 h -4.26 a 1.07,1.07 0 0 0 0,2.14 z m -17.06,12.8 h 3.2 a 1.07,1.07 0 0 0 0,-2.14 h -3.2 a 1.07,1.07 0 0 0 0,2.14 z m 19.2,-2.14 H 97.4 a 1.07,1.07 0 0 0 0,2.14 h 10.67 a 1.07,1.07 0 0 0 0,-2.14 z m 19.27,6.42 a 1.11,1.11 0 0 0 -1.13,0.92 L 123,121.52 a 1.06,1.06 0 0 0 0.91,1.2 h 0.15 a 1.06,1.06 0 0 0 1.05,-0.92 l 3.08,-22.52 c 3.68,0.09 6.2,0.79 7.49,2.08 a 4.34,4.34 0 0 1 1.18,3.23 v 17.08 a 1.07,1.07 0 0 0 2.13,0 V 104.6 a 6.46,6.46 0 0 0 -1.8,-4.74 c -1.83,-1.82 -5.06,-2.71 -9.86,-2.71 z m -9.68,0.91 3.2,23.46 a 1.07,1.07 0 0 1 -2.12,0.29 l -3.07,-22.54 h -17.2 v 4.26 h 11.73 a 1.06,1.06 0 0 1 1.06,1 l 2.13,21.34 a 1.05,1.05 0 0 1 -1,1.16 h -0.11 a 1.07,1.07 0 0 1 -1.06,-1 l -2,-20.37 h -14 c -5,0 -7.47,-4.79 -7.47,-7.47 a 1.07,1.07 0 0 1 1.07,-1.07 h 27.78 a 1.08,1.08 0 0 1 1.06,0.93 z m -21.33,1.21 h -6.21 c 0.52,1.74 2.16,4.26 5.15,4.26 h 1.06 z m 27.74,0 a 2.14,2.14 0 1 0 -4.27,0 2.11,2.11 0 0 0 1.07,1.83 v 7.77 a 1.07,1.07 0 0 0 2.13,0 v -7.77 a 2.14,2.14 0 0 0 1.07,-1.83 z m 6.4,-19.2 v 0.28 a 2.15,2.15 0 0 1 1.06,1.85 v 2.13 a 2.12,2.12 0 0 1 -1.1,1.87 12.85,12.85 0 0 1 -1.14,3.94 c -1,1.94 -2.43,4.86 -7.36,4.86 -4.93,0 -6.38,-2.92 -7.35,-4.86 a 12.55,12.55 0 0 1 -1.14,-3.94 2.13,2.13 0 0 1 -1.11,-1.87 V 82.2 a 2.13,2.13 0 0 1 1.07,-1.85 v -0.28 a 6.41,6.41 0 0 1 6.4,-6.4 h 4.27 a 6.41,6.41 0 0 1 6.4,6.4 z m -1.07,2.13 a 1.07,1.07 0 0 1 -1.07,-1.07 v -1.06 a 4.27,4.27 0 0 0 -4.26,-4.27 h -4.27 a 4.27,4.27 0 0 0 -4.27,4.27 v 1.06 a 1.06,1.06 0 0 1 -1.06,1.07 v 2.13 a 1.06,1.06 0 0 1 1.06,1.07 9.93,9.93 0 0 0 1,3.79 c 1.11,2.22 2.09,3.68 5.44,3.68 3.35,0 4.34,-1.46 5.45,-3.68 a 10,10 0 0 0 1,-3.79 1.07,1.07 0 0 1 1.07,-1.07 V 82.2 Z m -4.27,0 h -1.06 a 1.07,1.07 0 1 0 0,2.13 h 1.06 a 1.07,1.07 0 1 0 0,-2.13 z m -5.33,0 h -1.07 a 1.07,1.07 0 0 0 0,2.13 h 1.07 a 1.07,1.07 0 1 0 0,-2.13 z m 11.73,27.73 a 1.06,1.06 0 0 0 -1.06,1.07 v 14.93 a 1.07,1.07 0 1 0 2.13,0 V 111 a 1.07,1.07 0 0 0 -1.07,-1.07 z m -24.53,0 H 82.47 a 3.12,3.12 0 0 1 -3.2,-3.2 v -32 a 1.07,1.07 0 0 0 -2.14,0 v 32 a 5.29,5.29 0 0 0 5.34,5.34 H 107 a 1.07,1.07 0 0 0 0,-2.14 z"
- class="cls-2"
- id="presentation-man"
- inkscape:connector-curvature="0"
- style="fill:#222840" />
- <path
- id="path2724"
- style="fill:#17a81a"
- d="m 127.32716,41.74 h -2 V 29 h 2 v 7.36 l 1.11,-0.11 2.13,-3.51 h 2.19 l -2.59,4.26 2.74,4.78 h -2.21 l -2.2,-3.78 -1.17,0.12 z m -6.41,0 V 29 h 2 v 12.74 z m -2.57,-6.22 v 4.1 a 0.86,0.86 0 0 0 0.2,0.58 1,1 0 0 0 0.59,0.25 l -0.06,1.49 a 3.8,3.8 0 0 1 -2.38,-0.66 6.91,6.91 0 0 1 -2.9,0.66 c -1.79,0 -2.68,-1 -2.68,-2.86 a 2.44,2.44 0 0 1 0.73,-2 4,4 0 0 1 2.24,-0.74 l 2.32,-0.2 V 35.5 a 1.33,1.33 0 0 0 -0.31,-1 1.35,1.35 0 0 0 -0.93,-0.29 c -0.77,0 -1.73,0 -2.88,0.14 h -0.58 l -0.08,-1.35 a 15.72,15.72 0 0 1 3.61,-0.46 3.31,3.31 0 0 1 2.38,0.71 3.05,3.05 0 0 1 0.73,2.27 z m -4,2.23 a 1.21,1.21 0 0 0 -1.24,1.35 c 0,0.83 0.37,1.24 1.1,1.24 a 7,7 0 0 0 1.91,-0.29 l 0.32,-0.11 v -2.39 z m -11.65,-6.55 v -1.79 h 9 v 1.79 h -3.49 v 10.54 h -2 V 31.2 Z m -4.619996,3.22 h -2.49 v 4 a 4.12,4.12 0 0 0 0.17,1.46 c 0.1,0.24 0.38,0.36 0.82,0.36 l 1.48,-0.06 0.09,1.57 a 11,11 0 0 1 -1.84,0.23 2.55,2.55 0 0 1 -2.09,-0.7 4.41,4.41 0 0 1 -0.52,-2.69 v -4.17 h -1.2 v -1.68 h 1.2 v -2.61 h 1.94 v 2.61 h 2.49 z m -11.94,7.52 c -1.87,0 -3.17,-0.5 -3.91,-1.51 a 8.16,8.16 0 0 1 -1.11,-4.78 8.43,8.43 0 0 1 1.13,-4.85 c 0.75,-1.06 2,-1.58 3.89,-1.58 1.89,0 3.15,0.52 3.89,1.57 a 8.41,8.41 0 0 1 1.12,4.85 11.08,11.08 0 0 1 -0.45,3.49 4,4 0 0 1 -1.5,2 l 1.5,2.47 -1.86,0.86 -1.6,-2.63 a 3.68,3.68 0 0 1 -1.1,0.11 z m -2.34,-2.8 a 3.13,3.13 0 0 0 4.68,0 7.43,7.43 0 0 0 0.6,-3.5 7.78,7.78 0 0 0 -0.62,-3.58 3,3 0 0 0 -4.64,0 7.56,7.56 0 0 0 -0.63,3.56 7.47,7.47 0 0 0 0.61,3.52 z"
- inkscape:connector-curvature="0" />
- </g>
- <rect
- style="fill:url(#radialGradient3972)"
- id="src/plugins/welcome/images/border"
- width="37"
- height="37"
- x="642"
- y="91" />
</g>
<g
inkscape:groupmode="layer"
@@ -9921,43 +9896,6 @@
id="path6333" />
</g>
<g
- id="src/plugins/winrt/images/winrtdevice"
- transform="translate(-206,-74)">
- <use
- transform="translate(561,337)"
- style="display:inline"
- x="0"
- y="0"
- xlink:href="#backgroundRect_32_28"
- id="use5913-0-8-1-5-6-8-11"
- width="100%"
- height="100%" />
- <path
- sodipodi:nodetypes="cccccccccccccccccccc"
- style="fill:#000000;fill-opacity:1"
- inkscape:connector-curvature="0"
- d="m 607,391 h 10 v -10.16502 l -10,1.1313 z m 12,-10.3911 V 391 h 12 v -11.74108 z m 0,22.75938 12,1.34794 V 393 h -12 z m -12,-1.35943 10,1.12952 V 393 h -10 z"
- id="path5333-0" />
- </g>
- <g
- id="src/plugins/winrt/images/winrtdevicesmall"
- transform="translate(-238,-58)">
- <use
- x="0"
- y="0"
- xlink:href="#backgroundRect"
- id="use6054-3"
- width="100%"
- height="100%"
- transform="translate(650,-41)" />
- <path
- sodipodi:nodetypes="cccccccccccccccccccc"
- style="fill:#000000;fill-opacity:1"
- inkscape:connector-curvature="0"
- d="M 636.00003,403 H 641 v -4.67861 l -4.99997,0.67433 z M 642,398.18129 V 403 h 6.00003 v -5.6287 z m 0,10.72061 6.00003,0.81345 V 404 H 642 Z M 636.00003,408.09093 641,408.7667 V 404 h -4.99997 z"
- id="path5333" />
- </g>
- <g
id="src/plugins/debugger/images/debugger_stop_mask"
transform="translate(-711,333)"
style="display:inline">
diff --git a/src/tools/iostool/CMakeLists.txt b/src/tools/iostool/CMakeLists.txt
index e02bf7463d4..b7efdc1abda 100644
--- a/src/tools/iostool/CMakeLists.txt
+++ b/src/tools/iostool/CMakeLists.txt
@@ -18,6 +18,7 @@ add_qtc_executable(iostool
main.cpp
mobiledevicelib.cpp mobiledevicelib.h
relayserver.cpp relayserver.h
+ cfutils.h
)
if (TARGET iostool)
diff --git a/src/tools/iostool/cfutils.h b/src/tools/iostool/cfutils.h
new file mode 100644
index 00000000000..94e8452f0ce
--- /dev/null
+++ b/src/tools/iostool/cfutils.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QString>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace Ios {
+
+template<typename CFType>
+struct CFRefDeleter
+{
+ using pointer = CFType;
+ void operator()(CFType ref) { CFRelease(ref); }
+};
+
+inline QString toQStringRelease(CFStringRef str)
+{
+ QString result = QString::fromCFString(str);
+ CFRelease(str);
+ return result;
+}
+
+using CFString_t = std::unique_ptr<CFStringRef, CFRefDeleter<CFStringRef>>;
+using CFUrl_t = std::unique_ptr<CFURLRef, CFRefDeleter<CFURLRef>>;
+using CFPropertyList_t = std::unique_ptr<CFPropertyListRef, CFRefDeleter<CFPropertyListRef>>;
+using CFBundle_t = std::unique_ptr<CFBundleRef, CFRefDeleter<CFBundleRef>>;
+using CFDictionary_t = std::unique_ptr<CFDictionaryRef, CFRefDeleter<CFDictionaryRef>>;
+using CFArray_t = std::unique_ptr<CFArrayRef, CFRefDeleter<CFArrayRef>>;
+
+} // namespace Ios
diff --git a/src/tools/iostool/iosdevicemanager.cpp b/src/tools/iostool/iosdevicemanager.cpp
index 0f24d58868f..781420beeb0 100644
--- a/src/tools/iostool/iosdevicemanager.cpp
+++ b/src/tools/iostool/iosdevicemanager.cpp
@@ -25,19 +25,19 @@
#include "iosdevicemanager.h"
+#include "cfutils.h"
#include "mobiledevicelib.h"
-#include <QDebug>
#include <QDir>
#include <QFile>
#include <QHash>
#include <QLibrary>
+#include <QLoggingCategory>
#include <QMultiHash>
#include <QMutex>
#include <QMutexLocker>
#include <QProcess>
#include <QRegularExpression>
-#include <QRegularExpression>
#include <QSettings>
#include <QThread>
#include <QTimer>
@@ -54,6 +54,10 @@ static const bool debugAll = false;
static const bool verbose = true;
static const bool noWifi = true;
+namespace {
+ Q_LOGGING_CATEGORY(loggingCategory, "qtc.iostool.iosdevicemanager", QtWarningMsg)
+}
+
// ------- MobileDeviceLib interface --------
namespace {
@@ -277,8 +281,12 @@ public:
static IosDeviceManagerPrivate *instance();
explicit IosDeviceManagerPrivate (IosDeviceManager *q);
bool watchDevices();
- void requestAppOp(const QString &bundlePath, const QStringList &extraArgs,
- Ios::IosDeviceManager::AppOp appOp, const QString &deviceId, int timeout);
+ void requestAppOp(const QString &bundlePath,
+ const QStringList &extraArgs,
+ Ios::IosDeviceManager::AppOp appOp,
+ const QString &deviceId,
+ int timeout,
+ const QString &deltaPath);
void requestDeviceInfo(const QString &deviceId, int timeout);
QStringList errors();
void addError(QString errorMsg);
@@ -321,13 +329,17 @@ public:
QString bundlePath;
QStringList extraArgs;
Ios::IosDeviceManager::AppOp appOp;
+ QString deltaPath;
-
- AppOpSession(const QString &deviceId, const QString &bundlePath,
- const QStringList &extraArgs, Ios::IosDeviceManager::AppOp appOp);
+ AppOpSession(const QString &deviceId,
+ const QString &bundlePath,
+ const QStringList &extraArgs,
+ Ios::IosDeviceManager::AppOp appOp,
+ const QString &deltaPath);
void deviceCallbackReturned() override;
bool installApp();
+ bool installAppNew();
bool runApp();
int qmljsDebugPort() const override;
am_res_t appTransferCallback(CFDictionaryRef dict) override;
@@ -486,11 +498,13 @@ bool IosDeviceManagerPrivate::watchDevices()
}
void IosDeviceManagerPrivate::requestAppOp(const QString &bundlePath,
- const QStringList &extraArgs,
- IosDeviceManager::AppOp appOp,
- const QString &deviceId, int timeout)
+ const QStringList &extraArgs,
+ IosDeviceManager::AppOp appOp,
+ const QString &deviceId,
+ int timeout,
+ const QString &deltaPath)
{
- AppOpSession *session = new AppOpSession(deviceId, bundlePath, extraArgs, appOp);
+ AppOpSession *session = new AppOpSession(deviceId, bundlePath, extraArgs, appOp, deltaPath);
session->startDeviceLookup(timeout);
}
@@ -560,7 +574,7 @@ void IosDeviceManagerPrivate::addDevice(AMDeviceRef device)
m_pendingLookups.remove(devId);
devices << m_pendingLookups.values(QString());
m_pendingLookups.remove(QString());
- foreach (PendingDeviceLookup *devLookup, devices) {
+ for (PendingDeviceLookup *devLookup : qAsConst(devices)) {
if (debugAll) qDebug() << "found pending op";
devLookup->timer.stop();
devLookup->callback(devId, device, devLookup->userData);
@@ -589,8 +603,10 @@ void IosDeviceManagerPrivate::removeDevice(AMDeviceRef device)
void IosDeviceManagerPrivate::checkPendingLookups()
{
- foreach (const QString &deviceId, m_pendingLookups.keys()) {
- foreach (PendingDeviceLookup *deviceLookup, m_pendingLookups.values(deviceId)) {
+ const QStringList keys = m_pendingLookups.keys();
+ for (const QString &deviceId : keys) {
+ const QList<PendingDeviceLookup *> values = m_pendingLookups.values(deviceId);
+ for (PendingDeviceLookup *deviceLookup : values) {
if (!deviceLookup->timer.isActive()) {
m_pendingLookups.remove(deviceId, deviceLookup);
deviceLookup->callback(deviceId, 0, deviceLookup->userData);
@@ -1203,10 +1219,17 @@ bool CommandSession::developerDiskImagePath(QString *path, QString *signaturePat
return false;
}
-AppOpSession::AppOpSession(const QString &deviceId, const QString &bundlePath,
- const QStringList &extraArgs, IosDeviceManager::AppOp appOp):
- CommandSession(deviceId), bundlePath(bundlePath), extraArgs(extraArgs), appOp(appOp)
-{ }
+AppOpSession::AppOpSession(const QString &deviceId,
+ const QString &bundlePath,
+ const QStringList &extraArgs,
+ IosDeviceManager::AppOp appOp,
+ const QString &deltaPath)
+ : CommandSession(deviceId)
+ , bundlePath(bundlePath)
+ , extraArgs(extraArgs)
+ , appOp(appOp)
+ , deltaPath(deltaPath)
+{}
QString AppOpSession::commandName()
{
@@ -1216,72 +1239,145 @@ QString AppOpSession::commandName()
bool AppOpSession::installApp()
{
bool success = false;
- if (device != 0) {
- CFURLRef bundleUrl = QUrl::fromLocalFile(bundlePath).toCFURL();
- CFStringRef key[1] = {CFSTR("PackageType")};
- CFStringRef value[1] = {CFSTR("Developer")};
- CFDictionaryRef options = CFDictionaryCreate(0, reinterpret_cast<const void**>(&key[0]),
- reinterpret_cast<const void**>(&value[0]), 1,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
+ if (device) {
+ if (!installAppNew()) {
+ addError(QString::fromLatin1(
+ "Failed to transfer and install application, trying old way ..."));
- MobileDeviceLib &mLib = MobileDeviceLib::instance();
- // Transfer bundle with secure API AMDeviceTransferApplication.
- if (int error = mLib.deviceSecureTransferApplicationPath(0, device, bundleUrl, options,
- &appSecureTransferSessionCallback,0)) {
- addError(QString::fromLatin1("TransferAppSession(%1,%2) failed, AMDeviceTransferApplication returned %3 (0x%4)")
- .arg(bundlePath, deviceId).arg(mobileDeviceErrorString(error)).arg(error));
- success = false;
- } else {
- // App is transferred. Try installing.
- if (connectDevice()) {
- // Secure install app api requires device to be connected.
- if (am_res_t error = mLib.deviceSecureInstallApplication(0, device, bundleUrl, options,
- &appSecureTransferSessionCallback,0)) {
- const QString errorString = mobileDeviceErrorString(error);
- if (!errorString.isEmpty()) {
- addError(errorString
- + QStringLiteral(" (0x")
- + QString::number(error, 16)
- + QStringLiteral(")"));
+ const CFUrl_t bundleUrl(QUrl::fromLocalFile(bundlePath).toCFURL());
+ MobileDeviceLib &mLib = MobileDeviceLib::instance();
+
+ CFStringRef key[1] = {CFSTR("PackageType")};
+ CFStringRef value[1] = {CFSTR("Developer")};
+ const CFDictionary_t options(
+ CFDictionaryCreate(0,
+ reinterpret_cast<const void **>(&key[0]),
+ reinterpret_cast<const void **>(&value[0]),
+ 1,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ // Transfer bundle with secure API AMDeviceTransferApplication.
+ if (int error
+ = mLib.deviceSecureTransferApplicationPath(0,
+ device,
+ bundleUrl.get(),
+ options.get(),
+ &appSecureTransferSessionCallback,
+ 0)) {
+ addError(QString::fromLatin1("TransferAppSession(%1,%2) failed, "
+ "AMDeviceTransferApplication returned %3 (0x%4)")
+ .arg(bundlePath, deviceId)
+ .arg(mobileDeviceErrorString(error))
+ .arg(error));
+ success = false;
+ } else {
+ // App is transferred. Try installing.
+ if (connectDevice()) {
+ // Secure install app api requires device to be connected.
+ if (am_res_t error
+ = mLib.deviceSecureInstallApplication(0,
+ device,
+ bundleUrl.get(),
+ options.get(),
+ &appSecureTransferSessionCallback,
+ 0)) {
+ const QString errorString = mobileDeviceErrorString(error);
+ if (!errorString.isEmpty()) {
+ addError(errorString + QStringLiteral(" (0x")
+ + QString::number(error, 16) + QStringLiteral(")"));
+ } else {
+ addError(QString::fromLatin1("InstallAppSession(%1,%2) failed, "
+ "AMDeviceInstallApplication returned 0x%3")
+ .arg(bundlePath, deviceId)
+ .arg(QString::number(error, 16)));
+ }
+ success = false;
} else {
- addError(QString::fromLatin1("InstallAppSession(%1,%2) failed, "
- "AMDeviceInstallApplication returned 0x%3")
- .arg(bundlePath, deviceId).arg(QString::number(error, 16)));
+ // App is installed.
+ success = true;
}
- success = false;
- } else {
- // App is installed.
- success = true;
+ disconnectDevice();
}
- disconnectDevice();
}
+ } else {
+ success = true;
}
- if (debugAll) {
- qDebug() << "AMDeviceSecureTransferApplication finished request with " << (success ? "Success" : "Failure");
- }
-
- CFRelease(options);
- CFRelease(bundleUrl);
+ qCDebug(loggingCategory) << "AMDeviceSecureTransferApplication finished request with"
+ << (success ? "Success" : "Failure");
progressBase += 100;
}
-
if (success) {
sleep(5); // after installation the device needs a bit of quiet....
}
- if (debugAll) {
- qDebug() << "AMDeviceSecureInstallApplication finished request with " << (success ? "Success" : "Failure");
- }
+ qCDebug(loggingCategory) << "AMDeviceSecureInstallApplication finished request with"
+ << (success ? "Success" : "Failure");
- IosDeviceManagerPrivate::instance()->didTransferApp(bundlePath, deviceId,
- (success ? IosDeviceManager::Success : IosDeviceManager::Failure));
+ IosDeviceManagerPrivate::instance()->didTransferApp(bundlePath,
+ deviceId,
+ (success ? IosDeviceManager::Success
+ : IosDeviceManager::Failure));
return success;
}
+bool AppOpSession::installAppNew()
+{
+ const CFUrl_t bundleUrl(QUrl::fromLocalFile(bundlePath).toCFURL());
+ MobileDeviceLib &mLib = MobileDeviceLib::instance();
+
+ CFBundle_t bundle(CFBundleCreate(kCFAllocatorDefault, bundleUrl.get()));
+
+ if (!bundle) {
+ addError(QString::fromLatin1("Failed to create bundle"));
+ return false;
+ }
+
+ const CFString_t bundleId(CFBundleGetIdentifier(bundle.get()));
+ if (!bundleId) {
+ addError(QString::fromLatin1("Failed to retrieve bundle id"));
+ return false;
+ }
+
+ CFUrl_t dpath(QUrl::fromLocalFile(deltaPath).toCFURL());
+
+ CFStringRef keys[] = {
+ CFSTR("CFBundleIdentifier"),
+ CFSTR("CloseOnInvalidate"),
+ CFSTR("InvalidateOnDetach"),
+ CFSTR("IsUserInitiated"),
+ CFSTR("PackageType"),
+ CFSTR("PreferWifi"),
+ CFSTR("ShadowParentKey"),
+ };
+ CFStringRef values[] = {bundleId.get(),
+ CFSTR("1"),
+ CFSTR("1"),
+ CFSTR("1"),
+ CFSTR("Developer"),
+ CFSTR("1"),
+ (CFStringRef)dpath.get()};
+
+ const CFDictionary_t options(CFDictionaryCreate(0,
+ reinterpret_cast<const void **>(&keys[0]),
+ reinterpret_cast<const void **>(&values[0]),
+ 7,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ if (int error = mLib.deviceSecureInstallApplicationBundle(0,
+ device,
+ bundleUrl.get(),
+ options.get(),
+ &appSecureTransferSessionCallback))
+ return false;
+
+ return true;
+}
+
void AppOpSession::deviceCallbackReturned()
{
switch (appOp) {
@@ -1573,9 +1669,14 @@ bool IosDeviceManager::watchDevices() {
return d->watchDevices();
}
-void IosDeviceManager::requestAppOp(const QString &bundlePath, const QStringList &extraArgs,
- AppOp appOp, const QString &deviceId, int timeout) {
- d->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout);
+void IosDeviceManager::requestAppOp(const QString &bundlePath,
+ const QStringList &extraArgs,
+ AppOp appOp,
+ const QString &deviceId,
+ int timeout,
+ QString deltaPath)
+{
+ d->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout, deltaPath);
}
void IosDeviceManager::requestDeviceInfo(const QString &deviceId, int timeout)
diff --git a/src/tools/iostool/iosdevicemanager.h b/src/tools/iostool/iosdevicemanager.h
index 7c521c789fd..2fb3bb1c3a3 100644
--- a/src/tools/iostool/iosdevicemanager.h
+++ b/src/tools/iostool/iosdevicemanager.h
@@ -62,7 +62,7 @@ public:
static IosDeviceManager *instance();
bool watchDevices();
void requestAppOp(const QString &bundlePath, const QStringList &extraArgs, AppOp appOp,
- const QString &deviceId, int timeout = 1000);
+ const QString &deviceId, int timeout = 1000, QString deltaPath = QString());
void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
int processGdbServer(ServiceConnRef conn);
void stopGdbServer(ServiceConnRef conn, int phase);
diff --git a/src/tools/iostool/iostool.cpp b/src/tools/iostool/iostool.cpp
index e65cae852a4..2def3afa74a 100644
--- a/src/tools/iostool/iostool.cpp
+++ b/src/tools/iostool/iostool.cpp
@@ -82,6 +82,12 @@ void IosTool::run(const QStringList &args)
printHelp = true;
}
bundlePath = args.value(iarg);
+ } else if (arg == QLatin1String("--delta-path")) {
+ if (++iarg == args.size()) {
+ writeMsg(QStringLiteral("missing path after ") + arg);
+ printHelp = true;
+ }
+ m_deltasPath = args.value(iarg);
} else if (arg == QLatin1String("--install")) {
appOp = IosDeviceManager::AppOp(appOp | IosDeviceManager::Install);
} else if (arg == QLatin1String("--run")) {
@@ -163,7 +169,7 @@ void IosTool::run(const QStringList &args)
break;
}
maxProgress = 200;
- manager->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout);
+ manager->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout, m_deltasPath);
}
if (opLeft == 0)
doExit(0);
diff --git a/src/tools/iostool/iostool.h b/src/tools/iostool/iostool.h
index 6aa85216ca0..c71a30e6d8c 100644
--- a/src/tools/iostool/iostool.h
+++ b/src/tools/iostool/iostool.h
@@ -79,6 +79,7 @@ private:
Ios::IosDeviceManager::AppOp appOp;
QFile outFile;
QString m_qmlPort;
+ QString m_deltasPath;
QXmlStreamWriter out;
GdbRelayServer *gdbServer;
QmlRelayServer *qmlServer;
diff --git a/src/tools/iostool/iostool.qbs b/src/tools/iostool/iostool.qbs
index a39ace4dba1..d45172e23f2 100644
--- a/src/tools/iostool/iostool.qbs
+++ b/src/tools/iostool/iostool.qbs
@@ -11,6 +11,7 @@ QtcTool {
Depends { name: "app_version_header" }
files: [
+ "cfutils.h",
"Info.plist",
"gdbrunner.cpp",
"gdbrunner.h",
diff --git a/src/tools/iostool/mobiledevicelib.cpp b/src/tools/iostool/mobiledevicelib.cpp
index 79c4054a0d4..ae1c70f4a86 100644
--- a/src/tools/iostool/mobiledevicelib.cpp
+++ b/src/tools/iostool/mobiledevicelib.cpp
@@ -44,7 +44,8 @@ MobileDeviceLib::MobileDeviceLib()
if (!load())
addError(QLatin1String("Error loading MobileDevice.framework"));
if (!errors().isEmpty()) {
- foreach (const QString &msg, errors())
+ const QStringList errs = errors();
+ for (const QString &msg : errs)
addError(msg);
}
setLogLevel(5);
@@ -88,7 +89,15 @@ bool MobileDeviceLib::load()
m_AMDSetLogLevel = reinterpret_cast<AMDSetLogLevelPtr>(lib.resolve("AMDSetLogLevel"));
if (m_AMDSetLogLevel == 0)
addError("MobileDeviceLib does not define AMDSetLogLevel");
- m_AMDeviceNotificationSubscribe = reinterpret_cast<AMDeviceNotificationSubscribePtr>(lib.resolve("AMDeviceNotificationSubscribe"));
+
+ m_AMDeviceSecureInstallApplicationBundle
+ = reinterpret_cast<AMDeviceSecureInstallApplicationBundlePtr>(
+ lib.resolve("AMDeviceSecureInstallApplicationBundle"));
+ if (m_AMDeviceSecureInstallApplicationBundle == 0)
+ addError("MobileDeviceLib does not define m_AMDeviceSecureInstallApplicationBundle");
+
+ m_AMDeviceNotificationSubscribe = reinterpret_cast<AMDeviceNotificationSubscribePtr>(
+ lib.resolve("AMDeviceNotificationSubscribe"));
if (m_AMDeviceNotificationSubscribe == 0)
addError("MobileDeviceLib does not define AMDeviceNotificationSubscribe");
m_AMDeviceNotificationUnsubscribe = reinterpret_cast<AMDeviceNotificationUnsubscribePtr>(lib.resolve("AMDeviceNotificationUnsubscribe"));
@@ -357,6 +366,21 @@ int MobileDeviceLib::deviceSecureTransferApplicationPath(int zero, AMDeviceRef d
return returnCode;
}
+int MobileDeviceLib::deviceSecureInstallApplicationBundle(
+ int zero,
+ AMDeviceRef device,
+ CFURLRef url,
+ CFDictionaryRef options,
+ AMDeviceSecureInstallApplicationCallback callback)
+{
+ int returnCode = -1;
+
+ if (m_AMDeviceSecureInstallApplicationBundle) {
+ returnCode = m_AMDeviceSecureInstallApplicationBundle(device, url, options, callback, zero);
+ }
+ return returnCode;
+}
+
int MobileDeviceLib::deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg)
{
int returnCode = -1;
diff --git a/src/tools/iostool/mobiledevicelib.h b/src/tools/iostool/mobiledevicelib.h
index 97735fdcb1a..68bca9d316d 100644
--- a/src/tools/iostool/mobiledevicelib.h
+++ b/src/tools/iostool/mobiledevicelib.h
@@ -101,6 +101,7 @@ typedef am_res_t (MDEV_API *USBMuxConnectByPortPtr)(unsigned int, int, ServiceSo
// secure Api's
typedef am_res_t (MDEV_API *AMDeviceSecureStartServicePtr)(AMDeviceRef, CFStringRef, unsigned int *, ServiceConnRef *);
typedef int (MDEV_API *AMDeviceSecureTransferPathPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int);
+typedef int (MDEV_API *AMDeviceSecureInstallApplicationBundlePtr)(AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int zero);
typedef int (MDEV_API *AMDeviceSecureInstallApplicationPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int);
typedef int (MDEV_API *AMDServiceConnectionGetSocketPtr)(ServiceConnRef);
@@ -158,6 +159,13 @@ public:
int deviceSecureTransferApplicationPath(int, AMDeviceRef, CFURLRef,
CFDictionaryRef,
AMDeviceSecureInstallApplicationCallback callback, int);
+
+ int deviceSecureInstallApplicationBundle(int zero,
+ AMDeviceRef device,
+ CFURLRef url,
+ CFDictionaryRef options,
+ AMDeviceSecureInstallApplicationCallback callback);
+
int deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url,
CFDictionaryRef options,
AMDeviceSecureInstallApplicationCallback callback, int arg);
@@ -191,6 +199,7 @@ private:
AMDeviceMountImagePtr m_AMDeviceMountImage;
AMDeviceSecureStartServicePtr m_AMDeviceSecureStartService;
AMDeviceSecureTransferPathPtr m_AMDeviceSecureTransferPath;
+ AMDeviceSecureInstallApplicationBundlePtr m_AMDeviceSecureInstallApplicationBundle;
AMDeviceSecureInstallApplicationPtr m_AMDeviceSecureInstallApplication;
AMDServiceConnectionGetSocketPtr m_AMDServiceConnectionGetSocket;
AMDServiceConnectionSendPtr m_AMDServiceConnectionSend;
diff --git a/src/tools/iostool/relayserver.cpp b/src/tools/iostool/relayserver.cpp
index 03181a10ac4..312b3bd66d4 100644
--- a/src/tools/iostool/relayserver.cpp
+++ b/src/tools/iostool/relayserver.cpp
@@ -284,8 +284,7 @@ bool RelayServer::startServer()
void RelayServer::stopServer()
{
- foreach (Relayer *connection, m_connections)
- delete connection;
+ qDeleteAll(m_connections);
if (m_ipv4Server.isListening())
m_ipv4Server.close();
if (m_ipv6Server.isListening())
diff --git a/src/tools/processlauncher/CMakeLists.txt b/src/tools/processlauncher/CMakeLists.txt
index e0064c62b34..3777b7d2dda 100644
--- a/src/tools/processlauncher/CMakeLists.txt
+++ b/src/tools/processlauncher/CMakeLists.txt
@@ -3,7 +3,7 @@ set(UTILSDIR "${PROJECT_SOURCE_DIR}/src/libs/utils")
add_qtc_executable(qtcreator_processlauncher
INCLUDES "${UTILSDIR}"
DEPENDS Qt5::Core Qt5::Network
- DEFINES QTCREATOR_UTILS_STATIC_LIB
+ DEFINES UTILS_STATIC_LIBRARY
SOURCES
launcherlogging.cpp
launcherlogging.h
@@ -12,6 +12,7 @@ add_qtc_executable(qtcreator_processlauncher
processlauncher-main.cpp
${UTILSDIR}/launcherpackets.cpp
${UTILSDIR}/launcherpackets.h
+ ${UTILSDIR}/processenums.h
${UTILSDIR}/processreaper.cpp
${UTILSDIR}/processreaper.h
${UTILSDIR}/processutils.cpp
diff --git a/src/tools/processlauncher/launchersockethandler.cpp b/src/tools/processlauncher/launchersockethandler.cpp
index 52db9b4523f..03ddb6528ff 100644
--- a/src/tools/processlauncher/launchersockethandler.cpp
+++ b/src/tools/processlauncher/launchersockethandler.cpp
@@ -44,9 +44,12 @@ public:
ProcessHelper(parent), m_token(token) { }
quintptr token() const { return m_token; }
+ void setReaperTimeout(int msecs) { m_reaperTimeout = msecs; };
+ int reaperTimeout() const { return m_reaperTimeout; }
private:
const quintptr m_token;
+ int m_reaperTimeout = 500;
};
LauncherSocketHandler::LauncherSocketHandler(QString serverPath, QObject *parent)
@@ -59,13 +62,20 @@ LauncherSocketHandler::LauncherSocketHandler(QString serverPath, QObject *parent
LauncherSocketHandler::~LauncherSocketHandler()
{
+ for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) {
+ Process *p = it.value();
+ if (p->state() != QProcess::NotRunning)
+ logWarn(QStringLiteral("Shutting down while process %1 is running").arg(p->program()));
+ ProcessReaper::reap(p);
+ }
+
m_socket->disconnect();
- if (m_socket->state() != QLocalSocket::UnconnectedState) {
- logWarn("socket handler destroyed while connection was active");
+ m_socket->disconnectFromServer();
+ if (m_socket->state() != QLocalSocket::UnconnectedState
+ && !m_socket->waitForDisconnected()) {
+ logWarn("Could not disconnect from server");
m_socket->close();
}
- for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it)
- ProcessReaper::reap(it.value());
}
void LauncherSocketHandler::start()
@@ -74,11 +84,7 @@ void LauncherSocketHandler::start()
this, &LauncherSocketHandler::handleSocketClosed);
connect(m_socket, &QLocalSocket::readyRead, this, &LauncherSocketHandler::handleSocketData);
connect(m_socket,
-#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
- static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error),
-#else
&QLocalSocket::errorOccurred,
-#endif
this, &LauncherSocketHandler::handleSocketError);
m_socket->connectToServer(m_serverPath);
}
@@ -89,7 +95,7 @@ void LauncherSocketHandler::handleSocketData()
if (!m_packetParser.parse())
return;
} catch (const PacketParser::InvalidPacketSizeException &e) {
- logWarn(QStringLiteral("Internal protocol error: invalid packet size %1.")
+ logWarn(QStringLiteral("Internal protocol error: Invalid packet size %1")
.arg(e.size));
return;
}
@@ -107,7 +113,7 @@ void LauncherSocketHandler::handleSocketData()
handleShutdownPacket();
return;
default:
- logWarn(QStringLiteral("Internal protocol error: invalid packet type %1.")
+ logWarn(QStringLiteral("Internal protocol error: Invalid packet type %1")
.arg(static_cast<int>(m_packetParser.type())));
return;
}
@@ -117,7 +123,7 @@ void LauncherSocketHandler::handleSocketData()
void LauncherSocketHandler::handleSocketError()
{
if (m_socket->error() != QLocalSocket::PeerClosedError) {
- logError(QStringLiteral("socket error: %1").arg(m_socket->errorString()));
+ logError(QStringLiteral("Socket error: %1").arg(m_socket->errorString()));
m_socket->disconnect();
qApp->quit();
}
@@ -125,68 +131,55 @@ void LauncherSocketHandler::handleSocketError()
void LauncherSocketHandler::handleSocketClosed()
{
- for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) {
- if (it.value()->state() != QProcess::NotRunning) {
- logWarn("client closed connection while process still running");
- break;
- }
- }
+ logWarn("The connection has closed unexpectedly, shutting down");
m_socket->disconnect();
qApp->quit();
}
-void LauncherSocketHandler::handleProcessError()
+void LauncherSocketHandler::handleProcessError(Process *process)
{
- Process * proc = senderProcess();
- ProcessErrorPacket packet(proc->token());
- packet.error = proc->error();
- packet.errorString = proc->errorString();
- sendPacket(packet);
-
- // In case of FailedToStart we won't receive finished signal, so we remove the process here.
- // For all other errors we should expect corresponding finished signal to appear.
- if (proc->error() == QProcess::FailedToStart)
- removeProcess(proc->token());
+ // In case of FailedToStart we won't receive finished signal, so we send the error
+ // packet and remove the process here and now. For all other errors we should expect
+ // corresponding finished signal to appear, so we will send the error data together with
+ // the finished packet later on.
+ if (process->error() == QProcess::FailedToStart)
+ handleProcessFinished(process);
}
-void LauncherSocketHandler::handleProcessStarted()
+void LauncherSocketHandler::handleProcessStarted(Process *process)
{
- Process *proc = senderProcess();
- ProcessStartedPacket packet(proc->token());
- packet.processId = proc->processId();
- proc->processStartHandler()->handleProcessStarted();
+ ProcessStartedPacket packet(process->token());
+ packet.processId = process->processId();
+ process->processStartHandler()->handleProcessStarted();
sendPacket(packet);
}
-void LauncherSocketHandler::handleReadyReadStandardOutput()
+void LauncherSocketHandler::handleReadyReadStandardOutput(Process *process)
{
- Process * proc = senderProcess();
- ReadyReadStandardOutputPacket packet(proc->token());
- packet.standardChannel = proc->readAllStandardOutput();
+ ReadyReadStandardOutputPacket packet(process->token());
+ packet.standardChannel = process->readAllStandardOutput();
sendPacket(packet);
}
-void LauncherSocketHandler::handleReadyReadStandardError()
+void LauncherSocketHandler::handleReadyReadStandardError(Process *process)
{
- Process * proc = senderProcess();
- ReadyReadStandardErrorPacket packet(proc->token());
- packet.standardChannel = proc->readAllStandardError();
+ ReadyReadStandardErrorPacket packet(process->token());
+ packet.standardChannel = process->readAllStandardError();
sendPacket(packet);
}
-void LauncherSocketHandler::handleProcessFinished()
+void LauncherSocketHandler::handleProcessFinished(Process *process)
{
- Process * proc = senderProcess();
- ProcessFinishedPacket packet(proc->token());
- packet.error = proc->error();
- packet.errorString = proc->errorString();
- packet.exitCode = proc->exitCode();
- packet.exitStatus = proc->exitStatus();
- if (proc->processChannelMode() != QProcess::MergedChannels)
- packet.stdErr = proc->readAllStandardError();
- packet.stdOut = proc->readAllStandardOutput();
+ ProcessDonePacket packet(process->token());
+ packet.exitCode = process->exitCode();
+ packet.exitStatus = process->exitStatus();
+ packet.error = process->error();
+ packet.errorString = process->errorString();
+ if (process->processChannelMode() != QProcess::MergedChannels)
+ packet.stdErr = process->readAllStandardError();
+ packet.stdOut = process->readAllStandardOutput();
sendPacket(packet);
- removeProcess(proc->token());
+ removeProcess(process->token());
}
void LauncherSocketHandler::handleStartPacket()
@@ -195,7 +188,7 @@ void LauncherSocketHandler::handleStartPacket()
if (!process)
process = setupProcess(m_packetParser.token());
if (process->state() != QProcess::NotRunning) {
- logWarn("got start request while process was running");
+ logWarn("Got start request while process was running");
return;
}
const auto packet = LauncherPacket::extractPacket<StartProcessPacket>(
@@ -204,8 +197,8 @@ void LauncherSocketHandler::handleStartPacket()
process->setEnvironment(packet.env);
process->setWorkingDirectory(packet.workingDir);
// Forwarding is handled by the LauncherInterface
- process->setProcessChannelMode(packet.channelMode == QProcess::MergedChannels ?
- QProcess::MergedChannels : QProcess::SeparateChannels);
+ process->setProcessChannelMode(packet.processChannelMode == QProcess::MergedChannels
+ ? QProcess::MergedChannels : QProcess::SeparateChannels);
process->setStandardInputFile(packet.standardInputFile);
ProcessStartHandler *handler = process->processStartHandler();
handler->setProcessMode(packet.processMode);
@@ -217,6 +210,8 @@ void LauncherSocketHandler::handleStartPacket()
process->setLowPriority();
if (packet.unixTerminalDisabled)
process->setUnixTerminalDisabled();
+ process->setUseCtrlCStub(packet.useCtrlCStub);
+ process->setReaperTimeout(packet.reaperTimeout);
process->start(packet.command, packet.arguments, handler->openMode());
handler->handleProcessStart();
}
@@ -225,11 +220,11 @@ void LauncherSocketHandler::handleWritePacket()
{
Process * const process = m_processes.value(m_packetParser.token());
if (!process) {
- logWarn("got write request for unknown process");
+ logWarn("Got write request for unknown process");
return;
}
if (process->state() != QProcess::Running) {
- logDebug("can't write into not running process");
+ logDebug("Can't write into not running process");
return;
}
const auto packet = LauncherPacket::extractPacket<WritePacket>(
@@ -244,38 +239,29 @@ void LauncherSocketHandler::handleStopPacket()
if (!process) {
// This can happen when the process finishes on its own at about the same time the client
// sends the request. In this case the process was already deleted.
- logDebug("got stop request for unknown process");
+ logDebug("Got stop request for unknown process");
return;
}
- if (process->state() == QProcess::NotRunning) {
- // This shouldn't happen, since as soon as process finishes or error occurrs
- // the process is being removed.
- logWarn("got stop request when process was not running");
- } else {
- // We got the client request to stop the starting / running process.
- // We report process exit to the client.
- ProcessFinishedPacket packet(process->token());
- packet.error = QProcess::Crashed;
- packet.exitCode = -1;
- packet.exitStatus = QProcess::CrashExit;
- if (process->processChannelMode() != QProcess::MergedChannels)
- packet.stdErr = process->readAllStandardError();
- packet.stdOut = process->readAllStandardOutput();
- sendPacket(packet);
+ const auto packet = LauncherPacket::extractPacket<StopProcessPacket>(
+ m_packetParser.token(),
+ m_packetParser.packetData());
+
+ switch (packet.signalType) {
+ case StopProcessPacket::SignalType::Terminate:
+ process->terminate();
+ break;
+ case StopProcessPacket::SignalType::Kill:
+ process->kill();
+ break;
+ case StopProcessPacket::SignalType::Close:
+ removeProcess(process->token());
+ break;
}
- removeProcess(process->token());
}
void LauncherSocketHandler::handleShutdownPacket()
{
- logDebug("got shutdown request, closing down");
- for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) {
- it.value()->disconnect();
- if (it.value()->state() != QProcess::NotRunning) {
- logWarn("got shutdown request while process was running");
- it.value()->terminate();
- }
- }
+ logDebug("Got shutdown request, closing down");
m_socket->disconnect();
qApp->quit();
}
@@ -288,31 +274,26 @@ void LauncherSocketHandler::sendPacket(const LauncherPacket &packet)
Process *LauncherSocketHandler::setupProcess(quintptr token)
{
const auto p = new Process(token, this);
- connect(p, &QProcess::errorOccurred, this, &LauncherSocketHandler::handleProcessError);
- connect(p, &QProcess::started, this, &LauncherSocketHandler::handleProcessStarted);
+ connect(p, &QProcess::started, this, [this, p] { handleProcessStarted(p); });
+ connect(p, &QProcess::errorOccurred, this, [this, p] { handleProcessError(p); });
+ connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ this, [this, p] { handleProcessFinished(p); });
connect(p, &QProcess::readyReadStandardOutput,
- this, &LauncherSocketHandler::handleReadyReadStandardOutput);
+ this, [this, p] { handleReadyReadStandardOutput(p); });
connect(p, &QProcess::readyReadStandardError,
- this, &LauncherSocketHandler::handleReadyReadStandardError);
- connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
- this, &LauncherSocketHandler::handleProcessFinished);
+ this, [this, p] { handleReadyReadStandardError(p); });
return p;
}
void LauncherSocketHandler::removeProcess(quintptr token)
{
- const auto it = m_processes.find(token);
- if (it == m_processes.end())
+ const auto it = m_processes.constFind(token);
+ if (it == m_processes.constEnd())
return;
Process *process = it.value();
m_processes.erase(it);
- ProcessReaper::reap(process);
-}
-
-Process *LauncherSocketHandler::senderProcess() const
-{
- return static_cast<Process *>(sender());
+ ProcessReaper::reap(process, process->reaperTimeout());
}
} // namespace Internal
diff --git a/src/tools/processlauncher/launchersockethandler.h b/src/tools/processlauncher/launchersockethandler.h
index 56762bec9fd..baceeb169fc 100644
--- a/src/tools/processlauncher/launchersockethandler.h
+++ b/src/tools/processlauncher/launchersockethandler.h
@@ -52,11 +52,12 @@ private:
void handleSocketData();
void handleSocketError();
void handleSocketClosed();
- void handleProcessError();
- void handleProcessStarted();
- void handleReadyReadStandardOutput();
- void handleReadyReadStandardError();
- void handleProcessFinished();
+
+ void handleProcessStarted(Process *process);
+ void handleProcessError(Process *process);
+ void handleProcessFinished(Process *process);
+ void handleReadyReadStandardOutput(Process *process);
+ void handleReadyReadStandardError(Process *process);
void handleStartPacket();
void handleWritePacket();
@@ -67,7 +68,6 @@ private:
Process *setupProcess(quintptr token);
void removeProcess(quintptr token);
- Process *senderProcess() const;
const QString m_serverPath;
QLocalSocket * const m_socket;
diff --git a/src/tools/processlauncher/processlauncher.qbs b/src/tools/processlauncher/processlauncher.qbs
index bdcde4ac34d..d52add65583 100644
--- a/src/tools/processlauncher/processlauncher.qbs
+++ b/src/tools/processlauncher/processlauncher.qbs
@@ -6,7 +6,7 @@ QtcTool {
Depends { name: "Qt.network" }
- cpp.defines: base.concat("QTCREATOR_UTILS_STATIC_LIB")
+ cpp.defines: base.concat("UTILS_STATIC_LIBRARY")
cpp.includePaths: base.concat(pathToUtils)
Properties {
@@ -29,6 +29,7 @@ QtcTool {
files: [
"launcherpackets.cpp",
"launcherpackets.h",
+ "processenums.h",
"processreaper.cpp",
"processreaper.h",
"processutils.cpp",
diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt
index 15c5231d05d..ef8eb1eb512 100644
--- a/src/tools/qml2puppet/CMakeLists.txt
+++ b/src/tools/qml2puppet/CMakeLists.txt
@@ -277,6 +277,10 @@ extend_qtc_executable(qml2puppet
DEPENDS Nanotrace
)
+if (QTC_STATIC_BUILD AND Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0)
+ qt6_import_qml_plugins(qml2puppet PATH_TO_SCAN ${SRCDIR})
+endif()
+
# Crashpad
# only windows requires separate crashpad client per process until client->SetHandlerIPCPipe()
# is implemented (check the TODO inside startCrashpad())
diff --git a/src/tools/qtcreatorcrashhandler/CMakeLists.txt b/src/tools/qtcreatorcrashhandler/CMakeLists.txt
index 74dfd2199f4..fc2a477d06f 100644
--- a/src/tools/qtcreatorcrashhandler/CMakeLists.txt
+++ b/src/tools/qtcreatorcrashhandler/CMakeLists.txt
@@ -1,11 +1,10 @@
-if (LINUX) # Debug build only!
- add_qtc_executable(qtcreatorcrashhandler
- DEPENDS Utils Qt5::Widgets
- SOURCES
- backtracecollector.cpp backtracecollector.h
- crashhandler.cpp crashhandler.h
- crashhandlerdialog.cpp crashhandlerdialog.h crashhandlerdialog.ui
- main.cpp
- utils.cpp utils.h
- )
-endif()
+add_qtc_executable(qtcreator_crash_handler
+ CONDITION UNIX AND NOT APPLE AND (CMAKE_BUILD_TYPE STREQUAL "Debug")
+ DEPENDS app_version Utils Qt5::Widgets
+ SOURCES
+ backtracecollector.cpp backtracecollector.h
+ crashhandler.cpp crashhandler.h
+ crashhandlerdialog.cpp crashhandlerdialog.h crashhandlerdialog.ui
+ main.cpp
+ utils.cpp utils.h
+)
diff --git a/src/tools/qtcreatorcrashhandler/crashhandler.cpp b/src/tools/qtcreatorcrashhandler/crashhandler.cpp
index 621361499eb..fa0f4009266 100644
--- a/src/tools/qtcreatorcrashhandler/crashhandler.cpp
+++ b/src/tools/qtcreatorcrashhandler/crashhandler.cpp
@@ -70,7 +70,7 @@ class CExecList : public QVector<char *>
public:
CExecList(const QStringList &list)
{
- foreach (const QString &item, list)
+ for (const QString &item : list)
append(qstrdup(item.toLatin1().data()));
append(0);
}
@@ -195,7 +195,7 @@ bool CrashHandler::collectRestartAppData()
return false;
}
commandLine.removeLast();
- foreach (const QByteArray &item, commandLine)
+ for (const QByteArray &item : qAsConst(commandLine))
d->restartAppCommandLine.append(QString::fromLatin1(item));
// Get environment.
@@ -209,7 +209,7 @@ bool CrashHandler::collectRestartAppData()
}
if (environment.last().isEmpty())
environment.removeLast();
- foreach (const QByteArray &item, environment)
+ for (const QByteArray &item : qAsConst(environment))
d->restartAppEnvironment.append(QString::fromLatin1(item));
return true;
diff --git a/src/tools/qtpromaker/main.cpp b/src/tools/qtpromaker/main.cpp
index 60aba5476e9..4fddd6bdd48 100644
--- a/src/tools/qtpromaker/main.cpp
+++ b/src/tools/qtpromaker/main.cpp
@@ -159,7 +159,7 @@ private:
void Project::setPaths(const QStringList &paths)
{
- foreach (const QString &path, paths)
+ for (const QString &path : paths)
m_items.append(path);
}
@@ -220,7 +220,8 @@ void Project::handleBinary(const QString &item)
// "}] (gdb)
int first = input.indexOf(QLatin1Char('{'));
input = input.mid(first, input.lastIndexOf(QLatin1Char('}')) - first);
- foreach (QString item, input.split(QLatin1String("},{"))) {
+ const QStringList items = input.split(QLatin1String("},{"));
+ for (QString item : items) {
//qDebug() << "ITEM: " << item;
int full = item.indexOf(QLatin1String(",fullname=\""));
if (full != -1)
@@ -299,17 +300,17 @@ void Project::writeProFile()
if (m_subdirs.isEmpty()) {
ts << "TEMPLATE = app\n";
ts << "TARGET = " << QFileInfo(m_outputFileName).baseName() << "\n";
- foreach (const FileClass &fc, m_fileClasses)
+ for (const FileClass &fc : qAsConst(m_fileClasses))
fc.writeProBlock(ts);
ts << "\nPATHS *=";
- foreach (const QDir &dir, m_items)
+ for (const QDir dir : qAsConst(m_items))
ts << " \\\n " << dir.path();
ts << "\n\nDEPENDPATH *= $$PATHS\n";
ts << "\nINCLUDEPATH *= $$PATHS\n";
} else {
ts << "TEMPLATE = subdirs\n";
ts << "SUBDIRS = ";
- foreach (const QString &subdir, m_subdirs)
+ for (const QString &subdir : qAsConst(m_subdirs))
ts << " \\\n " << subdir;
ts << "\n";
}
diff --git a/src/tools/screenshotcropper/CMakeLists.txt b/src/tools/screenshotcropper/CMakeLists.txt
deleted file mode 100644
index 1eb807dc909..00000000000
--- a/src/tools/screenshotcropper/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-add_qtc_executable(screenshotcropper
- SKIP_INSTALL
- DEPENDS Qt5::Widgets Utils Core QtSupport
- SOURCES
- main.cpp
- cropimageview.cpp
- cropimageview.h
- screenshotcropperwindow.h screenshotcropperwindow.cpp screenshotcropperwindow.ui
-)
diff --git a/src/tools/screenshotcropper/cropimageview.cpp b/src/tools/screenshotcropper/cropimageview.cpp
deleted file mode 100644
index 6dadb04c014..00000000000
--- a/src/tools/screenshotcropper/cropimageview.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cropimageview.h"
-
-#include <QPainter>
-#include <QMouseEvent>
-
-CropImageView::CropImageView(QWidget *parent)
- : QWidget(parent)
-{
-}
-
-void CropImageView::mousePressEvent(QMouseEvent *event)
-{
- m_initialPoint = event->pos();
- setEndPoint(m_initialPoint);
-}
-
-void CropImageView::mouseMoveEvent(QMouseEvent *event)
-{
- setEndPoint(event->pos());
-}
-
-void CropImageView::mouseReleaseEvent(QMouseEvent *event)
-{
- setEndPoint(event->pos());
-}
-
-void CropImageView::setImage(const QImage &image)
-{
- m_image = image;
- setMinimumSize(image.size());
- update();
-}
-
-void CropImageView::setArea(const QRect &area)
-{
- m_area = m_image.rect().intersected(area);
- emit cropAreaChanged(m_area);
- update();
-}
-
-void CropImageView::setEndPoint(const QPoint &point)
-{
- setArea(QRect(m_initialPoint, point));
-}
-
-void CropImageView::paintEvent(QPaintEvent *event)
-{
- Q_UNUSED(event)
- QPainter p(this);
-
- if (!m_image.isNull())
- p.drawImage(0, 0, m_image);
-
- if (!m_area.isNull()) {
- p.setPen(Qt::white);
- p.drawRect(m_area);
- QPen redDashes;
- redDashes.setColor(Qt::red);
- redDashes.setStyle(Qt::DashLine);
- p.setPen(redDashes);
- p.drawRect(m_area);
- }
-}
-
diff --git a/src/tools/screenshotcropper/cropimageview.h b/src/tools/screenshotcropper/cropimageview.h
deleted file mode 100644
index cefccd92abd..00000000000
--- a/src/tools/screenshotcropper/cropimageview.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QWidget>
-
-class CropImageView : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit CropImageView(QWidget *parent = 0);
-
- void paintEvent(QPaintEvent *event);
- void mousePressEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
-
- void setImage(const QImage &image);
- void setArea(const QRect &area);
- void setEndPoint(const QPoint &point);
-
-signals:
- void cropAreaChanged(const QRect &area);
-
-private:
- QImage m_image;
- QRect m_area;
- QPoint m_initialPoint;
-};
diff --git a/src/tools/screenshotcropper/main.cpp b/src/tools/screenshotcropper/main.cpp
deleted file mode 100644
index b287aa035d7..00000000000
--- a/src/tools/screenshotcropper/main.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include <QApplication>
-#include <QFileDialog>
-#include <QSettings>
-
-#include "screenshotcropperwindow.h"
-
-const QString settingsKeyAreasXmlFile = QLatin1String("areasXmlFile");
-const QString settingsKeyImagesFolder = QLatin1String("imagesFolder");
-
-static void promptPaths(QString &areasXmlFile, QString &imagesFolder)
-{
- QSettings settings(QLatin1String("QtProject"), QLatin1String("Qt Creator Screenshot Cropper"));
-
- areasXmlFile = settings.value(settingsKeyAreasXmlFile).toString();
- areasXmlFile = QFileDialog::getOpenFileName(0, QLatin1String("Select the 'images_areaofinterest.xml' file in Qt Creator's sources"), areasXmlFile);
- settings.setValue(settingsKeyAreasXmlFile, areasXmlFile);
-
- imagesFolder = settings.value(settingsKeyImagesFolder).toString();
- imagesFolder = QFileDialog::getExistingDirectory(0, QLatin1String("Select the 'doc/src/images' folder in Qt's sources"), imagesFolder);
- settings.setValue(settingsKeyImagesFolder, imagesFolder);
-}
-
-int main(int argc, char *argv[])
-{
- QApplication a(argc, argv);
-
- QString areasXmlFile;
- QString imagesFolder;
- promptPaths(areasXmlFile, imagesFolder);
-
- ScreenShotCropperWindow w;
- w.show();
- w.loadData(areasXmlFile, imagesFolder);
- w.selectImage(0);
-
- return a.exec();
-}
diff --git a/src/tools/screenshotcropper/screenshotcropperwindow.cpp b/src/tools/screenshotcropper/screenshotcropperwindow.cpp
deleted file mode 100644
index f4f825edd96..00000000000
--- a/src/tools/screenshotcropper/screenshotcropperwindow.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "screenshotcropperwindow.h"
-#include "ui_screenshotcropperwindow.h"
-
-#include <coreplugin/welcomepagehelper.h>
-#include <qtsupport/screenshotcropper.h>
-
-#include <QListWidget>
-#include <QDebug>
-
-ScreenShotCropperWindow::ScreenShotCropperWindow(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::ScreenShotCropperWindow)
-{
- ui->setupUi(this);
- connect(ui->m_filenamesList, &QListWidget::currentRowChanged, this, &ScreenShotCropperWindow::selectImage);
- connect(ui->m_cropImageView, &CropImageView::cropAreaChanged, this, &ScreenShotCropperWindow::setArea);
- connect(ui->m_buttonBox, &QDialogButtonBox::accepted, this, &ScreenShotCropperWindow::saveData);
- connect(ui->m_buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close);
-}
-
-ScreenShotCropperWindow::~ScreenShotCropperWindow()
-{
- delete ui;
-}
-
-void ScreenShotCropperWindow::loadData(const QString &areasXmlFile, const QString &imagesFolder)
-{
- typedef QMap<QString, QRect>::ConstIterator StringRectConstIt;
-
- m_areasOfInterestFile = areasXmlFile;
- m_areasOfInterest = QtSupport::ScreenshotCropper::loadAreasOfInterest(m_areasOfInterestFile);
- m_imagesFolder = imagesFolder;
- const StringRectConstIt cend = m_areasOfInterest.constEnd();
- for (StringRectConstIt it = m_areasOfInterest.constBegin(); it != cend; ++it)
- ui->m_filenamesList->addItem(it.key());
-}
-
-void ScreenShotCropperWindow::selectImage(int index)
-{
- const QString fileName = ui->m_filenamesList->item(index)->text();
- ui->m_cropImageView->setImage(QImage(m_imagesFolder + QLatin1Char('/') + fileName));
- ui->m_cropImageView->setArea(m_areasOfInterest.value(fileName));
-}
-
-void ScreenShotCropperWindow::setArea(const QRect &area)
-{
- const QListWidgetItem *item = ui->m_filenamesList->currentItem();
- if (!item)
- return;
-
- if (!area.isValid()) {
- ui->m_previewLabel->setPixmap({});
- return;
- }
-
- const QString currentFile = item->text();
- m_areasOfInterest.insert(currentFile, area);
- const QImage img(m_imagesFolder + QLatin1Char('/') + currentFile);
- const QPixmap cropped = QPixmap::fromImage(
- QtSupport::ScreenshotCropper::croppedImage(img, currentFile,
- Core::ListModel::defaultImageSize,
- area));
- ui->m_previewLabel->setPixmap(cropped);
-}
-
-void ScreenShotCropperWindow::saveData()
-{
- if (!QtSupport::ScreenshotCropper::saveAreasOfInterest(m_areasOfInterestFile,
- m_areasOfInterest))
- qFatal("Cannot write %s", qPrintable(m_areasOfInterestFile));
-}
diff --git a/src/tools/screenshotcropper/screenshotcropperwindow.h b/src/tools/screenshotcropper/screenshotcropperwindow.h
deleted file mode 100644
index 1ba13b685ca..00000000000
--- a/src/tools/screenshotcropper/screenshotcropperwindow.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QMainWindow>
-#include <QMap>
-#include <QRect>
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class ScreenShotCropperWindow; }
-QT_END_NAMESPACE
-
-class ScreenShotCropperWindow : public QMainWindow
-{
- Q_OBJECT
-
-public:
- explicit ScreenShotCropperWindow(QWidget *parent = 0);
- ~ScreenShotCropperWindow();
-
- void loadData(const QString &areasXmlFile, const QString &imagesFolder);
-
- void selectImage(int index);
- void setArea(const QRect &area);
- void saveData();
-
-private:
- QMap<QString, QRect> m_areasOfInterest;
- QString m_areasOfInterestFile;
- QString m_imagesFolder;
- Ui::ScreenShotCropperWindow *ui;
-};
diff --git a/src/tools/screenshotcropper/screenshotcropperwindow.ui b/src/tools/screenshotcropper/screenshotcropperwindow.ui
deleted file mode 100644
index a298497a9be..00000000000
--- a/src/tools/screenshotcropper/screenshotcropperwindow.ui
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ScreenShotCropperWindow</class>
- <widget class="QMainWindow" name="ScreenShotCropperWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>680</width>
- <height>488</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>ScreenShotCropperWindow</string>
- </property>
- <widget class="QWidget" name="centralWidget">
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="0">
- <widget class="QDialogButtonBox" name="m_buttonBox">
- <property name="standardButtons">
- <set>QDialogButtonBox::Close|QDialogButtonBox::Save</set>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QSplitter" name="splitter">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <widget class="QListWidget" name="m_filenamesList">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- <widget class="QScrollArea" name="scrollArea">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="widgetResizable">
- <bool>true</bool>
- </property>
- <widget class="QWidget" name="scrollAreaWidgetContents">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>386</width>
- <height>438</height>
- </rect>
- </property>
- <layout class="QHBoxLayout">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="margin" stdset="0">
- <number>0</number>
- </property>
- <item>
- <widget class="CropImageView" name="m_cropImageView" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="m_previewLabel">
- <property name="frameShape">
- <enum>QFrame::Box</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <customwidgets>
- <customwidget>
- <class>CropImageView</class>
- <extends>QWidget</extends>
- <header>cropimageview.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/tools/sdktool/CMakeLists.txt b/src/tools/sdktool/CMakeLists.txt
index 0161cc2c2ed..e25a8c0b2c4 100644
--- a/src/tools/sdktool/CMakeLists.txt
+++ b/src/tools/sdktool/CMakeLists.txt
@@ -33,12 +33,12 @@ set(UtilsSourcesDir "../../libs/utils")
file(RELATIVE_PATH DATA_PATH "/${IDE_LIBEXEC_PATH}" "/${IDE_DATA_PATH}")
-add_qtc_executable(sdktool
- ${DESTINATION}
+add_qtc_library(sdktoolLib
+ STATIC
DEFINES DATA_PATH=\"${DATA_PATH}\"
- DEPENDS Qt5::Core
+ PUBLIC_DEPENDS Qt5::Core
+ PUBLIC_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} "${UtilsSourcesDir}/../"
INCLUDES
- "${UtilsSourcesDir}/../"
${CMAKE_CURRENT_BINARY_DIR}
SOURCES
addabiflavor.cpp addabiflavor.h
@@ -53,7 +53,6 @@ add_qtc_executable(sdktool
findkeyoperation.cpp findkeyoperation.h
findvalueoperation.cpp findvalueoperation.h
getoperation.cpp getoperation.h
- main.cpp
operation.cpp operation.h
rmcmakeoperation.cpp rmcmakeoperation.h
rmdebuggeroperation.cpp rmdebuggeroperation.h
@@ -65,17 +64,9 @@ add_qtc_executable(sdktool
settings.cpp settings.h
)
-if (MSVC AND TARGET sdktool)
- # find out if Qt is static and set /MT if so
- get_target_property(_input_type Qt5::Core TYPE)
- if (${_input_type} STREQUAL "STATIC_LIBRARY")
- set_property(TARGET sdktool PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
- endif()
-endif()
-
-extend_qtc_executable(sdktool
+extend_qtc_library(sdktoolLib
SOURCES_PREFIX "${UtilsSourcesDir}"
- DEFINES QTCREATOR_UTILS_STATIC_LIB
+ PUBLIC_DEFINES UTILS_STATIC_LIBRARY
SOURCES
commandline.cpp commandline.h
environment.cpp environment.h
@@ -92,18 +83,38 @@ extend_qtc_executable(sdktool
stringutils.cpp stringutils.h
)
-extend_qtc_executable(sdktool CONDITION APPLE
+extend_qtc_library(sdktoolLib CONDITION APPLE
SOURCES_PREFIX "${UtilsSourcesDir}"
SOURCES
fileutils_mac.mm fileutils_mac.h
- DEPENDS
+ PUBLIC_DEPENDS
${FWFoundation}
)
-extend_qtc_executable(sdktool CONDITION WIN32
- DEPENDS
+extend_qtc_library(sdktoolLib CONDITION WIN32
+ PUBLIC_DEPENDS
user32 iphlpapi ws2_32 shell32
DEFINES
_UNICODE UNICODE
_CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS
)
+
+add_qtc_executable(sdktool
+ ${DESTINATION}
+ DEFINES DATA_PATH=\"${DATA_PATH}\"
+ DEPENDS sdktoolLib
+ INCLUDES
+ ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES
+ main.cpp
+)
+
+if (MSVC AND TARGET sdktool AND Qt5_VERSION VERSION_LESS 6.0.0)
+ # find out if Qt is static and set /MT if so
+ get_target_property(_input_type Qt5::Core TYPE)
+ if (${_input_type} STREQUAL "STATIC_LIBRARY")
+ set_property(TARGET sdktool PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
+ set_property(TARGET sdktoolLib PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
+ endif()
+endif()
+
diff --git a/src/tools/sdktool/addabiflavor.cpp b/src/tools/sdktool/addabiflavor.cpp
index c7fde38a62a..6a7fedfa81f 100644
--- a/src/tools/sdktool/addabiflavor.cpp
+++ b/src/tools/sdktool/addabiflavor.cpp
@@ -33,11 +33,19 @@
#include "settings.h"
+#include <QLoggingCategory>
+
+#ifdef WITH_TESTS
+#include <QtTest>
+#endif
+
+Q_LOGGING_CATEGORY(addAbiFlavorLog, "qtc.sdktool.operations.addabiflavor", QtWarningMsg)
+
#include <iostream>
-static char VERSION[] = "Version";
-static char FLAVORS[] = "Flavors";
-static char ABI_FILE_ID[] = "abi";
+const char VERSION[] = "Version";
+const char FLAVORS[] = "Flavors";
+const char ABI_FILE_ID[] = "abi";
QString AddAbiFlavor::name() const
{
@@ -62,7 +70,7 @@ bool AddAbiFlavor::setArguments(const QStringList &args)
const QString next = ((i + 1) < args.count()) ? args.at(i + 1) : QString();
if (next.isNull() && current.startsWith("--")) {
- std::cerr << "No parameter for option '" << qPrintable(current) << "' given." << std::endl << std::endl;
+ qCCritical(addAbiFlavorLog) << "No parameter for option '" << qPrintable(current) << "' given.";
return false;
}
@@ -78,15 +86,15 @@ bool AddAbiFlavor::setArguments(const QStringList &args)
continue;
}
- std::cerr << "Unknown parameter: " << qPrintable(current) << std::endl << std::endl;
+ qCCritical(addAbiFlavorLog) << "Unknown parameter: " << qPrintable(current);
return false;
}
if (m_flavor.isEmpty())
- std::cerr << "Error no flavor was passed." << std::endl << std::endl;
+ qCCritical(addAbiFlavorLog) << "Error no flavor was passed.";
if (m_oses.isEmpty())
- std::cerr << "Error no OSes name was passed." << std::endl << std::endl;
+ qCCritical(addAbiFlavorLog) << "Error no OSes name was passed.";
return !m_flavor.isEmpty() && !m_oses.isEmpty();
}
@@ -106,32 +114,31 @@ int AddAbiFlavor::execute() const
}
#ifdef WITH_TESTS
-bool AddAbiFlavor::test() const
+void AddAbiFlavor::unittest()
{
QVariantMap map = initializeAbiFlavors();
- if (map.count() != 1
- || !map.contains(QLatin1String(VERSION)))
- return false;
+ QCOMPARE(map.count(), 1);
+ QVERIFY(map.contains(QLatin1String(VERSION)));
- map = AddAbiFlavorData{{"linux", "windows"}, "foo"}.addAbiFlavor(map);
+ AddAbiFlavorData d;
+ d.m_oses = QStringList{"linux", "windows"};
+ d.m_flavor = "foo";
+ map = d.addAbiFlavor(map);
- if (map.count() != 2
- || !map.contains(QLatin1String(VERSION))
- || !map.contains(QLatin1String(FLAVORS)))
- return false;
+ QCOMPARE(map.count(), 2);
+ QVERIFY(map.contains(QLatin1String(VERSION)));
+ QVERIFY(map.contains(QLatin1String(FLAVORS)));
const QVariantMap flavorMap = map.value(QLatin1String(FLAVORS)).toMap();
- if (flavorMap.count() != 1
- || flavorMap.value("foo").toStringList() != QStringList({"linux", "windows"}))
- return false;
+ QCOMPARE(flavorMap.count(), 1);
+ QCOMPARE(flavorMap.value("foo").toStringList(), QStringList({"linux", "windows"}));
// Ignore known flavors:
- const QVariantMap result = AddAbiFlavorData({{"linux"}, "foo"}).addAbiFlavor(map);;
-
- if (map != result)
- return false;
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Error: flavor .* already defined as extra ABI flavor."));
+ const QVariantMap result = AddAbiFlavorData({{"linux"}, "foo"}).addAbiFlavor(map);
- return true;
+ QCOMPARE(map, result);
}
#endif
@@ -139,7 +146,7 @@ QVariantMap AddAbiFlavorData::addAbiFlavor(const QVariantMap &map) const
{
// Sanity check: Is flavor already set in abi file?
if (exists(map, m_flavor)) {
- std::cerr << "Error: flavor " << qPrintable(m_flavor) << " already defined as extra ABI flavor." << std::endl;
+ qCCritical(addAbiFlavorLog) << "Error: flavor" << qPrintable(m_flavor) << "already defined as extra ABI flavor.";
return map;
}
diff --git a/src/tools/sdktool/addabiflavor.h b/src/tools/sdktool/addabiflavor.h
index fabd9d001a9..27ade701f51 100644
--- a/src/tools/sdktool/addabiflavor.h
+++ b/src/tools/sdktool/addabiflavor.h
@@ -53,6 +53,6 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
};
diff --git a/src/tools/sdktool/addcmakeoperation.cpp b/src/tools/sdktool/addcmakeoperation.cpp
index 9bbec46ac68..9b89433a42b 100644
--- a/src/tools/sdktool/addcmakeoperation.cpp
+++ b/src/tools/sdktool/addcmakeoperation.cpp
@@ -33,7 +33,14 @@
#include "settings.h"
-#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+Q_LOGGING_CATEGORY(addCMakeOperationLog, "qtc.sdktool.operations.addcmake", QtWarningMsg)
// CMakeTools file stuff:
const char COUNT[] = "CMakeTools.Count";
@@ -72,7 +79,7 @@ bool AddCMakeOperation::setArguments(const QStringList &args)
const QString next = ((i + 1) < args.count()) ? args.at(i + 1) : QString();
if (next.isNull() && current.startsWith("--")) {
- std::cerr << "No parameter for option '" << qPrintable(current) << "' given." << std::endl << std::endl;
+ qCCritical(addCMakeOperationLog) << "No parameter for option '" << qPrintable(current) << "' given.";
return false;
}
@@ -94,24 +101,24 @@ bool AddCMakeOperation::setArguments(const QStringList &args)
continue;
}
if (next.isNull()) {
- std::cerr << "No value given for key '" << qPrintable(current) << "'.";
+ qCCritical(addCMakeOperationLog) << "No value given for key '" << qPrintable(current) << "'.";
return false;
}
++i; // skip next;
KeyValuePair pair(current, next);
if (!pair.value.isValid()) {
- std::cerr << "Value for key '" << qPrintable(current) << "' is not valid.";
+ qCCritical(addCMakeOperationLog) << "Value for key '" << qPrintable(current) << "' is not valid.";
return false;
}
m_extra << pair;
}
if (m_id.isEmpty())
- std::cerr << "No id given for cmake tool." << std::endl;
+ qCCritical(addCMakeOperationLog) << "No id given for cmake tool.";
if (m_displayName.isEmpty())
- std::cerr << "No name given for cmake tool." << std::endl;
+ qCCritical(addCMakeOperationLog) << "No name given for cmake tool.";
if (m_path.isEmpty())
- std::cerr << "No path given for cmake tool." << std::endl;
+ qCCritical(addCMakeOperationLog) << "No path given for cmake tool.";
return !m_id.isEmpty() && !m_displayName.isEmpty() && !m_path.isEmpty();
}
@@ -130,55 +137,69 @@ int AddCMakeOperation::execute() const
}
#ifdef WITH_TESTS
-bool AddCMakeOperation::test() const
+void AddCMakeOperation::unittest()
{
QVariantMap map = initializeCMake();
// Add toolchain:
- map = AddCMakeData{"testId", "name", "/tmp/test", {{"ExtraKey", QVariant("ExtraValue")}}}.addCMake(map);
- if (map.value(COUNT).toInt() != 1
- || !map.contains(QString::fromLatin1(PREFIX) + '0'))
- return false;
+ AddCMakeData d;
+ d.m_id = "testId";
+ d.m_displayName = "name";
+ d.m_path = "/tmp/test";
+ d.m_extra = {{"ExtraKey", QVariant("ExtraValue")}};
+ map = d.addCMake(map);
+
+ QCOMPARE(map.value(COUNT).toInt(), 1);
+ QVERIFY(map.contains(QString::fromLatin1(PREFIX) + '0'));
+
QVariantMap cmData = map.value(QString::fromLatin1(PREFIX) + '0').toMap();
- if (cmData.count() != 5
- || cmData.value(ID_KEY).toString() != "testId"
- || cmData.value(DISPLAYNAME_KEY).toString() != "name"
- || cmData.value(AUTODETECTED_KEY).toBool() != true
- || cmData.value(PATH_KEY).toString() != "/tmp/test"
- || cmData.value("ExtraKey").toString() != "ExtraValue")
- return false;
+ QCOMPARE(cmData.count(), 5);
+ QCOMPARE(cmData.value(ID_KEY).toString(), "testId");
+ QCOMPARE(cmData.value(DISPLAYNAME_KEY).toString(), "name");
+ QCOMPARE(cmData.value(AUTODETECTED_KEY).toBool(), true);
+ QCOMPARE(cmData.value(PATH_KEY).toString(), "/tmp/test");
+ QCOMPARE(cmData.value("ExtraKey").toString(), "ExtraValue");
// Ignore same Id:
- QVariantMap unchanged = AddCMakeData{"testId", "name2", "/tmp/test2", {{"ExtraKey", QVariant("ExtraValue2")}}}
- .addCMake(map);
- if (!unchanged.isEmpty())
- return false;
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Error: Id .* already defined for tool chains."));
+
+ AddCMakeData ud;
+ ud.m_id = "testId";
+ ud.m_displayName = "name2";
+ ud.m_path = "/tmp/test2";
+ ud.m_extra = {{"ExtraKey", QVariant("ExtraValue2")}};
+
+ QVariantMap unchanged = ud.addCMake(map);
+ QVERIFY(unchanged.isEmpty());
// add 2nd cmake
- map = AddCMakeData{"{some-cm-id}", "name", "/tmp/test", {{"ExtraKey", QVariant("ExtraValue")}}}
- .addCMake(map);
- if (map.value(COUNT).toInt() != 2
- || !map.contains(QString::fromLatin1(PREFIX) + '0')
- || !map.contains(QString::fromLatin1(PREFIX) + '1'))
- return false;
+ AddCMakeData d2;
+ d2.m_id = "{some-cm-id}",
+ d2.m_displayName = "name";
+ d2.m_path = "/tmp/test";
+ d2.m_extra = {{"ExtraKey", QVariant("ExtraValue")}};
+ map = d2.addCMake(map);
+
+ QCOMPARE(map.value(COUNT).toInt(), 2);
+ QVERIFY(map.contains(QString::fromLatin1(PREFIX) + '0'));
+ QVERIFY(map.contains(QString::fromLatin1(PREFIX) + '1'));
+
cmData = map.value(QString::fromLatin1(PREFIX) + '0').toMap();
- if (cmData.count() != 5
- || cmData.value(ID_KEY).toString() != "testId"
- || cmData.value(DISPLAYNAME_KEY).toString() != "name"
- || cmData.value(AUTODETECTED_KEY).toBool() != true
- || cmData.value(PATH_KEY).toString() != "/tmp/test"
- || cmData.value("ExtraKey").toString() != "ExtraValue")
- return false;
- cmData = map.value(QString::fromLatin1(PREFIX) + '1').toMap();
- if (cmData.count() != 5
- || cmData.value(ID_KEY).toString() != "{some-cm-id}"
- || cmData.value(DISPLAYNAME_KEY).toString() != "name"
- || cmData.value(AUTODETECTED_KEY).toBool() != true
- || cmData.value(PATH_KEY).toString() != "/tmp/test"
- || cmData.value("ExtraKey").toString() != "ExtraValue")
- return false;
+ QCOMPARE(cmData.count(), 5);
+ QCOMPARE(cmData.value(ID_KEY).toString(), "testId");
+ QCOMPARE(cmData.value(DISPLAYNAME_KEY).toString(), "name");
+ QVERIFY(cmData.value(AUTODETECTED_KEY).toBool());
+ QCOMPARE(cmData.value(PATH_KEY).toString(), "/tmp/test");
+ QCOMPARE(cmData.value("ExtraKey").toString(), "ExtraValue");
- return true;
+ cmData = map.value(QString::fromLatin1(PREFIX) + '1').toMap();
+ QCOMPARE(cmData.count(), 5);
+ QCOMPARE(cmData.value(ID_KEY).toString(), "{some-cm-id}");
+ QCOMPARE(cmData.value(DISPLAYNAME_KEY).toString(), "name");
+ QVERIFY(cmData.value(AUTODETECTED_KEY).toBool());
+ QCOMPARE(cmData.value(PATH_KEY).toString(), "/tmp/test");
+ QCOMPARE(cmData.value("ExtraKey").toString(), "ExtraValue");
}
#endif
@@ -186,7 +207,7 @@ QVariantMap AddCMakeData::addCMake(const QVariantMap &map) const
{
// Sanity check: Does the Id already exist?
if (exists(map, m_id)) {
- std::cerr << "Error: Id " << qPrintable(m_id) << " already defined for tool chains." << std::endl;
+ qCCritical(addCMakeOperationLog) << "Error: Id" << qPrintable(m_id) << "already defined for tool chains.";
return QVariantMap();
}
@@ -194,7 +215,7 @@ QVariantMap AddCMakeData::addCMake(const QVariantMap &map) const
bool ok;
int count = GetOperation::get(map, COUNT).toInt(&ok);
if (!ok || count < 0) {
- std::cerr << "Error: Count found in toolchains file seems wrong." << std::endl;
+ qCCritical(addCMakeOperationLog) << "Error: Count found in toolchains file seems wrong.";
return QVariantMap();
}
@@ -208,7 +229,7 @@ QVariantMap AddCMakeData::addCMake(const QVariantMap &map) const
data << KeyValuePair({cm, AUTODETECTED_KEY}, QVariant(true));
data << KeyValuePair({cm, PATH_KEY}, Utils::FilePath::fromUserInput(m_path).toVariant());
KeyValuePairList extraList;
- foreach (const KeyValuePair &pair, m_extra)
+ for (const KeyValuePair &pair : qAsConst(m_extra))
extraList << KeyValuePair(QStringList({cm}) << pair.key, pair.value);
data.append(extraList);
data << KeyValuePair(COUNT, QVariant(count + 1));
@@ -230,7 +251,7 @@ bool AddCMakeData::exists(const QVariantMap &map, const QString &id)
// support old settings using QByteArray for id's
valueKeys.append(FindValueOperation::findValue(map, id.toUtf8()));
- foreach (const QString &k, valueKeys) {
+ for (const QString &k : qAsConst(valueKeys)) {
if (k.endsWith(QString('/') + ID_KEY)) {
return true;
}
diff --git a/src/tools/sdktool/addcmakeoperation.h b/src/tools/sdktool/addcmakeoperation.h
index 13045290178..90bfaf60357 100644
--- a/src/tools/sdktool/addcmakeoperation.h
+++ b/src/tools/sdktool/addcmakeoperation.h
@@ -55,6 +55,6 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
};
diff --git a/src/tools/sdktool/adddebuggeroperation.cpp b/src/tools/sdktool/adddebuggeroperation.cpp
index e3797525786..24020003e46 100644
--- a/src/tools/sdktool/adddebuggeroperation.cpp
+++ b/src/tools/sdktool/adddebuggeroperation.cpp
@@ -33,7 +33,14 @@
#include "settings.h"
-#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+Q_LOGGING_CATEGORY(addDebuggerOperationLog, "qtc.sdktool.operations.adddebugger", QtWarningMsg)
const char VERSION[] = "Version";
const char COUNT[] = "DebuggerItem.Count";
@@ -96,7 +103,7 @@ bool AddDebuggerOperation::setArguments(const QStringList &args)
bool ok;
m_engine = next.toInt(&ok);
if (!ok) {
- std::cerr << "Debugger type is not an integer!" << std::endl;
+ qCCritical(addDebuggerOperationLog) << "Debugger type is not an integer!";
return false;
}
continue;
@@ -128,12 +135,10 @@ bool AddDebuggerOperation::setArguments(const QStringList &args)
m_extra << pair;
}
-
-
if (m_id.isEmpty())
- std::cerr << "No id given for kit." << std::endl << std::endl;
+ qCCritical(addDebuggerOperationLog) << "No id given for kit.";
if (m_displayName.isEmpty())
- std::cerr << "No name given for kit." << std::endl << std::endl;
+ qCCritical(addDebuggerOperationLog) << "No name given for kit.";
return !m_id.isEmpty() && !m_displayName.isEmpty();
}
@@ -153,34 +158,66 @@ int AddDebuggerOperation::execute() const
}
#ifdef WITH_TESTS
-bool AddDebuggerOperation::test() const
+void AddDebuggerOperation::unittest()
{
QVariantMap map = initializeDebuggers();
- if (map.count() != 2
- || !map.contains(QLatin1String(VERSION))
- || map.value(QLatin1String(VERSION)).toInt() != 1
- || !map.contains(QLatin1String(COUNT))
- || map.value(QLatin1String(COUNT)).toInt() != 0)
- return false;
-
- return true;
+ QCOMPARE(map.count(), 2);
+
+ QVERIFY(map.contains(QLatin1String(VERSION)));
+ QCOMPARE(map.value(QLatin1String(VERSION)).toInt(), 1);
+ QVERIFY(map.contains(QLatin1String(COUNT)));
+ QCOMPARE(map.value(QLatin1String(COUNT)).toInt(), 0);
+
+ AddDebuggerData d;
+ d.m_id = "testId";
+ d.m_displayName = "name";
+ d.m_binary = "/tmp/bin/gdb";
+ d.m_abis = QStringList{"aarch64", "x86_64"};
+ d.m_extra = {{"ExtraKey", QVariant("ExtraValue")}};
+ map = d.addDebugger(map);
+
+ QCOMPARE(map.value(COUNT).toInt(), 1);
+ QVERIFY(map.contains(QString::fromLatin1(PREFIX) + '0'));
+
+ QVariantMap dbgData = map.value(QString::fromLatin1(PREFIX) + '0').toMap();
+ QCOMPARE(dbgData.count(), 7);
+ QCOMPARE(dbgData.value(ID).toString(), "testId");
+ QCOMPARE(dbgData.value(DISPLAYNAME).toString(), "name");
+ QCOMPARE(dbgData.value(AUTODETECTED).toBool(), true);
+ QCOMPARE(dbgData.value(ABIS).toStringList(), (QStringList{"aarch64", "x86_64"}));
+ QCOMPARE(dbgData.value(BINARY).toString(), "/tmp/bin/gdb");
+ QCOMPARE(dbgData.value(ENGINE_TYPE).toInt(), 0);
+ QCOMPARE(dbgData.value("ExtraKey").toString(), "ExtraValue");
+
+ // Ignore existing.
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Error: Id .* already defined as debugger."));
+
+ AddDebuggerData d2;
+ d2.m_id = "testId";
+ d2.m_displayName = "name2";
+ d2.m_binary = "/tmp/bin/gdb";
+ d2.m_abis = QStringList{};
+ d2.m_extra = {{"ExtraKey", QVariant("ExtraValue2")}};
+ QVariantMap unchanged = d2.addDebugger(map);
+ QVERIFY(unchanged.isEmpty());
}
#endif
QVariantMap AddDebuggerData::addDebugger(const QVariantMap &map) const
{
// Sanity check: Make sure autodetection source is not in use already:
- QStringList valueKeys = FindValueOperation::findValue(map, QVariant(m_id));
+ const QStringList valueKeys = FindValueOperation::findValue(map, QVariant(m_id));
bool hasId = false;
- foreach (const QString &k, valueKeys) {
+ for (const QString &k : valueKeys) {
if (k.endsWith(QString(QLatin1Char('/')) + QLatin1String(ID))) {
hasId = true;
break;
}
}
if (hasId) {
- std::cerr << "Error: Id " << qPrintable(m_id) << " already defined as debugger." << std::endl;
+ qCCritical(addDebuggerOperationLog) << "Error: Id" << qPrintable(m_id) << "already defined as debugger.";
return QVariantMap();
}
@@ -188,7 +225,7 @@ QVariantMap AddDebuggerData::addDebugger(const QVariantMap &map) const
bool ok;
int count = GetOperation::get(map, QLatin1String(COUNT)).toInt(&ok);
if (!ok || count < 0) {
- std::cerr << "Error: Count found in debuggers file seems wrong." << std::endl;
+ qCCritical(addDebuggerOperationLog) << "Error: Count found in debuggers file seems wrong.";
return QVariantMap();
}
const QString debugger = QString::fromLatin1(PREFIX) + QString::number(count);
@@ -213,7 +250,7 @@ QVariantMap AddDebuggerData::addDebugger(const QVariantMap &map) const
data << KeyValuePair(QStringList() << QLatin1String(COUNT), QVariant(count + 1));
KeyValuePairList qtExtraList;
- foreach (const KeyValuePair &pair, m_extra)
+ for (const KeyValuePair &pair : qAsConst(m_extra))
qtExtraList << KeyValuePair(QStringList() << debugger << pair.key, pair.value);
data.append(qtExtraList);
diff --git a/src/tools/sdktool/adddebuggeroperation.h b/src/tools/sdktool/adddebuggeroperation.h
index 788900ee2c6..57cdc55a448 100644
--- a/src/tools/sdktool/adddebuggeroperation.h
+++ b/src/tools/sdktool/adddebuggeroperation.h
@@ -54,6 +54,6 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
};
diff --git a/src/tools/sdktool/adddeviceoperation.cpp b/src/tools/sdktool/adddeviceoperation.cpp
index 00628be384c..d20636fb33e 100644
--- a/src/tools/sdktool/adddeviceoperation.cpp
+++ b/src/tools/sdktool/adddeviceoperation.cpp
@@ -33,7 +33,13 @@
#include "settings.h"
-#include <iostream>
+#include <QLoggingCategory>
+
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+Q_LOGGING_CATEGORY(addDeviceLog, "qtc.sdktool.operations.adddevice", QtWarningMsg)
const char DEVICEMANAGER_ID[] = "DeviceManager";
const char DEFAULT_DEVICES_ID[] = "DefaultDevices";
@@ -261,9 +267,9 @@ bool AddDeviceOperation::setArguments(const QStringList &args)
}
if (m_id.isEmpty())
- std::cerr << "No id given for device." << std::endl << std::endl;
+ qCCritical(addDeviceLog) << "No id given for device.";
if (m_displayName.isEmpty())
- std::cerr << "No name given for device." << std::endl << std::endl;
+ qCCritical(addDeviceLog) << "No name given for device.";
return !m_id.isEmpty() && !m_displayName.isEmpty() && m_type >= 0;
}
@@ -283,7 +289,7 @@ int AddDeviceOperation::execute() const
}
#ifdef WITH_TESTS
-bool AddDeviceOperation::test() const
+void AddDeviceOperation::unittest()
{
QVariantMap map = initializeDevices();
@@ -305,57 +311,37 @@ bool AddDeviceOperation::test() const
devData.m_timeout = 5;
devData.m_uname = "uname";
devData.m_version = 6;
+ devData.m_dockerMappedPaths = QStringList{"/opt", "/data"};
devData.m_dockerRepo = "repo";
devData.m_dockerTag = "tag";
- devData.m_dockerMappedPaths = QStringList{"/opt", "/data"};
+
QVariantMap result = devData.addDevice(map);
QVariantMap data = result.value(QLatin1String(DEVICEMANAGER_ID)).toMap();
QVariantList devList = data.value(QLatin1String(DEVICE_LIST_ID)).toList();
- if (devList.count() != 1)
- return false;
+ QCOMPARE(devList.count(), 1);
QVariantMap dev = devList.at(0).toMap();
- if (dev.count() != 20)
- return false;
- if (dev.value(QLatin1String("Authentication")).toInt() != 2)
- return false;
- if (dev.value(QLatin1String("DebugServerKey")).toString() != QLatin1String("debugServer"))
- return false;
- if (dev.value(QLatin1String("FreePortsSpec")).toString() != QLatin1String("ports"))
- return false;
- if (dev.value(QLatin1String("Host")).toString() != QLatin1String("host"))
- return false;
- if (dev.value(QLatin1String("InternalId")).toString() != QLatin1String("test id"))
- return false;
- if (dev.value(QLatin1String("KeyFile")).toString() != QLatin1String("keyfile"))
- return false;
- if (dev.value(QLatin1String("Name")).toString() != QLatin1String("test name"))
- return false;
- if (dev.value(QLatin1String("Origin")).toInt() != 3)
- return false;
- if (dev.value(QLatin1String("OsType")).toString() != QLatin1String("ostype"))
- return false;
- if (dev.value(QLatin1String("Password")).toString() != QLatin1String("passwd"))
- return false;
- if (dev.value(QLatin1String("SshPort")).toInt() != 4)
- return false;
- if (dev.value(QLatin1String("Timeout")).toInt() != 5)
- return false;
- if (dev.value(QLatin1String("Type")).toInt() != 1)
- return false;
- if (dev.value(QLatin1String("Uname")).toString() != QLatin1String("uname"))
- return false;
- if (dev.value(QLatin1String("Version")).toInt() != 6)
- return false;
- if (dev.value(QLatin1String("DockerDeviceDataRepo")).toString() != "repo")
- return false;
- if (dev.value(QLatin1String("DockerDeviceDataTag")).toString() != "tag")
- return false;
- const QStringList paths = dev.value(QLatin1String("DockerDeviceMappedPaths")).toStringList();
- if (paths != QStringList({"/opt", "/data"}))
- return false;
+ QCOMPARE(dev.count(), 20);
+ QCOMPARE(dev.value(QLatin1String("Authentication")).toInt(), 2);
+ QCOMPARE(dev.value(QLatin1String("DebugServerKey")).toString(), QLatin1String("debugServer"));
+ QCOMPARE(dev.value(QLatin1String("FreePortsSpec")).toString(), QLatin1String("ports"));
+ QCOMPARE(dev.value(QLatin1String("Host")).toString(), QLatin1String("host"));
+ QCOMPARE(dev.value(QLatin1String("InternalId")).toString(), QLatin1String("test id"));
+ QCOMPARE(dev.value(QLatin1String("KeyFile")).toString(), QLatin1String("keyfile"));
+ QCOMPARE(dev.value(QLatin1String("Name")).toString(), QLatin1String("test name"));
+ QCOMPARE(dev.value(QLatin1String("Origin")).toInt(), 3);
+ QCOMPARE(dev.value(QLatin1String("OsType")).toString(), QLatin1String("ostype"));
+ QCOMPARE(dev.value(QLatin1String("Password")).toString(), QLatin1String("passwd"));
+ QCOMPARE(dev.value(QLatin1String("SshPort")).toInt(), 4);
+ QCOMPARE(dev.value(QLatin1String("Timeout")).toInt(), 5);
+ QCOMPARE(dev.value(QLatin1String("Type")).toInt(), 1);
+ QCOMPARE(dev.value(QLatin1String("Uname")).toString(), QLatin1String("uname"));
+ QCOMPARE(dev.value(QLatin1String("Version")).toInt(), 6);
+ QCOMPARE(dev.value(QLatin1String("DockerDeviceDataRepo")).toString(), "repo");
+ QCOMPARE(dev.value(QLatin1String("DockerDeviceDataTag")).toString(), "tag");
- return true;
+ const QStringList paths = dev.value(QLatin1String("DockerDeviceMappedPaths")).toStringList();
+ QCOMPARE(paths, QStringList({"/opt", "/data"}));
}
#endif
@@ -363,7 +349,7 @@ QVariantMap AddDeviceData::addDevice(const QVariantMap &map) const
{
QVariantMap result = map;
if (exists(map, m_id)) {
- std::cerr << "Device " << qPrintable(m_id) << " already exists!" << std::endl;
+ qCCritical(addDeviceLog) << "Device " << qPrintable(m_id) << " already exists!";
return result;
}
@@ -426,8 +412,8 @@ bool AddDeviceData::exists(const QVariantMap &map, const QString &id)
if (id == QLatin1String(INTERNAL_DSEKTOP_DEVICE_ID))
return true;
QVariantMap dmMap = map.value(QLatin1String(DEVICEMANAGER_ID)).toMap();
- QVariantList devList = dmMap.value(QLatin1String(DEVICE_LIST_ID)).toList();
- foreach (const QVariant &dev, devList) {
+ const QVariantList devList = dmMap.value(QLatin1String(DEVICE_LIST_ID)).toList();
+ for (const QVariant &dev : devList) {
QVariantMap devData = dev.toMap();
QString current = devData.value(QLatin1String(DEVICE_ID_ID)).toString();
if (current == id)
diff --git a/src/tools/sdktool/adddeviceoperation.h b/src/tools/sdktool/adddeviceoperation.h
index 67f4a677d6d..2d5e7a54ad5 100644
--- a/src/tools/sdktool/adddeviceoperation.h
+++ b/src/tools/sdktool/adddeviceoperation.h
@@ -80,6 +80,6 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
};
diff --git a/src/tools/sdktool/addkeysoperation.cpp b/src/tools/sdktool/addkeysoperation.cpp
index cc26b536f58..2d100f315e4 100644
--- a/src/tools/sdktool/addkeysoperation.cpp
+++ b/src/tools/sdktool/addkeysoperation.cpp
@@ -27,6 +27,15 @@
#include <iostream>
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+Q_LOGGING_CATEGORY(addkeyslog, "qtc.sdktool.operations.addkeys", QtWarningMsg)
+
QString AddKeysOperation::name() const
{
return QLatin1String("addKeys");
@@ -39,8 +48,9 @@ QString AddKeysOperation::helpText() const
QString AddKeysOperation::argumentsHelpText() const
{
- return QLatin1String("A file (relative to top-level settings directory and without .xml extension)\n"
- "followed by one or more Tuples <KEY> <TYPE>:<VALUE> are required.\n");
+ return QLatin1String(
+ "A file (relative to top-level settings directory and without .xml extension)\n"
+ "followed by one or more Tuples <KEY> <TYPE>:<VALUE> are required.\n");
}
bool AddKeysOperation::setArguments(const QStringList &args)
@@ -55,7 +65,7 @@ bool AddKeysOperation::setArguments(const QStringList &args)
}
if (next.isNull()) {
- std::cerr << "Missing value for key '" << qPrintable(current) << "'." << std::endl << std::endl;
+ qCCritical(addkeyslog) << "Missing value for key '" << qPrintable(current) << "'.";
return false;
}
@@ -85,7 +95,7 @@ int AddKeysOperation::execute() const
}
#ifdef WITH_TESTS
-bool AddKeysOperation::test() const
+void AddKeysOperation::unittest()
{
QVariantMap testMap;
QVariantMap subKeys;
@@ -101,118 +111,116 @@ bool AddKeysOperation::test() const
data.append(KeyValuePair(QLatin1String("bool-false"), QString::fromLatin1("bool:false")));
data.append(KeyValuePair(QLatin1String("int"), QString::fromLatin1("int:42")));
data.append(KeyValuePair(QLatin1String("qstring"), QString::fromLatin1("QString:test string.")));
- data.append(KeyValuePair(QLatin1String("qbytearray"), QString::fromLatin1("QByteArray:test array.")));
-
- data.append(KeyValuePair(QLatin1String("subkeys/qbytearray"), QString::fromLatin1("QByteArray:test array.")));
- data.append(KeyValuePair(QLatin1String("subkeys/newsubkeys/qbytearray"), QString::fromLatin1("QByteArray:test array.")));
- data.append(KeyValuePair(QLatin1String("newsub/1/2/3/qbytearray"), QString::fromLatin1("QByteArray:test array.")));
- data.append(KeyValuePair(QLatin1String("newsub/1/2.1/3/qbytearray"), QString::fromLatin1("QByteArray:test array.")));
+ data.append(
+ KeyValuePair(QLatin1String("qbytearray"), QString::fromLatin1("QByteArray:test array.")));
+
+ data.append(KeyValuePair(QLatin1String("subkeys/qbytearray"),
+ QString::fromLatin1("QByteArray:test array.")));
+ data.append(KeyValuePair(QLatin1String("subkeys/newsubkeys/qbytearray"),
+ QString::fromLatin1("QByteArray:test array.")));
+ data.append(KeyValuePair(QLatin1String("newsub/1/2/3/qbytearray"),
+ QString::fromLatin1("QByteArray:test array.")));
+ data.append(KeyValuePair(QLatin1String("newsub/1/2.1/3/qbytearray"),
+ QString::fromLatin1("QByteArray:test array.")));
QVariantMap result = AddKeysData{data}.addKeys(testMap);
- if (result.count() != 9)
- return false;
+ QCOMPARE(result.count(), 9);
// subkeys:
QVariantMap cur = result.value(QLatin1String("subkeys")).toMap();
- if (cur.count() != 4
- || !cur.contains(QLatin1String("qbytearray"))
- || !cur.contains(QLatin1String("testbool"))
- || !cur.contains(QLatin1String("subsubkeys"))
- || !cur.contains(QLatin1String("newsubkeys")))
- return false;
+ QCOMPARE(cur.count(), 4);
+ QVERIFY(cur.contains(QLatin1String("qbytearray")));
+ QVERIFY(cur.contains(QLatin1String("testbool")));
+ QVERIFY(cur.contains(QLatin1String("subsubkeys")));
+ QVERIFY(cur.contains(QLatin1String("newsubkeys")));
// subkeys/newsubkeys:
QVariantMap tmp = cur;
cur = cur.value(QLatin1String("newsubkeys")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("qbytearray")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("qbytearray")));
// subkeys/subsubkeys:
cur = tmp.value(QLatin1String("subsubkeys")).toMap();
- if (cur.count() != 0)
- return false;
+ QVERIFY(cur.isEmpty());
// newsub:
cur = result.value(QLatin1String("newsub")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("1")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("1")));
// newsub/1:
cur = cur.value(QLatin1String("1")).toMap();
- if (cur.count() != 2
- || !cur.contains(QLatin1String("2"))
- || !cur.contains(QLatin1String("2.1")))
- return false;
+ QCOMPARE(cur.count(), 2);
+ QVERIFY(cur.contains(QLatin1String("2")));
+ QVERIFY(cur.contains(QLatin1String("2.1")));
// newsub/1/2:
tmp = cur;
cur = cur.value(QLatin1String("2")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("3")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("3")));
// newsub/1/2/3:
cur = cur.value(QLatin1String("3")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("qbytearray")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("qbytearray")));
// newsub/1/2.1:
cur = tmp.value(QLatin1String("2.1")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("3")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("3")));
// newsub/1/2.1/3:
cur = cur.value(QLatin1String("3")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("qbytearray")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("qbytearray")));
// subkeys2:
cur = result.value(QLatin1String("subkeys2")).toMap();
- if (cur.count() != 0)
- return false;
+ QVERIFY(cur.isEmpty());
// values:
- if (!result.contains(QLatin1String("bool-true")) || !result.value(QLatin1String("bool-true")).toBool())
- return false;
- if (!result.contains(QLatin1String("bool-false")) || result.value(QLatin1String("bool-false")).toBool())
- return false;
- if (!result.contains(QLatin1String("int")) || result.value(QLatin1String("int")).toInt() != 42)
- return false;
- if (!result.contains(QLatin1String("qstring"))
- || result.value(QLatin1String("qstring")).toString() != QLatin1String("test string."))
- return false;
- if (!result.contains(QLatin1String("qbytearray"))
- || result.value(QLatin1String("qbytearray")).toByteArray() != "test array.")
- return false;
+ QVERIFY(result.contains(QLatin1String("bool-true")));
+ QVERIFY(result.value(QLatin1String("bool-true")).toBool());
+
+ QVERIFY(result.contains(QLatin1String("bool-false")));
+ QVERIFY(!result.value(QLatin1String("bool-false")).toBool());
+
+ QVERIFY(result.contains(QLatin1String("int")));
+ QCOMPARE(result.value(QLatin1String("int")).toInt(), 42);
+ QVERIFY(result.contains(QLatin1String("qstring")));
+ QCOMPARE(result.value(QLatin1String("qstring")).toString(), QLatin1String("test string."));
+ QVERIFY(result.contains(QLatin1String("qbytearray")));
+ QCOMPARE(result.value(QLatin1String("qbytearray")).toByteArray(), "test array.");
// Make sure we do not overwrite data:
// preexisting:
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Cannot add key .* which already exists."));
+
data.clear();
data.append(KeyValuePair(QLatin1String("testint"), QString::fromLatin1("int:4")));
result = AddKeysData{data}.addKeys(testMap);
- if (!result.isEmpty())
- return false;
+ QVERIFY(result.isEmpty());
+
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Cannot add key .* which already exists."));
data.clear();
data.append(KeyValuePair(QLatin1String("subkeys/testbool"), QString::fromLatin1("int:24")));
result = AddKeysData{data}.addKeys(testMap);
- if (!result.isEmpty())
- return false;
+ QVERIFY(result.isEmpty());
+
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Cannot add key .* which already exists."));
// data inserted before:
data.clear();
data.append(KeyValuePair(QLatin1String("bool-true"), QString::fromLatin1("bool:trUe")));
data.append(KeyValuePair(QLatin1String("bool-true"), QString::fromLatin1("bool:trUe")));
result = AddKeysData{data}.addKeys(testMap);
- if (!result.isEmpty())
- return false;
-
- return true;
+ QVERIFY(result.isEmpty());
}
#endif
@@ -221,7 +229,7 @@ QVariantMap AddKeysData::addKeys(const QVariantMap &map) const
// Insert data:
QVariantMap result = map;
- foreach (const KeyValuePair &p, m_data) {
+ for (const KeyValuePair &p : m_data) {
QList<QVariantMap> stack;
// Set up a stack of QVariantMaps along the path we take:
@@ -236,14 +244,16 @@ QVariantMap AddKeysData::addKeys(const QVariantMap &map) const
// insert
Q_ASSERT(stack.count() == p.key.count());
if (stack.last().contains(p.key.last())) {
- std::cerr << "DEBUG: Adding key " << qPrintable(p.key.join(QLatin1Char('/'))) << " which already exists." << std::endl;
+ qCCritical(addkeyslog) << "Cannot add key" << qPrintable(p.key.join(QLatin1Char('/')))
+ << "which already exists.";
return QVariantMap();
}
stack.last().insert(p.key.last(), p.value);
// Generate new resultset by folding maps back in:
QVariantMap foldBack = stack.takeLast();
- for (int i = p.key.count() - 2; i >= 0; --i) { // skip last key, that is already taken care of
+ for (int i = p.key.count() - 2; i >= 0;
+ --i) { // skip last key, that is already taken care of
const QString k = p.key.at(i);
QVariantMap current = stack.takeLast();
current.insert(k, foldBack);
diff --git a/src/tools/sdktool/addkeysoperation.h b/src/tools/sdktool/addkeysoperation.h
index 9623d715045..47e6f881992 100644
--- a/src/tools/sdktool/addkeysoperation.h
+++ b/src/tools/sdktool/addkeysoperation.h
@@ -47,7 +47,8 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
+
#endif
private:
diff --git a/src/tools/sdktool/addkitoperation.cpp b/src/tools/sdktool/addkitoperation.cpp
index 4a326255e1a..2befb340c4a 100644
--- a/src/tools/sdktool/addkitoperation.cpp
+++ b/src/tools/sdktool/addkitoperation.cpp
@@ -26,10 +26,10 @@
#include "addkitoperation.h"
#include "addcmakeoperation.h"
+#include "adddeviceoperation.h"
#include "addkeysoperation.h"
-#include "addtoolchainoperation.h"
#include "addqtoperation.h"
-#include "adddeviceoperation.h"
+#include "addtoolchainoperation.h"
#include "findkeyoperation.h"
#include "findvalueoperation.h"
#include "getoperation.h"
@@ -37,9 +37,14 @@
#include "settings.h"
+#include <QLoggingCategory>
#include <QRegularExpression>
-#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+Q_LOGGING_CATEGORY(addkitlog, "qtc.sdktool.operations.addkit", QtWarningMsg)
// Qt version file stuff:
const char PREFIX[] = "Profile.";
@@ -84,27 +89,29 @@ QString AddKitOperation::helpText() const
QString AddKitOperation::argumentsHelpText() const
{
return QString(
- " --id <ID> id of the new kit (required).\n"
- " --name <NAME> display name of the new kit (required).\n"
- " --icon <PATH> icon of the new kit.\n"
- " --debuggerid <ID> the id of the debugger to use.\n"
- " (not compatible with --debugger and --debuggerengine)\n"
- " --debuggerengine <ENGINE> debuggerengine of the new kit.\n"
- " --debugger <PATH> debugger of the new kit.\n"
- " --devicetype <TYPE> (run-)device type of the new kit (required).\n"
- " --device <ID> (run-)device id to use (optional).\n"
- " --builddevice <ID> build device id to use (optional).\n"
- " --sysroot <PATH> sysroot of the new kit.\n"
- " --toolchain <ID> tool chain of the new kit (obsolete!).\n"
- " --<LANG>toolchain <ID> tool chain for a language.\n"
- " --qt <ID> Qt of the new kit.\n"
- " --mkspec <PATH> mkspec of the new kit.\n"
- " --env <VALUE> add a custom environment setting. [may be repeated]\n"
- " --cmake <ID> set a cmake tool.\n"
- " --cmake-generator <GEN>:<EXTRA>:<TOOLSET>:<PLATFORM>\n"
- " set a cmake generator.\n"
- " --cmake-config <KEY:TYPE=VALUE> set a cmake configuration value [may be repeated]\n"
- " <KEY> <TYPE:VALUE> extra key value pairs\n");
+ " --id <ID> id of the new kit (required).\n"
+ " --name <NAME> display name of the new kit (required).\n"
+ " --icon <PATH> icon of the new kit.\n"
+ " --debuggerid <ID> the id of the debugger to use.\n"
+ " (not compatible with --debugger and "
+ "--debuggerengine)\n"
+ " --debuggerengine <ENGINE> debuggerengine of the new kit.\n"
+ " --debugger <PATH> debugger of the new kit.\n"
+ " --devicetype <TYPE> (run-)device type of the new kit (required).\n"
+ " --device <ID> (run-)device id to use (optional).\n"
+ " --builddevice <ID> build device id to use (optional).\n"
+ " --sysroot <PATH> sysroot of the new kit.\n"
+ " --toolchain <ID> tool chain of the new kit (obsolete!).\n"
+ " --<LANG>toolchain <ID> tool chain for a language.\n"
+ " --qt <ID> Qt of the new kit.\n"
+ " --mkspec <PATH> mkspec of the new kit.\n"
+ " --env <VALUE> add a custom environment setting. [may be repeated]\n"
+ " --cmake <ID> set a cmake tool.\n"
+ " --cmake-generator <GEN>:<EXTRA>:<TOOLSET>:<PLATFORM>\n"
+ " set a cmake generator.\n"
+ " --cmake-config <KEY:TYPE=VALUE> set a cmake configuration value [may be "
+ "repeated]\n"
+ " <KEY> <TYPE:VALUE> extra key value pairs\n");
}
bool AddKitOperation::setArguments(const QStringList &args)
@@ -144,7 +151,7 @@ bool AddKitOperation::setArguments(const QStringList &args)
bool ok;
m_debuggerEngine = next.toInt(&ok);
if (!ok) {
- std::cerr << "Debugger type is not an integer!" << std::endl;
+ qCCritical(addkitlog) << "Debugger type is not an integer!";
return false;
}
continue;
@@ -208,11 +215,11 @@ bool AddKitOperation::setArguments(const QStringList &args)
const QString lang = tmp2.isEmpty() ? QString("Cxx") : tmp2;
if (next.isEmpty()) {
- std::cerr << "Empty langid for toolchain given." << std::endl << std::endl;
+ qCCritical(addkitlog) << "Empty langid for toolchain given.";
return false;
}
if (m_tcs.contains(lang)) {
- std::cerr << "No langid for toolchain given twice." << std::endl << std::endl;
+ qCCritical(addkitlog) << "No langid for toolchain given twice.";
return false;
}
m_tcs.insert(lang, next);
@@ -284,13 +291,13 @@ bool AddKitOperation::setArguments(const QStringList &args)
}
if (m_id.isEmpty())
- std::cerr << "No id given for kit." << std::endl << std::endl;
+ qCCritical(addkitlog) << "No id given for kit.";
if (m_displayName.isEmpty())
- std::cerr << "No name given for kit." << std::endl << std::endl;
+ qCCritical(addkitlog) << "No name given for kit.";
if (m_deviceType.isEmpty())
- std::cerr << "No devicetype given for kit." << std::endl << std::endl;
+ qCCritical(addkitlog) << "No devicetype given for kit.";
if (!m_debuggerId.isEmpty() && (!m_debugger.isEmpty() || m_debuggerEngine != 0)) {
- std::cerr << "Cannot set both debugger id and debugger/debuggerengine." << std::endl << std::endl;
+ qCCritical(addkitlog) << "Cannot set both debugger id and debugger/debuggerengine.";
return false;
}
@@ -311,29 +318,45 @@ int AddKitOperation::execute() const
}
#ifdef WITH_TESTS
-bool AddKitOperation::test() const
+void AddKitOperation::unittest()
{
AddKitData baseData;
- baseData.m_id ="testId";
+ baseData.m_id = "testId";
baseData.m_displayName = "Test Kit";
baseData.m_icon = "/tmp/icon.png";
baseData.m_debuggerEngine = 1;
baseData.m_debugger = "/usr/bin/gdb-test";
baseData.m_deviceType = "Desktop";
- baseData.m_device = "{dev-id}";
+ baseData.m_device = "{dev-id}";
baseData.m_qt = "{qt-id}";
- baseData.m_mkspec ="unsupported/mkspec";
+ baseData.m_mkspec = "unsupported/mkspec";
baseData.m_extra = {{"PE.Profile.Data/extraData", QVariant("extraValue")}};
QVariantMap map = initializeKits();
QVariantMap tcMap = AddToolChainData::initializeToolChains();
- tcMap = AddToolChainData{"{tc-id}", "langId", "TC", "/usr/bin/gcc",
- "x86-linux-generic-elf-32bit", "x86-linux-generic-elf-32bit", {}}
- .addToolChain(tcMap);
+ AddToolChainData atcd;
+ atcd.m_id = "{tc-id}";
+ atcd.m_languageId = "langId";
+ atcd.m_displayName = "TC";
+ atcd.m_path = "/usr/bin/gcc";
+ atcd.m_targetAbi = "x86-linux-generic-elf-32bit";
+ atcd.m_supportedAbis = "x86-linux-generic-elf-32bit";
+ atcd.m_extra = {};
+
+ tcMap = atcd.addToolChain(tcMap);
QVariantMap qtMap = AddQtData::initializeQtVersions();
- qtMap = AddQtData{"{qt-id}", "Qt", "desktop-qt", "/usr/bin/qmake", {}, {}}.addQt(qtMap);
+ AddQtData aqtd;
+
+ aqtd.m_id = "{qt-id}";
+ aqtd.m_displayName = "Qt";
+ aqtd.m_type = "desktop-qt";
+ aqtd.m_qmake = "/usr/bin/qmake";
+ aqtd.m_abis = QStringList{};
+ aqtd.m_extra = {};
+
+ qtMap = aqtd.addQt(qtMap);
QVariantMap devMap = AddDeviceOperation::initializeDevices();
AddDeviceData devData;
@@ -358,159 +381,119 @@ bool AddKitOperation::test() const
const QStringList env = {"TEST=1", "PATH"};
- if (map.count() != 3)
- return false;
- if (!map.contains(VERSION))
- return false;
- if (map.value(VERSION).toInt() != 1)
- return false;
- if (!map.contains(COUNT))
- return false;
- if (map.value(COUNT).toInt() != 0)
- return false;
- if (!map.contains(DEFAULT))
- return false;
- if (!map.value(DEFAULT).toString().isEmpty())
- return false;
+ QCOMPARE(map.count(), 3);
+ QVERIFY(map.contains(VERSION));
+ QCOMPARE(map.value(VERSION).toInt(), 1);
+ QVERIFY(map.contains(COUNT));
+ QCOMPARE(map.value(COUNT).toInt(), 0);
+ QVERIFY(map.contains(DEFAULT));
+ QVERIFY(map.value(DEFAULT).toString().isEmpty());
QHash<QString, QString> tcs;
tcs.insert("Cxx", "{tcXX-id}");
// Fail if TC is not there:
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression(
+ "Error: Toolchain .* for language Cxx does not exist."));
+
AddKitData kitData = baseData;
kitData.m_tcs = tcs;
QVariantMap empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (!empty.isEmpty())
- return false;
+ QVERIFY(empty.isEmpty());
// Do not fail if TC is an ABI:
tcs.clear();
tcs.insert("C", "x86-linux-generic-elf-64bit");
kitData = baseData;
kitData.m_tcs = tcs;
empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (empty.isEmpty())
- return false;
+ QVERIFY(!empty.isEmpty());
// QTCREATORBUG-11983, mach_o was not covered by the first attempt to fix this.
tcs.insert("D", "x86-macos-generic-mach_o-64bit");
kitData = baseData;
kitData.m_tcs = tcs;
empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (empty.isEmpty())
- return false;
+ QVERIFY(!empty.isEmpty());
tcs.clear();
tcs.insert("Cxx", "{tc-id}");
// Fail if Qt is not there:
+ QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Error: Qt .* does not exist."));
+
kitData = baseData;
kitData.m_qt = "{qtXX-id}";
empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (!empty.isEmpty())
- return false;
+ QVERIFY(empty.isEmpty());
// Fail if dev is not there:
+ QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Error: Device .* does not exist."));
+
kitData = baseData;
kitData.m_device = "{devXX-id}";
empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (!empty.isEmpty())
- return false;
+ QVERIFY(empty.isEmpty());
// Profile 0:
kitData = baseData;
kitData.m_tcs = tcs;
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (map.count() != 4)
- return false;
- if (!map.contains(VERSION))
- return false;
- if (map.value(VERSION).toInt() != 1)
- return false;
- if (!map.contains(COUNT))
- return false;
- if (map.value(COUNT).toInt() != 1)
- return false;
- if (!map.contains(DEFAULT))
- return false;
- if (map.value(DEFAULT).toString() != "testId")
- return false;
- if (!map.contains("Profile.0"))
- return false;
+ QCOMPARE(map.count(), 4);
+ QVERIFY(map.contains(VERSION));
+ QCOMPARE(map.value(VERSION).toInt(), 1);
+ QVERIFY(map.contains(COUNT));
+ QCOMPARE(map.value(COUNT).toInt(), 1);
+ QVERIFY(map.contains(DEFAULT));
+ QCOMPARE(map.value(DEFAULT).toString(), "testId");
+ QVERIFY(map.contains("Profile.0"));
QVariantMap profile0 = map.value("Profile.0").toMap();
- if (profile0.count() != 6)
- return false;
-
- if (!profile0.contains(ID))
- return false;
- if (profile0.value(ID).toString() != "testId")
- return false;
- if (!profile0.contains(DISPLAYNAME))
- return false;
- if (profile0.value(DISPLAYNAME).toString() != "Test Kit")
- return false;
- if (!profile0.contains(ICON))
- return false;
- if (profile0.value(ICON).toString() != "/tmp/icon.png")
- return false;
- if (!profile0.contains(DATA))
- return false;
- if (profile0.value(DATA).type() != QVariant::Map)
- return false;
- if (!profile0.contains(AUTODETECTED))
- return false;
- if (profile0.value(AUTODETECTED).toBool() != true)
- return false;
- if (!profile0.contains(SDK))
- return false;
- if (profile0.value(SDK).toBool() != true)
- return false;
+ QCOMPARE(profile0.count(), 6);
+ QVERIFY(profile0.contains(ID));
+ QCOMPARE(profile0.value(ID).toString(), "testId");
+ QVERIFY(profile0.contains(DISPLAYNAME));
+ QCOMPARE(profile0.value(DISPLAYNAME).toString(), "Test Kit");
+ QVERIFY(profile0.contains(ICON));
+ QCOMPARE(profile0.value(ICON).toString(), "/tmp/icon.png");
+ QVERIFY(profile0.contains(DATA));
+ QCOMPARE(profile0.value(DATA).type(), QVariant::Map);
+ QVERIFY(profile0.contains(AUTODETECTED));
+ QCOMPARE(profile0.value(AUTODETECTED).toBool(), true);
+ QVERIFY(profile0.contains(SDK));
+ QCOMPARE(profile0.value(SDK).toBool(), true);
QVariantMap data = profile0.value(DATA).toMap();
- if (data.count() != 7)
- return false;
- if (!data.contains(DEBUGGER))
- return false;
- if (data.value(DEBUGGER).type() != QVariant::Map)
- return false;
- if (!data.contains(DEVICE_TYPE))
- return false;
- if (data.value(DEVICE_TYPE).toString() != "Desktop")
- return false;
- if (!data.contains(TOOLCHAIN))
- return false;
- if (!data.contains(QT))
- return false;
- if (data.value(QT).toString() != "SDK.{qt-id}")
- return false;
- if (!data.contains(MKSPEC))
- return false;
- if (data.value(MKSPEC).toString() != "unsupported/mkspec")
- return false;
- if (!data.contains("extraData"))
- return false;
- if (data.value("extraData").toString() != "extraValue")
- return false;
+ QCOMPARE(data.count(), 7);
+ QVERIFY(data.contains(DEBUGGER));
+ QCOMPARE(data.value(DEBUGGER).type(), QVariant::Map);
+ QVERIFY(data.contains(DEVICE_TYPE));
+ QCOMPARE(data.value(DEVICE_TYPE).toString(), "Desktop");
+ QVERIFY(data.contains(TOOLCHAIN));
+ QVERIFY(data.contains(QT));
+ QCOMPARE(data.value(QT).toString(), "SDK.{qt-id}");
+ QVERIFY(data.contains(MKSPEC));
+ QCOMPARE(data.value(MKSPEC).toString(), "unsupported/mkspec");
+ QVERIFY(data.contains("extraData"));
+ QCOMPARE(data.value("extraData").toString(), "extraValue");
QVariantMap tcOutput = data.value(TOOLCHAIN).toMap();
- if (tcOutput.count() != 1)
- return false;
- if (!tcOutput.contains("Cxx"))
- return false;
- if (tcOutput.value("Cxx") != "{tc-id}")
- return false;
+ QCOMPARE(tcOutput.count(), 1);
+ QVERIFY(tcOutput.contains("Cxx"));
+ QCOMPARE(tcOutput.value("Cxx"), "{tc-id}");
// Ignore exist ids:
+ QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Error: Id .* already defined as kit."));
+
kitData = baseData;
kitData.m_displayName = "Test Qt Version X";
kitData.m_icon = "/tmp/icon3.png";
kitData.m_debugger = "/usr/bin/gdb-test3";
kitData.m_tcs = tcs;
QVariantMap result = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (!result.isEmpty())
- return false;
+ QVERIFY(result.isEmpty());
// Profile 1: Make sure name is unique:
kitData = baseData;
@@ -523,100 +506,56 @@ bool AddKitOperation::test() const
kitData.m_tcs = tcs;
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (map.count() != 5)
- return false;
- if (!map.contains(VERSION) )
- return false;
- if (map.value(VERSION).toInt() != 1)
- return false;
- if (!map.contains(COUNT) )
- return false;
- if (map.value(COUNT).toInt() != 2)
- return false;
- if (!map.contains(DEFAULT) )
- return false;
- if (map.value(DEFAULT).toInt() != 0)
- return false;
- if (!map.contains("Profile.0"))
- return false;
- if (!map.contains("Profile.1"))
- return false;
- if (map.value("Profile.0") != profile0)
- return false;
+ QCOMPARE(map.count(), 5);
+ QVERIFY(map.contains(VERSION));
+ QCOMPARE(map.value(VERSION).toInt(), 1);
+ QVERIFY(map.contains(COUNT));
+ QCOMPARE(map.value(COUNT).toInt(), 2);
+ QVERIFY(map.contains(DEFAULT));
+ QCOMPARE(map.value(DEFAULT).toInt(), 0);
+ QVERIFY(map.contains("Profile.0"));
+ QVERIFY(map.contains("Profile.1"));
+ QCOMPARE(map.value("Profile.0"), profile0);
QVariantMap profile1 = map.value("Profile.1").toMap();
- if (profile1.count() != 6)
- return false;
- if (!profile1.contains(ID) )
- return false;
- if (profile1.value(ID).toString() != "testId2")
- return false;
- if (!profile1.contains(DISPLAYNAME) )
- return false;
- if (profile1.value(DISPLAYNAME).toString() != "Test Kit2")
- return false;
- if (!profile1.contains(ICON) )
- return false;
- if (profile1.value(ICON).toString() != "/tmp/icon2.png")
- return false;
- if (!profile1.contains(DATA) )
- return false;
- if (profile1.value(DATA).type() != QVariant::Map)
- return false;
- if (!profile1.contains(AUTODETECTED) )
- return false;
- if (profile1.value(AUTODETECTED).toBool() != true)
- return false;
- if (!profile1.contains(SDK) )
- return false;
- if (profile1.value(SDK).toBool() != true)
- return false;
+ QCOMPARE(profile1.count(), 6);
+ QVERIFY(profile1.contains(ID));
+ QCOMPARE(profile1.value(ID).toString(), "testId2");
+ QVERIFY(profile1.contains(DISPLAYNAME));
+ QCOMPARE(profile1.value(DISPLAYNAME).toString(), "Test Kit2");
+ QVERIFY(profile1.contains(ICON));
+ QCOMPARE(profile1.value(ICON).toString(), "/tmp/icon2.png");
+ QVERIFY(profile1.contains(DATA));
+ QCOMPARE(profile1.value(DATA).type(), QVariant::Map);
+ QVERIFY(profile1.contains(AUTODETECTED));
+ QCOMPARE(profile1.value(AUTODETECTED).toBool(), true);
+ QVERIFY(profile1.contains(SDK));
+ QCOMPARE(profile1.value(SDK).toBool(), true);
data = profile1.value(DATA).toMap();
- if (data.count() != 9)
- return false;
- if (!data.contains(DEBUGGER) )
- return false;
- if (data.value(DEBUGGER).type() != QVariant::Map)
- return false;
- if (!data.contains(DEVICE_TYPE) )
- return false;
- if (data.value(DEVICE_TYPE).toString() != "Desktop")
- return false;
- if (!data.contains(DEVICE_ID) )
- return false;
- if (data.value(DEVICE_ID).toString() != "{dev-id}")
- return false;
- if (!data.contains(SYSROOT) )
- return false;
- if (data.value(SYSROOT).toString() != "/sys/root//")
- return false;
- if (!data.contains(TOOLCHAIN))
- return false;
- if (!data.contains(QT) )
- return false;
- if (data.value(QT).toString() != "SDK.{qt-id}")
- return false;
- if (!data.contains(MKSPEC) )
- return false;
- if (data.value(MKSPEC).toString() != "unsupported/mkspec")
- return false;
- if (!data.contains(ENV) )
- return false;
- if (data.value(ENV).toStringList() != env)
- return false;
- if (!data.contains("extraData") )
- return false;
- if (data.value("extraData").toString() != "extraValue")
- return false;
+ QCOMPARE(data.count(), 9);
+ QVERIFY(data.contains(DEBUGGER));
+ QCOMPARE(data.value(DEBUGGER).type(), QVariant::Map);
+ QVERIFY(data.contains(DEVICE_TYPE));
+ QCOMPARE(data.value(DEVICE_TYPE).toString(), "Desktop");
+ QVERIFY(data.contains(DEVICE_ID));
+ QCOMPARE(data.value(DEVICE_ID).toString(), "{dev-id}");
+ QVERIFY(data.contains(SYSROOT));
+ QCOMPARE(data.value(SYSROOT).toString(), "/sys/root//");
+ QVERIFY(data.contains(TOOLCHAIN));
+ QVERIFY(data.contains(QT));
+ QCOMPARE(data.value(QT).toString(), "SDK.{qt-id}");
+ QVERIFY(data.contains(MKSPEC));
+ QCOMPARE(data.value(MKSPEC).toString(), "unsupported/mkspec");
+ QVERIFY(data.contains(ENV));
+ QCOMPARE(data.value(ENV).toStringList(), env);
+ QVERIFY(data.contains("extraData"));
+ QCOMPARE(data.value("extraData").toString(), "extraValue");
tcOutput = data.value(TOOLCHAIN).toMap();
- if (tcOutput.count() != 1)
- return false;
- if (!tcOutput.contains("Cxx") )
- return false;
- if (tcOutput.value("Cxx") != "{tc-id}")
- return false;
+ QCOMPARE(tcOutput.count(), 1);
+ QVERIFY(tcOutput.contains("Cxx"));
+ QCOMPARE(tcOutput.value("Cxx"), "{tc-id}");
// Profile 2: Test debugger id:
kitData = baseData;
@@ -627,68 +566,38 @@ bool AddKitOperation::test() const
kitData.m_env = env;
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
- if (map.count() != 6)
- return false;
- if (!map.contains(VERSION) )
- return false;
- if (map.value(VERSION).toInt() != 1)
- return false;
- if (!map.contains(COUNT) )
- return false;
- if (map.value(COUNT).toInt() != 3)
- return false;
- if (!map.contains(DEFAULT) )
- return false;
- if (map.value(DEFAULT).toInt() != 0)
- return false;
- if (!map.contains("Profile.0"))
- return false;
- if (!map.contains("Profile.1"))
- return false;
- if (!map.contains("Profile.2"))
- return false;
- if (map.value("Profile.0") != profile0)
- return false;
- if (map.value("Profile.1") != profile1)
- return false;
+ QCOMPARE(map.count(), 6);
+ QVERIFY(map.contains(VERSION));
+ QCOMPARE(map.value(VERSION).toInt(), 1);
+ QVERIFY(map.contains(COUNT));
+ QCOMPARE(map.value(COUNT).toInt(), 3);
+ QVERIFY(map.contains(DEFAULT));
+ QCOMPARE(map.value(DEFAULT).toInt(), 0);
+ QVERIFY(map.contains("Profile.0"));
+ QVERIFY(map.contains("Profile.1"));
+ QVERIFY(map.contains("Profile.2"));
+ QCOMPARE(map.value("Profile.0"), profile0);
+ QCOMPARE(map.value("Profile.1"), profile1);
QVariantMap profile2 = map.value("Profile.2").toMap();
- if (profile2.count() != 6)
- return false;
- if (!profile2.contains(ID) )
- return false;
- if (profile2.value(ID).toString() != "test with debugger Id")
- return false;
- if (!profile2.contains(DISPLAYNAME) )
- return false;
- if (profile2.value(DISPLAYNAME).toString() != "Test debugger Id")
- return false;
- if (!profile2.contains(ICON) )
- return false;
- if (profile2.value(ICON).toString() != "/tmp/icon2.png")
- return false;
- if (!profile2.contains(DATA) )
- return false;
- if (profile2.value(DATA).type() != QVariant::Map)
- return false;
- if (!profile2.contains(AUTODETECTED) )
- return false;
- if (profile2.value(AUTODETECTED).toBool() != true)
- return false;
- if (!profile2.contains(SDK) )
- return false;
- if (profile2.value(SDK).toBool() != true)
- return false;
+ QCOMPARE(profile2.count(), 6);
+ QVERIFY(profile2.contains(ID));
+ QCOMPARE(profile2.value(ID).toString(), "test with debugger Id");
+ QVERIFY(profile2.contains(DISPLAYNAME));
+ QCOMPARE(profile2.value(DISPLAYNAME).toString(), "Test debugger Id");
+ QVERIFY(profile2.contains(ICON));
+ QCOMPARE(profile2.value(ICON).toString(), "/tmp/icon2.png");
+ QVERIFY(profile2.contains(DATA));
+ QCOMPARE(profile2.value(DATA).type(), QVariant::Map);
+ QVERIFY(profile2.contains(AUTODETECTED));
+ QCOMPARE(profile2.value(AUTODETECTED).toBool(), true);
+ QVERIFY(profile2.contains(SDK));
+ QCOMPARE(profile2.value(SDK).toBool(), true);
data = profile2.value(DATA).toMap();
- if (data.count() != 7)
- return false;
- if (!data.contains(DEBUGGER))
- return false;
- if (data.value(DEBUGGER).toString() != "debugger Id")
- return false;
-
- return true;
+ QCOMPARE(data.count(), 7);
+ QVERIFY(data.contains(DEBUGGER));
+ QCOMPARE(data.value(DEBUGGER).toString(), "debugger Id");
}
#endif
@@ -702,9 +611,11 @@ QVariantMap AddKitData::addKit(const QVariantMap &map) const
return AddKitData::addKit(map, tcMap, qtMap, devMap, cmakeMap);
}
-QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
- const QVariantMap &qtMap, const QVariantMap &devMap,
- const QVariantMap &cmakeMap) const
+QVariantMap AddKitData::addKit(const QVariantMap &map,
+ const QVariantMap &tcMap,
+ const QVariantMap &qtMap,
+ const QVariantMap &devMap,
+ const QVariantMap &cmakeMap) const
{
// Sanity check: Make sure autodetection source is not in use already:
const QStringList valueKeys = FindValueOperation::findValue(map, QVariant(m_id));
@@ -716,16 +627,17 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
}
}
if (hasId) {
- std::cerr << "Error: Id " << qPrintable(m_id) << " already defined as kit." << std::endl;
+ qCCritical(addkitlog) << "Error: Id" << qPrintable(m_id) << "already defined as kit.";
return QVariantMap();
}
for (auto i = m_tcs.constBegin(); i != m_tcs.constEnd(); ++i) {
if (!i.value().isEmpty() && !AddToolChainOperation::exists(tcMap, i.value())) {
- const QRegularExpression abiRegExp("^[a-z0-9_]+-[a-z0-9_]+-[a-z0-9_]+-[a-z0-9_]+-(8|16|32|64|128)bit$");
+ const QRegularExpression abiRegExp(
+ "^[a-z0-9_]+-[a-z0-9_]+-[a-z0-9_]+-[a-z0-9_]+-(8|16|32|64|128)bit$");
if (!abiRegExp.match(i.value()).hasMatch()) {
- std::cerr << "Error: Toolchain " << qPrintable(i.value())
- << " for language " << qPrintable(i.key()) << " does not exist." << std::endl;
+ qCCritical(addkitlog) << "Error: Toolchain" << qPrintable(i.value())
+ << "for language" << qPrintable(i.key()) << "does not exist.";
return QVariantMap();
}
}
@@ -735,15 +647,15 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
if (!qtId.isEmpty() && !qtId.startsWith("SDK."))
qtId = QString::fromLatin1("SDK.") + m_qt;
if (!qtId.isEmpty() && !AddQtData::exists(qtMap, qtId)) {
- std::cerr << "Error: Qt " << qPrintable(qtId) << " does not exist." << std::endl;
+ qCCritical(addkitlog) << "Error: Qt" << qPrintable(qtId) << "does not exist.";
return QVariantMap();
}
if (!m_device.isEmpty() && !AddDeviceOperation::exists(devMap, m_device)) {
- std::cerr << "Error: Device " << qPrintable(m_device) << " does not exist." << std::endl;
+ qCCritical(addkitlog) << "Error: Device" << qPrintable(m_device) << "does not exist.";
return QVariantMap();
}
if (!m_buildDevice.isEmpty() && !AddDeviceOperation::exists(devMap, m_buildDevice)) {
- std::cerr << "Error: Device " << qPrintable(m_buildDevice) << " does not exist." << std::endl;
+ qCCritical(addkitlog) << "Error: Device" << qPrintable(m_buildDevice) << "does not exist.";
return QVariantMap();
}
@@ -752,7 +664,7 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
qtId = "-1";
if (!m_cmakeId.isEmpty() && !AddCMakeData::exists(cmakeMap, m_cmakeId)) {
- std::cerr << "Error: CMake tool " << qPrintable(m_cmakeId) << " does not exist." << std::endl;
+ qCCritical(addkitlog) << "Error: CMake tool" << qPrintable(m_cmakeId) << "does not exist.";
return QVariantMap();
}
@@ -760,7 +672,7 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
bool ok;
int count = GetOperation::get(map, COUNT).toInt(&ok);
if (!ok || count < 0) {
- std::cerr << "Error: Count found in kits file seems wrong." << std::endl;
+ qCCritical(addkitlog) << "Error: Count found in kits file seems wrong.";
return QVariantMap();
}
const QString kit = QString::fromLatin1(PREFIX) + QString::number(count);
@@ -784,7 +696,7 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
data << KeyValuePair({kit, DATA, DEBUGGER, DEBUGGER_ENGINE}, QVariant(m_debuggerEngine));
data << KeyValuePair({kit, DATA, DEBUGGER, DEBUGGER_BINARY}, QVariant(m_debugger));
} else {
- data << KeyValuePair({kit, DATA, DEBUGGER }, QVariant(m_debuggerId));
+ data << KeyValuePair({kit, DATA, DEBUGGER}, QVariant(m_debuggerId));
}
}
@@ -795,7 +707,8 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
if (!m_buildDevice.isNull())
data << KeyValuePair({kit, DATA, BUILDDEVICE_ID}, QVariant(m_buildDevice));
if (!m_sysRoot.isNull())
- data << KeyValuePair({kit, DATA, SYSROOT}, Utils::FilePath::fromUserInput(m_sysRoot).toVariant());
+ data << KeyValuePair({kit, DATA, SYSROOT},
+ Utils::FilePath::fromUserInput(m_sysRoot).toVariant());
for (auto i = m_tcs.constBegin(); i != m_tcs.constEnd(); ++i)
data << KeyValuePair({kit, DATA, TOOLCHAIN, i.key()}, QVariant(i.value()));
if (!qtId.isNull())
@@ -824,7 +737,7 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
data << KeyValuePair(COUNT, QVariant(count + 1));
KeyValuePairList qtExtraList;
- foreach (const KeyValuePair &pair, m_extra)
+ for (const KeyValuePair &pair : qAsConst(m_extra))
qtExtraList << KeyValuePair(QStringList() << kit << pair.key, pair.value);
data.append(qtExtraList);
diff --git a/src/tools/sdktool/addkitoperation.h b/src/tools/sdktool/addkitoperation.h
index 3d3f3b8f5fd..c7cd23be30d 100644
--- a/src/tools/sdktool/addkitoperation.h
+++ b/src/tools/sdktool/addkitoperation.h
@@ -73,6 +73,7 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
+
#endif
};
diff --git a/src/tools/sdktool/addqtoperation.cpp b/src/tools/sdktool/addqtoperation.cpp
index 99eb3c78c0d..9a3e8c79496 100644
--- a/src/tools/sdktool/addqtoperation.cpp
+++ b/src/tools/sdktool/addqtoperation.cpp
@@ -35,7 +35,14 @@
#include <utils/filepath.h>
-#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+Q_LOGGING_CATEGORY(log, "qtc.sdktool.operations.addqt", QtWarningMsg)
using namespace Utils;
@@ -87,7 +94,7 @@ bool AddQtOperation::setArguments(const QStringList &args)
if (current == QLatin1String("--id")) {
if (next.isNull()) {
- std::cerr << "Error parsing after --id." << std::endl << std::endl;
+ qCCritical(log) << "Error parsing after --id.";
return false;
}
++i; // skip next;
@@ -97,7 +104,7 @@ bool AddQtOperation::setArguments(const QStringList &args)
if (current == QLatin1String("--name")) {
if (next.isNull()) {
- std::cerr << "Error parsing after --name." << std::endl << std::endl;
+ qCCritical(log) << "Error parsing after --name.";
return false;
}
++i; // skip next;
@@ -107,7 +114,7 @@ bool AddQtOperation::setArguments(const QStringList &args)
if (current == QLatin1String("--qmake")) {
if (next.isNull()) {
- std::cerr << "Error parsing after --qmake." << std::endl << std::endl;
+ qCCritical(log) << "Error parsing after --qmake.";
return false;
}
++i; // skip next;
@@ -117,7 +124,7 @@ bool AddQtOperation::setArguments(const QStringList &args)
if (current == QLatin1String("--type")) {
if (next.isNull()) {
- std::cerr << "Error parsing after --type." << std::endl << std::endl;
+ qCCritical(log) << "Error parsing after --type.";
return false;
}
++i; // skip next;
@@ -127,7 +134,7 @@ bool AddQtOperation::setArguments(const QStringList &args)
if (current == "--abis") {
if (next.isNull()) {
- std::cerr << "Error parsing after --abis." << std::endl << std::endl;
+ qCCritical(log) << "Error parsing after --abis.";
return false;
}
++i; // skip next;
@@ -136,29 +143,29 @@ bool AddQtOperation::setArguments(const QStringList &args)
}
if (next.isNull()) {
- std::cerr << "Unknown parameter: " << qPrintable(current) << std::endl << std::endl;
+ qCCritical(log) << "Unknown parameter: " << qPrintable(current);
return false;
}
++i; // skip next;
KeyValuePair pair(current, next);
if (!pair.value.isValid()) {
- std::cerr << "Error parsing: " << qPrintable(current) << " " << qPrintable(next) << std::endl << std::endl;
+ qCCritical(log) << "Error parsing: " << qPrintable(current) << " " << qPrintable(next);
return false;
}
m_extra << pair;
}
if (m_id.isEmpty())
- std::cerr << "Error no id was passed." << std::endl << std::endl;
+ qCCritical(log) << "Error no id was passed.";
if (m_displayName.isEmpty())
- std::cerr << "Error no display name was passed." << std::endl << std::endl;
+ qCCritical(log) << "Error no display name was passed.";
if (m_qmake.isEmpty())
- std::cerr << "Error no qmake was passed." << std::endl << std::endl;
+ qCCritical(log) << "Error no qmake was passed.";
if (m_type.isEmpty())
- std::cerr << "Error no type was passed." << std::endl << std::endl;
+ qCCritical(log) << "Error no type was passed.";
return !m_id.isEmpty() && !m_displayName.isEmpty() && !m_qmake.isEmpty() && !m_type.isEmpty();
}
@@ -178,93 +185,98 @@ int AddQtOperation::execute() const
}
#ifdef WITH_TESTS
-bool AddQtOperation::test() const
+void AddQtOperation::unittest()
{
- AddQtData qtData;
QVariantMap map = initializeQtVersions();
- if (map.count() != 1
- || !map.contains(QLatin1String(VERSION))
- || map.value(QLatin1String(VERSION)).toInt() != 1)
- return false;
-
-#if defined Q_OS_WIN
- qtData = {"{some-qt-id}", "Test Qt Version", "testType", "/tmp//../tmp/test\\qmake", {},
- {{QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))}}};
-#else
- qtData = {"{some-qt-id}", "Test Qt Version", "testType", "/tmp//../tmp/test/qmake", {},
- {{QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))}}};
-#endif
+ QCOMPARE(map.count(), 1);
+ QVERIFY(map.contains(QLatin1String(VERSION)));
+ QCOMPARE(map.value(QLatin1String(VERSION)).toInt(), 1);
+
+ AddQtData qtData;
+ qtData.m_id = "{some-qt-id}";
+ qtData.m_displayName = "Test Qt Version";
+ qtData.m_type = "testType";
+ qtData.m_qmake = "/tmp//../tmp/test/qmake";
+ qtData.m_abis = QStringList{};
+ qtData.m_extra = {{QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))}};
+
map = qtData.addQt(map);
- if (map.count() != 2
- || !map.contains(QLatin1String(VERSION))
- || map.value(QLatin1String(VERSION)).toInt() != 1
- || !map.contains(QLatin1String("QtVersion.0")))
- return false;
+ QCOMPARE(map.count(), 2);
+ QVERIFY(map.contains(QLatin1String(VERSION)));
+ QVERIFY(map.contains(QLatin1String("QtVersion.0")));
+ QCOMPARE(map.value(QLatin1String(VERSION)).toInt(),1);
QVariantMap version0 = map.value(QLatin1String("QtVersion.0")).toMap();
- if (version0.count() != 8
- || !version0.contains(QLatin1String(ID))
- || version0.value(QLatin1String(ID)).toInt() != -1
- || !version0.contains(QLatin1String(DISPLAYNAME))
- || version0.value(QLatin1String(DISPLAYNAME)).toString() != QLatin1String("Test Qt Version")
- || !version0.contains(QLatin1String(AUTODETECTED))
- || version0.value(QLatin1String(AUTODETECTED)).toBool() != true
- || !version0.contains(QLatin1String(AUTODETECTION_SOURCE))
- || version0.value(QLatin1String(AUTODETECTION_SOURCE)).toString() != QLatin1String("SDK.{some-qt-id}")
- || !version0.contains(QLatin1String(TYPE))
- || version0.value(QLatin1String(TYPE)).toString() != QLatin1String("testType")
- || !version0.contains(QLatin1String(ABIS))
- || version0.value(QLatin1String(ABIS)).toStringList() != QStringList()
- || !version0.contains(QLatin1String(QMAKE))
- || version0.value(QLatin1String(QMAKE)).toString() != QLatin1String("/tmp/test/qmake")
- || !version0.contains(QLatin1String("extraData"))
- || version0.value(QLatin1String("extraData")).toString() != QLatin1String("extraValue"))
- return false;
+ QCOMPARE(version0.count(), 8);
+ QVERIFY(version0.contains(QLatin1String(ID)));
+ QCOMPARE(version0.value(QLatin1String(ID)).toInt(), -1);
+ QVERIFY(version0.contains(QLatin1String(DISPLAYNAME)));
+ QCOMPARE(version0.value(QLatin1String(DISPLAYNAME)).toString(), QLatin1String("Test Qt Version"));
+ QVERIFY(version0.contains(QLatin1String(AUTODETECTED)));
+ QCOMPARE(version0.value(QLatin1String(AUTODETECTED)).toBool(), true);
+ QVERIFY(version0.contains(QLatin1String(AUTODETECTION_SOURCE)));
+ QCOMPARE(version0.value(QLatin1String(AUTODETECTION_SOURCE)).toString(), QLatin1String("SDK.{some-qt-id}"));
+ QVERIFY(version0.contains(QLatin1String(TYPE)));
+ QCOMPARE(version0.value(QLatin1String(TYPE)).toString(), QLatin1String("testType"));
+ QVERIFY(version0.contains(QLatin1String(ABIS)));
+ QCOMPARE(version0.value(QLatin1String(ABIS)).toStringList(), QStringList());
+ QVERIFY(version0.contains(QLatin1String(QMAKE)));
+ QCOMPARE(version0.value(QLatin1String(QMAKE)).toString(), QLatin1String("/tmp/test/qmake"));
+ QVERIFY(version0.contains(QLatin1String("extraData")));
+ QCOMPARE(version0.value(QLatin1String("extraData")).toString(), QLatin1String("extraValue"));
// Ignore existing ids:
- qtData = {"{some-qt-id}", "Test Qt Version2", "testType2", "/tmp/test/qmake2", {},
- {{QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))}}};
+ qtData.m_id = "{some-qt-id}";
+ qtData.m_displayName = "Test Qt Version2";
+ qtData.m_type = "testType2";
+ qtData.m_qmake = "/tmp/test/qmake2";
+ qtData.m_abis = QStringList{};
+ qtData.m_extra = {{QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))}};
+
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Error: Id .* already defined as Qt versions."));
+
QVariantMap result = qtData.addQt(map);
- if (!result.isEmpty())
- return false;
+ QVERIFY(result.isEmpty());
// add 2nd Qt version:
- qtData = {"testId2", "Test Qt Version", "testType3", "/tmp/test/qmake2", {},
- {{QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))}}};
+ qtData.m_id = "testId2";
+ qtData.m_displayName = "Test Qt Version";
+ qtData.m_type = "testType3";
+ qtData.m_qmake = "/tmp/test/qmake2";
+ qtData.m_abis = QStringList{};
+ qtData.m_extra = {{QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))}};
+
map = qtData.addQt(map);
- if (map.count() != 3
- || !map.contains(QLatin1String(VERSION))
- || map.value(QLatin1String(VERSION)).toInt() != 1
- || !map.contains(QLatin1String("QtVersion.0"))
- || !map.contains(QLatin1String("QtVersion.1")))
- return false;
- if (map.value(QLatin1String("QtVersion.0")) != version0)
- return false;
+ QCOMPARE(map.count(), 3);
+ QVERIFY(map.contains(QLatin1String(VERSION)));
+ QCOMPARE(map.value(QLatin1String(VERSION)).toInt(), 1);
+ QVERIFY(map.contains(QLatin1String("QtVersion.0")));
+ QVERIFY(map.contains(QLatin1String("QtVersion.1")));
+
+ QCOMPARE(map.value(QLatin1String("QtVersion.0")), version0);
QVariantMap version1 = map.value(QLatin1String("QtVersion.1")).toMap();
- if (version1.count() != 8
- || !version1.contains(QLatin1String(ID))
- || version1.value(QLatin1String(ID)).toInt() != -1
- || !version1.contains(QLatin1String(DISPLAYNAME))
- || version1.value(QLatin1String(DISPLAYNAME)).toString() != QLatin1String("Test Qt Version")
- || !version1.contains(QLatin1String(AUTODETECTED))
- || version1.value(QLatin1String(AUTODETECTED)).toBool() != true
- || !version1.contains(QLatin1String(AUTODETECTION_SOURCE))
- || version1.value(QLatin1String(AUTODETECTION_SOURCE)).toString() != QLatin1String("SDK.testId2")
- || !version1.contains(QLatin1String(TYPE))
- || version1.value(QLatin1String(TYPE)).toString() != QLatin1String("testType3")
- || !version1.contains(QLatin1String(ABIS))
- || version1.value(QLatin1String(ABIS)).toStringList() != QStringList()
- || !version1.contains(QLatin1String(QMAKE))
- || version1.value(QLatin1String(QMAKE)).toString() != QLatin1String("/tmp/test/qmake2")
- || !version1.contains(QLatin1String("extraData"))
- || version1.value(QLatin1String("extraData")).toString() != QLatin1String("extraValue"))
- return false;
-
- return true;
+ QCOMPARE(version1.count(), 8);
+ QVERIFY(version1.contains(QLatin1String(ID)));
+ QCOMPARE(version1.value(QLatin1String(ID)).toInt(), -1);
+ QVERIFY(version1.contains(QLatin1String(DISPLAYNAME)));
+ QCOMPARE(version1.value(QLatin1String(DISPLAYNAME)).toString(), QLatin1String("Test Qt Version"));
+ QVERIFY(version1.contains(QLatin1String(AUTODETECTED)));
+ QCOMPARE(version1.value(QLatin1String(AUTODETECTED)).toBool(), true);
+ QVERIFY(version1.contains(QLatin1String(AUTODETECTION_SOURCE)));
+ QCOMPARE(version1.value(QLatin1String(AUTODETECTION_SOURCE)).toString(), QLatin1String("SDK.testId2"));
+ QVERIFY(version1.contains(QLatin1String(TYPE)));
+ QCOMPARE(version1.value(QLatin1String(TYPE)).toString(), QLatin1String("testType3"));
+ QVERIFY(version1.contains(QLatin1String(ABIS)));
+ QCOMPARE(version1.value(QLatin1String(ABIS)).toStringList(), QStringList());
+ QVERIFY(version1.contains(QLatin1String(QMAKE)));
+ QCOMPARE(version1.value(QLatin1String(QMAKE)).toString(), QLatin1String("/tmp/test/qmake2"));
+ QVERIFY(version1.contains(QLatin1String("extraData")));
+ QCOMPARE(version1.value(QLatin1String("extraData")).toString(), QLatin1String("extraValue"));
}
#endif
@@ -274,7 +286,7 @@ QVariantMap AddQtData::addQt(const QVariantMap &map) const
// Sanity check: Make sure autodetection source is not in use already:
if (exists(map, sdkId)) {
- std::cerr << "Error: Id " << qPrintable(m_id) << " already defined as Qt versions." << std::endl;
+ qCCritical(log) << "Error: Id" << qPrintable(m_id) << "already defined as Qt versions.";
return QVariantMap();
}
@@ -306,7 +318,7 @@ QVariantMap AddQtData::addQt(const QVariantMap &map) const
data << KeyValuePair(QStringList() << qt << ABIS, QVariant(m_abis));
KeyValuePairList qtExtraList;
- foreach (const KeyValuePair &pair, m_extra)
+ for (const KeyValuePair &pair : qAsConst(m_extra))
qtExtraList << KeyValuePair(QStringList() << qt << pair.key, pair.value);
data.append(qtExtraList);
@@ -331,8 +343,8 @@ bool AddQtData::exists(const QVariantMap &map, const QString &id)
QString sdkId = extendId(id);
// Sanity check: Make sure autodetection source is not in use already:
- QStringList valueKeys = FindValueOperation::findValue(map, sdkId);
- foreach (const QString &k, valueKeys) {
+ const QStringList valueKeys = FindValueOperation::findValue(map, sdkId);
+ for (const QString &k : valueKeys) {
if (k.endsWith(QString(QLatin1Char('/')) + QLatin1String(AUTODETECTION_SOURCE)))
return true;
}
diff --git a/src/tools/sdktool/addqtoperation.h b/src/tools/sdktool/addqtoperation.h
index d7269e32454..4f137431a0e 100644
--- a/src/tools/sdktool/addqtoperation.h
+++ b/src/tools/sdktool/addqtoperation.h
@@ -55,6 +55,8 @@ private:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+public:
+ static void unittest();
+ // TODO: Remove
#endif
};
diff --git a/src/tools/sdktool/addtoolchainoperation.cpp b/src/tools/sdktool/addtoolchainoperation.cpp
index aec304b647e..f5ee2c51f49 100644
--- a/src/tools/sdktool/addtoolchainoperation.cpp
+++ b/src/tools/sdktool/addtoolchainoperation.cpp
@@ -35,6 +35,15 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+Q_LOGGING_CATEGORY(addtoolchainlog, "qtc.sdktool.operations.addtoolchain", QtWarningMsg)
+
// ToolChain file stuff:
const char COUNT[] = "ToolChain.Count";
const char PREFIX[] = "ToolChain.";
@@ -64,13 +73,13 @@ QString AddToolChainOperation::helpText() const
QString AddToolChainOperation::argumentsHelpText() const
{
return QString(
- " --id <ID> id of the new tool chain (required).\n"
- " --language <ID> input language id of the new tool chain (required).\n"
- " --name <NAME> display name of the new tool chain (required).\n"
- " --path <PATH> path to the compiler (required).\n"
- " --abi <ABI STRING> ABI of the compiler (required).\n"
- " --supportedAbis <ABI STRING>,<ABI STRING> list of ABIs supported by the compiler.\n"
- " <KEY> <TYPE:VALUE> extra key value pairs\n");
+ " --id <ID> id of the new tool chain (required).\n"
+ " --language <ID> input language id of the new tool chain (required).\n"
+ " --name <NAME> display name of the new tool chain (required).\n"
+ " --path <PATH> path to the compiler (required).\n"
+ " --abi <ABI STRING> ABI of the compiler (required).\n"
+ " --supportedAbis <ABI STRING>,<ABI STRING> list of ABIs supported by the compiler.\n"
+ " <KEY> <TYPE:VALUE> extra key value pairs\n");
}
bool AddToolChainOperation::setArguments(const QStringList &args)
@@ -80,7 +89,9 @@ bool AddToolChainOperation::setArguments(const QStringList &args)
const QString next = ((i + 1) < args.count()) ? args.at(i + 1) : QString();
if (next.isNull() && current.startsWith("--")) {
- std::cerr << "No parameter for option '" << qPrintable(current) << "' given." << std::endl << std::endl;
+ std::cerr << "No parameter for option '" << qPrintable(current) << "' given."
+ << std::endl
+ << std::endl;
return false;
}
@@ -149,7 +160,8 @@ bool AddToolChainOperation::setArguments(const QStringList &args)
if (m_targetAbi.isEmpty())
std::cerr << "No target abi given for tool chain." << std::endl;
- return !m_id.isEmpty() && !m_displayName.isEmpty() && !m_path.isEmpty() && !m_targetAbi.isEmpty();
+ return !m_id.isEmpty() && !m_displayName.isEmpty() && !m_path.isEmpty()
+ && !m_targetAbi.isEmpty();
}
int AddToolChainOperation::execute() const
@@ -166,66 +178,87 @@ int AddToolChainOperation::execute() const
}
#ifdef WITH_TESTS
-bool AddToolChainOperation::test() const
+void AddToolChainOperation::unittest()
{
QVariantMap map = initializeToolChains();
// Add toolchain:
- map = AddToolChainData{"testId", "langId", "name", "/tmp/test", "test-abi", "test-abi,test-abi2",
- {{"ExtraKey", QVariant("ExtraValue")}}}.addToolChain(map);
- if (map.value(COUNT).toInt() != 1
- || !map.contains(QString::fromLatin1(PREFIX) + '0'))
- return false;
+ AddToolChainData d;
+ d.m_id = "testId";
+ d.m_languageId = "langId";
+ d.m_displayName = "name";
+ d.m_path = "/tmp/test";
+ d.m_targetAbi = "test-abi";
+ d.m_supportedAbis = "test-abi,test-abi2";
+ d.m_extra = {{"ExtraKey", QVariant("ExtraValue")}};
+
+ map = d.addToolChain(map);
+ QCOMPARE(map.value(COUNT).toInt(), 1);
+ QVERIFY(map.contains(QString::fromLatin1(PREFIX) + '0'));
+
QVariantMap tcData = map.value(QString::fromLatin1(PREFIX) + '0').toMap();
- if (tcData.count() != 8
- || tcData.value(ID).toString() != "testId"
- || tcData.value(LANGUAGE_KEY_V2).toString() != "langId"
- || tcData.value(DISPLAYNAME).toString() != "name"
- || tcData.value(AUTODETECTED).toBool() != true
- || tcData.value(PATH).toString() != "/tmp/test"
- || tcData.value(TARGET_ABI).toString() != "test-abi"
- || tcData.value(SUPPORTED_ABIS).toList().count() != 2
- || tcData.value("ExtraKey").toString() != "ExtraValue")
- return false;
+ QCOMPARE(tcData.count(), 8);
+ QCOMPARE(tcData.value(ID).toString(), "testId");
+ QCOMPARE(tcData.value(LANGUAGE_KEY_V2).toString(), "langId");
+ QCOMPARE(tcData.value(DISPLAYNAME).toString(), "name");
+ QCOMPARE(tcData.value(AUTODETECTED).toBool(), true);
+ QCOMPARE(tcData.value(PATH).toString(), "/tmp/test");
+ QCOMPARE(tcData.value(TARGET_ABI).toString(), "test-abi");
+ QCOMPARE(tcData.value(SUPPORTED_ABIS).toList().count(), 2);
+ QCOMPARE(tcData.value("ExtraKey").toString(), "ExtraValue");
// Ignore same Id:
- QVariantMap unchanged = AddToolChainData{"testId", "langId", "name2", "/tmp/test2", "test-abi2",
- "test-abi2,test-abi3",
- {{"ExtraKey", QVariant("ExtraValue2")}}}.addToolChain(map);
- if (!unchanged.isEmpty())
- return false;
+ AddToolChainData ud;
+ ud.m_id = "testId";
+ ud.m_languageId = "langId";
+ ud.m_displayName = "name2";
+ ud.m_path = "/tmp/test2";
+ ud.m_targetAbi = "test-abi2";
+ ud.m_supportedAbis = "test-abi2,test-abi3";
+ ud.m_extra = {{"ExtraKey", QVariant("ExtraValue")}};
+
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Error: Id .* already defined for tool chains."));
+
+ QVariantMap unchanged = ud.addToolChain(map);
+ QVERIFY(unchanged.isEmpty());
// add 2nd tool chain:
- map = AddToolChainData{"{some-tc-id}", "langId2", "name", "/tmp/test", "test-abi", "test-abi,test-abi2",
- {{"ExtraKey", QVariant("ExtraValue")}}}.addToolChain(map);
- if (map.value(COUNT).toInt() != 2
- || !map.contains(QString::fromLatin1(PREFIX) + '0')
- || !map.contains(QString::fromLatin1(PREFIX) + '1'))
- return false;
+ AddToolChainData d2;
+ d2.m_id = "{some-tc-id}";
+ d2.m_languageId = "langId2";
+ d2.m_displayName = "name";
+ d2.m_path = "/tmp/test";
+ d2.m_targetAbi = "test-abi";
+ d2.m_supportedAbis = "test-abi,test-abi2";
+ d2.m_extra = {{"ExtraKey", QVariant("ExtraValue")}};
+
+ map = d2.addToolChain(map);
+ QCOMPARE(map.value(COUNT).toInt(), 2);
+ QVERIFY(map.contains(QString::fromLatin1(PREFIX) + '0'));
+ QVERIFY(map.contains(QString::fromLatin1(PREFIX) + '1'));
+
tcData = map.value(QString::fromLatin1(PREFIX) + '0').toMap();
- if (tcData.count() != 8
- || tcData.value(ID).toString() != "testId"
- || tcData.value(LANGUAGE_KEY_V2).toString() != "langId"
- || tcData.value(DISPLAYNAME).toString() != "name"
- || tcData.value(AUTODETECTED).toBool() != true
- || tcData.value(PATH).toString() != "/tmp/test"
- || tcData.value(TARGET_ABI).toString() != "test-abi"
- || tcData.value(SUPPORTED_ABIS).toList().count() != 2
- || tcData.value("ExtraKey").toString() != "ExtraValue")
- return false;
- tcData = map.value(QString::fromLatin1(PREFIX) + '1').toMap();
- if (tcData.count() != 8
- || tcData.value(ID).toString() != "{some-tc-id}"
- || tcData.value(LANGUAGE_KEY_V2).toString() != "langId2"
- || tcData.value(DISPLAYNAME).toString() != "name"
- || tcData.value(AUTODETECTED).toBool() != true
- || tcData.value(PATH).toString() != "/tmp/test"
- || tcData.value(TARGET_ABI).toString() != "test-abi"
- || tcData.value(SUPPORTED_ABIS).toList().count() != 2
- || tcData.value("ExtraKey").toString() != "ExtraValue")
- return false;
+ QCOMPARE(tcData.count(), 8);
+ QCOMPARE(tcData.value(ID).toString(), "testId");
+ QCOMPARE(tcData.value(LANGUAGE_KEY_V2).toString(), "langId");
+ QCOMPARE(tcData.value(DISPLAYNAME).toString(), "name");
+ QVERIFY(tcData.value(AUTODETECTED).toBool());
+ QCOMPARE(tcData.value(PATH).toString(), "/tmp/test");
+ QCOMPARE(tcData.value(TARGET_ABI).toString(), "test-abi");
+ QCOMPARE(tcData.value(SUPPORTED_ABIS).toList().count(), 2);
+ QCOMPARE(tcData.value("ExtraKey").toString(), "ExtraValue");
- return true;
+ tcData = map.value(QString::fromLatin1(PREFIX) + '1').toMap();
+ QCOMPARE(tcData.count(), 8);
+ QCOMPARE(tcData.value(ID).toString(), "{some-tc-id}");
+ QCOMPARE(tcData.value(LANGUAGE_KEY_V2).toString(), "langId2");
+ QCOMPARE(tcData.value(DISPLAYNAME).toString(), "name");
+ QVERIFY(tcData.value(AUTODETECTED).toBool());
+ QCOMPARE(tcData.value(PATH).toString(), "/tmp/test");
+ QCOMPARE(tcData.value(TARGET_ABI).toString(), "test-abi");
+ QCOMPARE(tcData.value(SUPPORTED_ABIS).toList().count(), 2);
+ QCOMPARE(tcData.value("ExtraKey").toString(), "ExtraValue");
}
#endif
@@ -233,7 +266,8 @@ QVariantMap AddToolChainData::addToolChain(const QVariantMap &map) const
{
// Sanity check: Does the Id already exist?
if (exists(map, m_id)) {
- std::cerr << "Error: Id " << qPrintable(m_id) << " already defined for tool chains." << std::endl;
+ qCCritical(addtoolchainlog)
+ << "Error: Id" << qPrintable(m_id) << "already defined for tool chains.";
return QVariantMap();
}
@@ -241,7 +275,7 @@ QVariantMap AddToolChainData::addToolChain(const QVariantMap &map) const
bool ok;
int count = GetOperation::get(map, COUNT).toInt(&ok);
if (!ok || count < 0) {
- std::cerr << "Error: Count found in toolchains file seems wrong." << std::endl;
+ qCCritical(addtoolchainlog) << "Error: Count found in toolchains file seems wrong.";
return QVariantMap();
}
@@ -261,9 +295,9 @@ QVariantMap AddToolChainData::addToolChain(const QVariantMap &map) const
} else if (m_languageId == "1" || m_languageId == "C") {
newLang = "C";
} else if (ok) {
- std::cerr << "Error: Language ID must be 1 for C, 2 for Cxx "
- << "or a string like \"C\", \"Cxx\", \"Nim\" (was \""
- << qPrintable(m_languageId) << "\")" << std::endl;
+ qCCritical(addtoolchainlog) << "Error: Language ID must be 1 for C, 2 for Cxx "
+ << "or a string like \"C\", \"Cxx\", \"Nim\" (was \""
+ << qPrintable(m_languageId) << "\")";
return {};
} else if (!ok) {
newLang = m_languageId;
@@ -274,12 +308,12 @@ QVariantMap AddToolChainData::addToolChain(const QVariantMap &map) const
data << KeyValuePair({tc, PATH}, Utils::FilePath::fromUserInput(m_path).toVariant());
data << KeyValuePair({tc, TARGET_ABI}, QVariant(m_targetAbi));
QVariantList abis;
- QStringList abiStrings = m_supportedAbis.split(',');
- foreach (const QString &s, abiStrings)
+ const QStringList abiStrings = m_supportedAbis.split(',');
+ for (const QString &s : abiStrings)
abis << QVariant(s);
data << KeyValuePair({tc, SUPPORTED_ABIS}, QVariant(abis));
KeyValuePairList tcExtraList;
- foreach (const KeyValuePair &pair, m_extra)
+ for (const KeyValuePair &pair : qAsConst(m_extra))
tcExtraList << KeyValuePair(QStringList({tc}) << pair.key, pair.value);
data.append(tcExtraList);
data << KeyValuePair(COUNT, QVariant(count + 1));
@@ -301,7 +335,7 @@ bool AddToolChainData::exists(const QVariantMap &map, const QString &id)
// support old settings using QByteArray for id's
valueKeys.append(FindValueOperation::findValue(map, id.toUtf8()));
- foreach (const QString &k, valueKeys) {
+ for (const QString &k : qAsConst(valueKeys)) {
if (k.endsWith(QString('/') + ID)) {
return true;
}
diff --git a/src/tools/sdktool/addtoolchainoperation.h b/src/tools/sdktool/addtoolchainoperation.h
index 5e6ac39a7c2..e5eeca41aac 100644
--- a/src/tools/sdktool/addtoolchainoperation.h
+++ b/src/tools/sdktool/addtoolchainoperation.h
@@ -58,6 +58,7 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
+
#endif
};
diff --git a/src/tools/sdktool/addvalueoperation.cpp b/src/tools/sdktool/addvalueoperation.cpp
index a604409f611..65bc5adc15d 100644
--- a/src/tools/sdktool/addvalueoperation.cpp
+++ b/src/tools/sdktool/addvalueoperation.cpp
@@ -33,6 +33,15 @@
#include <iomanip>
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+Q_LOGGING_CATEGORY(addvaluelog, "qtc.sdktool.operations.addvalue", QtWarningMsg)
+
namespace {
constexpr auto SUCCESS = 0;
constexpr auto FAILURE = !SUCCESS;
@@ -111,7 +120,7 @@ int AddValueOperation::execute() const
}
#ifdef WITH_TESTS
-bool AddValueOperation::test() const
+void AddValueOperation::unittest()
{
QVariantList testDataList;
testDataList.append(QLatin1String("Some String"));
@@ -127,40 +136,44 @@ bool AddValueOperation::test() const
QVariantMap testMap;
// add to empty map
- bool result = AddValueData{"some key", valueList}.appendListToMap(testMap);
+ AddValueData d;
+ d.m_key = "some key";
+ d.m_values = valueList;
- if (result)
- return false;
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Error: Could not retrieve value for key .*."));
+
+ QVERIFY(!d.appendListToMap(testMap));
testMap.insert(QLatin1String("someEmptyThing"), QVariantMap());
testMap.insert(QLatin1String("aKey"), "withAString");
// append to a value
- result = AddValueData{"aKey", valueList}.appendListToMap(testMap);
+ d.m_key = "aKey";
- if (result)
- return false;
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Error: Data stored in .* is not a QVariantList."));
+
+ QVERIFY(!d.appendListToMap(testMap));
testMap = AddKeysData{testKvpList}.addKeys(testMap);
// quick sanity check
- if (testMap.count() != 3 && testDataList.count() != 2 && testKvpList.count() != 3)
- return false;
+ QCOMPARE(testMap.count(), 3);
+ QCOMPARE(testDataList.count(), 2);
+ QCOMPARE(testKvpList.count(), 3);
// successful adding of values
- result = AddValueData{"test/bar", valueList}.appendListToMap(testMap);
- if (!result)
- return false;
+ d.m_key = "test/bar";
+ QVERIFY(d.appendListToMap(testMap));
const auto newList = qvariant_cast<QVariantList>(GetOperation::get(testMap, "test/bar"));
- if (newList.count() != (testDataList.count() + valueList.count()))
- return false;
+ QCOMPARE(newList.count(), (testDataList.count() + valueList.count()));
- if (!newList.contains(1860) || !newList.contains(QString("Some String"))
- || !newList.contains("ELIL") || !newList.contains(-1))
- return false;
-
- return true;
+ QVERIFY(newList.contains(1860));
+ QVERIFY(newList.contains(QString("Some String")));
+ QVERIFY(newList.contains("ELIL"));
+ QVERIFY(newList.contains(-1));
}
#endif
@@ -169,14 +182,14 @@ bool AddValueData::appendListToMap(QVariantMap &map) const
const QVariant data = GetOperation::get(map, m_key);
if (!data.isValid() || data.isNull()) {
- std::cerr << "Error: Could not retrieve value for key " << std::quoted(m_key.toStdString())
- << std::endl;
+ qCCritical(addvaluelog) << "Error: Could not retrieve value for key"
+ << m_key;
return false;
}
if (data.type() != QVariant::List) {
- std::cerr << "Error: Data stored in " << std::quoted(m_key.toStdString())
- << " is not a QVariantList." << std::endl;
+ qCCritical(addvaluelog) << "Error: Data stored in" << m_key
+ << "is not a QVariantList.";
return false;
}
diff --git a/src/tools/sdktool/addvalueoperation.h b/src/tools/sdktool/addvalueoperation.h
index df19f1f2357..010f5b7d67b 100644
--- a/src/tools/sdktool/addvalueoperation.h
+++ b/src/tools/sdktool/addvalueoperation.h
@@ -49,7 +49,7 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
private:
diff --git a/src/tools/sdktool/findkeyoperation.cpp b/src/tools/sdktool/findkeyoperation.cpp
index 58d3b31ed24..806e4e164b2 100644
--- a/src/tools/sdktool/findkeyoperation.cpp
+++ b/src/tools/sdktool/findkeyoperation.cpp
@@ -27,6 +27,15 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(findkeylog, "qtc.sdktool.operations.findkey", QtWarningMsg)
+
+
QString FindKeyOperation::name() const
{
return QLatin1String("findKey");
@@ -57,9 +66,9 @@ bool FindKeyOperation::setArguments(const QStringList &args)
}
if (m_file.isEmpty())
- std::cerr << "No file given." << std::endl << std::endl;
+ qCCritical(findkeylog) << "No file given.";
if (m_keys.isEmpty())
- std::cerr << "No keys given." << std::endl << std::endl;
+ qCCritical(findkeylog) << "No keys given.";
return (!m_file.isEmpty() && !m_keys.isEmpty());
}
@@ -69,17 +78,18 @@ int FindKeyOperation::execute() const
Q_ASSERT(!m_keys.isEmpty());
QVariantMap map = load(m_file);
- foreach (const QString &k, m_keys) {
+ for (const auto &k : m_keys) {
const QStringList result = findKey(map, k);
- foreach (const QString &r, result)
+ for (const auto &r: result) {
std::cout << qPrintable(r) << std::endl;
+ }
}
return 0;
}
#ifdef WITH_TESTS
-bool FindKeyOperation::test() const
+void FindKeyOperation::unittest()
{
QVariantMap testMap;
QVariantMap subKeys;
@@ -108,26 +118,20 @@ bool FindKeyOperation::test() const
QStringList result;
result = findKey(testMap, QLatin1String("missing"));
- if (!result.isEmpty())
- return false;
+ QVERIFY(result.isEmpty());
result = findKey(testMap, QLatin1String("testint"));
- if (result.count() != 2
- || !result.contains(QLatin1String("testint"))
- || !result.contains(QLatin1String("subkeys/subsubkeys/testint")))
- return false;
+ QCOMPARE(result.count(), 2);
+ QVERIFY(result.contains(QLatin1String("testint")));
+ QVERIFY(result.contains(QLatin1String("subkeys/subsubkeys/testint")));
result = findKey(testMap, QLatin1String("testbool"));
- if (result.count() != 2
- || !result.contains(QLatin1String("testbool")))
- return false;
+ QCOMPARE(result.count(), 2);
+ QVERIFY(result.contains(QLatin1String("testbool")));
result = findKey(testMap, QLatin1String("findMe"));
- if (result.count() != 1
- || !result.contains(QLatin1String("aList[2][1]/findMe")))
- return false;
-
- return true;
+ QCOMPARE(result.count(), 1);
+ QVERIFY(result.contains(QLatin1String("aList[2][1]/findMe")));
}
#endif
diff --git a/src/tools/sdktool/findkeyoperation.h b/src/tools/sdktool/findkeyoperation.h
index e8138fa7865..1d9e4fba8b5 100644
--- a/src/tools/sdktool/findkeyoperation.h
+++ b/src/tools/sdktool/findkeyoperation.h
@@ -39,11 +39,11 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
+
static QStringList findKey(const QVariant &in, const QString &key,
const QString &prefix = QString());
-
private:
QString m_file;
QStringList m_keys;
diff --git a/src/tools/sdktool/findvalueoperation.cpp b/src/tools/sdktool/findvalueoperation.cpp
index 2ed856c608b..51d1139454a 100644
--- a/src/tools/sdktool/findvalueoperation.cpp
+++ b/src/tools/sdktool/findvalueoperation.cpp
@@ -27,6 +27,14 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(findvaluelog, "qtc.sdktool.operations.findvalue", QtWarningMsg)
+
QString FindValueOperation::name() const
{
return QLatin1String("find");
@@ -55,16 +63,16 @@ bool FindValueOperation::setArguments(const QStringList &args)
QVariant v = valueFromString(current);
if (!v.isValid()) {
- std::cerr << "Value for key '" << qPrintable(current) << "' is not valid." << std::endl << std::endl;
+ qCCritical(findvaluelog) << "Value for key '" << qPrintable(current) << "' is not valid.";
return false;
}
m_values << v;
}
if (m_file.isEmpty())
- std::cerr << "No file given." << std::endl << std::endl;
+ qCCritical(findvaluelog) << "No file given.";
if (m_values.isEmpty())
- std::cerr << "No values given." << std::endl << std::endl;
+ qCCritical(findvaluelog) << "No values given.";
return (!m_file.isEmpty() && !m_values.isEmpty());
}
@@ -74,9 +82,9 @@ int FindValueOperation::execute() const
Q_ASSERT(!m_values.isEmpty());
QVariantMap map = load(m_file);
- foreach (const QVariant &v, m_values) {
+ for (const QVariant &v : qAsConst(m_values)) {
const QStringList result = findValue(map, v);
- foreach (const QString &r, result)
+ for (const QString &r : result)
std::cout << qPrintable(r) << std::endl;
}
@@ -84,7 +92,7 @@ int FindValueOperation::execute() const
}
#ifdef WITH_TESTS
-bool FindValueOperation::test() const
+void FindValueOperation::unittest()
{
QVariantMap testMap;
QVariantMap subKeys;
@@ -114,26 +122,21 @@ bool FindValueOperation::test() const
QStringList result;
result = findValue(testMap, QVariant(23));
- if (result.count() != 1
- || !result.contains(QLatin1String("testint")))
- return false;
+ QCOMPARE(result.count(), 1);
+ QVERIFY(result.contains(QLatin1String("testint")));
result = findValue(testMap, QVariant(53));
- if (result.count() != 2
- || !result.contains(QLatin1String("subkeys/subsubkeys/testint2"))
- || !result.contains(QLatin1String("subkeys/otherint")))
- return false;
+ QCOMPARE(result.count(), 2);
+
+ QVERIFY(result.contains(QLatin1String("subkeys/subsubkeys/testint2")));
+ QVERIFY(result.contains(QLatin1String("subkeys/otherint")));
result = findValue(testMap, QVariant(23456));
- if (!result.isEmpty())
- return false;
+ QVERIFY(result.isEmpty());
result = findValue(testMap, QVariant(QString::fromLatin1("FindInList")));
- if (result.count() != 1
- || !result.contains(QLatin1String("aList[2][1]/findMe")))
- return false;
-
- return true;
+ QCOMPARE(result.count(), 1);
+ QVERIFY(result.contains(QLatin1String("aList[2][1]/findMe")));
}
#endif
diff --git a/src/tools/sdktool/findvalueoperation.h b/src/tools/sdktool/findvalueoperation.h
index f53dae125b0..f441a3ab820 100644
--- a/src/tools/sdktool/findvalueoperation.h
+++ b/src/tools/sdktool/findvalueoperation.h
@@ -39,7 +39,7 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
static QStringList findValue(const QVariant &in, const QVariant &value,
diff --git a/src/tools/sdktool/getoperation.cpp b/src/tools/sdktool/getoperation.cpp
index fb15d42142e..5f8692f756e 100644
--- a/src/tools/sdktool/getoperation.cpp
+++ b/src/tools/sdktool/getoperation.cpp
@@ -27,6 +27,14 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(getlog, "qtc.sdktool.operations.get", QtWarningMsg)
+
QString GetOperation::name() const
{
return QLatin1String("get");
@@ -52,9 +60,9 @@ bool GetOperation::setArguments(const QStringList &args)
m_file = m_keys.takeFirst();
if (m_file.isEmpty())
- std::cerr << "No file given." << std::endl << std::endl;
+ qCCritical(getlog) << "No file given.";
if (m_keys.isEmpty())
- std::cerr << "No keys given." << std::endl << std::endl;
+ qCCritical(getlog) << "No keys given.";
return !m_file.isEmpty() && !m_keys.isEmpty();
}
@@ -83,10 +91,10 @@ static QString toString(const QVariant &variant, int indentation = 0)
return res;
}
case QVariant::List: {
- QVariantList list = variant.toList();
+ const QVariantList list = variant.toList();
QString res;
int counter = 0;
- foreach (const QVariant &item, list)
+ for (const QVariant &item : list)
res += indent + QString::number(counter++) + QLatin1String(":\n") + toString(item, indentation + 1);
return res;
}
@@ -100,7 +108,7 @@ int GetOperation::execute() const
Q_ASSERT(!m_keys.isEmpty());
QVariantMap map = load(m_file);
- foreach (const QString &key, m_keys) {
+ for (const QString &key : qAsConst(m_keys)) {
const QVariant result = get(map, key);
if (!result.isValid())
std::cout << "<invalid>" << std::endl;
@@ -112,7 +120,7 @@ int GetOperation::execute() const
}
#ifdef WITH_TESTS
-bool GetOperation::test() const
+void GetOperation::unittest()
{
QVariantMap testMap;
QVariantMap subKeys;
@@ -127,22 +135,16 @@ bool GetOperation::test() const
QVariant result;
result = get(testMap, QLatin1String("testint"));
- if (result.toString() != QLatin1String("23"))
- return false;
+ QCOMPARE(result.toString(), QLatin1String("23"));
result = get(testMap, QLatin1String("subkeys/testbool"));
- if (result.toString() != QLatin1String("true"))
- return false;
+ QCOMPARE(result.toString(), QLatin1String("true"));
result = get(testMap, QLatin1String("subkeys/subsubkeys"));
- if (result.type() != QVariant::Map)
- return false;
+ QCOMPARE(result.type(), QVariant::Map);
result = get(testMap, QLatin1String("nonexistant"));
- if (result.isValid())
- return false;
-
- return true;
+ QVERIFY(!result.isValid());
}
#endif
diff --git a/src/tools/sdktool/getoperation.h b/src/tools/sdktool/getoperation.h
index 56b7970ca35..3aab4ceb86f 100644
--- a/src/tools/sdktool/getoperation.h
+++ b/src/tools/sdktool/getoperation.h
@@ -39,11 +39,10 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
static QVariant get(const QVariantMap &map, const QString &key);
-
private:
QStringList m_keys;
QString m_file;
diff --git a/src/tools/sdktool/main.cpp b/src/tools/sdktool/main.cpp
index 1997604270d..7dbb9ff9277 100644
--- a/src/tools/sdktool/main.cpp
+++ b/src/tools/sdktool/main.cpp
@@ -214,21 +214,6 @@ int main(int argc, char *argv[])
operations.emplace_back(std::make_unique<FindKeyOperation>());
operations.emplace_back(std::make_unique<FindValueOperation>());
-#ifdef WITH_TESTS
- if (argc == 2 && !strcmp(argv[1], "-test")) {
- std::cerr << std::endl << std::endl << "Starting tests..." << std::endl;
- int res = 0;
- for (const std::unique_ptr<Operation> &o : operations) {
- if (!o->test()) {
- std::cerr << "!!!! Test failed for: " << qPrintable(o->name()) << " !!!!" << std::endl;
- ++res;
- }
- }
- std::cerr << "Tests done." << std::endl << std::endl;
- return res;
- }
-#endif
-
int result = parseArguments(a.arguments(), &settings, operations);
return settings.operation ? settings.operation->execute() : result;
}
diff --git a/src/tools/sdktool/operation.cpp b/src/tools/sdktool/operation.cpp
index 4c1eec03d96..cb6b1d66eb1 100644
--- a/src/tools/sdktool/operation.cpp
+++ b/src/tools/sdktool/operation.cpp
@@ -55,7 +55,7 @@ QVariant valueFromString(const QString &v)
} else if (type == QLatin1String("QVariantList")) {
QVariantList list;
const QStringList elements = value.split(QLatin1Char(','));
- foreach (const QString &e, elements)
+ for (const QString &e : elements)
list << QVariant(e);
return QVariant(list);
}
diff --git a/src/tools/sdktool/operation.h b/src/tools/sdktool/operation.h
index cc489ce0757..9fba8ef1d3a 100644
--- a/src/tools/sdktool/operation.h
+++ b/src/tools/sdktool/operation.h
@@ -59,10 +59,6 @@ public:
virtual int execute() const = 0;
-#ifdef WITH_TESTS
- virtual bool test() const = 0;
-#endif
-
static QVariantMap load(const QString &file);
bool save(const QVariantMap &map, const QString &file) const;
};
diff --git a/src/tools/sdktool/rmcmakeoperation.cpp b/src/tools/sdktool/rmcmakeoperation.cpp
index 423abdbc695..570e19703cc 100644
--- a/src/tools/sdktool/rmcmakeoperation.cpp
+++ b/src/tools/sdktool/rmcmakeoperation.cpp
@@ -25,8 +25,8 @@
#include "rmcmakeoperation.h"
-#include "addkeysoperation.h"
#include "addcmakeoperation.h"
+#include "addkeysoperation.h"
#include "findkeyoperation.h"
#include "findvalueoperation.h"
#include "getoperation.h"
@@ -34,6 +34,14 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(rmcmakelog, "qtc.sdktool.operations.rmcmake", QtWarningMsg)
+
// CMake file stuff:
const char COUNT[] = "CMakeTools.Count";
const char PREFIX[] = "CMakeTools.";
@@ -64,7 +72,7 @@ bool RmCMakeOperation::setArguments(const QStringList &args)
if (current == "--id") {
if (next.isNull()) {
- std::cerr << "No parameter for --id given." << std::endl << std::endl;
+ qCCritical(rmcmakelog) << "No parameter for --id given.";
return false;
}
++i; // skip next;
@@ -73,8 +81,9 @@ bool RmCMakeOperation::setArguments(const QStringList &args)
}
}
- if (m_id.isEmpty())
- std::cerr << "No id given." << std::endl << std::endl;
+ if (m_id.isEmpty()) {
+ qCCritical(rmcmakelog) << "No id given.";
+ }
return !m_id.isEmpty();
}
@@ -93,45 +102,55 @@ int RmCMakeOperation::execute() const
}
#ifdef WITH_TESTS
-bool RmCMakeOperation::test() const
+void RmCMakeOperation::unittest()
{
// Add cmakes:
QVariantMap map = AddCMakeOperation::initializeCMake();
const QVariantMap emptyMap = map;
- map = AddCMakeData{"testId", "name", "/tmp/test",
- {{"ExtraKey", QVariant("ExtraValue")}}}.addCMake(map);
- map = AddCMakeData{"testId2", "other name", "/tmp/test2", {}}.addCMake(map);
+ AddCMakeData d;
+ d.m_id = "testId";
+ d.m_displayName = "name";
+ d.m_path = "/tmp/test";
+ d.m_extra = {{"ExtraKey", QVariant("ExtraValue")}};
+ map = d.addCMake(map);
+
+ d.m_id = "testId2";
+ d.m_displayName = "other name";
+ d.m_path = "/tmp/test2";
+ d.m_extra = {};
+ map = d.addCMake(map);
+
+ RmCMakeData rmD;
+ rmD.m_id = "nonexistent";
- QVariantMap result = RmCMakeData{"nonexistent"}.rmCMake(QVariantMap());
- if (!result.isEmpty())
- return false;
+ QTest::ignoreMessage(QtCriticalMsg, "Error: Count found in cmake tools file seems wrong.");
- result = RmCMakeData{"nonexistent"}.rmCMake(map);
- if (result != map)
- return false;
+ QVERIFY(rmD.rmCMake(QVariantMap()).isEmpty());
+ QCOMPARE(rmD.rmCMake(map), map);
// Remove from map with both testId and testId2:
- result = RmCMakeData{"testId2"}.rmCMake(map);
- if (result == map
- || result.value(COUNT, 0).toInt() != 1
- || !result.contains(QString::fromLatin1(PREFIX) + "0")
- || result.value(QString::fromLatin1(PREFIX) + "0") != map.value(QString::fromLatin1(PREFIX) + "0"))
- return false;
+ rmD.m_id = "testId2";
+ QVariantMap result = rmD.rmCMake(map);
+ QVERIFY(result != map);
+
+ QCOMPARE(result.value(COUNT, 0).toInt(), 1);
+ QVERIFY(result.contains(QString::fromLatin1(PREFIX) + "0"));
+ QCOMPARE(result.value(QString::fromLatin1(PREFIX) + "0"),
+ map.value(QString::fromLatin1(PREFIX) + "0"));
// Remove from map with both testId and testId2:
- result = RmCMakeData{"testId"}.rmCMake(map);
- if (result == map
- || result.value(COUNT, 0).toInt() != 1
- || !result.contains(QString::fromLatin1(PREFIX) + "0")
- || result.value(QString::fromLatin1(PREFIX) + "0") != map.value(QString::fromLatin1(PREFIX) + "1"))
- return false;
+ rmD.m_id = "testId";
+ result = rmD.rmCMake(map);
+ QVERIFY(result != map);
+ QCOMPARE(result.value(COUNT, 0).toInt(), 1);
+ QVERIFY(result.contains(QString::fromLatin1(PREFIX) + "0"));
+ QCOMPARE(result.value(QString::fromLatin1(PREFIX) + "0"),
+ map.value(QString::fromLatin1(PREFIX) + "1"));
// Remove from map without testId!
- result = RmCMakeData{"testId2"}.rmCMake(result);
- if (result != emptyMap)
- return false;
-
- return true;
+ rmD.m_id = "testId2";
+ result = rmD.rmCMake(result);
+ QCOMPARE(result, emptyMap);
}
#endif
@@ -141,13 +160,14 @@ QVariantMap RmCMakeData::rmCMake(const QVariantMap &map) const
bool ok;
int count = GetOperation::get(map, COUNT).toInt(&ok);
if (!ok || count < 0) {
- std::cerr << "Error: Count found in cmake tools file seems wrong." << std::endl;
+ qCCritical(rmcmakelog) << "Error: Count found in cmake tools file seems wrong.";
return map;
}
QVariantList cmList;
for (int i = 0; i < count; ++i) {
- QVariantMap cmData = GetOperation::get(map, QString::fromLatin1(PREFIX) + QString::number(i)).toMap();
+ QVariantMap cmData
+ = GetOperation::get(map, QString::fromLatin1(PREFIX) + QString::number(i)).toMap();
if (cmData.value(ID).toString() != m_id)
cmList.append(cmData);
}
@@ -159,4 +179,3 @@ QVariantMap RmCMakeData::rmCMake(const QVariantMap &map) const
return newMap;
}
-
diff --git a/src/tools/sdktool/rmcmakeoperation.h b/src/tools/sdktool/rmcmakeoperation.h
index 98d9f7847a0..e77d8efecb6 100644
--- a/src/tools/sdktool/rmcmakeoperation.h
+++ b/src/tools/sdktool/rmcmakeoperation.h
@@ -47,6 +47,6 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
#endif
};
diff --git a/src/tools/sdktool/rmdebuggeroperation.cpp b/src/tools/sdktool/rmdebuggeroperation.cpp
index 5ed3ec6a86e..f7b44d57b2e 100644
--- a/src/tools/sdktool/rmdebuggeroperation.cpp
+++ b/src/tools/sdktool/rmdebuggeroperation.cpp
@@ -36,6 +36,15 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+Q_LOGGING_CATEGORY(rmdebuggerlog, "qtc.sdktool.operations.rmdebugger", QtWarningMsg)
+
// Qt version file stuff:
const char PREFIX[] = "DebuggerItem.";
const char COUNT[] = "DebuggerItem.Count";
@@ -58,7 +67,8 @@ QString RmDebuggerOperation::helpText() const
QString RmDebuggerOperation::argumentsHelpText() const
{
- return QLatin1String(" --id <ID> id of the debugger to remove.\n");
+ return QLatin1String(
+ " --id <ID> id of the debugger to remove.\n");
}
bool RmDebuggerOperation::setArguments(const QStringList &args)
@@ -70,8 +80,9 @@ bool RmDebuggerOperation::setArguments(const QStringList &args)
m_id = args.at(1);
- if (m_id.isEmpty())
- std::cerr << "No id given." << std::endl << std::endl;
+ if (m_id.isEmpty()) {
+ qCCritical(rmdebuggerlog) << "No id given.";
+ }
return !m_id.isEmpty();
}
@@ -91,51 +102,50 @@ int RmDebuggerOperation::execute() const
}
#ifdef WITH_TESTS
-bool RmDebuggerOperation::test() const
+void RmDebuggerOperation::unittest()
{
-
- QVariantMap map =
- AddDebuggerData{QLatin1String("id1"), QLatin1String("Name1"),
- 2, QLatin1String("/tmp/debugger1"),
- {"test11", "test12"}, {}}
- .addDebugger(AddDebuggerOperation::initializeDebuggers());
-
- map = AddDebuggerData{QLatin1String("id2"), QLatin1String("Name2"),
- 2, QLatin1String("/tmp/debugger2"),
- {"test21", "test22"}, {}}
- .addDebugger(map);
+ AddDebuggerData d;
+ d.m_id = "id1";
+ d.m_displayName = "Name1";
+ d.m_engine = 2;
+ d.m_binary = "/tmp/debugger1";
+ d.m_abis = QStringList{"test11", "test12"};
+
+ QVariantMap map = d.addDebugger(AddDebuggerOperation::initializeDebuggers());
+ d.m_id = "id2";
+ d.m_displayName = "Name2";
+ d.m_binary = "/tmp/debugger2";
+ d.m_abis = QStringList{"test21", "test22"};
+ map = d.addDebugger(map);
QVariantMap result = rmDebugger(map, QLatin1String("id2"));
- if (result.count() != 3
- || !result.contains(QLatin1String("DebuggerItem.0"))
- || !result.contains(QLatin1String(COUNT))
- || result.value(QLatin1String(COUNT)).toInt() != 1
- || !result.contains(QLatin1String(VERSION))
- || result.value(QLatin1String(VERSION)).toInt() != 1)
- return false;
+ QCOMPARE(result.count(), 3);
+ QVERIFY(result.contains(QLatin1String("DebuggerItem.0")));
+ QVERIFY(result.contains(QLatin1String(COUNT)));
+ QCOMPARE(result.value(QLatin1String(COUNT)).toInt(), 1);
+ QVERIFY(result.contains(QLatin1String(VERSION)));
+ QCOMPARE(result.value(QLatin1String(VERSION)).toInt(), 1);
+
+ QTest::ignoreMessage(QtCriticalMsg,
+ QRegularExpression("Error: Id was not found"));
result = rmDebugger(map, QLatin1String("unknown"));
- if (result != map)
- return false;
+ QVERIFY(result == map);
result = rmDebugger(map, QLatin1String("id2"));
- if (result.count() != 3
- || !result.contains(QLatin1String("DebuggerItem.0"))
- || !result.contains(QLatin1String(COUNT))
- || result.value(QLatin1String(COUNT)).toInt() != 1
- || !result.contains(QLatin1String(VERSION))
- || result.value(QLatin1String(VERSION)).toInt() != 1)
- return false;
+ QCOMPARE(result.count(), 3);
+ QVERIFY(result.contains(QLatin1String("DebuggerItem.0")));
+ QVERIFY(result.contains(QLatin1String(COUNT)));
+ QCOMPARE(result.value(QLatin1String(COUNT)).toInt(), 1);
+ QVERIFY(result.contains(QLatin1String(VERSION)));
+ QCOMPARE(result.value(QLatin1String(VERSION)).toInt(), 1);
result = rmDebugger(result, QLatin1String("id1"));
- if (result.count() != 2
- || !result.contains(QLatin1String(COUNT))
- || result.value(QLatin1String(COUNT)).toInt() != 0
- || !result.contains(QLatin1String(VERSION))
- || result.value(QLatin1String(VERSION)).toInt() != 1)
- return false;
-
- return true;
+ QCOMPARE(result.count(), 2);
+ QVERIFY(result.contains(QLatin1String(COUNT)));
+ QCOMPARE(result.value(QLatin1String(COUNT)).toInt(), 0);
+ QVERIFY(result.contains(QLatin1String(VERSION)));
+ QCOMPARE(result.value(QLatin1String(VERSION)).toInt(), 1);
}
#endif
@@ -147,7 +157,7 @@ QVariantMap RmDebuggerOperation::rmDebugger(const QVariantMap &map, const QStrin
bool ok;
int count = GetOperation::get(map, QLatin1String(COUNT)).toInt(&ok);
if (!ok) {
- std::cerr << "Error: The count found in map is not an integer." << std::endl;
+ qCCritical(rmdebuggerlog) << "Error: The count found in map is not an integer.";
return map;
}
@@ -159,7 +169,7 @@ QVariantMap RmDebuggerOperation::rmDebugger(const QVariantMap &map, const QStrin
debuggerList << debugger;
}
if (debuggerList.count() == map.count() - 2) {
- std::cerr << "Error: Id was not found." << std::endl;
+ qCCritical(rmdebuggerlog) << "Error: Id was not found.";
return map;
}
@@ -179,4 +189,3 @@ QVariantMap RmDebuggerOperation::rmDebugger(const QVariantMap &map, const QStrin
return AddKeysData{data}.addKeys(result);
}
-
diff --git a/src/tools/sdktool/rmdebuggeroperation.h b/src/tools/sdktool/rmdebuggeroperation.h
index 58c086849b2..c5535ace26f 100644
--- a/src/tools/sdktool/rmdebuggeroperation.h
+++ b/src/tools/sdktool/rmdebuggeroperation.h
@@ -41,11 +41,10 @@ public:
int execute() const;
#ifdef WITH_TESTS
- bool test() const;
+ static void unittest();
#endif
static QVariantMap rmDebugger(const QVariantMap &map, const QString &id);
-
private:
QString m_id;
};
diff --git a/src/tools/sdktool/rmdeviceoperation.cpp b/src/tools/sdktool/rmdeviceoperation.cpp
index 4558352ab33..4adb196e72e 100644
--- a/src/tools/sdktool/rmdeviceoperation.cpp
+++ b/src/tools/sdktool/rmdeviceoperation.cpp
@@ -32,6 +32,15 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(rmdevicelog, "qtc.sdktool.operations.rmdevice", QtWarningMsg)
+
+
QString RmDeviceOperation::name() const
{
return QLatin1String("rmDev");
@@ -57,7 +66,7 @@ bool RmDeviceOperation::setArguments(const QStringList &args)
m_id = args.at(1);
if (m_id.isEmpty())
- std::cerr << "No id given." << std::endl << std::endl;
+ qCCritical(rmdevicelog) << "No id given.";
return !m_id.isEmpty();
}
@@ -77,9 +86,9 @@ int RmDeviceOperation::execute() const
}
#ifdef WITH_TESTS
-bool RmDeviceOperation::test() const
+void RmDeviceOperation::unittest()
{
- return true;
+
}
#endif
@@ -107,8 +116,10 @@ QVariantMap RmDeviceOperation::rmDevice(const QVariantMap &map, const QString &i
dmMap.insert(QLatin1String(DEVICE_LIST_ID), devList);
result.insert(QLatin1String(DEVICEMANAGER_ID), dmMap);
- if (!found)
- std::cerr << "Device " << qPrintable(id) << " not found." << std::endl;
+ if (!found){
+ qCCritical(rmdevicelog) << "Device " << qPrintable(id) << " not found.";
+
+ }
return result;
}
diff --git a/src/tools/sdktool/rmdeviceoperation.h b/src/tools/sdktool/rmdeviceoperation.h
index f5f711b5f57..d9fe64845e4 100644
--- a/src/tools/sdktool/rmdeviceoperation.h
+++ b/src/tools/sdktool/rmdeviceoperation.h
@@ -41,7 +41,7 @@ public:
int execute() const;
#ifdef WITH_TESTS
- bool test() const;
+ static void unittest();
#endif
static QVariantMap rmDevice(const QVariantMap &map, const QString &id);
diff --git a/src/tools/sdktool/rmkeysoperation.cpp b/src/tools/sdktool/rmkeysoperation.cpp
index 6f3d190d5e2..e567b3baa68 100644
--- a/src/tools/sdktool/rmkeysoperation.cpp
+++ b/src/tools/sdktool/rmkeysoperation.cpp
@@ -27,6 +27,15 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+Q_LOGGING_CATEGORY(rmkeyslog, "qtc.sdktool.operations.rmkeys", QtWarningMsg)
+
QString RmKeysOperation::name() const
{
return QLatin1String("rmKeys");
@@ -52,9 +61,9 @@ bool RmKeysOperation::setArguments(const QStringList &args)
m_file = m_keys.takeFirst();
if (m_file.isEmpty())
- std::cerr << "No file given." << std::endl << std::endl;
+ qCCritical(rmkeyslog) << "No file given.";
if (m_keys.isEmpty())
- std::cerr << "No keys given." << std::endl << std::endl;
+ qCCritical(rmkeyslog) << "No keys given.";
return !m_file.isEmpty() && !m_keys.isEmpty();
}
@@ -73,7 +82,7 @@ int RmKeysOperation::execute() const
}
#ifdef WITH_TESTS
-bool RmKeysOperation::test() const
+void RmKeysOperation::unittest()
{
QVariantMap testMap;
QVariantMap subKeys;
@@ -90,77 +99,72 @@ bool RmKeysOperation::test() const
QVariantMap result = rmKeys(testMap, data);
- if (result != testMap)
- return false;
+ QVERIFY(result == testMap);
data.append(QLatin1String("testint"));
result = rmKeys(testMap, data);
- if (result.count() != 2
- || !result.contains(QLatin1String("subkeys"))
- || !result.contains(QLatin1String("subkeys2")))
- return false;
+ QCOMPARE(result.count(), 2);
+ QVERIFY(result.contains(QLatin1String("subkeys")));
+ QVERIFY(result.contains(QLatin1String("subkeys2")));
+
cur = result.value(QLatin1String("subkeys")).toMap();
- if (cur.count() != 2
- || !cur.contains(QLatin1String("subsubkeys"))
- || !cur.contains(QLatin1String("testbool")))
- return false;
+ QCOMPARE(cur.count(), 2);
+ QVERIFY(cur.contains(QLatin1String("subsubkeys")));
+ QVERIFY(cur.contains(QLatin1String("testbool")));
cur = cur.value(QLatin1String("subsubkeys")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("testint2")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("testint2")));
cur = result.value(QLatin1String("subkeys2")).toMap();
- if (cur.count() != 0)
- return false;
+ QVERIFY(cur.isEmpty());
data.clear();
data.append(QLatin1String("subkeys/subsubkeys"));
result = rmKeys(testMap, data);
- if (result.count() != 3
- || !result.contains(QLatin1String("subkeys"))
- || !result.contains(QLatin1String("subkeys2"))
- || !result.contains(QLatin1String("testint")))
- return false;
+ QCOMPARE(result.count(), 3);
+ QVERIFY(result.contains(QLatin1String("subkeys")));
+ QVERIFY(result.contains(QLatin1String("subkeys2")));
+ QVERIFY(result.contains(QLatin1String("testint")));
+
cur = result.value(QLatin1String("subkeys")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("testbool")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("testbool")));
cur = result.value(QLatin1String("subkeys2")).toMap();
- if (cur.count() != 0)
- return false;
+ QVERIFY(cur.isEmpty());
data.clear();
data.append(QLatin1String("subkeys/testbool"));
result = rmKeys(testMap, data);
- if (result.count() != 3
- || !result.contains(QLatin1String("subkeys"))
- || !result.contains(QLatin1String("subkeys2"))
- || !result.contains(QLatin1String("testint")))
- return false;
+ QCOMPARE(result.count(), 3);
+ QVERIFY(result.contains(QLatin1String("subkeys")));
+ QVERIFY(result.contains(QLatin1String("subkeys2")));
+ QVERIFY(result.contains(QLatin1String("testint")));
+
cur = result.value(QLatin1String("subkeys")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("subsubkeys")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("subsubkeys")));
cur = cur.value(QLatin1String("subsubkeys")).toMap();
- if (cur.count() != 1
- || !cur.contains(QLatin1String("testint2")))
- return false;
+ QCOMPARE(cur.count(), 1);
+ QVERIFY(cur.contains(QLatin1String("testint2")));
cur = result.value(QLatin1String("subkeys2")).toMap();
- if (cur.count() != 0)
- return false;
+ QVERIFY(cur.isEmpty());
cur = result.value(QLatin1String("subkeys2")).toMap();
- if (cur.count() != 0)
- return false;
+ QVERIFY(cur.isEmpty());
+
+ // Test removing of non-existent key ...
+ testMap = rmKeys(testMap, data);
- return true;
+ QTest::ignoreMessage(QtWarningMsg,
+ QRegularExpression("Key .* not found."));
+ testMap = rmKeys(testMap, data);
}
#endif
@@ -168,7 +172,7 @@ QVariantMap RmKeysOperation::rmKeys(const QVariantMap &map, const QStringList &r
{
QVariantMap result = map;
- foreach (const QString &r, removals) {
+ for (const QString &r : removals) {
QList<QVariantMap> stack;
const QStringList keys = r.split(QLatin1Char('/'));
@@ -180,7 +184,7 @@ QVariantMap RmKeysOperation::rmKeys(const QVariantMap &map, const QStringList &r
if (stack.last().contains(keys.at(i))) {
subMap = stack.last().value(keys.at(i)).toMap();
} else {
- std::cerr << "Warning: Key " << qPrintable(r) << " not found." << std::endl;
+ qCWarning(rmkeyslog) << "Key" << qPrintable(r) << "not found.";
continue;
}
stack.append(subMap);
@@ -189,7 +193,7 @@ QVariantMap RmKeysOperation::rmKeys(const QVariantMap &map, const QStringList &r
// remove
Q_ASSERT(stack.count() == keys.count());
if (!stack.last().contains(keys.last())) {
- std::cerr << "Warning: Key " << qPrintable(r) << " not found." << std::endl;
+ qCWarning(rmkeyslog) << "Key" << qPrintable(r) << "not found.";
continue;
}
stack.last().remove(keys.last());
diff --git a/src/tools/sdktool/rmkeysoperation.h b/src/tools/sdktool/rmkeysoperation.h
index d83c1860d5b..b9e016a2333 100644
--- a/src/tools/sdktool/rmkeysoperation.h
+++ b/src/tools/sdktool/rmkeysoperation.h
@@ -39,7 +39,7 @@ public:
int execute() const;
#ifdef WITH_TESTS
- bool test() const;
+ static void unittest();
#endif
static QVariantMap rmKeys(const QVariantMap &map, const QStringList &removals);
diff --git a/src/tools/sdktool/rmkitoperation.cpp b/src/tools/sdktool/rmkitoperation.cpp
index 8d042990326..ece4863daff 100644
--- a/src/tools/sdktool/rmkitoperation.cpp
+++ b/src/tools/sdktool/rmkitoperation.cpp
@@ -25,11 +25,11 @@
#include "rmkitoperation.h"
-#include "addkeysoperation.h"
-#include "addtoolchainoperation.h"
#include "adddeviceoperation.h"
-#include "addqtoperation.h"
+#include "addkeysoperation.h"
#include "addkitoperation.h"
+#include "addqtoperation.h"
+#include "addtoolchainoperation.h"
#include "findkeyoperation.h"
#include "findvalueoperation.h"
#include "getoperation.h"
@@ -39,6 +39,14 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(rmkitlog, "qtc.sdktool.operations.rmkit", QtWarningMsg)
+
// Qt version file stuff:
const char PREFIX[] = "Profile.";
const char COUNT[] = "Profile.Count";
@@ -75,7 +83,7 @@ bool RmKitOperation::setArguments(const QStringList &args)
m_id = args.at(1);
if (m_id.isEmpty())
- std::cerr << "No id given." << std::endl << std::endl;
+ qCCritical(rmkitlog) << "No id given.";
return !m_id.isEmpty();
}
@@ -95,15 +103,28 @@ int RmKitOperation::execute() const
}
#ifdef WITH_TESTS
-bool RmKitOperation::test() const
+void RmKitOperation::unittest()
{
QVariantMap tcMap = AddToolChainOperation::initializeToolChains();
- tcMap = AddToolChainData{"{tc-id}", "langId", "TC", "/usr/bin/gcc",
- "x86-linux-generic-elf-32bit", "x86-linux-generic-elf-32bit", {}}
- .addToolChain(tcMap);
+ AddToolChainData d;
+ d.m_id = "{tc-id}";
+ d.m_languageId = "langId";
+ d.m_displayName = "TC";
+ d.m_path = "/usr/bin/gcc";
+ d.m_targetAbi = "x86-linux-generic-elf-32bit";
+ d.m_supportedAbis = "x86-linux-generic-elf-32bit";
+ d.m_extra = {};
+
+ tcMap = d.addToolChain(tcMap);
QVariantMap qtMap = AddQtData::initializeQtVersions();
- qtMap = AddQtData{"{qt-id}", "Qt", "desktop-qt", "/usr/bin/qmake", {}, {}}.addQt(qtMap);
+ AddQtData qtd;
+ qtd.m_id = "{qt-id}";
+ qtd.m_displayName = "Qt";
+ qtd.m_type = "desktop-qt";
+ qtd.m_qmake = "/usr/bin/qmake";
+
+ qtMap = qtd.addQt(qtMap);
QVariantMap devMap = AddDeviceOperation::initializeDevices();
AddDeviceData devData;
@@ -134,52 +155,57 @@ bool RmKitOperation::test() const
kitData.m_displayName = "Test Qt Version";
kitData.m_icon = "/tmp/icon.png";
kitData.m_debuggerEngine = 1;
- kitData.m_debugger = "/usr/bin/gdb-test";
+ kitData.m_debugger = "/usr/bin/gdb-test";
kitData.m_deviceType = "Desktop";
kitData.m_tcs = tcs;
kitData.m_qt = "{qt-id}";
kitData.m_mkspec = "unsupported/mkspec";
- kitData.m_extra = {{"PE.Profile.Data/extraData", QVariant("extraValue")}};
+ kitData.m_extra = {{"PE.Profile.Data/extraData", QVariant("extraValue")}};
QVariantMap map = kitData.addKit(AddKitData::initializeKits(), tcMap, qtMap, devMap, {});
-
kitData.m_id = "testId2";
kitData.m_icon = "/tmp/icon2.png";
kitData.m_icon = "/usr/bin/gdb-test2";
kitData.m_mkspec = "unsupported/mkspec2";
- kitData.m_extra = {{"PE.Profile.Data/extraData", QVariant("extraValue2")}};
+ kitData.m_extra = {{"PE.Profile.Data/extraData", QVariant("extraValue2")}};
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
+ QTest::ignoreMessage(QtCriticalMsg, "Error: Could not find the default kit.");
QVariantMap result = rmKit(map, "testId");
- if (result.count() != 4
- || !result.contains("Profile.0")
- || !result.contains(COUNT) || result.value(COUNT).toInt() != 1
- || !result.contains(DEFAULT) || result.value(DEFAULT).toInt() != 0
- || !result.contains(VERSION) || result.value(VERSION).toInt() != 1)
- return false;
-
+ QCOMPARE(result.count(), 4);
+ QVERIFY(result.contains("Profile.0"));
+ QVERIFY(result.contains(COUNT));
+ QCOMPARE(result.value(COUNT).toInt(), 1);
+ QVERIFY(result.contains(DEFAULT));
+ QCOMPARE(result.value(DEFAULT).toInt(), 0);
+ QVERIFY(result.contains(VERSION));
+ QCOMPARE(result.value(VERSION).toInt(), 1);
+
+ QTest::ignoreMessage(QtCriticalMsg, "Error: Id was not found.");
result = rmKit(map, "unknown");
- if (result != map)
- return false;
+ QCOMPARE(result, map);
+ QTest::ignoreMessage(QtCriticalMsg, "Error: Could not find the default kit.");
result = rmKit(map, "testId2");
- if (result.count() != 4
- || !result.contains("Profile.0")
- || !result.contains(COUNT) || result.value(COUNT).toInt() != 1
- || !result.contains(DEFAULT) || result.value(DEFAULT).toInt() != 0
- || !result.contains(VERSION) || result.value(VERSION).toInt() != 1)
- return false;
+ QCOMPARE(result.count(), 4);
+ QVERIFY(result.contains("Profile.0"));
+ QVERIFY(result.contains(COUNT));
+ QCOMPARE(result.value(COUNT).toInt(), 1);
+ QVERIFY(result.contains(DEFAULT));
+ QCOMPARE(result.value(DEFAULT).toInt(), 0);
+ QVERIFY(result.contains(VERSION));
+ QCOMPARE(result.value(VERSION).toInt(), 1);
result = rmKit(result, QLatin1String("testId"));
- if (result.count() != 3
- || !result.contains(COUNT) || result.value(COUNT).toInt() != 0
- || !result.contains(DEFAULT) || result.value(DEFAULT).toInt() != -1
- || !result.contains(VERSION) || result.value(VERSION).toInt() != 1)
- return false;
-
- return true;
+ QCOMPARE(result.count(), 3);
+ QVERIFY(result.contains(COUNT));
+ QCOMPARE(result.value(COUNT).toInt(), 0);
+ QVERIFY(result.contains(DEFAULT));
+ QCOMPARE(result.value(DEFAULT).toInt(), -1);
+ QVERIFY(result.contains(VERSION));
+ QCOMPARE(result.value(VERSION).toInt(), 1);
}
#endif
@@ -191,7 +217,7 @@ QVariantMap RmKitOperation::rmKit(const QVariantMap &map, const QString &id)
bool ok;
int count = GetOperation::get(map, COUNT).toInt(&ok);
if (!ok) {
- std::cerr << "Error: The count found in map is not an integer." << std::endl;
+ qCCritical(rmkitlog) << "Error: The count found in map is not an integer.";
return map;
}
@@ -206,13 +232,13 @@ QVariantMap RmKitOperation::rmKit(const QVariantMap &map, const QString &id)
profileList << profile;
}
if (profileList.count() == map.count() - 3) {
- std::cerr << "Error: Id was not found." << std::endl;
+ qCCritical(rmkitlog) << "Error: Id was not found.";
return map;
}
int defaultKit = GetOperation::get(map, DEFAULT).toInt(&ok);
if (!ok) {
- std::cerr << "Error: Could not find the default kit." << std::endl;
+ qCCritical(rmkitlog) << "Error: Could not find the default kit.";
defaultKit = -1;
}
@@ -228,8 +254,7 @@ QVariantMap RmKitOperation::rmKit(const QVariantMap &map, const QString &id)
data << KeyValuePair(COUNT, QVariant(count - 1));
for (int i = 0; i < profileList.count(); ++i)
- data << KeyValuePair(QString::fromLatin1(PREFIX) + QString::number(i),
- profileList.at(i));
+ data << KeyValuePair(QString::fromLatin1(PREFIX) + QString::number(i), profileList.at(i));
return AddKeysData{data}.addKeys(result);
}
diff --git a/src/tools/sdktool/rmkitoperation.h b/src/tools/sdktool/rmkitoperation.h
index 75fb4cf5277..a5360c9d380 100644
--- a/src/tools/sdktool/rmkitoperation.h
+++ b/src/tools/sdktool/rmkitoperation.h
@@ -41,7 +41,7 @@ public:
int execute() const;
#ifdef WITH_TESTS
- bool test() const;
+ static void unittest();
#endif
static QVariantMap rmKit(const QVariantMap &map, const QString &id);
diff --git a/src/tools/sdktool/rmqtoperation.cpp b/src/tools/sdktool/rmqtoperation.cpp
index bad6c923060..5c107204793 100644
--- a/src/tools/sdktool/rmqtoperation.cpp
+++ b/src/tools/sdktool/rmqtoperation.cpp
@@ -34,6 +34,14 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(rmqtlog, "qtc.sdktool.operations.rmqt", QtWarningMsg)
+
// ToolChain file stuff:
const char PREFIX[] = "QtVersion.";
@@ -63,7 +71,7 @@ bool RmQtOperation::setArguments(const QStringList &args)
if (current == QLatin1String("--id")) {
if (next.isNull()) {
- std::cerr << "No parameter for --id given." << std::endl << std::endl;
+ qCCritical(rmqtlog) << "No parameter for --id given.";
return false;
}
++i; // skip next;
@@ -73,7 +81,7 @@ bool RmQtOperation::setArguments(const QStringList &args)
}
if (m_id.isEmpty())
- std::cerr << "No id given." << std::endl << std::endl;
+ qCCritical(rmqtlog) << "No id given.";
return !m_id.isEmpty();
}
@@ -92,42 +100,46 @@ int RmQtOperation::execute() const
}
#ifdef WITH_TESTS
-bool RmQtOperation::test() const
+void RmQtOperation::unittest()
{
// Add toolchain:
QVariantMap map = AddQtData::initializeQtVersions();
QVariantMap result = rmQt(QVariantMap(), QLatin1String("nonexistant"));
- if (result != map)
- return false;
+ QCOMPARE(result, map);
- map = AddQtData{"testId", "name", "type", "/tmp/test", {},
- {{QLatin1String("ExtraKey"), QVariant(QLatin1String("ExtraValue"))}}}
- .addQt(map);
+ AddQtData addData;
+ addData.m_id = "testId";
+ addData.m_displayName = "name";
+ addData.m_type = "type";
+ addData.m_qmake = "/tmp/test";
+ addData.m_extra = {{QLatin1String("ExtraKey"), QVariant(QLatin1String("ExtraValue"))}};
- map = AddQtData{"testId2", "other name", "type", "/tmp/test2", {}, {}}.addQt(map);
+ map = addData.addQt(map);
+
+ addData.m_id = "testId2";
+ addData.m_displayName = "other name";
+ addData.m_type = "type";
+ addData.m_qmake = "/tmp/test2";
+ addData.m_extra = {};
+
+ map = addData.addQt(map);
result = rmQt(map, QLatin1String("nonexistant"));
- if (result != map)
- return false;
+ QCOMPARE(result, map);
result = rmQt(map, QLatin1String("testId2"));
- if (result == map
- || !result.contains(QLatin1String("QtVersion.0"))
- || result.value(QLatin1String("QtVersion.0")) != map.value(QLatin1String("QtVersion.0")))
- return false;
+ QVERIFY(result != map);
+ QVERIFY(result.contains(QLatin1String("QtVersion.0")));
+ QCOMPARE(result.value(QLatin1String("QtVersion.0")), map.value(QLatin1String("QtVersion.0")));
result = rmQt(map, QLatin1String("testId"));
- if (result == map
- || !result.contains(QLatin1String("QtVersion.0"))
- || result.value(QLatin1String("QtVersion.0")) != map.value(QLatin1String("QtVersion.1")))
- return false;
+ QVERIFY(result != map);
+ QVERIFY(result.contains(QLatin1String("QtVersion.0")));
+ QCOMPARE(result.value(QLatin1String("QtVersion.0")), map.value(QLatin1String("QtVersion.1")));
result = rmQt(result, QLatin1String("testId2"));
- if (result == map)
- return false;
-
- return true;
+ QVERIFY(result != map);
}
#endif
@@ -153,4 +165,3 @@ QVariantMap RmQtOperation::rmQt(const QVariantMap &map, const QString &id)
return newMap;
}
-
diff --git a/src/tools/sdktool/rmqtoperation.h b/src/tools/sdktool/rmqtoperation.h
index 36ff9cee96e..8779e493802 100644
--- a/src/tools/sdktool/rmqtoperation.h
+++ b/src/tools/sdktool/rmqtoperation.h
@@ -41,7 +41,7 @@ public:
int execute() const;
#ifdef WITH_TESTS
- bool test() const;
+ static void unittest();
#endif
static QVariantMap rmQt(const QVariantMap &map, const QString &id);
diff --git a/src/tools/sdktool/rmtoolchainoperation.cpp b/src/tools/sdktool/rmtoolchainoperation.cpp
index bf71ec5cfe9..e546eb6354c 100644
--- a/src/tools/sdktool/rmtoolchainoperation.cpp
+++ b/src/tools/sdktool/rmtoolchainoperation.cpp
@@ -34,6 +34,14 @@
#include <iostream>
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(rmtoolchainlog, "qtc.sdktool.operations.rmtoolchain", QtWarningMsg)
+
// ToolChain file stuff:
const char COUNT[] = "ToolChain.Count";
const char PREFIX[] = "ToolChain.";
@@ -64,7 +72,7 @@ bool RmToolChainOperation::setArguments(const QStringList &args)
if (current == "--id") {
if (next.isNull()) {
- std::cerr << "No parameter for --id given." << std::endl << std::endl;
+ qCCritical(rmtoolchainlog) << "No parameter for --id given.";
return false;
}
++i; // skip next;
@@ -74,7 +82,7 @@ bool RmToolChainOperation::setArguments(const QStringList &args)
}
if (m_id.isEmpty())
- std::cerr << "No id given." << std::endl << std::endl;
+ qCCritical(rmtoolchainlog) << "No id given.";
return !m_id.isEmpty();
}
@@ -93,60 +101,72 @@ int RmToolChainOperation::execute() const
}
#ifdef WITH_TESTS
-bool RmToolChainOperation::test() const
+void RmToolChainOperation::unittest()
{
// Add toolchain:
QVariantMap map = AddToolChainOperation::initializeToolChains();
- map = AddToolChainData{"testId", "langId", "name", "/tmp/test", "test-abi",
- "test-abi,test-abi2", {{"ExtraKey", QVariant("ExtraValue")}}}
- .addToolChain(map);
-
- map = AddToolChainData{"testId2", "langId", "other name", "/tmp/test2", "test-abi",
- "test-abi,test-abi2", {}}
- .addToolChain(map);
+ AddToolChainData d;
+ d.m_id = "testId";
+ d.m_languageId = "langId";
+ d.m_displayName = "name";
+ d.m_path = "/tmp/test";
+ d.m_targetAbi = "test-abi";
+ d.m_supportedAbis = "test-abi,test-abi2";
+ d.m_extra = {{"ExtraKey", QVariant("ExtraValue")}};
+
+ map = d.addToolChain(map);
+
+ d.m_id = "testId2";
+ d.m_languageId = "langId";
+ d.m_displayName = "other name";
+ d.m_path = "/tmp/test2";
+ d.m_targetAbi = "test-abi";
+ d.m_supportedAbis = "test-abi,test-abi2";
+ d.m_extra = {};
+ map = d.addToolChain(map);
+
+ QTest::ignoreMessage(QtCriticalMsg, "Error: Count found in toolchains file seems wrong.");
QVariantMap result = rmToolChain(QVariantMap(), "nonexistent");
- if (!result.isEmpty())
- return false;
+ QVERIFY(result.isEmpty());
result = rmToolChain(map, "nonexistent");
- if (result != map)
- return false;
+ QCOMPARE(result, map);
result = rmToolChain(map, "testId2");
- if (result == map
- || result.value(COUNT, 0).toInt() != 1
- || !result.contains("ToolChain.0") || result.value("ToolChain.0") != map.value("ToolChain.0"))
- return false;
+ QVERIFY(result != map);
+ QCOMPARE(result.value(COUNT, 0).toInt(), 1);
+ QVERIFY(result.contains("ToolChain.0"));
+ QCOMPARE(result.value("ToolChain.0"), map.value("ToolChain.0"));
result = rmToolChain(map, "testId");
- if (result == map
- || result.value(COUNT, 0).toInt() != 1
- || !result.contains("ToolChain.0") || result.value("ToolChain.0") != map.value("ToolChain.1"))
- return false;
+ QVERIFY(result != map);
+ QCOMPARE(result.value(COUNT, 0).toInt(), 1);
+ QVERIFY(result.contains("ToolChain.0"));
+ QCOMPARE(result.value("ToolChain.0"), map.value("ToolChain.1"));
result = rmToolChain(result, "testId2");
- if (result == map
- || result.value(COUNT, 0).toInt() != 0)
- return false;
+ QVERIFY(result != map);
- return true;
+ QCOMPARE(result.value(COUNT, 0).toInt(), 0);
}
#endif
QVariantMap RmToolChainOperation::rmToolChain(const QVariantMap &map, const QString &id)
{
+
// Find count of tool chains:
bool ok;
int count = GetOperation::get(map, COUNT).toInt(&ok);
if (!ok || count < 0) {
- std::cerr << "Error: Count found in toolchains file seems wrong." << std::endl;
+ qCCritical(rmtoolchainlog) << "Error: Count found in toolchains file seems wrong.";
return map;
}
QVariantList tcList;
for (int i = 0; i < count; ++i) {
- QVariantMap tcData = GetOperation::get(map, QString::fromLatin1(PREFIX) + QString::number(i)).toMap();
+ QVariantMap tcData
+ = GetOperation::get(map, QString::fromLatin1(PREFIX) + QString::number(i)).toMap();
if (tcData.value(ID).toString() != id)
tcList.append(tcData);
}
@@ -158,4 +178,3 @@ QVariantMap RmToolChainOperation::rmToolChain(const QVariantMap &map, const QStr
return newMap;
}
-
diff --git a/src/tools/sdktool/rmtoolchainoperation.h b/src/tools/sdktool/rmtoolchainoperation.h
index cf4d12d1e5e..c2b7ddee6a6 100644
--- a/src/tools/sdktool/rmtoolchainoperation.h
+++ b/src/tools/sdktool/rmtoolchainoperation.h
@@ -41,7 +41,8 @@ public:
int execute() const final;
#ifdef WITH_TESTS
- bool test() const final;
+ static void unittest();
+
#endif
static QVariantMap rmToolChain(const QVariantMap &map, const QString &id);
diff --git a/src/tools/sdktool/sdktool.qbs b/src/tools/sdktool/sdktool.qbs
index b36b9b8dd83..a1da4f5df3e 100644
--- a/src/tools/sdktool/sdktool.qbs
+++ b/src/tools/sdktool/sdktool.qbs
@@ -5,8 +5,8 @@ QtcTool {
Depends { name: "Qt.core" }
Depends { name: "app_version_header" }
-
- property string libsDir: path + "/../../libs"
+ Depends { name: "Qt.testlib"; condition: project.withAutotests }
+ Depends { name: "sdktoolLib" }
cpp.defines: base.concat([
"UTILS_LIBRARY",
@@ -23,73 +23,8 @@ QtcTool {
condition: qbs.targetOS.contains("macos")
cpp.frameworks: ["Foundation"]
}
- cpp.includePaths: base.concat([libsDir])
files: [
- "addabiflavor.cpp", "addabiflavor.h",
- "addcmakeoperation.cpp", "addcmakeoperation.h",
- "adddebuggeroperation.cpp", "adddebuggeroperation.h",
- "adddeviceoperation.cpp", "adddeviceoperation.h",
- "addkeysoperation.cpp",
- "addkeysoperation.h",
- "addkitoperation.cpp",
- "addkitoperation.h",
- "addqtoperation.cpp",
- "addqtoperation.h",
- "addtoolchainoperation.cpp",
- "addtoolchainoperation.h",
- "addvalueoperation.cpp",
- "addvalueoperation.h",
- "findkeyoperation.cpp",
- "findkeyoperation.h",
- "findvalueoperation.cpp",
- "findvalueoperation.h",
- "getoperation.cpp",
- "getoperation.h",
"main.cpp",
- "operation.cpp",
- "operation.h",
- "rmcmakeoperation.cpp", "rmcmakeoperation.h",
- "rmdebuggeroperation.cpp", "rmdebuggeroperation.h",
- "rmdeviceoperation.cpp", "rmdeviceoperation.h",
- "rmkeysoperation.cpp",
- "rmkeysoperation.h",
- "rmkitoperation.cpp",
- "rmkitoperation.h",
- "rmqtoperation.cpp",
- "rmqtoperation.h",
- "rmtoolchainoperation.cpp",
- "rmtoolchainoperation.h",
- "settings.cpp",
- "settings.h",
]
-
- Group {
- name: "Utils"
- prefix: libsDir + "/utils/"
- files: [
- "commandline.cpp", "commandline.h",
- "environment.cpp", "environment.h",
- "filepath.cpp", "filepath.h",
- "fileutils.cpp", "fileutils.h",
- "hostosinfo.cpp", "hostosinfo.h",
- "macroexpander.cpp", "macroexpander.h",
- "namevaluedictionary.cpp", "namevaluedictionary.h",
- "namevalueitem.cpp", "namevalueitem.h",
- "persistentsettings.cpp", "persistentsettings.h",
- "porting.h",
- "qtcassert.cpp", "qtcassert.h",
- "savefile.cpp", "savefile.h",
- "stringutils.cpp"
- ]
- }
- Group {
- name: "Utils/macOS"
- condition: qbs.targetOS.contains("macos")
- prefix: libsDir + "/utils/"
- files: [
- "fileutils_mac.h",
- "fileutils_mac.mm",
- ]
- }
}
diff --git a/src/tools/sdktool/sdktoollib.qbs b/src/tools/sdktool/sdktoollib.qbs
new file mode 100644
index 00000000000..180dd14ce2f
--- /dev/null
+++ b/src/tools/sdktool/sdktoollib.qbs
@@ -0,0 +1,109 @@
+import qbs 1.0
+
+QtcLibrary {
+ name: "sdktoolLib"
+
+ type: "staticlibrary"
+
+ Depends { name: "Qt.core" }
+ Depends { name: "app_version_header" }
+ Depends { name: "Qt.testlib"; condition: project.withAutotests }
+
+ property string libsDir: path + "/../../libs"
+
+ cpp.defines: base.concat([
+ "UTILS_LIBRARY",
+ qbs.targetOS.contains("macos")
+ ? 'DATA_PATH="."'
+ : qbs.targetOS.contains("windows") ? 'DATA_PATH="../share/qtcreator"'
+ : 'DATA_PATH="../../share/qtcreator"'
+ ])
+ cpp.dynamicLibraries: {
+ if (qbs.targetOS.contains("windows"))
+ return ["user32", "shell32"]
+ }
+ Properties {
+ condition: qbs.targetOS.contains("macos")
+ cpp.frameworks: ["Foundation"]
+ }
+ cpp.includePaths: base.concat([libsDir])
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory, exportingProduct.libsDir]
+ }
+
+ files: [
+ "addabiflavor.cpp",
+ "addabiflavor.h",
+ "addcmakeoperation.cpp",
+ "addcmakeoperation.h",
+ "adddebuggeroperation.cpp",
+ "adddebuggeroperation.h",
+ "adddeviceoperation.cpp",
+ "adddeviceoperation.h",
+ "addkeysoperation.cpp",
+ "addkeysoperation.h",
+ "addkitoperation.cpp",
+ "addkitoperation.h",
+ "addqtoperation.cpp",
+ "addqtoperation.h",
+ "addtoolchainoperation.cpp",
+ "addtoolchainoperation.h",
+ "addvalueoperation.cpp",
+ "addvalueoperation.h",
+ "findkeyoperation.cpp",
+ "findkeyoperation.h",
+ "findvalueoperation.cpp",
+ "findvalueoperation.h",
+ "getoperation.cpp",
+ "getoperation.h",
+ "operation.cpp",
+ "operation.h",
+ "rmcmakeoperation.cpp",
+ "rmcmakeoperation.h",
+ "rmdebuggeroperation.cpp",
+ "rmdebuggeroperation.h",
+ "rmdeviceoperation.cpp",
+ "rmdeviceoperation.h",
+ "rmkeysoperation.cpp",
+ "rmkeysoperation.h",
+ "rmkitoperation.cpp",
+ "rmkitoperation.h",
+ "rmqtoperation.cpp",
+ "rmqtoperation.h",
+ "rmtoolchainoperation.cpp",
+ "rmtoolchainoperation.h",
+ "settings.cpp",
+ "settings.h",
+ ]
+
+ Group {
+ name: "Utils"
+ prefix: libsDir + "/utils/"
+ files: [
+ "commandline.cpp", "commandline.h",
+ "environment.cpp", "environment.h",
+ "filepath.cpp", "filepath.h",
+ "fileutils.cpp", "fileutils.h",
+ "hostosinfo.cpp", "hostosinfo.h",
+ "macroexpander.cpp", "macroexpander.h",
+ "namevaluedictionary.cpp", "namevaluedictionary.h",
+ "namevalueitem.cpp", "namevalueitem.h",
+ "persistentsettings.cpp", "persistentsettings.h",
+ "porting.h",
+ "qtcassert.cpp", "qtcassert.h",
+ "savefile.cpp", "savefile.h",
+ "stringutils.cpp"
+ ]
+ }
+ Group {
+ name: "Utils/macOS"
+ condition: qbs.targetOS.contains("macos")
+ prefix: libsDir + "/utils/"
+ files: [
+ "fileutils_mac.h",
+ "fileutils_mac.mm",
+ ]
+ }
+}
diff --git a/src/tools/tools.qbs b/src/tools/tools.qbs
index bcd94e0f24c..cb4230dfde4 100644
--- a/src/tools/tools.qbs
+++ b/src/tools/tools.qbs
@@ -5,7 +5,6 @@ Project {
name: "Tools"
references: [
"buildoutputparser/buildoutputparser.qbs",
- "clangbackend/clangbackend.qbs",
"cplusplustools.qbs",
"disclaim/disclaim.qbs",
"processlauncher/processlauncher.qbs",
@@ -15,9 +14,9 @@ Project {
"qtc-askpass/qtc-askpass.qbs",
"qtpromaker/qtpromaker.qbs",
"sdktool/sdktool.qbs",
+ "sdktool/sdktoollib.qbs",
"valgrindfake/valgrindfake.qbs",
"iostool/iostool.qbs",
- "winrtdebughelper/winrtdebughelper.qbs"
].concat(project.additionalTools)
Project {
diff --git a/src/tools/winrtdebughelper/CMakeLists.txt b/src/tools/winrtdebughelper/CMakeLists.txt
deleted file mode 100644
index d979f16f7b1..00000000000
--- a/src/tools/winrtdebughelper/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-if (NOT WIN32)
- return()
-endif()
-
-add_qtc_executable(winrtdebughelper
- SOURCES
- winrtdebughelper.cpp
-)
diff --git a/src/tools/winrtdebughelper/winrtdebughelper.cpp b/src/tools/winrtdebughelper/winrtdebughelper.cpp
deleted file mode 100644
index f871dbf345d..00000000000
--- a/src/tools/winrtdebughelper/winrtdebughelper.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include <windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char *argv[])
-{
- int pid = -1;
- const size_t maxPipeNameSize = 256;
- wchar_t pipeName[maxPipeNameSize] = {0};
-
- for (int i = 0; i < argc - 1; ++i) {
- if (!strcmp(argv[i], "-t")) {
- ++i;
- if (swprintf(pipeName, maxPipeNameSize, L"%hs", argv[i]) < 0)
- return 0; // Pipe name too long
- } else if (!strcmp(argv[i], "-p")) {
- ++i;
-
- // check if -p is followed by a number
- const char *pidString = argv[i];
- char *end;
- pid = strtoul(pidString, &end, 0);
- if (*end != 0)
- return 0;
- }
- }
-
- if (pid < 0)
- return 0;
-
- if (*pipeName == 0)
- swprintf(pipeName, maxPipeNameSize, L"\\\\.\\pipe\\QtCreatorWinRtDebugPIDPipe");
- HANDLE pipe;
- while (true) {
- pipe = CreateFile(pipeName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
- if (pipe != INVALID_HANDLE_VALUE)
- break;
- if ((GetLastError() != ERROR_PIPE_BUSY) || (!WaitNamedPipe(pipeName, 10000)))
- return 0;
- }
-
- const size_t msgBufferSize = 15;
- char pidMessageBuffer[msgBufferSize];
- int length = sprintf_s(pidMessageBuffer, msgBufferSize, "PID:%d", pid);
- if (length >= 0)
- WriteFile(pipe, pidMessageBuffer, length, NULL, NULL);
-
- return 0;
-}
diff --git a/src/tools/winrtdebughelper/winrtdebughelper.qbs b/src/tools/winrtdebughelper/winrtdebughelper.qbs
deleted file mode 100644
index d4d27a12ae4..00000000000
--- a/src/tools/winrtdebughelper/winrtdebughelper.qbs
+++ /dev/null
@@ -1,12 +0,0 @@
-import qbs 1.0
-
-QtcTool {
- name: "winrtdebughelper"
- condition: qbs.targetOS.contains("windows")
-
- Depends { name: "Qt.network" }
-
- files: [
- "winrtdebughelper.cpp",
- ]
-}
diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt
index bc58a5b953d..36c9c2c59cf 100644
--- a/tests/auto/CMakeLists.txt
+++ b/tests/auto/CMakeLists.txt
@@ -17,7 +17,6 @@ add_subdirectory(profilewriter)
add_subdirectory(qml)
add_subdirectory(runextensions)
add_subdirectory(sdktool)
-add_subdirectory(ssh)
add_subdirectory(toolchaincache)
add_subdirectory(tracing)
add_subdirectory(treeviewfind)
diff --git a/tests/auto/aggregation/tst_aggregate.cpp b/tests/auto/aggregation/tst_aggregate.cpp
index cb7d06dcb79..082da763f73 100644
--- a/tests/auto/aggregation/tst_aggregate.cpp
+++ b/tests/auto/aggregation/tst_aggregate.cpp
@@ -199,6 +199,6 @@ void tst_Aggregate::parentAggregate()
QCOMPARE(Aggregation::Aggregate::parentAggregate(component11), (Aggregation::Aggregate *)0);
}
-QTEST_MAIN(tst_Aggregate)
+QTEST_GUILESS_MAIN(tst_Aggregate)
#include "tst_aggregate.moc"
diff --git a/tests/auto/algorithm/tst_algorithm.cpp b/tests/auto/algorithm/tst_algorithm.cpp
index 3cc0301e810..56fcd84f756 100644
--- a/tests/auto/algorithm/tst_algorithm.cpp
+++ b/tests/auto/algorithm/tst_algorithm.cpp
@@ -577,6 +577,6 @@ void tst_Algorithm::take()
}
}
-QTEST_MAIN(tst_Algorithm)
+QTEST_GUILESS_MAIN(tst_Algorithm)
#include "tst_algorithm.moc"
diff --git a/tests/auto/android/tst_avdmanageroutputparser.cpp b/tests/auto/android/tst_avdmanageroutputparser.cpp
index ca3dcda19c5..4dc8a0d3571 100644
--- a/tests/auto/android/tst_avdmanageroutputparser.cpp
+++ b/tests/auto/android/tst_avdmanageroutputparser.cpp
@@ -58,13 +58,10 @@ void tst_AvdManagerOutputParser::parse_data()
<< AndroidDeviceInfoList({{"",
"Test",
{"x86"},
- "Google APIs (Google Inc.)",
- "Galaxy Nexus (Google)",
- "",
- "512 MB",
-1,
IDevice::DeviceConnected,
- IDevice::Emulator}})
+ IDevice::Emulator,
+ Utils::FilePath::fromString(":Test.avd")}})
<< QStringList();
QTest::newRow("two") << "Available Android Virtual Devices:\n"
@@ -84,23 +81,18 @@ void tst_AvdManagerOutputParser::parse_data()
<< AndroidDeviceInfoList({{"",
"Test",
{"x86"},
- "Google APIs (Google Inc.)",
- "Galaxy Nexus (Google)",
- "",
- "512 MB",
-1,
IDevice::DeviceConnected,
- IDevice::Emulator},
+ IDevice::Emulator,
+ Utils::FilePath::fromString(":Test.avd")},
{"",
"TestTablet",
{"x86"},
- "Google APIs (Google Inc.)",
- "7in WSVGA (Tablet) (Generic)",
- "",
- "256 MB",
-1,
IDevice::DeviceConnected,
- IDevice::Emulator}})
+ IDevice::Emulator,
+ Utils::FilePath::fromString(":TestTablet.avd")}}
+ )
<< QStringList();
}
@@ -116,6 +108,6 @@ void tst_AvdManagerOutputParser::parse()
QCOMPARE(avdErrorPaths, errorPaths);
}
-QTEST_MAIN(tst_AvdManagerOutputParser)
+QTEST_GUILESS_MAIN(tst_AvdManagerOutputParser)
#include "tst_avdmanageroutputparser.moc"
diff --git a/tests/auto/auto.qbs b/tests/auto/auto.qbs
index 6526653ab8e..7027997423a 100644
--- a/tests/auto/auto.qbs
+++ b/tests/auto/auto.qbs
@@ -20,7 +20,6 @@ Project {
"qml/qml.qbs",
"runextensions/runextensions.qbs",
"sdktool/sdktool.qbs",
- "ssh/ssh.qbs",
"toolchaincache/toolchaincache.qbs",
"tracing/tracing.qbs",
"treeviewfind/treeviewfind.qbs",
diff --git a/tests/auto/changeset/tst_changeset.cpp b/tests/auto/changeset/tst_changeset.cpp
index 5d5b6ed35a7..7c1ca1209f5 100644
--- a/tests/auto/changeset/tst_changeset.cpp
+++ b/tests/auto/changeset/tst_changeset.cpp
@@ -435,6 +435,6 @@ void tst_ChangeSet::conflicts()
}
}
-QTEST_MAIN(tst_ChangeSet)
+QTEST_GUILESS_MAIN(tst_ChangeSet)
#include "tst_changeset.moc"
diff --git a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
index d98dc3e21e2..d14c6eba39a 100644
--- a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
+++ b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
@@ -2221,7 +2221,7 @@ void tst_CodeFormatter::structuredBinding()
checkIndent(data);
}
-QTEST_MAIN(tst_CodeFormatter)
+QTEST_GUILESS_MAIN(tst_CodeFormatter)
#include "tst_codeformatter.moc"
diff --git a/tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp b/tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp
index f8808fbaebd..0f45c143222 100644
--- a/tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp
+++ b/tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp
@@ -1154,5 +1154,5 @@ void tst_CppSelectionChanger::testWholeDocumentSelection()
QVERIFY(!result);
}
-QTEST_MAIN(tst_CppSelectionChanger)
+QTEST_GUILESS_MAIN(tst_CppSelectionChanger)
#include "tst_cppselectionchangertest.moc"
diff --git a/tests/auto/cplusplus/fileiterationorder/tst_fileiterationorder.cpp b/tests/auto/cplusplus/fileiterationorder/tst_fileiterationorder.cpp
index 46f7a83da82..663b8f86d90 100644
--- a/tests/auto/cplusplus/fileiterationorder/tst_fileiterationorder.cpp
+++ b/tests/auto/cplusplus/fileiterationorder/tst_fileiterationorder.cpp
@@ -98,5 +98,5 @@ void tst_FileIterationOrder::preferWithCommonPrefixToReferenceFilePath()
QCOMPARE(order.toStringList(), expected);
}
-QTEST_MAIN(tst_FileIterationOrder)
+QTEST_GUILESS_MAIN(tst_FileIterationOrder)
#include "tst_fileiterationorder.moc"
diff --git a/tests/auto/cplusplus/misc/tst_misc.cpp b/tests/auto/cplusplus/misc/tst_misc.cpp
index 694594d7d2c..b88e75569b6 100644
--- a/tests/auto/cplusplus/misc/tst_misc.cpp
+++ b/tests/auto/cplusplus/misc/tst_misc.cpp
@@ -279,5 +279,5 @@ void tst_Misc::doNotCrashForInvalidRawString()
doc->check();
}
-QTEST_MAIN(tst_Misc)
+QTEST_GUILESS_MAIN(tst_Misc)
#include "tst_misc.moc"
diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp
index deda2aab2c3..61b2aa3bb48 100644
--- a/tests/auto/cplusplus/semantic/tst_semantic.cpp
+++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp
@@ -210,7 +210,7 @@ void tst_Semantic::function_declaration_1()
QCOMPARE(funTy->argumentCount(), 0);
QCOMPARE(funTy->refQualifier(), Function::NoRefQualifier);
- QVERIFY(decl->name()->isNameId());
+ QVERIFY(decl->name()->asNameId());
const Identifier *funId = decl->name()->asNameId()->identifier();
QVERIFY(funId);
@@ -261,7 +261,7 @@ void tst_Semantic::function_declaration_2()
QCOMPARE(QByteArray(namedTypeId->chars(), namedTypeId->size()),
QByteArray("QString"));
- QVERIFY(decl->name()->isNameId());
+ QVERIFY(decl->name()->asNameId());
const Identifier *funId = decl->name()->asNameId()->identifier();
QVERIFY(funId);
@@ -378,7 +378,7 @@ void tst_Semantic::function_definition_1()
QCOMPARE(funTy->argumentCount(), 0);
QCOMPARE(funTy->refQualifier(), Function::NoRefQualifier);
- QVERIFY(funTy->name()->isNameId());
+ QVERIFY(funTy->name()->asNameId());
const Identifier *funId = funTy->name()->asNameId()->identifier();
QVERIFY(funId);
@@ -1041,5 +1041,5 @@ void tst_Semantic::enum_constantValueNegative()
testEnumaratorDeclarator(e, 3, "1");
}
-QTEST_MAIN(tst_Semantic)
+QTEST_GUILESS_MAIN(tst_Semantic)
#include "tst_semantic.moc"
diff --git a/tests/auto/debugger/CMakeLists.txt b/tests/auto/debugger/CMakeLists.txt
index 5ab4c63f244..8dbf475ca6c 100644
--- a/tests/auto/debugger/CMakeLists.txt
+++ b/tests/auto/debugger/CMakeLists.txt
@@ -51,6 +51,7 @@ if (WITH_DEBUGGER_DUMPERS)
get_target_property(qmake_binary Qt5::qmake IMPORTED_LOCATION)
add_qtc_test(tst_debugger_dumpers
+ EXCLUDE_FROM_PRECHECK
TIMEOUT 0
DEPENDS Qt5::Network Utils
DEFINES
diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp
index 2046b948ee4..f682d6165e6 100644
--- a/tests/auto/debugger/tst_dumpers.cpp
+++ b/tests/auto/debugger/tst_dumpers.cpp
@@ -710,6 +710,12 @@ struct Cxx11Profile : public Profile
{}
};
+struct NonArmProfile : public Profile
+{
+ NonArmProfile()
+ : Profile(QByteArray()) {}
+};
+
struct BoostProfile : public Profile
{
BoostProfile()
@@ -1069,10 +1075,19 @@ public:
return *this;
}
+ const Data &operator+(const NonArmProfile &) const
+ {
+#if defined(__APPLE__) && defined(__aarch64__)
+ disabledOnARM = true;
+#endif
+ return *this;
+ }
+
public:
mutable bool useQt = false;
mutable bool useQHash = false;
mutable bool useBoost = false;
+ mutable bool disabledOnARM = false;
mutable int engines = AllEngines;
mutable int skipLevels = 0; // Levels to go 'up' before dumping variables.
mutable bool glibcxxDebug = false;
@@ -1339,6 +1354,9 @@ void tst_Dumpers::dumper()
+ QByteArray::number(data.neededLldbVersion.max)));
}
+ if (data.disabledOnARM)
+ MSKIP_SINGLE(QByteArray("Test disabled on arm macOS"));
+
QByteArray output;
QByteArray error;
@@ -3918,6 +3936,28 @@ void tst_Dumpers::dumper_data()
+ Check("empty", "(null)", "@QStringView");
+ QTest::newRow("QAnyStringView")
+ << Data("#include <QString>\n",
+
+ "QString s = \"Hi QString\";\n"
+ "QLatin1String l1 = QLatin1String(\"Hi QLatin1String\");\n"
+ "const char u8[] = \"Hi Yöü\";\n"
+ "const char asc[] = \"Hi Ascii\";\n"
+ "QAnyStringView v_s(s);\n"
+ "QAnyStringView v_l1(l1);\n"
+ "QAnyStringView v_u8(u8);\n"
+ "QAnyStringView v_asc(asc);\n",
+
+ "&v_s, &v_l1, &v_asc, &v_u8")
+
+ + CoreProfile()
+ + QtVersion(0x60200)
+
+ + Check("v_s", "\"Hi QString\"", "@QAnyStringView")
+ + Check("v_l1", "\"Hi QLatin1String\"", "@QAnyStringView")
+ + Check("v_u8", "\"Hi Yöü\"", "@QAnyStringView")
+ + Check("v_asc", "\"Hi Ascii\"", "@QAnyStringView");
+
QTest::newRow("QText")
<< Data("#include <QApplication>\n"
"#include <QTextCursor>\n"
@@ -4211,7 +4251,7 @@ void tst_Dumpers::dumper_data()
//+ Check("var72", "", "@QVariant (QRegion)") FIXME
+ Check("var73", "", "@QVariant (QBitmap)")
+ Check("var74", "", "@QVariant (QCursor)")
- + Check("var75", "", "@QVariant (QKeySequence)") % NoLldbEngine // FIXME
+ + Check("var75", "(0x0, 0x0, 0x0, 0x0)", "@QVariant (QKeySequence)")
+ Check("var76", "", "@QVariant (QPen)")
+ Check("var77", "", "@QVariant (QTextLength)")
//+ Check("var78", Value5(""), "@QVariant (QTextFormat)")
@@ -6081,6 +6121,29 @@ void tst_Dumpers::dumper_data()
+ Check("watch.1.12", "s.front", "13", "unsigned int") % GdbEngine;
+ QTest::newRow("Bitfield2")
+ << Data("#include <QList>\n\n"
+ "struct Entry\n"
+ "{\n"
+ " Entry(bool x) : enabled(x) {}\n"
+ " bool enabled : 1;\n"
+ " bool autorepeat : 1;\n"
+ " signed int id;\n"
+ "};\n",
+
+ "QList<Entry> list;\n"
+ "list.append(Entry(true));\n"
+ "list.append(Entry(false));\n",
+
+ "&list")
+
+ + CoreProfile()
+ + Check("list.0.enabled", "1", "bool : 1") % NoCdbEngine
+ + Check("list.0.enabled", "1", "bool") % CdbEngine
+ + Check("list.1.enabled", "0", "bool : 1") % NoCdbEngine
+ + Check("list.1.enabled", "0", "bool") % CdbEngine;
+
+
QTest::newRow("Function")
<< Data("#include <QByteArray>\n"
"struct Function\n"
@@ -6572,6 +6635,7 @@ void tst_Dumpers::dumper_data()
"&i, &sseA, &sseB")
+ Profile("QMAKE_CXXFLAGS += -msse2")
+ + NonArmProfile()
+ Check("sseA", AnyValue, "__m128")
+ Check("sseA.2", "[2]", FloatValue("4"), "float")
diff --git a/tests/auto/debugger/tst_gdb.cpp b/tests/auto/debugger/tst_gdb.cpp
index 6de43aa3da8..57f6858a2ea 100644
--- a/tests/auto/debugger/tst_gdb.cpp
+++ b/tests/auto/debugger/tst_gdb.cpp
@@ -114,6 +114,10 @@ void tst_gdb::version_data()
<< "GNU gdb (GDB) 7.3 qnx (rev. 613)"
<< 70300 << 613 << false << true;
+ QTest::newRow("QNX71")
+ << "GNU gdb (GDB) 8.2.1 [qnx710 r1469] (STABLE)"
+ << 80201 << 710 << false << true;
+
QTest::newRow("rubenvb")
<< "GNU gdb (rubenvb-4.7.2-release) 7.5.50.20120920-cvs"
<< 70550 << 20120920 << false << false;
diff --git a/tests/auto/diff/differ/tst_differ.cpp b/tests/auto/diff/differ/tst_differ.cpp
index 821bcc3dcf7..42f41348c86 100644
--- a/tests/auto/diff/differ/tst_differ.cpp
+++ b/tests/auto/diff/differ/tst_differ.cpp
@@ -795,8 +795,7 @@ void tst_Differ::cleanupSemanticsLossless()
QCOMPARE(result, expected);
}
-
-QTEST_MAIN(tst_Differ)
+QTEST_GUILESS_MAIN(tst_Differ)
#include "tst_differ.moc"
diff --git a/tests/auto/environment/tst_environment.cpp b/tests/auto/environment/tst_environment.cpp
index 71614400d6e..1ee17dec817 100644
--- a/tests/auto/environment/tst_environment.cpp
+++ b/tests/auto/environment/tst_environment.cpp
@@ -349,6 +349,6 @@ void tst_Environment::find()
}
-QTEST_MAIN(tst_Environment)
+QTEST_GUILESS_MAIN(tst_Environment)
#include "tst_environment.moc"
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.h b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.h
index 4b19bf1edfb..7ef8965f46e 100644
--- a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.h
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/plugin1.h
@@ -29,6 +29,8 @@
#if defined(PLUGIN1_LIBRARY)
# define PLUGIN1_EXPORT Q_DECL_EXPORT
+#elif defined(PLUGIN1_STATIC_LIBRARY)
+# define PLUGIN1_EXPORT
#else
# define PLUGIN1_EXPORT Q_DECL_IMPORT
#endif
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.h b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.h
index dcb6e88e9ea..3bf5b22c3ad 100644
--- a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.h
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/plugin2.h
@@ -29,6 +29,8 @@
#if defined(PLUGIN2_LIBRARY)
# define PLUGIN2_EXPORT Q_DECL_EXPORT
+#elif defined(PLUGIN2_STATIC_LIBRARY)
+# define PLUGIN2_EXPORT
#else
# define PLUGIN2_EXPORT Q_DECL_IMPORT
#endif
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.h b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.h
index 39acae592ab..8c9a2e7ce0c 100644
--- a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.h
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/plugin3.h
@@ -32,6 +32,8 @@
#if defined(PLUGIN3_LIBRARY)
# define PLUGIN3_EXPORT Q_DECL_EXPORT
+#elif defined(PLUGIN3_STATIC_LIBRARY)
+# define PLUGIN3_EXPORT
#else
# define PLUGIN3_EXPORT Q_DECL_IMPORT
#endif
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.h b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.h
index eaec46856f0..397d262e6c8 100644
--- a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.h
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/plugin1.h
@@ -29,6 +29,8 @@
#if defined(PLUGIN1_LIBRARY)
# define PLUGIN1_EXPORT Q_DECL_EXPORT
+#elif defined(PLUGIN1_STATIC_LIBRARY)
+# define PLUGIN1_EXPORT
#else
# define PLUGIN1_EXPORT Q_DECL_IMPORT
#endif
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.h b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.h
index 8d99fce4f6d..747626a4944 100644
--- a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.h
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/plugin2.h
@@ -29,6 +29,8 @@
#if defined(PLUGIN2_LIBRARY)
# define PLUGIN2_EXPORT Q_DECL_EXPORT
+#elif defined(PLUGIN2_STATIC_LIBRARY)
+# define PLUGIN2_EXPORT
#else
# define PLUGIN2_EXPORT Q_DECL_IMPORT
#endif
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.h b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.h
index 3d5d21d44cb..f71ba5ef733 100644
--- a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.h
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/plugin3.h
@@ -29,6 +29,8 @@
#if defined(PLUGIN3_LIBRARY)
# define PLUGIN3_EXPORT Q_DECL_EXPORT
+#elif defined(PLUGIN3_STATIC_LIBRARY)
+# define PLUGIN3_EXPORT
#else
# define PLUGIN3_EXPORT Q_DECL_IMPORT
#endif
diff --git a/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp b/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp
index 4b55043f968..523330deb60 100644
--- a/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp
+++ b/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp
@@ -212,7 +212,7 @@ void tst_PluginManager::correctPlugins1()
QVERIFY(plugin3running);
}
-QTEST_MAIN(tst_PluginManager)
+QTEST_GUILESS_MAIN(tst_PluginManager)
#include "tst_pluginmanager.moc"
diff --git a/tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt b/tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt
index a77550fa468..bd701ac2433 100644
--- a/tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt
+++ b/tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt
@@ -4,7 +4,7 @@ if(APPLE)
elseif(UNIX)
set(plugin_output_name "libtest")
else()
- set(plugin_output_name "testd")
+ set(plugin_output_name "test$<$<CONFIG:Debug>:d>")
endif()
file(RELATIVE_PATH TEST_PLUGIN_PATH ${QtCreator_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp b/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp
index a0ada8154a1..7a2d2ef05bb 100644
--- a/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp
+++ b/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp
@@ -338,6 +338,6 @@ void tst_PluginSpec::initializeExtensions()
QVERIFY(isExtensionsInitialized);
}
-QTEST_MAIN(tst_PluginSpec)
+QTEST_GUILESS_MAIN(tst_PluginSpec)
#include "tst_pluginspec.moc"
diff --git a/tests/auto/externaltool/CMakeLists.txt b/tests/auto/externaltool/CMakeLists.txt
index 944c3dc671c..c897bd6e8ac 100644
--- a/tests/auto/externaltool/CMakeLists.txt
+++ b/tests/auto/externaltool/CMakeLists.txt
@@ -2,6 +2,4 @@ add_qtc_test(tst_externaltooltest
DEPENDS Core app_version
SOURCES
tst_externaltooltest.cpp
- "${PROJECT_SOURCE_DIR}/src/plugins/coreplugin/externaltool.cpp"
- "${PROJECT_SOURCE_DIR}/src/plugins/coreplugin/externaltool.h"
)
diff --git a/tests/auto/externaltool/externaltool.qbs b/tests/auto/externaltool/externaltool.qbs
index 932ad725fb7..74dcdfefa7d 100644
--- a/tests/auto/externaltool/externaltool.qbs
+++ b/tests/auto/externaltool/externaltool.qbs
@@ -6,15 +6,6 @@ QtcAutotest {
Depends { name: "app_version_header" }
Group {
- name: "Duplicated sources from Core plugin" // Ewww. But the .pro file does the same.
- prefix: project.ide_source_tree + "/src/plugins/coreplugin/"
- files: [
- "externaltool.cpp",
- "externaltool.h"
- ]
- }
-
- Group {
name: "Test sources"
files: "tst_externaltooltest.cpp"
}
diff --git a/tests/auto/externaltool/tst_externaltooltest.cpp b/tests/auto/externaltool/tst_externaltooltest.cpp
index e7addf7a10c..dbd60bc8e34 100644
--- a/tests/auto/externaltool/tst_externaltooltest.cpp
+++ b/tests/auto/externaltool/tst_externaltooltest.cpp
@@ -28,7 +28,7 @@
#include <coreplugin/externaltool.h>
-using namespace Core::Internal;
+using namespace Core;
using namespace Utils;
static const char TEST_XML1[] =
diff --git a/tests/auto/filesearch/tst_filesearch.cpp b/tests/auto/filesearch/tst_filesearch.cpp
index 373981274e5..0139ff90b6a 100644
--- a/tests/auto/filesearch/tst_filesearch.cpp
+++ b/tests/auto/filesearch/tst_filesearch.cpp
@@ -146,6 +146,6 @@ void tst_FileSearch::matchCaseReplacement()
QCOMPARE(Utils::matchCaseReplacement("pReFiXTeStPaDSuFfIx", "prefixfoobarsuffix"), QString("pReFiXfoobarSuFfIx")); //mixed case, use replacement as specified
}
-QTEST_MAIN(tst_FileSearch)
+QTEST_GUILESS_MAIN(tst_FileSearch)
#include "tst_filesearch.moc"
diff --git a/tests/auto/json/tst_json.cpp b/tests/auto/json/tst_json.cpp
index cb38a70489a..5733a1eef41 100644
--- a/tests/auto/json/tst_json.cpp
+++ b/tests/auto/json/tst_json.cpp
@@ -2487,7 +2487,8 @@ void tst_Json::unicodeKeys()
JsonObject o = doc.object();
QCOMPARE(o.keys().size(), size_t(5));
- Q_FOREACH (const std::string &k, o.keys()) {
+ const JsonObject::Keys keys = o.keys();
+ for (const std::string &k : keys) {
QByteArray key(k.data());
std::string suffix = key.mid(key.indexOf('_')).data();
QCOMPARE(o[key.data()].toString(), "hello" + suffix);
@@ -2526,6 +2527,6 @@ void tst_Json::removeNonLatinKey()
QVERIFY(restoredObject.contains(nonLatinKeyName));
}
-QTEST_MAIN(tst_Json)
+QTEST_GUILESS_MAIN(tst_Json)
#include "tst_json.moc"
diff --git a/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp b/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp
index 20fb60cd538..d2b2cc72bfe 100644
--- a/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp
+++ b/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp
@@ -26,8 +26,8 @@
#include <languageserverprotocol/basemessage.h>
#include <languageserverprotocol/jsonobject.h>
#include <languageserverprotocol/jsonrpcmessages.h>
-#include <utils/mimetypes/mimetype.h>
-#include <utils/mimetypes/mimedatabase.h>
+
+#include <utils/hostosinfo.h>
#include <QTextCodec>
#include <QtTest>
@@ -36,7 +36,6 @@ using namespace LanguageServerProtocol;
Q_DECLARE_METATYPE(QTextCodec *)
Q_DECLARE_METATYPE(BaseMessage)
-Q_DECLARE_METATYPE(JsonRpcMessage)
Q_DECLARE_METATYPE(DocumentUri)
Q_DECLARE_METATYPE(Range)
@@ -74,7 +73,7 @@ private:
void tst_LanguageServerProtocol::initTestCase()
{
- defaultMimeType = JsonRpcMessageHandler::jsonRpcMimeType();
+ defaultMimeType = JsonRpcMessage::jsonRpcMimeType();
defaultCodec = QTextCodec::codecForName("utf-8");
}
@@ -360,7 +359,7 @@ void tst_LanguageServerProtocol::baseMessageToData()
QFETCH(BaseMessage, message);
QFETCH(QByteArray, data);
- QCOMPARE(message.toData(), data);
+ QCOMPARE(message.header() + message.content, data);
}
void tst_LanguageServerProtocol::fromJsonValue()
@@ -449,13 +448,13 @@ void tst_LanguageServerProtocol::toJsonObject()
QFETCH(bool, error);
QFETCH(QJsonObject, expected);
- QString parseError;
- const QJsonObject object = JsonRpcMessageHandler::toJsonObject(content, codec, parseError);
+ BaseMessage baseMessage(JsonRpcMessage::jsonRpcMimeType(), content, content.length(), codec);
+ JsonRpcMessage jsonRpcMessage(baseMessage);
- if (!error && !parseError.isEmpty())
- QFAIL(parseError.toLocal8Bit().data());
- QCOMPARE(object, expected);
- QCOMPARE(!parseError.isEmpty(), error);
+ if (!error && !jsonRpcMessage.parseError().isEmpty())
+ QFAIL(jsonRpcMessage.parseError().toLocal8Bit().data());
+ QCOMPARE(jsonRpcMessage.toJsonObject(), expected);
+ QCOMPARE(!jsonRpcMessage.parseError().isEmpty(), error);
}
void tst_LanguageServerProtocol::jsonMessageToBaseMessage_data()
@@ -464,11 +463,11 @@ void tst_LanguageServerProtocol::jsonMessageToBaseMessage_data()
QTest::addColumn<BaseMessage>("baseMessage");
QTest::newRow("empty object") << JsonRpcMessage(QJsonObject())
- << BaseMessage(JsonRpcMessageHandler::jsonRpcMimeType(),
+ << BaseMessage(JsonRpcMessage::jsonRpcMimeType(),
"{}");
- QTest::newRow("key value pair") << JsonRpcMessage({{"key", "value"}})
- << BaseMessage(JsonRpcMessageHandler::jsonRpcMimeType(),
+ QTest::newRow("key value pair") << JsonRpcMessage(QJsonObject{{"key", "value"}})
+ << BaseMessage(JsonRpcMessage::jsonRpcMimeType(),
R"({"key":"value"})");
}
@@ -597,6 +596,6 @@ void tst_LanguageServerProtocol::range()
QCOMPARE(r2.contains(r1), r2Containsr1);
}
-QTEST_MAIN(tst_LanguageServerProtocol)
+QTEST_GUILESS_MAIN(tst_LanguageServerProtocol)
#include "tst_languageserverprotocol.moc"
diff --git a/tests/auto/mapreduce/tst_mapreduce.cpp b/tests/auto/mapreduce/tst_mapreduce.cpp
index 60f1ebc0023..cc3620c8cf5 100644
--- a/tests/auto/mapreduce/tst_mapreduce.cpp
+++ b/tests/auto/mapreduce/tst_mapreduce.cpp
@@ -363,6 +363,6 @@ void tst_MapReduce::moveOnlyType()
#endif
-QTEST_MAIN(tst_MapReduce)
+QTEST_GUILESS_MAIN(tst_MapReduce)
#include "tst_mapreduce.moc"
diff --git a/tests/auto/pointeralgorithm/tst_pointeralgorithm.cpp b/tests/auto/pointeralgorithm/tst_pointeralgorithm.cpp
index d160768c5fc..142b8ef4db6 100644
--- a/tests/auto/pointeralgorithm/tst_pointeralgorithm.cpp
+++ b/tests/auto/pointeralgorithm/tst_pointeralgorithm.cpp
@@ -319,6 +319,6 @@ void tst_PointerAlgorithm::takeOrDefault()
}
}
-QTEST_MAIN(tst_PointerAlgorithm)
+QTEST_GUILESS_MAIN(tst_PointerAlgorithm)
#include "tst_pointeralgorithm.moc"
diff --git a/tests/auto/profilewriter/tst_profilewriter.cpp b/tests/auto/profilewriter/tst_profilewriter.cpp
index 62b375aaa7a..3be0fedaf11 100644
--- a/tests/auto/profilewriter/tst_profilewriter.cpp
+++ b/tests/auto/profilewriter/tst_profilewriter.cpp
@@ -744,6 +744,5 @@ void tst_ProFileWriter::removeFiles()
QCOMPARE(lines.join(QLatin1Char('\n')), output);
}
-
-QTEST_MAIN(tst_ProFileWriter)
+QTEST_GUILESS_MAIN(tst_ProFileWriter)
#include "tst_profilewriter.moc"
diff --git a/tests/auto/qml/codemodel/check/CMakeLists.txt b/tests/auto/qml/codemodel/check/CMakeLists.txt
index 462c2765171..ad78f01f5b7 100644
--- a/tests/auto/qml/codemodel/check/CMakeLists.txt
+++ b/tests/auto/qml/codemodel/check/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_test(tst_qml_check
+ EXCLUDE_FROM_PRECHECK
DEPENDS QmlJS QmlJSTools ExtensionSystem Utils
DEFINES
QT_CREATOR
diff --git a/tests/auto/qml/codemodel/check/tst_check.cpp b/tests/auto/qml/codemodel/check/tst_check.cpp
index 45d3d11880c..07bb0146c8b 100644
--- a/tests/auto/qml/codemodel/check/tst_check.cpp
+++ b/tests/auto/qml/codemodel/check/tst_check.cpp
@@ -225,6 +225,6 @@ void tst_Check::test()
}
}
-QTEST_MAIN(tst_Check);
+QTEST_GUILESS_MAIN(tst_Check);
#include "tst_check.moc"
diff --git a/tests/auto/qml/codemodel/dependencies/CMakeLists.txt b/tests/auto/qml/codemodel/dependencies/CMakeLists.txt
index 43e915176a0..606663fb2c7 100644
--- a/tests/auto/qml/codemodel/dependencies/CMakeLists.txt
+++ b/tests/auto/qml/codemodel/dependencies/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_test(tst_qml_dependencies
+ EXCLUDE_FROM_PRECHECK
DEPENDS QmlJS QmlJSTools ExtensionSystem Utils
INCLUDES "${PROJECT_SOURCE_DIR}/src/plugins"
DEFINES
diff --git a/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp b/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
index e2c5edc6bfd..26900bb68bf 100644
--- a/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
+++ b/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
@@ -181,6 +181,6 @@ void tst_Dependencies::test()
QCOMPARE(semanticInfo.staticAnalysisMessages.length(), nExpectedStaticMessages);
}
-QTEST_MAIN(tst_Dependencies)
+QTEST_GUILESS_MAIN(tst_Dependencies)
#include "tst_dependencies.moc"
diff --git a/tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp b/tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp
index ea530d21437..153a3fa8a02 100644
--- a/tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp
+++ b/tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp
@@ -207,6 +207,6 @@ void tst_Ecmascript::test()
QCOMPARE(semanticInfo.staticAnalysisMessages.length(), nExpectedStaticMessages);
}
-QTEST_MAIN(tst_Ecmascript)
+QTEST_GUILESS_MAIN(tst_Ecmascript)
#include "tst_ecmascript7.moc"
diff --git a/tests/auto/qml/codemodel/importscheck/CMakeLists.txt b/tests/auto/qml/codemodel/importscheck/CMakeLists.txt
index a7c10f9d5e2..60a22d77696 100644
--- a/tests/auto/qml/codemodel/importscheck/CMakeLists.txt
+++ b/tests/auto/qml/codemodel/importscheck/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_test(tst_qml_importscheck
+ EXCLUDE_FROM_PRECHECK
DEPENDS QmlJS QmlJSTools Utils CPlusPlus
INCLUDES "${PROJECT_SOURCE_DIR}/src/plugins"
DEFINES
diff --git a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
index 04660c7a9c7..d5cdce65031 100644
--- a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
+++ b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
@@ -414,7 +414,7 @@ int main(int argc, char *argv[])
#else
-QTEST_MAIN(tst_ImportCheck)
+QTEST_GUILESS_MAIN(tst_ImportCheck)
#endif // MANUAL_IMPORT_SCANNER
diff --git a/tests/auto/qml/persistenttrie/tst_testtrie.cpp b/tests/auto/qml/persistenttrie/tst_testtrie.cpp
index 0b78c28d34a..6d607aa4997 100644
--- a/tests/auto/qml/persistenttrie/tst_testtrie.cpp
+++ b/tests/auto/qml/persistenttrie/tst_testtrie.cpp
@@ -363,7 +363,7 @@ int main(int , const char *[])
#else
-QTEST_MAIN(tst_TestTrie);
+QTEST_GUILESS_MAIN(tst_TestTrie);
//#include "moc_tst_testtrie.cpp"
diff --git a/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt b/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt
index f81c14c74fa..349a721d9e1 100644
--- a/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt
+++ b/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt
@@ -1,4 +1,6 @@
add_qtc_test(tst_qml_testcore
+ EXCLUDE_FROM_PRECHECK
+ CONDITION TARGET QmlProjectManager
DEFINES
QT_CREATOR
QMLDESIGNER_TEST
diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp
index b6ff4903c43..7c79a32dd18 100644
--- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp
+++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp
@@ -170,7 +170,8 @@ tst_TestCore::tst_TestCore()
: QObject()
{
QLoggingCategory::setFilterRules(QStringLiteral("qtc.qmljs.imports=false"));
- QLoggingCategory::setFilterRules(QStringLiteral("*.info=false\n*.debug=false\n*.warning=false"));
+ //QLoggingCategory::setFilterRules(QStringLiteral("*.info=false\n*.debug=false\n*.warning=false"));
+ QLoggingCategory::setFilterRules(QStringLiteral("*.warning=false"));
}
void tst_TestCore::initTestCase()
@@ -1248,6 +1249,217 @@ void tst_TestCore::testRewriterReparentToNewNode()
QCOMPARE(testRewriterView->allModelNodes().count(), 8);
}
+void tst_TestCore::testRewriterBehaivours()
+{
+ const QLatin1String qmlString("\n"
+ "import QtQuick 2.0\n"
+ "\n"
+ "Item {\n"
+ " Item {}\n"
+ " Item {}\n"
+ " Behavior on width {\n"
+ " NumberAnimation { duration: 1000 }\n"
+ " }\n"
+ " Item {}\n"
+ "}\n");
+
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ NotIndentingTextEditModifier modifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("QtQuick.Rectangle"));
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView(0, RewriterView::Amend));
+ testRewriterView->setTextModifier(&modifier);
+ model->attachView(testRewriterView.data());
+
+ //qDebug() << testRewriterView->errors().first().toString();
+ QVERIFY(testRewriterView->errors().isEmpty());
+
+ ModelNode rootModelNode = testRewriterView->rootModelNode();
+ QVERIFY(rootModelNode.isValid());
+
+ const QList<ModelNode> children = rootModelNode.directSubModelNodes();
+
+ QCOMPARE(children.count(), 4);
+
+ ModelNode behavior;
+ for (const ModelNode &child : children) {
+ if (child.type() == "QtQuick.Behavior")
+ behavior = child;
+ }
+
+ QVERIFY(behavior.isValid());
+ QVERIFY(!behavior.behaviorPropertyName().isEmpty());
+ QCOMPARE(behavior.behaviorPropertyName(), "width");
+
+ QVERIFY(!behavior.directSubModelNodes().isEmpty());
+
+ ModelNode animation = behavior.directSubModelNodes().first();
+
+ QVERIFY(animation.isValid());
+
+ NodeMetaInfo metaInfo = behavior.metaInfo();
+
+ QVERIFY(metaInfo.isValid());
+
+ ModelNode newBehavior = testRewriterView->createModelNode("QtQuick.Behavior",
+ metaInfo.majorVersion(),
+ metaInfo.minorVersion(),
+ {},
+ {},
+ {},
+ ModelNode::NodeWithoutSource,
+ "height");
+
+ rootModelNode.defaultNodeListProperty().reparentHere(newBehavior);
+
+ QCOMPARE(newBehavior.behaviorPropertyName(), "height");
+
+ metaInfo = animation.metaInfo();
+ QVERIFY(metaInfo.isValid());
+ ModelNode newAnimation = testRewriterView->createModelNode(metaInfo.typeName(),
+ metaInfo.majorVersion(),
+ metaInfo.minorVersion());
+
+ newBehavior.defaultNodeListProperty().reparentHere(newAnimation);
+
+ newAnimation.variantProperty("duration").setValue(500);
+
+ const QLatin1String expextedQmlCode(
+ "\nimport QtQuick 2.0\n\n"
+ "Item {\n Item {}\n Item {}\n"
+ " Behavior on width {\n "
+ " NumberAnimation { duration: 1000 }\n"
+ " }\n"
+ " Item {}\n\n"
+ " Behavior on height {\n"
+ " NumberAnimation {\n"
+ " duration: 500\n"
+ " }\n }\n}\n");
+
+
+ QCOMPARE(textEdit.toPlainText(), expextedQmlCode);
+
+ newBehavior.destroy();
+
+ QVERIFY(!newBehavior.isValid());
+}
+
+void tst_TestCore::testRewriterSignalDefinition()
+{
+ const QLatin1String qmlString("\n"
+ "import QtQuick 2.1\n"
+ "\n"
+ "Rectangle {\n"
+ " id: root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " signal testSignal()\n"
+ " signal testSignal2(float i)\n"
+ " Rectangle {\n"
+ " id: rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " signal testSignal\n"
+ " }\n"
+ "}");
+
+
+ QPlainTextEdit textEdit;
+ textEdit.setPlainText(qmlString);
+ NotIndentingTextEditModifier modifier(&textEdit);
+
+ QScopedPointer<Model> model(Model::create("QtQuick.Text"));
+
+ QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+ testRewriterView->setTextModifier(&modifier);
+ model->attachView(testRewriterView.data());
+
+ QVERIFY(testRewriterView->errors().isEmpty());
+
+ ModelNode rootModelNode = testRewriterView->rootModelNode();
+ QVERIFY(rootModelNode.isValid());
+
+ QVERIFY(rootModelNode.hasProperty("testSignal"));
+ QVERIFY(rootModelNode.hasProperty("testSignal2"));
+
+ QVERIFY(rootModelNode.property("testSignal").isSignalDeclarationProperty());
+ QVERIFY(rootModelNode.signalDeclarationProperty("testSignal").isValid());
+ QCOMPARE(rootModelNode.signalDeclarationProperty("testSignal").signature(), "()");
+
+ QVERIFY(rootModelNode.property("testSignal2").isSignalDeclarationProperty());
+ QVERIFY(rootModelNode.signalDeclarationProperty("testSignal2").isValid());
+ QCOMPARE(rootModelNode.signalDeclarationProperty("testSignal2").signature(), "(float i)");
+
+ ModelNode rectangle = testRewriterView->modelNodeForId("rectangle1");
+ QVERIFY(rectangle.isValid());
+
+ QVERIFY(rectangle.hasProperty("testSignal"));
+
+ QVERIFY(rectangle.property("testSignal").isSignalDeclarationProperty());
+ QVERIFY(rectangle.signalDeclarationProperty("testSignal").isValid());
+ QCOMPARE(rectangle.signalDeclarationProperty("testSignal").signature(), "()");
+
+ rootModelNode.signalDeclarationProperty("addedSignal").setSignature("()");
+ rootModelNode.signalDeclarationProperty("addedSignal").setSignature("(real i)");
+
+ const QLatin1String expectedQmlCode(
+ "\nimport QtQuick 2.1\n\n"
+ "Rectangle {\n"
+ " id: root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " signal addedSignal (real i)\n"
+ " signal testSignal()\n"
+ " signal testSignal2(float i)\n"
+ " Rectangle {\n"
+ " id: rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " signal testSignal\n"
+ " }\n}");
+
+ QCOMPARE(textEdit.toPlainText(), expectedQmlCode);
+
+ rootModelNode.removeProperty("addedSignal");
+
+ const QLatin1String expectedQmlCode2(
+ "\nimport QtQuick 2.1\n\n"
+ "Rectangle {\n"
+ " id: root\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " signal testSignal()\n"
+ " signal testSignal2(float i)\n"
+ " Rectangle {\n"
+ " id: rectangle1\n"
+ " x: 10;\n"
+ " y: 10;\n"
+ " signal testSignal\n"
+ " }\n}");
+
+ QCOMPARE(textEdit.toPlainText(), expectedQmlCode2);
+
+ testRewriterView->executeInTransaction("identifer", [rectangle](){
+ ModelNode newRectangle = rectangle.view()->createModelNode(rectangle.type(),
+ rectangle.majorVersion(),
+ rectangle.minorVersion());
+
+ QVERIFY(newRectangle.isValid());
+ newRectangle.signalDeclarationProperty("newSignal").setSignature("()");
+ newRectangle.setIdWithoutRefactoring("newRect");
+ newRectangle.view()->rootModelNode().defaultNodeListProperty().reparentHere(newRectangle);
+ });
+
+ const QString expectedQmlCode3
+ = expectedQmlCode2.chopped(1)
+ + QLatin1String("\n Rectangle {\n id: newRect\n signal newSignal ()\n }\n}");
+
+ QCOMPARE(textEdit.toPlainText(), expectedQmlCode3);
+}
+
void tst_TestCore::testRewriterForGradientMagic()
{
const QLatin1String qmlString("\n"
@@ -6794,6 +7006,29 @@ void tst_TestCore::testModelChangeType()
QCOMPARE(textEdit.toPlainText(), expectedQmlCode2);
}
+void tst_TestCore::testModelSignalDefinition()
+{
+ QScopedPointer<Model> model(createModel("QtQuick.Rectangle", 2, 0));
+ QVERIFY(model.data());
+
+ QScopedPointer<TestView> view(new TestView(model.data()));
+ QVERIFY(view.data());
+ model->attachView(view.data());
+
+ ModelNode rootModelNode(view->rootModelNode());
+ QVERIFY(rootModelNode.isValid());
+
+ QVERIFY(!rootModelNode.hasProperty("mySignal"));
+
+ rootModelNode.signalDeclarationProperty("mySignal").setSignature("()");
+
+ QVERIFY(rootModelNode.hasProperty("mySignal"));
+
+ QVERIFY(rootModelNode.signalDeclarationProperty("mySignal").isValid());
+ QVERIFY(rootModelNode.property("mySignal").isSignalDeclarationProperty());
+ QCOMPARE(rootModelNode.signalDeclarationProperty("mySignal").signature(), "()");
+}
+
void tst_TestCore::testModelDefaultProperties()
{
QScopedPointer<Model> model(createModel("QtQuick.Rectangle", 2, 0));
@@ -7336,7 +7571,7 @@ void tst_TestCore::testRewriterChangeId()
void tst_TestCore::testRewriterRemoveId()
{
- const char* qmlString = "import QtQuick 2.1\nRectangle { id: rect }";
+ const char* qmlString = "import QtQuick 2.1\nRectangle { id: myRect }";
QPlainTextEdit textEdit;
textEdit.setPlainText(QString::fromUtf8(qmlString));
@@ -7355,7 +7590,7 @@ void tst_TestCore::testRewriterRemoveId()
ModelNode rootModelNode(view->rootModelNode());
QVERIFY(rootModelNode.isValid());
- QCOMPARE(rootModelNode.id(), QString("rect"));
+ QCOMPARE(rootModelNode.id(), QString("myRect"));
//
// remove id in text
@@ -8518,7 +8753,7 @@ void tst_TestCore::loadTestFiles()
QCOMPARE(rootModelNode.directSubModelNodes().count(), 4);
QCOMPARE(rootModelNode.variantProperty("width").value().toInt(), 200);
QCOMPARE(rootModelNode.variantProperty("height").value().toInt(), 200);
- QCOMPARE(rootModelNode.id(), QLatin1String("rect"));
+ QCOMPARE(rootModelNode.id(), QLatin1String("myRect"));
QVERIFY(rootModelNode.hasProperty("data"));
QVERIFY(rootModelNode.property("data").isDefaultProperty());
@@ -8800,7 +9035,7 @@ void tst_TestCore::writeAnnotations()
QVERIFY(rootModelNode.isValid());
rootModelNode.setAuxiliaryData("x", 10);
- for (const auto child : rootModelNode.allSubModelNodes()) {
+ for (const auto &child : rootModelNode.allSubModelNodes()) {
child.setAuxiliaryData("x", 10);
child.setAuxiliaryData("test", true);
child.setAuxiliaryData("test2", "string");
diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.h b/tests/auto/qml/qmldesigner/coretests/tst_testcore.h
index 5248763fef9..633731c7c28 100644
--- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.h
+++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.h
@@ -90,6 +90,7 @@ private slots:
void testModelNodeInHierarchy();
void testModelNodeIsAncestorOf();
void testModelChangeType();
+ void testModelSignalDefinition();
//
// unit tests Rewriter
@@ -145,6 +146,8 @@ private slots:
void testRewriterUnicodeChars();
void testRewriterTransactionAddingAfterReparenting();
void testRewriterReparentToNewNode();
+ void testRewriterBehaivours();
+ void testRewriterSignalDefinition();
//
// unit tests QmlModelNodeFacade/QmlModelState
diff --git a/tests/auto/qml/qmldesigner/data/fx/states.qml b/tests/auto/qml/qmldesigner/data/fx/states.qml
index b0dd3f3d386..a37db5b2d4d 100644
--- a/tests/auto/qml/qmldesigner/data/fx/states.qml
+++ b/tests/auto/qml/qmldesigner/data/fx/states.qml
@@ -26,7 +26,7 @@
import QtQuick 2.0
Rectangle {
- id: rect
+ id: myRect
width: 200
height: 200
Text {
@@ -39,7 +39,7 @@ Rectangle {
State {
name: "State1"
PropertyChanges {
- target: rect
+ target: myRect
color: "blue"
}
PropertyChanges {
@@ -50,7 +50,7 @@ Rectangle {
State {
name: "State2"
PropertyChanges {
- target: rect
+ target: myRect
color: "gray"
}
PropertyChanges {
diff --git a/tests/auto/qml/qmldesigner/wizard/CMakeLists.txt b/tests/auto/qml/qmldesigner/wizard/CMakeLists.txt
index a2965b22f1b..9a50fab71be 100644
--- a/tests/auto/qml/qmldesigner/wizard/CMakeLists.txt
+++ b/tests/auto/qml/qmldesigner/wizard/CMakeLists.txt
@@ -8,7 +8,6 @@ add_qtc_test(tst_qml_wizard
DEPENDS Core Utils StudioWelcome ProjectExplorer QmlDesigner Googletest
DEFINES
QT_CREATOR
- QMLDESIGNER_TEST
IDE_PLUGIN_PATH="${PROJECT_BINARY_DIR}/${IDE_PLUGIN_PATH}"
IDE_DATA_PATH="${PROJECT_BINARY_DIR}/${IDE_DATA_PATH}"
TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
diff --git a/tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp b/tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp
index 0c12c15cf25..7b9d733714b 100644
--- a/tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp
+++ b/tests/auto/qml/qmleditor/qmlcodeformatter/tst_qmlcodeformatter.cpp
@@ -1586,7 +1586,7 @@ void tst_QMLCodeFormatter::bug3()
checkIndent(data);
}
-QTEST_MAIN(tst_QMLCodeFormatter)
+QTEST_GUILESS_MAIN(tst_QMLCodeFormatter)
#include "tst_qmlcodeformatter.moc"
diff --git a/tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp b/tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp
index 128bc14c6bc..fd116600d02 100644
--- a/tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp
+++ b/tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp
@@ -248,6 +248,6 @@ void tst_SimpleReader::testBug01()
QCOMPARE(rootNode->propertyNames().count(), 1);
}
-QTEST_MAIN(tst_SimpleReader);
+QTEST_GUILESS_MAIN(tst_SimpleReader);
#include "tst_qmljssimplereader.moc"
diff --git a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
index 571fc96c4f6..551fc1a2d52 100644
--- a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
+++ b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
@@ -253,5 +253,5 @@ void tst_FileFormat::testMainFile()
delete project;
}
-QTEST_MAIN(tst_FileFormat);
+QTEST_GUILESS_MAIN(tst_FileFormat);
#include "tst_fileformat.moc"
diff --git a/tests/auto/qml/reformatter/nullishCoalescing.qml b/tests/auto/qml/reformatter/nullishCoalescing.qml
new file mode 100644
index 00000000000..f4407c0001a
--- /dev/null
+++ b/tests/auto/qml/reformatter/nullishCoalescing.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+
+Item {
+ property string otherString: ""
+ property string aProp: otherString ?? "N/A"
+ property string bProp: otherString?.trim()
+ property int unrelatedProp: 10
+}
diff --git a/tests/auto/qml/reformatter/tst_reformatter.cpp b/tests/auto/qml/reformatter/tst_reformatter.cpp
index 64506195c4a..f6fbe1d6b48 100644
--- a/tests/auto/qml/reformatter/tst_reformatter.cpp
+++ b/tests/auto/qml/reformatter/tst_reformatter.cpp
@@ -116,6 +116,6 @@ void tst_Reformatter::test()
QCOMPARE(sourceLines.size(), newLines.size());
}
-QTEST_MAIN(tst_Reformatter);
+QTEST_GUILESS_MAIN(tst_Reformatter);
#include "tst_reformatter.moc"
diff --git a/tests/auto/runextensions/tst_runextensions.cpp b/tests/auto/runextensions/tst_runextensions.cpp
index fd0c6609d8b..4e06d3e2955 100644
--- a/tests/auto/runextensions/tst_runextensions.cpp
+++ b/tests/auto/runextensions/tst_runextensions.cpp
@@ -631,6 +631,6 @@ void tst_RunExtensions::onResultReady()
}
}
-QTEST_MAIN(tst_RunExtensions)
+QTEST_GUILESS_MAIN(tst_RunExtensions)
#include "tst_runextensions.moc"
diff --git a/tests/auto/sdktool/CMakeLists.txt b/tests/auto/sdktool/CMakeLists.txt
index 4ee183ad3d4..622a2eb6293 100644
--- a/tests/auto/sdktool/CMakeLists.txt
+++ b/tests/auto/sdktool/CMakeLists.txt
@@ -1,6 +1,6 @@
qtc_output_binary_dir(_output_binary_dir)
add_qtc_test(tst_sdktool
- DEPENDS Utils
+ DEPENDS sdktoolLib
DEFINES SDKTOOL_DIR="${_output_binary_dir}/${IDE_LIBEXEC_PATH}"
SOURCES tst_sdktool.cpp
)
diff --git a/tests/auto/sdktool/sdktool.qbs b/tests/auto/sdktool/sdktool.qbs
index c69491d198e..18325929072 100644
--- a/tests/auto/sdktool/sdktool.qbs
+++ b/tests/auto/sdktool/sdktool.qbs
@@ -3,6 +3,8 @@ import qbs.FileInfo
QtcAutotest {
name: "sdktool autotest"
+ Depends { name: "sdktoolLib" }
+
Group {
name: "Test sources"
files: "tst_sdktool.cpp"
diff --git a/tests/auto/sdktool/tst_sdktool.cpp b/tests/auto/sdktool/tst_sdktool.cpp
index 4cb4876dd8a..939870aa919 100644
--- a/tests/auto/sdktool/tst_sdktool.cpp
+++ b/tests/auto/sdktool/tst_sdktool.cpp
@@ -28,27 +28,56 @@
#include <QProcess>
#include <QtTest>
+#ifndef WITH_TESTS
+#define WITH_TESTS
+#endif
+
+#include "addabiflavor.h"
+#include "addcmakeoperation.h"
+#include "adddebuggeroperation.h"
+#include "adddeviceoperation.h"
+#include "addkeysoperation.h"
+#include "addqtoperation.h"
+#include "addtoolchainoperation.h"
+#include "addvalueoperation.h"
+#include "findkeyoperation.h"
+#include "findvalueoperation.h"
+#include "getoperation.h"
+#include "rmcmakeoperation.h"
+#include "rmdebuggeroperation.h"
+#include "rmdeviceoperation.h"
+#include "rmkeysoperation.h"
+#include "rmkitoperation.h"
+#include "rmqtoperation.h"
+#include "rmtoolchainoperation.h"
+#include "addkitoperation.h"
+
class SdktoolTest : public QObject
{
Q_OBJECT
private slots:
- void testSdktool();
+ void test_AddAbiFlavorOperation() { AddAbiFlavor::unittest(); }
+ void test_AddCMakeOperation() { AddCMakeOperation::unittest(); }
+ void test_AddDebuggerOperation() { AddDebuggerOperation::unittest(); }
+ void test_AddDeviceOperation() { AddDeviceOperation::unittest(); }
+ void test_AddKeysOperation() { AddKeysOperation::unittest(); }
+ void test_AddKitOperation() { AddKitOperation::unittest(); }
+ void test_AddQtOperation() { AddQtOperation::unittest(); }
+ void test_AddToolchainOperation() { AddToolChainOperation::unittest(); }
+ void test_AddValueOperation() { AddValueOperation::unittest(); }
+ void test_FindKeyOperation() { FindKeyOperation::unittest(); }
+ void test_FindValueOperation() { FindValueOperation::unittest(); }
+ void test_GetOperation() { GetOperation::unittest(); }
+ void test_RmCMakeOperation() { RmCMakeOperation::unittest(); }
+ void test_RmDebuggerOperation() { RmDebuggerOperation::unittest(); }
+ void test_RmDeviceOperation() { RmDeviceOperation::unittest(); }
+ void test_RmKeysOperation() { RmKeysOperation::unittest(); }
+ void test_RmKitOperation() { RmKitOperation::unittest(); }
+ void test_RmQtOperation() { RmQtOperation::unittest(); }
+ void test_RmToolChainOperation() { RmToolChainOperation::unittest(); }
};
-void SdktoolTest::testSdktool()
-{
- QDir rootDir(SDKTOOL_DIR);
- QProcess process;
- process.start(rootDir.absoluteFilePath(QLatin1String("sdktool")),
- QStringList() << QLatin1String("-test"));
- process.waitForFinished();
- QByteArray output = process.readAllStandardError();
- for (auto line : output.split('\n'))
- qDebug() << line;
- QCOMPARE(process.exitCode(), 0);
-}
-
-QTEST_MAIN(SdktoolTest)
+QTEST_GUILESS_MAIN(SdktoolTest)
#include "tst_sdktool.moc"
diff --git a/tests/auto/ssh/CMakeLists.txt b/tests/auto/ssh/CMakeLists.txt
deleted file mode 100644
index 8dd1915805f..00000000000
--- a/tests/auto/ssh/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
-file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
-
-add_qtc_test(tst_ssh
- DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
- WITH_TESTS
- DEPENDS Utils QtcSsh
- SOURCES tst_ssh.cpp
-)
diff --git a/tests/auto/ssh/ssh.qbs b/tests/auto/ssh/ssh.qbs
deleted file mode 100644
index c4f4fe38c09..00000000000
--- a/tests/auto/ssh/ssh.qbs
+++ /dev/null
@@ -1,17 +0,0 @@
-import qbs.FileInfo
-
-QtcAutotest {
- name: "SSH autotest"
- Depends { name: "QtcSsh" }
- Depends { name: "Utils" }
- files: "tst_ssh.cpp"
- cpp.defines: {
- var defines = base;
- var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
- qtc.ide_libexec_path);
- var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
- defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
- defines.push("WITH_TESTS");
- return defines;
- }
-}
diff --git a/tests/auto/ssh/tst_ssh.cpp b/tests/auto/ssh/tst_ssh.cpp
deleted file mode 100644
index df26047d5bd..00000000000
--- a/tests/auto/ssh/tst_ssh.cpp
+++ /dev/null
@@ -1,594 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include <ssh/sftpsession.h>
-#include <ssh/sftptransfer.h>
-#include <ssh/sshconnection.h>
-#include <ssh/sshremoteprocessrunner.h>
-#include <ssh/sshsettings.h>
-
-#include <utils/algorithm.h>
-#include <utils/environment.h>
-#include <utils/launcherinterface.h>
-#include <utils/qtcprocess.h>
-#include <utils/singleton.h>
-#include <utils/temporarydirectory.h>
-
-#include <QDateTime>
-#include <QDir>
-#include <QEventLoop>
-#include <QRandomGenerator>
-#include <QStringList>
-#include <QTemporaryDir>
-#include <QTimer>
-#include <QtTest>
-
-#include <cstdlib>
-
-using namespace QSsh;
-
-class tst_Ssh : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase();
-
- void errorHandling_data();
- void errorHandling();
- void pristineConnectionObject();
- void remoteProcess_data();
- void remoteProcess();
- void remoteProcessChannels();
- void remoteProcessInput();
- void sftp();
-
- void cleanupTestCase();
-private:
- bool waitForConnection(SshConnection &connection);
-};
-
-void tst_Ssh::initTestCase()
-{
- const SshConnectionParameters params = SshTest::getParameters();
- if (!SshTest::checkParameters(params))
- SshTest::printSetupHelp();
-
- Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
- + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
- Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath()
- + "/qtc-ssh-autotest-XXXXXX");
-}
-
-void tst_Ssh::errorHandling_data()
-{
- QTest::addColumn<QString>("host");
- QTest::addColumn<quint16>("port");
- QTest::addColumn<SshConnectionParameters::AuthenticationType>("authType");
- QTest::addColumn<QString>("user");
- QTest::addColumn<QString>("keyFile");
-
- QTest::newRow("no host")
- << QString("hgdfxgfhgxfhxgfchxgcf") << quint16(12345)
- << SshConnectionParameters::AuthenticationTypeAll << QString("egal") << QString();
- const QString theHost = SshTest::getHostFromEnvironment();
- if (theHost.isEmpty())
- return;
- const quint16 thePort = SshTest::getPortFromEnvironment();
- QTest::newRow("non-existing key file")
- << theHost << thePort << SshConnectionParameters::AuthenticationTypeSpecificKey
- << QString("root") << QString("somefilenamethatwedontexpecttocontainavalidkey");
-}
-
-void tst_Ssh::errorHandling()
-{
- if (SshSettings::sshFilePath().isEmpty())
- QSKIP("No ssh found in PATH - skipping this test.");
-
- QFETCH(QString, host);
- QFETCH(quint16, port);
- QFETCH(SshConnectionParameters::AuthenticationType, authType);
- QFETCH(QString, user);
- QFETCH(QString, keyFile);
- SshConnectionParameters params;
- params.setHost(host);
- params.setPort(port);
- params.setUserName(user);
- params.timeout = 3;
- params.authenticationType = authType;
- params.privateKeyFile = Utils::FilePath::fromString(keyFile);
- SshConnection connection(params);
- QEventLoop loop;
- bool disconnected = false;
- QObject::connect(&connection, &SshConnection::connected, &loop, &QEventLoop::quit);
- QObject::connect(&connection, &SshConnection::errorOccurred, &loop, &QEventLoop::quit);
- QObject::connect(&connection, &SshConnection::disconnected,
- [&disconnected] { disconnected = true; });
- QTimer timer;
- QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
- timer.setSingleShot(true);
- timer.start((params.timeout + 15) * 1000);
- connection.connectToHost();
- loop.exec();
- QVERIFY(timer.isActive());
- const bool expectConnected = !SshSettings::connectionSharingEnabled();
- QCOMPARE(connection.state(), expectConnected ? SshConnection::Connected
- : SshConnection::Unconnected);
- QCOMPARE(connection.errorString().isEmpty(), expectConnected);
- QVERIFY(!disconnected);
-}
-
-void tst_Ssh::pristineConnectionObject()
-{
- QSsh::SshConnection connection((SshConnectionParameters()));
- QCOMPARE(connection.state(), SshConnection::Unconnected);
- QRegularExpression assertToIgnore(
- "SOFT ASSERT: \"state\\(\\) == Connected\" in file .*[/\\\\]sshconnection.cpp, line \\d*");
- QTest::ignoreMessage(QtDebugMsg, assertToIgnore);
- QVERIFY(!connection.createRemoteProcess(""));
- QTest::ignoreMessage(QtDebugMsg, assertToIgnore);
- QVERIFY(!connection.createSftpSession());
-}
-
-void tst_Ssh::remoteProcess_data()
-{
- QTest::addColumn<QByteArray>("commandLine");
- QTest::addColumn<bool>("isBlocking");
- QTest::addColumn<bool>("successExpected");
- QTest::addColumn<bool>("stdoutExpected");
- QTest::addColumn<bool>("stderrExpected");
-
- QTest::newRow("normal cmd") << QByteArray("ls -a /tmp") << false << true << true << false;
- QTest::newRow("failing cmd") << QByteArray("top -n 1") << false << false << false << true;
- QTest::newRow("blocking cmd") << QByteArray("sleep 100") << true << false << false << false;
-}
-
-void tst_Ssh::remoteProcess()
-{
- const SshConnectionParameters params = SshTest::getParameters();
- if (!SshTest::checkParameters(params))
- QSKIP("Insufficient setup - set QTC_SSH_TEST_* variables.");
-
- QFETCH(QByteArray, commandLine);
- QFETCH(bool, isBlocking);
- QFETCH(bool, successExpected);
- QFETCH(bool, stdoutExpected);
- QFETCH(bool, stderrExpected);
-
- QByteArray remoteStdout;
- QByteArray remoteStderr;
- SshRemoteProcessRunner runner;
- QEventLoop loop;
- connect(&runner, &SshRemoteProcessRunner::connectionError, &loop, &QEventLoop::quit);
- connect(&runner, &SshRemoteProcessRunner::processStarted, &loop, &QEventLoop::quit);
- connect(&runner, &SshRemoteProcessRunner::processClosed, &loop, &QEventLoop::quit);
- connect(&runner, &SshRemoteProcessRunner::readyReadStandardOutput,
- [&remoteStdout, &runner] { remoteStdout += runner.readAllStandardOutput(); });
- connect(&runner, &SshRemoteProcessRunner::readyReadStandardError,
- [&remoteStderr, &runner] { remoteStderr += runner.readAllStandardError(); });
- runner.run(QString::fromUtf8(commandLine), params);
- QTimer timer;
- QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
- timer.setSingleShot(true);
- timer.setInterval((params.timeout + 5) * 1000);
- timer.start();
- loop.exec();
- QVERIFY(timer.isActive());
- timer.stop();
- QVERIFY2(runner.lastConnectionErrorString().isEmpty(),
- qPrintable(runner.lastConnectionErrorString()));
- QVERIFY2(runner.processErrorString().isEmpty(), qPrintable(runner.processErrorString()));
- QVERIFY(runner.isProcessRunning()); // Event loop exit should have been triggered by started().
- QVERIFY2(remoteStdout.isEmpty(), remoteStdout.constData());
- QVERIFY2(remoteStderr.isEmpty(), remoteStderr.constData());
-
- SshRemoteProcessRunner killer;
- if (isBlocking)
- killer.run("pkill -f -9 \"" + QString::fromUtf8(commandLine) + '"', params);
-
- timer.start();
- loop.exec();
- QVERIFY(timer.isActive());
- timer.stop();
- QVERIFY(!runner.isProcessRunning());
- QVERIFY2(runner.lastConnectionErrorString().isEmpty(),
- qPrintable(runner.lastConnectionErrorString()));
- if (isBlocking) {
- QVERIFY(runner.processExitStatus() == QProcess::CrashExit
- || runner.processExitCode() != 0);
- } else {
- QCOMPARE(successExpected, runner.processExitCode() == 0);
- }
- QCOMPARE(stdoutExpected, !remoteStdout.isEmpty());
- QCOMPARE(stderrExpected, !remoteStderr.isEmpty());
-}
-
-void tst_Ssh::remoteProcessChannels()
-{
- const SshConnectionParameters params = SshTest::getParameters();
- if (!SshTest::checkParameters(params))
- QSKIP("Insufficient setup - set QTC_SSH_TEST_* variables.");
- SshConnection connection(params);
- QVERIFY(waitForConnection(connection));
-
- static const QByteArray testString("ChannelTest");
- QByteArray remoteStdout;
- QByteArray remoteStderr;
- QByteArray remoteData;
- SshRemoteProcessPtr echoProcess
- = connection.createRemoteProcess("printf " + QString::fromUtf8(testString) + " >&2");
- QEventLoop loop;
- connect(echoProcess.get(), &SshRemoteProcess::done, &loop, &QEventLoop::quit);
- connect(echoProcess.get(), &Utils::QtcProcess::readyReadStandardError,
- [&remoteData, p = echoProcess.get()] { remoteData += p->readAllStandardError(); });
- connect(echoProcess.get(), &SshRemoteProcess::readyReadStandardOutput,
- [&remoteStdout, p = echoProcess.get()] { remoteStdout += p->readAllStandardOutput(); });
- connect(echoProcess.get(), &SshRemoteProcess::readyReadStandardError,
- [&remoteStderr] { remoteStderr = testString; });
- echoProcess->start();
- QTimer timer;
- QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
- timer.setSingleShot(true);
- timer.setInterval((params.timeout + 5) * 1000);
- timer.start();
- loop.exec();
- QVERIFY(timer.isActive());
- timer.stop();
- QVERIFY(!echoProcess->isRunning());
- QCOMPARE(echoProcess->exitStatus(), QProcess::NormalExit);
- QCOMPARE(echoProcess->exitCode(), 0);
- QVERIFY(remoteStdout.isEmpty());
- QCOMPARE(remoteData, testString);
- QCOMPARE(remoteData, remoteStderr);
-}
-
-void tst_Ssh::remoteProcessInput()
-{
- const SshConnectionParameters params = SshTest::getParameters();
- if (!SshTest::checkParameters(params))
- QSKIP("Insufficient setup - set QTC_SSH_TEST_* variables.");
- SshConnection connection(params);
- QVERIFY(waitForConnection(connection));
-
- SshRemoteProcessPtr catProcess = connection.createRemoteProcess("/bin/cat",
- Utils::ProcessMode::Writer);
- QEventLoop loop;
- connect(catProcess.get(), &SshRemoteProcess::started, &loop, &QEventLoop::quit);
- connect(catProcess.get(), &SshRemoteProcess::done, &loop, &QEventLoop::quit);
- QTimer timer;
- QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
- timer.setSingleShot(true);
- timer.setInterval((params.timeout + 5) * 1000);
- timer.start();
- catProcess->start();
- loop.exec();
- QVERIFY(timer.isActive());
- timer.stop();
- QVERIFY(catProcess->isRunning());
-
- static QString testString = "x\r\n";
- connect(catProcess.get(), &Utils::QtcProcess::readyReadStandardOutput, &loop, &QEventLoop::quit);
-
- catProcess->write(testString.toUtf8());
- timer.start();
- loop.exec();
- QVERIFY(timer.isActive());
- timer.stop();
- QVERIFY(catProcess->isRunning());
-
- const QString data = QString::fromUtf8(catProcess->readAllStandardOutput());
- QCOMPARE(data, testString);
- SshRemoteProcessRunner * const killer = new SshRemoteProcessRunner(this);
- killer->run("pkill -9 cat", params);
- timer.start();
- loop.exec();
- QVERIFY(!catProcess->isRunning());
- QVERIFY(catProcess->exitCode() != 0 || catProcess->exitStatus() == QProcess::CrashExit);
-}
-
-void tst_Ssh::sftp()
-{
- // Connect to server
- const SshConnectionParameters params = SshTest::getParameters();
- if (!SshTest::checkParameters(params))
- QSKIP("Insufficient setup - set QTC_SSH_TEST_* variables.");
- SshConnection connection(params);
- QVERIFY(waitForConnection(connection));
-
- const SshConnectionInfo connInfo = connection.connectionInfo();
- QVERIFY(connInfo.isValid());
- QCOMPARE(connInfo.peerPort, params.port());
-
- // Create and upload 1000 small files and one big file
- QTemporaryDir dirForFilesToUpload;
- QTemporaryDir dirForFilesToDownload;
- QTemporaryDir dir2ForFilesToDownload;
- QVERIFY2(dirForFilesToUpload.isValid(), qPrintable(dirForFilesToUpload.errorString()));
- QVERIFY2(dirForFilesToDownload.isValid(), qPrintable(dirForFilesToDownload.errorString()));
- QVERIFY2(dir2ForFilesToDownload.isValid(), qPrintable(dirForFilesToDownload.errorString()));
- static const auto getRemoteFilePath = [](const QString &localFileName) {
- return QString("/tmp/").append(localFileName).append(".upload");
- };
- const auto getDownloadFilePath = [](const QTemporaryDir &dirForFilesToDownload,
- const QString &localFileName) {
- return QString(dirForFilesToDownload.path()).append('/').append(localFileName);
- };
- FilesToTransfer filesToUpload;
- std::srand(QDateTime::currentDateTime().toSecsSinceEpoch());
- for (int i = 0; i < 100; ++i) {
- const QString fileName = "sftptestfile" + QString::number(i + 1);
- QFile file(dirForFilesToUpload.path() + '/' + fileName);
- QVERIFY2(file.open(QIODevice::WriteOnly), qPrintable(file.errorString()));
- int content[1024 / sizeof(int)];
- for (size_t j = 0; j < sizeof content / sizeof content[0]; ++j)
- content[j] = QRandomGenerator::global()->generate();
- file.write(reinterpret_cast<char *>(content), sizeof content);
- file.close();
- QVERIFY2(file.error() == QFile::NoError, qPrintable(file.errorString()));
- filesToUpload << FileToTransfer(file.fileName(), getRemoteFilePath(fileName));
- }
- const QString bigFileName("sftpbigfile");
- QFile bigFile(dirForFilesToUpload.path() + '/' + bigFileName);
- QVERIFY2(bigFile.open(QIODevice::WriteOnly), qPrintable(bigFile.errorString()));
- const int bigFileSize = 100 * 1024 * 1024;
- const int blockSize = 8192;
- const int blockCount = bigFileSize / blockSize;
- for (int block = 0; block < blockCount; ++block) {
- int content[blockSize / sizeof(int)];
- for (size_t j = 0; j < sizeof content / sizeof content[0]; ++j)
- content[j] = QRandomGenerator::global()->generate();
- bigFile.write(reinterpret_cast<char *>(content), sizeof content);
- }
- bigFile.close();
- QVERIFY2(bigFile.error() == QFile::NoError, qPrintable(bigFile.errorString()));
- filesToUpload << FileToTransfer(bigFile.fileName(), getRemoteFilePath(bigFileName));
-
- const SftpTransferPtr upload = connection.createUpload(filesToUpload,
- FileTransferErrorHandling::Abort);
- QString jobError;
- QEventLoop loop;
- connect(upload.get(), &SftpTransfer::done, [&jobError, &loop](const QString &error) {
- jobError = error;
- loop.quit();
- });
- QTimer timer;
- QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
- timer.setSingleShot(true);
- timer.setInterval(30 * 1000);
- timer.start();
- upload->start();
- loop.exec();
- QVERIFY(timer.isActive());
- timer.stop();
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
-
- // Establish interactive SFTP session
- SftpSessionPtr sftpChannel = connection.createSftpSession();
- QList<SftpJobId> jobs;
- bool invalidFinishedSignal = false;
- connect(sftpChannel.get(), &SftpSession::started, &loop, &QEventLoop::quit);
- connect(sftpChannel.get(), &SftpSession::done, &loop, &QEventLoop::quit);
- connect(sftpChannel.get(), &SftpSession::commandFinished,
- [&loop, &jobs, &invalidFinishedSignal, &jobError](SftpJobId job, const QString &error) {
- if (!jobs.removeOne(job)) {
- invalidFinishedSignal = true;
- loop.quit();
- return;
- }
- if (!error.isEmpty()) {
- jobError = error;
- loop.quit();
- return;
- }
- if (jobs.empty())
- loop.quit();
- });
- timer.start();
- sftpChannel->start();
- loop.exec();
- QVERIFY(timer.isActive());
- timer.stop();
- QVERIFY(!invalidFinishedSignal);
- QCOMPARE(sftpChannel->state(), SftpSession::State::Running);
-
- // Download the uploaded files to a different location
- const QStringList allUploadedFileNames
- = QDir(dirForFilesToUpload.path()).entryList(QDir::Files);
- QCOMPARE(allUploadedFileNames.size(), 101);
- for (const QString &fileName : allUploadedFileNames) {
- const QString localFilePath = dirForFilesToUpload.path() + '/' + fileName;
- const QString remoteFilePath = getRemoteFilePath(fileName);
- const QString downloadFilePath = getDownloadFilePath(dirForFilesToDownload, fileName);
- const SftpJobId downloadJob = sftpChannel->downloadFile(remoteFilePath, downloadFilePath);
- QVERIFY(downloadJob != SftpInvalidJob);
- jobs << downloadJob;
- }
- QCOMPARE(jobs.size(), 101);
- loop.exec();
- QVERIFY(!invalidFinishedSignal);
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
- QCOMPARE(sftpChannel->state(), SftpSession::State::Running);
- QVERIFY(jobs.empty());
-
- // Compare contents of uploaded and downloaded files
- bool success;
- const auto compareFiles = [&](const QTemporaryDir &downloadDir) {
- success = false;
- for (const QString &fileName : allUploadedFileNames) {
- QFile originalFile(dirForFilesToUpload.path() + '/' + fileName);
- QVERIFY2(originalFile.open(QIODevice::ReadOnly), qPrintable(originalFile.errorString()));
- QFile downloadedFile(getDownloadFilePath(downloadDir, fileName));
- QVERIFY2(downloadedFile.open(QIODevice::ReadOnly),
- qPrintable(downloadedFile.errorString()));
- QVERIFY(originalFile.fileName() != downloadedFile.fileName());
- QCOMPARE(originalFile.size(), downloadedFile.size());
- qint64 bytesLeft = originalFile.size();
- while (bytesLeft > 0) {
- const qint64 bytesToRead = qMin(bytesLeft, Q_INT64_C(1024 * 1024));
- const QByteArray origBlock = originalFile.read(bytesToRead);
- const QByteArray copyBlock = downloadedFile.read(bytesToRead);
- QCOMPARE(origBlock.size(), bytesToRead);
- QCOMPARE(origBlock, copyBlock);
- bytesLeft -= bytesToRead;
- }
- }
- success = true;
- };
- compareFiles(dirForFilesToDownload);
- QVERIFY(success);
-
- // The same again, with a non-interactive download.
- FilesToTransfer filesToDownload = Utils::transform(filesToUpload, [&](const FileToTransfer &fileToUpload) {
- return FileToTransfer(fileToUpload.targetFile,
- getDownloadFilePath(dir2ForFilesToDownload,
- QFileInfo(fileToUpload.sourceFile).fileName()));
- });
- const SftpTransferPtr download = connection.createDownload(filesToDownload,
- FileTransferErrorHandling::Abort);
- connect(download.get(), &SftpTransfer::done, [&jobError, &loop](const QString &error) {
- jobError = error;
- loop.quit();
- });
- QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
- timer.setSingleShot(true);
- timer.setInterval(30 * 1000);
- timer.start();
- download->start();
- loop.exec();
- QVERIFY(timer.isActive());
- timer.stop();
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
- compareFiles(dir2ForFilesToDownload);
- QVERIFY(success);
-
- // Remove the uploaded files on the remote system
- timer.setInterval((params.timeout + 5) * 1000);
- for (const QString &fileName : allUploadedFileNames) {
- const QString remoteFilePath = getRemoteFilePath(fileName);
- const SftpJobId removeJob = sftpChannel->removeFile(remoteFilePath);
- QVERIFY(removeJob != SftpInvalidJob);
- jobs << removeJob;
- }
- loop.exec();
- QVERIFY(!invalidFinishedSignal);
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
- QCOMPARE(sftpChannel->state(), SftpSession::State::Running);
- QVERIFY(jobs.empty());
-
- // Create a directory on the remote system
- const QString remoteDirPath = "/tmp/sftptest-" + QDateTime::currentDateTime().toString();
- const SftpJobId mkdirJob = sftpChannel->createDirectory(remoteDirPath);
- QVERIFY(mkdirJob != SftpInvalidJob);
- jobs << mkdirJob;
- loop.exec();
- QVERIFY(!invalidFinishedSignal);
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
- QCOMPARE(sftpChannel->state(), SftpSession::State::Running);
- QVERIFY(jobs.empty());
-
- // Retrieve and check the attributes of the remote directory
- QList<SftpFileInfo> remoteFileInfo;
- const auto fileInfoHandler
- = [&remoteFileInfo](SftpJobId, const QList<SftpFileInfo> &fileInfoList) {
- remoteFileInfo << fileInfoList;
- };
- connect(sftpChannel.get(), &SftpSession::fileInfoAvailable, fileInfoHandler);
- const SftpJobId statDirJob = sftpChannel->ls(remoteDirPath + "/..");
- QVERIFY(statDirJob != SftpInvalidJob);
- jobs << statDirJob;
- loop.exec();
- QVERIFY(!invalidFinishedSignal);
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
- QCOMPARE(sftpChannel->state(), SftpSession::State::Running);
- QVERIFY(jobs.empty());
- QVERIFY(!remoteFileInfo.empty());
- SftpFileInfo remoteDirInfo;
- for (const SftpFileInfo &fi : qAsConst(remoteFileInfo)) {
- if (fi.name == QFileInfo(remoteDirPath).fileName()) {
- remoteDirInfo = fi;
- break;
- }
- }
- QCOMPARE(remoteDirInfo.type, FileTypeDirectory);
- QCOMPARE(remoteDirInfo.name, QFileInfo(remoteDirPath).fileName());
-
- // Retrieve and check the contents of the remote directory
- remoteFileInfo.clear();
- const SftpJobId lsDirJob = sftpChannel->ls(remoteDirPath);
- QVERIFY(lsDirJob != SftpInvalidJob);
- jobs << lsDirJob;
- loop.exec();
- QVERIFY(!invalidFinishedSignal);
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
- QCOMPARE(sftpChannel->state(), SftpSession::State::Running);
- QVERIFY(jobs.empty());
- QCOMPARE(remoteFileInfo.size(), 0);
-
- // Remove the remote directory.
- const SftpJobId rmDirJob = sftpChannel->removeDirectory(remoteDirPath);
- QVERIFY(rmDirJob != SftpInvalidJob);
- jobs << rmDirJob;
- loop.exec();
- QVERIFY(!invalidFinishedSignal);
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
- QCOMPARE(sftpChannel->state(), SftpSession::State::Running);
- QVERIFY(jobs.empty());
-
- // Closing down
- sftpChannel->quit();
- QCOMPARE(sftpChannel->state(), SftpSession::State::Closing);
- loop.exec();
- QVERIFY(!invalidFinishedSignal);
- QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
- QCOMPARE(sftpChannel->state(), SftpSession::State::Inactive);
- connect(&connection, &SshConnection::disconnected, &loop, &QEventLoop::quit);
- timer.start();
- connection.disconnectFromHost();
- loop.exec();
- QVERIFY(timer.isActive());
- QCOMPARE(connection.state(), SshConnection::Unconnected);
- QVERIFY2(connection.errorString().isEmpty(), qPrintable(connection.errorString()));
-}
-
-void tst_Ssh::cleanupTestCase()
-{
- Utils::Singleton::deleteAll();
-}
-
-bool tst_Ssh::waitForConnection(SshConnection &connection)
-{
- QEventLoop loop;
- QObject::connect(&connection, &SshConnection::connected, &loop, &QEventLoop::quit);
- QObject::connect(&connection, &SshConnection::errorOccurred, &loop, &QEventLoop::quit);
- connection.connectToHost();
- loop.exec();
- if (!connection.errorString().isEmpty())
- qDebug() << connection.errorString();
- return connection.state() == SshConnection::Connected && connection.errorString().isEmpty();
-}
-
-QTEST_MAIN(tst_Ssh)
-
-#include <tst_ssh.moc>
diff --git a/tests/auto/toolchaincache/tst_toolchaincache.cpp b/tests/auto/toolchaincache/tst_toolchaincache.cpp
index 3e4da445ac6..8fbcb43a23d 100644
--- a/tests/auto/toolchaincache/tst_toolchaincache.cpp
+++ b/tests/auto/toolchaincache/tst_toolchaincache.cpp
@@ -132,5 +132,5 @@ void tst_ToolChainCache::insertOneTwoOneThree()
QVERIFY(!cache.check({"other"}));
}
-QTEST_MAIN(tst_ToolChainCache)
+QTEST_GUILESS_MAIN(tst_ToolChainCache)
#include "tst_toolchaincache.moc"
diff --git a/tests/auto/tracing/flamegraphview/CMakeLists.txt b/tests/auto/tracing/flamegraphview/CMakeLists.txt
index 23f73fde899..e34941bd636 100644
--- a/tests/auto/tracing/flamegraphview/CMakeLists.txt
+++ b/tests/auto/tracing/flamegraphview/CMakeLists.txt
@@ -5,6 +5,7 @@ set(TSTFLAMEGRAPHVIEW_CPP_SOURCES
if(${Qt5_VERSION} VERSION_LESS "6.2.0")
add_qtc_test(tst_tracing_flamegraphview
+ EXCLUDE_FROM_PRECHECK
DEPENDS Tracing Qt5::QuickWidgets Qt5::Quick Utils
SOURCES
${TSTFLAMEGRAPHVIEW_CPP_SOURCES}
@@ -12,6 +13,7 @@ if(${Qt5_VERSION} VERSION_LESS "6.2.0")
)
else() # < Qt 6.2
add_qtc_test(tst_tracing_flamegraphview
+ EXCLUDE_FROM_PRECHECK
DEPENDS Tracing Qt5::QuickWidgets Qt5::Quick Utils
)
diff --git a/tests/auto/tracing/flamegraphview/tst_flamegraphview.cpp b/tests/auto/tracing/flamegraphview/tst_flamegraphview.cpp
index 9e217216870..f7d154cd220 100644
--- a/tests/auto/tracing/flamegraphview/tst_flamegraphview.cpp
+++ b/tests/auto/tracing/flamegraphview/tst_flamegraphview.cpp
@@ -112,20 +112,20 @@ void tst_FlameGraphView::testZoom()
QWindow *window = widget.windowHandle();
QCOMPARE(selectedTypeId(), -1);
- QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(widget.width() - 15,
- widget.height() - 15));
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(widget.width() - 25,
+ widget.height() - 25));
QTRY_VERIFY(selectedTypeId() != -1);
const int typeId1 = selectedTypeId();
- QTest::mouseDClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(15, widget.height() - 15));
+ QTest::mouseDClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(25, widget.height() - 25));
QTRY_VERIFY(selectedTypeId() != typeId1);
QVERIFY(selectedTypeId() != -1);
QTest::mouseDClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(widget.width() / 2,
widget.height() / 2));
QTRY_COMPARE(selectedTypeId(), -1);
- QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(widget.width() - 15,
- widget.height() - 15));
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(widget.width() - 25,
+ widget.height() - 25));
QTRY_COMPARE(selectedTypeId(), typeId1);
}
diff --git a/tests/auto/tracing/timelineabstractrenderer/tst_timelineabstractrenderer.cpp b/tests/auto/tracing/timelineabstractrenderer/tst_timelineabstractrenderer.cpp
index e4f8e7b69d9..d48dd1a1187 100644
--- a/tests/auto/tracing/timelineabstractrenderer/tst_timelineabstractrenderer.cpp
+++ b/tests/auto/tracing/timelineabstractrenderer/tst_timelineabstractrenderer.cpp
@@ -152,6 +152,6 @@ void tst_TimelineAbstractRenderer::dirty()
QVERIFY(!renderer.rowHeightsDirty());
}
-QTEST_MAIN(tst_TimelineAbstractRenderer)
+QTEST_GUILESS_MAIN(tst_TimelineAbstractRenderer)
#include "tst_timelineabstractrenderer.moc"
diff --git a/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp b/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp
index 812f51d2267..4d5e4dd9eef 100644
--- a/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp
+++ b/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp
@@ -483,6 +483,6 @@ void tst_TimelineModel::parentingOfEqualStarts()
QCOMPARE(dummy.lastIndex(2), 1);
}
-QTEST_MAIN(tst_TimelineModel)
+QTEST_GUILESS_MAIN(tst_TimelineModel)
#include "tst_timelinemodel.moc"
diff --git a/tests/auto/tracing/timelinemodelaggregator/tst_timelinemodelaggregator.cpp b/tests/auto/tracing/timelinemodelaggregator/tst_timelinemodelaggregator.cpp
index 7a964edb5ff..a1454c0475f 100644
--- a/tests/auto/tracing/timelinemodelaggregator/tst_timelinemodelaggregator.cpp
+++ b/tests/auto/tracing/timelinemodelaggregator/tst_timelinemodelaggregator.cpp
@@ -162,6 +162,6 @@ void tst_TimelineModelAggregator::prevNext()
}
}
-QTEST_MAIN(tst_TimelineModelAggregator)
+QTEST_GUILESS_MAIN(tst_TimelineModelAggregator)
#include "tst_timelinemodelaggregator.moc"
diff --git a/tests/auto/tracing/timelinenotesmodel/tst_timelinenotesmodel.cpp b/tests/auto/tracing/timelinenotesmodel/tst_timelinenotesmodel.cpp
index dd861cb5a9e..26171c387f8 100644
--- a/tests/auto/tracing/timelinenotesmodel/tst_timelinenotesmodel.cpp
+++ b/tests/auto/tracing/timelinenotesmodel/tst_timelinenotesmodel.cpp
@@ -193,6 +193,6 @@ void tst_TimelineNotesModel::modify()
}
-QTEST_MAIN(tst_TimelineNotesModel)
+QTEST_GUILESS_MAIN(tst_TimelineNotesModel)
#include "tst_timelinenotesmodel.moc"
diff --git a/tests/auto/tracing/timelineoverviewrenderer/tst_timelineoverviewrenderer.cpp b/tests/auto/tracing/timelineoverviewrenderer/tst_timelineoverviewrenderer.cpp
index 0dfed3eec85..8ca225f15d6 100644
--- a/tests/auto/tracing/timelineoverviewrenderer/tst_timelineoverviewrenderer.cpp
+++ b/tests/auto/tracing/timelineoverviewrenderer/tst_timelineoverviewrenderer.cpp
@@ -75,6 +75,6 @@ void tst_TimelineOverviewRenderer::updatePaintNode()
delete node;
}
-QTEST_MAIN(tst_TimelineOverviewRenderer)
+QTEST_GUILESS_MAIN(tst_TimelineOverviewRenderer)
#include "tst_timelineoverviewrenderer.moc"
diff --git a/tests/auto/tracing/timelinerenderer/CMakeLists.txt b/tests/auto/tracing/timelinerenderer/CMakeLists.txt
index 30e44a5cd20..db71a10c4a1 100644
--- a/tests/auto/tracing/timelinerenderer/CMakeLists.txt
+++ b/tests/auto/tracing/timelinerenderer/CMakeLists.txt
@@ -1,4 +1,5 @@
add_qtc_test(tst_tracing_timelinerenderer
+ EXCLUDE_FROM_PRECHECK
DEPENDS Tracing Qt5::Gui Qt5::Quick
SOURCES tst_timelinerenderer.cpp
)
diff --git a/tests/auto/tracing/timelinerenderpass/tst_timelinerenderpass.cpp b/tests/auto/tracing/timelinerenderpass/tst_timelinerenderpass.cpp
index d59fad4284d..6890e521ee3 100644
--- a/tests/auto/tracing/timelinerenderpass/tst_timelinerenderpass.cpp
+++ b/tests/auto/tracing/timelinerenderpass/tst_timelinerenderpass.cpp
@@ -86,7 +86,7 @@ void tst_TimelineRenderPass::emptyState()
QVERIFY(state.expandedRows().isEmpty());
}
-QTEST_MAIN(tst_TimelineRenderPass)
+QTEST_GUILESS_MAIN(tst_TimelineRenderPass)
#include "tst_timelinerenderpass.moc"
diff --git a/tests/auto/tracing/timelinerenderstate/tst_timelinerenderstate.cpp b/tests/auto/tracing/timelinerenderstate/tst_timelinerenderstate.cpp
index 08329bb69af..4fdbb025f5d 100644
--- a/tests/auto/tracing/timelinerenderstate/tst_timelinerenderstate.cpp
+++ b/tests/auto/tracing/timelinerenderstate/tst_timelinerenderstate.cpp
@@ -171,7 +171,7 @@ void tst_TimelineRenderState::assembleNodeTree()
delete node;
}
-QTEST_MAIN(tst_TimelineRenderState)
+QTEST_GUILESS_MAIN(tst_TimelineRenderState)
#include "tst_timelinerenderstate.moc"
diff --git a/tests/auto/tracing/timelinezoomcontrol/tst_timelinezoomcontrol.cpp b/tests/auto/tracing/timelinezoomcontrol/tst_timelinezoomcontrol.cpp
index e57763cf66d..770b1b67c2a 100644
--- a/tests/auto/tracing/timelinezoomcontrol/tst_timelinezoomcontrol.cpp
+++ b/tests/auto/tracing/timelinezoomcontrol/tst_timelinezoomcontrol.cpp
@@ -217,6 +217,6 @@ void tst_TimelineZoomControl::selection()
QCOMPARE(spy.count(), 2);
}
-QTEST_MAIN(tst_TimelineZoomControl)
+QTEST_GUILESS_MAIN(tst_TimelineZoomControl)
#include "tst_timelinezoomcontrol.moc"
diff --git a/tests/auto/updateinfo/tst_updateinfo.cpp b/tests/auto/updateinfo/tst_updateinfo.cpp
index 1fa1686919b..e15c42cb141 100644
--- a/tests/auto/updateinfo/tst_updateinfo.cpp
+++ b/tests/auto/updateinfo/tst_updateinfo.cpp
@@ -27,7 +27,7 @@
#include <updateinfo/updateinfotools.h>
-Q_LOGGING_CATEGORY(log, "qtc.updateinfo", QtWarningMsg)
+Q_LOGGING_CATEGORY(updateLog, "qtc.updateinfo", QtWarningMsg)
class tst_UpdateInfo : public QObject
{
@@ -40,7 +40,8 @@ private slots:
void tst_UpdateInfo::updates_data()
{
- QTest::addColumn<QString>("xml");
+ QTest::addColumn<QString>("updateXml");
+ QTest::addColumn<QString>("packageXml");
QTest::addColumn<QList<Update>>("xupdates");
QTest::addColumn<QList<QtPackage>>("xpackages");
@@ -48,8 +49,8 @@ void tst_UpdateInfo::updates_data()
<< R"raw(<?xml version="1.0"?>
<updates>
<update name="Qt Design Studio 3.2.0" version="3.2.0-0-202203291247" size="3113234690" id="qt.tools.qtdesignstudio"/>
- </updates>
- <?xml version="1.0"?>
+ </updates>)raw"
+ << R"raw(<?xml version="1.0"?>
<availablepackages>
<package name="qt.qt6.621" displayname="Qt 6.2.1" version="6.2.1-0-202110220854"/>
<package name="qt.qt5.5152" displayname="Qt 5.15.2" version="5.15.2-0-202011130607" installedVersion="5.15.2-0-202011130607"/>
@@ -64,14 +65,14 @@ void tst_UpdateInfo::updates_data()
void tst_UpdateInfo::updates()
{
- QFETCH(QString, xml);
+ QFETCH(QString, updateXml);
+ QFETCH(QString, packageXml);
QFETCH(QList<Update>, xupdates);
QFETCH(QList<QtPackage>, xpackages);
- std::unique_ptr<QDomDocument> doc = documentForResponse(xml);
- const QList<Update> updates = availableUpdates(*doc);
+ const QList<Update> updates = availableUpdates(updateXml);
QCOMPARE(updates, xupdates);
- const QList<QtPackage> packages = availableQtPackages(*doc);
+ const QList<QtPackage> packages = availableQtPackages(packageXml);
QCOMPARE(packages, xpackages);
}
diff --git a/tests/auto/utils/CMakeLists.txt b/tests/auto/utils/CMakeLists.txt
index 5680cde7aaf..60dd1cfbccc 100644
--- a/tests/auto/utils/CMakeLists.txt
+++ b/tests/auto/utils/CMakeLists.txt
@@ -9,3 +9,4 @@ add_subdirectory(stringutils)
add_subdirectory(templateengine)
add_subdirectory(treemodel)
add_subdirectory(multicursor)
+add_subdirectory(deviceshell)
diff --git a/tests/auto/utils/deviceshell/CMakeLists.txt b/tests/auto/utils/deviceshell/CMakeLists.txt
new file mode 100644
index 00000000000..e9b52c4ad82
--- /dev/null
+++ b/tests/auto/utils/deviceshell/CMakeLists.txt
@@ -0,0 +1,8 @@
+file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
+file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
+
+add_qtc_test(tst_utils_deviceshell
+ DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
+ DEPENDS Utils app_version
+ SOURCES tst_deviceshell.cpp
+)
diff --git a/tests/auto/utils/deviceshell/deviceshell.qbs b/tests/auto/utils/deviceshell/deviceshell.qbs
new file mode 100644
index 00000000000..207848f00d8
--- /dev/null
+++ b/tests/auto/utils/deviceshell/deviceshell.qbs
@@ -0,0 +1,12 @@
+Project {
+ QtcAutotest {
+ name: "DeviceShell autotest"
+
+ Depends { name: "Utils" }
+ Depends { name: "app_version_header" }
+
+ files: [
+ "tst_deviceshell.cpp",
+ ]
+ }
+}
diff --git a/tests/auto/utils/deviceshell/tst_deviceshell.cpp b/tests/auto/utils/deviceshell/tst_deviceshell.cpp
new file mode 100644
index 00000000000..399a76e1ca6
--- /dev/null
+++ b/tests/auto/utils/deviceshell/tst_deviceshell.cpp
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include <app/app_version.h>
+
+#include <utils/deviceshell.h>
+#include <utils/environment.h>
+#include <utils/hostosinfo.h>
+#include <utils/launcherinterface.h>
+#include <utils/mapreduce.h>
+#include <utils/qtcprocess.h>
+#include <utils/runextensions.h>
+#include <utils/temporarydirectory.h>
+
+#include <QObject>
+#include <QtTest>
+
+using namespace Utils;
+
+class TestShell : public DeviceShell
+{
+public:
+ TestShell(CommandLine cmdLine)
+ : m_cmdLine(std::move(cmdLine))
+ {
+ start();
+ }
+
+private:
+ void setupShellProcess(QtcProcess *shellProcess) override
+ {
+ shellProcess->setCommand(m_cmdLine);
+ }
+
+ CommandLine m_cmdLine;
+};
+
+bool testDocker(const FilePath &executable)
+{
+ QtcProcess p;
+ p.setCommand({executable, {"info", "--format", "{{.OSType}}"}});
+ p.runBlocking();
+ const QString platform = p.cleanedStdOut().trimmed();
+ return p.result() == ProcessResult::FinishedWithSuccess && platform == "linux";
+}
+
+class tst_DeviceShell : public QObject
+{
+ Q_OBJECT
+private:
+ QByteArray m_asciiTestData{256, Qt::Uninitialized};
+
+ QList<CommandLine> m_availableShells;
+ bool m_dockerSetupCheckOk{false};
+
+private:
+ QString testString(int length)
+ {
+ QRandomGenerator generator;
+ QString result;
+ for (int i = 0; i < length; ++i)
+ result.append(QChar{generator.bounded('a', 'z')});
+
+ return result;
+ }
+
+private slots:
+ void initTestCase()
+ {
+ TemporaryDirectory::setMasterTemporaryDirectory(
+ QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX");
+
+ const QString libExecPath(qApp->applicationDirPath() + '/'
+ + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
+ LauncherInterface::setPathToLauncher(libExecPath);
+
+ std::iota(m_asciiTestData.begin(), m_asciiTestData.end(), 0);
+
+ const FilePath dockerExecutable = Environment::systemEnvironment()
+ .searchInPath("docker", {"/usr/local/bin"});
+
+ if (dockerExecutable.exists()) {
+ m_availableShells.append({dockerExecutable, {"run", "-i", "--rm", "alpine"}});
+ if (testDocker(dockerExecutable)) {
+ m_dockerSetupCheckOk = true;
+ } else {
+ // On linux, docker needs some post-install steps: https://docs.docker.com/engine/install/linux-postinstall/
+ // Also check if you can start a simple container from the command line: "docker run -it alpine".
+ qWarning() << "Checking docker failed, tests will be skipped.";
+ }
+ }
+
+ // On older versions of macOS, base64 does not understand "-d" ( only "-D" ), so we skip the tests here.
+ const QVersionNumber osVersionNumber = QVersionNumber::fromString(
+ QSysInfo::productVersion());
+
+ const bool isOldMacOS = Utils::HostOsInfo::isMacHost()
+ && osVersionNumber.majorVersion() <= 10
+ && osVersionNumber.minorVersion() <= 14;
+
+ if (isOldMacOS)
+ qWarning() << "Skipping local tests, as macOS version is <= 10.14";
+
+ if (!Utils::HostOsInfo::isWindowsHost() && !isOldMacOS) {
+ // Windows by default has bash.exe, which does not work unless a working wsl is installed.
+ // Therefore we only test shells on linux / mac hosts.
+ const auto shells = {"dash", "bash", "sh", "zsh"};
+
+ for (const auto &shell : shells) {
+ const FilePath executable = Environment::systemEnvironment()
+ .searchInPath(shell, {"/usr/local/bin"});
+ if (executable.exists())
+ m_availableShells.append({executable, {}});
+ }
+ }
+
+ if (m_availableShells.isEmpty()) {
+ QSKIP("Skipping deviceshell tests, as no compatible shell could be found");
+ }
+ }
+
+ void cleanupTestCase() { Singleton::deleteAll(); }
+
+ void testArguments_data()
+ {
+ QTest::addColumn<CommandLine>("cmdLine");
+ QTest::addColumn<QString>("testData");
+
+ for (const auto &cmdLine : qAsConst(m_availableShells)) {
+ QTest::newRow((cmdLine.executable().baseName() + " : simple").toUtf8())
+ << cmdLine << "Hallo Welt!";
+ QTest::newRow((cmdLine.executable().baseName() + " : japanese").toUtf8())
+ << cmdLine
+ << QString::fromUtf8(u8"\xe8\xac\x9d\xe3\x81\x8d\xe3\x82\x81\xe9\x80\x80\x31\x30"
+ u8"\xe8\x89\xaf\xe3\x81\x9a\xe3"
+ u8"\x82\xa4\xe3\x81\xb5\xe3\x81\x8b\xe7\x89\x88\xe8\x84\xb3"
+ u8"\xe3\x83\xa9\xe3\x83\xaf\xe6"
+ u8"\xad\xa2\xe9\x80\x9a\xe3\x83\xa8\xe3\x83\xb2\xe3\x82\xad");
+ QTest::newRow((cmdLine.executable().baseName() + " : german").toUtf8())
+ << cmdLine
+ << QString::fromUtf8(u8"\x48\x61\x6c\x6c\xc3\xb6\x2c\x20\x77\x69\x65\x20\x67\xc3"
+ u8"\xa4\x68\x74\x20\x65\x73\x20"
+ u8"\x64\xc3\xbc\x72");
+
+ QTest::newRow((cmdLine.executable().baseName() + " : long").toUtf8())
+ << cmdLine << testString(4096 * 16);
+ }
+ }
+
+ void testArguments()
+ {
+ QFETCH(CommandLine, cmdLine);
+ QFETCH(QString, testData);
+
+ if (cmdLine.executable().toString().contains("docker") && !m_dockerSetupCheckOk) {
+ QSKIP("Docker was found, but does not seem to be set up correctly, skipping.");
+ }
+
+ TestShell shell(cmdLine);
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ QRandomGenerator generator;
+
+ const DeviceShell::RunResult result = shell.outputForRunInShell({"echo", {testData}});
+ QCOMPARE(result.exitCode, 0);
+ const QString expected = testData + "\n";
+ const QString resultAsUtf8 = QString::fromUtf8(result.stdOut);
+ QCOMPARE(resultAsUtf8.size(), expected.size());
+ QCOMPARE(resultAsUtf8, expected);
+ }
+
+ void testStdin_data()
+ {
+ QTest::addColumn<CommandLine>("cmdLine");
+ QTest::addColumn<QString>("testData");
+
+ for (const auto &cmdLine : qAsConst(m_availableShells)) {
+ QTest::newRow((cmdLine.executable().baseName() + " : simple").toUtf8())
+ << cmdLine << "Hallo Welt!";
+ QTest::newRow((cmdLine.executable().baseName() + " : japanese").toUtf8())
+ << cmdLine
+ << QString::fromUtf8(u8"\xe8\xac\x9d\xe3\x81\x8d\xe3\x82\x81\xe9\x80\x80\x31\x30"
+ u8"\xe8\x89\xaf\xe3\x81\x9a\xe3"
+ u8"\x82\xa4\xe3\x81\xb5\xe3\x81\x8b\xe7\x89\x88\xe8\x84\xb3"
+ u8"\xe3\x83\xa9\xe3\x83\xaf\xe6"
+ u8"\xad\xa2\xe9\x80\x9a\xe3\x83\xa8\xe3\x83\xb2\xe3\x82\xad");
+ QTest::newRow((cmdLine.executable().baseName() + " : german").toUtf8())
+ << cmdLine
+ << QString::fromUtf8(u8"\x48\x61\x6c\x6c\xc3\xb6\x2c\x20\x77\x69\x65\x20\x67\xc3"
+ u8"\xa4\x68\x74\x20\x65\x73\x20"
+ u8"\x64\xc3\xbc\x72");
+
+ QTest::newRow((cmdLine.executable().baseName() + " : long").toUtf8())
+ << cmdLine << testString(4096 * 16);
+ }
+ }
+
+ void testStdin()
+ {
+ QFETCH(CommandLine, cmdLine);
+ QFETCH(QString, testData);
+
+ if (cmdLine.executable().toString().contains("docker") && !m_dockerSetupCheckOk) {
+ QSKIP("Docker was found, but does not seem to be set up correctly, skipping.");
+ }
+
+ TestShell shell(cmdLine);
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ QRandomGenerator generator;
+
+ const DeviceShell::RunResult result = shell.outputForRunInShell({"cat", {}}, testData.toUtf8());
+ QCOMPARE(result.exitCode, 0);
+ const QString resultAsUtf8 = QString::fromUtf8(result.stdOut);
+ QCOMPARE(resultAsUtf8.size(), testData.size());
+ QCOMPARE(resultAsUtf8, testData);
+ }
+
+ void testAscii_data()
+ {
+ QTest::addColumn<CommandLine>("cmdLine");
+ for (const auto &cmdLine : qAsConst(m_availableShells)) {
+ QTest::newRow(cmdLine.executable().baseName().toUtf8()) << cmdLine;
+ }
+ }
+
+ void testAscii()
+ {
+ QFETCH(CommandLine, cmdLine);
+
+ if (cmdLine.executable().toString().contains("docker") && !m_dockerSetupCheckOk) {
+ QSKIP("Docker was found, but does not seem to be set up correctly, skipping.");
+ }
+
+ TestShell shell(cmdLine);
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ const DeviceShell::RunResult result = shell.outputForRunInShell({"cat", {}},
+ m_asciiTestData);
+ QCOMPARE(result.stdOut, m_asciiTestData);
+ }
+
+ void testStdErr_data()
+ {
+ QTest::addColumn<CommandLine>("cmdLine");
+ for (const auto &cmdLine : m_availableShells) {
+ QTest::newRow(cmdLine.executable().baseName().toUtf8()) << cmdLine;
+ }
+ }
+
+ void testStdErr()
+ {
+ QFETCH(CommandLine, cmdLine);
+
+ if (cmdLine.executable().toString().contains("docker") && !m_dockerSetupCheckOk) {
+ QSKIP("Docker was found, but does not seem to be set up correctly, skipping.");
+ }
+
+ TestShell shell(cmdLine);
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ const DeviceShell::RunResult result = shell.outputForRunInShell({"cat", {}},
+ m_asciiTestData);
+ QCOMPARE(result.stdOut, m_asciiTestData);
+ QVERIFY(result.stdErr.isEmpty());
+
+ const DeviceShell::RunResult result2 = shell.outputForRunInShell(
+ {"cat", {"/tmp/i-do-not-exist.none"}});
+ QVERIFY(!result2.stdErr.isEmpty());
+ QVERIFY(result2.exitCode != 0);
+ }
+
+ void testNoCommand_data()
+ {
+ QTest::addColumn<CommandLine>("cmdLine");
+ for (const auto &cmdLine : m_availableShells) {
+ QTest::newRow(cmdLine.executable().baseName().toUtf8()) << cmdLine;
+ }
+ }
+
+ void testNoCommand()
+ {
+ QFETCH(CommandLine, cmdLine);
+
+ if (cmdLine.executable().toString().contains("docker") && !m_dockerSetupCheckOk) {
+ QSKIP("Docker was found, but does not seem to be set up correctly, skipping.");
+ }
+
+ TestShell shell(cmdLine);
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ const DeviceShell::RunResult result = shell.outputForRunInShell({}, {});
+
+ QVERIFY(result.exitCode == 255);
+ }
+
+ void testMultiThreadedFind_data()
+ {
+ QTest::addColumn<CommandLine>("cmdLine");
+ for (const auto &cmdLine : m_availableShells) {
+ QTest::newRow(cmdLine.executable().baseName().toUtf8()) << cmdLine;
+ }
+ }
+
+ void testMultiThreadedFind()
+ {
+ QFETCH(CommandLine, cmdLine);
+
+ if (cmdLine.executable().toString().contains("docker") && !m_dockerSetupCheckOk) {
+ QSKIP("Docker was found, but does not seem to be set up correctly, skipping.");
+ }
+
+ TestShell shell(cmdLine);
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ QList<int> runs{1,2,3,4,5,6,7,8,9};
+
+ int maxDepth = 4;
+ int numMs = 0;
+
+ while (true) {
+ QElapsedTimer t;
+ t.start();
+ DeviceShell::RunResult result = shell.outputForRunInShell({"find", {"/usr", "-maxdepth", QString::number(maxDepth)}});
+ numMs = t.elapsed();
+ qDebug() << "adjusted maxDepth" << maxDepth << "took" << numMs << "ms";
+ if (numMs < 100 || maxDepth == 1) {
+ break;
+ }
+ maxDepth--;
+ }
+
+ QList<QByteArray> results = Utils::mapped<QList>(runs, [&shell, maxDepth](const int i) -> QByteArray{
+ QElapsedTimer t;
+ t.start();
+ DeviceShell::RunResult result = shell.outputForRunInShell({"find", {"/usr", "-maxdepth", QString::number(maxDepth)}});
+ qDebug() << i << "took" << t.elapsed() << "ms";
+ return result.stdOut;
+ });
+
+ QVERIFY (!Utils::anyOf(results, [&results](const QByteArray r){ return r != results[0]; }));
+ }
+};
+
+QTEST_GUILESS_MAIN(tst_DeviceShell)
+
+#include "tst_deviceshell.moc"
diff --git a/tests/auto/utils/fileutils/tst_fileutils.cpp b/tests/auto/utils/fileutils/tst_fileutils.cpp
index 3678da4193d..38856873b97 100644
--- a/tests/auto/utils/fileutils/tst_fileutils.cpp
+++ b/tests/auto/utils/fileutils/tst_fileutils.cpp
@@ -28,6 +28,7 @@
#include <QRandomGenerator>
#include <utils/fileutils.h>
+#include <utils/hostosinfo.h>
#include <utils/link.h>
//TESTED_COMPONENT=src/libs/utils
@@ -526,5 +527,5 @@ void tst_fileutils::asyncLocalCopy()
QVERIFY(spy.count() == 1 || spy.wait(3000));
}
-QTEST_MAIN(tst_fileutils)
+QTEST_GUILESS_MAIN(tst_fileutils)
#include "tst_fileutils.moc"
diff --git a/tests/auto/utils/indexedcontainerproxyconstiterator/tst_indexedcontainerproxyconstiterator.cpp b/tests/auto/utils/indexedcontainerproxyconstiterator/tst_indexedcontainerproxyconstiterator.cpp
index b60b5cf114d..e42068e626c 100644
--- a/tests/auto/utils/indexedcontainerproxyconstiterator/tst_indexedcontainerproxyconstiterator.cpp
+++ b/tests/auto/utils/indexedcontainerproxyconstiterator/tst_indexedcontainerproxyconstiterator.cpp
@@ -204,6 +204,6 @@ void tst_IndexedContainerProxyConstIterator::testIteration()
QCOMPARE(boolsCopy, bools);
}
-QTEST_MAIN(tst_IndexedContainerProxyConstIterator)
+QTEST_GUILESS_MAIN(tst_IndexedContainerProxyConstIterator)
#include "tst_indexedcontainerproxyconstiterator.moc"
diff --git a/tests/auto/utils/persistentsettings/tst_persistentsettings.cpp b/tests/auto/utils/persistentsettings/tst_persistentsettings.cpp
index bd965523f24..3885b5073dd 100644
--- a/tests/auto/utils/persistentsettings/tst_persistentsettings.cpp
+++ b/tests/auto/utils/persistentsettings/tst_persistentsettings.cpp
@@ -101,6 +101,6 @@ void PersistentSettingsTest::tst_readwrite()
tmpDir.setAutoRemove(!QTest::currentTestFailed());
}
-QTEST_MAIN(PersistentSettingsTest)
+QTEST_GUILESS_MAIN(PersistentSettingsTest)
#include "tst_persistentsettings.moc"
diff --git a/tests/auto/utils/qtcprocess/CMakeLists.txt b/tests/auto/utils/qtcprocess/CMakeLists.txt
index daa4dea7d12..4040548b334 100644
--- a/tests/auto/utils/qtcprocess/CMakeLists.txt
+++ b/tests/auto/utils/qtcprocess/CMakeLists.txt
@@ -1,8 +1,15 @@
+add_subdirectory(processtestapp)
+
file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
add_qtc_test(tst_qtcprocess
+ CONDITION Qt5_VERSION VERSION_GREATER_EQUAL 6.2.0
+ TIMEOUT 30
DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
- DEPENDS Utils
+ "PROCESS_TESTAPP=\"${CMAKE_CURRENT_BINARY_DIR}/processtestapp\""
+ DEPENDS Utils app_version
SOURCES tst_qtcprocess.cpp
+ processtestapp/processtestapp.h
+ processtestapp/processtestapp.cpp
)
diff --git a/tests/auto/utils/qtcprocess/processtestapp/CMakeLists.txt b/tests/auto/utils/qtcprocess/processtestapp/CMakeLists.txt
new file mode 100644
index 00000000000..7372cda14a7
--- /dev/null
+++ b/tests/auto/utils/qtcprocess/processtestapp/CMakeLists.txt
@@ -0,0 +1,17 @@
+file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
+file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
+
+add_qtc_executable(processtestapp
+ DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
+ "PROCESS_TESTAPP=\"${CMAKE_CURRENT_BINARY_DIR}\""
+ DEPENDS Utils app_version
+ SOURCES main.cpp processtestapp.h processtestapp.cpp
+ SKIP_INSTALL
+ INTERNAL_ONLY
+)
+
+set_target_properties(processtestapp PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+)
diff --git a/tests/auto/utils/qtcprocess/processtestapp/main.cpp b/tests/auto/utils/qtcprocess/processtestapp/main.cpp
new file mode 100644
index 00000000000..25d5d7aafa7
--- /dev/null
+++ b/tests/auto/utils/qtcprocess/processtestapp/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "processtestapp.h"
+
+#include <app/app_version.h>
+
+#include <utils/launcherinterface.h>
+#include <utils/qtcprocess.h>
+#include <utils/temporarydirectory.h>
+
+#include <QCoreApplication>
+#include <QScopeGuard>
+
+#ifdef Q_OS_WIN
+#include <crtdbg.h>
+#include <cstdlib>
+#endif
+
+using namespace Utils;
+
+int main(int argc, char **argv)
+{
+#ifdef Q_OS_WIN
+ // avoid crash reporter dialog
+ _set_error_mode(_OUT_TO_STDERR);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
+#endif
+ QCoreApplication app(argc, argv);
+
+ auto cleanup = qScopeGuard([] { Singleton::deleteAll(); });
+
+ TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/"
+ + Core::Constants::IDE_CASED_ID + "-XXXXXX");
+ const QString libExecPath(qApp->applicationDirPath() + '/'
+ + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
+ LauncherInterface::setPathToLauncher(libExecPath);
+ SubProcessConfig::setPathToProcessTestApp(QLatin1String(PROCESS_TESTAPP));
+
+ QMetaObject::invokeMethod(&app, [] { ProcessTestApp::invokeSubProcess(); }, Qt::QueuedConnection);
+ return app.exec();
+}
diff --git a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp
new file mode 100644
index 00000000000..28330786d38
--- /dev/null
+++ b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "processtestapp.h"
+
+#include <utils/qtcprocess.h>
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QHash>
+#include <QMutex>
+#include <QScopeGuard>
+#include <QThread>
+
+#include <iostream>
+
+#ifdef Q_OS_WIN
+#include <fcntl.h>
+#include <io.h>
+#else
+#include <atomic>
+#include <signal.h>
+#include <unistd.h>
+#endif
+
+using namespace Utils;
+
+static QHash<const char *, ProcessTestApp::SubProcessMain> s_subProcesses = {};
+
+ProcessTestApp::ProcessTestApp() = default;
+
+void ProcessTestApp::invokeSubProcess()
+{
+ ProcessTestApp processTestApp;
+ int returnValue = 1;
+ auto cleanup = qScopeGuard([&returnValue] {
+ QMetaObject::invokeMethod(qApp, [returnValue] {
+ qApp->exit(returnValue);
+ }, Qt::QueuedConnection);
+ });
+
+ for (auto it = s_subProcesses.constBegin(); it != s_subProcesses.constEnd(); ++it) {
+ if (qEnvironmentVariableIsSet(it.key())) {
+ returnValue = it.value()();
+ return;
+ }
+ }
+ qWarning() << "No test was run!";
+}
+
+void ProcessTestApp::registerSubProcess(const char *envVar, const SubProcessMain &main)
+{
+ s_subProcesses.insert(envVar, main);
+}
+
+void ProcessTestApp::unregisterSubProcess(const char *envVar)
+{
+ s_subProcesses.remove(envVar);
+}
+
+static QString s_pathToProcessTestApp;
+
+static Environment subEnvironment(const char *envVar, const QString &envVal)
+{
+ Environment env = Environment::systemEnvironment();
+ env.set(QString::fromLatin1(envVar), envVal);
+ return env;
+}
+
+void SubProcessConfig::setPathToProcessTestApp(const QString &path)
+{
+ s_pathToProcessTestApp = path;
+}
+
+SubProcessConfig::SubProcessConfig(const char *envVar, const QString &envVal)
+ : m_environment(subEnvironment(envVar, envVal))
+{
+}
+
+void SubProcessConfig::setupSubProcess(QtcProcess *subProcess)
+{
+ subProcess->setEnvironment(m_environment);
+ const FilePath filePath = FilePath::fromString(s_pathToProcessTestApp
+ + QLatin1String("/processtestapp")).withExecutableSuffix();
+ subProcess->setCommand(CommandLine(filePath, {}));
+}
+
+void SubProcessConfig::setupSubProcess(QProcess *subProcess)
+{
+ subProcess->setProcessEnvironment(m_environment.toProcessEnvironment());
+ subProcess->setProgram(FilePath::fromString(s_pathToProcessTestApp
+ + QLatin1String("/processtestapp")).withExecutableSuffix().toString());
+}
+
+
+static void doCrash()
+{
+ qFatal("The application has crashed purposefully!");
+}
+
+int ProcessTestApp::SimpleTest::main()
+{
+ std::cout << s_simpleTestData << std::endl;
+ return 0;
+}
+
+int ProcessTestApp::ExitCode::main()
+{
+ const int exitCode = qEnvironmentVariableIntValue(envVar());
+ std::cout << "Exiting with code:" << exitCode << std::endl;
+ return exitCode;
+}
+
+int ProcessTestApp::RunBlockingStdOut::main()
+{
+ std::cout << "Wait for the Answer to the Ultimate Question of Life, "
+ "The Universe, and Everything..." << std::endl;
+ QThread::msleep(300);
+ std::cout << s_runBlockingStdOutSubProcessMagicWord << "...Now wait for the question...";
+ if (qEnvironmentVariable(envVar()) == "true")
+ std::cout << std::endl;
+ else
+ std::cout << std::flush; // otherwise it won't reach the original process (will be buffered)
+ QThread::msleep(5000);
+ return 0;
+}
+
+int ProcessTestApp::LineCallback::main()
+{
+#ifdef Q_OS_WIN
+ // Prevent \r\n -> \r\r\n translation.
+ _setmode(_fileno(stderr), O_BINARY);
+#endif
+ fprintf(stderr, "%s", QByteArray(s_lineCallbackData).replace('|', "").data());
+ return 0;
+}
+
+int ProcessTestApp::StandardOutputAndErrorWriter::main()
+{
+ std::cout << s_outputData << std::endl;
+ std::cerr << s_errorData << std::endl;
+ return 0;
+}
+
+int ProcessTestApp::ChannelForwarding::main()
+{
+ const QProcess::ProcessChannelMode channelMode
+ = QProcess::ProcessChannelMode(qEnvironmentVariableIntValue(envVar()));
+ qunsetenv(envVar());
+
+ SubProcessConfig subConfig(StandardOutputAndErrorWriter::envVar(), {});
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+
+ process.setProcessChannelMode(channelMode);
+ process.start();
+ process.waitForFinished();
+ return 0;
+}
+
+int ProcessTestApp::BlockingProcess::main()
+{
+ std::cout << "Blocking process successfully executed." << std::endl;
+ const BlockType blockType = BlockType(qEnvironmentVariableIntValue(envVar()));
+ switch (blockType) {
+ case BlockType::EndlessLoop:
+ while (true)
+ ;
+ break;
+ case BlockType::InfiniteSleep:
+ QThread::sleep(INT_MAX);
+ break;
+ case BlockType::MutexDeadlock: {
+ QMutex mutex;
+ mutex.lock();
+ mutex.lock();
+ break;
+ }
+ case BlockType::EventLoop: {
+ QEventLoop loop;
+ loop.exec();
+ break;
+ }
+ }
+ return 1;
+}
+
+int ProcessTestApp::Crash::main()
+{
+ doCrash();
+ return 1;
+}
+
+int ProcessTestApp::CrashAfterOneSecond::main()
+{
+ QThread::sleep(1);
+ doCrash();
+ return 1;
+}
+
+int ProcessTestApp::RecursiveCrashingProcess::main()
+{
+ const int currentDepth = qEnvironmentVariableIntValue(envVar());
+ if (currentDepth == 1) {
+ QThread::sleep(1);
+ doCrash();
+ return 1;
+ }
+ SubProcessConfig subConfig(envVar(), QString::number(currentDepth - 1));
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+ process.start();
+ process.waitForFinished();
+ if (process.exitStatus() == QProcess::NormalExit)
+ return process.exitCode();
+ return s_crashCode;
+}
+
+#ifndef Q_OS_WIN
+static std::atomic_bool s_terminate = false;
+
+void terminate(int signum)
+{
+ Q_UNUSED(signum)
+ s_terminate.store(true);
+}
+#endif
+
+int ProcessTestApp::RecursiveBlockingProcess::main()
+{
+#ifndef Q_OS_WIN
+ struct sigaction action;
+ memset(&action, 0, sizeof(struct sigaction));
+ action.sa_handler = terminate;
+ sigaction(SIGTERM, &action, NULL);
+#endif
+
+ const int currentDepth = qEnvironmentVariableIntValue(envVar());
+ if (currentDepth == 1) {
+ std::cout << s_leafProcessStarted << std::flush;
+ while (true) {
+ // TODO: make it configurable so that we could test the reaper timeout
+ QThread::msleep(100);
+#ifndef Q_OS_WIN
+ if (s_terminate.load()) {
+ std::cout << s_leafProcessTerminated << std::flush;
+ return s_crashCode;
+ }
+#endif
+ }
+ }
+ SubProcessConfig subConfig(envVar(), QString::number(currentDepth - 1));
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+ process.setProcessChannelMode(QProcess::ForwardedChannels);
+ process.start();
+ while (true) {
+ if (process.waitForFinished(1000))
+ return 0;
+#ifndef Q_OS_WIN
+ if (s_terminate.load()) {
+ process.terminate();
+ process.waitForFinished(-1);
+ break;
+ }
+#endif
+ }
+ if (process.exitStatus() == QProcess::NormalExit)
+ return process.exitCode();
+ return s_crashCode;
+}
diff --git a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.h b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.h
new file mode 100644
index 00000000000..7fbcabc25dc
--- /dev/null
+++ b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include <functional>
+
+#include <utils/commandline.h>
+#include <utils/environment.h>
+#include <utils/qtcassert.h>
+
+QT_BEGIN_NAMESPACE
+class QProcess;
+QT_END_NAMESPACE
+
+namespace Utils { class QtcProcess; }
+
+#define SUB_PROCESS(SubProcessClass)\
+class SubProcessClass\
+{\
+public:\
+ static const char *envVar() { return m_envVar; }\
+private:\
+ SubProcessClass() { registerSubProcess(envVar(), &SubProcessClass::main); }\
+ ~SubProcessClass() { unregisterSubProcess(envVar()); }\
+ static int main();\
+ static constexpr char m_envVar[] = "TST_QTC_PROCESS_" QTC_ASSERT_STRINGIFY(SubProcessClass);\
+ friend class ProcessTestApp;\
+};\
+\
+SubProcessClass m_ ## SubProcessClass
+
+class ProcessTestApp
+{
+public:
+ using SubProcessMain = std::function<int ()>;
+
+ static void invokeSubProcess();
+
+ // Many tests inside tst_qtcprocess need to start a new subprocess with custom code.
+ // In order to simplify things we produce just one separate executable - processtestapp.
+ // We embed all our custom subprocesses in processtestapp and enclose them in separate
+ // classes. We select desired process to run by setting the relevant environment variable.
+ // Test classes are defined by the SUB_PROCESS macro. The macro defines a class
+ // alongside of the corresponding environment variable which is set prior to the execution
+ // of the subprocess. The following subprocess classes are defined:
+
+ SUB_PROCESS(SimpleTest);
+ SUB_PROCESS(ExitCode);
+ SUB_PROCESS(RunBlockingStdOut);
+ SUB_PROCESS(LineCallback);
+ SUB_PROCESS(StandardOutputAndErrorWriter);
+ SUB_PROCESS(ChannelForwarding);
+ SUB_PROCESS(BlockingProcess);
+ SUB_PROCESS(Crash);
+ SUB_PROCESS(CrashAfterOneSecond);
+ SUB_PROCESS(RecursiveCrashingProcess);
+ SUB_PROCESS(RecursiveBlockingProcess);
+
+ // In order to get a value associated with the certain subprocess use SubProcessClass::envVar().
+ // The classes above define different custom executables. Inside invokeSubProcess(), called
+ // by processtestapp, we are detecting if one of these variables is set and invoke a respective
+ // custom executable code directly. The exit code of the process is reported to the caller
+ // by the return value of SubProcessClass::main().
+
+private:
+ ProcessTestApp();
+
+ static void registerSubProcess(const char *envVar, const SubProcessMain &main);
+ static void unregisterSubProcess(const char *envVar);
+};
+
+class SubProcessConfig
+{
+public:
+ SubProcessConfig(const char *envVar, const QString &envVal);
+ void setupSubProcess(Utils::QtcProcess *subProcess);
+ void setupSubProcess(QProcess *subProcess);
+
+ static void setPathToProcessTestApp(const QString &path);
+
+private:
+ const Utils::Environment m_environment;
+};
+
+static const char s_simpleTestData[] = "Test process successfully executed.";
+static const char s_runBlockingStdOutSubProcessMagicWord[] = "42";
+
+// Expect ending lines detected at '|':
+static const char s_lineCallbackData[] =
+ "This is the first line\r\n|"
+ "Here comes the second one\r\n|"
+ "And a line without LF\n|"
+ "Rebasing (1/10)\r| <delay> Rebasing (2/10)\r| <delay> ...\r\n|"
+ "And no end";
+
+static const char s_outputData[] = "This is the output message.";
+static const char s_errorData[] = "This is the error message.";
+
+enum class BlockType {
+ EndlessLoop,
+ InfiniteSleep,
+ MutexDeadlock,
+ EventLoop
+};
+
+static const int s_crashCode = 123;
+static const char s_leafProcessStarted[] = "Leaf process started";
+static const char s_leafProcessTerminated[] = "Leaf process terminated";
+
+Q_DECLARE_METATYPE(BlockType)
diff --git a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.qbs b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.qbs
new file mode 100644
index 00000000000..a27c4e0da0b
--- /dev/null
+++ b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.qbs
@@ -0,0 +1,30 @@
+import qbs.FileInfo
+
+QtApplication {
+ name: "processtestapp"
+ Depends { name: "app_version_header" }
+ Depends { name: "qtc" }
+ Depends { name: "Utils" }
+
+ consoleApplication: true
+ cpp.cxxLanguageVersion: "c++17"
+ cpp.defines: {
+ var defines = base;
+ var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
+ qtc.ide_libexec_path);
+ var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
+ defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
+ defines.push('PROCESS_TESTAPP="' + destinationDirectory + '"');
+ return defines;
+ }
+
+ install: false
+ destinationDirectory: project.buildDirectory + '/'
+ + FileInfo.relativePath(project.ide_source_tree, sourceDirectory)
+
+ files: [
+ "main.cpp",
+ "processtestapp.cpp",
+ "processtestapp.h",
+ ]
+}
diff --git a/tests/auto/utils/qtcprocess/qtcprocess.qbs b/tests/auto/utils/qtcprocess/qtcprocess.qbs
index 966cf6cbe55..cc37a0124fc 100644
--- a/tests/auto/utils/qtcprocess/qtcprocess.qbs
+++ b/tests/auto/utils/qtcprocess/qtcprocess.qbs
@@ -1,17 +1,29 @@
import qbs.FileInfo
-QtcAutotest {
- name: "QtcProcess autotest"
- Depends { name: "Utils" }
- files: "tst_qtcprocess.cpp"
- cpp.defines: {
- var defines = base;
- if (qbs.targetOS === "windows")
- defines.push("_CRT_SECURE_NO_WARNINGS");
- var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
- qtc.ide_libexec_path);
- var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
- defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
- return defines;
+Project {
+ QtcAutotest {
+ name: "QtcProcess autotest"
+
+ Depends { name: "Utils" }
+ Depends { name: "app_version_header" }
+
+ files: [
+ "processtestapp/processtestapp.cpp",
+ "processtestapp/processtestapp.h",
+ "tst_qtcprocess.cpp",
+ ]
+ cpp.defines: {
+ var defines = base;
+ if (qbs.targetOS === "windows")
+ defines.push("_CRT_SECURE_NO_WARNINGS");
+ var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
+ qtc.ide_libexec_path);
+ var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
+ defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
+ defines.push('PROCESS_TESTAPP="'
+ + FileInfo.joinPaths(destinationDirectory, "processtestapp") + '"');
+ return defines;
+ }
}
+ references: "processtestapp/processtestapp.qbs"
}
diff --git a/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp b/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp
index ac0bf2f862a..9c4affd8701 100644
--- a/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp
+++ b/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp
@@ -23,13 +23,20 @@
**
****************************************************************************/
+#include "processtestapp/processtestapp.h"
+
+#include <app/app_version.h>
+
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/launcherinterface.h>
#include <utils/porting.h>
+#include <utils/processinfo.h>
+#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/singleton.h>
#include <utils/stringutils.h>
+#include <utils/temporarydirectory.h>
#include <QElapsedTimer>
#include <QRegularExpression>
@@ -38,123 +45,44 @@
#include <iostream>
#include <fstream>
-#ifdef Q_OS_WIN
- #include <io.h>
- #include <fcntl.h>
-#endif
-
-
using namespace Utils;
-// Many tests in this file need to start a new subprocess with custom code.
-// In order to simplify things we don't produce separate executables, but invoke
-// the same test process recursively and prior to the execution we set one of the
-// following environment variables:
-
-const char kExitCodeSubProcessCode[] = "QTC_TST_QTCPROCESS_EXITCODE_CODE";
-const char kRunBlockingStdOutSubProcessWithEndl[] = "QTC_TST_QTCPROCESS_RUNBLOCKINGSTDOUT_WITHENDL";
-const char kLineCallback[] = "QTC_TST_QTCPROCESS_LINECALLBACK";
-const char kTestProcess[] = "QTC_TST_TEST_PROCESS";
-const char kForwardProcess[] = "QTC_TST_FORWARD_PROCESS";
-const char kForwardSubProcess[] = "QTC_TST_FORWARD_SUB_PROCESS";
-const char kBlockingProcess[] = "QTC_TST_BLOCKING_PROCESS";
-
-// The variables above are meant to be different custom executables. Inside initTestCase()
-// we are detecting if one of these variables is set and invoke directly a respective custom
-// executable code, which always ends up with a call to exit(). In this case we need to stop
-// the recursion, as from the test point of view we meant to execute only our custom code
-// without further execution of the test itself.
-
-const char testProcessData[] = "Test process successfully executed.";
-const char forwardedOutputData[] = "This is the output message.";
-const char forwardedErrorData[] = "This is the error message.";
-const char runBlockingStdOutSubProcessMagicWord[] = "42";
-
-// Expect ending lines detected at '|':
-const char lineCallbackData[] =
- "This is the first line\r\n|"
- "Here comes the second one\r\n|"
- "And a line without LF\n|"
- "Rebasing (1/10)\r| <delay> Rebasing (2/10)\r| <delay> ...\r\n|"
- "And no end";
-
-static void exitCodeSubProcessMain()
-{
- const int exitCode = qEnvironmentVariableIntValue(kExitCodeSubProcessCode);
- std::cout << "Exiting with code:" << exitCode << std::endl;
- exit(exitCode);
-}
-
-static void blockingStdOutSubProcessMain()
-{
- std::cout << "Wait for the Answer to the Ultimate Question of Life, "
- "The Universe, and Everything..." << std::endl;
- QThread::msleep(300);
- std::cout << runBlockingStdOutSubProcessMagicWord << "...Now wait for the question...";
- if (qEnvironmentVariable(kRunBlockingStdOutSubProcessWithEndl) == "true")
- std::cout << std::endl;
- QThread::msleep(5000);
- exit(0);
-}
-
-static void lineCallbackMain()
-{
-#ifdef Q_OS_WIN
- // Prevent \r\n -> \r\r\n translation.
- setmode(fileno(stderr), O_BINARY);
-#endif
- fprintf(stderr, "%s", QByteArray(lineCallbackData).replace('|', "").data());
- exit(0);
-}
+// This handler is inspired by the one used in qtbase/tests/auto/corelib/io/qfile/tst_qfile.cpp
+class MessageHandler {
+public:
+ MessageHandler(QtMessageHandler messageHandler = handler)
+ {
+ s_oldMessageHandler = qInstallMessageHandler(messageHandler);
+ }
-static void testProcessSubProcessMain()
-{
- std::cout << testProcessData << std::endl;
- exit(0);
-}
+ ~MessageHandler()
+ {
+ qInstallMessageHandler(s_oldMessageHandler);
+ }
-// Since we want to test whether the process forwards its channels or not, we can't just create
-// a process and start it, because in this case there is no way on how to check whether something
-// went into out output channels or not.
-
-// So we start two processes in chain instead. On the beginning the processChannelForwarding()
-// test starts the "testForwardProcessMain" - this one will start another process
-// "testForwardSubProcessMain" with forwarding options. The "testForwardSubProcessMain"
-// is very simple - it just puts something to the output and the error channels.
-// Then "testForwardProcessMain" either forwards these channels or not - we check it in the outer
-// processChannelForwarding() test.
-static void testForwardProcessMain()
-{
- Environment env = Environment::systemEnvironment();
- env.set(kForwardSubProcess, {});
- QStringList args = QCoreApplication::arguments();
- const QString binary = args.takeFirst();
- const CommandLine command(FilePath::fromString(binary), args);
+ static int destroyCount()
+ {
+ return s_destroyCount;
+ }
- QtcProcess process;
- const QProcess::ProcessChannelMode channelMode
- = QProcess::ProcessChannelMode(qEnvironmentVariableIntValue(kForwardProcess));
- process.setProcessChannelMode(channelMode);
- process.setCommand(command);
- process.setEnvironment(env);
- process.start();
- process.waitForFinished();
- exit(0);
-}
+protected:
+ static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+ {
+ if (msg.contains("QProcess: Destroyed while process")
+ && msg.contains("is still running.")) {
+ ++s_destroyCount;
+ }
+ // Defer to old message handler.
+ if (s_oldMessageHandler)
+ s_oldMessageHandler(type, context, msg);
+ }
-static void testForwardSubProcessMain()
-{
- std::cout << forwardedOutputData << std::endl;
- std::cerr << forwardedErrorData << std::endl;
- exit(0);
-}
+ static QtMessageHandler s_oldMessageHandler;
+ static int s_destroyCount;
+};
-static void blockingProcessSubProcessMain()
-{
- std::cout << "Blocking process successfully executed." << std::endl;
- while (true)
- ;
-}
+int MessageHandler::s_destroyCount = 0;
+QtMessageHandler MessageHandler::s_oldMessageHandler = 0;
class MacroMapExpander : public AbstractMacroExpander {
public:
@@ -178,6 +106,9 @@ private:
QHash<QString, QString> m_map;
};
+static constexpr char s_skipTerminateOnWindows[] =
+ "Windows implementation of this test is lacking handling of WM_CLOSE message.";
+
class tst_QtcProcess : public QObject
{
Q_OBJECT
@@ -202,13 +133,23 @@ private slots:
void runBlockingStdOut_data();
void runBlockingStdOut();
void lineCallback();
- void lineCallbackIntern();
+ void waitForStartedAfterStarted();
+ void waitForStartedAfterStarted2();
void waitForStartedAndFinished();
void notRunningAfterStartingNonExistingProgram();
- void processChannelForwarding_data();
- void processChannelForwarding();
- void killBlockingProcess();
+ void channelForwarding_data();
+ void channelForwarding();
+ void mergedChannels_data();
+ void mergedChannels();
+ void destroyBlockingProcess_data();
+ void destroyBlockingProcess();
void flushFinishedWhileWaitingForReadyRead();
+ void crash();
+ void crashAfterOneSecond();
+ void recursiveCrashingProcess();
+ void recursiveBlockingProcess();
+ void quitBlockingProcess_data();
+ void quitBlockingProcess();
void cleanupTestCase();
@@ -222,26 +163,19 @@ private:
MacroMapExpander mxUnix;
QString homeStr;
QString home;
+
+ MessageHandler *msgHandler = nullptr;
};
void tst_QtcProcess::initTestCase()
{
- Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
- + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
- if (qEnvironmentVariableIsSet(kExitCodeSubProcessCode))
- exitCodeSubProcessMain();
- if (qEnvironmentVariableIsSet(kRunBlockingStdOutSubProcessWithEndl))
- blockingStdOutSubProcessMain();
- if (qEnvironmentVariableIsSet(kLineCallback))
- lineCallbackMain();
- if (qEnvironmentVariableIsSet(kTestProcess))
- testProcessSubProcessMain();
- if (qEnvironmentVariableIsSet(kForwardSubProcess))
- testForwardSubProcessMain();
- else if (qEnvironmentVariableIsSet(kForwardProcess))
- testForwardProcessMain();
- if (qEnvironmentVariableIsSet(kBlockingProcess))
- blockingProcessSubProcessMain();
+ msgHandler = new MessageHandler;
+ Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/"
+ + Core::Constants::IDE_CASED_ID + "-XXXXXX");
+ const QString libExecPath(qApp->applicationDirPath() + '/'
+ + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
+ LauncherInterface::setPathToLauncher(libExecPath);
+ SubProcessConfig::setPathToProcessTestApp(QLatin1String(PROCESS_TESTAPP));
homeStr = QLatin1String("@HOME@");
home = QDir::homePath();
@@ -287,10 +221,16 @@ void tst_QtcProcess::initTestCase()
void tst_QtcProcess::cleanupTestCase()
{
Utils::Singleton::deleteAll();
+ const int destroyCount = msgHandler->destroyCount();
+ delete msgHandler;
+ if (destroyCount)
+ qDebug() << "Received" << destroyCount << "messages about destroying running QProcess!";
+ QCOMPARE(destroyCount, 0);
}
Q_DECLARE_METATYPE(ProcessArgs::SplitError)
Q_DECLARE_METATYPE(Utils::OsType)
+Q_DECLARE_METATYPE(Utils::ProcessResult)
void tst_QtcProcess::splitArgs_data()
{
@@ -920,31 +860,24 @@ void tst_QtcProcess::exitCode()
{
QFETCH(int, exitCode);
- Environment env = Environment::systemEnvironment();
- env.set(kExitCodeSubProcessCode, QString::number(exitCode));
- QStringList args = QCoreApplication::arguments();
- const QString binary = args.takeFirst();
- const CommandLine command(FilePath::fromString(binary), args);
-
+ SubProcessConfig subConfig(ProcessTestApp::ExitCode::envVar(), QString::number(exitCode));
{
- QtcProcess qtcP;
- qtcP.setCommand(command);
- qtcP.setEnvironment(env);
- qtcP.start();
- const bool finished = qtcP.waitForFinished();
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+ process.start();
+ const bool finished = process.waitForFinished();
QVERIFY(finished);
- QCOMPARE(qtcP.exitCode(), exitCode);
- QCOMPARE(qtcP.exitCode() == 0, qtcP.result() == QtcProcess::FinishedWithSuccess);
+ QCOMPARE(process.exitCode(), exitCode);
+ QCOMPARE(process.exitCode() == 0, process.result() == ProcessResult::FinishedWithSuccess);
}
{
- QtcProcess sP;
- sP.setCommand(command);
- sP.setEnvironment(env);
- sP.runBlocking();
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+ process.runBlocking();
- QCOMPARE(sP.exitCode(), exitCode);
- QCOMPARE(sP.exitCode() == 0, sP.result() == QtcProcess::FinishedWithSuccess);
+ QCOMPARE(process.exitCode(), exitCode);
+ QCOMPARE(process.exitCode() == 0, process.result() == ProcessResult::FinishedWithSuccess);
}
}
@@ -952,62 +885,65 @@ void tst_QtcProcess::runBlockingStdOut_data()
{
QTest::addColumn<bool>("withEndl");
QTest::addColumn<int>("timeOutS");
+ QTest::addColumn<ProcessResult>("expectedResult");
+
+ // TerminatedAbnormally, since it didn't time out and callback stopped the process forcefully.
+ QTest::newRow("Short timeout with end of line")
+ << true << 2 << ProcessResult::TerminatedAbnormally;
+
+ // Hang, since it times out, calls the callback handler and stops the process forcefully.
+ QTest::newRow("Short timeout without end of line")
+ << false << 2 << ProcessResult::Hang;
- QTest::newRow("Terminated stdout delivered instantly")
- << true
- << 2;
- QTest::newRow("Unterminated stdout lost: early timeout")
- << false
- << 2;
- QTest::newRow("Unterminated stdout lost: hanging")
- << false
- << 20;
+ // FinishedWithSuccess, since it doesn't time out, it finishes process normally,
+ // calls the callback handler and tries to stop the process forcefully what is no-op
+ // at this point in time since the process is already finished.
+ QTest::newRow("Long timeout without end of line")
+ << false << 20 << ProcessResult::FinishedWithSuccess;
}
void tst_QtcProcess::runBlockingStdOut()
{
QFETCH(bool, withEndl);
QFETCH(int, timeOutS);
+ QFETCH(ProcessResult, expectedResult);
- QtcProcess sp;
- QStringList args = QCoreApplication::arguments();
- const QString binary = args.takeFirst();
- sp.setCommand(CommandLine(FilePath::fromString(binary), args));
- Environment env = Environment::systemEnvironment();
- env.set(kRunBlockingStdOutSubProcessWithEndl, withEndl ? "true" : "false");
- sp.setEnvironment(env);
- sp.setTimeoutS(timeOutS);
+ SubProcessConfig subConfig(ProcessTestApp::RunBlockingStdOut::envVar(), withEndl ? "true" : "false");
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+
+ process.setTimeoutS(timeOutS);
bool readLastLine = false;
- sp.setStdOutCallback([&readLastLine, &sp](const QString &out) {
- if (out.startsWith(runBlockingStdOutSubProcessMagicWord)) {
+ process.setStdOutCallback([&readLastLine, &process](const QString &out) {
+ if (out.startsWith(s_runBlockingStdOutSubProcessMagicWord)) {
readLastLine = true;
- sp.kill();
+ process.kill();
}
});
- sp.runBlocking();
+ process.runBlocking();
// See also QTCREATORBUG-25667 for why it is a bad idea to use QtcProcess::runBlocking
// with interactive cli tools.
- QEXPECT_FAIL("Unterminated stdout lost: early timeout", "", Continue);
- QVERIFY2(sp.result() != QtcProcess::Hang, "Process run did not time out.");
- QEXPECT_FAIL("Unterminated stdout lost: early timeout", "", Continue);
+ QCOMPARE(process.result(), expectedResult);
QVERIFY2(readLastLine, "Last line was read.");
}
void tst_QtcProcess::lineCallback()
{
+ SubProcessConfig subConfig(ProcessTestApp::LineCallback::envVar(), {});
QtcProcess process;
- QStringList args = QCoreApplication::arguments();
- const QString binary = args.takeFirst();
- process.setCommand(CommandLine(FilePath::fromString(binary), args));
- Environment env = Environment::systemEnvironment();
- env.set(kLineCallback, "Yes");
- process.setEnvironment(env);
- QStringList lines = QString(lineCallbackData).split('|');
+ subConfig.setupSubProcess(&process);
+
+ QStringList lines = QString(s_lineCallbackData).split('|');
int lineNumber = 0;
process.setStdErrLineCallback([lines, &lineNumber](const QString &actual) {
- QString expected = lines.at(lineNumber++);
+ QString expected = lines.at(lineNumber);
expected.replace("\r\n", "\n");
+ // Omit some initial lines generated by Qt, e.g.
+ // Warning: Ignoring WAYLAND_DISPLAY on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
+ if (lineNumber == 0 && actual != expected)
+ return;
+ ++lineNumber;
QCOMPARE(actual, expected);
});
process.start();
@@ -1015,33 +951,53 @@ void tst_QtcProcess::lineCallback()
QCOMPARE(lineNumber, lines.size());
}
-void tst_QtcProcess::lineCallbackIntern()
+void tst_QtcProcess::waitForStartedAfterStarted()
{
+ SubProcessConfig subConfig(ProcessTestApp::SimpleTest::envVar(), {});
QtcProcess process;
- QStringList lines = QString(lineCallbackData).split('|');
- int lineNumber = 0;
- process.setStdOutLineCallback([lines, &lineNumber](const QString &actual) {
- QString expected = lines.at(lineNumber++);
- expected.replace("\r\n", "\n");
- QCOMPARE(actual, expected);
+ subConfig.setupSubProcess(&process);
+
+ bool started = false;
+ bool waitForStartedResult = false;
+ connect(&process, &QtcProcess::started, this, [&] {
+ started = true;
+ waitForStartedResult = process.waitForStarted();
});
- process.beginFeed();
- process.feedStdOut(QByteArray(lineCallbackData).replace('|', ""));
- process.endFeed();
- QCOMPARE(lineNumber, lines.size());
+
+ process.start();
+ QVERIFY(process.waitForFinished());
+ QVERIFY(started);
+ QVERIFY(waitForStartedResult);
+ QVERIFY(!process.waitForStarted());
}
-void tst_QtcProcess::waitForStartedAndFinished()
+// This version is using QProcess
+void tst_QtcProcess::waitForStartedAfterStarted2()
{
- Environment env = Environment::systemEnvironment();
- env.set(kTestProcess, {});
- QStringList args = QCoreApplication::arguments();
- const QString binary = args.takeFirst();
- const CommandLine command(FilePath::fromString(binary), args);
+ SubProcessConfig subConfig(ProcessTestApp::SimpleTest::envVar(), {});
+ QProcess process;
+ subConfig.setupSubProcess(&process);
+
+ bool started = false;
+ bool waitForStartedResult = false;
+ connect(&process, &QProcess::started, this, [&] {
+ started = true;
+ waitForStartedResult = process.waitForStarted();
+ });
+
+ process.start();
+ QVERIFY(process.waitForFinished());
+ QVERIFY(started);
+ QVERIFY(waitForStartedResult);
+ QVERIFY(!process.waitForStarted());
+}
+void tst_QtcProcess::waitForStartedAndFinished()
+{
+ SubProcessConfig subConfig(ProcessTestApp::SimpleTest::envVar(), {});
QtcProcess process;
- process.setCommand(command);
- process.setEnvironment(env);
+ subConfig.setupSubProcess(&process);
+
process.start();
QThread::msleep(1000); // long enough for process to finish
QVERIFY(process.waitForStarted());
@@ -1056,11 +1012,10 @@ void tst_QtcProcess::notRunningAfterStartingNonExistingProgram()
process.setCommand({ FilePath::fromString(
"there_is_a_big_chance_that_executable_with_that_name_does_not_exists"), {} });
- int errorCount = 0;
- QObject::connect(&process, &QtcProcess::errorOccurred,
- [&errorCount](QProcess::ProcessError error) {
- ++errorCount;
- QCOMPARE(error, QProcess::FailedToStart);
+ int doneCount = 0;
+ QObject::connect(&process, &QtcProcess::done, [&process, &doneCount]() {
+ ++doneCount;
+ QCOMPARE(process.error(), QProcess::FailedToStart);
});
const int loopCount = 2;
@@ -1078,116 +1033,132 @@ void tst_QtcProcess::notRunningAfterStartingNonExistingProgram()
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.error(), QProcess::FailedToStart);
QVERIFY(process.exitCode() != 0);
+ QCOMPARE(process.result(), ProcessResult::StartFailed);
}
+ QCOMPARE(doneCount, loopCount);
}
-void tst_QtcProcess::processChannelForwarding_data()
+// Since we want to test whether the process forwards its channels or not, we can't just create
+// a process and start it, because in this case there is no way on how to check whether something
+// went into our output channels or not.
+
+// So we start two processes in chain instead. On the beginning the channelForwarding()
+// test starts the ChannelForwarding::main() - this one will start another process
+// StandardOutputAndErrorWriter::main() with forwarding options.
+// The StandardOutputAndErrorWriter::main() is very simple - it just puts something to the output
+// and the error channels. Then ChannelForwarding::main() either forwards these channels
+// or not - we check it in the outer channelForwarding() test.
+
+void tst_QtcProcess::channelForwarding_data()
{
QTest::addColumn<QProcess::ProcessChannelMode>("channelMode");
QTest::addColumn<bool>("outputForwarded");
QTest::addColumn<bool>("errorForwarded");
QTest::newRow("SeparateChannels") << QProcess::SeparateChannels << false << false;
+ QTest::newRow("MergedChannels") << QProcess::MergedChannels << false << false;
QTest::newRow("ForwardedChannels") << QProcess::ForwardedChannels << true << true;
QTest::newRow("ForwardedOutputChannel") << QProcess::ForwardedOutputChannel << true << false;
QTest::newRow("ForwardedErrorChannel") << QProcess::ForwardedErrorChannel << false << true;
}
-void tst_QtcProcess::processChannelForwarding()
+void tst_QtcProcess::channelForwarding()
{
QFETCH(QProcess::ProcessChannelMode, channelMode);
QFETCH(bool, outputForwarded);
QFETCH(bool, errorForwarded);
- Environment env = Environment::systemEnvironment();
- env.set(kForwardProcess, QString::number(int(channelMode)));
- QStringList args = QCoreApplication::arguments();
- const QString binary = args.takeFirst();
- const CommandLine command(FilePath::fromString(binary), args);
-
+ SubProcessConfig subConfig(ProcessTestApp::ChannelForwarding::envVar(),
+ QString::number(int(channelMode)));
QtcProcess process;
- process.setCommand(command);
- process.setEnvironment(env);
+ subConfig.setupSubProcess(&process);
+
process.start();
QVERIFY(process.waitForFinished());
const QByteArray output = process.readAllStandardOutput();
const QByteArray error = process.readAllStandardError();
- QCOMPARE(output.contains(QByteArray(forwardedOutputData)), outputForwarded);
- QCOMPARE(error.contains(QByteArray(forwardedErrorData)), errorForwarded);
+ QCOMPARE(output.contains(QByteArray(s_outputData)), outputForwarded);
+ QCOMPARE(error.contains(QByteArray(s_errorData)), errorForwarded);
}
-// This handler is inspired by the one used in qtbase/tests/auto/corelib/io/qfile/tst_qfile.cpp
-class MessageHandler {
-public:
- MessageHandler(QtMessageHandler messageHandler = handler)
- {
- ok = true;
- oldMessageHandler = qInstallMessageHandler(messageHandler);
- }
+void tst_QtcProcess::mergedChannels_data()
+{
+ QTest::addColumn<QProcess::ProcessChannelMode>("channelMode");
+ QTest::addColumn<bool>("outputOnOutput");
+ QTest::addColumn<bool>("outputOnError");
+ QTest::addColumn<bool>("errorOnOutput");
+ QTest::addColumn<bool>("errorOnError");
+
+ QTest::newRow("SeparateChannels") << QProcess::SeparateChannels
+ << true << false << false << true;
+ QTest::newRow("MergedChannels") << QProcess::MergedChannels
+ << true << false << true << false;
+ QTest::newRow("ForwardedChannels") << QProcess::ForwardedChannels
+ << false << false << false << false;
+ QTest::newRow("ForwardedOutputChannel") << QProcess::ForwardedOutputChannel
+ << false << false << false << true;
+ QTest::newRow("ForwardedErrorChannel") << QProcess::ForwardedErrorChannel
+ << true << false << false << false;
- ~MessageHandler()
- {
- qInstallMessageHandler(oldMessageHandler);
- }
+}
- static bool testPassed()
- {
- return ok;
- }
+void tst_QtcProcess::mergedChannels()
+{
+ QFETCH(QProcess::ProcessChannelMode, channelMode);
+ QFETCH(bool, outputOnOutput);
+ QFETCH(bool, outputOnError);
+ QFETCH(bool, errorOnOutput);
+ QFETCH(bool, errorOnError);
-protected:
- static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
- {
- if (msg.startsWith("QProcess: Destroyed while process")
- && msg.endsWith("is still running.")) {
- ok = false;
- }
- // Defer to old message handler.
- if (oldMessageHandler)
- oldMessageHandler(type, context, msg);
- }
+ SubProcessConfig subConfig(ProcessTestApp::StandardOutputAndErrorWriter::envVar(), {});
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
- static QtMessageHandler oldMessageHandler;
- static bool ok;
-};
+ process.setProcessChannelMode(channelMode);
+ process.start();
+ QVERIFY(process.waitForFinished());
+
+ const QByteArray output = process.readAllStandardOutput();
+ const QByteArray error = process.readAllStandardError();
-bool MessageHandler::ok = true;
-QtMessageHandler MessageHandler::oldMessageHandler = 0;
+ QCOMPARE(output.contains(QByteArray(s_outputData)), outputOnOutput);
+ QCOMPARE(error.contains(QByteArray(s_outputData)), outputOnError);
+ QCOMPARE(output.contains(QByteArray(s_errorData)), errorOnOutput);
+ QCOMPARE(error.contains(QByteArray(s_errorData)), errorOnError);
+}
-void tst_QtcProcess::killBlockingProcess()
+void tst_QtcProcess::destroyBlockingProcess_data()
{
- Environment env = Environment::systemEnvironment();
- env.set(kBlockingProcess, {});
- QStringList args = QCoreApplication::arguments();
- const QString binary = args.takeFirst();
- const CommandLine command(FilePath::fromString(binary), args);
+ QTest::addColumn<BlockType>("blockType");
- MessageHandler msgHandler;
- {
- QtcProcess process;
- process.setCommand(command);
- process.setEnvironment(env);
- process.start();
- QVERIFY(process.waitForStarted());
- QVERIFY(!process.waitForFinished(1000));
- }
+ QTest::newRow("EndlessLoop") << BlockType::EndlessLoop;
+ QTest::newRow("InfiniteSleep") << BlockType::InfiniteSleep;
+ QTest::newRow("MutexDeadlock") << BlockType::MutexDeadlock;
+ QTest::newRow("EventLoop") << BlockType::EventLoop;
+}
- QVERIFY(msgHandler.testPassed());
+void tst_QtcProcess::destroyBlockingProcess()
+{
+ QFETCH(BlockType, blockType);
+
+ SubProcessConfig subConfig(ProcessTestApp::BlockingProcess::envVar(),
+ QString::number(int(blockType)));
+
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+ process.start();
+ QVERIFY(process.waitForStarted());
+ QVERIFY(!process.waitForFinished(1000));
}
void tst_QtcProcess::flushFinishedWhileWaitingForReadyRead()
{
- Environment env = Environment::systemEnvironment();
- env.set(kTestProcess, {});
- QStringList args = QCoreApplication::arguments();
- const QString binary = args.takeFirst();
- const CommandLine command(FilePath::fromString(binary), args);
-
+ SubProcessConfig subConfig(ProcessTestApp::SimpleTest::envVar(), {});
QtcProcess process;
- process.setCommand(command);
- process.setEnvironment(env);
+ subConfig.setupSubProcess(&process);
+
process.start();
QVERIFY(process.waitForStarted());
@@ -1204,9 +1175,182 @@ void tst_QtcProcess::flushFinishedWhileWaitingForReadyRead()
QCOMPARE(process.state(), QProcess::NotRunning);
QVERIFY(!timer.hasExpired());
- QVERIFY(reply.contains(testProcessData));
+ QVERIFY(reply.contains(s_simpleTestData));
+}
+
+void tst_QtcProcess::crash()
+{
+ SubProcessConfig subConfig(ProcessTestApp::Crash::envVar(), {});
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+
+ process.start();
+ QVERIFY(process.waitForStarted(1000));
+ QVERIFY(process.isRunning());
+
+ QEventLoop loop;
+ connect(&process, &QtcProcess::done, &loop, &QEventLoop::quit);
+ loop.exec();
+
+ QCOMPARE(process.error(), QProcess::Crashed);
+ QCOMPARE(process.exitStatus(), QProcess::CrashExit);
+}
+
+void tst_QtcProcess::crashAfterOneSecond()
+{
+ SubProcessConfig subConfig(ProcessTestApp::CrashAfterOneSecond::envVar(), {});
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+
+ process.start();
+ QVERIFY(process.waitForStarted(1000));
+ QElapsedTimer timer;
+ timer.start();
+ // Please note that QProcess documentation says it should return false, but apparently
+ // it doesn't (try running this test with QTC_USE_QPROCESS=)
+ QVERIFY(process.waitForFinished(30000));
+ QVERIFY(timer.elapsed() < 30000);
+ QCOMPARE(process.state(), QProcess::NotRunning);
+ QCOMPARE(process.error(), QProcess::Crashed);
+}
+
+void tst_QtcProcess::recursiveCrashingProcess()
+{
+ const int recursionDepth = 5; // must be at least 2
+ SubProcessConfig subConfig(ProcessTestApp::RecursiveCrashingProcess::envVar(),
+ QString::number(recursionDepth));
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+ process.start();
+ QVERIFY(process.waitForStarted(1000));
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.state(), QProcess::NotRunning);
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), s_crashCode);
+}
+
+static int runningTestProcessCount()
+{
+ int testProcessCounter = 0;
+ const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
+ for (const ProcessInfo &processInfo : processInfoList) {
+ if (FilePath::fromString(processInfo.executable).baseName() == "processtestapp")
+ ++testProcessCounter;
+ }
+ return testProcessCounter;
+}
+
+void tst_QtcProcess::recursiveBlockingProcess()
+{
+ if (HostOsInfo::isWindowsHost())
+ QSKIP(s_skipTerminateOnWindows);
+
+ Singleton::deleteAll();
+ QCOMPARE(runningTestProcessCount(), 0);
+ const int recursionDepth = 5; // must be at least 2
+ SubProcessConfig subConfig(ProcessTestApp::RecursiveBlockingProcess::envVar(),
+ QString::number(recursionDepth));
+ {
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+ process.start();
+ QVERIFY(process.waitForStarted(1000));
+ QVERIFY(process.waitForReadyRead(1000));
+ QCOMPARE(process.readAllStandardOutput(), s_leafProcessStarted);
+ QCOMPARE(runningTestProcessCount(), recursionDepth);
+ QVERIFY(!process.waitForFinished(1000));
+ process.terminate();
+ QVERIFY(process.waitForReadyRead());
+ QCOMPARE(process.readAllStandardOutput(), s_leafProcessTerminated);
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), s_crashCode);
+ }
+ Singleton::deleteAll();
+ QCOMPARE(runningTestProcessCount(), 0);
+}
+
+enum class QuitType {
+ Terminate,
+ Kill,
+ Stop,
+ Close
+};
+
+Q_DECLARE_METATYPE(QuitType)
+
+void tst_QtcProcess::quitBlockingProcess_data()
+{
+ QTest::addColumn<QuitType>("quitType");
+ QTest::addColumn<bool>("doneExpected");
+ QTest::addColumn<bool>("gracefulQuit");
+
+ QTest::newRow("Terminate") << QuitType::Terminate << true << true;
+ QTest::newRow("Kill") << QuitType::Kill << true << false;
+ QTest::newRow("Stop") << QuitType::Stop << true << true;
+ QTest::newRow("Close") << QuitType::Close << false << true;
+}
+
+void tst_QtcProcess::quitBlockingProcess()
+{
+ QFETCH(QuitType, quitType);
+ QFETCH(bool, doneExpected);
+ QFETCH(bool, gracefulQuit);
+
+ if (HostOsInfo::isWindowsHost() && quitType == QuitType::Terminate)
+ QSKIP(s_skipTerminateOnWindows);
+
+ const int recursionDepth = 1;
+
+ SubProcessConfig subConfig(ProcessTestApp::RecursiveBlockingProcess::envVar(),
+ QString::number(recursionDepth));
+
+ QtcProcess process;
+ subConfig.setupSubProcess(&process);
+ bool done = false;
+ connect(&process, &QtcProcess::done, this, [&done] { done = true; });
+
+ process.start();
+ QVERIFY(process.waitForStarted());
+ QVERIFY(!done);
+ QVERIFY(process.isRunning());
+
+ QVERIFY(process.waitForReadyRead(1000));
+ QCOMPARE(process.readAllStandardOutput(), s_leafProcessStarted);
+
+ switch (quitType) {
+ case QuitType::Terminate: process.terminate(); break;
+ case QuitType::Kill: process.kill(); break;
+ case QuitType::Stop: process.stop(); break;
+ case QuitType::Close: process.close(); break;
+ }
+
+ QVERIFY(!done);
+
+ if (doneExpected) {
+ QVERIFY(process.isRunning());
+
+ QVERIFY(process.waitForFinished());
+
+ QVERIFY(!process.isRunning());
+ QVERIFY(done);
+
+ if (gracefulQuit) {
+ if (HostOsInfo::isWindowsHost())
+ QSKIP(s_skipTerminateOnWindows);
+ QCOMPARE(process.readAllStandardOutput(), s_leafProcessTerminated);
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), s_crashCode);
+ } else {
+ QCOMPARE(process.readAllStandardOutput(), QByteArray());
+ QCOMPARE(process.exitStatus(), QProcess::CrashExit);
+ QVERIFY(process.exitCode() != s_crashCode);
+ }
+ } else {
+ QVERIFY(!process.isRunning());
+ }
}
-QTEST_MAIN(tst_QtcProcess)
+QTEST_GUILESS_MAIN(tst_QtcProcess)
#include "tst_qtcprocess.moc"
diff --git a/tests/auto/utils/settings/tst_settings.cpp b/tests/auto/utils/settings/tst_settings.cpp
index 28385d9cedf..8e7d2df044e 100644
--- a/tests/auto/utils/settings/tst_settings.cpp
+++ b/tests/auto/utils/settings/tst_settings.cpp
@@ -752,6 +752,6 @@ void tst_SettingsAccessor::loadSettings_pickBest()
QCOMPARE(read.size(), data.size() + 2);
}
-QTEST_MAIN(tst_SettingsAccessor)
+QTEST_GUILESS_MAIN(tst_SettingsAccessor)
#include "tst_settings.moc"
diff --git a/tests/auto/utils/stringutils/tst_stringutils.cpp b/tests/auto/utils/stringutils/tst_stringutils.cpp
index 010e6ce8b42..14b9e1d479a 100644
--- a/tests/auto/utils/stringutils/tst_stringutils.cpp
+++ b/tests/auto/utils/stringutils/tst_stringutils.cpp
@@ -267,6 +267,6 @@ void tst_StringUtils::testParseUsedPortFromNetstatOutput_data()
QTest::newRow("QnxA") << "tcp6 0 0 *.22 *.* LISTEN " << 22;
}
-QTEST_MAIN(tst_StringUtils)
+QTEST_GUILESS_MAIN(tst_StringUtils)
#include "tst_stringutils.moc"
diff --git a/tests/auto/utils/templateengine/tst_templateengine.cpp b/tests/auto/utils/templateengine/tst_templateengine.cpp
index ed51e5330af..388cefb95f9 100644
--- a/tests/auto/utils/templateengine/tst_templateengine.cpp
+++ b/tests/auto/utils/templateengine/tst_templateengine.cpp
@@ -23,6 +23,7 @@
**
****************************************************************************/
+#include <utils/macroexpander.h>
#include <utils/templateengine.h>
#include <QtTest>
@@ -98,7 +99,6 @@ void tst_TemplateEngine::testTemplateEngine()
QCOMPARE(errorMessage, expectedErrorMessage);
}
-
-QTEST_MAIN(tst_TemplateEngine)
+QTEST_GUILESS_MAIN(tst_TemplateEngine)
#include "tst_templateengine.moc"
diff --git a/tests/auto/utils/treemodel/tst_treemodel.cpp b/tests/auto/utils/treemodel/tst_treemodel.cpp
index 22eb5a23f28..fbf181820e4 100644
--- a/tests/auto/utils/treemodel/tst_treemodel.cpp
+++ b/tests/auto/utils/treemodel/tst_treemodel.cpp
@@ -130,6 +130,6 @@ void tst_TreeModel::testTypes()
static_assert(std::is_same<Internal::SelectType<3, A, B, C>::Type, TreeItem>::value, "");
}
-QTEST_MAIN(tst_TreeModel)
+QTEST_GUILESS_MAIN(tst_TreeModel)
#include "tst_treemodel.moc"
diff --git a/tests/auto/utils/utils.qbs b/tests/auto/utils/utils.qbs
index 8960168fc74..5237f24a19e 100644
--- a/tests/auto/utils/utils.qbs
+++ b/tests/auto/utils/utils.qbs
@@ -14,5 +14,6 @@ Project {
"templateengine/templateengine.qbs",
"treemodel/treemodel.qbs",
"multicursor/multicursor.qbs",
+ "deviceshell/deviceshell.qbs",
]
}
diff --git a/tests/auto/valgrind/CMakeLists.txt b/tests/auto/valgrind/CMakeLists.txt
index 4091dd61268..9a19241b2a0 100644
--- a/tests/auto/valgrind/CMakeLists.txt
+++ b/tests/auto/valgrind/CMakeLists.txt
@@ -1,2 +1,4 @@
add_subdirectory(callgrind)
-# add_subdirectory(memcheck)
+if (UNIX)
+ add_subdirectory(memcheck)
+endif()
diff --git a/tests/auto/valgrind/callgrind/CMakeLists.txt b/tests/auto/valgrind/callgrind/CMakeLists.txt
index 70a5671caad..74ed6ef157a 100644
--- a/tests/auto/valgrind/callgrind/CMakeLists.txt
+++ b/tests/auto/valgrind/callgrind/CMakeLists.txt
@@ -1,5 +1,7 @@
+include(../valgrind.cmake)
+
add_qtc_test(tst_callgrindparsertests
- DEPENDS Utils QtcSsh Core ProjectExplorer Debugger Qt5::Core Qt5::Network
+ DEPENDS Utils Core ProjectExplorer Debugger Qt5::Core Qt5::Network
DEFINES
PARSERTESTS_DATA_DIR="${CMAKE_CURRENT_LIST_DIR}/data"
CALLGRINDPARSERTESTS
@@ -7,32 +9,6 @@ add_qtc_test(tst_callgrindparsertests
SOURCES callgrindparsertests.cpp callgrindparsertests.h
)
-extend_qtc_test(tst_callgrindparsertests
- SOURCES_PREFIX "${PROJECT_SOURCE_DIR}/src/plugins/valgrind/"
- SOURCES
- callgrind/callgrindcallmodel.h callgrind/callgrindcallmodel.cpp
- callgrind/callgrindcontroller.h callgrind/callgrindcontroller.cpp
- callgrind/callgrindcostitem.h callgrind/callgrindcostitem.cpp
- callgrind/callgrindcycledetection.h callgrind/callgrindcycledetection.cpp
- callgrind/callgrinddatamodel.h callgrind/callgrinddatamodel.cpp
- callgrind/callgrindfunction.h callgrind/callgrindfunction_p.h callgrind/callgrindfunction.cpp
- callgrind/callgrindfunctioncall.h callgrind/callgrindfunctioncall.cpp
- callgrind/callgrindfunctioncycle.h callgrind/callgrindfunctioncycle.cpp
- callgrind/callgrindparsedata.h callgrind/callgrindparsedata.cpp
- callgrind/callgrindparser.h callgrind/callgrindparser.cpp
- callgrind/callgrindproxymodel.h callgrind/callgrindproxymodel.cpp
- callgrind/callgrindstackbrowser.h callgrind/callgrindstackbrowser.cpp
- valgrindrunner.h valgrindrunner.cpp
- xmlprotocol/announcethread.h xmlprotocol/announcethread.cpp
- xmlprotocol/error.h xmlprotocol/error.cpp
- xmlprotocol/errorlistmodel.h xmlprotocol/errorlistmodel.cpp
- xmlprotocol/frame.h xmlprotocol/frame.cpp
- xmlprotocol/modelhelpers.h xmlprotocol/modelhelpers.cpp
- xmlprotocol/parser.h xmlprotocol/parser.cpp
- xmlprotocol/stack.h xmlprotocol/stack.cpp
- xmlprotocol/stackmodel.h xmlprotocol/stackmodel.cpp
- xmlprotocol/status.h xmlprotocol/status.cpp
- xmlprotocol/suppression.h xmlprotocol/suppression.cpp
- xmlprotocol/threadedparser.h xmlprotocol/threadedparser.cpp
-)
+extend_valgrind_test(tst_callgrindparsertests)
+
# skipping modeltest (does not compile due to missing widget handler)
diff --git a/tests/auto/valgrind/memcheck/CMakeLists.txt b/tests/auto/valgrind/memcheck/CMakeLists.txt
new file mode 100644
index 00000000000..653611c4d16
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/CMakeLists.txt
@@ -0,0 +1,27 @@
+add_subdirectory(testapps)
+
+include(../valgrind.cmake)
+
+file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
+file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
+
+add_qtc_test(modeldemo
+ MANUALTEST
+ DEPENDS
+ Utils
+ Core
+ Debugger
+ ProjectExplorer
+ TextEditor
+
+ SOURCES
+ modeldemo.cpp
+ modeldemo.h
+
+ DEFINES
+ PARSERTESTS_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+ VALGRIND_FAKE_PATH="${PROJECT_BINARY_DIR}/src/tools/valgrindfake/valgrind-fake"
+ TEST_RELATIVE_LIBEXEC_PATH="${TEST_RELATIVE_LIBEXEC_PATH}"
+)
+
+extend_valgrind_test(modeldemo)
diff --git a/tests/auto/valgrind/memcheck/modeldemo.cpp b/tests/auto/valgrind/memcheck/modeldemo.cpp
index 9f809161da9..996ddf1af04 100644
--- a/tests/auto/valgrind/memcheck/modeldemo.cpp
+++ b/tests/auto/valgrind/memcheck/modeldemo.cpp
@@ -24,6 +24,9 @@
**
****************************************************************************/
+#include <utils/launcherinterface.h>
+#include <utils/temporarydirectory.h>
+
#include <valgrind/xmlprotocol/frame.h>
#include <valgrind/xmlprotocol/parser.h>
#include <valgrind/xmlprotocol/stack.h>
@@ -41,12 +44,17 @@ using namespace Valgrind::XmlProtocol;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
+
+ Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/QtCreator-XXXXXX");
+ const QString libExecPath(qApp->applicationDirPath() + '/'
+ + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
+ Utils::LauncherInterface::setPathToLauncher(libExecPath);
+
qRegisterMetaType<Error>();
ValgrindRunner runner;
runner.setValgrindCommand({VALGRIND_FAKE_PATH,
{"-i", PARSERTESTS_DATA_DIR "/memcheck-output-sample1.xml"}});
-
ModelDemo demo(&runner);
QObject::connect(&runner, &ValgrindRunner::finished,
&demo, &ModelDemo::finished);
diff --git a/tests/auto/valgrind/memcheck/modeldemo.qbs b/tests/auto/valgrind/memcheck/modeldemo.qbs
index 8da8fd139e8..7da91345ee7 100644
--- a/tests/auto/valgrind/memcheck/modeldemo.qbs
+++ b/tests/auto/valgrind/memcheck/modeldemo.qbs
@@ -1,4 +1,5 @@
import qbs
+import qbs.FileInfo
import "../valgrindautotest.qbs" as ValgrindAutotest
ValgrindAutotest {
@@ -6,8 +7,14 @@ ValgrindAutotest {
Depends { name: "valgrind-fake" }
Depends { name: "Qt.network" }
files: ["modeldemo.h", "modeldemo.cpp"]
- cpp.defines: base.concat([
- 'PARSERTESTS_DATA_DIR="' + path + '/data"',
- 'VALGRIND_FAKE_PATH="' + project.buildDirectory + '/' + qtc.ide_bin_path + '/valgrind-fake"'
- ])
+ cpp.defines: {
+ var defines = base;
+ var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
+ qtc.ide_libexec_path);
+ var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
+ defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
+ defines.push('PARSERTESTS_DATA_DIR="' + path + '/data"');
+ defines.push('VALGRIND_FAKE_PATH="' + project.buildDirectory + '/' + qtc.ide_bin_path + '/valgrind-fake"');
+ return defines;
+ }
}
diff --git a/tests/auto/valgrind/memcheck/testapps/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/CMakeLists.txt
new file mode 100644
index 00000000000..89149fc5309
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_subdirectory(free1)
+add_subdirectory(free2)
+add_subdirectory(invalidjump)
+add_subdirectory(leak1)
+add_subdirectory(leak2)
+add_subdirectory(leak3)
+add_subdirectory(leak4)
+add_subdirectory(overlap)
+add_subdirectory(syscall)
+add_subdirectory(uninit1)
+add_subdirectory(uninit2)
+add_subdirectory(uninit3)
diff --git a/tests/auto/valgrind/memcheck/testapps/free1/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/free1/CMakeLists.txt
new file mode 100644
index 00000000000..99ca11c06c2
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/free1/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(free1)
diff --git a/tests/auto/valgrind/memcheck/testapps/free2/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/free2/CMakeLists.txt
new file mode 100644
index 00000000000..798be2b8122
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/free2/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(free2)
diff --git a/tests/auto/valgrind/memcheck/testapps/invalidjump/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/invalidjump/CMakeLists.txt
new file mode 100644
index 00000000000..17ab08a4e44
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/invalidjump/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(invalidjump)
diff --git a/tests/auto/valgrind/memcheck/testapps/leak1/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/leak1/CMakeLists.txt
new file mode 100644
index 00000000000..cd05f350fda
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/leak1/CMakeLists.txt
@@ -0,0 +1,5 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(leak1)
+target_link_libraries(leak1 PRIVATE Qt5::Core)
+
diff --git a/tests/auto/valgrind/memcheck/testapps/leak2/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/leak2/CMakeLists.txt
new file mode 100644
index 00000000000..a1134baf9c9
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/leak2/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(leak2)
diff --git a/tests/auto/valgrind/memcheck/testapps/leak3/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/leak3/CMakeLists.txt
new file mode 100644
index 00000000000..d825d1ac82d
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/leak3/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(leak3)
diff --git a/tests/auto/valgrind/memcheck/testapps/leak4/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/leak4/CMakeLists.txt
new file mode 100644
index 00000000000..112d8b2e9df
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/leak4/CMakeLists.txt
@@ -0,0 +1,4 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(leak4)
+target_link_libraries(leak4 PRIVATE Qt5::Core)
diff --git a/tests/auto/valgrind/memcheck/testapps/overlap/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/overlap/CMakeLists.txt
new file mode 100644
index 00000000000..149f26e3bdf
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/overlap/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(overlap)
diff --git a/tests/auto/valgrind/memcheck/testapps/syscall/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/syscall/CMakeLists.txt
new file mode 100644
index 00000000000..639996072b3
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/syscall/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(syscall)
diff --git a/tests/auto/valgrind/memcheck/testapps/testapp.cmake b/tests/auto/valgrind/memcheck/testapps/testapp.cmake
new file mode 100644
index 00000000000..25d8a154b7e
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/testapp.cmake
@@ -0,0 +1,4 @@
+function(add_valgrind_testapp name)
+ add_executable("${name}"
+ ${CMAKE_CURRENT_LIST_DIR}/main.cpp)
+endfunction()
diff --git a/tests/auto/valgrind/memcheck/testapps/uninit1/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/uninit1/CMakeLists.txt
new file mode 100644
index 00000000000..99296862d5f
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/uninit1/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(uninit1)
diff --git a/tests/auto/valgrind/memcheck/testapps/uninit2/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/uninit2/CMakeLists.txt
new file mode 100644
index 00000000000..32f279703cc
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/uninit2/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(uninit2)
diff --git a/tests/auto/valgrind/memcheck/testapps/uninit3/CMakeLists.txt b/tests/auto/valgrind/memcheck/testapps/uninit3/CMakeLists.txt
new file mode 100644
index 00000000000..def23876926
--- /dev/null
+++ b/tests/auto/valgrind/memcheck/testapps/uninit3/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../testapp.cmake)
+
+add_valgrind_testapp(uninit3)
diff --git a/tests/auto/valgrind/valgrind.cmake b/tests/auto/valgrind/valgrind.cmake
new file mode 100644
index 00000000000..fa7d8b4b60b
--- /dev/null
+++ b/tests/auto/valgrind/valgrind.cmake
@@ -0,0 +1,30 @@
+
+function(extend_valgrind_test targetName)
+ extend_qtc_test(${targetName}
+ SOURCES_PREFIX "${PROJECT_SOURCE_DIR}/src/plugins/valgrind/"
+ SOURCES
+ callgrind/callgrindcallmodel.h callgrind/callgrindcallmodel.cpp
+ callgrind/callgrindcostitem.h callgrind/callgrindcostitem.cpp
+ callgrind/callgrindcycledetection.h callgrind/callgrindcycledetection.cpp
+ callgrind/callgrinddatamodel.h callgrind/callgrinddatamodel.cpp
+ callgrind/callgrindfunction.h callgrind/callgrindfunction_p.h callgrind/callgrindfunction.cpp
+ callgrind/callgrindfunctioncall.h callgrind/callgrindfunctioncall.cpp
+ callgrind/callgrindfunctioncycle.h callgrind/callgrindfunctioncycle.cpp
+ callgrind/callgrindparsedata.h callgrind/callgrindparsedata.cpp
+ callgrind/callgrindparser.h callgrind/callgrindparser.cpp
+ callgrind/callgrindproxymodel.h callgrind/callgrindproxymodel.cpp
+ callgrind/callgrindstackbrowser.h callgrind/callgrindstackbrowser.cpp
+ valgrindrunner.h valgrindrunner.cpp
+ xmlprotocol/announcethread.h xmlprotocol/announcethread.cpp
+ xmlprotocol/error.h xmlprotocol/error.cpp
+ xmlprotocol/errorlistmodel.h xmlprotocol/errorlistmodel.cpp
+ xmlprotocol/frame.h xmlprotocol/frame.cpp
+ xmlprotocol/modelhelpers.h xmlprotocol/modelhelpers.cpp
+ xmlprotocol/parser.h xmlprotocol/parser.cpp
+ xmlprotocol/stack.h xmlprotocol/stack.cpp
+ xmlprotocol/stackmodel.h xmlprotocol/stackmodel.cpp
+ xmlprotocol/status.h xmlprotocol/status.cpp
+ xmlprotocol/suppression.h xmlprotocol/suppression.cpp
+ xmlprotocol/threadedparser.h xmlprotocol/threadedparser.cpp
+ )
+endfunction()
diff --git a/tests/auto/valgrind/valgrindautotest.qbs b/tests/auto/valgrind/valgrindautotest.qbs
index 78f546144f1..88b52b61393 100644
--- a/tests/auto/valgrind/valgrindautotest.qbs
+++ b/tests/auto/valgrind/valgrindautotest.qbs
@@ -3,7 +3,6 @@ import qbs
QtcAutotest {
Depends { name: "Debugger" }
Depends { name: "Core" }
- Depends { name: "QtcSsh" }
Depends { name: "Utils" }
Depends { name: "ProjectExplorer" }
property path pluginDir: project.ide_source_tree + "/src/plugins/valgrind"
diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt
index 436263a7e85..eecadda01f7 100644
--- a/tests/manual/CMakeLists.txt
+++ b/tests/manual/CMakeLists.txt
@@ -16,5 +16,5 @@ add_subdirectory(proparser)
# add_subdirectory(qt4projectmanager)
# add_subdirectory(search)
add_subdirectory(shootout)
-add_subdirectory(ssh)
add_subdirectory(widgets)
+add_subdirectory(deviceshell)
diff --git a/tests/manual/coco/README.md b/tests/manual/coco/README.md
new file mode 100644
index 00000000000..e795cacd8c4
--- /dev/null
+++ b/tests/manual/coco/README.md
@@ -0,0 +1,36 @@
+# Coco Manual Testing
+
+## Prerequisites
+
+* Squish coco installation with language server support (Version 6 or greater)
+* The result of coverage scan
+(for example the squish coco tutorial from /path/to/squish/tutorial just run build in that folder and execute hello)
+* Start Qt Creator with -load Coco or enable the plugin under Help > About Plugins... in Qt Creator
+
+## Starting Coco from Qt Creator
+
+* Select Analyze > Squish Coco ...
+* Insert the path to the CoverageBrowser (/path/to/squish/coveragebrowser)
+executable and the coco instrumentation file (*.csmes) of the coverage scan (/path/to/squish/tutorial/hello.csmes)
+* Select Open
+* In the started CoverageBrowser select File > Load Execution Report... and select
+the .csexe for the coverage scan (/path/to/squish/tutorial/hello.csexe)
+ * If you want to reuse that execution report make sure to deselect "Delete execution report after loading"
+
+## Tests
+
+* Open a file that was part of the coverage scan (/path/to/squish/tutorial/tutorial.cpp)
+* Verify that there are sensible annotations added to editor
+* Close the document
+* Goto Edit > Preferences > TextEditor > Font & Colors and change some formats of
+ * Code Coverage Added Code
+ * Partially Covered Code
+ * Uncovered Code
+ * Fully Covered Code
+ * Manually Validated Code
+ * Code Coverage Dead Code
+ * Code Coverage Execution Count To Low
+ * Implicitly Not Covered Code
+ * Implicitly Covered Code
+ * Implicit Manual Coverage Validation
+* Reopen the file and check whether the format changes are applied correctly
diff --git a/tests/manual/debugger/gui/CMakeLists.txt b/tests/manual/debugger/gui/CMakeLists.txt
index 59e45b3804d..21c89f291cb 100644
--- a/tests/manual/debugger/gui/CMakeLists.txt
+++ b/tests/manual/debugger/gui/CMakeLists.txt
@@ -16,3 +16,10 @@ add_executable(manual_test_debugger_gui
tst_gui.cpp
)
target_link_libraries(manual_test_debugger_gui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
+
+if (NOT QT_CREATOR_API_DEFINED)
+ if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set (CMAKE_INSTALL_PREFIX "/tmp/manual_test_debugger_gui" CACHE PATH "default install path" FORCE)
+ endif()
+ install(TARGETS manual_test_debugger_gui)
+ endif()
diff --git a/tests/manual/debugger/gui/gui.qbs b/tests/manual/debugger/gui/gui.qbs
index 7a464f77c17..88e9bd53071 100644
--- a/tests/manual/debugger/gui/gui.qbs
+++ b/tests/manual/debugger/gui/gui.qbs
@@ -1,5 +1,6 @@
QtApplication {
name: "Manual debugger gui test"
+ Depends { name: "qtc" }
Depends { name: "Qt.widgets" }
files: [
diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp
index 072345c3fcf..d51854d5393 100644
--- a/tests/manual/debugger/simple/simple_test_app.cpp
+++ b/tests/manual/debugger/simple/simple_test_app.cpp
@@ -58,7 +58,7 @@
// a test after a BREAK_HERE failed
// Default: 0
// Before using this, make sure that "Show a message box when receiving a signal"
-// is disabled in "Tools" -> "Options..." -> "Debugger" -> "GDB".
+// is disabled in "Edit" -> "Preferences..." -> "Debugger" -> "GDB".
#ifndef USE_AUTORUN
#define USE_AUTORUN 0
#endif
@@ -198,7 +198,9 @@ void dummyStatement(...) {}
#include <QWebPage>
#endif
+#if QT_VERSION < 0x060000
#include <QXmlAttributes>
+#endif
#include <QHostAddress>
#include <QNetworkRequest>
@@ -2515,6 +2517,7 @@ namespace qxml {
void testQXmlAttributes()
{
+#if QT_VERSION < 0x060000
// only works with Python dumper
QXmlAttributes atts;
atts.append("name1", "uri1", "localPart1", "value1");
@@ -2543,6 +2546,7 @@ namespace qxml {
// CheckType atts.d QXmlAttributesPrivate.
// Continue.
dummyStatement();
+#endif
}
} // namespace qxml
diff --git a/tests/manual/debugger/simple/simple_test_app.qbs b/tests/manual/debugger/simple/simple_test_app.qbs
index 59cf3fe3074..ca2c56229e4 100644
--- a/tests/manual/debugger/simple/simple_test_app.qbs
+++ b/tests/manual/debugger/simple/simple_test_app.qbs
@@ -5,6 +5,7 @@ CppApplication {
name: "Manual Test Simple Application"
targetName: "simple_test_app"
+ Depends { name: "qtc" }
Depends { name: "Qt.core" }
Depends { name: "Qt.core-private"; required: false; condition: Qt.core.versionMajor > 4 }
Depends { name: "Qt.core5compat"; condition: Qt.core.versionMajor > 5 }
diff --git a/tests/manual/debugger/simple/simple_test_plugin.qbs b/tests/manual/debugger/simple/simple_test_plugin.qbs
index 33f257c449b..eca6791c02c 100644
--- a/tests/manual/debugger/simple/simple_test_plugin.qbs
+++ b/tests/manual/debugger/simple/simple_test_plugin.qbs
@@ -4,6 +4,7 @@ DynamicLibrary {
name: "Manual Test Simple Plugin"
targetName: "simple_test_plugin"
+ Depends { name: "qtc" }
Depends { name: "Qt.core" }
files: [ "simple_test_plugin.cpp" ]
diff --git a/tests/manual/deviceshell/CMakeLists.txt b/tests/manual/deviceshell/CMakeLists.txt
new file mode 100644
index 00000000000..26671f7e4f8
--- /dev/null
+++ b/tests/manual/deviceshell/CMakeLists.txt
@@ -0,0 +1,10 @@
+file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
+file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
+
+add_qtc_test(tst_manual_deviceshell
+ MANUALTEST
+ DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
+ DEPENDS Utils app_version
+ SOURCES
+ tst_deviceshell.cpp
+)
diff --git a/tests/manual/deviceshell/deviceshell.qbs b/tests/manual/deviceshell/deviceshell.qbs
new file mode 100644
index 00000000000..9a4409793fe
--- /dev/null
+++ b/tests/manual/deviceshell/deviceshell.qbs
@@ -0,0 +1,22 @@
+import qbs.FileInfo
+
+Project {
+ QtcManualtest {
+ name: "DeviceShell manualtest"
+
+ Depends { name: "Utils" }
+ Depends { name: "app_version_header" }
+
+ files: [
+ "tst_deviceshell.cpp",
+ ]
+ cpp.defines: {
+ var defines = base;
+ var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
+ qtc.ide_libexec_path);
+ var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
+ defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
+ return defines;
+ }
+ }
+}
diff --git a/tests/manual/deviceshell/tst_deviceshell.cpp b/tests/manual/deviceshell/tst_deviceshell.cpp
new file mode 100644
index 00000000000..df3e28dab9f
--- /dev/null
+++ b/tests/manual/deviceshell/tst_deviceshell.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include <app/app_version.h>
+
+#include <utils/deviceshell.h>
+#include <utils/environment.h>
+#include <utils/hostosinfo.h>
+#include <utils/launcherinterface.h>
+#include <utils/qtcprocess.h>
+#include <utils/runextensions.h>
+#include <utils/temporarydirectory.h>
+#include <utils/mapreduce.h>
+
+#include <QObject>
+#include <QtTest>
+
+using namespace Utils;
+
+class TestShell : public DeviceShell
+{
+public:
+ TestShell() { start(); }
+
+ static CommandLine cmdLine() {
+ static CommandLine cmd;
+
+ if (cmd.isEmpty()) {
+ const FilePath dockerExecutable = Environment::systemEnvironment()
+ .searchInPath("docker", {"/usr/local/bin"});
+ const FilePath dashExecutable = Environment::systemEnvironment()
+ .searchInPath("dash", {"/usr/local/bin"});
+ const FilePath bashExecutable = Environment::systemEnvironment()
+ .searchInPath("bash", {"/usr/local/bin"});
+ const FilePath shExecutable = Environment::systemEnvironment()
+ .searchInPath("sh", {"/usr/local/bin"});
+
+ if (dockerExecutable.exists()) {
+ cmd = {dockerExecutable, {"run", "-i", "--rm","alpine"}};
+ } else if (dashExecutable.exists()) {
+ cmd = {dashExecutable, {}};
+ } else if (bashExecutable.exists()) {
+ cmd = {bashExecutable, {}};
+ } else if (shExecutable.exists()) {
+ cmd = {shExecutable, {}};
+ }
+
+ if (cmd.isEmpty()) {
+ return cmd;
+ }
+
+ qDebug() << "Using shell cmd:" << cmd;
+ }
+
+ return cmd;
+ }
+
+private:
+ void setupShellProcess(QtcProcess *shellProcess) override
+ {
+ shellProcess->setCommand(cmdLine());
+ }
+};
+
+class tst_DeviceShell : public QObject
+{
+ Q_OBJECT
+
+ QList<QByteArray> testArrays(const int numArrays)
+ {
+ QRandomGenerator generator;
+ QList<QByteArray> result;
+
+ for (int i = 0; i < numArrays; i++) {
+ QByteArray data;
+ auto numLines = generator.bounded(1, 100);
+ for (int l = 0; l < numLines; l++) {
+ auto numChars = generator.bounded(10, 40);
+ for (int c = 0; c < numChars; c++) {
+ data += static_cast<char>(generator.bounded('a', 'z'));
+ }
+ data += '\n';
+ }
+ result.append(data);
+ }
+ return result;
+ }
+
+ void test(int maxNumThreads, int numCalls)
+ {
+ TestShell shell;
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ QThreadPool::globalInstance()->setMaxThreadCount(maxNumThreads);
+
+ QList<QByteArray> testArray = testArrays(numCalls);
+
+ QElapsedTimer t;
+ t.start();
+
+ const QList<QByteArray> result
+ = mapped<QList>(testArray, [&shell](QByteArray data) -> QByteArray {
+ return shell.outputForRunInShell({"cat", {}}, data).stdOut;
+ }, MapReduceOption::Ordered, QThreadPool::globalInstance());
+
+ QCOMPARE(result, testArray);
+
+ qDebug() << "maxThreads:" << maxNumThreads << ", took:" << t.elapsed() / 1000.0
+ << "seconds";
+ }
+
+ void testSleep(QList<int> testData, int nThreads)
+ {
+ TestShell shell;
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ QThreadPool::globalInstance()->setMaxThreadCount(nThreads);
+
+ QElapsedTimer t;
+ t.start();
+
+ const auto result = mapped<QList>(testData, [&shell](const int &time) {
+ shell.runInShell({"sleep", {QString("%1").arg(time)}});
+ return 0;
+ }, MapReduceOption::Unordered, QThreadPool::globalInstance());
+
+ qDebug() << "maxThreads:" << nThreads << ", took:" << t.elapsed() / 1000.0 << "seconds";
+ }
+
+private slots:
+ void initTestCase()
+ {
+ TemporaryDirectory::setMasterTemporaryDirectory(
+ QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX");
+
+ const QString libExecPath(qApp->applicationDirPath() + '/'
+ + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
+ LauncherInterface::setPathToLauncher(libExecPath);
+
+ if (TestShell::cmdLine().isEmpty()) {
+ QSKIP("Skipping deviceshell tests, as no compatible shell could be found");
+ }
+ }
+
+ void cleanupTestCase() { Singleton::deleteAll(); }
+
+ void testEncoding_data()
+ {
+ QTest::addColumn<QString>("utf8string");
+
+ QTest::newRow("japanese") << QString::fromUtf8(
+ u8"\xe8\xac\x9d\xe3\x81\x8d\xe3\x82\x81\xe9\x80\x80\x31\x30\xe8\x89\xaf\xe3\x81\x9a\xe3"
+ u8"\x82\xa4\xe3\x81\xb5\xe3\x81\x8b\xe7\x89\x88\xe8\x84\xb3\xe3\x83\xa9\xe3\x83\xaf\xe6"
+ u8"\xad\xa2\xe9\x80\x9a\xe3\x83\xa8\xe3\x83\xb2\xe3\x82\xad\n");
+ QTest::newRow("german") << QString::fromUtf8(
+ u8"\x48\x61\x6c\x6c\xc3\xb6\x2c\x20\x77\x69\x65\x20\x67\xc3\xa4\x68\x74\x20\x65\x73\x20"
+ u8"\x64\xc3\xbc\x72\n");
+ }
+
+ void testEncoding()
+ {
+ QFETCH(QString, utf8string);
+
+ TestShell shell;
+ QCOMPARE(shell.state(), DeviceShell::State::Succeeded);
+
+ const DeviceShell::RunResult r = shell.outputForRunInShell({"cat", {}}, utf8string.toUtf8());
+ const QString output = QString::fromUtf8(r.stdOut);
+ QCOMPARE(output, utf8string);
+ }
+
+ void testThreading_data()
+ {
+ QTest::addColumn<int>("numThreads");
+ QTest::addColumn<int>("numIterations");
+
+ QTest::newRow("multi-threaded") << 10 << 1000;
+ QTest::newRow("single-threaded") << 1 << 1000;
+ }
+
+ void testThreading()
+ {
+ QFETCH(int, numThreads);
+ QFETCH(int, numIterations);
+
+ test(numThreads, numIterations);
+ }
+
+ void testSleepMulti()
+ {
+ QList<int> testData{4, 7, 10, 3, 1, 10, 3, 3, 5, 4};
+ int full = std::accumulate(testData.begin(), testData.end(), 0);
+ qDebug() << "Testing sleep, full time is:" << full << "seconds";
+ QElapsedTimer t;
+ t.start();
+ testSleep(testData, 10);
+ const int multiThreadRunTime = t.restart();
+ testSleep(testData, 1);
+ const int singleThreadRunTime = t.elapsed();
+ QVERIFY(multiThreadRunTime < singleThreadRunTime);
+ }
+};
+
+QTEST_GUILESS_MAIN(tst_DeviceShell)
+
+#include "tst_deviceshell.moc"
diff --git a/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-build b/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-build
index 6aa5aad09ea..e7755cf0255 100644
--- a/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-build
+++ b/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-build
@@ -34,6 +34,7 @@ RUN apt-get update && \
nim \
linux-tools-common \
valgrind \
+ x11-apps \
&& apt-get clean
# && rm -rf /var/lib/apt/lists/*
diff --git a/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-clang-llbd-build b/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-clang-llbd-build
index 79137849e8b..63fae87f9a6 100644
--- a/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-clang-llbd-build
+++ b/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-clang-llbd-build
@@ -34,6 +34,7 @@ RUN apt-get update && \
nim \
linux-tools-common \
valgrind \
+ x11-apps \
&& apt-get clean
# && rm -rf /var/lib/apt/lists/*
diff --git a/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-run b/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-run
index 9731342fb4e..4ded6ab648a 100644
--- a/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-run
+++ b/tests/manual/docker/Dockerfile-qt-5-ubuntu-20.04-run
@@ -14,5 +14,7 @@ RUN apt-get update \
gdb \
linux-tools-common \
valgrind \
- && apt-get clean \
- && rm -rf /var/lib/apt/lists/*
+ x11-apps \
+ && apt-get clean
+
+# && rm -rf /var/lib/apt/lists/*
diff --git a/tests/manual/docker/README.md b/tests/manual/docker/README.md
index 078127fe60d..f7eec1e4dd0 100644
--- a/tests/manual/docker/README.md
+++ b/tests/manual/docker/README.md
@@ -35,7 +35,7 @@ For testing:
install similar docker images containing Qt, e.g. darkmattercoder/qt-build
-- Go to Tools -> Options -> Devices, 'Add', 'Apply' for both images.
+- Go to Edit -> Preferences -> Devices, 'Add', 'Apply' for both images.
Note that the Build container alone is sufficient also to run applications,
but using the Run container gives a more restricted setup closer to a
real world scenario.
diff --git a/tests/manual/manual.qbs b/tests/manual/manual.qbs
index 5a5bddbf29d..f36312fcd69 100644
--- a/tests/manual/manual.qbs
+++ b/tests/manual/manual.qbs
@@ -8,13 +8,12 @@ Project {
references: [
"debugger/gui/gui.qbs",
"debugger/simple/simple.qbs",
+ "deviceshell/deviceshell.qbs",
"fakevim/fakevim.qbs",
"pluginview/pluginview.qbs",
"process/process.qbs",
"proparser/testreader.qbs",
"shootout/shootout.qbs",
- "ssh/shell/shell.qbs",
- "ssh/sftpfsmodel/sftpfsmodel.qbs",
"widgets/widgets.qbs",
]
}
diff --git a/tests/manual/ssh/CMakeLists.txt b/tests/manual/ssh/CMakeLists.txt
deleted file mode 100644
index 91464d83178..00000000000
--- a/tests/manual/ssh/CMakeLists.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-add_subdirectory(sftpfsmodel)
-add_subdirectory(shell)
diff --git a/tests/manual/ssh/sftpfsmodel/CMakeLists.txt b/tests/manual/ssh/sftpfsmodel/CMakeLists.txt
deleted file mode 100644
index 3e6119cd911..00000000000
--- a/tests/manual/ssh/sftpfsmodel/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
-file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
-
-add_qtc_test(tst_manual_sftpfsmodel
- MANUALTEST
- DEPENDS Utils QtcSsh Qt5::Widgets
- INCLUDES "${PROJECT_SOURCE_DIR}/src/shared/modeltest"
- DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
- SOURCES
- main.cpp
- window.cpp window.h window.ui
-)
-
-extend_qtc_test(tst_manual_sftpfsmodel
- SOURCES_PREFIX "${PROJECT_SOURCE_DIR}/src/shared/modeltest/"
- SOURCES
- modeltest.cpp modeltest.h
-)
diff --git a/tests/manual/ssh/sftpfsmodel/main.cpp b/tests/manual/ssh/sftpfsmodel/main.cpp
deleted file mode 100644
index 15fa8535fac..00000000000
--- a/tests/manual/ssh/sftpfsmodel/main.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "window.h"
-
-#include <ssh/sftpfilesystemmodel.h>
-#include <ssh/sshconnection.h>
-#include <utils/launcherinterface.h>
-#include <utils/temporarydirectory.h>
-
-#include <QApplication>
-#include <QTreeView>
-
-int main(int argc, char *argv[])
-{
- QApplication app(argc, argv);
- Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
- + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
- Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath()
- + "/qtc-ssh-shelltest-XXXXXX");
- SftpFsWindow w;
- w.show();
- return app.exec();
-}
diff --git a/tests/manual/ssh/sftpfsmodel/sftpfsmodel.pro b/tests/manual/ssh/sftpfsmodel/sftpfsmodel.pro
deleted file mode 100644
index e768e8ea691..00000000000
--- a/tests/manual/ssh/sftpfsmodel/sftpfsmodel.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-include(../ssh.pri)
-include(../../../../src/shared/modeltest/modeltest.pri)
-
-QT += widgets
-
-TARGET=sftpfsmodel
-SOURCES+=main.cpp window.cpp
-HEADERS+=window.h
-FORMS=window.ui
diff --git a/tests/manual/ssh/sftpfsmodel/sftpfsmodel.qbs b/tests/manual/ssh/sftpfsmodel/sftpfsmodel.qbs
deleted file mode 100644
index 1216d806ec1..00000000000
--- a/tests/manual/ssh/sftpfsmodel/sftpfsmodel.qbs
+++ /dev/null
@@ -1,38 +0,0 @@
-import qbs
-import qbs.FileInfo
-
-QtcManualtest {
- name: "Manual sftpfs model test"
- condition: qbs.targetOS.contains("unix")
- Depends { name: "Utils" }
- Depends { name: "QtcSsh" }
- Depends { name: "Qt.widgets" }
-
- cpp.includePaths: [ "../../../../src/shared/modeltest" ]
-
- cpp.defines: {
- var defines = base;
- var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
- qtc.ide_libexec_path);
- var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
- defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
- return defines;
- }
-
- files: [
- "main.cpp",
- "window.cpp",
- "window.h",
- "window.ui",
- ]
-
- Group {
- name: "Model test files"
- prefix: "../../../../src/shared/modeltest/"
-
- files: [
- "modeltest.cpp",
- "modeltest.h"
- ]
- }
-}
diff --git a/tests/manual/ssh/sftpfsmodel/window.cpp b/tests/manual/ssh/sftpfsmodel/window.cpp
deleted file mode 100644
index 997d60787b6..00000000000
--- a/tests/manual/ssh/sftpfsmodel/window.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "window.h"
-#include "ui_window.h"
-
-#include "modeltest.h"
-
-#include <ssh/sftpfilesystemmodel.h>
-#include <ssh/sshconnection.h>
-
-#include <QApplication>
-#include <QDir>
-#include <QFileDialog>
-#include <QMessageBox>
-#include <QModelIndexList>
-#include <QItemSelectionModel>
-#include <QString>
-
-using namespace QSsh;
-
-SftpFsWindow::SftpFsWindow(QWidget *parent) : QDialog(parent), m_ui(new Ui::Window)
-{
- m_ui->setupUi(this);
- connect(m_ui->connectButton, &QAbstractButton::clicked, this, &SftpFsWindow::connectToHost);
- connect(m_ui->downloadButton, &QAbstractButton::clicked, this, &SftpFsWindow::downloadFile);
-}
-
-SftpFsWindow::~SftpFsWindow()
-{
- delete m_ui;
-}
-
-void SftpFsWindow::connectToHost()
-{
- m_ui->connectButton->setEnabled(false);
- SshConnectionParameters sshParams;
- sshParams.setHost(m_ui->hostLineEdit->text());
- sshParams.setUserName(m_ui->userLineEdit->text());
- sshParams.authenticationType
- = SshConnectionParameters::AuthenticationTypeAll;
- sshParams.setPort(m_ui->portSpinBox->value());
- sshParams.timeout = 10;
- m_fsModel = new SftpFileSystemModel(this);
- if (m_ui->useModelTesterCheckBox->isChecked())
- new ModelTest(m_fsModel, this);
- connect(m_fsModel, &SftpFileSystemModel::sftpOperationFailed,
- this, &SftpFsWindow::handleSftpOperationFailed);
- connect(m_fsModel, &SftpFileSystemModel::connectionError,
- this, &SftpFsWindow::handleConnectionError);
- connect(m_fsModel, &SftpFileSystemModel::sftpOperationFinished,
- this, &SftpFsWindow::handleSftpOperationFinished);
- m_fsModel->setSshConnection(sshParams);
- m_ui->fsView->setModel(m_fsModel);
-}
-
-void SftpFsWindow::downloadFile()
-{
- const QModelIndexList selectedIndexes = m_ui->fsView->selectionModel()->selectedIndexes();
- if (selectedIndexes.count() != 2)
- return;
- const QString targetFilePath = QFileDialog::getSaveFileName(this, tr("Choose Target File"),
- QDir::tempPath());
- if (targetFilePath.isEmpty())
- return;
- const SftpJobId jobId = m_fsModel->downloadFile(selectedIndexes.at(1), targetFilePath);
- QString message;
- if (jobId == SftpInvalidJob)
- message = tr("Download failed.");
- else
- message = tr("Queuing download operation %1.").arg(jobId);
- m_ui->outputTextEdit->appendPlainText(message);
-}
-
-void SftpFsWindow::handleSftpOperationFailed(const QString &errorMessage)
-{
- m_ui->outputTextEdit->appendPlainText(errorMessage);
-}
-
-void SftpFsWindow::handleSftpOperationFinished(SftpJobId jobId, const QString &error)
-{
- QString message;
- if (error.isEmpty())
- message = tr("Operation %1 finished successfully.").arg(jobId);
- else
- message = tr("Operation %1 failed: %2.").arg(jobId).arg(error);
- m_ui->outputTextEdit->appendPlainText(message);
-}
-
-void SftpFsWindow::handleConnectionError(const QString &errorMessage)
-{
- QMessageBox::warning(this, tr("Connection Error"),
- tr("Fatal SSH error: %1").arg(errorMessage));
- QCoreApplication::quit();
-}
diff --git a/tests/manual/ssh/sftpfsmodel/window.h b/tests/manual/ssh/sftpfsmodel/window.h
deleted file mode 100644
index d3ba03c1345..00000000000
--- a/tests/manual/ssh/sftpfsmodel/window.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include <ssh/sftpdefs.h>
-
-#include <QDialog>
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class Window; }
-QT_END_NAMESPACE
-
-namespace QSsh { class SftpFileSystemModel; }
-
-class SftpFsWindow : public QDialog
-{
- Q_OBJECT
-public:
- SftpFsWindow(QWidget *parent = 0);
- ~SftpFsWindow();
-
-private:
- void connectToHost();
- void downloadFile();
- void handleConnectionError(const QString &errorMessage);
- void handleSftpOperationFailed(const QString &errorMessage);
- void handleSftpOperationFinished(QSsh::SftpJobId jobId, const QString &error);
-
- QSsh::SftpFileSystemModel *m_fsModel;
- Ui::Window *m_ui;
-};
diff --git a/tests/manual/ssh/sftpfsmodel/window.ui b/tests/manual/ssh/sftpfsmodel/window.ui
deleted file mode 100644
index 314236daa69..00000000000
--- a/tests/manual/ssh/sftpfsmodel/window.ui
+++ /dev/null
@@ -1,201 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Window</class>
- <widget class="QDialog" name="Window">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>546</width>
- <height>676</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Dialog</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Connection Parameters</string>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Remote host:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="hostLineEdit"/>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>User:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="userLineEdit"/>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Port:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QSpinBox" name="portSpinBox">
- <property name="value">
- <number>22</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="useModelTesterCheckBox">
- <property name="text">
- <string>Use model tester</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="title">
- <string>Remote File System</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QTreeView" name="fsView">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>1</horstretch>
- <verstretch>1</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QPushButton" name="connectButton">
- <property name="text">
- <string>Connect</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="downloadButton">
- <property name="text">
- <string>Download...</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_3">
- <property name="title">
- <string>Debug output</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QPlainTextEdit" name="outputTextEdit"/>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Close</set>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>Window</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
- </hint>
- <hint type="destinationlabel">
- <x>286</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>Window</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>248</x>
- <y>254</y>
- </hint>
- <hint type="destinationlabel">
- <x>157</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- </connections>
-</ui>
diff --git a/tests/manual/ssh/shell/CMakeLists.txt b/tests/manual/ssh/shell/CMakeLists.txt
deleted file mode 100644
index f7748f2e96b..00000000000
--- a/tests/manual/ssh/shell/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
-file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
-
-add_qtc_test(tst_manual_shell
- MANUALTEST
- CONDITION UNIX
- DEPENDS Utils QtcSsh Qt5::Network
- DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
- SOURCES
- argumentscollector.cpp argumentscollector.h
- main.cpp
- shell.cpp shell.h
-)
diff --git a/tests/manual/ssh/shell/argumentscollector.cpp b/tests/manual/ssh/shell/argumentscollector.cpp
deleted file mode 100644
index e9e7e61888b..00000000000
--- a/tests/manual/ssh/shell/argumentscollector.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "argumentscollector.h"
-
-#include <QDir>
-#include <QProcessEnvironment>
-
-#include <iostream>
-
-using namespace QSsh;
-
-using namespace std;
-
-ArgumentsCollector::ArgumentsCollector(const QStringList &args)
- : m_arguments(args)
-{
-}
-
-SshConnectionParameters ArgumentsCollector::collect(bool &success) const
-{
- SshConnectionParameters parameters;
- try {
- bool authTypeGiven = false;
- bool portGiven = false;
- bool timeoutGiven = false;
- int pos;
- int port = 22;
-
- for (pos = 1; pos < m_arguments.count() - 1; ++pos) {
- QString str;
- if (checkAndSetStringArg(pos, str, "-h")) {
- parameters.setHost(str);
- } else if (checkAndSetStringArg(pos, str, "-u")) {
- parameters.setUserName(str);
- } else if (checkAndSetIntArg(pos, port, portGiven, "-p")
- || checkAndSetIntArg(pos, parameters.timeout, timeoutGiven, "-t")) {
- continue;
- } else if (checkAndSetStringArg(pos, str, "-k")) {
- parameters.privateKeyFile = Utils::FilePath::fromString(str);
- parameters.authenticationType
- = SshConnectionParameters::AuthenticationTypeSpecificKey;
- authTypeGiven = true;
- }
- }
-
- Q_ASSERT(pos <= m_arguments.count());
-
- if (!authTypeGiven)
- parameters.authenticationType = SshConnectionParameters::AuthenticationTypeAll;
-
- if (parameters.userName().isEmpty())
- parameters.setUserName(QProcessEnvironment::systemEnvironment().value("USER"));
- if (parameters.userName().isEmpty())
- throw ArgumentErrorException(QLatin1String("No user name given."));
-
- if (parameters.host().isEmpty())
- throw ArgumentErrorException(QLatin1String("No host given."));
-
- parameters.setPort(portGiven ? port : 22);
- if (!timeoutGiven)
- parameters.timeout = 30;
- success = true;
- } catch (ArgumentErrorException &ex) {
- cerr << "Error: " << qPrintable(ex.error) << endl;
- printUsage();
- success = false;
- }
- return parameters;
-}
-
-void ArgumentsCollector::printUsage() const
-{
- cerr << "Usage: " << qPrintable(m_arguments.first())
- << " -h <host> [ -u <user> ] "
- << "[ -k <private key file> ] [ -p <port> ] "
- << "[ -t <timeout> ] [ -no-proxy ]" << endl;
-}
-
-bool ArgumentsCollector::checkAndSetStringArg(int &pos, QString &arg, const char *opt) const
-{
- if (m_arguments.at(pos) == QLatin1String(opt)) {
- if (!arg.isEmpty()) {
- throw ArgumentErrorException(QLatin1String("option ") + QLatin1String(opt)
- + QLatin1String(" was given twice."));
- }
- arg = m_arguments.at(++pos);
- if (arg.isEmpty() && QLatin1String(opt) != QLatin1String("-pwd"))
- throw ArgumentErrorException(QLatin1String("empty argument not allowed here."));
- return true;
- }
- return false;
-}
-
-bool ArgumentsCollector::checkAndSetIntArg(int &pos, int &val,
- bool &alreadyGiven, const char *opt) const
-{
- if (m_arguments.at(pos) == QLatin1String(opt)) {
- if (alreadyGiven) {
- throw ArgumentErrorException(QLatin1String("option ") + QLatin1String(opt)
- + QLatin1String(" was given twice."));
- }
- bool isNumber;
- val = m_arguments.at(++pos).toInt(&isNumber);
- if (!isNumber) {
- throw ArgumentErrorException(QLatin1String("option ") + QLatin1String(opt)
- + QLatin1String(" needs integer argument"));
- }
- alreadyGiven = true;
- return true;
- }
- return false;
-}
diff --git a/tests/manual/ssh/shell/argumentscollector.h b/tests/manual/ssh/shell/argumentscollector.h
deleted file mode 100644
index 4d36ca18020..00000000000
--- a/tests/manual/ssh/shell/argumentscollector.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <ssh/sshconnection.h>
-
-#include <QStringList>
-
-class ArgumentsCollector
-{
-public:
- ArgumentsCollector(const QStringList &args);
- QSsh::SshConnectionParameters collect(bool &success) const;
-private:
- struct ArgumentErrorException
- {
- ArgumentErrorException(const QString &error) : error(error) {}
- const QString error;
- };
-
- void printUsage() const;
- bool checkAndSetStringArg(int &pos, QString &arg, const char *opt) const;
- bool checkAndSetIntArg(int &pos, int &val, bool &alreadyGiven,
- const char *opt) const;
-
- const QStringList m_arguments;
-};
diff --git a/tests/manual/ssh/shell/main.cpp b/tests/manual/ssh/shell/main.cpp
deleted file mode 100644
index c47471ae7de..00000000000
--- a/tests/manual/ssh/shell/main.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "argumentscollector.h"
-#include "shell.h"
-
-#include <ssh/sshconnection.h>
-#include <utils/launcherinterface.h>
-#include <utils/temporarydirectory.h>
-
-#include <QCoreApplication>
-#include <QDir>
-#include <QObject>
-#include <QStringList>
-
-#include <cstdlib>
-#include <iostream>
-
-int main(int argc, char *argv[])
-{
- QCoreApplication app(argc, argv);
- Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
- + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
- bool parseSuccess;
- const QSsh::SshConnectionParameters &parameters
- = ArgumentsCollector(app.arguments()).collect(parseSuccess);
- if (!parseSuccess)
- return EXIT_FAILURE;
- Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath()
- + "/qtc-ssh-shelltest-XXXXXX");
- Shell shell(parameters);
- shell.run();
- return app.exec();
-}
diff --git a/tests/manual/ssh/shell/shell.cpp b/tests/manual/ssh/shell/shell.cpp
deleted file mode 100644
index a588a17c908..00000000000
--- a/tests/manual/ssh/shell/shell.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "shell.h"
-
-#include <ssh/sshremoteprocess.h>
-
-#include <QCoreApplication>
-#include <QFile>
-#include <QSocketNotifier>
-
-#include <cstdlib>
-#include <iostream>
-
-using namespace QSsh;
-
-Shell::Shell(const SshConnectionParameters &parameters, QObject *parent)
- : QObject(parent),
- m_connection(new SshConnection(parameters)),
- m_stdin(new QFile(this))
-{
- connect(m_connection, &SshConnection::connected, this, &Shell::handleConnected);
- connect(m_connection, &SshConnection::errorOccurred, this, &Shell::handleConnectionError);
-}
-
-Shell::~Shell()
-{
- delete m_connection;
-}
-
-void Shell::run()
-{
- if (!m_stdin->open(stdin, QIODevice::ReadOnly | QIODevice::Unbuffered)) {
- std::cerr << "Error: Cannot read from standard input." << std::endl;
- QCoreApplication::exit(EXIT_FAILURE);
- return;
- }
-
- m_connection->connectToHost();
-}
-
-void Shell::handleConnectionError()
-{
- std::cerr << "SSH connection error: " << qPrintable(m_connection->errorString()) << std::endl;
- QCoreApplication::exit(EXIT_FAILURE);
-}
-
-void Shell::handleConnected()
-{
- m_shell = m_connection->createRemoteShell();
- connect(m_shell.get(), &SshRemoteProcess::started, this, &Shell::handleShellStarted);
- connect(m_shell.get(), &SshRemoteProcess::readyReadStandardOutput,
- this, &Shell::handleRemoteStdout);
- connect(m_shell.get(), &SshRemoteProcess::readyReadStandardError,
- this, &Shell::handleRemoteStderr);
- connect(m_shell.get(), &SshRemoteProcess::done, this, &Shell::handleChannelClosed);
- m_shell->start();
-}
-
-void Shell::handleShellStarted()
-{
- QSocketNotifier * const notifier = new QSocketNotifier(0, QSocketNotifier::Read, this);
- connect(notifier, &QSocketNotifier::activated, this, &Shell::handleStdin);
-}
-
-void Shell::handleRemoteStdout()
-{
- std::cout << m_shell->readAllStandardOutput().data() << std::flush;
-}
-
-void Shell::handleRemoteStderr()
-{
- std::cerr << m_shell->readAllStandardError().data() << std::flush;
-}
-
-void Shell::handleChannelClosed(const QString &error)
-{
- std::cerr << "Shell closed. Exit code was " << m_shell->exitCode() << "." << std::endl;
- QCoreApplication::exit(error.isEmpty() && m_shell->exitCode() == 0
- ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-void Shell::handleStdin()
-{
- m_shell->write(m_stdin->readLine());
-}
diff --git a/tests/manual/ssh/shell/shell.h b/tests/manual/ssh/shell/shell.h
deleted file mode 100644
index afebee0de40..00000000000
--- a/tests/manual/ssh/shell/shell.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <ssh/sshconnection.h>
-
-#include <QObject>
-
-QT_BEGIN_NAMESPACE
-class QByteArray;
-class QFile;
-class QString;
-QT_END_NAMESPACE
-
-class Shell : public QObject
-{
- Q_OBJECT
-public:
- Shell(const QSsh::SshConnectionParameters &parameters, QObject *parent = 0);
- ~Shell();
-
- void run();
-
-private:
- void handleConnected();
- void handleConnectionError();
- void handleRemoteStdout();
- void handleRemoteStderr();
- void handleShellMessage(const QString &message);
- void handleChannelClosed(const QString &error);
- void handleShellStarted();
- void handleStdin();
-
- QSsh::SshConnection *m_connection;
- QSsh::SshRemoteProcessPtr m_shell;
- QFile * const m_stdin;
-};
diff --git a/tests/manual/ssh/shell/shell.pro b/tests/manual/ssh/shell/shell.pro
deleted file mode 100644
index f7d0b174f0e..00000000000
--- a/tests/manual/ssh/shell/shell.pro
+++ /dev/null
@@ -1,6 +0,0 @@
-include(../ssh.pri)
-QT += network
-
-TARGET=shell
-SOURCES=main.cpp shell.cpp argumentscollector.cpp
-HEADERS=shell.h argumentscollector.h
diff --git a/tests/manual/ssh/shell/shell.qbs b/tests/manual/ssh/shell/shell.qbs
deleted file mode 100644
index f8cc41a0223..00000000000
--- a/tests/manual/ssh/shell/shell.qbs
+++ /dev/null
@@ -1,27 +0,0 @@
-import qbs
-import qbs.FileInfo
-
-QtcManualtest {
- name: "Manual ssh shell test"
- condition: qbs.targetOS.contains("unix")
- Depends { name: "Utils" }
- Depends { name: "QtcSsh" }
- Depends { name: "Qt.network" }
-
- cpp.defines: {
- var defines = base;
- var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
- qtc.ide_libexec_path);
- var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
- defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
- return defines;
- }
-
- files: [
- "argumentscollector.cpp",
- "argumentscollector.h",
- "main.cpp",
- "shell.cpp",
- "shell.h",
- ]
-}
diff --git a/tests/manual/ssh/ssh.pri b/tests/manual/ssh/ssh.pri
deleted file mode 100644
index b7927278b87..00000000000
--- a/tests/manual/ssh/ssh.pri
+++ /dev/null
@@ -1,17 +0,0 @@
-QT = core network
-
-QTC_LIB_DEPENDS += ssh utils
-include (../../../qtcreator.pri)
-
-macx:QMAKE_LFLAGS += -Wl,-rpath,\"$$IDE_BIN_PATH/..\"
-LIBS *= -L$$IDE_LIBRARY_PATH
-unix {
- QMAKE_LFLAGS += -Wl,-rpath,\"$$IDE_LIBRARY_PATH\"
-}
-
-CONFIG += console
-CONFIG -= app_bundle
-TEMPLATE = app
-
-DEPENDPATH+=.
-INCLUDEPATH+=.
diff --git a/tests/manual/ssh/ssh.pro b/tests/manual/ssh/ssh.pro
deleted file mode 100644
index 1801bd1d9b0..00000000000
--- a/tests/manual/ssh/ssh.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-#-------------------------------------------------
-#
-# Project created by QtCreator 2010-07-01T09:44:44
-#
-#-------------------------------------------------
-
-TEMPLATE = subdirs
-SUBDIRS = shell sftpfsmodel
diff --git a/tests/manual/widgets/crumblepath/crumblepath.qbs b/tests/manual/widgets/crumblepath/crumblepath.qbs
index af1860a52ec..c9b32a0810f 100644
--- a/tests/manual/widgets/crumblepath/crumblepath.qbs
+++ b/tests/manual/widgets/crumblepath/crumblepath.qbs
@@ -3,6 +3,7 @@ import "../common/common.qbs" as Common
CppApplication {
name: "Manual Test Utils CrumblePath"
+ Depends { name: "qtc" }
Depends { name: "Core" }
Depends { name: "Utils" }
diff --git a/tests/manual/widgets/infolabel/infolabel.qbs b/tests/manual/widgets/infolabel/infolabel.qbs
index ce00065c7cf..dfba3bd9ef7 100644
--- a/tests/manual/widgets/infolabel/infolabel.qbs
+++ b/tests/manual/widgets/infolabel/infolabel.qbs
@@ -3,6 +3,7 @@ import "../common/common.qbs" as Common
CppApplication {
name: "Manual Test Utils InfoLabel"
+ Depends { name: "qtc" }
Depends { name: "Core" }
Depends { name: "Utils" }
diff --git a/tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp b/tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp
index 67e406c5884..803125fc48c 100644
--- a/tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp
+++ b/tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp
@@ -54,13 +54,15 @@ int main(int argc, char *argv[])
const static struct {
const InfoLabel::InfoType type;
const char *text;
+ const char *tooltip;
+ const char *tooltipSeparator;
} labels[] = {
- {InfoLabel::Information, "Information"},
- {InfoLabel::Warning, "Warning"},
- {InfoLabel::Error, "Error"},
- {InfoLabel::Ok, "Ok"},
- {InfoLabel::NotOk, "NotOk"},
- {InfoLabel::None, "None"},
+ {InfoLabel::Information, "Information", "This is an informative Tooltip for you", "\n\n"},
+ {InfoLabel::Warning, "Warning", "This is a warning Tooltip for you", " - "},
+ {InfoLabel::Error, "Error", "This is an erroneous Tooltip for you", " | "},
+ {InfoLabel::Ok, "Ok", "This is an ok Tooltip for you", " :) "},
+ {InfoLabel::NotOk, "NotOk", "This Tooltip is just not ok", ""},
+ {InfoLabel::None, "None", "", "----"},
};
int gridRow = 0;
@@ -72,6 +74,8 @@ int main(int argc, char *argv[])
+ QLatin1String(enabled ? "" : " (disabled)"), label.type);
infoLabel->setEnabled(enabled);
infoLabel->setFilled(filled);
+ infoLabel->setAdditionalToolTip(label.tooltip);
+ infoLabel->setAdditionalToolTipSeparator(label.tooltipSeparator);
variationsLayout->addWidget(infoLabel, gridRow, enabled ? 0 : 1);
}
gridRow++;
@@ -102,11 +106,27 @@ int main(int argc, char *argv[])
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
"ullamco laboris nisi ut aliquid ex ea commodi consequat.";
- mainLayout->addWidget(new Utils::InfoLabel("Qt::ElideRight: " + lorem, InfoLabel::Information));
+ auto elideRight = new Utils::InfoLabel("Qt::ElideRight: " + lorem, InfoLabel::Information);
+ elideRight->setAdditionalToolTip("This control will elide the right side and show an Information Icon to its left. The Elided text will be separated from this text by two \\n");
+ mainLayout->addWidget(elideRight);
+
+ auto elideLeft = new Utils::InfoLabel("Qt::ElideLeft: " + lorem, InfoLabel::Warning);
+ elideLeft->setElideMode(Qt::ElideLeft);
+ elideLeft->setAdditionalToolTip("This control will elide the left side and show a Warning Icon to its left. The Elided text will be separated from this text by \" :) \"");
+ elideLeft->setAdditionalToolTipSeparator(" :) ");
+ mainLayout->addWidget(elideLeft);
+
+ auto elideMid= new Utils::InfoLabel("Qt::ElideMiddle: " + lorem, InfoLabel::Ok);
+ elideMid->setElideMode(Qt::ElideMiddle);
+ elideMid->setAdditionalToolTip("This control will elide the middle and show an Ok Icon to its left. The Elided text will be separated from this text by \" -> \"");
+ elideMid->setAdditionalToolTipSeparator(" -> ");
+ mainLayout->addWidget(elideMid);
+
auto elideNone = new Utils::InfoLabel("Qt::ElideNone: " + lorem, InfoLabel::Information);
elideNone->setElideMode(Qt::ElideNone);
elideNone->setWordWrap(true);
+ elideNone->setAdditionalToolTip("This control is never elided due to setElideMode(Qt::ElideNone) being used");
mainLayout->addWidget(elideNone);
widget->resize(350, 500);
diff --git a/tests/manual/widgets/manhattanstyle/manhattanstyle.qbs b/tests/manual/widgets/manhattanstyle/manhattanstyle.qbs
index 97a728a6f63..c04bd03e89f 100644
--- a/tests/manual/widgets/manhattanstyle/manhattanstyle.qbs
+++ b/tests/manual/widgets/manhattanstyle/manhattanstyle.qbs
@@ -3,6 +3,7 @@ import "../common/common.qbs" as Common
CppApplication {
name: "Manual Test Utils ManhattanStyle"
+ Depends { name: "qtc" }
Depends { name: "Core" }
Depends { name: "Utils" }
diff --git a/tests/manual/widgets/tracing/tracing.qbs b/tests/manual/widgets/tracing/tracing.qbs
index 06bbc4edd4a..95e661910ce 100644
--- a/tests/manual/widgets/tracing/tracing.qbs
+++ b/tests/manual/widgets/tracing/tracing.qbs
@@ -3,6 +3,7 @@ import "../common/common.qbs" as Common
CppApplication {
name: "Manual Test Tracing"
+ Depends { name: "qtc" }
Depends { name: "Qt.quick" }
Depends { name: "Tracing" }
Depends { name: "Utils" }
diff --git a/tests/system/objects.map b/tests/system/objects.map
index 81120f94964..7922cacca2c 100644
--- a/tests/system/objects.map
+++ b/tests/system/objects.map
@@ -89,7 +89,7 @@
:JsonWizard_ProjectExplorer::JsonFieldPage {type='ProjectExplorer::JsonFieldPage' unnamed='1' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:Kits_QtVersion_QComboBox {container=':qt_tabwidget_stackedwidget_QWidget' leftWidget=':QtVersionLabel_KitPage' type='QComboBox' unnamed='1' visible='1'}
:Locals and Expressions_Debugger::Internal::WatchTreeView {container=':Debugger.Docks.LocalsAndWatchersDockWidget.Inspector_QFrame' name='WatchWindow' type='Debugger::Internal::WatchTreeView' visible='1'}
-:Minimal required Qt version:_QLabel {text='Minimal required Qt version:' type='QLabel' unnamed='1' visible='1' window=':New_ProjectExplorer::JsonWizard'}
+:Minimal required Qt version:_QLabel {text='Minimum required Qt version:' type='QLabel' unnamed='1' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:New Text File.Add to project:_QLabel {name='projectLabel' text='Add to project:' type='QLabel' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:New Text File.nameLineEdit_Utils::FileNameValidatingLineEdit {name='nameLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:New.comboBox_QComboBox {name='comboBox' type='QComboBox' visible='1' window=':New_Core::Internal::NewDialog'}
diff --git a/tests/system/shared/clang.py b/tests/system/shared/clang.py
index cccafa8a205..43976ab3aca 100644
--- a/tests/system/shared/clang.py
+++ b/tests/system/shared/clang.py
@@ -52,7 +52,7 @@ def startCreatorVerifyingClang(useClang):
return False
def __openCodeModelOptions__():
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "C++"))
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Code Model")
diff --git a/tests/system/shared/suites_qtta.py b/tests/system/shared/suites_qtta.py
index 64a31e6a9a4..dc7424a59a8 100644
--- a/tests/system/shared/suites_qtta.py
+++ b/tests/system/shared/suites_qtta.py
@@ -59,7 +59,7 @@ def checkSyntaxError(issuesView, expectedTextsArray, warnIfMoreIssues = True):
# change autocomplete options to manual
def changeAutocompleteToManual(toManual=True):
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Text Editor"))
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Completion")
ensureChecked(waitForObject(":Behavior.Autocomplete common prefix_QCheckBox"), not toManual)
diff --git a/tests/system/shared/utils.py b/tests/system/shared/utils.py
index 72f38a52852..9a7332c6d16 100644
--- a/tests/system/shared/utils.py
+++ b/tests/system/shared/utils.py
@@ -180,7 +180,7 @@ def invokeMenuItem(menu, item, *subItems):
except:
nativeMouseClick(waitForObject(":Qt Creator_Core::Internal::MainWindow", 1000), 20, 20, 0, Qt.LeftButton)
# Use Locator for menu items which wouldn't work on macOS
- if menu == "Tools" and item == "Options..." or menu == "File" and item == "Exit":
+ if menu == "Edit" and item == "Preferences..." or menu == "File" and item == "Exit":
selectFromLocator("t %s" % item, item)
return
menuObject = waitForObjectItem(":Qt Creator.QtCreator.MenuBar_QMenuBar", menu)
@@ -269,7 +269,7 @@ def selectFromFileDialog(fileName, waitForFile=False, ignoreFinalSnooze=False):
# add Qt documentations from given paths
# param which a list/tuple of the paths to the qch files to be added
def addHelpDocumentation(which):
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Help"))
waitForObject("{container=':Options.qt_tabwidget_tabbar_QTabBar' type='TabItem' text='Documentation'}")
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Documentation")
@@ -295,7 +295,7 @@ def addCurrentCreatorDocumentation():
if not os.path.exists(docPath):
test.fatal("Missing current Qt Creator documentation (expected in %s)" % docPath)
return
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Help"))
waitForObject("{container=':Options.qt_tabwidget_tabbar_QTabBar' type='TabItem' text='Documentation'}")
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Documentation")
@@ -398,7 +398,7 @@ def regexVerify(text, expectedTexts):
# the function returns a list of the found Qt versions
def iterateQtVersions():
qtVersionNames = []
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Kits"))
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Qt Versions")
treeView = waitForObject(":qtdirList_QTreeView")
@@ -417,7 +417,7 @@ def iterateQtVersions():
# param clickOkWhenDone set to True if the Options dialog should be closed by clicking the
# "OK" button. If False, the dialog will stay open
# param alreadyOnOptionsDialog set to True if you already have opened the Options Dialog
-# (if False this function will open it via the MenuBar -> Tools -> Options...)
+# (if False this function will open it via the MenuBar -> Edit -> Preferences...)
# param additionalFunction pass a function or name of a defined function to execute
# for each configured item on the list of Kits
# this function must take at least 2 parameters - the first is the full string
@@ -434,7 +434,7 @@ def iterateKits(clickOkWhenDone, alreadyOnOptionsDialog,
result = []
additionalResult = []
if not alreadyOnOptionsDialog:
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Kits"))
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Kits")
treeView = waitForObject(":BuildAndRun_QTreeView")
@@ -470,7 +470,7 @@ class HelpViewer:
HELPMODE, SIDEBYSIDE, EXTERNALWINDOW = range(3)
def setFixedHelpViewer(helpViewer):
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Help"))
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "General")
mode = "Always Show "
@@ -582,11 +582,11 @@ def openVcsLog():
waitForObject("{text='Version Control' type='QLabel' unnamed='1' visible='1' "
"window=':Qt Creator_Core::Internal::MainWindow'}", 2000)
except:
- invokeMenuItem("View", "Output Panes", "Version Control")
+ invokeMenuItem("View", "Output", "Version Control")
def openGeneralMessages():
if not object.exists(":Qt Creator_Core::OutputWindow"):
- invokeMenuItem("View", "Output Panes", "General Messages")
+ invokeMenuItem("View", "Output", "General Messages")
# function that retrieves a specific child object by its class
# this is sometimes the best way to avoid using waitForObject() on objects that
diff --git a/tests/system/suite_HELP/tst_HELP02/test.py b/tests/system/suite_HELP/tst_HELP02/test.py
index 921a1c701b9..aee31c78e80 100644
--- a/tests/system/suite_HELP/tst_HELP02/test.py
+++ b/tests/system/suite_HELP/tst_HELP02/test.py
@@ -72,7 +72,7 @@ def _shortcutMatches_(shortcutEdit, expectedText):
def setKeyboardShortcutForAboutQtC():
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Environment"))
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Keyboard")
filter = waitForObject("{container={title='Keyboard Shortcuts' type='QGroupBox' unnamed='1' "
diff --git a/tests/system/suite_QMLS/tst_QMLS02/test.py b/tests/system/suite_QMLS/tst_QMLS02/test.py
index a89be4d0327..5807691d31e 100644
--- a/tests/system/suite_QMLS/tst_QMLS02/test.py
+++ b/tests/system/suite_QMLS/tst_QMLS02/test.py
@@ -41,7 +41,7 @@ def main():
type(editorArea, "<Return>")
type(editorArea, testingCodeLine)
- invokeMenuItem("View", "Output Panes", "Issues")
+ invokeMenuItem("View", "Output", "Issues")
issuesView = waitForObject(":Qt Creator.Issues_QListView")
clickButton(waitForObject(":*Qt Creator.Clear_QToolButton"))
diff --git a/tests/system/suite_debugger/tst_qml_js_console/test.py b/tests/system/suite_debugger/tst_qml_js_console/test.py
index 206e3f8a25b..82c6510974a 100644
--- a/tests/system/suite_debugger/tst_qml_js_console/test.py
+++ b/tests/system/suite_debugger/tst_qml_js_console/test.py
@@ -149,7 +149,7 @@ def main():
mainRect = getQModelIndexStr("text='Rectangle'", rootIndex)
doubleClick(waitForObject(mainRect))
if not object.exists(":DebugModeWidget_Debugger::Internal::ConsoleView"):
- invokeMenuItem("View", "Output Panes", "QML Debugger Console")
+ invokeMenuItem("View", "Output", "QML Debugger Console")
# Window might be too small to show Locals, so close what we don't need
for view in ("Stack", "Breakpoints", "Expressions"):
invokeMenuItem("View", "Views", view)
diff --git a/tests/system/suite_editors/tst_clean_whitespaces/test.py b/tests/system/suite_editors/tst_clean_whitespaces/test.py
index bf6e83a6e26..7a6decacb67 100644
--- a/tests/system/suite_editors/tst_clean_whitespaces/test.py
+++ b/tests/system/suite_editors/tst_clean_whitespaces/test.py
@@ -131,7 +131,7 @@ def isIgnoredFile(fileName, ignoredFiles):
def ignoredFilesFromSettings():
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Text Editor"))
waitForObject("{container=':Options.qt_tabwidget_tabbar_QTabBar' type='TabItem' "
"text='Behavior'}")
diff --git a/tests/system/suite_editors/tst_edit_externally/test.py b/tests/system/suite_editors/tst_edit_externally/test.py
index d0fd4a643e8..4bf6c2bf790 100644
--- a/tests/system/suite_editors/tst_edit_externally/test.py
+++ b/tests/system/suite_editors/tst_edit_externally/test.py
@@ -48,7 +48,7 @@ def main():
mBox = ("{text?='The file * has been changed on disk. Do you want to reload it?' "
"type='QMessageBox' unnamed='1' visible='1'}")
popupText = ("<p>The file <i>%s</i> has been changed on disk. Do you want to reload it?</p>"
- "<p>The default behavior can be set in Tools > Options > Environment > System.</p>")
+ "<p>The default behavior can be set in Edit > Preferences > Environment > System.</p>")
formerContent = None
for i, currentFile in enumerate(files):
diff --git a/tests/system/suite_editors/tst_generic_highlighter/test.py b/tests/system/suite_editors/tst_generic_highlighter/test.py
index e3975c787e7..fc5808f6924 100644
--- a/tests/system/suite_editors/tst_generic_highlighter/test.py
+++ b/tests/system/suite_editors/tst_generic_highlighter/test.py
@@ -52,7 +52,7 @@ def getOrModifyFilePatternsFor(mimeType, filter='', toBePresent=None):
toSuffixArray = lambda x : [pat.replace("*", "") for pat in x.split(";")]
result = []
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Environment"))
waitForObject("{container=':Options.qt_tabwidget_tabbar_QTabBar' type='TabItem' "
"text='MIME Types'}")
@@ -115,7 +115,7 @@ def addHighlighterDefinition(*languages):
syntaxDirectory = __highlighterDefinitionsDirectory__()
toBeChecked = (os.path.join(syntaxDirectory, x + ".xml") for x in languages)
test.log("Updating highlighter definitions...")
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Text Editor"))
waitForObject("{container=':Options.qt_tabwidget_tabbar_QTabBar' type='TabItem' "
"text='Generic Highlighter'}")
diff --git a/tests/system/suite_general/tst_create_proj_wizard/test.py b/tests/system/suite_general/tst_create_proj_wizard/test.py
index 38550a96aff..00bccc86259 100644
--- a/tests/system/suite_general/tst_create_proj_wizard/test.py
+++ b/tests/system/suite_general/tst_create_proj_wizard/test.py
@@ -55,14 +55,19 @@ def main():
# skip non-configurable
if "Import" in category:
continue
+ # FIXME
+ if "Qt for Python" in category:
+ continue
mouseClick(waitForObjectItem(categoriesView, "Projects." + category))
templatesView = waitForObject("{name='templatesView' type='QListView' visible='1'}")
# needed because categoriesView and templatesView using same model
for template in dumpItems(templatesView.model(), templatesView.rootIndex()):
template = template.replace(".", "\\.")
+ # FIXME this needs Qt6.2+
+ if template == "Qt Quick 2 Extension Plugin":
+ continue
# skip non-configurable
- if (template not in ["Qt Quick UI Prototype", "Auto Test Project", "Qt Creator Plugin"]
- and "Qt for Python - " not in template): # FIXME
+ if template not in ["Qt Quick UI Prototype", "Auto Test Project", "Qt Creator Plugin"]:
availableProjectTypes.append({category:template})
safeClickButton("Cancel")
for current in availableProjectTypes:
diff --git a/tests/system/suite_general/tst_default_settings/test.py b/tests/system/suite_general/tst_default_settings/test.py
index 29c65425b09..88b2160e5ea 100644
--- a/tests/system/suite_general/tst_default_settings/test.py
+++ b/tests/system/suite_general/tst_default_settings/test.py
@@ -35,7 +35,7 @@ def main():
appContext = startQC(['-settingspath', '"%s"' % emptySettings], False)
if not startedWithoutPluginError():
return
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
__checkKits__()
clickButton(waitForObject(":Options.Cancel_QPushButton"))
invokeMenuItem("File", "Exit")
@@ -171,37 +171,6 @@ def __kitFunc__(it, foundQt, foundCompNames):
details = details.replace("<b>", "").replace("</b>", "")
test.warning("Detected error and/or warning: %s" % details)
-def __extendExpectedCompilersWithInternalClang__(expected):
- global appContext
- # QC ships a clang itself
- regex = '^(.*(qtcreator(.exe)?|Qt Creator))( .*)?$' # QC with optional arguments
- qcPath = re.match(regex, appContext.commandLine)
- if qcPath is None:
- test.warning("Regular expression failed.")
- else:
- qcPath = qcPath.group(1)
- if platform.system() == 'Darwin':
- internalClang = os.path.join(qcPath, '..', '..', 'Resources')
- elif platform.system() in ('Windows', 'Microsoft'):
- internalClang = os.path.join(qcPath, '..')
- else:
- internalClang = os.path.join(qcPath, '..', '..', 'libexec', 'qtcreator')
- internalClang = os.path.join(internalClang, 'clang', 'bin', 'clang')
- if platform.system() in ('Microsoft', 'Windows'):
- internalClang += '-cl.exe'
- internalClang = os.path.abspath(internalClang)
- if os.path.exists(internalClang):
- if platform.system() in ('Microsoft', 'Windows'):
- # just add a fuzzy comparable name - everything else is not worth the effort here
- expected.append({'^Default LLVM \d{2} bit based on MSVC\d{4}$':''})
- else:
- expected.append(internalClang)
- else:
- test.fail("QC package seems to be faulty - missing internal provided clang.\nIf this "
- "is not a package, but a self-compiled QC, just copy the clang executable "
- "located inside the LLVM_INSTALL_DIR/bin (used while building) to the "
- "expected path.", "Expected '%s'" % internalClang)
-
def __getExpectedCompilers__():
# TODO: enhance this to distinguish between C and C++ compilers
expected = []
@@ -219,8 +188,6 @@ def __getExpectedCompilers__():
if xcodeClang and os.path.exists(xcodeClang) and xcodeClang not in expected:
expected.append(xcodeClang)
- __extendExpectedCompilersWithInternalClang__(expected)
-
for compiler in compilers:
compilerPath = which(compiler)
if compilerPath:
@@ -309,13 +276,6 @@ def __compareCompilers__(foundCompilers, expectedCompilers):
if isString(currentExp):
continue
key = currentExp.keys()[0]
- # special case for (fuzzy) regex comparison on Windows (internal LLVM)
- if isWin and key.startswith('^') and key.endswith('$'):
- if re.match(key, currentFound.keys()[0], flags):
- test.verify(os.path.exists(currentFound.values()[0].rsplit(" ", 1)[0]),
- "Verifying whether shipped clang got set up.")
- foundExp = True
- break
# the regex .*? is used for the different possible version strings of the WinSDK
# if it's present a regex will be validated otherwise simple string comparison
if (((".*?" in key and re.match(key, currentFound.keys()[0], flags))
diff --git a/tests/system/suite_general/tst_installed_languages/test.py b/tests/system/suite_general/tst_installed_languages/test.py
index 237150a8a02..f2068b2a226 100644
--- a/tests/system/suite_general/tst_installed_languages/test.py
+++ b/tests/system/suite_general/tst_installed_languages/test.py
@@ -30,7 +30,7 @@ def main():
startQC()
if not startedWithoutPluginError():
return
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Environment"))
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Interface")
languageName = testData.field(lang, "language")
diff --git a/tests/system/suite_general/tst_save_before_build/test.py b/tests/system/suite_general/tst_save_before_build/test.py
index 3befbbd8eac..74d0f685ae6 100644
--- a/tests/system/suite_general/tst_save_before_build/test.py
+++ b/tests/system/suite_general/tst_save_before_build/test.py
@@ -27,7 +27,7 @@ source("../../shared/qtcreator.py")
def __openBuildAndRunSettings__():
- invokeMenuItem("Tools", "Options...")
+ invokeMenuItem("Edit", "Preferences...")
mouseClick(waitForObjectItem(":Options_QListView", "Build & Run"))
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "General")
diff --git a/tests/system/suite_qtquick/tst_qtquick_creation4/test.py b/tests/system/suite_qtquick/tst_qtquick_creation4/test.py
index 82d04ef8d3d..9408acaf7df 100644
--- a/tests/system/suite_qtquick/tst_qtquick_creation4/test.py
+++ b/tests/system/suite_qtquick/tst_qtquick_creation4/test.py
@@ -26,6 +26,10 @@
source("../../shared/qtcreator.py")
def main():
+ # FIXME
+ test.warning("Qt Quick 2 Extension Plugin needs Qt6.2+ nowadays.")
+ return
+
startQC()
if not startedWithoutPluginError():
return
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 815b20fa182..8eb2367774f 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -21,8 +21,6 @@ if (NOT QT_CREATOR_API_DEFINED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
- set(BUILD_EXECUTABLES echo)
-
set(IMPLICIT_DEPENDS Qt5::Test)
include(QtCreatorIDEBranding)
@@ -38,5 +36,4 @@ if (NOT QT_CREATOR_API_DEFINED)
find_package(Threads)
endif()
-add_subdirectory(echoserver)
add_subdirectory(unittest)
diff --git a/tests/unit/echoserver/CMakeLists.txt b/tests/unit/echoserver/CMakeLists.txt
deleted file mode 100644
index 1be94e375d0..00000000000
--- a/tests/unit/echoserver/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-add_qtc_executable(echo
- DEPENDS Qt5::Core Qt5::Network ClangSupport
- DEFINES CLANGSUPPORT_TESTS DONT_CHECK_MESSAGE_COUNTER
- SOURCES
- echoclangcodemodelserver.cpp echoclangcodemodelserver.h
- echoserverprocessmain.cpp
- SKIP_INSTALL
- PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-)
diff --git a/tests/unit/echoserver/echoclangcodemodelserver.cpp b/tests/unit/echoserver/echoclangcodemodelserver.cpp
deleted file mode 100644
index 67ba74cae94..00000000000
--- a/tests/unit/echoserver/echoclangcodemodelserver.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "echoclangcodemodelserver.h"
-
-#include <clangsupport/clangcodemodelservermessages.h>
-#include <clangsupport/connectionserver.h>
-
-#include <QCoreApplication>
-#include <QDebug>
-
-namespace ClangBackEnd {
-
-void EchoClangCodeModelServer::dispatch(const MessageEnvelop &message)
-{
- ClangCodeModelServerInterface::dispatch(message);
-}
-
-void EchoClangCodeModelServer::end()
-{
- QCoreApplication::quit();
-}
-
-void EchoClangCodeModelServer::documentsOpened(const DocumentsOpenedMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::documentsChanged(const DocumentsChangedMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::documentsClosed(const DocumentsClosedMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::requestCompletions(const RequestCompletionsMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::requestAnnotations(const RequestAnnotationsMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::requestReferences(const RequestReferencesMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::requestToolTip(const RequestToolTipMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::documentVisibilityChanged(const DocumentVisibilityChangedMessage &message)
-{
- echoMessage(message);
-}
-
-void EchoClangCodeModelServer::echoMessage(const MessageEnvelop &message)
-{
- client()->echo(EchoMessage(message));
-}
-
-} // namespace ClangBackEnd
-
diff --git a/tests/unit/echoserver/echoclangcodemodelserver.h b/tests/unit/echoserver/echoclangcodemodelserver.h
deleted file mode 100644
index 58db3613e3c..00000000000
--- a/tests/unit/echoserver/echoclangcodemodelserver.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangsupport/clangcodemodelserverinterface.h>
-#include <ipcclientprovider.h>
-
-namespace ClangBackEnd {
-
-class EchoClangCodeModelServer : public ClangCodeModelServerInterface,
- public IpcClientProvider<ClangCodeModelClientInterface>
-{
-public:
- void dispatch(const MessageEnvelop &message) override;
- void end() override;
-
- void documentsOpened(const DocumentsOpenedMessage &message) override;
- void documentsChanged(const DocumentsChangedMessage &message) override;
- void documentsClosed(const DocumentsClosedMessage &message) override;
- void documentVisibilityChanged(const DocumentVisibilityChangedMessage &message) override;
-
- void unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message) override;
- void unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message) override;
-
- void requestCompletions(const RequestCompletionsMessage &message) override;
- void requestAnnotations(const RequestAnnotationsMessage &message) override;
- void requestReferences(const RequestReferencesMessage &message) override;
- void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
- void requestToolTip(const RequestToolTipMessage &message) override;
-
-private:
- void echoMessage(const MessageEnvelop &message);
-};
-
-} // namespace ClangBackEnd
diff --git a/tests/unit/echoserver/echoserver.qbs b/tests/unit/echoserver/echoserver.qbs
deleted file mode 100644
index 77df73a6d60..00000000000
--- a/tests/unit/echoserver/echoserver.qbs
+++ /dev/null
@@ -1,30 +0,0 @@
-import qbs.FileInfo
-
-QtcProduct {
- name: "echoserver"
- type: "application"
- targetName: "echo"
- consoleApplication: true
- destinationDirectory: FileInfo.joinPaths(project.buildDirectory,
- FileInfo.relativePath(project.ide_source_tree, sourceDirectory))
- install: false
-
- Depends { name: "qtc" }
- Depends { name: "ClangSupport" }
- Depends { name: "Sqlite" }
- Depends { name: "Utils" }
- Depends { name: "Qt.network" }
-
- cpp.defines: ["CLANGSUPPORT_TESTS", "DONT_CHECK_MESSAGE_COUNTER"]
- cpp.dynamicLibraries: qbs.targetOS.contains("unix:") ? ["dl"] : []
- cpp.rpaths: [
- FileInfo.joinPaths(project.buildDirectory, qtc.ide_library_path),
- FileInfo.joinPaths(project.buildDirectory, qtc.ide_plugin_path)
- ]
-
- files: [
- "echoclangcodemodelserver.cpp",
- "echoclangcodemodelserver.h",
- "echoserverprocessmain.cpp",
- ]
-}
diff --git a/tests/unit/echoserver/echoserverprocessmain.cpp b/tests/unit/echoserver/echoserverprocessmain.cpp
deleted file mode 100644
index 5225007617f..00000000000
--- a/tests/unit/echoserver/echoserverprocessmain.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "echoclangcodemodelserver.h"
-
-#include <clangsupport/clangcodemodelclientproxy.h>
-#include <clangsupport/connectionserver.h>
-
-#include <QCoreApplication>
-
-using ClangBackEnd::ClangCodeModelClientProxy;
-using ClangBackEnd::ConnectionServer;
-using ClangBackEnd::EchoClangCodeModelServer;
-
-int main(int argc, char *argv[])
-{
- QCoreApplication::setOrganizationName("QtProject");
- QCoreApplication::setOrganizationDomain("qt-project.org");
- QCoreApplication::setApplicationName("EchoCodeModelBackend");
- QCoreApplication::setApplicationVersion("1.0.0");
-
- QCoreApplication application(argc, argv);
-
- if (application.arguments().count() < 2)
- return 1;
- if (application.arguments().contains("connectionName"))
- return 0;
-
- EchoClangCodeModelServer echoClangCodeModelServer;
- ConnectionServer<EchoClangCodeModelServer, ClangCodeModelClientProxy> connectionServer;
- connectionServer.setServer(&echoClangCodeModelServer);
- connectionServer.start(application.arguments()[1]);
-
- return application.exec();
-}
diff --git a/tests/unit/unit.qbs b/tests/unit/unit.qbs
index cd81873834c..f6c9dc3e9d3 100644
--- a/tests/unit/unit.qbs
+++ b/tests/unit/unit.qbs
@@ -2,7 +2,6 @@ Project {
name: "C++ unit tests"
condition: project.withAutotests
references: [
- "echoserver/echoserver.qbs",
"unittest/unittest.qbs",
]
}
diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt
index 3451bd7116e..70cff54788a 100644
--- a/tests/unit/unittest/CMakeLists.txt
+++ b/tests/unit/unittest/CMakeLists.txt
@@ -1,12 +1,3 @@
-if (TARGET libclang)
- set(HAVE_LIBCLANG ON)
-endif()
-
-if (HAVE_LIBCLANG AND NOT QTC_CLANG_BUILDMODE_MATCH)
- message(STATUS "Disabling libclang tests due to build mode mismatch.")
- set(HAVE_LIBCLANG OFF)
-endif()
-
find_package(Googletest MODULE)
find_package(GoogleBenchmark MODULE)
@@ -42,19 +33,14 @@ add_qtc_test(unittest GTEST
DONT_CHECK_MESSAGE_COUNTER
QTC_RESOURCE_DIR="${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator"
TESTDATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data"
- ECHOSERVER="$<TARGET_FILE_DIR:echo>/echo"
TEST_RELATIVE_LIBEXEC_PATH="${TEST_RELATIVE_LIBEXEC_PATH}"
SOURCES
abstractviewmock.h
- clientserverinprocess-test.cpp
- clientserveroutsideprocess-test.cpp
compare-operators.h
conditionally-disabled-tests.h
- dummyclangipcclient.h
dynamicastmatcherdiagnosticcontainer-matcher.h
eventspy.cpp eventspy.h
fakeprocess.cpp fakeprocess.h
- filesystem-utilities.h
googletest.h
google-using-declarations.h
gtest-creator-printing.cpp gtest-creator-printing.h
@@ -62,26 +48,18 @@ add_qtc_test(unittest GTEST
gtest-qt-printing.cpp gtest-qt-printing.h
gtest-std-printing.h
lastchangedrowid-test.cpp
- lineprefixer-test.cpp
matchingtext-test.cpp
- mockclangcodemodelclient.h
- mockclangcodemodelserver.h
mockfutureinterface.h
mockmutex.h
mockqfilesystemwatcher.h
- mockqueue.h
mocksqlitestatement.h
mocksqlitetransactionbackend.h
mocksyntaxhighligher.h
mocktimer.cpp mocktimer.h
nodelistproperty-test.cpp
- processcreator-test.cpp
processevents-utilities.cpp processevents-utilities.h
- readandwritemessageblock-test.cpp
- rundocumentparse-utility.h
sizedarray-test.cpp
smallstring-test.cpp
- sourcerangecontainer-matcher.h
spydummy.cpp spydummy.h
sqlitealgorithms-test.cpp
sqliteindex-test.cpp
@@ -89,7 +67,6 @@ add_qtc_test(unittest GTEST
sqlitetransaction-test.cpp
unittests-main.cpp
unittest-utility-functions.h
- utf8-test.cpp
sqlitecolumn-test.cpp
sqlitedatabasebackend-test.cpp
sqlitedatabase-test.cpp
@@ -143,16 +120,11 @@ function(extend_qtc_test_with_target_sources target)
)
endfunction()
-if (HAVE_LIBCLANG AND NOT TARGET clangbackend_lib)
- add_subdirectory(../../../src/tools/clangbackend/source ${CMAKE_CURRENT_BINARY_DIR}/clangbackend)
-endif()
-extend_qtc_test(unittest DEPENDS clangbackend_lib CONDITION HAVE_LIBCLANG)
-
if (NOT TARGET Sqlite)
add_subdirectory(../../../src/libs/sqlite ${CMAKE_CURRENT_BINARY_DIR}/sqlite)
endif()
extend_qtc_test_with_target_sources(Sqlite
- DEFINES SQLITE_CUSTOM_INCLUDE=config.h
+ DEFINES SQLITE_CUSTOM_INCLUDE=config.h SQLITE_STATIC_LIBRARY
)
if (APPLE)
@@ -169,80 +141,19 @@ add_custom_command(TARGET unittest POST_BUILD
)
extend_qtc_test(unittest
- CONDITION HAVE_LIBCLANG
- INCLUDES "${CLANG_INCLUDE_DIRS}"
- DEFINES CLANG_UNIT_TESTS
- DEPENDS libclang
- SOURCES
- activationsequencecontextprocessor-test.cpp
- activationsequenceprocessor-test.cpp
- chunksreportedmonitor.cpp
- clangasyncjob-base.cpp
- clangcodecompleteresults-test.cpp
- clangcodemodelserver-test.cpp
- clangcompletecodejob-test.cpp
- clangcompletioncontextanalyzer-test.cpp
- clangdiagnosticfilter-test.cpp
- clangdocumentprocessors-test.cpp
- clangdocumentprocessor-test.cpp
- clangdocuments-test.cpp
- clangdocumentsuspenderresumer-test.cpp
- clangdocument-test.cpp
- clangfixitoperation-test.cpp
- clangfollowsymbol-test.cpp
- clangisdiagnosticrelatedtolocation-test.cpp
- clangjobqueue-test.cpp
- clangjobs-test.cpp
- clangparsesupportivetranslationunitjob-test.cpp
- clangreferencescollector-test.cpp
- clangrequestannotationsjob-test.cpp
- clangrequestreferencesjob-test.cpp
- clangresumedocumentjob-test.cpp
- clangstring-test.cpp
- clangsupportivetranslationunitinitializer-test.cpp
- clangsuspenddocumentjob-test.cpp
- clangtooltipinfo-test.cpp
- clangtranslationunits-test.cpp
- clangtranslationunit-test.cpp
- clangupdateannotationsjob-test.cpp
- codecompleter-test.cpp
- codecompletionsextractor-test.cpp
- completionchunkstotextconverter-test.cpp
- cursor-test.cpp
- diagnosticset-test.cpp
- diagnostic-test.cpp
- fixit-test.cpp
- gtest-clang-printing.cpp gtest-clang-printing.h
- highlightingresultreporter-test.cpp
- readexporteddiagnostics-test.cpp
- skippedsourceranges-test.cpp
- sourcelocation-test.cpp
- sourcerange-test.cpp
- token-test.cpp
- tokenprocessor-test.cpp
- translationunitupdater-test.cpp
- unsavedfile-test.cpp
- unsavedfiles-test.cpp
- utf8positionfromlinecolumn-test.cpp
- chunksreportedmonitor.h
- clangasyncjob-base.h
- clangcompareoperators.h
- diagnosticcontainer-matcher.h
-)
-
-extend_qtc_test(unittest
CONDITION TARGET GoogleBenchmark
DEPENDS GoogleBenchmark
SOURCES
smallstring-benchmark.cpp
)
-finalize_qtc_gtest(unittest ".c$")
+finalize_qtc_gtest(unittest
+ EXCLUDE_SOURCES_REGEX ".c$"
+ EXCLUDE_ALL_FROM_PRECHECK)
# Path needs to be before CppEditor
target_include_directories(unittest
PRIVATE
- BEFORE ../../../src/tools/clangbackend/source
BEFORE ../../../src/plugins
)
@@ -258,7 +169,7 @@ extend_qtc_test(unittest
"${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/interfaces"
"${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/types"
DEFINES
- QMLDESIGNER_TEST DESIGNER_STATIC_CORE_LIBRARY
+ QMLDESIGNER_TEST QMLDESIGNER_STATIC_LIBRARY
SOURCES_PREFIX
"${QmlDesignerDir}"
SOURCES
@@ -409,46 +320,8 @@ if (NOT TARGET CPlusPlus)
add_subdirectory(../../../src/libs/3rdparty/cplusplus ${CMAKE_CURRENT_BINARY_DIR}/3rd_cplusplus)
add_subdirectory(../../../src/libs/cplusplus ${CMAKE_CURRENT_BINARY_DIR}/cplusplus)
endif()
-if (NOT TARGET ClangSupport)
- add_subdirectory(../../../src/libs/clangsupport ${CMAKE_CURRENT_BINARY_DIR}/clangsupport)
-endif()
-
-extend_qtc_test(unittest DEPENDS Utils CPlusPlus ClangSupport)
-
-extend_qtc_test(unittest
- SOURCES_PREFIX ../../../src/plugins/clangcodemodel
- SOURCES
- clangactivationsequencecontextprocessor.cpp clangactivationsequencecontextprocessor.h
- clangactivationsequenceprocessor.cpp clangactivationsequenceprocessor.h
- clangcompletionchunkstotextconverter.cpp clangcompletionchunkstotextconverter.h
- clangcompletioncontextanalyzer.cpp clangcompletioncontextanalyzer.h
- clangdiagnosticfilter.cpp clangdiagnosticfilter.h
- clangfixitoperation.cpp clangfixitoperation.h
- clanghighlightingresultreporter.cpp clanghighlightingresultreporter.h
- clanguiheaderondiskmanager.cpp clanguiheaderondiskmanager.h
- clangisdiagnosticrelatedtolocation.h
-)
-
-find_package(yaml-cpp QUIET MODULE)
-
-extend_qtc_test(unittest
- DEPENDS yaml-cpp
- DEFINES CLANGTOOLS_STATIC_LIBRARY
- SOURCES_PREFIX ../../../src/plugins/clangtools
- SOURCES
- clangtoolsdiagnostic.cpp
- clangtoolsdiagnostic.h
- clangtoolslogfilereader.cpp
- clangtoolslogfilereader.h
-)
-extend_qtc_test(unittest
- DEFINES DEBUGGER_STATIC_LIBRARY
- SOURCES_PREFIX ../../../src/plugins/debugger
- SOURCES
- analyzer/diagnosticlocation.cpp
- analyzer/diagnosticlocation.h
-)
+extend_qtc_test(unittest DEPENDS Utils CPlusPlus)
extend_qtc_test(unittest
SOURCES_PREFIX ../../../src/plugins/coreplugin
@@ -459,13 +332,6 @@ extend_qtc_test(unittest
locator/ilocatorfilter.cpp locator/ilocatorfilter.h
)
-extend_qtc_test(unittest
- SOURCES_PREFIX ../../../src/plugins/cppeditor
- DEFINES CPPEDITOR_STATIC_LIBRARY
- SOURCES
- cppprojectfile.cpp cppprojectfile.h
-)
-
get_filename_component(
QMLDOM_STANDALONE_CMAKELISTS
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../qmldom_standalone/src/qmldom/standalone/"
diff --git a/tests/unit/unittest/activationsequencecontextprocessor-test.cpp b/tests/unit/unittest/activationsequencecontextprocessor-test.cpp
deleted file mode 100644
index 84c2e87c76b..00000000000
--- a/tests/unit/unittest/activationsequencecontextprocessor-test.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangactivationsequencecontextprocessor.h>
-
-#include <clangcodemodel/clangcompletionassistinterface.h>
-
-#include <cplusplus/Token.h>
-
-#include <QTextCursor>
-#include <QTextDocument>
-
-namespace {
-
-using ContextProcessor = ClangCodeModel::Internal::ActivationSequenceContextProcessor;
-using TextEditor::AssistInterface;
-using ClangCodeModel::Internal::ClangCompletionAssistInterface;
-
-TEST(ActivationSequenceContextProcessorSlowTest, TextCursorPosition)
-{
- ClangCompletionAssistInterface interface("foobar", 4);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.textCursor_forTestOnly().position(), 0);
-}
-
-TEST(ActivationSequenceContextProcessor, StringLiteral)
-{
- ClangCompletionAssistInterface interface("auto foo = \"bar\"", 12);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, EndOfStringLiteral)
-{
- ClangCompletionAssistInterface interface("auto foo = \"bar\"", 16);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, FunctionCallComma)
-{
- ClangCompletionAssistInterface interface("f(x, ", 4);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_COMMA);
-}
-
-TEST(ActivationSequenceContextProcessor, NonFunctionCallComma)
-{
- ClangCompletionAssistInterface interface("int x, ", 6);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, DoxygenComment)
-{
- ClangCompletionAssistInterface interface("//! @", 5);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_DOXY_COMMENT);
-}
-
-TEST(ActivationSequenceContextProcessor, NonDoxygenComment)
-{
- ClangCompletionAssistInterface interface("// @", 4);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, Comment)
-{
- ClangCompletionAssistInterface interface("//", 2);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, InsideALiteral)
-{
- ClangCompletionAssistInterface interface("\"foo\"", 2);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, ShlashInsideAString)
-{
- ClangCompletionAssistInterface interface("\"foo/bar\"", 5);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, ShlashOutsideAString)
-{
- ClangCompletionAssistInterface interface("foo/bar", 4);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, FunctionLeftParen)
-{
- ClangCompletionAssistInterface interface("foo(", 4);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_LPAREN);
-}
-
-TEST(ActivationSequenceContextProcessor, TemplateFunctionLeftParen)
-{
- ClangCompletionAssistInterface interface("foo<X>(", 7);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_LPAREN);
-}
-
-TEST(ActivationSequenceContextProcessor, TemplateFunctionSecondParameter)
-{
- ClangCompletionAssistInterface interface("foo<X>(", 7);
- int startOfname = ContextProcessor::findStartOfName(interface.textDocument(),
- 6,
- ContextProcessor::NameCategory::Function);
-
- ASSERT_THAT(startOfname, 0);
-}
-
-TEST(ActivationSequenceContextProcessor, ExpressionLeftParen)
-{
- ClangCompletionAssistInterface interface("x * (", 5);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, AngleInclude)
-{
- ClangCompletionAssistInterface interface("#include <foo/bar>", 10);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_ANGLE_STRING_LITERAL);
-}
-
-TEST(ActivationSequenceContextProcessor, SlashInclude)
-{
- ClangCompletionAssistInterface interface("#include <foo/bar>", 14);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_SLASH);
-}
-
-TEST(ActivationSequenceContextProcessor, QuoteInclude)
-{
- ClangCompletionAssistInterface interface("#include \"foo/bar\"", 10);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_STRING_LITERAL);
-}
-
-TEST(ActivationSequenceContextProcessor, SlashInExlude)
-{
- ClangCompletionAssistInterface interface("#exclude <foo/bar>", 14);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, QuoteExclude)
-{
- ClangCompletionAssistInterface interface("#exclude \"foo/bar\"", 10);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL);
-}
-
-TEST(ActivationSequenceContextProcessor, SkipeWhiteSpacesBeforeCursor)
-{
- ClangCompletionAssistInterface interface("x-> ", 7);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_ARROW);
-}
-
-TEST(ActivationSequenceContextProcessor, SkipIdentifier)
-{
- ClangCompletionAssistInterface interface("x->foo_", 7);
- ContextProcessor processor{&interface};
-
- ASSERT_THAT(processor.completionKind(), CPlusPlus::T_ARROW);
-}
-
-}
diff --git a/tests/unit/unittest/activationsequenceprocessor-test.cpp b/tests/unit/unittest/activationsequenceprocessor-test.cpp
deleted file mode 100644
index b51f2c75986..00000000000
--- a/tests/unit/unittest/activationsequenceprocessor-test.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangactivationsequenceprocessor.h>
-
-#include <cplusplus/Token.h>
-
-namespace {
-
-using testing::PrintToString;
-using namespace CPlusPlus;
-using ClangCodeModel::Internal::ActivationSequenceProcessor;
-
-MATCHER_P3(HasResult, completionKind, offset, newPosition,
- std::string(negation ? "hasn't" : "has")
- + " result of completion kind " + PrintToString(Token::name(completionKind))
- + ", offset " + PrintToString(offset)
- + " and new operator start position" + PrintToString(newPosition))
-{
- if (arg.completionKind() != completionKind
- || arg.offset() != offset
- || arg.operatorStartPosition() != newPosition) {
- *result_listener << "completion kind is " << PrintToString(Token::name(arg.completionKind()))
- << ", offset is " << PrintToString(arg.offset())
- << " and new operator start position is " << PrintToString(arg.operatorStartPosition());
- return false;
- }
-
- return true;
-}
-
-TEST(ActivationSequenceProcessor, CouldNotProcesseRandomCharacters)
-{
- ActivationSequenceProcessor processor(QStringLiteral("xxx"), 3, false);
-
- ASSERT_THAT(processor, HasResult(T_EOF_SYMBOL, 0, 3));
-}
-
-TEST(ActivationSequenceProcessor, CouldNotProcesseEmptyString)
-{
- ActivationSequenceProcessor processor(QStringLiteral(""), 0, true);
-
- ASSERT_THAT(processor, HasResult(T_EOF_SYMBOL, 0, 0));
-}
-
-TEST(ActivationSequenceProcessor, Dot)
-{
- ActivationSequenceProcessor processor(QStringLiteral("."), 1, true);
-
- ASSERT_THAT(processor, HasResult(T_DOT, 1, 0));
-}
-
-TEST(ActivationSequenceProcessor, Comma)
-{
- ActivationSequenceProcessor processor(QStringLiteral(","), 2, false);
-
- ASSERT_THAT(processor, HasResult(T_COMMA, 1, 1));
-}
-
-TEST(ActivationSequenceProcessor, LeftParenAsFunctionCall)
-{
- ActivationSequenceProcessor processor(QStringLiteral("("), 3, true);
-
- ASSERT_THAT(processor, HasResult(T_LPAREN, 1, 2));
-}
-
-TEST(ActivationSequenceProcessor, LeftParenNotAsFunctionCall)
-{
- ActivationSequenceProcessor processor(QStringLiteral("("), 3, false);
-
- ASSERT_THAT(processor, HasResult(T_EOF_SYMBOL, 0, 3));
-}
-
-TEST(ActivationSequenceProcessor, ColonColon)
-{
- ActivationSequenceProcessor processor(QStringLiteral("::"), 20, true);
-
- ASSERT_THAT(processor, HasResult(T_COLON_COLON, 2, 18));
-}
-
-TEST(ActivationSequenceProcessor, Arrow)
-{
- ActivationSequenceProcessor processor(QStringLiteral("->"), 2, true);
-
- ASSERT_THAT(processor, HasResult(T_ARROW, 2, 0));
-}
-
-TEST(ActivationSequenceProcessor, DotStar)
-{
- ActivationSequenceProcessor processor(QStringLiteral(".*"), 3, true);
-
- ASSERT_THAT(processor, HasResult(T_DOT_STAR, 2, 1));
-}
-
-TEST(ActivationSequenceProcessor, ArrowStar)
-{
- ActivationSequenceProcessor processor(QStringLiteral("->*"), 3, true);
-
- ASSERT_THAT(processor, HasResult(T_ARROW_STAR, 3, 0));
-}
-
-TEST(ActivationSequenceProcessor, DoxyGenCommentBackSlash)
-{
- ActivationSequenceProcessor processor(QStringLiteral(" \\"), 3, true);
-
- ASSERT_THAT(processor, HasResult(T_DOXY_COMMENT, 1, 2));
-}
-
-TEST(ActivationSequenceProcessor, DoxyGenCommentAt)
-{
- ActivationSequenceProcessor processor(QStringLiteral(" @"), 2, true);
-
- ASSERT_THAT(processor, HasResult(T_DOXY_COMMENT, 1, 1));
-}
-
-TEST(ActivationSequenceProcessor, AngleStringLiteral)
-{
- ActivationSequenceProcessor processor(QStringLiteral("<"), 1, true);
-
- ASSERT_THAT(processor, HasResult(T_ANGLE_STRING_LITERAL, 1, 0));
-}
-
-TEST(ActivationSequenceProcessor, StringLiteral)
-{
- ActivationSequenceProcessor processor(QStringLiteral("\""), 1, true);
-
- ASSERT_THAT(processor, HasResult(T_STRING_LITERAL, 1, 0));
-}
-
-TEST(ActivationSequenceProcessor, Slash)
-{
- ActivationSequenceProcessor processor(QStringLiteral("/"), 1, true);
-
- ASSERT_THAT(processor, HasResult(T_SLASH, 1, 0));
-}
-
-TEST(ActivationSequenceProcessor, Pound)
-{
- ActivationSequenceProcessor processor(QStringLiteral("#"), 1, true);
-
- ASSERT_THAT(processor, HasResult(T_POUND, 1, 0));
-}
-
-TEST(ActivationSequenceProcessor, PositionIsOne)
-{
- ActivationSequenceProcessor processor(QStringLiteral("<xx"), 1, false);
-
- ASSERT_THAT(processor, HasResult(T_ANGLE_STRING_LITERAL, 1, 0));
-}
-
-TEST(ActivationSequenceProcessor, PositionIsTwo)
-{
- ActivationSequenceProcessor processor(QStringLiteral(" @x"), 2, true);
-
- ASSERT_THAT(processor, HasResult(T_DOXY_COMMENT, 1, 1));
-}
-
-TEST(ActivationSequenceProcessor, PositionIsTwoWithASingleSign)
-{
- ActivationSequenceProcessor processor(QStringLiteral("x<x"), 2, false);
-
- ASSERT_THAT(processor, HasResult(T_ANGLE_STRING_LITERAL, 1, 1));
-}
-
-TEST(ActivationSequenceProcessor, PositionIsThree)
-{
- ActivationSequenceProcessor processor(QStringLiteral("xx<"), 3, false);
-
- ASSERT_THAT(processor, HasResult(T_ANGLE_STRING_LITERAL, 1, 2));
-}
-}
diff --git a/tests/unit/unittest/chunksreportedmonitor.cpp b/tests/unit/unittest/chunksreportedmonitor.cpp
deleted file mode 100644
index 542a5936866..00000000000
--- a/tests/unit/unittest/chunksreportedmonitor.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "chunksreportedmonitor.h"
-
-#include <QSignalSpy>
-
-namespace ClangBackEnd {
-
-ChunksReportedMonitor::ChunksReportedMonitor(const QFuture<TextEditor::HighlightingResult> &future)
- : m_future(future)
-{
- connect(&m_futureWatcher, &QFutureWatcher<TextEditor::HighlightingResult>::resultsReadyAt,
- this, &ChunksReportedMonitor::onResultsReadyAt);
- m_futureWatcher.setFuture(future);
-}
-
-bool ChunksReportedMonitor::waitUntilFinished(int timeoutInMs)
-{
- QSignalSpy spy(&m_futureWatcher, SIGNAL(finished()));
- return spy.wait(timeoutInMs);
-}
-
-void ChunksReportedMonitor::onResultsReadyAt(int, int)
-{
- ++m_resultsReadyCounter;
-}
-
-uint ChunksReportedMonitor::resultsReadyCounter()
-{
- waitUntilFinished();
- return m_resultsReadyCounter;
-}
-
-} // namespace ClangBackEnd
diff --git a/tests/unit/unittest/chunksreportedmonitor.h b/tests/unit/unittest/chunksreportedmonitor.h
deleted file mode 100644
index 01058492fca..00000000000
--- a/tests/unit/unittest/chunksreportedmonitor.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QObject>
-#include <QFuture>
-#include <QFutureWatcher>
-
-#include <texteditor/semantichighlighter.h>
-
-namespace ClangBackEnd {
-
-class ChunksReportedMonitor : public QObject
-{
- Q_OBJECT
-
-public:
- ChunksReportedMonitor(const QFuture<TextEditor::HighlightingResult> &future);
-
- uint resultsReadyCounter();
-
-private:
- bool waitUntilFinished(int timeoutInMs = 5000);
- void onResultsReadyAt(int beginIndex, int endIndex);
-
-private:
- QFuture<TextEditor::HighlightingResult> m_future;
- QFutureWatcher<TextEditor::HighlightingResult> m_futureWatcher;
- uint m_resultsReadyCounter = 0;
-};
-
-} // namespace ClangBackEnd
diff --git a/tests/unit/unittest/clangasyncjob-base.cpp b/tests/unit/unittest/clangasyncjob-base.cpp
deleted file mode 100644
index 859e0ffb794..00000000000
--- a/tests/unit/unittest/clangasyncjob-base.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangasyncjob-base.h"
-#include "processevents-utilities.h"
-
-#include <clangsupport/filecontainer.h>
-
-using namespace ClangBackEnd;
-
-void ClangAsyncJobTest::BaseSetUp(ClangBackEnd::JobRequest::Type jobRequestType,
- IAsyncJob &asyncJob)
-{
- const QVector<FileContainer> fileContainer{FileContainer(filePath)};
- document = documents.create(fileContainer).front();
- documents.setVisibleInEditors({filePath});
- documents.setUsedByCurrentEditor(filePath);
-
- jobRequest = createJobRequest(filePath, jobRequestType);
- jobContext = JobContext(jobRequest, &documents, &unsavedFiles, &dummyIpcClient);
- jobContextWithMockClient = JobContext(jobRequest, &documents, &unsavedFiles, &mockIpcClient);
- asyncJob.setFinishedHandler([](IAsyncJob *){});
-}
-
-JobRequest ClangAsyncJobTest::createJobRequest(const Utf8String &filePath,
- JobRequest::Type type) const
-{
- JobRequest jobRequest(type);
- jobRequest.filePath = filePath;
- jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint();
- jobRequest.documentRevision = document.documentRevision();
-
- return jobRequest;
-}
-
-bool ClangAsyncJobTest::waitUntilJobFinished(const ClangBackEnd::IAsyncJob &asyncJob,
- int timeOutInMs) const
-{
- const auto isOnFinishedSlotExecuted = [&asyncJob](){ return asyncJob.isFinished(); };
-
- return ProcessEventUtilities::processEventsUntilTrue(isOnFinishedSlotExecuted, timeOutInMs);
-}
diff --git a/tests/unit/unittest/clangasyncjob-base.h b/tests/unit/unittest/clangasyncjob-base.h
deleted file mode 100644
index e0d7fbfa226..00000000000
--- a/tests/unit/unittest/clangasyncjob-base.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "googletest.h"
-
-#include "dummyclangipcclient.h"
-#include "mockclangcodemodelclient.h"
-
-#include <clangdocument.h>
-#include <clangiasyncjob.h>
-#include <clangjobrequest.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-
-class ClangAsyncJobTest : public ::testing::Test
-{
-protected:
- void BaseSetUp(ClangBackEnd::JobRequest::Type jobRequestType,
- ClangBackEnd::IAsyncJob &asyncJob);
-
- ClangBackEnd::JobRequest createJobRequest(const Utf8String &filePath,
- ClangBackEnd::JobRequest::Type type) const;
-
- bool waitUntilJobFinished(const ClangBackEnd::IAsyncJob &asyncJob,
- int timeOutInMs = 10000) const;
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- ClangBackEnd::Document document;
-
- MockClangCodeModelClient mockIpcClient;
- DummyIpcClient dummyIpcClient;
-
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")};
-
- ClangBackEnd::JobRequest jobRequest;
- ClangBackEnd::JobContext jobContext;
- ClangBackEnd::JobContext jobContextWithMockClient;
-};
diff --git a/tests/unit/unittest/clangcodecompleteresults-test.cpp b/tests/unit/unittest/clangcodecompleteresults-test.cpp
deleted file mode 100644
index 30356a3744b..00000000000
--- a/tests/unit/unittest/clangcodecompleteresults-test.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangcodecompleteresults.h>
-#include <clangdocument.h>
-#include <clangfilepath.h>
-#include <clangtranslationunitupdater.h>
-#include <clangtranslationunit.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-#include <utf8string.h>
-
-#include <clang-c/Index.h>
-
-namespace {
-
-using ClangBackEnd::ClangCodeCompleteResults;
-using ClangBackEnd::FilePath;
-using ClangBackEnd::Document;
-using ClangBackEnd::UnsavedFiles;
-
-static unsigned completionOptions()
-{
- return ClangBackEnd::TranslationUnitUpdater::defaultParseOptions()
- & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion
- ? CXCodeComplete_IncludeBriefComments
- : 0;
-}
-
-TEST(ClangCodeCompleteResultsSlowTest, GetData)
-{
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Document document(Utf8StringLiteral(TESTDATA_DIR"/complete_testfile_1.cpp"),
- {},
- {},
- documents);
- Utf8String nativeFilePath = FilePath::toNativeSeparators(document.filePath());
- document.parse();
- CXCodeCompleteResults *cxCodeCompleteResults =
- clang_codeCompleteAt(document.translationUnit().cxTranslationUnit(),
- nativeFilePath.constData(),
- 49, 1, 0, 0,
- completionOptions());
-
- ClangCodeCompleteResults codeCompleteResults(cxCodeCompleteResults);
-
- ASSERT_THAT(codeCompleteResults.data(), cxCodeCompleteResults);
-}
-
-TEST(ClangCodeCompleteResults, GetInvalidData)
-{
- CXCodeCompleteResults *cxCodeCompleteResults = clang_codeCompleteAt(nullptr, "file.cpp", 49, 1, 0, 0, 0);
-
- ClangCodeCompleteResults codeCompleteResults(cxCodeCompleteResults);
-
- ASSERT_THAT(codeCompleteResults.data(), cxCodeCompleteResults);
-}
-
-TEST(ClangCodeCompleteResultsSlowTest, MoveClangCodeCompleteResults)
-{
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Document document(Utf8StringLiteral(TESTDATA_DIR"/complete_testfile_1.cpp"),
- {},
- {},
- documents);
- Utf8String nativeFilePath = FilePath::toNativeSeparators(document.filePath());
- document.parse();
- CXCodeCompleteResults *cxCodeCompleteResults =
- clang_codeCompleteAt(document.translationUnit().cxTranslationUnit(),
- nativeFilePath.constData(),
- 49, 1, 0, 0,
- completionOptions());
-
- ClangCodeCompleteResults codeCompleteResults(cxCodeCompleteResults);
-
- const ClangCodeCompleteResults codeCompleteResults2 = std::move(codeCompleteResults);
-
- ASSERT_TRUE(codeCompleteResults.isNull());
- ASSERT_FALSE(codeCompleteResults2.isNull());
-}
-
-}
diff --git a/tests/unit/unittest/clangcodemodelserver-test.cpp b/tests/unit/unittest/clangcodemodelserver-test.cpp
deleted file mode 100644
index c74e2a96d8e..00000000000
--- a/tests/unit/unittest/clangcodemodelserver-test.cpp
+++ /dev/null
@@ -1,753 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "mockclangcodemodelclient.h"
-#include "processevents-utilities.h"
-
-#include <clangcodemodelserver.h>
-#include <tokeninfocontainer.h>
-#include <clangcodemodelclientproxy.h>
-#include <clangcodemodelserverproxy.h>
-#include <clangtranslationunits.h>
-#include <clangexceptions.h>
-
-#include <clangcodemodelservermessages.h>
-
-#include <clangcodemodel/clanguiheaderondiskmanager.h>
-
-#include <utils/algorithm.h>
-#include <utils/temporarydirectory.h>
-
-#include <QCoreApplication>
-#include <QFile>
-
-using testing::Property;
-using testing::Contains;
-using testing::Not;
-using testing::Eq;
-using testing::PrintToString;
-using testing::_;
-
-namespace {
-
-using namespace ClangBackEnd;
-
-MATCHER_P4(HasDirtyDocument,
- filePath,
- documentRevision,
- isDirty,
- hasNewDiagnostics,
- std::string(negation ? "isn't" : "is")
- + " document with file path "+ PrintToString(filePath)
- + " and document revision " + PrintToString(documentRevision)
- + " and isDirty = " + PrintToString(isDirty)
- + " and hasNewDiagnostics = " + PrintToString(hasNewDiagnostics)
- )
-{
- auto &&documents = arg.documentsForTestOnly();
- try {
- auto document = documents.document(filePath);
-
- if (document.documentRevision() == documentRevision) {
- if (document.isDirty() && !isDirty) {
- *result_listener << "isNeedingReparse is true";
- return false;
- } else if (!document.isDirty() && isDirty) {
- *result_listener << "isNeedingReparse is false";
- return false;
- }
-
- return true;
- }
-
- *result_listener << "revision number is " << PrintToString(document.documentRevision());
- return false;
-
- } catch (...) {
- *result_listener << "has no translation unit";
- return false;
- }
-}
-
-MATCHER_P(PartlyContains, token, "")
-{
- for (const auto &item: arg) {
- if (item.types == token.types && item.line == token.line && item.column == token.column
- && item.length == token.length) {
- return true;
- }
- }
- return false;
-}
-
-static constexpr int AnnotationJobsMultiplier = 2;
-
-class ClangCodeModelServer : public ::testing::Test
-{
-protected:
- void SetUp() override;
- void TearDown() override;
-
-protected:
- bool waitUntilAllJobsFinished(int timeOutInMs = 10000);
-
- void openDocumentAndWaitForFinished(
- const Utf8String &filePath, int expectedAnnotationsMessages = AnnotationJobsMultiplier);
-
- void openDocument(const Utf8String &filePath,
- int expectedAnnotationsMessages = AnnotationJobsMultiplier);
- void openDocument(const Utf8String &filePath,
- const Utf8StringVector &compilationArguments,
- const Utf8StringVector &headerPaths,
- int expectedAnnotationsMessages = AnnotationJobsMultiplier);
- void openDocuments(int expectedAnnotationsMessages);
- void openDocumentWithUnsavedContent(const Utf8String &filePath, const Utf8String &content);
- void closeDocument(const Utf8String &filePath);
-
- void updateUnsavedFile(const Utf8String &filePath, const Utf8String &fileContent);
- void updateUnsavedContent(const Utf8String &filePath,
- const Utf8String &fileContent,
- quint32 revisionNumber);
- void removeUnsavedFile(const Utf8String &filePath);
-
- void updateVisibilty(const Utf8String &currentEditor, const Utf8String &additionalVisibleEditor);
-
- void requestAnnotations(const Utf8String &filePath);
- void requestReferences(quint32 documentRevision = 0);
- void requestFollowSymbol(quint32 documentRevision = 0);
- void requestCompletions(const Utf8String &filePath,
- uint line = 1,
- uint column = 1);
- void requestCompletionsInFileA();
-
- bool isSupportiveTranslationUnitInitialized(const Utf8String &filePath);
-
- DocumentProcessor documentProcessorForFile(const Utf8String &filePath);
-
- void expectAnnotations(int count);
- void expectCompletion(const CodeCompletion &completion);
- void expectCompletionFromFileA();
- void expectCompletionFromFileAUnsavedMethodVersion1();
- void expectCompletionFromFileAUnsavedMethodVersion2();
- void expectNoCompletionWithUnsavedMethod();
- void expectReferences();
- void expectFollowSymbol();
- void expectAnnotationsForFileBWithSpecificHighlightingMark();
-
- static const Utf8String unsavedContent(const QString &unsavedFilePath);
-
-protected:
- MockClangCodeModelClient mockClangCodeModelClient;
- ClangBackEnd::ClangCodeModelServer clangServer;
- const ClangBackEnd::Documents &documents = clangServer.documentsForTestOnly();
-
- const Utf8String filePathA = Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_function.cpp");
- const QString filePathAUnsavedVersion1
- = QStringLiteral(TESTDATA_DIR) + QStringLiteral("/complete_extractor_function_unsaved.cpp");
- const QString filePathAUnsavedVersion2
- = QStringLiteral(TESTDATA_DIR) + QStringLiteral("/complete_extractor_function_unsaved_2.cpp");
-
- const Utf8String filePathB = Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_variable.cpp");
- const Utf8String filePathC = Utf8StringLiteral(TESTDATA_DIR"/references.cpp");
-
- const Utf8String aFilePath = Utf8StringLiteral("afile.cpp");
- const Utf8String anExistingFilePath
- = Utf8StringLiteral(TESTDATA_DIR"/complete_translationunit_parse_error.cpp");
-
- const Utf8String uicMainPath = Utf8StringLiteral(TESTDATA_DIR"/uicmain.cpp");
-};
-
-using ClangCodeModelServerSlowTest = ClangCodeModelServer;
-
-TEST_F(ClangCodeModelServerSlowTest, GetCodeCompletion)
-{
- openDocument(filePathA);
-
- expectCompletionFromFileA();
- requestCompletionsInFileA();
-}
-
-TEST_F(ClangCodeModelServerSlowTest, RequestAnnotations)
-{
- openDocumentAndWaitForFinished(filePathB);
-
- expectAnnotationsForFileBWithSpecificHighlightingMark();
- requestAnnotations(filePathB);
-}
-
-TEST_F(ClangCodeModelServerSlowTest, RequestReferencesForCurrentDocumentRevision)
-{
- openDocumentAndWaitForFinished(filePathC);
-
- expectReferences();
- requestReferences();
-}
-
-TEST_F(ClangCodeModelServerSlowTest, RequestReferencesTakesRevisionFromMessage)
-{
- openDocumentAndWaitForFinished(filePathC);
-
- requestReferences(/*documentRevision=*/ 99);
-
- JobRequests &queue = documentProcessorForFile(filePathC).queue();
- ASSERT_TRUE(Utils::anyOf(queue, [](const JobRequest &request) {
- return request.documentRevision == 99;
- }));
- queue.clear(); // Avoid blocking
-}
-
-TEST_F(ClangCodeModelServerSlowTest, RequestFollowSymbolForCurrentDocumentRevision)
-{
- openDocumentAndWaitForFinished(filePathC);
-
- expectFollowSymbol();
- requestFollowSymbol();
-}
-
-TEST_F(ClangCodeModelServerSlowTest, RequestFollowSymbolTakesRevisionFromMessage)
-{
- openDocumentAndWaitForFinished(filePathC);
-
- requestFollowSymbol(/*documentRevision=*/ 99);
-
- JobRequests &queue = documentProcessorForFile(filePathC).queue();
- ASSERT_TRUE(Utils::anyOf(queue, [](const JobRequest &request) {
- return request.documentRevision == 99;
- }));
- queue.clear(); // Avoid blocking
-}
-
-TEST_F(ClangCodeModelServerSlowTest, NoInitialAnnotationsForClosedDocument)
-{
- const int expectedAnnotationsCount = 0;
- openDocument(filePathA, expectedAnnotationsCount);
-
- closeDocument(filePathA);
-}
-
-TEST_F(ClangCodeModelServerSlowTest, AnnotationsForInitiallyNotVisibleDocument)
-{
- const int expectedAnnotationsCount = 2;
- updateVisibilty(filePathA, filePathA);
- expectAnnotations(expectedAnnotationsCount);
- clangServer.documentsOpened( // Open document while another is still visible
- DocumentsOpenedMessage({FileContainer(filePathB, Utf8String(), false, 1)},
- filePathA, {filePathA}));
- clangServer.unsavedFilesUpdated( // Invalidate added jobs
- UnsavedFilesUpdatedMessage({FileContainer(Utf8StringLiteral("aFile"), Utf8String())}));
-
- updateVisibilty(filePathB, filePathB);
-}
-
-TEST_F(ClangCodeModelServerSlowTest, NoAnnotationsForClosedDocument)
-{
- const int expectedAnnotationsCount = AnnotationJobsMultiplier; // Only for registration.
- openDocumentAndWaitForFinished(filePathA, expectedAnnotationsCount);
- updateUnsavedContent(filePathA, Utf8String(), 1);
-
- closeDocument(filePathA);
-}
-
-TEST_F(ClangCodeModelServerSlowTest, NoInitialAnnotationsForOutdatedDocumentRevision)
-{
- const int expectedAnnotationsCount = AnnotationJobsMultiplier; // Only for registration.
- openDocument(filePathA, expectedAnnotationsCount);
-
- updateUnsavedContent(filePathA, Utf8String(), 1);
-}
-
-TEST_F(ClangCodeModelServerSlowTest, NoCompletionsForClosedDocument)
-{
- const int expectedAnnotationsCount = AnnotationJobsMultiplier; // Only for registration.
- openDocumentAndWaitForFinished(filePathA, expectedAnnotationsCount);
- requestCompletionsInFileA();
-
- closeDocument(filePathA);
-}
-
-TEST_F(ClangCodeModelServerSlowTest, GetCodeCompletionForUnsavedFile)
-{
- expectAnnotations(AnnotationJobsMultiplier);
- openDocumentWithUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion1));
- expectCompletionFromFileAUnsavedMethodVersion1();
-
- requestCompletionsInFileA();
-}
-
-TEST_F(ClangCodeModelServerSlowTest, GetNoCodeCompletionAfterRemovingUnsavedFile)
-{
- const int expectedAnnotationsCount = 2 * AnnotationJobsMultiplier; // For registration and update/removal.
- openDocumentAndWaitForFinished(filePathA, expectedAnnotationsCount);
- removeUnsavedFile(filePathA);
-
- expectNoCompletionWithUnsavedMethod();
- requestCompletionsInFileA();
-}
-
-TEST_F(ClangCodeModelServerSlowTest, GetNewCodeCompletionAfterUpdatingUnsavedFile)
-{
- const int expectedAnnotationsCount = 2 * AnnotationJobsMultiplier; // For registration and update/removal.
- openDocumentAndWaitForFinished(filePathA, expectedAnnotationsCount);
- updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 1);
-
- expectCompletionFromFileAUnsavedMethodVersion2();
- requestCompletionsInFileA();
-}
-
-TEST_F(ClangCodeModelServerSlowTest, OpenedDocumentsAreDirty)
-{
- openDocument(filePathA, AnnotationJobsMultiplier);
-
- ASSERT_THAT(clangServer, HasDirtyDocument(filePathA, 0U, true, false));
-}
-
-TEST_F(ClangCodeModelServerSlowTest, SetCurrentAndVisibleEditor)
-{
- openDocuments(2 * AnnotationJobsMultiplier);
- ASSERT_TRUE(waitUntilAllJobsFinished());
- auto functionDocument = documents.document(filePathA);
- auto variableDocument = documents.document(filePathB);
-
- updateVisibilty(filePathB, filePathA);
-
- ASSERT_TRUE(variableDocument.isUsedByCurrentEditor());
- ASSERT_TRUE(variableDocument.isVisibleInEditor());
- ASSERT_TRUE(functionDocument.isVisibleInEditor());
-}
-
-TEST_F(ClangCodeModelServerSlowTest, StartCompletionJobFirstOnEditThatTriggersCompletion)
-{
- openDocument(filePathA, 2 * AnnotationJobsMultiplier);
- ASSERT_TRUE(waitUntilAllJobsFinished());
- expectCompletionFromFileA();
-
- updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 1);
- requestCompletionsInFileA();
-
- const QList<Jobs::RunningJob> jobs = clangServer.runningJobsForTestsOnly();
- ASSERT_THAT(jobs.size(), Eq(1));
- ASSERT_THAT(jobs.first().jobRequest.type, Eq(JobRequest::Type::RequestCompletions));
-}
-
-TEST_F(ClangCodeModelServerSlowTest, SupportiveTranslationUnitNotInitializedAfterRegister)
-{
- openDocument(filePathA, AnnotationJobsMultiplier);
-
- ASSERT_TRUE(waitUntilAllJobsFinished());
- ASSERT_FALSE(isSupportiveTranslationUnitInitialized(filePathA));
-}
-
-TEST_F(ClangCodeModelServerSlowTest, SupportiveTranslationUnitIsSetupAfterFirstEdit)
-{
- openDocument(filePathA, 2 * AnnotationJobsMultiplier);
- ASSERT_TRUE(waitUntilAllJobsFinished());
-
- updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 1);
-
- ASSERT_TRUE(waitUntilAllJobsFinished());
- ASSERT_TRUE(isSupportiveTranslationUnitInitialized(filePathA));
-}
-
-TEST_F(ClangCodeModelServerSlowTest, DoNotRunDuplicateJobs)
-{
- openDocument(filePathA, 3 * AnnotationJobsMultiplier);
- ASSERT_TRUE(waitUntilAllJobsFinished());
- updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 1);
- ASSERT_TRUE(waitUntilAllJobsFinished());
- ASSERT_TRUE(isSupportiveTranslationUnitInitialized(filePathA));
- updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 2);
- QCoreApplication::processEvents(); // adds + runs a job
- updateVisibilty(Utf8String(), Utf8String());
-
- updateVisibilty(filePathA, filePathA); // triggers adding + runnings job on next processevents()
-}
-
-TEST_F(ClangCodeModelServerSlowTest, OpenDocumentAndEdit)
-{
- openDocument(filePathA, 4 * AnnotationJobsMultiplier);
- ASSERT_TRUE(waitUntilAllJobsFinished());
-
- for (unsigned revision = 1; revision <= 3; ++revision) {
- updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), revision);
- ASSERT_TRUE(waitUntilAllJobsFinished());
- }
-}
-
-TEST_F(ClangCodeModelServerSlowTest, IsNotCurrentCurrentAndVisibleEditorAnymore)
-{
- const int expectedAnnotationsCount = 2 * AnnotationJobsMultiplier;
- openDocuments(expectedAnnotationsCount);
- ASSERT_TRUE(waitUntilAllJobsFinished());
- auto functionDocument = documents.document(filePathA);
- auto variableDocument = documents.document(filePathB);
- updateVisibilty(filePathB, filePathA);
-
- updateVisibilty(filePathB, Utf8String());
-
- ASSERT_FALSE(functionDocument.isUsedByCurrentEditor());
- ASSERT_FALSE(functionDocument.isVisibleInEditor());
- ASSERT_TRUE(variableDocument.isUsedByCurrentEditor());
- ASSERT_TRUE(variableDocument.isVisibleInEditor());
-}
-
-TEST_F(ClangCodeModelServerSlowTest, TranslationUnitAfterUpdateNeedsReparse)
-{
- openDocumentAndWaitForFinished(filePathA, 2 * AnnotationJobsMultiplier);
-
- updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion1), 1U);
- ASSERT_THAT(clangServer, HasDirtyDocument(filePathA, 1U, true, true));
-}
-
-TEST_F(ClangCodeModelServerSlowTest, TakeOverJobsOnDocumentChange)
-{
- openDocument(filePathC, AnnotationJobsMultiplier);
- ASSERT_TRUE(waitUntilAllJobsFinished());
- updateVisibilty(filePathB, filePathB); // Disable processing jobs
- requestReferences();
-
- expectReferences();
-
- openDocument(filePathC, AnnotationJobsMultiplier); // Do not loose jobs
- updateVisibilty(filePathC, filePathC); // Enable processing jobs
-}
-
-TEST_F(ClangCodeModelServerSlowTest, UicHeaderAvailableBeforeParse)
-{
- // Write ui file
- ClangCodeModel::Internal::UiHeaderOnDiskManager uiManager;
- const QByteArray content = "class UicObject{};";
- const QString uiHeaderFilePath = uiManager.write("uicheader.h", content);
-
- // Open document
- openDocument(uicMainPath,
- {Utf8StringLiteral("-I"), Utf8String(uiManager.directoryPath())},
- {uiManager.directoryPath()},
- AnnotationJobsMultiplier);
- updateVisibilty(uicMainPath, uicMainPath);
- ASSERT_TRUE(waitUntilAllJobsFinished());
-
- // Check
- ASSERT_THAT(documents.document(uicMainPath).dependedFilePaths(),
- Contains(uiHeaderFilePath));
-}
-
-TEST_F(ClangCodeModelServerSlowTest, UicHeaderAvailableAfterParse)
-{
- ClangCodeModel::Internal::UiHeaderOnDiskManager uiManager;
- const QString uiHeaderFilePath = uiManager.mapPath("uicheader.h");
-
- // Open document
- openDocument(uicMainPath,
- {Utf8StringLiteral("-I"), Utf8String(uiManager.directoryPath())},
- {uiManager.directoryPath()},
- 2 * AnnotationJobsMultiplier);
- updateVisibilty(uicMainPath, uicMainPath);
- ASSERT_TRUE(waitUntilAllJobsFinished());
- ASSERT_THAT(documents.document(uicMainPath).dependedFilePaths(),
- Not(Contains(uiHeaderFilePath)));
-
- // Write ui file and notify backend
- const QByteArray content = "class UicObject{};";
- uiManager.write("uicheader.h", content);
- updateUnsavedFile(Utf8String(uiHeaderFilePath), Utf8String::fromByteArray(content));
-
- // Check
- ASSERT_TRUE(waitUntilAllJobsFinished());
- ASSERT_THAT(documents.document(uicMainPath).dependedFilePaths(),
- Contains(uiHeaderFilePath));
-}
-
-void ClangCodeModelServer::SetUp()
-{
- clangServer.setClient(&mockClangCodeModelClient);
- clangServer.setUpdateAnnotationsTimeOutInMsForTestsOnly(0);
- clangServer.setUpdateVisibleButNotCurrentDocumentsTimeOutInMsForTestsOnly(0);
-}
-
-void ClangCodeModelServer::TearDown()
-{
- ASSERT_TRUE(waitUntilAllJobsFinished());
-}
-
-bool ClangCodeModelServer::waitUntilAllJobsFinished(int timeOutInMs)
-{
- const auto noJobsRunningAnymore = [this]() {
- return clangServer.runningJobsForTestsOnly().isEmpty()
- && clangServer.queueSizeForTestsOnly() == 0
- && !clangServer.isTimerRunningForTestOnly();
- };
-
- return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
-}
-
-void ClangCodeModelServer::openDocument(const Utf8String &filePath,
- int expectedAnnotationsMessages)
-{
- openDocument(filePath, {}, {}, expectedAnnotationsMessages);
-}
-
-void ClangCodeModelServer::openDocument(const Utf8String &filePath,
- const Utf8StringVector &compilationArguments,
- const Utf8StringVector &headerPaths,
- int expectedAnnotationsMessages)
-{
- const FileContainer fileContainer(filePath, compilationArguments, headerPaths);
- const DocumentsOpenedMessage message({fileContainer}, filePath, {filePath});
-
- expectAnnotations(expectedAnnotationsMessages);
-
- clangServer.documentsOpened(message);
-}
-
-void ClangCodeModelServer::openDocuments(int expectedAnnotationsMessages)
-{
- const FileContainer fileContainerA(filePathA);
- const FileContainer fileContainerB(filePathB);
- const DocumentsOpenedMessage message({fileContainerA, fileContainerB},
- filePathA,
- {filePathA, filePathB});
-
- expectAnnotations(expectedAnnotationsMessages);
-
- clangServer.documentsOpened(message);
-}
-
-void ClangCodeModelServer::expectAnnotations(int count)
-{
- EXPECT_CALL(mockClangCodeModelClient, annotations(_)).Times(count);
-}
-
-void ClangCodeModelServer::openDocumentWithUnsavedContent(const Utf8String &filePath,
- const Utf8String &unsavedContent)
-{
- const FileContainer fileContainer(filePath, unsavedContent, true);
- const DocumentsOpenedMessage message({fileContainer}, filePath, {filePath});
-
- clangServer.documentsOpened(message);
-}
-
-void ClangCodeModelServer::requestCompletions(const Utf8String &filePath, uint line, uint column)
-{
- const RequestCompletionsMessage message(filePath, line, column);
-
- clangServer.requestCompletions(message);
-}
-
-void ClangCodeModelServer::requestCompletionsInFileA()
-{
- requestCompletions(filePathA, 20, 1);
-}
-
-bool ClangCodeModelServer::isSupportiveTranslationUnitInitialized(const Utf8String &filePath)
-{
- Document document = clangServer.documentsForTestOnly().document(filePath);
- DocumentProcessor documentProcessor = clangServer.documentProcessors().processor(document);
-
- return document.translationUnits().size() == 2
- && documentProcessor.hasSupportiveTranslationUnit()
- && documentProcessor.isSupportiveTranslationUnitInitialized();
-}
-
-DocumentProcessor ClangCodeModelServer::documentProcessorForFile(const Utf8String &filePath)
-{
- Document document = clangServer.documentsForTestOnly().document(filePath);
- DocumentProcessor documentProcessor = clangServer.documentProcessors().processor(document);
-
- return documentProcessor;
-}
-
-void ClangCodeModelServer::expectCompletion(const CodeCompletion &completion)
-{
- EXPECT_CALL(mockClangCodeModelClient,
- completions(Field(&CompletionsMessage::codeCompletions,
- Contains(completion))))
- .Times(1);
-}
-
-void ClangCodeModelServer::expectCompletionFromFileAUnsavedMethodVersion1()
-{
- const CodeCompletion completion(Utf8StringLiteral("Method2"),
- 34,
- CodeCompletion::FunctionDefinitionCompletionKind);
-
- expectCompletion(completion);
-}
-
-void ClangCodeModelServer::expectCompletionFromFileAUnsavedMethodVersion2()
-{
- const CodeCompletion completion(Utf8StringLiteral("Method3"),
- 34,
- CodeCompletion::FunctionDefinitionCompletionKind);
-
- expectCompletion(completion);
-}
-
-void ClangCodeModelServer::expectNoCompletionWithUnsavedMethod()
-{
- const CodeCompletion completion(Utf8StringLiteral("Method2"),
- 34,
- CodeCompletion::FunctionCompletionKind);
-
- EXPECT_CALL(mockClangCodeModelClient,
- completions(Field(&CompletionsMessage::codeCompletions,
- Not(Contains(completion)))))
- .Times(1);
-}
-
-void ClangCodeModelServer::expectReferences()
-{
- const QVector<ClangBackEnd::SourceRangeContainer> references{{
- {filePathC, 3, 9},
- {filePathC, 3, 12}
- }};
-
- EXPECT_CALL(mockClangCodeModelClient,
- references(
- Field(&ReferencesMessage::references,
- Eq(references))))
- .Times(1);
-}
-
-void ClangCodeModelServer::expectFollowSymbol()
-{
- const ClangBackEnd::FollowSymbolResult classDefinition
- = ClangBackEnd::SourceRangeContainer({filePathC, 40, 7}, {filePathC, 40, 10});
-
- EXPECT_CALL(mockClangCodeModelClient,
- followSymbol(
- Field(&FollowSymbolMessage::result,
- Eq(classDefinition))))
- .Times(1);
-}
-
-void ClangCodeModelServer::expectCompletionFromFileA()
-{
- const CodeCompletion completion(Utf8StringLiteral("Function"),
- 34,
- CodeCompletion::FunctionCompletionKind);
-
- expectCompletion(completion);
-}
-
-void ClangCodeModelServer::requestAnnotations(const Utf8String &filePath)
-{
- const RequestAnnotationsMessage message(FileContainer{filePath});
-
- clangServer.requestAnnotations(message);
-}
-
-void ClangCodeModelServer::requestReferences(quint32 documentRevision)
-{
- const FileContainer fileContainer{filePathC, {}, {}, documentRevision};
- const RequestReferencesMessage message{fileContainer, 3, 9};
-
- clangServer.requestReferences(message);
-}
-
-void ClangCodeModelServer::requestFollowSymbol(quint32 documentRevision)
-{
- const FileContainer fileContainer{filePathC, {}, {}, documentRevision};
- const RequestFollowSymbolMessage message{fileContainer, 43, 9};
-
- clangServer.requestFollowSymbol(message);
-}
-
-void ClangCodeModelServer::expectAnnotationsForFileBWithSpecificHighlightingMark()
-{
- HighlightingTypes types;
- types.mainHighlightingType = ClangBackEnd::HighlightingType::Function;
- types.mixinHighlightingTypes.push_back(ClangBackEnd::HighlightingType::Declaration);
- types.mixinHighlightingTypes.push_back(ClangBackEnd::HighlightingType::FunctionDefinition);
- const TokenInfoContainer tokenInfo(1, 6, 8, types);
- EXPECT_CALL(mockClangCodeModelClient,
- annotations(
- Field(&AnnotationsMessage::tokenInfos,
- PartlyContains(tokenInfo)))).Times(AnnotationJobsMultiplier);
-}
-
-void ClangCodeModelServer::updateUnsavedContent(const Utf8String &filePath,
- const Utf8String &fileContent,
- quint32 revisionNumber)
-{
- const FileContainer fileContainer(filePath, fileContent, true, revisionNumber);
- const DocumentsChangedMessage message({fileContainer});
-
- clangServer.documentsChanged(message);
-}
-
-void ClangCodeModelServer::removeUnsavedFile(const Utf8String &filePath)
-{
- const FileContainer fileContainer(filePath, {}, {}, 74);
- const DocumentsChangedMessage message({fileContainer});
-
- clangServer.documentsChanged(message);
-}
-
-void ClangCodeModelServer::closeDocument(const Utf8String &filePath)
-{
- const QVector<FileContainer> fileContainers = {FileContainer(filePath)};
- const DocumentsClosedMessage message(fileContainers);
-
- clangServer.documentsClosed(message);
-}
-
-void ClangCodeModelServer::updateUnsavedFile(const Utf8String &filePath,
- const Utf8String &fileContent)
-{
- const FileContainer fileContainer(filePath, fileContent, true, 0);
- const UnsavedFilesUpdatedMessage message({fileContainer});
-
- clangServer.unsavedFilesUpdated(message);
-}
-
-void ClangCodeModelServer::openDocumentAndWaitForFinished(
- const Utf8String &filePath, int expectedAnnotationsMessages)
-{
- openDocument(filePath, expectedAnnotationsMessages);
- ASSERT_TRUE(waitUntilAllJobsFinished());
-}
-
-void ClangCodeModelServer::updateVisibilty(const Utf8String &currentEditor,
- const Utf8String &additionalVisibleEditor)
-{
- const DocumentVisibilityChangedMessage message(currentEditor,
- {currentEditor, additionalVisibleEditor});
-
- clangServer.documentVisibilityChanged(message);
-}
-
-const Utf8String ClangCodeModelServer::unsavedContent(const QString &unsavedFilePath)
-{
- QFile unsavedFileContentFile(unsavedFilePath);
- const bool isOpen = unsavedFileContentFile.open(QIODevice::ReadOnly | QIODevice::Text);
- if (!isOpen)
- ADD_FAILURE() << "File with the unsaved content cannot be opened!";
-
- return Utf8String::fromByteArray(unsavedFileContentFile.readAll());
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangcompareoperators.h b/tests/unit/unittest/clangcompareoperators.h
deleted file mode 100644
index 39351946beb..00000000000
--- a/tests/unit/unittest/clangcompareoperators.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clang-c/Index.h>
-
-inline
-bool operator==(const CXSourceLocation &first, const CXSourceLocation &second)
-{
- return clang_equalLocations(first, second);
-}
-
-inline
-bool operator==(const CXSourceRange &first, const CXSourceRange &second)
-{
- return clang_equalRanges(first, second);
-}
diff --git a/tests/unit/unittest/clangcompletecodejob-test.cpp b/tests/unit/unittest/clangcompletecodejob-test.cpp
deleted file mode 100644
index 025a4b4f4e1..00000000000
--- a/tests/unit/unittest/clangcompletecodejob-test.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangasyncjob-base.h"
-
-#include <clangcompletecodejob.h>
-
-using namespace ClangBackEnd;
-
-using testing::_;
-using testing::Eq;
-using testing::Property;
-
-namespace {
-
-class CompleteCodeJob : public ClangAsyncJobTest
-{
-protected:
- void SetUp() override { BaseSetUp(JobRequest::Type::RequestCompletions, job); }
-
-protected:
- ClangBackEnd::CompleteCodeJob job;
-};
-
-TEST_F(CompleteCodeJob, PrepareAsyncRun)
-{
- job.setContext(jobContext);
-
- ASSERT_TRUE(job.prepareAsyncRun());
-}
-
-TEST_F(CompleteCodeJob, RunAsync)
-{
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(CompleteCodeJob, SendAnnotations)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, completions(_)).Times(1);
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(CompleteCodeJob, ForwardTicketNumber)
-{
- jobRequest.ticketNumber = static_cast<quint64>(99);
- jobContextWithMockClient = JobContext(jobRequest, &documents, &unsavedFiles, &mockIpcClient);
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient,
- completions(Field(&CompletionsMessage::ticketNumber,
- Eq(jobRequest.ticketNumber))))
- .Times(1);
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(CompleteCodeJob, DontSendCompletionsIfDocumentWasClosed)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, completions(_)).Times(0);
-
- job.runAsync();
- documents.remove({FileContainer{filePath}});
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp b/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp
deleted file mode 100644
index 66ed01b19db..00000000000
--- a/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp
+++ /dev/null
@@ -1,589 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangcodemodel/clangcompletioncontextanalyzer.h>
-#include <clangcodemodel/clangcompletionassistinterface.h>
-
-#include <utils/qtcassert.h>
-
-#include <QTextDocument>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-void PrintTo(const ClangCompletionContextAnalyzer::CompletionAction &completionAction,
- ::std::ostream* os)
-{
- using CCA = ClangCompletionContextAnalyzer;
-
- switch (completionAction) {
- case CCA::PassThroughToLibClang: *os << "PassThroughToLibClang"; break;
- case CCA::PassThroughToLibClangAfterLeftParen: *os << "PassThroughToLibClangAfterLeftParen"; break;
- case CCA::CompleteDoxygenKeyword: *os << "CompleteDoxygenKeyword"; break;
- case CCA::CompleteIncludePath: *os << "CompleteIncludePath"; break;
- case CCA::CompletePreprocessorDirective: *os << "CompletePreprocessorDirective"; break;
- case CCA::CompleteSignal: *os << "CompleteSignal"; break;
- case CCA::CompleteSlot: *os << "CompleteSlot"; break;
- case CCA::CompleteNone: *os << "CompleteNone"; break;
- }
-}
-
-} // Internal
-} // ClangCodeModel
-
-namespace {
-
-using ::testing::PrintToString;
-using ClangCodeModel::Internal::ClangCompletionAssistInterface;
-using CCA = ClangCodeModel::Internal::ClangCompletionContextAnalyzer;
-
-class TestDocument
-{
-public:
- TestDocument(const QByteArray &theSource)
- : source(theSource),
- position(theSource.lastIndexOf('@')) // Use 'lastIndexOf' due to doxygen: "//! @keyword"
- {
- source.remove(position, 1);
- }
-
- QByteArray source;
- int position;
-};
-
-bool isPassThrough(CCA::CompletionAction completionAction)
-{
- return completionAction != CCA::PassThroughToLibClang
- && completionAction != CCA::PassThroughToLibClangAfterLeftParen;
-}
-
-MATCHER(IsPassThroughToClang, std::string(negation ? "isn't" : "is") + " passed through to Clang")
-{
- const auto completionAction = arg.completionAction();
- if (isPassThrough(completionAction)) {
- *result_listener << "completion action is " << PrintToString(completionAction);
- return false;
- }
-
- return true;
-}
-
-// Offsets are relative to positionInText
-MATCHER_P5(HasResult,
- completionAction,
- positionForClangOffset,
- positionForProposalOffset,
- positionInText,
- addSnippets,
- std::string(negation ? "hasn't" : "has")
- + " result of completion action " + PrintToString(completionAction)
- + " and offset for clang " + PrintToString(positionForClangOffset)
- + " and offset for proprosal " + PrintToString(positionForProposalOffset)
- + " and addSnippets " + PrintToString(addSnippets))
-{
- const int actualPositionForClangOffset = arg.positionForClang() - positionInText;
- const int actualPositionForProposalOffset = arg.positionForProposal() - positionInText;
-
- if (arg.completionAction() != completionAction
- || actualPositionForClangOffset != positionForClangOffset
- || actualPositionForProposalOffset != positionForProposalOffset
- || addSnippets != arg.addSnippets()) {
- *result_listener << "completion action is " << PrintToString(arg.completionAction())
- << " and offset for clang is " << PrintToString(actualPositionForClangOffset)
- << " and offset for proprosal is " << PrintToString(actualPositionForProposalOffset)
- << " and addSnippets is " << PrintToString(arg.addSnippets());
- return false;
- }
-
- return true;
-}
-
-// Offsets are relative to positionInText
-MATCHER_P5(HasResultWithoutClangDifference,
- completionAction,
- positionForClangOffset,
- positionForProposalOffset,
- positionInText,
- addSnippets,
- std::string(negation ? "hasn't" : "has")
- + " result of completion action " + PrintToString(completionAction)
- + " and offset for clang " + PrintToString(positionForClangOffset)
- + " and offset for proprosal " + PrintToString(positionForProposalOffset)
- + " and addSnippets " + PrintToString(addSnippets))
-{
- const int actualPositionForProposalOffset = arg.positionForProposal() - positionInText;
-
- if (arg.completionAction() != completionAction
- || arg.positionForClang() != positionForClangOffset
- || actualPositionForProposalOffset != positionForProposalOffset
- || addSnippets != arg.addSnippets()) {
- *result_listener << "completion action is " << PrintToString(arg.completionAction())
- << " and offset for clang is " << PrintToString(arg.positionForClang())
- << " and offset for proprosal is " << PrintToString(actualPositionForProposalOffset)
- << " and addSnippets is " << PrintToString(arg.addSnippets());
- return false;
- }
-
- return true;
-}
-
-class ClangCompletionContextAnalyzer : public ::testing::Test
-{
-protected:
- CCA runAnalyzer(const char *text);
-
-protected:
- int positionInText = 0;
-};
-
-CCA ClangCompletionContextAnalyzer::runAnalyzer(const char *text)
-{
- const TestDocument testDocument(text);
- ClangCompletionAssistInterface assistInterface(testDocument.source, testDocument.position);
- CCA analyzer(&assistInterface, CPlusPlus::LanguageFeatures::defaultFeatures());
-
- positionInText = testDocument.position;
-
- analyzer.analyze();
-
- return analyzer;
-}
-
-TEST_F(ClangCompletionContextAnalyzer, WordsBeforeCursor)
-{
- auto analyzer = runAnalyzer("foo bar@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterSpace)
-{
- auto analyzer = runAnalyzer("foo @");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterQualification)
-{
- auto analyzer = runAnalyzer(" Foo::@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtEndOfDotMember)
-{
- auto analyzer = runAnalyzer("o.mem@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtEndOfDotMemberWithSpaceInside)
-{
- auto analyzer = runAnalyzer("o. mem@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtBeginOfDotMember)
-{
- auto analyzer = runAnalyzer("o.@mem");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtBeginOfDotMemberWithSpaceInside)
-{
- auto analyzer = runAnalyzer("o. @mem");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtEndOfArrow)
-{
- auto analyzer = runAnalyzer("o->mem@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtEndOfArrowWithSpaceInside)
-{
- auto analyzer = runAnalyzer("o-> mem@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtBeginOfArrow)
-{
- auto analyzer = runAnalyzer("o->@mem");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtBeginOfArrowWithSpaceInside)
-{
- auto analyzer = runAnalyzer("o-> @mem");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ArgumentOneAtCall)
-{
- auto analyzer = runAnalyzer("f(@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoAtCall)
-{
- auto analyzer = runAnalyzer("f(1,@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -2, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtCall)
-{
- auto analyzer = runAnalyzer("f(1, @");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, WhitespaceAfterFunctionName)
-{
- auto analyzer = runAnalyzer("foo (@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ConstructorCallWithBraceInitializer)
-{
- auto analyzer = runAnalyzer("f{@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtConstructorCallWithBraceInitializer)
-{
- auto analyzer = runAnalyzer("f{1, @");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, WhitespaceBeforeConstructorCallWithBraceInitializer)
-{
- auto analyzer = runAnalyzer("foo {@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, OpenFunctionScopeNotAConstructor)
-{
- auto analyzer = runAnalyzer("foo() {@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterOpeningParenthesis)
-{
- auto analyzer = runAnalyzer("(@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterOpeningBraceAndIdentifierOnNewLine)
-{
- auto analyzer = runAnalyzer("if (1) {\n"
- "cla@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ArgumentOneAtSignal)
-{
- auto analyzer = runAnalyzer("SIGNAL(@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::CompleteSignal, 0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ArgumentOneWithLettersAtSignal)
-{
- auto analyzer = runAnalyzer("SIGNAL(foo@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::CompleteSignal, -3, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ArgumentOneAtSlot)
-{
- auto analyzer = runAnalyzer("SLOT(@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::CompleteSlot, -0, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, ArgumentOneWithLettersAtSlot)
-{
- auto analyzer = runAnalyzer("SLOT(foo@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::CompleteSlot, -3, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, DoxygenWithBackslash)
-{
- auto analyzer = runAnalyzer("//! \\@");
-
- ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteDoxygenKeyword, -1, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, DoxygenWithAt)
-{
- auto analyzer = runAnalyzer("//! @@");
-
- ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteDoxygenKeyword, -1, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, DoxygenWithParameter)
-{
- auto analyzer = runAnalyzer("//! \\par@");
-
- ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteDoxygenKeyword, -1, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, Preprocessor)
-{
- auto analyzer = runAnalyzer("#@");
-
- ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompletePreprocessorDirective, -1, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, PreprocessorIf)
-{
- auto analyzer = runAnalyzer("#if@");
-
- ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompletePreprocessorDirective, -1, -2, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, LocalInclude)
-{
- auto analyzer = runAnalyzer("#include \"foo@\"");
-
- ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteIncludePath, -1, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, GlobalInclude)
-{
- auto analyzer = runAnalyzer("#include <foo@>");
-
- ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteIncludePath, -1, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, GlocalIncludeWithDirectory)
-{
- auto analyzer = runAnalyzer("#include <foo/@>");
-
- ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteIncludePath, -1, 0, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterQuote)
-{
- auto analyzer = runAnalyzer("\"@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterSpaceQuote)
-{
- auto analyzer = runAnalyzer(" \"@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterQuotedText)
-{
- auto analyzer = runAnalyzer("\"text\"@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, InQuotedText)
-{
- auto analyzer = runAnalyzer("\"hello cruel@ world\"");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, SingleQuote)
-{
- auto analyzer = runAnalyzer("'@'");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterLetterInSingleQuoted)
-{
- auto analyzer = runAnalyzer("'a@'");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, CommaOperator)
-{
- auto analyzer = runAnalyzer("a = b,@\"");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, DoxygenMarkerInNonDoxygenComment)
-{
- auto analyzer = runAnalyzer("@@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, DoxygenMarkerInNonDoxygenComment2)
-{
- auto analyzer = runAnalyzer("\\@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AtEndOfOneLineComment)
-{
- auto analyzer = runAnalyzer("// comment@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterOneLineCommentLine)
-{
- auto analyzer = runAnalyzer("// comment\n"
- "@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterEmptyOneLineComment)
-{
- auto analyzer = runAnalyzer("//\n"
- "@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterOneLineDoxygenComment1)
-{
- auto analyzer = runAnalyzer("/// comment\n"
- "@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AfterOneLineDoxygenComment2)
-{
- auto analyzer = runAnalyzer("//! comment \n"
- "@");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, BeginEndComment)
-{
- auto analyzer = runAnalyzer("/* text@ */");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, Slash)
-{
- auto analyzer = runAnalyzer("5 /@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, LeftParen)
-{
- auto analyzer = runAnalyzer("(@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, TwoLeftParen)
-{
- auto analyzer = runAnalyzer("((@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, AsteriskLeftParen)
-{
- auto analyzer = runAnalyzer("*(@");
-
- ASSERT_THAT(analyzer, IsPassThroughToClang());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, TemplatedFunctionSecondArgument)
-{
- auto analyzer = runAnalyzer("f < decltype(bar -> member) > (1, @");
-
- ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false));
-}
-
-TEST_F(ClangCompletionContextAnalyzer, FunctionNameStartPosition)
-{
- auto analyzer = runAnalyzer(" f<Bar>(1, @");
- int functionNameStartPosition = analyzer.functionNameStart();
-
- ASSERT_THAT(functionNameStartPosition, 1);
-}
-
-TEST_F(ClangCompletionContextAnalyzer, QualifiedFunctionNameStartPosition)
-{
- auto analyzer = runAnalyzer(" Namespace::f<Bar>(1, @");
- int functionNameStartPosition = analyzer.functionNameStart();
-
- ASSERT_THAT(functionNameStartPosition, 1);
-}
-
-TEST_F(ClangCompletionContextAnalyzer, SnippetsAfterOpeningBrace)
-{
- auto analyzer = runAnalyzer("{@");
-
- ASSERT_TRUE(analyzer.addSnippets());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, NoSnippetsAfterFunctionCallLike_OpeningBrace)
-{
- auto analyzer = runAnalyzer("foo{@");
-
- ASSERT_FALSE(analyzer.addSnippets());
-}
-
-TEST_F(ClangCompletionContextAnalyzer, NoSnippetsAfterFunctionCallLike_OpeningParen)
-{
- auto analyzer = runAnalyzer("foo(@");
-
- ASSERT_FALSE(analyzer.addSnippets());
-}
-
-} // namespace
diff --git a/tests/unit/unittest/clangdiagnosticfilter-test.cpp b/tests/unit/unittest/clangdiagnosticfilter-test.cpp
deleted file mode 100644
index 502e2538fca..00000000000
--- a/tests/unit/unittest/clangdiagnosticfilter-test.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangdiagnosticfilter.h>
-#include <diagnosticcontainer.h>
-#include <fixitcontainer.h>
-
-namespace {
-
-using ::testing::Contains;
-using ::testing::Not;
-
-using ClangBackEnd::DiagnosticContainer;
-using ClangBackEnd::FixItContainer;
-using ClangBackEnd::SourceLocationContainer;
-using ClangBackEnd::SourceRangeContainer;
-
-DiagnosticContainer createDiagnostic(const QString &text,
- ClangBackEnd::DiagnosticSeverity severity,
- const QString &filePath,
- QVector<DiagnosticContainer> children = QVector<DiagnosticContainer>(),
- bool addFixItContainer = false)
-{
- QVector<FixItContainer> fixIts;
- if (addFixItContainer)
- fixIts.append(FixItContainer(Utf8StringLiteral("("), {{filePath, 1, 1}, {filePath, 1, 2}}));
-
- return DiagnosticContainer(
- text,
- Utf8StringLiteral(""),
- {},
- severity,
- {filePath, 0u, 0u},
- {},
- fixIts,
- children
- );
-}
-
-const QString mainFileHeaderPath = QString::fromUtf8(TESTDATA_DIR "/someHeader.h");
-const QString mainFilePath = QString::fromUtf8(TESTDATA_DIR "/diagnostic_erroneous_source.cpp");
-const QString headerFilePath = QString::fromUtf8(TESTDATA_DIR "/diagnostic_erroneous_header.cpp");
-
-DiagnosticContainer warningFromHeader()
-{
- return createDiagnostic(
- QStringLiteral("warning: control reaches end of non-void function"),
- ClangBackEnd::DiagnosticSeverity::Warning,
- headerFilePath);
-}
-
-DiagnosticContainer errorFromHeader()
-{
- return createDiagnostic(
- QStringLiteral("C++ requires a type specifier for all declarations"),
- ClangBackEnd::DiagnosticSeverity::Error,
- headerFilePath);
-}
-
-DiagnosticContainer warningFromMainFile()
-{
- return createDiagnostic(
- QStringLiteral("warning: enumeration value 'Three' not handled in switch"),
- ClangBackEnd::DiagnosticSeverity::Warning,
- mainFilePath);
-}
-
-DiagnosticContainer pragmaOnceWarningInHeader()
-{
- return createDiagnostic(
- QStringLiteral("warning: #pragma once in main file"),
- ClangBackEnd::DiagnosticSeverity::Warning,
- mainFileHeaderPath);
-}
-
-DiagnosticContainer includeNextInPrimarySourceFileWarningInHeader()
-{
- return createDiagnostic(
- QStringLiteral("warning: #include_next in primary source file"),
- ClangBackEnd::DiagnosticSeverity::Warning,
- mainFileHeaderPath);
-}
-
-DiagnosticContainer errorFromMainFile()
-{
- return createDiagnostic(
- QStringLiteral("error: void function 'g' should not return a value"),
- ClangBackEnd::DiagnosticSeverity::Error,
- mainFilePath);
-}
-
-DiagnosticContainer fixIt1(const QString &filePath)
-{
- return createDiagnostic(
- QStringLiteral("note: place parentheses around the assignment to silence this warning"),
- ClangBackEnd::DiagnosticSeverity::Note,
- filePath);
-}
-
-DiagnosticContainer fixIt2(const QString &filePath)
-{
- return createDiagnostic(
- QStringLiteral("note: use '==' to turn this assignment into an equality comparison"),
- ClangBackEnd::DiagnosticSeverity::Note,
- filePath);
-}
-
-DiagnosticContainer createDiagnosticWithFixIt(const QString &filePath)
-{
- return createDiagnostic(
- QStringLiteral("warning: using the result of an assignment as a condition without parentheses"),
- ClangBackEnd::DiagnosticSeverity::Warning,
- filePath,
- {fixIt1(filePath), fixIt2(filePath)},
- true);
-}
-
-DiagnosticContainer warningFromMainFileWithFixits()
-{
- return createDiagnosticWithFixIt(mainFilePath);
-}
-
-DiagnosticContainer warningFromHeaderFileWithFixits()
-{
- return createDiagnosticWithFixIt(headerFilePath);
-}
-
-class ClangDiagnosticFilter : public ::testing::Test
-{
-protected:
- ClangCodeModel::Internal::ClangDiagnosticFilter clangDiagnosticFilter{mainFilePath};
-};
-
-TEST_F(ClangDiagnosticFilter, WarningsFromMainFileAreLetThrough)
-{
- clangDiagnosticFilter.filter({warningFromMainFile()});
-
- ASSERT_THAT(clangDiagnosticFilter.takeWarnings(),Contains(warningFromMainFile()));
-}
-
-TEST_F(ClangDiagnosticFilter, WarningsFromHeaderAreIgnored)
-{
- clangDiagnosticFilter.filter({warningFromHeader()});
-
- ASSERT_THAT(clangDiagnosticFilter.takeWarnings(), Not(Contains(warningFromHeader())));
-}
-
-TEST_F(ClangDiagnosticFilter, ErrorsFromMainFileAreLetThrough)
-{
- clangDiagnosticFilter.filter({errorFromMainFile()});
-
- ASSERT_THAT(clangDiagnosticFilter.takeErrors(), Contains(errorFromMainFile()));
-}
-
-TEST_F(ClangDiagnosticFilter, ErrorsFromHeaderAreIgnored)
-{
- clangDiagnosticFilter.filter({errorFromHeader()});
-
- ASSERT_THAT(clangDiagnosticFilter.takeErrors(), Not(Contains(errorFromHeader())));
-}
-
-TEST_F(ClangDiagnosticFilter, FixItsFromMainFileAreLetThrough)
-{
- clangDiagnosticFilter.filter({warningFromMainFileWithFixits()});
-
- ASSERT_THAT(clangDiagnosticFilter.takeFixIts(), Contains(warningFromMainFileWithFixits()));
-}
-
-TEST_F(ClangDiagnosticFilter, FixItsFromHeaderAreIgnored)
-{
- clangDiagnosticFilter.filter({warningFromHeaderFileWithFixits()});
-
- ASSERT_THAT(clangDiagnosticFilter.takeFixIts(),
- Not(Contains(warningFromHeaderFileWithFixits())));
-}
-
-TEST_F(ClangDiagnosticFilter, WarningsAreEmptyAfterTaking)
-{
- clangDiagnosticFilter.filter({warningFromMainFile()});
-
- clangDiagnosticFilter.takeWarnings();
-
- ASSERT_TRUE(clangDiagnosticFilter.takeWarnings().isEmpty());
-}
-
-TEST_F(ClangDiagnosticFilter, IgnoreCertainWarningsInHeaderFiles)
-{
- ClangCodeModel::Internal::ClangDiagnosticFilter myClangDiagnosticFilter{mainFileHeaderPath};
-
- myClangDiagnosticFilter.filter({pragmaOnceWarningInHeader(),
- includeNextInPrimarySourceFileWarningInHeader()});
-
- ASSERT_TRUE(myClangDiagnosticFilter.takeWarnings().isEmpty());
-}
-
-TEST_F(ClangDiagnosticFilter, ErrorsAreEmptyAfterTaking)
-{
- clangDiagnosticFilter.filter({errorFromMainFile()});
-
- clangDiagnosticFilter.takeErrors();
-
- ASSERT_TRUE(clangDiagnosticFilter.takeErrors().isEmpty());
-}
-
-TEST_F(ClangDiagnosticFilter, FixItssAreEmptyAfterTaking)
-{
- clangDiagnosticFilter.filter({warningFromMainFileWithFixits()});
-
- clangDiagnosticFilter.takeFixIts();
-
- ASSERT_TRUE(clangDiagnosticFilter.takeFixIts().isEmpty());
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/clangdocument-test.cpp b/tests/unit/unittest/clangdocument-test.cpp
deleted file mode 100644
index 4978f41fd73..00000000000
--- a/tests/unit/unittest/clangdocument-test.cpp
+++ /dev/null
@@ -1,361 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangclock.h>
-#include <clangfilepath.h>
-#include <clangtranslationunitupdater.h>
-#include <clangtranslationunits.h>
-#include <clangtranslationunit.h>
-#include <commandlinearguments.h>
-#include <diagnosticset.h>
-#include <tokenprocessor.h>
-#include <filecontainer.h>
-#include <clangexceptions.h>
-#include <clangdocument.h>
-#include <clangtranslationunit.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-#include <utf8string.h>
-
-#include <clang-c/Index.h>
-
-#include <QTemporaryFile>
-
-#include <thread>
-
-using ClangBackEnd::Clock;
-using ClangBackEnd::Duration;
-using ClangBackEnd::FileContainer;
-using ClangBackEnd::FilePath;
-using ClangBackEnd::Document;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::Documents;
-using ClangBackEnd::TranslationUnitUpdateResult;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::TranslationUnits;
-
-using testing::IsNull;
-using testing::NotNull;
-using testing::Eq;
-using testing::Gt;
-using testing::Contains;
-using testing::EndsWith;
-using testing::AllOf;
-
-namespace {
-
-class Document : public ::testing::Test
-{
-protected:
- void SetUp() override;
- ::Document createDocumentAndDeleteFile();
- QByteArray readContentFromDocumentFile() const;
-
-protected:
- Utf8String documentFilePath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp");
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- ::Document document;
-};
-
-using DocumentSlowTest = Document;
-
-TEST_F(Document, DefaultDocumentIsInvalid)
-{
- ::Document document;
-
- ASSERT_TRUE(document.isNull());
-}
-
-TEST_F(Document, DefaultDocumentIsNotIntact)
-{
- ::Document document;
-
- ASSERT_FALSE(document.isIntact());
-}
-
-TEST_F(Document, ThrowExceptionForNonExistingFilePath)
-{
- ASSERT_THROW(::Document(Utf8StringLiteral("file.cpp"), {}, {}, documents),
- ClangBackEnd::DocumentFileDoesNotExistException);
-}
-
-TEST_F(Document, ThrowNoExceptionForNonExistingFilePathIfDoNotCheckIfFileExistsIsSet)
-{
- ASSERT_NO_THROW(::Document(Utf8StringLiteral("file.cpp"),
- {},
- {},
- documents,
- ::Document::FileExistsCheck::DoNotCheck));
-}
-
-TEST_F(Document, DocumentIsValid)
-{
- ASSERT_FALSE(document.isNull());
-}
-
-
-TEST_F(Document, ThrowExceptionForGettingIndexForInvalidUnit)
-{
- ::Document document;
-
- ASSERT_THROW(document.translationUnit().cxIndex(), ClangBackEnd::DocumentIsNullException);
-}
-
-TEST_F(Document, ThrowExceptionForGettingCxTranslationUnitForInvalidUnit)
-{
- ::Document document;
-
- ASSERT_THROW(document.translationUnit().cxIndex(), ClangBackEnd::DocumentIsNullException);
-}
-
-TEST_F(DocumentSlowTest, CxTranslationUnitGetterIsNonNullForParsedUnit)
-{
- document.parse();
-
- ASSERT_THAT(document.translationUnit().cxIndex(), NotNull());
-}
-
-TEST_F(Document, ThrowExceptionIfGettingFilePathForNullUnit)
-{
- ::Document document;
-
- ASSERT_THROW(document.filePath(), ClangBackEnd::DocumentIsNullException);
-}
-
-TEST_F(Document, ResettedDocumentIsNull)
-{
- document.reset();
-
- ASSERT_TRUE(document.isNull());
-}
-
-TEST_F(Document, LastCommandLineArgumentIsFilePath)
-{
- const Utf8String nativeFilePath = FilePath::toNativeSeparators(documentFilePath);
- const auto arguments = document.createUpdater().commandLineArguments();
-
- ASSERT_THAT(arguments.at(arguments.count() - 1), Eq(nativeFilePath));
-}
-
-TEST_F(Document, DocumentRevisionInFileContainerGetter)
-{
- document.setDocumentRevision(74);
-
- ASSERT_THAT(document.fileContainer().documentRevision, 74);
-}
-
-TEST_F(DocumentSlowTest, DependedFilePaths)
-{
- document.parse();
-
- ASSERT_THAT(document.dependedFilePaths(),
- AllOf(Contains(documentFilePath),
- Contains(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h"))));
-}
-
-TEST_F(Document, DeletedFileShouldNotNeedReparsing)
-{
- auto document = createDocumentAndDeleteFile();
-
- document.setDirtyIfDependencyIsMet(document.filePath());
-
- ASSERT_FALSE(document.isDirty());
-}
-
-TEST_F(Document, NeedsNoReparseAfterCreation)
-{
- ASSERT_FALSE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, NeedsReparseAfterChangeOfMainFile)
-{
- document.parse();
-
- document.setDirtyIfDependencyIsMet(documentFilePath);
-
- ASSERT_TRUE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependentFile)
-{
- document.parse();
-
- document.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/otherfiles.h"));
-
- ASSERT_FALSE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, NeedsReparsingForDependentFile)
-{
- document.parse();
-
- document.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h"));
-
- ASSERT_TRUE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, NeedsNoReparsingAfterReparsing)
-{
- document.parse();
- document.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h"));
-
- document.reparse();
-
- ASSERT_FALSE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, IsIntactAfterParsing)
-{
- document.parse();
-
- ASSERT_TRUE(document.isIntact());
-}
-
-TEST_F(Document, IsNotIntactForDeletedFile)
-{
- auto document = createDocumentAndDeleteFile();
-
- ASSERT_FALSE(document.isIntact());
-}
-
-TEST_F(DocumentSlowTest, DoesNotNeedReparseAfterParse)
-{
- document.parse();
-
- ASSERT_FALSE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, NeedsReparseAfterMainFileChanged)
-{
- document.parse();
-
- document.setDirtyIfDependencyIsMet(documentFilePath);
-
- ASSERT_TRUE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, NeedsReparseAfterIncludedFileChanged)
-{
- document.parse();
-
- document.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h"));
-
- ASSERT_TRUE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, DoesNotNeedReparseAfterNotIncludedFileChanged)
-{
- document.parse();
-
- document.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/otherfiles.h"));
-
- ASSERT_FALSE(document.isDirty());
-}
-
-TEST_F(DocumentSlowTest, DoesNotNeedReparseAfterReparse)
-{
- document.parse();
- document.setDirtyIfDependencyIsMet(documentFilePath);
-
- document.reparse();
-
- ASSERT_FALSE(document.isDirty());
-}
-
-TEST_F(Document, IncorporateUpdaterResultResetsDirtyness)
-{
- document.setDirtyIfDependencyIsMet(document.filePath());
- TranslationUnitUpdateResult result;
- result.reparseTimePoint = Clock::now();
- result.needsToBeReparsedChangeTimePoint = document.isDirtyTimeChangePoint();
- result.translationUnitId = document.translationUnit().id();
-
- document.incorporateUpdaterResult(result);
-
- ASSERT_FALSE(document.isDirty());
-}
-
-TEST_F(Document, IncorporateUpdaterResultDoesNotResetDirtynessIfItWasChanged)
-{
- TranslationUnitUpdateResult result;
- result.reparseTimePoint = Clock::now();
- result.needsToBeReparsedChangeTimePoint = Clock::now();
- result.translationUnitId = document.translationUnit().id();
- document.setDirtyIfDependencyIsMet(document.filePath());
-
- document.incorporateUpdaterResult(result);
-
- ASSERT_TRUE(document.isDirty());
-}
-
-TEST_F(Document, IncorporateUpdaterResultUpdatesTranslationUnitsReparseTimePoint)
-{
- TranslationUnits &translationUnits = document.translationUnits();
- const TranslationUnit initialTranslationUnit = translationUnits.get();
- translationUnits.updateParseTimePoint(initialTranslationUnit.id(), Clock::now());
- const TranslationUnit alternativeTranslationUnit = translationUnits.createAndAppend();
- translationUnits.updateParseTimePoint(alternativeTranslationUnit.id(), Clock::now());
- TranslationUnitUpdateResult result;
- result.reparseTimePoint = Clock::now();
- result.needsToBeReparsedChangeTimePoint = Clock::now();
- result.translationUnitId = initialTranslationUnit.id();
- document.setDirtyIfDependencyIsMet(document.filePath());
- ASSERT_THAT(translationUnits.get().id(), Eq(alternativeTranslationUnit.id()));
-
- document.incorporateUpdaterResult(result);
-
- ASSERT_THAT(translationUnits.get().id(), Eq(initialTranslationUnit.id()));
-}
-
-void Document::SetUp()
-{
- const QVector<FileContainer> fileContainer{FileContainer(documentFilePath)};
- const auto createdDocuments = documents.create(fileContainer);
- document = createdDocuments.front();
-}
-
-::Document Document::createDocumentAndDeleteFile()
-{
- QTemporaryFile temporaryFile;
- EXPECT_TRUE(temporaryFile.open());
- EXPECT_TRUE(temporaryFile.write(readContentFromDocumentFile()));
- ::Document document(temporaryFile.fileName(), {}, {}, documents);
-
- return document;
-}
-
-QByteArray Document::readContentFromDocumentFile() const
-{
- QFile contentFile(documentFilePath);
- EXPECT_TRUE(contentFile.open(QIODevice::ReadOnly));
-
- return contentFile.readAll();
-}
-
-}
-
diff --git a/tests/unit/unittest/clangdocumentprocessor-test.cpp b/tests/unit/unittest/clangdocumentprocessor-test.cpp
deleted file mode 100644
index 5ed3fd328d0..00000000000
--- a/tests/unit/unittest/clangdocumentprocessor-test.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "clangiasyncjob.h"
-#include "dummyclangipcclient.h"
-#include "processevents-utilities.h"
-
-#include <clangdocument.h>
-#include <clangdocumentprocessor.h>
-#include <clangdocuments.h>
-#include <clangjobrequest.h>
-#include <clangjobs.h>
-#include <unsavedfiles.h>
-
-using namespace ClangBackEnd;
-
-namespace {
-
-class DocumentProcessor : public ::testing::Test
-{
-protected:
- void SetUp() override;
- void TearDown() override;
- bool waitUntilAllJobsFinished(int timeOutInMs = 10000) const;
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
-
- DummyIpcClient dummyIpcClient;
-
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")};
- std::unique_ptr<ClangBackEnd::DocumentProcessor> documentProcessor;
-};
-
-using DocumentProcessorSlowTest = DocumentProcessor;
-
-TEST_F(DocumentProcessor, ProcessEmpty)
-{
- const JobRequests jobsStarted = documentProcessor->process();
-
- ASSERT_THAT(jobsStarted.size(), 0);
-}
-
-TEST_F(DocumentProcessorSlowTest, ProcessSingleJob)
-{
- const JobRequest jobRequest
- = documentProcessor->createJobRequest(JobRequest::Type::UpdateAnnotations);
- documentProcessor->addJob(jobRequest);
-
- const JobRequests jobsStarted = documentProcessor->process();
-
- ASSERT_THAT(jobsStarted.size(), 1);
-}
-
-void DocumentProcessor::SetUp()
-{
- const QVector<FileContainer> fileContainer{FileContainer(filePath)};
-
- ClangBackEnd::Document document = {documents.create(fileContainer).front()};
- documents.setVisibleInEditors({filePath});
- documents.setUsedByCurrentEditor(filePath);
- documentProcessor = std::make_unique<ClangBackEnd::DocumentProcessor>(
- document, documents, unsavedFiles, dummyIpcClient);
-}
-
-void DocumentProcessor::TearDown()
-{
- ASSERT_TRUE(waitUntilAllJobsFinished()); // QFuture/QFutureWatcher is implemented with events
-}
-
-bool DocumentProcessor::waitUntilAllJobsFinished(int timeOutInMs) const
-{
- const auto noJobsRunningAnymore = [this](){ return documentProcessor->runningJobs().isEmpty(); };
-
- return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangdocumentprocessors-test.cpp b/tests/unit/unittest/clangdocumentprocessors-test.cpp
deleted file mode 100644
index 62a5d475430..00000000000
--- a/tests/unit/unittest/clangdocumentprocessors-test.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "clangiasyncjob.h"
-#include "dummyclangipcclient.h"
-#include "processevents-utilities.h"
-
-#include <clangdocument.h>
-#include <clangdocumentprocessor.h>
-#include <clangdocumentprocessors.h>
-#include <clangdocuments.h>
-#include <clangexceptions.h>
-#include <clangjobrequest.h>
-#include <clangjobs.h>
-#include <unsavedfiles.h>
-
-using testing::Eq;
-
-using namespace ClangBackEnd;
-
-namespace {
-
-class DocumentProcessors : public ::testing::Test
-{
-protected:
- void SetUp() override;
- void TearDown() override;
-
- bool waitUntilAllJobsFinished(int timeOutInMs = 10000) const;
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- ClangBackEnd::Document document;
-
- DummyIpcClient dummyIpcClient;
-
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")};
-
- ClangBackEnd::JobRequest jobRequest;
- ClangBackEnd::JobContext jobContext;
-
- ClangBackEnd::DocumentProcessors documentProcessors{documents,
- unsavedFiles,
- dummyIpcClient};
-};
-
-using DocumentProcessorsSlowTest = DocumentProcessors;
-
-TEST_F(DocumentProcessors, HasNoItemsInitially)
-{
- ASSERT_TRUE(documentProcessors.processors().empty());
-}
-
-TEST_F(DocumentProcessors, CreateAddsADocumentProcessor)
-{
- documentProcessors.create(document);
-
- ASSERT_THAT(documentProcessors.processors().size(), Eq(1));
-}
-
-TEST_F(DocumentProcessors, CreateReturnsDocumentProcessor)
-{
- const DocumentProcessor documentProcessor = documentProcessors.create(document);
-
- ASSERT_THAT(documentProcessor.document(), Eq(document));
-}
-
-TEST_F(DocumentProcessors, CreateThrowsForAlreadyExisting)
-{
- documentProcessors.create(document);
-
- ASSERT_THROW(documentProcessors.create(document),
- ClangBackEnd::DocumentProcessorAlreadyExists);
-}
-
-TEST_F(DocumentProcessors, Access)
-{
- documentProcessors.create(document);
-
- const DocumentProcessor documentProcessor = documentProcessors.processor(document);
-
- ASSERT_THAT(documentProcessor.document(), Eq(document));
-}
-
-TEST_F(DocumentProcessors, AccessThrowsForNotExisting)
-{
- ASSERT_THROW(documentProcessors.processor(document),
- ClangBackEnd::DocumentProcessorDoesNotExist);
-}
-
-TEST_F(DocumentProcessors, Remove)
-{
- documentProcessors.create(document);
-
- documentProcessors.remove(document);
-
- ASSERT_TRUE(documentProcessors.processors().empty());
-}
-
-TEST_F(DocumentProcessors, ResetTakesOverJobsInQueue)
-{
- documentProcessors.create(document);
- documentProcessors.processor(document).addJob(JobRequest::Type::RequestReferences);
- documents.remove({document.fileContainer()});
- const auto newDocument = *documents.create({document.fileContainer()}).begin();
-
- documentProcessors.reset(document, newDocument);
-
- ASSERT_THAT(documentProcessors.processor(document).queue().first().type,
- JobRequest::Type::RequestReferences);
-}
-
-TEST_F(DocumentProcessors, RemoveThrowsForNotExisting)
-{
- ASSERT_THROW(documentProcessors.remove(document),
- ClangBackEnd::DocumentProcessorDoesNotExist);
-}
-
-TEST_F(DocumentProcessors, ProcessEmpty)
-{
- documentProcessors.create(document);
-
- const JobRequests jobsStarted = documentProcessors.process();
-
- ASSERT_TRUE(jobsStarted.isEmpty());
-}
-
-TEST_F(DocumentProcessorsSlowTest, ProcessSingle)
-{
- DocumentProcessor documentProcessor = documentProcessors.create(document);
- documentProcessor.addJob(JobRequest::Type::UpdateAnnotations);
-
- const JobRequests jobsStarted = documentProcessors.process();
-
- ASSERT_THAT(jobsStarted.size(), 1);
-}
-
-void DocumentProcessors::SetUp()
-{
- const QVector<FileContainer> fileContainer{FileContainer(filePath)};
- document = documents.create(fileContainer).front();
- documents.setVisibleInEditors({filePath});
- documents.setUsedByCurrentEditor(filePath);
-}
-
-void DocumentProcessors::TearDown()
-{
- ASSERT_TRUE(waitUntilAllJobsFinished()); // QFuture/QFutureWatcher is implemented with events
-}
-
-bool DocumentProcessors::waitUntilAllJobsFinished(int timeOutInMs) const
-{
- const auto noJobsRunningAnymore = [this](){ return documentProcessors.runningJobs().isEmpty(); };
-
- return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangdocuments-test.cpp b/tests/unit/unittest/clangdocuments-test.cpp
deleted file mode 100644
index 71a2ebed804..00000000000
--- a/tests/unit/unittest/clangdocuments-test.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangexceptions.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-#include <utf8string.h>
-
-#include <clang-c/Index.h>
-
-using ClangBackEnd::Document;
-using ClangBackEnd::UnsavedFiles;
-
-using testing::IsNull;
-using testing::NotNull;
-using testing::Gt;
-using testing::Eq;
-using testing::Not;
-using testing::Contains;
-
-namespace {
-
-using ::testing::PrintToString;
-
-MATCHER_P2(IsDocument, filePath, documentRevision,
- std::string(negation ? "isn't" : "is")
- + " document with file path "+ PrintToString(filePath)
- + " and document revision " + PrintToString(documentRevision)
- )
-{
- return arg.filePath() == filePath
- && arg.documentRevision() == documentRevision;
-}
-
-class Documents : public ::testing::Test
-{
-protected:
- void SetUp() override;
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- const Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp");
- const Utf8String otherFilePath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.h");
- const Utf8String headerPath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.h");
- const Utf8String nonExistingFilePath = Utf8StringLiteral("foo.cpp");
- const ClangBackEnd::FileContainer fileContainer{filePath};
- const ClangBackEnd::FileContainer headerContainer{headerPath};
-};
-
-using DocumentsSlowTest = Documents;
-
-TEST_F(Documents, ThrowForGettingWithWrongFilePath)
-{
- ASSERT_THROW(documents.document(nonExistingFilePath),
- ClangBackEnd::DocumentDoesNotExistException);
-
-}
-
-TEST_F(Documents, ThrowForAddingNonExistingFile)
-{
- ClangBackEnd::FileContainer fileContainer(nonExistingFilePath);
-
- ASSERT_THROW(documents.create({fileContainer}),
- ClangBackEnd::DocumentFileDoesNotExistException);
-}
-
-TEST_F(Documents, DoNotThrowForAddingNonExistingFileWithUnsavedContent)
-{
- ClangBackEnd::FileContainer fileContainer(nonExistingFilePath, Utf8String(), true);
-
- ASSERT_NO_THROW(documents.create({fileContainer}));
-}
-
-TEST_F(Documents, Add)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
-
- documents.create({fileContainer});
-
- ASSERT_THAT(documents.document(filePath),
- IsDocument(filePath, 74u));
-}
-
-TEST_F(Documents, CreateWithUnsavedContentSetsDependenciesDirty)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
- ClangBackEnd::FileContainer fileContainerWithUnsavedContent(otherFilePath, {}, {}, Utf8String(), true, 2u);
- auto dependentDocument = documents.create({fileContainer}).at(0);
- dependentDocument.setDependedFilePaths(QSet<Utf8String>() << filePath << otherFilePath);
-
- documents.create({fileContainerWithUnsavedContent});
-
- ASSERT_TRUE(dependentDocument.isDirty());
-}
-
-TEST_F(Documents, AddAndTestCreatedTranslationUnit)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
-
- auto createdDocuments = documents.create({fileContainer});
-
- ASSERT_THAT(createdDocuments.front(), IsDocument(filePath, 74u));
-}
-
-TEST_F(Documents, ThrowForCreatingAnExistingDocument)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
- documents.create({fileContainer});
-
- ASSERT_THROW(documents.create({fileContainer}), ClangBackEnd::DocumentAlreadyExistsException);
-}
-
-TEST_F(Documents, ThrowForUpdatingANonExistingDocument)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
- ASSERT_THROW(documents.update({fileContainer}),
- ClangBackEnd::DocumentDoesNotExistException);
-}
-
-TEST_F(Documents, UpdateSingle)
-{
- ClangBackEnd::FileContainer createFileContainer(filePath, {}, {}, 74u);
- ClangBackEnd::FileContainer updateFileContainer(filePath, {}, {}, 75u);
- documents.create({createFileContainer});
-
- documents.update({updateFileContainer});
-
- ASSERT_THAT(documents.document(filePath), IsDocument(filePath, 75u));
-}
-
-TEST_F(Documents, UpdateReturnsUpdatedDocument)
-{
- ClangBackEnd::FileContainer createFileContainer(filePath, {}, {}, 74u);
- ClangBackEnd::FileContainer updateFileContainer(filePath, {}, {}, 75u);
- documents.create({createFileContainer});
-
- const std::vector<Document> updatedDocuments = documents.update({updateFileContainer});
-
- ASSERT_THAT(updatedDocuments.size(), Eq(1u));
- ASSERT_THAT(updatedDocuments.front().documentRevision(), Eq(75u));
-}
-
-// TODO: Does this test still makes sense?
-TEST_F(Documents, UpdateMultiple)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
- ClangBackEnd::FileContainer fileContainerWithOtherProject(filePath, {}, {}, 74u);
- ClangBackEnd::FileContainer updatedFileContainer(filePath, {}, {}, 75u);
- documents.create({fileContainer, fileContainerWithOtherProject});
-
- documents.update({updatedFileContainer});
-
- ASSERT_THAT(documents.document(filePath), IsDocument(filePath, 75u));
-}
-
-TEST_F(DocumentsSlowTest, UpdateUnsavedFileAndCheckForReparse)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
- ClangBackEnd::FileContainer headerContainer(headerPath, {}, {}, 74u);
- ClangBackEnd::FileContainer headerContainerWithUnsavedContent(headerPath, Utf8String(), true, 75u);
- documents.create({fileContainer, headerContainer});
- Document document = documents.document(filePath);
- document.parse();
-
- documents.update({headerContainerWithUnsavedContent});
-
- ASSERT_TRUE(documents.document(filePath).isDirty());
-}
-
-TEST_F(DocumentsSlowTest, RemoveFileAndCheckForReparse)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
- ClangBackEnd::FileContainer headerContainer(headerPath, {}, {}, 74u);
- ClangBackEnd::FileContainer headerContainerWithUnsavedContent(headerPath, Utf8String(), true, 75u);
- documents.create({fileContainer, headerContainer});
- Document document = documents.document(filePath);
- document.parse();
-
- documents.remove({headerContainerWithUnsavedContent});
-
- ASSERT_TRUE(documents.document(filePath).isDirty());
-}
-
-TEST_F(Documents, DontGetNewerFileContainerIfRevisionIsTheSame)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
- documents.create({fileContainer});
-
- auto newerFileContainers = documents.newerFileContainers({fileContainer});
-
- ASSERT_THAT(newerFileContainers.size(), 0);
-}
-
-TEST_F(Documents, GetNewerFileContainerIfRevisionIsDifferent)
-{
- ClangBackEnd::FileContainer fileContainer(filePath, {}, {}, 74u);
- ClangBackEnd::FileContainer newerContainer(filePath, {}, {}, 75u);
- documents.create({fileContainer});
-
- auto newerFileContainers = documents.newerFileContainers({newerContainer});
-
- ASSERT_THAT(newerFileContainers.size(), 1);
-}
-
-TEST_F(Documents, ThrowForRemovingWithWrongFilePath)
-{
- ClangBackEnd::FileContainer fileContainer(nonExistingFilePath);
-
- ASSERT_THROW(documents.remove({fileContainer}),
- ClangBackEnd::DocumentDoesNotExistException);
-}
-
-TEST_F(Documents, Remove)
-{
- ClangBackEnd::FileContainer fileContainer(filePath);
- documents.create({fileContainer});
-
- documents.remove({fileContainer});
-
- ASSERT_THROW(documents.document(filePath),
- ClangBackEnd::DocumentDoesNotExistException);
-}
-
-TEST_F(Documents, RemoveAllValidIfExceptionIsThrown)
-{
- ClangBackEnd::FileContainer fileContainer(filePath);
- documents.create({fileContainer});
-
- ASSERT_THROW(documents.remove({ClangBackEnd::FileContainer(Utf8StringLiteral("dontextist.pro")), fileContainer}),
- ClangBackEnd::DocumentDoesNotExistException);
-
- ASSERT_THAT(documents.documents(),
- Not(Contains(Document(filePath, {}, {}, documents))));
-}
-
-TEST_F(Documents, HasDocument)
-{
- documents.create({{filePath}});
-
- ASSERT_TRUE(documents.hasDocument(filePath));
-}
-
-TEST_F(Documents, HasNotDocument)
-{
- ASSERT_FALSE(documents.hasDocument(filePath));
-}
-
-TEST_F(Documents, FilteredPositive)
-{
- documents.create({{filePath}});
- const auto isMatchingFilePath = [this](const Document &document) {
- return document.filePath() == filePath;
- };
-
- const bool hasMatches = !documents.filtered(isMatchingFilePath).empty();
-
- ASSERT_TRUE(hasMatches);
-}
-
-TEST_F(Documents, FilteredNegative)
-{
- documents.create({{filePath}});
- const auto isMatchingNothing = [](const Document &) {
- return false;
- };
-
- const bool hasMatches = !documents.filtered(isMatchingNothing).empty();
-
- ASSERT_FALSE(hasMatches);
-}
-
-TEST_F(Documents, DirtyAndVisibleButNotCurrentDocuments)
-{
- documents.create({{filePath}});
- documents.updateDocumentsWithChangedDependency(filePath);
- documents.setVisibleInEditors({filePath});
- documents.setUsedByCurrentEditor(Utf8String());
-
- const bool hasMatches = !documents.dirtyAndVisibleButNotCurrentDocuments().empty();
-
- ASSERT_TRUE(hasMatches);
-}
-
-TEST_F(Documents, isUsedByCurrentEditor)
-{
- documents.create({fileContainer});
- auto document = documents.document(fileContainer);
-
- documents.setUsedByCurrentEditor(filePath);
-
- ASSERT_TRUE(document.isUsedByCurrentEditor());
-}
-
-TEST_F(Documents, IsNotCurrentEditor)
-{
- documents.create({fileContainer});
- auto document = documents.document(fileContainer);
-
- documents.setUsedByCurrentEditor(headerPath);
-
- ASSERT_FALSE(document.isUsedByCurrentEditor());
-}
-
-TEST_F(Documents, IsNotCurrentEditorAfterBeingCurrent)
-{
- documents.create({fileContainer});
- auto document = documents.document(fileContainer);
- documents.setUsedByCurrentEditor(filePath);
-
- documents.setUsedByCurrentEditor(headerPath);
-
- ASSERT_FALSE(document.isUsedByCurrentEditor());
-}
-
-TEST_F(Documents, IsVisibleEditor)
-{
- documents.create({fileContainer});
- auto document = documents.document(fileContainer);
-
- documents.setVisibleInEditors({filePath});
-
- ASSERT_TRUE(document.isVisibleInEditor());
-}
-
-TEST_F(Documents, IsNotVisibleEditor)
-{
- documents.create({fileContainer});
- auto document = documents.document(fileContainer);
-
- documents.setVisibleInEditors({headerPath});
-
- ASSERT_FALSE(document.isVisibleInEditor());
-}
-
-TEST_F(Documents, IsNotVisibleEditorAfterBeingVisible)
-{
- documents.create({fileContainer});
- auto document = documents.document(fileContainer);
- documents.setVisibleInEditors({filePath});
-
- documents.setVisibleInEditors({headerPath});
-
- ASSERT_FALSE(document.isVisibleInEditor());
-}
-
-// TODO: Remove?
-void Documents::SetUp()
-{
-}
-
-}
diff --git a/tests/unit/unittest/clangdocumentsuspenderresumer-test.cpp b/tests/unit/unittest/clangdocumentsuspenderresumer-test.cpp
deleted file mode 100644
index 569f7d63553..00000000000
--- a/tests/unit/unittest/clangdocumentsuspenderresumer-test.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "dummyclangipcclient.h"
-
-#include <clangclock.h>
-#include <clangdocument.h>
-#include <clangdocumentprocessors.h>
-#include <clangdocuments.h>
-#include <clangdocumentsuspenderresumer.h>
-#include <clangtranslationunits.h>
-#include <unsavedfiles.h>
-#include <utf8string.h>
-
-#include <utils/algorithm.h>
-
-#include <clang-c/Index.h>
-
-using ClangBackEnd::Clock;
-using ClangBackEnd::Document;
-using ClangBackEnd::JobRequest;
-using ClangBackEnd::PreferredTranslationUnit;
-using ClangBackEnd::SuspendResumeJobs;
-using ClangBackEnd::SuspendResumeJobsEntry;
-using ClangBackEnd::TimePoint;
-
-using testing::ContainerEq;
-using testing::ElementsAre;
-using testing::IsEmpty;
-
-namespace ClangBackEnd {
-
-bool operator==(const SuspendResumeJobsEntry &a, const SuspendResumeJobsEntry &b)
-{
- return a.document == b.document
- && a.jobRequestType == b.jobRequestType
- && a.preferredTranslationUnit == b.preferredTranslationUnit;
-}
-
-} // ClangBackEnd
-
-namespace {
-
-class DocumentSuspenderResumer : public ::testing::Test
-{
-protected:
- Document getDocument(const Utf8String &filePath);
- void categorizeDocuments(int hotDocumentsSize);
- SuspendResumeJobs createSuspendResumeJobs(int hotDocumentsSize = -1);
- static void setParsed(Document &document);
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- DummyIpcClient dummyIpcClient;
- ClangBackEnd::DocumentProcessors documentProcessors{documents, unsavedFiles, dummyIpcClient};
-
- const Utf8String filePath1 = Utf8StringLiteral(TESTDATA_DIR"/empty1.cpp");
- const ClangBackEnd::FileContainer fileContainer1{filePath1, Utf8String(), true};
-
- const Utf8String filePath2 = Utf8StringLiteral(TESTDATA_DIR"/empty2.cpp");
- const ClangBackEnd::FileContainer fileContainer2{filePath2, Utf8String(), true};
-
- const Utf8String filePath3 = Utf8StringLiteral(TESTDATA_DIR"/empty3.cpp");
- const ClangBackEnd::FileContainer fileContainer3{filePath3, Utf8String(), true};
-
- std::vector<Document> hotDocuments;
- std::vector<Document> coldDocuments;
-};
-
-TEST_F(DocumentSuspenderResumer, CategorizeNoDocuments)
-{
- categorizeDocuments(99);
-
- ASSERT_THAT(hotDocuments, IsEmpty());
- ASSERT_THAT(coldDocuments, IsEmpty());
-}
-
-TEST_F(DocumentSuspenderResumer, CategorizeSingleDocument)
-{
- documents.create({fileContainer1});
-
- categorizeDocuments(99);
-
- ASSERT_THAT(hotDocuments, ElementsAre(getDocument(filePath1)));
- ASSERT_THAT(coldDocuments, IsEmpty());
-}
-
-TEST_F(DocumentSuspenderResumer, CategorizeKeepsStableOrder)
-{
- documents.create({fileContainer1, fileContainer2});
-
- categorizeDocuments(99);
-
- ASSERT_THAT(hotDocuments, ElementsAre(getDocument(filePath1),
- getDocument(filePath2)));
-}
-
-TEST_F(DocumentSuspenderResumer, CategorizePutsLastVisibleToTopOfHotDocuments)
-{
- documents.create({fileContainer1, fileContainer2});
- documents.setVisibleInEditors({filePath1});
- documents.setVisibleInEditors({filePath2});
-
- categorizeDocuments(99);
-
- ASSERT_THAT(hotDocuments, ElementsAre(getDocument(filePath2),
- getDocument(filePath1)));
-}
-
-TEST_F(DocumentSuspenderResumer, CategorizeWithLessDocumentsThanWeCareFor)
-{
- documents.create({fileContainer1});
-
- categorizeDocuments(2);
-
- ASSERT_THAT(hotDocuments, ElementsAre(getDocument(filePath1)));
- ASSERT_THAT(coldDocuments, IsEmpty());
-}
-
-TEST_F(DocumentSuspenderResumer, CategorizeWithZeroHotDocuments)
-{
- documents.create({fileContainer1});
-
- categorizeDocuments(0);
-
- ASSERT_THAT(hotDocuments, IsEmpty());
- ASSERT_THAT(coldDocuments, ElementsAre(getDocument(filePath1)));
-}
-
-TEST_F(DocumentSuspenderResumer, CategorizeWithMoreVisibleDocumentsThanHotDocuments)
-{
- const TimePoint timePoint = Clock::now();
- Document document1 = documents.create({fileContainer1})[0];
- document1.setIsVisibleInEditor(true, timePoint);
- Document document2 = documents.create({fileContainer2})[0];
- document2.setIsVisibleInEditor(true, timePoint);
-
- categorizeDocuments(1);
-
- ASSERT_THAT(hotDocuments, ElementsAre(getDocument(filePath1), getDocument(filePath2)));
- ASSERT_THAT(coldDocuments, IsEmpty());
-}
-
-TEST_F(DocumentSuspenderResumer, CreateSuspendJobForInvisible)
-{
- Document document = documents.create({fileContainer1})[0];
- document.setIsSuspended(false);
- document.setIsVisibleInEditor(false, Clock::now());
- setParsed(document);
-
- const SuspendResumeJobs expectedJobs = {
- {document, JobRequest::Type::SuspendDocument, PreferredTranslationUnit::RecentlyParsed}
- };
-
- const SuspendResumeJobs jobs = createSuspendResumeJobs(/*hotDocumentsSize=*/ 0);
-
- ASSERT_THAT(jobs, ContainerEq(expectedJobs));
-}
-
-TEST_F(DocumentSuspenderResumer, DoNotCreateSuspendJobForVisible)
-{
- Document document = documents.create({fileContainer1})[0];
- document.setIsSuspended(false);
- document.setIsVisibleInEditor(true, Clock::now());
-
- const SuspendResumeJobs jobs = createSuspendResumeJobs(/*hotDocumentsSize=*/ 0);
-
- ASSERT_THAT(jobs, IsEmpty());
-}
-
-TEST_F(DocumentSuspenderResumer, DoNotCreateSuspendJobForUnparsed)
-{
- Document document = documents.create({fileContainer1})[0];
- document.setIsSuspended(false);
- document.setIsVisibleInEditor(true, Clock::now());
-
- const SuspendResumeJobs jobs = createSuspendResumeJobs(/*hotDocumentsSize=*/ 0);
-
- ASSERT_THAT(jobs, IsEmpty());
-}
-
-TEST_F(DocumentSuspenderResumer, CreateSuspendJobsForDocumentWithSupportiveTranslationUnit)
-{
- Document document = documents.create({fileContainer1})[0];
- document.setIsSuspended(false);
- document.setIsVisibleInEditor(false, Clock::now());
- document.translationUnits().createAndAppend(); // Add supportive translation unit
- setParsed(document);
- const SuspendResumeJobs expectedJobs = {
- {document, JobRequest::Type::SuspendDocument, PreferredTranslationUnit::RecentlyParsed},
- {document, JobRequest::Type::SuspendDocument, PreferredTranslationUnit::PreviouslyParsed},
- };
-
- const SuspendResumeJobs jobs = createSuspendResumeJobs(/*hotDocumentsSize=*/ 0);
-
- ASSERT_THAT(jobs, ContainerEq(expectedJobs));
-}
-
-TEST_F(DocumentSuspenderResumer, CreateResumeJob)
-{
- Document document = documents.create({fileContainer1})[0];
- document.setIsSuspended(true);
- document.setIsVisibleInEditor(true, Clock::now());
- const SuspendResumeJobs expectedJobs = {
- {document, JobRequest::Type::ResumeDocument, PreferredTranslationUnit::RecentlyParsed}
- };
-
- const SuspendResumeJobs jobs = createSuspendResumeJobs();
-
- ASSERT_THAT(jobs, ContainerEq(expectedJobs));
-}
-
-TEST_F(DocumentSuspenderResumer, DoNotCreateResumeJobForInvisible)
-{
- Document document = documents.create({fileContainer1})[0];
- document.setIsSuspended(true);
- document.setIsVisibleInEditor(false, Clock::now());
-
- const SuspendResumeJobs jobs = createSuspendResumeJobs(/*hotDocumentsSize=*/ 0);
-
- ASSERT_THAT(jobs, IsEmpty());
-}
-
-TEST_F(DocumentSuspenderResumer, CreateResumeJobsForDocumentWithSupportiveTranslationUnit)
-{
- Document document = documents.create({fileContainer1})[0];
- document.setIsSuspended(true);
- document.setIsVisibleInEditor(true, Clock::now());
- document.translationUnits().createAndAppend(); // Add supportive translation unit
- const SuspendResumeJobs expectedJobs = {
- {document, JobRequest::Type::ResumeDocument, PreferredTranslationUnit::RecentlyParsed},
- {document, JobRequest::Type::ResumeDocument, PreferredTranslationUnit::PreviouslyParsed},
- };
-
- const SuspendResumeJobs jobs = createSuspendResumeJobs();
-
- ASSERT_THAT(jobs, ContainerEq(expectedJobs));
-}
-
-TEST_F(DocumentSuspenderResumer, CreateSuspendAndResumeJobs)
-{
- Document hotDocument = documents.create({fileContainer1})[0];
- hotDocument.setIsSuspended(true);
- Document coldDocument = documents.create({fileContainer2})[0];
- setParsed(coldDocument);
- coldDocument.setIsSuspended(false);
- documents.setVisibleInEditors({filePath1});
- const SuspendResumeJobs expectedJobs = {
- {coldDocument, JobRequest::Type::SuspendDocument, PreferredTranslationUnit::RecentlyParsed},
- {hotDocument, JobRequest::Type::ResumeDocument, PreferredTranslationUnit::RecentlyParsed},
- };
-
- const SuspendResumeJobs jobs = createSuspendResumeJobs(/*hotDocumentsSize=*/ 1);
-
- ASSERT_THAT(jobs, ContainerEq(expectedJobs));
-}
-
-ClangBackEnd::Document DocumentSuspenderResumer::getDocument(const Utf8String &filePath)
-{
- return documents.document(filePath);
-}
-
-void DocumentSuspenderResumer::categorizeDocuments(int hotDocumentsSize)
-{
- categorizeHotColdDocuments(hotDocumentsSize, documents.documents(), hotDocuments,
- coldDocuments);
-}
-
-ClangBackEnd::SuspendResumeJobs
-DocumentSuspenderResumer::createSuspendResumeJobs(int hotDocumentsSize)
-{
- return ClangBackEnd::createSuspendResumeJobs(documents.documents(), hotDocumentsSize);
-}
-
-void DocumentSuspenderResumer::setParsed(ClangBackEnd::Document &document)
-{
- const Utf8String first = document.translationUnit().id();
- document.translationUnits().updateParseTimePoint(first, Clock::now());
-
- const Utf8String second
- = document.translationUnit(PreferredTranslationUnit::LastUninitialized).id();
- if (second != first)
- document.translationUnits().updateParseTimePoint(second, Clock::now());
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangfixitoperation-test.cpp b/tests/unit/unittest/clangfixitoperation-test.cpp
deleted file mode 100644
index e8fa178014b..00000000000
--- a/tests/unit/unittest/clangfixitoperation-test.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangfixitoperation.h>
-#include <fixitcontainer.h>
-
-#include <utils/changeset.h>
-
-#include <QFile>
-#include <QVector>
-
-using ClangBackEnd::FixItContainer;
-using ClangCodeModel::Internal::ClangFixItOperation;
-
-using ::testing::PrintToString;
-
-namespace {
-
-QString unsavedFileContent(const QString &unsavedFilePath)
-{
- QFile unsavedFileContentFile(unsavedFilePath);
- const bool isOpen = unsavedFileContentFile.open(QFile::ReadOnly | QFile::Text);
- if (!isOpen)
- ADD_FAILURE() << "File with the unsaved content cannot be opened!";
-
- return QString::fromUtf8(unsavedFileContentFile.readAll());
-}
-
-MATCHER_P(MatchText, expectedText,
- std::string(negation ? "hasn't" : "has")
- + " expected text:\n" + PrintToString(expectedText))
-{
- const ::ClangFixItOperation &operation = arg;
- QString resultText = operation.firstRefactoringFileContent_forTestOnly();
-
- if (resultText != expectedText) {
- *result_listener << "\n" << resultText.toUtf8().constData();
- return false;
- }
-
- return true;
-}
-
-class ClangFixItOperation : public ::testing::Test
-{
-protected:
- Utf8String semicolonFilePath{TESTDATA_DIR"/diagnostic_semicolon_fixit.cpp", -1};
- Utf8String compareFilePath{TESTDATA_DIR"/diagnostic_comparison_fixit.cpp", -1};
- Utf8String diagnosticText{Utf8StringLiteral("expected ';' at end of declaration")};
- FixItContainer semicolonFixItContainer{Utf8StringLiteral(";"),
- {{semicolonFilePath, 3u, 13u},
- {semicolonFilePath, 3u, 13u}}};
- QString semicolonErrorFile{semicolonFilePath.toString()};
- QString semicolonExpectedFile{QString::fromUtf8(TESTDATA_DIR"/diagnostic_semicolon_fixit_expected.cpp")};
- QString compareWarningFile{compareFilePath.toString()};
- QString compareExpected1File{QString::fromUtf8(TESTDATA_DIR"/diagnostic_comparison_fixit_expected1.cpp")};
- QString compareExpected2File{QString::fromUtf8(TESTDATA_DIR"/diagnostic_comparison_fixit_expected2.cpp")};
- FixItContainer compareFixItContainer{Utf8StringLiteral("=="),
- {{compareFilePath, 4u, 11u},
- {compareFilePath, 4u, 12u}}};
- FixItContainer assignmentFixItContainerParenLeft{Utf8StringLiteral("("),
- {{compareFilePath, 4u, 9u},
- {compareFilePath, 4u, 9u}}};
- FixItContainer assignmentFixItContainerParenRight{Utf8StringLiteral(")"),
- {{compareFilePath, 4u, 14u},
- {compareFilePath, 4u, 14u}}};
-};
-
-TEST_F(ClangFixItOperation, Description)
-{
- ::ClangFixItOperation operation(diagnosticText, {semicolonFixItContainer});
-
- ASSERT_THAT(operation.description(),
- QStringLiteral("Apply Fix: expected ';' at end of declaration"));
-}
-
-TEST_F(ClangFixItOperation, AppendSemicolon)
-{
- ::ClangFixItOperation operation(diagnosticText, {semicolonFixItContainer});
-
- operation.perform();
-
- ASSERT_THAT(operation, MatchText(unsavedFileContent(semicolonExpectedFile)));
-}
-
-TEST_F(ClangFixItOperation, ComparisonVersusAssignmentChooseComparison)
-{
- ::ClangFixItOperation operation(diagnosticText, {compareFixItContainer});
-
- operation.perform();
-
- ASSERT_THAT(operation, MatchText(unsavedFileContent(compareExpected1File)));
-}
-
-TEST_F(ClangFixItOperation, ComparisonVersusAssignmentChooseParentheses)
-{
- ::ClangFixItOperation operation(diagnosticText,
- {assignmentFixItContainerParenLeft,
- assignmentFixItContainerParenRight});
-
- operation.perform();
-
- ASSERT_THAT(operation, MatchText(unsavedFileContent(compareExpected2File)));
-}
-
-}
diff --git a/tests/unit/unittest/clangfollowsymbol-test.cpp b/tests/unit/unittest/clangfollowsymbol-test.cpp
deleted file mode 100644
index 29c0a702b37..00000000000
--- a/tests/unit/unittest/clangfollowsymbol-test.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "unittest-utility-functions.h"
-
-#include <clangsupport_global.h>
-#include <clangfollowsymboljob.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangtranslationunit.h>
-#include <fixitcontainer.h>
-#include <followsymbolmessage.h>
-#include <sourcelocationcontainer.h>
-#include <sourcerangecontainer.h>
-#include <unsavedfiles.h>
-#include <commandlinearguments.h>
-
-#include <utils/qtcassert.h>
-
-#include <clang-c/Index.h>
-
-using ::testing::Contains;
-using ::testing::Not;
-using ::testing::ContainerEq;
-using ::testing::Eq;
-using ::testing::PrintToString;
-
-using ::ClangBackEnd::SourceLocationContainer;
-using ::ClangBackEnd::Document;
-using ::ClangBackEnd::UnsavedFiles;
-using ::ClangBackEnd::ReferencesResult;
-using ::ClangBackEnd::SourceRangeContainer;
-using ::ClangBackEnd::FollowSymbolResult;
-
-namespace {
-const Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_main.cpp");
-const Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_header.h");
-const Utf8String cursorPath = Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp");
-
-MATCHER_P3(MatchesHeaderSourceRange, line, column, length,
- std::string(negation ? "isn't " : "is ")
- + PrintToString(SourceRangeContainer {
- SourceLocationContainer(headerFilePath, line, column),
- SourceLocationContainer(headerFilePath, line, column + length)
- })
- )
-{
- const SourceRangeContainer expected = {
- SourceLocationContainer(headerFilePath, line, column),
- SourceLocationContainer(headerFilePath, line, column + length)
- };
-
- return arg == expected;
-}
-
-MATCHER_P3(MatchesSourceRange, line, column, length,
- std::string(negation ? "isn't " : "is ")
- + PrintToString(SourceRangeContainer {
- SourceLocationContainer(sourceFilePath, line, column),
- SourceLocationContainer(sourceFilePath, line, column + length)
- })
- )
-{
- const SourceRangeContainer expected = {
- SourceLocationContainer(sourceFilePath, line, column),
- SourceLocationContainer(sourceFilePath, line, column + length)
- };
-
- return arg == expected;
-}
-
-MATCHER_P4(MatchesFileSourceRange, filename, line, column, length,
- std::string(negation ? "isn't " : "is ")
- + PrintToString(SourceRangeContainer {
- SourceLocationContainer(filename, line, column),
- SourceLocationContainer(filename, line, column + length)
- })
- )
-{
- const SourceRangeContainer expected = {
- SourceLocationContainer(filename, line, column),
- SourceLocationContainer(filename, line, column + length)
- };
-
- return arg == expected;
-}
-
-class Data {
-public:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Utf8StringVector compilationArguments{
- UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++14")})};
- Document document = {sourceFilePath, compilationArguments, {}, documents};
- Document headerDocument = {headerFilePath, compilationArguments, {}, documents};
- QVector<Utf8String> deps{sourceFilePath, cursorPath};
-};
-
-class FollowSymbol : public ::testing::Test
-{
-protected:
- FollowSymbolResult followSymbol(uint line, uint column)
- {
- return document.translationUnit().followSymbol(line, column);
- }
-
- FollowSymbolResult followHeaderSymbol(uint line, uint column)
- {
- return headerDocument.translationUnit().followSymbol(line, column);
- }
-
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-private:
- static std::unique_ptr<const Data> data;
- const Document &document{data->document};
- const Document &headerDocument{data->headerDocument};
- const QVector<Utf8String> &deps{data->deps};
-};
-
-// NOTE: some tests are disabled because clang code model does not need to follow symbols
-// to other translation units. When there's infrastructure to test database based follow symbol
-// they should be moved there.
-
-TEST_F(FollowSymbol, CursorOnNamespace)
-{
- const auto namespaceDefinition = followSymbol(27, 1);
-
- ASSERT_THAT(namespaceDefinition, MatchesHeaderSourceRange(28, 11, 6));
-}
-
-TEST_F(FollowSymbol, CursorOnClassReference)
-{
- const auto classDefinition = followSymbol(27, 9);
-
- ASSERT_THAT(classDefinition, MatchesHeaderSourceRange(34, 7, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnClassForwardDeclarationFollowToHeader)
-{
- const auto classDefinition = followHeaderSymbol(32, 7);
-
- ASSERT_THAT(classDefinition, MatchesHeaderSourceRange(34, 7, 3));
-}
-
-TEST_F(FollowSymbol, DISABLED_CursorOnClassForwardDeclarationFollowToCpp)
-{
- const auto classDefinition = followHeaderSymbol(48, 9);
-
- ASSERT_THAT(classDefinition, MatchesSourceRange(54, 7, 8));
-}
-
-TEST_F(FollowSymbol, CursorOnClassDefinition)
-{
- const auto classForwardDeclaration = followHeaderSymbol(34, 7);
-
- ASSERT_THAT(classForwardDeclaration, MatchesHeaderSourceRange(32, 7, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnClassDefinitionInCpp)
-{
- const auto classForwardDeclaration = followSymbol(54, 7);
-
- ASSERT_THAT(classForwardDeclaration, MatchesHeaderSourceRange(48, 7, 8));
-}
-
-TEST_F(FollowSymbol, DISABLED_CursorOnConstructorDeclaration)
-{
- const auto constructorDefinition = followHeaderSymbol(36, 5);
-
- ASSERT_THAT(constructorDefinition, MatchesSourceRange(27, 14, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnConstructorDefinition)
-{
- const auto constructorDeclaration = followSymbol(27, 14);
-
- ASSERT_THAT(constructorDeclaration, MatchesHeaderSourceRange(36, 5, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnMemberReference)
-{
- const auto memberDeclaration = followSymbol(39, 10);
-
- ASSERT_THAT(memberDeclaration, MatchesHeaderSourceRange(38, 18, 6));
-}
-
-TEST_F(FollowSymbol, CursorOnMemberReferenceAnonymousUnion)
-{
- const auto memberDeclaration = followSymbol(91, 20);
-
- ASSERT_THAT(memberDeclaration, MatchesSourceRange(86, 13, 1));
-}
-
-TEST_F(FollowSymbol, CursorOnMemberDeclaration)
-{
- const auto sameMemberDeclaration = followHeaderSymbol(38, 18);
-
- ASSERT_THAT(sameMemberDeclaration, MatchesHeaderSourceRange(38, 18, 6));
-}
-
-TEST_F(FollowSymbol, CursorOnFunctionReference)
-{
- const auto functionDefinition = followSymbol(66, 12);
-
- ASSERT_THAT(functionDefinition, MatchesSourceRange(35, 5, 3));
-}
-
-TEST_F(FollowSymbol, DISABLED_CursorOnMemberFunctionReference)
-{
- const auto memberFunctionDefinition = followSymbol(42, 12);
-
- ASSERT_THAT(memberFunctionDefinition, MatchesSourceRange(49, 21, 3));
-}
-
-TEST_F(FollowSymbol, DISABLED_CursorOnFunctionWithoutDefinitionReference)
-{
- const auto functionDeclaration = followSymbol(43, 5);
-
- ASSERT_THAT(functionDeclaration, MatchesHeaderSourceRange(59, 5, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnFunctionDefinition)
-{
- const auto functionDeclaration = followSymbol(35, 5);
-
- ASSERT_THAT(functionDeclaration, MatchesHeaderSourceRange(52, 5, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnMemberFunctionDefinition)
-{
- const auto memberFunctionDeclaration = followSymbol(49, 21);
-
- ASSERT_THAT(memberFunctionDeclaration, MatchesHeaderSourceRange(43, 9, 3));
-}
-
-TEST_F(FollowSymbol, DISABLED_CursorOnMemberFunctionDeclaration)
-{
- const auto memberFunctionDefinition = followHeaderSymbol(43, 9);
-
- ASSERT_THAT(memberFunctionDefinition, MatchesSourceRange(49, 21, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnInclude)
-{
- const auto startOfIncludeFile = followSymbol(25, 13);
-
- ASSERT_THAT(startOfIncludeFile, MatchesHeaderSourceRange(1, 1, 0));
-}
-
-TEST_F(FollowSymbol, CursorOnLocalVariable)
-{
- const auto variableDeclaration = followSymbol(39, 6);
-
- ASSERT_THAT(variableDeclaration, MatchesSourceRange(36, 9, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnClassAlias)
-{
- const auto aliasDefinition = followSymbol(36, 5);
-
- ASSERT_THAT(aliasDefinition, MatchesSourceRange(33, 7, 3));
-}
-
-TEST_F(FollowSymbol, CursorOnStaticVariable)
-{
- const auto staticVariableDeclaration = followSymbol(40, 27);
-
- ASSERT_THAT(staticVariableDeclaration, MatchesHeaderSourceRange(30, 7, 7));
-}
-
-TEST_F(FollowSymbol, DISABLED_CursorOnFunctionFromOtherClass)
-{
- const auto functionDefinition = followSymbol(62, 39);
-
- ASSERT_THAT(functionDefinition, MatchesFileSourceRange(cursorPath, 104, 22, 8));
-}
-
-TEST_F(FollowSymbol, DISABLED_CursorOnDefineReference)
-{
- const auto functionDefinition = followSymbol(66, 43);
-
- ASSERT_THAT(functionDefinition, MatchesHeaderSourceRange(27, 9, 11));
-}
-
-
-TEST_F(FollowSymbol, CursorInTheMiddleOfNamespace)
-{
- const auto namespaceDefinition = followSymbol(27, 3);
-
- ASSERT_THAT(namespaceDefinition, MatchesHeaderSourceRange(28, 11, 6));
-}
-
-TEST_F(FollowSymbol, CursorAfterNamespace)
-{
- const auto namespaceDefinition = followSymbol(27, 7);
-
- ASSERT_THAT(namespaceDefinition, MatchesFileSourceRange(QString(""), 0, 0, 0));
-}
-
-TEST_F(FollowSymbol, CursorOnOneSymbolOperatorDefinition)
-{
- const auto namespaceDefinition = followSymbol(76, 13);
-
- ASSERT_THAT(namespaceDefinition, MatchesSourceRange(72, 9, 9));
-}
-
-TEST_F(FollowSymbol, CursorOnTwoSymbolOperatorDefinition)
-{
- const auto namespaceDefinition = followSymbol(80, 15);
-
- ASSERT_THAT(namespaceDefinition, MatchesSourceRange(73, 10, 10));
-}
-
-TEST_F(FollowSymbol, CursorOnOneSymbolOperatorDeclaration)
-{
- const auto namespaceDefinition = followSymbol(72, 12);
-
- ASSERT_THAT(namespaceDefinition, MatchesSourceRange(76, 10, 9));
-}
-
-TEST_F(FollowSymbol, CursorOnTwoSymbolOperatorDeclaration)
-{
- const auto namespaceDefinition = followSymbol(73, 12);
-
- ASSERT_THAT(namespaceDefinition, MatchesSourceRange(80, 11, 10));
-}
-
-std::unique_ptr<const Data> FollowSymbol::data;
-
-void FollowSymbol::SetUpTestCase()
-{
- data = std::make_unique<Data>();
- data->document.parse();
- data->headerDocument.parse();
-}
-
-void FollowSymbol::TearDownTestCase()
-{
- data.reset();
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/clangisdiagnosticrelatedtolocation-test.cpp b/tests/unit/unittest/clangisdiagnosticrelatedtolocation-test.cpp
deleted file mode 100644
index 7e008886ad4..00000000000
--- a/tests/unit/unittest/clangisdiagnosticrelatedtolocation-test.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangisdiagnosticrelatedtolocation.h>
-#include <diagnosticcontainer.h>
-
-using ClangBackEnd::DiagnosticContainer;
-using ClangBackEnd::SourceLocationContainer;
-using ClangBackEnd::SourceRangeContainer;
-using ClangCodeModel::Internal::isDiagnosticRelatedToLocation;
-
-namespace {
-
-SourceRangeContainer createRange(uint startLine,
- uint startColumn,
- uint endLine,
- uint endColumn)
-{
- const SourceLocationContainer startLocation(Utf8String(), startLine, startColumn);
- const SourceLocationContainer endLocation(Utf8String(), endLine, endColumn);
-
- return SourceRangeContainer(startLocation, endLocation);
-}
-
-DiagnosticContainer createDiagnosticWithLocation(uint line, uint column)
-{
- const SourceLocationContainer location(Utf8String(), line, column);
-
- return DiagnosticContainer(Utf8String(),
- Utf8String(),
- std::pair<Utf8String, Utf8String>(),
- ClangBackEnd::DiagnosticSeverity::Error,
- location,
- QVector<SourceRangeContainer>(),
- QVector<ClangBackEnd::FixItContainer>(),
- QVector<DiagnosticContainer>());
-}
-
-DiagnosticContainer createDiagnosticWithRange(uint startLine,
- uint startColumn,
- uint endLine,
- uint endColumn)
-{
- const SourceRangeContainer range = createRange(startLine, startColumn, endLine, endColumn);
-
- return DiagnosticContainer(Utf8String(),
- Utf8String(),
- std::pair<Utf8String, Utf8String>(),
- ClangBackEnd::DiagnosticSeverity::Error,
- SourceLocationContainer(),
- {range},
- QVector<ClangBackEnd::FixItContainer>(),
- QVector<DiagnosticContainer>());
-}
-
-class ClangIsDiagnosticRelatedToLocation : public ::testing::Test
-{
-public:
- ClangIsDiagnosticRelatedToLocation() {}
-
-protected:
- const QVector<SourceRangeContainer> emptyRanges;
-};
-
-TEST_F(ClangIsDiagnosticRelatedToLocation, MatchLocation)
-{
- const DiagnosticContainer diagnostic = createDiagnosticWithLocation(5, 5);
-
- ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 5));
-}
-
-TEST_F(ClangIsDiagnosticRelatedToLocation, DoNotMatchLocation)
-{
- const DiagnosticContainer diagnostic = createDiagnosticWithLocation(5, 5);
-
- ASSERT_FALSE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 4));
-}
-
-TEST_F(ClangIsDiagnosticRelatedToLocation, MatchStartRange)
-{
- const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
-
- ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 5));
-}
-
-TEST_F(ClangIsDiagnosticRelatedToLocation, MatchWithinRange)
-{
- const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
-
- ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 7));
-}
-
-TEST_F(ClangIsDiagnosticRelatedToLocation, MatchEndRange)
-{
- const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
-
- ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 10));
-}
-
-TEST_F(ClangIsDiagnosticRelatedToLocation, DoNoMatchBeforeRangeStart)
-{
- const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
-
- ASSERT_FALSE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 4));
-}
-
-TEST_F(ClangIsDiagnosticRelatedToLocation, DoNoMatchAfterRangeEnd)
-{
- const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
-
- ASSERT_FALSE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 11));
-}
-
-TEST_F(ClangIsDiagnosticRelatedToLocation, MatchInAdditionalRange)
-{
- const QVector<SourceRangeContainer> additionalRanges{createRange(5, 5, 5, 10)};
- const DiagnosticContainer diagnostic = createDiagnosticWithLocation(1, 1);
-
- ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, additionalRanges, 5, 7));
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangjobqueue-test.cpp b/tests/unit/unittest/clangjobqueue-test.cpp
deleted file mode 100644
index 8e00dccd2f9..00000000000
--- a/tests/unit/unittest/clangjobqueue-test.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "processevents-utilities.h"
-
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangtranslationunit.h>
-#include <clangtranslationunits.h>
-#include <clangjobs.h>
-#include <filecontainer.h>
-#include <unsavedfiles.h>
-
-#include <clang-c/Index.h>
-
-#include <QTemporaryFile>
-
-using namespace ClangBackEnd;
-
-using testing::IsNull;
-using testing::NotNull;
-using testing::Eq;
-using testing::Gt;
-using testing::Contains;
-using testing::EndsWith;
-using testing::AllOf;
-
-namespace {
-
-class JobQueue : public ::testing::Test
-{
-protected:
- void SetUp() override;
-
- void resetVisibilityAndCurrentEditor();
-
- Utf8String createTranslationUnitForDeletedFile();
-
- JobRequest createJobRequest(const Utf8String &filePath,
- JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit
- = PreferredTranslationUnit::RecentlyParsed) const;
-
- void pretendParsedTranslationUnit();
-
- void updateDocumentRevision();
- void updateUnsavedFiles();
- void removeDocument();
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- ClangBackEnd::Document document;
-
- Utf8String filePath1 = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp");
- Utf8String filePath2 = Utf8StringLiteral(TESTDATA_DIR"/skippedsourceranges.cpp");
-
- ClangBackEnd::JobQueue jobQueue{documents};
-};
-
-TEST_F(JobQueue, AddJob)
-{
- const JobRequest jobRequest = createJobRequest(filePath1,
- JobRequest::Type::UpdateAnnotations);
-
- jobQueue.add(jobRequest);
-
- ASSERT_THAT(jobQueue.queue().size(), Eq(1));
-}
-
-TEST_F(JobQueue, DoNotAddDuplicate)
-{
- const JobRequest request = createJobRequest(filePath1,
- JobRequest::Type::UpdateAnnotations);
- jobQueue.add(request);
-
- const bool added = jobQueue.add(request);
-
- ASSERT_FALSE(added);
-}
-
-TEST_F(JobQueue, DoNotAddDuplicateForWhichAJobIsAlreadyRunning)
-{
- jobQueue.setIsJobRunningForJobRequestHandler([](const JobRequest &) {
- return true;
- });
-
- const bool added = jobQueue.add(createJobRequest(filePath1,
- JobRequest::Type::UpdateAnnotations));
-
- ASSERT_FALSE(added);
-}
-
-TEST_F(JobQueue, DoNotAddForNotExistingDocument)
-{
- jobQueue.setCancelJobRequest([](const JobRequest &) {
- return true;
- });
-
- const bool added = jobQueue.add(createJobRequest(Utf8StringLiteral("notExistingDocument.cpp"),
- JobRequest::Type::UpdateAnnotations));
-
- ASSERT_FALSE(added);
-}
-
-TEST_F(JobQueue, DoNotAddForNotIntactDocument)
-{
- document.setHasParseOrReparseFailed(true);
- const bool added = jobQueue.add(createJobRequest(filePath1,
- JobRequest::Type::UpdateAnnotations));
-
- ASSERT_FALSE(added);
-}
-
-TEST_F(JobQueue, CancelDuringAddForNotIntactDocument)
-{
- document.setHasParseOrReparseFailed(true);
- bool canceled = false;
- jobQueue.setCancelJobRequest([&canceled](const JobRequest &) {
- canceled = true;
- });
-
-
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
-
- ASSERT_TRUE(canceled);
-}
-
-TEST_F(JobQueue, ProcessEmpty)
-{
- jobQueue.processQueue();
-
- ASSERT_THAT(jobQueue.size(), Eq(0));
-}
-
-TEST_F(JobQueue, ProcessSingleJob)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
-
- const JobRequests jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToRun.size(), Eq(1));
- ASSERT_THAT(jobQueue.size(), Eq(0));
-}
-
-TEST_F(JobQueue, ProcessUntilEmpty)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::ParseSupportiveTranslationUnit));
-
- JobRequests jobsToRun;
- ASSERT_THAT(jobQueue.size(), Eq(2));
-
- jobsToRun = jobQueue.processQueue();
- ASSERT_THAT(jobQueue.size(), Eq(1));
- ASSERT_THAT(jobsToRun.size(), Eq(1));
-
- jobsToRun = jobQueue.processQueue();
- ASSERT_THAT(jobQueue.size(), Eq(0));
- ASSERT_THAT(jobsToRun.size(), Eq(1));
-}
-
-TEST_F(JobQueue, RemoveRequestsForClosedDocuments)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- removeDocument();
-
- const JobRequests jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobQueue.size(), Eq(0));
- ASSERT_THAT(jobsToRun.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RemoveRequestsForOudatedUnsavedFiles)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- updateUnsavedFiles();
-
- const JobRequests jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobQueue.size(), Eq(0));
- ASSERT_THAT(jobsToRun.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RemoveRequestsForChangedDocumentRevision)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- updateDocumentRevision();
-
- const JobRequests jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobQueue.size(), Eq(0));
- ASSERT_THAT(jobsToRun.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RemoveRequestsForNotIntactDocuments)
-{
- const Utf8String filePath = createTranslationUnitForDeletedFile();
- jobQueue.add(createJobRequest(filePath, JobRequest::Type::UpdateAnnotations));
-
- const JobRequests jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobQueue.size(), Eq(0));
- ASSERT_THAT(jobsToRun.size(), Eq(0));
-}
-
-TEST_F(JobQueue, CancelRequestsForNotIntactDocuments)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- document.setHasParseOrReparseFailed(true);
- bool canceled = false;
- jobQueue.setCancelJobRequest([&canceled](const JobRequest &) {
- canceled = true;
- });
-
- jobQueue.processQueue();
-
- ASSERT_TRUE(canceled);
-}
-
-TEST_F(JobQueue, PrioritizeCurrentDocumentOverNotCurrent)
-{
- resetVisibilityAndCurrentEditor();
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- jobQueue.add(createJobRequest(filePath2, JobRequest::Type::UpdateAnnotations));
- documents.setUsedByCurrentEditor(filePath2);
-
- jobQueue.prioritizeRequests();
-
- ASSERT_THAT(jobQueue.queue().first().filePath, Eq(filePath2));
-}
-
-TEST_F(JobQueue, PrioritizeVisibleDocumentsOverNotVisible)
-{
- resetVisibilityAndCurrentEditor();
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- jobQueue.add(createJobRequest(filePath2, JobRequest::Type::UpdateAnnotations));
- documents.setVisibleInEditors({filePath2});
-
- jobQueue.prioritizeRequests();
-
- ASSERT_THAT(jobQueue.queue().first().filePath, Eq(filePath2));
-}
-
-TEST_F(JobQueue, PrioritizeCurrentDocumentOverVisible)
-{
- resetVisibilityAndCurrentEditor();
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- jobQueue.add(createJobRequest(filePath2, JobRequest::Type::UpdateAnnotations));
- documents.setVisibleInEditors({filePath1, filePath2});
- documents.setUsedByCurrentEditor(filePath2);
-
- jobQueue.prioritizeRequests();
-
- ASSERT_THAT(jobQueue.queue().first().filePath, Eq(filePath2));
-}
-
-TEST_F(JobQueue, RunNothingForNotCurrentOrVisibleDocument)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- documents.setVisibleInEditors({});
- documents.setUsedByCurrentEditor(Utf8StringLiteral("aNonExistingFilePath"));
-
- const JobRequests jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToRun.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RunOnlyOneJobPerTranslationUnitIfMultipleAreInQueue)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::RequestAnnotations));
-
- const JobRequests jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToRun.size(), Eq(1));
- ASSERT_THAT(jobQueue.size(), Eq(1));
-}
-
-TEST_F(JobQueue, RunJobsForDistinctTranslationUnits)
-{
- const TranslationUnit initialTu = document.translationUnit();
- document.translationUnits().updateParseTimePoint(initialTu.id(), Clock::now());
- const TranslationUnit alternativeTu = document.translationUnits().createAndAppend();
- document.translationUnits().updateParseTimePoint(alternativeTu.id(), Clock::now());
- jobQueue.add(createJobRequest(filePath1,
- JobRequest::Type::UpdateAnnotations,
- PreferredTranslationUnit::RecentlyParsed));
- jobQueue.add(createJobRequest(filePath1,
- JobRequest::Type::UpdateAnnotations,
- PreferredTranslationUnit::PreviouslyParsed));
-
- const JobRequests jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToRun.size(), Eq(2));
- ASSERT_THAT(jobQueue.size(), Eq(0));
-}
-TEST_F(JobQueue, DoNotRunJobForTranslationUnittThatIsBeingProcessed)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- JobRequests jobsToRun = jobQueue.processQueue();
- jobQueue.setIsJobRunningForTranslationUnitHandler([](const Utf8String &) {
- return true;
- });
-
- jobsToRun = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToRun.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RequestUpdateAnnotationsOutdatableByUnsavedFileChange)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- updateUnsavedFiles();
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RequestUpdateAnnotationsOutdatableByDocumentClose)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- removeDocument();
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RequestUpdateAnnotationsOutdatableByNotIntactDocument)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateAnnotations));
- document.setHasParseOrReparseFailed(true);
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RequestCompleteCodeOutdatableByDocumentClose)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::RequestCompletions));
- removeDocument();
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RequestCompleteCodeNotOutdatableByUnsavedFilesChange)
-{
- pretendParsedTranslationUnit();
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::RequestCompletions));
- updateUnsavedFiles();
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(1));
-}
-
-TEST_F(JobQueue, RequestCompleteCodeNotOutdatableByDocumentRevisionChange)
-{
- pretendParsedTranslationUnit();
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::RequestCompletions));
- updateDocumentRevision();
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(1));
-}
-
-TEST_F(JobQueue, RequestCompleteCodeOutdatableByDocumentRevisionChange)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::RequestAnnotations));
- updateDocumentRevision();
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RequestReferencesRunsForCurrentDocumentRevision)
-{
- pretendParsedTranslationUnit();
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::RequestReferences));
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(1));
-}
-
-TEST_F(JobQueue, RequestReferencesOutdatableByDocumentClose)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::RequestReferences));
- removeDocument();
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(0));
- ASSERT_THAT(jobQueue.size(), Eq(0));
-}
-
-TEST_F(JobQueue, RequestReferencesDoesNotRunOnSuspendedDocument)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::RequestReferences));
- document.setIsSuspended(true);
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(0));
- ASSERT_THAT(jobQueue.size(), Eq(1));
-}
-
-TEST_F(JobQueue, ResumeDocumentDoesNotRunOnUnsuspended)
-{
- jobQueue.add(createJobRequest(filePath1, JobRequest::Type::ResumeDocument));
- document.setIsSuspended(false);
-
- const JobRequests jobsToStart = jobQueue.processQueue();
-
- ASSERT_THAT(jobsToStart.size(), Eq(0));
- ASSERT_THAT(jobQueue.size(), Eq(1));
-}
-
-void JobQueue::SetUp()
-{
- const QVector<FileContainer> fileContainer{FileContainer(filePath1),
- FileContainer(filePath2)};
- document = documents.create(fileContainer).front();
- documents.setVisibleInEditors({filePath1});
- documents.setUsedByCurrentEditor(filePath1);
-}
-
-void JobQueue::resetVisibilityAndCurrentEditor()
-{
- documents.setVisibleInEditors({});
- documents.setUsedByCurrentEditor(Utf8String());
-}
-
-Utf8String JobQueue::createTranslationUnitForDeletedFile()
-{
- QTemporaryFile temporaryFile(QLatin1String("XXXXXX.cpp"));
- EXPECT_TRUE(temporaryFile.open());
- const QString temporaryFilePath = Utf8String::fromString(temporaryFile.fileName());
-
- ClangBackEnd::FileContainer fileContainer(temporaryFilePath, Utf8String(), true);
- documents.create({fileContainer});
- auto document = documents.document(fileContainer);
- document.setIsUsedByCurrentEditor(true);
-
- return temporaryFilePath;
-}
-
-JobRequest JobQueue::createJobRequest(
- const Utf8String &filePath,
- JobRequest::Type type,
- PreferredTranslationUnit preferredTranslationUnit) const
-{
- JobRequest jobRequest(type);
- jobRequest.filePath = filePath;
- jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint();
- jobRequest.documentRevision = document.documentRevision();
- jobRequest.preferredTranslationUnit = preferredTranslationUnit;
-
- return jobRequest;
-}
-
-void JobQueue::pretendParsedTranslationUnit()
-{
- document.translationUnits().updateParseTimePoint(document.translationUnit().id(), Clock::now());
-}
-
-void JobQueue::updateDocumentRevision()
-{
- documents.update({FileContainer(filePath1, Utf8String(), true, 1)});
-}
-
-void JobQueue::updateUnsavedFiles()
-{
- unsavedFiles.createOrUpdate({FileContainer(filePath1, Utf8String(), true, 1)});
-}
-
-void JobQueue::removeDocument()
-{
- documents.remove({FileContainer(filePath1)});
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangjobs-test.cpp b/tests/unit/unittest/clangjobs-test.cpp
deleted file mode 100644
index a55a550220a..00000000000
--- a/tests/unit/unittest/clangjobs-test.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "processevents-utilities.h"
-#include "dummyclangipcclient.h"
-
-#include <clangdocument.h>
-#include <clangjobs.h>
-#include <filecontainer.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-
-#include <clang-c/Index.h>
-
-using namespace ClangBackEnd;
-
-using testing::IsNull;
-using testing::NotNull;
-using testing::Eq;
-using testing::Gt;
-using testing::Contains;
-using testing::EndsWith;
-using testing::AllOf;
-
-namespace {
-
-class Jobs : public ::testing::Test
-{
-protected:
- void SetUp() override;
- void TearDown() override;
-
- bool waitUntilAllJobsFinished(int timeOutInMs = 10000) const;
- bool waitUntilJobChainFinished(int timeOutInMs = 10000);
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- ClangBackEnd::Document document;
- DummyIpcClient dummyClientInterface;
-
- Utf8String filePath1 = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp");
-
- ClangBackEnd::Jobs jobs{documents, unsavedFiles, dummyClientInterface};
-};
-
-using JobsSlowTest = Jobs;
-
-TEST_F(Jobs, ProcessEmptyQueue)
-{
- const JobRequests jobsStarted = jobs.process();
-
- ASSERT_THAT(jobsStarted.size(), Eq(0));
- ASSERT_TRUE(jobs.runningJobs().isEmpty());
-}
-
-TEST_F(JobsSlowTest, ProcessQueueWithSingleJob)
-{
- jobs.add(document, JobRequest::Type::UpdateAnnotations);
-
- const JobRequests jobsStarted = jobs.process();
-
- ASSERT_THAT(jobsStarted.size(), Eq(1));
- ASSERT_THAT(jobs.runningJobs().size(), Eq(1));
-}
-
-TEST_F(JobsSlowTest, ProcessQueueUntilEmpty)
-{
- jobs.add(document, JobRequest::Type::UpdateAnnotations);
- jobs.add(document, JobRequest::Type::UpdateAnnotations);
- jobs.add(document, JobRequest::Type::UpdateAnnotations);
-
- jobs.process();
-
- waitUntilJobChainFinished();
-}
-
-TEST_F(JobsSlowTest, IsJobRunning)
-{
- jobs.add(document, JobRequest::Type::UpdateAnnotations);
- jobs.process();
-
- const bool isJobRunning = jobs.isJobRunningForTranslationUnit(document.translationUnit().id());
-
- ASSERT_TRUE(isJobRunning);
-}
-
-void Jobs::SetUp()
-{
- const QVector<FileContainer> fileContainer{FileContainer(filePath1)};
- document = documents.create(fileContainer).front();
- documents.setVisibleInEditors({filePath1});
- documents.setUsedByCurrentEditor(filePath1);
-}
-
-void Jobs::TearDown()
-{
- ASSERT_TRUE(waitUntilAllJobsFinished()); // QFuture/QFutureWatcher is implemented with events
-}
-
-bool Jobs::waitUntilAllJobsFinished(int timeOutInMs) const
-{
- const auto noJobsRunningAnymore = [this](){ return jobs.runningJobs().isEmpty(); };
-
- return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
-}
-
-bool Jobs::waitUntilJobChainFinished(int timeOutInMs)
-{
- const auto noJobsRunningAnymore = [this]() {
- return jobs.runningJobs().isEmpty() && jobs.queue().isEmpty();
- };
-
- return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangparsesupportivetranslationunitjob-test.cpp b/tests/unit/unittest/clangparsesupportivetranslationunitjob-test.cpp
deleted file mode 100644
index dbb4554a41c..00000000000
--- a/tests/unit/unittest/clangparsesupportivetranslationunitjob-test.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangasyncjob-base.h"
-
-#include <clangparsesupportivetranslationunitjob.h>
-#include <clangtranslationunits.h>
-
-using namespace ClangBackEnd;
-
-using testing::Eq;
-using testing::Not;
-using testing::_;
-
-namespace {
-
-class ParseSupportiveTranslationUnitJob : public ClangAsyncJobTest
-{
-protected:
- void SetUp() override { BaseSetUp(JobRequest::Type::ParseSupportiveTranslationUnit, job); }
-
- TimePoint parseTimePointOfDocument();
-
-protected:
- ClangBackEnd::ParseSupportiveTranslationUnitJob job;
-};
-
-using ParseSupportiveTranslationUnitJobSlowTest = ParseSupportiveTranslationUnitJob;
-
-TEST_F(ParseSupportiveTranslationUnitJob, PrepareAsyncRun)
-{
- job.setContext(jobContext);
-
- ASSERT_TRUE(job.prepareAsyncRun());
-}
-
-TEST_F(ParseSupportiveTranslationUnitJobSlowTest, RunAsync)
-{
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangreferencescollector-test.cpp b/tests/unit/unittest/clangreferencescollector-test.cpp
deleted file mode 100644
index bb04d8c8d1d..00000000000
--- a/tests/unit/unittest/clangreferencescollector-test.cpp
+++ /dev/null
@@ -1,506 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "unittest-utility-functions.h"
-
-#include <clangsupport_global.h>
-#include <clangreferencescollector.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangtranslationunit.h>
-#include <fixitcontainer.h>
-#include <sourcelocationcontainer.h>
-#include <sourcerangecontainer.h>
-#include <unsavedfiles.h>
-
-#include <utils/qtcassert.h>
-
-#include <clang-c/Index.h>
-
-using ::testing::Contains;
-using ::testing::Not;
-using ::testing::ContainerEq;
-using ::testing::Eq;
-
-using ::ClangBackEnd::SourceLocationContainer;
-using ::ClangBackEnd::Document;
-using ::ClangBackEnd::UnsavedFiles;
-using ::ClangBackEnd::ReferencesResult;
-using ::ClangBackEnd::SourceRangeContainer;
-
-using References = QVector<SourceRangeContainer>;
-
-namespace {
-
-struct Data {
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Document document{Utf8StringLiteral(TESTDATA_DIR"/references.cpp"),
- UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++14")}),
- {},
- documents};
-};
-
-class ReferencesCollector : public ::testing::Test
-{
-protected:
- ReferencesResult getReferences(uint line, uint column)
- {
- return document.translationUnit().references(line, column);
- }
-
- SourceLocationContainer createSourceLocation(uint line, uint column) const
- {
- return SourceLocationContainer(document.filePath(), line, column);
- }
-
- SourceRangeContainer createSourceRange(uint line, uint column, uint length) const
- {
- return SourceRangeContainer {
- createSourceLocation(line, column),
- createSourceLocation(line, column + length)
- };
- }
-
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-protected:
- static std::unique_ptr<const Data> data;
- const Document &document{data->document};
-};
-
-// This test is not strictly needed as the plugin is supposed to put the cursor
-// on the identifier start.
-TEST_F(ReferencesCollector, CursorNotOnIdentifier)
-{
- const ReferencesResult expected { false, {}, };
-
- const ReferencesResult actual = getReferences(3, 5);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, LocalVariableWithSingleUse)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(3, 9, 3)},
- };
-
- const ReferencesResult actual = getReferences(3, 9);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, LocalVariableWithTwoUses)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(10, 9, 3),
- createSourceRange(11, 12, 3)},
- };
-
- const ReferencesResult actual = getReferences(10, 9);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, ClassName)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(16, 7, 3),
- createSourceRange(19, 5, 3)},
- };
-
- const ReferencesResult actual = getReferences(16, 7);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, Namespace)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(24, 11, 1),
- createSourceRange(25, 11, 1),
- createSourceRange(26, 1, 1)},
- };
-
- const ReferencesResult actual = getReferences(24, 11);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, ClassNameDeclaredWithUsing)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(30, 21, 3),
- createSourceRange(31, 10, 3)},
- };
-
- const ReferencesResult actual = getReferences(30, 21);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, ClassNameForwardDeclared)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(35, 7, 3),
- createSourceRange(36, 14, 3)},
- };
-
- const ReferencesResult actual = getReferences(35, 7);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, ClassNameAndNewExpression)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(40, 7, 3),
- createSourceRange(43, 9, 3)},
- };
-
- const ReferencesResult actual = getReferences(40, 7);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, InstantiatedTemplateObject)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(52, 19, 3),
- createSourceRange(53, 5, 3)},
- };
-
- const ReferencesResult actual = getReferences(52, 19);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, VariableInTemplate)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(62, 13, 3),
- createSourceRange(63, 11, 3)},
- };
-
- const ReferencesResult actual = getReferences(62, 13);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, MemberInTemplate)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(64, 16, 3),
- createSourceRange(67, 7, 3)},
- };
-
- const ReferencesResult actual = getReferences(67, 7);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, TemplateType)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(58, 19, 1),
- createSourceRange(60, 5, 1),
- createSourceRange(67, 5, 1)},
- };
-
- const ReferencesResult actual = getReferences(58, 19);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, MemberAccessIntoTemplateParameter)
-{
- const ReferencesResult expected { false, {}, };
-
- const ReferencesResult actual = getReferences(76, 9);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, ConstructorAsType)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(81, 8, 3),
- createSourceRange(82, 5, 3),
- createSourceRange(83, 6, 3)},
- };
-
- const ReferencesResult actual = getReferences(82, 5);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, OverloadsFreeStanding)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(88, 5, 3),
- createSourceRange(89, 5, 3)},
- };
-
- const ReferencesResult actual = getReferences(88, 5);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, OverloadsMemberFunctions)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(94, 9, 3),
- createSourceRange(95, 9, 3)},
- };
-
- const ReferencesResult actual = getReferences(94, 9);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, FunctionAndTemplateFunction)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(100, 26, 3),
- createSourceRange(101, 5, 3)},
- };
-
- const ReferencesResult actual = getReferences(100, 26);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, FunctionAndTemplateFunctionAsMember)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(106, 30, 3),
- createSourceRange(107, 9, 3)},
- };
-
- const ReferencesResult actual = getReferences(106, 30);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, EnumType)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(112, 6, 2),
- createSourceRange(113, 8, 2)},
- };
-
- const ReferencesResult actual = getReferences(112, 6);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, LambdaCapturedObject)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(122, 15, 3),
- createSourceRange(122, 33, 3)},
- };
-
- const ReferencesResult actual = getReferences(122, 15);
-
- ASSERT_THAT(actual, expected);
-}
-
-//// Disabled because it looks like the lambda initializer is not yet exposed by libclang.
-TEST_F(ReferencesCollector, DISABLED_LambdaCaptureInitializer)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(121, 19, 3),
- createSourceRange(122, 19, 3)},
- };
-
- const ReferencesResult actual = getReferences(122, 19);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, TemplateSpecialization)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(127, 25, 3),
- createSourceRange(128, 25, 3),
- createSourceRange(129, 18, 3)},
- };
-
- const ReferencesResult actual = getReferences(127, 25);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, TemplateDependentName)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(133, 34, 3)},
- };
-
- const ReferencesResult actual = getReferences(133, 34);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, FunctionCallAndDefinition)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(140, 5, 3),
- createSourceRange(142, 25, 3)},
- };
-
- const ReferencesResult actual = getReferences(140, 5);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, ObjectLikeMacro)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(147, 9, 3),
- createSourceRange(150, 12, 3)},
- };
-
- const ReferencesResult actual = getReferences(147, 9);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, FunctionLikeMacro)
-{
- const ReferencesResult expected {
- false,
- {createSourceRange(155, 9, 3),
- createSourceRange(158, 12, 3)},
- };
-
- const ReferencesResult actual = getReferences(155, 9);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, ArgumentToFunctionLikeMacro)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(156, 27, 3),
- createSourceRange(158, 16, 3)},
- };
-
- const ReferencesResult actual = getReferences(156, 27);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, OverloadedBraceOperatorArgument)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(171, 7, 1),
- createSourceRange(172, 7, 1),
- createSourceRange(172, 12, 1),
- createSourceRange(173, 7, 1),
- createSourceRange(173, 10, 1)},
- };
-
- const ReferencesResult actual = getReferences(172, 7);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, OverloadedParenOperatorSecondArgument)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(171, 7, 1),
- createSourceRange(172, 7, 1),
- createSourceRange(172, 12, 1),
- createSourceRange(173, 7, 1),
- createSourceRange(173, 10, 1)},
- };
-
- const ReferencesResult actual = getReferences(173, 10);
-
- ASSERT_THAT(actual, expected);
-}
-
-TEST_F(ReferencesCollector, OverloadedOperatorsArgumentsFromOutside)
-{
- const ReferencesResult expected {
- true,
- {createSourceRange(171, 7, 1),
- createSourceRange(172, 7, 1),
- createSourceRange(172, 12, 1),
- createSourceRange(173, 7, 1),
- createSourceRange(173, 10, 1)},
- };
-
- const ReferencesResult actual = getReferences(171, 7);
-
- ASSERT_THAT(actual, expected);
-}
-
-std::unique_ptr<const Data> ReferencesCollector::data;
-
-void ReferencesCollector::SetUpTestCase()
-{
- data = std::make_unique<const Data>();
-
- data->document.parse();
-}
-
-void ReferencesCollector::TearDownTestCase()
-{
- data.reset();
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/clangrequestannotationsjob-test.cpp b/tests/unit/unittest/clangrequestannotationsjob-test.cpp
deleted file mode 100644
index 9fb80d2ff01..00000000000
--- a/tests/unit/unittest/clangrequestannotationsjob-test.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangasyncjob-base.h"
-
-#include <clangrequestannotationsjob.h>
-
-using namespace ClangBackEnd;
-
-using testing::_;
-
-namespace {
-
-class RequestAnnotationsJob : public ClangAsyncJobTest
-{
-protected:
- void SetUp() override { BaseSetUp(JobRequest::Type::RequestAnnotations, job); }
-
-protected:
- ClangBackEnd::RequestAnnotationsJob job;
-};
-
-TEST_F(RequestAnnotationsJob, PrepareAsyncRun)
-{
- job.setContext(jobContext);
-
- ASSERT_TRUE(job.prepareAsyncRun());
-}
-
-TEST_F(RequestAnnotationsJob, RunAsync)
-{
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(RequestAnnotationsJob, SendAnnotations)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, annotations(_)).Times(1);
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(RequestAnnotationsJob, DontSendAnnotationsIfDocumentWasClosed)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, annotations(_)).Times(0);
-
- job.runAsync();
- documents.remove({FileContainer{filePath}});
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangrequestreferencesjob-test.cpp b/tests/unit/unittest/clangrequestreferencesjob-test.cpp
deleted file mode 100644
index 83d7d97a258..00000000000
--- a/tests/unit/unittest/clangrequestreferencesjob-test.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangasyncjob-base.h"
-
-#include <clangrequestreferencesjob.h>
-
-using namespace ClangBackEnd;
-
-using testing::_;
-using testing::Eq;
-using testing::Property;
-
-namespace {
-
-class RequestReferencesJob : public ClangAsyncJobTest
-{
-protected:
- void SetUp() override { BaseSetUp(JobRequest::Type::RequestReferences, job); }
-
-protected:
- ClangBackEnd::RequestReferencesJob job;
-};
-
-TEST_F(RequestReferencesJob, PrepareAsyncRun)
-{
- job.setContext(jobContext);
-
- ASSERT_TRUE(job.prepareAsyncRun());
-}
-
-TEST_F(RequestReferencesJob, RunAsync)
-{
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(RequestReferencesJob, SendReferences)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, references(_)).Times(1);
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(RequestReferencesJob, ForwardTicketNumber)
-{
- jobRequest.ticketNumber = static_cast<quint64>(99);
- jobContextWithMockClient = JobContext(jobRequest, &documents, &unsavedFiles, &mockIpcClient);
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient,
- references(Field(&ReferencesMessage::ticketNumber, Eq(jobRequest.ticketNumber))))
- .Times(1);
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(RequestReferencesJob, DontSendReferencesIfDocumentWasClosed)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, references(_)).Times(0);
-
- job.runAsync();
- documents.remove({FileContainer{filePath}});
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(RequestReferencesJob, DontSendReferencesIfDocumentRevisionChanged)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, references(_)).Times(0);
-
- job.runAsync();
- documents.update({FileContainer(filePath, Utf8String(), true, 99)});
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangresumedocumentjob-test.cpp b/tests/unit/unittest/clangresumedocumentjob-test.cpp
deleted file mode 100644
index 9582b0c0d1f..00000000000
--- a/tests/unit/unittest/clangresumedocumentjob-test.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangasyncjob-base.h"
-
-#include <clangresumedocumentjob.h>
-
-using namespace ClangBackEnd;
-
-using testing::_;
-
-namespace {
-
-class ResumeDocumentJob : public ClangAsyncJobTest
-{
-protected:
- void SetUp() override { BaseSetUp(JobRequest::Type::ResumeDocument, job); }
- void suspendDocument()
- {
- document.parse();
- document.translationUnit().suspend();
- document.setIsSuspended(true);
- }
-
-protected:
- ClangBackEnd::ResumeDocumentJob job;
-};
-
-TEST_F(ResumeDocumentJob, PrepareAsyncRun)
-{
- job.setContext(jobContext);
-
- ASSERT_TRUE(job.prepareAsyncRun());
-}
-
-TEST_F(ResumeDocumentJob, RunAsync)
-{
- suspendDocument();
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(ResumeDocumentJob, DocumentIsResumedAfterRun)
-{
- suspendDocument();
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
- ASSERT_TRUE(waitUntilJobFinished(job));
-
- ASSERT_FALSE(document.isSuspended());
-}
-
-TEST_F(ResumeDocumentJob, SendsAnnotationsAfterResume)
-{
- suspendDocument();
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, annotations(_)).Times(1);
-
- job.runAsync();
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangstring-test.cpp b/tests/unit/unittest/clangstring-test.cpp
deleted file mode 100644
index 8e30da93e24..00000000000
--- a/tests/unit/unittest/clangstring-test.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangstring.h>
-
-#include <utf8string.h>
-
-#include <clang-c/CXString.h>
-#include <clang-c/Index.h>
-
-namespace {
-
-using ::testing::StrEq;
-using ::testing::Eq;
-
-using ClangBackEnd::ClangString;
-
-TEST(ClangString, ConvertToUtf8String)
-{
- const CXString cxString = { "text", 0};
-
- ASSERT_THAT(Utf8String(ClangString(cxString)), Utf8StringLiteral("text"));
-}
-
-TEST(ClangString, ConvertNullStringToUtf8String)
-{
- const CXString cxString = { 0, 0};
-
- ASSERT_THAT(Utf8String(ClangString(cxString)), Utf8String());
-}
-
-TEST(ClangString, MoveContructor)
-{
- ClangString text(CXString{ "text", 0});
-
- const ClangString text2 = std::move(text);
-
- ASSERT_TRUE(text.isNull());
- ASSERT_FALSE(text2.isNull());
-}
-
-TEST(ClangString, MoveAssigment)
-{
- ClangString text(CXString{ "text", 0});
-
- ClangString text2 = std::move(text);
- text = std::move(text2);
-
- ASSERT_TRUE(text2.isNull());
- ASSERT_FALSE(text.isNull());
-}
-
-TEST(ClangString, MoveSelfAssigment)
-{
- ClangString text(CXString{ "text", 0});
-
- text = std::move(text);
-
- ASSERT_FALSE(text.isNull());
-}
-
-TEST(ClangString, SpellingAsCString)
-{
- ClangString text(CXString{"text", 0});
-
- ASSERT_THAT(text.cString(), StrEq("text"));
-}
-
-TEST(ClangString, EqualBetweenClangStrings)
-{
- ClangString text(CXString{"text", 0});
- ClangString text2(CXString{"text", 0});
-
- bool textIsEqual = text == text2;
-
- ASSERT_TRUE(textIsEqual);
-}
-
-TEST(ClangString, NotEqualBetweenClangStrings)
-{
- ClangString text(CXString{"text", 0});
- ClangString text2(CXString{"text ", 0});
-
- bool textIsNotEqual = text != text2;
-
- ASSERT_TRUE(textIsNotEqual);
-}
-
-TEST(ClangString, EqualClangStringAndCString)
-{
- ClangString text(CXString{"text", 0});
-
- bool textIsEqual = text == "text";
-
- ASSERT_TRUE(textIsEqual);
-}
-
-TEST(ClangString, NotEqualClangStringAndCString)
-{
- ClangString text(CXString{"text", 0});
-
- bool textIsNotEqual = text != "text ";
-
- ASSERT_TRUE(textIsNotEqual);
-}
-
-TEST(ClangString, EqualCStringAndClangString)
-{
- ClangString text(CXString{"text", 0});
-
- bool textIsEqual = "text" == text;
-
- ASSERT_TRUE(textIsEqual);
-}
-
-TEST(ClangString, NotEqualCStringAndClangString)
-{
- ClangString text(CXString{"text", 0});
-
- bool textIsNotEqual = "text " != text;
-
- ASSERT_TRUE(textIsNotEqual);
-}
-
-TEST(ClangString, EqualClangStringPointerAndCString)
-{
- ClangString text(CXString{"text", 0});
- const char *cString = "text";
-
- bool textIsEqual = cString == text;
-
- ASSERT_TRUE(textIsEqual);
-}
-
-TEST(ClangString, NotEqualClangStringPointerAndCString)
-{
- ClangString text(CXString{"text", 0});
- const char *cString = "text ";
-
- bool textIsNotEqual = cString != text;
-
- ASSERT_TRUE(textIsNotEqual);
-}
-
-TEST(ClangString, EqualCStringAndClangStringPointer)
-{
- ClangString text(CXString{"text", 0});
- const char *cString = "text";
-
- bool textIsEqual = text == cString;
-
- ASSERT_TRUE(textIsEqual);
-}
-
-TEST(ClangString, NotEqualCStringAndClangStringPointer)
-{
- ClangString text(CXString{"text", 0});
- const char *cString = "text ";
-
- bool textIsNotEqual = text != cString;
-
- ASSERT_TRUE(textIsNotEqual);
-}
-
-TEST(ClangString, NullStringHasNoContent)
-{
- ClangString text(CXString{nullptr, 0});
-
- bool hasContent = text.hasContent();
-
- ASSERT_FALSE(hasContent);
-}
-
-TEST(ClangString, EmptyStringHasNoContent)
-{
- ClangString text(CXString{"", 0});
-
- bool hasContent = text.hasContent();
-
- ASSERT_FALSE(hasContent);
-}
-
-TEST(ClangString, StringHasNoContent)
-{
- ClangString text(CXString{"text", 0});
-
- bool hasContent = text.hasContent();
-
- ASSERT_TRUE(hasContent);
-}
-
-}
diff --git a/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp b/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp
deleted file mode 100644
index c62b803a71c..00000000000
--- a/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "dummyclangipcclient.h"
-#include "processevents-utilities.h"
-
-#include <clangbackend_global.h>
-#include <clangdocuments.h>
-#include <clangexceptions.h>
-#include <clangsupportivetranslationunitinitializer.h>
-#include <clangtranslationunit.h>
-#include <clangtranslationunits.h>
-#include <utf8string.h>
-
-#include <clang-c/Index.h>
-
-#include <memory>
-
-using namespace ClangBackEnd;
-
-using testing::Eq;
-
-namespace {
-
-class SupportiveTranslationUnitInitializer : public ::testing::Test
-{
-protected:
- void SetUp() override;
- void parse();
- Jobs::RunningJob createRunningJob(JobRequest::Type type) const;
-
- void assertNoJobIsRunningAndEmptyQueue();
- void assertSingleJobRunningAndEmptyQueue();
-
- bool waitUntilJobChainFinished(int timeOutInMs = 10000) const;
-
-protected:
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")};
-
- UnsavedFiles unsavedFiles;
- const QVector<FileContainer> fileContainer{FileContainer(filePath)};
- Documents documents{unsavedFiles};
- Document document{documents.create(fileContainer).front()};
- DummyIpcClient dummyClientInterface;
-
- Jobs jobs{documents, unsavedFiles, dummyClientInterface};
-
- ClangBackEnd::SupportiveTranslationUnitInitializer initializer{document, jobs};
-};
-
-using SupportiveTranslationUnitInitializerSlowTest = SupportiveTranslationUnitInitializer;
-
-TEST_F(SupportiveTranslationUnitInitializer, HasInitiallyNotInitializedState)
-{
- ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::NotInitialized));
-}
-
-TEST_F(SupportiveTranslationUnitInitializer, StartInitializingAbortsIfDocumentIsClosed)
-{
- documents.remove({FileContainer(filePath)});
-
- initializer.startInitializing();
-
- assertNoJobIsRunningAndEmptyQueue();
- ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted));
-}
-
-TEST_F(SupportiveTranslationUnitInitializerSlowTest, StartInitializingAddsTranslationUnit)
-{
- initializer.startInitializing();
-
- ASSERT_THAT(document.translationUnits().size(), Eq(2));
- ASSERT_FALSE(document.translationUnits().areAllTranslationUnitsParsed());
-}
-
-TEST_F(SupportiveTranslationUnitInitializerSlowTest, StartInitializingStartsJob)
-{
- initializer.startInitializing();
-
- assertSingleJobRunningAndEmptyQueue();
- const Jobs::RunningJob runningJob = jobs.runningJobs().first();
- ASSERT_THAT(runningJob.jobRequest.type, JobRequest::Type::ParseSupportiveTranslationUnit);
-}
-
-TEST_F(SupportiveTranslationUnitInitializerSlowTest, Abort)
-{
- initializer.startInitializing();
- assertSingleJobRunningAndEmptyQueue();
-
- initializer.abort();
-
- ASSERT_THAT(initializer.state(),
- Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted));
- ASSERT_FALSE(jobs.jobFinishedCallback());
-}
-
-TEST_F(SupportiveTranslationUnitInitializer, CheckIfParseJobFinishedAbortsIfDocumentIsClosed)
-{
- documents.remove({FileContainer(filePath)});
- initializer.setState(ClangBackEnd::SupportiveTranslationUnitInitializer::State::WaitingForParseJob);
- const Jobs::RunningJob runningJob = createRunningJob(JobRequest::Type::ParseSupportiveTranslationUnit);
-
- initializer.checkIfParseJobFinished(runningJob);
-
- assertNoJobIsRunningAndEmptyQueue();
- ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted));
-}
-
-TEST_F(SupportiveTranslationUnitInitializerSlowTest, CheckIfParseJobFinishedStartsJob)
-{
- parse();
- initializer.setState(ClangBackEnd::SupportiveTranslationUnitInitializer::State::WaitingForParseJob);
- Jobs::RunningJob runningJob = createRunningJob(JobRequest::Type::ParseSupportiveTranslationUnit);
-
- initializer.checkIfParseJobFinished(runningJob);
- jobs.process();
-
- ASSERT_THAT(jobs.runningJobs(), IsEmpty());
- ASSERT_THAT(jobs.queue(), IsEmpty());
-}
-
-TEST_F(SupportiveTranslationUnitInitializerSlowTest, FullRun)
-{
- parse();
- initializer.startInitializing();
-
- waitUntilJobChainFinished();
- ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Initialized));
-}
-
-void SupportiveTranslationUnitInitializer::SetUp()
-{
- documents.setVisibleInEditors({filePath});
- documents.setUsedByCurrentEditor(filePath);
-
- const auto isDocumentClosed = [this](const Utf8String &filePath) {
- return !documents.hasDocument(filePath);
- };
- initializer.setIsDocumentClosedChecker(isDocumentClosed);
-}
-
-void SupportiveTranslationUnitInitializer::parse()
-{
- document.parse();
-}
-
-Jobs::RunningJob SupportiveTranslationUnitInitializer::createRunningJob(JobRequest::Type type) const
-{
- const JobRequest jobRequest = jobs.createJobRequest(document,
- type,
- PreferredTranslationUnit::LastUninitialized);
- return Jobs::RunningJob{jobRequest, Utf8String(), QFuture<void>()};
-}
-
-void SupportiveTranslationUnitInitializer::assertNoJobIsRunningAndEmptyQueue()
-{
- ASSERT_TRUE(jobs.runningJobs().isEmpty());
- ASSERT_TRUE(jobs.queue().isEmpty());
-}
-
-void SupportiveTranslationUnitInitializer::assertSingleJobRunningAndEmptyQueue()
-{
- ASSERT_THAT(jobs.runningJobs().size(), Eq(1));
- ASSERT_TRUE(jobs.queue().isEmpty());
-}
-
-bool SupportiveTranslationUnitInitializer::waitUntilJobChainFinished(int timeOutInMs) const
-{
- const auto noJobsRunningAnymore = [this]() {
- return jobs.runningJobs().isEmpty() && jobs.queue().isEmpty();
- };
-
- return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/clangsuspenddocumentjob-test.cpp b/tests/unit/unittest/clangsuspenddocumentjob-test.cpp
deleted file mode 100644
index b9f92f3beb5..00000000000
--- a/tests/unit/unittest/clangsuspenddocumentjob-test.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangasyncjob-base.h"
-
-#include <clangsuspenddocumentjob.h>
-
-using namespace ClangBackEnd;
-
-namespace {
-
-class SuspendDocumentJob : public ClangAsyncJobTest
-{
-protected:
- void SetUp() override { BaseSetUp(JobRequest::Type::SuspendDocument, job); }
-
-protected:
- ClangBackEnd::SuspendDocumentJob job;
-};
-
-TEST_F(SuspendDocumentJob, PrepareAsyncRun)
-{
- job.setContext(jobContext);
-
- ASSERT_TRUE(job.prepareAsyncRun());
-}
-
-TEST_F(SuspendDocumentJob, RunAsync)
-{
- document.parse();
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(SuspendDocumentJob, DocumentIsSuspendedAfterRun)
-{
- document.parse();
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
- ASSERT_TRUE(waitUntilJobFinished(job));
-
- ASSERT_TRUE(document.isSuspended());
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clangtooltipinfo-test.cpp b/tests/unit/unittest/clangtooltipinfo-test.cpp
deleted file mode 100644
index bb1fbb8a441..00000000000
--- a/tests/unit/unittest/clangtooltipinfo-test.cpp
+++ /dev/null
@@ -1,696 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "rundocumentparse-utility.h"
-
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangsupport_global.h>
-#include <clangtooltipinfocollector.h>
-#include <clangtranslationunit.h>
-#include <fixitcontainer.h>
-#include <sourcelocationcontainer.h>
-#include <sourcerangecontainer.h>
-#include <unsavedfiles.h>
-
-#include <utils/qtcassert.h>
-
-#include <clang-c/Index.h>
-
-using ::ClangBackEnd::SourceLocationContainer;
-using ::ClangBackEnd::Document;
-using ::ClangBackEnd::UnsavedFiles;
-using ::ClangBackEnd::ToolTipInfo;
-using ::ClangBackEnd::SourceRangeContainer;
-
-namespace {
-
-#define CHECK_MEMBER(actual, expected, memberName) \
- if (actual.memberName != expected.memberName) { \
- *result_listener << #memberName " is " + PrintToString(actual.memberName) \
- << " and not " + PrintToString(expected.memberName); \
- return false; \
- }
-
-MATCHER_P(IsToolTip, expected, std::string(negation ? "isn't" : "is") + PrintToString(expected))
-{
- CHECK_MEMBER(arg, expected, text);
- CHECK_MEMBER(arg, expected, briefComment);
-
- CHECK_MEMBER(arg, expected, qdocIdCandidates);
- CHECK_MEMBER(arg, expected, qdocMark);
- CHECK_MEMBER(arg, expected, qdocCategory);
-
- CHECK_MEMBER(arg, expected, sizeInBytes);
-
- return true;
-}
-
-MATCHER_P(IsQdocToolTip, expected, std::string(negation ? "isn't" : "is") + PrintToString(expected))
-{
- CHECK_MEMBER(arg, expected, qdocIdCandidates);
- CHECK_MEMBER(arg, expected, qdocMark);
- CHECK_MEMBER(arg, expected, qdocCategory);
-
- return true;
-}
-
-#undef CHECK_MEMBER
-
-struct Data {
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Document document{Utf8StringLiteral(TESTDATA_DIR "/tooltipinfo.cpp"),
- {Utf8StringLiteral("-std=c++14")},
- {},
- documents};
- UnitTest::RunDocumentParse _1{document};
-};
-
-class ToolTipInfo : public ::testing::Test
-{
-protected:
- ::ToolTipInfo tooltip(uint line, uint column)
- {
- return d->document.translationUnit().tooltip(d->unsavedFiles,
- Utf8StringLiteral("UTF-8"),
- line,
- column);
- }
-
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-private:
- static std::unique_ptr<Data> d;
-};
-
-TEST_F(ToolTipInfo, LocalVariableInt)
-{
- const ::ToolTipInfo actual = tooltip(3, 5);
-
- ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("int"))));
-}
-
-TEST_F(ToolTipInfo, LocalVariableConstInt)
-{
- ASSERT_THAT(tooltip(211, 19), IsToolTip(::ToolTipInfo(Utf8StringLiteral("const int"))));
-}
-
-TEST_F(ToolTipInfo, FileScopeVariableConstInt)
-{
- ASSERT_THAT(tooltip(206, 11), IsToolTip(::ToolTipInfo(Utf8StringLiteral("const int"))));
-}
-
-TEST_F(ToolTipInfo, LocalVariablePointerToConstInt)
-{
- const ::ToolTipInfo actual = tooltip(4, 5);
-
- ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("const int *"))));
-}
-
-TEST_F(ToolTipInfo, LocalParameterVariableConstRefCustomType)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("const Foo &"));
- expected.qdocIdCandidates = {Utf8StringLiteral("Foo")};
- expected.qdocMark = Utf8StringLiteral("Foo");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(12, 12);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, LocalNonParameterVariableConstRefCustomType)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("const Foo"));
- expected.qdocIdCandidates = {Utf8StringLiteral("Foo")};
- expected.qdocMark = Utf8StringLiteral("Foo");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(14, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, MemberVariable)
-{
- const ::ToolTipInfo actual = tooltip(12, 16);
-
- ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("int"))));
-}
-
-TEST_F(ToolTipInfo, MemberFunctionCall_QualifiedName)
-{
- const ::ToolTipInfo actual = tooltip(21, 9);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("int Bar::mem()"));
-}
-
-// ChangeLog: Show extra specifiers. For functions e.g.: virtual, inline, explicit, const, volatile
-TEST_F(ToolTipInfo, MemberFunctionCall_ExtraSpecifiers)
-{
- const ::ToolTipInfo actual = tooltip(22, 9);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("virtual int Bar::virtualConstMem() const"));
-}
-
-TEST_F(ToolTipInfo, MemberFunctionCall_qdocIdCandidates)
-{
- const ::ToolTipInfo actual = tooltip(21, 9);
-
- ASSERT_THAT(actual.qdocIdCandidates, ElementsAre(Utf8StringLiteral("Bar::mem"),
- Utf8StringLiteral("mem")));
-}
-
-TEST_F(ToolTipInfo, MemberFunctionCall_qdocMark_FIXLIBCLANG_CHECKED)
-{
- const ::ToolTipInfo actual = tooltip(21, 9);
-
- ASSERT_THAT(actual.qdocMark, Utf8StringLiteral("mem()"));
-}
-
-// TODO: Check what is really needed for qdoc before implementing this one.
-TEST_F(ToolTipInfo, DISABLED_MemberFunctionCall_qdocMark_extraSpecifiers)
-{
- const ::ToolTipInfo actual = tooltip(22, 9);
-
- ASSERT_THAT(actual.qdocMark, Utf8StringLiteral("virtualConstMem() const"));
-}
-
-TEST_F(ToolTipInfo, MemberFunctionCall_qdocCategory)
-{
- const ::ToolTipInfo actual = tooltip(21, 9);
-
- ASSERT_THAT(actual.qdocCategory, ::ToolTipInfo::Function);
-}
-
-// TODO: Show the template parameter type, too: "template<typename T>...)"
-TEST_F(ToolTipInfo, TemplateFunctionCall)
-{
- const ::ToolTipInfo actual = tooltip(30, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("template<> void t<Foo>(int foo)"));
-}
-
-TEST_F(ToolTipInfo, TemplateFunctionCall_qdocIdCandidates)
-{
- const ::ToolTipInfo actual = tooltip(30, 5);
-
- ASSERT_THAT(actual.qdocIdCandidates, ElementsAre(Utf8StringLiteral("t")));
-}
-
-TEST_F(ToolTipInfo, TemplateFunctionCall_qdocMark_FIXLIBCLANG_CHECKED)
-{
- const ::ToolTipInfo actual = tooltip(30, 5);
-
- ASSERT_THAT(actual.qdocMark, Utf8StringLiteral("t(int)"));
-}
-
-TEST_F(ToolTipInfo, TemplateFunctionCall_qdocCategory)
-{
- const ::ToolTipInfo actual = tooltip(30, 5);
-
- ASSERT_THAT(actual.qdocCategory, ::ToolTipInfo::Function);
-}
-
-TEST_F(ToolTipInfo, BriefComment)
-{
- const ::ToolTipInfo actual = tooltip(41, 5);
-
- ASSERT_THAT(actual.briefComment, Utf8StringLiteral("This is a crazy function."));
-}
-
-TEST_F(ToolTipInfo, Enum)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("EnumType"));
- expected.qdocIdCandidates = {Utf8StringLiteral("EnumType")};
- expected.qdocMark = Utf8StringLiteral("EnumType");
- expected.qdocCategory = ::ToolTipInfo::Enum;
-
- const ::ToolTipInfo actual = tooltip(49, 12);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, Enumerator)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("6"));
- expected.qdocIdCandidates = {Utf8StringLiteral("Custom")};
- expected.qdocMark = Utf8StringLiteral("EnumType");
- expected.qdocCategory = ::ToolTipInfo::Enum;
-
- const ::ToolTipInfo actual = tooltip(49, 22);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, TemplateTypeFromParameter)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("const Baz<int> &"));
- expected.qdocIdCandidates = {Utf8StringLiteral("Baz")};
- expected.qdocMark = Utf8StringLiteral("Baz");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(55, 25);
-
- ASSERT_THAT(actual, IsQdocToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, TemplateTypeFromNonParameter)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("Baz<int>"));
- expected.qdocIdCandidates = {Utf8StringLiteral("Baz")};
- expected.qdocMark = Utf8StringLiteral("Baz");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(56, 19);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, IncludeDirective)
-{
- ::ToolTipInfo expected(
- QDir::toNativeSeparators(Utf8StringLiteral(TESTDATA_DIR "/tooltipinfo.h")));
- expected.qdocIdCandidates = {Utf8StringLiteral("tooltipinfo.h")};
- expected.qdocMark = Utf8StringLiteral("tooltipinfo.h");
- expected.qdocCategory = ::ToolTipInfo::Brief;
-
- const ::ToolTipInfo actual = tooltip(59, 11);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, MacroUse_WithMacroFromSameFile)
-{
- const ::ToolTipInfo actual = tooltip(66, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("#define MACRO_FROM_MAINFILE(x) x + 3"));
-}
-
-TEST_F(ToolTipInfo, MacroUse_WithMacroFromHeader)
-{
- const ::ToolTipInfo actual = tooltip(67, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("#define MACRO_FROM_HEADER(x) x + \\\n x + \\\n x"));
-}
-
-TEST_F(ToolTipInfo, MacroUse_qdoc)
-{
- ::ToolTipInfo expected;
- expected.qdocIdCandidates = {Utf8StringLiteral("MACRO_FROM_MAINFILE")};
- expected.qdocMark = Utf8StringLiteral("MACRO_FROM_MAINFILE");
- expected.qdocCategory = ::ToolTipInfo::Macro;
-
- const ::ToolTipInfo actual = tooltip(66, 5);
-
- ASSERT_THAT(actual, IsQdocToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDirectiveIsQualified)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
- expected.qdocIdCandidates = {Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")};
- expected.qdocMark = Utf8StringLiteral("Muu");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(77, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDirectiveOfAliasIsResolvedAndQualified)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
- expected.qdocIdCandidates = {Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")};
- expected.qdocMark = Utf8StringLiteral("Muu");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(82, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDeclarationIsQualified)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
- expected.qdocIdCandidates = {Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")};
- expected.qdocMark = Utf8StringLiteral("Muu");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(87, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, SizeForClassDefinition)
-{
- const ::ToolTipInfo actual = tooltip(92, 8);
-
- ASSERT_THAT(actual.sizeInBytes, Utf8StringLiteral("2"));
-}
-
-TEST_F(ToolTipInfo, SizeForMemberField)
-{
- const ::ToolTipInfo actual = tooltip(95, 10);
-
- ASSERT_THAT(actual.sizeInBytes, Utf8StringLiteral("1"));
-}
-
-TEST_F(ToolTipInfo, SizeForEnum)
-{
- const ::ToolTipInfo actual = tooltip(97, 12);
-
- ASSERT_THAT(actual.sizeInBytes, Utf8StringLiteral("4"));
-}
-
-TEST_F(ToolTipInfo, SizeForUnion)
-{
- const ::ToolTipInfo actual = tooltip(98, 7);
-
- ASSERT_THAT(actual.sizeInBytes, Utf8StringLiteral("1"));
-}
-
-TEST_F(ToolTipInfo, constexprValue)
-{
- ASSERT_THAT(tooltip(204, 12).value.toInt(), 4);
- ASSERT_THAT(tooltip(204, 27).value.toInt(), CINDEX_VERSION_MINOR > 59 ? 3 : 4);
- ASSERT_THAT(tooltip(204, 30).value.toInt(), 4);
- ASSERT_THAT(tooltip(204, 32).value.toInt(), CINDEX_VERSION_MINOR > 59 ? 1 : 4);
-}
-
-TEST_F(ToolTipInfo, Namespace)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("X"));
- expected.qdocIdCandidates = {Utf8StringLiteral("X")};
- expected.qdocMark = Utf8StringLiteral("X");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(106, 11);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, NamespaceQualified)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("X::Y"));
- expected.qdocIdCandidates = {Utf8StringLiteral("X::Y"), Utf8StringLiteral("Y")};
- expected.qdocMark = Utf8StringLiteral("Y");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(107, 11);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-// TODO: Show unresolved and resolved name, for F1 try both.
-TEST_F(ToolTipInfo, TypeName_ResolveTypeDef)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("Ptr<Nuu>"));
- expected.qdocIdCandidates = {Utf8StringLiteral("PtrFromTypeDef")};
- expected.qdocMark = Utf8StringLiteral("PtrFromTypeDef");
- expected.qdocCategory = ::ToolTipInfo::Typedef;
-
- const ::ToolTipInfo actual = tooltip(122, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-// TODO: Show unresolved and resolved name, for F1 try both.
-TEST_F(ToolTipInfo, TypeName_ResolveAlias)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("Ptr<Nuu>"));
- expected.qdocIdCandidates = {Utf8StringLiteral("PtrFromTypeAlias")};
- expected.qdocMark = Utf8StringLiteral("PtrFromTypeAlias");
- expected.qdocCategory = ::ToolTipInfo::Typedef;
-
- const ::ToolTipInfo actual = tooltip(123, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-// The referenced cursor is a CXCursor_TypeAliasTemplateDecl, its type is invalid
-// and so probably clang_getTypedefDeclUnderlyingType() does not return anything useful.
-// TODO: Fix the cursor's type or add new API in libclang for querying the template type alias.
-TEST_F(ToolTipInfo, DISABLED_TypeName_ResolveTemplateTypeAlias)
-{
- const ::ToolTipInfo actual = tooltip(124, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("Ptr<Nuu>"));
-}
-
-TEST_F(ToolTipInfo, TypeName_ResolveTemplateTypeAlias_qdoc)
-{
- ::ToolTipInfo expected;
- expected.qdocIdCandidates = {Utf8StringLiteral("PtrFromTemplateTypeAlias")};
- expected.qdocMark = Utf8StringLiteral("PtrFromTemplateTypeAlias");
- expected.qdocCategory = ::ToolTipInfo::Typedef;
-
- const ::ToolTipInfo actual = tooltip(124, 5);
-
- ASSERT_THAT(actual, IsQdocToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, TemplateClassReference)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("Zii<T>"));
- expected.qdocIdCandidates = {Utf8StringLiteral("Zii")};
- expected.qdocMark = Utf8StringLiteral("Zii");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(134, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, TemplateClassQualified)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("U::Yii<T>"));
- expected.qdocIdCandidates = {Utf8StringLiteral("U::Yii"), Utf8StringLiteral("Yii")};
- expected.qdocMark = Utf8StringLiteral("Yii");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(135, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, ResolveNamespaceAliasForType)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("A::X"));
- expected.qdocIdCandidates = {Utf8StringLiteral("A::X"), Utf8StringLiteral("X")};
- expected.qdocMark = Utf8StringLiteral("X");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(144, 8);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-// TODO: Show unresolved and resolved name, for F1 try both.
-TEST_F(ToolTipInfo, ResolveNamespaceAlias)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("A"));
- expected.qdocIdCandidates = {Utf8StringLiteral("B")};
- expected.qdocMark = Utf8StringLiteral("B");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(144, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, QualificationForTemplateClassInClassInNamespace)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("N::Outer::Inner<int>"));
- expected.qdocIdCandidates = {Utf8StringLiteral("N::Outer::Inner"),
- Utf8StringLiteral("Outer::Inner"),
- Utf8StringLiteral("Inner")};
- expected.qdocMark = Utf8StringLiteral("Inner");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
- expected.sizeInBytes = Utf8StringLiteral("1");
-
- const ::ToolTipInfo actual = tooltip(153, 16);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, Function)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("void f()"));
- expected.qdocIdCandidates = {Utf8StringLiteral("f")};
- expected.qdocMark = Utf8StringLiteral("f()");
- expected.qdocCategory = ::ToolTipInfo::Function;
-
- const ::ToolTipInfo actual = tooltip(165, 5);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-TEST_F(ToolTipInfo, Function_QualifiedName)
-{
- const ::ToolTipInfo actual = tooltip(166, 8);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("void R::f()"));
-}
-
-TEST_F(ToolTipInfo, Function_qdocIdCandidatesAreQualified)
-{
- const ::ToolTipInfo actual = tooltip(166, 8);
-
- ASSERT_THAT(actual.qdocIdCandidates, ElementsAre(Utf8StringLiteral("R::f"),
- Utf8StringLiteral("f")));
-}
-
-TEST_F(ToolTipInfo, Function_HasParameterName)
-{
- const ::ToolTipInfo actual = tooltip(167, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("void f(int param)"));
-}
-
-// TODO: Implement with CXPrintingPolicy
-TEST_F(ToolTipInfo, DISABLED_Function_HasDefaultArgument)
-{
- const ::ToolTipInfo actual = tooltip(168, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("void z(int = 1)"));
-}
-
-TEST_F(ToolTipInfo, Function_qdocMarkHasNoParameterName)
-{
- const ::ToolTipInfo actual = tooltip(167, 5);
-
- ASSERT_THAT(actual.qdocMark, Utf8StringLiteral("f(int)"));
-}
-
-TEST_F(ToolTipInfo, Function_qdocMarkHasNoDefaultArgument)
-{
- const ::ToolTipInfo actual = tooltip(168, 5);
-
- ASSERT_THAT(actual.qdocMark, Utf8StringLiteral("z(int)"));
-}
-
-TEST_F(ToolTipInfo, AutoTypeBuiltin)
-{
- const ::ToolTipInfo actual = tooltip(176, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("int"));
-}
-
-TEST_F(ToolTipInfo, PointerToPointerToClass)
-{
- ::ToolTipInfo expected(Utf8StringLiteral("Nuu **"));
- expected.qdocIdCandidates = {Utf8StringLiteral("Nuu")};
- expected.qdocMark = Utf8StringLiteral("Nuu");
- expected.qdocCategory = ::ToolTipInfo::ClassOrNamespace;
-
- const ::ToolTipInfo actual = tooltip(200, 12);
-
- ASSERT_THAT(actual, IsToolTip(expected));
-}
-
-// TODO: Test for qdoc entries, too.
-TEST_F(ToolTipInfo, AutoTypeEnum)
-{
- const ::ToolTipInfo actual = tooltip(177, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("EnumType"));
-}
-
-// TODO: Test for qdoc entries, too.
-TEST_F(ToolTipInfo, AutoTypeClassType)
-{
- const ::ToolTipInfo actual = tooltip(178, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("Bar"));
-}
-
-// TODO: Test for qdoc entries, too.
-// TODO: Deduced template arguments work, too?!
-TEST_F(ToolTipInfo, AutoTypeClassTemplateType)
-{
- const ::ToolTipInfo actual = tooltip(179, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("Zii<int>"));
-}
-
-TEST_F(ToolTipInfo, Function_DefaultConstructor)
-{
- const ::ToolTipInfo actual = tooltip(193, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("inline constexpr Con::Con() noexcept"));
-}
-
-TEST_F(ToolTipInfo, Function_ExplicitDefaultConstructor)
-{
- const ::ToolTipInfo actual = tooltip(194, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("ExplicitCon::ExplicitCon() noexcept = default"));
-}
-
-TEST_F(ToolTipInfo, Function_CustomConstructor)
-{
- const ::ToolTipInfo actual = tooltip(195, 5);
-
- ASSERT_THAT(actual.text, Utf8StringLiteral("ExplicitCon::ExplicitCon(int m)"));
-}
-
-// Overloads are problematic for the help system since the data base has not
-// enough information about them. At least for constructors we can improve
-// the situation a bit - provide a help system query that:
-// 1) will not lead to the replacement of the constructor signature as
-// clang sees it with the wrong overload documentation
-// (signature + main help sentence). That's the qdocCategory=Unknown
-// part.
-// 2) finds the documentation for the class instead of the overload,
-// so F1 will go to the class documentation.
-TEST_F(ToolTipInfo, Function_ConstructorQDoc)
-{
- ::ToolTipInfo expected;
- expected.qdocIdCandidates = {Utf8StringLiteral("Con")};
- expected.qdocMark = Utf8StringLiteral("Con");
- expected.qdocCategory = ::ToolTipInfo::Unknown;
-
- const ::ToolTipInfo actual = tooltip(193, 5);
-
- ASSERT_THAT(actual, IsQdocToolTip(expected));
-}
-
-std::unique_ptr<Data> ToolTipInfo::d;
-
-void ToolTipInfo::SetUpTestCase()
-{
- d.reset(new Data);
-}
-
-void ToolTipInfo::TearDownTestCase()
-{
- d.reset();
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/clangtranslationunit-test.cpp b/tests/unit/unittest/clangtranslationunit-test.cpp
deleted file mode 100644
index 52fd447e988..00000000000
--- a/tests/unit/unittest/clangtranslationunit-test.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangtranslationunit.h>
-#include <clangtranslationunitupdater.h>
-#include <diagnosticcontainer.h>
-#include <utf8string.h>
-
-#include <clang-c/Index.h>
-
-using ClangBackEnd::DiagnosticContainer;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::TranslationUnitUpdateInput;
-using ClangBackEnd::TranslationUnitUpdateResult;
-
-using testing::ContainerEq;
-using testing::Eq;
-
-namespace {
-
-class TranslationUnit : public ::testing::Test
-{
-protected:
- void SetUp() override;
- void TearDown() override;
-
- void parse();
- void reparse();
-
- DiagnosticContainer createDiagnostic(const QString &text,
- ClangBackEnd::DiagnosticSeverity severity,
- int line,
- int column,
- const QString &filePath) const;
- QVector<DiagnosticContainer> diagnosticsFromMainFile() const;
- QVector<DiagnosticContainer> errorDiagnosticsFromHeaders() const;
-
-protected:
- Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/diagnostic_erroneous_source.cpp");
- Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/diagnostic_erroneous_header.h");
- CXIndex cxIndex = nullptr;
- CXTranslationUnit cxTranslationUnit = nullptr;
- ::TranslationUnit translationUnit{Utf8String(), sourceFilePath, cxIndex, cxTranslationUnit};
-
- DiagnosticContainer extractedFirstHeaderErrorDiagnostic;
- QVector<DiagnosticContainer> extractedMainFileDiagnostics;
-};
-
-using TranslationUnitSlowTest = TranslationUnit;
-
-TEST_F(TranslationUnitSlowTest, HasExpectedMainFileDiagnostics)
-{
- translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
- extractedMainFileDiagnostics);
-
- ASSERT_THAT(extractedMainFileDiagnostics, ContainerEq(diagnosticsFromMainFile()));
-}
-
-TEST_F(TranslationUnitSlowTest, HasExpectedMainFileDiagnosticsAfterReparse)
-{
- reparse();
-
- translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
- extractedMainFileDiagnostics);
-
- ASSERT_THAT(extractedMainFileDiagnostics, ContainerEq(diagnosticsFromMainFile()));
-}
-
-TEST_F(TranslationUnitSlowTest, HasErrorDiagnosticsInHeaders)
-{
- translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
- extractedMainFileDiagnostics);
-
- ASSERT_THAT(extractedFirstHeaderErrorDiagnostic,
- Eq(errorDiagnosticsFromHeaders().first()));
-}
-
-TEST_F(TranslationUnitSlowTest, HasErrorDiagnosticsInHeadersAfterReparse)
-{
- reparse();
-
- translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
- extractedMainFileDiagnostics);
-
- ASSERT_THAT(extractedFirstHeaderErrorDiagnostic,
- Eq(errorDiagnosticsFromHeaders().first()));
-}
-
-void TranslationUnit::SetUp()
-{
- parse();
-}
-
-void TranslationUnit::TearDown()
-{
- clang_disposeTranslationUnit(cxTranslationUnit);
- clang_disposeIndex(cxIndex);
-}
-
-void TranslationUnit::parse()
-{
- TranslationUnitUpdateInput parseInput;
- parseInput.filePath = sourceFilePath;
- parseInput.parseNeeded = true;
- const TranslationUnitUpdateResult parseResult = translationUnit.update(parseInput);
- ASSERT_TRUE(parseResult.hasParsed());
-}
-
-void TranslationUnit::reparse()
-{
- TranslationUnitUpdateInput parseInput;
- parseInput.filePath = sourceFilePath;
- parseInput.reparseNeeded = true;
- const TranslationUnitUpdateResult parseResult = translationUnit.update(parseInput);
- ASSERT_TRUE(parseResult.hasReparsed());
-}
-
-DiagnosticContainer TranslationUnit::createDiagnostic(const QString &text,
- ClangBackEnd::DiagnosticSeverity severity,
- int line,
- int column,
- const QString &filePath) const
-{
- return DiagnosticContainer(
- text,
- Utf8StringLiteral(""),
- {},
- severity,
- {filePath, line, column},
- {},
- {},
- {}
- );
-}
-
-QVector<ClangBackEnd::DiagnosticContainer> TranslationUnit::diagnosticsFromMainFile() const
-{
- return {
- createDiagnostic(
- QStringLiteral("warning: enumeration value 'Three' not handled in switch"),
- ClangBackEnd::DiagnosticSeverity::Warning,
- 7,
- 13,
- sourceFilePath),
- createDiagnostic(
- QStringLiteral("error: void function 'g' should not return a value"),
- ClangBackEnd::DiagnosticSeverity::Error,
- 15,
- 5,
- sourceFilePath),
- createDiagnostic(
- QStringLiteral("warning: using the result of an assignment as a condition without parentheses"),
- ClangBackEnd::DiagnosticSeverity::Warning,
- 21,
- 11,
- sourceFilePath),
- };
-}
-
-QVector<ClangBackEnd::DiagnosticContainer> TranslationUnit::errorDiagnosticsFromHeaders() const
-{
- return {
- createDiagnostic(
- QStringLiteral("error: C++ requires a type specifier for all declarations"),
- ClangBackEnd::DiagnosticSeverity::Error,
- 11,
- 1,
- headerFilePath),
- };
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/clangtranslationunits-test.cpp b/tests/unit/unittest/clangtranslationunits-test.cpp
deleted file mode 100644
index acdf5704819..00000000000
--- a/tests/unit/unittest/clangtranslationunits-test.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangbackend_global.h>
-#include <clangexceptions.h>
-#include <clangtranslationunit.h>
-#include <clangtranslationunits.h>
-#include <utf8string.h>
-
-#include <clang-c/Index.h>
-
-using ClangBackEnd::Clock;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::TranslationUnits;
-using ClangBackEnd::TranslationUnitDoesNotExist;
-using ClangBackEnd::PreferredTranslationUnit;
-
-using testing::Eq;
-
-namespace {
-
-class TranslationUnits : public ::testing::Test
-{
-protected:
- Utf8String someFilePath = Utf8StringLiteral("someFilePath");
- ClangBackEnd::TranslationUnits translationUnits{someFilePath};
-};
-
-TEST_F(TranslationUnits, CreatedUnitIsNull)
-{
- TranslationUnit translationUnit = translationUnits.createAndAppend();
-
- ASSERT_TRUE(translationUnit.isNull());
-}
-
-TEST_F(TranslationUnits, GetThrowsForNotExisting)
-{
- ASSERT_THROW(translationUnits.get(), TranslationUnitDoesNotExist);
-}
-
-TEST_F(TranslationUnits, GetForSingleTranslationUnit)
-{
- const TranslationUnit created = translationUnits.createAndAppend();
-
- const TranslationUnit queried = translationUnits.get();
-
- ASSERT_THAT(queried.id(), Eq(created.id()));
-}
-
-TEST_F(TranslationUnits, GetFirstForMultipleTranslationUnits)
-{
- const TranslationUnit created1 = translationUnits.createAndAppend();
- translationUnits.createAndAppend();
-
- const TranslationUnit queried = translationUnits.get();
-
- ASSERT_THAT(queried.id(), Eq(created1.id()));
-}
-
-TEST_F(TranslationUnits, GetFirstForMultipleTranslationUnitsAndOnlyFirstParsed)
-{
- const TranslationUnit created1 = translationUnits.createAndAppend();
- translationUnits.updateParseTimePoint(created1.id(), Clock::now());
- translationUnits.createAndAppend();
-
- const TranslationUnit queried = translationUnits.get();
-
- ASSERT_THAT(queried.id(), Eq(created1.id()));
-}
-
-TEST_F(TranslationUnits, GetFirstForMultipleTranslationUnitsAndOnlySecondParsed)
-{
- const TranslationUnit created1 = translationUnits.createAndAppend();
- const TranslationUnit created2 = translationUnits.createAndAppend();
- translationUnits.updateParseTimePoint(created2.id(), Clock::now());
-
- const TranslationUnit queried = translationUnits.get();
-
- ASSERT_THAT(queried.id(), Eq(created1.id()));
-}
-
-TEST_F(TranslationUnits, GetLastUnitializedForMultipleTranslationUnits)
-{
- const TranslationUnit created1 = translationUnits.createAndAppend();
- translationUnits.updateParseTimePoint(created1.id(), Clock::now());
- const TranslationUnit created2 = translationUnits.createAndAppend();
-
- const TranslationUnit queried = translationUnits.get(PreferredTranslationUnit::LastUninitialized);
-
- ASSERT_THAT(queried.id(), Eq(created2.id()));
-}
-
-TEST_F(TranslationUnits, GetRecentForMultipleTranslationUnits)
-{
- const TranslationUnit created1 = translationUnits.createAndAppend();
- translationUnits.updateParseTimePoint(created1.id(), Clock::now());
- const TranslationUnit created2 = translationUnits.createAndAppend();
- translationUnits.updateParseTimePoint(created2.id(), Clock::now());
-
- const TranslationUnit queried = translationUnits.get(PreferredTranslationUnit::RecentlyParsed);
-
- ASSERT_THAT(queried.id(), Eq(created2.id()));
-}
-
-TEST_F(TranslationUnits, GetPreviousForMultipleTranslationUnits)
-{
- const TranslationUnit created1 = translationUnits.createAndAppend();
- translationUnits.updateParseTimePoint(created1.id(), Clock::now());
- const TranslationUnit created2 = translationUnits.createAndAppend();
- translationUnits.updateParseTimePoint(created2.id(), Clock::now());
-
- const TranslationUnit queried = translationUnits.get(PreferredTranslationUnit::PreviouslyParsed);
-
- ASSERT_THAT(queried.id(), Eq(created1.id()));
-}
-
-TEST_F(TranslationUnits, UpdateThrowsForNotExisting)
-{
- ClangBackEnd::TranslationUnits otherTranslationUnits{someFilePath};
- const TranslationUnit translationUnit = otherTranslationUnits.createAndAppend();
-
- ASSERT_THROW(translationUnits.updateParseTimePoint(translationUnit.id(), Clock::now()),
- TranslationUnitDoesNotExist);
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/clangupdateannotationsjob-test.cpp b/tests/unit/unittest/clangupdateannotationsjob-test.cpp
deleted file mode 100644
index 79623619c1c..00000000000
--- a/tests/unit/unittest/clangupdateannotationsjob-test.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangasyncjob-base.h"
-
-#include <clangupdateannotationsjob.h>
-
-using namespace ClangBackEnd;
-
-using testing::Not;
-using testing::_;
-
-namespace {
-
-class UpdateAnnotationsJob : public ClangAsyncJobTest
-{
-protected:
- void SetUp() override { BaseSetUp(JobRequest::Type::UpdateAnnotations, job); }
-
-protected:
- ClangBackEnd::UpdateAnnotationsJob job;
-};
-
-using UpdateAnnotationsJobSlowTest = UpdateAnnotationsJob;
-
-TEST_F(UpdateAnnotationsJob, PrepareAsyncRun)
-{
- job.setContext(jobContext);
-
- ASSERT_TRUE(job.prepareAsyncRun());
-}
-
-TEST_F(UpdateAnnotationsJobSlowTest, RunAsync)
-{
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(UpdateAnnotationsJobSlowTest, SendAnnotations)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, annotations(_)).Times(1);
-
- job.runAsync();
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(UpdateAnnotationsJobSlowTest, DontSendAnnotationsIfDocumentWasClosed)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, annotations(_)).Times(0);
-
- job.runAsync();
- documents.remove({FileContainer{filePath}});
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(UpdateAnnotationsJobSlowTest, DontSendAnnotationsIfDocumentRevisionChanged)
-{
- job.setContext(jobContextWithMockClient);
- job.prepareAsyncRun();
- EXPECT_CALL(mockIpcClient, annotations(_)).Times(0);
-
- job.runAsync();
- documents.update({FileContainer(filePath, Utf8String(), true, 99)});
-
- ASSERT_TRUE(waitUntilJobFinished(job));
-}
-
-TEST_F(UpdateAnnotationsJobSlowTest, UpdatesDependentFilePaths)
-{
- const QSet<Utf8String> dependentOnFilesBefore = document.dependedFilePaths();
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
- ASSERT_TRUE(waitUntilJobFinished(job));
-
- ASSERT_THAT(dependentOnFilesBefore, Not(document.dependedFilePaths()));
-}
-
-TEST_F(UpdateAnnotationsJobSlowTest, UpdatesUnresolvedFilePaths)
-{
- const QSet<Utf8String> unresolvedBefore = document.unresolvedFilePaths();
- job.setContext(jobContext);
- job.prepareAsyncRun();
-
- job.runAsync();
- ASSERT_TRUE(waitUntilJobFinished(job));
-
- ASSERT_THAT(unresolvedBefore, Not(document.unresolvedFilePaths()));
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/clientserverinprocess-test.cpp b/tests/unit/unittest/clientserverinprocess-test.cpp
deleted file mode 100644
index 2fe5f89bac9..00000000000
--- a/tests/unit/unittest/clientserverinprocess-test.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "mockclangcodemodelclient.h"
-#include "mockclangcodemodelserver.h"
-
-#include <clangcodemodelclientproxy.h>
-#include <clangcodemodelserverproxy.h>
-
-#include <clangcodemodelservermessages.h>
-
-#include <readmessageblock.h>
-#include <writemessageblock.h>
-
-#include <QBuffer>
-#include <QString>
-#include <QVariant>
-
-#include <vector>
-
-using namespace ClangBackEnd;
-
-namespace {
-
-using ::testing::Args;
-using ::testing::Property;
-using ::testing::Eq;
-
-class ClientServerInProcess : public ::testing::Test
-{
-protected:
- ClientServerInProcess();
-
- void SetUp();
- void TearDown();
-
-
- void scheduleServerMessages();
- void scheduleClientMessages();
-
-protected:
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_function.cpp")};
- ClangBackEnd::FileContainer fileContainer{filePath,
- Utf8StringLiteral("unsaved content"),
- true,
- 1};
- QBuffer buffer;
- MockClangCodeModelClient mockClangCodeModelClient;
- MockClangCodeModelServer mockClangCodeModelServer;
-
- ClangBackEnd::ClangCodeModelServerProxy serverProxy;
- ClangBackEnd::ClangCodeModelClientProxy clientProxy;
-};
-
-TEST_F(ClientServerInProcess, SendEndMessage)
-{
- EXPECT_CALL(mockClangCodeModelServer, end())
- .Times(1);
-
- serverProxy.end();
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendAliveMessage)
-{
- EXPECT_CALL(mockClangCodeModelClient, alive())
- .Times(1);
-
- clientProxy.alive();
- scheduleClientMessages();
-}
-
-TEST_F(ClientServerInProcess, SendDocumentsOpenedMessage)
-{
- ClangBackEnd::DocumentsOpenedMessage message({fileContainer}, filePath, {filePath});
-
- EXPECT_CALL(mockClangCodeModelServer, documentsOpened(message))
- .Times(1);
-
- serverProxy.documentsOpened(message);
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendUpdateTranslationUnitsForEditorMessage)
-{
- ClangBackEnd::DocumentsChangedMessage message({fileContainer});
-
- EXPECT_CALL(mockClangCodeModelServer, documentsChanged(message))
- .Times(1);
-
- serverProxy.documentsChanged(message);
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendDocumentsClosedMessage)
-{
- ClangBackEnd::DocumentsClosedMessage message({fileContainer});
-
- EXPECT_CALL(mockClangCodeModelServer, documentsClosed(message))
- .Times(1);
-
- serverProxy.documentsClosed(message);
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendRegisterUnsavedFilesForEditorMessage)
-{
- ClangBackEnd::UnsavedFilesUpdatedMessage message({fileContainer});
-
- EXPECT_CALL(mockClangCodeModelServer, unsavedFilesUpdated(message))
- .Times(1);
-
- serverProxy.unsavedFilesUpdated(message);
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendUnregisterUnsavedFilesForEditorMessage)
-{
- ClangBackEnd::UnsavedFilesRemovedMessage message({fileContainer});
-
- EXPECT_CALL(mockClangCodeModelServer, unsavedFilesRemoved(message))
- .Times(1);
-
- serverProxy.unsavedFilesRemoved(message);
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendCompleteCodeMessage)
-{
- ClangBackEnd::RequestCompletionsMessage message(Utf8StringLiteral("foo.cpp"), 24, 33);
-
- EXPECT_CALL(mockClangCodeModelServer, requestCompletions(message))
- .Times(1);
-
- serverProxy.requestCompletions(message);
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendRequestAnnotationsMessage)
-{
- ClangBackEnd::RequestAnnotationsMessage message(
- {Utf8StringLiteral("foo.cpp"), Utf8StringLiteral("projectId")});
-
- EXPECT_CALL(mockClangCodeModelServer, requestAnnotations(message))
- .Times(1);
-
- serverProxy.requestAnnotations(message);
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendCompletionsMessage)
-{
- ClangBackEnd::CodeCompletions codeCompletions({Utf8StringLiteral("newFunction()")});
- ClangBackEnd::CompletionsMessage message(codeCompletions, 1);
-
- EXPECT_CALL(mockClangCodeModelClient, completions(message))
- .Times(1);
-
- clientProxy.completions(message);
- scheduleClientMessages();
-}
-
-TEST_F(ClientServerInProcess, DocumentVisibilityChangedMessage)
-{
- ClangBackEnd::DocumentVisibilityChangedMessage
- message(Utf8StringLiteral(TESTDATA_DIR "/fileone.cpp"),
- {Utf8StringLiteral(TESTDATA_DIR "/fileone.cpp"),
- Utf8StringLiteral(TESTDATA_DIR "/filetwo.cpp")});
-
- EXPECT_CALL(mockClangCodeModelServer, documentVisibilityChanged(message))
- .Times(1);
-
- serverProxy.documentVisibilityChanged(message);
- scheduleServerMessages();
-}
-
-TEST_F(ClientServerInProcess, SendAnnotationsMessage)
-{
- ClangBackEnd::HighlightingTypes types;
- types.mainHighlightingType = ClangBackEnd::HighlightingType::Keyword;
- ClangBackEnd::TokenInfoContainer tokenInfo(1, 1, 1, types);
- ClangBackEnd::DiagnosticContainer diagnostic(Utf8StringLiteral("don't do that"),
- Utf8StringLiteral("warning"),
- {Utf8StringLiteral("-Wpadded"), Utf8StringLiteral("-Wno-padded")},
- ClangBackEnd::DiagnosticSeverity::Warning,
- {Utf8StringLiteral("foo.cpp"), 20u, 103u},
- {{{Utf8StringLiteral("foo.cpp"), 20u, 103u}, {Utf8StringLiteral("foo.cpp"), 20u, 110u}}},
- {},
- {});
-
- ClangBackEnd::AnnotationsMessage message(fileContainer,
- {diagnostic},
- {},
- {tokenInfo},
- QVector<SourceRangeContainer>());
-
- EXPECT_CALL(mockClangCodeModelClient, annotations(message))
- .Times(1);
-
- clientProxy.annotations(message);
- scheduleClientMessages();
-}
-
-ClientServerInProcess::ClientServerInProcess()
- : serverProxy(&mockClangCodeModelClient, &buffer),
- clientProxy(&mockClangCodeModelServer, &buffer)
-{
-}
-
-void ClientServerInProcess::SetUp()
-{
- buffer.open(QIODevice::ReadWrite);
-}
-
-void ClientServerInProcess::TearDown()
-{
- buffer.close();
-}
-
-void ClientServerInProcess::scheduleServerMessages()
-{
- buffer.seek(0);
- clientProxy.readMessages();
- buffer.buffer().clear();
-}
-
-void ClientServerInProcess::scheduleClientMessages()
-{
- buffer.seek(0);
- serverProxy.readMessages();
- buffer.buffer().clear();
-}
-
-}
diff --git a/tests/unit/unittest/clientserveroutsideprocess-test.cpp b/tests/unit/unittest/clientserveroutsideprocess-test.cpp
deleted file mode 100644
index 75e838c8a66..00000000000
--- a/tests/unit/unittest/clientserveroutsideprocess-test.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "mockclangcodemodelclient.h"
-
-#include <clangcodemodelconnectionclient.h>
-#include <clangcodemodelservermessages.h>
-#include <readmessageblock.h>
-#include <writemessageblock.h>
-
-#include <utils/hostosinfo.h>
-
-#include <QBuffer>
-#include <QSignalSpy>
-#include <QString>
-#include <QVariant>
-
-#include <memory>
-#include <vector>
-
-using namespace ClangBackEnd;
-
-using ::testing::Eq;
-using ::testing::SizeIs;
-
-class ClientServerOutsideProcess : public ::testing::Test
-{
-protected:
- void SetUp();
- void TearDown();
-
-protected:
- NiceMock<MockClangCodeModelClient> mockClangCodeModelClient;
- ClangBackEnd::ClangCodeModelConnectionClient client{&mockClangCodeModelClient};
-};
-
-using ClientServerOutsideProcessSlowTest = ClientServerOutsideProcess;
-
-TEST_F(ClientServerOutsideProcessSlowTest, RestartProcessAsynchronously)
-{
- QSignalSpy clientSpy(&client, &ConnectionClient::connectedToLocalSocket);
-
- client.restartProcessAsynchronously();
-
- ASSERT_TRUE(clientSpy.wait(100000));
- ASSERT_TRUE(client.isProcessRunning());
- ASSERT_TRUE(client.isConnected());
-}
-
-TEST_F(ClientServerOutsideProcessSlowTest, RestartProcessAfterAliveTimeout)
-{
- QSignalSpy clientSpy(&client, &ConnectionClient::connectedToLocalSocket);
-
- client.setProcessAliveTimerInterval(1);
-
- ASSERT_TRUE(clientSpy.wait(100000));
- ASSERT_THAT(clientSpy, SizeIs(1));
-}
-
-TEST_F(ClientServerOutsideProcessSlowTest, RestartProcessAfterTermination)
-{
- QSignalSpy clientSpy(&client, &ConnectionClient::connectedToLocalSocket);
-
- client.processForTestOnly()->kill();
-
- ASSERT_TRUE(clientSpy.wait(100000));
- ASSERT_THAT(clientSpy, SizeIs(1));
-}
-
-TEST_F(ClientServerOutsideProcess, SendDocumentsOpenedMessage)
-{
- auto filePath = Utf8StringLiteral("foo.cpp");
- ClangBackEnd::FileContainer fileContainer(filePath, Utf8StringLiteral("projectId"));
- ClangBackEnd::DocumentsOpenedMessage documentsOpenedMessage({fileContainer},
- filePath,
- {filePath});
- EchoMessage echoMessage(documentsOpenedMessage);
-
- EXPECT_CALL(mockClangCodeModelClient, echo(echoMessage));
-
- client.serverProxy().documentsOpened(documentsOpenedMessage);
- ASSERT_TRUE(client.waitForEcho());
-}
-
-TEST_F(ClientServerOutsideProcess, SendDocumentsClosedMessage)
-{
- FileContainer fileContainer(Utf8StringLiteral("foo.cpp"), Utf8StringLiteral("projectId"));
- ClangBackEnd::DocumentsClosedMessage documentsClosedMessage({fileContainer});
- EchoMessage echoMessage(documentsClosedMessage);
-
- EXPECT_CALL(mockClangCodeModelClient, echo(echoMessage));
-
- client.serverProxy().documentsClosed(documentsClosedMessage);
- ASSERT_TRUE(client.waitForEcho());
-}
-
-TEST_F(ClientServerOutsideProcess, SendCompleteCodeMessage)
-{
- RequestCompletionsMessage codeCompleteMessage(Utf8StringLiteral("foo.cpp"), 24, 33);
- EchoMessage echoMessage(codeCompleteMessage);
-
- EXPECT_CALL(mockClangCodeModelClient, echo(echoMessage));
-
- client.serverProxy().requestCompletions(codeCompleteMessage);
- ASSERT_TRUE(client.waitForEcho());
-}
-
-void ClientServerOutsideProcess::SetUp()
-{
- QSignalSpy clientSpy(&client, &ConnectionClient::connectedToLocalSocket);
- client.setProcessPath(Utils::HostOsInfo::withExecutableSuffix(QStringLiteral(ECHOSERVER)));
-
- client.startProcessAndConnectToServerAsynchronously();
-
- ASSERT_TRUE(clientSpy.wait(100000));
- ASSERT_THAT(clientSpy, SizeIs(1));
-
- client.setProcessAliveTimerInterval(1000000);
-
- ASSERT_TRUE(client.isConnected());
-}
-
-void ClientServerOutsideProcess::TearDown()
-{
- client.setProcessAliveTimerInterval(1000000);
- client.waitForConnected();
-
- ASSERT_TRUE(client.isProcessRunning());
- ASSERT_TRUE(client.isConnected());
-
- client.finishProcess();
-}
diff --git a/tests/unit/unittest/codecompleter-test.cpp b/tests/unit/unittest/codecompleter-test.cpp
deleted file mode 100644
index 714d3802600..00000000000
--- a/tests/unit/unittest/codecompleter-test.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <codecompleter.h>
-#include <clangdocument.h>
-#include <filecontainer.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-#include <utf8stringvector.h>
-
-#include <QCoreApplication>
-#include <QFile>
-#include <QTemporaryDir>
-
-using ::testing::ElementsAreArray;
-using ::testing::Contains;
-using ::testing::AllOf;
-using ::testing::Not;
-using ::testing::PrintToString;
-
-using ClangBackEnd::CodeCompletion;
-using ClangBackEnd::CodeCompletionChunk;
-using ClangBackEnd::CodeCompleter;
-
-namespace {
-
-MATCHER_P2(IsCodeCompletion, text, completionKind,
- std::string(negation ? "isn't" : "is") + " code completion with text "
- + PrintToString(text) + " and kind " + PrintToString(completionKind)
- )
-{
- if (arg.text != text) {
- *result_listener << "text is " + PrintToString(arg.text) + " and not " + PrintToString(text);
- return false;
- }
-
- if (arg.completionKind != completionKind) {
- *result_listener << "kind is " + PrintToString(arg.completionKind) + " and not " + PrintToString(completionKind);
- return false;
- }
-
- return true;
-}
-
-MATCHER_P(IsOverloadCompletion, text,
- std::string(negation ? "isn't" : "is") + " overload completion with text " + PrintToString(text))
-{
- Utf8String overloadName;
- for (auto &chunk : arg.chunks) {
- if (chunk.kind == CodeCompletionChunk::Text) {
- overloadName = chunk.text;
- break;
- }
- }
- if (overloadName != text) {
- *result_listener << "text is " + PrintToString(overloadName) + " and not " + PrintToString(text);
- return false;
- }
-
- if (arg.completionKind != CodeCompletion::FunctionOverloadCompletionKind) {
- *result_listener << "kind is " + PrintToString(arg.completionKind) + " and not " + PrintToString(CodeCompletion::FunctionOverloadCompletionKind);
- return false;
- }
-
- return true;
-}
-
-MATCHER(HasFixIts, "")
-{
- return !arg.requiredFixIts.empty();
-}
-
-class CodeCompleter : public ::testing::Test
-{
-protected:
- void SetUp();
- void copyTargetHeaderToTemporaryIncludeDirecory();
- void copyChangedTargetHeaderToTemporaryIncludeDirecory();
- ClangBackEnd::CodeCompleter setupCompleter(const ClangBackEnd::FileContainer &fileContainer);
- static Utf8String readFileContent(const QString &fileName);
-
-protected:
- QTemporaryDir includeDirectory;
- Utf8String includePathArgument{QStringLiteral("-I") + includeDirectory.path()};
- QString targetHeaderPath{includeDirectory.path() + QStringLiteral("/complete_target_header.h")};
- ClangBackEnd::FileContainer mainFileContainer{Utf8StringLiteral(TESTDATA_DIR
- "/complete_completer_main.cpp"),
- Utf8StringVector{includePathArgument},
- {}};
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- ClangBackEnd::Document document;
- QScopedPointer<ClangBackEnd::CodeCompleter> completer;
- ClangBackEnd::FileContainer unsavedMainFileContainer{mainFileContainer.filePath,
- {includePathArgument},
- {},
- readFileContent("/complete_completer_main_unsaved.cpp"),
- true};
- ClangBackEnd::FileContainer unsavedTargetHeaderFileContainer{targetHeaderPath,
- {includePathArgument},
- {},
- readFileContent("/complete_target_header_unsaved.h"),
- true};
-
- ClangBackEnd::FileContainer arrowFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_arrow.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_arrow.cpp"),
- true
- };
- ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withDotArrowCorrectionForPointer.cpp"),
- true
- };
- ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainerBeforeTyping{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withDotArrowCorrectionForPointer_beforeTyping.cpp"),
- true
- };
- ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainerAfterTyping{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withDotArrowCorrectionForPointer_afterTyping.cpp"),
- true
- };
- ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainerInitial{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withDotArrowCorrectionForPointerInitial.cpp"),
- true
- };
- ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainerUpdated{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withDotArrowCorrectionForPointerUpdated.cpp"),
- true
- };
- ClangBackEnd::FileContainer noDotArrowCorrectionForObjectFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForObject.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withNoDotArrowCorrectionForObject.cpp"),
- true
- };
- ClangBackEnd::FileContainer noDotArrowCorrectionForFloatFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForFloat.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withNoDotArrowCorrectionForFloat.cpp"),
- true
- };
- ClangBackEnd::FileContainer noDotArrowCorrectionForObjectWithArrowOperatortFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForObjectWithArrowOperator.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withNoDotArrowCorrectionForObjectWithArrowOperator.cpp"),
- true
- };
- ClangBackEnd::FileContainer noDotArrowCorrectionForDotDotFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForDotDot.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withNoDotArrowCorrectionForDotDot.cpp"),
- true
- };
- ClangBackEnd::FileContainer noDotArrowCorrectionForArrowDotFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForArrowDot.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withNoDotArrowCorrectionForArrowDot.cpp"),
- true
- };
- ClangBackEnd::FileContainer noDotArrowCorrectionForOnlyDotFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForOnlyDot.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withNoDotArrowCorrectionForOnlyDot.cpp"),
- true
- };
- ClangBackEnd::FileContainer noDotArrowCorrectionForColonColonFileContainer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForColonColon.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withNoDotArrowCorrectionForColonColon.cpp"),
- true
- };
- ClangBackEnd::FileContainer dotArrowCorrectionForForwardDeclaredClassPointer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForForwardDeclaredClassPointer.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withDotArrowCorrectionForForwardDeclaredClassPointer.cpp"),
- true
- };
- ClangBackEnd::FileContainer globalCompletionAfterForwardDeclaredClassPointer{
- Utf8StringLiteral(TESTDATA_DIR"/complete_withGlobalCompletionAfterForwardDeclaredClassPointer.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_withGlobalCompletionAfterForwardDeclaredClassPointer.cpp"),
- true
- };
- ClangBackEnd::FileContainer smartPointerCompletion{
- Utf8StringLiteral(TESTDATA_DIR"/complete_smartpointer.cpp"),
- {includePathArgument},
- {},
- readFileContent("/complete_smartpointer.cpp"),
- true
- };
- ClangBackEnd::FileContainer completionsOrder{
- Utf8StringLiteral(TESTDATA_DIR"/completions_order.cpp"),
- {includePathArgument},
- {},
- readFileContent("/completions_order.cpp"),
- true
- };
-};
-
-using CodeCompleterSlowTest = CodeCompleter;
-
-Utf8String CodeCompleter::readFileContent(const QString &fileName)
-{
- QFile readFileContentFile(QStringLiteral(TESTDATA_DIR) + fileName);
- bool hasOpened = readFileContentFile.open(QIODevice::ReadOnly | QIODevice::Text);
-
- EXPECT_TRUE(hasOpened);
-
- return Utf8String::fromByteArray(readFileContentFile.readAll());
-}
-
-void CodeCompleter::copyTargetHeaderToTemporaryIncludeDirecory()
-{
- QFile::remove(targetHeaderPath);
- bool hasCopied = QFile::copy(QString::fromUtf8(TESTDATA_DIR "/complete_target_header.h"),
- targetHeaderPath);
- EXPECT_TRUE(hasCopied);
-}
-
-void CodeCompleter::copyChangedTargetHeaderToTemporaryIncludeDirecory()
-{
- QFile::remove(targetHeaderPath);
- bool hasCopied = QFile::copy(QString::fromUtf8(TESTDATA_DIR "/complete_target_header_changed.h"),
- targetHeaderPath);
- EXPECT_TRUE(hasCopied);
-}
-
-void CodeCompleter::SetUp()
-{
- EXPECT_TRUE(includeDirectory.isValid());
- documents.create({mainFileContainer});
- document = documents.document(mainFileContainer);
- completer.reset(new ClangBackEnd::CodeCompleter(document.translationUnit(), unsavedFiles));
-
- copyTargetHeaderToTemporaryIncludeDirecory();
- document.parse();
-}
-
-TEST_F(CodeCompleterSlowTest, FunctionInUnsavedFile)
-{
- unsavedFiles.createOrUpdate({unsavedMainFileContainer});
- documents.update({unsavedMainFileContainer});
- ClangBackEnd::CodeCompleter myCompleter(document.translationUnit(), unsavedFiles);
-
- ASSERT_THAT(myCompleter.complete(27, 1),
- AllOf(Contains(IsCodeCompletion(Utf8StringLiteral("FunctionWithArguments"),
- CodeCompletion::FunctionCompletionKind)),
- Contains(IsCodeCompletion(Utf8StringLiteral("Function"),
- CodeCompletion::FunctionCompletionKind)),
- Contains(IsCodeCompletion(Utf8StringLiteral("UnsavedFunction"),
- CodeCompletion::FunctionCompletionKind)),
- Contains(IsCodeCompletion(Utf8StringLiteral("f"),
- CodeCompletion::FunctionCompletionKind)),
- Not(Contains(IsCodeCompletion(Utf8StringLiteral("SavedFunction"),
- CodeCompletion::FunctionCompletionKind)))));
-}
-
-TEST_F(CodeCompleterSlowTest, VariableInUnsavedFile)
-{
- unsavedFiles.createOrUpdate({unsavedMainFileContainer});
- documents.update({unsavedMainFileContainer});
- ClangBackEnd::CodeCompleter myCompleter(document.translationUnit(), unsavedFiles);
-
- ASSERT_THAT(myCompleter.complete(27, 1),
- Contains(IsCodeCompletion(Utf8StringLiteral("VariableInUnsavedFile"),
- CodeCompletion::VariableCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, GlobalVariableInUnsavedFile)
-{
- unsavedFiles.createOrUpdate({unsavedMainFileContainer});
- documents.update({unsavedMainFileContainer});
- ClangBackEnd::CodeCompleter myCompleter(document.translationUnit(), unsavedFiles);
-
- ASSERT_THAT(myCompleter.complete(27, 1),
- Contains(IsCodeCompletion(Utf8StringLiteral("GlobalVariableInUnsavedFile"),
- CodeCompletion::VariableCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, Macro)
-{
- unsavedFiles.createOrUpdate({unsavedMainFileContainer});
- documents.update({unsavedMainFileContainer});
- ClangBackEnd::CodeCompleter myCompleter(document.translationUnit(), unsavedFiles);
-
- ASSERT_THAT(myCompleter.complete(27, 1),
- Contains(IsCodeCompletion(Utf8StringLiteral("Macro"),
- CodeCompletion::PreProcessorCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, Keyword)
-{
- ASSERT_THAT(completer->complete(27, 1),
- Contains(IsCodeCompletion(Utf8StringLiteral("switch"),
- CodeCompletion::KeywordCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, FunctionInIncludedHeader)
-{
- ASSERT_THAT(completer->complete(27, 1),
- Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeader"),
- CodeCompletion::FunctionCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, UniquePointerCompletion)
-{
- auto myCompleter = setupCompleter(smartPointerCompletion);
-
- ASSERT_THAT(myCompleter.complete(59, 54, 59, 32),
- Contains(IsOverloadCompletion(Utf8StringLiteral("Bar"))));
-}
-
-TEST_F(CodeCompleterSlowTest, SharedPointerCompletion)
-{
- auto myCompleter = setupCompleter(smartPointerCompletion);
-
- ASSERT_THAT(myCompleter.complete(60, 55, 60, 33),
- Contains(IsOverloadCompletion(Utf8StringLiteral("Bar"))));
-}
-
-TEST_F(CodeCompleterSlowTest, QSharedPointerCompletion)
-{
- auto myCompleter = setupCompleter(smartPointerCompletion);
-
- ASSERT_THAT(myCompleter.complete(61, 60, 61, 32),
- Contains(IsOverloadCompletion(Utf8StringLiteral("Bar"))));
-}
-
-TEST_F(CodeCompleterSlowTest, FunctionInUnsavedIncludedHeader)
-{
- unsavedFiles.createOrUpdate({unsavedTargetHeaderFileContainer});
- documents.create({unsavedTargetHeaderFileContainer});
- ClangBackEnd::CodeCompleter myCompleter(document.translationUnit(), unsavedFiles);
-
- ASSERT_THAT(myCompleter.complete(27, 1),
- Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeaderUnsaved"),
- CodeCompletion::FunctionCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, DISABLED_FunctionInChangedIncludedHeader)
-{
- copyChangedTargetHeaderToTemporaryIncludeDirecory();
-
- ASSERT_THAT(completer->complete(27, 1),
- Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeaderChanged"),
- CodeCompletion::FunctionCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, DISABLED_FunctionInChangedIncludedHeaderWithUnsavedContentInMainFile) // it's not that bad because we reparse anyway
-{
- unsavedFiles.createOrUpdate({unsavedMainFileContainer});
- documents.update({unsavedMainFileContainer});
- ClangBackEnd::CodeCompleter myCompleter(document.translationUnit(), unsavedFiles);
-
- copyChangedTargetHeaderToTemporaryIncludeDirecory();
-
- ASSERT_THAT(myCompleter.complete(27, 1),
- Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeaderChanged"),
- CodeCompletion::FunctionCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, ArrowCompletion)
-{
- auto myCompleter = setupCompleter(arrowFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 10);
-
- ASSERT_THAT(completions,
- Contains(IsCodeCompletion(Utf8StringLiteral("member"),
- CodeCompletion::VariableCompletionKind)));
- ASSERT_THAT(completions, Not(Contains(HasFixIts())));
-}
-
-TEST_F(CodeCompleterSlowTest, DotToArrowCompletionForPointer)
-{
- auto myCompleter = setupCompleter(dotArrowCorrectionForPointerFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 9);
-
- ASSERT_THAT(completions,
- Contains(IsCodeCompletion(Utf8StringLiteral("member"),
- CodeCompletion::VariableCompletionKind)));
- ASSERT_THAT(completions, Contains(HasFixIts()));
-}
-
-TEST_F(CodeCompleterSlowTest, DotToArrowCompletionForPointerInOutdatedDocument)
-{
- auto fileContainerBeforeTyping = dotArrowCorrectionForPointerFileContainerBeforeTyping;
- documents.create({fileContainerBeforeTyping});
- unsavedFiles.createOrUpdate({fileContainerBeforeTyping});
- auto document = documents.document(fileContainerBeforeTyping.filePath);
- document.parse();
- unsavedFiles.createOrUpdate({dotArrowCorrectionForPointerFileContainerAfterTyping});
- ClangBackEnd::CodeCompleter myCompleter(documents.document(dotArrowCorrectionForPointerFileContainerAfterTyping).translationUnit(),
- unsavedFiles);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 9);
-
- ASSERT_THAT(completions,
- Contains(IsCodeCompletion(Utf8StringLiteral("member"),
- CodeCompletion::VariableCompletionKind)));
- ASSERT_THAT(completions, Contains(HasFixIts()));
-}
-
-TEST_F(CodeCompleterSlowTest, NoDotToArrowCompletionForObject)
-{
- auto myCompleter = setupCompleter(noDotArrowCorrectionForObjectFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 9);
-
- ASSERT_THAT(completions,
- Contains(IsCodeCompletion(Utf8StringLiteral("member"),
- CodeCompletion::VariableCompletionKind)));
- ASSERT_THAT(completions, Not(Contains(HasFixIts())));
-}
-
-TEST_F(CodeCompleterSlowTest, NoDotToArrowCompletionForFloat)
-{
- auto myCompleter = setupCompleter(noDotArrowCorrectionForFloatFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(3, 18);
-
- ASSERT_TRUE(completions.isEmpty());
-}
-
-TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForObjectWithArrowOperator)
-{
- auto myCompleter = setupCompleter(noDotArrowCorrectionForObjectWithArrowOperatortFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 9);
-
- ASSERT_THAT(completions,
- Contains(IsCodeCompletion(Utf8StringLiteral("member"),
- CodeCompletion::VariableCompletionKind)));
- ASSERT_THAT(completions, Not(Contains(HasFixIts())));
-}
-
-TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForDotDot)
-{
- auto myCompleter = setupCompleter(noDotArrowCorrectionForDotDotFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 10);
-
- ASSERT_TRUE(completions.isEmpty());
-}
-
-TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForArrowDot)
-{
- auto myCompleter = setupCompleter(noDotArrowCorrectionForArrowDotFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 11);
-
- ASSERT_TRUE(completions.isEmpty());
-}
-
-TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForOnlyDot)
-{
- auto myCompleter = setupCompleter(noDotArrowCorrectionForOnlyDotFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 6);
-
- ASSERT_TRUE(completions.isEmpty());
-}
-
-TEST_F(CodeCompleterSlowTest, GlobalCompletionForSpaceAfterOnlyDot)
-{
- auto myCompleter = setupCompleter(noDotArrowCorrectionForOnlyDotFileContainer);
-
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 7);
- ASSERT_THAT(completions,
- Contains(IsCodeCompletion(Utf8StringLiteral("Foo"),
- CodeCompletion::ClassCompletionKind)));
-}
-
-TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForColonColon)
-{
- auto myCompleter = setupCompleter(noDotArrowCorrectionForColonColonFileContainer);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(1, 7);
-
- ASSERT_THAT(completions, Not(Contains(HasFixIts())));
-}
-
-// Our workaround is not applicable with LLVM/Clang 10 anymore, so disable this test for that version.
-// Luckily, the workaround is not needed anymore with LLVM/Clang 11.
-TEST_F(CodeCompleterSlowTest, DISABLED_FOR_CLANG_10(NoGlobalCompletionAfterForwardDeclaredClassPointer))
-{
- auto myCompleter = setupCompleter(globalCompletionAfterForwardDeclaredClassPointer);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 10);
-
- ASSERT_TRUE(completions.isEmpty());
-}
-
-TEST_F(CodeCompleterSlowTest, GlobalCompletionAfterForwardDeclaredClassPointer)
-{
- auto myCompleter = setupCompleter(globalCompletionAfterForwardDeclaredClassPointer);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(6, 4);
-
- ASSERT_EQ(completions.isEmpty(), CINDEX_VERSION_MINOR != 59);
-}
-
-TEST_F(CodeCompleterSlowTest, ConstructorCompletionExists)
-{
- auto myCompleter = setupCompleter(completionsOrder);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1);
-
- int constructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind;
- });
-
- ASSERT_THAT(constructorIndex != -1, true);
-}
-
-TEST_F(CodeCompleterSlowTest, ClassConstructorCompletionsOrder)
-{
- auto myCompleter = setupCompleter(completionsOrder);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1);
-
- int classIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ClassCompletionKind;
- });
- int constructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind;
- });
-
- ASSERT_THAT(classIndex < constructorIndex, true);
-}
-
-TEST_F(CodeCompleterSlowTest, SharedPointerCompletionsOrder)
-{
- auto myCompleter = setupCompleter(smartPointerCompletion);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(62, 11);
-
- int resetIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "reset";
- });
- int barDestructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "~Bar";
- });
-
- ASSERT_THAT(barDestructorIndex < resetIndex, true);
-}
-
-TEST_F(CodeCompleterSlowTest, ConstructorHasOverloadCompletions)
-{
- auto myCompleter = setupCompleter(completionsOrder);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1);
-
- int constructorsCount = Utils::count(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind;
- });
-
- ASSERT_THAT(constructorsCount, 2);
-}
-
-TEST_F(CodeCompleterSlowTest, FunctionOverloadsNoParametersOrder)
-{
- auto myCompleter = setupCompleter(completionsOrder);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(27, 7);
-
- const int fooCount = Utils::count(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "foo";
- });
-
- ASSERT_THAT(fooCount, 1);
-}
-
-TEST_F(CodeCompleterSlowTest, FunctionOverloadsWithParametersOrder)
-{
- auto myCompleter = setupCompleter(completionsOrder);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(27, 7);
-
- int firstIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "bar";
- });
- int secondIndex = Utils::indexOf(completions, [i = 0, firstIndex](const CodeCompletion &codeCompletion) mutable {
- return (i++) > firstIndex && codeCompletion.text == "bar";
- });
-
- ASSERT_THAT(abs(firstIndex - secondIndex), 1);
-}
-
-TEST_F(CodeCompleterSlowTest, FunctionOverloadsWithoutDotOrArrowOrder)
-{
- auto myCompleter = setupCompleter(completionsOrder);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(21, 1);
-
- int firstIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "bar";
- });
- int secondIndex = Utils::indexOf(completions, [i = 0, firstIndex](const CodeCompletion &codeCompletion) mutable {
- return (i++) > firstIndex && codeCompletion.text == "bar";
- });
-
- ASSERT_THAT(abs(firstIndex - secondIndex), 1);
-}
-
-TEST_F(CodeCompleterSlowTest, LexicographicalSorting)
-{
- auto myCompleter = setupCompleter(completionsOrder);
- const ClangBackEnd::CodeCompletions completions = myCompleter.complete(40, 18);
-
- const int funcAIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "memberFuncAAA";
- });
- const int funcBIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "memberFuncBB";
- });
- const int funcCIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) {
- return codeCompletion.text == "memberFuncC";
- });
-
- ASSERT_NE(funcAIndex, -1);
- ASSERT_EQ(funcBIndex, funcAIndex + 1);
- ASSERT_EQ(funcCIndex, funcAIndex + 2);
-}
-
-ClangBackEnd::CodeCompleter CodeCompleter::setupCompleter(
- const ClangBackEnd::FileContainer &fileContainer)
-{
- documents.create({fileContainer});
- unsavedFiles.createOrUpdate({fileContainer});
- document = documents.document(fileContainer);
- document.parse();
-
- ClangBackEnd::Document document = documents.document(fileContainer);
- return ClangBackEnd::CodeCompleter(document.translationUnit(),
- unsavedFiles);
-}
-
-}
diff --git a/tests/unit/unittest/codecompletionsextractor-test.cpp b/tests/unit/unittest/codecompletionsextractor-test.cpp
deleted file mode 100644
index 25c83cd14ca..00000000000
--- a/tests/unit/unittest/codecompletionsextractor-test.cpp
+++ /dev/null
@@ -1,865 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "unittest-utility-functions.h"
-
-#include <clangcodecompleteresults.h>
-#include <clangdocument.h>
-#include <clangfilepath.h>
-#include <codecompletionsextractor.h>
-#include <filecontainer.h>
-#include <clangunsavedfilesshallowarguments.h>
-#include <clangtranslationunit.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-#include <utf8stringvector.h>
-
-#include <clang-c/Index.h>
-
-#include <QFile>
-
-using ClangBackEnd::CodeCompletionsExtractor;
-using ClangBackEnd::ClangCodeCompleteResults;
-using ClangBackEnd::FilePath;
-using ClangBackEnd::Document;
-using ClangBackEnd::CodeCompletion;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::UnsavedFilesShallowArguments;
-using ClangBackEnd::CodeCompletionChunk;
-using ClangBackEnd::CodeCompletionChunks;
-
-namespace {
-
-using ::testing::PrintToString;
-using ::testing::Not;
-
-MATCHER_P3(HasCompletion, name, kind, availability,
- std::string(negation ? "hasn't" : "has") + " completion of name " + PrintToString(name) +
- ", kind " + PrintToString(kind))
-{
- ::CodeCompletionsExtractor &extractor = const_cast<::CodeCompletionsExtractor&>(arg);
- while (extractor.next()) {
- if (extractor.currentCodeCompletion().text == name) {
- if (extractor.currentCodeCompletion().completionKind == kind) {
- if (extractor.currentCodeCompletion().availability == availability) {
- return true;
- } else if (!extractor.peek(name)) {
- *result_listener << "availability is " << PrintToString(extractor.currentCodeCompletion().availability) << " and not " << PrintToString(availability);
- return false;
- }
- } else if (!extractor.peek(name)) {
- *result_listener << "kind is " << PrintToString(extractor.currentCodeCompletion().completionKind) << " and not " << PrintToString(kind);
- return false;
- }
- }
- }
-
- return false;
-}
-
-MATCHER_P2(HasCompletionChunks, name, chunks,
- std::string(negation ? "hasn't" : "has") + " completion of name " + PrintToString(name) +
- " with the chunks " + PrintToString(chunks))
-{
- ::CodeCompletionsExtractor &extractor = const_cast<::CodeCompletionsExtractor&>(arg);
- while (extractor.next()) {
- if (extractor.currentCodeCompletion().text == name) {
- if (extractor.currentCodeCompletion().chunks == chunks) {
- return true;
- } else if (!extractor.peek(name)) {
- *result_listener << "chunks are " << PrintToString(arg.currentCodeCompletion().chunks) << " and not " << PrintToString(chunks);
- return false;
- }
- }
- }
-
- return false;
-}
-
-MATCHER_P2(HasBriefComment, name, briefComment,
- std::string(negation ? "hasn't" : "has") + " completion of name " + PrintToString(name) +
- " with the brief comment " + PrintToString(briefComment))
-{
- ::CodeCompletionsExtractor &extractor = const_cast<::CodeCompletionsExtractor&>(arg);
- while (extractor.next()) {
- if (extractor.currentCodeCompletion().text == name) {
- if (extractor.currentCodeCompletion().briefComment == briefComment) {
- return true;
- } else if (!extractor.peek(name)) {
- *result_listener << "briefComment is " << PrintToString(arg.currentCodeCompletion().briefComment) << " and not " << PrintToString(briefComment);
- return false;
- }
- }
- }
-
- return false;
-}
-
-
-const Utf8String unsavedFileContent(const char *unsavedFilePath)
-{
- QFile unsavedFileContentFile(QString::fromUtf8(unsavedFilePath));
- bool isOpen = unsavedFileContentFile.open(QIODevice::ReadOnly | QIODevice::Text);
- if (!isOpen)
- ADD_FAILURE() << "File with the unsaved content cannot be opened!";
-
- return Utf8String::fromByteArray(unsavedFileContentFile.readAll());
-}
-
-const ClangBackEnd::FileContainer unsavedDataFileContainer(const char *filePath,
- const char *unsavedFilePath)
-{
- return ClangBackEnd::FileContainer(Utf8String::fromUtf8(filePath),
- unsavedFileContent(unsavedFilePath),
- true);
-}
-
-class CodeCompletionsExtractor : public ::testing::Test
-{
-protected:
- ClangCodeCompleteResults getResults(const Document &document,
- uint line,
- uint column = 1,
- bool needsReparse = false);
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Utf8StringVector compilationArguments{UnitTest::addPlatformArguments()};
- Document functionDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_function.cpp"), compilationArguments, {}, documents};
- Document functionOverloadDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_functionoverload.cpp"), compilationArguments, {}, documents};
- Document variableDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_variable.cpp"), compilationArguments, {}, documents};
- Document classDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_class.cpp"), compilationArguments, {}, documents};
- Document namespaceDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_namespace.cpp"), compilationArguments, {}, documents};
- Document enumerationDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_enumeration.cpp"), compilationArguments, {}, documents};
- Document constructorDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_constructor.cpp"), compilationArguments, {}, documents};
- Document constructorMemberInitDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_constructorMemberInitialization.cpp"), compilationArguments, {}, documents};
- Document briefCommentDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_brief_comment.cpp"), compilationArguments, {}, documents};
- Document privateFunctionDefinitionDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_private_function_definition.cpp"), compilationArguments, {}, documents};
-};
-
-using CodeCompletionsExtractorSlowTest = CodeCompletionsExtractor;
-
-TEST_F(CodeCompletionsExtractorSlowTest, Function)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Function"),
- CodeCompletion::FunctionCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, TemplateFunction)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("TemplateFunction"),
- CodeCompletion::TemplateFunctionCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Variable)
-{
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 4));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Var"),
- CodeCompletion::VariableCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, NonTypeTemplateParameter)
-{
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 25, 19));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("NonTypeTemplateParameter"),
- CodeCompletion::VariableCompletionKind,
- CodeCompletion::Available));
-}
-
-
-TEST_F(CodeCompletionsExtractorSlowTest, VariableReference)
-{
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 12));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Var"),
- CodeCompletion::VariableCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Parameter)
-{
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 4));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Parameter"),
- CodeCompletion::VariableCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Field)
-{
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Field"),
- CodeCompletion::VariableCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Class)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Class"),
- CodeCompletion::ClassCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Struct)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Struct"),
- CodeCompletion::ClassCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Union)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Union"),
- CodeCompletion::ClassCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Typedef)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("TypeDef"),
- CodeCompletion::TypeAliasCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, UsingAsTypeAlias)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("UsingClass"),
- CodeCompletion::TypeAliasCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, TemplateTypeParameter)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("TemplateTypeParameter"),
- CodeCompletion::ClassCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, TemplateClass)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("TemplateClass"),
- CodeCompletion::TemplateClassCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, TemplateTemplateParameter)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("TemplateTemplateParameter"),
- CodeCompletion::TemplateClassCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, ClassTemplatePartialSpecialization)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("ClassTemplatePartialSpecialization"),
- CodeCompletion::TemplateClassCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Namespace)
-{
- ClangCodeCompleteResults completeResults(getResults(namespaceDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(namespaceDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Namespace"),
- CodeCompletion::NamespaceCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, NamespaceAlias)
-{
- ClangCodeCompleteResults completeResults(getResults(namespaceDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(namespaceDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("NamespaceAlias"),
- CodeCompletion::NamespaceCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Enumeration)
-{
- ClangCodeCompleteResults completeResults(getResults(enumerationDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(enumerationDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Enumeration"),
- CodeCompletion::EnumerationCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Enumerator)
-{
- ClangCodeCompleteResults completeResults(getResults(enumerationDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(enumerationDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Enumerator"),
- CodeCompletion::EnumeratorCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Constructor)
-{
- ClangCodeCompleteResults completeResults(getResults(constructorDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(constructorDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Constructor"),
- CodeCompletion::ConstructorCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, ConstructorMemberInitializer) {
- ClangCodeCompleteResults completeResults(getResults(constructorMemberInitDocument, 2, 18));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(constructorDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor,
- HasCompletion(Utf8StringLiteral("member"),
- CodeCompletion::VariableCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Destructor)
-{
- ClangCodeCompleteResults completeResults(getResults(constructorDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(constructorDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("~Constructor"),
- CodeCompletion::DestructorCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Method)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Method"),
- CodeCompletion::FunctionDefinitionCompletionKind,
- CodeCompletion::Available));
- ASSERT_FALSE(extractor.currentCodeCompletion().hasParameters);
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, MethodWithParameters)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("MethodWithParameters"),
- CodeCompletion::FunctionDefinitionCompletionKind,
- CodeCompletion::Available));
- ASSERT_TRUE(extractor.currentCodeCompletion().hasParameters);
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Slot)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Slot"),
- CodeCompletion::SlotCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, Signal)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Signal"),
- CodeCompletion::SignalCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, MacroDefinition)
-{
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 35));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("MacroDefinition"),
- CodeCompletion::PreProcessorCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, FunctionMacro)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("FunctionMacro"),
- CodeCompletion::FunctionCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, IntKeyword)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("int"),
- CodeCompletion::KeywordCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, SwitchKeyword)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("switch"),
- CodeCompletion::KeywordCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, ClassKeyword)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("class"),
- CodeCompletion::KeywordCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, DeprecatedFunction)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("DeprecatedFunction"),
- CodeCompletion::FunctionDefinitionCompletionKind,
- CodeCompletion::Deprecated));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, NotAccessibleFunction)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- // Availability should be NotAccessible, but see QTCREATORBUG-25244.
- // It's better to offer completion for some non-accessible functions than
- // not to offer completion for some accessible ones.
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("NotAccessibleFunction"),
- CodeCompletion::FunctionDefinitionCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, NotAvailableFunction)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("NotAvailableFunction"),
- CodeCompletion::FunctionDefinitionCompletionKind,
- CodeCompletion::NotAvailable));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, UnsavedFile)
-{
- Document document(Utf8String::fromUtf8(TESTDATA_DIR "/complete_extractor_function.cpp"),
- compilationArguments,
- {},
- documents);
- unsavedFiles.createOrUpdate(
- {unsavedDataFileContainer(TESTDATA_DIR "/complete_extractor_function.cpp",
- TESTDATA_DIR "/complete_extractor_function_unsaved.cpp")});
- ClangCodeCompleteResults completeResults(getResults(document, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(document.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Method2"),
- CodeCompletion::FunctionDefinitionCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, ChangeUnsavedFile)
-{
- Document document(Utf8String::fromUtf8(TESTDATA_DIR "/complete_extractor_function.cpp"),
- compilationArguments,
- {},
- documents);
- unsavedFiles.createOrUpdate(
- {unsavedDataFileContainer(TESTDATA_DIR "/complete_extractor_function.cpp",
- TESTDATA_DIR "/complete_extractor_function_unsaved.cpp")});
- ClangCodeCompleteResults completeResults(getResults(document, 20));
- unsavedFiles.createOrUpdate({unsavedDataFileContainer(TESTDATA_DIR"/complete_extractor_function.cpp",
- TESTDATA_DIR"/complete_extractor_function_unsaved_2.cpp")});
- completeResults = getResults(document, 20);
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(document.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("Method3"),
- CodeCompletion::FunctionDefinitionCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, ArgumentDefinition)
-{
- Document variableDocument{Utf8StringLiteral(TESTDATA_DIR "/complete_extractor_variable.cpp"),
- {Utf8StringLiteral("-DArgumentDefinition"),
- Utf8StringLiteral("-std=gnu++14")},
- {},
- documents};
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 35));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("ArgumentDefinitionVariable"),
- CodeCompletion::VariableCompletionKind,
- CodeCompletion::Available));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, NoArgumentDefinition)
-{
- Document variableDocument{Utf8StringLiteral(TESTDATA_DIR "/complete_extractor_variable.cpp"),
- {Utf8StringLiteral("-std=gnu++14")},
- {},
- documents};
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 35));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, Not(HasCompletion(Utf8StringLiteral("ArgumentDefinitionVariable"),
- CodeCompletion::VariableCompletionKind,
- CodeCompletion::Available)));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksFunction)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletionChunks(Utf8StringLiteral("Function"),
- CodeCompletionChunks({{CodeCompletionChunk::ResultType, Utf8StringLiteral("void")},
- {CodeCompletionChunk::TypedText, Utf8StringLiteral("Function")},
- {CodeCompletionChunk::LeftParen, Utf8StringLiteral("(")},
- {CodeCompletionChunk::RightParen, Utf8StringLiteral(")")}})));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksFunctionWithOptionalChunks)
-{
- ClangCodeCompleteResults completeResults(getResults(functionDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletionChunks(Utf8StringLiteral("FunctionWithOptional"),
- CodeCompletionChunks({{CodeCompletionChunk::ResultType, Utf8StringLiteral("void")},
- {CodeCompletionChunk::TypedText, Utf8StringLiteral("FunctionWithOptional")},
- {CodeCompletionChunk::LeftParen, Utf8StringLiteral("(")},
- {CodeCompletionChunk::Placeholder, Utf8StringLiteral("int x")},
- {CodeCompletionChunk::Comma, Utf8StringLiteral(", "), true},
- {CodeCompletionChunk::Placeholder, Utf8StringLiteral("char y = 1"), true},
- {CodeCompletionChunk::Comma, Utf8StringLiteral(", "), true},
- {CodeCompletionChunk::Placeholder, Utf8StringLiteral("int z = 5"), true},
- {CodeCompletionChunk::RightParen, Utf8StringLiteral(")")}})));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksField)
-{
- ClangCodeCompleteResults completeResults(getResults(variableDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(variableDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletionChunks(Utf8StringLiteral("Field"),
- CodeCompletionChunks({{CodeCompletionChunk::ResultType, Utf8StringLiteral("int")},
- {CodeCompletionChunk::TypedText, Utf8StringLiteral("Field")}})));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksEnumerator)
-{
- ClangCodeCompleteResults completeResults(getResults(enumerationDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(enumerationDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletionChunks(Utf8StringLiteral("Enumerator"),
- CodeCompletionChunks({{CodeCompletionChunk::ResultType, Utf8StringLiteral("Enumeration")},
- {CodeCompletionChunk::TypedText, Utf8StringLiteral("Enumerator")}})));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksEnumeration)
-{
- ClangCodeCompleteResults completeResults(getResults(enumerationDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(enumerationDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletionChunks(Utf8StringLiteral("Enumeration"),
- CodeCompletionChunks({{CodeCompletionChunk::TypedText, Utf8StringLiteral("Enumeration")}})));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksClass)
-{
- ClangCodeCompleteResults completeResults(getResults(classDocument, 20));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(classDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletionChunks(Utf8StringLiteral("Class"),
- CodeCompletionChunks({{CodeCompletionChunk::TypedText, Utf8StringLiteral("Class")}})));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, BriefComment)
-{
- ClangCodeCompleteResults completeResults(getResults(briefCommentDocument, 10, 1,
- /*needsReparse=*/ true));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(briefCommentDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasBriefComment(Utf8StringLiteral("BriefComment"), Utf8StringLiteral("A brief comment")));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, OverloadCandidate)
-{
- ClangCodeCompleteResults completeResults(getResults(functionOverloadDocument, 8, 13));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(functionOverloadDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletionChunks(Utf8String(),
- CodeCompletionChunks({
- {CodeCompletionChunk::Text, Utf8StringLiteral("Foo")},
- {CodeCompletionChunk::LeftParen, Utf8StringLiteral("(")},
- {CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("const Foo &foo")},
- {CodeCompletionChunk::RightParen, Utf8StringLiteral(")")},
- })));
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, ExtractAll)
-{
- ClangCodeCompleteResults completeResults(getResults(constructorDocument, 25));
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(constructorDocument.filePath()),
- completeResults.data());
-
- auto codeCompletions = extractor.extractAll(false);
-
- ASSERT_THAT(codeCompletions.empty(), false);
-}
-
-TEST_F(CodeCompletionsExtractorSlowTest, PrivateFunctionDefinition)
-{
- ClangCodeCompleteResults completeResults(getResults(privateFunctionDefinitionDocument, 5, 12));
-
- ::CodeCompletionsExtractor extractor(
- unsavedFiles.unsavedFile(privateFunctionDefinitionDocument.filePath()),
- completeResults.data());
-
- ASSERT_THAT(extractor, HasCompletion(Utf8StringLiteral("method"),
- CodeCompletion::FunctionDefinitionCompletionKind,
- CodeCompletion::Available));
-}
-
-ClangCodeCompleteResults CodeCompletionsExtractor::getResults(const Document &document,
- uint line,
- uint column,
- bool needsReparse)
-{
- document.parse();
- if (needsReparse)
- document.reparse();
-
- const Utf8String nativeFilePath = FilePath::toNativeSeparators(document.filePath());
- UnsavedFilesShallowArguments unsaved = unsavedFiles.shallowArguments();
-
- return ClangCodeCompleteResults(clang_codeCompleteAt(document.translationUnit().cxTranslationUnit(),
- nativeFilePath.constData(),
- line,
- column,
- unsaved.data(),
- unsaved.count(),
- CXCodeComplete_IncludeMacros | CXCodeComplete_IncludeCodePatterns | CXCodeComplete_IncludeBriefComments));
-}
-
-}
diff --git a/tests/unit/unittest/completionchunkstotextconverter-test.cpp b/tests/unit/unittest/completionchunkstotextconverter-test.cpp
deleted file mode 100644
index e54161f8363..00000000000
--- a/tests/unit/unittest/completionchunkstotextconverter-test.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <codecompletionchunk.h>
-#include <clangcompletionchunkstotextconverter.h>
-
-namespace {
-
-using ClangBackEnd::CodeCompletionChunk;
-using ClangBackEnd::CodeCompletionChunks;
-using Converter = ClangCodeModel::Internal::CompletionChunksToTextConverter;
-
-class CompletionChunksToTextConverter : public ::testing::Test
-{
-protected:
- Converter converter;
- CodeCompletionChunk integerResultType{CodeCompletionChunk::ResultType, Utf8StringLiteral("int")};
- CodeCompletionChunk templateResultType{CodeCompletionChunk::ResultType, Utf8StringLiteral("Foo<int>")};
- CodeCompletionChunk enumerationResultType{CodeCompletionChunk::ResultType, Utf8StringLiteral("Enumeration")};
- CodeCompletionChunk functionName{CodeCompletionChunk::TypedText, Utf8StringLiteral("Function")};
- CodeCompletionChunk namespaceName{CodeCompletionChunk::TypedText, Utf8StringLiteral("Namespace")};
- CodeCompletionChunk variableName{CodeCompletionChunk::TypedText, Utf8StringLiteral("Variable")};
- CodeCompletionChunk enumeratorName{CodeCompletionChunk::TypedText, Utf8StringLiteral("Enumerator")};
- CodeCompletionChunk enumerationName{CodeCompletionChunk::TypedText, Utf8StringLiteral("Enumeration")};
- CodeCompletionChunk className{CodeCompletionChunk::TypedText, Utf8StringLiteral("Class")};
- CodeCompletionChunk leftParen{CodeCompletionChunk::LeftParen, Utf8StringLiteral("(")};
- CodeCompletionChunk rightParen{CodeCompletionChunk::RightParen, Utf8StringLiteral(")")};
- CodeCompletionChunk comma{CodeCompletionChunk::Comma, Utf8StringLiteral(", ")};
- CodeCompletionChunk semicolon{CodeCompletionChunk::SemiColon, Utf8StringLiteral(";")};
- CodeCompletionChunk colonColonText{CodeCompletionChunk::Text, Utf8StringLiteral("::")};
- CodeCompletionChunk functionArgumentX{CodeCompletionChunk::Placeholder, Utf8StringLiteral("char x")};
- CodeCompletionChunk functionArgumentXAsCurrentParameter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("char x")};
- CodeCompletionChunk functionArgumentY{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int y")};
- CodeCompletionChunk functionArgumentYAsCurrentParamter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("int y")};
- CodeCompletionChunk functionArgumentZ{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int z")};
- CodeCompletionChunk functionArgumentTemplate{CodeCompletionChunk::Placeholder, Utf8StringLiteral("const Foo<int> &foo")};
- CodeCompletionChunk switchName{CodeCompletionChunk::TypedText, Utf8StringLiteral("switch")};
- CodeCompletionChunk condition{CodeCompletionChunk::Placeholder, Utf8StringLiteral("condition")};
- CodeCompletionChunk leftBrace{CodeCompletionChunk::LeftBrace, Utf8StringLiteral("{")};
- CodeCompletionChunk rightBrace{CodeCompletionChunk::RightBrace, Utf8StringLiteral("}")};
- CodeCompletionChunk verticalSpace{CodeCompletionChunk::VerticalSpace, Utf8StringLiteral("\n")};
- CodeCompletionChunk throwName{CodeCompletionChunk::TypedText, Utf8StringLiteral("throw")};
- CodeCompletionChunk voidResultType{CodeCompletionChunk::ResultType, Utf8StringLiteral("void")};
- CodeCompletionChunk forName{CodeCompletionChunk::TypedText, Utf8StringLiteral("for")};
- CodeCompletionChunk initStatement{CodeCompletionChunk::Placeholder, Utf8StringLiteral("init-statement")};
- CodeCompletionChunk initExpression{CodeCompletionChunk::Placeholder, Utf8StringLiteral("init-expression")};
- CodeCompletionChunk statements{CodeCompletionChunk::Placeholder, Utf8StringLiteral("statements")};
- CodeCompletionChunk constCastName{CodeCompletionChunk::TypedText, Utf8StringLiteral("const_cast")};
- CodeCompletionChunk leftAngle{CodeCompletionChunk::LeftAngle, Utf8StringLiteral("<")};
- CodeCompletionChunk rightAngle{CodeCompletionChunk::RightAngle, Utf8StringLiteral(">")};
- CodeCompletionChunk elseName{CodeCompletionChunk::TypedText, Utf8StringLiteral("else")};
- CodeCompletionChunk ifName{CodeCompletionChunk::TypedText, Utf8StringLiteral("if")};
- CodeCompletionChunk horizontalSpace{CodeCompletionChunk::HorizontalSpace, Utf8StringLiteral(" ")};
- CodeCompletionChunk enableIfT{CodeCompletionChunk::TypedText, Utf8StringLiteral("enable_if_t")};
- CodeCompletionChunk enableIfTCondition{CodeCompletionChunk::Placeholder, Utf8StringLiteral("_Cond")};
- CodeCompletionChunk optionalEnableIfTType{CodeCompletionChunk::Placeholder, Utf8StringLiteral("_Tp"), true};
- CodeCompletionChunk optionalComma{CodeCompletionChunk::Comma, Utf8StringLiteral(", "), true};
- CodeCompletionChunk optionalFunctionArgumentY{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int y"), true};
- CodeCompletionChunk optionalFunctionArgumentYAsCurrentParameter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("int y"), true};
- CodeCompletionChunk optionalFunctionArgumentZ{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int z"), true};
-};
-
-TEST_F(CompletionChunksToTextConverter, ParseIsClearingText)
-{
- CodeCompletionChunks completionChunks({integerResultType, functionName, leftParen, rightParen});
- converter.setAddResultType(true);
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("int Function()"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertFunction)
-{
- CodeCompletionChunks completionChunks({integerResultType, functionName, leftParen, rightParen});
- converter.setAddResultType(true);
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("int Function()"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertFunctionWithParameters)
-{
- CodeCompletionChunks completionChunks({integerResultType, functionName, leftParen, functionArgumentX,rightParen});
- converter.setAddResultType(true);
- converter.setAddPlaceHolderText(true);
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("int Function(char x)"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneArgument)
-{
- CodeCompletionChunks completionChunks({integerResultType,
- functionName,
- leftParen,
- functionArgumentXAsCurrentParameter,
- rightParen});
-
- ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(
- completionChunks,
- ClangBackEnd::CodeCompletion::FunctionCompletionKind),
- QStringLiteral("int Function(char x)"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneParameterThatIsActive)
-{
- CodeCompletionChunks completionChunks({integerResultType,
- functionName,
- leftParen,
- functionArgumentXAsCurrentParameter,
- rightParen});
-
- ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(
- completionChunks,
- ClangBackEnd::CodeCompletion::FunctionCompletionKind,
- 1),
- QStringLiteral("int Function(<b>char x</b>)"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParametersWhereOneIsActive)
-{
- CodeCompletionChunks completionChunks({integerResultType,
- functionName,
- leftParen,
- functionArgumentX,
- comma,
- functionArgumentYAsCurrentParamter,
- rightParen});
-
- ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(
- completionChunks,
- ClangBackEnd::CodeCompletion::FunctionCompletionKind,
- 2),
- QStringLiteral("int Function(char x, <b>int y</b>)"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParametersWhereOneIsOptionalAndActive)
-{
- CodeCompletionChunks completionChunks({integerResultType,
- functionName,
- leftParen,
- functionArgumentX,
- optionalComma,
- optionalFunctionArgumentYAsCurrentParameter,
- rightParen});
-
- ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(
- completionChunks,
- ClangBackEnd::CodeCompletion::FunctionCompletionKind,
- 2),
- QStringLiteral("int Function(char x<i>, <b>int y</b></i>)"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTemplateReturnType)
-{
- CodeCompletionChunks completionChunks({templateResultType,
- functionName,
- leftParen,
- functionArgumentX,
- rightParen});
-
- using ClangCodeModel::Internal::CompletionChunksToTextConverter;
-
- ASSERT_THAT(CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(
- completionChunks,
- ClangBackEnd::CodeCompletion::FunctionCompletionKind),
- QStringLiteral("Foo&lt;int&gt; Function(char x)"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTemplateArgument)
-{
- CodeCompletionChunks completionChunks({integerResultType,
- functionName,
- leftParen,
- functionArgumentTemplate,
- rightParen});
-
- using ClangCodeModel::Internal::CompletionChunksToTextConverter;
-
- ASSERT_THAT(CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(
- completionChunks,
- ClangBackEnd::CodeCompletion::FunctionCompletionKind),
- QStringLiteral("int Function(const Foo&lt;int&gt; &amp;foo)"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertFunctionWithOptionalParameter)
-{
- CodeCompletionChunks completionChunks({integerResultType,
- functionName,
- leftParen,
- functionArgumentX,
- optionalComma,
- optionalFunctionArgumentY,
- optionalComma,
- optionalFunctionArgumentZ,
- rightParen});
-
- ASSERT_THAT(Converter::convertToToolTipWithHtml(completionChunks,
- ClangBackEnd::CodeCompletion::FunctionCompletionKind),
- QStringLiteral("int Function(char x<i>, int y, int z</i>)"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ConvertVariable)
-{
- CodeCompletionChunks completionChunks({integerResultType, variableName});
- converter.setAddResultType(true);
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("int Variable"));
-}
-
-TEST_F(CompletionChunksToTextConverter, Enumerator)
-{
- CodeCompletionChunks completionChunks({enumerationResultType, enumeratorName});
- converter.setAddResultType(true);
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("Enumeration Enumerator"));
-}
-
-TEST_F(CompletionChunksToTextConverter, Enumeration)
-{
- CodeCompletionChunks completionChunks({className});
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("Class"));
-}
-
-TEST_F(CompletionChunksToTextConverter, SwitchAsKeyword)
-{
- CodeCompletionChunks completionChunks({switchName,
- leftParen,
- condition,
- rightParen,
- leftBrace,
- verticalSpace,
- rightBrace});
- converter.setupForKeywords();
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("switch () {\n\n}"));
- ASSERT_THAT(converter.placeholderPositions().at(0), 8);
-}
-
-TEST_F(CompletionChunksToTextConverter, SwitchAsName)
-{
- CodeCompletionChunks completionChunks({switchName,
- leftParen,
- condition,
- rightParen,
- leftBrace,
- verticalSpace,
- rightBrace});
-
- const QString text = ClangCodeModel::Internal::CompletionChunksToTextConverter::convertToName(
- completionChunks);
-
- ASSERT_THAT(text, QStringLiteral("switch(){}"));
-}
-
-TEST_F(CompletionChunksToTextConverter, For)
-{
- CodeCompletionChunks completionChunks({forName,
- leftParen,
- initStatement,
- semicolon,
- initExpression,
- semicolon,
- condition,
- rightParen,
- leftBrace,
- verticalSpace,
- statements,
- verticalSpace,
- rightBrace});
- converter.setupForKeywords();
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("for (;;) {\n\n}"));
-}
-
-TEST_F(CompletionChunksToTextConverter, const_cast)
-{
- CodeCompletionChunks completionChunks({constCastName,
- leftAngle,
- rightAngle,
- leftParen,
- rightParen});
- converter.setupForKeywords();
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("const_cast<>()"));
-}
-
-TEST_F(CompletionChunksToTextConverter, Throw)
-{
- CodeCompletionChunks completionChunks({voidResultType, throwName});
-
- auto completionName = Converter::convertToName(completionChunks);
-
- ASSERT_THAT(completionName, QStringLiteral("throw"));
-}
-
-TEST_F(CompletionChunksToTextConverter, ElseIf)
-{
- CodeCompletionChunks completionChunks({elseName,
- horizontalSpace,
- ifName,
- horizontalSpace,
- leftBrace,
- verticalSpace,
- statements,
- verticalSpace,
- rightBrace});
- converter.setupForKeywords();
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("else if {\n\n}"));
-}
-
-TEST_F(CompletionChunksToTextConverter, EnableIfT)
-{
- CodeCompletionChunks completionChunks({enableIfT,
- leftAngle,
- enableIfTCondition,
- optionalComma,
- optionalEnableIfTType,
- rightAngle});
- converter.setupForKeywords();
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("enable_if_t<>"));
-}
-
-TEST_F(CompletionChunksToTextConverter, Namespace)
-{
- CodeCompletionChunks completionChunks({namespaceName, colonColonText});
-
- converter.parseChunks(completionChunks);
-
- ASSERT_THAT(converter.text(), QStringLiteral("Namespace::"));
-}
-
-}
diff --git a/tests/unit/unittest/cursor-test.cpp b/tests/unit/unittest/cursor-test.cpp
deleted file mode 100644
index 521002f3d22..00000000000
--- a/tests/unit/unittest/cursor-test.cpp
+++ /dev/null
@@ -1,941 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "clangcompareoperators.h"
-#include "unittest-utility-functions.h"
-
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangstring.h>
-#include <cursor.h>
-#include <sourcelocation.h>
-#include <sourcerange.h>
-#include <clangtranslationunit.h>
-#include <unsavedfiles.h>
-
-using ClangBackEnd::Cursor;
-using ClangBackEnd::Document;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::Documents;
-using ClangBackEnd::ClangString;
-using ClangBackEnd::SourceRange;
-
-using testing::IsNull;
-using testing::NotNull;
-using testing::Gt;
-using testing::Contains;
-using testing::EndsWith;
-using testing::AllOf;
-using testing::Not;
-using testing::IsEmpty;
-using testing::StrEq;
-using testing::Eq;
-
-namespace {
-
-struct Data {
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp")};
- Document document{filePath,
- UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++11")}),
- {},
- documents};
- TranslationUnit translationUnit{filePath,
- filePath,
- document.translationUnit().cxIndex(),
- document.translationUnit().cxTranslationUnit()};
-};
-
-class Cursor : public ::testing::Test
-{
-public:
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-protected:
- static Data *d;
- const Document &document = d->document;
- const TranslationUnit &translationUnit = d->translationUnit;
-};
-
-
-
-TEST_F(Cursor, CreateNullCursor)
-{
- ::Cursor cursor;
-
- ASSERT_TRUE(cursor.isNull());
-}
-
-TEST_F(Cursor, CompareNullCursors)
-{
- ::Cursor cursor;
- ::Cursor cursor2;
-
- ASSERT_THAT(cursor, cursor2);
-}
-
-TEST_F(Cursor, IsNotValid)
-{
- ::Cursor cursor;
-
- ASSERT_FALSE(cursor.isValid());
-}
-
-TEST_F(Cursor, IsValid)
-{
- auto cursor = translationUnit.cursor();
-
- ASSERT_TRUE(cursor.isValid());
-}
-
-TEST_F(Cursor, IsTranslationUnit)
-{
- auto cursor = translationUnit.cursor();
-
- ASSERT_TRUE(cursor.isTranslationUnit());
-}
-
-TEST_F(Cursor, NullCursorIsNotTranslationUnit)
-{
- ::Cursor cursor;
-
- ASSERT_FALSE(cursor.isTranslationUnit());
-}
-
-TEST_F(Cursor, UnifiedSymbolResolution)
-{
- ::Cursor cursor;
-
- ASSERT_FALSE(cursor.unifiedSymbolResolution().hasContent());
-}
-
-TEST_F(Cursor, GetCursorAtLocation)
-{
- auto cursor = translationUnit.cursorAt(3, 6);
-
- ASSERT_THAT(cursor.unifiedSymbolResolution(), Eq("c:@F@function#I#"));
-}
-
-TEST_F(Cursor, GetCursoSourceLocation)
-{
- auto cursor = translationUnit.cursorAt(3, 6);
-
- ASSERT_THAT(cursor.sourceLocation(), translationUnit.sourceLocationAt(3, 6));
-}
-
-TEST_F(Cursor, GetCursoSourceRange)
-{
- auto cursor = translationUnit.cursorAt(3, 6);
-
- ASSERT_THAT(cursor.sourceRange(), SourceRange(translationUnit.sourceLocationAt(3, 1),
- translationUnit.sourceLocationAt(6, 2)));
-}
-
-TEST_F(Cursor, Mangling)
-{
- auto cursor = translationUnit.cursorAt(3, 6);
-
- ASSERT_TRUE(cursor.mangling().hasContent());
-}
-
-TEST_F(Cursor, Spelling)
-{
- auto cursor = translationUnit.cursorAt(3, 6);
-
- ASSERT_THAT(cursor.spelling().cString(), StrEq("function"));
-}
-
-TEST_F(Cursor, DisplayName)
-{
- auto cursor = translationUnit.cursorAt(3, 6);
-
- ASSERT_THAT(cursor.displayName(), Eq("function(int)"));
-}
-
-TEST_F(Cursor, BriefComment)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
-
- ASSERT_THAT(cursor.briefComment(), Eq("A brief comment"));
-}
-
-TEST_F(Cursor, RawComment)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
-
- ASSERT_THAT(cursor.rawComment(), Eq("/**\n * A brief comment\n */"));
-}
-
-TEST_F(Cursor, CommentRange)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
-
-
- ASSERT_THAT(cursor.commentRange(),
- SourceRange(translationUnit.sourceLocationAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 7, 1),
- translationUnit.sourceLocationAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 9, 4)));
-}
-
-TEST_F(Cursor, IsDefinition)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
-
- ASSERT_TRUE(cursor.isDefinition());
-}
-
-TEST_F(Cursor, ForwardDeclarationIsNotDefinition)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7);
-
- ASSERT_FALSE(cursor.isDefinition());
-}
-
-TEST_F(Cursor, GetDefinitionOfFowardDeclaration)
-{
- auto forwardDeclarationcursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7);
- auto definitionCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
-
- ASSERT_THAT(forwardDeclarationcursor.definition(), definitionCursor);
-}
-
-TEST_F(Cursor, CallToMethodeIsNotDynamic)
-{
- auto cursor = translationUnit.cursorAt(18, 5);
-
- ASSERT_FALSE(cursor.isDynamicCall());
-}
-
-TEST_F(Cursor, CallToAbstractVirtualMethodeIsDynamic)
-{
- auto cursor = translationUnit.cursorAt(19, 5);
-
- ASSERT_TRUE(cursor.isDynamicCall());
-}
-
-TEST_F(Cursor, CanonicalCursor)
-{
- auto forwardDeclarationcursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7);
- auto definitionCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
-
- ASSERT_THAT(definitionCursor.canonical(), forwardDeclarationcursor);
-}
-
-TEST_F(Cursor, ReferencedCursor)
-{
- auto functionCallCursor = translationUnit.cursorAt(18, 5);
- auto functionCursor = translationUnit.cursorAt(16, 17);
-
- ASSERT_THAT(functionCallCursor.referenced(), functionCursor);
-}
-
-TEST_F(Cursor, IsVirtual)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17);
-
- ASSERT_TRUE(cursor.isVirtualMethod());
-}
-
-TEST_F(Cursor, IsNotPureVirtualOnlyVirtual)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17);
-
- ASSERT_FALSE(cursor.isPureVirtualMethod());
-}
-
-TEST_F(Cursor, IsPureVirtual)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 16, 17);
-
- ASSERT_TRUE(cursor.isPureVirtualMethod());
-}
-
-TEST_F(Cursor, ConstantMethod)
-{
- auto cursor = translationUnit.cursorAt(31, 18);
-
- ASSERT_TRUE(cursor.isConstantMethod());
-}
-
-TEST_F(Cursor, IsStaticMethod)
-{
- auto cursor = translationUnit.cursorAt(36, 18);
-
- ASSERT_TRUE(cursor.isStaticMethod());
-}
-
-TEST_F(Cursor, TypeSpelling)
-{
- auto cursor = translationUnit.cursorAt(43, 5);
-
- ASSERT_THAT(cursor.type().utf8Spelling(), Utf8StringLiteral("lint"));
-}
-
-TEST_F(Cursor, CanonicalTypeSpelling)
-{
- auto cursor = translationUnit.cursorAt(43, 5);
-
- ASSERT_THAT(cursor.type().canonical().utf8Spelling(), Utf8StringLiteral("long long"));
-}
-
-TEST_F(Cursor, CanonicalTypeCStringSpelling)
-{
- auto cursor = translationUnit.cursorAt(43, 5);
-
- auto spelling = cursor.type().canonical().spelling();
-
- ASSERT_THAT(spelling.cString(), StrEq("long long"));
-}
-
-TEST_F(Cursor, CanonicalTypeIsNotType)
-{
- auto cursor = translationUnit.cursorAt(43, 5);
-
- ASSERT_THAT(cursor.type().canonical(), Not(cursor.type()));
-}
-
-TEST_F(Cursor, TypeDeclartionIsAlias)
-{
- auto declarationCursor = translationUnit.cursorAt(41, 5);
- auto lintCursor = translationUnit.cursorAt(39, 11);
-
- ASSERT_THAT(declarationCursor.type().declaration().type(), lintCursor.type());
-}
-
-TEST_F(Cursor, TypeIsConstantWithoutAliasLookup)
-{
- auto cursor = translationUnit.cursorAt(45, 16);
-
- ASSERT_TRUE(cursor.type().isConstant());
-}
-
-TEST_F(Cursor, ClassIsCompoundType)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
-
- ASSERT_TRUE(cursor.isCompoundType());
-}
-
-TEST_F(Cursor, StructIsCompoundType)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8);
-
- ASSERT_TRUE(cursor.isCompoundType());
-}
-
-TEST_F(Cursor, UnionIsCompoundType)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 33, 7);
-
- ASSERT_TRUE(cursor.isCompoundType());
-}
-
-TEST_F(Cursor, IsDeclaration)
-{
- auto cursor = translationUnit.cursorAt(41, 10);
-
- ASSERT_TRUE(cursor.isDeclaration());
-}
-
-TEST_F(Cursor, SemanticParent)
-{
- auto cursor = translationUnit.cursorAt(43, 6);
- auto expectedSemanticParent = translationUnit.cursorAt(36, 18);
-
- auto semanticParent = cursor.semanticParent();
-
- ASSERT_THAT(semanticParent, expectedSemanticParent);
-}
-
-TEST_F(Cursor, IsLocalVariableInMethod)
-{
- auto cursor = translationUnit.cursorAt(20, 9);
-
- ASSERT_TRUE(cursor.isLocalVariable());
-}
-
-TEST_F(Cursor, IsLocalVariableInStaticFunction)
-{
- auto cursor = translationUnit.cursorAt(43, 5);
-
- ASSERT_TRUE(cursor.isLocalVariable());
-}
-
-TEST_F(Cursor, IsLocalVariableInTemplateFunction)
-{
- auto cursor = translationUnit.cursorAt(52, 7);
-
- ASSERT_TRUE(cursor.isLocalVariable());
-}
-
-TEST_F(Cursor, IsLocalVariableInConversionOperator)
-{
- auto cursor = translationUnit.cursorAt(57, 9);
-
- ASSERT_TRUE(cursor.isLocalVariable());
-}
-
-TEST_F(Cursor, IsLocalVariableInOperator)
-{
- auto cursor = translationUnit.cursorAt(62, 9);
-
- ASSERT_TRUE(cursor.isLocalVariable());
-}
-
-TEST_F(Cursor, IsLocalVariableInConstructor)
-{
- auto cursor = translationUnit.cursorAt(13, 9);
-
- ASSERT_TRUE(cursor.isLocalVariable());
-}
-
-TEST_F(Cursor, IsLocalVariableInDestructor)
-{
- auto cursor = translationUnit.cursorAt(69, 9);
-
- ASSERT_TRUE(cursor.isLocalVariable());
-}
-
-TEST_F(Cursor, FindFunctionCaller)
-{
- auto functionCursor = translationUnit.cursorAt(92, 24);
- auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8);
-
- ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor);
-}
-
-TEST_F(Cursor, FindFunctionCallerPointer)
-{
- auto functionCursor = translationUnit.cursorAt(79, 25);
- auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8);
-
- ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor);
-}
-
-TEST_F(Cursor, FindFunctionCallerThis)
-{
- auto functionCursor = translationUnit.cursorAt(106, 5);
- auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 38, 8);
-
- ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor);
-}
-
-TEST_F(Cursor, NonPointerTypeForValue)
-{
- auto variableCursor = translationUnit.cursorAt(101, 10);
- auto variablePointerCursor = translationUnit.cursorAt(100, 11);
-
- ASSERT_THAT(variableCursor.nonPointerTupe(), variablePointerCursor.nonPointerTupe());
-}
-
-TEST_F(Cursor, HasFinalAttributeInFunction)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 30, 18);
-
- ASSERT_TRUE(cursor.hasFinalFunctionAttribute());
-}
-
-TEST_F(Cursor, HasNotFinalAttributeInFunction)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17);
-
- ASSERT_FALSE(cursor.hasFinalFunctionAttribute());
-}
-
-TEST_F(Cursor, HasFinalAttributeInClass)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8);
-
- ASSERT_TRUE(cursor.hasFinalClassAttribute());
-}
-
-TEST_F(Cursor, HasNotFinaAttributeInClass)
-{
- auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 38, 8);
-
- ASSERT_FALSE(cursor.hasFinalClassAttribute());
-}
-
-TEST_F(Cursor, HasOutputValues)
-{
- auto callExpressionCursor = translationUnit.cursorAt(117, 19);
- auto outputArgumentExpectedSourceLocation = translationUnit.cursorAt(117, 20).cxSourceRange();
-
- auto outputArgumentLocations = callExpressionCursor.outputArgumentRanges();
-
- ASSERT_THAT(outputArgumentLocations.size(), 2);
- ASSERT_THAT(outputArgumentLocations[0], outputArgumentExpectedSourceLocation);
-}
-
-TEST_F(Cursor, HasOnlyInputValues)
-{
- auto callExpressionCursor = translationUnit.cursorAt(118, 18);
-
- auto outputArgumentLocations = callExpressionCursor.outputArgumentRanges();
-
- ASSERT_THAT(outputArgumentLocations, IsEmpty());
-}
-
-TEST_F(Cursor, ArgumentCountIsZero)
-{
- auto cursor = translationUnit.cursorAt(121, 23);
-
- auto count = cursor.type().argumentCount();
-
- ASSERT_THAT(count, 0);
-}
-
-TEST_F(Cursor, ArgumentCountIsTwo)
-{
- auto cursor = translationUnit.cursorAt(122, 22);
-
- auto count = cursor.type().argumentCount();
-
- ASSERT_THAT(count, 2);
-}
-
-TEST_F(Cursor, ArgumentOneIsValue)
-{
- auto callExpressionCursor = translationUnit.cursorAt(122, 22);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isConstant());
- ASSERT_THAT(argument.kind(), CXType_Int);
-}
-
-TEST_F(Cursor, ArgumentTwoIsLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(122, 22);
-
- auto argument = callExpressionCursor.type().argument(1);
-
- ASSERT_THAT(argument.kind(), CXType_LValueReference);
-}
-
-TEST_F(Cursor, ArgumentTwoIsConstantReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(122, 22);
-
- auto argumentPointee = callExpressionCursor.type().argument(1);
-
- ASSERT_TRUE(argumentPointee.isConstantReference());
-}
-
-TEST_F(Cursor, CursorArgumentCount)
-{
- auto cursor = translationUnit.cursorAt(117, 19);
-
- ASSERT_THAT(cursor.kind(), CXCursor_CallExpr);
- ASSERT_THAT(cursor.argumentCount(), 4);
-}
-
-TEST_F(Cursor, CursorArgumentInputValue)
-{
- auto callExpressionCursor = translationUnit.cursorAt(117, 19);
- auto declarationReferenceExpressionCursor = translationUnit.cursorAt(117, 20);
-
- ASSERT_THAT(callExpressionCursor.argument(0), declarationReferenceExpressionCursor);
-}
-
-TEST_F(Cursor, IsConstantLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(125, 26);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isConstantReference());
-}
-
-TEST_F(Cursor, LValueReferenceIsNotConstantLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(124, 21);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isConstantReference());
-}
-
-TEST_F(Cursor, ValueIsNotConstantLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(123, 18);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isConstantReference());
-}
-
-TEST_F(Cursor, PointerToConstantNotConstantLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(126, 20);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isConstantReference());
-}
-
-TEST_F(Cursor, IsLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(124, 21);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isLValueReference());
-}
-
-TEST_F(Cursor, ConstantLValueReferenceIsLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(125, 26);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isLValueReference());
-}
-
-TEST_F(Cursor, ValueIsNotLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(123, 18);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isLValueReference());
-}
-
-TEST_F(Cursor, PointerIsNotLValueReference)
-{
- auto callExpressionCursor = translationUnit.cursorAt(126, 20);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isLValueReference());
-}
-
-TEST_F(Cursor, PointerToConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(126, 20);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isPointerToConstant());
-}
-
-TEST_F(Cursor, ValueIsNotPointerToConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(123, 18);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isPointerToConstant());
-}
-
-TEST_F(Cursor, PointerNotPointerToConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(127, 13);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isPointerToConstant());
-}
-
-TEST_F(Cursor, ConstantLValueReferenceIsNotPointerToConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(125, 26);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isPointerToConstant());
-}
-
-TEST_F(Cursor, IsConstantPointer)
-{
- auto callExpressionCursor = translationUnit.cursorAt(128, 21);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isConstantPointer());
-}
-
-TEST_F(Cursor, PointerToConstantIsNotConstantPointer)
-{
- auto callExpressionCursor = translationUnit.cursorAt(126, 20);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isConstantPointer());
-}
-
-TEST_F(Cursor, ConstValueIsNotConstantPointer)
-{
- auto callExpressionCursor = translationUnit.cursorAt(129, 23);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isConstantPointer());
-}
-
-TEST_F(Cursor, PointerToConstantIsReferencingConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(126, 20);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isReferencingConstant());
-}
-
-TEST_F(Cursor, ConstantReferenceIsReferencingConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(125, 26);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isReferencingConstant());
-}
-
-TEST_F(Cursor, LValueReferenceIsNotReferencingConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(124, 21);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isReferencingConstant());
-}
-
-TEST_F(Cursor, ValueIsNotReferencingConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(123, 18);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isReferencingConstant());
-}
-
-TEST_F(Cursor, PointerIsNotRefencingConstant)
-{
- auto callExpressionCursor = translationUnit.cursorAt(127, 13);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isReferencingConstant());
-}
-
-TEST_F(Cursor, PointerIsOutputArgument)
-{
- auto callExpressionCursor = translationUnit.cursorAt(127, 13);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isOutputArgument());
-}
-
-TEST_F(Cursor, ConstantReferenceIsNotOutputArgument)
-{
- auto callExpressionCursor = translationUnit.cursorAt(125, 26);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isOutputArgument());
-}
-
-TEST_F(Cursor, PointerToConstantIsNotOutputArgument)
-{
- auto callExpressionCursor = translationUnit.cursorAt(126, 20);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isOutputArgument()) << argument.isConstant() << argument.pointeeType().isConstant();
-}
-
-TEST_F(Cursor, ConstantPointerIsOutputArgument)
-{
- auto callExpressionCursor = translationUnit.cursorAt(128, 21);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isOutputArgument());
-}
-
-TEST_F(Cursor, ReferenceIsOutputArgument)
-{
- auto callExpressionCursor = translationUnit.cursorAt(124, 21);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_TRUE(argument.isOutputArgument());
-}
-
-TEST_F(Cursor, ConstReferenceIsNotOutputArgument)
-{
- auto callExpressionCursor = translationUnit.cursorAt(125, 26);
-
- auto argument = callExpressionCursor.type().argument(0);
-
- ASSERT_FALSE(argument.isOutputArgument());
-}
-
-TEST_F(Cursor, ResultType)
-{
- auto methodCursor = translationUnit.cursorAt(31, 18);
-
- Utf8String resultType = methodCursor.type().resultType().spelling();
-
- ASSERT_THAT(resultType, Utf8String("bool", 4));
-}
-
-TEST_F(Cursor, PrivateMethodAccessSpecifier)
-{
- auto methodCursor = translationUnit.cursorAt(16, 17);
-
- auto accessSpecifier = methodCursor.accessSpecifier();
-
- ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Private);
-}
-
-TEST_F(Cursor, PublicMethodAccessSpecifier)
-{
- auto methodCursor = translationUnit.cursorAt(79, 25);
-
- auto accessSpecifier = methodCursor.accessSpecifier();
-
- ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Public);
-}
-
-TEST_F(Cursor, ProtectedMethodAccessSpecifier)
-{
- auto methodCursor = translationUnit.cursorAt(131, 22);
-
- auto accessSpecifier = methodCursor.accessSpecifier();
-
- ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Protected);
-}
-
-TEST_F(Cursor, PrivateFieldAccessSpecifier)
-{
- auto fieldCursor = translationUnit.cursorAt(21, 12);
-
- auto accessSpecifier = fieldCursor.accessSpecifier();
-
- ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Private);
-}
-
-TEST_F(Cursor, InvalidAccessSpecifier)
-{
- auto localVarCursor = translationUnit.cursorAt(62, 9);
-
- auto accessSpecifier = localVarCursor.accessSpecifier();
-
- ASSERT_THAT(accessSpecifier, ClangBackEnd::AccessSpecifier::Invalid);
-}
-
-TEST_F(Cursor, NoStorageClass)
-{
- auto localVarCursor = translationUnit.cursorAt(62, 9);
-
- auto storageClass = localVarCursor.storageClass();
-
- ASSERT_THAT(storageClass, ClangBackEnd::StorageClass::None);
-}
-
-TEST_F(Cursor, ExternVarStorageClass)
-{
- auto externalVarCursor = translationUnit.cursorAt(133, 12);
-
- auto storageClass = externalVarCursor.storageClass();
-
- ASSERT_THAT(storageClass, ClangBackEnd::StorageClass::Extern);
-}
-
-TEST_F(Cursor, StaticMethodStorageClass)
-{
- auto methodCursor = translationUnit.cursorAt(135, 13);
-
- auto storageClass = methodCursor.storageClass();
-
- ASSERT_THAT(storageClass, ClangBackEnd::StorageClass::Static);
-}
-
-TEST_F(Cursor, InvalidStorageClass)
-{
- auto functionTemplateCursor = translationUnit.cursorAt(137, 28);
-
- auto storageClass = functionTemplateCursor.storageClass();
-
- ASSERT_THAT(storageClass, ClangBackEnd::StorageClass::Invalid);
-}
-
-TEST_F(Cursor, IsAnonymousNamespace)
-{
- auto anonymousCursor = translationUnit.cursorAt(140, 1);
-
- bool anonymous = anonymousCursor.isAnonymous();
-
- ASSERT_THAT(anonymous, true);
-}
-
-TEST_F(Cursor, IsNotAnonymousNamespace)
-{
- auto anonymousCursor = translationUnit.cursorAt(139, 1);
-
- bool anonymous = anonymousCursor.isAnonymous();
-
- ASSERT_THAT(anonymous, false);
-}
-
-TEST_F(Cursor, AnonymousNamespaceDisplayName)
-{
- auto anonymousCursor = translationUnit.cursorAt(140, 1);
-
- auto name = anonymousCursor.displayName();
-
- ASSERT_THAT(name, Utf8String("(anonymous)"));
-}
-
-TEST_F(Cursor, AnonymousEnumDisplayName)
-{
- auto anonymousCursor = translationUnit.cursorAt(144, 1);
-
- auto name = anonymousCursor.displayName();
-
- ASSERT_THAT(name, Utf8String("(anonymous)"));
-}
-
-Data *Cursor::d;
-
-void Cursor::SetUpTestCase()
-{
- d = new Data;
- d->document.parse();
-}
-
-void Cursor::TearDownTestCase()
-{
- delete d;
- d = nullptr;
-}
-
-}
diff --git a/tests/unit/unittest/data/complete_arrow.cpp b/tests/unit/unittest/data/complete_arrow.cpp
deleted file mode 100644
index 2d969e2bfbd..00000000000
--- a/tests/unit/unittest/data/complete_arrow.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
- foo->
-}
diff --git a/tests/unit/unittest/data/complete_completer_main.cpp b/tests/unit/unittest/data/complete_completer_main.cpp
deleted file mode 100644
index 877ce23d286..00000000000
--- a/tests/unit/unittest/data/complete_completer_main.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "complete_forwarding_header_1.h"
-
-void Function()
-{
-
-}
-
-class Foo;
-void FunctionWithArguments(int i, char *c, const Foo &ref)
-{
-
-}
-
-void SavedFunction()
-{
-
-}
-
-
-
-
-
-
-
-void f()
-{
-
-}
diff --git a/tests/unit/unittest/data/complete_completer_main_unsaved.cpp b/tests/unit/unittest/data/complete_completer_main_unsaved.cpp
deleted file mode 100644
index 38af12b8583..00000000000
--- a/tests/unit/unittest/data/complete_completer_main_unsaved.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "complete_forwarding_header_2.h"
-
-void Function()
-{
-
-}
-
-class Foo;
-void FunctionWithArguments(int i, char *c, const Foo &ref)
-{
-
-}
-
-void UnsavedFunction()
-{
-
-}
-
-#define Macro
-
-int GlobalVariableInUnsavedFile;
-
-void f()
-{
- int VariableInUnsavedFile;
-
-
-}
diff --git a/tests/unit/unittest/data/complete_extractor_brief_comment.cpp b/tests/unit/unittest/data/complete_extractor_brief_comment.cpp
deleted file mode 100644
index 89ffa79e427..00000000000
--- a/tests/unit/unittest/data/complete_extractor_brief_comment.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * A brief comment
- */
-void BriefComment()
-{
-
-}
-
-void f() {
-
-}
diff --git a/tests/unit/unittest/data/complete_extractor_class.cpp b/tests/unit/unittest/data/complete_extractor_class.cpp
deleted file mode 100644
index 218b5fbe25d..00000000000
--- a/tests/unit/unittest/data/complete_extractor_class.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-class Class {};
-struct Struct{};
-union Union{};
-typedef Class TypeDef;
-using UsingClass = Class;
-template<class T> class TemplateClass{};
-template<class T> class ClassTemplatePartialSpecialization;
-template<class T> class ClassTemplatePartialSpecialization<T*>;
-
-
-
-
-
-
-
-
-template<class TemplateTypeParameter, template<class> class TemplateTemplateParameter>
-void function()
-{
-
-}
diff --git a/tests/unit/unittest/data/complete_extractor_constructor.cpp b/tests/unit/unittest/data/complete_extractor_constructor.cpp
deleted file mode 100644
index e28ccaea824..00000000000
--- a/tests/unit/unittest/data/complete_extractor_constructor.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-class Constructor {
- Constructor();
- ~Constructor();
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- void function()
- {
-
- }
-};
diff --git a/tests/unit/unittest/data/complete_extractor_constructorMemberInitialization.cpp b/tests/unit/unittest/data/complete_extractor_constructorMemberInitialization.cpp
deleted file mode 100644
index bbbe8ccfb81..00000000000
--- a/tests/unit/unittest/data/complete_extractor_constructorMemberInitialization.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-class Constructor {
- Constructor() : {}
-
- int member;
-};
diff --git a/tests/unit/unittest/data/complete_extractor_enumeration.cpp b/tests/unit/unittest/data/complete_extractor_enumeration.cpp
deleted file mode 100644
index 79973a616b0..00000000000
--- a/tests/unit/unittest/data/complete_extractor_enumeration.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-enum Enumeration {
- Enumerator
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-void function()
-{
-
-}
-
diff --git a/tests/unit/unittest/data/complete_extractor_function.cpp b/tests/unit/unittest/data/complete_extractor_function.cpp
deleted file mode 100644
index 6a3d1bf73ac..00000000000
--- a/tests/unit/unittest/data/complete_extractor_function.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-void Function();
-template<class T> void TemplateFunction();
-void FunctionWithOptional(int x, char y = 1, int z = 5);
-#define FunctionMacro(X, Y) X + Y
-
-class base {
- void NotAccessibleFunction();
-};
-class Class : public base {
- void Method();
- void MethodWithParameters(int x = 30);
- __attribute__((annotate("qt_slot"))) void Slot();
- __attribute__((annotate("qt_signal"))) void Signal();
- __attribute__ ((deprecated)) void DeprecatedFunction();
- void NotAvailableFunction() = delete;
-
-public:
- void function()
- {
-
- }
-};
diff --git a/tests/unit/unittest/data/complete_extractor_function_unsaved.cpp b/tests/unit/unittest/data/complete_extractor_function_unsaved.cpp
deleted file mode 100644
index adab53527b4..00000000000
--- a/tests/unit/unittest/data/complete_extractor_function_unsaved.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-void Function();
-template<class T> void TemplateFunction();
-
-#define FunctionMacro(X, Y) X + Y
-
-class base {
- void NotAccessibleFunction();
-};
-class Class : public base {
- void Method2();
- void MethodWithParameters(int x = 30);
- __attribute__((annotate("qt_slot"))) void Slot();
- __attribute__((annotate("qt_signal"))) void Signal();
- __attribute__ ((deprecated)) void DeprecatedFunction();
- void NotAvailableFunction() = delete;
-
-public:
- void function()
- {
-
- }
-};
diff --git a/tests/unit/unittest/data/complete_extractor_function_unsaved_2.cpp b/tests/unit/unittest/data/complete_extractor_function_unsaved_2.cpp
deleted file mode 100644
index 08153184f46..00000000000
--- a/tests/unit/unittest/data/complete_extractor_function_unsaved_2.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-void Function();
-template<class T> void TemplateFunction();
-
-#define FunctionMacro(X, Y) X + Y
-
-class base {
- void NotAccessibleFunction();
-};
-class Class : public base {
- void Method3();
- void MethodWithParameters(int x = 30);
- __attribute__((annotate("qt_slot"))) void Slot();
- __attribute__((annotate("qt_signal"))) void Signal();
- __attribute__ ((deprecated)) void DeprecatedFunction();
- void NotAvailableFunction() = delete;
-
-public:
- void function()
- {
-
- }
-};
diff --git a/tests/unit/unittest/data/complete_extractor_functionoverload.cpp b/tests/unit/unittest/data/complete_extractor_functionoverload.cpp
deleted file mode 100644
index fa447158f4f..00000000000
--- a/tests/unit/unittest/data/complete_extractor_functionoverload.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-struct Foo {
- Foo(const Foo &foo);
- Foo(char c);
-};
-
-void f()
-{
- Foo foo(
-}
diff --git a/tests/unit/unittest/data/complete_extractor_namespace.cpp b/tests/unit/unittest/data/complete_extractor_namespace.cpp
deleted file mode 100644
index 46d273da9d3..00000000000
--- a/tests/unit/unittest/data/complete_extractor_namespace.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Namespace {}
-namespace NamespaceAlias = Namespace;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-void function()
-{
-
-}
-
diff --git a/tests/unit/unittest/data/complete_extractor_private_function_definition.cpp b/tests/unit/unittest/data/complete_extractor_private_function_definition.cpp
deleted file mode 100644
index c2dd9e3daba..00000000000
--- a/tests/unit/unittest/data/complete_extractor_private_function_definition.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-class Foo {
- void method();
-};
-
-void Foo::m
diff --git a/tests/unit/unittest/data/complete_extractor_variable.cpp b/tests/unit/unittest/data/complete_extractor_variable.cpp
deleted file mode 100644
index e8a67f9c6cd..00000000000
--- a/tests/unit/unittest/data/complete_extractor_variable.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-void function(int Parameter)
-{
- int Var = 0;
-
-}
-
-void function2()
-{
- int Var = 0;
- auto Lambda = [&Var]()
- {
-
- };
-}
-
-class Class {
- int Field;
-
- void function() {
-
- }
-};
-
-template <int NonTypeTemplateParameter>
-void function3() {}
-
-#define MacroDefinition
-
-
-void function4()
-{
-#ifdef ArgumentDefinition
- int ArgumentDefinitionVariable;
-#endif
-
-}
diff --git a/tests/unit/unittest/data/complete_forwarding_header_1.h b/tests/unit/unittest/data/complete_forwarding_header_1.h
deleted file mode 100644
index ebd822c41bf..00000000000
--- a/tests/unit/unittest/data/complete_forwarding_header_1.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-#include <complete_target_header.h>
diff --git a/tests/unit/unittest/data/complete_forwarding_header_2.h b/tests/unit/unittest/data/complete_forwarding_header_2.h
deleted file mode 100644
index ebd822c41bf..00000000000
--- a/tests/unit/unittest/data/complete_forwarding_header_2.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-#include <complete_target_header.h>
diff --git a/tests/unit/unittest/data/complete_smartpointer.cpp b/tests/unit/unittest/data/complete_smartpointer.cpp
deleted file mode 100644
index a6e7d73a58a..00000000000
--- a/tests/unit/unittest/data/complete_smartpointer.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-namespace std {
-template<class Type, class... Args>
-class unique_ptr {};
-
-template<class Type, class... Args>
-class shared_ptr {
-public:
- void reset();
- Type *operator->();
-};
-
-template<class Type, class... Args>
-unique_ptr<Type> make_unique(Args&&... args);
-
-template<class Type, class... Args>
-shared_ptr<Type> make_shared(Args&&... args);
-} // namespace std
-
-template<class Type>
-class QSharedPointer
-{
-public:
- template<class... Args>
- static QSharedPointer<Type> create(Args&&... args);
-};
-
-class Bar
-{
-public:
- Bar();
- Bar(int, int);
-};
-void f2()
-{
- std::unique_ptr<Bar> bar = std::make_unique<Bar>();
- std::shared_ptr<Bar> bar2 = std::make_shared<Bar>();
- QSharedPointer<Bar> bar3 = QSharedPointer<Bar>::create();
- bar2->
-}
diff --git a/tests/unit/unittest/data/complete_target_header.h b/tests/unit/unittest/data/complete_target_header.h
deleted file mode 100644
index 67bc13701d0..00000000000
--- a/tests/unit/unittest/data/complete_target_header.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void FunctionInIncludedHeader();
diff --git a/tests/unit/unittest/data/complete_target_header_changed.h b/tests/unit/unittest/data/complete_target_header_changed.h
deleted file mode 100644
index be7ac4e5320..00000000000
--- a/tests/unit/unittest/data/complete_target_header_changed.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-void FunctionInIncludedHeader();
-void FunctionInIncludedHeaderChanged();
diff --git a/tests/unit/unittest/data/complete_target_header_unsaved.h b/tests/unit/unittest/data/complete_target_header_unsaved.h
deleted file mode 100644
index 7007f9b5fe2..00000000000
--- a/tests/unit/unittest/data/complete_target_header_unsaved.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-void FunctionInIncludedHeader();
-void FunctionInIncludedHeaderUnsaved();
diff --git a/tests/unit/unittest/data/complete_testfile_1.cpp b/tests/unit/unittest/data/complete_testfile_1.cpp
deleted file mode 100644
index d53b0a1e98b..00000000000
--- a/tests/unit/unittest/data/complete_testfile_1.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-void function()
-{
-
-}
-
-class Foo;
-void functionWithArguments(int i, char *c, const Foo &ref)
-{
-
-}
-
-void otherFunction()
-{
-
-}
-
-void f()
-{
-
-}
diff --git a/tests/unit/unittest/data/complete_translationunit_parse_error.cpp b/tests/unit/unittest/data/complete_translationunit_parse_error.cpp
deleted file mode 100644
index 288cef2a330..00000000000
--- a/tests/unit/unittest/data/complete_translationunit_parse_error.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-NAMESPACE {
-
diff --git a/tests/unit/unittest/data/complete_withDotArrowCorrectionForForwardDeclaredClassPointer.cpp b/tests/unit/unittest/data/complete_withDotArrowCorrectionForForwardDeclaredClassPointer.cpp
deleted file mode 100644
index 46e7e9d08bb..00000000000
--- a/tests/unit/unittest/data/complete_withDotArrowCorrectionForForwardDeclaredClassPointer.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-struct Bar;
-
-void g(Bar *bar)
-{
- bar.
-}
diff --git a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer.cpp b/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer.cpp
deleted file mode 100644
index 9f8d3645b2e..00000000000
--- a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
- foo.
-}
diff --git a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointerInitial.cpp b/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointerInitial.cpp
deleted file mode 100644
index 0472cfacaa4..00000000000
--- a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointerInitial.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
-
-}
diff --git a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointerUpdated.cpp b/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointerUpdated.cpp
deleted file mode 100644
index 9f8d3645b2e..00000000000
--- a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointerUpdated.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
- foo.
-}
diff --git a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer_afterTyping.cpp b/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer_afterTyping.cpp
deleted file mode 100644
index 9f8d3645b2e..00000000000
--- a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer_afterTyping.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
- foo.
-}
diff --git a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer_beforeTyping.cpp b/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer_beforeTyping.cpp
deleted file mode 100644
index 0472cfacaa4..00000000000
--- a/tests/unit/unittest/data/complete_withDotArrowCorrectionForPointer_beforeTyping.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
-
-}
diff --git a/tests/unit/unittest/data/complete_withGlobalCompletionAfterForwardDeclaredClassPointer.cpp b/tests/unit/unittest/data/complete_withGlobalCompletionAfterForwardDeclaredClassPointer.cpp
deleted file mode 100644
index 66ef372934f..00000000000
--- a/tests/unit/unittest/data/complete_withGlobalCompletionAfterForwardDeclaredClassPointer.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-struct Bar;
-
-void g(Bar *bar)
-{
- bar->
- // white space preserver
-}
diff --git a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForArrowDot.cpp b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForArrowDot.cpp
deleted file mode 100644
index 304c17c05b6..00000000000
--- a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForArrowDot.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
- foo->.
-}
-
diff --git a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForColonColon.cpp b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForColonColon.cpp
deleted file mode 100644
index 62af4343c10..00000000000
--- a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForColonColon.cpp
+++ /dev/null
@@ -1 +0,0 @@
-Blah::
diff --git a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForDotDot.cpp b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForDotDot.cpp
deleted file mode 100644
index 8f77989da67..00000000000
--- a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForDotDot.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
- foo..
-}
-
diff --git a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForFloat.cpp b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForFloat.cpp
deleted file mode 100644
index c27a0ee8f08..00000000000
--- a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForFloat.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-void f()
-{
- float pi = 3.
-}
diff --git a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForObject.cpp b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForObject.cpp
deleted file mode 100644
index d2e3b88da7c..00000000000
--- a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForObject.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo foo)
-{
- foo.
-}
diff --git a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForObjectWithArrowOperator.cpp b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForObjectWithArrowOperator.cpp
deleted file mode 100644
index 6a741603a18..00000000000
--- a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForObjectWithArrowOperator.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-struct Foo {
- Foo *operator->();
- int member;
-};
-
-void g(Foo foo)
-{
- foo.
-}
diff --git a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForOnlyDot.cpp b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForOnlyDot.cpp
deleted file mode 100644
index 1607d6a6fbd..00000000000
--- a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForOnlyDot.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-struct Foo { int member; };
-
-void g(Foo *foo)
-{
- . // white space preserver
-}
-
diff --git a/tests/unit/unittest/data/completions_order.cpp b/tests/unit/unittest/data/completions_order.cpp
deleted file mode 100644
index 3812225ad75..00000000000
--- a/tests/unit/unittest/data/completions_order.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-class Constructor {
-public:
- Constructor() = default;
- Constructor(int) {}
-};
-
-void testConstructor() {
-
-}
-
-class Base {
- virtual void bar(int a) const;
-};
-
-class DifferentPriorities : public Base {
-public:
- void foo();
- void foo() const;
- void bar(int a) const override;
- void testBar() {
-
- }
-};
-
-void testPriorities() {
- DifferentPriorities d;
- d.
-}
-
-class LexicographicalSorting
-{
-public:
- void memberFuncBB();
- void memberFuncC();
- void memberFuncAAA() const;
-};
-
-void testLexicographicalSorting() {
- LexicographicalSorting ls;
- ls.memberFunc
-}
diff --git a/tests/unit/unittest/data/cursor.cpp b/tests/unit/unittest/data/cursor.cpp
deleted file mode 100644
index 82df2cb378c..00000000000
--- a/tests/unit/unittest/data/cursor.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-#include "cursor.h"
-
-void function(int x)
-{
-
-}
-
-namespace Namespace
-{
-SuperClass::SuperClass(int x) noexcept
- : y(x)
-{
- int LocalVariable;
-}
-
-int SuperClass::Method()
-{
- Method();
- AbstractVirtualMethod(y);
- int LocalVariable;
- return y;
-}
-
-int SuperClass::VirtualMethod(int z)
-{
- AbstractVirtualMethod(z);
-
- return y;
-}
-
-bool SuperClass::ConstMethod() const
-{
- return y;
-}
-
-void SuperClass::StaticMethod()
-{
- using longint = long long int;
- using lint = longint;
-
- lint foo;
-
- foo = 30;
-
- const lint bar = 20;
-}
-}
-
-template <class T>
-void TemplateFunction(T LocalVariableParameter)
-{
- T LocalVariable;
-}
-
-Namespace::SuperClass::operator int() const
-{
- int LocalVariable;
-}
-
-int Namespace::SuperClass::operator ++() const
-{
- int LocalVariable;
-
- return LocalVariable;
-}
-
-Namespace::SuperClass::~SuperClass()
-{
- int LocalVariable;
-}
-
-void Struct::FinalVirtualMethod()
-{
-
-}
-
-void f1(Struct *FindFunctionCaller)
-{
- FindFunctionCaller->FinalVirtualMethod();
-}
-
-void f2(){
- Struct *s = new Struct;
-
- f1(s);
-}
-
-void f3()
-{
- auto FindFunctionCaller = Struct();
-
- FindFunctionCaller.FinalVirtualMethod();
-}
-
-
-void f4()
-{
- Struct s;
-
- auto *sPointer = &s;
- auto sValue = s;
-}
-
-void NonFinalStruct::function()
-{
- FinalVirtualMethod();
-}
-
-void OutputFunction(int &out, int in = 1, const int &in2=2, int *out2=nullptr);
-void InputFunction(const int &value);
-
-void f5()
-{
- int OutputValue;
- int InputValue = 20;
-
- OutputFunction(OutputValue);
- InputFunction(InputValue);
-}
-
-void ArgumentCountZero();
-void ArgumentCountTwo(int one, const int &two);
-void IntegerValue(int);
-void LValueReference(int &);
-void ConstLValueReference(const int &);
-void PointerToConst(const int *);
-void Pointer(int *);
-void ConstantPointer(int *const);
-void ConstIntegerValue(const int);
-
-void NonFinalStruct::ProtectedMethodAccessSpecifier() {}
-
-extern int ExternVarStorageClass;
-
-static void StaticMethodStorageClass() {}
-
-template<class T> const T &InvalidStorageClass(const T &type) { return type; }
-
-namespace Outer {
-namespace {
-
-}
-
-enum {
- X, Y
-};
-}
diff --git a/tests/unit/unittest/data/cursor.h b/tests/unit/unittest/data/cursor.h
deleted file mode 100644
index 7db9be6e97b..00000000000
--- a/tests/unit/unittest/data/cursor.h
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-namespace Namespace
-{
-class SuperClass;
-/**
- * A brief comment
- */
-class SuperClass
-{
- SuperClass() = default;
- SuperClass(int x) noexcept;
- int Method();
- virtual int VirtualMethod(int z);
- virtual int AbstractVirtualMethod(int z) = 0;
- bool ConstMethod() const;
- static void StaticMethod();
- operator int() const;
- int operator ++() const;
- ~SuperClass();
-
-private:
- int y;
-};
-}
-
-struct Struct final
-{
- virtual void FinalVirtualMethod() final;
-};
-
-union Union
-{
-
-};
-
-struct NonFinalStruct
-{
- virtual void FinalVirtualMethod() final;
- void function();
-protected:
- void ProtectedMethodAccessSpecifier();
-};
diff --git a/tests/unit/unittest/data/diagnostic_diagnostic.cpp b/tests/unit/unittest/data/diagnostic_diagnostic.cpp
deleted file mode 100644
index 51423c20b51..00000000000
--- a/tests/unit/unittest/data/diagnostic_diagnostic.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-int noReturnValue()
-{
-}
-
-void f(int)
-{
- f();
-}
diff --git a/tests/unit/unittest/data/diagnostic_diagnosticset.cpp b/tests/unit/unittest/data/diagnostic_diagnosticset.cpp
deleted file mode 100644
index 20ea8ffe1e4..00000000000
--- a/tests/unit/unittest/data/diagnostic_diagnosticset.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-int function()
-{
-
-}
-
diff --git a/tests/unit/unittest/data/diagnostic_diagnosticset_header.cpp b/tests/unit/unittest/data/diagnostic_diagnosticset_header.cpp
deleted file mode 100644
index cf05802cb6b..00000000000
--- a/tests/unit/unittest/data/diagnostic_diagnosticset_header.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-void f() {}
-
diff --git a/tests/unit/unittest/data/diagnostic_diagnosticset_mainfile.cpp b/tests/unit/unittest/data/diagnostic_diagnosticset_mainfile.cpp
deleted file mode 100644
index 323842ca580..00000000000
--- a/tests/unit/unittest/data/diagnostic_diagnosticset_mainfile.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "diagnostic_diagnosticset_header.cpp"
-
-void f() {}
-
diff --git a/tests/unit/unittest/data/diagnostic_erroneous_header.h b/tests/unit/unittest/data/diagnostic_erroneous_header.h
deleted file mode 100644
index 5dd2740c16c..00000000000
--- a/tests/unit/unittest/data/diagnostic_erroneous_header.h
+++ /dev/null
@@ -1,11 +0,0 @@
-int warningInHeader()
-{
-}
-
-void myfun()
-{
- int i = 0;
- if (i = 3) {}
-}
-
-errorInHeader;
diff --git a/tests/unit/unittest/data/diagnostic_erroneous_source.cpp b/tests/unit/unittest/data/diagnostic_erroneous_source.cpp
deleted file mode 100644
index a0efee52b54..00000000000
--- a/tests/unit/unittest/data/diagnostic_erroneous_source.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "diagnostic_erroneous_header.h"
-
-enum Numbers { One, Two, Three };
-
-void f(Numbers n)
-{
- switch (n) {
- case One: return;
- case Two: return;
- }
-}
-
-void g()
-{
- return 3;
-}
-
-void function()
-{
- int i = 0;
- if (i = 3) {}
-}
-
-
diff --git a/tests/unit/unittest/data/diagnostic_source_location.cpp b/tests/unit/unittest/data/diagnostic_source_location.cpp
deleted file mode 100644
index 537675c619e..00000000000
--- a/tests/unit/unittest/data/diagnostic_source_location.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-int function()
-{
-
-}
-
-int function2()
-{
- /*abcdЙf*/
-}
diff --git a/tests/unit/unittest/data/diagnostic_source_range.cpp b/tests/unit/unittest/data/diagnostic_source_range.cpp
deleted file mode 100644
index 121d402ea89..00000000000
--- a/tests/unit/unittest/data/diagnostic_source_range.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-class XXX
-{
-
-};
-
-int function(XXX i)
-{
- i + 20;
-}
-
-struct Foo {
- someIdentifierLeadingToInvalidRange;
-};
diff --git a/tests/unit/unittest/data/empty1.cpp b/tests/unit/unittest/data/empty1.cpp
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/tests/unit/unittest/data/empty1.cpp
+++ /dev/null
diff --git a/tests/unit/unittest/data/empty2.cpp b/tests/unit/unittest/data/empty2.cpp
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/tests/unit/unittest/data/empty2.cpp
+++ /dev/null
diff --git a/tests/unit/unittest/data/empty3.cpp b/tests/unit/unittest/data/empty3.cpp
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/tests/unit/unittest/data/empty3.cpp
+++ /dev/null
diff --git a/tests/unit/unittest/data/followsymbol_header.h b/tests/unit/unittest/data/followsymbol_header.h
deleted file mode 100644
index 86308340231..00000000000
--- a/tests/unit/unittest/data/followsymbol_header.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-#pragma once
-
-#define TEST_DEFINE 1
-namespace Fooish
-{
-float flvalue = 100.f;
-
-class Bar;
-
-class Bar {
-public:
- Bar();
-
- volatile int member = 0;
-};
-
-struct Barish
-{
- int foo(float p, int u);
- int mem = 10;
-};
-}
-
-class FooClass;
-
-int foo(const float p, int u);
-
-int foo();
-
-int foo(float p, int u)
-{
- return foo() + p + u;
-}
-
-int foo(int x, float y);
diff --git a/tests/unit/unittest/data/followsymbol_main.cpp b/tests/unit/unittest/data/followsymbol_main.cpp
deleted file mode 100644
index f967d8653be..00000000000
--- a/tests/unit/unittest/data/followsymbol_main.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-#include "followsymbol_header.h"
-#include "cursor.h"
-Fooish::Bar::Bar() {
-
-}
-
-class X;
-
-using YYY = Fooish::Bar;
-
-int foo() {
- YYY bar;
- bar.member = 30;
- Fooish::Barish barish;
- bar.member++;
- barish.mem = Fooish::flvalue;
-
- barish.foo(1.f, 2);
- foo(1, 2.f);
- return 1;
-
- X* x;
-}
-
-int Fooish::Barish::foo(float p, int u)
-{
- return ::foo() + p + u;
-}
-
-class FooClass
-{
-public:
- FooClass();
- static int mememember;
-};
-
-FooClass::FooClass() {
- NonFinalStruct nfStruct; nfStruct.function();
-}
-
-int main() {
- return foo() + FooClass::mememember + TEST_DEFINE;
-}
-
-class Bar
-{
-public:
- int operator&();
- Bar& operator[](int);
-};
-
-int Bar::operator&() {
- return 0;
-}
-
-Bar& Bar::operator[](int) {
- return *this;
-}
-
-struct S {
- union {
- int i = 12;
- void *something;
- };
- int func(bool b) {
- if (b)
- return i;
- int i = 42;
- return i;
- }
-};
diff --git a/tests/unit/unittest/data/highlightingmarks.cpp b/tests/unit/unittest/data/highlightingmarks.cpp
deleted file mode 100644
index 57f4586daba..00000000000
--- a/tests/unit/unittest/data/highlightingmarks.cpp
+++ /dev/null
@@ -1,811 +0,0 @@
-auto *Variable = "Variable";
-auto *u8Variable = u8"Variable";
-auto *rawVariable = R"(Variable)";
-auto Character = 'c';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-auto integer = 1;
-auto numFloat = 1.2f;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-int function(int x)
-{
- return x;
-}
-
-struct Foo
-{
- void memberFunction() {}
-};
-
-int functionDeclaration(int x);
-
-struct Foo2
-{
- void memberFunction();
-};
-
-void f()
-{
- function(1);
-}
-
-struct ConversionFunction {
- operator Foo();
- operator int();
-};
-
-void TypeReference()
-{
- Foo foo;
-}
-
-void LocalVariableDeclaration()
-{
- Foo foo;
-
- foo.memberFunction();
-}
-
-void LocalVariableFunctionArgument(Foo &foo)
-{
- foo.memberFunction();
-}
-
-struct Foo3 {
- int ClassMember;
-
- void ClassMemberReference()
- {
- ClassMember++;
- }
-};
-
-struct Foo4
-{
- void MemberFunctionReference();
-
- void function()
- {
- MemberFunctionReference();
- }
-};
-
-struct Foo5
-{
- void StaticMethod();
-
- void function()
- {
- Foo5::StaticMethod();
- }
-};
-
-enum Enumeration
-{
- Enumerator
-};
-
-void f2()
-{
- Enumeration enumeration;
-
- enumeration = Enumerator;
-}
-
-class ForwardReference;
-
-class Class
-{ public:
- Class();
- ~Class();
-};
-
-ForwardReference *f3()
-{
- Class ConstructorReference;
-
- return 0;
-}
-
-union Union
-{
-
-};
-
-Union UnionDeclarationReference;
-
-
-
-
-
-
-
-
-
-namespace NameSpace {
-struct StructInNameSpace {};
-}
-
-namespace NameSpaceAlias = NameSpace;
-using NameSpace::StructInNameSpace;
-NameSpace::StructInNameSpace foo6;
-
-class BaseClass {
-public:
- virtual void VirtualFunction();
- virtual void FinalVirtualFunction();
-};
-
-
-void f8()
-{
- BaseClass NonVirtualFunctionCall;
- NonVirtualFunctionCall.VirtualFunction();
-
- BaseClass *NonVirtualFunctionCallPointer = new BaseClass();
- NonVirtualFunctionCallPointer->VirtualFunction();
-}
-
-class DerivedClass : public BaseClass
-{public:
- void VirtualFunction() override;
- void FinalVirtualFunction() final;
-};
-
-void f8(BaseClass *VirtualFunctionCallPointer)
-{
- VirtualFunctionCallPointer->VirtualFunction();
-}
-
-class FinalClass final : public DerivedClass
-{
- void FinalClassThisCall();
-};
-
-void f8(DerivedClass *FinalVirtualFunctionCallPointer)
-{
- FinalVirtualFunctionCallPointer->FinalVirtualFunction();
-}
-
-void f9(BaseClass *NonFinalVirtualFunctionCallPointer)
-{
- NonFinalVirtualFunctionCallPointer->FinalVirtualFunction();
-}
-
-void f10(FinalClass *ClassFinalVirtualFunctionCallPointer)
-{
- ClassFinalVirtualFunctionCallPointer->VirtualFunction();
-}
-
-class Operator {
-public:
- Operator operator+=(const Operator &first);
-};
-
-Operator operator+(const Operator &first, const Operator &second);
-
-void f10()
-{
- auto PlusOperator = Operator() + Operator();
- Operator PlusAssignOperator;
- PlusAssignOperator += Operator();
-}
-
-/* Comment */
-
-#define PreprocessorDefinition Class
-#define MacroDefinition(a,b) ((a)>(b)?(a):(b))
-
-void f11()
-{
- MacroDefinition(2, 4);
-}
-
-#include "highlightingmarks.h"
-
-void f12() {
-GOTO_LABEL:
-
- goto GOTO_LABEL;
-}
-
-template <class T>
-void TemplateFunction(T v)
-{
- T XXXXX = v;
-}
-void TemplateReference()
-{
- TemplateFunction(1);
-// std::vector<int> TemplateIntance;
-}
-
-
-
-
-template <class T>
-class TemplateFoo {};
-
-
-template <class TemplateTypeParameter = Foo, int NonTypeTemplateParameter = 1, template <class> class TemplateTemplateParameter = TemplateFoo>
-void TemplateFunction(TemplateTypeParameter TemplateParameter)
-{
- TemplateTypeParameter TemplateTypeParameterReference;
- auto NonTypeTemplateParameterReference = NonTypeTemplateParameter;
- TemplateTemplateParameter<TemplateTypeParameter> TemplateTemplateParameterReference;
-}
-
-
-
-void FinalClass::FinalClassThisCall()
-{
- VirtualFunction();
-}
-
-
-void OutputArgument(int &one, const int &two, int *three=0);
-
-void f12b()
-{
- int One;
- OutputArgument(One, 2);
-}
-
-#include <highlightingmarks.h>
-
-#define FOREACH(variable, container) \
- variable; \
- auto x = container;
-
-#define foreach2 FOREACH
-
-
-
-void f13()
-{
- auto container = 1;
- foreach2(int index, container);
-}
-
-class SecondArgumentInMacroExpansionIsField {
- int container = 1;
-
- void f()
- {
- foreach2(int index, container);
- }
-};
-
-typedef unsigned uint32;
-
-enum EnumerationType : uint32
-{
- Other = 0,
-};
-
-
-struct TypeInCast {
- void function();
-};
-
-void f14()
-{
- static_cast<void (TypeInCast::*)()>(&TypeInCast::function);
- reinterpret_cast<void (TypeInCast::*)()>(&TypeInCast::function);
-}
-
-using IntegerAlias = int;
-using SecondIntegerAlias = IntegerAlias;
-typedef int IntegerTypedef;
-using Function = void (*)();
-
-
-
-void f15()
-{
- IntegerAlias integerAlias;
- SecondIntegerAlias secondIntegerAlias;
- IntegerTypedef integerTypedef;
- Function();
-}
-
-class FriendFoo
-{
-public:
- friend class FooFriend;
- friend bool operator==(const FriendFoo &first, const FriendFoo &second);
-};
-
-class FieldInitialization
-{
-public:
- FieldInitialization() :
- member(0)
- {}
-
- int member;
-};
-
-template<class Type>
-void TemplateFunctionCall(Type type)
-{
- type + type;
-}
-
-void f16()
-{
- TemplateFunctionCall(1);
-}
-
-
-template <typename T>
-class TemplatedType
-{
- T value = T();
-};
-
-void f17()
-{
- TemplatedType<int> TemplatedTypeDeclaration;
-}
-
-void f18()
-{
- auto value = 1 + 2;
-}
-
-class ScopeClass
-{
-public:
- static void ScopeOperator();
-};
-
-void f19()
-{
- ScopeClass::ScopeOperator();
-}
-
-namespace TemplateClassNamespace {
-template<class X>
-class TemplateClass
-{
-
-};
-}
-
-void f20()
-{
- TemplateClassNamespace::TemplateClass<ScopeClass> TemplateClassDefinition;
-}
-
-void f21()
-{
- typedef int TypeDefDeclaration;
- TypeDefDeclaration TypeDefDeclarationUsage;
-}
-
-typedef int EnumerationTypeDef;
-
-enum Enumeration2 : EnumerationTypeDef {
-
-};
-
-struct Bar {
- Bar &operator[](int &key);
-};
-
-void argumentToUserDefinedIndexOperator(Bar object, int index = 3)
-{
- object[index];
-}
-
-struct LambdaTester
-{
- int member = 0;
- void func() {
- const int var = 42, var2 = 84;
- auto lambda = [var, this](int input) {
- return var + input + member;
- };
- lambda(var2);
- }
-};
-
-void NonConstReferenceArgument(int &argument);
-
-void f22()
-{
- int x = 1;
-
- NonConstReferenceArgument(x);
-}
-
-void ConstReferenceArgument(const int &argument);
-
-void f23()
-{
- int x = 1;
-
- ConstReferenceArgument(x);
-}
-
-void RValueReferenceArgument(int &&argument);
-
-void f24()
-{
- int x = 1;
-
- RValueReferenceArgument(static_cast<int&&>(x));
-}
-
-void NonConstPointerArgument(int *argument);
-
-void f25()
-{
- int *x;
-
- NonConstPointerArgument(x);
-}
-
-void PointerToConstArgument(const int *argument);
-void ConstPointerArgument(int *const argument);
-void f26()
-{
- int *x;
- PointerToConstArgument(x);
- ConstPointerArgument(x);
-}
-
-void NonConstReferenceArgumentCallInsideCall(int x, int &argument);
-int GetArgument(int x);
-
-void f27()
-{
- int x = 1;
-
- NonConstReferenceArgumentCallInsideCall(GetArgument(x), x);
-}
-
-void f28(int &Reference)
-{
- NonConstReferenceArgument(Reference);
-}
-
-void f29()
-{
- int x;
-
- NonConstPointerArgument(&x);
-}
-
-struct NonConstPointerArgumentAsMemberOfClass
-{
- int member;
-};
-
-void f30()
-{
- NonConstPointerArgumentAsMemberOfClass instance;
-
- NonConstReferenceArgument(instance.member);
-}
-
-struct NonConstReferenceArgumentConstructor
-{
- NonConstReferenceArgumentConstructor() = default;
- NonConstReferenceArgumentConstructor(NonConstReferenceArgumentConstructor &other);
-
- void NonConstReferenceArgumentMember(NonConstReferenceArgumentConstructor &other);
-};
-
-void f31()
-{
- NonConstReferenceArgumentConstructor instance;
-
- NonConstReferenceArgumentConstructor copy(instance);
-}
-
-struct NonConstReferenceMemberInitialization
-{
- NonConstReferenceMemberInitialization(int &foo)
- : foo(foo)
- {}
-
- int &foo;
-};
-
-template<class T> class Coo;
-template<class T> class Coo<T*>;
-
-namespace N { void goo(); }
-using N::goo;
-
-#if 1
-#endif
-
-#include <new>
-
-struct OtherOperator { void operator()(int); };
-void g(OtherOperator o, int var)
-{
- o(var);
-}
-
-void NonConstPointerArgument(int &argument);
-
-struct PointerGetterClass
-{
- int &getter();
-};
-
-void f32()
-{
- PointerGetterClass x;
-
- NonConstPointerArgument(x.getter());
-}
-
-namespace N { template <typename T> void SizeIs(); }
-using N::SizeIs;
-
-void BaseClass::VirtualFunction() {}
-
-class WithVirtualFunctionDefined {
- virtual void VirtualFunctionDefinition() {};
-};
-
-namespace NFoo { namespace NBar { namespace NTest { class NamespaceTypeSpelling; } } }
-
-Undeclared u;
-#define Q_PROPERTY(arg) static_assert("Q_PROPERTY", #arg); // Keep these in sync with wrappedQtHeaders/QtCore/qobjectdefs.h
-#define SIGNAL(arg) #arg
-#define SLOT(arg) #arg
-class Property {
- Q_PROPERTY(const volatile unsigned long long * prop READ getProp WRITE setProp NOTIFY propChanged)
- Q_PROPERTY(const QString str READ getStr)
-};
-
-struct X {
- void operator*(int) {}
-};
-
-void operator*(X, float) {}
-
-void CallSite() {
- X x;
- int y = 10;
- float z = 10;
- x * y;
- x * z;
-}
-
-struct Dummy {
- Dummy operator<<=(int key);
- Dummy operator()(int a);
- int& operator[] (unsigned index);
- void* operator new(unsigned size);
- void operator delete(void* ptr);
- void* operator new[](unsigned size);
- void operator delete[](void* ptr);
-};
-
-void TryOverloadedOperators(Dummy object)
-{
- object <<= 3;
-
- Dummy stacked;
- stacked(4);
- stacked[1];
- int *i = new int;
- Dummy* use_new = new Dummy();
- delete use_new;
- Dummy* many = new Dummy[10];
- delete [] many;
-}
-
-enum {
- Test = 0
-};
-
-namespace {
-class B {
- struct {
- int a;
- };
-};
-}
-
-struct Dummy2 {
- Dummy2 operator()();
- int operator*();
- Dummy2 operator=(int foo);
-};
-
-void TryOverloadedOperators2(Dummy object)
-{
- Dummy2 dummy2;
- dummy2();
- *dummy2;
- dummy2 = 3;
-}
-
-int OperatorTest() {
- return 1 < 2 ? 20 : 30;
-}
-
-int signalSlotTest() {
- SIGNAL(something(QString));
- SLOT(something(QString));
- SIGNAL(something(QString (*func1)(QString)));
- 1 == 2;
-}
-
-class NonConstParameterConstructor
-{
- NonConstParameterConstructor() = default;
- NonConstParameterConstructor(NonConstParameterConstructor &buildDependenciesStorage);
-
- void Call()
- {
- NonConstParameterConstructor foo;
- NonConstParameterConstructor bar(foo);
- }
-};
-
-class StaticMembersAccess
-{
-protected:
- static int protectedValue;
-
-private:
- static int privateValue;
-};
-
-template <int i, int j> struct S { };
-template <int i> using spec = S<i, 1>;
-spec<2> s;
-
-class Property {
- Q_PROPERTY(
-
- const
-
- volatile
-
- unsigned
-
- long
-
- long
-
- *
-
- prop
-
- READ
-
- getProp
-
- WRITE
-
- setProp
-
- NOTIFY
-
- propChanged
-
- )
-};
-
-void structuredBindingTest() {
- const int a[] = {1, 2};
- const auto [x, y] = a;
-}
-
-#define ASSIGN(decl, ptr) do { decl = *ptr; } while (false)
-#define ASSIGN2 ASSIGN
-void f4()
-{
- int *thePointer = 0;
- ASSIGN(int i, thePointer);
- ASSIGN2(int i, thePointer);
-}
-
-const int MyConstant = 8;
-void f5()
-{
- int arr[MyConstant][8];
-}
-
-static int GlobalVar = 0;
-
-namespace N { [[deprecated]] void f(); }
-
-template<typename T>
-void func(T v);
-
-void f6()
-{
- GlobalVar = 5;
- func(1); // QTCREATORBUG-21856
-}
-
-template<typename T>
-void func(T v) {
- GlobalVar = 5;
-}
-
-static std::vector<std::pair<int, int>> pv;
-
-template <class T, long S>
-struct vecn
-{
- T v[S];
-};
-
-template <class T, long S>
-static inline constexpr vecn<T, S> operator<(vecn<T, S> a, vecn<T, S> b)
-{
- vecn<T, S> x = vecn<T, S>{};
- for(long i = 0; i < S; ++i)
- {
- x[i] = a[i] < b[i];
- }
- return x;
-}
-
-const char *cyrillic = "б";
-
-struct foo {
-#define blubb
-};
-
-#define test_micro(A,B) ((A##B>1?A:B))
-
-int a = (a1 > 0);
-
-int func() {
- int a = (a1 > 0);
-}
-
-namespace std {
- template<typename T1, typename T2> struct pair;
- template<typename T> struct vector;
-}
-
-static std::vector<std::pair<int, int>> pvr;
diff --git a/tests/unit/unittest/data/highlightingmarks.h b/tests/unit/unittest/data/highlightingmarks.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/tests/unit/unittest/data/highlightingmarks.h
+++ /dev/null
diff --git a/tests/unit/unittest/data/include_testfile.cpp b/tests/unit/unittest/data/include_testfile.cpp
deleted file mode 100644
index 9be5fa082f6..00000000000
--- a/tests/unit/unittest/data/include_testfile.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include <vector>
-
diff --git a/tests/unit/unittest/data/references.cpp b/tests/unit/unittest/data/references.cpp
deleted file mode 100644
index 32ff1b90753..00000000000
--- a/tests/unit/unittest/data/references.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-void variableSingleReference()
-{
- int foo;
-}
-
-
-
-int variableMultipleReferences()
-{
- int foo = 0;
- return foo;
-}
-
-
-
-class Foo {};
-void bla()
-{
- Foo foo;
-}
-
-
-
-namespace N { class Bar {}; }
-namespace N { class Baz {}; }
-N::Bar bar;
-
-
-
-namespace G { class App {}; }
-using G::App;
-
-
-
-class Hoo;
-void f(const Hoo &);
-
-
-
-class Moo {};
-void x()
-{
- new Moo;
-}
-
-
-
-class Element {};
-template<typename T> struct Wrap { T member; };
-void g()
-{
- Wrap<Element> con;
- con.member;
-}
-
-
-
-template<typename T>
-struct Wrapper {
- T f()
- {
- int foo;
- ++foo;
- return mem;
- }
-
- T mem;
-};
-
-
-
-template<typename T>
-void f()
-{
- T mem;
- mem.foo();
-}
-
-
-
-struct Woo {
- Woo();
- ~Woo();
-};
-
-
-
-int muu();
-int muu(int);
-
-
-
-struct Doo {
- int muu();
- int muu(int);
-};
-
-
-
-template<typename T> int tuu();
-int tuu(int);
-
-
-
-struct Xoo {
- template<typename T> int tuu();
- int tuu(int);
-};
-
-
-
-enum ET { E1 };
-bool e(ET e)
-{
- return e == E1;
-}
-
-
-
-struct LData { int member; };
-void lambda(LData foo) {
- auto l = [bar=foo] { return bar.member; };
-}
-
-
-
-template<class T> class Coo;
-template<class T> class Coo<T*>;
-template<> class Coo<int>;
-
-
-
-template<typename T> typename T::foo n()
-{
- typename T::bla hello;
-}
-
-
-
-int rec(int n = 100)
-{
- return n == 0 ? 0 : rec(--n);
-}
-
-
-
-#define FOO 3
-int objectLikeMacro()
-{
- return FOO;
-}
-
-
-
-#define BAR(x) x
-int functionLikeMacro(int foo)
-{
- return BAR(foo);
-}
-
-template<class T>
-class Container
-{
-public:
- T &operator[](int); T &operator()(int, int);
-};
-
-int testOperator() {
- Container<int> vec;
-
- int n = 10;
- vec[n] = n * 100;
- vec(n, n) = 100;
-}
diff --git a/tests/unit/unittest/data/skippedsourceranges.cpp b/tests/unit/unittest/data/skippedsourceranges.cpp
deleted file mode 100644
index 775393fcedc..00000000000
--- a/tests/unit/unittest/data/skippedsourceranges.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#if 0
-
-void f();
-
-#endif
-
-#ifndef BLAH
-class Class
-{
-
-};
-#endif
-
-#ifdef BLAH
-class Class
-{
-
-};
-#endif
diff --git a/tests/unit/unittest/data/token.cpp b/tests/unit/unittest/data/token.cpp
deleted file mode 100644
index 2fccc37acf6..00000000000
--- a/tests/unit/unittest/data/token.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-void function(int x)
-{
-}
diff --git a/tests/unit/unittest/data/tooltipinfo.cpp b/tests/unit/unittest/data/tooltipinfo.cpp
deleted file mode 100644
index bc1f17066ef..00000000000
--- a/tests/unit/unittest/data/tooltipinfo.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-void f(int foo, const int *cfoo)
-{
- foo++;
- cfoo++;
-}
-
-
-
-struct Foo { int member = 0; };
-int g(const Foo &foo)
-{
- return foo.member;
- const Foo bar;
- bar;
-}
-
-struct Bar { virtual ~Bar(); int mem(){} virtual int virtualConstMem() const; };
-void h(const Foo &foo, Bar &bar)
-{
- g(foo);
- bar.mem();
- bar.virtualConstMem();
-}
-
-
-template <typename T>
-void t(int foo) { (void)foo; }
-void c()
-{
- t<Foo>(3);
-}
-
-
-
-/**
- * \brief This is a crazy function.
- */
-void documentedFunction();
-void d()
-{
- documentedFunction();
-}
-
-
-
-enum EnumType { V1, V2, Custom = V2 + 5 };
-EnumType e()
-{
- return EnumType::Custom;
-}
-
-
-
-template <typename T> struct Baz { T member; };
-void t2(const Baz<int> &b) {
- Baz<int> baz; baz = b;
-}
-
-#include "tooltipinfo.h"
-
-
-
-#define MACRO_FROM_MAINFILE(x) x + 3
-void foo()
-{
- MACRO_FROM_MAINFILE(7);
- MACRO_FROM_HEADER(7);
-}
-
-
-
-namespace N { struct Muu{}; }
-namespace G = N;
-void o()
-{
- using namespace N;
- Muu muu; (void)muu;
-}
-void n()
-{
- using namespace G;
- Muu muu; (void)muu;
-}
-void q()
-{
- using N::Muu;
- Muu muu; (void)muu;
-}
-
-
-
-struct Sizes
-{
- char memberChar1;
- char memberChar2;
-};
-enum class FancyEnumType { V1, V2 };
-union Union
-{
- char memberChar1;
- char memberChar2;
-};
-
-
-
-namespace X {
-namespace Y {
-}
-}
-
-
-
-template<typename T> struct Ptr {};
-struct Nuu {};
-
-typedef Ptr<Nuu> PtrFromTypeDef;
-using PtrFromTypeAlias = Ptr<Nuu>;
-template<typename T> using PtrFromTemplateTypeAlias = Ptr<T>;
-
-void y()
-{
- PtrFromTypeDef b; (void)b;
- PtrFromTypeAlias a; (void)a;
- PtrFromTemplateTypeAlias<Nuu> c; (void)c;
-}
-
-
-
-template <typename T> struct Zii {};
-namespace U { template <typename T> struct Yii {}; }
-void mc()
-{
- using namespace U;
- Zii<int> zii; (void) zii;
- Yii<int> yii; (void) yii;
-}
-
-
-
-namespace A { struct X {}; }
-namespace B = A;
-void ab()
-{
- B::X x; (void)x;
-}
-
-
-
-namespace N {
-struct Outer
-{
- template <typename T> struct Inner {};
- Inner<int> inner;
-};
-}
-
-
-
-void f();
-namespace R { void f(); }
-void f(int param);
-void z(int = 1);
-void user()
-{
- f();
- R::f();
- f(1);
- z();
-}
-
-
-
-
-void autoTypes()
-{
- auto a = 3; (void)a;
- auto b = EnumType::V1; (void)b;
- auto c = Bar(); (void)c;
- auto d = Zii<int>(); (void)d;
-}
-
-
-
-
-struct Con {};
-struct ExplicitCon {
- ExplicitCon() = default;
- ExplicitCon(int m) :member(m) {}
- int member;
-};
-void constructor()
-{
- Con();
- ExplicitCon();
- ExplicitCon(2);
-}
-
-Nuu **pointers(Nuu **p1)
-{
- return p1;
-}
-
-static constexpr int calcValue() { return 1 + 2; }
-const auto val = calcValue() + sizeof(char);
-
-const int zero = 0;
-
-static void func()
-{
- const int i = 5;
- const int j = i;
-}
diff --git a/tests/unit/unittest/data/tooltipinfo.h b/tests/unit/unittest/data/tooltipinfo.h
deleted file mode 100644
index 47d3bb92e75..00000000000
--- a/tests/unit/unittest/data/tooltipinfo.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#define MACRO_FROM_HEADER(x) x + \
- x + \
- x
diff --git a/tests/unit/unittest/data/translationunits.cpp b/tests/unit/unittest/data/translationunits.cpp
deleted file mode 100644
index 8ab60b10e17..00000000000
--- a/tests/unit/unittest/data/translationunits.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "translationunits.h"
-#include "some/unresolved/file.h"
-
-void function()
-{
-
-}
-
diff --git a/tests/unit/unittest/data/translationunits.h b/tests/unit/unittest/data/translationunits.h
deleted file mode 100644
index 67bc13701d0..00000000000
--- a/tests/unit/unittest/data/translationunits.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void FunctionInIncludedHeader();
diff --git a/tests/unit/unittest/data/uicmain.cpp b/tests/unit/unittest/data/uicmain.cpp
deleted file mode 100644
index 7739b1027b2..00000000000
--- a/tests/unit/unittest/data/uicmain.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "uicheader.h"
-
-static UicObject o;
diff --git a/tests/unit/unittest/diagnostic-test.cpp b/tests/unit/unittest/diagnostic-test.cpp
deleted file mode 100644
index adfc503d3e4..00000000000
--- a/tests/unit/unittest/diagnostic-test.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "diagnosticcontainer-matcher.h"
-#include "googletest.h"
-#include "rundocumentparse-utility.h"
-#include "unittest-utility-functions.h"
-
-#include <diagnostic.h>
-#include <diagnosticcontainer.h>
-#include <diagnosticset.h>
-#include <fixitcontainer.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangtranslationunit.h>
-#include <unsavedfiles.h>
-#include <sourcelocation.h>
-#include <sourcerange.h>
-
-#include <clang-c/Index.h>
-
-
-using ::testing::Contains;
-using ::testing::Not;
-using ::testing::PrintToString;
-
-using ClangBackEnd::DiagnosticSet;
-using ClangBackEnd::DiagnosticContainer;
-using ClangBackEnd::Document;
-using ClangBackEnd::Documents;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::Diagnostic;
-using ClangBackEnd::SourceLocation;
-using ClangBackEnd::DiagnosticSeverity;
-using ClangBackEnd::FixItContainer;
-using ClangBackEnd::SourceLocationContainer;
-
-namespace {
-
-MATCHER_P4(IsSourceLocation, filePath, line, column, offset,
- std::string(negation ? "isn't" : "is")
- + " source location with file path "+ PrintToString(filePath)
- + ", line " + PrintToString(line)
- + ", column " + PrintToString(column)
- + " and offset " + PrintToString(offset)
- )
-{
- if (!arg.filePath().endsWith(filePath)
- || arg.line() != line
- || arg.column() != column
- || arg.offset() != offset)
- return false;
-
- return true;
-}
-
-class Diagnostic : public ::testing::Test
-{
-protected:
- enum ChildMode { WithChild, WithoutChild };
-
- DiagnosticContainer expectedDiagnostic(ChildMode childMode) const;
-
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Document document{Utf8StringLiteral(TESTDATA_DIR"/diagnostic_diagnostic.cpp"),
- UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++11")}),
- {},
- documents};
- UnitTest::RunDocumentParse _1{document};
- DiagnosticSet diagnosticSet{document.translationUnit().diagnostics()};
- ::Diagnostic diagnostic{diagnosticSet.front()};
-};
-
-using DiagnosticSlowTest = Diagnostic;
-
-TEST_F(DiagnosticSlowTest, MoveContructor)
-{
- const auto diagnostic2 = std::move(diagnostic);
-
- ASSERT_TRUE(diagnostic.isNull());
- ASSERT_FALSE(diagnostic2.isNull());
-}
-
-TEST_F(DiagnosticSlowTest, MoveAssigment)
-{
- auto diagnostic2 = std::move(diagnostic);
- diagnostic = std::move(diagnostic2);
-
- ASSERT_TRUE(diagnostic2.isNull());
- ASSERT_FALSE(diagnostic.isNull());
-}
-
-TEST_F(DiagnosticSlowTest, MoveSelfAssigment)
-{
- diagnostic = std::move(diagnostic);
-
- ASSERT_FALSE(diagnostic.isNull());
-}
-
-TEST_F(DiagnosticSlowTest, Text)
-{
-#if CINDEX_VERSION_MAJOR == 0 && CINDEX_VERSION_MINOR >= 59 // >= LLVM/Clang 10
- ASSERT_THAT(diagnostic.text(), Utf8StringLiteral("warning: non-void function does not return a value"));
-#else
- ASSERT_THAT(diagnostic.text(), Utf8StringLiteral("warning: control reaches end of non-void function"));
-#endif
-}
-
-TEST_F(DiagnosticSlowTest, Category)
-{
- ASSERT_THAT(diagnostic.category(), Utf8StringLiteral("Semantic Issue"));
-}
-
-TEST_F(DiagnosticSlowTest, EnableOption)
-{
- ASSERT_THAT(diagnostic.options().first, Utf8StringLiteral("-Wreturn-type"));
-}
-
-TEST_F(DiagnosticSlowTest, DisableOption)
-{
- ASSERT_THAT(diagnostic.options().second, Utf8StringLiteral("-Wno-return-type"));
-}
-
-TEST_F(DiagnosticSlowTest, Severity)
-{
- ASSERT_THAT(diagnostic.severity(), DiagnosticSeverity::Warning);
-}
-
-TEST_F(DiagnosticSlowTest, ChildDiagnosticsSize)
-{
- auto diagnostic = diagnosticSet.back();
-
- ASSERT_THAT(diagnostic.childDiagnostics().size(), 1);
-}
-
-TEST_F(DiagnosticSlowTest, ChildDiagnosticsText)
-{
- auto childDiagnostic = diagnosticSet.back().childDiagnostics().front();
-
- ASSERT_THAT(childDiagnostic.text(), Utf8StringLiteral("note: candidate function not viable: requires 1 argument, but 0 were provided"));
-}
-
-TEST_F(DiagnosticSlowTest, toDiagnosticContainerLetChildrenThroughByDefault)
-{
- const auto diagnosticWithChild = expectedDiagnostic(WithChild);
-
- const auto diagnostic = diagnosticSet.back().toDiagnosticContainer();
-
- ASSERT_THAT(diagnostic, IsDiagnosticContainer(diagnosticWithChild));
-}
-
-DiagnosticContainer Diagnostic::expectedDiagnostic(Diagnostic::ChildMode childMode) const
-{
- QVector<DiagnosticContainer> children;
- if (childMode == WithChild) {
- const auto child = DiagnosticContainer(
- Utf8StringLiteral("note: candidate function not viable: requires 1 argument, but 0 were provided"),
- Utf8StringLiteral("Semantic Issue"),
- {Utf8String(), Utf8String()},
- ClangBackEnd::DiagnosticSeverity::Note,
- SourceLocationContainer(document.filePath(), 5, 6),
- {},
- {},
- {}
- );
- children.append(child);
- }
-
- return
- DiagnosticContainer(
- Utf8StringLiteral("error: no matching function for call to 'f'"),
- Utf8StringLiteral("Semantic Issue"),
- {Utf8String(), Utf8String()},
- ClangBackEnd::DiagnosticSeverity::Error,
- SourceLocationContainer(document.filePath(), 7, 5),
- {},
- {},
- children
- );
-}
-
-}
diff --git a/tests/unit/unittest/diagnosticcontainer-matcher.h b/tests/unit/unittest/diagnosticcontainer-matcher.h
deleted file mode 100644
index 7b8032936fc..00000000000
--- a/tests/unit/unittest/diagnosticcontainer-matcher.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-namespace {
-
-using ::testing::PrintToString;
-
-MATCHER_P(IsDiagnosticContainer, diagnosticContainer, "")
-{
- if (arg.text != diagnosticContainer.text) {
- *result_listener << "text is " + PrintToString(arg.text)
- + " and not " + PrintToString(diagnosticContainer.text);
- return false;
- }
-
- if (arg.location != diagnosticContainer.location) {
- *result_listener << "location is " + PrintToString(arg.location)
- + " and not " + PrintToString(diagnosticContainer.location);
- return false;
- }
-
- if (arg.children != diagnosticContainer.children) {
- *result_listener << "children are " + PrintToString(arg.children)
- + " and not " + PrintToString(diagnosticContainer.children);
- return false;
- }
-
- return true;
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/diagnosticset-test.cpp b/tests/unit/unittest/diagnosticset-test.cpp
deleted file mode 100644
index b59325e0e71..00000000000
--- a/tests/unit/unittest/diagnosticset-test.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "diagnosticcontainer-matcher.h"
-#include "googletest.h"
-#include "unittest-utility-functions.h"
-
-#include <clangsupport_global.h>
-#include <clangdocument.h>
-#include <diagnosticcontainer.h>
-#include <diagnosticset.h>
-#include <fixitcontainer.h>
-#include <sourcelocation.h>
-#include <sourcelocationcontainer.h>
-#include <sourcerangecontainer.h>
-#include <clangtranslationunit.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-
-#include <clang-c/Index.h>
-
-using ::testing::Contains;
-using ::testing::Not;
-using ::testing::PrintToString;
-
-using ::ClangBackEnd::Diagnostic;
-using ::ClangBackEnd::DiagnosticSet;
-using ::ClangBackEnd::DiagnosticContainer;
-using ::ClangBackEnd::FixItContainer;
-using ::ClangBackEnd::SourceLocation;
-using ::ClangBackEnd::SourceLocationContainer;
-using ::ClangBackEnd::Document;
-using ::ClangBackEnd::UnsavedFiles;
-
-namespace {
-
-const Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/diagnostic_diagnosticset_header.cpp");
-
-class DiagnosticSet : public ::testing::Test
-{
-protected:
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Utf8StringVector compilationArguments{
- UnitTest::addPlatformArguments({Utf8StringLiteral("-pedantic")})};
- Document document{Utf8StringLiteral(TESTDATA_DIR "/diagnostic_diagnosticset.cpp"),
- compilationArguments,
- {},
- documents};
- Document documentMainFile{Utf8StringLiteral(TESTDATA_DIR"/diagnostic_diagnosticset_mainfile.cpp"),
- compilationArguments,
- {},
- documents};
-
-protected:
- enum ChildMode { WithChild, WithoutChild };
- DiagnosticContainer expectedDiagnostic(ChildMode childMode) const;
-};
-
-using DiagnosticSetSlowTest = DiagnosticSet;
-
-TEST_F(DiagnosticSetSlowTest, SetHasContent)
-{
- document.parse();
- const auto set = document.translationUnit().diagnostics();
-
- ASSERT_THAT(set.size(), 1);
-}
-
-TEST_F(DiagnosticSetSlowTest, MoveConstructor)
-{
- document.parse();
- auto set = document.translationUnit().diagnostics();
-
- const auto set2 = std::move(set);
-
- ASSERT_TRUE(set.isNull());
- ASSERT_FALSE(set2.isNull());
-}
-
-TEST_F(DiagnosticSetSlowTest, MoveAssigment)
-{
- document.parse();
- auto set = document.translationUnit().diagnostics();
-
- auto set2 = std::move(set);
- set = std::move(set2);
-
- ASSERT_TRUE(set2.isNull());
- ASSERT_FALSE(set.isNull());
-}
-
-TEST_F(DiagnosticSetSlowTest, MoveSelfAssigment)
-{
- document.parse();
- auto set = document.translationUnit().diagnostics();
-
- set = std::move(set);
-
- ASSERT_FALSE(set.isNull());
-}
-
-TEST_F(DiagnosticSetSlowTest, FirstElementEqualBegin)
-{
- document.parse();
- auto set = document.translationUnit().diagnostics();
-
- ASSERT_TRUE(set.front() == *set.begin());
-}
-
-TEST_F(DiagnosticSetSlowTest, BeginIsUnequalEnd)
-{
- document.parse();
- auto set = document.translationUnit().diagnostics();
-
- ASSERT_TRUE(set.begin() != set.end());
-}
-
-TEST_F(DiagnosticSetSlowTest, BeginPlusOneIsEqualEnd)
-{
- document.parse();
- auto set = document.translationUnit().diagnostics();
-
- ASSERT_TRUE(++set.begin() == set.end());
-}
-
-TEST_F(DiagnosticSetSlowTest, ToDiagnosticContainersLetThroughByDefault)
-{
- const auto diagnosticContainerWithoutChild = expectedDiagnostic(WithChild);
- documentMainFile.parse();
-
- const auto diagnostics = documentMainFile.translationUnit().diagnostics().toDiagnosticContainers();
-
- ASSERT_THAT(diagnostics, Contains(IsDiagnosticContainer(diagnosticContainerWithoutChild)));
-}
-
-TEST_F(DiagnosticSetSlowTest, ToDiagnosticContainersFiltersOutTopLevelItem)
-{
- documentMainFile.parse();
- const ::DiagnosticSet diagnosticSetWithChildren{documentMainFile.translationUnit().diagnostics()};
- const auto acceptNoDiagnostics = [](const Diagnostic &) { return false; };
-
- const auto diagnostics = diagnosticSetWithChildren.toDiagnosticContainers(acceptNoDiagnostics);
-
- ASSERT_TRUE(diagnostics.isEmpty());
-}
-
-DiagnosticContainer DiagnosticSet::expectedDiagnostic(DiagnosticSet::ChildMode childMode) const
-{
- QVector<DiagnosticContainer> children;
- if (childMode == WithChild) {
- const auto child = DiagnosticContainer(
- Utf8StringLiteral("note: previous definition is here"),
- Utf8StringLiteral("Semantic Issue"),
- {Utf8String(), Utf8String()},
- ClangBackEnd::DiagnosticSeverity::Note,
- SourceLocationContainer(headerFilePath, 1, 6),
- {},
- {},
- {}
- );
- children.append(child);
- }
-
- return DiagnosticContainer(
- Utf8StringLiteral("error: redefinition of 'f'"),
- Utf8StringLiteral("Semantic Issue"),
- {Utf8String(), Utf8String()},
- ClangBackEnd::DiagnosticSeverity::Error,
- SourceLocationContainer(documentMainFile.filePath(), 3, 6),
- {},
- {},
- children
- );
-}
-
-}
diff --git a/tests/unit/unittest/dummyclangipcclient.h b/tests/unit/unittest/dummyclangipcclient.h
deleted file mode 100644
index b58fd912842..00000000000
--- a/tests/unit/unittest/dummyclangipcclient.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangcodemodelclientinterface.h>
-
-class DummyIpcClient: public ClangBackEnd::ClangCodeModelClientInterface
-{
-public:
- void dispatch(const ClangBackEnd::MessageEnvelop &) override {}
-
- void alive() override {}
- void echo(const ClangBackEnd::EchoMessage &) override {}
- void completions(const ClangBackEnd::CompletionsMessage &) override {}
- void annotations(const ClangBackEnd::AnnotationsMessage &) override {}
- void references(const ClangBackEnd::ReferencesMessage &) override {}
- void followSymbol(const ClangBackEnd::FollowSymbolMessage &) override {}
- void tooltip(const ClangBackEnd::ToolTipMessage &) override {}
-};
diff --git a/tests/unit/unittest/filesystem-utilities.h b/tests/unit/unittest/filesystem-utilities.h
deleted file mode 100644
index bb6c007d641..00000000000
--- a/tests/unit/unittest/filesystem-utilities.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/hostosinfo.h>
-
-#include <filepath.h>
-#include <nativefilepath.h>
-
-#include <QCoreApplication>
-#include <QDir>
-
-template<std::size_t Size>
-ClangBackEnd::NativeFilePath toNativePath(const char (&text)[Size])
-{
- ClangBackEnd::FilePath path = text;
-
- return ClangBackEnd::NativeFilePath{path};
-}
-
-inline Utils::PathString toNativePath(const QString &text)
-{
- ClangBackEnd::FilePath path{text};
-
- return ClangBackEnd::NativeFilePath{path}.path();
-}
-
-inline Utils::PathString toNativePath(Utils::SmallStringView text)
-{
- ClangBackEnd::FilePath path{text};
-
- return ClangBackEnd::NativeFilePath{path}.path();
-}
-
-inline QString resourcePath()
-{
- return QDir::cleanPath(QCoreApplication::applicationDirPath() + '/' + RELATIVE_DATA_PATH
- + "/indexing_preincludes");
-}
diff --git a/tests/unit/unittest/fixit-test.cpp b/tests/unit/unittest/fixit-test.cpp
deleted file mode 100644
index 0d64107d099..00000000000
--- a/tests/unit/unittest/fixit-test.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "rundocumentparse-utility.h"
-
-#include <diagnostic.h>
-#include <diagnosticset.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangtranslationunit.h>
-#include <unsavedfiles.h>
-#include <sourcelocation.h>
-#include <sourcerange.h>
-#include <fixit.h>
-
-#include <clang-c/Index.h>
-
-using ClangBackEnd::DiagnosticSet;
-using ClangBackEnd::Document;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::Diagnostic;
-using ClangBackEnd::FixIt;
-using testing::PrintToString;
-
-namespace {
-
-MATCHER_P4(IsSourceLocation, filePath, line, column, offset,
- std::string(negation ? "isn't" : "is")
- + " source location with file path "+ PrintToString(filePath)
- + ", line " + PrintToString(line)
- + ", column " + PrintToString(column)
- + " and offset " + PrintToString(offset)
- )
-{
- if (!arg.filePath().endsWith(filePath)
- || arg.line() != line
- || arg.column() != column
- || arg.offset() != offset)
- return false;
-
- return true;
-}
-
-struct Data
-{
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Document document{Utf8StringLiteral(TESTDATA_DIR"/diagnostic_semicolon_fixit.cpp"),
- {},
- {},
- documents};
- UnitTest::RunDocumentParse _1{document};
- TranslationUnit translationUnit{document.translationUnit()};
- DiagnosticSet diagnosticSet{translationUnit.diagnostics()};
- Diagnostic diagnostic{diagnosticSet.front()};
- ClangBackEnd::FixIt fixIt{diagnostic.fixIts().front()};
-};
-
-class FixIt : public ::testing::Test
-{
-public:
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-protected:
- static std::unique_ptr<const Data> data;
- const Diagnostic &diagnostic{data->diagnostic};
- const ClangBackEnd::FixIt &fixIt{data->fixIt};
-};
-
-std::unique_ptr<const Data> FixIt::data;
-
-TEST_F(FixIt, Size)
-{
- ASSERT_THAT(diagnostic.fixIts().size(), 1);
-}
-
-TEST_F(FixIt, Text)
-{
- ASSERT_THAT(fixIt.text(), Utf8StringLiteral(";"));
-}
-
-
-TEST_F(FixIt, DISABLED_ON_WINDOWS(Start))
-{
- ASSERT_THAT(fixIt.range().start(), IsSourceLocation(Utf8StringLiteral("diagnostic_semicolon_fixit.cpp"),
- 3,
- 13,
- 29));
-}
-
-TEST_F(FixIt, DISABLED_ON_WINDOWS(End))
-{
- ASSERT_THAT(fixIt.range().end(), IsSourceLocation(Utf8StringLiteral("diagnostic_semicolon_fixit.cpp"),
- 3,
- 13,
- 29));
-}
-
-void FixIt::SetUpTestCase()
-{
- data = std::make_unique<const Data>();
-}
-
-void FixIt::TearDownTestCase()
-{
- data.reset();
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/googletest.h b/tests/unit/unittest/googletest.h
index 4c917a45b32..efc24cae964 100644
--- a/tests/unit/unittest/googletest.h
+++ b/tests/unit/unittest/googletest.h
@@ -42,9 +42,6 @@
#include "gtest-llvm-printing.h"
#include "gtest-qt-printing.h"
#include "gtest-std-printing.h"
-#ifdef CLANG_UNIT_TESTS
-# include "gtest-clang-printing.h"
-#endif
#include "google-using-declarations.h"
diff --git a/tests/unit/unittest/gtest-clang-printing.cpp b/tests/unit/unittest/gtest-clang-printing.cpp
deleted file mode 100644
index 00bb0d2e443..00000000000
--- a/tests/unit/unittest/gtest-clang-printing.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "gtest-creator-printing.h"
-#include "gtest-std-printing.h"
-
-#ifdef CLANG_UNIT_TESTS
-#include <clangdocumentsuspenderresumer.h>
-#include <clangreferencescollector.h>
-#include <fulltokeninfo.h>
-#include <tokenprocessor.h>
-
-#endif
-
-#include <gtest/gtest-printers.h>
-
-
-namespace ClangBackEnd {
-std::ostream &operator<<(std::ostream &os, const TokenInfo &tokenInfo)
-{
- os << "(type: " << tokenInfo.types() << ", "
- << " line: " << tokenInfo.line() << ", "
- << " column: " << tokenInfo.column() << ", "
- << " length: " << tokenInfo.length() << ")";
-
- return os;
-}
-
-template<class T>
-std::ostream &operator<<(std::ostream &out, const TokenProcessor<T> &tokenInfos)
-{
- out << "[";
-
- for (const T &entry : tokenInfos)
- out << entry;
-
- out << "]";
-
- return out;
-}
-
-template std::ostream &operator<<(std::ostream &out, const TokenProcessor<TokenInfo> &tokenInfos);
-template std::ostream &operator<<(std::ostream &out, const TokenProcessor<FullTokenInfo> &tokenInfos);
-
-std::ostream &operator<<(std::ostream &out, const SuspendResumeJobsEntry &entry)
-{
- return out << "(" << entry.document.filePath() << ", " << entry.jobRequestType << ", "
- << entry.preferredTranslationUnit << ")";
-}
-
-std::ostream &operator<<(std::ostream &os, const ReferencesResult &value)
-{
- os << "ReferencesResult(";
- os << value.isLocalVariable << ", {";
- for (const SourceRangeContainer &r : value.references) {
- os << r.start.line << ",";
- os << r.start.column << ",";
- os << r.end.column - r.start.column << ",";
- }
- os << "})";
-
- return os;
-}
-
-} // namespace ClangBackEnd
diff --git a/tests/unit/unittest/gtest-clang-printing.h b/tests/unit/unittest/gtest-clang-printing.h
deleted file mode 100644
index 4dfdbb2685a..00000000000
--- a/tests/unit/unittest/gtest-clang-printing.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <iosfwd>
-
-#include <gtest/gtest-printers.h>
-
-namespace ClangBackEnd {
-class TokenInfo;
-template<typename T>
-class TokenProcessor;
-class SuspendResumeJobsEntry;
-class ReferencesResult;
-
-std::ostream &operator<<(std::ostream &os, const TokenInfo &tokenInfo);
-template<class T>
-std::ostream &operator<<(std::ostream &out, const TokenProcessor<T> &tokenInfos);
-std::ostream &operator<<(std::ostream &out, const SuspendResumeJobsEntry &entry);
-std::ostream &operator<<(std::ostream &os, const ReferencesResult &value);
-
-} // namespace ClangBackEnd
diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp
index 9d90fdb3e0f..3d247803386 100644
--- a/tests/unit/unittest/gtest-creator-printing.cpp
+++ b/tests/unit/unittest/gtest-creator-printing.cpp
@@ -31,8 +31,6 @@
#include <gtest/gtest-printers.h>
#include <gmock/gmock-matchers.h>
-#include <clangcodemodelclientmessages.h>
-#include <clangcodemodelservermessages.h>
#include <clangtools/clangtoolsdiagnostic.h>
#include <debugger/analyzer/diagnosticlocation.h>
#include <modelnode.h>
@@ -43,16 +41,20 @@
#include <sqlite.h>
#include <sqlitesessionchangeset.h>
#include <sqlitevalue.h>
-#include <tooltipinfo.h>
#include <utils/fileutils.h>
#include <utils/linecolumn.h>
#include <variantproperty.h>
#include <qmldesigner/designercore/imagecache/imagecachestorageinterface.h>
-void PrintTo(const Utf8String &text, ::std::ostream *os)
+namespace std {
+template <typename T> ostream &operator<<(ostream &out, const QVector<T> &vector)
{
- *os << text;
+ out << "[";
+ copy(vector.cbegin(), vector.cend(), ostream_iterator<T>(out, ", "));
+ out << "]";
+ return out;
}
+} // namespace std
namespace Utils {
@@ -421,490 +423,6 @@ std::ostream &operator<<(std::ostream &out, const ConstTupleIterator &iterator)
} // namespace SessionChangeSetInternal
} // namespace Sqlite
-namespace ClangBackEnd {
-
-std::ostream &operator<<(std::ostream &os, const FollowSymbolResult &result)
-{
- os << "("
- << result.range
- << ", " << result.isResultOnlyForFallBack
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message)
-{
- os << "("
- << message.fileContainer << ", "
- << message.ticketNumber << ", "
- << message.result << ", "
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const RequestCompletionsMessage &message)
-{
- os << "("
- << message.filePath << ", "
- << message.line << ", "
- << message.column << ", "
- << message.ticketNumber << ", "
- << message.funcNameStartLine << ", "
- << message.funcNameStartColumn
-
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const DocumentsOpenedMessage &message)
-{
- os << "DocumentsOpenedMessage("
- << message.fileContainers << ", "
- << message.currentEditorFilePath << ", "
- << message.visibleEditorFilePaths << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const EndMessage &/*message*/)
-{
- return os << "()";
-}
-
-std::ostream &operator<<(std::ostream &os, const AliveMessage &/*message*/)
-{
- return os << "()";
-}
-
-std::ostream &operator<<(std::ostream &os, const CompletionsMessage &message)
-{
- os << "("
- << message.codeCompletions << ", "
- << message.ticketNumber
-
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const AnnotationsMessage &message)
-{
- os << "AnnotationsMessage("
- << message.fileContainer
- << "," << message.diagnostics.size()
- << "," << !message.firstHeaderErrorDiagnostic.text.isEmpty()
- << "," << message.tokenInfos.size()
- << "," << message.skippedPreprocessorRanges.size()
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const ReferencesMessage &message)
-{
- os << "("
- << message.fileContainer << ", "
- << message.ticketNumber << ", "
- << message.isLocalVariable << ", "
- << message.references << ", "
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const ToolTipMessage &message)
-{
- os << "("
- << message.fileContainer << ", "
- << message.ticketNumber << ", "
- << message.toolTipInfo << ", "
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const EchoMessage &/*message*/)
-{
- return os << "()";
-}
-
-std::ostream &operator<<(std::ostream &os, const DocumentsClosedMessage &message)
-{
- os << "("
- << message.fileContainers
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const CodeCompletion &message)
-{
- os << "("
- << message.text << ", "
- << message.priority << ", "
- << message.completionKind << ", "
- << message.availability << ", "
- << message.hasParameters
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const CodeCompletionChunk &chunk)
-{
- os << "("
- << chunk.kind << ", "
- << chunk.text;
-
- if (chunk.isOptional)
- os << ", optional";
-
- os << ")";
-
- return os;
-}
-
-static const char *severityToText(DiagnosticSeverity severity)
-{
- switch (severity) {
- case DiagnosticSeverity::Ignored: return "Ignored";
- case DiagnosticSeverity::Note: return "Note";
- case DiagnosticSeverity::Warning: return "Warning";
- case DiagnosticSeverity::Error: return "Error";
- case DiagnosticSeverity::Fatal: return "Fatal";
- }
-
- Q_UNREACHABLE();
-}
-
-std::ostream &operator<<(std::ostream &os, const DiagnosticContainer &container)
-{
- os << "("
- << severityToText(container.severity) << ": "
- << container.text << ", "
- << container.category << ", "
- << container.enableOption << ", "
- << container.location << ", "
- << container.ranges << ", "
- << container.fixIts << ", "
- << container.children << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const FileContainer &container)
-{
- os << "("
- << container.filePath << ", "
- << container.compilationArguments << ", "
- << container.documentRevision << ", "
- << container.textCodecName;
-
- if (container.hasUnsavedFileContent)
- os << ", "
- << container.unsavedFileContent;
-
- os << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const FixItContainer &container)
-{
- os << "("
- << container.text << ", "
- << container.range
- << ")";
-
- return os;
-}
-
-#define RETURN_TEXT_FOR_CASE(enumValue) case HighlightingType::enumValue: return #enumValue
-static const char *highlightingTypeToCStringLiteral(HighlightingType type)
-{
- switch (type) {
- RETURN_TEXT_FOR_CASE(Invalid);
- RETURN_TEXT_FOR_CASE(Comment);
- RETURN_TEXT_FOR_CASE(Keyword);
- RETURN_TEXT_FOR_CASE(StringLiteral);
- RETURN_TEXT_FOR_CASE(NumberLiteral);
- RETURN_TEXT_FOR_CASE(Function);
- RETURN_TEXT_FOR_CASE(VirtualFunction);
- RETURN_TEXT_FOR_CASE(Type);
- RETURN_TEXT_FOR_CASE(LocalVariable);
- RETURN_TEXT_FOR_CASE(Parameter);
- RETURN_TEXT_FOR_CASE(GlobalVariable);
- RETURN_TEXT_FOR_CASE(Field);
- RETURN_TEXT_FOR_CASE(Enumeration);
- RETURN_TEXT_FOR_CASE(Operator);
- RETURN_TEXT_FOR_CASE(Preprocessor);
- RETURN_TEXT_FOR_CASE(Label);
- RETURN_TEXT_FOR_CASE(FunctionDefinition);
- RETURN_TEXT_FOR_CASE(OutputArgument);
- RETURN_TEXT_FOR_CASE(OverloadedOperator);
- RETURN_TEXT_FOR_CASE(PreprocessorDefinition);
- RETURN_TEXT_FOR_CASE(PreprocessorExpansion);
- RETURN_TEXT_FOR_CASE(PrimitiveType);
- RETURN_TEXT_FOR_CASE(Punctuation);
- RETURN_TEXT_FOR_CASE(Declaration);
- RETURN_TEXT_FOR_CASE(Namespace);
- RETURN_TEXT_FOR_CASE(Class);
- RETURN_TEXT_FOR_CASE(Struct);
- RETURN_TEXT_FOR_CASE(Enum);
- RETURN_TEXT_FOR_CASE(Union);
- RETURN_TEXT_FOR_CASE(TypeAlias);
- RETURN_TEXT_FOR_CASE(Typedef);
- RETURN_TEXT_FOR_CASE(QtProperty);
- RETURN_TEXT_FOR_CASE(ObjectiveCClass);
- RETURN_TEXT_FOR_CASE(ObjectiveCCategory);
- RETURN_TEXT_FOR_CASE(ObjectiveCProtocol);
- RETURN_TEXT_FOR_CASE(ObjectiveCInterface);
- RETURN_TEXT_FOR_CASE(ObjectiveCImplementation);
- RETURN_TEXT_FOR_CASE(ObjectiveCProperty);
- RETURN_TEXT_FOR_CASE(ObjectiveCMethod);
- RETURN_TEXT_FOR_CASE(TemplateTypeParameter);
- RETURN_TEXT_FOR_CASE(TemplateTemplateParameter);
- RETURN_TEXT_FOR_CASE(AngleBracketOpen);
- RETURN_TEXT_FOR_CASE(AngleBracketClose);
- RETURN_TEXT_FOR_CASE(DoubleAngleBracketClose);
- RETURN_TEXT_FOR_CASE(TernaryIf);
- RETURN_TEXT_FOR_CASE(TernaryElse);
- }
-
- return "";
-}
-#undef RETURN_TEXT_FOR_CASE
-
-std::ostream &operator<<(std::ostream &os, HighlightingType highlightingType)
-{
- return os << highlightingTypeToCStringLiteral(highlightingType);
-}
-
-std::ostream &operator<<(std::ostream &os, HighlightingTypes types)
-{
- os << "("
- << types.mainHighlightingType;
-
- if (!types.mixinHighlightingTypes.empty())
- os << ", "<< types.mixinHighlightingTypes;
-
- os << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const ExtraInfo &extraInfo)
-{
- os << "("
- << extraInfo.token << ", "
- << extraInfo.typeSpelling << ", "
- << extraInfo.semanticParentTypeSpelling << ", "
- << static_cast<uint>(extraInfo.accessSpecifier) << ", "
- << static_cast<uint>(extraInfo.storageClass) << ", "
- << extraInfo.identifier << ", "
- << extraInfo.includeDirectivePath << ", "
- << extraInfo.declaration << ", "
- << extraInfo.definition << ", "
- << extraInfo.signal << ", "
- << extraInfo.slot
- << ")";
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const TokenInfoContainer &container)
-{
- os << "("
- << container.line << ", "
- << container.column << ", "
- << container.length << ", "
- << container.types << ", "
- << container.extraInfo << ", "
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const UnsavedFilesUpdatedMessage &message)
-{
- os << "("
- << message.fileContainers
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const RequestAnnotationsMessage &message)
-{
- os << "("
- << message.fileContainer.filePath << ","
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const RequestFollowSymbolMessage &message)
-{
- os << "("
- << message.fileContainer << ", "
- << message.ticketNumber << ", "
- << message.line << ", "
- << message.column << ", "
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const RequestReferencesMessage &message)
-{
- os << "("
- << message.fileContainer << ", "
- << message.ticketNumber << ", "
- << message.line << ", "
- << message.column << ", "
- << message.local << ", "
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &out, const RequestToolTipMessage &message)
-{
- out << "("
- << message.fileContainer << ", "
- << message.ticketNumber << ", "
- << message.line << ", "
- << message.column << ", "
- << ")";
-
- return out;
-}
-
-namespace {
-
-std::ostream &operator<<(std::ostream &os, const ToolTipInfo::QdocCategory category)
-{
- return os << qdocCategoryToString(category);
-}
-} // namespace
-
-std::ostream &operator<<(std::ostream &out, const ToolTipInfo &info)
-{
- out << "("
- << info.text << ", "
- << info.briefComment << ", "
- << info.qdocIdCandidates << ", "
- << info.qdocMark << ", "
- << info.qdocCategory
- << info.sizeInBytes << ", "
- << ")";
-
- return out;
-}
-
-std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container)
-{
- os << "("
- << container.filePath << ", "
- << container.line << ", "
- << container.column
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const SourceRangeContainer &container)
-{
- os << "("
- << container.start << ", "
- << container.end
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const UnsavedFilesRemovedMessage &message)
-{
- os << "("
- << message.fileContainers
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const DocumentsChangedMessage &message)
-{
- os << "DocumentsChangedMessage("
- << message.fileContainers
- << ")";
-
- return os;
-}
-
-std::ostream &operator<<(std::ostream &os, const DocumentVisibilityChangedMessage &message)
-{
- os << "("
- << message.currentEditorFilePath << ", "
- << message.visibleEditorFilePaths
- << ")";
-
- return os;
-}
-
-namespace {
-const char *symbolKindString(SymbolKind symbolKind)
-{
- using ClangBackEnd::SymbolKind;
-
- switch (symbolKind) {
- case SymbolKind::None: return "None";
- case SymbolKind::Enumeration: return "Enumeration";
- case SymbolKind::Record: return "Record";
- case SymbolKind::Function: return "Function";
- case SymbolKind::Variable: return "Variable";
- case SymbolKind::Macro: return "Macro";
- }
-
- return "";
-}
-
-const char *symbolTagString(SymbolTag symbolTag)
-{
- using ClangBackEnd::SymbolTag;
-
- switch (symbolTag) {
- case SymbolTag::None: return "None";
- case SymbolTag::Class: return "Class";
- case SymbolTag::Struct: return "Struct";
- case SymbolTag::Union: return "Union";
- case SymbolTag::MsvcInterface: return "MsvcInterface";
- }
-
- return "";
-}
-} // namespace
-
-std::ostream &operator<<(std::ostream &out, SymbolKind symbolKind)
-{
- return out << symbolKindString(symbolKind);
-}
-
-std::ostream &operator<<(std::ostream &out, SymbolTag symbolTag)
-{
- return out << symbolTagString(symbolTag);
-}
-
-std::ostream &operator<<(std::ostream &out, SymbolTags symbolTags)
-{
- std::copy(symbolTags.cbegin(), symbolTags.cend(), std::ostream_iterator<SymbolTag>(out, ", "));
-
- return out;
-}
-
-} // namespace ClangBackEnd
-
namespace Debugger {
std::ostream &operator<<(std::ostream &out, const DiagnosticLocation &loc)
{
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 7e89dca0481..83971a2a4f9 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -30,17 +30,12 @@
#include <utils/smallstringio.h>
#include <utils/variant.h>
-#include <clangsupport_global.h>
-
#include <QtGlobal>
#include <iosfwd>
#include <gtest/gtest-printers.h>
-class Utf8String;
-void PrintTo(const Utf8String &text, ::std::ostream *os);
-
namespace Sqlite {
class Value;
class ValueView;
@@ -112,93 +107,6 @@ void PrintTo(const Utils::PathString &text, ::std::ostream *os);
} // namespace Utils
-namespace ClangBackEnd {
-class AliveMessage;
-class CompletionsMessage;
-class EchoMessage;
-class AnnotationsMessage;
-class ReferencesMessage;
-class ToolTipMessage;
-class FollowSymbolResult;
-class FollowSymbolMessage;
-class RequestCompletionsMessage;
-class EndMessage;
-class DocumentsOpenedMessage;
-class DocumentsClosedMessage;
-class CodeCompletion;
-class CodeCompletionChunk;
-class DiagnosticContainer;
-class FileContainer;
-class FixItContainer;
-class FullTokenInfo;
-class HighlightingMarkContainer;
-class UnsavedFilesUpdatedMessage;
-class RequestAnnotationsMessage;
-class RequestFollowSymbolMessage;
-class RequestReferencesMessage;
-class RequestToolTipMessage;
-class SourceLocationContainer;
-class SourceRangeContainer;
-class TokenInfo;
-template<class T>
-class TokenProcessor;
-class DocumentsChangedMessage;
-class DocumentVisibilityChangedMessage;
-class ToolTipInfo;
-class SuspendResumeJobsEntry;
-class ReferencesResult;
-struct ExtraInfo;
-class TokenInfoContainer;
-class UnsavedFilesRemovedMessage;
-
-std::ostream &operator<<(std::ostream &out, const AliveMessage &message);
-std::ostream &operator<<(std::ostream &out, const CompletionsMessage &message);
-std::ostream &operator<<(std::ostream &out, const EchoMessage &message);
-std::ostream &operator<<(std::ostream &out, const AnnotationsMessage &message);
-std::ostream &operator<<(std::ostream &out, const ReferencesMessage &message);
-std::ostream &operator<<(std::ostream &out, const ToolTipMessage &message);
-std::ostream &operator<<(std::ostream &out, const FollowSymbolResult &result);
-std::ostream &operator<<(std::ostream &out, const FollowSymbolMessage &message);
-std::ostream &operator<<(std::ostream &out, const RequestCompletionsMessage &message);
-std::ostream &operator<<(std::ostream &out, const EndMessage &message);
-std::ostream &operator<<(std::ostream &out, const DocumentsOpenedMessage &message);
-std::ostream &operator<<(std::ostream &out, const DocumentsClosedMessage &message);
-std::ostream &operator<<(std::ostream &out, const CodeCompletion &message);
-std::ostream &operator<<(std::ostream &out, const CodeCompletionChunk &chunk);
-std::ostream &operator<<(std::ostream &out, const DiagnosticContainer &container);
-std::ostream &operator<<(std::ostream &out, const FileContainer &container);
-std::ostream &operator<<(std::ostream &out, const FixItContainer &container);
-std::ostream &operator<<(std::ostream &out, HighlightingType highlightingType);
-std::ostream &operator<<(std::ostream &out, HighlightingTypes types);
-std::ostream &operator<<(std::ostream &out, const HighlightingMarkContainer &container);
-std::ostream &operator<<(std::ostream &out, const UnsavedFilesUpdatedMessage &message);
-std::ostream &operator<<(std::ostream &out, const RequestAnnotationsMessage &message);
-std::ostream &operator<<(std::ostream &out, const RequestFollowSymbolMessage &message);
-std::ostream &operator<<(std::ostream &out, const RequestReferencesMessage &message);
-std::ostream &operator<<(std::ostream &out, const RequestToolTipMessage &message);
-std::ostream &operator<<(std::ostream &out, const ToolTipInfo &info);
-std::ostream &operator<<(std::ostream &out, const SourceLocationContainer &container);
-std::ostream &operator<<(std::ostream &out, const SourceRangeContainer &container);
-std::ostream &operator<<(std::ostream &out, const DocumentsChangedMessage &message);
-std::ostream &operator<<(std::ostream &out, const DocumentVisibilityChangedMessage &message);
-std::ostream &operator<<(std::ostream &out, const TokenInfo& tokenInfo);
-template<class T>
-std::ostream &operator<<(std::ostream &out, const TokenProcessor<T> &tokenInfos);
-extern template
-std::ostream &operator<<(std::ostream &out, const TokenProcessor<TokenInfo> &tokenInfos);
-extern template std::ostream &operator<<(std::ostream &out,
- const TokenProcessor<FullTokenInfo> &tokenInfos);
-std::ostream &operator<<(std::ostream &out, SymbolKind symbolKind);
-std::ostream &operator<<(std::ostream &out, SymbolTag symbolTag);
-std::ostream &operator<<(std::ostream &out, SymbolTags symbolTags);
-std::ostream &operator<<(std::ostream &os, const SuspendResumeJobsEntry &entry);
-std::ostream &operator<<(std::ostream &os, const ReferencesResult &value);
-std::ostream &operator<<(std::ostream &os, const ExtraInfo &extraInfo);
-std::ostream &operator<<(std::ostream &os, const TokenInfoContainer &container);
-std::ostream &operator<<(std::ostream &os, const UnsavedFilesRemovedMessage &message);
-
-} // namespace ClangBackEnd
-
namespace Debugger {
class DiagnosticLocation;
std::ostream &operator<<(std::ostream &out, const DiagnosticLocation &loc);
diff --git a/tests/unit/unittest/highlightingresultreporter-test.cpp b/tests/unit/unittest/highlightingresultreporter-test.cpp
deleted file mode 100644
index f7651f5134c..00000000000
--- a/tests/unit/unittest/highlightingresultreporter-test.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "unittest-utility-functions.h"
-
-#include <chunksreportedmonitor.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <cursor.h>
-#include <tokeninfocontainer.h>
-#include <tokenprocessor.h>
-#include <clanghighlightingresultreporter.h>
-#include <unsavedfiles.h>
-
-using ClangBackEnd::Cursor;
-using ClangBackEnd::TokenProcessor;
-using ClangBackEnd::TokenInfoContainer;
-using ClangBackEnd::HighlightingType;
-using ClangBackEnd::Document;
-using ClangBackEnd::Documents;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::ChunksReportedMonitor;
-
-namespace {
-
-struct Data {
- UnsavedFiles unsavedFiles;
- Documents documents{unsavedFiles};
- Document document{Utf8StringLiteral(TESTDATA_DIR "/highlightingmarks.cpp"),
- UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++14")}),
- Utf8StringVector(),
- documents};
-};
-
-class HighlightingResultReporter : public ::testing::Test
-{
-public:
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-protected:
- static Data *d;
-};
-
-QVector<TokenInfoContainer> noTokenInfos()
-{
- return QVector<TokenInfoContainer>();
-}
-
-QVector<TokenInfoContainer> generateTokenInfos(uint count)
-{
- auto container = QVector<TokenInfoContainer>();
-
- for (uint i = 0; i < count; ++i) {
- const uint line = i + 1;
- ClangBackEnd::HighlightingTypes types;
- types.mainHighlightingType = ClangBackEnd::HighlightingType::Type;
- container.append(TokenInfoContainer(line, 1, 1, types));
- }
-
- return container;
-}
-
-TEST_F(HighlightingResultReporter, StartAndFinish)
-{
- auto future = ClangCodeModel::Internal::highlightResults(noTokenInfos());
-
- future.waitForFinished();
- ASSERT_THAT(future.isFinished(), true);
-}
-
-TEST_F(HighlightingResultReporter, ReportNothingIfNothingToReport)
-{
- auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(0));
-
- ChunksReportedMonitor monitor(future);
- ASSERT_THAT(monitor.resultsReadyCounter(), 0L);
-}
-
-TEST_F(HighlightingResultReporter, ReportSingleResultAsOneChunk)
-{
- auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(1), 1);
-
- ChunksReportedMonitor monitor(future);
- ASSERT_THAT(monitor.resultsReadyCounter(), 1L);
-}
-
-TEST_F(HighlightingResultReporter, ReportRestIfChunkSizeNotReached)
-{
- auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(1), 100);
-
- ChunksReportedMonitor monitor(future);
- ASSERT_THAT(monitor.resultsReadyCounter(), 1L);
-}
-
-TEST_F(HighlightingResultReporter, ReportChunksWithoutRest)
-{
- auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(4), 1);
-
- ChunksReportedMonitor monitor(future);
- ASSERT_THAT(monitor.resultsReadyCounter(), 2L);
-}
-
-TEST_F(HighlightingResultReporter, ReportSingleChunkAndRest)
-{
- auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(5), 2);
-
- ChunksReportedMonitor monitor(future);
- ASSERT_THAT(monitor.resultsReadyCounter(), 2L);
-}
-
-TEST_F(HighlightingResultReporter, ReportCompleteLines)
-{
- ClangBackEnd::HighlightingTypes types;
- types.mainHighlightingType = ClangBackEnd::HighlightingType::Type;
- QVector<TokenInfoContainer> tokenInfos {
- TokenInfoContainer(1, 1, 1, types),
- TokenInfoContainer(1, 2, 1, types),
- TokenInfoContainer(2, 1, 1, types),
- };
-
- auto future = ClangCodeModel::Internal::highlightResults(tokenInfos, 1);
-
- ChunksReportedMonitor monitor(future);
- ASSERT_THAT(monitor.resultsReadyCounter(), 2L);
-}
-
-Data *HighlightingResultReporter::d;
-
-void HighlightingResultReporter::SetUpTestCase()
-{
- d = new Data;
-}
-
-void HighlightingResultReporter::TearDownTestCase()
-{
- delete d;
- d = nullptr;
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/lineprefixer-test.cpp b/tests/unit/unittest/lineprefixer-test.cpp
deleted file mode 100644
index 222a0f282bb..00000000000
--- a/tests/unit/unittest/lineprefixer-test.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <lineprefixer.h>
-#include <utf8string.h>
-
-namespace {
-
-QByteArray runPrefixer(QList<QByteArray> inputChunks);
-
-TEST(LinePrefixer, OneChunkEndsWithNewline)
-{
- const QList<QByteArray> inputChunks = {"hello\n"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX hello\n");
-}
-
-TEST(LinePrefixer, OneChunkEndsWithoutNewline)
-{
- const QList<QByteArray> inputChunks = {"hello"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX hello");
-}
-
-TEST(LinePrefixer, OneChunkStartsWithNewline)
-{
- const QList<QByteArray> inputChunks = {"\nhello"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX \n"
- "PREFIX hello");
-}
-
-TEST(LinePrefixer, OneChunkStartsAndEndsWithNewline)
-{
- const QList<QByteArray> inputChunks = {"\nhello\n"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX \n"
- "PREFIX hello\n");
-}
-
-TEST(LinePrefixer, OneChunkEndsWithExtraNewline)
-{
- const QList<QByteArray> inputChunks = {"hello\n\n"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX hello\n"
- "PREFIX \n");
-}
-
-TEST(LinePrefixer, OneChunkEndsWithTwoExtraNewlines)
-{
- const QList<QByteArray> inputChunks = {"hello\n\n\n"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX hello\n"
- "PREFIX \n"
- "PREFIX \n");
-}
-
-TEST(LinePrefixer, ChunkWithoutNewlineAndChunkWithNewline)
-{
- const QList<QByteArray> inputChunks = {"hello", "\n"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX hello\n");
-}
-
-TEST(LinePrefixer, ChunkWithoutNewlineAndChunkWithTwoNewlines)
-{
- const QList<QByteArray> inputChunks = {"hello", "\n\n"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX hello\n"
- "PREFIX \n");
-}
-
-TEST(LinePrefixer, ChunkWithTwoNewlinesAndChunkWithoutNewline)
-{
- const QList<QByteArray> inputChunks = {"\n\n", "hello"};
-
- auto text = runPrefixer(inputChunks);
-
- ASSERT_THAT(text, "PREFIX \n"
- "PREFIX \n"
- "PREFIX hello");
-}
-
-QByteArray runPrefixer(QList<QByteArray> inputChunks)
-{
- QByteArray actualOutput;
- ClangBackEnd::LinePrefixer prefixer("PREFIX ");
-
- for (const auto &chunk : inputChunks)
- actualOutput += prefixer.prefix(chunk);
-
- return actualOutput;
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/mockclangcodemodelclient.h b/tests/unit/unittest/mockclangcodemodelclient.h
deleted file mode 100644
index 9244e05eb8b..00000000000
--- a/tests/unit/unittest/mockclangcodemodelclient.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "googletest.h"
-
-#include <clangsupport/clangcodemodelclientinterface.h>
-#include <clangsupport/clangcodemodelclientmessages.h>
-
-class MockClangCodeModelClient : public ClangBackEnd::ClangCodeModelClientInterface
-{
-public:
- MOCK_METHOD0(alive,
- void());
- MOCK_METHOD1(echo,
- void(const ClangBackEnd::EchoMessage &message));
- MOCK_METHOD1(completions,
- void(const ClangBackEnd::CompletionsMessage &message));
- MOCK_METHOD1(annotations,
- void(const ClangBackEnd::AnnotationsMessage &message));
- MOCK_METHOD1(references,
- void(const ClangBackEnd::ReferencesMessage &message));
- MOCK_METHOD1(followSymbol,
- void(const ClangBackEnd::FollowSymbolMessage &message));
- MOCK_METHOD1(tooltip,
- void(const ClangBackEnd::ToolTipMessage &message));
-};
diff --git a/tests/unit/unittest/mockclangcodemodelserver.h b/tests/unit/unittest/mockclangcodemodelserver.h
deleted file mode 100644
index 7cbe596b369..00000000000
--- a/tests/unit/unittest/mockclangcodemodelserver.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "googletest.h"
-
-#include <clangcodemodelserverinterface.h>
-
-class MockClangCodeModelServer : public ClangBackEnd::ClangCodeModelServerInterface {
-public:
- MOCK_METHOD0(end,
- void());
-
- MOCK_METHOD1(documentsOpened,
- void(const ClangBackEnd::DocumentsOpenedMessage &message));
- MOCK_METHOD1(documentsChanged,
- void(const ClangBackEnd::DocumentsChangedMessage &message));
- MOCK_METHOD1(documentsClosed,
- void(const ClangBackEnd::DocumentsClosedMessage &message));
- MOCK_METHOD1(documentVisibilityChanged,
- void(const ClangBackEnd::DocumentVisibilityChangedMessage &message));
-
- MOCK_METHOD1(unsavedFilesUpdated,
- void(const ClangBackEnd::UnsavedFilesUpdatedMessage &message));
- MOCK_METHOD1(unsavedFilesRemoved,
- void(const ClangBackEnd::UnsavedFilesRemovedMessage &message));
-
- MOCK_METHOD1(requestCompletions,
- void(const ClangBackEnd::RequestCompletionsMessage &message));
- MOCK_METHOD1(requestAnnotations,
- void(const ClangBackEnd::RequestAnnotationsMessage &message));
- MOCK_METHOD1(requestReferences,
- void(const ClangBackEnd::RequestReferencesMessage &message));
- MOCK_METHOD1(requestFollowSymbol,
- void(const ClangBackEnd::RequestFollowSymbolMessage &message));
- MOCK_METHOD1(requestToolTip,
- void(const ClangBackEnd::RequestToolTipMessage &message));
-
-};
diff --git a/tests/unit/unittest/mockqueue.h b/tests/unit/unittest/mockqueue.h
deleted file mode 100644
index 74c35139149..00000000000
--- a/tests/unit/unittest/mockqueue.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "googletest.h"
-
-#include <queueinterface.h>
-
-class MockQueue : public ClangBackEnd::QueueInterface
-{
-public:
- MOCK_METHOD0(processEntries, void());
-};
-
diff --git a/tests/unit/unittest/readandwritemessageblock-test.cpp b/tests/unit/unittest/readandwritemessageblock-test.cpp
deleted file mode 100644
index a13def699d0..00000000000
--- a/tests/unit/unittest/readandwritemessageblock-test.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangcodemodelclientmessages.h>
-#include <clangcodemodelservermessages.h>
-
-#include <diagnosticcontainer.h>
-#include <tokeninfocontainer.h>
-#include <messageenvelop.h>
-#include <readmessageblock.h>
-#include <writemessageblock.h>
-
-#include <QBuffer>
-#include <QString>
-#include <QVariant>
-
-#include <vector>
-
-using namespace testing;
-namespace CodeModelBackeEndTest {
-
-class ReadAndWriteMessageBlock : public ::testing::Test
-{
-protected:
- ReadAndWriteMessageBlock();
-
- virtual void SetUp() override;
- virtual void TearDown() override;
-
- template<class Type>
- void CompareMessage(const Type &message);
-
- ClangBackEnd::MessageEnvelop writeCompletionsMessage();
- void popLastCharacterFromBuffer();
- void pushLastCharacterToBuffer();
- void readPartialMessage();
-
-protected:
- Utf8String filePath{Utf8StringLiteral("foo.cpp")};
- ClangBackEnd::FileContainer fileContainer{filePath,
- Utf8StringLiteral("unsaved content"),
- true,
- 1};
- QBuffer buffer;
- ClangBackEnd::WriteMessageBlock writeMessageBlock;
- ClangBackEnd::ReadMessageBlock readMessageBlock;
- char lastCharacter = 0;
-};
-
-ReadAndWriteMessageBlock::ReadAndWriteMessageBlock()
- : writeMessageBlock(&buffer),
- readMessageBlock(&buffer)
-{
-}
-
-void ReadAndWriteMessageBlock::SetUp()
-{
- buffer.open(QIODevice::ReadWrite);
- writeMessageBlock = ClangBackEnd::WriteMessageBlock(&buffer);
- readMessageBlock = ClangBackEnd::ReadMessageBlock(&buffer);
-}
-
-void ReadAndWriteMessageBlock::TearDown()
-{
- buffer.close();
-}
-
-TEST_F(ReadAndWriteMessageBlock, WriteMessageAndTestSize)
-{
- writeMessageBlock.write(ClangBackEnd::EndMessage());
-
- ASSERT_EQ(17, buffer.size());
-}
-
-TEST_F(ReadAndWriteMessageBlock, WriteSecondMessageAndTestSize)
-{
- writeMessageBlock.write(ClangBackEnd::EndMessage());
-
- ASSERT_EQ(17, buffer.size());
-}
-
-TEST_F(ReadAndWriteMessageBlock, WriteTwoMessagesAndTestCount)
-{
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- writeMessageBlock.write(ClangBackEnd::EndMessage());
-
- ASSERT_EQ(2, writeMessageBlock.counter());
-}
-
-TEST_F(ReadAndWriteMessageBlock, ReadThreeMessagesAndTestCount)
-{
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- buffer.seek(0);
-
- ASSERT_THAT(readMessageBlock.readAll(), SizeIs(3));
-}
-
-TEST_F(ReadAndWriteMessageBlock, WriteMessagesToWriteBlockWithoutIoDeviceAndNoMessagesAreSent)
-{
- ClangBackEnd::WriteMessageBlock writeMessageBlock;
-
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- buffer.seek(0);
-
- ASSERT_THAT(readMessageBlock.readAll(), IsEmpty());
-}
-
-TEST_F(ReadAndWriteMessageBlock, WriteMessagesToWriteBlockWithoutIoDeviceAndSetIoDeviceToNullPointerLater)
-{
- ClangBackEnd::WriteMessageBlock writeMessageBlock;
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- writeMessageBlock.write(ClangBackEnd::EndMessage());
-
- writeMessageBlock.setLocalSocket(nullptr);
- buffer.seek(0);
-
- ASSERT_THAT(readMessageBlock.readAll(), IsEmpty());
-}
-
-TEST_F(ReadAndWriteMessageBlock, WriteMessagesToWriteBlockWithoutIoDeviceAndSetIoDeviceLater)
-{
- ClangBackEnd::WriteMessageBlock writeMessageBlock;
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- writeMessageBlock.write(ClangBackEnd::EndMessage());
-
- writeMessageBlock.setIoDevice(&buffer);
- buffer.seek(0);
-
- ASSERT_THAT(readMessageBlock.readAll(), SizeIs(2));
-}
-
-TEST_F(ReadAndWriteMessageBlock, ResetStateResetsCounter)
-{
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- writeMessageBlock.write(ClangBackEnd::EndMessage());
- buffer.seek(0);
-
- writeMessageBlock.resetState();
-
- ASSERT_THAT(writeMessageBlock.counter(), 0);
-}
-
-TEST_F(ReadAndWriteMessageBlock, ResetStateResetsWritingBlock)
-{
- ClangBackEnd::WriteMessageBlock writeMessageBlock;
- writeMessageBlock.write(ClangBackEnd::EndMessage());
-
- writeMessageBlock.resetState();
-
- writeMessageBlock.setIoDevice(&buffer);
- buffer.seek(0);
- ASSERT_THAT(readMessageBlock.readAll(), IsEmpty());
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareEndMessage)
-{
- CompareMessage(ClangBackEnd::EndMessage());
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareAliveMessage)
-{
- CompareMessage(ClangBackEnd::AliveMessage());
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareDocumentsOpenedMessage)
-{
- CompareMessage(ClangBackEnd::DocumentsOpenedMessage({fileContainer}, filePath, {filePath}));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareDocumentsChangedMessage)
-{
- CompareMessage(ClangBackEnd::DocumentsChangedMessage({fileContainer}));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareDocumentsClosedMessage)
-{
- CompareMessage(ClangBackEnd::DocumentsClosedMessage({fileContainer}));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareRequestCompletionsMessage)
-{
- CompareMessage(ClangBackEnd::RequestCompletionsMessage(Utf8StringLiteral("foo.cpp"), 24, 33));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareCompletionsMessage)
-{
- ClangBackEnd::CodeCompletions codeCompletions({Utf8StringLiteral("newFunction()")});
-
- CompareMessage(ClangBackEnd::CompletionsMessage(codeCompletions, 1));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareAnnotationsMessage)
-{
- ClangBackEnd::DiagnosticContainer diagnostic(Utf8StringLiteral("don't do that"),
- Utf8StringLiteral("warning"),
- {Utf8StringLiteral("-Wpadded"), Utf8StringLiteral("-Wno-padded")},
- ClangBackEnd::DiagnosticSeverity::Warning,
- {Utf8StringLiteral("foo.cpp"), 20u, 103u},
- {{{Utf8StringLiteral("foo.cpp"), 20u, 103u}, {Utf8StringLiteral("foo.cpp"), 20u, 110u}}},
- {},
- {});
-
- ClangBackEnd::HighlightingTypes types;
- types.mainHighlightingType = ClangBackEnd::HighlightingType::Keyword;
- ClangBackEnd::TokenInfoContainer tokenInfo(1, 1, 1, types);
-
- CompareMessage(ClangBackEnd::AnnotationsMessage(fileContainer,
- {diagnostic},
- {},
- {tokenInfo},
- QVector<ClangBackEnd::SourceRangeContainer>()));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareUnsavedFilesUpdatedMessage)
-{
- CompareMessage(ClangBackEnd::UnsavedFilesUpdatedMessage({fileContainer}));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareUnsavedFilesRemovedMessage)
-{
- CompareMessage(ClangBackEnd::UnsavedFilesRemovedMessage({fileContainer}));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareRequestAnnotationsMessage)
-{
- CompareMessage(ClangBackEnd::RequestAnnotationsMessage(fileContainer));
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareRequestReferencesMessage)
-{
- CompareMessage(ClangBackEnd::RequestReferencesMessage{fileContainer, 13, 37});
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareRequestFollowSymbolMessage)
-{
- CompareMessage(ClangBackEnd::RequestFollowSymbolMessage{fileContainer, 13, 37});
-}
-
-TEST_F(ReadAndWriteMessageBlock, CompareReferencesMessage)
-{
- const QVector<ClangBackEnd::SourceRangeContainer> references{
- true,
- {{fileContainer.filePath, 12, 34},
- {fileContainer.filePath, 56, 78}}
- };
- CompareMessage(ClangBackEnd::ReferencesMessage(fileContainer, references, true, 1));
-}
-
-TEST_F(ReadAndWriteMessageBlock, GetInvalidMessageForAPartialBuffer)
-{
- writeCompletionsMessage();
- popLastCharacterFromBuffer();
- buffer.seek(0);
-
- readPartialMessage();
-}
-
-TEST_F(ReadAndWriteMessageBlock, ReadMessageAfterInterruption)
-{
- const auto writeMessage = writeCompletionsMessage();
- popLastCharacterFromBuffer();
- buffer.seek(0);
- readPartialMessage();
- pushLastCharacterToBuffer();
-
- ASSERT_EQ(readMessageBlock.read(), writeMessage);
-}
-
-ClangBackEnd::MessageEnvelop ReadAndWriteMessageBlock::writeCompletionsMessage()
-{
- ClangBackEnd::CompletionsMessage message(
- ClangBackEnd::CodeCompletions({Utf8StringLiteral("newFunction()")}), 1);
-
- writeMessageBlock.write(message);
-
- return message;
-}
-
-void ReadAndWriteMessageBlock::popLastCharacterFromBuffer()
-{
- auto &internalBuffer = buffer.buffer();
- lastCharacter = internalBuffer.at(internalBuffer.size() - 1);
- internalBuffer.chop(1);
-}
-
-void ReadAndWriteMessageBlock::pushLastCharacterToBuffer()
-{
- buffer.buffer().push_back(lastCharacter);
-}
-
-void ReadAndWriteMessageBlock::readPartialMessage()
-{
- const ClangBackEnd::MessageEnvelop readMessage = readMessageBlock.read();
-
- ASSERT_FALSE(readMessage.isValid());
-}
-
-template<class Type>
-void ReadAndWriteMessageBlock::CompareMessage(const Type &message)
-{
- const ClangBackEnd::MessageEnvelop writeMessage = message;
- writeMessageBlock.write(writeMessage);
- buffer.seek(0);
-
- const ClangBackEnd::MessageEnvelop readMessage = readMessageBlock.read();
-
- ASSERT_EQ(writeMessage, readMessage);
-}
-
-}
diff --git a/tests/unit/unittest/readexporteddiagnostics-test.cpp b/tests/unit/unittest/readexporteddiagnostics-test.cpp
deleted file mode 100644
index dcd0a00ee79..00000000000
--- a/tests/unit/unittest/readexporteddiagnostics-test.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangtools/clangtoolslogfilereader.h>
-
-#include <utils/fileutils.h>
-#include <utils/qtcassert.h>
-
-#define TESTDATA TESTDATA_DIR "/clangtools/"
-
-using namespace ClangTools::Internal;
-using Debugger::DiagnosticLocation;
-
-namespace {
-
-class ReadExportedDiagnostics : public ::testing::Test
-{
-protected:
- void SetUp() override
- {
- ASSERT_TRUE(temporaryDir.isValid());
- }
-
- // Replace FILE_PATH with a real absolute file path in the *.yaml files.
- QString createFile(const QString &yamlFilePath, const QString &filePathToInject)
- {
- QTC_ASSERT(QDir::isAbsolutePath(filePathToInject), return QString());
- const Utils::FilePath newFileName = temporaryDir.filePath(QFileInfo(yamlFilePath).fileName());
-
- Utils::FileReader reader;
- if (QTC_GUARD(reader.fetch(Utils::FilePath::fromString(yamlFilePath),
- QIODevice::ReadOnly | QIODevice::Text))) {
- QByteArray contents = reader.data();
- contents.replace("FILE_PATH", filePathToInject.toLocal8Bit());
-
- Utils::FileSaver fileSaver(newFileName, QIODevice::WriteOnly | QIODevice::Text);
- QTC_CHECK(fileSaver.write(contents));
- QTC_CHECK(fileSaver.finalize());
- }
-
- return newFileName.toString();
- }
-
-protected:
- QString errorMessage;
- Utils::TemporaryDirectory temporaryDir{"clangtools-tests-XXXXXX"};
-};
-
-TEST_F(ReadExportedDiagnostics, NotExistingFile)
-{
- Diagnostics diags = readExportedDiagnostics("notExistingFile.yaml",
- {},
- &errorMessage);
-
- ASSERT_THAT(diags, IsEmpty());
- ASSERT_FALSE(errorMessage.isEmpty());
-}
-
-TEST_F(ReadExportedDiagnostics, EmptyFile)
-{
- Diagnostics diags = readExportedDiagnostics(TESTDATA "empty.yaml",
- {},
- &errorMessage);
-
- ASSERT_THAT(diags, IsEmpty());
- ASSERT_TRUE(errorMessage.isEmpty());
-}
-
-TEST_F(ReadExportedDiagnostics, UnexpectedFileContents)
-{
- const QString sourceFile = TESTDATA "tidy.modernize-use-nullptr.cpp";
-
- Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(sourceFile),
- {},
- &errorMessage);
-
- ASSERT_FALSE(errorMessage.isEmpty());
- ASSERT_THAT(diags, IsEmpty());
-}
-
-static QString appendYamlSuffix(const char *filePathFragment)
-{
- const QString yamlSuffix = QLatin1String(Utils::HostOsInfo::isWindowsHost()
- ? "_win.yaml" : ".yaml");
- return filePathFragment + yamlSuffix;
-}
-
-TEST_F(ReadExportedDiagnostics, Tidy)
-{
- const Utils::FilePath sourceFile = Utils::FilePath::fromString(
- TESTDATA "tidy.modernize-use-nullptr.cpp");
- const QString exportedFile = createFile(appendYamlSuffix(TESTDATA "tidy.modernize-use-nullptr"),
- sourceFile.toString());
- Diagnostic expectedDiag;
- expectedDiag.name = "modernize-use-nullptr";
- expectedDiag.location = {sourceFile, 2, 25};
- expectedDiag.description = "use nullptr [modernize-use-nullptr]";
- expectedDiag.type = "warning";
- expectedDiag.hasFixits = true;
- expectedDiag.explainingSteps = {
- ExplainingStep{"nullptr",
- expectedDiag.location,
- {expectedDiag.location, {sourceFile, 2, 26}},
- true}};
-
- Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
- {},
- &errorMessage);
-
- ASSERT_TRUE(errorMessage.isEmpty());
- ASSERT_THAT(diags, ElementsAre(expectedDiag));
-}
-
-TEST_F(ReadExportedDiagnostics, AcceptDiagsFromFilePaths_None)
-{
- const QString sourceFile = TESTDATA "tidy.modernize-use-nullptr.cpp";
- const QString exportedFile = createFile(TESTDATA "tidy.modernize-use-nullptr.yaml", sourceFile);
- const auto acceptNone = [](const Utils::FilePath &) { return false; };
-
- Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
- acceptNone,
- &errorMessage);
-
- ASSERT_TRUE(errorMessage.isEmpty());
- ASSERT_THAT(diags, IsEmpty());
-}
-
-// Diagnostics from clang (static) analyzer passed through via clang-tidy
-TEST_F(ReadExportedDiagnostics, Tidy_ClangAnalyzer)
-{
- const Utils::FilePath sourceFile = Utils::FilePath::fromString(TESTDATA
- "clang-analyzer.dividezero.cpp");
- const QString exportedFile = createFile(appendYamlSuffix(TESTDATA "clang-analyzer.dividezero"),
- sourceFile.toString());
- Diagnostic expectedDiag;
- expectedDiag.name = "clang-analyzer-core.DivideZero";
- expectedDiag.location = {sourceFile, 4, 15};
- expectedDiag.description = "Division by zero [clang-analyzer-core.DivideZero]";
- expectedDiag.type = "warning";
- expectedDiag.hasFixits = false;
- expectedDiag.explainingSteps = {
- ExplainingStep{"Assuming 'z' is equal to 0",
- {sourceFile, 3, 7},
- {},
- false,
- },
- ExplainingStep{"Taking true branch",
- {sourceFile, 3, 3},
- {},
- false,
- },
- ExplainingStep{"Division by zero",
- {sourceFile, 4, 15},
- {},
- false,
- },
- };
-
- Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
- {},
- &errorMessage);
-
- ASSERT_TRUE(errorMessage.isEmpty());
- ASSERT_THAT(diags, ElementsAre(expectedDiag));
-}
-
-TEST_F(ReadExportedDiagnostics, Clazy)
-{
- const Utils::FilePath sourceFile = Utils::FilePath::fromString(TESTDATA "clazy.qgetenv.cpp");
- const QString exportedFile = createFile(appendYamlSuffix(TESTDATA "clazy.qgetenv"),
- sourceFile.toString());
- Diagnostic expectedDiag;
- expectedDiag.name = "clazy-qgetenv";
- expectedDiag.location = {sourceFile, 7, 5};
- expectedDiag.description = "qgetenv().isEmpty() allocates. Use qEnvironmentVariableIsEmpty() instead [clazy-qgetenv]";
- expectedDiag.type = "warning";
- expectedDiag.hasFixits = true;
- expectedDiag.explainingSteps = {
- ExplainingStep{"qEnvironmentVariableIsEmpty",
- expectedDiag.location,
- {expectedDiag.location, {sourceFile, 7, 12}},
- true
- },
- ExplainingStep{")",
- {sourceFile, 7, 18},
- {{sourceFile, 7, 18}, {sourceFile, 7, 29}},
- true},
- };
-
- Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
- {},
- &errorMessage);
-
- ASSERT_TRUE(errorMessage.isEmpty());
- ASSERT_THAT(diags, ElementsAre(expectedDiag));
-}
-
-class ByteOffsetInUtf8TextToLineColumn : public ::testing::Test
-{
-protected:
- const char *empty = "";
- const char *asciiWord = "FOO";
- const char *asciiMultiLine = "FOO\nBAR";
- const char *asciiMultiLine_dos = "FOO\r\nBAR";
- const char *asciiEmptyMultiLine = "\n\n";
- // U+00FC - 2 code units in UTF8, 1 in UTF16 - LATIN SMALL LETTER U WITH DIAERESIS
- // U+4E8C - 3 code units in UTF8, 1 in UTF16 - CJK UNIFIED IDEOGRAPH-4E8C
- // U+10302 - 4 code units in UTF8, 2 in UTF16 - OLD ITALIC LETTER KE
- const char *nonAsciiMultiLine = "\xc3\xbc" "\n"
- "\xe4\xba\x8c" "\n"
- "\xf0\x90\x8c\x82" "X";
-
- // Convenience
- const char *text = nullptr;
-};
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidText)
-{
- ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(nullptr, 0));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidOffset_EmptyInput)
-{
- ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(empty, 0));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidOffset_Before)
-{
- ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(asciiWord, -1));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidOffset_After)
-{
- ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(asciiWord, 3));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidOffset_NotFirstByteOfMultiByte)
-{
- ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 1));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, StartOfFirstLine)
-{
- auto info = byteOffsetInUtf8TextToLineColumn(asciiWord, 0);
-
- ASSERT_TRUE(info);
- ASSERT_THAT(info->line, Eq(1));
- ASSERT_THAT(info->column, Eq(1));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, EndOfFirstLine)
-{
- auto info = byteOffsetInUtf8TextToLineColumn(asciiWord, 2);
-
- ASSERT_TRUE(info);
- ASSERT_THAT(info->line, Eq(1));
- ASSERT_THAT(info->column, Eq(3));
-}
-
-// The invocation
-//
-// clang-tidy "-checks=-*,readability-braces-around-statements" /path/to/file
-//
-// for the code
-//
-// void f(bool b)
-// {
-// if (b)
-// f(b);
-// }
-//
-// emits
-//
-// 3:11: warning: statement should be inside braces [readability-braces-around-statements]
-//
-// The new line in the if-line is considered as column 11, which is normally not visible in the
-// editor.
-TEST_F(ByteOffsetInUtf8TextToLineColumn, OffsetPointingToLineSeparator_unix)
-{
- auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine, 3);
-
- ASSERT_TRUE(info);
- ASSERT_THAT(info->line, Eq(1));
- ASSERT_THAT(info->column, Eq(4));
-}
-
-// For a file with dos style line endings ("\r\n"), clang-tidy points to '\r'.
-TEST_F(ByteOffsetInUtf8TextToLineColumn, OffsetPointingToLineSeparator_dos)
-{
- auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine_dos, 3);
-
- ASSERT_TRUE(info);
- ASSERT_THAT(info->line, Eq(1));
- ASSERT_THAT(info->column, Eq(4));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, StartOfSecondLine)
-{
- auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine, 4);
-
- ASSERT_TRUE(info);
- ASSERT_THAT(info->line, Eq(2));
- ASSERT_THAT(info->column, Eq(1));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, MultiByteCodePoint1)
-{
- auto info = byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 3);
-
- ASSERT_TRUE(info);
- ASSERT_THAT(info->line, Eq(2));
- ASSERT_THAT(info->column, Eq(1));
-}
-
-TEST_F(ByteOffsetInUtf8TextToLineColumn, MultiByteCodePoint2)
-{
- auto info = byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 11);
-
- ASSERT_TRUE(info);
- ASSERT_THAT(info->line, Eq(3));
- ASSERT_THAT(info->column, Eq(2));
-}
-
-} // namespace
-
-#undef TESTDATA
diff --git a/tests/unit/unittest/rundocumentparse-utility.h b/tests/unit/unittest/rundocumentparse-utility.h
deleted file mode 100644
index 8bff06185db..00000000000
--- a/tests/unit/unittest/rundocumentparse-utility.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <clangdocument.h>
-
-namespace UnitTest {
-
-struct RunDocumentParse {
- RunDocumentParse(ClangBackEnd::Document &document)
- {
- document.parse();
- }
-};
-
-} // namespace UnitTest
-
diff --git a/tests/unit/unittest/skippedsourceranges-test.cpp b/tests/unit/unittest/skippedsourceranges-test.cpp
deleted file mode 100644
index 6a2d80d852f..00000000000
--- a/tests/unit/unittest/skippedsourceranges-test.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "unittest-utility-functions.h"
-
-#include <cursor.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangstring.h>
-#include <clangtranslationunit.h>
-#include <skippedsourceranges.h>
-#include <sourcelocation.h>
-#include <sourcerange.h>
-#include <unsavedfiles.h>
-
-#include <sourcerangecontainer.h>
-
-#include <QVector>
-
-using ClangBackEnd::Cursor;
-using ClangBackEnd::Document;
-using ClangBackEnd::Documents;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::ClangString;
-using ClangBackEnd::SourceRange;
-using ClangBackEnd::SkippedSourceRanges;
-
-using testing::IsNull;
-using testing::NotNull;
-using testing::Gt;
-using testing::Contains;
-using testing::EndsWith;
-using testing::AllOf;
-using testing::Not;
-using testing::IsEmpty;
-using testing::SizeIs;
-using testing::PrintToString;
-
-namespace {
-
-MATCHER_P4(IsSourceLocation, filePath, line, column, offset,
- std::string(negation ? "isn't" : "is")
- + " source location with file path "+ PrintToString(filePath)
- + ", line " + PrintToString(line)
- + ", column " + PrintToString(column)
- + " and offset " + PrintToString(offset)
- )
-{
- if (!arg.filePath().endsWith(filePath)
- || arg.line() != line
- || arg.column() != column
- || arg.offset() != offset) {
- return false;
- }
-
- return true;
-}
-
-struct Data {
- Data()
- {
- document.parse();
- }
-
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/skippedsourceranges.cpp");
- Utf8StringVector compilationArguments{UnitTest::addPlatformArguments(
- {Utf8StringLiteral("-std=c++11"), {}, Utf8StringLiteral("-DBLAH")})};
- Document document{filePath, compilationArguments, {}, documents};
- TranslationUnit translationUnit{filePath,
- filePath,
- document.translationUnit().cxIndex(),
- document.translationUnit().cxTranslationUnit()};
-};
-
-class SkippedSourceRanges : public ::testing::Test
-{
-public:
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-protected:
- static Data *d;
- const TranslationUnit &translationUnit = d->translationUnit;
- const Utf8String &filePath = d->filePath;
- ::SkippedSourceRanges skippedSourceRanges{d->translationUnit.skippedSourceRanges()};
- ::SkippedSourceRanges otherSkippedSourceRanges{d->translationUnit.skippedSourceRanges()};
-};
-
-Data *SkippedSourceRanges::d;
-
-TEST_F(SkippedSourceRanges, MoveConstructor)
-{
- const auto other = std::move(skippedSourceRanges);
-
- ASSERT_TRUE(skippedSourceRanges.isNull());
- ASSERT_FALSE(other.isNull());
-}
-
-TEST_F(SkippedSourceRanges, MoveAssignment)
-{
- skippedSourceRanges = std::move(otherSkippedSourceRanges);
-
- ASSERT_TRUE(otherSkippedSourceRanges.isNull());
- ASSERT_FALSE(skippedSourceRanges.isNull());
-}
-
-TEST_F(SkippedSourceRanges, RangeWithZero)
-{
- auto ranges = skippedSourceRanges.sourceRanges();
-
- ASSERT_THAT(ranges, SizeIs(2));
-}
-
-TEST_F(SkippedSourceRanges, DISABLED_ON_WINDOWS(RangeOne))
-{
- auto ranges = skippedSourceRanges.sourceRanges();
-
- ASSERT_THAT(ranges[0].start(), IsSourceLocation(filePath, 2, 1, 6));
- ASSERT_THAT(ranges[0].end(), IsSourceLocation(filePath, 5, 1, 18));
-}
-
-TEST_F(SkippedSourceRanges, DISABLED_ON_WINDOWS(RangeTwo))
-{
- auto ranges = skippedSourceRanges.sourceRanges();
-
- ASSERT_THAT(ranges[1].start(), IsSourceLocation(filePath, 8, 1, 39));
- ASSERT_THAT(ranges[1].end(), IsSourceLocation(filePath, 12, 1, 57));
-}
-
-TEST_F(SkippedSourceRanges, RangeContainerSize)
-{
- auto ranges = skippedSourceRanges.toSourceRangeContainers();
-
- ASSERT_THAT(ranges, SizeIs(2));
-}
-
-void SkippedSourceRanges::SetUpTestCase()
-{
- d = new Data;
-}
-
-void SkippedSourceRanges::TearDownTestCase()
-{
- delete d;
- d = nullptr;
-}
-
-}
diff --git a/tests/unit/unittest/sourcelocation-test.cpp b/tests/unit/unittest/sourcelocation-test.cpp
deleted file mode 100644
index 3465682bf7c..00000000000
--- a/tests/unit/unittest/sourcelocation-test.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "rundocumentparse-utility.h"
-
-#include <diagnostic.h>
-#include <diagnosticset.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangtranslationunit.h>
-#include <unsavedfiles.h>
-#include <sourcelocation.h>
-
-#include <utils/hostosinfo.h>
-
-#include <clang-c/Index.h>
-
-using ClangBackEnd::Diagnostic;
-using ClangBackEnd::DiagnosticSet;
-using ClangBackEnd::SourceLocation;
-using ClangBackEnd::Document;
-using ClangBackEnd::UnsavedFiles;
-
-using testing::EndsWith;
-using testing::Not;
-
-namespace {
-
-struct Data {
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Document document{Utf8StringLiteral(TESTDATA_DIR"/diagnostic_source_location.cpp"),
- {},
- {},
- documents};
- UnitTest::RunDocumentParse _1{document};
- DiagnosticSet diagnosticSet{document.translationUnit().diagnostics()};
- Diagnostic diagnostic{diagnosticSet.front()};
- ClangBackEnd::SourceLocation sourceLocation{diagnostic.location()};
-};
-
-class SourceLocation : public ::testing::Test
-{
-public:
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-protected:
- static std::unique_ptr<const Data> data;
- const Document &document = data->document;
- const ClangBackEnd::SourceLocation &sourceLocation = data->sourceLocation;
-};
-
-TEST_F(SourceLocation, FilePath)
-{
- ASSERT_THAT(sourceLocation.filePath().constData(), EndsWith("diagnostic_source_location.cpp"));
-}
-
-TEST_F(SourceLocation, Line)
-{
- ASSERT_THAT(sourceLocation.line(), 4);
-}
-
-TEST_F(SourceLocation, Column)
-{
- ASSERT_THAT(sourceLocation.column(), 1);
-}
-
-TEST_F(SourceLocation, Offset)
-{
- ASSERT_THAT(sourceLocation.offset(), Utils::HostOsInfo::isWindowsHost() ? 21 : 18);
-}
-
-TEST_F(SourceLocation, Create)
-{
- ASSERT_THAT(document.translationUnit().sourceLocationAt(4, 1), sourceLocation);
-}
-
-TEST_F(SourceLocation, NotEqual)
-{
- ASSERT_THAT(document.translationUnit().sourceLocationAt(3, 1), Not(sourceLocation));
-}
-
-TEST_F(SourceLocation, BeforeMultibyteCharacter)
-{
- ClangBackEnd::SourceLocation sourceLocation(
- document.translationUnit().cxTranslationUnit(),
- clang_getLocation(document.translationUnit().cxTranslationUnit(),
- clang_getFile(document.translationUnit().cxTranslationUnit(),
- document.filePath().constData()),
- 8, 10));
-
- ASSERT_THAT(document.translationUnit().sourceLocationAt(8, 10).column(), sourceLocation.column());
-}
-
-TEST_F(SourceLocation, AfterMultibyteCharacter)
-{
- ClangBackEnd::SourceLocation sourceLocation(
- document.translationUnit().cxTranslationUnit(),
- clang_getLocation(document.translationUnit().cxTranslationUnit(),
- clang_getFile(document.translationUnit().cxTranslationUnit(),
- document.filePath().constData()),
- 8, 12));
-
- ASSERT_THAT(document.translationUnit().sourceLocationAt(8, 13).column(), sourceLocation.column());
-}
-
-std::unique_ptr<const Data> SourceLocation::data;
-
-void SourceLocation::SetUpTestCase()
-{
- data = std::make_unique<const Data>();
-}
-
-void SourceLocation::TearDownTestCase()
-{
- data.reset();
-}
-
-}
diff --git a/tests/unit/unittest/sourcerange-test.cpp b/tests/unit/unittest/sourcerange-test.cpp
deleted file mode 100644
index 26c7a5a4223..00000000000
--- a/tests/unit/unittest/sourcerange-test.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "rundocumentparse-utility.h"
-#include "unittest-utility-functions.h"
-
-#include <clangtranslationunit.h>
-#include <diagnostic.h>
-#include <diagnosticset.h>
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <unsavedfiles.h>
-#include <sourcerange.h>
-
-#include <clang-c/Index.h>
-
-#include <memory>
-
-using ClangBackEnd::DiagnosticSet;
-using ClangBackEnd::Document;
-using ClangBackEnd::Documents;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::Diagnostic;
-using ClangBackEnd::SourceRange;
-
-using testing::PrintToString;
-using testing::IsEmpty;
-
-namespace {
-
-MATCHER_P4(IsSourceLocation, filePath, line, column, offset,
- std::string(negation ? "isn't" : "is")
- + " source location with file path "+ PrintToString(filePath)
- + ", line " + PrintToString(line)
- + ", column " + PrintToString(column)
- + " and offset " + PrintToString(offset)
- )
-{
- if (!arg.filePath().endsWith(filePath)
- || arg.line() != line
- || arg.column() != column
- || arg.offset() != offset) {
- return false;
- }
-
- return true;
-}
-
-struct Data {
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/diagnostic_source_range.cpp")};
- Document document{filePath,
- {UnitTest::addPlatformArguments({Utf8StringLiteral("-pedantic")})},
- {},
- documents};
- UnitTest::RunDocumentParse _1{document};
- TranslationUnit translationUnit{filePath,
- filePath,
- document.translationUnit().cxIndex(),
- document.translationUnit().cxTranslationUnit()};
- DiagnosticSet diagnosticSet{document.translationUnit().diagnostics()};
- Diagnostic diagnostic{diagnosticSet.front()};
- Diagnostic diagnosticWithFilteredOutInvalidRange{diagnosticSet.at(1)};
- ClangBackEnd::SourceRange sourceRange{diagnostic.ranges().front()};
-};
-
-class SourceRange : public ::testing::Test
-{
-public:
- static void SetUpTestCase();
- static void TearDownTestCase();
-
-protected:
- static std::unique_ptr<const Data> data;
- const ::SourceRange &sourceRange = data->sourceRange;
- const Diagnostic &diagnostic = data->diagnostic;
- const Diagnostic &diagnosticWithFilteredOutInvalidRange = data->diagnosticWithFilteredOutInvalidRange;
- const TranslationUnit &translationUnit = data->translationUnit;
-};
-
-TEST_F(SourceRange, IsNull)
-{
- ::SourceRange sourceRange;
-
- ASSERT_TRUE(sourceRange.isNull());
-}
-
-TEST_F(SourceRange, IsNotNull)
-{
- ::SourceRange sourceRange = diagnostic.ranges()[0];
-
- ASSERT_FALSE(sourceRange.isNull());
-}
-
-TEST_F(SourceRange, Size)
-{
- ASSERT_THAT(diagnostic.ranges().size(), 2);
-}
-
-TEST_F(SourceRange, DISABLED_ON_WINDOWS(Start))
-{
- ASSERT_THAT(sourceRange.start(), IsSourceLocation(Utf8StringLiteral("diagnostic_source_range.cpp"),
- 8,
- 5,
- 43));
-}
-
-TEST_F(SourceRange, DISABLED_ON_WINDOWS(End))
-{
- ASSERT_THAT(sourceRange.end(), IsSourceLocation(Utf8StringLiteral("diagnostic_source_range.cpp"),
- 8,
- 6,
- 44));
-}
-
-TEST_F(SourceRange, Create)
-{
- ASSERT_THAT(sourceRange, ::SourceRange(sourceRange.start(), sourceRange.end()));
-}
-
-TEST_F(SourceRange, SourceRangeFromTranslationUnit)
-{
- auto sourceRangeFromTranslationUnit = translationUnit.sourceRange(8u, 5u, 8u, 6u);
-
- ASSERT_THAT(sourceRangeFromTranslationUnit, sourceRange);
-}
-
-TEST_F(SourceRange, InvalidRangeIsFilteredOut)
-{
- ASSERT_THAT(diagnosticWithFilteredOutInvalidRange.ranges(), IsEmpty());
-}
-
-std::unique_ptr<const Data> SourceRange::data;
-
-void SourceRange::SetUpTestCase()
-{
- data = std::make_unique<const Data>();
-}
-
-void SourceRange::TearDownTestCase()
-{
- data.reset();
-}
-
-}
diff --git a/tests/unit/unittest/sourcerangecontainer-matcher.h b/tests/unit/unittest/sourcerangecontainer-matcher.h
deleted file mode 100644
index c2345be533a..00000000000
--- a/tests/unit/unittest/sourcerangecontainer-matcher.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "googletest.h"
-
-using testing::PrintToString;
-
-namespace {
-
-MATCHER_P4(IsSourceRange, startLine, startColumn, endLine, endColumn,
- std::string(negation ? "isn't" : "is")
- + "[(" + PrintToString(startLine)
- + ", " + PrintToString(startColumn)
- + "), (" + PrintToString(endLine)
- + ", " + PrintToString(endColumn)
- + ")]"
- )
-{
- return arg.start.line == uint(startLine)
- && arg.start.column == uint(startColumn)
- && arg.end.line == uint(endLine)
- && arg.end.column == uint(endColumn);
-}
-
-MATCHER_P5(IsSourceRangeWithText, startLine, startColumn, endLine, endColumn, text,
- std::string(negation ? "isn't " : "is ")
- + "((" + PrintToString(startLine)
- + ", " + PrintToString(startColumn)
- + "), (" + PrintToString(endLine)
- + ", " + PrintToString(endColumn)
- + "), " + PrintToString(text)
- + ")"
- )
-{
- return arg.start.line == uint(startLine)
- && arg.start.column == uint(startColumn)
- && arg.end.line == uint(endLine)
- && arg.end.column == uint(endColumn)
- && arg.text.toCarriageReturnsStripped() == text;
-
-}
-
-}
diff --git a/tests/unit/unittest/sqlitedatabase-test.cpp b/tests/unit/unittest/sqlitedatabase-test.cpp
index 92cdf01961c..f95c4d84737 100644
--- a/tests/unit/unittest/sqlitedatabase-test.cpp
+++ b/tests/unit/unittest/sqlitedatabase-test.cpp
@@ -31,7 +31,6 @@
#include <sqlitereadstatement.h>
#include <sqlitetable.h>
#include <sqlitewritestatement.h>
-#include <utf8string.h>
#include <utils/temporarydirectory.h>
diff --git a/tests/unit/unittest/token-test.cpp b/tests/unit/unittest/token-test.cpp
deleted file mode 100644
index f5f8a36e3a9..00000000000
--- a/tests/unit/unittest/token-test.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include "unittest-utility-functions.h"
-
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangstring.h>
-#include <clangtranslationunit.h>
-#include <cursor.h>
-#include <sourcelocation.h>
-#include <sourcerange.h>
-#include <token.h>
-#include <unsavedfiles.h>
-
-using ClangBackEnd::Cursor;
-using ClangBackEnd::Document;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::Documents;
-using ClangBackEnd::ClangString;
-using ClangBackEnd::SourceLocation;
-using ClangBackEnd::SourceRange;
-using ClangBackEnd::Token;
-using ClangBackEnd::Tokens;
-
-namespace {
-
-struct Data {
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/token.cpp")};
- Utf8StringVector compilationArguments{
- UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++11")})};
- Document document{filePath, compilationArguments, {}, documents};
- TranslationUnit translationUnit{filePath,
- filePath,
- document.translationUnit().cxIndex(),
- document.translationUnit().cxTranslationUnit()};
-};
-
-class Token : public ::testing::Test
-{
-protected:
- static void SetUpTestCase()
- {
- d = std::make_unique<const Data>();
- d->document.parse();
- }
-
-protected:
- static std::unique_ptr<const Data> d;
- const Document &document = d->document;
- const TranslationUnit &translationUnit = d->translationUnit;
- const SourceRange range{{translationUnit.cxTranslationUnit(),
- clang_getLocation(translationUnit.cxTranslationUnit(),
- clang_getFile(translationUnit.cxTranslationUnit(),
- d->filePath.constData()),
- 1, 1)},
- {translationUnit.cxTranslationUnit(),
- clang_getLocation(translationUnit.cxTranslationUnit(),
- clang_getFile(translationUnit.cxTranslationUnit(),
- d->filePath.constData()),
- 3, 2)}};
- const Tokens tokens{range};
-};
-
-std::unique_ptr<const Data> Token::d;
-
-TEST_F(Token, CreateTokens)
-{
- ASSERT_THAT(tokens.size(), 8u);
-}
-
-TEST_F(Token, AnnotateTokens)
-{
- auto cursors = tokens.annotate();
-
- ASSERT_THAT(cursors.size(), 8u);
-}
-
-TEST_F(Token, TokenKind)
-{
- auto kind = tokens[0].kind();
-
- ASSERT_THAT(kind, CXToken_Keyword);
-}
-
-TEST_F(Token, TokenLocation)
-{
- auto location = range.start();
-
- auto tokenLocation = tokens[0].location();
-
- ASSERT_THAT(tokenLocation, location);
-}
-
-TEST_F(Token, TokenSpelling)
-{
- auto spelling = tokens[0].spelling();
-
- ASSERT_THAT(spelling, "void");
-}
-
-TEST_F(Token, TokenExtent)
-{
- ::SourceRange tokenRange(range.start(), ::SourceLocation(translationUnit.cxTranslationUnit(),
- clang_getLocation(translationUnit.cxTranslationUnit(),
- clang_getFile(translationUnit.cxTranslationUnit(),
- d->filePath.constData()),
- 1, 5)));
-
- auto extent = tokens[0].extent();
-
- ASSERT_THAT(extent, tokenRange);
-}
-
-
-}
diff --git a/tests/unit/unittest/tokenprocessor-test.cpp b/tests/unit/unittest/tokenprocessor-test.cpp
deleted file mode 100644
index 0a6106569f7..00000000000
--- a/tests/unit/unittest/tokenprocessor-test.cpp
+++ /dev/null
@@ -1,1871 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-#include "unittest-utility-functions.h"
-
-#include <clangdocument.h>
-#include <clangdocuments.h>
-#include <clangtranslationunit.h>
-#include <cursor.h>
-#include <clangsupport_global.h>
-#include <clangstring.h>
-#include <fulltokeninfo.h>
-#include <sourcelocation.h>
-#include <sourcerange.h>
-#include <tokeninfo.h>
-#include <tokenprocessor.h>
-#include <unsavedfiles.h>
-
-#include <clang-c/Index.h>
-
-using ClangBackEnd::Cursor;
-using ClangBackEnd::HighlightingTypes;
-using ClangBackEnd::TokenInfo;
-using ClangBackEnd::TokenProcessor;
-using ClangBackEnd::HighlightingType;
-using ClangBackEnd::Document;
-using ClangBackEnd::Documents;
-using ClangBackEnd::TranslationUnit;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::ClangString;
-using ClangBackEnd::SourceRange;
-
-using testing::PrintToString;
-using testing::IsNull;
-using testing::NotNull;
-using testing::Gt;
-using testing::Contains;
-using testing::ElementsAre;
-using testing::_;
-using testing::EndsWith;
-using testing::AllOf;
-using testing::Not;
-using testing::IsEmpty;
-using testing::SizeIs;
-
-namespace {
-
-MATCHER_P4(IsHighlightingMark, line, column, length, type,
- std::string(negation ? "isn't " : "is ")
- + PrintToString(line) + ", "
- + PrintToString(column) + ", "
- + PrintToString(length) + ", "
- + PrintToString(type) + ", "
- )
-{
- return arg.line() == line && arg.column() == column && arg.length() == length
- && arg.types().mainHighlightingType == type;
-}
-
-MATCHER_P(HasOnlyType, type,
- std::string(negation ? "isn't " : "is ")
- + PrintToString(type)
- )
-{
- return arg.hasOnlyType(type);
-}
-
-MATCHER_P2(HasTwoTypes, firstType, secondType,
- std::string(negation ? "isn't " : "is ")
- + PrintToString(firstType)
- + " and "
- + PrintToString(secondType)
- )
-{
- return arg.hasMainType(firstType) && arg.hasMixinTypeAt(0, secondType) && arg.mixinSize() == 1;
-}
-
-MATCHER_P3(HasThreeTypes, firstType, secondType, thirdType,
- std::string(negation ? "isn't " : "is ")
- + PrintToString(firstType)
- + ", "
- + PrintToString(secondType)
- + " and "
- + PrintToString(thirdType)
- )
-{
- return arg.hasMainType(firstType) && arg.hasMixinTypeAt(0, secondType) && arg.hasMixinTypeAt(1, thirdType) && arg.mixinSize() == 2;
-}
-
-MATCHER_P(HasMixin, mixinType,
- std::string(negation ? "isn't " : "is ")
- + PrintToString(mixinType)
- )
-{
- return arg.hasMixinType(mixinType);
-}
-
-struct Data {
- Data()
- {
- document.parse();
- }
-
- ClangBackEnd::UnsavedFiles unsavedFiles;
- ClangBackEnd::Documents documents{unsavedFiles};
- Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/highlightingmarks.cpp")};
- Document document{filePath,
- UnitTest::addPlatformArguments(
- {Utf8StringLiteral("-std=c++14"),
- Utf8StringLiteral("-I" TESTDATA_DIR)}),
- {},
- documents};
- TranslationUnit translationUnit{filePath,
- filePath,
- document.translationUnit().cxIndex(),
- document.translationUnit().cxTranslationUnit()};
-};
-
-class TokenProcessor : public ::testing::Test
-{
-public:
- static void SetUpTestCase();
- static void TearDownTestCase();
-
- SourceRange sourceRange(uint line, uint columnEnd) const;
- SourceRange sourceRangeMultiLine(uint firstLine, uint lastLine, uint columnEnd) const;
-
-protected:
- static Data *d;
- const TranslationUnit &translationUnit = d->translationUnit;
-};
-
-TEST_F(TokenProcessor, CreateNullInformations)
-{
- ::TokenProcessor<TokenInfo> infos;
-
- ASSERT_TRUE(infos.isNull());
-}
-
-TEST_F(TokenProcessor, NullInformationsAreEmpty)
-{
- ::TokenProcessor<TokenInfo> infos;
-
- ASSERT_TRUE(infos.isEmpty());
-}
-
-TEST_F(TokenProcessor, IsNotNull)
-{
- const auto aRange = translationUnit.sourceRange(3, 1, 5, 1);
-
- const auto infos = translationUnit.tokenInfosInRange(aRange);
-
- ASSERT_FALSE(infos.isNull());
-}
-
-TEST_F(TokenProcessor, IteratorBeginEnd)
-{
- const auto aRange = translationUnit.sourceRange(3, 1, 5, 1);
- const auto infos = translationUnit.tokenInfosInRange(aRange);
-
- const auto endIterator = std::next(infos.begin(), infos.size());
-
- ASSERT_THAT(infos.end(), endIterator);
-}
-
-TEST_F(TokenProcessor, ForFullTranslationUnitRange)
-{
- const auto infos = translationUnit.tokenInfos();
-
- ASSERT_THAT(infos, AllOf(Contains(IsHighlightingMark(1u, 1u, 4u, HighlightingType::Keyword)),
- Contains(IsHighlightingMark(277u, 5u, 15u, HighlightingType::Function))));
-}
-
-TEST_F(TokenProcessor, Size)
-{
- const auto range = translationUnit.sourceRange(5, 5, 5, 10);
-
- const auto infos = translationUnit.tokenInfosInRange(range);
-
- ASSERT_THAT(infos.size(), 1);
-}
-
-TEST_F(TokenProcessor, DISABLED_Keyword)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(5, 12));
-
- ASSERT_THAT(infos[0], IsHighlightingMark(5u, 5u, 6u, HighlightingType::Keyword));
-}
-
-TEST_F(TokenProcessor, StringLiteral)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(1, 29));
-
- ASSERT_THAT(infos[4], IsHighlightingMark(1u, 24u, 10u, HighlightingType::StringLiteral));
-}
-
-TEST_F(TokenProcessor, Utf8StringLiteral)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(2, 33));
-
- ASSERT_THAT(infos[4], IsHighlightingMark(2u, 24u, 12u, HighlightingType::StringLiteral));
-}
-
-TEST_F(TokenProcessor, RawStringLiteral)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(3, 34));
-
- ASSERT_THAT(infos[4], IsHighlightingMark(3u, 24u, 13u, HighlightingType::StringLiteral));
-}
-
-TEST_F(TokenProcessor, CharacterLiteral)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(4, 28));
-
- ASSERT_THAT(infos[3], IsHighlightingMark(4u, 24u, 3u, HighlightingType::StringLiteral));
-}
-
-TEST_F(TokenProcessor, IntegerLiteral)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(23, 26));
-
- ASSERT_THAT(infos[3], IsHighlightingMark(23u, 24u, 1u, HighlightingType::NumberLiteral));
-}
-
-TEST_F(TokenProcessor, FloatLiteral)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(24, 29));
-
- ASSERT_THAT(infos[3], IsHighlightingMark(24u, 24u, 4u, HighlightingType::NumberLiteral));
-}
-
-TEST_F(TokenProcessor, FunctionDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(45, 20));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Function, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
-}
-
-TEST_F(TokenProcessor, MemberFunctionDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(52, 29));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Function, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
-}
-
-TEST_F(TokenProcessor, VirtualMemberFunctionDefinitionOutsideOfClassBody)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(586, 37));
-
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::VirtualFunction, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
-}
-
-TEST_F(TokenProcessor, VirtualMemberFunctionDefinitionInsideOfClassBody)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(589, 47));
-
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::VirtualFunction, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
-}
-
-TEST_F(TokenProcessor, FunctionDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(55, 32));
-
- ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Function, HighlightingType::Declaration));
-}
-
-TEST_F(TokenProcessor, MemberFunctionDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(59, 27));
-
- ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Function, HighlightingType::Declaration));
-}
-
-TEST_F(TokenProcessor, MemberFunctionReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(104, 35));
-
- ASSERT_THAT(infos[0], IsHighlightingMark(104u, 9u, 23u, HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, FunctionCall)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(64, 16));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, TypeConversionFunction)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(68, 20));
-
- ASSERT_THAT(infos[1], IsHighlightingMark(68u, 14u, 3u, HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, InbuiltTypeConversionFunction)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(69, 20));
-
- ASSERT_THAT(infos[1], IsHighlightingMark(69u, 14u, 3u, HighlightingType::PrimitiveType));
-}
-
-TEST_F(TokenProcessor, TypeReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(74, 13));
-
- ASSERT_THAT(infos[0], IsHighlightingMark(74u, 5u, 3u, HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, LocalVariable)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(79, 13));
-
- ASSERT_THAT(infos[1], IsHighlightingMark(79u, 9u, 3u, HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, LocalVariableDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(79, 13));
-
- ASSERT_THAT(infos[1], IsHighlightingMark(79u, 9u, 3u, HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, LocalVariableReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(81, 26));
-
- ASSERT_THAT(infos[0], IsHighlightingMark(81u, 5u, 3u, HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, ParameterFunctionArgumentDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(84, 45));
-
- ASSERT_THAT(infos[5], IsHighlightingMark(84u, 41u, 3u, HighlightingType::Parameter));
-}
-
-TEST_F(TokenProcessor, ParameterFunctionArgumentReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(86, 26));
-
- ASSERT_THAT(infos[0], IsHighlightingMark(86u, 5u, 3u, HighlightingType::Parameter));
-}
-
-TEST_F(TokenProcessor, ClassVariableDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(90, 21));
-
- ASSERT_THAT(infos[1], IsHighlightingMark(90u, 9u, 11u, HighlightingType::Field));
-}
-
-TEST_F(TokenProcessor, ClassVariableReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(94, 23));
-
- ASSERT_THAT(infos[0], IsHighlightingMark(94u, 9u, 11u, HighlightingType::Field));
-}
-
-TEST_F(TokenProcessor, StaticMethodDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(110, 25));
-
- ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Function, HighlightingType::Declaration));
-}
-
-TEST_F(TokenProcessor, StaticMethodReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(114, 30));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, Enumeration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(118, 17));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Enum));
-}
-
-TEST_F(TokenProcessor, Enumerator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(120, 15));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Enumeration));
-}
-
-TEST_F(TokenProcessor, EnumerationReferenceDeclarationType)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(125, 28));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Enum));
-}
-
-TEST_F(TokenProcessor, EnumerationReferenceDeclarationVariable)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(125, 28));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, EnumerationReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(127, 30));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, EnumeratorReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(127, 30));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Enumeration));
-}
-
-TEST_F(TokenProcessor, ClassForwardDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(130, 12));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, ConstructorDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(134, 13));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Function, HighlightingType::Declaration));
-}
-
-TEST_F(TokenProcessor, DestructorDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(135, 15));
-
- ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Function, HighlightingType::Declaration));
-}
-
-TEST_F(TokenProcessor, ClassForwardDeclarationReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(138, 23));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, ClassTypeReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(140, 32));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, ConstructorReferenceVariable)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(140, 32));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, UnionDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(145, 12));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Union));
-}
-
-TEST_F(TokenProcessor, UnionDeclarationReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(150, 33));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Union));
-}
-
-TEST_F(TokenProcessor, GlobalVariable)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(150, 33));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::GlobalVariable));
-}
-
-TEST_F(TokenProcessor, StructDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(50, 11));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Struct));
-}
-
-TEST_F(TokenProcessor, NameSpace)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(160, 22));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Namespace));
-}
-
-TEST_F(TokenProcessor, NameSpaceAlias)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(164, 38));
-
- ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Type, HighlightingType::Namespace));
-}
-
-TEST_F(TokenProcessor, UsingStructInNameSpace)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(165, 36));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, NameSpaceReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(166, 35));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Namespace));
-}
-
-TEST_F(TokenProcessor, StructInNameSpaceReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(166, 35));
-
- ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type, HighlightingType::Struct));
-}
-
-TEST_F(TokenProcessor, VirtualFunctionDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(170, 35));
-
- ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::VirtualFunction, HighlightingType::Declaration));
-}
-
-TEST_F(TokenProcessor, DISABLED_NonVirtualFunctionCall)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(177, 46));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, DISABLED_NonVirtualFunctionCallPointer)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(180, 54));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, VirtualFunctionCallPointer)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(192, 51));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::VirtualFunction));
-}
-
-TEST_F(TokenProcessor, FinalVirtualFunctionCallPointer)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(202, 61));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, NonFinalVirtualFunctionCallPointer)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(207, 61));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::VirtualFunction));
-}
-
-TEST_F(TokenProcessor, OverriddenPlusOperatorDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(220, 67));
-
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, CallToOverriddenPlusOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(224, 49));
-
- ASSERT_THAT(infos[6], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, CallToOverriddenPlusAssignOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(226, 24));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, OverriddenStarOperatorMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(604, 26));
-
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, OverriddenStarOperatorNonMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(607, 29));
-
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, IntegerCallToOverriddenBinaryOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(613, 9));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, FloatCallToOverriddenBinaryOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(614, 9));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, LeftShiftAssignmentOperatorMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(618, 32));
-
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation.
-}
-
-TEST_F(TokenProcessor, CalledLeftShiftAssignmentOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(629, 18));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::NumberLiteral));
-}
-
-TEST_F(TokenProcessor, FunctionCallOperatorMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(619, 29));
-
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation.
-}
-
-TEST_F(TokenProcessor, CalledFunctionCallOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(632, 16));
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, AccessOperatorMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(620, 38));
-
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[4], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation.
-}
-
-TEST_F(TokenProcessor, CalledAccessOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(633, 16));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator));
-}
-
-TEST_F(TokenProcessor, NewOperatorMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(621, 39));
-
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Keyword, HighlightingType::Operator, HighlightingType::OverloadedOperator));
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation.
-}
-
-TEST_F(TokenProcessor, CalledNewOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(635, 34));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Punctuation)); // = is not marked.
- // CLANG-UPGRADE-CHECK: Check if 'new' keyword usage cursor correctly returns referenced() cursor
- // and uncomment this test in that case.
- // ASSERT_THAT(infos[4], HasTwoTypes(HighlightingType::Keyword, HighlightingType::OverloadedOperator)); // new
-}
-
-TEST_F(TokenProcessor, DeleteOperatorMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(622, 37));
-
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Keyword, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // delete
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation.
-}
-
-TEST_F(TokenProcessor, CalledDeleteOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(636, 20));
-
- // CLANG-UPGRADE-CHECK: Check if 'delete' keyword usage cursor correctly returns referenced() cursor
- // and uncomment this test in that case.
- // ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Keyword, HighlightingType::OverloadedOperator)); // delete
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::LocalVariable));
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Punctuation)); // ; is a punctuation.
-}
-
-TEST_F(TokenProcessor, NewArrayOperatorMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(623, 41));
-
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Keyword, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // new
- ASSERT_THAT(infos[4], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // [
- ASSERT_THAT(infos[5], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // ]
- ASSERT_THAT(infos[6], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation.
-}
-
-TEST_F(TokenProcessor, CalledNewArrayOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(637, 34));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Punctuation)); // = is not marked.
- // CLANG-UPGRADE-CHECK: Check if 'new' keyword usage cursor correctly returns referenced() cursor
- // and uncomment this test in that case.
- // ASSERT_THAT(infos[4], HasTwoTypes(HighlightingType::Keyword, HighlightingType::OverloadedOperator)); // new
-}
-
-TEST_F(TokenProcessor, DeleteArrayOperatorMemberDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(624, 39));
-
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Keyword, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // delete
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // [
- ASSERT_THAT(infos[4], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // ]
- ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation.
-}
-
-TEST_F(TokenProcessor, CalledDeleteArrayOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(638, 20));
-
- // CLANG-UPGRADE-CHECK: Check if 'delete' keyword usage cursor correctly returns referenced() cursor
- // and uncomment this test in that case.
- // ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Keyword, HighlightingType::OverloadedOperator)); // delete
-}
-
-TEST_F(TokenProcessor, CalledNotOverloadedOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(634, 22));
-
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Keyword)); // new
-}
-
-TEST_F(TokenProcessor, ParenthesisOperatorWithoutArguments)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(654, 25));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Keyword, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // operator
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // '('
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // ')'
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Punctuation)); // second '(' is a punctuation
-}
-
-TEST_F(TokenProcessor, CalledParenthesisOperatorWithoutArguments)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(662, 14));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // '('
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // ')'
-}
-
-TEST_F(TokenProcessor, OperatorWithOnePunctuationTokenWithoutArguments)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(655, 25));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Keyword, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // operator
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // '*'
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation
-}
-
-TEST_F(TokenProcessor, CalledOperatorWithOnePunctuationTokenWithoutArguments)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(663, 13));
-
- ASSERT_THAT(infos[0], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // '*'
-}
-
-TEST_F(TokenProcessor, EqualsOperatorOverload)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(656, 43));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Keyword, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // operator
- ASSERT_THAT(infos[2], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // '='
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Punctuation)); // ( is a punctuation
-}
-
-TEST_F(TokenProcessor, CalledEqualsOperatorOverload)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(664, 23));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator, HighlightingType::OverloadedOperator)); // '='
-}
-
-TEST_F(TokenProcessor, LeftParenthesisIsAPunctuation)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(607, 29));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, SeparatingCommaIsAPunctuation)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(607, 29));
-
- ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, RightParenthesisIsAPunctuation)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(607, 29));
-
- ASSERT_THAT(infos[7], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, CurlyLeftParenthesisIsAPunctuation)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(607, 29));
-
- ASSERT_THAT(infos[8], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, CurlyRightParenthesisIsAPunctuation)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(607, 29));
-
- ASSERT_THAT(infos[9], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, OperatorColon)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(668, 28));
-
- ASSERT_THAT(infos[6], HasThreeTypes(HighlightingType::Punctuation, HighlightingType::Operator,
- HighlightingType::TernaryElse));
-}
-
-TEST_F(TokenProcessor, PunctuationColon)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(133, 10));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, LessThanOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(668, 28));
-
- ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Punctuation, HighlightingType::Operator));
-}
-
-TEST_F(TokenProcessor, LessThanPunctuation)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(247, 10));
-
- ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Punctuation,
- HighlightingType::AngleBracketOpen));
-}
-
-TEST_F(TokenProcessor, GreaterThanPunctuation)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(247, 19));
-
- ASSERT_THAT(infos[4], HasTwoTypes(HighlightingType::Punctuation,
- HighlightingType::AngleBracketClose));
-}
-
-TEST_F(TokenProcessor, Comment)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(229, 14));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Comment));
-}
-
-TEST_F(TokenProcessor, PreprocessingDirective)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(231, 37));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Preprocessor));
-}
-
-TEST_F(TokenProcessor, PreprocessorMacroDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(231, 37));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::PreprocessorDefinition));
-}
-
-TEST_F(TokenProcessor, PreprocessorFunctionMacroDefinition)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(232, 47));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::PreprocessorDefinition));
-}
-
-TEST_F(TokenProcessor, PreprocessorMacroExpansion)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(236, 27));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::PreprocessorExpansion));
-}
-
-TEST_F(TokenProcessor, PreprocessorMacroExpansionArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(236, 27));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::NumberLiteral));
-}
-
-TEST_F(TokenProcessor, PreprocessorInclusionDirective)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(239, 18));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Preprocessor));
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::StringLiteral));
-}
-
-TEST_F(TokenProcessor, GotoLabelStatement)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(242, 12));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Label));
-}
-
-TEST_F(TokenProcessor, GotoLabelStatementReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(244, 21));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Label));
-}
-
-TEST_F(TokenProcessor, TemplateReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(254, 25));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, TemplateTypeParameter)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(265, 135));
-
- ASSERT_THAT(infos[3], HasTwoTypes(HighlightingType::Type,
- HighlightingType::TemplateTypeParameter));
-}
-
-TEST_F(TokenProcessor, TemplateDefaultParameter)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(265, 135));
-
- ASSERT_THAT(infos[5], HasTwoTypes(HighlightingType::Type, HighlightingType::Struct));
-}
-
-TEST_F(TokenProcessor, NonTypeTemplateParameter)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(265, 135));
-
- ASSERT_THAT(infos[8], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, NonTypeTemplateParameterDefaultArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(265, 135));
-
- ASSERT_THAT(infos[10], HasOnlyType(HighlightingType::NumberLiteral));
-}
-
-TEST_F(TokenProcessor, TemplateTemplateParameter)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(265, 135));
-
- ASSERT_THAT(infos[17], HasTwoTypes(HighlightingType::Type,
- HighlightingType::TemplateTemplateParameter));
-}
-
-TEST_F(TokenProcessor, TemplateTemplateParameterDefaultArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(265, 135));
-
- ASSERT_THAT(infos[19], HasTwoTypes(HighlightingType::Type, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, TemplateFunctionDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(266, 63));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Function, HighlightingType::Declaration, HighlightingType::FunctionDefinition));
-}
-
-TEST_F(TokenProcessor, TemplateTypeParameterReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(268, 58));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type,
- HighlightingType::TemplateTypeParameter));
-}
-
-TEST_F(TokenProcessor, TemplateTypeParameterDeclarationReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(268, 58));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, NonTypeTemplateParameterReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(269, 71));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, NonTypeTemplateParameterReferenceReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(269, 71));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, TemplateTemplateParameterReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(270, 89));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type,
- HighlightingType::TemplateTemplateParameter));
-}
-
-TEST_F(TokenProcessor, TemplateTemplateContainerParameterReference)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(270, 89));
-
- ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type,
- HighlightingType::TemplateTypeParameter));
-}
-
-TEST_F(TokenProcessor, TemplateTemplateParameterReferenceVariable)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(270, 89));
-
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, ClassFinalVirtualFunctionCallPointer)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(212, 61));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, ClassFinalVirtualFunctionCall)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(277, 23));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, HasFunctionArguments)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(286, 29));
-
- ASSERT_TRUE(infos[1].hasFunctionArguments());
-}
-
-TEST_F(TokenProcessor, PreprocessorInclusionDirectiveWithAngleBrackets )
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(289, 38));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Preprocessor));
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::StringLiteral));
-}
-
-TEST_F(TokenProcessor, ArgumentInMacroExpansionIsKeyword)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(302, 36));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::PrimitiveType));
-}
-
-TEST_F(TokenProcessor, DISABLED_FirstArgumentInMacroExpansionIsLocalVariable)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(302, 36));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Invalid));
-}
-
-TEST_F(TokenProcessor, DISABLED_SecondArgumentInMacroExpansionIsLocalVariable)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(302, 36));
-
- ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Invalid));
-}
-
-TEST_F(TokenProcessor, DISABLED_SecondArgumentInMacroExpansionIsField)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(310, 40));
-
- ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Invalid));
-}
-
-
-TEST_F(TokenProcessor, EnumerationType)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(316, 30));
-
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Enum));
-}
-
-TEST_F(TokenProcessor, TypeInStaticCast)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(328, 64));
-
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, StaticCastIsKeyword)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(328, 64));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Keyword));
-}
-
-TEST_F(TokenProcessor, StaticCastPunctation)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(328, 64));
-
- ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Punctuation,
- HighlightingType::AngleBracketOpen));
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Punctuation));
- ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, TypeInReinterpretCast)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(329, 69));
-
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, IntegerAliasDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(333, 41));
-
- ASSERT_THAT(infos[1], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias));
-}
-
-TEST_F(TokenProcessor, IntegerAlias)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(341, 31));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias));
-}
-
-TEST_F(TokenProcessor, SecondIntegerAlias)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(342, 43));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias));
-}
-
-TEST_F(TokenProcessor, IntegerTypedef)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(343, 35));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Typedef));
-}
-
-TEST_F(TokenProcessor, FunctionAlias)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(344, 16));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias));
-}
-
-TEST_F(TokenProcessor, FriendTypeDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(350, 28));
-
- ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, FriendArgumentTypeDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(351, 65));
-
- ASSERT_THAT(infos[6], HasTwoTypes(HighlightingType::Type, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, FriendArgumentDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(351, 65));
-
- ASSERT_THAT(infos[8], HasOnlyType(HighlightingType::Parameter));
-}
-
-TEST_F(TokenProcessor, FieldInitialization)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(358, 18));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Field));
-}
-
-TEST_F(TokenProcessor, TemplateFunctionCall)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(372, 29));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, TemplatedType)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(377, 21));
-
- ASSERT_THAT(infos[1], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, TemplatedTypeDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(384, 49));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, NoOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(389, 24));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, ScopeOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(400, 33));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, TemplateClassNamespace)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(413, 78));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Namespace));
-}
-
-TEST_F(TokenProcessor, TemplateClass)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(413, 78));
-
- ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, TemplateClassParameter)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(413, 78));
-
- ASSERT_THAT(infos[4], HasTwoTypes(HighlightingType::Type, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, TemplateClassDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(413, 78));
-
- ASSERT_THAT(infos[6], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, TypeDefDeclaration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(418, 36));
-
- ASSERT_THAT(infos[2], HasTwoTypes(HighlightingType::Type, HighlightingType::Typedef));
-}
-
-TEST_F(TokenProcessor, TypeDefDeclarationUsage)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(419, 48));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::Typedef));
-}
-
-TEST_F(TokenProcessor, NonConstReferenceArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(455, 35));
-
- infos[1];
-
- ASSERT_THAT(infos[2],
- HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, ConstReferenceArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(464, 32));
-
- infos[1];
-
- ASSERT_THAT(infos[2],
- HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, RValueReferenceArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(473, 52));
-
- infos[1];
-
- ASSERT_THAT(infos[8],
- HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, NonConstPointerArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(482, 33));
-
- infos[1];
-
- ASSERT_THAT(infos[2],
- HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, PointerToConstArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(490, 31));
-
- infos[1];
-
- ASSERT_THAT(infos[2],
- HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, ConstPointerArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(491, 30));
-
- infos[1];
-
- ASSERT_THAT(infos[2],
- HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, NonConstPointerGetterAsArgument)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(580, 42));
-
- infos[1];
-
- ASSERT_THAT(infos[2] ,HasMixin(HighlightingType::OutputArgument));
- ASSERT_THAT(infos[3], HasMixin(HighlightingType::OutputArgument));
- ASSERT_THAT(infos[4], HasMixin(HighlightingType::OutputArgument));
- ASSERT_THAT(infos[5], HasMixin(HighlightingType::OutputArgument));
- ASSERT_THAT(infos[6], HasMixin(HighlightingType::OutputArgument));
- ASSERT_THAT(infos[7], Not(HasMixin(HighlightingType::OutputArgument)));
-}
-
-TEST_F(TokenProcessor, NonConstReferenceArgumentCallInsideCall)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(501, 64));
- infos[1];
-
- infos[3];
-
- ASSERT_THAT(infos[7],
- HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, OutputArgumentsAreEmptyAfterIteration)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(501, 63));
-
- for (const auto &info : infos ) { Q_UNUSED(info) }
-
- ASSERT_TRUE(infos.currentOutputArgumentRangesAreEmpty());
-}
-
-TEST_F(TokenProcessor, NonConstReferenceArgumentFromFunctionParameter)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(506, 42));
-
- infos[1];
-
- ASSERT_THAT(infos[2],
- HasTwoTypes(HighlightingType::Parameter, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, NonConstPointerArgumentAsExpression)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(513, 33));
-
- infos[1];
-
- ASSERT_THAT(infos[3],
- HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, NonConstPointerArgumentAsInstanceWithMember)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(525, 46));
-
- infos[1];
-
- ASSERT_THAT(infos[2],
- HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, NonConstPointerArgumentAsMemberOfInstance)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(525, 46));
-
- infos[1];
- infos[2];
-
- ASSERT_THAT(infos[4],
- HasTwoTypes(HighlightingType::Field, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, DISABLED_NonConstReferenceArgumentConstructor)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(540, 57));
-
- infos[2];
-
- ASSERT_THAT(infos[3],
- HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, DISABLED_NonConstReferenceMemberInitialization)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(546, 19));
-
- infos[2];
-
- ASSERT_THAT(infos[3],
- HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, EnumerationTypeDef)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(424, 41));
-
- ASSERT_THAT(infos[3], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Enum));
-}
-
-// QTCREATORBUG-15473
-TEST_F(TokenProcessor, DISABLED_ArgumentToUserDefinedIndexOperator)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(434, 19));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, ClassTemplateParticalSpecialization)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(553, 33));
-
- ASSERT_THAT(infos[6], HasThreeTypes(HighlightingType::Type, HighlightingType::Declaration, HighlightingType::Class));
-}
-
-TEST_F(TokenProcessor, UsingFunction)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(556, 27));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, PreprocessorIfDirective)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(558, 6));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Preprocessor));
-}
-
-TEST_F(TokenProcessor, PreprocessorInclusionDirectiveWithKeyword)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(561, 15));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::StringLiteral));
-}
-
-TEST_F(TokenProcessor, VariableInOperatorFunctionCall)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(566, 12));
-
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Parameter));
-}
-
-TEST_F(TokenProcessor, UsingTemplateFunction)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(584, 17));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, HeaderNameIsInclusion)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(239, 31));
-
- ClangBackEnd::TokenInfoContainer container(infos[2]);
-
- ASSERT_THAT(container.extraInfo.includeDirectivePath, true);
-}
-
-TEST_F(TokenProcessor, HeaderNameIsInclusionWithAngleBrackets)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(289, 31));
-
- ClangBackEnd::TokenInfoContainer container(infos[2]);
-
- ASSERT_THAT(container.extraInfo.includeDirectivePath, true);
-}
-
-TEST_F(TokenProcessor, NotInclusion)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(241, 13));
-
- ClangBackEnd::TokenInfoContainer container(infos[1]);
-
- ASSERT_THAT(container.extraInfo.includeDirectivePath, false);
-}
-
-TEST_F(TokenProcessor, MacroIsIdentifier)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(232, 30));
-
- ClangBackEnd::TokenInfoContainer container(infos[2]);
-
- ASSERT_THAT(container.extraInfo.identifier, true);
-}
-
-TEST_F(TokenProcessor, DefineIsNotIdentifier)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(232, 30));
-
- ClangBackEnd::TokenInfoContainer container(infos[1]);
-
- ASSERT_THAT(container.extraInfo.includeDirectivePath, false);
-}
-
-TEST_F(TokenProcessor, NamespaceTypeSpelling)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(592, 59));
- ClangBackEnd::TokenInfoContainer container(infos[10]);
- ASSERT_THAT(container.extraInfo.semanticParentTypeSpelling, Utf8StringLiteral("NFoo::NBar::NTest"));
-}
-
-TEST_F(TokenProcessor, TypeNameOfInvalidDeclarationIsInvalid)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(594, 14));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Invalid));
-}
-
-TEST_F(TokenProcessor, VariableNameOfInvalidDeclarationIsInvalid)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(594, 14));
-
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Invalid));
-}
-
-TEST_F(TokenProcessor, QtPropertyName)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(599, 103));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::PreprocessorExpansion));
- ASSERT_THAT(infos[8], HasOnlyType(HighlightingType::QtProperty));
-}
-
-TEST_F(TokenProcessor, QtPropertyNameMultiLine)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRangeMultiLine(704, 732, 14));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::PreprocessorExpansion));
- ASSERT_THAT(infos[8], HasOnlyType(HighlightingType::QtProperty));
-}
-
-TEST_F(TokenProcessor, QtPropertyFunction)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(599, 103));
-
- ASSERT_THAT(infos[10], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, QtPropertyFunctionMultiLine)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRangeMultiLine(704, 732, 14));
-
- ASSERT_THAT(infos[10], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, QtPropertyInternalKeyword)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(599, 103));
-
- ASSERT_THAT(infos[9], HasOnlyType(HighlightingType::Invalid));
-}
-
-TEST_F(TokenProcessor, QtPropertyInternalKeywordMultiLine)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRangeMultiLine(704, 732, 14));
-
- ASSERT_THAT(infos[9], HasOnlyType(HighlightingType::Invalid));
-}
-
-TEST_F(TokenProcessor, QtPropertyLastToken)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(599, 103));
-
- ASSERT_THAT(infos[14], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, QtPropertyLastTokenMultiLine)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRangeMultiLine(704, 732, 14));
-
- ASSERT_THAT(infos[14], HasOnlyType(HighlightingType::Function));
-}
-
-TEST_F(TokenProcessor, QtPropertyType)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(600, 46));
-
- ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, CursorRange)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(592, 15));
- const auto expectedRange = translationUnit.sourceRange(592, 1, 592, 87);
-
- ClangBackEnd::TokenInfoContainer container(infos[1]);
-
- ASSERT_THAT(container.extraInfo.cursorRange, expectedRange);
-}
-
-TEST_F(TokenProcessor, AnonymousEnum)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(641, 7));
-
- ClangBackEnd::TokenInfoContainer container(infos[0]);
-
- ASSERT_THAT(container.types.mainHighlightingType, ClangBackEnd::HighlightingType::Keyword);
- ASSERT_THAT(container.types.mixinHighlightingTypes[0], ClangBackEnd::HighlightingType::Enum);
-}
-
-TEST_F(TokenProcessor, AnonymousNamespace)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(645, 12));
-
- ClangBackEnd::TokenInfoContainer container(infos[0]);
-
- ASSERT_THAT(container.types.mainHighlightingType, ClangBackEnd::HighlightingType::Keyword);
- ASSERT_THAT(container.types.mixinHighlightingTypes[0], ClangBackEnd::HighlightingType::Namespace);
-}
-
-TEST_F(TokenProcessor, AnonymousStruct)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(647, 13));
-
- ClangBackEnd::TokenInfoContainer container(infos[0]);
-
- ASSERT_THAT(container.types.mainHighlightingType, ClangBackEnd::HighlightingType::Keyword);
- ASSERT_THAT(container.types.mixinHighlightingTypes[0], ClangBackEnd::HighlightingType::Struct);
-}
-
-TEST_F(TokenProcessor, LexicalParentIndex)
-{
- const auto containers = translationUnit.fullTokenInfosInRange(
- translationUnit.sourceRange(50, 1, 53, 3)).toTokenInfoContainers();
-
- ASSERT_THAT(containers[4].extraInfo.lexicalParentIndex, 1);
-}
-
-TEST_F(TokenProcessor, QtOldStyleSignal)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(672, 32));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::PreprocessorExpansion));
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Function));
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, QtOldStyleSlot)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(673, 30));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::PreprocessorExpansion));
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Function));
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, QtOldStyleSignalFunctionPointerType)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(674, 50));
-
- ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::PreprocessorExpansion));
- ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Function));
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::Type));
- ASSERT_THAT(infos[7], HasOnlyType(HighlightingType::Type));
- ASSERT_THAT(infos[10], HasOnlyType(HighlightingType::Type));
-}
-
-TEST_F(TokenProcessor, NonConstParameterConstructor)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(681, 90));
-
- infos[1];
-
- ASSERT_THAT(infos[4], Not(HasMixin(HighlightingType::OutputArgument)));
-}
-
-TEST_F(TokenProcessor, DISABLED_NonConstArgumentConstructor)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(686, 47));
-
- infos[2];
-
- ASSERT_THAT(infos[3], HasMixin(HighlightingType::OutputArgument));
-}
-
-TEST_F(TokenProcessor, LambdaLocalVariableCapture)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(442, 47));
-
- ASSERT_THAT(infos[4], HasOnlyType(HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, StaticProtectedMember)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(693, 31));
-
- ClangBackEnd::TokenInfoContainer container(infos[2]);
-
- ASSERT_THAT(container.extraInfo.accessSpecifier, ClangBackEnd::AccessSpecifier::Protected);
-}
-
-TEST_F(TokenProcessor, StaticPrivateMember)
-{
- const auto infos = translationUnit.fullTokenInfosInRange(sourceRange(696, 29));
-
- ClangBackEnd::TokenInfoContainer container(infos[2]);
-
- ASSERT_THAT(container.extraInfo.accessSpecifier, ClangBackEnd::AccessSpecifier::Private);
-}
-
-TEST_F(TokenProcessor, TemplateAlias)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(701, 8));
-
- ASSERT_THAT(infos[0], HasTwoTypes(HighlightingType::Type, HighlightingType::TypeAlias));
-}
-
-TEST_F(TokenProcessor, StructuredBinding)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(737, 23));
-
- ASSERT_THAT(infos[3], IsHighlightingMark(737u, 17u, 1u, HighlightingType::LocalVariable));
- ASSERT_THAT(infos[5], IsHighlightingMark(737u, 20u, 1u, HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, IndirectMacro)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(746, 32));
-
- ASSERT_THAT(infos[5], IsHighlightingMark(746u, 20u, 10u, HighlightingType::LocalVariable));
-}
-
-TEST_F(TokenProcessor, MultiDimArray)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(752, 28));
-
- ASSERT_THAT(infos[3], IsHighlightingMark(752u, 13u, 10u, HighlightingType::GlobalVariable));
-}
-
-TEST_F(TokenProcessor, TemplateSeparateDeclDef)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRangeMultiLine(755, 771, 1));
- ASSERT_THAT(infos[11], IsHighlightingMark(757u, 17u, 10u, HighlightingType::Invalid));
- ASSERT_THAT(infos[37], IsHighlightingMark(764u, 5u, 9u, HighlightingType::GlobalVariable));
-}
-
-TEST_F(TokenProcessor, NestedTemplateIncorrect)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(773, 44));
- ASSERT_THAT(infos[12], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, OperatorInTemplate)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(787, 28));
- ASSERT_THAT(infos[9], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, CyrillicString)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(792, 28));
- ASSERT_THAT(infos[5], IsHighlightingMark(792u, 24u, 3u, HighlightingType::StringLiteral));
-}
-
-TEST_F(TokenProcessor, PreProcessorInStruct)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(795, 14));
- ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Preprocessor));
-}
-
-TEST_F(TokenProcessor, DefinitionWithComparison)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(798, 39));
- ASSERT_THAT(infos[13], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, GlobalVariableWithComparison)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(800, 18));
- ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Punctuation));
-}
-
-TEST_F(TokenProcessor, VariableWithComparison)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(803, 22));
- ASSERT_THAT(infos[5], HasOnlyType(HighlightingType::Punctuation));
-}
-
-
-TEST_F(TokenProcessor, NestedTemplate)
-{
- const auto infos = translationUnit.tokenInfosInRange(sourceRange(811, 44));
- ASSERT_THAT(infos[12], HasTwoTypes(HighlightingType::Punctuation,
- HighlightingType::DoubleAngleBracketClose));
-}
-
-Data *TokenProcessor::d;
-
-void TokenProcessor::SetUpTestCase()
-{
- d = new Data;
-}
-
-void TokenProcessor::TearDownTestCase()
-{
- delete d;
- d = nullptr;
-}
-
-ClangBackEnd::SourceRange TokenProcessor::sourceRange(uint line, uint columnEnd) const
-{
- return translationUnit.sourceRange(line, 1, line, columnEnd);
-}
-
-ClangBackEnd::SourceRange TokenProcessor::sourceRangeMultiLine(uint firstLine, uint lastLine,
- uint columnEnd) const
-{
- return translationUnit.sourceRange(firstLine, 1, lastLine, columnEnd);
-}
-
-}
diff --git a/tests/unit/unittest/translationunitupdater-test.cpp b/tests/unit/unittest/translationunitupdater-test.cpp
deleted file mode 100644
index ea71070351e..00000000000
--- a/tests/unit/unittest/translationunitupdater-test.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangclock.h>
-#include <clangtranslationunitupdater.h>
-
-#include <clang-c/Index.h>
-
-using ClangBackEnd::Clock;
-using ClangBackEnd::TimePoint;
-using ClangBackEnd::TranslationUnitUpdater;
-using ClangBackEnd::TranslationUnitUpdateInput;
-using ClangBackEnd::TranslationUnitUpdateResult;
-
-using testing::Eq;
-using testing::Gt;
-
-namespace {
-
-class TranslationUnitUpdater : public ::testing::Test
-{
-protected:
- void TearDown() override;
-
- ::TranslationUnitUpdater createUpdater(const TranslationUnitUpdateInput &input,
- const Utf8String &translationUnitId = Utf8String());
-
- enum ReparseMode { SetReparseNeeded, DoNotSetReparseNeeded };
- TranslationUnitUpdateInput createInput(ReparseMode reparseMode = DoNotSetReparseNeeded);
-
-protected:
- CXIndex cxIndex = nullptr;
- CXTranslationUnit cxTranslationUnit = nullptr;
-
- Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp");
-};
-
-using TranslationUnitUpdaterSlowTest = TranslationUnitUpdater;
-
-TEST_F(TranslationUnitUpdaterSlowTest, ParsesIfNeeded)
-{
- ::TranslationUnitUpdater updater = createUpdater(createInput());
-
- TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
-
- ASSERT_TRUE(cxTranslationUnit);
- ASSERT_FALSE(result.hasReparsed());
-}
-
-TEST_F(TranslationUnitUpdaterSlowTest, ReparsesIfNeeded)
-{
- ::TranslationUnitUpdater updater = createUpdater(createInput(SetReparseNeeded));
-
- TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
-
- ASSERT_TRUE(result.hasReparsed());
-}
-
-TEST_F(TranslationUnitUpdaterSlowTest, PropagatesTranslationUnitId)
-{
- const Utf8String translationUnitId = Utf8StringLiteral("myId");
- ::TranslationUnitUpdater updater = createUpdater(createInput(SetReparseNeeded), translationUnitId);
-
- TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
-
- ASSERT_THAT(result.translationUnitId, Eq(translationUnitId));
-}
-
-TEST_F(TranslationUnitUpdaterSlowTest, UpdatesParseTimePoint)
-{
- ::TranslationUnitUpdater updater = createUpdater(createInput());
- const TimePoint now = Clock::now();
-
- TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
-
- ASSERT_TRUE(result.hasParsed());
- ASSERT_THAT(result.parseTimePoint, Gt(now));
-}
-
-TEST_F(TranslationUnitUpdaterSlowTest, NotUpdatingParseTimePointForReparseOnly)
-{
- ::TranslationUnitUpdater updater = createUpdater(createInput());
- TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
-
- ::TranslationUnitUpdater reparseUpdater = createUpdater(createInput(SetReparseNeeded));
- result = reparseUpdater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
-
- ASSERT_TRUE(result.hasReparsed());
- ASSERT_FALSE(result.hasParsed());
-}
-
-TEST_F(TranslationUnitUpdaterSlowTest, UpdatesDependentOnFilesOnParse)
-{
- ::TranslationUnitUpdater updater = createUpdater(createInput());
-
- TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
-
- ASSERT_FALSE(result.dependedOnFilePaths.isEmpty());
-}
-
-void TranslationUnitUpdater::TearDown()
-{
- clang_disposeTranslationUnit(cxTranslationUnit);
- clang_disposeIndex(cxIndex);
-}
-
-::TranslationUnitUpdater
-TranslationUnitUpdater::createUpdater(const TranslationUnitUpdateInput &input,
- const Utf8String &translationUnitId)
-{
- return ::TranslationUnitUpdater(translationUnitId, cxIndex, cxTranslationUnit, input);
-}
-
-TranslationUnitUpdateInput
-TranslationUnitUpdater::createInput(ReparseMode reparseMode)
-{
- TranslationUnitUpdateInput updateInput;
- updateInput.filePath = filePath;
- updateInput.reparseNeeded = reparseMode == SetReparseNeeded;
-
- return updateInput;
-}
-
-} // anonymous
diff --git a/tests/unit/unittest/unittest-utility-functions.h b/tests/unit/unittest/unittest-utility-functions.h
index 5102769e78f..31dac0e98e4 100644
--- a/tests/unit/unittest/unittest-utility-functions.h
+++ b/tests/unit/unittest/unittest-utility-functions.h
@@ -29,8 +29,6 @@
#include <utils/smallstring.h>
#include <utils/temporarydirectory.h>
-#include <utf8stringvector.h>
-
inline
bool operator==(const QString &first, const char *second)
{
@@ -45,11 +43,4 @@ Utils::PathString temporaryDirPath()
return Utils::PathString::fromQString(Utils::TemporaryDirectory::masterDirectoryPath());
}
-inline QVector<Utf8String> addPlatformArguments(std::initializer_list<Utf8String> arguments = {})
-{
- QVector<Utf8String> result{arguments};
- if (Utils::HostOsInfo::isWindowsHost())
- result.append(Utf8StringLiteral("-fno-delayed-template-parsing"));
- return result;
-}
} // namespace UnitTest
diff --git a/tests/unit/unittest/unittest.qbs b/tests/unit/unittest/unittest.qbs
index 5401aa09e1b..143ec4de46f 100644
--- a/tests/unit/unittest/unittest.qbs
+++ b/tests/unit/unittest/unittest.qbs
@@ -6,7 +6,8 @@ Project {
QtcProduct {
name: "Unit test"
- condition: qtc_gtest_gmock.hasRepo || qtc_gtest_gmock.externalLibsPresent
+ condition: (qtc_gtest_gmock.hasRepo || qtc_gtest_gmock.externalLibsPresent)
+ && QmlDesigner.present
type: ["application", "autotest"]
consoleApplication: true
@@ -14,16 +15,11 @@ Project {
FileInfo.relativePath(project.ide_source_tree, sourceDirectory))
install: false
- Depends { name: "echoserver" }
- Depends { name: "libclang"; required: false }
- Depends { name: "clang_defines" }
-
- Depends { name: "QmlDesigner" }
+ Depends { name: "QmlDesigner"; required: false }
Depends { name: "sqlite_sources" }
Depends { name: "Core" }
Depends { name: "CPlusPlus" }
- Depends { name: "yaml-cpp" }
Depends { name: "Qt"; submodules: ["network", "widgets", "testlib"] }
@@ -40,22 +36,13 @@ Project {
"QT_RESTRICTED_CAST_FROM_ASCII",
"QT_USE_FAST_OPERATOR_PLUS",
"QT_USE_FAST_CONCATENATION",
- "CLANGSUPPORT_BUILD_STATIC_LIB",
- "CLANGTOOLS_STATIC_LIBRARY",
- "CPPEDITOR_STATIC_LIBRARY",
- "DEBUGGER_STATIC_LIBRARY",
"UNIT_TESTS",
"DONT_CHECK_MESSAGE_COUNTER",
'QTC_RESOURCE_DIR="' + path + "/../../../share/qtcreator" + '"',
'TESTDATA_DIR="' + FileInfo.joinPaths(sourceDirectory, "data") + '"',
- 'ECHOSERVER="' + FileInfo.joinPaths(project.buildDirectory, "tests", "unit",
- "echoserver", "echo") + '"',
'RELATIVE_DATA_PATH="' + FileInfo.relativePath(destinationDirectory,
FileInfo.joinPaths(project.sourceDirectory, "share", "qtcreator")) + '"',
];
- if (libclang.present) {
- defines.push("CLANG_UNIT_TESTS");
- }
var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
qtc.ide_libexec_path);
var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
@@ -82,63 +69,28 @@ Project {
return flags;
}
cpp.cxxLanguageVersion: "c++17"
- cpp.dynamicLibraries: {
- var libs = [];
- if (libclang.present) {
- libs = libs.concat(libclang.llvmLibs);
- if (libclang.llvmFormattingLibs.length
- && (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches)) {
- libs = libs.concat(libclang.llvmFormattingLibs);
- }
- }
- return libs;
- }
- cpp.includePaths: {
- var paths = [
- ".",
- "../mockup",
- "../../../src/libs",
- "../../../src/libs/3rdparty",
- "../../../src/libs/clangsupport",
- "../../../src/plugins",
- "../../../src/plugins/clangcodemodel",
- "../../../src/tools/clangbackend/source",
- "../../../share/qtcreator/qml/qmlpuppet/types",
- ];
- if (libclang.present) {
- paths.push(libclang.llvmIncludeDir);
- }
- return paths;
- }
- cpp.libraryPaths: {
- var paths = [];
- if (libclang.present)
- paths.push(libclang.llvmLibDir);
- return paths;
- }
- cpp.rpaths: {
- var paths = [
- FileInfo.joinPaths(project.buildDirectory, qtc.ide_library_path),
- FileInfo.joinPaths(project.buildDirectory, qtc.ide_plugin_path)
- ];
- if (libclang.present)
- paths.push(libclang.llvmLibDir);
- return paths;
- }
+ cpp.includePaths: [
+ ".",
+ "../mockup",
+ "../../../src/libs",
+ "../../../src/libs/3rdparty",
+ "../../../src/plugins",
+ "../../../share/qtcreator/qml/qmlpuppet/types",
+ ]
+ cpp.rpaths: [
+ FileInfo.joinPaths(project.buildDirectory, qtc.ide_library_path),
+ FileInfo.joinPaths(project.buildDirectory, qtc.ide_plugin_path)
+ ]
files: [
- "clientserverinprocess-test.cpp",
- "clientserveroutsideprocess-test.cpp",
"compare-operators.h",
"conditionally-disabled-tests.h",
"createtablesqlstatementbuilder-test.cpp",
- "dummyclangipcclient.h",
"dynamicastmatcherdiagnosticcontainer-matcher.h",
"eventspy.cpp",
"eventspy.h",
"fakeprocess.cpp",
"fakeprocess.h",
- "filesystem-utilities.h",
"google-using-declarations.h",
"googletest.h",
"gtest-creator-printing.cpp",
@@ -146,27 +98,19 @@ Project {
"gtest-llvm-printing.h",
"gtest-qt-printing.cpp",
"gtest-qt-printing.h",
- "lineprefixer-test.cpp",
"matchingtext-test.cpp",
- "mockclangcodemodelclient.h",
- "mockclangcodemodelserver.h",
"mockfutureinterface.h",
"mockmutex.h",
"mockqfilesystemwatcher.h",
- "mockqueue.h",
"mocksqlitestatement.h",
"mocksqlitetransactionbackend.h",
"mocksyntaxhighligher.h",
"mocktimer.cpp",
"mocktimer.h",
- "processcreator-test.cpp",
"processevents-utilities.cpp",
"processevents-utilities.h",
- "readandwritemessageblock-test.cpp",
- "rundocumentparse-utility.h",
"sizedarray-test.cpp",
"smallstring-test.cpp",
- "sourcerangecontainer-matcher.h",
"spydummy.cpp",
"spydummy.h",
"sqlitecolumn-test.cpp",
@@ -186,70 +130,9 @@ Project {
"sqlstatementbuilder-test.cpp",
"unittest-utility-functions.h",
"unittests-main.cpp",
- "utf8-test.cpp",
]
Group {
- name: "libclang tests"
- condition: libclang.present && (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches)
- files: [
- "activationsequencecontextprocessor-test.cpp",
- "activationsequenceprocessor-test.cpp",
- "chunksreportedmonitor.cpp",
- "chunksreportedmonitor.h",
- "clangasyncjob-base.cpp",
- "clangasyncjob-base.h",
- "clangcodecompleteresults-test.cpp",
- "clangcodemodelserver-test.cpp",
- "clangcompareoperators.h",
- "clangcompletecodejob-test.cpp",
- "clangcompletioncontextanalyzer-test.cpp",
- "clangdiagnosticfilter-test.cpp",
- "clangdocument-test.cpp",
- "clangdocumentprocessor-test.cpp",
- "clangdocumentprocessors-test.cpp",
- "clangdocuments-test.cpp",
- "clangfixitoperation-test.cpp",
- "clangfollowsymbol-test.cpp",
- "clangisdiagnosticrelatedtolocation-test.cpp",
- "clangjobqueue-test.cpp",
- "clangjobs-test.cpp",
- "clangparsesupportivetranslationunitjob-test.cpp",
- "clangrequestannotationsjob-test.cpp",
- "clangrequestreferencesjob-test.cpp",
- "clangresumedocumentjob-test.cpp",
- "clangstring-test.cpp",
- "clangsupportivetranslationunitinitializer-test.cpp",
- "clangsuspenddocumentjob-test.cpp",
- "clangtooltipinfo-test.cpp",
- "clangtranslationunit-test.cpp",
- "clangtranslationunits-test.cpp",
- "clangupdateannotationsjob-test.cpp",
- "codecompleter-test.cpp",
- "codecompletionsextractor-test.cpp",
- "completionchunkstotextconverter-test.cpp",
- "cursor-test.cpp",
- "diagnostic-test.cpp",
- "diagnosticcontainer-matcher.h",
- "diagnosticset-test.cpp",
- "fixit-test.cpp",
- "gtest-clang-printing.cpp",
- "gtest-clang-printing.h",
- "highlightingresultreporter-test.cpp",
- "readexporteddiagnostics-test.cpp",
- "skippedsourceranges-test.cpp",
- "sourcelocation-test.cpp",
- "sourcerange-test.cpp",
- "token-test.cpp",
- "tokenprocessor-test.cpp",
- "translationunitupdater-test.cpp",
- "unsavedfile-test.cpp",
- "unsavedfiles-test.cpp",
- "utf8positionfromlinecolumn-test.cpp",
- ]
- }
-
- Group {
name: "benchmark test"
condition: benchmark.present
files: "smallstring-benchmark.cpp"
@@ -259,190 +142,8 @@ Project {
name: "data"
files: [
"data/*",
- "data/include/*",
]
fileTags: []
}
-
- Group {
- name: "sources from clangbackend"
- condition: libclang.present
- prefix: "../../../src/tools/clangbackend/source/"
- files: [
- "clangasyncjob.h",
- "clangbackend_global.h",
- "clangclock.h",
- "clangcodecompleteresults.cpp",
- "clangcodecompleteresults.h",
- "clangcodemodelserver.cpp",
- "clangcodemodelserver.h",
- "clangcompletecodejob.cpp",
- "clangcompletecodejob.h",
- "clangdocument.cpp",
- "clangdocument.h",
- "clangdocumentjob.h",
- "clangdocumentprocessor.cpp",
- "clangdocumentprocessor.h",
- "clangdocumentprocessors.cpp",
- "clangdocumentprocessors.h",
- "clangdocuments.cpp",
- "clangdocuments.h",
- "clangdocumentsuspenderresumer.cpp",
- "clangdocumentsuspenderresumer.h",
- "clangexceptions.cpp",
- "clangexceptions.h",
- "clangfilepath.cpp",
- "clangfilepath.h",
- "clangfilesystemwatcher.cpp",
- "clangfilesystemwatcher.h",
- "clangfollowsymbol.cpp",
- "clangfollowsymbol.h",
- "clangfollowsymboljob.cpp",
- "clangfollowsymboljob.h",
- "clangiasyncjob.cpp",
- "clangiasyncjob.h",
- "clangjobcontext.cpp",
- "clangjobcontext.h",
- "clangjobqueue.cpp",
- "clangjobqueue.h",
- "clangjobrequest.cpp",
- "clangjobrequest.h",
- "clangjobs.cpp",
- "clangjobs.h",
- "clangparsesupportivetranslationunitjob.cpp",
- "clangparsesupportivetranslationunitjob.h",
- "clangreferencescollector.cpp",
- "clangreferencescollector.h",
- "clangrequestannotationsjob.cpp",
- "clangrequestannotationsjob.h",
- "clangrequestreferencesjob.cpp",
- "clangrequestreferencesjob.h",
- "clangrequesttooltipjob.cpp",
- "clangrequesttooltipjob.h",
- "clangresumedocumentjob.cpp",
- "clangresumedocumentjob.h",
- "clangstring.h",
- "clangsupportivetranslationunitinitializer.cpp",
- "clangsupportivetranslationunitinitializer.h",
- "clangsuspenddocumentjob.cpp",
- "clangsuspenddocumentjob.h",
- "clangtooltipinfocollector.cpp",
- "clangtooltipinfocollector.h",
- "clangtranslationunit.cpp",
- "clangtranslationunit.h",
- "clangtranslationunits.cpp",
- "clangtranslationunits.h",
- "clangtranslationunitupdater.cpp",
- "clangtranslationunitupdater.h",
- "clangtype.cpp",
- "clangtype.h",
- "clangunsavedfilesshallowarguments.cpp",
- "clangunsavedfilesshallowarguments.h",
- "clangupdateannotationsjob.cpp",
- "clangupdateannotationsjob.h",
- "clangupdateextraannotationsjob.cpp",
- "clangupdateextraannotationsjob.h",
- "codecompleter.cpp",
- "codecompleter.h",
- "codecompletionchunkconverter.cpp",
- "codecompletionchunkconverter.h",
- "codecompletionsextractor.cpp",
- "codecompletionsextractor.h",
- "commandlinearguments.cpp",
- "commandlinearguments.h",
- "cursor.cpp",
- "cursor.h",
- "diagnostic.cpp",
- "diagnostic.h",
- "diagnosticset.cpp",
- "diagnosticset.h",
- "diagnosticsetiterator.h",
- "fixit.cpp",
- "fixit.h",
- "fulltokeninfo.cpp",
- "fulltokeninfo.h",
- "skippedsourceranges.cpp",
- "skippedsourceranges.h",
- "sourcelocation.cpp",
- "sourcelocation.h",
- "sourcerange.cpp",
- "sourcerange.h",
- "token.cpp",
- "token.h",
- "tokeninfo.cpp",
- "tokeninfo.h",
- "tokenprocessor.h",
- "tokenprocessoriterator.h",
- "unsavedfile.cpp",
- "unsavedfile.h",
- "unsavedfiles.cpp",
- "unsavedfiles.h",
- "utf8positionfromlinecolumn.cpp",
- "utf8positionfromlinecolumn.h",
- ]
- }
-
- Group {
- name: "sources from clangsupport"
- prefix: "../../../src/libs/clangsupport/"
- files: [
- "*.cpp",
- "*.h",
- ]
- }
-
- Group {
- name: "sources from clangcodemodel"
- prefix: "../../../src/plugins/clangcodemodel/"
- files: [
- "clangactivationsequencecontextprocessor.cpp",
- "clangactivationsequencecontextprocessor.h",
- "clangactivationsequenceprocessor.cpp",
- "clangactivationsequenceprocessor.h",
- "clangcompletionchunkstotextconverter.cpp",
- "clangcompletionchunkstotextconverter.h",
- "clangcompletioncontextanalyzer.cpp",
- "clangcompletioncontextanalyzer.h",
- "clangdiagnosticfilter.cpp",
- "clangdiagnosticfilter.h",
- "clangfixitoperation.cpp",
- "clangfixitoperation.h",
- "clanghighlightingresultreporter.cpp",
- "clanghighlightingresultreporter.h",
- "clangisdiagnosticrelatedtolocation.h",
- "clanguiheaderondiskmanager.cpp",
- "clanguiheaderondiskmanager.h",
- ]
- }
-
- Group {
- name: "sources from cppeditor"
- prefix: "../../../src/plugins/cppeditor/"
- files: [
- "cppprojectfile.cpp",
- "cppprojectfile.h",
- ]
- }
-
- Group {
- name: "sources from clangtools"
- condition: libclang.present
- prefix: "../../../src/plugins/clangtools/"
- files: [
- "clangtoolsdiagnostic.cpp",
- "clangtoolsdiagnostic.h",
- "clangtoolslogfilereader.cpp",
- "clangtoolslogfilereader.h",
- ]
- }
-
- Group {
- name: "sources from Debugger"
- prefix: "../../../src/plugins/debugger/analyzer/"
- files: [
- "diagnosticlocation.cpp",
- "diagnosticlocation.h",
- ]
- }
}
}
diff --git a/tests/unit/unittest/unsavedfile-test.cpp b/tests/unit/unittest/unsavedfile-test.cpp
deleted file mode 100644
index 7e4d3dae685..00000000000
--- a/tests/unit/unittest/unsavedfile-test.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <clangfilepath.h>
-#include <unsavedfile.h>
-#include <unsavedfiles.h>
-
-using ClangBackEnd::FilePath;
-using ClangBackEnd::UnsavedFile;
-using ClangBackEnd::UnsavedFiles;
-
-using ::testing::Eq;
-using ::testing::PrintToString;
-
-namespace {
-
-MATCHER_P3(IsUnsavedFile, fileName, contents, contentsLength,
- std::string(negation ? "isn't" : "is")
- + " file name " + PrintToString(fileName)
- + ", contents " + PrintToString(contents)
- + ", contents length " + PrintToString(contentsLength))
-{
- return fileName == arg.filePath()
- && contents == arg.fileContent()
- && int(contentsLength) == arg.fileContent().byteSize();
-}
-
-class UnsavedFile : public ::testing::Test
-{
-protected:
- Utf8String filePath = Utf8StringLiteral("path");
- Utf8String fileContent = Utf8StringLiteral("content");
-
- Utf8String otherFilePath = Utf8StringLiteral("otherpath");
- Utf8String otherFileContent = Utf8StringLiteral("othercontent");
-
- Utf8String absoluteFilePath = Utf8StringLiteral(TESTDATA_DIR"/file.cpp");
-
- uint aLength = 2;
- Utf8String aReplacement = Utf8StringLiteral("replacement");
-};
-
-TEST_F(UnsavedFile, Create)
-{
- ::UnsavedFile unsavedFile(filePath, fileContent);
-
- ASSERT_THAT(unsavedFile, IsUnsavedFile(filePath,
- fileContent,
- fileContent.byteSize()));
-}
-
-TEST_F(UnsavedFile, CopyConstruct)
-{
- ::UnsavedFile copyFrom(filePath, fileContent);
-
- ::UnsavedFile copyTo = copyFrom;
-
- ASSERT_THAT(copyTo, IsUnsavedFile(filePath,
- fileContent,
- fileContent.byteSize()));
-}
-
-TEST_F(UnsavedFile, FilePath)
-{
- ::UnsavedFile unsavedFile(absoluteFilePath, QStringLiteral(""));
-
- ASSERT_THAT(unsavedFile.filePath(), Eq(absoluteFilePath));
-}
-
-TEST_F(UnsavedFile, NativeFilePath)
-{
- ::UnsavedFile unsavedFile(absoluteFilePath, QStringLiteral(""));
- const Utf8String nativeFilePath = FilePath::toNativeSeparators(absoluteFilePath);
-
- ASSERT_THAT(unsavedFile.nativeFilePath(), Eq(nativeFilePath));
-}
-
-TEST_F(UnsavedFile, DoNotReplaceWithOffsetZeroInEmptyContent)
-{
- ::UnsavedFile unsavedFile(filePath, QStringLiteral(""));
-
- ASSERT_FALSE(unsavedFile.replaceAt(0, aLength, aReplacement));
-}
-
-TEST_F(UnsavedFile, DoNotReplaceWithOffsetOneInEmptyContent)
-{
- ::UnsavedFile unsavedFile(filePath, QStringLiteral(""));
-
- ASSERT_FALSE(unsavedFile.replaceAt(1, aLength, aReplacement));
-}
-
-TEST_F(UnsavedFile, Replace)
-{
- const Utf8String expectedContent = Utf8StringLiteral("hello replacement!");
- ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("hello world!"));
-
- const bool hasReplaced = unsavedFile.replaceAt(6, 5, aReplacement);
-
- ASSERT_TRUE(hasReplaced);
- ASSERT_THAT(unsavedFile, IsUnsavedFile(filePath, expectedContent, expectedContent.byteSize()));
-}
-
-TEST_F(UnsavedFile, ToUtf8PositionForValidLineColumn)
-{
- ::UnsavedFile unsavedFile(filePath, fileContent);
- bool ok = false;
-
- const uint position = unsavedFile.toUtf8Position(1, 1, &ok);
-
- ASSERT_TRUE(ok);
- ASSERT_THAT(position, Eq(0L));
-}
-
-TEST_F(UnsavedFile, ToUtf8PositionForInValidLineColumn)
-{
- ::UnsavedFile unsavedFile(filePath, fileContent);
- bool ok = false;
-
- unsavedFile.toUtf8Position(2, 1, &ok);
-
- ASSERT_FALSE(ok);
-}
-
-TEST_F(UnsavedFile, ToUtf8PositionForDefaultConstructedUnsavedFile)
-{
- ::UnsavedFile unsavedFile;
- bool ok = false;
-
- unsavedFile.toUtf8Position(1, 1, &ok);
-
- ASSERT_FALSE(ok);
-}
-
-TEST_F(UnsavedFile, HasNoCharacterForDefaultConstructedUnsavedFile)
-{
- ::UnsavedFile unsavedFile;
-
- ASSERT_FALSE(unsavedFile.hasCharacterAt(0, 'x'));
-}
-
-TEST_F(UnsavedFile, ReplacingInCopyDoesNotModifyOriginal)
-{
- const Utf8String originalContent = Utf8StringLiteral("foo");
- ::UnsavedFile original(filePath, originalContent);
- ::UnsavedFile copy = original;
-
- const bool hasReplaced = copy.replaceAt(0, 3, aReplacement);
-
- ASSERT_TRUE(hasReplaced);
- ASSERT_THAT(original, IsUnsavedFile(filePath, originalContent, originalContent.byteSize()));
- ASSERT_THAT(copy, IsUnsavedFile(filePath, aReplacement, aReplacement.byteSize()));
-}
-
-TEST_F(UnsavedFile, HasNoCharacterForTooBigOffset)
-{
- ::UnsavedFile unsavedFile(filePath, fileContent);
-
- ASSERT_FALSE(unsavedFile.hasCharacterAt(100, 'x'));
-}
-
-TEST_F(UnsavedFile, HasNoCharacterForWrongOffset)
-{
- ::UnsavedFile unsavedFile(filePath, fileContent);
-
- ASSERT_FALSE(unsavedFile.hasCharacterAt(0, 'x'));
-}
-
-TEST_F(UnsavedFile, HasCharacterForCorrectOffset)
-{
- ::UnsavedFile unsavedFile(filePath, fileContent);
-
- ASSERT_TRUE(unsavedFile.hasCharacterAt(0, 'c'));
-}
-
-TEST_F(UnsavedFile, HasCharacterForLastLineColumn)
-{
- ::UnsavedFile unsavedFile(filePath, fileContent);
-
- ASSERT_TRUE(unsavedFile.hasCharacterAt(1, 7, 't'));
-}
-
-TEST_F(UnsavedFile, LineRangeForInvalidLines)
-{
- ::UnsavedFile unsavedFile(filePath, fileContent);
-
- ASSERT_THAT(unsavedFile.lineRange(2, 1), Utf8String());
-}
-
-TEST_F(UnsavedFile, LineRangeForSingleLine)
-{
- ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo"));
-
- ASSERT_THAT(unsavedFile.lineRange(1, 1), Utf8StringLiteral("foo"));
-}
-
-TEST_F(UnsavedFile, LineRangeForSingleLineInMultipleLines)
-{
- ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo\nbar\n\baz"));
-
- ASSERT_THAT(unsavedFile.lineRange(2, 2), Utf8StringLiteral("bar"));
-}
-
-TEST_F(UnsavedFile, LineRangeForTwoLines)
-{
- ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo\nbar\n\baz"));
-
- ASSERT_THAT(unsavedFile.lineRange(2, 3), Utf8StringLiteral("bar\n\baz"));
-}
-
-} // anonymous namespace
diff --git a/tests/unit/unittest/unsavedfiles-test.cpp b/tests/unit/unittest/unsavedfiles-test.cpp
deleted file mode 100644
index 283c941d574..00000000000
--- a/tests/unit/unittest/unsavedfiles-test.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <filecontainer.h>
-#include <unsavedfiles.h>
-#include <unsavedfile.h>
-
-#include <QVector>
-
-using ClangBackEnd::UnsavedFile;
-using ClangBackEnd::UnsavedFiles;
-using ClangBackEnd::FileContainer;
-
-using ::testing::Eq;
-using ::testing::Gt;
-using ::testing::IsNull;
-using ::testing::Ne;
-using ::testing::NotNull;
-using ::testing::PrintToString;
-
-namespace {
-
-bool operator==(const ClangBackEnd::FileContainer &fileContainer, const UnsavedFile &unsavedFile)
-{
- return fileContainer.filePath == unsavedFile.filePath()
- && fileContainer.unsavedFileContent == unsavedFile.fileContent();
-}
-
-bool fileContainersContainsItemMatchingToCxUnsavedFile(const QVector<FileContainer> &fileContainers, const UnsavedFile &unsavedFile)
-{
- for (const FileContainer &fileContainer : fileContainers) {
- if (fileContainer == unsavedFile)
- return true;
- }
-
- return false;
-}
-
-MATCHER_P(HasUnsavedFiles, fileContainers, "")
-{
- ClangBackEnd::UnsavedFiles unsavedFiles = arg;
- if (unsavedFiles.count() != uint(fileContainers.size())) {
- *result_listener << "unsaved count is " << unsavedFiles.count() << " and not " << fileContainers.size();
- return false;
- }
-
- for (uint i = 0, to = unsavedFiles.count(); i < to; ++i) {
- UnsavedFile unsavedFile = unsavedFiles.at(i);
- if (!fileContainersContainsItemMatchingToCxUnsavedFile(fileContainers, unsavedFile))
- return false;
- }
-
- return true;
-}
-
-MATCHER_P3(IsUnsavedFile, fileName, contents, contentsLength,
- std::string(negation ? "isn't" : "is")
- + " file name " + PrintToString(fileName)
- + ", contents " + PrintToString(contents)
- + ", contents length " + PrintToString(contentsLength))
-{
- return fileName == arg.filePath()
- && contents == arg.fileContent()
- && int(contentsLength) == arg.fileContent().byteSize();
-}
-
-class UnsavedFiles : public ::testing::Test
-{
-protected:
- ::UnsavedFiles unsavedFiles;
- Utf8String filePath{Utf8StringLiteral("file.cpp")};
-
- Utf8String unsavedContent1{Utf8StringLiteral("foo")};
- Utf8String unsavedContent2{Utf8StringLiteral("bar")};
-};
-
-TEST_F(UnsavedFiles, ModifiedCopyIsDifferent)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath, unsavedContent1, true)});
- unsavedFiles.createOrUpdate(fileContainers);
-
- ::UnsavedFiles copy = unsavedFiles;
- QVector<FileContainer> updatedFileContainers({FileContainer(filePath, unsavedContent2, true)});
- copy.createOrUpdate(updatedFileContainers);
-
- ASSERT_THAT(copy.at(0).fileContent(), Ne(unsavedFiles.at(0).fileContent()));
- ASSERT_THAT(copy.lastChangeTimePoint(), Gt(unsavedFiles.lastChangeTimePoint()));
-}
-
-TEST_F(UnsavedFiles, DoNothingForUpdateIfFileHasNoUnsavedContent)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath)});
-
- unsavedFiles.createOrUpdate(fileContainers);
-
- ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>()));
-}
-
-TEST_F(UnsavedFiles, AddUnsavedFileForUpdateWithUnsavedContent)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath),
- FileContainer(filePath, unsavedContent1, true)});
- unsavedFiles.createOrUpdate(fileContainers);
-
- ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>({FileContainer(filePath, unsavedContent1, true)})));
-}
-
-TEST_F(UnsavedFiles, RemoveUnsavedFileForUpdateWithUnsavedContent)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath, unsavedContent1, true),
- FileContainer(filePath)});
-
- unsavedFiles.createOrUpdate(fileContainers);
-
- ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>()));
-}
-
-TEST_F(UnsavedFiles, ExchangeUnsavedFileForUpdateWithUnsavedContent)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath, unsavedContent1, true),
- FileContainer(filePath, unsavedContent2, true)});
- unsavedFiles.createOrUpdate(fileContainers);
-
- ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>({FileContainer(filePath, unsavedContent2, true)})));
-}
-
-TEST_F(UnsavedFiles, TimeStampIsUpdatedAsUnsavedFilesChanged)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath, unsavedContent1, true),
- FileContainer(filePath, unsavedContent2, true)});
- auto lastChangeTimePoint = unsavedFiles.lastChangeTimePoint();
-
- unsavedFiles.createOrUpdate(fileContainers);
-
- ASSERT_THAT(unsavedFiles.lastChangeTimePoint(), Gt(lastChangeTimePoint));
-}
-
-TEST_F(UnsavedFiles, RemoveUnsavedFiles)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath, unsavedContent1, true)});
- unsavedFiles.createOrUpdate(fileContainers);
-
- unsavedFiles.remove(fileContainers);
-
- ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>()));
-}
-
-TEST_F(UnsavedFiles, FindUnsavedFile)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath, unsavedContent1, true)});
- unsavedFiles.createOrUpdate(fileContainers);
-
- UnsavedFile &unsavedFile = unsavedFiles.unsavedFile(filePath);
-
- ASSERT_THAT(unsavedFile, IsUnsavedFile(filePath, unsavedContent1, unsavedContent1.byteSize()));
-}
-
-TEST_F(UnsavedFiles, FindNoUnsavedFile)
-{
- QVector<FileContainer> fileContainers({FileContainer(filePath, unsavedContent1, true)});
- unsavedFiles.createOrUpdate(fileContainers);
-
- UnsavedFile &unsavedFile = unsavedFiles.unsavedFile(Utf8StringLiteral("nonExistingFilePath.cpp"));
-
- ASSERT_THAT(unsavedFile, IsUnsavedFile(Utf8String(), Utf8String(), 0UL));
-}
-
-}
diff --git a/tests/unit/unittest/utf8-test.cpp b/tests/unit/unittest/utf8-test.cpp
deleted file mode 100644
index 663955dcbc0..00000000000
--- a/tests/unit/unittest/utf8-test.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <QString>
-
-#include <utf8stringvector.h>
-
-using namespace ::testing;
-
-TEST(Utf8, QStringConversionConstructor)
-{
- ASSERT_THAT(Utf8String(QStringLiteral("text")), Utf8StringLiteral("text"));
-}
-
-TEST(Utf8, QByteArrayConversionFunction)
-{
- ASSERT_THAT(Utf8String::fromByteArray("text"), Utf8StringLiteral("text"));
-}
-
-TEST(Utf8, QStringConversionFunction)
-{
- ASSERT_THAT(Utf8String::fromString(QStringLiteral("text")), Utf8StringLiteral("text"));
-}
-
-TEST(Utf8, Utf8ConversationFunction)
-{
- ASSERT_THAT(Utf8String::fromUtf8("text"), Utf8StringLiteral("text"));
-}
-
-TEST(Utf8, Mid)
-{
- Utf8String text(Utf8StringLiteral("some text"));
-
- ASSERT_THAT(text.mid(5, 4), Utf8StringLiteral("text"));
- ASSERT_THAT(text.mid(5), Utf8StringLiteral("text"));
-}
-
-TEST(Utf8, ByteSize)
-{
- ASSERT_THAT(Utf8StringLiteral("text").byteSize(), 4);
-}
-
-TEST(Utf8, Append)
-{
- Utf8String text(Utf8StringLiteral("some "));
- text.append(Utf8StringLiteral("text"));
-
- ASSERT_THAT(text, Utf8StringLiteral("some text"));
-}
-
-TEST(Utf8, ToByteArray)
-{
- Utf8String text(Utf8StringLiteral("some text"));
-
- ASSERT_THAT(text.toByteArray(), QByteArrayLiteral("some text"));
-}
-
-TEST(Utf8, ToString)
-{
- Utf8String text(Utf8StringLiteral("some text"));
-
- ASSERT_THAT(text.toString(), QStringLiteral("some text"));
-}
-
-
-TEST(Utf8, Contains)
-{
- Utf8String text(Utf8StringLiteral("some text"));
-
- ASSERT_TRUE(text.contains(Utf8StringLiteral("text")));
- ASSERT_TRUE(text.contains("text"));
- ASSERT_TRUE(text.contains('x'));
-}
-
-TEST(Utf8, EqualOperator)
-{
- ASSERT_TRUE(Utf8StringLiteral("text") == Utf8StringLiteral("text"));
- ASSERT_FALSE(Utf8StringLiteral("text") == Utf8StringLiteral("text2"));
-}
-
-TEST(Utf8, SmallerOperator)
-{
- ASSERT_TRUE(Utf8StringLiteral("some") < Utf8StringLiteral("text"));
- ASSERT_TRUE(Utf8StringLiteral("text") < Utf8StringLiteral("texta"));
- ASSERT_FALSE(Utf8StringLiteral("text") < Utf8StringLiteral("some"));
- ASSERT_FALSE(Utf8StringLiteral("text") < Utf8StringLiteral("text"));
-}
-
-TEST(Utf8, UnequalOperator)
-{
- ASSERT_FALSE(Utf8StringLiteral("text") != Utf8StringLiteral("text"));
- ASSERT_TRUE(Utf8StringLiteral("text") != Utf8StringLiteral("text2"));
-}
-
-TEST(Utf8, Join)
-{
- Utf8StringVector vector;
-
- vector.append(Utf8StringLiteral("some"));
- vector.append(Utf8StringLiteral("text"));
-
- ASSERT_THAT(Utf8StringLiteral("some, text"), vector.join(Utf8StringLiteral(", ")));
-}
-
-TEST(Utf8, Split)
-{
- Utf8String test(Utf8StringLiteral("some text"));
-
- Utf8StringVector splittedText = test.split(' ');
-
- ASSERT_THAT(splittedText.at(0), Utf8StringLiteral("some"));
- ASSERT_THAT(splittedText.at(1), Utf8StringLiteral("text"));
-}
-
-TEST(Utf8, IsEmpty)
-{
- ASSERT_FALSE(Utf8StringLiteral("text").isEmpty());
- ASSERT_TRUE(Utf8String().isEmpty());
-}
-
-TEST(Utf8, HasContent)
-{
- ASSERT_TRUE(Utf8StringLiteral("text").hasContent());
- ASSERT_FALSE(Utf8String().hasContent());
-}
-
-TEST(Utf8, Replace)
-{
- Utf8String text(Utf8StringLiteral("some text"));
-
- text.replace(Utf8StringLiteral("some"), Utf8StringLiteral("any"));
-
- ASSERT_THAT(text, Utf8StringLiteral("any text"));
-}
-
-TEST(Utf8, ReplaceNBytesFromIndexPosition)
-{
- Utf8String text(Utf8StringLiteral("min"));
-
- text.replace(1, 1, Utf8StringLiteral("aa"));
-
- ASSERT_THAT(text, Utf8StringLiteral("maan"));
-}
-
-TEST(Utf8, StartsWith)
-{
- Utf8String text(Utf8StringLiteral("$column"));
-
- ASSERT_TRUE(text.startsWith(Utf8StringLiteral("$col")));
- ASSERT_FALSE(text.startsWith(Utf8StringLiteral("col")));
- ASSERT_TRUE(text.startsWith("$col"));
- ASSERT_FALSE(text.startsWith("col"));
- ASSERT_TRUE(text.startsWith('$'));
- ASSERT_FALSE(text.startsWith('@'));
-}
-
-TEST(Utf8, EndsWith)
-{
- Utf8String text(Utf8StringLiteral("/my/path"));
-
- ASSERT_TRUE(text.endsWith(Utf8StringLiteral("path")));
-}
-
-TEST(Utf8, Clear)
-{
- Utf8String text(Utf8StringLiteral("$column"));
-
- text.clear();
-
- ASSERT_TRUE(text.isEmpty());
-}
-
-TEST(Utf8, Number)
-{
- ASSERT_THAT(Utf8String::number(20), Utf8StringLiteral("20"));
-}
-
-TEST(Utf8, FromIntegerVector)
-{
- QVector<int> integers({1, 2, 3});
-
- ASSERT_THAT(Utf8StringVector::fromIntegerVector(integers).join(Utf8StringLiteral(", ")), Utf8StringLiteral("1, 2, 3"));
-}
-
-TEST(Utf8, PlusOperator)
-{
- auto text = Utf8StringLiteral("foo") + Utf8StringLiteral("bar");
-
- ASSERT_THAT(text, Utf8StringLiteral("foobar"));
-}
-
-TEST(Utf8, PlusAssignmentOperator)
-{
- Utf8String text("foo", 3);
-
- text += Utf8StringLiteral("bar");
-
- ASSERT_THAT(text, Utf8StringLiteral("foobar"));
-}
-
-TEST(Utf8, CompareCharPointer)
-{
- Utf8String text("foo", 3);
-
- ASSERT_TRUE(text == "foo");
- ASSERT_FALSE(text == "foo2");
-}
-
-TEST(Utf8, RemoveFastFromVectorFailed)
-{
- Utf8StringVector values({Utf8StringLiteral("a"),
- Utf8StringLiteral("b"),
- Utf8StringLiteral("c"),
- Utf8StringLiteral("d")});
-
- ASSERT_FALSE(values.removeFast(Utf8StringLiteral("e")));
-}
-
-TEST(Utf8, RemoveFastFromVector)
-{
- Utf8StringVector values({Utf8StringLiteral("a"),
- Utf8StringLiteral("b"),
- Utf8StringLiteral("c"),
- Utf8StringLiteral("d")});
-
- bool removed = values.removeFast(Utf8StringLiteral("b"));
-
- ASSERT_TRUE(removed);
- ASSERT_THAT(values, Not(Contains(Utf8StringLiteral("b"))));
-}
-
-TEST(Utf8, ConverteAutomaticallyFromQString)
-{
- QString text(QStringLiteral("foo"));
-
- Utf8String utf8Text(text);
-
- ASSERT_THAT(utf8Text, Utf8StringLiteral("foo"));
-}
-
-TEST(Utf8, ConverteAutomaticallyToQString)
-{
- Utf8String utf8Text(Utf8StringLiteral("foo"));
-
- QString text = utf8Text;
-
- ASSERT_THAT(text, QStringLiteral("foo"));
-}
-
-TEST(Utf8, ConverteAutomaticallyToQByteArray)
-{
- Utf8String utf8Text(Utf8StringLiteral("foo"));
-
- QByteArray bytes = utf8Text;
-
- ASSERT_THAT(bytes, QByteArrayLiteral("foo"));
-}
-
diff --git a/tests/unit/unittest/utf8positionfromlinecolumn-test.cpp b/tests/unit/unittest/utf8positionfromlinecolumn-test.cpp
deleted file mode 100644
index 3cca681f7c0..00000000000
--- a/tests/unit/unittest/utf8positionfromlinecolumn-test.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "googletest.h"
-
-#include <utf8positionfromlinecolumn.h>
-#include <utf8string.h>
-
-using ClangBackEnd::Utf8PositionFromLineColumn;
-using ::testing::PrintToString;
-
-namespace {
-
-class Utf8PositionFromLineColumn : public ::testing::Test
-{
-protected:
- Utf8String empty;
- Utf8String asciiWord = Utf8StringLiteral("FOO");
- Utf8String asciiMultiLine = Utf8StringLiteral("FOO\nBAR");
- Utf8String asciiEmptyMultiLine = Utf8StringLiteral("\n\n");
- // U+00FC - 2 code units in UTF8, 1 in UTF16 - LATIN SMALL LETTER U WITH DIAERESIS
- // U+4E8C - 3 code units in UTF8, 1 in UTF16 - CJK UNIFIED IDEOGRAPH-4E8C
- // U+10302 - 4 code units in UTF8, 2 in UTF16 - OLD ITALIC LETTER KE
- Utf8String nonAsciiMultiLine = Utf8StringLiteral("\xc3\xbc" "\n"
- "\xe4\xba\x8c" "\n"
- "\xf0\x90\x8c\x82" "X");
-};
-
-TEST_F(Utf8PositionFromLineColumn, FindsNothingForEmptyContents)
-{
- ::Utf8PositionFromLineColumn converter(empty.constData());
-
- ASSERT_FALSE(converter.find(1, 1));
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsNothingForNoContents)
-{
- ::Utf8PositionFromLineColumn converter(0);
-
- ASSERT_FALSE(converter.find(1, 1));
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsNothingForLineZero)
-{
- ::Utf8PositionFromLineColumn converter(asciiWord.constData());
-
- ASSERT_FALSE(converter.find(0, 1));
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsNothingForColumnZero)
-{
- ::Utf8PositionFromLineColumn converter(asciiWord.constData());
-
- ASSERT_FALSE(converter.find(1, 0));
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsFirstForAsciiWord)
-{
- ::Utf8PositionFromLineColumn converter(asciiWord.constData());
-
- ASSERT_TRUE(converter.find(1, 1));
- ASSERT_THAT(converter.position(), 0);
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsLastForAsciiWord)
-{
- ::Utf8PositionFromLineColumn converter(asciiWord.constData());
-
- ASSERT_TRUE(converter.find(1, 3));
- ASSERT_THAT(converter.position(), 2);
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsFirstForSecondLineAscii)
-{
- ::Utf8PositionFromLineColumn converter(asciiMultiLine.constData());
-
- ASSERT_TRUE(converter.find(2, 1));
- ASSERT_THAT(converter.position(), 4);
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsLastForAsciiMultiLine)
-{
- ::Utf8PositionFromLineColumn converter(asciiMultiLine.constData());
-
- ASSERT_TRUE(converter.find(2, 3));
- ASSERT_THAT(converter.position(), 6);
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsLastInFirstLine)
-{
- ::Utf8PositionFromLineColumn converter(asciiMultiLine.constData());
-
- ASSERT_TRUE(converter.find(1, 3));
- ASSERT_THAT(converter.position(), 2);
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsNothingBeyondMaxColumn)
-{
- ::Utf8PositionFromLineColumn converter(asciiWord.constData());
-
- ASSERT_FALSE(converter.find(1, 4));
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsNothingBeyondMaxColumnForMultiLine)
-{
- ::Utf8PositionFromLineColumn converter(asciiMultiLine.constData());
-
- ASSERT_FALSE(converter.find(1, 4));
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsNothingBeyondMaxLine)
-{
- ::Utf8PositionFromLineColumn converter(asciiWord.constData());
-
- ASSERT_FALSE(converter.find(2, 1));
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsNothingForLineWithoutContent)
-{
- ::Utf8PositionFromLineColumn converter(asciiEmptyMultiLine.constData());
-
- ASSERT_FALSE(converter.find(1, 1));
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsFirstOnNonAsciiMultiLine)
-{
- ::Utf8PositionFromLineColumn converter(nonAsciiMultiLine.constData());
-
- ASSERT_TRUE(converter.find(1, 1));
- ASSERT_THAT(converter.position(), 0);
-}
-
-TEST_F(Utf8PositionFromLineColumn, FindsLastOnNonAsciiMultiLine)
-{
- ::Utf8PositionFromLineColumn converter(nonAsciiMultiLine.constData());
-
- ASSERT_TRUE(converter.find(3, 2));
- ASSERT_THAT(converter.position(), 11);
-}
-
-} // anonymous namespace